Source Code
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 319256736 | 233 days ago | 0.00000045 ETH | ||||
| 319256736 | 233 days ago | 0.00045032 ETH | ||||
| 319256736 | 233 days ago | 0.00000022 ETH | ||||
| 319254874 | 233 days ago | 0.00000041 ETH | ||||
| 319254874 | 233 days ago | 0.00041669 ETH | ||||
| 319254874 | 233 days ago | 0.0000002 ETH | ||||
| 319238246 | 233 days ago | 0.00000044 ETH | ||||
| 319238246 | 233 days ago | 0.00044433 ETH | ||||
| 319238246 | 233 days ago | 0.00000022 ETH | ||||
| 319076562 | 234 days ago | 0.00000045 ETH | ||||
| 319076562 | 234 days ago | 0.00045431 ETH | ||||
| 319076562 | 234 days ago | 0.00000022 ETH | ||||
| 319065841 | 234 days ago | 0.00000045 ETH | ||||
| 319065841 | 234 days ago | 0.00045032 ETH | ||||
| 319065841 | 234 days ago | 0.00000022 ETH | ||||
| 319038571 | 234 days ago | 0.00000039 ETH | ||||
| 319038571 | 234 days ago | 0.0003994 ETH | ||||
| 319038571 | 234 days ago | 0.0000002 ETH | ||||
| 318022269 | 237 days ago | 0.0069965 ETH | ||||
| 318022269 | 237 days ago | 0.0000035 ETH | ||||
| 316581731 | 241 days ago | 0.00000099 ETH | ||||
| 316581731 | 241 days ago | 0.0009985 ETH | ||||
| 316581731 | 241 days ago | 0.0000005 ETH | ||||
| 315482890 | 244 days ago | 0.00000499 ETH | ||||
| 315482890 | 244 days ago | 0.0049925 ETH |
Cross-Chain Transactions
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 {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 {Errors as IntentErrors} from "./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";
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
/**
* @title BatchTransaction
* @author Shivam Agrawal
* @notice Batch Transaction Contract for EOAs.
*/
contract BatchTransaction is
Basic,
AccessControl,
ReentrancyGuard,
IERC721Receiver
{
using SafeERC20 for IERC20;
struct RefundData {
address[] tokens;
}
struct FeeInfo {
uint96 fee;
address recipient;
}
bytes32 public constant SETTER_ROLE = keccak256("SETTER_ROLE");
address private immutable _native;
address private immutable _wnative;
address private _assetForwarder;
address private _dexspan;
address private _assetBridge;
address private _feeAdapter;
// user -> token array
mapping(address => RefundData) private tokensToRefund;
mapping(address => bool) private adapterWhitelist;
event OperationFailedRefundEvent(
address token,
address recipient,
uint256 amount
);
event OperationSuccessful();
event Executed(uint256 appId);
constructor(
address __native,
address __wnative,
address __assetForwarder,
address __dexspan,
address __assetBridge,
address __feeAdapter
) {
_native = __native;
_wnative = __wnative;
_assetForwarder = __assetForwarder;
_dexspan = __dexspan;
_assetBridge = __assetBridge;
_feeAdapter = __feeAdapter;
_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 return the address of Dexspan.
*/
function dexspan() public view virtual returns (address) {
return _dexspan;
}
/**
* @notice function to return the address of AssetForwarder.
*/
function assetForwarder() public view virtual returns (address) {
return _assetForwarder;
}
/**
* @notice function to return the address of AssetBridge.
*/
function assetBridge() public view virtual returns (address) {
return _assetBridge;
}
/**
* @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 dexspan address.
* @param __dexspan Address of the dexspan.
*/
function setDexspan(address __dexspan) external onlyRole(SETTER_ROLE) {
_dexspan = __dexspan;
}
/**
* @notice function to set assetForwarder address.
* @param __assetForwarder Address of the assetForwarder.
*/
function setAssetForwarder(
address __assetForwarder
) external onlyRole(SETTER_ROLE) {
_assetForwarder = __assetForwarder;
}
/**
* @notice function to set assetForwarder address.
* @param __assetBridge Address of the assetBridge.
*/
function setAssetBridge(
address __assetBridge
) external onlyRole(SETTER_ROLE) {
_assetBridge = __assetBridge;
}
/**
* @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 appId Application Id
* @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(
uint256 appId,
address[] calldata tokens,
uint256[] calldata amounts,
bytes calldata feeData,
address[] calldata target,
uint256[] calldata value,
uint256[] calldata callType,
bytes[] calldata data
) external payable nonReentrant {
uint256 tokensLength = tokens.length;
require(
tokensLength == amounts.length,
Errors.ARRAY_LENGTH_MISMATCH
);
uint256 totalValue = 0;
//add fee
for (uint256 i = 0; i < tokensLength; ) {
totalValue += _pullTokens(tokens[i], amounts[i]);
tokensToRefund[msg.sender].tokens.push(tokens[i]);
unchecked {
++i;
}
}
if(_feeAdapter != address(0))
{
_execute(
msg.sender,
_feeAdapter,
address(0),
address(0),
0,
2,
feeData
);
}
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(appId, msg.sender, target, value, callType, data);
}
/**
* @dev function to execute batch calls
* @param appId Application Id
* @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(
uint256 appId,
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(
appId,
refundRecipient,
target,
value,
callType,
data
);
}
/**
* @dev function to execute batch calls
* @param appId Application Id
* @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(
uint256 appId,
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);
emit Executed(appId);
}
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];
}
function handleMessage(
address tokenSent,
uint256 amount,
bytes memory instruction
) external onlyNitro nonReentrant {
(
uint256 appId,
address refundAddress,
address[] memory target,
uint256[] memory value,
uint256[] memory callType,
bytes[] memory data
) = abi.decode(
instruction,
(uint256, 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,
appId,
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 {}
function adminWithdrawFunds(
address _token,
address _recipient,
uint256 _amount
) external onlyRole(DEFAULT_ADMIN_ROLE) {
if (_token == native()) {
if (_amount == type(uint256).max) _amount = address(this).balance;
(bool success, ) = _recipient.call{value: _amount}("");
if (!success) revert("Transfer failed");
} else {
if (_amount == type(uint256).max)
_amount = IERC20(_token).balanceOf(address(this));
IERC20(_token).transfer(_recipient, _amount);
}
}
/**
* @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 ||
msg.sender == _assetBridge,
Errors.ONLY_NITRO
);
}
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4) {
return this.onERC721Received.selector;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `_msgSender()` is missing `role`.
* Overriding this function changes the behavior of the {onlyRole} modifier.
*
* Format of the revert message is described in {_checkRole}.
*
* _Available since v4.6._
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(account),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* May emit a {RoleGranted} event.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*
* NOTE: This function is deprecated in favor of {_grantRole}.
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Grants `role` to `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
/**
* @dev Revokes `role` from `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// 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;
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;
}
}// 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'
string public constant INVALID_BRIDGE_ADDRESS = "8"; // 'Bridge address neither asset forwarder nor dexspan'
string public constant BRIDGE_CALL_FAILED = "9"; // 'Bridge call failed'
string public constant INVALID_BRDIGE_TX_TYPE = "10"; // 'Bridge tx type cannot be greater than 3'
string public constant INVALID_AMOUNT = "11"; // 'Amount is invalid'
string public constant INVALID_BRIDGE_CHAIN_ID = "12"; // 'Bridging chainId is invalid'
string public constant ZERO_AMOUNT_RECEIVED = "13"; // 'Zero amount received'
string public constant INVALID_TX_TYPE = "14"; // 'Invalid txType value'
string public constant INVALID_REQUEST = "15"; // 'Invalid Request'
string public constant INVALID_ASSET_BRDIGE_TX_TYPE = "16"; // 'Asset Bridge tx type cannot be greater than 1'
string public constant FEE_EXCEEDS_MAX_BIPS = "17"; // 'Fee passed exceeds max bips fee'
string public constant FEE_RECIPIENT_CANNOT_BE_ZERO_ADDRESS = "18"; // 'Fee recipient cannot be address(0)'
}{
"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
Contract ABI
API[{"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"},{"internalType":"address","name":"__assetBridge","type":"address"},{"internalType":"address","name":"__feeAdapter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"NonContractCall","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"appId","type":"uint256"}],"name":"Executed","type":"event"},{"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":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"adminWithdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"assetBridge","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"uint256","name":"appId","type":"uint256"},{"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":"uint256","name":"appId","type":"uint256"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"feeData","type":"bytes"},{"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":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"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":"address","name":"__assetBridge","type":"address"}],"name":"setAssetBridge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"__assetForwarder","type":"address"}],"name":"setAssetForwarder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"__dexspan","type":"address"}],"name":"setDexspan","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
60c034620001f657601f6200381938819003918201601f191683019291906001600160401b03841183851017620001fb578160c09284926040968752833981010312620001f657620000518162000211565b6020916200006183820162000211565b916200006f85830162000211565b926200007e6060840162000211565b906200009b60a0620000936080870162000211565b950162000211565b926001805560805260a05260018060a01b03928380928160018060a01b031997168760025416176002551685600354161760035516836004541617600455169060055416176005556000808052808252828120338252825260ff838220541615620001be575b7f61c92169ef077349011ff0b1383c894d86c5f0b41d986366b58a6cf31e93beda91828252818152838220338352815260ff84832054161562000183575b83516135d2908162000227823960805181818161029a015281816109450152818161217801528181612e5901528181612fb8015261305b015260a0518161051b0152f35b8282528181528382209033835252828120600160ff198254161790553391600080516020620037f9833981519152339280a43880806200013f565b8080528082528281203382528252828120600160ff19825416179055333382600080516020620037f98339815191528180a462000101565b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203620001f65756fe6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c806301ffc9a71461018b57806311b0b42d14610186578063150b7a021461018157806318137a411461017c578063248a9ca314610177578063285f94a0146101725780632cebdeb21461016d5780632f2ff15d1461016857806336568abe14610163578063383536901461015e5780636cec044b1461015957806375ea1c92146101545780637fe689171461014f57806391d148541461014a578063963276f3146101455780639e99ec3914610140578063a2011b3f1461013b578063a217fddf14610136578063c5962f2614610131578063d00a2d5f1461012c578063d547741f14610127578063dfd7cb06146101225763f6f38e7c0361000e5761127d565b6111b3565b6110c9565b610f89565b610e00565b610dc6565b610d6d565b610ce6565b610c33565b610bb1565b610b5f565b6108d6565b610884565b610791565b610678565b61053f565b6104d0565b61047e565b610431565b6103aa565b610319565b61024f565b3461024a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361024a57807f7965db0b0000000000000000000000000000000000000000000000000000000060209214908115610220575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501438610215565b600080fd5b3461024a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b73ffffffffffffffffffffffffffffffffffffffff81160361024a57565b602435906102e9826102be565b565b9181601f8401121561024a5782359167ffffffffffffffff831161024a576020838186019501011161024a57565b3461024a5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a576103536004356102be565b61035e6024356102be565b60643567ffffffffffffffff811161024a5761037e9036906004016102eb565b505060206040517f150b7a02000000000000000000000000000000000000000000000000000000008152f35b3461024a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5773ffffffffffffffffffffffffffffffffffffffff6004356103fa816102be565b6104026112eb565b167fffffffffffffffffffffffff00000000000000000000000000000000000000006002541617600255600080f35b3461024a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5760043560005260006020526020600160406000200154604051908152f35b3461024a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57602073ffffffffffffffffffffffffffffffffffffffff60045416604051908152f35b3461024a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461024a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5760043560243561057d816102be565b60009180835282602052610597600160408520015461157f565b8083528260205260ff6105cd83604086209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b5416156105d8578280f35b8083528260205261060c82604085209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d8480a438808280f35b3461024a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a576024356106b3816102be565b3373ffffffffffffffffffffffffffffffffffffffff8216036106dc57610019906004356116e3565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152fd5b9181601f8401121561024a5782359167ffffffffffffffff831161024a576020808501948460051b01011161024a57565b6101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5767ffffffffffffffff60243581811161024a576107de60049136908301610760565b60449291923584811161024a576107f89036908401610760565b60649291923586811161024a5761081290369086016102eb565b60849291923588811161024a5761082c9036908801610760565b9160a4358a811161024a576108449036908a01610760565b95909460c4358c811161024a5761085e9036908c01610760565b99909860e4359d8e1161024a5761087b8c6100199f369101610760565b9d909c35611b08565b3461024a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57602073ffffffffffffffffffffffffffffffffffffffff60035416604051908152f35b3461024a5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57600435610911816102be565b60243561091d816102be565b604435906109296114b3565b8173ffffffffffffffffffffffffffffffffffffffff809416937f0000000000000000000000000000000000000000000000000000000000000000168414600014610a1e57506000809350828193927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff839414610a16575b5af16109ab61230d565b50156109b357005b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5472616e73666572206661696c656400000000000000000000000000000000006044820152606490fd5b0390fd5b4791506109a1565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14610adb575b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602481019190915290602090829081600081604481015b03925af18015610ad657610aaf57005b6100199060203d8111610acf575b610ac78183610ed7565b810190612220565b503d610abd565b61245b565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529150602082602481865afa928315610ad657610a9f93602093600091610b32575b5092509250610a45565b610b529150843d8111610b58575b610b4a8183610ed7565b810190613031565b38610b28565b503d610b40565b3461024a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57602073ffffffffffffffffffffffffffffffffffffffff60025416604051908152f35b3461024a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57602060ff610c27602435610bf3816102be565b6004356000526000845260406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54166040519015158152f35b60c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57610c656102dc565b67ffffffffffffffff9060443582811161024a57610c87903690600401610760565b60649291923584811161024a57610ca2903690600401610760565b60849291923586811161024a57610cbd903690600401610760565b93909260a43597881161024a57610cdb610019983690600401610760565b979096600435611d96565b3461024a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5773ffffffffffffffffffffffffffffffffffffffff600435610d36816102be565b610d3e6112eb565b167fffffffffffffffffffffffff00000000000000000000000000000000000000006004541617600455600080f35b3461024a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5760206040517f61c92169ef077349011ff0b1383c894d86c5f0b41d986366b58a6cf31e93beda8152f35b3461024a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57602060405160008152f35b3461024a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5773ffffffffffffffffffffffffffffffffffffffff600435610e50816102be565b610e586112eb565b167fffffffffffffffffffffffff00000000000000000000000000000000000000006003541617600355600080f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff821117610ed257604052565b610e87565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610ed257604052565b67ffffffffffffffff8111610ed257601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b929192610f5e82610f18565b91610f6c6040519384610ed7565b82948184528183011161024a578281602093846000960137010152565b3461024a5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57600435610fc4816102be565b60443567ffffffffffffffff811161024a573660238201121561024a57610ff5903690602481600401359101610f52565b61106073ffffffffffffffffffffffffffffffffffffffff806002541633149081156110ba575b81156110ac575b506040519061103182610eb6565b600182527f35000000000000000000000000000000000000000000000000000000000000006020830152611aae565b6002600154146110825761107c91600260015560243590613422565b60018055005b60046040517f37ed32e8000000000000000000000000000000000000000000000000000000008152fd5b905060045416331438611023565b8091506003541633149061101c565b3461024a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5761001960243560043561110a826102be565b80600052600060205261112460016040600020015461157f565b6116e3565b67ffffffffffffffff8111610ed25760051b60200190565b8015150361024a57565b81601f8201121561024a5780359161116283611129565b926111706040519485610ed7565b808452602092838086019260051b82010192831161024a578301905b82821061119a575050505090565b83809183356111a881611141565b81520191019061118c565b3461024a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5767ffffffffffffffff60043581811161024a573660238201121561024a57806004013561120e81611129565b9161121c6040519384610ed7565b81835260209160248385019160051b8301019136831161024a57602401905b828210611264576024358587821161024a5761125e61001992369060040161114b565b906119c4565b8380918335611272816102be565b81520191019061123b565b3461024a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5773ffffffffffffffffffffffffffffffffffffffff6004356112cd816102be565b166000526007602052602060ff604060002054166040519015158152f35b3360009081527f637999432676374d4ea036a5e1ac845bfb5900b653d4393f12108092e01503ce60205260409020547f61c92169ef077349011ff0b1383c894d86c5f0b41d986366b58a6cf31e93beda9060ff16156113475750565b61135033611927565b61135861180e565b91603061136484611869565b53607861137084611876565b5360415b6001811161146057610a12604861142e856114028861139388156118c2565b6040519485937f416363657373436f6e74726f6c3a206163636f756e742000000000000000000060208601526113d3815180926020603789019101611652565b84017f206973206d697373696e6720726f6c652000000000000000000000000000000060378201520190611675565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610ed7565b6040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352600483016116cf565b90600f81169060108210156114ae577f30313233343536373839616263646566000000000000000000000000000000006114a9921a61149f8487611886565b5360041c91611897565b611374565b61183a565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16156114ec57565b6114f533611927565b60009061150061180e565b91603061150c84611869565b53607861151884611876565b5360415b6001811161153b57610a12604861142e856114028861139388156118c2565b90600f81169060108210156114ae577f303132333435363738396162636465660000000000000000000000000000000061157a921a61149f8487611886565b61151c565b80600052600060205260ff6115b83360406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b5416156115c25750565b6115cb33611927565b6115d361180e565b9160306115df84611869565b5360786115eb84611876565b5360415b6001811161160e57610a12604861142e856114028861139388156118c2565b90600f81169060108210156114ae577f303132333435363738396162636465660000000000000000000000000000000061164d921a61149f8487611886565b6115ef565b60005b8381106116655750506000910152565b8181015183820152602001611655565b9061168860209282815194859201611652565b0190565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936116c881518092818752878088019101611652565b0116010190565b9060206116e092818152019061168c565b90565b6000908082528160205260ff61171c84604085209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b541661172757505050565b8082528160205261175b83604084209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541690557ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b73ffffffffffffffffffffffffffffffffffffffff3394169280a4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b90600182018092116117fc57565b6117bf565b919082018092116117fc57565b604051906080820182811067ffffffffffffffff821117610ed257604052604282526060366020840137565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8051156114ae5760200190565b8051600110156114ae5760210190565b9081518110156114ae570160200190565b80156117fc577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b156118c957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152fd5b604051906060820182811067ffffffffffffffff821117610ed257604052602a82526040366020840137603061195c83611869565b53607861196883611876565b536029905b60018211611980576116e09150156118c2565b600f81169060108210156114ae577f30313233343536373839616263646566000000000000000000000000000000006119be921a61149f8486611886565b9061196d565b6119cc6112eb565b80519182151580611a6b575b6119ea906119e4611a75565b90611aae565b600090815b8481106119fd575050505050565b80611a0a60019284611af4565b51151573ffffffffffffffffffffffffffffffffffffffff611a2c8388611af4565b511685526007602052604085209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008354169116179055016119ef565b50805183146119d8565b60405190611a8282610eb6565b600182527f31000000000000000000000000000000000000000000000000000000000000006020830152565b15611ab65750565b610a12906040519182917f08c379a000000000000000000000000000000000000000000000000000000000835260206004840152602483019061168c565b80518210156114ae5760209160051b010190565b9e9d9c9b9a99989796959294939160026001541461108257939291906002600155611b3c611b34611a75565b838714611aae565b60009485965b818810611c035750505050611ba29350611b7160055473ffffffffffffffffffffffffffffffffffffffff1690565b9073ffffffffffffffffffffffffffffffffffffffff8216611be5575b505050611b99611d24565b90341015611aae565b60005b868110611bc25750611bb998993390611f08565b6102e960018055565b80611bdf6003611bd56001948b8b611ca4565b35106119e4611d5d565b01611ba5565b611bfb92611bf4913691610f52565b9033612523565b388080611b8e565b909192939495611c3d600191611c37611c25611c208c888a611ca4565b611cb4565b611c308c8a88611ca4565b359061215a565b90611801565b97611c7f611c6b3373ffffffffffffffffffffffffffffffffffffffff166000526006602052604060002090565b611c79611c2084888a611ca4565b90611cd6565b0196959493929190611b42565b90156114ae5790565b90600110156114ae5760200190565b91908110156114ae5760051b0190565b356116e0816102be565b80548210156114ae5760005260206000200190600090565b805468010000000000000000811015610ed257611cf891600182018155611cbe565b819291549060031b9173ffffffffffffffffffffffffffffffffffffffff809116831b921b1916179055565b60405190611d3182610eb6565b600182527f32000000000000000000000000000000000000000000000000000000000000006020830152565b60405190611d6a82610eb6565b600182527f34000000000000000000000000000000000000000000000000000000000000006020830152565b906102e9999897969594939291611de4604051611db281610eb6565b600181527f36000000000000000000000000000000000000000000000000000000000000006020820152303314611aae565b611f08565b60405190611df682610eb6565b600182527f33000000000000000000000000000000000000000000000000000000000000006020830152565b90156114ae578035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561024a57019081359167ffffffffffffffff831161024a57602001823603811361024a579190565b91908110156114ae5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561024a57019081359167ffffffffffffffff831161024a57602001823603811361024a579190565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116117fc57565b98939692909795949181151580612151575b80612148575b8061213f575b611f32906119e4611de9565b6001828103611fc45750611f9c611faa95611f957fbcf6a68a2f901be4a23a41b53acd7697893a7e34def4e28acba584da75283b679c9a96611f8e611faf9b97611f88611fbf9f9c98611c2090611fa399611c8c565b99611c8c565b3595611c8c565b3594611e22565b3691610f52565b9285612915565b612d72565b6040519081529081906020820190565b0390a1565b97926120198a89898786612013611f9c829f9d8d9f9d61200c906120058c8f859f81611ff9611c20611fff94611c2094611c8c565b9a611c95565b98611c8c565b3597611c8c565b3596611e22565b94612684565b885b83811061205a57505050505050505050507fbcf6a68a2f901be4a23a41b53acd7697893a7e34def4e28acba584da75283b6791611faf611fbf92612d72565b80888c8989898f968f908a8a8d9361207185611edb565b84146120eb57926120df926120d8826120e59c6120d182611f9c976120cb611c208c6120bb8f9e8f611c20886120aa92611c2094611ca4565b9f6120b488611edb565b9084611ca4565b9e6120c5866117ee565b91611ca4565b9c611ca4565b359a611ca4565b3598611e7b565b95612a3c565b0161201b565b9161212d8461213a9b612126828096612120611c208a612116611c208f9e6121349f611f9c9f611ca4565b9d6120c586611edb565b9b611ca4565b3599611ca4565b3597611e7b565b946127ed565b6120e5565b50848414611f26565b50848314611f20565b50828214611f1a565b60009073ffffffffffffffffffffffffffffffffffffffff908116907f00000000000000000000000000000000000000000000000000000000000000001681036121a357505090565b6040517f23b872dd000000000000000000000000000000000000000000000000000000006020820152336024820152306044820152606481019390935290916116e09161221b82608481015b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101845283610ed7565b612235565b9081602091031261024a57516116e081611141565b61228b9173ffffffffffffffffffffffffffffffffffffffff6040519261225b84610eb6565b602084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656460208501521661233d565b80519081612297575050565b6020806122a8938301019101612220565b156122af57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5361666545524332303a206f7065726174696f6e206661696c656400000000006044820152fd5b3d15612338573d9061231e82610f18565b9161232c6040519384610ed7565b82523d6000602084013e565b606090565b803f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708114159081612403575b50156123d95781600092918360208194519301915af19061238961230d565b9115612393575090565b8151156123a35750805190602001fd5b610a12906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352600483016116cf565b60046040517f304619b5000000000000000000000000000000000000000000000000000000008152fd5b905015153861236a565b6040519061241a82610eb6565b600182527f37000000000000000000000000000000000000000000000000000000000000006020830152565b9081602091031261024a57516116e0816102be565b6040513d6000823e3d90fd5b9060606116e0926000815260006020820152816040820152019061168c565b60609073ffffffffffffffffffffffffffffffffffffffff6116e0949360008352166020820152816040820152019061168c565b60609073ffffffffffffffffffffffffffffffffffffffff6116e0949316815260006020820152816040820152019061168c565b6060916116e0949373ffffffffffffffffffffffffffffffffffffffff8092168352166020820152816040820152019061168c565b919061256461255c6125558373ffffffffffffffffffffffffffffffffffffffff166000526007602052604060002090565b5460ff1690565b6119e461240d565b6000916040517f6af563e900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff906020816004818588165afa908115610ad6576126079591612656575b501661261a57612601611402916040519283917f09c5eabe000000000000000000000000000000000000000000000000000000006020840152602483016116cf565b90612b9c565b8051612611575050565b6102e991612cae565b612601611402916040519283917ff5542f2d00000000000000000000000000000000000000000000000000000000602084015260248301612467565b612677915060203d811161267d575b61266f8183610ed7565b810190612446565b386125bf565b503d612665565b949092916126b861255c6125558673ffffffffffffffffffffffffffffffffffffffff166000526007602052604060002090565b6000604051907f6af563e900000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff91602081600481868b165afa918215610ad657916127cf575b501661278d5750612752611402916040519283917f09c5eabe000000000000000000000000000000000000000000000000000000006020840152602483016116cf565b915b6060936001810361276a57506126079350612b68565b60029192501461277c575b5050612607565b6127869250612b9c565b3880612775565b6127c9906114026040519384927ff5542f2d00000000000000000000000000000000000000000000000000000000602085015260248401612486565b91612754565b6127e7915060203d811161267d5761266f8183610ed7565b3861270f565b9490929161282161255c6125558673ffffffffffffffffffffffffffffffffffffffff166000526007602052604060002090565b6000604051907f6af563e900000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff91602081600481868b165afa918215610ad657916128f7575b50166128bb5750612752611402916040519283917f09c5eabe000000000000000000000000000000000000000000000000000000006020840152602483016116cf565b6127c9906114026040519384927ff5542f2d000000000000000000000000000000000000000000000000000000006020850152602484016124ba565b61290f915060203d811161267d5761266f8183610ed7565b38612878565b9391909161294961255c6125558573ffffffffffffffffffffffffffffffffffffffff166000526007602052604060002090565b6000604051907f6af563e900000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff91602081600481868a165afa918215610ad65791612a1e575b50166129e257612752611402916040519283917f09c5eabe000000000000000000000000000000000000000000000000000000006020840152602483016116cf565b6127c9611402916040519283917ff5542f2d00000000000000000000000000000000000000000000000000000000602084015260248301612467565b612a36915060203d811161267d5761266f8183610ed7565b386129a0565b959193929093612a7261255c6125558773ffffffffffffffffffffffffffffffffffffffff166000526007602052604060002090565b6000604051907f6af563e900000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff91602081600481868c165afa918215610ad65791612b4a575b5016612b0d575050612752611402916040519283917f09c5eabe000000000000000000000000000000000000000000000000000000006020840152602483016116cf565b6114026127c992936040519485937ff5542f2d000000000000000000000000000000000000000000000000000000006020860152602485016124ee565b612b62915060203d811161267d5761266f8183610ed7565b38612ac9565b916000928392602083519301915af1903d916020604051938085528060008387013e84010160405215612b9757565b503d90fd5b3073ffffffffffffffffffffffffffffffffffffffff821614612be857816000929160208493519201905af4903d916020604051938085528060008387013e84010160405215612b9757565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64656c656761746563616c6c20746f2073656c660000000000000000000000006044820152fd5b81601f8201121561024a57805191612c5d83611129565b92612c6b6040519485610ed7565b808452602092838086019260051b82010192831161024a578301905b828210612c95575050505090565b8380918351612ca3816102be565b815201910190612c87565b91909182518301602093848183031261024a57848101519167ffffffffffffffff831161024a57612ce59286809201920101612c46565b92600090815b8551811015612d3557600190612d2f73ffffffffffffffffffffffffffffffffffffffff8087168652600685526040862090612d27848b611af4565b511690611cd6565b01612ceb565b505050509050565b80549060009081815582612d5057505050565b815260208120918201915b828110612d6757505050565b818155600101612d5b565b73ffffffffffffffffffffffffffffffffffffffff811660005260069060209082825260406000205460005b818110612dce57505073ffffffffffffffffffffffffffffffffffffffff16600052526102e96040600020612d3d565b60019073ffffffffffffffffffffffffffffffffffffffff841660005285855273ffffffffffffffffffffffffffffffffffffffff612e11826040600020611cbe565b90549060031b1c16612e233082613040565b73ffffffffffffffffffffffffffffffffffffffff861680151590612ece575b80612ec5575b612e56575b505001612d9e565b857f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168314612ea457612e9d926130eb565b3880612e4e565b612ec09250600080809381935af1612eba61230d565b50612eee565b612e9d565b50801515612e49565b503073ffffffffffffffffffffffffffffffffffffffff87161415612e43565b15612ef557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e61746976652073656e64206661696c000000000000000000000000000000006044820152fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831461301f575b829073ffffffffffffffffffffffffffffffffffffffff908184168015159081613014575b508061300b575b612fb3575b5050505090565b8116907f0000000000000000000000000000000000000000000000000000000000000000168114612ff15791612fe8926130eb565b38818180612fac565b50600080808093613006955af1612eba61230d565b612fe8565b50821515612fa7565b905030141538612fa0565b915061302b3083613040565b91612f7b565b9081602091031261024a575190565b73ffffffffffffffffffffffffffffffffffffffff908116907f0000000000000000000000000000000000000000000000000000000000000000811682036130885750503190565b60246020929360405194859384927f70a082310000000000000000000000000000000000000000000000000000000084521660048301525afa908115610ad6576000916130d3575090565b6116e0915060203d8111610b5857610b4a8183610ed7565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000602082015273ffffffffffffffffffffffffffffffffffffffff909216602483015260448201929092526102e99161221b82606481016121ef565b51906102e9826102be565b81601f8201121561024a5780519161316c83611129565b9261317a6040519485610ed7565b808452602092838086019260051b82010192831161024a578301905b8282106131a4575050505090565b81518152908301908301613196565b9080601f8301121561024a578151916131cb83611129565b926040906131db82519586610ed7565b808552602093848087019260051b8501019381851161024a57858101925b85841061320a575050505050505090565b835167ffffffffffffffff811161024a5782019083603f8301121561024a57878201519061323782610f18565b61324388519182610ed7565b8281528588848601011161024a576132648a949385948a8685019101611652565b8152019301926131f9565b91909160c08184031261024a5780519261328b6020830161314a565b9260408301519067ffffffffffffffff9182811161024a57836132af918601612c46565b93606081015183811161024a57846132c8918301613155565b93608082015184811161024a57816132e1918401613155565b9360a083015190811161024a576116e092016131b3565b90815180825260208080930193019160005b828110613318575050505090565b83518552938101939281019260010161330a565b90815180825260208092019182818360051b85019501936000915b8483106133575750505050505090565b909192939495848061337183856001950387528a5161168c565b9801930193019194939290613347565b949291909695939660c0860190865273ffffffffffffffffffffffffffffffffffffffff9182602091168188015260c0604088015283518092528060e088019401926000905b838210613409575050505050906133ed826116e09697866133fb950360608801526132f8565b9084820360808601526132f8565b9160a081840391015261332c565b84518116865294820194938201936001909101906133c7565b61344b73ffffffffffffffffffffffffffffffffffffffff92936020808251830101910161326f565b979492969093169560005b84518110156134e857600261346b8287611af4565b511161347957600101613456565b50505050507fb69677b2a82170abd46dbc9853e73529a3ac021a6e65e7c02f89cdf3b3d063c79350806134b0611fbf928585612f53565b506040519384938460409194939294606082019573ffffffffffffffffffffffffffffffffffffffff80921683521660208201520152565b5061352e906114026000969987966040519586948c60208701997f963276f3000000000000000000000000000000000000000000000000000000008b5260248801613381565b519082305af161353c61230d565b501561356c575050507fc2623b31705c3a17d595c59e4c160723c6c140a0a0cbea051392e781b741575d600080a1565b611fbf836134b07fb69677b2a82170abd46dbc9853e73529a3ac021a6e65e7c02f89cdf3b3d063c7958585612f5356fea26469706673582212202db9a97959341231f02c86e9171c308452b692da53e6bcc02c20cef15c9c8b2b64736f6c634300081200332f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1000000000000000000000000ef300fb4243a0ff3b90c8ccfa1264d78182adaa4000000000000000000000000ca94d8c245601b152c904f42fe788b4125f5b46b0000000000000000000000000fa205c0446cd9eedcc7538c9e24bc55ad08207f000000000000000000000000b4504778dbb8ea95e01fd72a0b3d028e941c378f
Deployed Bytecode
0x6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c806301ffc9a71461018b57806311b0b42d14610186578063150b7a021461018157806318137a411461017c578063248a9ca314610177578063285f94a0146101725780632cebdeb21461016d5780632f2ff15d1461016857806336568abe14610163578063383536901461015e5780636cec044b1461015957806375ea1c92146101545780637fe689171461014f57806391d148541461014a578063963276f3146101455780639e99ec3914610140578063a2011b3f1461013b578063a217fddf14610136578063c5962f2614610131578063d00a2d5f1461012c578063d547741f14610127578063dfd7cb06146101225763f6f38e7c0361000e5761127d565b6111b3565b6110c9565b610f89565b610e00565b610dc6565b610d6d565b610ce6565b610c33565b610bb1565b610b5f565b6108d6565b610884565b610791565b610678565b61053f565b6104d0565b61047e565b610431565b6103aa565b610319565b61024f565b3461024a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361024a57807f7965db0b0000000000000000000000000000000000000000000000000000000060209214908115610220575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501438610215565b600080fd5b3461024a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57602060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee168152f35b73ffffffffffffffffffffffffffffffffffffffff81160361024a57565b602435906102e9826102be565b565b9181601f8401121561024a5782359167ffffffffffffffff831161024a576020838186019501011161024a57565b3461024a5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a576103536004356102be565b61035e6024356102be565b60643567ffffffffffffffff811161024a5761037e9036906004016102eb565b505060206040517f150b7a02000000000000000000000000000000000000000000000000000000008152f35b3461024a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5773ffffffffffffffffffffffffffffffffffffffff6004356103fa816102be565b6104026112eb565b167fffffffffffffffffffffffff00000000000000000000000000000000000000006002541617600255600080f35b3461024a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5760043560005260006020526020600160406000200154604051908152f35b3461024a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57602073ffffffffffffffffffffffffffffffffffffffff60045416604051908152f35b3461024a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57602060405173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1168152f35b3461024a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5760043560243561057d816102be565b60009180835282602052610597600160408520015461157f565b8083528260205260ff6105cd83604086209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b5416156105d8578280f35b8083528260205261060c82604085209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d8480a438808280f35b3461024a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a576024356106b3816102be565b3373ffffffffffffffffffffffffffffffffffffffff8216036106dc57610019906004356116e3565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152fd5b9181601f8401121561024a5782359167ffffffffffffffff831161024a576020808501948460051b01011161024a57565b6101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5767ffffffffffffffff60243581811161024a576107de60049136908301610760565b60449291923584811161024a576107f89036908401610760565b60649291923586811161024a5761081290369086016102eb565b60849291923588811161024a5761082c9036908801610760565b9160a4358a811161024a576108449036908a01610760565b95909460c4358c811161024a5761085e9036908c01610760565b99909860e4359d8e1161024a5761087b8c6100199f369101610760565b9d909c35611b08565b3461024a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57602073ffffffffffffffffffffffffffffffffffffffff60035416604051908152f35b3461024a5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57600435610911816102be565b60243561091d816102be565b604435906109296114b3565b8173ffffffffffffffffffffffffffffffffffffffff809416937f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee168414600014610a1e57506000809350828193927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff839414610a16575b5af16109ab61230d565b50156109b357005b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5472616e73666572206661696c656400000000000000000000000000000000006044820152606490fd5b0390fd5b4791506109a1565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14610adb575b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602481019190915290602090829081600081604481015b03925af18015610ad657610aaf57005b6100199060203d8111610acf575b610ac78183610ed7565b810190612220565b503d610abd565b61245b565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529150602082602481865afa928315610ad657610a9f93602093600091610b32575b5092509250610a45565b610b529150843d8111610b58575b610b4a8183610ed7565b810190613031565b38610b28565b503d610b40565b3461024a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57602073ffffffffffffffffffffffffffffffffffffffff60025416604051908152f35b3461024a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57602060ff610c27602435610bf3816102be565b6004356000526000845260406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54166040519015158152f35b60c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57610c656102dc565b67ffffffffffffffff9060443582811161024a57610c87903690600401610760565b60649291923584811161024a57610ca2903690600401610760565b60849291923586811161024a57610cbd903690600401610760565b93909260a43597881161024a57610cdb610019983690600401610760565b979096600435611d96565b3461024a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5773ffffffffffffffffffffffffffffffffffffffff600435610d36816102be565b610d3e6112eb565b167fffffffffffffffffffffffff00000000000000000000000000000000000000006004541617600455600080f35b3461024a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5760206040517f61c92169ef077349011ff0b1383c894d86c5f0b41d986366b58a6cf31e93beda8152f35b3461024a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57602060405160008152f35b3461024a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5773ffffffffffffffffffffffffffffffffffffffff600435610e50816102be565b610e586112eb565b167fffffffffffffffffffffffff00000000000000000000000000000000000000006003541617600355600080f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff821117610ed257604052565b610e87565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610ed257604052565b67ffffffffffffffff8111610ed257601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b929192610f5e82610f18565b91610f6c6040519384610ed7565b82948184528183011161024a578281602093846000960137010152565b3461024a5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a57600435610fc4816102be565b60443567ffffffffffffffff811161024a573660238201121561024a57610ff5903690602481600401359101610f52565b61106073ffffffffffffffffffffffffffffffffffffffff806002541633149081156110ba575b81156110ac575b506040519061103182610eb6565b600182527f35000000000000000000000000000000000000000000000000000000000000006020830152611aae565b6002600154146110825761107c91600260015560243590613422565b60018055005b60046040517f37ed32e8000000000000000000000000000000000000000000000000000000008152fd5b905060045416331438611023565b8091506003541633149061101c565b3461024a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5761001960243560043561110a826102be565b80600052600060205261112460016040600020015461157f565b6116e3565b67ffffffffffffffff8111610ed25760051b60200190565b8015150361024a57565b81601f8201121561024a5780359161116283611129565b926111706040519485610ed7565b808452602092838086019260051b82010192831161024a578301905b82821061119a575050505090565b83809183356111a881611141565b81520191019061118c565b3461024a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5767ffffffffffffffff60043581811161024a573660238201121561024a57806004013561120e81611129565b9161121c6040519384610ed7565b81835260209160248385019160051b8301019136831161024a57602401905b828210611264576024358587821161024a5761125e61001992369060040161114b565b906119c4565b8380918335611272816102be565b81520191019061123b565b3461024a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024a5773ffffffffffffffffffffffffffffffffffffffff6004356112cd816102be565b166000526007602052602060ff604060002054166040519015158152f35b3360009081527f637999432676374d4ea036a5e1ac845bfb5900b653d4393f12108092e01503ce60205260409020547f61c92169ef077349011ff0b1383c894d86c5f0b41d986366b58a6cf31e93beda9060ff16156113475750565b61135033611927565b61135861180e565b91603061136484611869565b53607861137084611876565b5360415b6001811161146057610a12604861142e856114028861139388156118c2565b6040519485937f416363657373436f6e74726f6c3a206163636f756e742000000000000000000060208601526113d3815180926020603789019101611652565b84017f206973206d697373696e6720726f6c652000000000000000000000000000000060378201520190611675565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610ed7565b6040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352600483016116cf565b90600f81169060108210156114ae577f30313233343536373839616263646566000000000000000000000000000000006114a9921a61149f8487611886565b5360041c91611897565b611374565b61183a565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16156114ec57565b6114f533611927565b60009061150061180e565b91603061150c84611869565b53607861151884611876565b5360415b6001811161153b57610a12604861142e856114028861139388156118c2565b90600f81169060108210156114ae577f303132333435363738396162636465660000000000000000000000000000000061157a921a61149f8487611886565b61151c565b80600052600060205260ff6115b83360406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b5416156115c25750565b6115cb33611927565b6115d361180e565b9160306115df84611869565b5360786115eb84611876565b5360415b6001811161160e57610a12604861142e856114028861139388156118c2565b90600f81169060108210156114ae577f303132333435363738396162636465660000000000000000000000000000000061164d921a61149f8487611886565b6115ef565b60005b8381106116655750506000910152565b8181015183820152602001611655565b9061168860209282815194859201611652565b0190565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936116c881518092818752878088019101611652565b0116010190565b9060206116e092818152019061168c565b90565b6000908082528160205260ff61171c84604085209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b541661172757505050565b8082528160205261175b83604084209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541690557ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b73ffffffffffffffffffffffffffffffffffffffff3394169280a4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b90600182018092116117fc57565b6117bf565b919082018092116117fc57565b604051906080820182811067ffffffffffffffff821117610ed257604052604282526060366020840137565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8051156114ae5760200190565b8051600110156114ae5760210190565b9081518110156114ae570160200190565b80156117fc577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b156118c957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152fd5b604051906060820182811067ffffffffffffffff821117610ed257604052602a82526040366020840137603061195c83611869565b53607861196883611876565b536029905b60018211611980576116e09150156118c2565b600f81169060108210156114ae577f30313233343536373839616263646566000000000000000000000000000000006119be921a61149f8486611886565b9061196d565b6119cc6112eb565b80519182151580611a6b575b6119ea906119e4611a75565b90611aae565b600090815b8481106119fd575050505050565b80611a0a60019284611af4565b51151573ffffffffffffffffffffffffffffffffffffffff611a2c8388611af4565b511685526007602052604085209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008354169116179055016119ef565b50805183146119d8565b60405190611a8282610eb6565b600182527f31000000000000000000000000000000000000000000000000000000000000006020830152565b15611ab65750565b610a12906040519182917f08c379a000000000000000000000000000000000000000000000000000000000835260206004840152602483019061168c565b80518210156114ae5760209160051b010190565b9e9d9c9b9a99989796959294939160026001541461108257939291906002600155611b3c611b34611a75565b838714611aae565b60009485965b818810611c035750505050611ba29350611b7160055473ffffffffffffffffffffffffffffffffffffffff1690565b9073ffffffffffffffffffffffffffffffffffffffff8216611be5575b505050611b99611d24565b90341015611aae565b60005b868110611bc25750611bb998993390611f08565b6102e960018055565b80611bdf6003611bd56001948b8b611ca4565b35106119e4611d5d565b01611ba5565b611bfb92611bf4913691610f52565b9033612523565b388080611b8e565b909192939495611c3d600191611c37611c25611c208c888a611ca4565b611cb4565b611c308c8a88611ca4565b359061215a565b90611801565b97611c7f611c6b3373ffffffffffffffffffffffffffffffffffffffff166000526006602052604060002090565b611c79611c2084888a611ca4565b90611cd6565b0196959493929190611b42565b90156114ae5790565b90600110156114ae5760200190565b91908110156114ae5760051b0190565b356116e0816102be565b80548210156114ae5760005260206000200190600090565b805468010000000000000000811015610ed257611cf891600182018155611cbe565b819291549060031b9173ffffffffffffffffffffffffffffffffffffffff809116831b921b1916179055565b60405190611d3182610eb6565b600182527f32000000000000000000000000000000000000000000000000000000000000006020830152565b60405190611d6a82610eb6565b600182527f34000000000000000000000000000000000000000000000000000000000000006020830152565b906102e9999897969594939291611de4604051611db281610eb6565b600181527f36000000000000000000000000000000000000000000000000000000000000006020820152303314611aae565b611f08565b60405190611df682610eb6565b600182527f33000000000000000000000000000000000000000000000000000000000000006020830152565b90156114ae578035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561024a57019081359167ffffffffffffffff831161024a57602001823603811361024a579190565b91908110156114ae5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561024a57019081359167ffffffffffffffff831161024a57602001823603811361024a579190565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116117fc57565b98939692909795949181151580612151575b80612148575b8061213f575b611f32906119e4611de9565b6001828103611fc45750611f9c611faa95611f957fbcf6a68a2f901be4a23a41b53acd7697893a7e34def4e28acba584da75283b679c9a96611f8e611faf9b97611f88611fbf9f9c98611c2090611fa399611c8c565b99611c8c565b3595611c8c565b3594611e22565b3691610f52565b9285612915565b612d72565b6040519081529081906020820190565b0390a1565b97926120198a89898786612013611f9c829f9d8d9f9d61200c906120058c8f859f81611ff9611c20611fff94611c2094611c8c565b9a611c95565b98611c8c565b3597611c8c565b3596611e22565b94612684565b885b83811061205a57505050505050505050507fbcf6a68a2f901be4a23a41b53acd7697893a7e34def4e28acba584da75283b6791611faf611fbf92612d72565b80888c8989898f968f908a8a8d9361207185611edb565b84146120eb57926120df926120d8826120e59c6120d182611f9c976120cb611c208c6120bb8f9e8f611c20886120aa92611c2094611ca4565b9f6120b488611edb565b9084611ca4565b9e6120c5866117ee565b91611ca4565b9c611ca4565b359a611ca4565b3598611e7b565b95612a3c565b0161201b565b9161212d8461213a9b612126828096612120611c208a612116611c208f9e6121349f611f9c9f611ca4565b9d6120c586611edb565b9b611ca4565b3599611ca4565b3597611e7b565b946127ed565b6120e5565b50848414611f26565b50848314611f20565b50828214611f1a565b60009073ffffffffffffffffffffffffffffffffffffffff908116907f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1681036121a357505090565b6040517f23b872dd000000000000000000000000000000000000000000000000000000006020820152336024820152306044820152606481019390935290916116e09161221b82608481015b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101845283610ed7565b612235565b9081602091031261024a57516116e081611141565b61228b9173ffffffffffffffffffffffffffffffffffffffff6040519261225b84610eb6565b602084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656460208501521661233d565b80519081612297575050565b6020806122a8938301019101612220565b156122af57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5361666545524332303a206f7065726174696f6e206661696c656400000000006044820152fd5b3d15612338573d9061231e82610f18565b9161232c6040519384610ed7565b82523d6000602084013e565b606090565b803f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708114159081612403575b50156123d95781600092918360208194519301915af19061238961230d565b9115612393575090565b8151156123a35750805190602001fd5b610a12906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352600483016116cf565b60046040517f304619b5000000000000000000000000000000000000000000000000000000008152fd5b905015153861236a565b6040519061241a82610eb6565b600182527f37000000000000000000000000000000000000000000000000000000000000006020830152565b9081602091031261024a57516116e0816102be565b6040513d6000823e3d90fd5b9060606116e0926000815260006020820152816040820152019061168c565b60609073ffffffffffffffffffffffffffffffffffffffff6116e0949360008352166020820152816040820152019061168c565b60609073ffffffffffffffffffffffffffffffffffffffff6116e0949316815260006020820152816040820152019061168c565b6060916116e0949373ffffffffffffffffffffffffffffffffffffffff8092168352166020820152816040820152019061168c565b919061256461255c6125558373ffffffffffffffffffffffffffffffffffffffff166000526007602052604060002090565b5460ff1690565b6119e461240d565b6000916040517f6af563e900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff906020816004818588165afa908115610ad6576126079591612656575b501661261a57612601611402916040519283917f09c5eabe000000000000000000000000000000000000000000000000000000006020840152602483016116cf565b90612b9c565b8051612611575050565b6102e991612cae565b612601611402916040519283917ff5542f2d00000000000000000000000000000000000000000000000000000000602084015260248301612467565b612677915060203d811161267d575b61266f8183610ed7565b810190612446565b386125bf565b503d612665565b949092916126b861255c6125558673ffffffffffffffffffffffffffffffffffffffff166000526007602052604060002090565b6000604051907f6af563e900000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff91602081600481868b165afa918215610ad657916127cf575b501661278d5750612752611402916040519283917f09c5eabe000000000000000000000000000000000000000000000000000000006020840152602483016116cf565b915b6060936001810361276a57506126079350612b68565b60029192501461277c575b5050612607565b6127869250612b9c565b3880612775565b6127c9906114026040519384927ff5542f2d00000000000000000000000000000000000000000000000000000000602085015260248401612486565b91612754565b6127e7915060203d811161267d5761266f8183610ed7565b3861270f565b9490929161282161255c6125558673ffffffffffffffffffffffffffffffffffffffff166000526007602052604060002090565b6000604051907f6af563e900000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff91602081600481868b165afa918215610ad657916128f7575b50166128bb5750612752611402916040519283917f09c5eabe000000000000000000000000000000000000000000000000000000006020840152602483016116cf565b6127c9906114026040519384927ff5542f2d000000000000000000000000000000000000000000000000000000006020850152602484016124ba565b61290f915060203d811161267d5761266f8183610ed7565b38612878565b9391909161294961255c6125558573ffffffffffffffffffffffffffffffffffffffff166000526007602052604060002090565b6000604051907f6af563e900000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff91602081600481868a165afa918215610ad65791612a1e575b50166129e257612752611402916040519283917f09c5eabe000000000000000000000000000000000000000000000000000000006020840152602483016116cf565b6127c9611402916040519283917ff5542f2d00000000000000000000000000000000000000000000000000000000602084015260248301612467565b612a36915060203d811161267d5761266f8183610ed7565b386129a0565b959193929093612a7261255c6125558773ffffffffffffffffffffffffffffffffffffffff166000526007602052604060002090565b6000604051907f6af563e900000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff91602081600481868c165afa918215610ad65791612b4a575b5016612b0d575050612752611402916040519283917f09c5eabe000000000000000000000000000000000000000000000000000000006020840152602483016116cf565b6114026127c992936040519485937ff5542f2d000000000000000000000000000000000000000000000000000000006020860152602485016124ee565b612b62915060203d811161267d5761266f8183610ed7565b38612ac9565b916000928392602083519301915af1903d916020604051938085528060008387013e84010160405215612b9757565b503d90fd5b3073ffffffffffffffffffffffffffffffffffffffff821614612be857816000929160208493519201905af4903d916020604051938085528060008387013e84010160405215612b9757565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64656c656761746563616c6c20746f2073656c660000000000000000000000006044820152fd5b81601f8201121561024a57805191612c5d83611129565b92612c6b6040519485610ed7565b808452602092838086019260051b82010192831161024a578301905b828210612c95575050505090565b8380918351612ca3816102be565b815201910190612c87565b91909182518301602093848183031261024a57848101519167ffffffffffffffff831161024a57612ce59286809201920101612c46565b92600090815b8551811015612d3557600190612d2f73ffffffffffffffffffffffffffffffffffffffff8087168652600685526040862090612d27848b611af4565b511690611cd6565b01612ceb565b505050509050565b80549060009081815582612d5057505050565b815260208120918201915b828110612d6757505050565b818155600101612d5b565b73ffffffffffffffffffffffffffffffffffffffff811660005260069060209082825260406000205460005b818110612dce57505073ffffffffffffffffffffffffffffffffffffffff16600052526102e96040600020612d3d565b60019073ffffffffffffffffffffffffffffffffffffffff841660005285855273ffffffffffffffffffffffffffffffffffffffff612e11826040600020611cbe565b90549060031b1c16612e233082613040565b73ffffffffffffffffffffffffffffffffffffffff861680151590612ece575b80612ec5575b612e56575b505001612d9e565b857f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff168314612ea457612e9d926130eb565b3880612e4e565b612ec09250600080809381935af1612eba61230d565b50612eee565b612e9d565b50801515612e49565b503073ffffffffffffffffffffffffffffffffffffffff87161415612e43565b15612ef557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e61746976652073656e64206661696c000000000000000000000000000000006044820152fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831461301f575b829073ffffffffffffffffffffffffffffffffffffffff908184168015159081613014575b508061300b575b612fb3575b5050505090565b8116907f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee168114612ff15791612fe8926130eb565b38818180612fac565b50600080808093613006955af1612eba61230d565b612fe8565b50821515612fa7565b905030141538612fa0565b915061302b3083613040565b91612f7b565b9081602091031261024a575190565b73ffffffffffffffffffffffffffffffffffffffff908116907f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811682036130885750503190565b60246020929360405194859384927f70a082310000000000000000000000000000000000000000000000000000000084521660048301525afa908115610ad6576000916130d3575090565b6116e0915060203d8111610b5857610b4a8183610ed7565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000602082015273ffffffffffffffffffffffffffffffffffffffff909216602483015260448201929092526102e99161221b82606481016121ef565b51906102e9826102be565b81601f8201121561024a5780519161316c83611129565b9261317a6040519485610ed7565b808452602092838086019260051b82010192831161024a578301905b8282106131a4575050505090565b81518152908301908301613196565b9080601f8301121561024a578151916131cb83611129565b926040906131db82519586610ed7565b808552602093848087019260051b8501019381851161024a57858101925b85841061320a575050505050505090565b835167ffffffffffffffff811161024a5782019083603f8301121561024a57878201519061323782610f18565b61324388519182610ed7565b8281528588848601011161024a576132648a949385948a8685019101611652565b8152019301926131f9565b91909160c08184031261024a5780519261328b6020830161314a565b9260408301519067ffffffffffffffff9182811161024a57836132af918601612c46565b93606081015183811161024a57846132c8918301613155565b93608082015184811161024a57816132e1918401613155565b9360a083015190811161024a576116e092016131b3565b90815180825260208080930193019160005b828110613318575050505090565b83518552938101939281019260010161330a565b90815180825260208092019182818360051b85019501936000915b8483106133575750505050505090565b909192939495848061337183856001950387528a5161168c565b9801930193019194939290613347565b949291909695939660c0860190865273ffffffffffffffffffffffffffffffffffffffff9182602091168188015260c0604088015283518092528060e088019401926000905b838210613409575050505050906133ed826116e09697866133fb950360608801526132f8565b9084820360808601526132f8565b9160a081840391015261332c565b84518116865294820194938201936001909101906133c7565b61344b73ffffffffffffffffffffffffffffffffffffffff92936020808251830101910161326f565b979492969093169560005b84518110156134e857600261346b8287611af4565b511161347957600101613456565b50505050507fb69677b2a82170abd46dbc9853e73529a3ac021a6e65e7c02f89cdf3b3d063c79350806134b0611fbf928585612f53565b506040519384938460409194939294606082019573ffffffffffffffffffffffffffffffffffffffff80921683521660208201520152565b5061352e906114026000969987966040519586948c60208701997f963276f3000000000000000000000000000000000000000000000000000000008b5260248801613381565b519082305af161353c61230d565b501561356c575050507fc2623b31705c3a17d595c59e4c160723c6c140a0a0cbea051392e781b741575d600080a1565b611fbf836134b07fb69677b2a82170abd46dbc9853e73529a3ac021a6e65e7c02f89cdf3b3d063c7958585612f5356fea26469706673582212202db9a97959341231f02c86e9171c308452b692da53e6bcc02c20cef15c9c8b2b64736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1000000000000000000000000ef300fb4243a0ff3b90c8ccfa1264d78182adaa4000000000000000000000000ca94d8c245601b152c904f42fe788b4125f5b46b0000000000000000000000000fa205c0446cd9eedcc7538c9e24bc55ad08207f000000000000000000000000b4504778dbb8ea95e01fd72a0b3d028e941c378f
-----Decoded View---------------
Arg [0] : __native (address): 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
Arg [1] : __wnative (address): 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1
Arg [2] : __assetForwarder (address): 0xEF300Fb4243a0Ff3b90C8cCfa1264D78182AdaA4
Arg [3] : __dexspan (address): 0xCA94d8C245601B152C904f42fE788B4125f5b46B
Arg [4] : __assetBridge (address): 0x0Fa205c0446cD9EeDCc7538c9E24BC55AD08207f
Arg [5] : __feeAdapter (address): 0xB4504778dBb8eA95e01FD72a0B3d028E941C378f
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
Arg [1] : 00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1
Arg [2] : 000000000000000000000000ef300fb4243a0ff3b90c8ccfa1264d78182adaa4
Arg [3] : 000000000000000000000000ca94d8c245601b152c904f42fe788b4125f5b46b
Arg [4] : 0000000000000000000000000fa205c0446cd9eedcc7538c9e24bc55ad08207f
Arg [5] : 000000000000000000000000b4504778dbb8ea95e01fd72a0b3d028e941c378f
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.