diff --git a/rskj-core/src/main/resources/genesis/orchid-testnet.json b/rskj-core/src/main/resources/genesis/orchid-testnet.json index 47b83993075..43503a57d2f 100644 --- a/rskj-core/src/main/resources/genesis/orchid-testnet.json +++ b/rskj-core/src/main/resources/genesis/orchid-testnet.json @@ -13,7 +13,7 @@ "timestamp": "0x00", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "extraData": "0x434d272841", - "gasLimit": "0x4c4b40", + "gasLimit": "0x67c280", "difficulty": "0x0000100000", "coinbase": "0x3333333333333333333333333333333333333333", "minimumGasPrice": "0x00", diff --git a/rskj-core/src/main/resources/genesis/rsk-unittests.json b/rskj-core/src/main/resources/genesis/rsk-unittests.json index 59304f7d6af..fe6d1360b5a 100644 --- a/rskj-core/src/main/resources/genesis/rsk-unittests.json +++ b/rskj-core/src/main/resources/genesis/rsk-unittests.json @@ -120,7 +120,7 @@ "timestamp": "0x00", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "extraData": "0x686f727365", - "gasLimit": "0x2dc6c0", + "gasLimit": "0x5B8D80", "difficulty": "0x0000000001", "minimumGasPrice": "0x00", "coinbase": "0x3333333333333333333333333333333333333333" diff --git a/rskj-core/src/test/java/co/rsk/vm/opcode/TransientStorageDslTest.java b/rskj-core/src/test/java/co/rsk/vm/opcode/TransientStorageDslTest.java index af3c6a73211..a7d8349adaf 100644 --- a/rskj-core/src/test/java/co/rsk/vm/opcode/TransientStorageDslTest.java +++ b/rskj-core/src/test/java/co/rsk/vm/opcode/TransientStorageDslTest.java @@ -224,18 +224,91 @@ void testNoConstructorCodeCreateContext() throws FileNotFoundException, DslProce } @Test - void testDynamicCallCodeExecutionContext() throws FileNotFoundException, DslProcessorException { - DslParser parser = DslParser.fromResource("dsl/transaction_storage_rskip446/no_constructor_code_create_context.txt"); + void testDynamicExecutionContextSimpleScenario() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transaction_storage_rskip446/dynamic_execution_context_simple.txt"); World world = new World(); WorldDslProcessor processor = new WorldDslProcessor(world); processor.processCommands(parser); - String txTestTransientStorageCreateContextsContract = "txTestTransientStorageCreateContextsContract"; - assertTransactionReceiptWithStatus(world, txTestTransientStorageCreateContextsContract, "b01", true); + String txCallAndDelegateCallSimpleTest = "txCallAndDelegateCallSimpleTest"; + assertTransactionReceiptWithStatus(world, txCallAndDelegateCallSimpleTest, "b01", true); - String txNoConstructorCode = "txNoConstructorCode"; - TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txNoConstructorCode, "b02", true); + String txExecuteCallCode = "txExecuteCallCode"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txExecuteCallCode, "b02", true); Assertions.assertEquals(5, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txExecuteDelegateCall = "txExecuteDelegateCall"; + txReceipt = assertTransactionReceiptWithStatus(world, txExecuteDelegateCall, "b03", true); + Assertions.assertEquals(5, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testDynamicExecutionContextWithRevert() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transaction_storage_rskip446/dynamic_execution_context_with_revert.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txDynamicExecutionContextWithRevertTest = "txDynamicExecutionContextWithRevertTest"; + assertTransactionReceiptWithStatus(world, txDynamicExecutionContextWithRevertTest, "b01", true); + + String txExecuteCallCode = "txExecuteCallCode"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txExecuteCallCode, "b02", true); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txExecuteDelegateCall = "txExecuteDelegateCall"; + txReceipt = assertTransactionReceiptWithStatus(world, txExecuteDelegateCall, "b03", true); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txExecuteCall = "txExecuteCall"; + txReceipt = assertTransactionReceiptWithStatus(world, txExecuteCall, "b04", true); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testDynamicExecutionContextWithInvalid() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transaction_storage_rskip446/dynamic_execution_context_with_invalid.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txDynamicExecutionContextWithInvalidTest = "txDynamicExecutionContextWithInvalidTest"; + assertTransactionReceiptWithStatus(world, txDynamicExecutionContextWithInvalidTest, "b01", true); + + String txExecuteCallCode = "txExecuteCallCode"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txExecuteCallCode, "b02", true); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txExecuteDelegateCall = "txExecuteDelegateCall"; + txReceipt = assertTransactionReceiptWithStatus(world, txExecuteDelegateCall, "b03", true); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txExecuteCall = "txExecuteCall"; + txReceipt = assertTransactionReceiptWithStatus(world, txExecuteCall, "b04", true); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testDynamicExecutionContextWithStackOverflow() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transaction_storage_rskip446/dynamic_execution_context_with_stack_overflow.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txDynamicExecutionContextWithStackOverflowTest = "txDynamicExecutionContextWithStackOverflowTest"; + assertTransactionReceiptWithStatus(world, txDynamicExecutionContextWithStackOverflowTest, "b01", true); + + String txExecuteCallCode = "txExecuteCallCode"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txExecuteCallCode, "b02", true); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txExecuteDelegateCall = "txExecuteDelegateCall"; + txReceipt = assertTransactionReceiptWithStatus(world, txExecuteDelegateCall, "b03", true); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txExecuteCall = "txExecuteCall"; + txReceipt = assertTransactionReceiptWithStatus(world, txExecuteCall, "b04", true); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); } private static TransactionReceipt assertTransactionReceiptWithStatus(World world, String txName, String blockName, boolean withSuccess) { diff --git a/rskj-core/src/test/resources/dsl/transaction_storage_rskip446/dynamic_execution_context_simple.txt b/rskj-core/src/test/resources/dsl/transaction_storage_rskip446/dynamic_execution_context_simple.txt new file mode 100644 index 00000000000..36eac43363a --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transaction_storage_rskip446/dynamic_execution_context_simple.txt @@ -0,0 +1,147 @@ +comment + +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TestTransientStorageCallAndDelegateCall { + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function testCallCodeAndDelegateCall(uint256 useCallCode) external { + // Deploy the Callee contract + address calleeAddress = address(new Callee()); + uint256 success; + uint256 valueLoadedFrom0; + uint256 valueLoadedFrom1; + uint256 valueLoadedSstore2; + uint256 valueLoadedSstore3; + bytes4 executeSignature = bytes4(keccak256("execute()")); + + assembly { + tstore(0, 420) + let availablePointer := mload(0x40) + mstore(availablePointer, executeSignature) + + // If useCallCode is 0, execute callCode otherwise execute delegateCall + switch useCallCode + case 1 { + success := callcode(gas(), calleeAddress, 0, availablePointer, 0x4, availablePointer, 0x20) + } + default { + success := delegatecall(gas(), calleeAddress, availablePointer, 0x4, availablePointer, 0x20) + } + valueLoadedFrom0 := tload(0) + valueLoadedSstore2 := sload(2) + valueLoadedSstore3 := sload(3) + valueLoadedFrom1 := tload(1) + } + + checkReturnValueExpected(success, 'Checking result callee execution', 1); + checkReturnValueExpected(valueLoadedFrom0, 'Checking value from tload 0', 420); + checkReturnValueExpected(valueLoadedSstore2, 'Checking value from sstore 2', 420); + checkReturnValueExpected(valueLoadedSstore3, 'Checking value from sstore 3', 69); + checkReturnValueExpected(valueLoadedFrom1, 'Checking value from tload 1', 69); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract Callee { + + function execute() external { + assembly { + sstore(2, tload(0)) + tstore(1, 69) + sstore(3, tload(1)) + } + } +} + +// CONTRACT BYTECODE + +TestTransientStorageCallAndDelegateCall: 6080604052348015600e575f5ffd5b5061048e8061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063a61face91461002d575b5f5ffd5b610047600480360381019061004291906102ec565b610049565b005b5f604051610056906102a9565b604051809103905ff08015801561006f573d5f5f3e3d5ffd5b5090505f5f5f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d60405181815288600181146100bf576020826004848c5af497506100cc565b6020826004845f8d5af297505b505f5c95506002549350600354925060015c945050610122866040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e8152506001610232565b610164856040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a4610232565b6101a6836040518060400160405280601c81526020017f436865636b696e672076616c75652066726f6d207373746f72652032000000008152506101a4610232565b6101e7826040518060400160405280601c81526020017f436865636b696e672076616c75652066726f6d207373746f72652033000000008152506045610232565b610228846040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152506045610232565b5050505050505050565b80830361026a577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16102a4565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161029b929190610396565b60405180910390a15b505050565b6094806103c583390190565b5f5ffd5b5f819050919050565b6102cb816102b9565b81146102d5575f5ffd5b50565b5f813590506102e6816102c2565b92915050565b5f60208284031215610301576103006102b5565b5b5f61030e848285016102d8565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61035982610317565b6103638185610321565b9350610373818560208601610331565b61037c8161033f565b840191505092915050565b610390816102b9565b82525050565b5f6040820190508181035f8301526103ae818561034f565b90506103bd6020830184610387565b939250505056fe6080604052348015600e575f5ffd5b50607a80601a5f395ff3fe6080604052348015600e575f5ffd5b50600436106026575f3560e01c80636146195414602a575b5f5ffd5b60306032565b005b5f5c600255604560015d60015c60035556fea26469706673582212201771c67495697664bc8f0b297a683b4e7dbb7e31feaf9cf735faf209a14d64fa64736f6c634300081c0033a2646970667358221220ce4a7e6da5344a1d5a34ebef6c0267ac15796a3a9529427da9ba17a9cc4bee0864736f6c634300081c0033 + +a61face9: testCallCodeAndDelegateCall(uint256) + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TestTransientStorageCallAndDelegateCall contract +transaction_build txCallAndDelegateCallSimpleTest + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f5ffd5b5061048e8061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063a61face91461002d575b5f5ffd5b610047600480360381019061004291906102ec565b610049565b005b5f604051610056906102a9565b604051809103905ff08015801561006f573d5f5f3e3d5ffd5b5090505f5f5f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d60405181815288600181146100bf576020826004848c5af497506100cc565b6020826004845f8d5af297505b505f5c95506002549350600354925060015c945050610122866040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e8152506001610232565b610164856040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a4610232565b6101a6836040518060400160405280601c81526020017f436865636b696e672076616c75652066726f6d207373746f72652032000000008152506101a4610232565b6101e7826040518060400160405280601c81526020017f436865636b696e672076616c75652066726f6d207373746f72652033000000008152506045610232565b610228846040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152506045610232565b5050505050505050565b80830361026a577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16102a4565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161029b929190610396565b60405180910390a15b505050565b6094806103c583390190565b5f5ffd5b5f819050919050565b6102cb816102b9565b81146102d5575f5ffd5b50565b5f813590506102e6816102c2565b92915050565b5f60208284031215610301576103006102b5565b5b5f61030e848285016102d8565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61035982610317565b6103638185610321565b9350610373818560208601610331565b61037c8161033f565b840191505092915050565b610390816102b9565b82525050565b5f6040820190508181035f8301526103ae818561034f565b90506103bd6020830184610387565b939250505056fe6080604052348015600e575f5ffd5b50607a80601a5f395ff3fe6080604052348015600e575f5ffd5b50600436106026575f3560e01c80636146195414602a575b5f5ffd5b60306032565b005b5f5c600255604560015d60015c60035556fea26469706673582212201771c67495697664bc8f0b297a683b4e7dbb7e31feaf9cf735faf209a14d64fa64736f6c634300081c0033a2646970667358221220ce4a7e6da5344a1d5a34ebef6c0267ac15796a3a9529427da9ba17a9cc4bee0864736f6c634300081c0033 + gas 1000000 + build + +# Create block to hold txCallAndDelegateCallSimpleTest transaction +block_build b01 + parent g00 + transactions txCallAndDelegateCallSimpleTest + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txExecuteCallCode transaction +transaction_build txExecuteCallCode + sender acc1 + nonce 1 + contract txCallAndDelegateCallSimpleTest + value 0 + data a61face90000000000000000000000000000000000000000000000000000000000000001 + gas 1000000 + build + +# Create block to hold txExecuteCallCode transaction +block_build b02 + parent b01 + transactions txExecuteCallCode + gasLimit 2000000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 + +# Create transaction to execute txExecuteDelegateCall transaction +transaction_build txExecuteDelegateCall + sender acc1 + nonce 2 + contract txCallAndDelegateCallSimpleTest + value 0 + data a61face90000000000000000000000000000000000000000000000000000000000000000 + gas 1000000 + build + +# Create block to hold txExecuteDelegateCall transaction +block_build b03 + parent b02 + transactions txExecuteDelegateCall + gasLimit 2000000 + build + +# Connect block +block_connect b03 + +# Check b03 is best block +assert_best b03 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transaction_storage_rskip446/dynamic_execution_context_with_invalid.txt b/rskj-core/src/test/resources/dsl/transaction_storage_rskip446/dynamic_execution_context_with_invalid.txt new file mode 100644 index 00000000000..96321e7ead6 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transaction_storage_rskip446/dynamic_execution_context_with_invalid.txt @@ -0,0 +1,166 @@ +comment +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TestTStorageDynamicExecutionContextWithInvalid{ + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function testCallSelectingContractCallOpcode(uint256 contractCallSelector) external { + // Deploy the Callee contract + address calleeAddress = address(new Callee()); + uint256 success; + uint256 valueLoadedFrom0; + uint256 valueLoadedFrom1; + bytes4 executeSignature = bytes4(keccak256("execute()")); + + assembly { + tstore(0, 420) + tstore(1, 420) + + let availablePointer := mload(0x40) + mstore(availablePointer, executeSignature) + // If useDelegateCall is greater than 0, execute delegateCall otherwise execute callCode + switch contractCallSelector + case 0 { + success := callcode(0xFF, calleeAddress, 0, availablePointer, 0x4, availablePointer, 0x20) + } + case 1 { + success := delegatecall(0xFF, calleeAddress, availablePointer, 0x4, availablePointer, 0x20) + } + default { + success := call(0xFF, calleeAddress, 0, availablePointer, 0x4, availablePointer, 0x20) + } + valueLoadedFrom0 := tload(0) + valueLoadedFrom1 := tload(1) + } + + checkReturnValueExpected(success, 'Checking result callee execution', 0); + checkReturnValueExpected(valueLoadedFrom0, 'Checking value from tload 0', 420); + checkReturnValueExpected(valueLoadedFrom1, 'Checking value from tload 1', 420); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract Callee { + + function execute() external { + assembly { + tstore(1, 69) + invalid() + } + } +} + +// CONTRACT BYTECODE + +TestTStorageDynamicExecutionContextWithInvalid: 6080604052348015600e575f5ffd5b506104138061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c80639823c4061461002d575b5f5ffd5b6100476004803603810190610042919061027c565b610049565b005b5f60405161005690610239565b604051809103905ff08015801561006f573d5f5f3e3d5ffd5b5090505f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d6101a460015d604051818152865f81146100cc57600181146100de576020826004845f8b60fff195506100eb565b6020826004845f8b60fff295506100eb565b6020826004848a60fff495505b505f5c935060015c925050610136846040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e8152505f6101c2565b610178836040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a46101c2565b6101ba826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152506101a46101c2565b505050505050565b8083036101fa577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610234565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161022b929190610326565b60405180910390a15b505050565b60898061035583390190565b5f5ffd5b5f819050919050565b61025b81610249565b8114610265575f5ffd5b50565b5f8135905061027681610252565b92915050565b5f6020828403121561029157610290610245565b5b5f61029e84828501610268565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6102e9826102a7565b6102f381856102b1565b93506103038185602086016102c1565b61030c816102cf565b840191505092915050565b61032081610249565b82525050565b5f6040820190508181035f83015261033e81856102df565b905061034d6020830184610317565b939250505056fe6080604052348015600e575f5ffd5b50606f80601a5f395ff3fe6080604052348015600e575f5ffd5b50600436106026575f3560e01c80636146195414602a575b5f5ffd5b60306032565b005b604560015dfefea26469706673582212207c61e75cb53c4ad046d081a86c932bf15e83580e0d3ceae3fa417efcab11607e64736f6c634300081c0033a264697066735822122099e5211521504bd8cd35e3f045924e1065174f722e1fb24d137b65571be0fbb364736f6c634300081c0033 + +9823c406: testCallSelectingContractCallOpcode(uint256) + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TestTransientStorageCallAndDelegateCall contract +transaction_build txDynamicExecutionContextWithInvalidTest + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f5ffd5b506104138061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c80639823c4061461002d575b5f5ffd5b6100476004803603810190610042919061027c565b610049565b005b5f60405161005690610239565b604051809103905ff08015801561006f573d5f5f3e3d5ffd5b5090505f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d6101a460015d604051818152865f81146100cc57600181146100de576020826004845f8b60fff195506100eb565b6020826004845f8b60fff295506100eb565b6020826004848a60fff495505b505f5c935060015c925050610136846040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e8152505f6101c2565b610178836040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a46101c2565b6101ba826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152506101a46101c2565b505050505050565b8083036101fa577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610234565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161022b929190610326565b60405180910390a15b505050565b60898061035583390190565b5f5ffd5b5f819050919050565b61025b81610249565b8114610265575f5ffd5b50565b5f8135905061027681610252565b92915050565b5f6020828403121561029157610290610245565b5b5f61029e84828501610268565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6102e9826102a7565b6102f381856102b1565b93506103038185602086016102c1565b61030c816102cf565b840191505092915050565b61032081610249565b82525050565b5f6040820190508181035f83015261033e81856102df565b905061034d6020830184610317565b939250505056fe6080604052348015600e575f5ffd5b50606f80601a5f395ff3fe6080604052348015600e575f5ffd5b50600436106026575f3560e01c80636146195414602a575b5f5ffd5b60306032565b005b604560015dfefea26469706673582212207c61e75cb53c4ad046d081a86c932bf15e83580e0d3ceae3fa417efcab11607e64736f6c634300081c0033a264697066735822122099e5211521504bd8cd35e3f045924e1065174f722e1fb24d137b65571be0fbb364736f6c634300081c0033 + gas 1000000 + build + +# Create block to hold txDynamicExecutionContextWithInvalidTest transaction +block_build b01 + parent g00 + transactions txDynamicExecutionContextWithInvalidTest + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txExecuteCallCode transaction +transaction_build txExecuteCallCode + sender acc1 + nonce 1 + contract txDynamicExecutionContextWithInvalidTest + value 0 + data 9823c4060000000000000000000000000000000000000000000000000000000000000000 + gas 500000 + build + +# Create block to hold txExecuteCallCode transaction +block_build b02 + parent b01 + transactions txExecuteCallCode + gasLimit 550000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 + +# Create transaction to execute txExecuteDelegateCall transaction +transaction_build txExecuteDelegateCall + sender acc1 + nonce 2 + contract txDynamicExecutionContextWithInvalidTest + value 0 + data 9823c4060000000000000000000000000000000000000000000000000000000000000001 + gas 500000 + build + +# Create block to hold txExecuteDelegateCall transaction +block_build b03 + parent b02 + transactions txExecuteDelegateCall + gasLimit 550000 + build + +# Connect block +block_connect b03 + +# Check b03 is best block +assert_best b03 + +# Create transaction to execute txExecuteDelegateCall transaction +transaction_build txExecuteCall + sender acc1 + nonce 3 + contract txDynamicExecutionContextWithInvalidTest + value 0 + data 9823c4060000000000000000000000000000000000000000000000000000000000000002 + gas 500000 + build + +# Create block to hold txExecuteCall transaction +block_build b04 + parent b03 + transactions txExecuteCall + gasLimit 550000 + build + +# Connect block +block_connect b04 + +# Check b04 is best block +assert_best b04 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transaction_storage_rskip446/dynamic_execution_context_with_revert.txt b/rskj-core/src/test/resources/dsl/transaction_storage_rskip446/dynamic_execution_context_with_revert.txt new file mode 100644 index 00000000000..39ba6b71be9 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transaction_storage_rskip446/dynamic_execution_context_with_revert.txt @@ -0,0 +1,166 @@ +comment +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TestTStorageDynamicExecutionContextWithRevert { + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function testCallSelectingContractCallOpcode(uint256 contractCallSelector) external { + // Deploy the Callee contract + address calleeAddress = address(new Callee()); + uint256 success; + uint256 valueLoadedFrom0; + uint256 valueLoadedFrom1; + bytes4 executeSignature = bytes4(keccak256("execute()")); + + assembly { + tstore(0, 420) + tstore(1, 420) + + let availablePointer := mload(0x40) + mstore(availablePointer, executeSignature) + // If useDelegateCall is greater than 0, execute delegateCall otherwise execute callCode + switch contractCallSelector + case 0 { + success := callcode(gas(), calleeAddress, 0, availablePointer, 0x4, availablePointer, 0x20) + } + case 1 { + success := delegatecall(gas(), calleeAddress, availablePointer, 0x4, availablePointer, 0x20) + } + default { + success := call(gas(), calleeAddress, 0, availablePointer, 0x4, availablePointer, 0x20) + } + valueLoadedFrom0 := tload(0) + valueLoadedFrom1 := tload(1) + } + + checkReturnValueExpected(success, 'Checking result callee execution', 0); + checkReturnValueExpected(valueLoadedFrom0, 'Checking value from tload 0', 420); + checkReturnValueExpected(valueLoadedFrom1, 'Checking value from tload 1', 420); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract Callee { + + function execute() external { + assembly { + tstore(1, 69) + revert(0,0) + } + } +} + +// CONTRACT BYTECODE + +TestTStorageDynamicExecutionContextWithRevert: 6080604052348015600e575f5ffd5b506104128061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c80639823c4061461002d575b5f5ffd5b61004760048036038101906100429190610279565b610049565b005b5f60405161005690610236565b604051809103905ff08015801561006f573d5f5f3e3d5ffd5b5090505f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d6101a460015d604051818152865f81146100cb57600181146100dc576020826004845f8b5af195506100e8565b6020826004845f8b5af295506100e8565b6020826004848a5af495505b505f5c935060015c925050610133846040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e8152505f6101bf565b610175836040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a46101bf565b6101b7826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152506101a46101bf565b505050505050565b8083036101f7577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610231565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f8284604051610228929190610323565b60405180910390a15b505050565b608b8061035283390190565b5f5ffd5b5f819050919050565b61025881610246565b8114610262575f5ffd5b50565b5f813590506102738161024f565b92915050565b5f6020828403121561028e5761028d610242565b5b5f61029b84828501610265565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6102e6826102a4565b6102f081856102ae565b93506103008185602086016102be565b610309816102cc565b840191505092915050565b61031d81610246565b82525050565b5f6040820190508181035f83015261033b81856102dc565b905061034a6020830184610314565b939250505056fe6080604052348015600e575f5ffd5b50607180601a5f395ff3fe6080604052348015600e575f5ffd5b50600436106026575f3560e01c80636146195414602a575b5f5ffd5b60306032565b005b604560015d5f5ffdfea264697066735822122012b2acf84430846181c2090e00f142a45789288a3094ef935604fa5b2cb44e1f64736f6c634300081c0033a26469706673582212200323b022738aab6530f9ff3cde3c2b7774d6dc76d7ee932e8bd4edb7b517a59064736f6c634300081c0033 + +9823c406: testCallSelectingContractCallOpcode(uint256) + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TestTransientStorageCallAndDelegateCall contract +transaction_build txDynamicExecutionContextWithRevertTest + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f5ffd5b506104128061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c80639823c4061461002d575b5f5ffd5b61004760048036038101906100429190610279565b610049565b005b5f60405161005690610236565b604051809103905ff08015801561006f573d5f5f3e3d5ffd5b5090505f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d6101a460015d604051818152865f81146100cb57600181146100dc576020826004845f8b5af195506100e8565b6020826004845f8b5af295506100e8565b6020826004848a5af495505b505f5c935060015c925050610133846040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e8152505f6101bf565b610175836040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a46101bf565b6101b7826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152506101a46101bf565b505050505050565b8083036101f7577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610231565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f8284604051610228929190610323565b60405180910390a15b505050565b608b8061035283390190565b5f5ffd5b5f819050919050565b61025881610246565b8114610262575f5ffd5b50565b5f813590506102738161024f565b92915050565b5f6020828403121561028e5761028d610242565b5b5f61029b84828501610265565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6102e6826102a4565b6102f081856102ae565b93506103008185602086016102be565b610309816102cc565b840191505092915050565b61031d81610246565b82525050565b5f6040820190508181035f83015261033b81856102dc565b905061034a6020830184610314565b939250505056fe6080604052348015600e575f5ffd5b50607180601a5f395ff3fe6080604052348015600e575f5ffd5b50600436106026575f3560e01c80636146195414602a575b5f5ffd5b60306032565b005b604560015d5f5ffdfea264697066735822122012b2acf84430846181c2090e00f142a45789288a3094ef935604fa5b2cb44e1f64736f6c634300081c0033a26469706673582212200323b022738aab6530f9ff3cde3c2b7774d6dc76d7ee932e8bd4edb7b517a59064736f6c634300081c0033 + gas 1000000 + build + +# Create block to hold txDynamicExecutionContextWithRevertTest transaction +block_build b01 + parent g00 + transactions txDynamicExecutionContextWithRevertTest + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txExecuteCallCode transaction +transaction_build txExecuteCallCode + sender acc1 + nonce 1 + contract txDynamicExecutionContextWithRevertTest + value 0 + data 9823c4060000000000000000000000000000000000000000000000000000000000000000 + gas 500000 + build + +# Create block to hold txExecuteCallCode transaction +block_build b02 + parent b01 + transactions txExecuteCallCode + gasLimit 550000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 + +# Create transaction to execute txExecuteDelegateCall transaction +transaction_build txExecuteDelegateCall + sender acc1 + nonce 2 + contract txDynamicExecutionContextWithRevertTest + value 0 + data 9823c4060000000000000000000000000000000000000000000000000000000000000001 + gas 500000 + build + +# Create block to hold txExecuteDelegateCall transaction +block_build b03 + parent b02 + transactions txExecuteDelegateCall + gasLimit 550000 + build + +# Connect block +block_connect b03 + +# Check b03 is best block +assert_best b03 + +# Create transaction to execute txExecuteDelegateCall transaction +transaction_build txExecuteCall + sender acc1 + nonce 3 + contract txDynamicExecutionContextWithRevertTest + value 0 + data 9823c4060000000000000000000000000000000000000000000000000000000000000002 + gas 500000 + build + +# Create block to hold txExecuteCall transaction +block_build b04 + parent b03 + transactions txExecuteCall + gasLimit 550000 + build + +# Connect block +block_connect b04 + +# Check b04 is best block +assert_best b04 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transaction_storage_rskip446/dynamic_execution_context_with_stack_overflow.txt b/rskj-core/src/test/resources/dsl/transaction_storage_rskip446/dynamic_execution_context_with_stack_overflow.txt new file mode 100644 index 00000000000..8b937302c20 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transaction_storage_rskip446/dynamic_execution_context_with_stack_overflow.txt @@ -0,0 +1,173 @@ +comment +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TestTStorageDynamicExecutionContextWithStackOverflow { + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function testCallSelectingContractCallOpcode(uint256 contractCallSelector) external { + // Deploy the Callee contract + address calleeAddress = address(new Callee()); + uint256 success; + uint256 valueLoadedFrom0; + uint256 valueLoadedFrom1; + bytes4 executeSignature = bytes4(keccak256("execute()")); + + assembly { + tstore(0, 420) + tstore(1, 420) + + let availablePointer := mload(0x40) + mstore(availablePointer, executeSignature) + // If useDelegateCall is greater than 0, execute delegateCall otherwise execute callCode + switch contractCallSelector + case 0 { + success := callcode(0xFFFF, calleeAddress, 0, availablePointer, 0x4, availablePointer, 0x20) + } + case 1 { + success := delegatecall(0xFFFF, calleeAddress, availablePointer, 0x4, availablePointer, 0x20) + } + default { + success := call(0xFFFF, calleeAddress, 0, availablePointer, 0x4, availablePointer, 0x20) + } + valueLoadedFrom0 := tload(0) + valueLoadedFrom1 := tload(1) + } + + checkReturnValueExpected(success, 'Checking result callee execution', 0); + checkReturnValueExpected(valueLoadedFrom0, 'Checking value from tload 0', 420); + checkReturnValueExpected(valueLoadedFrom1, 'Checking value from tload 1', 420); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract Callee { + + function execute() external { + assembly { + tstore(1,69) + } + this.executeRecursive(0); + } + + function executeRecursive(uint256 counter) external { + if(counter < 1026){ + counter ++; + this.executeRecursive(counter); + } + } +} + +// CONTRACT BYTECODE + +TestTStorageDynamicExecutionContextWithStackOverflow: 6080604052348015600e575f5ffd5b506106868061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c80639823c4061461002d575b5f5ffd5b61004760048036038101906100429190610280565b610049565b005b5f6040516100569061023c565b604051809103905ff08015801561006f573d5f5f3e3d5ffd5b5090505f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d6101a460015d604051818152865f81146100cd57600181146100e0576020826004845f8b61fffff195506100ee565b6020826004845f8b61fffff295506100ee565b6020826004848a61fffff495505b505f5c935060015c925050610139846040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e8152505f6101c5565b61017b836040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a46101c5565b6101bd826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152506101a46101c5565b505050505050565b8083036101fd577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610237565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161022e92919061032a565b60405180910390a15b505050565b6102f88061035983390190565b5f5ffd5b5f819050919050565b61025f8161024d565b8114610269575f5ffd5b50565b5f8135905061027a81610256565b92915050565b5f6020828403121561029557610294610249565b5b5f6102a28482850161026c565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6102ed826102ab565b6102f781856102b5565b93506103078185602086016102c5565b610310816102d3565b840191505092915050565b6103248161024d565b82525050565b5f6040820190508181035f83015261034281856102e3565b9050610351602083018461031b565b939250505056fe6080604052348015600e575f5ffd5b506102dc8061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c80636146195414610038578063fccbafb914610042575b5f5ffd5b61004061005e565b005b61005c60048036038101906100579190610184565b6100cb565b005b604560015d3073ffffffffffffffffffffffffffffffffffffffff1663fccbafb95f6040518263ffffffff1660e01b815260040161009c91906101f1565b5f604051808303815f87803b1580156100b3575f5ffd5b505af11580156100c5573d5f5f3e3d5ffd5b50505050565b61040281101561014a5780806100e090610237565b9150503073ffffffffffffffffffffffffffffffffffffffff1663fccbafb9826040518263ffffffff1660e01b815260040161011c919061028d565b5f604051808303815f87803b158015610133575f5ffd5b505af1158015610145573d5f5f3e3d5ffd5b505050505b50565b5f5ffd5b5f819050919050565b61016381610151565b811461016d575f5ffd5b50565b5f8135905061017e8161015a565b92915050565b5f602082840312156101995761019861014d565b5b5f6101a684828501610170565b91505092915050565b5f819050919050565b5f819050919050565b5f6101db6101d66101d1846101af565b6101b8565b610151565b9050919050565b6101eb816101c1565b82525050565b5f6020820190506102045f8301846101e2565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61024182610151565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036102735761027261020a565b5b600182019050919050565b61028781610151565b82525050565b5f6020820190506102a05f83018461027e565b9291505056fea26469706673582212208c06dbf10708fcc54598b88ca5465d5b4189bd294c289c13db194e75762635f764736f6c634300081c0033a2646970667358221220c007921bf7d900df9462a49fe9fca543537ec9f988ce2d601da8182ad224485364736f6c634300081c0033 + +9823c406: testCallSelectingContractCallOpcode(uint256) + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TestTransientStorageCallAndDelegateCall contract +transaction_build txDynamicExecutionContextWithStackOverflowTest + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f5ffd5b506106868061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c80639823c4061461002d575b5f5ffd5b61004760048036038101906100429190610280565b610049565b005b5f6040516100569061023c565b604051809103905ff08015801561006f573d5f5f3e3d5ffd5b5090505f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d6101a460015d604051818152865f81146100cd57600181146100e0576020826004845f8b61fffff195506100ee565b6020826004845f8b61fffff295506100ee565b6020826004848a61fffff495505b505f5c935060015c925050610139846040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e8152505f6101c5565b61017b836040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a46101c5565b6101bd826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152506101a46101c5565b505050505050565b8083036101fd577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610237565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161022e92919061032a565b60405180910390a15b505050565b6102f88061035983390190565b5f5ffd5b5f819050919050565b61025f8161024d565b8114610269575f5ffd5b50565b5f8135905061027a81610256565b92915050565b5f6020828403121561029557610294610249565b5b5f6102a28482850161026c565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6102ed826102ab565b6102f781856102b5565b93506103078185602086016102c5565b610310816102d3565b840191505092915050565b6103248161024d565b82525050565b5f6040820190508181035f83015261034281856102e3565b9050610351602083018461031b565b939250505056fe6080604052348015600e575f5ffd5b506102dc8061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c80636146195414610038578063fccbafb914610042575b5f5ffd5b61004061005e565b005b61005c60048036038101906100579190610184565b6100cb565b005b604560015d3073ffffffffffffffffffffffffffffffffffffffff1663fccbafb95f6040518263ffffffff1660e01b815260040161009c91906101f1565b5f604051808303815f87803b1580156100b3575f5ffd5b505af11580156100c5573d5f5f3e3d5ffd5b50505050565b61040281101561014a5780806100e090610237565b9150503073ffffffffffffffffffffffffffffffffffffffff1663fccbafb9826040518263ffffffff1660e01b815260040161011c919061028d565b5f604051808303815f87803b158015610133575f5ffd5b505af1158015610145573d5f5f3e3d5ffd5b505050505b50565b5f5ffd5b5f819050919050565b61016381610151565b811461016d575f5ffd5b50565b5f8135905061017e8161015a565b92915050565b5f602082840312156101995761019861014d565b5b5f6101a684828501610170565b91505092915050565b5f819050919050565b5f819050919050565b5f6101db6101d66101d1846101af565b6101b8565b610151565b9050919050565b6101eb816101c1565b82525050565b5f6020820190506102045f8301846101e2565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61024182610151565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036102735761027261020a565b5b600182019050919050565b61028781610151565b82525050565b5f6020820190506102a05f83018461027e565b9291505056fea26469706673582212208c06dbf10708fcc54598b88ca5465d5b4189bd294c289c13db194e75762635f764736f6c634300081c0033a2646970667358221220c007921bf7d900df9462a49fe9fca543537ec9f988ce2d601da8182ad224485364736f6c634300081c0033 + gas 1000000 + build + +# Create block to hold txDynamicExecutionContextWithStackOverflowTest transaction +block_build b01 + parent g00 + transactions txDynamicExecutionContextWithStackOverflowTest + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txExecuteCallCode transaction +transaction_build txExecuteCallCode + sender acc1 + nonce 1 + contract txDynamicExecutionContextWithStackOverflowTest + value 0 + data 9823c4060000000000000000000000000000000000000000000000000000000000000000 + gas 500000 + build + +# Create block to hold txExecuteCallCode transaction +block_build b02 + parent b01 + transactions txExecuteCallCode + gasLimit 550000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 + +# Create transaction to execute txExecuteDelegateCall transaction +transaction_build txExecuteDelegateCall + sender acc1 + nonce 2 + contract txDynamicExecutionContextWithStackOverflowTest + value 0 + data 9823c4060000000000000000000000000000000000000000000000000000000000000001 + gas 500000 + build + +# Create block to hold txExecuteDelegateCall transaction +block_build b03 + parent b02 + transactions txExecuteDelegateCall + gasLimit 550000 + build + +# Connect block +block_connect b03 + +# Check b03 is best block +assert_best b03 + +# Create transaction to execute txExecuteDelegateCall transaction +transaction_build txExecuteCall + sender acc1 + nonce 3 + contract txDynamicExecutionContextWithStackOverflowTest + value 0 + data 9823c4060000000000000000000000000000000000000000000000000000000000000002 + gas 500000 + build + +# Create block to hold txExecuteCall transaction +block_build b04 + parent b03 + transactions txExecuteCall + gasLimit 550000 + build + +# Connect block +block_connect b04 + +# Check b04 is best block +assert_best b04 \ No newline at end of file