Files
lotus/itests/contracts/TransientStorageTest.sol
Mikers a526c480d4 feat: tstore fevm test (#12849)
* check in fevm tstorage test. note that the network upgrade is a todo. Because the network upgrade does not happen the tests currently fail so they are commented with what needs to change once the network upgrade can be wired in.

* remove TODOs from tstore test and update asserts to assert that the expected correct result happens.

* typo bugfix

* Update itests/contracts/TransientStorageTest.sol

Co-authored-by: Rod Vagg <rod@vagg.org>

* Update itests/contracts/TransientStorageTest.sol

Co-authored-by: Rod Vagg <rod@vagg.org>

* upgrade go-state-types version for tstore migration code

* ran `make bundle-gen` and `bash pack.sh v16 v16.0.0-dev1`

---------

Co-authored-by: Rod Vagg <rod@vagg.org>
2025-01-31 12:31:07 +01:00

166 lines
4.8 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract TransientStorageTest {
constructor() {
}
// Test 0: Initial Constructor Test
function runTests() public returns (bool) {
_runTests();
}
function _runTests() internal {
testBasicFunctionality();
testLifecycleValidation();
}
// Test 1: Basic Functionality
function testBasicFunctionality() public {
uint256 slot = 1;
uint256 value = 42;
// Store value using TSTORE
assembly {
tstore(slot, value)
}
// Retrieve value using TLOAD
uint256 retrievedValue;
assembly {
retrievedValue := tload(slot)
}
require(retrievedValue == value, "TLOAD did not retrieve the correct value");
// Verify TLOAD from uninitialized location
uint256 uninitializedSlot = 2;
uint256 uninitializedValue;
assembly {
uninitializedValue := tload(uninitializedSlot)
}
require(uninitializedValue == 0, "Uninitialized TLOAD did not return zero");
}
// Test 2.1: Verify transient storage clears after transaction
function testLifecycleValidation() public {
uint256 slot = 3;
uint256 value = 99;
// Store value using TSTORE
assembly {
tstore(slot, value)
}
// Verify it exists within the same transaction
uint256 retrievedValue;
assembly {
retrievedValue := tload(slot)
}
require(retrievedValue == value, "TLOAD did not retrieve stored value within transaction");
}
// Test 2.2: Verify transient storage clears in subsequent transactions
function testLifecycleValidationSubsequentTransaction() public {
uint256 slot = 3;
bool cleared = isStorageCleared(slot);
require(cleared, "Transient storage was not cleared after transaction");
}
// Utility Function: Check if transient storage is cleared
function isStorageCleared(uint256 slot) public view returns (bool) {
uint256 retrievedValue;
assembly {
retrievedValue := tload(slot)
}
return retrievedValue == 0; // True if cleared
}
// Test 3: Verify nested contract independence
function testNestedContracts(address other) public returns (bool) {
uint256 slot = 4;
uint256 value = 88;
TransientStorageTest nested = TransientStorageTest(other);
// Store in this contract's transient storage
assembly {
tstore(slot, value)
}
// Call nested contract to write its own transient storage
nested.writeTransientData(slot, 123);
// Verify this contract's data is unchanged
uint256 retrievedValue;
assembly {
retrievedValue := tload(slot)
}
require(retrievedValue == value, "Nested contract interfered with this contract's storage");
// Verify nested contract's data independently
uint256 nestedValue = nested.readTransientData(slot);
require(nestedValue == 123, "Nested contract data incorrect");
return true;
}
// Test 4: Reentry scenario
function testReentry(address otherContract) public returns (bool) {
uint256 slot = 5;
uint256 value = 123;
// Store a value in transient storage
assembly {
tstore(slot, value)
}
// Call the other contract to trigger a callback to this contract
TransientStorageTest(otherContract).reentryCallback();
// After reentry, check that the transient storage still has the correct value
uint256 retrievedValue;
assembly {
retrievedValue := tload(slot)
}
require(retrievedValue == value, "Reentry altered transient storage");
return true;
}
// Utility Function for Test 4: Reentry callback
function reentryCallback() public {
uint256 slot = 6;
uint256 value = 456;
// Store a different value in a different slot
assembly {
tstore(slot, value)
}
// Verify the value was stored correctly
uint256 retrievedValue;
assembly {
retrievedValue := tload(slot)
}
require(retrievedValue == value, "Reentry callback failed to store correct value");
}
// Utility Function for Test 3: Write to transient storage
function writeTransientData(uint256 slot, uint256 value) external {
assembly {
tstore(slot, value)
}
}
// Utility Function for Test 3: Read from transient storage
function readTransientData(uint256 slot) external view returns (uint256) {
uint256 value;
assembly {
value := tload(slot)
}
return value;
}
}