Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: tstore fevm test #12849

Merged
merged 7 commits into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions itests/contracts/TransientStorageTest.hex
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6080604052348015600e575f5ffd5b50610d0c8061001c5f395ff3fe608060405234801561000f575f5ffd5b506004361061009c575f3560e01c8063ad5963ca11610064578063ad5963ca14610158578063b279888b14610188578063cf83c71c146101a4578063dec9f688146101ae578063e90bf998146101b85761009c565b806302a5e064146100a057806306c0f8b9146100d057806318e1813f1461010057806323d746281461013057806354e84d1b1461014e575b5f5ffd5b6100ba60048036038101906100b59190610639565b6101c2565b6040516100c79190610673565b60405180910390f35b6100ea60048036038101906100e591906106e6565b6101d1565b6040516100f7919061072b565b60405180910390f35b61011a60048036038101906101159190610639565b610361565b604051610127919061072b565b60405180910390f35b610138610372565b604051610145919061072b565b60405180910390f35b61015661037e565b005b610172600480360381019061016d91906106e6565b6103d3565b60405161017f919061072b565b60405180910390f35b6101a2600480360381019061019d9190610744565b61048f565b005b6101ac610496565b005b6101b661053d565b005b6101c0610597565b005b5f5f825c905080915050919050565b5f5f600490505f605890505f84905081835d8073ffffffffffffffffffffffffffffffffffffffff1663b279888b6004607b6040518363ffffffff1660e01b81526004016102209291906107fd565b5f604051808303815f87803b158015610237575f5ffd5b505af1158015610249573d5f5f3e3d5ffd5b505050505f835c9050828114610294576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161028b906108a4565b60405180910390fd5b5f8273ffffffffffffffffffffffffffffffffffffffff166302a5e06460046040518263ffffffff1660e01b81526004016102cf91906108c2565b602060405180830381865afa1580156102ea573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061030e91906108ef565b9050607b8114610353576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161034a90610964565b60405180910390fd5b600195505050505050919050565b5f5f825c90505f8114915050919050565b5f61037b6105f0565b90565b5f600390505f61038d82610361565b9050806103cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103c6906109f2565b60405180910390fd5b5050565b5f5f600590505f607b905080825d8373ffffffffffffffffffffffffffffffffffffffff1663dec9f6886040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610426575f5ffd5b505af1158015610438573d5f5f3e3d5ffd5b505050505f825c9050818114610483576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161047a90610a80565b60405180910390fd5b60019350505050919050565b80825d5050565b5f600190505f602a905080825d5f825c90508181146104ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104e190610b0e565b60405180910390fd5b5f600290505f815c90505f8114610536576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052d90610b9c565b60405180910390fd5b5050505050565b5f600690505f6101c8905080825d5f825c9050818114610592576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161058990610c2a565b60405180910390fd5b505050565b5f600390505f6063905080825d5f825c90508181146105eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e290610cb8565b60405180910390fd5b505050565b6105f8610496565b610600610597565b565b5f5ffd5b5f819050919050565b61061881610606565b8114610622575f5ffd5b50565b5f813590506106338161060f565b92915050565b5f6020828403121561064e5761064d610602565b5b5f61065b84828501610625565b91505092915050565b61066d81610606565b82525050565b5f6020820190506106865f830184610664565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6106b58261068c565b9050919050565b6106c5816106ab565b81146106cf575f5ffd5b50565b5f813590506106e0816106bc565b92915050565b5f602082840312156106fb576106fa610602565b5b5f610708848285016106d2565b91505092915050565b5f8115159050919050565b61072581610711565b82525050565b5f60208201905061073e5f83018461071c565b92915050565b5f5f6040838503121561075a57610759610602565b5b5f61076785828601610625565b925050602061077885828601610625565b9150509250929050565b5f819050919050565b5f819050919050565b5f6107ae6107a96107a484610782565b61078b565b610606565b9050919050565b6107be81610794565b82525050565b5f819050919050565b5f6107e76107e26107dd846107c4565b61078b565b610606565b9050919050565b6107f7816107cd565b82525050565b5f6040820190506108105f8301856107b5565b61081d60208301846107ee565b9392505050565b5f82825260208201905092915050565b7f4e657374656420636f6e747261637420696e74657266657265642077697468205f8201527f7468697320636f6e747261637427732073746f72616765000000000000000000602082015250565b5f61088e603783610824565b915061089982610834565b604082019050919050565b5f6020820190508181035f8301526108bb81610882565b9050919050565b5f6020820190506108d55f8301846107b5565b92915050565b5f815190506108e98161060f565b92915050565b5f6020828403121561090457610903610602565b5b5f610911848285016108db565b91505092915050565b7f4e657374656420636f6e7472616374206461746120696e636f727265637400005f82015250565b5f61094e601e83610824565b91506109598261091a565b602082019050919050565b5f6020820190508181035f83015261097b81610942565b9050919050565b7f5472616e7369656e742073746f7261676520776173206e6f7420636c656172655f8201527f64206166746572207472616e73616374696f6e00000000000000000000000000602082015250565b5f6109dc603383610824565b91506109e782610982565b604082019050919050565b5f6020820190508181035f830152610a09816109d0565b9050919050565b7f5265656e74727920616c7465726564207472616e7369656e742073746f7261675f8201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b5f610a6a602183610824565b9150610a7582610a10565b604082019050919050565b5f6020820190508181035f830152610a9781610a5e565b9050919050565b7f544c4f414420646964206e6f742072657472696576652074686520636f7272655f8201527f63742076616c7565000000000000000000000000000000000000000000000000602082015250565b5f610af8602883610824565b9150610b0382610a9e565b604082019050919050565b5f6020820190508181035f830152610b2581610aec565b9050919050565b7f556e696e697469616c697a656420544c4f414420646964206e6f7420726574755f8201527f726e207a65726f00000000000000000000000000000000000000000000000000602082015250565b5f610b86602783610824565b9150610b9182610b2c565b604082019050919050565b5f6020820190508181035f830152610bb381610b7a565b9050919050565b7f5265656e7472792063616c6c6261636b206661696c656420746f2073746f72655f8201527f20636f72726563742076616c7565000000000000000000000000000000000000602082015250565b5f610c14602e83610824565b9150610c1f82610bba565b604082019050919050565b5f6020820190508181035f830152610c4181610c08565b9050919050565b7f544c4f414420646964206e6f742072657472696576652073746f7265642076615f8201527f6c75652077697468696e207472616e73616374696f6e00000000000000000000602082015250565b5f610ca2603683610824565b9150610cad82610c48565b604082019050919050565b5f6020820190508181035f830152610ccf81610c96565b905091905056fea26469706673582212201a4d9f2694a40645ce896b3becdae2e653fa67b8642d2b7567a7c34ae759829564736f6c634300081c0033
165 changes: 165 additions & 0 deletions itests/contracts/TransientStorageTest.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
// 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");
snissn marked this conversation as resolved.
Show resolved Hide resolved
}

// 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(4, 123);
snissn marked this conversation as resolved.
Show resolved Hide resolved

// 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(4);
snissn marked this conversation as resolved.
Show resolved Hide resolved
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;
}
}
54 changes: 54 additions & 0 deletions itests/fevm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1789,3 +1789,57 @@ func TestFEVMEamCreateTwiceFail(t *testing.T) {
req.Equal("create", traces[2].EthTrace.Type)
req.Contains(traces[2].EthTrace.Error, "ErrForbidden")
}

func TestTstore(t *testing.T) {
nv25epoch := abi.ChainEpoch(100)
upgradeSchedule := kit.UpgradeSchedule(
stmgr.Upgrade{
Network: network.Version24,
Height: -1,
},
stmgr.Upgrade{
Network: network.Version25,
Height: nv25epoch,
Migration: filcns.UpgradeActorsV16,
},
)

ctx, cancel, client := kit.SetupFEVMTest(t, upgradeSchedule)
defer cancel()

// try to deploy the contract before the upgrade, expect an error somewhere' in deploy or in call,
// if the error is in deploy we may need to implement DeployContractFromFilename here where we can
// assert an error

filenameActor := "contracts/TransientStorageTest.hex"
fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor)

inputData := make([]byte, 0)
_, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "runTests()", inputData)
// We expect an error here due to TSTORE not being available in this network version
require.ErrorContains(t, err, "undefined instruction (35)")

client.WaitTillChain(ctx, kit.HeightAtLeast(nv25epoch+5))

// wait for the upgrade

//Step 1 initial reentry test
// should be able to deploy and call the contract now
_, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "runTests()", inputData)
require.NoError(t, err)

//Step 2 subsequent transaction to confirm the transient data was reset
_, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "testLifecycleValidationSubsequentTransaction()", inputData)
require.NoError(t, err)

fromAddr, contractAddr2 := client.EVM().DeployContractFromFilename(ctx, filenameActor)
inputDataContract := inputDataFromFrom(ctx, t, client, contractAddr2)

//Step 3 test reentry from multiple contracts in a transaction
_, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "testReentry(address)", inputDataContract)
require.NoError(t, err)

//Step 4 test tranisent data from nested contract calls
_, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "testNestedContracts(address)", inputDataContract)
require.NoError(t, err)
}
Loading