Skip to content

Commit

Permalink
Merge pull request #2894 from rsksmart/fmacleal/tstorage-selfdestruct…
Browse files Browse the repository at this point in the history
…-test-cases

Added test scenarios for selfdestruct cases
  • Loading branch information
Vovchyk authored Dec 17, 2024
2 parents ec733dd + 750cdca commit b730550
Show file tree
Hide file tree
Showing 32 changed files with 887 additions and 27 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
comment

// CONTRACT CODE

pragma solidity ^0.8.24;

contract TloadAfterInnerSelfdestructingNewContract {

constructor() {
}

event OK();
event ERROR(string, uint256);

function performTest() external {
Callee callee = new Callee();
address calleeAddress = address(callee);
uint256 resultCallOption1;
uint256 valueLoadedFromMemory;
bytes4 executeSignature = bytes4(keccak256("execute(uint256)"));

assembly {
// Call Option 1: Executes tstore, inner call to selfdestruct and then tload and return data
let availablePointerCallOption1 := mload(0x40)
mstore(availablePointerCallOption1, executeSignature)
mstore(add(availablePointerCallOption1, 4), 1)
resultCallOption1 := call(gas(), calleeAddress, 0, availablePointerCallOption1, 0x24, availablePointerCallOption1, 0x20)

// Copy returndata into memory to retrieve the returned value
returndatacopy(availablePointerCallOption1, 0, returndatasize())
valueLoadedFromMemory := mload(availablePointerCallOption1)
}

checkReturnValueExpected(resultCallOption1, 'Checking result call option 1', 0x01);
checkReturnValueExpected(valueLoadedFromMemory, 'Checking value from mload 0', 0x100);
}

function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private {
if( valueReceived == expectedValue){
emit OK();
} else {
emit ERROR(message, valueReceived);
}
}
}

contract Callee {

event OK();
event ERROR(string, uint256);

function execute(uint256 callOption) external returns (uint256) {
address calleeAddress = address(this);
bytes4 executeSignature = bytes4(keccak256("execute(uint256)"));
uint256 resultCallOption2;
assembly {
switch callOption
case 1 {
tstore(0xFF, 0x100)
// Call Option 2: Executes tload and returns data
let availablePointerCallOption2 := mload(0x40)
mstore(availablePointerCallOption2, executeSignature)
mstore(add(availablePointerCallOption2, 4), 2)
resultCallOption2 := call(gas(), calleeAddress, 0, availablePointerCallOption2, 0x24, availablePointerCallOption2, 0x20)

// Load value from transient storage
let value := tload(0xFF)
mstore(0x00, value) // Store it in memory to return
return(0x00, 0x20) // Return 32 bytes from memory
}
case 2 {
selfdestruct(0)
}
}
}
}

// DESCRIPTION

// CONTRACT BYTECODE

TloadAfterInnerSelfdestructingNewContract: 608060405234801561000f575f80fd5b506104708061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630d0b85f11461002d575b5f80fd5b610035610037565b005b5f604051610044906101ad565b604051809103905ff08015801561005d573d5f803e3d5ffd5b5090505f8190505f805f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b9050604051818152600160048201526020816024835f895af193503d5f823e80519250506100ed836040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e20310000008152506001610136565b61012f826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d206d6c6f616420300000000000815250610100610136565b5050505050565b80830361016e577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16101a8565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161019f92919061025c565b60405180910390a15b505050565b6101b08061028b83390190565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156101f15780820151818401526020810190506101d6565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610216826101ba565b61022081856101c4565b93506102308185602086016101d4565b610239816101fc565b840191505092915050565b5f819050919050565b61025681610244565b82525050565b5f6040820190508181035f830152610274818561020c565b9050610283602083018461024d565b939250505056fe608060405234801561000f575f80fd5b506101938061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063fe0d94c11461002d575b5f80fd5b6100476004803603810190610042919061010a565b61005d565b6040516100549190610144565b60405180910390f35b5f803090505f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b90505f846001811461009d57600281146100c7576100ca565b61010060ff5d604051838152600260048201526020816024835f895af1925060ff5c805f5260205ff35b5fff5b50505050919050565b5f80fd5b5f819050919050565b6100e9816100d7565b81146100f3575f80fd5b50565b5f81359050610104816100e0565b92915050565b5f6020828403121561011f5761011e6100d3565b5b5f61012c848285016100f6565b91505092915050565b61013e816100d7565b82525050565b5f6020820190506101575f830184610135565b9291505056fea2646970667358221220df3fda34f805973d73508c3bff5aa075ac36fd7769240906d19a4ade4713155464736f6c63430008180033a26469706673582212202ee0175c4410ed0d1259c8ad0377835933ddf29c77105e09bac218f55b6c5f3464736f6c63430008180033

function hashes:s

- 0d0b85f1: performTest()

end

# Create and fund new account
account_new acc1 10000000

# Create transaction to deploy TloadAfterSelfdestructPreExistingContract contract
transaction_build txDeployTestContract
sender acc1
receiverAddress 00
value 0
data 608060405234801561000f575f80fd5b506104708061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630d0b85f11461002d575b5f80fd5b610035610037565b005b5f604051610044906101ad565b604051809103905ff08015801561005d573d5f803e3d5ffd5b5090505f8190505f805f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b9050604051818152600160048201526020816024835f895af193503d5f823e80519250506100ed836040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e20310000008152506001610136565b61012f826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d206d6c6f616420300000000000815250610100610136565b5050505050565b80830361016e577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16101a8565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161019f92919061025c565b60405180910390a15b505050565b6101b08061028b83390190565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156101f15780820151818401526020810190506101d6565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610216826101ba565b61022081856101c4565b93506102308185602086016101d4565b610239816101fc565b840191505092915050565b5f819050919050565b61025681610244565b82525050565b5f6040820190508181035f830152610274818561020c565b9050610283602083018461024d565b939250505056fe608060405234801561000f575f80fd5b506101938061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063fe0d94c11461002d575b5f80fd5b6100476004803603810190610042919061010a565b61005d565b6040516100549190610144565b60405180910390f35b5f803090505f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b90505f846001811461009d57600281146100c7576100ca565b61010060ff5d604051838152600260048201526020816024835f895af1925060ff5c805f5260205ff35b5fff5b50505050919050565b5f80fd5b5f819050919050565b6100e9816100d7565b81146100f3575f80fd5b50565b5f81359050610104816100e0565b92915050565b5f6020828403121561011f5761011e6100d3565b5b5f61012c848285016100f6565b91505092915050565b61013e816100d7565b82525050565b5f6020820190506101575f830184610135565b9291505056fea2646970667358221220df3fda34f805973d73508c3bff5aa075ac36fd7769240906d19a4ade4713155464736f6c63430008180033a26469706673582212202ee0175c4410ed0d1259c8ad0377835933ddf29c77105e09bac218f55b6c5f3464736f6c63430008180033
gas 1000000
build

# Create block to hold txDeployTestContract transaction
block_build b01
parent g00
transactions txDeployTestContract
gasLimit 1200000
build

# Connect block
block_connect b01

# Check b01 is best block
assert_best b01

# Create transaction to execute performTest function from contract
transaction_build txPerformTest
sender acc1
nonce 1
contract txDeployTestContract
value 0
data 0d0b85f1
gas 300000
build

# Create block to hold txPerformTest transaction
block_build b02
parent b01
transactions txPerformTest
gasLimit 350000
build

# Connect block
block_connect b02

# Check b02 is best block
assert_best b02
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
comment

// CONTRACT CODE
pragma solidity ^0.8.24;

contract TloadAfterInnerSelfdestructingPreExistingContract {
Callee callee;

constructor() {
callee = new Callee();
}

event OK();
event ERROR(string, uint256);

function performTest() external {
address calleeAddress = address(callee);
uint256 resultCallOption1;
uint256 valueLoadedFromMemory;
bytes4 executeSignature = bytes4(keccak256("execute(uint256)"));

assembly {
// Call Option 1: Executes tstore, inner call to selfdestruct and then tload and return data
let availablePointerCallOption1 := mload(0x40)
mstore(availablePointerCallOption1, executeSignature)
mstore(add(availablePointerCallOption1, 4), 1)
resultCallOption1 := call(gas(), calleeAddress, 0, availablePointerCallOption1, 0x24, availablePointerCallOption1, 0x20)

// Copy returndata into memory to retrieve the returned value
returndatacopy(availablePointerCallOption1, 0, returndatasize())
valueLoadedFromMemory := mload(availablePointerCallOption1)
}

checkReturnValueExpected(resultCallOption1, 'Checking result call option 1', 0x01);
checkReturnValueExpected(valueLoadedFromMemory, 'Checking value from mload 0', 0x100);
}

function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private {
if( valueReceived == expectedValue){
emit OK();
} else {
emit ERROR(message, valueReceived);
}
}
}

contract Callee {

event OK();
event ERROR(string, uint256);

function execute(uint256 callOption) external returns (uint256) {
address calleeAddress = address(this);
bytes4 executeSignature = bytes4(keccak256("execute(uint256)"));
uint256 resultCallOption2;
assembly {
switch callOption
case 1 {
tstore(0xFF, 0x100)
// Call Option 2: Executes tload and returns data
let availablePointerCallOption2 := mload(0x40)
mstore(availablePointerCallOption2, executeSignature)
mstore(add(availablePointerCallOption2, 4), 2)
resultCallOption2 := call(gas(), calleeAddress, 0, availablePointerCallOption2, 0x24, availablePointerCallOption2, 0x20)

// Load value from transient storage
let value := tload(0xFF)
mstore(0x00, value) // Store it in memory to return
return(0x00, 0x20) // Return 32 bytes from memory
}
case 2 {
selfdestruct(0)
}
}
}
}

// DESCRIPTION

// CONTRACT BYTECODE

TloadAfterInnerSelfdestructingPreExistingContract: 608060405234801561000f575f80fd5b5060405161001c90610079565b604051809103905ff080158015610035573d5f803e3d5ffd5b505f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610086565b6101b08061033c83390190565b6102a9806100935f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630d0b85f11461002d575b5f80fd5b610035610037565b005b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f805f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b9050604051818152600160048201526020816024835f895af193503d5f823e80519250506100e4836040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e2031000000815250600161012c565b610126826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d206d6c6f61642030000000000081525061010061012c565b50505050565b808303610164577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a161019e565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f8284604051610195929190610245565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156101da5780820151818401526020810190506101bf565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6101ff826101a3565b61020981856101ad565b93506102198185602086016101bd565b610222816101e5565b840191505092915050565b5f819050919050565b61023f8161022d565b82525050565b5f6040820190508181035f83015261025d81856101f5565b905061026c6020830184610236565b939250505056fea2646970667358221220314f4ea23497493d6086e14a2ebfdd4290728740c02f4713001e260d7d662c4164736f6c63430008180033608060405234801561000f575f80fd5b506101938061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063fe0d94c11461002d575b5f80fd5b6100476004803603810190610042919061010a565b61005d565b6040516100549190610144565b60405180910390f35b5f803090505f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b90505f846001811461009d57600281146100c7576100ca565b61010060ff5d604051838152600260048201526020816024835f895af1925060ff5c805f5260205ff35b5fff5b50505050919050565b5f80fd5b5f819050919050565b6100e9816100d7565b81146100f3575f80fd5b50565b5f81359050610104816100e0565b92915050565b5f6020828403121561011f5761011e6100d3565b5b5f61012c848285016100f6565b91505092915050565b61013e816100d7565b82525050565b5f6020820190506101575f830184610135565b9291505056fea264697066735822122000dadba91902cd6d3eaf38fdb47cdccbbf9036448d79da3ff9b15dc0012e4a0864736f6c63430008180033

function hashes:s

- 0d0b85f1: performTest()

end

# Create and fund new account
account_new acc1 10000000

# Create transaction to deploy TloadAfterSelfdestructPreExistingContract contract
transaction_build txDeployTestContract
sender acc1
receiverAddress 00
value 0
data 608060405234801561000f575f80fd5b5060405161001c90610079565b604051809103905ff080158015610035573d5f803e3d5ffd5b505f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610086565b6101b08061033c83390190565b6102a9806100935f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630d0b85f11461002d575b5f80fd5b610035610037565b005b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f805f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b9050604051818152600160048201526020816024835f895af193503d5f823e80519250506100e4836040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e2031000000815250600161012c565b610126826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d206d6c6f61642030000000000081525061010061012c565b50505050565b808303610164577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a161019e565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f8284604051610195929190610245565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156101da5780820151818401526020810190506101bf565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6101ff826101a3565b61020981856101ad565b93506102198185602086016101bd565b610222816101e5565b840191505092915050565b5f819050919050565b61023f8161022d565b82525050565b5f6040820190508181035f83015261025d81856101f5565b905061026c6020830184610236565b939250505056fea2646970667358221220314f4ea23497493d6086e14a2ebfdd4290728740c02f4713001e260d7d662c4164736f6c63430008180033608060405234801561000f575f80fd5b506101938061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063fe0d94c11461002d575b5f80fd5b6100476004803603810190610042919061010a565b61005d565b6040516100549190610144565b60405180910390f35b5f803090505f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b90505f846001811461009d57600281146100c7576100ca565b61010060ff5d604051838152600260048201526020816024835f895af1925060ff5c805f5260205ff35b5fff5b50505050919050565b5f80fd5b5f819050919050565b6100e9816100d7565b81146100f3575f80fd5b50565b5f81359050610104816100e0565b92915050565b5f6020828403121561011f5761011e6100d3565b5b5f61012c848285016100f6565b91505092915050565b61013e816100d7565b82525050565b5f6020820190506101575f830184610135565b9291505056fea264697066735822122000dadba91902cd6d3eaf38fdb47cdccbbf9036448d79da3ff9b15dc0012e4a0864736f6c63430008180033
gas 1000000
build

# Create block to hold txDeployTestContract transaction
block_build b01
parent g00
transactions txDeployTestContract
gasLimit 1200000
build

# Connect block
block_connect b01

# Check b01 is best block
assert_best b01

# Create transaction to execute performTest function from contract
transaction_build txPerformTest
sender acc1
nonce 1
contract txDeployTestContract
value 0
data 0d0b85f1
gas 300000
build

# Create block to hold txPerformTest transaction
block_build b02
parent b01
transactions txPerformTest
gasLimit 350000
build

# Connect block
block_connect b02

# Check b02 is best block
assert_best b02
Loading

0 comments on commit b730550

Please sign in to comment.