public void NoBalance_TxValue0_TransferValue0()
        {
            uint160 contractAddress = new uint160(1);

            // No balance
            var stateMock = new Mock <IStateRepository>();

            stateMock.Setup(x => x.GetUnspent(contractAddress)).Returns <ContractUnspentOutput>(null);

            // No tx value
            var txContextMock = new Mock <IContractTransactionContext>();

            txContextMock.SetupGet(p => p.TxOutValue).Returns(0);

            // No transfers
            var transfers = new List <TransferInfo>();

            var result = new SmartContractExecutionResult();

            Transaction internalTransaction = this.transferProcessor.Process(stateMock.Object, contractAddress, txContextMock.Object, transfers, false);

            // Ensure no state changes were made and no transaction has been added
            Assert.Null(internalTransaction);
            stateMock.Verify(x => x.SetUnspent(It.IsAny <uint160>(), It.IsAny <ContractUnspentOutput>()), Times.Never);
        }
        public void NoBalance_TxValue1_TransferValue0()
        {
            uint160 contractAddress = new uint160(1);

            // No balance
            var stateMock = new Mock <IStateRepository>();

            stateMock.Setup(x => x.GetUnspent(contractAddress)).Returns <ContractUnspentOutput>(null);

            // 100 tx value
            var txContextMock = new Mock <IContractTransactionContext>();

            txContextMock.SetupGet(p => p.TxOutValue).Returns(100);

            // No transfers
            var transfers = new List <TransferInfo>();

            var result = new SmartContractExecutionResult();

            Transaction internalTransaction = this.transferProcessor.Process(stateMock.Object, contractAddress, txContextMock.Object, transfers, false);

            // Ensure unspent was saved, but no condensing transaction was generated.
            Assert.Null(internalTransaction);
            stateMock.Verify(x => x.SetUnspent(contractAddress, It.IsAny <ContractUnspentOutput>()));
        }
        public void HasBalance_TxValue0_TransferValue1()
        {
            uint160 contractAddress = new uint160(1);
            uint160 receiverAddress = new uint160(2);

            // Has balance
            var stateMock = new Mock <IStateRepository>();

            stateMock.Setup(x => x.GetAccountState(contractAddress)).Returns(new AccountState
            {
                CodeHash    = new byte[32],
                StateRoot   = new byte[32],
                TypeName    = "Mock",
                UnspentHash = new byte[32]
            });
            stateMock.Setup(x => x.GetUnspent(contractAddress)).Returns(new ContractUnspentOutput
            {
                Hash  = new uint256(1),
                Nvout = 1,
                Value = 100
            });

            // no tx value
            var txContextMock = new Mock <IContractTransactionContext>();

            txContextMock.SetupGet(p => p.TxOutValue).Returns(0);
            txContextMock.SetupGet(p => p.Time).Returns(12345);

            // transfer 75
            var transferInfos = new List <TransferInfo>
            {
                new TransferInfo
                {
                    From  = contractAddress,
                    To    = receiverAddress,
                    Value = 75
                }
            };

            var result = new SmartContractExecutionResult();

            // Condensing tx generated. 1 input. 2 outputs for each receiver and contract.
            Transaction internalTransaction = this.transferProcessor.Process(stateMock.Object, contractAddress, txContextMock.Object, transferInfos, false);

            Assert.NotNull(internalTransaction);
            Assert.Equal(txContextMock.Object.Time, internalTransaction.Time);
            Assert.Single(internalTransaction.Inputs);
            Assert.Equal(2, internalTransaction.Outputs.Count);
            Assert.Equal(new uint256(1), internalTransaction.Inputs[0].PrevOut.Hash);
            Assert.Equal((uint)1, internalTransaction.Inputs[0].PrevOut.N);
            string output1Address = PayToPubkeyHashTemplate.Instance.ExtractScriptPubKeyParameters(internalTransaction.Outputs[0].ScriptPubKey).GetAddress(this.network).ToString();

            Assert.Equal(receiverAddress.ToAddress(this.network).Value, output1Address);
            Assert.Equal(75, internalTransaction.Outputs[0].Value);
            Assert.True(internalTransaction.Outputs[1].ScriptPubKey.IsSmartContractInternalCall());
            Assert.Equal(25, internalTransaction.Outputs[1].Value);

            // Ensure db updated
            stateMock.Verify(x => x.SetUnspent(contractAddress, It.Is <ContractUnspentOutput>(unspent => unspent.Value == 25)), Times.Once);
        }
        public void Transfers_With_0Value()
        {
            // Scenario where contract was not sent any funds, but did make a method call with value 0.
            var stateMock = new Mock <IStateRepository>();

            stateMock.Setup(x => x.GetCode(It.IsAny <uint160>())).Returns <byte[]>(null);
            var txContextMock = new Mock <IContractTransactionContext>();

            txContextMock.SetupGet(p => p.TxOutValue).Returns(0);
            var result = new SmartContractExecutionResult();

            var transferInfos = new List <TransferInfo>
            {
                new TransferInfo
                {
                    From  = uint160.One,
                    To    = new uint160(2),
                    Value = 0
                }
            };

            Transaction internalTransaction = this.transferProcessor.Process(stateMock.Object, uint160.One, txContextMock.Object, transferInfos, false);

            // No condensing transaction was generated.
            Assert.Null(internalTransaction);
        }
        public void NoBalance_TxValue0_TransferValue1()
        {
            uint160 contractAddress = new uint160(1);
            uint160 receiverAddress = new uint160(2);

            // No balance
            var stateMock = new Mock <IStateRepository>();

            stateMock.Setup(x => x.GetUnspent(contractAddress)).Returns <ContractUnspentOutput>(null);

            // No tx value
            var txContextMock = new Mock <IContractTransactionContext>();

            txContextMock.SetupGet(p => p.TxOutValue).Returns(0);

            // A transfer of 100
            var transferInfos = new List <TransferInfo>
            {
                new TransferInfo
                {
                    From  = contractAddress,
                    To    = receiverAddress,
                    Value = 100
                }
            };

            var result = new SmartContractExecutionResult();

            // This should be impossible - contract has no existing balance and didn't get sent anything so it cannot send value.
            // TODO: Could be more informative exception
            Assert.ThrowsAny <Exception>(() =>
            {
                Transaction internalTransaction = this.transferProcessor.Process(stateMock.Object, contractAddress, txContextMock.Object, transferInfos, false);
            });
        }
        public void NoBalance_TxValue1_TransferValue1()
        {
            uint160 contractAddress = new uint160(1);
            uint160 receiverAddress = new uint160(2);

            // No balance
            var stateMock = new Mock <IStateRepository>();

            stateMock.Setup(x => x.GetAccountState(contractAddress)).Returns(new AccountState
            {
                CodeHash    = new byte[32],
                StateRoot   = new byte[32],
                TypeName    = "Mock",
                UnspentHash = new byte[32]
            });
            stateMock.Setup(x => x.GetUnspent(contractAddress)).Returns <ContractUnspentOutput>(null);

            // tx value 100
            var txContextMock = new Mock <IContractTransactionContext>();

            txContextMock.SetupGet(p => p.TxOutValue).Returns(100);
            txContextMock.SetupGet(p => p.TransactionHash).Returns(new uint256(123));
            txContextMock.SetupGet(p => p.Nvout).Returns(1);
            txContextMock.SetupGet(p => p.Time).Returns(12345);

            // transfer 75
            var transferInfos = new List <TransferInfo>
            {
                new TransferInfo(contractAddress, receiverAddress, 75)
            };

            var result = new SmartContractExecutionResult();

            // Condensing tx generated. 1 input from tx and 2 outputs - 1 for each contract and receiver
            Transaction internalTransaction = this.transferProcessor.Process(stateMock.Object, contractAddress, txContextMock.Object, transferInfos, false);

            Assert.NotNull(internalTransaction);
            Assert.Equal(txContextMock.Object.Time, internalTransaction.Time);
            Assert.Single(internalTransaction.Inputs);
            Assert.Equal(2, internalTransaction.Outputs.Count);
            Assert.Equal(txContextMock.Object.TransactionHash, internalTransaction.Inputs[0].PrevOut.Hash);
            Assert.Equal(txContextMock.Object.Nvout, internalTransaction.Inputs[0].PrevOut.N);
            string output1Address = PayToPubkeyHashTemplate.Instance.ExtractScriptPubKeyParameters(internalTransaction.Outputs[0].ScriptPubKey).GetAddress(this.network).ToString();

            Assert.Equal(receiverAddress.ToBase58Address(this.network), output1Address);
            Assert.Equal(75, internalTransaction.Outputs[0].Value); // Note outputs are in descending order by value.
            Assert.True(internalTransaction.Outputs[1].ScriptPubKey.IsSmartContractInternalCall());
            Assert.Equal(25, internalTransaction.Outputs[1].Value);

            // Ensure db updated
            stateMock.Verify(x => x.SetUnspent(contractAddress, It.Is <ContractUnspentOutput>(unspent => unspent.Value == 25)), Times.Once);
        }
        public void HasBalance_TxValue1_TransferValue0()
        {
            uint160 contractAddress = new uint160(1);

            // Has balance
            var stateMock = new Mock <IStateRepository>();

            stateMock.Setup(x => x.GetAccountState(contractAddress)).Returns(new AccountState
            {
                CodeHash    = new byte[32],
                StateRoot   = new byte[32],
                TypeName    = "Mock",
                UnspentHash = new byte[32]
            });
            stateMock.Setup(x => x.GetUnspent(contractAddress)).Returns(new ContractUnspentOutput
            {
                Hash  = new uint256(1),
                Nvout = 1,
                Value = 100
            });

            // tx value 100
            var txContextMock = new Mock <IContractTransactionContext>();

            txContextMock.SetupGet(p => p.TxOutValue).Returns(100);
            txContextMock.SetupGet(p => p.TransactionHash).Returns(new uint256(123));
            txContextMock.SetupGet(p => p.Nvout).Returns(1);
            txContextMock.SetupGet(p => p.Time).Returns(12345);

            // no transfers
            var transferInfos = new List <TransferInfo>();

            var result = new SmartContractExecutionResult();

            // Condensing tx generated. 2 inputs. Current tx and stored spendable output. 1 output.
            Transaction internalTransaction = this.transferProcessor.Process(stateMock.Object, contractAddress, txContextMock.Object, transferInfos, false);

            Assert.NotNull(internalTransaction);
            Assert.Equal(txContextMock.Object.Time, internalTransaction.Time);
            Assert.Equal(2, internalTransaction.Inputs.Count);
            Assert.Single(internalTransaction.Outputs);
            Assert.Equal(txContextMock.Object.TransactionHash, internalTransaction.Inputs[0].PrevOut.Hash);
            Assert.Equal(txContextMock.Object.Nvout, internalTransaction.Inputs[0].PrevOut.N);
            Assert.Equal(new uint256(1), internalTransaction.Inputs[1].PrevOut.Hash);
            Assert.Equal((uint)1, internalTransaction.Inputs[1].PrevOut.N);
            Assert.True(internalTransaction.Outputs[0].ScriptPubKey.IsSmartContractInternalCall());
            Assert.Equal(200, internalTransaction.Outputs[0].Value);

            // Ensure db updated
            stateMock.Verify(x => x.SetUnspent(contractAddress, It.Is <ContractUnspentOutput>(unspent => unspent.Value == 200)), Times.Once);
        }
        public void TransferProcessor_NoBalance_NoTransfers()
        {
            // Scenario where contract was sent 0, doesn't yet have any UTXO assigned, and no transfers were made.
            var stateMock = new Mock <IContractState>();

            stateMock.Setup(x => x.GetCode(It.IsAny <uint160>())).Returns <byte[]>(null);
            var txContextMock = new Mock <ISmartContractTransactionContext>();

            txContextMock.SetupGet(p => p.TxOutValue).Returns(0);
            var         result = new SmartContractExecutionResult();
            Transaction internalTransaction = this.transferProcessor.Process(stateMock.Object, uint160.One, txContextMock.Object, new List <TransferInfo>(), false);

            // Ensure no state changes were made and no transaction has been added
            Assert.Null(internalTransaction);
        }
        public void TransferProcessor_NoBalance_ReceivedFunds()
        {
            // Scenario where contract was sent some funds, doesn't yet have any UTXO assigned, and no transfers were made.
            var stateMock = new Mock <IContractStateRepository>();

            stateMock.Setup(x => x.GetCode(It.IsAny <uint160>())).Returns <byte[]>(null);
            var txContextMock = new Mock <ISmartContractTransactionContext>();

            txContextMock.SetupGet(p => p.TxOutValue).Returns(100);
            var result = new SmartContractExecutionResult();

            this.transferProcessor.Process(stateMock.Object, uint160.One, txContextMock.Object, new List <TransferInfo>(), false);

            // Ensure unspent was saved, but no condensing transaction was generated.
            Assert.Null(result.InternalTransaction);
            stateMock.Verify(x => x.SetUnspent(new uint160(1), It.IsAny <ContractUnspentOutput>()));
        }
        public void TransferProcessor_NoBalance_NoTransfers()
        {
            // Scenario where contract was sent 0, doesn't yet have any UTXO assigned, and no transfers were made.
            var carrierSkeleton = SmartContractCarrier.CallContract(1, new uint160(1), "Test", 1, (Gas)100_000);
            var transaction     = new Transaction();

            transaction.AddOutput(0, new Script(carrierSkeleton.Serialize()));
            var carrier   = SmartContractCarrier.Deserialize(transaction);
            var stateMock = new Mock <IContractStateRepository>();

            stateMock.Setup(x => x.GetCode(It.IsAny <uint160>())).Returns <byte[]>(null);
            var txContextMock = new Mock <ISmartContractTransactionContext>();
            var result        = new SmartContractExecutionResult();

            this.transferProcessor.Process(carrier, stateMock.Object, txContextMock.Object, new List <TransferInfo>(), false);

            // Ensure no state changes were made and no transaction has been added
            Assert.Null(result.InternalTransaction);
        }
        public void TransferProcessor_NoBalance_ReceivedFunds()
        {
            // Scenario where contract was sent some funds, doesn't yet have any UTXO assigned, and no transfers were made.
            var carrierSkeleton = SmartContractCarrier.CallContract(1, new uint160(1), "Test", 1, (Gas)100_000);
            var transaction     = new Transaction();

            transaction.AddOutput(100, new Script(carrierSkeleton.Serialize()));
            var carrier   = SmartContractCarrier.Deserialize(transaction);
            var stateMock = new Mock <IContractStateRepository>();

            stateMock.Setup(x => x.GetCode(It.IsAny <uint160>())).Returns <byte[]>(null);
            var txContextMock = new Mock <ISmartContractTransactionContext>();
            var result        = new SmartContractExecutionResult();

            this.transferProcessor.Process(carrier, stateMock.Object, txContextMock.Object, new List <TransferInfo>(), false);

            // Ensure unspent was saved, but no condensing transaction was generated.
            Assert.Null(result.InternalTransaction);
            stateMock.Verify(x => x.SetUnspent(new uint160(1), It.IsAny <ContractUnspentOutput>()));
        }
        public void Transfers_Summed_Correctly()
        {
            uint160 contractAddress = new uint160(1);
            uint160 receiverAddress = new uint160(2);
            uint160 thirdAddress    = new uint160(3);

            // Has balance
            var stateMock = new Mock <IStateRepository>();

            stateMock.Setup(x => x.GetAccountState(contractAddress)).Returns(new AccountState
            {
                CodeHash    = new byte[32],
                StateRoot   = new byte[32],
                TypeName    = "Mock",
                UnspentHash = new byte[32]
            });
            stateMock.Setup(x => x.GetUnspent(contractAddress)).Returns(new ContractUnspentOutput
            {
                Hash  = new uint256(1),
                Nvout = 1,
                Value = 100
            });

            // no tx value
            var txContextMock = new Mock <IContractTransactionContext>();

            txContextMock.SetupGet(p => p.TxOutValue).Returns(0);
            txContextMock.SetupGet(p => p.Time).Returns(12345);

            // several transfers
            var transferInfos = new List <TransferInfo>
            {
                new TransferInfo(contractAddress, receiverAddress, 75),
                new TransferInfo(receiverAddress, contractAddress, 20),
                new TransferInfo(receiverAddress, thirdAddress, 5)
            };

            // End result should be Contract: 45, Receiver: 50, ThirdAddress: 5

            var result = new SmartContractExecutionResult();

            // Condensing tx generated. 1 input. 3 outputs with consolidated balances.
            Transaction internalTransaction = this.transferProcessor.Process(stateMock.Object, contractAddress, txContextMock.Object, transferInfos, false);

            Assert.NotNull(internalTransaction);
            Assert.Equal(txContextMock.Object.Time, internalTransaction.Time);
            Assert.Single(internalTransaction.Inputs);
            Assert.Equal(3, internalTransaction.Outputs.Count);
            Assert.Equal(new uint256(1), internalTransaction.Inputs[0].PrevOut.Hash);
            Assert.Equal((uint)1, internalTransaction.Inputs[0].PrevOut.N);
            string output1Address = PayToPubkeyHashTemplate.Instance.ExtractScriptPubKeyParameters(internalTransaction.Outputs[0].ScriptPubKey).GetAddress(this.network).ToString();

            Assert.Equal(receiverAddress.ToBase58Address(this.network), output1Address);
            Assert.Equal(50, internalTransaction.Outputs[0].Value);
            Assert.True(internalTransaction.Outputs[1].ScriptPubKey.IsSmartContractInternalCall());
            Assert.Equal(45, internalTransaction.Outputs[1].Value);
            string output3Address = PayToPubkeyHashTemplate.Instance.ExtractScriptPubKeyParameters(internalTransaction.Outputs[2].ScriptPubKey).GetAddress(this.network).ToString();

            Assert.Equal(thirdAddress.ToBase58Address(this.network), output3Address);
            Assert.Equal(5, internalTransaction.Outputs[2].Value);

            // Ensure db updated
            stateMock.Verify(x => x.SetUnspent(contractAddress, It.Is <ContractUnspentOutput>(unspent => unspent.Value == 45)), Times.Once);
        }