@@ -68,10 +68,13 @@ contract Portal is ReentrancyGuardTransient {
6868 // TODO: Re-estimate the constants.
6969 /// @notice Gas reserved for the execution logic between the `_hasMinGas` check and the actual Twin contract
7070 /// execution in `relayCall`.
71- uint64 public constant RELAY_GAS_CHECK_BUFFER = 5_000 ;
71+ uint64 public constant RELAY_CALL_CHECK_BUFFER_GAS = 5_000 ;
7272
7373 /// @notice Gas reserved for finalizing the execution of `relayCall` after the safe call.
74- uint64 public constant POST_EXECUTION_RESERVED_GAS = 40_000 ;
74+ uint64 public constant RELAY_CALL_POST_EXECUTION_RESERVED_GAS = 40_000 ;
75+
76+ /// @notice Gas reserved for the dynamic parts of the `CALL` opcode.
77+ uint64 public constant RELAY_CALL_OVERHEAD_GAS = 40_000 ;
7578
7679 /// @notice Address of the trusted relayer.
7780 address public immutable TRUSTED_RELAYER;
@@ -153,7 +156,7 @@ contract Portal is ReentrancyGuardTransient {
153156 if (
154157 ! _hasMinGas ({
155158 minGas: minGasLimit,
156- reservedGas: gasUsedForDeployment + POST_EXECUTION_RESERVED_GAS + RELAY_GAS_CHECK_BUFFER
159+ reservedGas: gasUsedForDeployment + RELAY_CALL_POST_EXECUTION_RESERVED_GAS + RELAY_CALL_CHECK_BUFFER_GAS
157160 })
158161 ) {
159162 failedCalls[callHash] = true ;
@@ -168,7 +171,7 @@ contract Portal is ReentrancyGuardTransient {
168171 }
169172
170173 // Relay the calls via the Twin contract.
171- try twin.executeBatch {gas: gasleft () - POST_EXECUTION_RESERVED_GAS , value: value}(call) {
174+ try twin.executeBatch {gas: gasleft () - RELAY_CALL_POST_EXECUTION_RESERVED_GAS , value: value}(call) {
172175 successfulCalls[callHash] = true ;
173176 emit RelayedCall (callHash);
174177 } catch {
@@ -226,37 +229,38 @@ contract Portal is ReentrancyGuardTransient {
226229 /// https://github.com/ethereum-optimism/optimism/blob/4e9ef1aeffd2afd7a2378e2dc5efffa71f04207d/packages/contracts-bedrock/src/libraries/SafeCall.sol#L100
227230 ///
228231 /// @dev !!!!! FOOTGUN ALERT !!!!!
229- /// 1.) The 40_000 base buffer is to account for the worst case of the dynamic cost of the
230- /// `CALL` opcode's `address_access_cost`, `positive_value_cost`, and
231- /// `value_to_empty_account_cost` factors with an added buffer of 5,700 gas. It is
232- /// still possible to self-rekt by initiating a withdrawal with a minimum gas limit
233- /// that does not account for the `memory_expansion_cost` & `code_execution_cost`
234- /// factors of the dynamic cost of the `CALL` opcode.
235- /// 2.) This function should *directly* precede the external call if possible. There is an
236- /// added buffer to account for gas consumed between this check and the call, but it
237- /// is only 5,700 gas.
238- /// 3.) Because EIP-150 ensures that a maximum of 63/64ths of the remaining gas in the call
239- /// frame may be passed to a subcontext, we need to ensure that the gas will not be
240- /// truncated.
232+ /// 1.) The RELAY_CALL_OVERHEAD_GAS base buffer is to account for the worst case of the dynamic cost of the
233+ /// `CALL` opcode's `address_access_cost`, `positive_value_cost`, and `value_to_empty_account_cost` factors
234+ /// with an added buffer of 5,700 gas. It is still possible to self-rekt by initiating a withdrawal with a
235+ /// minimum gas limit that does not account for the `memory_expansion_cost` & `code_execution_cost` factors
236+ /// of the dynamic cost of the `CALL` opcode.
237+ /// 2.) This function should *directly* precede the external call if possible. There is an added buffer to
238+ /// account for gas consumed between this check and the call, but it is only 5,700 gas.
239+ /// 3.) Because EIP-150 ensures that a maximum of 63/64ths of the remaining gas in the call frame may be passed
240+ /// to a subcontext, we need to ensure that the gas will not be truncated.
241241 /// 4.) Use wisely. This function is not a silver bullet.
242242 ///
243243 /// @param minGas Minimum amount of gas that is forwarded to the Solana sender's Twin contract.
244244 /// @param reservedGas Amount of gas that is reserved for the caller after the execution of the target context.
245245 ///
246246 /// @return hasMinGas `true` if there is enough gas remaining to safely supply `minGas` to the target
247- /// context as well as reserve `reservedGas` for the caller after the execution of
248- /// the target context.
247+ /// context as well as reserve `reservedGas` for the caller after the execution of
248+ /// the target context.
249249 function _hasMinGas (uint256 minGas , uint256 reservedGas ) private view returns (bool hasMinGas ) {
250250 assembly {
251251 // Equation: gas × 63 ≥ minGas × 64 + 63(40_000 + reservedGas)
252- hasMinGas := iszero (lt (mul (gas (), 63 ), add (mul (minGas, 64 ), mul (add (40000 , reservedGas), 63 ))))
252+ hasMinGas :=
253+ iszero (lt (mul (gas (), 63 ), add (mul (minGas, 64 ), mul (add (RELAY_CALL_OVERHEAD_GAS, reservedGas), 63 ))))
253254 }
254255 }
255256
256257 /// @notice Checks whether the ISM verification is successful.
257258 ///
258259 /// @dev TODO: Plug some ISM verification here.
259260 function _ismVerify (bytes calldata call , bytes calldata ismData ) private pure {
261+ call; // Silence unused variable warning.
262+ ismData; // Silence unused variable warning.
263+
260264 // TODO: Plug some ISM verification here.
261265 require (true , ISMVerificationFailed ());
262266 }
0 commit comments