public void Contract_Transfer_To_Other_Contract_Balance_Error()
        {
            var contractTransferMessage = new ContractTransferMessage(
                uint160.One,
                uint160.Zero,
                10,
                (Gas)(GasPriceList.BaseCost + 100000)
                );

            var state = new Mock <IState>();

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

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

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

            state.Verify(s => s.GetBalance(contractTransferMessage.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);
        }
        public void Contract_Transfer_To_Other_Contract_Success()
        {
            // There is code at the destination address, which causes an internal call to the receive method
            var vmExecutionResult = VmExecutionResult.Success(true, "Test");
            var code     = new byte[1];
            var typeName = "Test";

            var contractTransferMessage = new ContractTransferMessage(
                uint160.One,
                uint160.Zero,
                10,
                (Gas)(GasPriceList.BaseCost + 100000)
                );

            // Code must be returned for this test to ensure we apply the call.
            this.contractStateRoot
            .Setup(sr => sr.GetCode(contractTransferMessage.To))
            .Returns(code);

            this.contractStateRoot
            .Setup(sr => sr.GetContractType(contractTransferMessage.To))
            .Returns(typeName);

            this.vm.Setup(v => v.ExecuteMethod(It.IsAny <ISmartContractState>(), contractTransferMessage.Method, code, typeName))
            .Returns(vmExecutionResult);

            var state = new Mock <IState>();

            // Return the sent amount + 1
            state.Setup(s => s.GetBalance(contractTransferMessage.From)).Returns(contractTransferMessage.Amount + 1);

            state.SetupGet(s => s.ContractState).Returns(this.contractStateRoot.Object);

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

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

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

            // Verify we get the code from the destination address' code cache
            this.contractStateRoot.Verify(s => s.GetCode(contractTransferMessage.To), Times.Once);

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

            // Verify the VM was invoked
            this.vm.Verify(v => v.ExecuteMethod(It.IsAny <ISmartContractState>(), contractTransferMessage.Method, code, typeName), Times.Once);

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

            Assert.True(result.IsSuccess);
            Assert.NotNull(result.Success);
            Assert.Equal(contractTransferMessage.To, result.Success.ContractAddress);
            Assert.Equal(vmExecutionResult.Result, result.Success.ExecutionResult);
            Assert.Equal(GasPriceList.BaseCost, result.GasConsumed);
        }
Exemplo n.º 3
0
        public void Contract_Transfer_To_Other_Contract_VM_Error()
        {
            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 contractTransferMessage = new ContractTransferMessage(
                uint160.One,
                uint160.Zero,
                10,
                (RuntimeObserver.Gas)(GasPriceList.BaseCost + 100000)
                );

            this.vm.Setup(v => v.ExecuteMethod(
                              It.IsAny <ISmartContractState>(),
                              It.IsAny <ExecutionContext>(),
                              contractTransferMessage.Method,
                              code,
                              typeName))
            .Returns(vmExecutionResult);

            this.contractStateRoot
            .Setup(sr => sr.GetCode(contractTransferMessage.To))
            .Returns(code);

            this.contractStateRoot
            .Setup(sr => sr.GetContractType(contractTransferMessage.To))
            .Returns(typeName);

            var state = new Mock <IState>();

            state.Setup(s => s.GetBalance(contractTransferMessage.From))
            .Returns(contractTransferMessage.Amount + 1);
            state.SetupGet(s => s.ContractState).Returns(this.contractStateRoot.Object);

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

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

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

            this.vm.Verify(
                v => v.ExecuteMethod(
                    It.IsAny <ISmartContractState>(),
                    It.IsAny <ExecutionContext>(),
                    contractTransferMessage.Method,
                    code,
                    typeName),
                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.BaseCost, result.GasConsumed);
        }
        public void Contract_Transfer_To_Other_P2PKH_Success()
        {
            // There is no code at the destination address, which causes a regular P2PKH transaction to be created
            var emptyCode = new byte[0];

            var contractTransferMessage = new ContractTransferMessage(
                uint160.One,
                uint160.Zero,
                10,
                (Gas)(GasPriceList.BaseCost + 100000)
                );

            // No code should be returned
            this.contractStateRoot
            .Setup(sr => sr.GetCode(contractTransferMessage.To))
            .Returns(emptyCode);

            var state = new Mock <IState>();

            // Return the sent amount + 1
            state.Setup(s => s.GetBalance(contractTransferMessage.From)).Returns(contractTransferMessage.Amount + 1);

            state.SetupGet(s => s.ContractState).Returns(this.contractStateRoot.Object);

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

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

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

            // Verify we get the code from the destination address' code cache
            this.contractStateRoot.Verify(s => s.GetCode(contractTransferMessage.To), Times.Once);

            // Verify the VM was NOT invoked
            this.vm.Verify(v => v.ExecuteMethod(It.IsAny <ISmartContractState>(), It.IsAny <MethodCall>(), It.IsAny <byte[]>(), It.IsAny <string>()), Times.Never);

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

            Assert.True(result.IsSuccess);
            Assert.NotNull(result.Success);
            Assert.Equal(contractTransferMessage.To, result.Success.ContractAddress);
            Assert.Null(result.Success.ExecutionResult);

            // No gas is consumed
            Assert.Equal((Gas)0, result.GasConsumed);
        }