Skip to content

Commit

Permalink
Merge pull request #48 from ProjectOpenSea/tstorish-handle-gas-issues
Browse files Browse the repository at this point in the history
call test contract (forwarding portion of gas) instead of using const…
  • Loading branch information
0age authored Feb 29, 2024
2 parents b85b304 + c91cdf6 commit 0868178
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 19 deletions.
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

0 comments on commit 0868178

Please sign in to comment.