Exemple #1
0
        public void Load_self_destruct()
        {
            TestState.CreateAccount(TestItem.PrivateKeyA.Address, 100.Ether());
            TestState.Commit(SpecProvider.GenesisSpec);
            TestState.CommitTree(0);

            byte[] initByteCode = Prepare.EvmCode
                                  .ForInitOf(
                Prepare.EvmCode
                .PushData(1)
                .Op(Instruction.SLOAD)
                .PushData(1)
                .Op(Instruction.EQ)
                .PushData(17)
                .Op(Instruction.JUMPI)
                .PushData(1)
                .PushData(1)
                .Op(Instruction.SSTORE)
                .PushData(21)
                .Op(Instruction.JUMP)
                .Op(Instruction.JUMPDEST)
                .PushData(0)
                .Op(Instruction.SELFDESTRUCT)
                .Op(Instruction.JUMPDEST)
                .Done)
                                  .Done;

            Address contractAddress = ContractAddress.From(TestItem.PrivateKeyA.Address, 0);

            byte[] byteCode1 = Prepare.EvmCode
                               .Call(contractAddress, 100000)
                               .Op(Instruction.STOP).Done;

            byte[] byteCode2 = Prepare.EvmCode
                               .Call(contractAddress, 100000)
                               .Op(Instruction.STOP).Done;

            long gasLimit = 1000000;

            EthereumEcdsa ecdsa  = new(1, LimboLogs.Instance);
            Transaction   initTx = Build.A.Transaction.WithCode(initByteCode).WithGasLimit(gasLimit).SignedAndResolved(ecdsa, TestItem.PrivateKeyA).TestObject;
            Transaction   tx1    = Build.A.Transaction.WithCode(byteCode1).WithGasLimit(gasLimit).WithNonce(1).SignedAndResolved(ecdsa, TestItem.PrivateKeyA).TestObject;
            Transaction   tx2    = Build.A.Transaction.WithCode(byteCode2).WithGasLimit(gasLimit).WithNonce(2).SignedAndResolved(ecdsa, TestItem.PrivateKeyA).TestObject;
            Block         block  = Build.A.Block.WithNumber(MainnetSpecProvider.MuirGlacierBlockNumber).WithTransactions(initTx, tx1, tx2).WithGasLimit(2 * gasLimit).TestObject;

            ParityLikeTxTracer initTracer = new(block, initTx, ParityTraceTypes.Trace | ParityTraceTypes.StateDiff);

            _processor.Execute(initTx, block.Header, initTracer);
            AssertStorage(new StorageCell(contractAddress, 1), 0);

            ParityLikeTxTracer tracer1 = new(block, tx1, ParityTraceTypes.Trace | ParityTraceTypes.StateDiff);

            _processor.Execute(tx1, block.Header, tracer1);
            AssertStorage(new StorageCell(contractAddress, 1), 1);

            ParityLikeTxTracer tracer2 = new(block, tx2, ParityTraceTypes.Trace | ParityTraceTypes.StateDiff);

            _processor.Execute(tx2, block.Header, tracer2);
            AssertStorage(new StorageCell(contractAddress, 1), 0);
        }
        public void Throws_on_theoretical_contract_crash()
        {
            var contractAddress = ContractAddress.From(_senderPublicKey.ToKvmAddress(), 0);

            _stateProvider.CreateAccount(contractAddress, 1000.Kat());
            var codeHash = _stateProvider.UpdateCode(Bytes.FromHexString("0x01"));

            _stateProvider.UpdateCodeHash(contractAddress, codeHash, _specProvider.GenesisSpec);
            _stateProvider.Commit(_specProvider.GenesisSpec);

            var delta = EntryUtils.PrepareSingleContractEntryDelta(null, _senderPublicKey, 0,
                                                                   "0x60016000526001601FF300");

            delta.PublicEntries[0].GasLimit        = 1_000_000L;
            delta.PublicEntries[0].ReceiverAddress = ByteString.Empty;
            delta.PublicEntries[0].Signature       = delta.PublicEntries[0]
                                                     .GenerateSignature(_cryptoContext, _senderPrivateKey, _signingContext);

            var tracer = Substitute.For <ITxTracer>();

            tracer.IsTracingReceipt.Returns(true);

            _executor.Execute(delta, tracer);

            tracer.Received().MarkAsFailed(contractAddress, 1_000_000L, Arg.Any <byte[]>(), null);
        }
Exemple #3
0
        public void Create_returns_code_hash()
        {
            byte[] deployedCode     = { 1, 2, 3 };
            Keccak deployedCodeHash = Keccak.Compute(deployedCode);

            byte[] initCode = Prepare.EvmCode
                              .ForInitOf(deployedCode).Done;

            byte[] createCode = Prepare.EvmCode
                                .Create(initCode, 0).Done;

            TestState.CreateAccount(TestItem.AddressC, 1.Ether());
            Keccak createCodeHash = TestState.UpdateCode(createCode);

            TestState.UpdateCodeHash(TestItem.AddressC, createCodeHash, Spec);

            byte[] code = Prepare.EvmCode
                          .Call(TestItem.AddressC, 50000)
                          .PushData(ContractAddress.From(TestItem.AddressC, 0))
                          .Op(Instruction.EXTCODEHASH)
                          .PushData(0)
                          .Op(Instruction.SSTORE)
                          .Done;

            Execute(code);
            AssertStorage(0, deployedCodeHash);
        }
        public async Task Tree_tracker_insert_leaves([ValueSource(nameof(InsertLeavesTestCases))] InsertLeavesTest test)
        {
            var address = TestItem.Addresses[0];
            var result  = await InitializeTestRpc(address);

            var          testRpc            = result.TestRpc;
            BaselineTree baselineTree       = BuildATree();
            var          fromContractAdress = ContractAddress.From(address, 0);
            var          baselineTreeHelper = new BaselineTreeHelper(testRpc.LogFinder, _baselineDb, _metadataBaselineDb, LimboNoErrorLogger.Instance);

            new BaselineTreeTracker(fromContractAdress, baselineTree, testRpc.BlockProcessor, baselineTreeHelper, testRpc.BlockFinder, LimboNoErrorLogger.Instance);

            var contract = new MerkleTreeSHAContract(_abiEncoder, fromContractAdress);

            UInt256 nonce = 1L;

            for (int i = 0; i < test.ExpectedTreeCounts.Length; i++)
            {
                nonce = await InsertLeavesFromArray(test.LeavesInTransactionsAndBlocks[i], nonce, testRpc, contract, address);

                await testRpc.AddBlock();

                Assert.AreEqual(test.ExpectedTreeCounts[i], baselineTree.Count);
            }
        }
Exemple #5
0
        public async Task deploy_bytecode_validates_input(string bytecode)
        {
            var spec = new SingleReleaseSpecProvider(ConstantinopleFix.Instance, 1);
            TestRpcBlockchain testRpc = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).Build(spec);

            testRpc.TestWallet.UnlockAccount(TestItem.Addresses[0], new SecureString());
            await testRpc.AddFunds(TestItem.Addresses[0], 1.Ether());

            BaselineModule baselineModule = CreateBaselineModule(testRpc);

            var result = await baselineModule.baseline_deployBytecode(
                TestItem.Addresses[0],
                bytecode); // invalid input

            result.Data.Should().Be(null);
            result.ErrorCode.Should().Be(ErrorCodes.InvalidInput);
            result.Result.Error.Should().NotBeNull();
            result.Result.ResultType.Should().Be(ResultType.Failure);
            await testRpc.AddBlock();

            testRpc.BlockTree.Head.Number.Should().Be(5);
            testRpc.BlockTree.Head.Transactions.Should().NotContain(tx => tx.IsContractCreation);

            var code = testRpc.StateReader
                       .GetCode(testRpc.BlockTree.Head.StateRoot, ContractAddress.From(TestItem.Addresses[0], 0));

            code.Should().BeEmpty();
        }
Exemple #6
0
        public void Create_and_revert_returns_zero()
        {
            byte[] deployedCode = { 1, 2, 3 };

            byte[] initCode = Prepare.EvmCode
                              .PushData(deployedCode.PadRight(32))
                              .PushData(0)
                              .Op(Instruction.MSTORE)
                              .PushData(3)
                              .PushData(0)
                              .Op(Instruction.RETURN)
                              .Done;

            byte[] createCode = Prepare.EvmCode
                                .Create(initCode, 0)
                                .Op(Instruction.REVERT).Done;

            TestState.CreateAccount(TestItem.AddressC, 1.Ether());
            Keccak createCodeHash = TestState.UpdateCode(createCode);

            TestState.UpdateCodeHash(TestItem.AddressC, createCodeHash, Spec);

            byte[] code = Prepare.EvmCode
                          .Call(TestItem.AddressC, 50000)
                          .PushData(ContractAddress.From(TestItem.AddressC, 0))
                          .Op(Instruction.EXTCODEHASH)
                          .PushData(0)
                          .Op(Instruction.SSTORE)
                          .Done;

            Execute(code);
            AssertStorage(0, Keccak.Zero);
        }
        public void Test_out_of_gas_non_existing_account()
        {
            byte[] salt         = { 4, 5, 6 };
            byte[] deployedCode = { 1, 2, 3 };

            byte[] initCode = Prepare.EvmCode
                              .ForInitOf(deployedCode).Done;

            byte[] createCode = Prepare.EvmCode
                                .Create2(initCode, salt, 0).Done;

            Address expectedAddress = ContractAddress.From(TestItem.AddressC, salt.PadLeft(32).AsSpan(), initCode.AsSpan());

            // TestState.CreateAccount(expectedAddress, 1.Ether()); <-- non-existing
            TestState.CreateAccount(TestItem.AddressC, 1.Ether());

            Keccak createCodeHash = TestState.UpdateCode(createCode);

            TestState.UpdateCodeHash(TestItem.AddressC, createCodeHash, Spec);

            byte[] code = Prepare.EvmCode
                          .Call(TestItem.AddressC, 32100)
                          .Done;

            Execute(code);

            TestState.AccountExists(expectedAddress).Should().BeFalse();
        }
        public void Test()
        {
            byte[] salt = { 4, 5, 6 };

            byte[] deployedCode = { 1, 2, 3 };

            byte[] initCode = Prepare.EvmCode
                              .ForInitOf(deployedCode).Done;

            byte[] createCode = Prepare.EvmCode
                                .Create2(initCode, salt, 0).Done;

            TestState.CreateAccount(TestItem.AddressC, 1.Ether());
            Keccak createCodeHash = TestState.UpdateCode(createCode);

            TestState.UpdateCodeHash(TestItem.AddressC, createCodeHash, Spec);

            byte[] code = Prepare.EvmCode
                          .Call(TestItem.AddressC, 50000)
                          .Done;

            Execute(code);

            Address expectedAddress = ContractAddress.From(TestItem.AddressC, salt.PadLeft(32).AsSpan(), initCode.AsSpan());

            AssertEip1014(expectedAddress, deployedCode);
        }
        public void Test_out_of_gas_existing_account()
        {
            byte[] salt         = { 4, 5, 6 };
            byte[] deployedCode = { 1, 2, 3 };

            byte[] initCode = Prepare.EvmCode
                              .ForInitOf(deployedCode).Done;

            byte[] createCode = Prepare.EvmCode
                                .Create2(initCode, salt, 0).Done;

            Address expectedAddress = ContractAddress.From(TestItem.AddressC, salt.PadLeft(32).AsSpan(), initCode.AsSpan());

            TestState.CreateAccount(expectedAddress, 1.Ether());
            TestState.CreateAccount(TestItem.AddressC, 1.Ether());

            Keccak createCodeHash = TestState.UpdateCode(createCode);

            TestState.UpdateCodeHash(TestItem.AddressC, createCodeHash, Spec);

            byte[] code = Prepare.EvmCode
                          .Call(TestItem.AddressC, 32100)
                          .Done;

            Execute(code);

            TestState.GetAccount(expectedAddress).Should().NotBeNull();
            TestState.GetAccount(expectedAddress).Balance.Should().Be(1.Ether());
            AssertEip1014(expectedAddress, Bytes.Empty);
        }
        public async Task deploy_bytecode_deploys_the_contract()
        {
            var spec = new SingleReleaseSpecProvider(ConstantinopleFix.Instance, 1);

            using TestRpcBlockchain testRpc = await TestRpcBlockchain.ForTest <BaseLineRpcBlockchain>(SealEngineType.NethDev).Build(spec);

            testRpc.TestWallet.UnlockAccount(TestItem.Addresses[0], new SecureString());
            BaselineModule baselineModule = CreateBaselineModule(testRpc);

            var result = await baselineModule.baseline_deployBytecode(
                TestItem.Addresses[0],
                File.ReadAllText("testBytecode"));

            result.Data.Should().NotBe(null);
            result.ErrorCode.Should().Be(0);
            result.Result.Error.Should().BeNull();
            result.Result.ResultType.Should().Be(ResultType.Success);

            await testRpc.AddBlock();

            testRpc.BlockTree.Head.Number.Should().Be(2);
            testRpc.BlockTree.Head.Transactions.Should().Contain(tx => tx.IsContractCreation);

            var code = testRpc.StateReader
                       .GetCode(testRpc.BlockTree.Head.StateRoot, ContractAddress.From(TestItem.Addresses[0], 0));

            code.Should().NotBeEmpty();
        }
        public async Task deploy_deploys_the_contract()
        {
            var spec = new SingleReleaseSpecProvider(ConstantinopleFix.Instance, 1);
            TestRpcBlockchain testRpc = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).Build(spec);

            testRpc.TestWallet.UnlockAccount(TestItem.Addresses[0], new SecureString());
            await testRpc.AddFunds(TestItem.Addresses[0], 1.Ether());

            DepositModule depositModule = new DepositModule(
                testRpc.TxPoolBridge,
                testRpc.LogFinder,
                new DepositConfig()
            {
                DepositContractAddress = TestItem.AddressA.ToString()
            },
                LimboLogs.Instance);

            var result = await depositModule.deposit_deploy(TestItem.Addresses[0]);

            result.Data.Should().NotBe(null);
            result.ErrorCode.Should().Be(0);
            result.Result.Error.Should().BeNull();
            result.Result.ResultType.Should().Be(ResultType.Success);

            await testRpc.AddBlock();

            testRpc.BlockTree.Head.Number.Should().Be(5);
            testRpc.BlockTree.Head.Transactions.Should().Contain(tx => tx.IsContractCreation);

            var code = testRpc.StateReader
                       .GetCode(testRpc.BlockTree.Head.StateRoot, ContractAddress.From(TestItem.Addresses[0], 0));

            code.Should().NotBeEmpty();
        }
        public void Can_estimate_with_single_call()
        {
            byte[] initByteCode = Prepare.EvmCode
                                  .ForInitOf(Bytes.FromHexString("6000")).Done;

            Address contractAddress = ContractAddress.From(TestItem.PrivateKeyA.Address, 0);

            byte[] byteCode = Prepare.EvmCode
                              .Call(contractAddress, 46179).Done;

            long gasLimit = 100000;

            Transaction initTx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, 1).WithInit(initByteCode).WithGasLimit(gasLimit).TestObject;
            Transaction tx     = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, 1).WithInit(byteCode).WithGasLimit(gasLimit).WithNonce(1).TestObject;
            Block       block  = Build.A.Block.WithNumber(MainNetSpecProvider.MuirGlacierBlockNumber).WithTransactions(tx).WithGasLimit(2 * gasLimit).TestObject;

            IntrinsicGasCalculator gasCalculator = new IntrinsicGasCalculator();
            long intrinsic = gasCalculator.Calculate(tx, MuirGlacier.Instance);

            _transactionProcessor.Execute(initTx, block.Header, NullTxTracer.Instance);

            EstimateGasTracer tracer = new EstimateGasTracer();

            _transactionProcessor.CallAndRestore(tx, block.Header, tracer);

            long actualIntrinsic = tx.GasLimit - tracer.IntrinsicGasAt;

            actualIntrinsic.Should().Be(53000);
            tracer.AdditionalGasRequired.Should().Be(1);
            tracer.GasSpent.Should().Be(53724);
            long estimate = tracer.GasSpent + tracer.AdditionalGasRequired;

            estimate.Should().Be(53725);
        }
        public async Task deploy_deploys_the_contract()
        {
            var spec = new SingleReleaseSpecProvider(ConstantinopleFix.Instance, 1);
            TestRpcBlockchain testRpc = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).Build(spec);

            testRpc.TestWallet.UnlockAccount(TestItem.Addresses[0], new SecureString());
            await testRpc.AddFunds(TestItem.Addresses[0], 1.Ether());

            BaselineModule baselineModule = new BaselineModule(
                testRpc.TxSender,
                testRpc.StateReader,
                testRpc.LogFinder,
                testRpc.BlockTree,
                _abiEncoder,
                _fileSystem,
                new MemDb(),
                LimboLogs.Instance);

            var result = await baselineModule.baseline_deploy(TestItem.Addresses[0], "MerkleTreeSHA");

            result.Data.Should().NotBe(null);
            result.ErrorCode.Should().Be(0);
            result.Result.Error.Should().BeNull();
            result.Result.ResultType.Should().Be(ResultType.Success);

            await testRpc.AddBlock();

            testRpc.BlockTree.Head.Number.Should().Be(5);
            testRpc.BlockTree.Head.Transactions.Should().Contain(tx => tx.IsContractCreation);

            var code = testRpc.StateReader
                       .GetCode(testRpc.BlockTree.Head.StateRoot, ContractAddress.From(TestItem.Addresses[0], 0));

            code.Should().NotBeEmpty();
        }
Exemple #14
0
        private (Address sender, Address recipient) ExtractSenderAndRecipient(PublicEntry entry)
        {
            var sender    = entry.SenderAddress.ToAddress();
            var recipient = entry.ReceiverAddress.ToAddress();

            if (entry.IsValidDeploymentEntry)
            {
                recipient = ContractAddress.From(sender, _stateProvider.GetNonce(sender));
            }

            return(sender, recipient);
        }
        private void RecoverReceiptData(IReleaseSpec releaseSpec, TxReceipt receipt, Block block, Transaction transaction, int transactionIndex, long gasUsedBefore)
        {
            receipt.BlockHash   = block.Hash;
            receipt.BlockNumber = block.Number;
            receipt.TxHash      = transaction.Hash;
            receipt.Index       = transactionIndex;
            receipt.Sender      = transaction.SenderAddress ?? _ecdsa.RecoverAddress(transaction, !releaseSpec.ValidateChainId);
            receipt.Recipient   = transaction.IsContractCreation ? null : transaction.To;

            // how would it be in CREATE2?
            receipt.ContractAddress = transaction.IsContractCreation ? ContractAddress.From(receipt.Sender, transaction.Nonce) : null;
            receipt.GasUsed         = receipt.GasUsedTotal - gasUsedBefore;
            if (receipt.StatusCode != StatusCode.Success)
            {
                receipt.StatusCode = receipt.Logs.Length == 0 ? StatusCode.Failure : StatusCode.Success;
            }
        }
Exemple #16
0
        public void Newly_created_empty_account_returns_empty_data_hash()
        {
            byte[] code = Prepare.EvmCode
                          .Create(Bytes.Empty, 0)
                          .PushData(ContractAddress.From(Recipient, 0))
                          .Op(Instruction.EXTCODEHASH)
                          .PushData(0)
                          .Op(Instruction.SSTORE)
                          .Done;

            Execute(code);

            // todo: so far EIP does not define whether it should be zero or empty data
            AssertStorage(0, Keccak.OfAnEmptyString);
            Assert.True(TestState.AccountExists(ContractAddress.From(Recipient, 0)),
                        "did not test the right thing - it was not a newly created empty account scenario");
        }
Exemple #17
0
                private async Task <ScenarioBuilder> DeployContractAsync()
                {
                    await ExecuteAntecedentIfNeeded();

                    _contractAddress = ContractAddress.From(_address, 0L);
                    byte[] bytecode = await GetContractBytecode("BadContract");

                    Transaction tx = new();

                    tx.Value         = 0;
                    tx.Data          = bytecode;
                    tx.GasLimit      = 1000000;
                    tx.GasPrice      = 20.GWei();
                    tx.SenderAddress = _address;
                    await _testRpcBlockchain.TxSender.SendTransaction(tx, TxHandlingOptions.ManagedNonce | TxHandlingOptions.PersistentBroadcast);

                    return(this);
                }
Exemple #18
0
        public async Task Tree_tracker_reorganization([ValueSource(nameof(ReorganizationTestCases))] ReorganizedInsertLeafTest test)
        {
            Address address = TestItem.Addresses[0];

            (TestRpcBlockchain TestRpc, BaselineModule BaselineModule)result = await InitializeTestRpc(address);

            TestRpcBlockchain  testRpc            = result.TestRpc;
            BaselineTree       baselineTree       = BuildATree();
            Address            contractAddress    = ContractAddress.From(address, 0L);
            BaselineTreeHelper baselineTreeHelper = new (testRpc.LogFinder, _baselineDb, _metadataBaselineDb, LimboNoErrorLogger.Instance);

            _ = new BaselineTreeTracker(contractAddress, baselineTree, testRpc.BlockProcessor, baselineTreeHelper, testRpc.BlockFinder, LimboNoErrorLogger.Instance);

            MerkleTreeSHAContract contract = new (_abiEncoder, contractAddress);

            for (int i = 0; i < test.LeavesInBlocksCounts.Length; i++)
            {
                InsertLeafFromArray(test.LeavesInTransactionsAndBlocks[i], testRpc, contract, address);

                await testRpc.AddBlock();

                Assert.AreEqual(test.LeavesInBlocksCounts[i], baselineTree.Count);
            }

            int initBlocksCount = 4;
            int allBlocksCount  = initBlocksCount + test.LeavesInBlocksCounts.Length;
            TestBlockProducer testRpcBlockProducer = (TestBlockProducer)testRpc.BlockProducer;
            Block             lastProducedBlock    = null;

            testRpcBlockProducer.BlockProduced += (o, e) => lastProducedBlock = e.Block;
            testRpcBlockProducer.BlockParent    = testRpc.BlockTree.FindHeader(allBlocksCount);

            InsertLeafFromArray(test.LeavesInMiddleOfReorganization, testRpc, contract, address);

            await testRpc.AddBlock(false);

            testRpcBlockProducer.BlockParent = lastProducedBlock.Header;

            InsertLeafFromArray(test.LeavesInAfterReorganization, testRpc, contract, address);

            await testRpc.AddBlock();

            Assert.AreEqual(test.FinalLeavesCount, baselineTree.Count);
        }
Exemple #19
0
        public async Task Tree_tracker_reorganization([ValueSource(nameof(ReorganizationTestCases))] ReorganizedInsertLeafTest test)
        {
            var address = TestItem.Addresses[0];
            var result  = await InitializeTestRpc(address);

            var          testRpc            = result.TestRpc;
            BaselineTree baselineTree       = BuildATree();
            var          fromContractAdress = ContractAddress.From(address, 0L);
            var          baselineTreeHelper = new BaselineTreeHelper(testRpc.LogFinder, _baselineDb, _metadataBaselineDb, LimboNoErrorLogger.Instance);

            new BaselineTreeTracker(fromContractAdress, baselineTree, testRpc.BlockProcessor, baselineTreeHelper, testRpc.BlockFinder, LimboNoErrorLogger.Instance);

            var     contract = new MerkleTreeSHAContract(_abiEncoder, fromContractAdress);
            UInt256 nonce    = 1L;

            for (int i = 0; i < test.LeavesInBlocksCounts.Length; i++)
            {
                nonce = await InsertLeafFromArray(test.LeavesInTransactionsAndBlocks[i], nonce, testRpc, contract, address);

                await testRpc.AddBlock();

                Assert.AreEqual(test.LeavesInBlocksCounts[i], baselineTree.Count);
            }

            var initBlocksCount = 4;
            var allBlocksCount  = initBlocksCount + test.LeavesInBlocksCounts.Length;

            testRpc.BlockProducer.BlockParent = testRpc.BlockTree.FindHeader(allBlocksCount);

            nonce = 1L;
            nonce = await InsertLeafFromArray(test.LeavesInMiddleOfReorganization, nonce, testRpc, contract, address);

            await testRpc.AddBlock(false);

            testRpc.BlockProducer.BlockParent = testRpc.BlockProducer.LastProducedBlock.Header;

            await InsertLeafFromArray(test.LeavesInAfterReorganization, nonce, testRpc, contract, address);

            await testRpc.AddBlock();

            Assert.AreEqual(test.FinalLeavesCount, baselineTree.Count);
        }
        public void Can_self_destruct()
        {
            var delta = EntryUtils.PrepareSingleContractEntryDelta(null, _senderPublicKey, 0,
                                                                   "0x730001020304050607080910111213141516171819ff");

            delta.PublicEntries[0].GasLimit        = 1_000_000L;
            delta.PublicEntries[0].ReceiverAddress = ByteString.Empty;
            delta.PublicEntries[0].Signature       = delta.PublicEntries[0]
                                                     .GenerateSignature(_cryptoContext, _senderPrivateKey, _signingContext);

            var tracer = Substitute.For <ITxTracer>();

            tracer.IsTracingReceipt.Returns(true);

            _executor.Execute(delta, tracer);

            var contractAddress = ContractAddress.From(_senderPublicKey.ToKvmAddress(), 0);

            tracer.Received().MarkAsSuccess(contractAddress, 34343, Arg.Any <byte[]>(), Arg.Any <LogEntry[]>());
        }
        public void Fails_when_not_enough_gas_for_code_deposit()
        {
            var delta = EntryUtils.PrepareSingleContractEntryDelta(null, _senderPublicKey, 0,
                                                                   "0x60016000526001601FF300");

            delta.PublicEntries[0].GasLimit        = 53369;
            delta.PublicEntries[0].ReceiverAddress = ByteString.Empty;
            delta.PublicEntries[0].Signature       = delta.PublicEntries[0]
                                                     .GenerateSignature(_cryptoContext, _senderPrivateKey, _signingContext);

            var tracer = Substitute.For <ITxTracer>();

            tracer.IsTracingReceipt.Returns(true);

            _executor.Execute(delta, tracer);

            var contractAddress = ContractAddress.From(_senderPublicKey.ToKvmAddress(), 0);

            tracer.Received().MarkAsFailed(contractAddress, 53369, Arg.Any <byte[]>(), null);
        }
        public void Can_deploy_code_read_only()
        {
            var delta = EntryUtils.PrepareSingleContractEntryDelta(null, _senderPublicKey, 0,
                                                                   "0x60016000526001601FF300");

            delta.PublicEntries[0].GasLimit        = 1_000_000L;
            delta.PublicEntries[0].ReceiverAddress = ByteString.Empty;
            delta.PublicEntries[0].Signature       = delta.PublicEntries[0]
                                                     .GenerateSignature(_cryptoContext, _senderPrivateKey, _signingContext);

            var tracer = Substitute.For <ITxTracer>();

            tracer.IsTracingReceipt.Returns(true);

            _executor.CallAndReset(delta, tracer);

            var contractAddress = ContractAddress.From(_senderPublicKey.ToKvmAddress(), 0);

            tracer.Received().MarkAsSuccess(contractAddress, 53370, Arg.Any <byte[]>(), Arg.Any <LogEntry[]>());
        }
        public void Does_not_crash_on_kvm_error()
        {
            // here we test a case when we deploy a contract where constructor throws invalid opcode EVM error
            // 0xfe is a bad opcode that immediately causes an EVM error
            var delta = EntryUtils.PrepareSingleContractEntryDelta(null, _senderPublicKey, 0, "0xfe");

            delta.PublicEntries[0].GasLimit  = 1_000_000L;
            delta.PublicEntries[0].Signature = delta.PublicEntries[0]
                                               .GenerateSignature(_cryptoContext, _senderPrivateKey, _signingContext);

            var tracer = Substitute.For <ITxTracer>();

            tracer.IsTracingReceipt.Returns(true);

            _executor.Execute(delta, tracer);

            var contractAddress = ContractAddress.From(_senderPublicKey.ToKvmAddress(), 0);

            tracer.Received().MarkAsFailed(contractAddress, 1_000_000L, Arg.Any <byte[]>(), "BadInstruction");
        }
        public void Test_out_of_gas_existing_account_with_storage()
        {
            byte[] salt         = { 4, 5, 6 };
            byte[] deployedCode = { 1, 2, 3 };

            byte[] initCode = Prepare.EvmCode
                              .ForInitOf(deployedCode).Done;

            byte[] createCode = Prepare.EvmCode
                                .Create2(initCode, salt, 0).Done;

            Address expectedAddress = ContractAddress.From(TestItem.AddressC, salt.PadLeft(32).AsSpan(), initCode.AsSpan());

            TestState.CreateAccount(expectedAddress, 1.Ether());
            Storage.Set(new StorageCell(expectedAddress, 1), new byte[] { 1, 2, 3, 4, 5 });
            Storage.Commit();
            Storage.CommitTrees();
            TestState.Commit(Spec);
            TestState.CommitTree();

            Keccak storageRoot = TestState.GetAccount(expectedAddress).StorageRoot;

            storageRoot.Should().NotBe(PatriciaTree.EmptyTreeHash);

            TestState.CreateAccount(TestItem.AddressC, 1.Ether());

            Keccak createCodeHash = TestState.UpdateCode(createCode);

            TestState.UpdateCodeHash(TestItem.AddressC, createCodeHash, Spec);

            byte[] code = Prepare.EvmCode
                          .Call(TestItem.AddressC, 32100)
                          .Done;

            Execute(code);

            TestState.GetAccount(expectedAddress).Should().NotBeNull();
            TestState.GetAccount(expectedAddress).Balance.Should().Be(1.Ether());
            TestState.GetAccount(expectedAddress).StorageRoot.Should().Be(storageRoot);
            AssertEip1014(expectedAddress, Bytes.Empty);
        }
        public void Regression_mainnet_226522()
        {
            _blockNumber = 1;
            Address     deployed    = ContractAddress.From(TestItem.AddressC, 0);
            StorageCell storageCell = new StorageCell(deployed, 1);

            byte[] deployedCode = new byte[106]; // cost is * 200

            byte[] initCode = Prepare.EvmCode
                              .PushData(1)
                              .PushData(1)
                              .Op(Instruction.SSTORE)
                              .PushData(0)
                              .PushData(1)
                              .Op(Instruction.SSTORE) // here we reset storage so we would get refund of 15000 gas
                              .ForInitOf(deployedCode).Done;

            byte[] createCode = Prepare.EvmCode
                                .Create(initCode, 0)
                                .PushData(0)
                                .Op(Instruction.SSTORE)
                                .Done;

            TestState.CreateAccount(TestItem.AddressC, 1.Ether());
            Keccak createCodeHash = TestState.UpdateCode(createCode);

            TestState.UpdateCodeHash(TestItem.AddressC, createCodeHash, Spec);

            byte[] code = Prepare.EvmCode
                          .Call(TestItem.AddressC, 32000 + 20003 + 20000 + 5000 + 500 + 0) // not enough
                          .Done;

            var receipt = Execute(code);

            byte[] result = Storage.Get(storageCell);
            Assert.AreEqual(new byte[] { 0 }, result, "storage reverted");
            Assert.AreEqual(83199, receipt.GasSpent, "with refund");

            byte[] returnData = Storage.Get(new StorageCell(TestItem.AddressC, 0));
            Assert.AreEqual(deployed.Bytes, returnData, "address returned");
        }
        public void Does_not_crash_on_kvm_exception()
        {
            // here we test a case when we deploy a contract where constructor throws StackUnderflowException
            // 0x01 is the ADD opcode which requires two items on the stack and stack is empty here
            // added here for full coverage as the errors (EVM) are handled differently in some cases (via .NET exceptions)
            var delta = EntryUtils.PrepareSingleContractEntryDelta(null, _senderPublicKey, 0, "0x01");

            delta.PublicEntries[0].GasLimit  = 1_000_000L;
            delta.PublicEntries[0].Signature = delta.PublicEntries[0]
                                               .GenerateSignature(_cryptoContext, _senderPrivateKey, _signingContext);

            var tracer = Substitute.For <ITxTracer>();

            tracer.IsTracingReceipt.Returns(true);

            _executor.Execute(delta, tracer);

            var contractAddress = ContractAddress.From(_senderPublicKey.ToKvmAddress(), 0);

            tracer.Received().MarkAsFailed(contractAddress, 1_000_000L, Arg.Any <byte[]>(), "StackUnderflow");
        }
        private void QuickFail(Transaction tx, BlockHeader block, ITxTracer txTracer, bool eip658NotEnabled,
                               string?reason)
        {
            block.GasUsed += tx.GasLimit;

            Address recipient = tx.To ?? ContractAddress.From(
                tx.SenderAddress ?? Address.Zero,
                _stateProvider.GetNonce(tx.SenderAddress ?? Address.Zero));

            if (txTracer.IsTracingReceipt)
            {
                Keccak?stateRoot = null;
                if (eip658NotEnabled)
                {
                    _stateProvider.RecalculateStateRoot();
                    stateRoot = _stateProvider.StateRoot;
                }

                txTracer.MarkAsFailed(recipient, tx.GasLimit, Array.Empty <byte>(), reason ?? "invalid", stateRoot);
            }
        }
        public async Task can_deposit_32eth()
        {
            var spec = new SingleReleaseSpecProvider(ConstantinopleFix.Instance, 1);
            TestRpcBlockchain testRpc = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).Build(spec);

            testRpc.TestWallet.UnlockAccount(TestItem.Addresses[0], new SecureString());
            await testRpc.AddFunds(TestItem.Addresses[0], 33.Ether());

            DepositModule depositModule = new DepositModule(
                testRpc.TxPoolBridge,
                testRpc.LogFinder,
                new DepositConfig(),
                LimboLogs.Instance);

            await depositModule.deposit_deploy(TestItem.Addresses[0]);

            await testRpc.AddBlock();

            var contractAddress = ContractAddress.From(TestItem.Addresses[0], 0);
            await depositModule.deposit_setContractAddress(contractAddress);

            var result = await depositModule.deposit_make(
                TestItem.Addresses[0],
                new byte[48],
                new byte[32],
                new byte[96]);

            result.Data.Should().NotBe(null);
            result.ErrorCode.Should().Be(0);
            result.Result.Error.Should().BeNull();
            result.Result.ResultType.Should().Be(ResultType.Success);

            await testRpc.AddBlock();

            testRpc.BlockTree.Head.Transactions.Should().Contain(tx => !tx.IsContractCreation);

            /* if status is 1 then it means that no revert has been made */
            testRpc.ReceiptStorage.Get(testRpc.BlockTree.Head)[0].StatusCode.Should().Be(1);
        }
        public async Task can_getLogs()
        {
            var spec = new SingleReleaseSpecProvider(ConstantinopleFix.Instance, 1);
            TestRpcBlockchain testRpc = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).Build(spec);

            testRpc.TestWallet.UnlockAccount(TestItem.Addresses[0], new SecureString());
            await testRpc.AddFunds(TestItem.Addresses[0], 33.Ether());

            DepositModule depositModule = new DepositModule(
                testRpc.TxPoolBridge,
                testRpc.LogFinder,
                new DepositConfig()
            {
                DepositContractAddress = TestItem.AddressA.ToString()
            },
                LimboLogs.Instance);

            await depositModule.deposit_deploy(TestItem.Addresses[0]);

            await testRpc.AddBlock();

            var contractAddress = ContractAddress.From(TestItem.Addresses[0], 0);
            await depositModule.deposit_setContractAddress(contractAddress);

            await depositModule.deposit_make(
                TestItem.Addresses[0],
                GetNonZeroBytes(48),
                GetNonZeroBytes(32),
                GetNonZeroBytes(96));

            await testRpc.AddBlock();

            var all = depositModule.deposit_getAll();

            all.Result.Data.Length.Should().Be(1);
            ulong amount = BinaryPrimitives.ReadUInt64LittleEndian(all.Result.Data[0].Amount);

            ((BigInteger)amount).Should().Be((BigInteger)32.Ether() / (BigInteger)1.GWei());
        }
        public void Can_estimate_with_destroy_refund_and_below_intrinsic()
        {
            byte[]  initByteCode    = Prepare.EvmCode.ForInitOf(Prepare.EvmCode.PushData(Address.Zero).Op(Instruction.SELFDESTRUCT).Done).Done;
            Address contractAddress = ContractAddress.From(TestItem.PrivateKeyA.Address, 0);

            byte[] byteCode = Prepare.EvmCode
                              .Call(contractAddress, 46179)
                              .Op(Instruction.STOP).Done;

            long gasLimit = 100000;

            Transaction initTx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithInit(initByteCode).WithGasLimit(gasLimit).TestObject;
            Transaction tx     = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithInit(byteCode).WithGasLimit(gasLimit).WithNonce(1).TestObject;
            Block       block  = Build.A.Block.WithNumber(MainnetSpecProvider.MuirGlacierBlockNumber).WithTransactions(tx).WithGasLimit(2 * gasLimit).TestObject;

            IntrinsicGasCalculator gasCalculator = new IntrinsicGasCalculator();
            long intrinsic = gasCalculator.Calculate(tx, MuirGlacier.Instance);

            _transactionProcessor.Execute(initTx, block.Header, NullTxTracer.Instance);

            EstimateGasTracer tracer     = new EstimateGasTracer();
            GethLikeTxTracer  gethTracer = new GethLikeTxTracer(GethTraceOptions.Default);

            _transactionProcessor.CallAndRestore(tx, block.Header, tracer);
            _transactionProcessor.CallAndRestore(tx, block.Header, gethTracer);
            TestContext.WriteLine(new EthereumJsonSerializer().Serialize(gethTracer.BuildResult(), true));

            long actualIntrinsic = tx.GasLimit - tracer.IntrinsicGasAt;

            actualIntrinsic.Should().Be(intrinsic);
            tracer.CalculateAdditionalGasRequired(tx).Should().Be(24080);
            tracer.GasSpent.Should().Be(35228L);
            long estimate = tracer.CalculateEstimate(tx);

            estimate.Should().Be(59308);

            ConfirmEnoughEstimate(tx, block, estimate);
        }