Overview
ETH Balance
0 ETH
Eth Value
$0.00Token Holdings
Latest 6 from a total of 6 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Set Adapter Whit... | 19368381 | 208 days ago | IN | 0 ETH | 0.00337523 | ||||
Set Adapter Whit... | 19340443 | 212 days ago | IN | 0 ETH | 0.00265714 | ||||
Execute Batch Ca... | 19190989 | 233 days ago | IN | 0 ETH | 0.04275563 | ||||
Set Adapter Whit... | 19190103 | 233 days ago | IN | 0 ETH | 0.0024437 | ||||
Set Adapter Whit... | 19185544 | 234 days ago | IN | 0 ETH | 0.00330186 | ||||
0x61010034 | 19185081 | 234 days ago | IN | 0 ETH | 0.21629369 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
19375089 | 207 days ago | 0.00895273 ETH | ||||
19375089 | 207 days ago | 0.00895273 ETH | ||||
19369670 | 208 days ago | 0.00112644 ETH | ||||
19369670 | 208 days ago | 0.07396211 ETH | ||||
19369670 | 208 days ago | 0.07508855 ETH | ||||
19369587 | 208 days ago | 0.00112644 ETH | ||||
19369587 | 208 days ago | 0.04769612 ETH | ||||
19369587 | 208 days ago | 0.04882257 ETH | ||||
19368917 | 208 days ago | 0.01870218 ETH | ||||
19368917 | 208 days ago | 0.01870218 ETH | ||||
19367552 | 208 days ago | 0.0881503 ETH | ||||
19367552 | 208 days ago | 0.0872688 ETH | ||||
19367552 | 208 days ago | 0.0881503 ETH | ||||
19361397 | 209 days ago | 0.00008117 ETH | ||||
19361397 | 209 days ago | 0.00803618 ETH | ||||
19361397 | 209 days ago | 0.00811735 ETH | ||||
19249025 | 225 days ago | 0.00010479 ETH | ||||
19249025 | 225 days ago | 0.0103746 ETH | ||||
19249025 | 225 days ago | 0.01047939 ETH | ||||
19241303 | 226 days ago | 0.00002448 ETH | ||||
19241303 | 226 days ago | 0.00242392 ETH | ||||
19241303 | 226 days ago | 0.00244841 ETH | ||||
19238778 | 227 days ago | 0.00010874 ETH | ||||
19238778 | 227 days ago | 0.01076578 ETH | ||||
19238778 | 227 days ago | 0.01087453 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
BatchTransaction
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; import {ReentrancyGuard} from "@routerprotocol/intents-core/contracts/utils/ReentrancyGuard.sol"; import {Basic} from "@routerprotocol/intents-core/contracts/common/Basic.sol"; import {NitroMessageHandler} from "@routerprotocol/intents-core/contracts/utils/NitroMessageHandler.sol"; import {CallLib} from "@routerprotocol/intents-core/contracts/utils/CallLib.sol"; import {IERC20, SafeERC20} from "@routerprotocol/intents-core/contracts/utils/SafeERC20.sol"; import {Errors} from "@routerprotocol/intents-core/contracts/utils/Errors.sol"; import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; import {EoaExecutorWithDataProvider, EoaExecutorWithoutDataProvider} from "@routerprotocol/intents-core/contracts/RouterIntentEoaAdapter.sol"; import {BaseAdapter} from "@routerprotocol/intents-core/contracts/BaseAdapter.sol"; /** * @title BatchTransaction * @author Shivam Agrawal * @notice Batch Transaction Contract for EOAs. */ contract BatchTransaction is Basic, NitroMessageHandler, AccessControl, ReentrancyGuard { using SafeERC20 for IERC20; struct RefundData { address[] tokens; } bytes32 public constant SETTER_ROLE = keccak256("SETTER_ROLE"); address private immutable _native; address private immutable _wnative; // user -> token array mapping(address => RefundData) private tokensToRefund; mapping(address => bool) private adapterWhitelist; event OperationFailedRefundEvent( address token, address recipient, uint256 amount ); event OperationSuccessful(); constructor( address __native, address __wnative, address __assetForwarder, address __dexspan ) NitroMessageHandler(__assetForwarder, __dexspan) { _native = __native; _wnative = __wnative; _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); _grantRole(SETTER_ROLE, msg.sender); } /** * @notice function to return the address of WNative token. */ function wnative() public view virtual override returns (address) { return _wnative; } /** * @notice function to return the address of Native token. */ function native() public view virtual override returns (address) { return _native; } /** * @notice function to check whether an adapter is whitelisted. * @param adapter Address of the adapter. */ function isAdapterWhitelisted(address adapter) public view returns (bool) { return adapterWhitelist[adapter]; } /** * @notice function to set adapter whitelist. * @param adapters Addresses of the adapters. * @param shouldWhitelist Boolean array suggesting whether to whitelist the adapters. */ function setAdapterWhitelist( address[] memory adapters, bool[] memory shouldWhitelist ) external onlyRole(SETTER_ROLE) { uint256 len = adapters.length; require( len != 0 && len == shouldWhitelist.length, Errors.ARRAY_LENGTH_MISMATCH ); for (uint i = 0; i < len; ) { adapterWhitelist[adapters[i]] = shouldWhitelist[i]; unchecked { ++i; } } } /** * @dev function to execute batch calls on the same chain * @param tokens Addresses of the tokens to fetch from the user * @param amounts amounts of the tokens to fetch from the user * @param target Addresses of the contracts to call * @param value Amounts of native tokens to send along with the transactions * @param callType Type of call. 1: call, 2: delegatecall * @param data Data of the transactions */ function executeBatchCallsSameChain( address[] calldata tokens, uint256[] calldata amounts, address[] calldata target, uint256[] calldata value, uint256[] calldata callType, bytes[] calldata data ) external payable { uint256 tokensLength = tokens.length; require(tokensLength == amounts.length, Errors.ARRAY_LENGTH_MISMATCH); uint256 totalValue = 0; for (uint256 i = 0; i < tokensLength; ) { totalValue += _pullTokens(tokens[i], amounts[i]); tokensToRefund[msg.sender].tokens.push(tokens[i]); unchecked { ++i; } } require( msg.value >= totalValue, Errors.INSUFFICIENT_NATIVE_FUNDS_PASSED ); for (uint256 i = 0; i < callType.length; ) { // callType can be either 1 or 2 require(callType[i] < 3, Errors.INVALID_CALL_TYPE); unchecked { ++i; } } _executeBatchCalls(msg.sender, target, value, callType, data); } /** * @dev function to execute batch calls * @param refundRecipient Address of recipient of refunds of dust at the end * @param target Addresses of the contracts to call * @param value Amounts of native tokens to send along with the transactions * @param data Data of the transactions * @param callType Type of call. 1: call, 2: delegatecall */ function executeBatchCallsDestChain( address refundRecipient, address[] calldata target, uint256[] calldata value, uint256[] calldata callType, bytes[] calldata data ) external payable { require(msg.sender == address(this), Errors.ONLY_SELF); _executeBatchCalls(refundRecipient, target, value, callType, data); } /** * @dev function to execute batch calls * @param target Addresses of the contracts to call * @param value Amounts of native tokens to send along with the transactions * @param data Data of the transactions * @param callType Type of call. 1: call, 2: delegatecall */ function _executeBatchCalls( address refundRecipient, address[] calldata target, uint256[] calldata value, uint256[] calldata callType, bytes[] calldata data ) internal { uint256 targetLength = target.length; require( targetLength != 0 && targetLength == value.length && value.length == data.length && data.length == callType.length, Errors.WRONG_BATCH_PROVIDED ); if (target.length == 1) { _execute( refundRecipient, target[0], address(0), address(0), value[0], callType[0], data[0] ); } else { _execute( refundRecipient, target[0], address(0), target[1], value[0], callType[0], data[0] ); for (uint256 i = 1; i < targetLength; ) { if (i != targetLength - 1) { _execute( refundRecipient, target[i], target[i - 1], target[i + 1], value[i], callType[i], data[i] ); } else { _execute( refundRecipient, target[i], target[i - 1], address(0), value[i], callType[i], data[i] ); } unchecked { ++i; } } } processRefunds(refundRecipient); } function _pullTokens( address token, uint256 amount ) internal returns (uint256) { uint256 totalValue = 0; if (token == native()) { totalValue += amount; } else { IERC20(token).safeTransferFrom(msg.sender, address(this), amount); } return totalValue; } function _execute( address refundRecipient, address target, address precedingAdapter, address succeedingAdapter, uint256 value, uint256 callType, bytes memory data ) internal { require(adapterWhitelist[target], Errors.ADAPTER_NOT_WHITELISTED); bytes memory _calldata; if (address(BaseAdapter(target).adapterDataProvider()) == address(0)) { _calldata = abi.encodeWithSelector( EoaExecutorWithoutDataProvider.execute.selector, data ); } else { _calldata = abi.encodeWithSelector( EoaExecutorWithDataProvider.execute.selector, precedingAdapter, succeedingAdapter, data ); } bytes memory result; if (callType == 1) result = CallLib._call(target, value, _calldata); else if (callType == 2) result = CallLib._delegateCall(target, _calldata); if (result.length != 0) processResult(refundRecipient, result); } function processResult(address user, bytes memory data) internal { address[] memory tokens = abi.decode(data, (address[])); for (uint256 i = 0; i < tokens.length; ) { tokensToRefund[user].tokens.push(tokens[i]); unchecked { ++i; } } } function processRefunds(address user) internal { uint256 len = tokensToRefund[user].tokens.length; for (uint256 i = 0; i < len; ) { withdrawTokens( tokensToRefund[user].tokens[i], user, type(uint256).max ); unchecked { ++i; } } delete tokensToRefund[user]; } /** * @inheritdoc NitroMessageHandler */ function handleMessage( address tokenSent, uint256 amount, bytes memory instruction ) external override onlyNitro nonReentrant { ( address refundAddress, address[] memory target, uint256[] memory value, uint256[] memory callType, bytes[] memory data ) = abi.decode( instruction, (address, address[], uint256[], uint256[], bytes[]) ); for (uint256 i = 0; i < callType.length; ) { if (callType[i] > 2) { withdrawTokens(tokenSent, refundAddress, amount); emit OperationFailedRefundEvent( tokenSent, refundAddress, amount ); return; } unchecked { ++i; } } // solhint-disable-next-line avoid-low-level-calls (bool success, ) = address(this).call( abi.encodeWithSelector( this.executeBatchCallsDestChain.selector, refundAddress, target, value, callType, data ) ); if (success) { emit OperationSuccessful(); } else { withdrawTokens(tokenSent, refundAddress, amount); emit OperationFailedRefundEvent(tokenSent, refundAddress, amount); } } // solhint-disable-next-line no-empty-blocks receive() external payable {} }
// 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 v4.4.1 (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; } }
// 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: MIT pragma solidity ^0.8.18; import {IAdapterDataProvider} from "./interfaces/IAdapterDataProvider.sol"; /** * @title AdapterDataProvider * @author Router Protocol * @notice This contract serves as the data provider for an intent adapter based on Router * Cross-Chain Intent Framework. */ contract AdapterDataProvider is IAdapterDataProvider { address private _owner; mapping(address => bool) private _headRegistry; mapping(address => bool) private _tailRegistry; mapping(address => bool) private _inboundAssetRegistry; mapping(address => bool) private _outboundAssetRegistry; constructor(address __owner) { _owner = __owner; } /** * @inheritdoc IAdapterDataProvider */ function owner() external view returns (address) { return _owner; } /** * @inheritdoc IAdapterDataProvider */ function setOwner(address __owner) external onlyOwner { _owner = __owner; } /** * @inheritdoc IAdapterDataProvider */ function isAuthorizedPrecedingContract( address precedingContract ) external view returns (bool) { if (precedingContract == address(0)) return true; return _headRegistry[precedingContract]; } /** * @inheritdoc IAdapterDataProvider */ function isAuthorizedSucceedingContract( address succeedingContract ) external view returns (bool) { if (succeedingContract == address(0)) return true; return _tailRegistry[succeedingContract]; } /** * @inheritdoc IAdapterDataProvider */ function isValidInboundAsset(address asset) external view returns (bool) { return _inboundAssetRegistry[asset]; } /** * @inheritdoc IAdapterDataProvider */ function isValidOutboundAsset(address asset) external view returns (bool) { return _outboundAssetRegistry[asset]; } /** * @inheritdoc IAdapterDataProvider */ function setPrecedingContract( address precedingContract, bool isValid ) external onlyOwner { _headRegistry[precedingContract] = isValid; } /** * @inheritdoc IAdapterDataProvider */ function setSucceedingContract( address succeedingContract, bool isValid ) external onlyOwner { _tailRegistry[succeedingContract] = isValid; } /** * @inheritdoc IAdapterDataProvider */ function setInboundAsset(address asset, bool isValid) external onlyOwner { _inboundAssetRegistry[asset] = isValid; } /** * @inheritdoc IAdapterDataProvider */ function setOutboundAsset(address asset, bool isValid) external onlyOwner { _outboundAssetRegistry[asset] = isValid; } /** * @notice modifier to ensure that only owner can call this function */ modifier onlyOwner() { _onlyOwner(); _; } function _onlyOwner() private view { require(msg.sender == _owner, "Only owner"); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; import {Basic} from "./common/Basic.sol"; import {Errors} from "./utils/Errors.sol"; import {ReentrancyGuard} from "./utils/ReentrancyGuard.sol"; import {AdapterDataProvider} from "./AdapterDataProvider.sol"; /** * @title BaseAdapter * @author Router Protocol * @notice This contract is the base implementation of an intent adapter based on Router * Cross-Chain Intent Framework. */ abstract contract BaseAdapter is Basic, ReentrancyGuard { address private immutable _self; address private immutable _native; address private immutable _wnative; AdapterDataProvider private immutable _adapterDataProvider; event ExecutionEvent(string indexed adapterName, bytes data); event OperationFailedRefundEvent( address token, address recipient, uint256 amount ); event UnsupportedOperation( address token, address refundAddress, uint256 amount ); constructor( address __native, address __wnative, bool __deployDataProvider, address __owner ) { _self = address(this); _native = __native; _wnative = __wnative; AdapterDataProvider dataProvider; if (__deployDataProvider) dataProvider = new AdapterDataProvider(__owner); else dataProvider = AdapterDataProvider(address(0)); _adapterDataProvider = dataProvider; } /** * @dev function to get the address of weth */ function wnative() public view override returns (address) { return _wnative; } /** * @dev function to get the address of native token */ function native() public view override returns (address) { return _native; } /** * @dev function to get the AdapterDataProvider instance for this contract */ function adapterDataProvider() public view returns (AdapterDataProvider) { return _adapterDataProvider; } /** * @dev Function to check whether the contract is a valid preceding contract registered in * the head registry. * @dev This registry governs the initiation of the adapter, exclusively listing authorized * preceding adapters. * @notice Only the adapters documented in this registry can invoke the current adapter, * thereby guaranteeing regulated and secure execution sequences. * @param precedingContract Address of preceding contract. * @return true if valid, false if invalid. */ function isAuthorizedPrecedingContract( address precedingContract ) public view returns (bool) { return _adapterDataProvider.isAuthorizedPrecedingContract( precedingContract ); } /** * @dev Function to check whether the contract is a valid succeeding contract registered in * the tail registry. * @dev This registry dictates the potential succeeding actions by listing adapters that * may be invoked following the current one. * @notice Only the adapters documented in this registry can be invoked by the current adapter, * thereby guaranteeing regulated and secure execution sequences. * @param succeedingContract Address of succeeding contract. * @return true if valid, false if invalid. */ function isAuthorizedSucceedingContract( address succeedingContract ) public view returns (bool) { return _adapterDataProvider.isAuthorizedSucceedingContract( succeedingContract ); } /** * @dev Function to check whether the asset is a valid inbound asset registered in the inbound * asset registry. * @dev This registry keeps track of all the acceptable incoming assets, ensuring that the * adapter only processes predefined asset types. * @param asset Address of the asset. * @return true if valid, false if invalid. */ function isValidInboundAsset(address asset) public view returns (bool) { return _adapterDataProvider.isValidInboundAsset(asset); } /** * @dev Function to check whether the asset is a valid outbound asset registered in the outbound * asset registry. * @dev It manages the types of assets that the adapter is allowed to output, thus controlling * the flow’s output and maintaining consistency. * @param asset Address of the asset. * @return true if valid, false if invalid. */ function isValidOutboundAsset(address asset) public view returns (bool) { return _adapterDataProvider.isValidOutboundAsset(asset); } /** * @dev function to get the name of the adapter */ function name() public view virtual returns (string memory); /** * @dev function to get the address of the contract */ function self() public view returns (address) { return _self; } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.18; import {TokenInterface} from "./Interfaces.sol"; import {TokenUtilsBase} from "./TokenUtilsBase.sol"; abstract contract Basic is TokenUtilsBase { function getTokenBal(address token) internal view returns (uint _amt) { _amt = address(token) == native() ? address(this).balance : TokenInterface(token).balanceOf(address(this)); } function approve(address token, address spender, uint256 amount) internal { // solhint-disable-next-line no-empty-blocks try TokenInterface(token).approve(spender, amount) {} catch { TokenInterface(token).approve(spender, 0); TokenInterface(token).approve(spender, amount); } } function convertNativeToWnative(uint amount) internal { TokenInterface(wnative()).deposit{value: amount}(); } function convertWnativeToNative(uint amount) internal { TokenInterface(wnative()).withdraw(amount); } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.18; interface TokenInterface { function approve(address, uint256) external; function transfer(address, uint) external; function transferFrom(address, address, uint) external; function deposit() external payable; function withdraw(uint) external; function balanceOf(address) external view returns (uint); function decimals() external view returns (uint); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; import {IWETH} from "../interfaces/IWETH.sol"; import {SafeERC20, IERC20} from "../utils/SafeERC20.sol"; abstract contract TokenUtilsBase { using SafeERC20 for IERC20; function wnative() public view virtual returns (address); function native() public view virtual returns (address); function approveToken( address _tokenAddr, address _to, uint256 _amount ) internal { if (_tokenAddr == native()) return; if (IERC20(_tokenAddr).allowance(address(this), _to) < _amount) { IERC20(_tokenAddr).safeApprove(_to, _amount); } } function pullTokensIfNeeded( address _token, address _from, uint256 _amount ) internal returns (uint256) { // handle max uint amount if (_amount == type(uint256).max) { _amount = getBalance(_token, _from); } if ( _from != address(0) && _from != address(this) && _token != native() && _amount != 0 ) { IERC20(_token).safeTransferFrom(_from, address(this), _amount); } return _amount; } function withdrawTokens( address _token, address _to, uint256 _amount ) internal returns (uint256) { if (_amount == type(uint256).max) { _amount = getBalance(_token, address(this)); } if (_to != address(0) && _to != address(this) && _amount != 0) { if (_token != native()) { IERC20(_token).safeTransfer(_to, _amount); } else { (bool success, ) = _to.call{value: _amount}(""); require(success, "native send fail"); } } return _amount; } function depositWnative(uint256 _amount) internal { IWETH(wnative()).deposit{value: _amount}(); } function withdrawWnative(uint256 _amount) internal { IWETH(wnative()).withdraw(_amount); } function getBalance( address _tokenAddr, address _acc ) internal view returns (uint256) { if (_tokenAddr == native()) { return _acc.balance; } else { return IERC20(_tokenAddr).balanceOf(_acc); } } function getTokenDecimals(address _token) internal view returns (uint256) { if (_token == native()) return 18; return IERC20(_token).decimals(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; /** * @title Interface for Adapter Data Provider contract for intent adapter. * @author Router Protocol. */ interface IAdapterDataProvider { /** * @dev Function to get the address of owner. */ function owner() external view returns (address); /** * @dev Function to set the address of owner. * @dev This function can only be called by the owner of this contract. * @param __owner Address of the new owner */ function setOwner(address __owner) external; /** * @dev Function to check whether the contract is a valid preceding contract registered in * the head registry. * @dev This registry governs the initiation of the adapter, exclusively listing authorized * preceding adapters. * @notice Only the adapters documented in this registry can invoke the current adapter, * thereby guaranteeing regulated and secure execution sequences. * @param precedingContract Address of preceding contract. * @return true if valid, false if invalid. */ function isAuthorizedPrecedingContract( address precedingContract ) external view returns (bool); /** * @dev Function to check whether the contract is a valid succeeding contract registered in * the tail registry. * @dev This registry dictates the potential succeeding actions by listing adapters that * may be invoked following the current one. * @notice Only the adapters documented in this registry can be invoked by the current adapter, * thereby guaranteeing regulated and secure execution sequences. * @param succeedingContract Address of succeeding contract. * @return true if valid, false if invalid. */ function isAuthorizedSucceedingContract( address succeedingContract ) external view returns (bool); /** * @dev Function to check whether the asset is a valid inbound asset registered in the inbound * asset registry. * @dev This registry keeps track of all the acceptable incoming assets, ensuring that the * adapter only processes predefined asset types. * @param asset Address of the asset. * @return true if valid, false if invalid. */ function isValidInboundAsset(address asset) external view returns (bool); /** * @dev Function to check whether the asset is a valid outbound asset registered in the outbound * asset registry. * @dev It manages the types of assets that the adapter is allowed to output, thus controlling * the flow’s output and maintaining consistency. * @param asset Address of the asset. * @return true if valid, false if invalid. */ function isValidOutboundAsset(address asset) external view returns (bool); /** * @dev Function to set preceding contract (head registry) for the adapter. * @dev This registry governs the initiation of the adapter, exclusively listing authorized * preceding adapters. * @notice Only the adapters documented in this registry can invoke the current adapter, * thereby guaranteeing regulated and secure execution sequences. * @param precedingContract Address of preceding contract. * @param isValid Boolean value suggesting if this is a valid preceding contract. */ function setPrecedingContract( address precedingContract, bool isValid ) external; /** * @dev Function to set succeeding contract (tail registry) for the adapter. * @dev This registry dictates the potential succeeding actions by listing adapters that * may be invoked following the current one. * @notice Only the adapters documented in this registry can be invoked by the current adapter, * thereby guaranteeing regulated and secure execution sequences. * @param succeedingContract Address of succeeding contract. * @param isValid Boolean value suggesting if this is a valid succeeding contract. */ function setSucceedingContract( address succeedingContract, bool isValid ) external; /** * @dev Function to set inbound asset registry for the adapter. * @dev This registry keeps track of all the acceptable incoming assets, ensuring that the * adapter only processes predefined asset types. * @param asset Address of the asset. * @param isValid Boolean value suggesting if this is a valid inbound asset. */ function setInboundAsset(address asset, bool isValid) external; /** * @dev Function to set outbound asset registry for the adapter. * @dev It manages the types of assets that the adapter is allowed to output, thus controlling * the flow’s output and maintaining consistency. * @param asset Address of the asset. * @param isValid Boolean value suggesting if this is a valid inbound asset. */ function setOutboundAsset(address asset, bool isValid) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; interface IERC20 { function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function totalSupply() external view returns (uint256 supply); function balanceOf(address _owner) external view returns (uint256 balance); function transfer( address _to, uint256 _value ) external returns (bool success); function transferFrom( address _from, address _to, uint256 _value ) external returns (bool success); function approve( address _spender, uint256 _value ) external returns (bool success); function allowance( address _owner, address _spender ) external view returns (uint256 remaining); event Approval( address indexed _owner, address indexed _spender, uint256 _value ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; import {IERC20} from "../utils/SafeERC20.sol"; abstract contract IWETH { function allowance(address, address) public view virtual returns (uint256); function balanceOf(address) public view virtual returns (uint256); function approve(address, uint256) public virtual; function transfer(address, uint256) public virtual returns (bool); function transferFrom( address, address, uint256 ) public virtual returns (bool); function deposit() public payable virtual; function withdraw(uint256) public virtual; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; import {BaseAdapter} from "./BaseAdapter.sol"; import {EoaExecutorWithDataProvider, EoaExecutorWithoutDataProvider} from "./utils/EoaExecutor.sol"; abstract contract RouterIntentEoaAdapterWithDataProvider is BaseAdapter, EoaExecutorWithDataProvider { constructor( address __native, address __wnative, address __owner ) BaseAdapter(__native, __wnative, true, __owner) // solhint-disable-next-line no-empty-blocks { } } abstract contract RouterIntentEoaAdapterWithoutDataProvider is BaseAdapter, EoaExecutorWithoutDataProvider { constructor( address __native, address __wnative ) BaseAdapter(__native, __wnative, false, address(0)) // solhint-disable-next-line no-empty-blocks { } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; library Address { //insufficient balance error InsufficientBalance(uint256 available, uint256 required); //unable to send value, recipient may have reverted error SendingValueFail(); //insufficient balance for call error InsufficientBalanceForCall(uint256 available, uint256 required); //call to non-contract error NonContractCall(); function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } function sendValue(address payable recipient, uint256 amount) internal { uint256 balance = address(this).balance; if (balance < amount) { revert InsufficientBalance(balance, amount); } // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{value: amount}(""); if (!(success)) { revert SendingValueFail(); } } function functionCall( address target, bytes memory data ) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return _functionCallWithValue(target, data, 0, errorMessage); } function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue( target, data, value, "Address: low-level call with value failed" ); } function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { uint256 balance = address(this).balance; if (balance < value) { revert InsufficientBalanceForCall(balance, value); } return _functionCallWithValue(target, data, value, errorMessage); } function _functionCallWithValue( address target, bytes memory data, uint256 weiValue, string memory errorMessage ) private returns (bytes memory) { if (!(isContract(target))) { revert NonContractCall(); } // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{value: weiValue}( data ); if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; library CallLib { /** * @dev internal method that fecilitates the extenral calls from SmartAccount * @dev similar to execute() of Executor.sol * @param target destination address contract/non-contract * @param value amount of native tokens * @param data function singature of destination */ function _call( address target, uint256 value, bytes memory data ) internal returns (bytes memory result) { // solhint-disable-next-line no-inline-assembly assembly { let success := call( gas(), target, value, add(data, 0x20), mload(data), 0, 0 ) // Get the size of the returned data let size := returndatasize() // Allocate memory for the return data result := mload(0x40) // Set the length of the return data mstore(result, size) // Copy the return data to the allocated memory returndatacopy(add(result, 0x20), 0, size) // Update the free memory pointer mstore(0x40, add(result, add(0x20, size))) if iszero(success) { revert(result, returndatasize()) } } } /** * @dev internal method that fecilitates the extenral calls from SmartAccount * @dev similar to execute() of Executor.sol * @param target destination address contract/non-contract * @param data function singature of destination */ function _delegateCall( address target, bytes memory data ) internal returns (bytes memory result) { require(target != address(this), "delegatecall to self"); // solhint-disable-next-line no-inline-assembly assembly { // Perform delegatecall to the target contract let success := delegatecall( gas(), target, add(data, 0x20), mload(data), 0, 0 ) // Get the size of the returned data let size := returndatasize() // Allocate memory for the return data result := mload(0x40) // Set the length of the return data mstore(result, size) // Copy the return data to the allocated memory returndatacopy(add(result, 0x20), 0, size) // Update the free memory pointer mstore(0x40, add(result, add(0x20, size))) if iszero(success) { revert(result, returndatasize()) } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; abstract contract EoaExecutorWithDataProvider { /** * @dev function to execute an action on an adapter used in an EOA. * @param precedingAdapter Address of the preceding adapter. * @param succeedingAdapter Address of the succeeding adapter. * @param data inputs data. * @return tokens to be refunded to user at the end of tx. */ function execute( address precedingAdapter, address succeedingAdapter, bytes calldata data ) external payable virtual returns (address[] memory tokens); } abstract contract EoaExecutorWithoutDataProvider { /** * @dev function to execute an action on an adapter used in an EOA. * @param data inputs data. * @return tokens to be refunded to user at the end of tx. */ function execute( bytes calldata data ) external payable virtual returns (address[] memory tokens); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.18; /** * @title Errors library * @author Router Intents Error * @notice Defines the error messages emitted by the contracts on Router Intents */ library Errors { string public constant ARRAY_LENGTH_MISMATCH = "1"; // 'Array lengths mismatch' string public constant INSUFFICIENT_NATIVE_FUNDS_PASSED = "2"; // 'Insufficient native tokens passed' string public constant WRONG_BATCH_PROVIDED = "3"; // 'The targetLength, valueLength, callTypeLength, funcLength do not match in executeBatch transaction functions in batch transaction contract' string public constant INVALID_CALL_TYPE = "4"; // 'The callType value can only be 1 (call)' and 2(delegatecall)' string public constant ONLY_NITRO = "5"; // 'Only nitro can call this function' string public constant ONLY_SELF = "6"; // 'Only the current contract can call this function' string public constant ADAPTER_NOT_WHITELISTED = "7"; // 'Adapter not whitelisted' }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; import {Errors} from "./Errors.sol"; abstract contract NitroMessageHandler { address private immutable _assetForwarder; address private immutable _dexspan; constructor(address __assetForwarder, address __dexspan) { _assetForwarder = __assetForwarder; _dexspan = __dexspan; } /** * @dev function to get the address of asset forwarder */ function assetForwarder() public view returns (address) { return _assetForwarder; } /** * @dev function to get the address of dexspan */ function dexspan() public view returns (address) { return _dexspan; } /** * @notice function to handle instructions received from source chain. * @param tokenSent address of token received. * @param amount amount of tokens received. * @param instruction instruction passed from source chain. */ function handleMessage( address tokenSent, uint256 amount, bytes memory instruction ) external virtual; /** * @notice modifier to ensure that only Nitro bridge can call handleMessage function */ modifier onlyNitro() { _onlyNitro(); _; } function _onlyNitro() private view { require( msg.sender == _assetForwarder || msg.sender == _dexspan, Errors.ONLY_NITRO ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; error ReentrantCall(); constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true if (_status == _ENTERED) { revert ReentrantCall(); } // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; import {IERC20} from "../interfaces/IERC20.sol"; import {Address} from "./Address.sol"; import {SafeMath} from "./SafeMath.sol"; library SafeERC20 { using SafeMath for uint256; using Address for address; 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) ); } /// @dev Edited so it always first approves 0 and then the value, because of non standard tokens function safeApprove( IERC20 token, address spender, uint256 value ) internal { _callOptionalReturn( token, abi.encodeWithSelector(token.approve.selector, spender, 0) ); _callOptionalReturn( token, abi.encodeWithSelector(token.approve.selector, spender, value) ); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender).add( value ); _callOptionalReturn( token, abi.encodeWithSelector( token.approve.selector, spender, newAllowance ) ); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender).sub( value, "SafeERC20: decreased allowance below zero" ); _callOptionalReturn( token, abi.encodeWithSelector( token.approve.selector, spender, newAllowance ) ); } function _callOptionalReturn(IERC20 token, bytes memory data) private { bytes memory returndata = address(token).functionCall( data, "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: operation failed" ); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; library SafeMath { function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: mul overflow"); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
{ "optimizer": { "enabled": true, "runs": 1000000 }, "viaIR": true, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"__native","type":"address"},{"internalType":"address","name":"__wnative","type":"address"},{"internalType":"address","name":"__assetForwarder","type":"address"},{"internalType":"address","name":"__dexspan","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"NonContractCall","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"OperationFailedRefundEvent","type":"event"},{"anonymous":false,"inputs":[],"name":"OperationSuccessful","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"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SETTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetForwarder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dexspan","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"refundRecipient","type":"address"},{"internalType":"address[]","name":"target","type":"address[]"},{"internalType":"uint256[]","name":"value","type":"uint256[]"},{"internalType":"uint256[]","name":"callType","type":"uint256[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"executeBatchCallsDestChain","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address[]","name":"target","type":"address[]"},{"internalType":"uint256[]","name":"value","type":"uint256[]"},{"internalType":"uint256[]","name":"callType","type":"uint256[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"executeBatchCallsSameChain","outputs":[],"stateMutability":"payable","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":"address","name":"tokenSent","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"instruction","type":"bytes"}],"name":"handleMessage","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":[{"internalType":"address","name":"adapter","type":"address"}],"name":"isAdapterWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"native","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","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"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"adapters","type":"address[]"},{"internalType":"bool[]","name":"shouldWhitelist","type":"bool[]"}],"name":"setAdapterWhitelist","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":[],"name":"wnative","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
61010034620001bc57601f6200303438819003918201601f191683019291906001600160401b03841183851017620001c1578160809284926040968752833981010312620001bc576200005281620001d7565b9060209162000063838301620001d7565b916200007f606062000077878401620001d7565b9201620001d7565b9060805260a0526001805560c05260e0526000808052808252828120338252825260ff83822054161562000184575b7f61c92169ef077349011ff0b1383c894d86c5f0b41d986366b58a6cf31e93beda91828252818152838220338352815260ff84832054161562000149575b8351612e279081620001ed823960805181818161071a0152610a90015260a0518181816106ab0152610b47015260c05181818161023a01528181611b1f0152818161269b015281816127fa015261288e015260e051816102f60152f35b8282528181528382209033835252828120600160ff19825416179055339160008051602062003014833981519152339280a4388080620000ec565b8080528082528281203382528252828120600160ff19825416179055333382600080516020620030148339815191528180a4620000ae565b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203620001bc5756fe6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c806301ffc9a71461012b57806311b0b42d14610126578063248a9ca3146101215780632cebdeb21461011c5780632f2ff15d1461011757806336568abe146101125780633657eb9a1461010d5780636cec044b146101085780637fe689171461010357806391d14854146100fe57806394bf2b30146100f9578063a2011b3f146100f4578063a217fddf146100ef578063d00a2d5f146100ea578063d547741f146100e5578063dfd7cb06146100e05763f6f38e7c0361000e57610d23565b610c59565b610b6f565b610a09565b6108cd565b610874565b6107c0565b61073e565b6106cf565b610660565b61058a565b610471565b610338565b6102ab565b61025e565b6101ef565b346101ea5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea576004357fffffffff0000000000000000000000000000000000000000000000000000000081168091036101ea57807f7965db0b00000000000000000000000000000000000000000000000000000000602092149081156101c0575b506040519015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386101b5565b600080fd5b346101ea5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101ea5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea5760043560005260006020526020600160406000200154604051908152f35b346101ea5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b73ffffffffffffffffffffffffffffffffffffffff8116036101ea57565b346101ea5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea576004356024356103768161031a565b600091808352826020526103906001604085200154610d91565b8083528260205260ff6103c683604086209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b5416156103d1578280f35b8083528260205261040582604085209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d8480a438808280f35b346101ea5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea576024356104ac8161031a565b3373ffffffffffffffffffffffffffffffffffffffff8216036104d55761001990600435610fd5565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152fd5b9181601f840112156101ea5782359167ffffffffffffffff83116101ea576020808501948460051b0101116101ea57565b60c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea57600467ffffffffffffffff81358181116101ea576105d59036908401610559565b916024358181116101ea576105ed9036908601610559565b6044929192358281116101ea576106079036908801610559565b6064929192358481116101ea576106219036908a01610559565b9390926084358681116101ea5761063b9036908c01610559565b97909660a4359081116101ea576100199b61065891369101610559565b9a9099611697565b346101ea5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101ea5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101ea5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea57602060ff6107b46024356107808161031a565b6004356000526000845260406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54166040519015158152f35b60a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea576004356107f68161031a565b67ffffffffffffffff906024358281116101ea57610818903690600401610559565b6044929192358481116101ea57610833903690600401610559565b6064929192358681116101ea5761084e903690600401610559565b9390926084359788116101ea5761086c610019983690600401610559565b97909661179f565b346101ea5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea5760206040517f61c92169ef077349011ff0b1383c894d86c5f0b41d986366b58a6cf31e93beda8152f35b346101ea5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea57602060405160008152f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761095257604052565b610907565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761095257604052565b67ffffffffffffffff811161095257601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b9291926109de82610998565b916109ec6040519384610957565b8294818452818301116101ea578281602093846000960137010152565b346101ea5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea57600435610a448161031a565b60443567ffffffffffffffff81116101ea57366023820112156101ea57610a759036906024816004013591016109d2565b610af773ffffffffffffffffffffffffffffffffffffffff807f0000000000000000000000000000000000000000000000000000000000000000163314908115610b43575b5060405190610ac882610936565b600182527f35000000000000000000000000000000000000000000000000000000000000006020830152611533565b600260015414610b1957610b1391600260015560243590612c71565b60018055005b60046040517f37ed32e8000000000000000000000000000000000000000000000000000000008152fd5b90507f000000000000000000000000000000000000000000000000000000000000000016331438610aba565b346101ea5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea57610019602435600435610bb08261031a565b806000526000602052610bca600160406000200154610d91565b610fd5565b67ffffffffffffffff81116109525760051b60200190565b801515036101ea57565b81601f820112156101ea57803591610c0883610bcf565b92610c166040519485610957565b808452602092838086019260051b8201019283116101ea578301905b828210610c40575050505090565b8380918335610c4e81610be7565b815201910190610c32565b346101ea5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea5767ffffffffffffffff6004358181116101ea57366023820112156101ea578060040135610cb481610bcf565b91610cc26040519384610957565b81835260209160248385019160051b830101913683116101ea57602401905b828210610d0a57602435858782116101ea57610d04610019923690600401610bf1565b90611353565b8380918335610d188161031a565b815201910190610ce1565b346101ea5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea5773ffffffffffffffffffffffffffffffffffffffff600435610d738161031a565b166000526003602052602060ff604060002054166040519015158152f35b80600052600060205260ff610dca3360406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b541615610dd45750565b610ddd33611219565b610de5611100565b916030610df18461115b565b536078610dfd84611168565b5360415b60018111610ef157610eed6048610ebb85610e8f88610e2088156111b4565b6040519485937f416363657373436f6e74726f6c3a206163636f756e74200000000000000000006020860152610e60815180926020603789019101610f44565b84017f206973206d697373696e6720726f6c652000000000000000000000000000000060378201520190610f67565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610957565b6040519182917f08c379a000000000000000000000000000000000000000000000000000000000835260048301610fc1565b0390fd5b90600f8116906010821015610f3f577f3031323334353637383961626364656600000000000000000000000000000000610f3a921a610f308487611178565b5360041c91611189565b610e01565b61112c565b60005b838110610f575750506000910152565b8181015183820152602001610f47565b90610f7a60209282815194859201610f44565b0190565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602093610fba81518092818752878088019101610f44565b0116010190565b906020610fd2928181520190610f7e565b90565b6000908082528160205260ff61100e84604085209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b541661101957505050565b8082528160205261104d83604084209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541690557ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b73ffffffffffffffffffffffffffffffffffffffff3394169280a4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b90600182018092116110ee57565b6110b1565b919082018092116110ee57565b604051906080820182811067ffffffffffffffff82111761095257604052604282526060366020840137565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b805115610f3f5760200190565b805160011015610f3f5760210190565b908151811015610f3f570160200190565b80156110ee577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b156111bb57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152fd5b604051906060820182811067ffffffffffffffff82111761095257604052602a82526040366020840137603061124e8361115b565b53607861125a83611168565b536029905b6001821161127257610fd29150156111b4565b600f8116906010821015610f3f577f30313233343536373839616263646566000000000000000000000000000000006112b0921a610f308486611178565b9061125f565b7f61c92169ef077349011ff0b1383c894d86c5f0b41d986366b58a6cf31e93beda6112df611100565b9060306112eb8361115b565b5360786112f783611168565b536041905b6001821161130f57610fd29150156111b4565b600f8116906010821015610f3f577f303132333435363738396162636465660000000000000000000000000000000061134d921a610f308486611178565b906112fc565b3360009081527f637999432676374d4ea036a5e1ac845bfb5900b653d4393f12108092e01503ce60209081526040808320549195949392909160ff16156114425782519384151580611438575b6113b2906113ac6114fa565b90611533565b815b8581106113c5575050505050509050565b806114326113d560019385611579565b51151573ffffffffffffffffffffffffffffffffffffffff6113f7848a611579565b5116865260038b528686209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b016113b4565b50805185146113a0565b610eed610e60836114ca8961149e61145933611219565b60486114636112b6565b91865197857f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008a978801528251928391603789019101610f44565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101845283610957565b519182917f08c379a000000000000000000000000000000000000000000000000000000000835260048301610fc1565b6040519061150782610936565b600182527f31000000000000000000000000000000000000000000000000000000000000006020830152565b1561153b5750565b610eed906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352602060048401526024830190610f7e565b8051821015610f3f5760209160051b010190565b9015610f3f5790565b9060011015610f3f5760200190565b9190811015610f3f5760051b0190565b35610fd28161031a565b8054821015610f3f5760005260206000200190600090565b805468010000000000000000811015610952576115f9916001820181556115bf565b819291549060031b9173ffffffffffffffffffffffffffffffffffffffff809116831b921b1916179055565b6040519061163282610936565b600182527f32000000000000000000000000000000000000000000000000000000000000006020830152565b6040519061166b82610936565b600182527f34000000000000000000000000000000000000000000000000000000000000006020830152565b9b9a999897969594939b929091926116b86116b06114fa565b838514611533565b60009283945b81861061171a57505050506116df91506116d6611625565b90341015611533565b60005b8581106116f757506116f5979833611910565b565b80611714600361170a6001948a8a6115a5565b35106113ac61165e565b016116e2565b9091929361175260019161174c61173a6117358a888a6115a5565b6115b5565b6117458a8a886115a5565b3590611b01565b906110f3565b956117946117803373ffffffffffffffffffffffffffffffffffffffff166000526002602052604060002090565b61178e61173584888a6115a5565b906115d7565b0194939291906116be565b906116f598979695949392916117ec6040516117ba81610936565b600181527f36000000000000000000000000000000000000000000000000000000000000006020820152303314611533565b611910565b604051906117fe82610936565b600182527f33000000000000000000000000000000000000000000000000000000000000006020830152565b9015610f3f578035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101ea57019081359167ffffffffffffffff83116101ea5760200182360381136101ea579190565b9190811015610f3f5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101ea57019081359167ffffffffffffffff83116101ea5760200182360381136101ea579190565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116110ee57565b979391909695929681151580611af8575b80611aef575b80611ae6575b611939906113ac6117f1565b60018281036119905750936119766116f59998969461196f6119849561196961173561197d9761198b9d9b61158d565b9961158d565b359561158d565b359461182a565b36916109d2565b9285612157565b6125b4565b97926119e58a898987866119df61197d829f9d8d9f9d6119d8906119d18c8f859f816119c56117356119cb946117359461158d565b9a611596565b9861158d565b359761158d565b359661182a565b94611e8f565b885b838110611a0157505050505050505050506116f5906125b4565b80888c8989898f968f908a8a8d93611a18856118e3565b8414611a925792611a8692611a7f82611a8c9c611a788261197d97611a726117358c611a628f9e8f61173588611a5192611735946115a5565b9f611a5b886118e3565b90846115a5565b9e611a6c866110e0565b916115a5565b9c6115a5565b359a6115a5565b3598611883565b9561227e565b016119e7565b91611ad484611ae19b611acd828096611ac76117358a611abd6117358f9e611adb9f61197d9f6115a5565b9d611a6c866118e3565b9b6115a5565b35996115a5565b3597611883565b9461202f565b611a8c565b5084841461192d565b50848314611927565b50828214611921565b60009073ffffffffffffffffffffffffffffffffffffffff908116907f0000000000000000000000000000000000000000000000000000000000000000168103611b4a57505090565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000602082015233602482015230604482015260648101939093529091610fd291611b9a826084810161149e565b611bf09173ffffffffffffffffffffffffffffffffffffffff60405192611bc084610936565b602084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564602085015216611ca9565b805180611bfb575050565b81602091810103126101ea5760200151611c1481610be7565b15611c1b57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5361666545524332303a206f7065726174696f6e206661696c656400000000006044820152fd5b3d15611ca4573d90611c8a82610998565b91611c986040519384610957565b82523d6000602084013e565b606090565b803f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708114159081611d6f575b5015611d455781600092918360208194519301915af190611cf5611c79565b9115611cff575090565b815115611d0f5750805190602001fd5b610eed906040519182917f08c379a000000000000000000000000000000000000000000000000000000000835260048301610fc1565b60046040517f304619b5000000000000000000000000000000000000000000000000000000008152fd5b9050151538611cd6565b60405190611d8682610936565b600182527f37000000000000000000000000000000000000000000000000000000000000006020830152565b908160209103126101ea5751610fd28161031a565b6040513d6000823e3d90fd5b60609073ffffffffffffffffffffffffffffffffffffffff610fd29493600083521660208201528160408201520190610f7e565b60609073ffffffffffffffffffffffffffffffffffffffff610fd29493168152600060208201528160408201520190610f7e565b906060610fd29260008152600060208201528160408201520190610f7e565b606091610fd2949373ffffffffffffffffffffffffffffffffffffffff80921683521660208201528160408201520190610f7e565b94909291611ed2611eca611ec38673ffffffffffffffffffffffffffffffffffffffff166000526003602052604060002090565b5460ff1690565b6113ac611d79565b6000604051907f6af563e900000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff91602081600481868b165afa91821561202a5791611ffc575b5016611fba5750611f6c610e8f916040519283917f09c5eabe00000000000000000000000000000000000000000000000000000000602084015260248301610fc1565b915b60609360018103611f975750611f8493506123aa565b8051611f8e575050565b6116f5916124f0565b600291925014611fa9575b5050611f84565b611fb392506123de565b3880611fa2565b611ff690610e8f6040519384927ff5542f2d00000000000000000000000000000000000000000000000000000000602085015260248401611dd3565b91611f6e565b61201d915060203d8111612023575b6120158183610957565b810190611db2565b38611f29565b503d61200b565b611dc7565b94909291612063611eca611ec38673ffffffffffffffffffffffffffffffffffffffff166000526003602052604060002090565b6000604051907f6af563e900000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff91602081600481868b165afa91821561202a5791612139575b50166120fd5750611f6c610e8f916040519283917f09c5eabe00000000000000000000000000000000000000000000000000000000602084015260248301610fc1565b611ff690610e8f6040519384927ff5542f2d00000000000000000000000000000000000000000000000000000000602085015260248401611e07565b612151915060203d8111612023576120158183610957565b386120ba565b9391909161218b611eca611ec38573ffffffffffffffffffffffffffffffffffffffff166000526003602052604060002090565b6000604051907f6af563e900000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff91602081600481868a165afa91821561202a5791612260575b501661222457611f6c610e8f916040519283917f09c5eabe00000000000000000000000000000000000000000000000000000000602084015260248301610fc1565b611ff6610e8f916040519283917ff5542f2d00000000000000000000000000000000000000000000000000000000602084015260248301611e3b565b612278915060203d8111612023576120158183610957565b386121e2565b9591939290936122b4611eca611ec38773ffffffffffffffffffffffffffffffffffffffff166000526003602052604060002090565b6000604051907f6af563e900000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff91602081600481868c165afa91821561202a579161238c575b501661234f575050611f6c610e8f916040519283917f09c5eabe00000000000000000000000000000000000000000000000000000000602084015260248301610fc1565b610e8f611ff692936040519485937ff5542f2d00000000000000000000000000000000000000000000000000000000602086015260248501611e5a565b6123a4915060203d8111612023576120158183610957565b3861230b565b916000928392602083519301915af1903d916020604051938085528060008387013e840101604052156123d957565b503d90fd5b3073ffffffffffffffffffffffffffffffffffffffff82161461242a57816000929160208493519201905af4903d916020604051938085528060008387013e840101604052156123d957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64656c656761746563616c6c20746f2073656c660000000000000000000000006044820152fd5b81601f820112156101ea5780519161249f83610bcf565b926124ad6040519485610957565b808452602092838086019260051b8201019283116101ea578301905b8282106124d7575050505090565b83809183516124e58161031a565b8152019101906124c9565b9190918251830160209384818303126101ea57848101519167ffffffffffffffff83116101ea576125279286809201920101612488565b92600090815b85518110156125775760019061257173ffffffffffffffffffffffffffffffffffffffff8087168652600285526040862090612569848b611579565b5116906115d7565b0161252d565b505050509050565b8054906000908181558261259257505050565b815260208120918201915b8281106125a957505050565b81815560010161259d565b73ffffffffffffffffffffffffffffffffffffffff811660005260029060209082825260406000205460005b81811061261057505073ffffffffffffffffffffffffffffffffffffffff16600052526116f5604060002061257f565b60019073ffffffffffffffffffffffffffffffffffffffff841660005285855273ffffffffffffffffffffffffffffffffffffffff6126538260406000206115bf565b90549060031b1c166126653082612873565b73ffffffffffffffffffffffffffffffffffffffff861680151590612710575b80612707575b612698575b5050016125e0565b857f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1683146126e6576126df92612937565b3880612690565b6127029250600080809381935af16126fc611c79565b50612730565b6126df565b5080151561268b565b503073ffffffffffffffffffffffffffffffffffffffff87161415612685565b1561273757565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e61746976652073656e64206661696c000000000000000000000000000000006044820152fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8314612861575b829073ffffffffffffffffffffffffffffffffffffffff908184168015159081612856575b508061284d575b6127f5575b5050505090565b8116907f0000000000000000000000000000000000000000000000000000000000000000168114612833579161282a92612937565b388181806127ee565b50600080808093612848955af16126fc611c79565b61282a565b508215156127e9565b9050301415386127e2565b915061286d3083612873565b916127bd565b73ffffffffffffffffffffffffffffffffffffffff908116907f0000000000000000000000000000000000000000000000000000000000000000811682036128bb5750503190565b60246020929360405194859384927f70a082310000000000000000000000000000000000000000000000000000000084521660048301525afa90811561202a57600091612906575090565b906020823d821161292f575b8161291f60209383610957565b8101031261292c57505190565b80fd5b3d9150612912565b9173ffffffffffffffffffffffffffffffffffffffff604051927fa9059cbb000000000000000000000000000000000000000000000000000000006020850152166024830152604482015260448152608081019181831067ffffffffffffffff841117610952576116f592604052611b9a565b81601f820112156101ea578051916129c183610bcf565b926129cf6040519485610957565b808452602092838086019260051b8201019283116101ea578301905b8282106129f9575050505090565b815181529083019083016129eb565b919060a0838203126101ea578251612a1f8161031a565b926020928382015167ffffffffffffffff908181116101ea5784612a44918501612488565b94604094858501518381116101ea5781612a5f9187016129aa565b9560608601518481116101ea5782612a789188016129aa565b956080810151908582116101ea57019180601f840112156101ea57825190612a9f82610bcf565b95612aac84519788610957565b828752858088019360051b860101948286116101ea57868101935b868510612ad957505050505050505090565b84518381116101ea5782019084603f830112156101ea578882015190612afe82610998565b612b0a89519182610957565b828152868984860101116101ea57612b2b8b949385948b8685019101610f44565b815201940193612ac7565b90815180825260208080930193019160005b828110612b56575050505090565b835185529381019392810192600101612b48565b9391909260a085019373ffffffffffffffffffffffffffffffffffffffff809116865260209460a08688015283518091528560c088019401916000905b87838310612c5757505050505081612bca9186612bd89594036040880152612b36565b908482036060860152612b36565b9160808184039101528251908183528083019281808460051b8301019501936000915b848310612c0b5750505050505090565b9091929394958480612c47837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600196030187528a51610f7e565b9801930193019194939290612bfb565b845182168752958601959093019260019190910190612ba7565b612c9a73ffffffffffffffffffffffffffffffffffffffff929360208082518301019101612a08565b96939590929195169460005b8351811015612d3c576002612cbb8286611579565b5111612cc957600101612ca6565b505050507fb69677b2a82170abd46dbc9853e73529a3ac021a6e65e7c02f89cdf3b3d063c7935080612cff612d37928585612795565b506040519384938460409194939294606082019573ffffffffffffffffffffffffffffffffffffffff80921683521660208201520152565b0390a1565b5091612d836000949793610e8f869560405194859360208501977f94bf2b300000000000000000000000000000000000000000000000000000000089528c60248701612b6a565b519082305af1612d91611c79565b5015612dc1575050507fc2623b31705c3a17d595c59e4c160723c6c140a0a0cbea051392e781b741575d600080a1565b612d3783612cff7fb69677b2a82170abd46dbc9853e73529a3ac021a6e65e7c02f89cdf3b3d063c795858561279556fea2646970667358221220d2d419a68d96a4a4fe0c6895034cd970514b89d40652d61b5d90c14a5d4ea19564736f6c634300081200332f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000c21e4ebd1d92036cb467b53fe3258f219d909eb90000000000000000000000006a0fd5577c540e16a3a49c40b51e0880a2a528ce
Deployed Bytecode
0x6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c806301ffc9a71461012b57806311b0b42d14610126578063248a9ca3146101215780632cebdeb21461011c5780632f2ff15d1461011757806336568abe146101125780633657eb9a1461010d5780636cec044b146101085780637fe689171461010357806391d14854146100fe57806394bf2b30146100f9578063a2011b3f146100f4578063a217fddf146100ef578063d00a2d5f146100ea578063d547741f146100e5578063dfd7cb06146100e05763f6f38e7c0361000e57610d23565b610c59565b610b6f565b610a09565b6108cd565b610874565b6107c0565b61073e565b6106cf565b610660565b61058a565b610471565b610338565b6102ab565b61025e565b6101ef565b346101ea5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea576004357fffffffff0000000000000000000000000000000000000000000000000000000081168091036101ea57807f7965db0b00000000000000000000000000000000000000000000000000000000602092149081156101c0575b506040519015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386101b5565b600080fd5b346101ea5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea57602060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee168152f35b346101ea5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea5760043560005260006020526020600160406000200154604051908152f35b346101ea5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea57602060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2168152f35b73ffffffffffffffffffffffffffffffffffffffff8116036101ea57565b346101ea5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea576004356024356103768161031a565b600091808352826020526103906001604085200154610d91565b8083528260205260ff6103c683604086209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b5416156103d1578280f35b8083528260205261040582604085209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d8480a438808280f35b346101ea5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea576024356104ac8161031a565b3373ffffffffffffffffffffffffffffffffffffffff8216036104d55761001990600435610fd5565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152fd5b9181601f840112156101ea5782359167ffffffffffffffff83116101ea576020808501948460051b0101116101ea57565b60c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea57600467ffffffffffffffff81358181116101ea576105d59036908401610559565b916024358181116101ea576105ed9036908601610559565b6044929192358281116101ea576106079036908801610559565b6064929192358481116101ea576106219036908a01610559565b9390926084358681116101ea5761063b9036908c01610559565b97909660a4359081116101ea576100199b61065891369101610559565b9a9099611697565b346101ea5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006a0fd5577c540e16a3a49c40b51e0880a2a528ce168152f35b346101ea5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea57602060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c21e4ebd1d92036cb467b53fe3258f219d909eb9168152f35b346101ea5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea57602060ff6107b46024356107808161031a565b6004356000526000845260406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54166040519015158152f35b60a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea576004356107f68161031a565b67ffffffffffffffff906024358281116101ea57610818903690600401610559565b6044929192358481116101ea57610833903690600401610559565b6064929192358681116101ea5761084e903690600401610559565b9390926084359788116101ea5761086c610019983690600401610559565b97909661179f565b346101ea5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea5760206040517f61c92169ef077349011ff0b1383c894d86c5f0b41d986366b58a6cf31e93beda8152f35b346101ea5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea57602060405160008152f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761095257604052565b610907565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761095257604052565b67ffffffffffffffff811161095257601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b9291926109de82610998565b916109ec6040519384610957565b8294818452818301116101ea578281602093846000960137010152565b346101ea5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea57600435610a448161031a565b60443567ffffffffffffffff81116101ea57366023820112156101ea57610a759036906024816004013591016109d2565b610af773ffffffffffffffffffffffffffffffffffffffff807f000000000000000000000000c21e4ebd1d92036cb467b53fe3258f219d909eb9163314908115610b43575b5060405190610ac882610936565b600182527f35000000000000000000000000000000000000000000000000000000000000006020830152611533565b600260015414610b1957610b1391600260015560243590612c71565b60018055005b60046040517f37ed32e8000000000000000000000000000000000000000000000000000000008152fd5b90507f0000000000000000000000006a0fd5577c540e16a3a49c40b51e0880a2a528ce16331438610aba565b346101ea5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea57610019602435600435610bb08261031a565b806000526000602052610bca600160406000200154610d91565b610fd5565b67ffffffffffffffff81116109525760051b60200190565b801515036101ea57565b81601f820112156101ea57803591610c0883610bcf565b92610c166040519485610957565b808452602092838086019260051b8201019283116101ea578301905b828210610c40575050505090565b8380918335610c4e81610be7565b815201910190610c32565b346101ea5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea5767ffffffffffffffff6004358181116101ea57366023820112156101ea578060040135610cb481610bcf565b91610cc26040519384610957565b81835260209160248385019160051b830101913683116101ea57602401905b828210610d0a57602435858782116101ea57610d04610019923690600401610bf1565b90611353565b8380918335610d188161031a565b815201910190610ce1565b346101ea5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ea5773ffffffffffffffffffffffffffffffffffffffff600435610d738161031a565b166000526003602052602060ff604060002054166040519015158152f35b80600052600060205260ff610dca3360406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b541615610dd45750565b610ddd33611219565b610de5611100565b916030610df18461115b565b536078610dfd84611168565b5360415b60018111610ef157610eed6048610ebb85610e8f88610e2088156111b4565b6040519485937f416363657373436f6e74726f6c3a206163636f756e74200000000000000000006020860152610e60815180926020603789019101610f44565b84017f206973206d697373696e6720726f6c652000000000000000000000000000000060378201520190610f67565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610957565b6040519182917f08c379a000000000000000000000000000000000000000000000000000000000835260048301610fc1565b0390fd5b90600f8116906010821015610f3f577f3031323334353637383961626364656600000000000000000000000000000000610f3a921a610f308487611178565b5360041c91611189565b610e01565b61112c565b60005b838110610f575750506000910152565b8181015183820152602001610f47565b90610f7a60209282815194859201610f44565b0190565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602093610fba81518092818752878088019101610f44565b0116010190565b906020610fd2928181520190610f7e565b90565b6000908082528160205260ff61100e84604085209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b541661101957505050565b8082528160205261104d83604084209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541690557ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b73ffffffffffffffffffffffffffffffffffffffff3394169280a4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b90600182018092116110ee57565b6110b1565b919082018092116110ee57565b604051906080820182811067ffffffffffffffff82111761095257604052604282526060366020840137565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b805115610f3f5760200190565b805160011015610f3f5760210190565b908151811015610f3f570160200190565b80156110ee577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b156111bb57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152fd5b604051906060820182811067ffffffffffffffff82111761095257604052602a82526040366020840137603061124e8361115b565b53607861125a83611168565b536029905b6001821161127257610fd29150156111b4565b600f8116906010821015610f3f577f30313233343536373839616263646566000000000000000000000000000000006112b0921a610f308486611178565b9061125f565b7f61c92169ef077349011ff0b1383c894d86c5f0b41d986366b58a6cf31e93beda6112df611100565b9060306112eb8361115b565b5360786112f783611168565b536041905b6001821161130f57610fd29150156111b4565b600f8116906010821015610f3f577f303132333435363738396162636465660000000000000000000000000000000061134d921a610f308486611178565b906112fc565b3360009081527f637999432676374d4ea036a5e1ac845bfb5900b653d4393f12108092e01503ce60209081526040808320549195949392909160ff16156114425782519384151580611438575b6113b2906113ac6114fa565b90611533565b815b8581106113c5575050505050509050565b806114326113d560019385611579565b51151573ffffffffffffffffffffffffffffffffffffffff6113f7848a611579565b5116865260038b528686209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b016113b4565b50805185146113a0565b610eed610e60836114ca8961149e61145933611219565b60486114636112b6565b91865197857f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008a978801528251928391603789019101610f44565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101845283610957565b519182917f08c379a000000000000000000000000000000000000000000000000000000000835260048301610fc1565b6040519061150782610936565b600182527f31000000000000000000000000000000000000000000000000000000000000006020830152565b1561153b5750565b610eed906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352602060048401526024830190610f7e565b8051821015610f3f5760209160051b010190565b9015610f3f5790565b9060011015610f3f5760200190565b9190811015610f3f5760051b0190565b35610fd28161031a565b8054821015610f3f5760005260206000200190600090565b805468010000000000000000811015610952576115f9916001820181556115bf565b819291549060031b9173ffffffffffffffffffffffffffffffffffffffff809116831b921b1916179055565b6040519061163282610936565b600182527f32000000000000000000000000000000000000000000000000000000000000006020830152565b6040519061166b82610936565b600182527f34000000000000000000000000000000000000000000000000000000000000006020830152565b9b9a999897969594939b929091926116b86116b06114fa565b838514611533565b60009283945b81861061171a57505050506116df91506116d6611625565b90341015611533565b60005b8581106116f757506116f5979833611910565b565b80611714600361170a6001948a8a6115a5565b35106113ac61165e565b016116e2565b9091929361175260019161174c61173a6117358a888a6115a5565b6115b5565b6117458a8a886115a5565b3590611b01565b906110f3565b956117946117803373ffffffffffffffffffffffffffffffffffffffff166000526002602052604060002090565b61178e61173584888a6115a5565b906115d7565b0194939291906116be565b906116f598979695949392916117ec6040516117ba81610936565b600181527f36000000000000000000000000000000000000000000000000000000000000006020820152303314611533565b611910565b604051906117fe82610936565b600182527f33000000000000000000000000000000000000000000000000000000000000006020830152565b9015610f3f578035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101ea57019081359167ffffffffffffffff83116101ea5760200182360381136101ea579190565b9190811015610f3f5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101ea57019081359167ffffffffffffffff83116101ea5760200182360381136101ea579190565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116110ee57565b979391909695929681151580611af8575b80611aef575b80611ae6575b611939906113ac6117f1565b60018281036119905750936119766116f59998969461196f6119849561196961173561197d9761198b9d9b61158d565b9961158d565b359561158d565b359461182a565b36916109d2565b9285612157565b6125b4565b97926119e58a898987866119df61197d829f9d8d9f9d6119d8906119d18c8f859f816119c56117356119cb946117359461158d565b9a611596565b9861158d565b359761158d565b359661182a565b94611e8f565b885b838110611a0157505050505050505050506116f5906125b4565b80888c8989898f968f908a8a8d93611a18856118e3565b8414611a925792611a8692611a7f82611a8c9c611a788261197d97611a726117358c611a628f9e8f61173588611a5192611735946115a5565b9f611a5b886118e3565b90846115a5565b9e611a6c866110e0565b916115a5565b9c6115a5565b359a6115a5565b3598611883565b9561227e565b016119e7565b91611ad484611ae19b611acd828096611ac76117358a611abd6117358f9e611adb9f61197d9f6115a5565b9d611a6c866118e3565b9b6115a5565b35996115a5565b3597611883565b9461202f565b611a8c565b5084841461192d565b50848314611927565b50828214611921565b60009073ffffffffffffffffffffffffffffffffffffffff908116907f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee168103611b4a57505090565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000602082015233602482015230604482015260648101939093529091610fd291611b9a826084810161149e565b611bf09173ffffffffffffffffffffffffffffffffffffffff60405192611bc084610936565b602084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564602085015216611ca9565b805180611bfb575050565b81602091810103126101ea5760200151611c1481610be7565b15611c1b57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5361666545524332303a206f7065726174696f6e206661696c656400000000006044820152fd5b3d15611ca4573d90611c8a82610998565b91611c986040519384610957565b82523d6000602084013e565b606090565b803f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708114159081611d6f575b5015611d455781600092918360208194519301915af190611cf5611c79565b9115611cff575090565b815115611d0f5750805190602001fd5b610eed906040519182917f08c379a000000000000000000000000000000000000000000000000000000000835260048301610fc1565b60046040517f304619b5000000000000000000000000000000000000000000000000000000008152fd5b9050151538611cd6565b60405190611d8682610936565b600182527f37000000000000000000000000000000000000000000000000000000000000006020830152565b908160209103126101ea5751610fd28161031a565b6040513d6000823e3d90fd5b60609073ffffffffffffffffffffffffffffffffffffffff610fd29493600083521660208201528160408201520190610f7e565b60609073ffffffffffffffffffffffffffffffffffffffff610fd29493168152600060208201528160408201520190610f7e565b906060610fd29260008152600060208201528160408201520190610f7e565b606091610fd2949373ffffffffffffffffffffffffffffffffffffffff80921683521660208201528160408201520190610f7e565b94909291611ed2611eca611ec38673ffffffffffffffffffffffffffffffffffffffff166000526003602052604060002090565b5460ff1690565b6113ac611d79565b6000604051907f6af563e900000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff91602081600481868b165afa91821561202a5791611ffc575b5016611fba5750611f6c610e8f916040519283917f09c5eabe00000000000000000000000000000000000000000000000000000000602084015260248301610fc1565b915b60609360018103611f975750611f8493506123aa565b8051611f8e575050565b6116f5916124f0565b600291925014611fa9575b5050611f84565b611fb392506123de565b3880611fa2565b611ff690610e8f6040519384927ff5542f2d00000000000000000000000000000000000000000000000000000000602085015260248401611dd3565b91611f6e565b61201d915060203d8111612023575b6120158183610957565b810190611db2565b38611f29565b503d61200b565b611dc7565b94909291612063611eca611ec38673ffffffffffffffffffffffffffffffffffffffff166000526003602052604060002090565b6000604051907f6af563e900000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff91602081600481868b165afa91821561202a5791612139575b50166120fd5750611f6c610e8f916040519283917f09c5eabe00000000000000000000000000000000000000000000000000000000602084015260248301610fc1565b611ff690610e8f6040519384927ff5542f2d00000000000000000000000000000000000000000000000000000000602085015260248401611e07565b612151915060203d8111612023576120158183610957565b386120ba565b9391909161218b611eca611ec38573ffffffffffffffffffffffffffffffffffffffff166000526003602052604060002090565b6000604051907f6af563e900000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff91602081600481868a165afa91821561202a5791612260575b501661222457611f6c610e8f916040519283917f09c5eabe00000000000000000000000000000000000000000000000000000000602084015260248301610fc1565b611ff6610e8f916040519283917ff5542f2d00000000000000000000000000000000000000000000000000000000602084015260248301611e3b565b612278915060203d8111612023576120158183610957565b386121e2565b9591939290936122b4611eca611ec38773ffffffffffffffffffffffffffffffffffffffff166000526003602052604060002090565b6000604051907f6af563e900000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff91602081600481868c165afa91821561202a579161238c575b501661234f575050611f6c610e8f916040519283917f09c5eabe00000000000000000000000000000000000000000000000000000000602084015260248301610fc1565b610e8f611ff692936040519485937ff5542f2d00000000000000000000000000000000000000000000000000000000602086015260248501611e5a565b6123a4915060203d8111612023576120158183610957565b3861230b565b916000928392602083519301915af1903d916020604051938085528060008387013e840101604052156123d957565b503d90fd5b3073ffffffffffffffffffffffffffffffffffffffff82161461242a57816000929160208493519201905af4903d916020604051938085528060008387013e840101604052156123d957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64656c656761746563616c6c20746f2073656c660000000000000000000000006044820152fd5b81601f820112156101ea5780519161249f83610bcf565b926124ad6040519485610957565b808452602092838086019260051b8201019283116101ea578301905b8282106124d7575050505090565b83809183516124e58161031a565b8152019101906124c9565b9190918251830160209384818303126101ea57848101519167ffffffffffffffff83116101ea576125279286809201920101612488565b92600090815b85518110156125775760019061257173ffffffffffffffffffffffffffffffffffffffff8087168652600285526040862090612569848b611579565b5116906115d7565b0161252d565b505050509050565b8054906000908181558261259257505050565b815260208120918201915b8281106125a957505050565b81815560010161259d565b73ffffffffffffffffffffffffffffffffffffffff811660005260029060209082825260406000205460005b81811061261057505073ffffffffffffffffffffffffffffffffffffffff16600052526116f5604060002061257f565b60019073ffffffffffffffffffffffffffffffffffffffff841660005285855273ffffffffffffffffffffffffffffffffffffffff6126538260406000206115bf565b90549060031b1c166126653082612873565b73ffffffffffffffffffffffffffffffffffffffff861680151590612710575b80612707575b612698575b5050016125e0565b857f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff1683146126e6576126df92612937565b3880612690565b6127029250600080809381935af16126fc611c79565b50612730565b6126df565b5080151561268b565b503073ffffffffffffffffffffffffffffffffffffffff87161415612685565b1561273757565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e61746976652073656e64206661696c000000000000000000000000000000006044820152fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8314612861575b829073ffffffffffffffffffffffffffffffffffffffff908184168015159081612856575b508061284d575b6127f5575b5050505090565b8116907f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee168114612833579161282a92612937565b388181806127ee565b50600080808093612848955af16126fc611c79565b61282a565b508215156127e9565b9050301415386127e2565b915061286d3083612873565b916127bd565b73ffffffffffffffffffffffffffffffffffffffff908116907f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811682036128bb5750503190565b60246020929360405194859384927f70a082310000000000000000000000000000000000000000000000000000000084521660048301525afa90811561202a57600091612906575090565b906020823d821161292f575b8161291f60209383610957565b8101031261292c57505190565b80fd5b3d9150612912565b9173ffffffffffffffffffffffffffffffffffffffff604051927fa9059cbb000000000000000000000000000000000000000000000000000000006020850152166024830152604482015260448152608081019181831067ffffffffffffffff841117610952576116f592604052611b9a565b81601f820112156101ea578051916129c183610bcf565b926129cf6040519485610957565b808452602092838086019260051b8201019283116101ea578301905b8282106129f9575050505090565b815181529083019083016129eb565b919060a0838203126101ea578251612a1f8161031a565b926020928382015167ffffffffffffffff908181116101ea5784612a44918501612488565b94604094858501518381116101ea5781612a5f9187016129aa565b9560608601518481116101ea5782612a789188016129aa565b956080810151908582116101ea57019180601f840112156101ea57825190612a9f82610bcf565b95612aac84519788610957565b828752858088019360051b860101948286116101ea57868101935b868510612ad957505050505050505090565b84518381116101ea5782019084603f830112156101ea578882015190612afe82610998565b612b0a89519182610957565b828152868984860101116101ea57612b2b8b949385948b8685019101610f44565b815201940193612ac7565b90815180825260208080930193019160005b828110612b56575050505090565b835185529381019392810192600101612b48565b9391909260a085019373ffffffffffffffffffffffffffffffffffffffff809116865260209460a08688015283518091528560c088019401916000905b87838310612c5757505050505081612bca9186612bd89594036040880152612b36565b908482036060860152612b36565b9160808184039101528251908183528083019281808460051b8301019501936000915b848310612c0b5750505050505090565b9091929394958480612c47837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600196030187528a51610f7e565b9801930193019194939290612bfb565b845182168752958601959093019260019190910190612ba7565b612c9a73ffffffffffffffffffffffffffffffffffffffff929360208082518301019101612a08565b96939590929195169460005b8351811015612d3c576002612cbb8286611579565b5111612cc957600101612ca6565b505050507fb69677b2a82170abd46dbc9853e73529a3ac021a6e65e7c02f89cdf3b3d063c7935080612cff612d37928585612795565b506040519384938460409194939294606082019573ffffffffffffffffffffffffffffffffffffffff80921683521660208201520152565b0390a1565b5091612d836000949793610e8f869560405194859360208501977f94bf2b300000000000000000000000000000000000000000000000000000000089528c60248701612b6a565b519082305af1612d91611c79565b5015612dc1575050507fc2623b31705c3a17d595c59e4c160723c6c140a0a0cbea051392e781b741575d600080a1565b612d3783612cff7fb69677b2a82170abd46dbc9853e73529a3ac021a6e65e7c02f89cdf3b3d063c795858561279556fea2646970667358221220d2d419a68d96a4a4fe0c6895034cd970514b89d40652d61b5d90c14a5d4ea19564736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000c21e4ebd1d92036cb467b53fe3258f219d909eb90000000000000000000000006a0fd5577c540e16a3a49c40b51e0880a2a528ce
-----Decoded View---------------
Arg [0] : __native (address): 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
Arg [1] : __wnative (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
Arg [2] : __assetForwarder (address): 0xC21e4ebD1d92036Cb467b53fE3258F219d909Eb9
Arg [3] : __dexspan (address): 0x6A0fD5577c540e16A3A49C40b51E0880a2a528ce
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
Arg [1] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [2] : 000000000000000000000000c21e4ebd1d92036cb467b53fe3258f219d909eb9
Arg [3] : 0000000000000000000000006a0fd5577c540e16a3a49c40b51e0880a2a528ce
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
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.