Safe ETH and ERC20 transfer library that gracefully handles missing return values.
Note:
- For ETH transfers, please use
forceSafeTransferETHfor DoS protection.
error ETHTransferFailed()The ETH transfer has failed.
error TransferFromFailed()The ERC20 transferFrom has failed.
error TransferFailed()The ERC20 transfer has failed.
error ApproveFailed()The ERC20 approve has failed.
error TotalSupplyQueryFailed()The ERC20 totalSupply query has failed.
error Permit2Failed()The Permit2 operation has failed.
error Permit2AmountOverflow()The Permit2 amount must be less than 2**160 - 1.
error Permit2ApproveFailed()The Permit2 approve operation has failed.
error Permit2LockdownFailed()The Permit2 lockdown operation has failed.
uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300Suggested gas stipend for contract receiving ETH that disallows any storage writes.
uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000Suggested gas stipend for contract receiving ETH to perform a few
storage reads and writes, but low enough to prevent griefing.
bytes32 internal constant DAI_DOMAIN_SEPARATOR =
0xdbb8cf42e1ecb028be3f3dbc922e1d878b963f411dc388ced501601c60f7c6f7The unique EIP-712 domain separator for the DAI token contract.
address internal constant WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2The address for the WETH9 contract on Ethereum mainnet.
address internal constant PERMIT2 =
0x000000000022D473030F116dDEE9F6B43aC78BA3The canonical Permit2 address.
Github
Etherscan
address internal constant ETH_MOVER =
0x00000000000073c48c8055bD43D1A53799176f0DThe canonical address of the SELFDESTRUCT ETH mover.
See: https://gist.github.com/Vectorized/1cb8ad4cf393b1378e08f23f79bd99fa
Etherscan
If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants.
The regular variants:
- Forwards all remaining gas to the target.
- Reverts if the target reverts.
- Reverts if the current contract has insufficient balance.
The force variants: - Forwards with an optional gas stipend
(defaults toGAS_STIPEND_NO_GRIEF, which is sufficient for most cases). - If the target reverts, or if the gas stipend is exhausted,
creates a temporary contract to force send the ETH viaSELFDESTRUCT.
Future compatible withSENDALL: https://eips.ethereum.org/EIPS/eip-4758. - Reverts if the current contract has insufficient balance.
The try variants: - Forwards with a mandatory gas stipend.
- Instead of reverting, returns whether the transfer succeeded.
function safeTransferETH(address to, uint256 amount) internalSends amount (in wei) ETH to to.
function safeTransferAllETH(address to) internalSends all the ETH in the current contract to to.
function forceSafeTransferETH(
address to,
uint256 amount,
uint256 gasStipend
) internalForce sends amount (in wei) ETH to to, with a gasStipend.
function forceSafeTransferAllETH(address to, uint256 gasStipend) internalForce sends all the ETH in the current contract to to, with a gasStipend.
function forceSafeTransferETH(address to, uint256 amount) internalForce sends amount (in wei) ETH to to, with GAS_STIPEND_NO_GRIEF.
function forceSafeTransferAllETH(address to) internalForce sends all the ETH in the current contract to to, with GAS_STIPEND_NO_GRIEF.
function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)
internal
returns (bool success)Sends amount (in wei) ETH to to, with a gasStipend.
function trySafeTransferAllETH(address to, uint256 gasStipend)
internal
returns (bool success)Sends all the ETH in the current contract to to, with a gasStipend.
function safeMoveETH(address to, uint256 amount)
internal
returns (address vault)Force transfers ETH to to, without triggering the fallback (if any).
This method attempts to use a separate contract to send via SELFDESTRUCT,
and upon failure, deploys a minimal vault to accrue the ETH.
function safeTransferFrom(
address token,
address from,
address to,
uint256 amount
) internalSends amount of ERC20 token from from to to.
Reverts upon failure.
The from account must have at least amount approved for
the current contract to manage.
function trySafeTransferFrom(
address token,
address from,
address to,
uint256 amount
) internal returns (bool success)Sends amount of ERC20 token from from to to.
The from account must have at least amount approved for the current contract to manage.
function safeTransferAllFrom(address token, address from, address to)
internal
returns (uint256 amount)Sends all of ERC20 token from from to to.
Reverts upon failure.
The from account must have their entire balance approved for the current contract to manage.
function safeTransfer(address token, address to, uint256 amount) internalSends amount of ERC20 token from the current contract to to.
Reverts upon failure.
function safeTransferAll(address token, address to)
internal
returns (uint256 amount)Sends all of ERC20 token from the current contract to to.
Reverts upon failure.
function safeApprove(address token, address to, uint256 amount) internalSets amount of ERC20 token for to to manage on behalf of the current contract.
Reverts upon failure.
function safeApproveWithRetry(address token, address to, uint256 amount)
internalSets amount of ERC20 token for to to manage on behalf of the current contract.
If the initial attempt to approve fails, attempts to reset the approved amount to zero,
then retries the approval again (some tokens, e.g. USDT, requires this).
Reverts upon failure.
function balanceOf(address token, address account)
internal
view
returns (uint256 amount)Returns the amount of ERC20 token owned by account.
Returns zero if the token does not exist.
function checkBalanceOf(address token, address account)
internal
view
returns (bool implemented, uint256 amount)Performs a token.balanceOf(account) check.
implemented denotes whether the token does not implement balanceOf.
amount is zero if the token does not implement balanceOf.
function totalSupply(address token)
internal
view
returns (uint256 result)Returns the total supply of the token.
Reverts if the token does not exist or does not implement totalSupply().
function safeTransferFrom2(
address token,
address from,
address to,
uint256 amount
) internalSends amount of ERC20 token from from to to.
If the initial attempt fails, try to use Permit2 to transfer the token.
Reverts upon failure.
The from account must have at least amount approved for the current contract to manage.
function permit2TransferFrom(
address token,
address from,
address to,
uint256 amount
) internalSends amount of ERC20 token from from to to via Permit2.
Reverts upon failure.
function permit2(
address token,
address owner,
address spender,
uint256 amount,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internalPermit a user to spend a given amount of
another user's tokens via native EIP-2612 permit if possible, falling
back to Permit2 if native permit fails or is not implemented on the token.
function simplePermit2(
address token,
address owner,
address spender,
uint256 amount,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internalSimple permit on the Permit2 contract.
function permit2Approve(
address token,
address spender,
uint160 amount,
uint48 expiration
) internalApproves spender to spend amount of token for address(this).
function permit2Lockdown(address token, address spender) internalRevokes an approval for token and spender for address(this).