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); }
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); }
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); }