Example #1
0
        /// <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);
        }
        public void SmartContracts_GasInjector_SingleParamConstructorGasInjectedSuccess()
        {
            ContractCompilationResult compilationResult =
                ContractCompiler.Compile(TestSingleConstructorSource);

            Assert.True(compilationResult.Success);
            byte[] originalAssemblyBytes = compilationResult.Compilation;

            IContractModuleDefinition module = this.moduleReader.Read(originalAssemblyBytes).Value;

            module.Rewrite(this.rewriter);

            CSharpFunctionalExtensions.Result <IContractAssembly> assembly = this.assemblyLoader.Load(module.ToByteCode());

            IContract contract = Contract.CreateUninitialized(assembly.Value.GetType(module.ContractType.Name), this.state, null);

            IContractInvocationResult result = contract.InvokeConstructor(null);

            // TODO: Un-hard-code this.
            // Constructor: 15
            // Property setter: 12
            // Storage: 150
            // "string newString = this.Owner + 1;": 36
            Assert.Equal((Gas)213, this.gasMeter.GasConsumed);
        }
Example #3
0
        public void TestGasInjector_OutOfGasFails()
        {
            ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/OutOfGasTest.cs");

            Assert.True(compilationResult.Success);

            byte[] originalAssemblyBytes = compilationResult.Compilation;

            var callData = new MethodCall("UseAllGas");

            IContractModuleDefinition module = this.moduleReader.Read(originalAssemblyBytes).Value;

            module.Rewrite(this.rewriter);

            CSharpFunctionalExtensions.Result <IContractAssembly> assembly = this.assemblyLoader.Load(module.ToByteCode());

            IContract contract = Contract.CreateUninitialized(assembly.Value.GetType(module.ContractType.Name), this.state, null);

            // Because our contract contains an infinite loop, we want to kill our test after
            // some amount of time without achieving a result. 3 seconds is an arbitrarily high enough timeout
            // for the method body to have finished execution while minimising the amount of time we spend
            // running tests
            // If you're running with the debugger on this will obviously be a source of failures
            IContractInvocationResult result = TimeoutHelper.RunCodeWithTimeout(5, () => contract.Invoke(callData));

            Assert.False(result.IsSuccess);
            Assert.Equal((RuntimeObserver.Gas) 0, this.gasMeter.GasAvailable);
            Assert.Equal(this.gasMeter.GasLimit, this.gasMeter.GasConsumed);
            Assert.Equal(this.gasMeter.GasLimit, this.gasMeter.GasConsumed);
        }
Example #4
0
        public void TestGasInjector_OutOfGasFails()
        {
            SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/OutOfGasTest.cs");

            Assert.True(compilationResult.Success);

            byte[] originalAssemblyBytes = compilationResult.Compilation;

            var callData = new MethodCall("UseAllGas");

            IContractModuleDefinition module = this.moduleReader.Read(originalAssemblyBytes);

            module.Rewrite(this.rewriter);

            CSharpFunctionalExtensions.Result <IContractAssembly> assembly = this.assemblyLoader.Load(module.ToByteCode());

            IContract contract = Contract.CreateUninitialized(assembly.Value.GetType(module.ContractType.Name), this.state, null);

            IContractInvocationResult result = contract.Invoke(callData);

            Assert.False(result.IsSuccess);
            Assert.Equal((Gas)0, this.gasMeter.GasAvailable);
            Assert.Equal(this.gasMeter.GasLimit, this.gasMeter.GasConsumed);
            Assert.Equal(this.gasMeter.GasLimit, this.gasMeter.GasConsumed);
        }
        public void TestGasInjector_ContractMethodWithRecursion_GasInjectionSucceeds()
        {
            ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/Recursion.cs");

            Assert.True(compilationResult.Success);

            byte[] originalAssemblyBytes = compilationResult.Compilation;

            var callData = new MethodCall(nameof(Recursion.DoRecursion));

            IContractModuleDefinition module = this.moduleReader.Read(originalAssemblyBytes).Value;

            module.Rewrite(this.rewriter);

            CSharpFunctionalExtensions.Result <IContractAssembly> assembly = this.assemblyLoader.Load(module.ToByteCode());

            assembly.Value.SetObserver(new Observer(this.gasMeter, new MemoryMeter(ReflectionVirtualMachine.MemoryUnitLimit)));

            IContract contract = Contract.CreateUninitialized(assembly.Value.GetType(module.ContractType.Name), this.state, null);

            IContractInvocationResult result = contract.Invoke(callData);

            Assert.True(result.IsSuccess);
            Assert.True(this.gasMeter.GasConsumed > 0);
        }
Example #6
0
        private void AssertPasses(IContract contract, string methodName)
        {
            var callData = new MethodCall(methodName);
            IContractInvocationResult result = contract.Invoke(callData);

            Assert.True(result.IsSuccess);
        }
Example #7
0
        private void AssertFailsDueToMemory(IContract contract, string methodName)
        {
            var callData = new MethodCall(methodName);
            IContractInvocationResult result = contract.Invoke(callData);

            Assert.False(result.IsSuccess);
            Assert.Equal(ContractInvocationErrorType.OverMemoryLimit, result.InvocationErrorType);
        }
Example #8
0
        public void Invoke_Method_With_Null_Params()
        {
            var methodCall = new MethodCall("Test1");
            IContractInvocationResult result = this.contract.Invoke(methodCall);

            Assert.True(result.IsSuccess);
            Assert.True(this.instance.Test1Called);
            Assert.Equal(0, this.instance.ConstructorCalledCount);
        }
Example #9
0
        public void Invoke_Private_Method_Fails()
        {
            var methodCall = new MethodCall("TestPrivate");

            IContractInvocationResult result = this.contract.Invoke(methodCall);

            Assert.False(result.IsSuccess);
            Assert.Equal(ContractInvocationErrorType.MethodDoesNotExist, result.InvocationErrorType);
        }
Example #10
0
        public void Invoke_Method_Throws_OutOfGasException()
        {
            var methodCall = new MethodCall("TestOutOfGas");

            IContractInvocationResult result = this.contract.Invoke(methodCall);

            Assert.False(result.IsSuccess);
            Assert.Equal(ContractInvocationErrorType.OutOfGas, result.InvocationErrorType);
        }
        public void EmptyMethodName_DoesNot_Invoke_Receive()
        {
            IContract receiveContract = Contract.CreateUninitialized(typeof(HasNoReceive), this.state, this.address);
            var       methodCall      = MethodCall.Receive();

            IContractInvocationResult result = receiveContract.Invoke(methodCall);

            Assert.False(result.IsSuccess);
        }
Example #12
0
        public void Invoke_Method_With_Empty_Optional_Param()
        {
            // Method binding should fail when a method has an optional param that is not provided
            var methodCall = new MethodCall("TestOptionalParam");

            IContractInvocationResult result = this.contract.Invoke(methodCall);

            Assert.False(result.IsSuccess);
            Assert.Equal(ContractInvocationErrorType.MethodDoesNotExist, result.InvocationErrorType);
        }
Example #13
0
        public void Invoke_Method_With_Null_Param()
        {
            var param      = (string)null;
            var methodCall = new MethodCall("Test2", new object[] { param });

            IContractInvocationResult result = this.contract.Invoke(methodCall);

            Assert.False(result.IsSuccess);
            Assert.Equal(ContractInvocationErrorType.ParameterTypesDontMatch, result.InvocationErrorType);
        }
Example #14
0
        public void Invoke_Constructor_With_Null_Params()
        {
            IContractInvocationResult result = this.contract.InvokeConstructor(null);

            Assert.Equal(ContractInvocationErrorType.None, result.InvocationErrorType);
            Assert.True(result.IsSuccess);
            // We expect the count to be 2 because we call the constructor when setting up the test as well
            Assert.Equal(1, this.instance.ConstructorCalledCount);
            Assert.Equal(this.state, this.instance.State);
        }
Example #15
0
        public void Invoke_Method_With_One_Params()
        {
            var param      = 9999;
            var methodCall = new MethodCall("Test2", new object[] { param });

            IContractInvocationResult result = this.contract.Invoke(methodCall);

            Assert.True(result.IsSuccess);
            Assert.Equal(param, result.Return);
        }
        public void EmptyMethodName_Invokes_Receive()
        {
            IContract receiveContract = Contract.CreateUninitialized(typeof(HasReceive), this.state, this.address);
            var       receiveInstance = (HasReceive)receiveContract.GetPrivateFieldValue("instance");
            var       methodCall      = MethodCall.Receive();

            IContractInvocationResult result = receiveContract.Invoke(methodCall);

            Assert.True(result.IsSuccess);
            Assert.True(receiveInstance.ReceiveInvoked);
        }
        public void Non_Existent_Method_DoesNot_Invoke_Receive()
        {
            IContract receiveContract = Contract.CreateUninitialized(typeof(HasReceive), this.state, this.address);
            var       receiveInstance = (HasReceive)receiveContract.GetPrivateFieldValue("instance");
            var       methodCall      = new MethodCall("DoesntExist");

            IContractInvocationResult result = receiveContract.Invoke(methodCall);

            Assert.False(result.IsSuccess);
            Assert.False(receiveInstance.ReceiveInvoked);
            Assert.Equal(ContractInvocationErrorType.MethodDoesNotExist, result.InvocationErrorType);
        }
        /// <summary>
        /// Invokes a method on an existing smart contract
        /// </summary>
        public VmExecutionResult ExecuteMethod(ISmartContractState contractState, RuntimeObserver.IGasMeter gasMeter, MethodCall methodCall, byte[] contractCode, string typeName)
        {
            ContractByteCode code;

            // Code we're loading from database - can assume it's valid.
            using (IContractModuleDefinition moduleDefinition = this.moduleDefinitionReader.Read(contractCode).Value)
            {
                var observer = new Observer(gasMeter, new MemoryMeter(MemoryUnitLimit));
                var rewriter = new ObserverRewriter(observer);

                if (!this.Rewrite(moduleDefinition, rewriter))
                {
                    return(VmExecutionResult.Fail(VmExecutionErrorKind.RewriteFailed, "Rewrite module failed"));
                }

                Result <ContractByteCode> getCodeResult = this.GetByteCode(moduleDefinition);

                if (!getCodeResult.IsSuccess)
                {
                    return(VmExecutionResult.Fail(VmExecutionErrorKind.RewriteFailed, "Serialize module failed"));
                }

                code = getCodeResult.Value;
            }

            Result <IContract> contractLoadResult = this.Load(
                code,
                typeName,
                contractState.Message.ContractAddress.ToUint160(),
                contractState);

            if (!contractLoadResult.IsSuccess)
            {
                return(VmExecutionResult.Fail(VmExecutionErrorKind.LoadFailed, contractLoadResult.Error));
            }

            IContract contract = contractLoadResult.Value;

            this.LogExecutionContext(contract.State.Block, contract.State.Message, contract.Address);

            IContractInvocationResult invocationResult = contract.Invoke(methodCall);

            if (!invocationResult.IsSuccess)
            {
                this.logger.LogTrace("(-)[CALLCONTRACT_INSTANTIATION_FAILED]");

                return(GetInvocationVmErrorResult(invocationResult));
            }

            this.logger.LogTrace("[CALL_CONTRACT_INSTANTIATION_SUCCEEDED]");

            return(VmExecutionResult.Ok(invocationResult.Return, typeName));
        }
Example #19
0
        public void Invoke_Constructor_With_Too_Many_Params_None_Correct()
        {
            IContractInvocationResult result = this.contract.InvokeConstructor(
                new List <object>
            {
                "123", "abc"
            });

            Assert.Equal(ContractInvocationErrorType.MethodDoesNotExist, result.InvocationErrorType);
            Assert.False(result.IsSuccess);
            Assert.Equal(0, this.instance.ConstructorCalledCount);
        }
        public void EmptyMethodName_WithParams_DoesNot_Invoke_Receive()
        {
            IContract receiveContract = Contract.CreateUninitialized(typeof(HasReceive), this.state, this.address);
            var       receiveInstance = (HasReceive)receiveContract.GetPrivateFieldValue("instance");

            var parameters = new object[] { 1, "1" };
            var methodCall = new MethodCall(MethodCall.ExternalReceiveHandlerName, parameters);
            IContractInvocationResult result = receiveContract.Invoke(methodCall);

            Assert.False(result.IsSuccess);
            Assert.False(receiveInstance.ReceiveInvoked);
            Assert.Equal(ContractInvocationErrorType.MethodDoesNotExist, result.InvocationErrorType);
        }
Example #21
0
        public void Invoke_Constructor_With_One_Params()
        {
            var param = 99999;
            IContractInvocationResult result = this.contract.InvokeConstructor(new List <object> {
                param
            });

            Assert.Equal(ContractInvocationErrorType.None, result.InvocationErrorType);
            Assert.True(result.IsSuccess);
            Assert.Equal(1, this.instance.ConstructorCalledCount);
            Assert.Equal(param, this.instance.Param);
            Assert.Equal(this.state, this.instance.State);
        }
        private static VmExecutionResult GetInvocationVmErrorResult(IContractInvocationResult invocationResult)
        {
            if (invocationResult.InvocationErrorType == ContractInvocationErrorType.OutOfGas)
            {
                return(VmExecutionResult.Fail(VmExecutionErrorKind.OutOfGas, invocationResult.ErrorMessage));
            }

            if (invocationResult.InvocationErrorType == ContractInvocationErrorType.OverMemoryLimit)
            {
                return(VmExecutionResult.Fail(VmExecutionErrorKind.OutOfResources, invocationResult.ErrorMessage));
            }

            return(VmExecutionResult.Fail(VmExecutionErrorKind.InvocationFailed, invocationResult.ErrorMessage));
        }
        /// <summary>
        /// Invokes a method on an existing smart contract
        /// </summary>
        public VmExecutionResult ExecuteMethod(ISmartContractState contractState, MethodCall methodCall, byte[] contractCode, string typeName)
        {
            this.logger.LogTrace("(){0}:{1}", nameof(methodCall.Name), methodCall.Name);

            ContractByteCode code;

            // Code we're loading from database - can assume it's valid.
            using (IContractModuleDefinition moduleDefinition = this.moduleDefinitionReader.Read(contractCode).Value)
            {
                var observer = new Observer(contractState.GasMeter, MemoryUnitLimit);
                var rewriter = new ObserverRewriter(observer);
                moduleDefinition.Rewrite(rewriter);
                code = moduleDefinition.ToByteCode();
            }

            Result <IContract> contractLoadResult = this.Load(
                code,
                typeName,
                contractState.Message.ContractAddress.ToUint160(this.network),
                contractState);

            if (!contractLoadResult.IsSuccess)
            {
                LogErrorMessage(contractLoadResult.Error);

                this.logger.LogTrace("(-)[LOAD_CONTRACT_FAILED]");

                return(VmExecutionResult.Fail(VmExecutionErrorKind.LoadFailed, contractLoadResult.Error));
            }

            IContract contract = contractLoadResult.Value;

            LogExecutionContext(this.logger, contract.State.Block, contract.State.Message, contract.Address);

            IContractInvocationResult invocationResult = contract.Invoke(methodCall);

            if (!invocationResult.IsSuccess)
            {
                this.logger.LogTrace("(-)[CALLCONTRACT_INSTANTIATION_FAILED]");

                return(GetInvocationVmErrorResult(invocationResult));
            }

            this.logger.LogTrace("[CALL_CONTRACT_INSTANTIATION_SUCCEEDED]");

            this.logger.LogTrace("(-)");

            return(VmExecutionResult.Ok(invocationResult.Return, typeName));
        }
        /// <summary>
        /// Invokes a method on an existing smart contract
        /// </summary>
        public VmExecutionResult ExecuteMethod(ISmartContractState contractState, MethodCall methodCall, byte[] contractCode, string typeName)
        {
            this.logger.LogTrace("(){0}:{1}", nameof(methodCall.Name), methodCall.Name);

            ContractByteCode code;

            using (IContractModuleDefinition moduleDefinition = this.moduleDefinitionReader.Read(contractCode))
            {
                moduleDefinition.InjectMethodGas(typeName, methodCall);

                code = moduleDefinition.ToByteCode();
            }

            Result <IContract> contractLoadResult = this.Load(
                code,
                typeName,
                contractState.Message.ContractAddress.ToUint160(this.network),
                contractState);

            if (!contractLoadResult.IsSuccess)
            {
                // TODO this is temporary until we improve error handling overloads
                var exception = new Exception(contractLoadResult.Error);

                LogException(exception);

                this.logger.LogTrace("(-)[LOAD_CONTRACT_FAILED]");

                return(VmExecutionResult.Error(exception));
            }

            IContract contract = contractLoadResult.Value;

            LogExecutionContext(this.logger, contract.State.Block, contract.State.Message, contract.Address);

            IContractInvocationResult invocationResult = contract.Invoke(methodCall);

            if (!invocationResult.IsSuccess)
            {
                this.logger.LogTrace("(-)[CALLCONTRACT_INSTANTIATION_FAILED]");
                return(VmExecutionResult.Error(new Exception("Method invocation failed!")));
            }

            this.logger.LogTrace("[CALL_CONTRACT_INSTANTIATION_SUCCEEDED]");

            this.logger.LogTrace("(-)");

            return(VmExecutionResult.Success(invocationResult.Return, typeName));
        }
        public void TestGasInjector_NestedType_GasInjectionSucceeds()
        {
            ContractCompilationResult compilationResult = ContractCompiler.Compile(@"
using System;
using Stratis.SmartContracts;

public class Test : SmartContract
{
    public Test(ISmartContractState state): base(state) {
        var other = new Other.NestedOther();
        other.Loop();
    }
}

public static class Other
{
    public struct NestedOther {
        public void Loop() { while(true) {}}
    }
}
");

            Assert.True(compilationResult.Success);

            byte[] originalAssemblyBytes = compilationResult.Compilation;

            IContractModuleDefinition module = this.moduleReader.Read(originalAssemblyBytes).Value;

            module.Rewrite(this.rewriter);

            CSharpFunctionalExtensions.Result <IContractAssembly> assembly = this.assemblyLoader.Load(module.ToByteCode());

            assembly.Value.SetObserver(new Observer(this.gasMeter, new MemoryMeter(ReflectionVirtualMachine.MemoryUnitLimit)));

            IContract contract = Contract.CreateUninitialized(assembly.Value.GetType(module.ContractType.Name), this.state, null);

            IContractInvocationResult result = contract.InvokeConstructor(null);

            Assert.False(result.IsSuccess);
            Assert.Equal(this.gasMeter.GasLimit, this.gasMeter.GasConsumed);
        }
Example #26
0
        public void SmartContracts_GasInjector_MultipleParamConstructorGasInjectedSuccess()
        {
            ContractCompilationResult compilationResult =
                ContractCompiler.Compile(TestMultipleConstructorSource);

            Assert.True(compilationResult.Success);
            byte[] originalAssemblyBytes = compilationResult.Compilation;

            IContractModuleDefinition module = this.moduleReader.Read(originalAssemblyBytes).Value;

            module.Rewrite(this.rewriter);

            CSharpFunctionalExtensions.Result <IContractAssembly> assembly = this.assemblyLoader.Load(module.ToByteCode());

            IContract contract = Contract.CreateUninitialized(assembly.Value.GetType(module.ContractType.Name), this.state, null);

            IContractInvocationResult result = contract.InvokeConstructor(new[] { "Test Owner" });

            // Number here shouldn't be hardcoded - note this is really only to let us know of consensus failure
            Assert.Equal((RuntimeObserver.Gas) 328, this.gasMeter.GasConsumed);
        }
Example #27
0
        public void TestGasInjector()
        {
            SmartContractCompilationResult compilationResult = SmartContractCompiler.Compile(TestSource);

            Assert.True(compilationResult.Success);

            byte[] originalAssemblyBytes = compilationResult.Compilation;

            var resolver = new DefaultAssemblyResolver();

            resolver.AddSearchDirectory(AppContext.BaseDirectory);
            int aimGasAmount;

            using (ModuleDefinition moduleDefinition = ModuleDefinition.ReadModule(
                       new MemoryStream(originalAssemblyBytes),
                       new ReaderParameters {
                AssemblyResolver = resolver
            }))
            {
                TypeDefinition   contractType = moduleDefinition.GetType(ContractName);
                MethodDefinition testMethod   = contractType.Methods.FirstOrDefault(x => x.Name == MethodName);
                aimGasAmount =
                    testMethod?.Body?.Instructions?
                    .Count ?? 10000000;
            }

            var callData = new MethodCall("TestMethod", new object[] { 1 });

            IContractModuleDefinition module = this.moduleReader.Read(originalAssemblyBytes);

            module.Rewrite(this.rewriter);

            CSharpFunctionalExtensions.Result <IContractAssembly> assembly = this.assemblyLoader.Load(module.ToByteCode());

            IContract contract = Contract.CreateUninitialized(assembly.Value.GetType(module.ContractType.Name), this.state, null);

            IContractInvocationResult result = contract.Invoke(callData);

            Assert.Equal((ulong)aimGasAmount, this.state.GasMeter.GasConsumed);
        }
        public void TestGasInjector()
        {
            ContractCompilationResult compilationResult = ContractCompiler.Compile(TestSource);

            Assert.True(compilationResult.Success);

            byte[] originalAssemblyBytes = compilationResult.Compilation;

            var resolver = new DefaultAssemblyResolver();

            resolver.AddSearchDirectory(AppContext.BaseDirectory);

            using (ModuleDefinition moduleDefinition = ModuleDefinition.ReadModule(
                       new MemoryStream(originalAssemblyBytes),
                       new ReaderParameters {
                AssemblyResolver = resolver
            }))
            {
                TypeDefinition   contractType = moduleDefinition.GetType(ContractName);
                MethodDefinition testMethod   = contractType.Methods.FirstOrDefault(x => x.Name == MethodName);
            }

            var callData = new MethodCall("TestMethod", new object[] { 1 });

            IContractModuleDefinition module = this.moduleReader.Read(originalAssemblyBytes).Value;

            module.Rewrite(this.rewriter);

            CSharpFunctionalExtensions.Result <IContractAssembly> assembly = this.assemblyLoader.Load(module.ToByteCode());

            assembly.Value.SetObserver(new Observer(this.gasMeter, new MemoryMeter(ReflectionVirtualMachine.MemoryUnitLimit)));

            IContract contract = Contract.CreateUninitialized(assembly.Value.GetType(module.ContractType.Name), this.state, null);

            IContractInvocationResult result = contract.Invoke(callData);

            // Number here shouldn't be hardcoded - note this is really only to let us know of consensus failure
            Assert.Equal(22uL, this.gasMeter.GasConsumed);
        }
Example #29
0
        /// <summary>
        /// Creates a new instance of a smart contract by invoking the contract's constructor
        /// </summary>
        public VmExecutionResult Create(IStateRepository repository, ISmartContractState contractState, byte[] contractCode, object[] parameters, string typeName = null)
        {
            this.logger.LogTrace("()");

            string           typeToInstantiate;
            ContractByteCode code;

            // Decompile the contract execution code
            Result <IContractModuleDefinition> moduleResult = this.moduleDefinitionReader.Read(contractCode);

            if (moduleResult.IsFailure)
            {
                this.logger.LogTrace("(-)[CONTRACT_BYTECODE_INVALID]");
                return(VmExecutionResult.Error(new ContractErrorMessage("Contract bytecode is not valid IL.")));
            }

            // Validate contract execution code
            using (IContractModuleDefinition moduleDefinition = moduleResult.Value)
            {
                SmartContractValidationResult validation = moduleDefinition.Validate(this.validator);

                // If validation failed, refund the sender any remaining gas.
                if (!validation.IsValid)
                {
                    this.logger.LogTrace("(-)[CONTRACT_VALIDATION_FAILED]");
                    // TODO: List errors by string.
                    return(VmExecutionResult.Error(new ContractErrorMessage(new SmartContractValidationException(validation.Errors).ToString())));
                }

                typeToInstantiate = typeName ?? moduleDefinition.ContractType.Name;

                var observer = new Observer(contractState.GasMeter, MemoryUnitLimit);
                var rewriter = new ObserverRewriter(observer);
                moduleDefinition.Rewrite(rewriter);

                code = moduleDefinition.ToByteCode();
            }

            Result <IContract> contractLoadResult = this.Load(
                code,
                typeToInstantiate,
                contractState.Message.ContractAddress.ToUint160(this.network),
                contractState);

            if (!contractLoadResult.IsSuccess)
            {
                LogErrorMessage(contractLoadResult.Error);

                this.logger.LogTrace("(-)[LOAD_CONTRACT_FAILED]");

                return(VmExecutionResult.Error(new ContractErrorMessage(contractLoadResult.Error)));
            }

            IContract contract = contractLoadResult.Value;

            LogExecutionContext(this.logger, contract.State.Block, contract.State.Message, contract.Address);

            // Set the code and the Type before the method is invoked
            repository.SetCode(contract.Address, contractCode);
            repository.SetContractType(contract.Address, typeToInstantiate);

            // Invoke the constructor of the provided contract code
            IContractInvocationResult invocationResult = contract.InvokeConstructor(parameters);

            if (!invocationResult.IsSuccess)
            {
                this.logger.LogTrace("[CREATE_CONTRACT_INSTANTIATION_FAILED]");
                return(VmExecutionResult.Error(invocationResult.ErrorMessage));
            }

            this.logger.LogTrace("[CREATE_CONTRACT_INSTANTIATION_SUCCEEDED]");

            this.logger.LogTrace("(-):{0}={1}", nameof(contract.Address), contract.Address);

            return(VmExecutionResult.Success(invocationResult.Return, typeToInstantiate));
        }
        /// <summary>
        /// Creates a new instance of a smart contract by invoking the contract's constructor
        /// </summary>
        public VmExecutionResult Create(IStateRepository repository,
                                        ISmartContractState contractState,
                                        RuntimeObserver.IGasMeter gasMeter,
                                        byte[] contractCode,
                                        object[] parameters,
                                        string typeName = null)
        {
            string           typeToInstantiate;
            ContractByteCode code;

            // Decompile the contract execution code
            Result <IContractModuleDefinition> moduleResult = this.moduleDefinitionReader.Read(contractCode);

            if (moduleResult.IsFailure)
            {
                this.logger.LogTrace(moduleResult.Error);
                this.logger.LogTrace("(-)[CONTRACT_BYTECODE_INVALID]");
                return(VmExecutionResult.Fail(VmExecutionErrorKind.LoadFailed, "Contract bytecode is not valid IL."));
            }

            // Validate contract execution code
            using (IContractModuleDefinition moduleDefinition = moduleResult.Value)
            {
                SmartContractValidationResult validation = moduleDefinition.Validate(this.validator);

                // If validation failed, refund the sender any remaining gas.
                if (!validation.IsValid)
                {
                    this.logger.LogTrace("(-)[CONTRACT_VALIDATION_FAILED]");
                    return(VmExecutionResult.Fail(VmExecutionErrorKind.ValidationFailed, new SmartContractValidationException(validation.Errors).ToString()));
                }

                typeToInstantiate = typeName ?? moduleDefinition.ContractType.Name;

                var observer = new Observer(gasMeter, new MemoryMeter(MemoryUnitLimit));
                var rewriter = new ObserverRewriter(observer);

                if (!this.Rewrite(moduleDefinition, rewriter))
                {
                    return(VmExecutionResult.Fail(VmExecutionErrorKind.RewriteFailed, "Rewrite module failed"));
                }

                Result <ContractByteCode> getCodeResult = this.GetByteCode(moduleDefinition);

                if (!getCodeResult.IsSuccess)
                {
                    return(VmExecutionResult.Fail(VmExecutionErrorKind.RewriteFailed, "Serialize module failed"));
                }

                code = getCodeResult.Value;
            }

            Result <IContract> contractLoadResult = this.Load(
                code,
                typeToInstantiate,
                contractState.Message.ContractAddress.ToUint160(),
                contractState);

            if (!contractLoadResult.IsSuccess)
            {
                return(VmExecutionResult.Fail(VmExecutionErrorKind.LoadFailed, contractLoadResult.Error));
            }

            IContract contract = contractLoadResult.Value;

            this.LogExecutionContext(contract.State.Block, contract.State.Message, contract.Address);

            // Set the code and the Type before the method is invoked
            repository.SetCode(contract.Address, contractCode);
            repository.SetContractType(contract.Address, typeToInstantiate);

            // Invoke the constructor of the provided contract code
            IContractInvocationResult invocationResult = contract.InvokeConstructor(parameters);

            if (!invocationResult.IsSuccess)
            {
                this.logger.LogTrace("[CREATE_CONTRACT_INSTANTIATION_FAILED]");
                return(GetInvocationVmErrorResult(invocationResult));
            }

            this.logger.LogTrace("[CREATE_CONTRACT_INSTANTIATION_SUCCEEDED]");

            return(VmExecutionResult.Ok(invocationResult.Return, typeToInstantiate));
        }