public void InternalCreate_Balance_Error()
        {
            var typeName = "Test";

            var internalCreateMessage = new InternalCreateMessage(
                uint160.Zero,
                10,
                (Gas)(GasPriceList.BaseCost + 100000),
                new object[] { },
                typeName
                );

            var state = new Mock <IState>();

            // Setup the balance with less than the required amount.
            state.Setup(s => s.GetBalance(internalCreateMessage.From))
            .Returns(internalCreateMessage.Amount - 1);

            var stateProcessor = new StateProcessor(this.vm.Object, this.addressGenerator.Object);

            StateTransitionResult result = stateProcessor.Apply(state.Object, internalCreateMessage);

            state.Verify(s => s.GetBalance(internalCreateMessage.From));

            Assert.True(result.IsFailure);
            Assert.NotNull(result.Error);
            Assert.Null(result.Error.VmError);
            Assert.Equal(StateTransitionErrorKind.InsufficientBalance, result.Error.Kind);
            Assert.Equal((Gas)0, result.GasConsumed);
        }
Example #2
0
        public void InternalCreate_Vm_Error()
        {
            var newContractAddress = uint160.One;

            var vmExecutionResult = VmExecutionResult.Fail(VmExecutionErrorKind.InvocationFailed, "Error");

            // Code must have a length to pass precondition checks.
            var code     = new byte[1];
            var typeName = "Test";

            var internalCreateMessage = new InternalCreateMessage(
                uint160.Zero,
                10,
                (RuntimeObserver.Gas)(GasPriceList.BaseCost + 100000),
                new object[] { },
                typeName
                );

            this.vm.Setup(v =>
                          v.Create(It.IsAny <IStateRepository>(),
                                   It.IsAny <ISmartContractState>(),
                                   It.IsAny <ExecutionContext>(),
                                   It.IsAny <byte[]>(),
                                   It.IsAny <object[]>(),
                                   It.IsAny <string>()))
            .Returns(vmExecutionResult);

            // Need to return code for the sender
            this.contractStateRoot
            .Setup(sr => sr.GetCode(internalCreateMessage.From))
            .Returns(code);

            var state = new Mock <IState>();

            state.Setup(s => s.GetBalance(internalCreateMessage.From)).Returns(internalCreateMessage.Amount + 1);
            state.SetupGet(s => s.ContractState).Returns(this.contractStateRoot.Object);
            state.Setup(s => s.GenerateAddress(It.IsAny <IAddressGenerator>())).Returns(newContractAddress);

            var stateProcessor = new StateProcessor(this.vm.Object, this.addressGenerator.Object);

            StateTransitionResult result = stateProcessor.Apply(state.Object, internalCreateMessage);

            state.Verify(s => s.CreateSmartContractState(state.Object, It.IsAny <RuntimeObserver.IGasMeter>(), newContractAddress, internalCreateMessage, this.contractStateRoot.Object));

            this.vm.Verify(
                v => v.Create(
                    this.contractStateRoot.Object,
                    It.IsAny <ISmartContractState>(),
                    It.IsAny <ExecutionContext>(),
                    code,
                    internalCreateMessage.Parameters,
                    internalCreateMessage.Type),
                Times.Once);

            Assert.True(result.IsFailure);
            Assert.NotNull(result.Error);
            Assert.Equal(result.Error.VmError, vmExecutionResult.Error.Message);
            Assert.Equal(StateTransitionErrorKind.VmError, result.Error.Kind);
            Assert.Equal(GasPriceList.CreateCost, result.GasConsumed);
        }
        public void InternalCreate_Success()
        {
            // The difference between an internal and an external create:
            // - Internal create performs a balance check before execution
            // - Internal create appends a new internal transfer if successful
            var newContractAddress = uint160.One;
            var vmExecutionResult  = VmExecutionResult.Success(true, "Test");
            var code     = new byte[1];
            var typeName = "Test";

            var internalCreateMessage = new InternalCreateMessage(
                uint160.Zero,
                10,
                (Gas)(GasPriceList.BaseCost + 100000),
                new object[] {},
                typeName
                );

            this.contractStateRoot
            .Setup(sr => sr.GetCode(internalCreateMessage.From))
            .Returns(code);

            this.vm.Setup(v => v.Create(this.contractStateRoot.Object, It.IsAny <ISmartContractState>(), code, internalCreateMessage.Parameters, internalCreateMessage.Type))
            .Returns(vmExecutionResult);

            var state = new Mock <IState>();

            // Return the sent amount + 1
            state.Setup(s => s.GetBalance(internalCreateMessage.From)).Returns(internalCreateMessage.Amount + 1);
            state.SetupGet(s => s.ContractState).Returns(this.contractStateRoot.Object);
            state.Setup(s => s.GenerateAddress(It.IsAny <IAddressGenerator>())).Returns(newContractAddress);

            var stateProcessor = new StateProcessor(this.vm.Object, this.addressGenerator.Object);

            StateTransitionResult result = stateProcessor.Apply(state.Object, internalCreateMessage);

            // Verify we check the balance of the sender first
            state.Verify(s => s.GetBalance(internalCreateMessage.From));

            // Because this is an internal create we get the code from the sender's code cache
            this.contractStateRoot.Verify(s => s.GetCode(internalCreateMessage.From), Times.Once);

            state.Verify(s => s.GenerateAddress(this.addressGenerator.Object), Times.Once);

            // Verify the account was created
            this.contractStateRoot.Verify(s => s.CreateAccount(newContractAddress), Times.Once);

            // Verify we set up the smart contract state
            state.Verify(s => s.CreateSmartContractState(state.Object, It.IsAny <GasMeter>(), newContractAddress, internalCreateMessage, this.contractStateRoot.Object));

            // Verify the VM was invoked
            this.vm.Verify(v => v.Create(this.contractStateRoot.Object, It.IsAny <ISmartContractState>(), code, internalCreateMessage.Parameters, internalCreateMessage.Type), Times.Once);

            // Verify the value was added to the internal transfer list
            state.Verify(s => s.AddInternalTransfer(It.Is <TransferInfo>(t => t.From == internalCreateMessage.From &&
                                                                         t.To == newContractAddress &&
                                                                         t.Value == internalCreateMessage.Amount)));

            Assert.True(result.IsSuccess);
            Assert.NotNull(result.Success);
            Assert.Equal(newContractAddress, result.Success.ContractAddress);
            Assert.Equal(vmExecutionResult.Result, result.Success.ExecutionResult);
            Assert.Equal(GasPriceList.BaseCost, result.GasConsumed);
        }