-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'ccip-develop' into CCIP-1039-Publish-test-image-on-each…
…-release-with-release-tag
- Loading branch information
Showing
36 changed files
with
5,742 additions
and
270 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity ^0.8.0; | ||
|
||
/// @dev Handles the edge case where we want to pass a specific amount of gas, | ||
/// @dev but EIP-150 sends all but 1/64 of the remaining gas instead so the user gets | ||
/// @dev less gas than they paid for. The other 2 parts of EIP-150 do not apply since | ||
/// @dev a) we hard code value=0 and b) we ensure code already exists. | ||
/// @dev If we revert instead, then that will never happen. | ||
/// @dev Separately we capture the return data up to a maximum size to avoid return bombs, | ||
/// @dev borrowed from https://github.com/nomad-xyz/ExcessivelySafeCall/blob/main/src/ExcessivelySafeCall.sol. | ||
library CallWithExactGas { | ||
error NoContract(); | ||
error NoGasForCallExactCheck(); | ||
error NotEnoughGasForCall(); | ||
|
||
function _callWithExactGas( | ||
bytes memory payload, | ||
address target, | ||
uint256 gasLimit, | ||
uint16 maxReturnBytes, | ||
uint16 gasForCallExactCheck | ||
) internal returns (bool success, bytes memory retData) { | ||
// allocate retData memory ahead of time | ||
retData = new bytes(maxReturnBytes); | ||
|
||
bytes4 noContract = NoContract.selector; | ||
bytes4 noGasForCallExactCheck = NoGasForCallExactCheck.selector; | ||
bytes4 notEnoughGasForCall = NotEnoughGasForCall.selector; | ||
|
||
// solhint-disable-next-line no-inline-assembly | ||
assembly { | ||
// solidity calls check that a contract actually exists at the destination, so we do the same | ||
// Note we do this check prior to measuring gas so gasForCallExactCheck (our "cushion") | ||
// doesn't need to account for it. | ||
if iszero(extcodesize(target)) { | ||
mstore(0, noContract) | ||
revert(0, 0x4) | ||
} | ||
|
||
let g := gas() | ||
// Compute g -= gasForCallExactCheck and check for underflow | ||
// The gas actually passed to the callee is _min(gasAmount, 63//64*gas available). | ||
// We want to ensure that we revert if gasAmount > 63//64*gas available | ||
// as we do not want to provide them with less, however that check itself costs | ||
// gas. gasForCallExactCheck ensures we have at least enough gas to be able | ||
// to revert if gasAmount > 63//64*gas available. | ||
if lt(g, gasForCallExactCheck) { | ||
mstore(0, noGasForCallExactCheck) | ||
revert(0, 0x4) | ||
} | ||
g := sub(g, gasForCallExactCheck) | ||
// if g - g//64 <= gasAmount, revert | ||
// (we subtract g//64 because of EIP-150) | ||
if iszero(gt(sub(g, div(g, 64)), gasLimit)) { | ||
mstore(0, notEnoughGasForCall) | ||
revert(0, 0x4) | ||
} | ||
// call and return whether we succeeded. ignore return data | ||
// call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) | ||
success := call(gasLimit, target, 0, add(payload, 0x20), mload(payload), 0, 0) | ||
|
||
// limit our copy to maxReturnBytes bytes | ||
let toCopy := returndatasize() | ||
if gt(toCopy, maxReturnBytes) { | ||
toCopy := maxReturnBytes | ||
} | ||
// Store the length of the copied bytes | ||
mstore(retData, toCopy) | ||
// copy the bytes from retData[0:_toCopy] | ||
returndatacopy(add(retData, 0x20), 0, toCopy) | ||
} | ||
return (success, retData); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.