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

call test contract (forwarding portion of gas) instead of using const… #48

Merged
merged 1 commit into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
53 changes: 37 additions & 16 deletions src/core/lib/ReentrancyGuard.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ contract ReentrancyGuard is ReentrancyErrors, LowLevelHelpers {
// Declare an immutable variable to store the initial TSTORE support status.
bool private immutable _tstoreInitialSupport;

// Declare an immutable variable to store the tstore test contract address.
address private immutable _tloadTestContract;

/**
* @dev Initialize the reentrancy guard during deployment. This involves
* attempting to deploy a contract that utilizes TLOAD as part of the
Expand All @@ -53,8 +56,19 @@ contract ReentrancyGuard is ReentrancyErrors, LowLevelHelpers {
* result.
*/
constructor() {
// Determine if TSTORE is supported & store the result in an immutable.
_tstoreInitialSupport = _testTload();
// Deploy the contract testing TLOAD support and store the address.
address tloadTestContract = _prepareTloadTest();

// Ensure the deployment was successful.
if (tloadTestContract == address(0)) {
revert TloadTestContractDeploymentFailed();
}

// Determine if TSTORE is supported & store the result as an immutable.
_tstoreInitialSupport = _testTload(tloadTestContract);

// Set the address of the deployed TLOAD test contract as an immutable.
_tloadTestContract = tloadTestContract;

// Initialize the reentrancy guard in a cleared state.
_clearReentrancyGuard();
Expand Down Expand Up @@ -83,7 +97,7 @@ contract ReentrancyGuard is ReentrancyErrors, LowLevelHelpers {
}

// Determine if TSTORE can be activated and revert if not.
if (!_testTload()) {
if (!_testTload(_tloadTestContract)) {
revert TStoreNotSupported();
}

Expand Down Expand Up @@ -404,26 +418,33 @@ contract ReentrancyGuard is ReentrancyErrors, LowLevelHelpers {
}

/**
* @dev Internal function to determine if TSTORE/TLOAD are supported by the
* current EVM implementation by attempting to create a contract that
* utilizes TLOAD as part of the contract construction bytecode.
* @dev Internal function to deploy a test contract that utilizes TLOAD as
* part of its fallback logic.
*/
function _testTload() private returns (bool success) {
function _prepareTloadTest() private returns (address contractAddress) {
// Utilize assembly to deploy a contract testing TLOAD support.
assembly {
// Write the contract deployment code payload to scratch space.
mstore(0, _TLOAD_TEST_PAYLOAD)

// Deploy the contract and return the success status.
success := iszero(
iszero(
create(
0,
_TLOAD_TEST_PAYLOAD_OFFSET,
_TLOAD_TEST_PAYLOAD_LENGTH
)
// Deploy the contract.
contractAddress := create(
0,
_TLOAD_TEST_PAYLOAD_OFFSET,
_TLOAD_TEST_PAYLOAD_LENGTH
)
)
}
}

/**
* @dev Internal function to determine if TSTORE/TLOAD are supported by the
* current EVM implementation by attempting to call the test contract,
* which utilizes TLOAD as part of its fallback logic.
*/
function _testTload(address tloadTestContract) private returns (bool ok) {
// Call the test contract, which will perform a TLOAD test. If the call
// does not revert, then TLOAD/TSTORE is supported. Do not forward all
// available gas, as all forwarded gas will be consumed on revert.
(ok, ) = tloadTestContract.call{gas: gasleft() / 10}("");
}
}
6 changes: 6 additions & 0 deletions src/types/interfaces/ReentrancyErrors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,10 @@ interface ReentrancyErrors {
* in an EVM environment that does not support it.
*/
error TStoreNotSupported();

/**
* @dev Revert with an error when deployment of the contract for testing
* TSTORE support fails.
*/
error TloadTestContractDeploymentFailed();
}
6 changes: 3 additions & 3 deletions src/types/lib/ConsiderationConstants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ uint256 constant information_length = 0xa0;

uint256 constant _REENTRANCY_GUARD_SLOT = 0x929eee14;
uint256 constant _TSTORE_SUPPORTED_SLOT = 0x54778ab1;
uint256 constant _TLOAD_TEST_PAYLOAD = 0x3d5c;
uint256 constant _TLOAD_TEST_PAYLOAD_LENGTH = 0x02;
uint256 constant _TLOAD_TEST_PAYLOAD_OFFSET = 0x0e;
uint256 constant _TLOAD_TEST_PAYLOAD = 0x6002601e613d5c3d52f3;
uint256 constant _TLOAD_TEST_PAYLOAD_LENGTH = 0x0a;
uint256 constant _TLOAD_TEST_PAYLOAD_OFFSET = 0x16;
uint256 constant _NOT_ENTERED = 0;
uint256 constant _ENTERED = 1;
uint256 constant _ENTERED_AND_ACCEPTING_NATIVE_TOKENS = 2;
Expand Down
Loading