Skip to content

Commit

Permalink
Added tests for dynamic execution contexts
Browse files Browse the repository at this point in the history
- WIP
- Now we will add unit tests for underflow execution tests
  • Loading branch information
fmacleal committed Nov 11, 2024
1 parent 612a66a commit 2b12be5
Show file tree
Hide file tree
Showing 5 changed files with 372 additions and 0 deletions.
4 changes: 4 additions & 0 deletions rskj-core/src/main/java/org/ethereum/vm/VM.java
Original file line number Diff line number Diff line change
Expand Up @@ -1361,6 +1361,10 @@ protected void doTLOAD(){
protected void doTSTORE(){
//TODO: Gas cost calculation will be done here and also shared contexts verifications for
// different types of calls
if (program.isStaticCall() && program.getActivations().isActive(RSKIP91)) {
throw Program.ExceptionHelper.modificationException(program);
}

DataWord key = program.stackPop();
DataWord value = program.stackPop();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,36 @@ void testDynamicExecutionContextWithStackOverflow() throws FileNotFoundException
Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null));
}

@Test
void testDynamicExecutionCallContextSubcall() throws FileNotFoundException, DslProcessorException {
DslParser parser = DslParser.fromResource("dsl/transaction_storage_rskip446/dynamic_execution_context_call_subcall.txt");
World world = new World();
WorldDslProcessor processor = new WorldDslProcessor(world);
processor.processCommands(parser);

String txContextCallSubcallContract = "txContextCallSubcallContract";
assertTransactionReceiptWithStatus(world, txContextCallSubcallContract, "b01", true);

String txExecuteCallCode = "txExecuteCallCode";
TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txExecuteCallCode, "b02", true);
Assertions.assertEquals(6, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null));
}

@Test
void testDynamicExecutionStaticCallSubcallCantUseTstore() throws FileNotFoundException, DslProcessorException {
DslParser parser = DslParser.fromResource("dsl/transaction_storage_rskip446/dynamic_execution_context_staticcall_subcall_cant_call_tstore.txt");
World world = new World();
WorldDslProcessor processor = new WorldDslProcessor(world);
processor.processCommands(parser);

String txContextStaticCallCantCallTstoreContract = "txContextStaticCallCantCallTstoreContract";
assertTransactionReceiptWithStatus(world, txContextStaticCallCantCallTstoreContract, "b01", true);

String txExecuteStaticCallCode = "txExecuteStaticCallCode";
TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txExecuteStaticCallCode, "b02", true);
Assertions.assertEquals(2, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null));
}

private static TransactionReceipt assertTransactionReceiptWithStatus(World world, String txName, String blockName, boolean withSuccess) {
Transaction txCreation = world.getTransactionByName(txName);
assertNotNull(txCreation);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
comment

// CONTRACT CODE
pragma solidity ^0.8.24;

contract TestTransientStorageCallContext {

constructor() {
}

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

function testCall() external {
// Deploy the Callee contract
address calleeAddress = address(new Callee());
uint256 success;
uint256 valueLoadedFrom0;
uint256 valueLoadedFrom1;
uint256 valueLoadedSstore0;
uint256 valueLoadedSstore1;
bytes4 executeSignature = bytes4(keccak256("execute()"));

assembly {
tstore(0, 420)
let availablePointer := mload(0x40)
mstore(availablePointer, executeSignature)
success := call(gas(), calleeAddress, 0, availablePointer, 0x4, availablePointer, 0x20)
valueLoadedFrom0 := tload(0)
valueLoadedFrom1 := tload(1)
valueLoadedSstore0 := sload(0)
valueLoadedSstore1 := sload(1)
}

checkReturnValueExpected(success, 'Checking result callee execution', 1);
checkReturnValueExpected(valueLoadedFrom0, 'Checking value from tload 0', 420);
checkReturnValueExpected(valueLoadedFrom1, 'Checking value from tload 1', 0);

checkReturnValueExpected(valueLoadedSstore0, 'Checking value from sstore 0', 0);
checkReturnValueExpected(valueLoadedSstore1, 'Checking value from sstore 1', 0);
}

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() external {
uint256 valueLoadedFrom1;
assembly {
sstore(0, tload(0))
tstore(1, 69)
sstore(1, tload(1))
valueLoadedFrom1 := tload(1)
}
if( valueLoadedFrom1 == 69){
emit OK();
} else {
emit ERROR('Checking value from tload 1 in callee', valueLoadedFrom1);
}
}
}

// CONTRACT BYTECODE

TestTransientStorageCallContext: 6080604052348015600e575f5ffd5b506105458061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063b7f058361461002d575b5f5ffd5b610035610037565b005b5f60405161004490610276565b604051809103905ff08015801561005d573d5f5f3e3d5ffd5b5090505f5f5f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d6040518181526020816004835f8c5af196505f5c955060015c94505f5493506001549250506100f4866040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e81525060016101ff565b610136856040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a46101ff565b610176846040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152505f6101ff565b6101b6836040518060400160405280601c81526020017f436865636b696e672076616c75652066726f6d207373746f72652030000000008152505f6101ff565b6101f6826040518060400160405280601c81526020017f436865636b696e672076616c75652066726f6d207373746f72652031000000008152505f6101ff565b50505050505050565b808303610237577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610271565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161026892919061030b565b60405180910390a15b505050565b6101d68061033a83390190565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6102c582610283565b6102cf818561028d565b93506102df81856020860161029d565b6102e8816102ab565b840191505092915050565b5f819050919050565b610305816102f3565b82525050565b5f6040820190508181035f83015261032381856102bb565b905061033260208301846102fc565b939250505056fe6080604052348015600e575f5ffd5b506101ba8061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063614619541461002d575b5f5ffd5b610035610037565b005b5f5f5c5f55604560015d60015c60015560015c905060458103610085577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16100bd565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f816040516100b49190610158565b60405180910390a15b50565b5f82825260208201905092915050565b7f436865636b696e672076616c75652066726f6d20746c6f6164203120696e20635f8201527f616c6c6565000000000000000000000000000000000000000000000000000000602082015250565b5f61012a6025836100c0565b9150610135826100d0565b604082019050919050565b5f819050919050565b61015281610140565b82525050565b5f6040820190508181035f83015261016f8161011e565b905061017e6020830184610149565b9291505056fea2646970667358221220525015013274fe464b5371de8d79b5a498b2073f16a0ead556b61bb8daa945d664736f6c634300081c0033a2646970667358221220fe0d0f67ed34e641f6305bc910b9eb817769785a12a0f1837fe2371e930c5d1a64736f6c634300081c0033

b7f05836: testCall()

end

# Create and fund new account
account_new acc1 10000000

# Create transaction to deploy TestTransientStorageCallContext contract
transaction_build txContextCallSubcallContract
sender acc1
receiverAddress 00
value 0
data 6080604052348015600e575f5ffd5b506105458061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063b7f058361461002d575b5f5ffd5b610035610037565b005b5f60405161004490610276565b604051809103905ff08015801561005d573d5f5f3e3d5ffd5b5090505f5f5f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d6040518181526020816004835f8c5af196505f5c955060015c94505f5493506001549250506100f4866040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e81525060016101ff565b610136856040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a46101ff565b610176846040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152505f6101ff565b6101b6836040518060400160405280601c81526020017f436865636b696e672076616c75652066726f6d207373746f72652030000000008152505f6101ff565b6101f6826040518060400160405280601c81526020017f436865636b696e672076616c75652066726f6d207373746f72652031000000008152505f6101ff565b50505050505050565b808303610237577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610271565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161026892919061030b565b60405180910390a15b505050565b6101d68061033a83390190565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6102c582610283565b6102cf818561028d565b93506102df81856020860161029d565b6102e8816102ab565b840191505092915050565b5f819050919050565b610305816102f3565b82525050565b5f6040820190508181035f83015261032381856102bb565b905061033260208301846102fc565b939250505056fe6080604052348015600e575f5ffd5b506101ba8061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063614619541461002d575b5f5ffd5b610035610037565b005b5f5f5c5f55604560015d60015c60015560015c905060458103610085577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16100bd565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f816040516100b49190610158565b60405180910390a15b50565b5f82825260208201905092915050565b7f436865636b696e672076616c75652066726f6d20746c6f6164203120696e20635f8201527f616c6c6565000000000000000000000000000000000000000000000000000000602082015250565b5f61012a6025836100c0565b9150610135826100d0565b604082019050919050565b5f819050919050565b61015281610140565b82525050565b5f6040820190508181035f83015261016f8161011e565b905061017e6020830184610149565b9291505056fea2646970667358221220525015013274fe464b5371de8d79b5a498b2073f16a0ead556b61bb8daa945d664736f6c634300081c0033a2646970667358221220fe0d0f67ed34e641f6305bc910b9eb817769785a12a0f1837fe2371e930c5d1a64736f6c634300081c0033
gas 1000000
build

# Create block to hold txContextCallSubcallContract transaction
block_build b01
parent g00
transactions txContextCallSubcallContract
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 txContextCallSubcallContract
value 0
data b7f05836
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
comment

// CONTRACT CODE
pragma solidity ^0.8.24;

contract TstorageExecutionContextsStaticCallCanCallTload {

constructor() {
}

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

function testStaticCall() external {
// Deploy the Callee contract
address calleeAddress = address(new Callee());
uint256 success;
uint256 valueLoadedFrom0;
bytes4 executeSignature = bytes4(keccak256("execute()"));

assembly {
tstore(0, 420)
let availablePointer := mload(0x40)
mstore(availablePointer, executeSignature)
success := staticcall(gas(), calleeAddress, availablePointer, 0x4, availablePointer, 0x20)
valueLoadedFrom0 := tload(0)
}

checkReturnValueExpected(success, 'Checking result callee execution', 1);
checkReturnValueExpected(valueLoadedFrom0, 'Checking value from tload 0', 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 {
uint256 valueLoadedFrom0;
assembly {
valueLoadedFrom0 := tload(0)
}
}
}
// CONTRACT BYTECODE

TstorageExecutionContextsStaticCallCanCallTload: 608060405234801561000f575f80fd5b5061033d8061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063d411defb1461002d575b5f80fd5b610035610037565b005b5f604051610044906101a1565b604051809103905ff08015801561005d573d5f803e3d5ffd5b5090505f805f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d604051818152602081600483885afa93505f5c9250506100e2836040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e815250600161012a565b610124826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a461012a565b50505050565b808303610162577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a161019c565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161019392919061024f565b60405180910390a15b505050565b608a8061027e83390190565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156101e45780820151818401526020810190506101c9565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610209826101ad565b61021381856101b7565b93506102238185602086016101c7565b61022c816101ef565b840191505092915050565b5f819050919050565b61024981610237565b82525050565b5f6040820190508181035f83015261026781856101ff565b90506102766020830184610240565b939250505056fe6080604052348015600e575f80fd5b50607080601a5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c80636146195414602a575b5f80fd5b60306032565b005b5f805c90505056fea26469706673582212208f7b43026cae3d8abeeba9ec0dbacdfc50382579f514a511fcb33502ea8b0b3164736f6c63430008180033a2646970667358221220faf33c612e077d0439d4663f3700736865523f14d281f5a1ac59f82062390bd664736f6c63430008180033

d411defb: testStaticCall()

end

# Create and fund new account
account_new acc1 10000000

# Create transaction to deploy TstorageExecutionContextsStaticCallCanCallTload contract
transaction_build txContextStaticCallCanCallTloadContract
sender acc1
receiverAddress 00
value 0
data 608060405234801561000f575f80fd5b5061033d8061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063d411defb1461002d575b5f80fd5b610035610037565b005b5f604051610044906101a1565b604051809103905ff08015801561005d573d5f803e3d5ffd5b5090505f805f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d604051818152602081600483885afa93505f5c9250506100e2836040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e815250600161012a565b610124826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a461012a565b50505050565b808303610162577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a161019c565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161019392919061024f565b60405180910390a15b505050565b608a8061027e83390190565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156101e45780820151818401526020810190506101c9565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610209826101ad565b61021381856101b7565b93506102238185602086016101c7565b61022c816101ef565b840191505092915050565b5f819050919050565b61024981610237565b82525050565b5f6040820190508181035f83015261026781856101ff565b90506102766020830184610240565b939250505056fe6080604052348015600e575f80fd5b50607080601a5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c80636146195414602a575b5f80fd5b60306032565b005b5f805c90505056fea26469706673582212208f7b43026cae3d8abeeba9ec0dbacdfc50382579f514a511fcb33502ea8b0b3164736f6c63430008180033a2646970667358221220faf33c612e077d0439d4663f3700736865523f14d281f5a1ac59f82062390bd664736f6c63430008180033
gas 1000000
build

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

# Connect block
block_connect b01

# Check b01 is best block
assert_best b01

# Create transaction to execute txExecuteStaticCallCode transaction
transaction_build txExecuteStaticCallCode
sender acc1
nonce 1
contract txContextStaticCallCanCallTloadContract
value 0
data d411defb
gas 1000000
build

# Create block to hold txExecuteStaticCallCode transaction
block_build b02
parent b01
transactions txExecuteStaticCallCode
gasLimit 2000000
build

# Connect block
block_connect b02

# Check b02 is best block
assert_best b02
Loading

0 comments on commit 2b12be5

Please sign in to comment.