Source Code
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Cross-Chain Transactions
Loading...
Loading
Contract Name:
AlgebraAdapter
Compiler Version
v0.8.30+commit.73712a01
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
prague EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// ╟╗ ╔╬
// ╞╬╬ ╬╠╬
// ╔╣╬╬╬ ╠╠╠╠╦
// ╬╬╬╬╬╩ ╘╠╠╠╠╬
// ║╬╬╬╬╬ ╘╠╠╠╠╬
// ╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╒╬╬╬╬╬╬╬╜ ╠╠╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╬╬╬╬╬╬╬╬╠╠╠╠╠╠╠╠
// ╙╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╕ ╬╬╬╬╬╬╬╜ ╣╠╠╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╬╬╬╬╬╬╬╬╬╠╠╠╠╠╠╠╩
// ╙╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╔╬╬╬╬╬╬╬ ╔╠╠╠╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╣╬╬╬╬╬╬╬╬╬╬╬╠╠╠╠╝╙
// ╘╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╒╠╠╠╬╠╬╩╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╣╬╬╬╬╬╬╬╙
// ╣╬╬╬╬╬╬╬╬╬╬╠╣ ╣╬╠╠╠╬╩ ╚╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╬╬╬╬╬╬╬
// ╣╬╬╬╬╬╬╬╬╬╣ ╣╬╠╠╠╬╬ ╣╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╬╬╬╬╬╬╬
// ╟╬╬╬╬╬╬╬╩ ╬╬╠╠╠╠╬╬╬╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╠╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╒╬╬╠╠╬╠╠╬╬╬╬╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╣╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╬╬╬╠╠╠╠╝╝╝╝╝╝╝╠╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╚╬╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╣╬╬╬╬╠╠╩ ╘╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╙╬╬╬╬╬╬╬╬
//
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.30;
import {
UniswapV3likeAdapter, QParams, IUniV3Pool
} from "contracts/adapters/UniswapV3likeAdapter.sol";
import {SafeERC20, IERC20} from "contracts/lib/SafeERC20.sol";
interface IAlgebraFactory {
function poolByPair(address, address) external view returns (address);
}
interface IAlgebraPool {
function swapSupportingFeeOnInputTokens(
address sender,
address recipient,
bool zeroForOne,
int256 amountSpecified,
uint160 sqrtPriceLimitX96,
bytes calldata data
) external returns (int256 amount0, int256 amount1);
}
contract AlgebraAdapter is UniswapV3likeAdapter {
using SafeERC20 for IERC20;
address public immutable FACTORY;
constructor(
string memory _name,
uint256 _quoterGasLimit,
address _router,
address _quoter,
address _factory
) UniswapV3likeAdapter(_name, _quoterGasLimit, _router, _quoter) {
if (_factory == address(0) || _quoter == address(0)) revert AddressZero();
FACTORY = _factory;
}
function getBestPool(address token0, address token1)
internal
view
override
returns (address mostLiquid)
{
return IAlgebraFactory(FACTORY).poolByPair(token0, token1);
}
function algebraSwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata)
external
{
if (msg.sender != tempPoolAddress) revert NotPoolAddress();
if (amount0Delta > 0) {
IERC20(IUniV3Pool(msg.sender).token0()).transfer(msg.sender, uint256(amount0Delta));
} else {
IERC20(IUniV3Pool(msg.sender).token1()).transfer(msg.sender, uint256(amount1Delta));
}
}
function _underlyingSwap(QParams memory params, bytes memory callbackData)
internal
virtual
override
returns (uint256)
{
tempPoolAddress = getBestPool(params.tokenIn, params.tokenOut);
(bool zeroForOne, uint160 priceLimit) =
getZeroOneAndSqrtPriceLimitX96(params.tokenIn, params.tokenOut);
(int256 amount0, int256 amount1) = IAlgebraPool(tempPoolAddress)
.swapSupportingFeeOnInputTokens(
address(this),
address(this),
zeroForOne,
int256(params.amount),
priceLimit,
callbackData
);
return zeroForOne ? uint256(-amount1) : uint256(-amount0);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `_msgSender()` is missing `role`.
* Overriding this function changes the behavior of the {onlyRole} modifier.
*
* Format of the revert message is described in {_checkRole}.
*
* _Available since v4.6._
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(account),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* May emit a {RoleGranted} event.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*
* NOTE: This function is deprecated in favor of {_grantRole}.
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Grants `role` to `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
/**
* @dev Revokes `role` from `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/Math.sol";
import "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}// ╟╗ ╔╬
// ╞╬╬ ╬╠╬
// ╔╣╬╬╬ ╠╠╠╠╦
// ╬╬╬╬╬╩ ╘╠╠╠╠╬
// ║╬╬╬╬╬ ╘╠╠╠╠╬
// ╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╒╬╬╬╬╬╬╬╜ ╠╠╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╬╬╬╬╬╬╬╬╠╠╠╠╠╠╠╠
// ╙╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╕ ╬╬╬╬╬╬╬╜ ╣╠╠╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╬╬╬╬╬╬╬╬╬╠╠╠╠╠╠╠╩
// ╙╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╔╬╬╬╬╬╬╬ ╔╠╠╠╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╣╬╬╬╬╬╬╬╬╬╬╬╠╠╠╠╝╙
// ╘╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╒╠╠╠╬╠╬╩╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╣╬╬╬╬╬╬╬╙
// ╣╬╬╬╬╬╬╬╬╬╬╠╣ ╣╬╠╠╠╬╩ ╚╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╬╬╬╬╬╬╬
// ╣╬╬╬╬╬╬╬╬╬╣ ╣╬╠╠╠╬╬ ╣╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╬╬╬╬╬╬╬
// ╟╬╬╬╬╬╬╬╩ ╬╬╠╠╠╠╬╬╬╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╠╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╒╬╬╠╠╬╠╠╬╬╬╬╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╣╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╬╬╬╠╠╠╠╝╝╝╝╝╝╝╠╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╚╬╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╣╬╬╬╬╠╠╩ ╘╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╙╬╬╬╬╬╬╬╬
//
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.0;
import {IERC20} from "contracts/interface/IERC20.sol";
import {SafeERC20} from "contracts/lib/SafeERC20.sol";
import {YakAdapter} from "contracts/YakAdapter.sol";
struct QParams {
address tokenIn;
address tokenOut;
int256 amount;
bool exactIn;
}
interface IUniV3Pool {
function swap(
address recipient,
bool zeroForOne,
int256 amountSpecified,
uint160 sqrtPriceLimitX96,
bytes calldata data
) external returns (int256 amount0, int256 amount1);
function token0() external view returns (address);
function token1() external view returns (address);
function liquidity() external view returns (uint128);
}
interface IUniV3Quoter {
function quoteExactInputSingle(QParams memory params) external view returns (uint256);
function quote(address, bool, int256, uint160) external view returns (int256, int256);
}
abstract contract UniswapV3likeAdapter is YakAdapter {
using SafeERC20 for IERC20;
error InsufficientOutputAmount(uint256 amountOut, uint256 requiredAmount);
error NotPoolAddress();
error InvalidGasLimit();
event QuoterUpdated(address newQuoter);
event QuoterGasLimitSet(uint256 newGasLimit);
uint160 internal constant MAX_SQRT_RATIO =
1_461_446_703_485_210_103_287_273_052_203_988_822_378_723_970_342;
uint160 internal constant MIN_SQRT_RATIO = 4_295_128_739;
uint256 public quoterGasLimit;
address public immutable ROUTER;
address public quoter;
address public tempPoolAddress;
constructor(string memory _name, uint256 _quoterGasLimit, address _router, address _quoter)
YakAdapter(_name)
{
if (_router == address(0)) revert AddressZero();
ROUTER = _router;
setQuoterGasLimit(_quoterGasLimit);
setQuoter(_quoter);
}
function setQuoter(address newQuoter) public onlyMaintainer {
if (newQuoter == address(0)) revert AddressZero();
quoter = newQuoter;
emit QuoterUpdated(newQuoter);
}
function setQuoterGasLimit(uint256 newGasLimit) public onlyMaintainer {
if (newGasLimit == 0) revert InvalidGasLimit();
quoterGasLimit = newGasLimit;
emit QuoterGasLimitSet(newGasLimit);
}
function getQuoteForPool(
address pool,
uint256 amount,
address tokenIn,
address tokenOut,
bool exactIn
) external view returns (uint256) {
QParams memory params;
params.amount = exactIn ? int256(amount) : -int256(amount);
params.tokenIn = tokenIn;
params.tokenOut = tokenOut;
params.exactIn = exactIn;
return getQuoteForPool(pool, params);
}
function _query(uint256 _amount, address _tokenIn, address _tokenOut, bool _exactIn)
internal
view
override
returns (uint256 quote, address recipient)
{
QParams memory params = getQParams(_amount, _tokenIn, _tokenOut, _exactIn);
quote = getQuoteForBestPool(params);
recipient = address(this);
}
function _swap(
uint256 _amountIn,
uint256 _amountOut,
address _tokenIn,
address _tokenOut,
address _to
) internal override {
QParams memory params = getQParams(_amountIn, _tokenIn, _tokenOut, true);
uint256 amountOutBefore = IERC20(_tokenOut).balanceOf(address(this));
_underlyingSwap(params, new bytes(0));
uint256 amountOutAfter = IERC20(_tokenOut).balanceOf(address(this));
uint256 amountOut = amountOutAfter - amountOutBefore;
if (amountOut < _amountOut) revert InsufficientOutputAmount(amountOut, _amountOut);
tempPoolAddress = address(0);
uint256 remainingBalance = IERC20(_tokenIn).balanceOf(address(this));
if (remainingBalance > 0) IERC20(_tokenIn).safeTransfer(ROUTER, remainingBalance);
_returnTo(_tokenOut, amountOut, _to);
}
function getQParams(uint256 amount, address tokenIn, address tokenOut, bool exactIn)
internal
pure
returns (QParams memory params)
{
params = QParams({
amount: exactIn ? int256(amount) : -int256(amount),
tokenIn: tokenIn,
tokenOut: tokenOut,
exactIn: exactIn
});
}
function _underlyingSwap(QParams memory params, bytes memory callbackData)
internal
virtual
returns (uint256)
{
address pool = getBestPool(params.tokenIn, params.tokenOut);
(bool zeroForOne, uint160 priceLimit) =
getZeroOneAndSqrtPriceLimitX96(params.tokenIn, params.tokenOut);
(int256 amount0, int256 amount1) = IUniV3Pool(pool).swap(
address(this), zeroForOne, int256(params.amount), priceLimit, callbackData
);
return zeroForOne ? uint256(-amount1) : uint256(-amount0);
}
function getQuoteForBestPool(QParams memory params) internal view returns (uint256 quote) {
address bestPool = getBestPool(params.tokenIn, params.tokenOut);
if (bestPool != address(0)) quote = getQuoteForPool(bestPool, params);
}
function getBestPool(address token0, address token1)
internal
view
virtual
returns (address mostLiquid);
function getQuoteForPool(address pool, QParams memory params) internal view returns (uint256) {
(bool zeroForOne, uint160 priceLimit) =
getZeroOneAndSqrtPriceLimitX96(params.tokenIn, params.tokenOut);
(int256 amount0, int256 amount1) = getQuoteSafe(pool, zeroForOne, params.amount, priceLimit);
return params.exactIn
? (zeroForOne ? uint256(-amount1) : uint256(-amount0))
: (zeroForOne ? uint256(amount0) : uint256(amount1));
}
function getQuoteSafe(address pool, bool zeroForOne, int256 amount, uint160 priceLimit)
internal
view
returns (int256 amount0, int256 amount1)
{
bytes memory calldata_ = abi.encodeWithSignature(
"quote(address,bool,int256,uint160)", pool, zeroForOne, amount, priceLimit
);
(bool success, bytes memory data) = staticCallQuoterRaw(calldata_);
if (success) (amount0, amount1) = abi.decode(data, (int256, int256));
}
function staticCallQuoterRaw(bytes memory calldata_)
internal
view
returns (bool success, bytes memory data)
{
(success, data) = quoter.staticcall{gas: quoterGasLimit}(calldata_);
}
function getZeroOneAndSqrtPriceLimitX96(address tokenIn, address tokenOut)
internal
pure
returns (bool zeroForOne, uint160 sqrtPriceLimitX96)
{
zeroForOne = tokenIn < tokenOut;
sqrtPriceLimitX96 = zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title IAdapter
* @author Yak Exchange
* @notice Interface for DEX adapter contracts that integrate various AMMs
* @dev Each adapter implements swap functionality for a specific DEX protocol
*/
interface IAdapter {
/**
* @notice Returns the name of the adapter
* @return name The adapter's descriptive name (e.g., "UniswapV2Adapter")
*/
function name() external view returns (string memory);
/**
* @notice Executes a token swap through the adapter's underlying DEX
* @param _amountIn Amount of input tokens to swap
* @param _amountOut Minimum amount of output tokens expected
* @param _fromToken Address of the input token
* @param _toToken Address of the output token
* @param _to Address that will receive the output tokens
* @dev Adapter must ensure _to receives at least _amountOut tokens
*/
function swap(uint256 _amountIn, uint256 _amountOut, address _fromToken, address _toToken, address _to) external;
/**
* @notice Queries the adapter for expected swap output/input amount
* @param _amount Input amount (if exactIn) or output amount (if !exactIn)
* @param _tokenIn Address of the input token
* @param _tokenOut Address of the output token
* @param _exactIn True for exact input quote, false for exact output quote
* @return amountOut The output amount (if exactIn) or required input amount (if !exactIn)
* @return recipient The address that should receive tokens for this adapter
* @dev Should return (0, address(0)) if swap is not available
*/
function query(uint256 _amount, address _tokenIn, address _tokenOut, bool _exactIn)
external
view
returns (uint256 amountOut, address recipient);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC20 {
event Approval(address, address, uint256);
event Transfer(address, address, uint256);
function name() external view returns (string memory);
function decimals() external view returns (uint8);
function transferFrom(
address,
address,
uint256
) external returns (bool);
function allowance(address, address) external view returns (uint256);
function approve(address, uint256) external returns (bool);
function transfer(address, uint256) external returns (bool);
function balanceOf(address) external view returns (uint256);
function nonces(address) external view returns (uint256); // Only tokens that support permit
function permit(
address,
address,
uint256,
uint256,
uint8,
bytes32,
bytes32
) external; // Only tokens that support permit
function swap(address, uint256) external; // Only Avalanche bridge tokens
function swapSupply(address) external view returns (uint256); // Only Avalanche bridge tokens
function totalSupply() external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {AccessControl, Context} from "@openzeppelin/contracts/access/AccessControl.sol";
/**
* @dev Contract module which extends the basic access control mechanism of Ownable
* to include many maintainers, whom only the owner (DEFAULT_ADMIN_ROLE) may add and
* remove.
*
* By default, the owner account will be the one that deploys the contract. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available this modifier:
* `onlyMaintainer`, which can be applied to your functions to restrict their use to
* the accounts with the role of maintainer.
*/
abstract contract Maintainable is Context, AccessControl {
error OnlyMaintainer();
bytes32 public constant MAINTAINER_ROLE = keccak256("MAINTAINER_ROLE");
constructor() {
address msgSender = _msgSender();
// members of the DEFAULT_ADMIN_ROLE alone may revoke and grant role membership
_setupRole(DEFAULT_ADMIN_ROLE, msgSender);
_setupRole(MAINTAINER_ROLE, msgSender);
}
function addMaintainer(address addedMaintainer) public virtual {
grantRole(MAINTAINER_ROLE, addedMaintainer);
}
function removeMaintainer(address removedMaintainer) public virtual {
revokeRole(MAINTAINER_ROLE, removedMaintainer);
}
function renounceRole(bytes32 role) public virtual {
address msgSender = _msgSender();
renounceRole(role, msgSender);
}
function transferOwnership(address newOwner) public virtual {
address msgSender = _msgSender();
grantRole(DEFAULT_ADMIN_ROLE, newOwner);
renounceRole(DEFAULT_ADMIN_ROLE, msgSender);
}
modifier onlyMaintainer() {
address msgSender = _msgSender();
if (!hasRole(MAINTAINER_ROLE, msgSender)) revert OnlyMaintainer();
_;
}
}// This is a simplified version of OpenZepplin's SafeERC20 library
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;
import {IERC20} from "contracts/interface/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 ERC20;` 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(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(
token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)
);
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 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).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 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.
// A Solidity high level call has three parts:
// 1. The target address is checked to verify it contains contract code
// 2. The call itself is made, and success asserted
// 3. The return value is decoded, which in turn checks the size of the returned data.
// solhint-disable-next-line max-line-length
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// ╟╗ ╔╬
// ╞╬╬ ╬╠╬
// ╔╣╬╬╬ ╠╠╠╠╦
// ╬╬╬╬╬╩ ╘╠╠╠╠╬
// ║╬╬╬╬╬ ╘╠╠╠╠╬
// ╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╒╬╬╬╬╬╬╬╜ ╠╠╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╬╬╬╬╬╬╬╬╠╠╠╠╠╠╠╠
// ╙╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╕ ╬╬╬╬╬╬╬╜ ╣╠╠╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╬╬╬╬╬╬╬╬╬╠╠╠╠╠╠╠╩
// ╙╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╔╬╬╬╬╬╬╬ ╔╠╠╠╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╣╬╬╬╬╬╬╬╬╬╬╬╠╠╠╠╝╙
// ╘╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╒╠╠╠╬╠╬╩╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╣╬╬╬╬╬╬╬╙
// ╣╬╬╬╬╬╬╬╬╬╬╠╣ ╣╬╠╠╠╬╩ ╚╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╬╬╬╬╬╬╬
// ╣╬╬╬╬╬╬╬╬╬╣ ╣╬╠╠╠╬╬ ╣╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╬╬╬╬╬╬╬
// ╟╬╬╬╬╬╬╬╩ ╬╬╠╠╠╠╬╬╬╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╠╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╒╬╬╠╠╬╠╠╬╬╬╬╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╣╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╬╬╬╠╠╠╠╝╝╝╝╝╝╝╠╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╚╬╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╣╬╬╬╬╠╠╩ ╘╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╙╬╬╬╬╬╬╬╬
//
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.0;
import {IAdapter} from "contracts/interface/IAdapter.sol";
import {IERC20} from "contracts/interface/IERC20.sol";
import {SafeERC20} from "contracts/lib/SafeERC20.sol";
import {Maintainable} from "contracts/lib/Maintainable.sol";
/**
* @title YakAdapter
* @notice Abstract base contract for DEX adapters
* @dev Implements common functionality for all adapters including token recovery and safety checks
*/
abstract contract YakAdapter is IAdapter, Maintainable {
using SafeERC20 for IERC20;
/**
* @notice Thrown when a zero address is provided
*/
error AddressZero();
/**
* @notice Thrown when ETH transfer fails
*/
error ETHTransferFailed();
/**
* @notice Thrown when adapter name is empty
*/
error InvalidAdapterName();
/**
* @notice Thrown when query parameters are invalid
*/
error InvalidQuery();
/**
* @notice Thrown when trying to recover zero amount
*/
error NothingToRecover();
/**
* @notice Thrown when swap output is less than required
* @param amountOut Actual output amount
* @param requiredAmount Required minimum output
*/
error InsufficientAmountOut(uint256 amountOut, uint256 requiredAmount);
/**
* @notice Emitted when a swap is executed through the adapter
* @param _tokenFrom Input token address
* @param _tokenTo Output token address
* @param _amountIn Input amount
* @param _amountOut Output amount
*/
event YakAdapterSwap(
address indexed _tokenFrom, address indexed _tokenTo, uint256 _amountIn, uint256 _amountOut
);
/**
* @notice Emitted when tokens are recovered from the adapter
* @param _asset Token address (address(0) for ETH)
* @param amount Amount recovered
*/
event Recovered(address indexed _asset, uint256 amount);
/// @notice Name of the adapter
string public name;
/**
* @notice Initializes the adapter with a name
* @param _name Name of the adapter
* @dev Name cannot be empty
*/
constructor(string memory _name) {
if (bytes(_name).length == 0) revert InvalidAdapterName();
name = _name;
}
/**
* @notice Revokes token approval for a spender
* @param _token Token address
* @param _spender Spender address
* @dev Only callable by maintainer
*/
function revokeAllowance(address _token, address _spender) external onlyMaintainer {
IERC20(_token).safeApprove(_spender, 0);
}
/**
* @notice Recovers ERC20 tokens sent to this contract
* @param _tokenAddress Token to recover
* @param _tokenAmount Amount to recover
* @dev Only callable by maintainer
*/
function recoverERC20(address _tokenAddress, uint256 _tokenAmount) external onlyMaintainer {
if (_tokenAmount == 0) revert NothingToRecover();
IERC20(_tokenAddress).safeTransfer(msg.sender, _tokenAmount);
emit Recovered(_tokenAddress, _tokenAmount);
}
/**
* @notice Recovers ETH sent to this contract
* @param _amount Amount of ETH to recover
* @dev Only callable by maintainer
*/
function recoverETH(uint256 _amount) external onlyMaintainer {
if (_amount == 0) revert NothingToRecover();
(bool success,) = msg.sender.call{value: _amount}("");
if (!success) revert ETHTransferFailed();
emit Recovered(address(0), _amount);
}
/**
* @notice External query function that delegates to internal implementation
* @inheritdoc IAdapter
*/
function query(uint256 _amount, address _tokenIn, address _tokenOut, bool _exactIn)
external
view
returns (uint256, address)
{
(uint256 quoteAmount, address recipient) = _query(_amount, _tokenIn, _tokenOut, _exactIn);
if (quoteAmount == 0 || recipient == address(0)) revert InvalidQuery();
return (quoteAmount, recipient);
}
/**
* @notice External swap function
* @inheritdoc IAdapter
*/
function swap(
uint256 _amountIn,
uint256 _amountOut,
address _fromToken,
address _toToken,
address _to
) external virtual {
_swap(_amountIn, _amountOut, _fromToken, _toToken, _to);
emit YakAdapterSwap(_fromToken, _toToken, _amountIn, _amountOut);
}
/**
* @notice Transfers tokens to recipient if not this contract
* @param _token Token to transfer
* @param _amount Amount to transfer
* @param _to Recipient address
* @dev Skips transfer if recipient is this contract
*/
function _returnTo(address _token, uint256 _amount, address _to) internal {
if (address(this) != _to) IERC20(_token).safeTransfer(_to, _amount);
}
/**
* @notice Internal swap implementation to be overridden by adapters
* @param _amountIn Amount of input tokens
* @param _amountOut Minimum output amount expected
* @param _fromToken Input token address
* @param _toToken Output token address
* @param _to Recipient address
* @dev Must be implemented by concrete adapters
*/
function _swap(
uint256 _amountIn,
uint256 _amountOut,
address _fromToken,
address _toToken,
address _to
) internal virtual;
/**
* @notice Internal query implementation to be overridden by adapters
* @param _amount Input or output amount depending on exactIn
* @param _tokenIn Input token address
* @param _tokenOut Output token address
* @param _exactIn True for exact input, false for exact output
* @return amountOut Output amount or required input
* @return recipient Address that should receive tokens
* @dev Must be implemented by concrete adapters
*/
function _query(uint256 _amount, address _tokenIn, address _tokenOut, bool _exactIn)
internal
view
virtual
returns (uint256, address);
/**
* @notice Fallback function to receive ETH
*/
receive() external payable {}
}{
"evmVersion": "prague",
"optimizer": {
"enabled": true,
"runs": 1000000,
"details": {
"yulDetails": {
"optimizerSteps": "u"
}
}
},
"viaIR": true,
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"uint256","name":"_quoterGasLimit","type":"uint256"},{"internalType":"address","name":"_router","type":"address"},{"internalType":"address","name":"_quoter","type":"address"},{"internalType":"address","name":"_factory","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressZero","type":"error"},{"inputs":[],"name":"ETHTransferFailed","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"requiredAmount","type":"uint256"}],"name":"InsufficientAmountOut","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"requiredAmount","type":"uint256"}],"name":"InsufficientOutputAmount","type":"error"},{"inputs":[],"name":"InvalidAdapterName","type":"error"},{"inputs":[],"name":"InvalidGasLimit","type":"error"},{"inputs":[],"name":"InvalidQuery","type":"error"},{"inputs":[],"name":"NotPoolAddress","type":"error"},{"inputs":[],"name":"NothingToRecover","type":"error"},{"inputs":[],"name":"OnlyMaintainer","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newGasLimit","type":"uint256"}],"name":"QuoterGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newQuoter","type":"address"}],"name":"QuoterUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_tokenFrom","type":"address"},{"indexed":true,"internalType":"address","name":"_tokenTo","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_amountOut","type":"uint256"}],"name":"YakAdapterSwap","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FACTORY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAINTAINER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROUTER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addedMaintainer","type":"address"}],"name":"addMaintainer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"algebraSwapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"bool","name":"exactIn","type":"bool"}],"name":"getQuoteForPool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_tokenIn","type":"address"},{"internalType":"address","name":"_tokenOut","type":"address"},{"internalType":"bool","name":"_exactIn","type":"bool"}],"name":"query","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quoter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quoterGasLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"recoverETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"removedMaintainer","type":"address"}],"name":"removeMaintainer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_spender","type":"address"}],"name":"revokeAllowance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newQuoter","type":"address"}],"name":"setQuoter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newGasLimit","type":"uint256"}],"name":"setQuoterGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"uint256","name":"_amountOut","type":"uint256"},{"internalType":"address","name":"_fromToken","type":"address"},{"internalType":"address","name":"_toToken","type":"address"},{"internalType":"address","name":"_to","type":"address"}],"name":"swap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tempPoolAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60c06040523461004e5761001d6100146101b1565b939290926101ec565b60405161266f61074582396080518181816106f90152611b1b015260a05181818161066e0152612599015261266f90f35b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b90601f01601f191681019081106001600160401b0382111761008757604052565b610052565b906100a061009960405190565b9283610066565b565b6001600160401b03811161008757602090601f01601f19160190565b90825f9392825e0152565b909291926100de6100d9826100a2565b61008c565b938185528183011161004e576100a09160208501906100be565b9080601f8301121561004e578151610112926020016100c9565b90565b805b0361004e57565b905051906100a082610115565b6001600160a01b031690565b6001600160a01b038116610117565b905051906100a082610137565b919060a08382031261004e5782516001600160401b03811161004e578161017b9185016100f8565b92610189826020830161011e565b9261011261019a8460408501610146565b9360806101aa8260608701610146565b9401610146565b6101cf612dd4803803806101c48161008c565b928339810190610153565b9091929394565b61012b6101126101129290565b610112906101d6565b9183916101f893610251565b6102015f6101e3565b906001600160a01b0382166001600160a01b0384161491821561023b575b505061022a5760a052565b639fabe1c160e01b5f908152600490fd5b6001600160a01b03908116925016145f8061021f565b61025e9093929193610459565b61026a61012b5f6101e3565b6001600160a01b0382161461022a576100a09261028991608052610587565b61065a565b6101126101126101129290565b634e487b7160e01b5f52602260045260245ffd5b90600160028304921680156102cf575b60208310146102ca57565b61029b565b91607f16916102bf565b915f1960089290920291821b911b5b9181191691161790565b919061030361011261030b9361028e565b9083546102d9565b9055565b6100a0915f916102f2565b818110610325575050565b806103325f60019361030f565b0161031a565b9190601f811161034757505050565b6103576100a0935f5260205f2090565b906020601f840181900483019310610379575b6020601f90910104019061031a565b909150819061036a565b9061038c815190565b906001600160401b038211610087576103af826103a985546102af565b85610338565b602090601f83116001146103e85761030b92915f91836103dd575b50505f19600883021c1916906002021790565b015190505f806103ca565b601f198316916103fb855f5260205f2090565b925f5b8181106104375750916002939185600196941061041f575b50505002019055565b01515f196008601f8516021c191690555f8080610416565b919360206001819287870151815501950192016103fe565b906100a091610383565b61046161049d565b805161047361046f5f61028e565b9190565b14610483576100a090600161044f565b630b388d8d60e11b5f908152600490fd5b6101125f61028e565b6100a0336104b2816104ad610494565b610663565b5f516020612db45f395f51905f52610663565b6104e46104e0335b5f516020612db45f395f51905f52610685565b1590565b6104f1576100a090610522565b6301c42f3160e61b5f908152600490fd5b905f19906102e8565b9061051b61011261030b9261028e565b8254610502565b61052b5f61028e565b811461057657610571816105617f575efdb178bd088e0c8dfe86c45529c7829d6060a40bf6f6ef7628939f823c2993600261050b565b6040519182918290815260200190565b0390a1565b6304c5ed9760e51b5f908152600490fd5b6100a0906104c5565b61059c6104e0336104cd565b6104f1576100a0906105f5565b906001600160a01b03906102e8565b6101129061012b906001600160a01b031682565b610112906105b8565b610112906105cc565b906105ee61011261030b926105d5565b82546105a9565b61060161012b5f6101e3565b6001600160a01b0382161461022a57610571816106407f06526a30af2ff868c2686df12e95844d8ae300416bbec5d5ccc2d2f4afdb17a09360036105de565b604051918291826001600160a01b03909116815260200190565b6100a090610590565b906100a0916106cc565b905b5f5260205260405f2090565b9061066f906105d5565b610112915f61069f6106a5936106985f90565b508261066d565b0161067b565b5460ff1690565b9060ff906102e8565b906106c561011261030b92151590565b82546106ac565b6106d96104e08383610685565b6106e1575050565b6106fa60016106f5845f61069f868261066d565b6106b5565b61071461070e610708339390565b936105d5565b916105d5565b917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d61073f60405190565b5f90a456fe6080604052600436101561001a575b3615610018575f80fd5b005b5f3560e01c806301ffc9a7146101c957806306fdde03146101c4578063129be381146101bf578063248a9ca3146101ba5780632bc857a0146101b55780632c8958f6146101b05780632dd31000146101ab5780632f2ff15d146101a657806332fe7b26146101a157806336568abe1461019c578063409d653d1461019757806348f12791146101925780636b453c1f1461018d5780637ae26773146101885780638980f11f146101835780638bb9c5bf1461017e57806391d1485414610179578063a217fddf14610174578063c6bbd5a71461016f578063d33355531461016a578063d547741f14610165578063d8baf7cf14610160578063eab90da61461015b578063f2fde38b14610156578063f35c4d4514610151578063f87422541461014c5763f912c64b0361000e57610a78565b610a3f565b610a27565b610a0f565b6109f3565b610996565b61097d565b610965565b61094a565b610924565b6108ea565b6108d2565b6108b9565b61087d565b610849565b610816565b61079f565b61071d565b6106e4565b6106cb565b610659565b610638565b6105a7565b61055a565b61050c565b610494565b610227565b7fffffffff0000000000000000000000000000000000000000000000000000000081165b036101f957565b5f80fd5b9050359061020a826101ce565b565b906020828203126101f957610220916101fd565b90565b9052565b346101f95761025461024261023d36600461020c565b610a90565b60405191829182901515815260200190565b0390f35b5f9103126101f957565b7f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b90600160028304921680156102db575b60208310146102d657565b61028e565b91607f16916102cb565b80545f9392916103016102f7836102bb565b8085529360200190565b9160018116908115610350575060011461031a57505050565b61032b91929394505f5260205f2090565b915f925b81841061033c5750500190565b80548484015260209093019260010161032f565b92949550505060ff1916825215156020020190565b90610220916102e5565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810190811067ffffffffffffffff8211176103dc57604052565b61036f565b9061020a6103fb926103f260405190565b93848092610365565b038361039c565b905f1061041257610220906103e1565b610262565b6102205f6001610402565b90825f9392825e0152565b61044e61045760209361047f93610442815190565b80835293849260200190565b95869101610422565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690565b0190565b60208082526102209291019061042d565b346101f9576104a4366004610258565b6102546104af610417565b60405191829182610483565b610220916008021c5b73ffffffffffffffffffffffffffffffffffffffff1690565b9061022091546104bb565b6102205f60046104dd565b610223906104c4565b60208101929161020a91906104f3565b346101f95761051c366004610258565b6102546105276104e8565b604051918291826104fc565b806101f2565b9050359061020a82610533565b906020828203126101f95761022091610539565b346101f957610254610575610570366004610546565b610b4b565b6040515b9182918290815260200190565b610220916008021c81565b906102209154610586565b6102205f6002610591565b346101f9576105b7366004610258565b61025461057561059c565b909182601f830112156101f95781359167ffffffffffffffff83116101f95760200192600183028401116101f957565b916060838303126101f9576106078284610539565b926106158360208301610539565b92604082013567ffffffffffffffff81116101f95761063492016105c2565b9091565b346101f95761065461064b3660046105f2565b92919091610c1b565b604051005b346101f957610669366004610258565b6102547f0000000000000000000000000000000000000000000000000000000000000000610527565b6101f2816104c4565b9050359061020a82610692565b91906040838203126101f9576102209060206106c48286610539565b940161069b565b346101f9576106546106de3660046106a8565b90610df9565b346101f9576106f4366004610258565b6102547f0000000000000000000000000000000000000000000000000000000000000000610527565b346101f9576106546107303660046106a8565b90610e94565b8015156101f2565b9050359061020a82610736565b6080818303126101f95761075f8282610539565b92610220610770846020850161069b565b936060610780826040870161069b565b940161073e565b90815260408101929161020a916020905b01906104f3565b346101f9576107bb6107b236600461074b565b92919091610ecf565b906102546107c860405190565b92839283610787565b919060a0838203126101f9576107e7818461069b565b926107f58260208301610539565b92610220610806846040850161069b565b936080610780826060870161069b565b346101f95761025461057561082c3660046107d1565b93929092610fed565b906020828203126101f9576102209161069b565b346101f95761065461085c366004610835565b61105b565b91906040838203126101f9576102209060206106c4828661069b565b346101f957610654610890366004610861565b9061110c565b91906040838203126101f9576102209060206108b2828661069b565b9401610539565b346101f9576106546108cc366004610896565b906111af565b346101f9576106546108e5366004610546565b6111b9565b346101f9576102546102426109003660046106a8565b906111e2565b6102206102206102209290565b6102205f610906565b610220610913565b346101f957610934366004610258565b61025461057561091c565b6102205f60036104dd565b346101f95761095a366004610258565b61025461052761093f565b346101f957610654610978366004610546565b61131e565b346101f9576106546109903660046106a8565b90611342565b346101f9576106546109a9366004610835565b61134c565b919060a0838203126101f9576109c48184610539565b926109d28260208301610539565b926102206109e3846040850161069b565b9360806106c4826060870161069b565b346101f957610654610a063660046109ae565b93929092611389565b346101f957610654610a22366004610835565b6113e0565b346101f957610654610a3a366004610546565b6114cd565b346101f957610a4f366004610258565b6102547f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab95610575565b346101f957610654610a8b366004610835565b611596565b7f7965db0b000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000821614908115610ae0575090565b61022091507fffffffff00000000000000000000000000000000000000000000000000000000167f01ffc9a7000000000000000000000000000000000000000000000000000000001490565b905b5f5260205260405f2090565b6102209081565b6102209054610b3a565b6001610b6261022092610b5b5f90565b505f610b2c565b01610b41565b610220906104c4565b6102209054610b68565b6104c46102206102209273ffffffffffffffffffffffffffffffffffffffff1690565b61022090610b7b565b61022090610b9e565b9050519061020a82610692565b906020828203126101f95761022091610bb0565b6040513d5f823e3d90fd5b9050519061020a82610736565b906020828203126101f95761022091610bdc565b91602061020a929493610c1760408201965f8301906104f3565b0152565b92509050610c31610c2c6004610b71565b6104c4565b610c3a336104c4565b03610dad57610c485f610906565b821315610d6b5750610c61610c5c33610ba7565b610ba7565b6020610c6c60405190565b9182907f0dfe1681000000000000000000000000000000000000000000000000000000005b825260049082905afa8015610d39575f92610cc5610cbf610c5c610cfd946020968891610d3e575b50610ba7565b91610906565b60405194859384928391907fa9059cbb0000000000000000000000000000000000000000000000000000000083523360048401610bfd565b03925af18015610d3957610d0e5750565b610d2f9060203d602011610d32575b610d27818361039c565b810190610be9565b50565b503d610d1d565b610bd1565b610d5e9150873d8911610d64575b610d56818361039c565b810190610bbd565b5f610cb9565b503d610d4c565b9050610d79610c5c33610ba7565b6020610d8460405190565b9182907fd21220a700000000000000000000000000000000000000000000000000000000610c91565b7f136bd7cc000000000000000000000000000000000000000000000000000000005f90815260045b035ffd5b9061020a91610def610dea82610b4b565b61159f565b9061020a916115ca565b9061020a91610dd9565b15610e0a57565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c660000000000000000000000000000000000606482015280608481015b0390fd5b61020a9190610eb4610ea5336104c4565b610eae846104c4565b14610e03565b61163c565b6104c46102206102209290565b61022090610eb9565b610edb9392919061169a565b9190610ee65f610906565b81148015610f21575b610ef7579190565b7f19e4cb10000000000000000000000000000000000000000000000000000000005f908152600490fd5b50610f2e610c2c5f610ec6565b610f37846104c4565b14610eef565b9061020a610f4a60405190565b928361039c565b6102206080610f3d565b610f63610f51565b5f8082526020820181905260408201819052606082015290565b610220610f5b565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7f80000000000000000000000000000000000000000000000000000000000000008114610fde575f0390565b610f85565b90610223906104c4565b9193611037611040929461102e610220976110055f90565b50611028611011610f7d565b9886156110455761102190610906565b60408a0152565b87610fe3565b60208601610fe3565b15156060840152565b6116ca565b61105161105691610906565b610fb2565b611021565b61020a907f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab95610df9565b906110b86110b4335b7f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab956111e2565b1590565b6110c55761020a916110ef565b7f710bcc40000000000000000000000000000000000000000000000000000000005f908152600490fd5b906110fc61020a92610ba7565b906111065f610906565b9161185b565b9061020a91611085565b906111236110b43361108e565b6110c55761020a916111345f610906565b82146111855761118061117682610c5c8561116f7f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa2896610ba7565b339061196f565b9261057960405190565b0390a2565b7faba3a548000000000000000000000000000000000000000000000000000000005f908152600490fd5b9061020a91611116565b61020a9033610730565b90610b2e90610ba7565b610220905b60ff1690565b61022090546111cd565b610220915f6111fc611202936111f55f90565b5082610b2c565b016111c3565b6111d8565b6112136110b43361108e565b6110c55761020a90611290565b67ffffffffffffffff81116103dc57602090601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190565b9061126d61126883611220565b610f3d565b918252565b3d1561128b576112813d61125b565b903d5f602084013e565b606090565b6112995f610906565b8114611185576112c05f806112ad60405190565b5f9085335af16112bb611272565b501590565b6112f4577f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa28611180611176610c5c5f610ec6565b7fb12d13eb000000000000000000000000000000000000000000000000000000005f908152600490fd5b61020a90611207565b9061020a91611338610dea82610b4b565b9061020a9161163c565b9061020a91611327565b61020a907f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab95611342565b90815260408101929161020a9160200152565b936113bf7fe2bdbc6b7225eb0a972ac943c485a6cc05f7c6811838bce8903f23200fb744fa93610c5c6113c5938783878b6119dc565b93610ba7565b936113db6113d260405190565b92839283611376565b0390a3565b61020a9033906113f86113f1610913565b9182610df9565b610e94565b6114096110b43361108e565b6110c55761020a9061145f565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905b9181191691161790565b9061145461022061145b92610906565b8254611416565b9055565b6114685f610906565b81146114a35761149e816105757f575efdb178bd088e0c8dfe86c45529c7829d6060a40bf6f6ef7628939f823c29936002611444565b0390a1565b7f98bdb2e0000000000000000000000000000000000000000000000000000000005f908152600490fd5b61020a906113fd565b6114e26110b43361108e565b6110c55761020a90611522565b9073ffffffffffffffffffffffffffffffffffffffff9061143a565b9061151b61022061145b92610ba7565b82546114ef565b61152e610c2c5f610ec6565b611537826104c4565b1461156c5761149e816105277f06526a30af2ff868c2686df12e95844d8ae300416bbec5d5ccc2d2f4afdb17a093600361150b565b7f9fabe1c1000000000000000000000000000000000000000000000000000000005f908152600490fd5b61020a906114d6565b61020a903390611c6a565b9060ff9061143a565b906115c361022061145b92151590565b82546115aa565b6115d76110b483836111e2565b6115df575050565b6115f860016115f3845f6111fc8682610b2c565b6115b3565b61160c6116066113bf339390565b91610ba7565b917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d61163760405190565b5f90a4565b61164682826111e2565b61164e575050565b6116615f6115f384826111fc8682610b2c565b61166f6116066113bf339390565b917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b61163760405190565b916116b693916116b1936116ab5f90565b50611d08565b611d6d565b9061022030610ba7565b61022090516104c4565b606091906117106117066116f26116e0856116c0565b6116ec602087016116c0565b90611e75565b909384611700604088015190565b91611f3e565b9490930151151590565b1561173a571561172c575061172761022091610fb2565b610906565b610220915061172790610fb2565b9091901561174c575061022090610906565b6102209150610906565b9050519061020a82610533565b906020828203126101f95761022091611756565b91602061020a92949361079860408201965f8301906104f3565b1561179857565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608490fd5b6118366118306102209263ffffffff1690565b60e01b90565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b90916118665f610906565b811480156118c1575b61020a936118ad600494936118866118bc94611791565b61189363095ea7b361181d565b9261189d60405190565b9687946020860190815201610bfd565b6020820181038252038361039c565b6120c1565b50906118fd6020846118d284610ba7565b6118db30610ba7565b6040518095819482936118f263dd62ed3e60e01b90565b845260048401611777565b03915afa938415610d39576118ad60049461188661020a976118bc955f91611940575b5061193161192d5f610906565b9190565b1494505093945050935061186f565b611962915060203d602011611968575b61195a818361039c565b810190611763565b5f611920565b503d611950565b6118bc6004926118ad61020a9561189363a9059cbb61181d565b369037565b9061020a6119a461199e8461125b565b93611220565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00160208401611989565b91908203918211610fde57565b600184846119ef93989796949598611d08565b946119fc610c5c83610ba7565b956370a0823191611a0c30610ba7565b97611a1660405190565b90611a218560e01b90565b825260208280611a348d600483016104fc565b0381845afa8015610d39578a611a8a935f92611bb9575b5060209192611a6c611a5c5f610906565b97611a668961198e565b9061218b565b506040518080968194611a7f8c60e01b90565b8352600483016104fc565b03915afa8015610d3957611aa5925f91611b9a575b506119cf565b94808610611b685750611af09697611acc602092610c5c611ac55f610ec6565b600461150b565b93611a7f611ad986610ba7565b91611ae360405190565b9a8b948593849360e01b90565b03915afa908115610d395761020a965f92611b47575b508111611b15575b5050612284565b611b40917f00000000000000000000000000000000000000000000000000000000000000009061196f565b5f80611b0e565b611b6191925060203d6020116119685761195a818361039c565b905f611b06565b610dd55f91877fd28d3eb500000000000000000000000000000000000000000000000000000000845260048401611376565b611bb3915060203d6020116119685761195a818361039c565b5f611a9f565b60209250611bd390833d85116119685761195a818361039c565b91611a4b565b61022090610906565b61047f611bfa92602092611bf4815190565b94859290565b93849101610422565b611c416102209392611c3b611c3b937f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260170190565b90611be2565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000815260110190565b90611c786110b482846111e2565b611c80575050565b611cca610220610e9093611cb2611ca2611c9c611cd6966122ff565b92611bd9565b611cac6020610906565b90612443565b90611cbc60405190565b938492602084019283611c03565b9081038252038261039c565b6040519182917f08c379a000000000000000000000000000000000000000000000000000000000835260048301610483565b61022092611d4b611d5292959395611d1e610f7d565b508415611d5b57611d2e90610906565b915b611d42611d3b610f51565b9788610fe3565b60208701610fe3565b6040850152565b15156060830152565b611051611d6791610906565b91611d30565b905f91611d8e611d7c826116c0565b611d88602084016116c0565b9061258a565b611d9a610c2c5f610ec6565b611da3826104c4565b03611dac575050565b6102209293506116ca565b61022073fffd8963efd1fc6a506488495d951d5263988d26610eb9565b611e099073ffffffffffffffffffffffffffffffffffffffff165b9173ffffffffffffffffffffffffffffffffffffffff1690565b90039073ffffffffffffffffffffffffffffffffffffffff8211610fde57565b6102206401000276a3610eb9565b611e569073ffffffffffffffffffffffffffffffffffffffff16611def565b019073ffffffffffffffffffffffffffffffffffffffff8211610fde57565b90611e8a611e9091611e845f90565b506104c4565b916104c4565b10908115611eb357610220611ea3611e29565b611ead6001610eb9565b90611e37565b610220611ebe611db7565b611ec86001610eb9565b90611dd4565b611eff61020a94611ef8606094989795611eef608086019a5f8701906104f3565b15156020850152565b6040830152565b019073ffffffffffffffffffffffffffffffffffffffff169052565b91906040838203126101f957610220906020611f378286611756565b9401611756565b90611fa1611fa69295939495611f92611f545f90565b978897611f6060405190565b9586946004602087017f90405d3600000000000000000000000000000000000000000000000000000000815201611ece565b6020820181038252038261039c565b612609565b90611fae5750565b90925061063491506020611fc0825190565b818301019101611f1b565b15611fd257565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815280610e90600482016020808252818101527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604082015260600190565b1561203c57565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608490fd5b5f916120cd8392610ba7565b82602083519301915af16120e86120e2611272565b91611fcb565b80516120f661192d5f610906565b116120fe5750565b61211a81602061210f61020a945190565b818301019101610be9565b612035565b92610220969461215a6121619261215161217e9699959961214760c08a019b5f8b01906104f3565b60208901906104f3565b15156040870152565b6060850152565b73ffffffffffffffffffffffffffffffffffffffff166080830152565b60a081840391015261042d565b60406121c0826116ec6121ba6121a0836116c0565b926121b5611ac56020890195611d88876116c0565b6116c0565b916116c0565b939092835f6121d5610c5c610c5c6004610b71565b9261222a6121ec876121e630610ba7565b93015190565b956121f660405190565b998a97889687957f71334694000000000000000000000000000000000000000000000000000000008752806004880161211f565b03925af1908115610d39575f928392612251575b501561172c575061172761022091610fb2565b909250612276915060403d60401161227d575b61226e818361039c565b810190611f1b565b915f61223e565b503d612264565b9161228e30610ba7565b61229a611e8a836104c4565b036122a457505050565b6122b061020a93610ba7565b61196f565b6102206102206102209273ffffffffffffffffffffffffffffffffffffffff1690565b6111d26102206102209290565b61022060146122d8565b6102206102206102209260ff1690565b61231c61231761022092612311606090565b50610b9e565b6122b5565b611cac6123276122e5565b6122ef565b81810292918115918404141715610fde57565b91908201809211610fde57565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b90612382825190565b811015612390570160200190565b61234c565b8015610fde577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b610220906123d461192d6102209460ff1690565b901c90565b156123e057565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815280610e90600482016020808252818101527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604082015260600190565b61247161246c61245c846124576002610906565b61232c565b6124666002610906565b9061233f565b61198e565b9160306124866124805f610906565b85612379565b537f78000000000000000000000000000000000000000000000000000000000000006124db6124d260019384935f1a6124c76124c186610906565b89612379565b536124576002610906565b61246683610906565b915b6124fe575b505090610220610220926124f861192d5f610906565b146123d9565b909161250982610906565b831115612584577f303132333435363738396162636465660000000000000000000000000000000061253b600f610906565b821690601082101561239057839261255b6125789261257e941a60f81b90565b5f1a6125678789612379565b5361257260046122d8565b906123c0565b93612395565b916124dd565b916124e2565b6125db916020916125bd610c5c7f0000000000000000000000000000000000000000000000000000000000000000610ba7565b906125c760405190565b8095819482936118f263d9a641e160e01b90565b03915afa908115610d39575f916125f0575090565b610220915060203d602011610d6457610d56818361039c565b5f80916126135f90565b5061261e6003610b71565b6126286002610b41565b9060208351930191fa61063461127256fea2646970667358221220c1c5988c80e6f6d7e3729f82dd76d9f32443aab1c7ce394e0cd03b53247de28c64736f6c634300081e0033339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab9500000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000061a8000000000000000000000000050c8e97feb1e629196012b7ccca4d4785ed1eb1f00000000000000000000000088ecdbf923f4a980024ed2b7ce44d82814ef2afb0000000000000000000000001a3c9b1d2f0529d97f2afc5136cc23e58f1fd35b000000000000000000000000000000000000000000000000000000000000000e416c676562726141646170746572000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436101561001a575b3615610018575f80fd5b005b5f3560e01c806301ffc9a7146101c957806306fdde03146101c4578063129be381146101bf578063248a9ca3146101ba5780632bc857a0146101b55780632c8958f6146101b05780632dd31000146101ab5780632f2ff15d146101a657806332fe7b26146101a157806336568abe1461019c578063409d653d1461019757806348f12791146101925780636b453c1f1461018d5780637ae26773146101885780638980f11f146101835780638bb9c5bf1461017e57806391d1485414610179578063a217fddf14610174578063c6bbd5a71461016f578063d33355531461016a578063d547741f14610165578063d8baf7cf14610160578063eab90da61461015b578063f2fde38b14610156578063f35c4d4514610151578063f87422541461014c5763f912c64b0361000e57610a78565b610a3f565b610a27565b610a0f565b6109f3565b610996565b61097d565b610965565b61094a565b610924565b6108ea565b6108d2565b6108b9565b61087d565b610849565b610816565b61079f565b61071d565b6106e4565b6106cb565b610659565b610638565b6105a7565b61055a565b61050c565b610494565b610227565b7fffffffff0000000000000000000000000000000000000000000000000000000081165b036101f957565b5f80fd5b9050359061020a826101ce565b565b906020828203126101f957610220916101fd565b90565b9052565b346101f95761025461024261023d36600461020c565b610a90565b60405191829182901515815260200190565b0390f35b5f9103126101f957565b7f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b90600160028304921680156102db575b60208310146102d657565b61028e565b91607f16916102cb565b80545f9392916103016102f7836102bb565b8085529360200190565b9160018116908115610350575060011461031a57505050565b61032b91929394505f5260205f2090565b915f925b81841061033c5750500190565b80548484015260209093019260010161032f565b92949550505060ff1916825215156020020190565b90610220916102e5565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810190811067ffffffffffffffff8211176103dc57604052565b61036f565b9061020a6103fb926103f260405190565b93848092610365565b038361039c565b905f1061041257610220906103e1565b610262565b6102205f6001610402565b90825f9392825e0152565b61044e61045760209361047f93610442815190565b80835293849260200190565b95869101610422565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690565b0190565b60208082526102209291019061042d565b346101f9576104a4366004610258565b6102546104af610417565b60405191829182610483565b610220916008021c5b73ffffffffffffffffffffffffffffffffffffffff1690565b9061022091546104bb565b6102205f60046104dd565b610223906104c4565b60208101929161020a91906104f3565b346101f95761051c366004610258565b6102546105276104e8565b604051918291826104fc565b806101f2565b9050359061020a82610533565b906020828203126101f95761022091610539565b346101f957610254610575610570366004610546565b610b4b565b6040515b9182918290815260200190565b610220916008021c81565b906102209154610586565b6102205f6002610591565b346101f9576105b7366004610258565b61025461057561059c565b909182601f830112156101f95781359167ffffffffffffffff83116101f95760200192600183028401116101f957565b916060838303126101f9576106078284610539565b926106158360208301610539565b92604082013567ffffffffffffffff81116101f95761063492016105c2565b9091565b346101f95761065461064b3660046105f2565b92919091610c1b565b604051005b346101f957610669366004610258565b6102547f0000000000000000000000001a3c9b1d2f0529d97f2afc5136cc23e58f1fd35b610527565b6101f2816104c4565b9050359061020a82610692565b91906040838203126101f9576102209060206106c48286610539565b940161069b565b346101f9576106546106de3660046106a8565b90610df9565b346101f9576106f4366004610258565b6102547f00000000000000000000000050c8e97feb1e629196012b7ccca4d4785ed1eb1f610527565b346101f9576106546107303660046106a8565b90610e94565b8015156101f2565b9050359061020a82610736565b6080818303126101f95761075f8282610539565b92610220610770846020850161069b565b936060610780826040870161069b565b940161073e565b90815260408101929161020a916020905b01906104f3565b346101f9576107bb6107b236600461074b565b92919091610ecf565b906102546107c860405190565b92839283610787565b919060a0838203126101f9576107e7818461069b565b926107f58260208301610539565b92610220610806846040850161069b565b936080610780826060870161069b565b346101f95761025461057561082c3660046107d1565b93929092610fed565b906020828203126101f9576102209161069b565b346101f95761065461085c366004610835565b61105b565b91906040838203126101f9576102209060206106c4828661069b565b346101f957610654610890366004610861565b9061110c565b91906040838203126101f9576102209060206108b2828661069b565b9401610539565b346101f9576106546108cc366004610896565b906111af565b346101f9576106546108e5366004610546565b6111b9565b346101f9576102546102426109003660046106a8565b906111e2565b6102206102206102209290565b6102205f610906565b610220610913565b346101f957610934366004610258565b61025461057561091c565b6102205f60036104dd565b346101f95761095a366004610258565b61025461052761093f565b346101f957610654610978366004610546565b61131e565b346101f9576106546109903660046106a8565b90611342565b346101f9576106546109a9366004610835565b61134c565b919060a0838203126101f9576109c48184610539565b926109d28260208301610539565b926102206109e3846040850161069b565b9360806106c4826060870161069b565b346101f957610654610a063660046109ae565b93929092611389565b346101f957610654610a22366004610835565b6113e0565b346101f957610654610a3a366004610546565b6114cd565b346101f957610a4f366004610258565b6102547f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab95610575565b346101f957610654610a8b366004610835565b611596565b7f7965db0b000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000821614908115610ae0575090565b61022091507fffffffff00000000000000000000000000000000000000000000000000000000167f01ffc9a7000000000000000000000000000000000000000000000000000000001490565b905b5f5260205260405f2090565b6102209081565b6102209054610b3a565b6001610b6261022092610b5b5f90565b505f610b2c565b01610b41565b610220906104c4565b6102209054610b68565b6104c46102206102209273ffffffffffffffffffffffffffffffffffffffff1690565b61022090610b7b565b61022090610b9e565b9050519061020a82610692565b906020828203126101f95761022091610bb0565b6040513d5f823e3d90fd5b9050519061020a82610736565b906020828203126101f95761022091610bdc565b91602061020a929493610c1760408201965f8301906104f3565b0152565b92509050610c31610c2c6004610b71565b6104c4565b610c3a336104c4565b03610dad57610c485f610906565b821315610d6b5750610c61610c5c33610ba7565b610ba7565b6020610c6c60405190565b9182907f0dfe1681000000000000000000000000000000000000000000000000000000005b825260049082905afa8015610d39575f92610cc5610cbf610c5c610cfd946020968891610d3e575b50610ba7565b91610906565b60405194859384928391907fa9059cbb0000000000000000000000000000000000000000000000000000000083523360048401610bfd565b03925af18015610d3957610d0e5750565b610d2f9060203d602011610d32575b610d27818361039c565b810190610be9565b50565b503d610d1d565b610bd1565b610d5e9150873d8911610d64575b610d56818361039c565b810190610bbd565b5f610cb9565b503d610d4c565b9050610d79610c5c33610ba7565b6020610d8460405190565b9182907fd21220a700000000000000000000000000000000000000000000000000000000610c91565b7f136bd7cc000000000000000000000000000000000000000000000000000000005f90815260045b035ffd5b9061020a91610def610dea82610b4b565b61159f565b9061020a916115ca565b9061020a91610dd9565b15610e0a57565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c660000000000000000000000000000000000606482015280608481015b0390fd5b61020a9190610eb4610ea5336104c4565b610eae846104c4565b14610e03565b61163c565b6104c46102206102209290565b61022090610eb9565b610edb9392919061169a565b9190610ee65f610906565b81148015610f21575b610ef7579190565b7f19e4cb10000000000000000000000000000000000000000000000000000000005f908152600490fd5b50610f2e610c2c5f610ec6565b610f37846104c4565b14610eef565b9061020a610f4a60405190565b928361039c565b6102206080610f3d565b610f63610f51565b5f8082526020820181905260408201819052606082015290565b610220610f5b565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7f80000000000000000000000000000000000000000000000000000000000000008114610fde575f0390565b610f85565b90610223906104c4565b9193611037611040929461102e610220976110055f90565b50611028611011610f7d565b9886156110455761102190610906565b60408a0152565b87610fe3565b60208601610fe3565b15156060840152565b6116ca565b61105161105691610906565b610fb2565b611021565b61020a907f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab95610df9565b906110b86110b4335b7f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab956111e2565b1590565b6110c55761020a916110ef565b7f710bcc40000000000000000000000000000000000000000000000000000000005f908152600490fd5b906110fc61020a92610ba7565b906111065f610906565b9161185b565b9061020a91611085565b906111236110b43361108e565b6110c55761020a916111345f610906565b82146111855761118061117682610c5c8561116f7f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa2896610ba7565b339061196f565b9261057960405190565b0390a2565b7faba3a548000000000000000000000000000000000000000000000000000000005f908152600490fd5b9061020a91611116565b61020a9033610730565b90610b2e90610ba7565b610220905b60ff1690565b61022090546111cd565b610220915f6111fc611202936111f55f90565b5082610b2c565b016111c3565b6111d8565b6112136110b43361108e565b6110c55761020a90611290565b67ffffffffffffffff81116103dc57602090601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190565b9061126d61126883611220565b610f3d565b918252565b3d1561128b576112813d61125b565b903d5f602084013e565b606090565b6112995f610906565b8114611185576112c05f806112ad60405190565b5f9085335af16112bb611272565b501590565b6112f4577f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa28611180611176610c5c5f610ec6565b7fb12d13eb000000000000000000000000000000000000000000000000000000005f908152600490fd5b61020a90611207565b9061020a91611338610dea82610b4b565b9061020a9161163c565b9061020a91611327565b61020a907f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab95611342565b90815260408101929161020a9160200152565b936113bf7fe2bdbc6b7225eb0a972ac943c485a6cc05f7c6811838bce8903f23200fb744fa93610c5c6113c5938783878b6119dc565b93610ba7565b936113db6113d260405190565b92839283611376565b0390a3565b61020a9033906113f86113f1610913565b9182610df9565b610e94565b6114096110b43361108e565b6110c55761020a9061145f565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905b9181191691161790565b9061145461022061145b92610906565b8254611416565b9055565b6114685f610906565b81146114a35761149e816105757f575efdb178bd088e0c8dfe86c45529c7829d6060a40bf6f6ef7628939f823c29936002611444565b0390a1565b7f98bdb2e0000000000000000000000000000000000000000000000000000000005f908152600490fd5b61020a906113fd565b6114e26110b43361108e565b6110c55761020a90611522565b9073ffffffffffffffffffffffffffffffffffffffff9061143a565b9061151b61022061145b92610ba7565b82546114ef565b61152e610c2c5f610ec6565b611537826104c4565b1461156c5761149e816105277f06526a30af2ff868c2686df12e95844d8ae300416bbec5d5ccc2d2f4afdb17a093600361150b565b7f9fabe1c1000000000000000000000000000000000000000000000000000000005f908152600490fd5b61020a906114d6565b61020a903390611c6a565b9060ff9061143a565b906115c361022061145b92151590565b82546115aa565b6115d76110b483836111e2565b6115df575050565b6115f860016115f3845f6111fc8682610b2c565b6115b3565b61160c6116066113bf339390565b91610ba7565b917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d61163760405190565b5f90a4565b61164682826111e2565b61164e575050565b6116615f6115f384826111fc8682610b2c565b61166f6116066113bf339390565b917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b61163760405190565b916116b693916116b1936116ab5f90565b50611d08565b611d6d565b9061022030610ba7565b61022090516104c4565b606091906117106117066116f26116e0856116c0565b6116ec602087016116c0565b90611e75565b909384611700604088015190565b91611f3e565b9490930151151590565b1561173a571561172c575061172761022091610fb2565b610906565b610220915061172790610fb2565b9091901561174c575061022090610906565b6102209150610906565b9050519061020a82610533565b906020828203126101f95761022091611756565b91602061020a92949361079860408201965f8301906104f3565b1561179857565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608490fd5b6118366118306102209263ffffffff1690565b60e01b90565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b90916118665f610906565b811480156118c1575b61020a936118ad600494936118866118bc94611791565b61189363095ea7b361181d565b9261189d60405190565b9687946020860190815201610bfd565b6020820181038252038361039c565b6120c1565b50906118fd6020846118d284610ba7565b6118db30610ba7565b6040518095819482936118f263dd62ed3e60e01b90565b845260048401611777565b03915afa938415610d39576118ad60049461188661020a976118bc955f91611940575b5061193161192d5f610906565b9190565b1494505093945050935061186f565b611962915060203d602011611968575b61195a818361039c565b810190611763565b5f611920565b503d611950565b6118bc6004926118ad61020a9561189363a9059cbb61181d565b369037565b9061020a6119a461199e8461125b565b93611220565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00160208401611989565b91908203918211610fde57565b600184846119ef93989796949598611d08565b946119fc610c5c83610ba7565b956370a0823191611a0c30610ba7565b97611a1660405190565b90611a218560e01b90565b825260208280611a348d600483016104fc565b0381845afa8015610d39578a611a8a935f92611bb9575b5060209192611a6c611a5c5f610906565b97611a668961198e565b9061218b565b506040518080968194611a7f8c60e01b90565b8352600483016104fc565b03915afa8015610d3957611aa5925f91611b9a575b506119cf565b94808610611b685750611af09697611acc602092610c5c611ac55f610ec6565b600461150b565b93611a7f611ad986610ba7565b91611ae360405190565b9a8b948593849360e01b90565b03915afa908115610d395761020a965f92611b47575b508111611b15575b5050612284565b611b40917f00000000000000000000000050c8e97feb1e629196012b7ccca4d4785ed1eb1f9061196f565b5f80611b0e565b611b6191925060203d6020116119685761195a818361039c565b905f611b06565b610dd55f91877fd28d3eb500000000000000000000000000000000000000000000000000000000845260048401611376565b611bb3915060203d6020116119685761195a818361039c565b5f611a9f565b60209250611bd390833d85116119685761195a818361039c565b91611a4b565b61022090610906565b61047f611bfa92602092611bf4815190565b94859290565b93849101610422565b611c416102209392611c3b611c3b937f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260170190565b90611be2565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000815260110190565b90611c786110b482846111e2565b611c80575050565b611cca610220610e9093611cb2611ca2611c9c611cd6966122ff565b92611bd9565b611cac6020610906565b90612443565b90611cbc60405190565b938492602084019283611c03565b9081038252038261039c565b6040519182917f08c379a000000000000000000000000000000000000000000000000000000000835260048301610483565b61022092611d4b611d5292959395611d1e610f7d565b508415611d5b57611d2e90610906565b915b611d42611d3b610f51565b9788610fe3565b60208701610fe3565b6040850152565b15156060830152565b611051611d6791610906565b91611d30565b905f91611d8e611d7c826116c0565b611d88602084016116c0565b9061258a565b611d9a610c2c5f610ec6565b611da3826104c4565b03611dac575050565b6102209293506116ca565b61022073fffd8963efd1fc6a506488495d951d5263988d26610eb9565b611e099073ffffffffffffffffffffffffffffffffffffffff165b9173ffffffffffffffffffffffffffffffffffffffff1690565b90039073ffffffffffffffffffffffffffffffffffffffff8211610fde57565b6102206401000276a3610eb9565b611e569073ffffffffffffffffffffffffffffffffffffffff16611def565b019073ffffffffffffffffffffffffffffffffffffffff8211610fde57565b90611e8a611e9091611e845f90565b506104c4565b916104c4565b10908115611eb357610220611ea3611e29565b611ead6001610eb9565b90611e37565b610220611ebe611db7565b611ec86001610eb9565b90611dd4565b611eff61020a94611ef8606094989795611eef608086019a5f8701906104f3565b15156020850152565b6040830152565b019073ffffffffffffffffffffffffffffffffffffffff169052565b91906040838203126101f957610220906020611f378286611756565b9401611756565b90611fa1611fa69295939495611f92611f545f90565b978897611f6060405190565b9586946004602087017f90405d3600000000000000000000000000000000000000000000000000000000815201611ece565b6020820181038252038261039c565b612609565b90611fae5750565b90925061063491506020611fc0825190565b818301019101611f1b565b15611fd257565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815280610e90600482016020808252818101527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604082015260600190565b1561203c57565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608490fd5b5f916120cd8392610ba7565b82602083519301915af16120e86120e2611272565b91611fcb565b80516120f661192d5f610906565b116120fe5750565b61211a81602061210f61020a945190565b818301019101610be9565b612035565b92610220969461215a6121619261215161217e9699959961214760c08a019b5f8b01906104f3565b60208901906104f3565b15156040870152565b6060850152565b73ffffffffffffffffffffffffffffffffffffffff166080830152565b60a081840391015261042d565b60406121c0826116ec6121ba6121a0836116c0565b926121b5611ac56020890195611d88876116c0565b6116c0565b916116c0565b939092835f6121d5610c5c610c5c6004610b71565b9261222a6121ec876121e630610ba7565b93015190565b956121f660405190565b998a97889687957f71334694000000000000000000000000000000000000000000000000000000008752806004880161211f565b03925af1908115610d39575f928392612251575b501561172c575061172761022091610fb2565b909250612276915060403d60401161227d575b61226e818361039c565b810190611f1b565b915f61223e565b503d612264565b9161228e30610ba7565b61229a611e8a836104c4565b036122a457505050565b6122b061020a93610ba7565b61196f565b6102206102206102209273ffffffffffffffffffffffffffffffffffffffff1690565b6111d26102206102209290565b61022060146122d8565b6102206102206102209260ff1690565b61231c61231761022092612311606090565b50610b9e565b6122b5565b611cac6123276122e5565b6122ef565b81810292918115918404141715610fde57565b91908201809211610fde57565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b90612382825190565b811015612390570160200190565b61234c565b8015610fde577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b610220906123d461192d6102209460ff1690565b901c90565b156123e057565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815280610e90600482016020808252818101527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604082015260600190565b61247161246c61245c846124576002610906565b61232c565b6124666002610906565b9061233f565b61198e565b9160306124866124805f610906565b85612379565b537f78000000000000000000000000000000000000000000000000000000000000006124db6124d260019384935f1a6124c76124c186610906565b89612379565b536124576002610906565b61246683610906565b915b6124fe575b505090610220610220926124f861192d5f610906565b146123d9565b909161250982610906565b831115612584577f303132333435363738396162636465660000000000000000000000000000000061253b600f610906565b821690601082101561239057839261255b6125789261257e941a60f81b90565b5f1a6125678789612379565b5361257260046122d8565b906123c0565b93612395565b916124dd565b916124e2565b6125db916020916125bd610c5c7f0000000000000000000000001a3c9b1d2f0529d97f2afc5136cc23e58f1fd35b610ba7565b906125c760405190565b8095819482936118f263d9a641e160e01b90565b03915afa908115610d39575f916125f0575090565b610220915060203d602011610d6457610d56818361039c565b5f80916126135f90565b5061261e6003610b71565b6126286002610b41565b9060208351930191fa61063461127256fea2646970667358221220c1c5988c80e6f6d7e3729f82dd76d9f32443aab1c7ce394e0cd03b53247de28c64736f6c634300081e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000061a8000000000000000000000000050c8e97feb1e629196012b7ccca4d4785ed1eb1f00000000000000000000000088ecdbf923f4a980024ed2b7ce44d82814ef2afb0000000000000000000000001a3c9b1d2f0529d97f2afc5136cc23e58f1fd35b000000000000000000000000000000000000000000000000000000000000000e416c676562726141646170746572000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _name (string): AlgebraAdapter
Arg [1] : _quoterGasLimit (uint256): 400000
Arg [2] : _router (address): 0x50c8E97fEb1e629196012b7CCCA4D4785Ed1eb1f
Arg [3] : _quoter (address): 0x88ECdbF923F4a980024Ed2B7Ce44D82814eF2aFB
Arg [4] : _factory (address): 0x1a3c9B1d2F0529D97f2afC5136Cc23e58f1FD35B
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [1] : 0000000000000000000000000000000000000000000000000000000000061a80
Arg [2] : 00000000000000000000000050c8e97feb1e629196012b7ccca4d4785ed1eb1f
Arg [3] : 00000000000000000000000088ecdbf923f4a980024ed2b7ce44d82814ef2afb
Arg [4] : 0000000000000000000000001a3c9b1d2f0529d97f2afc5136cc23e58f1fd35b
Arg [5] : 000000000000000000000000000000000000000000000000000000000000000e
Arg [6] : 416c676562726141646170746572000000000000000000000000000000000000
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.