/// <inheritdoc />
        public IContractInvocationResult InvokeConstructor(IReadOnlyList <object> parameters)
        {
            // If it's a constructor we need to append the ISmartContractState to the start of the parameters array
            object[] invokeParams = { this.State };

            if (parameters != null)
            {
                invokeParams = invokeParams.Concat(parameters).ToArray();
            }

            Type[] types = invokeParams.Select(p => p.GetType()).ToArray();

            ConstructorInfo methodToInvoke = this.Type.GetConstructor(types);

            if (methodToInvoke == null)
            {
                return(ContractInvocationResult.Failure(ContractInvocationErrorType.MethodDoesNotExist));
            }

            IContractInvocationResult result = this.InvokeInternal(methodToInvoke, invokeParams);

            this.initialized = result.IsSuccess;

            return(result);
        }
        /// <summary>
        /// Shared internal logic for invoking a method.
        /// </summary>
        private IContractInvocationResult InvokeInternal(MethodBase method, object[] parameters)
        {
            try
            {
                object result = method.Invoke(this.instance, parameters);

                return(ContractInvocationResult.Success(result));
            }
            catch (ArgumentException argumentException)
            {
                // Parameters do not match
                // This should not happen
                return(ContractInvocationResult.Failure(ContractInvocationErrorType.ParameterTypesDontMatch, argumentException));
            }
            catch (TargetInvocationException targetException) when(!(targetException.InnerException is OutOfGasException))
            {
                // Method threw an exception that was not an OutOfGasException
                return(ContractInvocationResult.Failure(ContractInvocationErrorType.MethodThrewException, targetException));
            }
            catch (TargetInvocationException targetException) when(targetException.InnerException is OutOfGasException)
            {
                // Method threw an exception that was an OutOfGasException
                return(ContractInvocationResult.Failure(ContractInvocationErrorType.OutOfGas));
            }
            catch (TargetParameterCountException parameterException)
            {
                // Parameter count incorrect
                // This should not happen
                return(ContractInvocationResult.Failure(ContractInvocationErrorType.ParameterCountIncorrect, parameterException));
            }
        }
        /// <inheritdoc />
        public IContractInvocationResult Invoke(MethodCall call)
        {
            if (call.IsReceiveHandlerCall)
            {
                return(this.InvokeReceiveHandler());
            }

            object[] invokeParams = call.Parameters?.ToArray() ?? new object[0];

            Type[] types = invokeParams.Select(p => p.GetType()).ToArray();

            MethodInfo methodToInvoke = this.Type.GetMethod(call.Name, types);

            if (methodToInvoke == null)
            {
                return(ContractInvocationResult.Failure(ContractInvocationErrorType.MethodDoesNotExist));
            }

            // This should not happen without setting the appropriate binding flags
            if (methodToInvoke.IsConstructor)
            {
                return(ContractInvocationResult.Failure(ContractInvocationErrorType.MethodIsConstructor));
            }

            // This should not happen without setting the appropriate binding flags
            if (methodToInvoke.IsPrivate)
            {
                return(ContractInvocationResult.Failure(ContractInvocationErrorType.MethodIsPrivate));
            }

            EnsureInitialized();

            return(this.InvokeInternal(methodToInvoke, invokeParams));
        }
        private IContractInvocationResult InvokeReceiveHandler()
        {
            // Handles the scenario where no receive was defined, but it is attempted to be invoked anyway.
            // This could occur if a method invocation is directly made to the receive via a transaction.
            if (this.ReceiveHandler == null)
            {
                return(ContractInvocationResult.Failure(ContractInvocationErrorType.MethodDoesNotExist));
            }

            EnsureInitialized();

            return(this.InvokeInternal(this.ReceiveHandler, null));
        }
Esempio n. 5
0
        /// <summary>
        /// Shared internal logic for invoking a method.
        /// </summary>
        private IContractInvocationResult InvokeInternal(MethodBase method, object[] parameters)
        {
            try
            {
                object result = method.Invoke(this.instance, parameters);

                return(ContractInvocationResult.Success(result));
            }
            catch (TargetParameterCountException parameterException)
            {
                // Parameter count incorrect
                // This should not happen
                return(ContractInvocationResult.Failure(ContractInvocationErrorType.ParameterCountIncorrect));
            }
            catch (ArgumentException argumentException)
            {
                // Parameters do not match
                // This should not happen
                return(ContractInvocationResult.Failure(ContractInvocationErrorType.ParameterTypesDontMatch));
            }
            catch (TargetInvocationException targetException)
                when(!(targetException.InnerException is OutOfGasException) &&
                     !(targetException.InnerException is MemoryConsumptionException))
                {
                    // Method threw an exception that was not an OutOfGasException or a MemoryConsumptionException
                    // TODO: OutofGas and MemoryConsumption exceptions should inherit from same base 'ResourceTrackingException'
                    // which can be tracked here.
                    return(ContractInvocationResult.ExecutionFailure(ContractInvocationErrorType.MethodThrewException, targetException.InnerException));
                }
            catch (TargetInvocationException targetException) when(targetException.InnerException is OutOfGasException)
            {
                // Method threw an OutOfGasException
                return(ContractInvocationResult.ExecutionFailure(ContractInvocationErrorType.OutOfGas, targetException.InnerException));
            }
            catch (TargetInvocationException targetException) when(targetException.InnerException is MemoryConsumptionException)
            {
                // Method threw a MemoryConsumptionException
                return(ContractInvocationResult.ExecutionFailure(ContractInvocationErrorType.OverMemoryLimit, targetException.InnerException));
            }
        }