// SPDX-License-Identifier: MIT // Based on the ReentrancyGuard library from OpenZeppelin Contracts, altered to reduce gas costs. // The `safeTransfer` and `safeTransferFrom` functions assume that `token` is a contract (an account with code), and // work differently from the OpenZeppelin version if it is not. pragma solidity ^0.7.0; import "@aurora-balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/BalancerErrors.sol"; import "@aurora-balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/IERC20.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(address(token), abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(address(token), abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * * WARNING: `token` is assumed to be a contract: calls to EOAs will *not* revert. */ function _callOptionalReturn(address token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = token.call(data); // If the low-level call didn't succeed we return whatever was returned from it. // solhint-disable-next-line no-inline-assembly assembly { if eq(success, 0) { returndatacopy(0, 0, returndatasize()) revert(0, returndatasize()) } } // Finally we check the returndata size is either zero or true - note that this check will always pass for EOAs _require(returndata.length == 0 || abi.decode(returndata, (bool)), Errors.SAFE_ERC20_CALL_FAILED); } }