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.Ok(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.Success.Result, result.Success.ExecutionResult);
            Assert.Equal(GasPriceList.BaseCost, result.GasConsumed);
        }
        public void ExternalCall_Success()
        {
            var gasLimit          = (Gas)(GasPriceList.BaseCost + 100000);
            var vmExecutionResult = VmExecutionResult.Ok(true, "Test");

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

            var externalCallMessage = new ExternalCallMessage(
                uint160.Zero,
                uint160.Zero,
                0,
                gasLimit,
                new MethodCall("Test", null)
                );

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

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

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

            var state = new Mock <IState>();

            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, externalCallMessage);

            state.Verify(s => s.AddInitialTransfer(It.Is <TransferInfo>(t => t.Value == externalCallMessage.Amount && t.To == externalCallMessage.To)));

            this.contractStateRoot.Verify(sr => sr.GetCode(externalCallMessage.To), Times.Once);

            this.contractStateRoot.Verify(sr => sr.GetContractType(externalCallMessage.To), Times.Once);

            state.Verify(s => s.CreateSmartContractState(state.Object, It.IsAny <GasMeter>(), externalCallMessage.To, externalCallMessage, this.contractStateRoot.Object));

            this.vm.Verify(
                v => v.ExecuteMethod(It.IsAny <ISmartContractState>(), externalCallMessage.Method, code, typeName),
                Times.Once);

            Assert.True(result.IsSuccess);
            Assert.NotNull(result.Success);
            Assert.Equal(externalCallMessage.To, result.Success.ContractAddress);
            Assert.Equal(vmExecutionResult.Success.Result, result.Success.ExecutionResult);
            Assert.Equal(GasPriceList.BaseCost, result.GasConsumed);
        }
        public void Create_Contract_Success()
        {
            var contractTxData = new ContractTxData(1, 1, (Gas)1000, new byte[] { 0xAA, 0xBB, 0xCC });

            VmExecutionResult vmExecutionResult = VmExecutionResult.Ok(new object(), null);

            StateTransitionResult stateTransitionResult = StateTransitionResult.Ok((Gas)100, uint160.One, vmExecutionResult.Success.Result);

            var    fixture  = new ExecutorFixture(contractTxData);
            IState snapshot = fixture.State.Object.Snapshot();

            fixture.StateProcessor
            .Setup(s => s.Apply(snapshot, It.IsAny <ExternalCreateMessage>()))
            .Returns(stateTransitionResult);

            IStateRepository trackedMock = Mock.Of <IStateRepository>();

            fixture.ContractStateRoot.Setup(s => s.StartTracking()).Returns(trackedMock);

            var sut = new LocalExecutor(
                fixture.LoggerFactory,
                fixture.CallDataSerializer.Object,
                fixture.ContractStateRoot.Object,
                fixture.StateFactory.Object,
                fixture.StateProcessor.Object,
                fixture.ContractPrimitiveSerializer.Object);

            ILocalExecutionResult result = sut.Execute(fixture.ContractTransactionContext);

            fixture.CallDataSerializer.Verify(s => s.Deserialize(fixture.ContractTransactionContext.Data), Times.Once);

            fixture.StateFactory.Verify(sf => sf
                                        .Create(
                                            trackedMock,
                                            It.IsAny <IBlock>(),
                                            fixture.ContractTransactionContext.TxOutValue,
                                            fixture.ContractTransactionContext.TransactionHash),
                                        Times.Once);

            // We only apply the message to the snapshot.
            fixture.StateProcessor.Verify(sm => sm.Apply(snapshot, It.IsAny <ExternalCreateMessage>()), Times.Once);

            // Should never transition to the snapshot.
            fixture.State.Verify(sm => sm.TransitionTo(snapshot), Times.Never);

            // Should never save on the state
            fixture.ContractStateRoot.Verify(sr => sr.Commit(), Times.Never);

            Assert.Null(result.ErrorMessage);
            Assert.False(result.Revert);
            Assert.Equal(fixture.State.Object.InternalTransfers, result.InternalTransfers);
            Assert.Equal(stateTransitionResult.GasConsumed, result.GasConsumed);
            Assert.Equal(stateTransitionResult.Success.ExecutionResult, result.Return);
            Assert.Equal(fixture.State.Object.GetLogs(fixture.ContractPrimitiveSerializer.Object), result.Logs);
        }
        public void ExternalCreate_Success()
        {
            var newContractAddress = uint160.One;
            var vmExecutionResult  = VmExecutionResult.Ok(true, "Test");

            var externalCreateMessage = new ExternalCreateMessage(
                uint160.Zero,
                10,
                (Gas)(GasPriceList.BaseCost + 100000),
                new byte[0],
                null
                );

            this.vm.Setup(v => v.Create(this.contractStateRoot.Object, It.IsAny <ISmartContractState>(), externalCreateMessage.Code, externalCreateMessage.Parameters, null))
            .Returns(vmExecutionResult);

            var state = new Mock <IState>();

            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, externalCreateMessage);

            state.Verify(s => s.AddInitialTransfer(It.Is <TransferInfo>(t => t.Value == externalCreateMessage.Amount && t.To == newContractAddress)));

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

            this.contractStateRoot.Verify(s => s.CreateAccount(newContractAddress), Times.Once);

            state.Verify(s => s.CreateSmartContractState(state.Object, It.IsAny <GasMeter>(), newContractAddress, externalCreateMessage, this.contractStateRoot.Object));

            this.vm.Verify(v => v.Create(this.contractStateRoot.Object, It.IsAny <ISmartContractState>(), externalCreateMessage.Code, externalCreateMessage.Parameters, null), Times.Once);

            Assert.True(result.IsSuccess);
            Assert.NotNull(result.Success);
            Assert.Equal(newContractAddress, result.Success.ContractAddress);
            Assert.Equal(vmExecutionResult.Success.Result, result.Success.ExecutionResult);
            Assert.Equal(GasPriceList.CreateCost, result.GasConsumed);
        }
Ejemplo n.º 5
0
        public void Call_Contract_Success()
        {
            var parameters     = new object[] { };
            var contractTxData = new ContractTxData(1, 1, (RuntimeObserver.Gas) 1000, uint160.One, "TestMethod", parameters);

            VmExecutionResult vmExecutionResult = VmExecutionResult.Ok(new object(), null);

            StateTransitionResult stateTransitionResult = StateTransitionResult.Ok((RuntimeObserver.Gas) 100, uint160.One, vmExecutionResult.Success.Result);

            var    fixture  = new ExecutorFixture(contractTxData);
            IState snapshot = fixture.State.Object.Snapshot();

            fixture.StateProcessor
            .Setup(s => s.Apply(snapshot, It.IsAny <ExternalCallMessage>()))
            .Returns(stateTransitionResult);

            IStateRepository trackedMock = Mock.Of <IStateRepository>();

            fixture.ContractStateRoot.Setup(s => s.StartTracking()).Returns(trackedMock);

            var sut = new LocalExecutor(
                fixture.LoggerFactory,
                fixture.CallDataSerializer.Object,
                fixture.ContractStateRoot.Object,
                fixture.StateFactory.Object,
                fixture.StateProcessor.Object,
                fixture.ContractPrimitiveSerializer.Object);

            ILocalExecutionResult result = sut.Execute(fixture.ContractTransactionContext.BlockHeight,
                                                       fixture.ContractTransactionContext.Sender,
                                                       fixture.ContractTransactionContext.TxOutValue,
                                                       contractTxData);

            // Local executor used a tracked staterepository
            fixture.StateFactory.Verify(sf => sf
                                        .Create(
                                            trackedMock,
                                            It.IsAny <IBlock>(),
                                            fixture.ContractTransactionContext.TxOutValue,
                                            It.IsAny <uint256>()),
                                        Times.Once);

            // We only apply the message to the snapshot.
            fixture.StateProcessor.Verify(sm => sm.Apply(snapshot, It.Is <ExternalCallMessage>(m =>
                                                                                               m.Method.Name == contractTxData.MethodName &&
                                                                                               m.Method.Parameters == contractTxData.MethodParameters &&
                                                                                               m.Amount == fixture.ContractTransactionContext.TxOutValue &&
                                                                                               m.From == fixture.ContractTransactionContext.Sender &&
                                                                                               m.To == contractTxData.ContractAddress)), Times.Once);

            // Should never transition to the snapshot.
            fixture.State.Verify(sm => sm.TransitionTo(snapshot), Times.Never);

            // Should never save on the state
            fixture.ContractStateRoot.Verify(sr => sr.Commit(), Times.Never);

            Assert.Null(result.ErrorMessage);
            Assert.False(result.Revert);
            Assert.Equal <IReadOnlyList <TransferInfo> >(fixture.State.Object.InternalTransfers, result.InternalTransfers);
            Assert.Equal(stateTransitionResult.GasConsumed, result.GasConsumed);
            Assert.Equal(stateTransitionResult.Success.ExecutionResult, result.Return);
            Assert.Equal <IList <Log> >(fixture.State.Object.GetLogs(fixture.ContractPrimitiveSerializer.Object), result.Logs);
        }
        public void Call_Contract_Success()
        {
            var parameters     = new object[] { };
            var contractTxData = new ContractTxData(1, 1, (Gas)1000, uint160.One, "TestMethod", parameters);

            VmExecutionResult vmExecutionResult = VmExecutionResult.Ok(new object(), null);

            StateTransitionResult stateTransitionResult = StateTransitionResult.Ok((Gas)100, uint160.One, vmExecutionResult.Success.Result);

            var    fixture  = new ExecutorFixture(contractTxData);
            IState snapshot = fixture.State.Object.Snapshot();

            fixture.StateProcessor
            .Setup(s => s.Apply(snapshot, It.IsAny <ExternalCallMessage>()))
            .Returns(stateTransitionResult);

            var sut = new ContractExecutor(
                fixture.LoggerFactory,
                fixture.CallDataSerializer.Object,
                fixture.ContractStateRoot.Object,
                fixture.RefundProcessor.Object,
                fixture.TransferProcessor.Object,
                fixture.StateFactory.Object,
                fixture.StateProcessor.Object,
                fixture.ContractPrimitiveSerializer.Object);

            IContractExecutionResult result = sut.Execute(fixture.ContractTransactionContext);

            fixture.CallDataSerializer.Verify(s => s.Deserialize(fixture.ContractTransactionContext.Data), Times.Once);

            fixture.StateFactory.Verify(sf => sf
                                        .Create(
                                            fixture.ContractStateRoot.Object,
                                            It.IsAny <IBlock>(),
                                            fixture.ContractTransactionContext.TxOutValue,
                                            fixture.ContractTransactionContext.TransactionHash),
                                        Times.Once);

            // We only apply the message to the snapshot.
            fixture.StateProcessor.Verify(sm => sm.Apply(snapshot, It.Is <ExternalCallMessage>(m =>
                                                                                               m.Method.Name == contractTxData.MethodName &&
                                                                                               m.Method.Parameters == contractTxData.MethodParameters &&
                                                                                               m.Amount == fixture.ContractTransactionContext.TxOutValue &&
                                                                                               m.From == fixture.ContractTransactionContext.Sender &&
                                                                                               m.To == contractTxData.ContractAddress)), Times.Once);

            // Must transition to the snapshot.
            fixture.State.Verify(sm => sm.TransitionTo(snapshot), Times.Once);

            fixture.TransferProcessor.Verify(t => t
                                             .Process(
                                                 snapshot.ContractState,
                                                 stateTransitionResult.Success.ContractAddress,
                                                 fixture.ContractTransactionContext,
                                                 snapshot.InternalTransfers,
                                                 false),
                                             Times.Once);

            fixture.RefundProcessor.Verify(t => t
                                           .Process(
                                               contractTxData,
                                               fixture.MempoolFee,
                                               fixture.ContractTransactionContext.Sender,
                                               It.IsAny <Gas>(),
                                               false),
                                           Times.Once);

            Assert.Equal(contractTxData.ContractAddress, result.To);
            Assert.Null(result.NewContractAddress);
            Assert.Null(result.ErrorMessage);
            Assert.False(result.Revert);
            Assert.Equal(stateTransitionResult.GasConsumed, result.GasConsumed);
            Assert.Equal(stateTransitionResult.Success.ExecutionResult, result.Return);
            Assert.Equal(fixture.InternalTransaction, result.InternalTransaction);
            Assert.Equal(fixture.Fee, (Money)result.Fee);
            Assert.Equal(fixture.Refund, result.Refund);
            Assert.Equal(fixture.State.Object.GetLogs(fixture.ContractPrimitiveSerializer.Object), result.Logs);
        }
        public void InternalCall_Success()
        {
            // The difference between an internal and an external call:
            // - Internal call performs a balance check before execution
            // - Internal call appends a new internal transfer if successful
            var vmExecutionResult = VmExecutionResult.Ok(true, "Test");
            var code     = new byte[1];
            var typeName = "Test";

            var internalCallMessage = new InternalCallMessage(
                uint160.One,
                uint160.Zero,
                10,
                (Gas)(GasPriceList.BaseCost + 100000),
                new MethodCall("Test", new object[] {})
                );

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

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

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

            var state = new Mock <IState>();

            // Return the sent amount + 1
            state.Setup(s => s.GetBalance(internalCallMessage.From)).Returns(internalCallMessage.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, internalCallMessage);

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

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

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

            // Verify the VM was invoked
            this.vm.Verify(v => v.ExecuteMethod(It.IsAny <ISmartContractState>(), internalCallMessage.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 == internalCallMessage.From &&
                                                                         t.To == internalCallMessage.To &&
                                                                         t.Value == internalCallMessage.Amount)));

            Assert.True(result.IsSuccess);
            Assert.NotNull(result.Success);
            Assert.Equal(internalCallMessage.To, result.Success.ContractAddress);
            Assert.Equal(vmExecutionResult.Success.Result, result.Success.ExecutionResult);
            Assert.Equal(GasPriceList.BaseCost, result.GasConsumed);
        }
Ejemplo n.º 8
0
        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.Ok(true, "Test");
            var code     = new byte[1];
            var typeName = "Test";

            var internalCreateMessage = new InternalCreateMessage(
                uint160.Zero,
                10,
                (RuntimeObserver.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>(), It.IsAny <ExecutionContext>(), 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 <RuntimeObserver.IGasMeter>(), newContractAddress, internalCreateMessage, this.contractStateRoot.Object));

            // Verify the VM was invoked
            this.vm.Verify(v => v.Create(this.contractStateRoot.Object, It.IsAny <ISmartContractState>(), It.IsAny <ExecutionContext>(), 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.Success.Result, result.Success.ExecutionResult);
            Assert.Equal(GasPriceList.CreateCost, result.GasConsumed);
        }