Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
Contract Name:
UniversalERC4626Adapter
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 1 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
// solhint-disable
pragma solidity ^0.8.0;
import {IAdapter} from "../../interfaces/IAdapter.sol";
import {IERC20} from "../../interfaces/IERC20.sol";
import {IERC4626} from "../../interfaces/IERC4626.sol";
import {SafeERC20} from "../../libraries/SafeERC20.sol";
import {RefundLib} from "../../libraries/Adapters.sol";
/**
* @title UniversalERC4626Adapter
* @notice Universal adapter for ERC4626 vaults (asset <-> share)
* @dev Converts the full balance held by this adapter, and sends output to `to`.
*
* External Methods Used:
* - IERC4626(pool).asset() -> address : Returns the underlying asset token of the vault
* - IERC4626(pool).deposit(uint256 assets, address receiver) -> uint256 shares : Deposits assets and mints shares to receiver
* - IERC4626(pool).redeem(uint256 shares, address receiver, address owner) -> uint256 assets : Burns shares and sends assets to receiver
* - IERC20(token).balanceOf(address account) -> uint256 : Reads this adapter's token balance
* - IERC20(token).approve(address spender, uint256 amount) -> bool : Allows vault to pull assets (used via SafeERC20.safeApprove)
*
* Supported Vault Protocols:
* - Any ERC4626-compliant vault (EIP-4626)
*
* moreInfo encoding:
* abi.encode(address tokenIn, address tokenOut)
*
* Usage Examples:
* ```solidity
* // asset -> shares
* adapter.sellBase(to, vault, "");
*
* // shares -> asset
* adapter.sellQuote(to, vault, "");
* ```
*/
contract UniversalERC4626Adapter is IAdapter {
/// @notice throw error when amount is zero
error InvalidAmount();
/// @notice throw error when tokenIn/tokenOut is not an ERC4626 asset/share pair
error InvalidTokenPair();
// sellBase: token0 -> token1 (asset -> share)
function sellBase(
address to,
address pool,
bytes memory
) external override {
address asset = IERC4626(pool).asset();
uint256 amountIn = IERC20(asset).balanceOf(address(this));
if (amountIn == 0) revert InvalidAmount();
SafeERC20.safeApprove(
IERC20(asset),
pool,
amountIn
);
IERC4626(pool).deposit(amountIn, to);
_refund(asset);
}
// sellQuote: token1 -> token0 (share -> asset)
function sellQuote(
address to,
address pool,
bytes memory
) external override {
address asset = IERC4626(pool).asset();
uint256 amountIn = IERC20(pool).balanceOf(address(this));
if (amountIn == 0) revert InvalidAmount();
IERC4626(pool).redeem(amountIn, to, address(this));
_refund(asset);
}
function _refund(address token) internal {
address payerOrigin = RefundLib.getPayerOrigin();
if (payerOrigin == address(0)) return;
uint256 dust = IERC20(token).balanceOf(address(this));
if (dust > 0) {
SafeERC20.safeTransfer(IERC20(token), payerOrigin, dust);
}
}
}/// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;
interface IAdapter {
function sellBase(
address to,
address pool,
bytes memory data
) external;
function sellQuote(
address to,
address pool,
bytes memory data
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC20 {
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
event Transfer(address indexed from, address indexed to, uint256 value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function balanceOf(address owner) external view returns (uint256);
function allowance(address owner, address spender)
external
view
returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transfer(address to, uint256 value) external returns (bool);
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC20.sol";
interface IERC4626 is IERC20 {
/**
* @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
*
* - MUST be an ERC-20 token contract.
* - MUST NOT revert.
*/
function asset() external view returns (address assetTokenAddress);
/**
* @dev Returns the total amount of the underlying asset that is “managed” by Vault.
*
* - SHOULD include any compounding that occurs from yield.
* - MUST be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT revert.
*/
function totalAssets() external view returns (uint256 totalManagedAssets);
/**
* @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToShares(uint256 assets) external view returns (uint256 shares);
/**
* @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
* through a deposit call.
*
* - MUST return a limited value if receiver is subject to some deposit limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
* - MUST NOT revert.
*/
function maxDeposit(address receiver) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
* call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
* in the same transaction.
* - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
* deposit would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewDeposit(uint256 assets) external view returns (uint256 shares);
/**
* @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* deposit execution, and are accounted for during deposit.
* - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
* - MUST return a limited value if receiver is subject to some mint limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
* - MUST NOT revert.
*/
function maxMint(address receiver) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
* in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
* same transaction.
* - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
* would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by minting.
*/
function previewMint(uint256 shares) external view returns (uint256 assets);
/**
* @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
* execution, and are accounted for during mint.
* - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function mint(uint256 shares, address receiver) external returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
* Vault, through a withdraw call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxWithdraw(address owner) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
* call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
* called
* in the same transaction.
* - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
* the withdrawal would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewWithdraw(uint256 assets) external view returns (uint256 shares);
/**
* @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* withdraw execution, and are accounted for during withdraw.
* - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
* through a redeem call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxRedeem(address owner) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
* in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
* same transaction.
* - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
* redemption would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by redeeming.
*/
function previewRedeem(uint256 shares) external view returns (uint256 assets);
/**
* @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* redeem execution, and are accounted for during redeem.
* - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}/// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./SafeMath.sol"; import "./Address.sol"; import "./RevertReasonForwarder.sol"; import "../interfaces/IERC20.sol"; import "../interfaces/IERC20Permit.sol"; import "../interfaces/IDaiLikePermit.sol"; // File @1inch/solidity-utils/contracts/libraries/[email protected] library SafeERC20 { error SafeTransferFailed(); error SafeTransferFromFailed(); error ForceApproveFailed(); error SafeIncreaseAllowanceFailed(); error SafeDecreaseAllowanceFailed(); error SafePermitBadLength(); // Ensures method do not revert or return boolean `true`, admits call to non-smart-contract function safeTransferFrom(IERC20 token, address from, address to, uint256 amount) internal { bytes4 selector = token.transferFrom.selector; bool success; /// @solidity memory-safe-assembly assembly { // solhint-disable-line no-inline-assembly let data := mload(0x40) mstore(data, selector) mstore(add(data, 0x04), from) mstore(add(data, 0x24), to) mstore(add(data, 0x44), amount) success := call(gas(), token, 0, data, 100, 0x0, 0x20) if success { switch returndatasize() case 0 { success := gt(extcodesize(token), 0) } default { success := and(gt(returndatasize(), 31), eq(mload(0), 1)) } } } if (!success) revert SafeTransferFromFailed(); } // Ensures method do not revert or return boolean `true`, admits call to non-smart-contract function safeTransfer(IERC20 token, address to, uint256 value) internal { if (!_makeCall(token, token.transfer.selector, to, value)) { revert SafeTransferFailed(); } } function safeApprove(IERC20 token, address spender, uint256 value) internal { forceApprove(token, spender, value); } // If `approve(from, to, amount)` fails, try to `approve(from, to, 0)` before retry function forceApprove(IERC20 token, address spender, uint256 value) internal { if (!_makeCall(token, token.approve.selector, spender, value)) { if (!_makeCall(token, token.approve.selector, spender, 0) || !_makeCall(token, token.approve.selector, spender, value)) { revert ForceApproveFailed(); } } } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 allowance = token.allowance(address(this), spender); if (value > type(uint256).max - allowance) revert SafeIncreaseAllowanceFailed(); forceApprove(token, spender, allowance + value); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 allowance = token.allowance(address(this), spender); if (value > allowance) revert SafeDecreaseAllowanceFailed(); forceApprove(token, spender, allowance - value); } function safePermit(IERC20 token, bytes calldata permit) internal { bool success; if (permit.length == 32 * 7) { success = _makeCalldataCall(token, IERC20Permit.permit.selector, permit); } else if (permit.length == 32 * 8) { success = _makeCalldataCall(token, IDaiLikePermit.permit.selector, permit); } else { revert SafePermitBadLength(); } if (!success) RevertReasonForwarder.reRevert(); } function _makeCall(IERC20 token, bytes4 selector, address to, uint256 amount) private returns(bool success) { /// @solidity memory-safe-assembly assembly { // solhint-disable-line no-inline-assembly let data := mload(0x40) mstore(data, selector) mstore(add(data, 0x04), to) mstore(add(data, 0x24), amount) success := call(gas(), token, 0, data, 0x44, 0x0, 0x20) if success { switch returndatasize() case 0 { success := gt(extcodesize(token), 0) } default { success := and(gt(returndatasize(), 31), eq(mload(0), 1)) } } } } function _makeCalldataCall(IERC20 token, bytes4 selector, bytes calldata args) private returns(bool success) { /// @solidity memory-safe-assembly assembly { // solhint-disable-line no-inline-assembly let len := add(4, args.length) let data := mload(0x40) mstore(data, selector) calldatacopy(add(data, 0x04), args.offset, args.length) success := call(gas(), token, 0, data, len, 0x0, 0x20) if success { switch returndatasize() case 0 { success := gt(extcodesize(token), 0) } default { success := and(gt(returndatasize(), 31), eq(mload(0), 1)) } } } } }
pragma solidity ^0.8.0;
// restricted liquidity lib for adapter developer
library RestrictedLiquidityLib {
// if dex is restricted liquidity, then must use this struct to build more info
struct TradeInfo {
address fundAddress; // fromTokenAddress
address tokenAddress; // toTokenAddress
bool buyMeme;
uint256 sellMemeAmount;
uint256 sellCommissionRate1;
address sellCommissionReceiver1;
uint256 sellCommissionRate2;
address sellCommissionReceiver2;
uint256 minReturnAmount;
}
}
// refund lib for adapter developer
library RefundLib {
uint256 private constant ORIGIN_PAYER = 0x3ca20afc2ccc0000000000000000000000000000000000000000000000000000;
uint256 private constant ADDRESS_MASK = 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff;
function getPayerOrigin() internal pure returns (address payerOriginAddr) {
uint256 _payerOrigin;
// solhint-disable-next-line no-inline-assembly
// This assembly is necessary to access calldata size and load data from specific positions
// which cannot be achieved with pure Solidity code
assembly {
// Get the total size of the calldata
let size := calldatasize()
// Load the last 32 bytes of the calldata, which is assumed to contain the payer origin
// Assumption: The calldata is structured such that the payer origin is always at the end
_payerOrigin := calldataload(sub(size, 32))
}
if ((_payerOrigin & ORIGIN_PAYER) == ORIGIN_PAYER) {
payerOriginAddr = address(uint160(uint256(_payerOrigin) & ADDRESS_MASK));
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library SafeMath {
uint256 constant WAD = 10**18;
uint256 constant RAY = 10**27;
function wad() public pure returns (uint256) {
return WAD;
}
function ray() public pure returns (uint256) {
return RAY;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a <= b ? a : b;
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
function sqrt(uint256 a) internal pure returns (uint256 b) {
if (a > 3) {
b = a;
uint256 x = a / 2 + 1;
while (x < b) {
b = x;
x = (a / x + x) / 2;
}
} else if (a != 0) {
b = 1;
}
}
function wmul(uint256 a, uint256 b) internal pure returns (uint256) {
return mul(a, b) / WAD;
}
function wmulRound(uint256 a, uint256 b) internal pure returns (uint256) {
return add(mul(a, b), WAD / 2) / WAD;
}
function rmul(uint256 a, uint256 b) internal pure returns (uint256) {
return mul(a, b) / RAY;
}
function rmulRound(uint256 a, uint256 b) internal pure returns (uint256) {
return add(mul(a, b), RAY / 2) / RAY;
}
function wdiv(uint256 a, uint256 b) internal pure returns (uint256) {
return div(mul(a, WAD), b);
}
function wdivRound(uint256 a, uint256 b) internal pure returns (uint256) {
return add(mul(a, WAD), b / 2) / b;
}
function rdiv(uint256 a, uint256 b) internal pure returns (uint256) {
return div(mul(a, RAY), b);
}
function rdivRound(uint256 a, uint256 b) internal pure returns (uint256) {
return add(mul(a, RAY), b / 2) / b;
}
function wpow(uint256 x, uint256 n) internal pure returns (uint256) {
uint256 result = WAD;
while (n > 0) {
if (n % 2 != 0) {
result = wmul(result, x);
}
x = wmul(x, x);
n /= 2;
}
return result;
}
function rpow(uint256 x, uint256 n) internal pure returns (uint256) {
uint256 result = RAY;
while (n > 0) {
if (n % 2 != 0) {
result = rmul(result, x);
}
x = rmul(x, x);
n /= 2;
}
return result;
}
function divCeil(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 quotient = div(a, b);
uint256 remainder = a - quotient * b;
if (remainder > 0) {
return quotient + 1;
} else {
return quotient;
}
}
}/// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
// for accounts without code, i.e. `keccak256('')`
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
// solhint-disable-next-line no-inline-assembly
assembly {
codehash := extcodehash(account)
}
return (codehash != accountHash && codehash != 0x0);
}
/**
* @dev Converts an `address` into `address payable`. Note that this is
* simply a type cast: the actual underlying value is not changed.
*
* _Available since v2.4.0._
*/
function toPayable(address account)
internal
pure
returns (address payable)
{
return payable(account);
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*
* _Available since v2.4.0._
*/
function sendValue(address recipient, uint256 amount) internal {
require(
address(this).balance >= amount,
"Address: insufficient balance"
);
// solhint-disable-next-line avoid-call-value
(bool success, ) = recipient.call{value: amount}("");
require(
success,
"Address: unable to send value, recipient may have reverted"
);
}
}/// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library RevertReasonForwarder {
function reRevert() internal pure {
// bubble up revert reason from latest external call
/// @solidity memory-safe-assembly
assembly { // solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,
* given `owner`'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Interface for DAI-style permits
interface IDaiLikePermit {
function permit(
address holder,
address spender,
uint256 nonce,
uint256 expiry,
bool allowed,
uint8 v,
bytes32 r,
bytes32 s
) external;
}{
"remappings": [
"@ensdomains/=node_modules/@ensdomains/",
"@openzeppelin/=node_modules/@openzeppelin/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"eth-gas-reporter/=node_modules/eth-gas-reporter/",
"forge-std/=lib/forge-std/src/",
"hardhat/=node_modules/hardhat/",
"@dex/=contracts/8/",
"@uniswap/=node_modules/@uniswap/",
"@zetachain/=node_modules/@zetachain/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/"
],
"optimizer": {
"enabled": true,
"runs": 1
},
"metadata": {
"useLiteralContent": true,
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"ForceApproveFailed","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidTokenPair","type":"error"},{"inputs":[],"name":"SafeTransferFailed","type":"error"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"pool","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"sellBase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"pool","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"sellQuote","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50610676806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806330e6ae311461003b5780636f7929f214610050575b600080fd5b61004e61004936600461051a565b610063565b005b61004e61005e36600461051a565b6101eb565b6000826001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100c791906105ef565b90506000816001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016100f79190610613565b602060405180830381865afa158015610114573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101389190610627565b90508060000361015b5760405163162908e360e11b815260040160405180910390fd5b61016682858361031e565b604051636e553f6560e01b8152600481018290526001600160a01b038681166024830152851690636e553f65906044015b6020604051808303816000875af11580156101b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101da9190610627565b506101e48261032e565b5050505050565b6000826001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561022b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061024f91906105ef565b90506000836001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161027f9190610613565b602060405180830381865afa15801561029c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102c09190610627565b9050806000036102e35760405163162908e360e11b815260040160405180910390fd5b604051635d043b2960e11b8152600481018290526001600160a01b03868116602483015230604483015285169063ba08765290606401610197565b6103298383836103cf565b505050565b6000610338610434565b90506001600160a01b03811661034c575050565b6040516370a0823160e01b81526000906001600160a01b038416906370a082319061037b903090600401610613565b602060405180830381865afa158015610398573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103bc9190610627565b9050801561032957610329838383610468565b6103e28363095ea7b360e01b8484610498565b610329576103fa8363095ea7b360e01b846000610498565b158061041657506104148363095ea7b360e01b8484610498565b155b156103295760405163019be9a960e41b815260040160405180910390fd5b6000601f193601356530d77d40f4cd60d21b650f2882bf0b3360d21b821601610464576001600160a01b03811691505b5090565b61047b8363a9059cbb60e01b8484610498565b6103295760405163fb7f507960e01b815260040160405180910390fd5b60006040518481528360048201528260248201526020600060448360008a5af191505080156104e4573d80156104da57600160005114601f3d111691506104e2565b6000863b1191505b505b949350505050565b6001600160a01b038116811461050157600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561052f57600080fd5b833561053a816104ec565b9250602084013561054a816104ec565b915060408401356001600160401b038082111561056657600080fd5b818601915086601f83011261057a57600080fd5b81358181111561058c5761058c610504565b604051601f8201601f19908116603f011681019083821181831017156105b4576105b4610504565b816040528281528960208487010111156105cd57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60006020828403121561060157600080fd5b815161060c816104ec565b9392505050565b6001600160a01b0391909116815260200190565b60006020828403121561063957600080fd5b505191905056fea264697066735822122036fe66bf80aa3f53ba12488e3835ecf20f0d246c867ce01a821c984c35291f9a64736f6c63430008110033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100365760003560e01c806330e6ae311461003b5780636f7929f214610050575b600080fd5b61004e61004936600461051a565b610063565b005b61004e61005e36600461051a565b6101eb565b6000826001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100c791906105ef565b90506000816001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016100f79190610613565b602060405180830381865afa158015610114573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101389190610627565b90508060000361015b5760405163162908e360e11b815260040160405180910390fd5b61016682858361031e565b604051636e553f6560e01b8152600481018290526001600160a01b038681166024830152851690636e553f65906044015b6020604051808303816000875af11580156101b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101da9190610627565b506101e48261032e565b5050505050565b6000826001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561022b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061024f91906105ef565b90506000836001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161027f9190610613565b602060405180830381865afa15801561029c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102c09190610627565b9050806000036102e35760405163162908e360e11b815260040160405180910390fd5b604051635d043b2960e11b8152600481018290526001600160a01b03868116602483015230604483015285169063ba08765290606401610197565b6103298383836103cf565b505050565b6000610338610434565b90506001600160a01b03811661034c575050565b6040516370a0823160e01b81526000906001600160a01b038416906370a082319061037b903090600401610613565b602060405180830381865afa158015610398573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103bc9190610627565b9050801561032957610329838383610468565b6103e28363095ea7b360e01b8484610498565b610329576103fa8363095ea7b360e01b846000610498565b158061041657506104148363095ea7b360e01b8484610498565b155b156103295760405163019be9a960e41b815260040160405180910390fd5b6000601f193601356530d77d40f4cd60d21b650f2882bf0b3360d21b821601610464576001600160a01b03811691505b5090565b61047b8363a9059cbb60e01b8484610498565b6103295760405163fb7f507960e01b815260040160405180910390fd5b60006040518481528360048201528260248201526020600060448360008a5af191505080156104e4573d80156104da57600160005114601f3d111691506104e2565b6000863b1191505b505b949350505050565b6001600160a01b038116811461050157600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561052f57600080fd5b833561053a816104ec565b9250602084013561054a816104ec565b915060408401356001600160401b038082111561056657600080fd5b818601915086601f83011261057a57600080fd5b81358181111561058c5761058c610504565b604051601f8201601f19908116603f011681019083821181831017156105b4576105b4610504565b816040528281528960208487010111156105cd57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60006020828403121561060157600080fd5b815161060c816104ec565b9392505050565b6001600160a01b0391909116815260200190565b60006020828403121561063957600080fd5b505191905056fea264697066735822122036fe66bf80aa3f53ba12488e3835ecf20f0d246c867ce01a821c984c35291f9a64736f6c63430008110033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.