More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 107 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Bridge Token Cci... | 21447688 | 41 days ago | IN | 0.00014688 ETH | 0.00156848 | ||||
Bridge Token Cci... | 21446806 | 41 days ago | IN | 0.0001561 ETH | 0.00199234 | ||||
Bridge Token Cci... | 21301961 | 61 days ago | IN | 0.00016937 ETH | 0.00350338 | ||||
Bridge Token Cci... | 21171430 | 80 days ago | IN | 0.00015843 ETH | 0.00460996 | ||||
Bridge Token Cci... | 20942101 | 112 days ago | IN | 0.00021083 ETH | 0.00203929 | ||||
Bridge Token Cci... | 20270559 | 205 days ago | IN | 0.00016891 ETH | 0.0011027 | ||||
Bridge Token Cci... | 20270533 | 205 days ago | IN | 0.00016891 ETH | 0.00105579 | ||||
Bridge Token Cci... | 19913032 | 255 days ago | IN | 0.00018578 ETH | 0.00220596 | ||||
Bridge Token Cci... | 19902458 | 257 days ago | IN | 0.00017224 ETH | 0.00085671 | ||||
Bridge Token Cci... | 19884858 | 259 days ago | IN | 0.00021368 ETH | 0.00115378 | ||||
Bridge Token Cci... | 19842092 | 265 days ago | IN | 0.00022521 ETH | 0.00132894 | ||||
Bridge Token Cci... | 19841543 | 265 days ago | IN | 0.00024466 ETH | 0.00178026 | ||||
Bridge Token Cci... | 19837244 | 266 days ago | IN | 0.00027557 ETH | 0.00097785 | ||||
Bridge Token Cci... | 19831399 | 267 days ago | IN | 0.00020974 ETH | 0.00089237 | ||||
Bridge Token Cci... | 19831271 | 267 days ago | IN | 0.00027007 ETH | 0.00103215 | ||||
Bridge Token Cci... | 19831148 | 267 days ago | IN | 0.00027007 ETH | 0.00085848 | ||||
Bridge Token Cci... | 19812600 | 269 days ago | IN | 0.00021837 ETH | 0.00158444 | ||||
Bridge Token Cci... | 19811479 | 270 days ago | IN | 0.00023788 ETH | 0.00165906 | ||||
Bridge Token Cci... | 19806742 | 270 days ago | IN | 0.00019548 ETH | 0.00091437 | ||||
Bridge Token Cci... | 19785744 | 273 days ago | IN | 0.00021054 ETH | 0.00107054 | ||||
Bridge Token Cci... | 19780387 | 274 days ago | IN | 0.00018897 ETH | 0.00112554 | ||||
Bridge Token Cci... | 19772142 | 275 days ago | IN | 0.00020447 ETH | 0.00148337 | ||||
Bridge Token Cci... | 19771482 | 275 days ago | IN | 0.00018777 ETH | 0.00109168 | ||||
Bridge Token Cci... | 19761096 | 277 days ago | IN | 0.00019056 ETH | 0.00229612 | ||||
Bridge Token Cci... | 19758578 | 277 days ago | IN | 0.0001833 ETH | 0.00086099 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
21447688 | 41 days ago | 0.00014688 ETH | ||||
21446806 | 41 days ago | 0.0001561 ETH | ||||
21301961 | 61 days ago | 0.00016937 ETH | ||||
21171430 | 80 days ago | 0.00015843 ETH | ||||
20942101 | 112 days ago | 0.00021083 ETH | ||||
20270559 | 205 days ago | 0.00016891 ETH | ||||
20270533 | 205 days ago | 0.00016891 ETH | ||||
19913032 | 255 days ago | 0.00018578 ETH | ||||
19902458 | 257 days ago | 0.00017224 ETH | ||||
19884858 | 259 days ago | 0.00021368 ETH | ||||
19842092 | 265 days ago | 0.00022521 ETH | ||||
19841543 | 265 days ago | 0.00024466 ETH | ||||
19837244 | 266 days ago | 0.00027557 ETH | ||||
19831399 | 267 days ago | 0.00020974 ETH | ||||
19831271 | 267 days ago | 0.00027007 ETH | ||||
19831148 | 267 days ago | 0.00027007 ETH | ||||
19812600 | 269 days ago | 0.00021837 ETH | ||||
19811479 | 270 days ago | 0.00023788 ETH | ||||
19806742 | 270 days ago | 0.00019548 ETH | ||||
19785744 | 273 days ago | 0.00021054 ETH | ||||
19780387 | 274 days ago | 0.00018897 ETH | ||||
19772142 | 275 days ago | 0.00020447 ETH | ||||
19771482 | 275 days ago | 0.00018777 ETH | ||||
19761096 | 277 days ago | 0.00019056 ETH | ||||
19758578 | 277 days ago | 0.0001833 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
MainNetworkBridgeGatewayHybrid
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import {AccessControlEnumerable} from "@openzeppelin/contracts/access/extensions/AccessControlEnumerable.sol"; import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol"; import {CCIPClient} from "../../ccip/CCIPClient.sol"; import {ServiceFeeable} from "../../service_feeable/ServiceFeeable.sol"; contract MainNetworkBridgeGatewayHybrid is AccessControlEnumerable, ServiceFeeable, CCIPClient, ReentrancyGuard { bytes32 public constant BRIDGE_AUTOMATOR = keccak256("BRIDGE_AUTOMATOR"); bool ccipBridgingEnabled; bool customBridgingEnabled; IERC20 public token; event BridgeCustom(address indexed sender, address indexed recipient, uint64 indexed chainId, uint256 amount); event UnbridgeCustom(address indexed recipient, uint64 indexed chainId, uint256 amount); event BridgeCcip(address indexed sender, address indexed recipient, uint64 indexed chainId, uint256 amount); event UnbridgeCcip(address indexed recipient, uint64 indexed chainId, uint256 amount); error CcipBridgingDisabled(); error CustomBridgingDisabled(); modifier ccipEnabled() { if(!ccipBridgingEnabled) { revert CcipBridgingDisabled(); } _; } modifier customEnabled() { if(!customBridgingEnabled) { revert CustomBridgingDisabled(); } _; } constructor( address _tokenAddress, address _ccipRouter, address _serviceFeeRecipient, uint256 _serviceFee, uint256 _minServiceAmount ) CCIPClient(_ccipRouter, address(0)) ServiceFeeable(_serviceFeeRecipient, _serviceFee, _minServiceAmount) { token = IERC20(_tokenAddress); ccipBridgingEnabled = false; customBridgingEnabled = false; _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); } // #### ADMINISTRATION #### function supportsInterface(bytes4 interfaceId) public pure virtual override(AccessControlEnumerable, CCIPClient) returns (bool) { return CCIPClient.supportsInterface(interfaceId); } function setCcipBridgingEnabled(bool status) external onlyRole(DEFAULT_ADMIN_ROLE) { ccipBridgingEnabled = status; } function setCustomBridgingEnabled(bool status) external onlyRole(DEFAULT_ADMIN_ROLE) { customBridgingEnabled = status; } // #### CUSTOM BRIDGING #### function bridgeTokenCustom( address recipient, uint256 amount, uint64 targetNetwork ) external payable onlySupportedNetwork(targetNetwork) customEnabled gteMinAmount(amount) collectsServiceFee nonReentrant { token.transferFrom(msg.sender, address(this), amount); emit BridgeCustom(msg.sender, recipient, targetNetwork, amount); } function unbridgeTokenCustom( uint64 sourceNetwork, address recipient, uint256 amount ) external onlyRole(BRIDGE_AUTOMATOR) onlySupportedNetwork(sourceNetwork) { token.transfer(recipient, amount); emit UnbridgeCustom(recipient, sourceNetwork, amount); } // #### CCIP BRIDGING #### /** * request CCIP messaging fee for bridging */ function estimateCcipFee(uint64 targetNetwork) external view onlySupportedNetwork(targetNetwork) returns (uint256) { bytes memory dummyMessage = abi.encode(address(0), uint256(0)); return CCIPClient.estimateMessageFee(uint64(targetNetwork), dummyMessage); } /** * Bridge the specified token amount to a supported target network. */ function bridgeTokenCcip( address recipient, uint256 amount, uint64 targetNetwork ) external payable onlySupportedNetwork(targetNetwork) ccipEnabled nonReentrant { token.transferFrom(msg.sender, address(this), amount); emit BridgeCcip(msg.sender, recipient, targetNetwork, amount); CCIPClient.sendCcipMessage(targetNetwork, ccipNetworkToPartnerContract[targetNetwork], abi.encode(recipient, amount)); } /** * Handle receiving ccip message with an unbridging/unwrapping request and release the locked tokens to the recipient. */ function _ccipReceive(Client.Any2EVMMessage memory ccipMessage) internal override onlySupportedNetwork(ccipMessage.sourceChainSelector) { // check if sender is the correct partner contract of the corresponding source network address ccipSender = abi.decode(ccipMessage.sender, (address)); if(ccipSender != ccipNetworkToPartnerContract[ccipMessage.sourceChainSelector]) { revert IncorrectPartnerContract(ccipMessage.sourceChainSelector, ccipNetworkToPartnerContract[ccipMessage.sourceChainSelector], ccipSender); } // decode message content (address recipient, uint256 amount) = abi.decode(ccipMessage.data, (address, uint256)); // unbridge token token.transfer(recipient, amount); emit UnbridgeCcip(recipient, ccipMessage.sourceChainSelector, amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Client} from "../libraries/Client.sol"; /// @notice Application contracts that intend to receive messages from /// the router should implement this interface. interface IAny2EVMMessageReceiver { /// @notice Called by the Router to deliver a message. /// If this reverts, any token transfers also revert. The message /// will move to a FAILED state and become available for manual execution. /// @param message CCIP Message /// @dev Note ensure you check the msg.sender is the OffRampRouter function ccipReceive(Client.Any2EVMMessage calldata message) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Client} from "../libraries/Client.sol"; interface IRouterClient { error UnsupportedDestinationChain(uint64 destChainSelector); error InsufficientFeeTokenAmount(); error InvalidMsgValue(); /// @notice Checks if the given chain ID is supported for sending/receiving. /// @param chainSelector The chain to check. /// @return supported is true if it is supported, false if not. function isChainSupported(uint64 chainSelector) external view returns (bool supported); /// @notice Gets a list of all supported tokens which can be sent or received /// to/from a given chain id. /// @param chainSelector The chainSelector. /// @return tokens The addresses of all tokens that are supported. function getSupportedTokens(uint64 chainSelector) external view returns (address[] memory tokens); /// @param destinationChainSelector The destination chainSelector /// @param message The cross-chain CCIP message including data and/or tokens /// @return fee returns guaranteed execution fee for the specified message /// delivery to destination chain /// @dev returns 0 fee on invalid message. function getFee( uint64 destinationChainSelector, Client.EVM2AnyMessage memory message ) external view returns (uint256 fee); /// @notice Request a message to be sent to the destination chain /// @param destinationChainSelector The destination chain ID /// @param message The cross-chain CCIP message including data and/or tokens /// @return messageId The message ID /// @dev Note if msg.value is larger than the required fee (from getFee) we accept /// the overpayment with no refund. function ccipSend( uint64 destinationChainSelector, Client.EVM2AnyMessage calldata message ) external payable returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // End consumer library. library Client { struct EVMTokenAmount { address token; // token address on the local chain. uint256 amount; // Amount of tokens. } struct Any2EVMMessage { bytes32 messageId; // MessageId corresponding to ccipSend on source. uint64 sourceChainSelector; // Source chain selector. bytes sender; // abi.decode(sender) if coming from an EVM chain. bytes data; // payload sent in original message. EVMTokenAmount[] destTokenAmounts; // Tokens and their amounts in their destination chain representation. } // If extraArgs is empty bytes, the default is 200k gas limit and strict = false. struct EVM2AnyMessage { bytes receiver; // abi.encode(receiver address) for dest EVM chains bytes data; // Data payload EVMTokenAmount[] tokenAmounts; // Token transfers address feeToken; // Address of feeToken. address(0) means you will send msg.value. bytes extraArgs; // Populate this with _argsToBytes(EVMExtraArgsV1) } // extraArgs will evolve to support new features // bytes4(keccak256("CCIP EVMExtraArgsV1")); bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9; struct EVMExtraArgsV1 { uint256 gasLimit; // ATTENTION!!! MAX GAS LIMIT 4M FOR BETA TESTING bool strict; // See strict sequencing details below. } function _argsToBytes(EVMExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) { return abi.encodeWithSelector(EVM_EXTRA_ARGS_V1_TAG, extraArgs); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol) pragma solidity ^0.8.20; import {IAccessControl} from "./IAccessControl.sol"; import {Context} from "../utils/Context.sol"; import {ERC165} from "../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 account => bool) hasRole; bytes32 adminRole; } mapping(bytes32 role => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with an {AccessControlUnauthorizedAccount} error including the required role. */ 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 returns (bool) { return _roles[role].hasRole[account]; } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` * is missing `role`. */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert AccessControlUnauthorizedAccount(account, role); } } /** * @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 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 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 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 `callerConfirmation`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address callerConfirmation) public virtual { if (callerConfirmation != _msgSender()) { revert AccessControlBadConfirmation(); } _revokeRole(role, callerConfirmation); } /** * @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 Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual returns (bool) { if (!hasRole(role, account)) { _roles[role].hasRole[account] = true; emit RoleGranted(role, account, _msgSender()); return true; } else { return false; } } /** * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { if (hasRole(role, account)) { _roles[role].hasRole[account] = false; emit RoleRevoked(role, account, _msgSender()); return true; } else { return false; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol) pragma solidity ^0.8.20; import {IAccessControlEnumerable} from "./IAccessControlEnumerable.sol"; import {AccessControl} from "../AccessControl.sol"; import {EnumerableSet} from "../../utils/structs/EnumerableSet.sol"; /** * @dev Extension of {AccessControl} that allows enumerating the members of each role. */ abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { using EnumerableSet for EnumerableSet.AddressSet; mapping(bytes32 role => EnumerableSet.AddressSet) private _roleMembers; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) { return _roleMembers[role].at(index); } /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) { return _roleMembers[role].length(); } /** * @dev Overload {AccessControl-_grantRole} to track enumerable memberships */ function _grantRole(bytes32 role, address account) internal virtual override returns (bool) { bool granted = super._grantRole(role, account); if (granted) { _roleMembers[role].add(account); } return granted; } /** * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships */ function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) { bool revoked = super._revokeRole(role, account); if (revoked) { _roleMembers[role].remove(account); } return revoked; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol) pragma solidity ^0.8.20; import {IAccessControl} from "../IAccessControl.sol"; /** * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. */ interface IAccessControlEnumerable is IAccessControl { /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) external view returns (address); /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @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. */ 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 `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./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); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @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 v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ 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; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); 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 making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be NOT_ENTERED if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail _status = ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.20; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position is the index of the value in the `values` array plus 1. // Position 0 is used to mean a value is not in the set. mapping(bytes32 value => uint256) _positions; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._positions[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We cache the value's position to prevent multiple reads from the same storage slot uint256 position = set._positions[value]; if (position != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 valueIndex = position - 1; uint256 lastIndex = set._values.length - 1; if (valueIndex != lastIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the lastValue to the index where the value to delete is set._values[valueIndex] = lastValue; // Update the tracked position of the lastValue (that was just moved) set._positions[lastValue] = position; } // Delete the slot where the moved value was stored set._values.pop(); // Delete the tracked position for the deleted slot delete set._positions[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._positions[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {AccessControlEnumerable} from "@openzeppelin/contracts/access/extensions/AccessControlEnumerable.sol"; import {IAccessControlEnumerable} from "@openzeppelin/contracts/access/extensions/IAccessControlEnumerable.sol"; import {IAny2EVMMessageReceiver} from "@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol"; import {IRouterClient} from "@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IRouterClient.sol"; import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol"; abstract contract CCIPClient is IAny2EVMMessageReceiver, IERC165, AccessControlEnumerable { IRouterClient public ccipRouter; IERC20 public ccipFeeToken; // if fee token is address(0), fees will be payed with native coin uint256 public ccipMessageGasLimit; mapping(uint64 chainId => bool) public isSupportedCcipNetwork; // mapping of supported partner networks to which the token can be bridged mapping(uint64 chainId => address) public ccipNetworkToPartnerContract; // mapping of network to address of token on that network error CcipFeeTokenBalanceTooLow(address token, uint256 balance, uint256 requiredFee); error InvalidRouter(address routerAddress); error UnsupportedNetwork(uint64 chainId); error IncorrectPartnerContract(uint64 chainId, address expected, address actual); event CcipMessageSent(uint64 indexed targetChainSelector, bytes32 messageId); event CcipMessageReceived(uint64 indexed sourceChainSelector, bytes32 messageId); //only calls from the set router are accepted. modifier onlyRouter() { if (msg.sender != address(ccipRouter)) revert InvalidRouter(msg.sender); _; } modifier onlySupportedNetwork(uint64 chainId) { if (!isSupportedCcipNetwork[chainId]) { revert UnsupportedNetwork(chainId); } _; } constructor(address _router, address _feeToken) { ccipRouter = IRouterClient(_router); ccipFeeToken = IERC20(_feeToken); ccipMessageGasLimit = 200_000; _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); } function supportsInterface(bytes4 interfaceId) public pure virtual override(AccessControlEnumerable, IERC165) returns (bool) { return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || interfaceId == type(IERC165).interfaceId || interfaceId == type(AccessControlEnumerable).interfaceId; } // ### CCIP MESSAGING ADMINISTRATION ### function setCcipRouter(address _router) external onlyRole(DEFAULT_ADMIN_ROLE) { ccipRouter = IRouterClient(_router); } function setCcipGasLimit(uint256 _gasLimit) external onlyRole(DEFAULT_ADMIN_ROLE) { ccipMessageGasLimit = _gasLimit; } function setCcipFeeToken(address _feeToken) external onlyRole(DEFAULT_ADMIN_ROLE) { ccipFeeToken = IERC20(_feeToken); } /** * Specificy which networks have a counterpart of this bridge gateway * and thus are able to bridge the asset. */ function setSupportedNetwork( uint64 chainId, bool supported ) external onlyRole(DEFAULT_ADMIN_ROLE) { isSupportedCcipNetwork[chainId] = supported; } /** * Specificy the token address on a supported network, which is * assumed to be the receiver for any ccip messaging to that * network. */ function setSupportedNetworkReceiverAddress( uint64 chainId, address receiverAddress ) external onlySupportedNetwork(chainId) onlyRole(DEFAULT_ADMIN_ROLE) { ccipNetworkToPartnerContract[chainId] = receiverAddress; } // ### CCIP SENDER FUNCTIONALITY ### function createCcipMessage(address receiver, bytes memory message) private view returns (Client.EVM2AnyMessage memory) { Client.EVM2AnyMessage memory ccipMessage = Client.EVM2AnyMessage({ receiver: abi.encode(receiver), data: message, tokenAmounts: new Client.EVMTokenAmount[](0), // empty array indicating no tokens are being sent extraArgs: Client._argsToBytes( // Additional arguments, setting gas limit and non-strict sequencing mode Client.EVMExtraArgsV1({gasLimit: ccipMessageGasLimit, strict: false}) ), feeToken: address(ccipFeeToken) }); return ccipMessage; } function estimateMessageFee(uint64 chainSelector, bytes memory message) internal view returns (uint256) { Client.EVM2AnyMessage memory ccipMessage = createCcipMessage(address(0), message); return ccipRouter.getFee(chainSelector, ccipMessage); } function sendCcipMessage(uint64 chainSelector, address receiver, bytes memory message) internal returns (bytes32) { // Create an EVM2AnyMessage struct in memory with necessary information for sending a cross-chain message Client.EVM2AnyMessage memory ccipMessage = createCcipMessage(receiver, message); // query required fee uint256 fee = ccipRouter.getFee(chainSelector, ccipMessage); if(address(ccipFeeToken) == address(0)) { // fee payment via native coin if (fee > address(this).balance) { revert CcipFeeTokenBalanceTooLow(address(0), address(this).balance, fee); } else { // send message bytes32 messageId = ccipRouter.ccipSend{value: fee}(chainSelector, ccipMessage); emit CcipMessageSent(chainSelector, messageId); return messageId; } } else { // fee payment via erc20 token if (fee > ccipFeeToken.balanceOf(address(this))) { revert CcipFeeTokenBalanceTooLow(address(ccipFeeToken), ccipFeeToken.balanceOf(address(this)), fee); } else { ccipFeeToken.approve(address(ccipRouter), fee); // send message bytes32 messageId = ccipRouter.ccipSend(chainSelector, ccipMessage); emit CcipMessageSent(chainSelector, messageId); return messageId; } } } // ### CCIP RECEIVER FUNCTIONALITY ### function ccipReceive(Client.Any2EVMMessage calldata message) external virtual override onlyRouter { emit CcipMessageReceived(message.sourceChainSelector, message.messageId); _ccipReceive(message); } /// @notice Override this function in your implementation. function _ccipReceive(Client.Any2EVMMessage memory message) internal virtual; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {AccessControlEnumerable} from "@openzeppelin/contracts/access/extensions/AccessControlEnumerable.sol"; abstract contract ServiceFeeable is AccessControlEnumerable { address serviceFeeRecipient; // reciepient of service fees uint256 public serviceFee; // the service fee amount for triggering a service uint256 public minServiceAmount; // a minimum amount that acts as a guard to avoid service spamming error MinimumServiceAmountNotReached(uint256 actual, uint256 required); error ServiceFeeRequired(uint256 actual, uint256 required); modifier collectsServiceFee() { if (msg.value < serviceFee) { revert ServiceFeeRequired(msg.value, serviceFee); } payable(serviceFeeRecipient).transfer(msg.value); _; } modifier gteMinAmount(uint256 amount) { if (amount < minServiceAmount) { revert MinimumServiceAmountNotReached(amount, minServiceAmount); } _; } constructor (address _serviceFeeRecipient, uint256 _serviceFee, uint256 _minServiceAmount) { serviceFeeRecipient = _serviceFeeRecipient; serviceFee = _serviceFee; minServiceAmount = _minServiceAmount; _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); } /** * Set the minimum amount that is required to bridge in order to prevent * service flooding for small amounts. */ function setMinServiceAmount( uint256 amount ) external onlyRole(DEFAULT_ADMIN_ROLE) { minServiceAmount = amount; } function setServiceFeeRecipient( address recipient ) external onlyRole(DEFAULT_ADMIN_ROLE) { serviceFeeRecipient = recipient; } function setServiceFee( uint256 amount ) external onlyRole(DEFAULT_ADMIN_ROLE) { serviceFee = amount; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"address","name":"_ccipRouter","type":"address"},{"internalType":"address","name":"_serviceFeeRecipient","type":"address"},{"internalType":"uint256","name":"_serviceFee","type":"uint256"},{"internalType":"uint256","name":"_minServiceAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"CcipBridgingDisabled","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"requiredFee","type":"uint256"}],"name":"CcipFeeTokenBalanceTooLow","type":"error"},{"inputs":[],"name":"CustomBridgingDisabled","type":"error"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"address","name":"expected","type":"address"},{"internalType":"address","name":"actual","type":"address"}],"name":"IncorrectPartnerContract","type":"error"},{"inputs":[{"internalType":"address","name":"routerAddress","type":"address"}],"name":"InvalidRouter","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"MinimumServiceAmountNotReached","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"ServiceFeeRequired","type":"error"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"UnsupportedNetwork","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeCcip","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeCustom","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"messageId","type":"bytes32"}],"name":"CcipMessageReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"targetChainSelector","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"messageId","type":"bytes32"}],"name":"CcipMessageSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"UnbridgeCcip","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"UnbridgeCustom","type":"event"},{"inputs":[],"name":"BRIDGE_AUTOMATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"targetNetwork","type":"uint64"}],"name":"bridgeTokenCcip","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"targetNetwork","type":"uint64"}],"name":"bridgeTokenCustom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"ccipFeeToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ccipMessageGasLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"ccipNetworkToPartnerContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"messageId","type":"bytes32"},{"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"internalType":"bytes","name":"sender","type":"bytes"},{"internalType":"bytes","name":"data","type":"bytes"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Client.EVMTokenAmount[]","name":"destTokenAmounts","type":"tuple[]"}],"internalType":"struct Client.Any2EVMMessage","name":"message","type":"tuple"}],"name":"ccipReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ccipRouter","outputs":[{"internalType":"contract IRouterClient","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"targetNetwork","type":"uint64"}],"name":"estimateCcipFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"isSupportedCcipNetwork","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minServiceAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","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":[],"name":"serviceFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"status","type":"bool"}],"name":"setCcipBridgingEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeToken","type":"address"}],"name":"setCcipFeeToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_gasLimit","type":"uint256"}],"name":"setCcipGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_router","type":"address"}],"name":"setCcipRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"status","type":"bool"}],"name":"setCustomBridgingEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setMinServiceAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setServiceFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"setServiceFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"bool","name":"supported","type":"bool"}],"name":"setSupportedNetwork","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"address","name":"receiverAddress","type":"address"}],"name":"setSupportedNetworkReceiverAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"sourceNetwork","type":"uint64"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unbridgeTokenCustom","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b506040516200236b3803806200236b83398101604081905262000034916200025b565b600280546001600160a01b0319166001600160a01b038516179055600382905560048190558360008484846200006b8433620000f9565b5050600580546001600160a01b038087166001600160a01b0319928316179092556006805492861692909116919091179055505062030d40600755620000b3600033620000f9565b50506001600a5550600b80546001600160b01b031916620100006001600160a01b0388160261ffff1916179055620000ed600033620000f9565b505050505050620002b8565b60008062000108848462000136565b905080156200012d5760008481526001602052604090206200012b9084620001e4565b505b90505b92915050565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16620001db576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055620001923390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600162000130565b50600062000130565b60006200012d836001600160a01b0384166000818152600183016020526040812054620001db5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000130565b80516001600160a01b03811681146200025657600080fd5b919050565b600080600080600060a086880312156200027457600080fd5b6200027f866200023e565b94506200028f602087016200023e565b93506200029f604087016200023e565b6060870151608090970151959894975095949392505050565b6120a380620002c86000396000f3fe6080604052600436106101ee5760003560e01c8063626bd2831161010d57806391d14854116100a0578063b04bc9d81161006f578063b04bc9d8146105c1578063ca15c873146105d7578063d547741f146105f7578063d5ed71bc14610617578063fc0c546a1461063757600080fd5b806391d148541461053c578063937d2e5d1461055c5780639d3cd4c81461058c578063a217fddf146105ac57600080fd5b806380a4a40f116100dc57806380a4a40f146104c657806385572ffb146104e65780638abdf5aa146105065780639010d07c1461051c57600080fd5b8063626bd2831461043d57806367c210df146104505780636d1414dd14610470578063769d35d31461049057600080fd5b80632ec2a612116101855780633a1811ca116101545780633a1811ca146103a9578063481e443d146103c9578063562a7a54146103e95780635cdf76f81461041d57600080fd5b80632ec2a612146103295780632f2ff15d1461034957806336568abe14610369578063388a62fe1461038957600080fd5b8063248a9ca3116101c1578063248a9ca3146102a6578063274027e1146102d657806327bf9b44146102f65780632b9b5f181461031657600080fd5b806301ffc9a7146101f35780630de22984146102285780630e047ea61461026057806310123ddc14610284575b600080fd5b3480156101ff57600080fd5b5061021361020e3660046119f1565b61065d565b60405190151581526020015b60405180910390f35b34801561023457600080fd5b50600554610248906001600160a01b031681565b6040516001600160a01b03909116815260200161021f565b34801561026c57600080fd5b5061027660075481565b60405190815260200161021f565b34801561029057600080fd5b506102a461029f366004611a29565b61066e565b005b3480156102b257600080fd5b506102766102c1366004611a46565b60009081526020819052604090206001015490565b3480156102e257600080fd5b506102a46102f1366004611a74565b61068d565b34801561030257600080fd5b506102a4610311366004611a74565b6106bb565b6102a4610324366004611aad565b6106e9565b34801561033557600080fd5b506102a4610344366004611aeb565b6108a0565b34801561035557600080fd5b506102a4610364366004611b22565b61092c565b34801561037557600080fd5b506102a4610384366004611b22565b610951565b34801561039557600080fd5b506102a46103a4366004611a46565b610989565b3480156103b557600080fd5b506102a46103c4366004611a74565b61099a565b3480156103d557600080fd5b506102a46103e4366004611a46565b6109c8565b3480156103f557600080fd5b506102767f11f34962d73cf2abb1f455b18b9e623b91e4dc168e9ccd5765f5b567db9d5b3281565b34801561042957600080fd5b506102a4610438366004611a46565b6109d9565b6102a461044b366004611aad565b6109ea565b34801561045c57600080fd5b506102a461046b366004611b47565b610be2565b34801561047c57600080fd5b50600654610248906001600160a01b031681565b34801561049c57600080fd5b506102486104ab366004611b73565b6009602052600090815260409020546001600160a01b031681565b3480156104d257600080fd5b506102766104e1366004611b73565b610c19565b3480156104f257600080fd5b506102a4610501366004611b8e565b610c93565b34801561051257600080fd5b5061027660035481565b34801561052857600080fd5b50610248610537366004611bc8565b610d2a565b34801561054857600080fd5b50610213610557366004611b22565b610d49565b34801561056857600080fd5b50610213610577366004611b73565b60086020526000908152604090205460ff1681565b34801561059857600080fd5b506102a46105a7366004611bea565b610d72565b3480156105b857600080fd5b50610276600081565b3480156105cd57600080fd5b5061027660045481565b3480156105e357600080fd5b506102766105f2366004611a46565b610eb5565b34801561060357600080fd5b506102a4610612366004611b22565b610ecc565b34801561062357600080fd5b506102a4610632366004611a29565b610ef1565b34801561064357600080fd5b50600b54610248906201000090046001600160a01b031681565b600061066882610f17565b92915050565b600061067981610f68565b50600b805460ff1916911515919091179055565b600061069881610f68565b50600280546001600160a01b0319166001600160a01b0392909216919091179055565b60006106c681610f68565b50600580546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160401b038116600090815260086020526040902054819060ff166107345760405163900d29db60e01b81526001600160401b03821660048201526024015b60405180910390fd5b600b5460ff166107575760405163449b1e0560e01b815260040160405180910390fd5b61075f610f72565b600b546040516323b872dd60e01b815233600482015230602482015260448101859052620100009091046001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107df9190611c29565b50816001600160401b0316846001600160a01b0316336001600160a01b03167f02bce4780eb34df717d5d40a3fa6c9f128938b3a0aa4c6bd382fd2a579974d1e8660405161082f91815260200190565b60405180910390a46001600160401b0382166000908152600960209081526040918290205482516001600160a01b038881169382019390935292830186905261088f92859290911690606001604051602081830303815290604052610f9c565b5061089a6001600a55565b50505050565b6001600160401b038216600090815260086020526040902054829060ff166108e65760405163900d29db60e01b81526001600160401b038216600482015260240161072b565b60006108f181610f68565b50506001600160401b0391909116600090815260096020526040902080546001600160a01b0319166001600160a01b03909216919091179055565b60008281526020819052604090206001015461094781610f68565b61089a838361132f565b6001600160a01b038116331461097a5760405163334bd91960e11b815260040160405180910390fd5b6109848282611364565b505050565b600061099481610f68565b50600455565b60006109a581610f68565b50600680546001600160a01b0319166001600160a01b0392909216919091179055565b60006109d381610f68565b50600755565b60006109e481610f68565b50600355565b6001600160401b038116600090815260086020526040902054819060ff16610a305760405163900d29db60e01b81526001600160401b038216600482015260240161072b565b600b54610100900460ff16610a5857604051631b7def5360e01b815260040160405180910390fd5b82600454811015610a8757600480546040516315f9724f60e11b8152918201839052602482015260440161072b565b600354341015610ab75760035460405163028a4b4760e41b8152346004820152602481019190915260440161072b565b6002546040516001600160a01b03909116903480156108fc02916000818181858888f19350505050158015610af0573d6000803e3d6000fd5b50610af9610f72565b600b546040516323b872dd60e01b815233600482015230602482015260448101869052620100009091046001600160a01b0316906323b872dd906064016020604051808303816000875af1158015610b55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b799190611c29565b50826001600160401b0316856001600160a01b0316336001600160a01b03167f06f05b76452c95072eef5574f395bd492c98b74e3887ea6af620ace7702afbc787604051610bc991815260200190565b60405180910390a4610bdb6001600a55565b5050505050565b6000610bed81610f68565b506001600160401b03919091166000908152600860205260409020805460ff1916911515919091179055565b6001600160401b038116600090815260086020526040812054829060ff16610c5f5760405163900d29db60e01b81526001600160401b038216600482015260240161072b565b60408051600060208201819052818301528151808203830181526060909101909152610c8b8482611391565b949350505050565b6005546001600160a01b03163314610cc0576040516335fdcccd60e21b815233600482015260240161072b565b610cd06040820160208301611b73565b6001600160401b03167ff73c9844657a686f2ee76b0b0d0a68248c35db7964b89e167b8b6ec8eb7b0db18260000135604051610d0e91815260200190565b60405180910390a2610d27610d2282611df1565b611413565b50565b6000828152600160205260408120610d4290836115e7565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b7f11f34962d73cf2abb1f455b18b9e623b91e4dc168e9ccd5765f5b567db9d5b32610d9c81610f68565b6001600160401b038416600090815260086020526040902054849060ff16610de25760405163900d29db60e01b81526001600160401b038216600482015260240161072b565b600b5460405163a9059cbb60e01b81526001600160a01b03868116600483015260248201869052620100009092049091169063a9059cbb906044016020604051808303816000875af1158015610e3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e609190611c29565b50846001600160401b0316846001600160a01b03167f25497b32c71ad1d4c74c17c7cbe5d107e530962a6955fc9143a344457a9955e585604051610ea691815260200190565b60405180910390a35050505050565b6000818152600160205260408120610668906115f3565b600082815260208190526040902060010154610ee781610f68565b61089a8383611364565b6000610efc81610f68565b50600b80549115156101000261ff0019909216919091179055565b60006001600160e01b031982166385572ffb60e01b1480610f4857506001600160e01b031982166301ffc9a760e01b145b8061066857506001600160e01b03198216630b7f5a3560e31b1492915050565b610d2781336115fd565b6002600a5403610f9557604051633ee5aeb560e01b815260040160405180910390fd5b6002600a55565b600080610fa9848461163a565b6005546040516320487ded60e01b81529192506000916001600160a01b03909116906320487ded90610fe19089908690600401611ee3565b602060405180830381865afa158015610ffe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110229190611fbc565b6006549091506001600160a01b031661112d5747811115611066576040516309585ebd60e41b8152600060048201524760248201526044810182905260640161072b565b6005546040516396f4e9f960e01b81526000916001600160a01b0316906396f4e9f990849061109b908b908890600401611ee3565b60206040518083038185885af11580156110b9573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906110de9190611fbc565b9050866001600160401b03167f85d86ea9e5ad05d3e8b2e36b9eeacb7009a413889b842f7c5ce4ba5eb7ae1bcc8260405161111b91815260200190565b60405180910390a29250610d42915050565b6006546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611175573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111999190611fbc565b81111561123f576006546040516370a0823160e01b81523060048201526001600160a01b039091169081906370a0823190602401602060405180830381865afa1580156111ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120e9190611fbc565b6040516309585ebd60e41b81526001600160a01b03909216600483015260248201526044810182905260640161072b565b60065460055460405163095ea7b360e01b81526001600160a01b0391821660048201526024810184905291169063095ea7b3906044016020604051808303816000875af1158015611294573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b89190611c29565b506005546040516396f4e9f960e01b81526000916001600160a01b0316906396f4e9f9906112ec908a908790600401611ee3565b6020604051808303816000875af115801561130b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110de9190611fbc565b60008061133c8484611766565b90508015610d4257600084815260016020526040902061135c90846117f8565b509392505050565b600080611371848461180d565b90508015610d4257600084815260016020526040902061135c9084611878565b60008061139f60008461163a565b6005546040516320487ded60e01b81529192506001600160a01b0316906320487ded906113d29087908590600401611ee3565b602060405180830381865afa1580156113ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8b9190611fbc565b6020808201516001600160401b0381166000908152600890925260409091205460ff1661145e5760405163900d29db60e01b81526001600160401b038216600482015260240161072b565b600082604001518060200190518101906114789190611fd5565b6020808501516001600160401b03166000908152600990915260409020549091506001600160a01b038083169116146114ff576020838101516001600160401b0316600081815260099092526040918290205491516307c22cd360e41b815260048101919091526001600160a01b039182166024820152908216604482015260640161072b565b600080846060015180602001905181019061151a9190611ff2565b600b5460405163a9059cbb60e01b81526001600160a01b038085166004830152602482018490529395509193506201000090049091169063a9059cbb906044016020604051808303816000875af1158015611579573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159d9190611c29565b5084602001516001600160401b0316826001600160a01b03167f15675fd7e3a643c9323adc305c813839c80f0eca329a7402536f617a3ecd1ca083604051610ea691815260200190565b6000610d42838361188d565b6000610668825490565b6116078282610d49565b6116365760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440161072b565b5050565b6116756040518060a0016040528060608152602001606081526020016060815260200160006001600160a01b03168152602001606081525090565b6040805160a0810182526001600160a01b03851660c0808301919091528251808303909101815260e082018352815260208082018590528251600080825291810184529092820190836116ea565b60408051808201909152600080825260208201528152602001906001900390816116c35790505b5081526006546001600160a01b031660208083019190915260408051808201825260075480825260009184019182528251602481019190915290511515604480830191909152825180830390910181526064909101825291820180516001600160e01b03166397a657c960e01b17905290910152949350505050565b60006117728383610d49565b6117f0576000838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556117a83390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610668565b506000610668565b6000610d42836001600160a01b0384166118b7565b60006118198383610d49565b156117f0576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610668565b6000610d42836001600160a01b0384166118fe565b60008260000182815481106118a4576118a4612020565b9060005260206000200154905092915050565b60008181526001830160205260408120546117f057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610668565b600081815260018301602052604081205480156119e7576000611922600183612036565b855490915060009061193690600190612036565b905080821461199b57600086600001828154811061195657611956612020565b906000526020600020015490508087600001848154811061197957611979612020565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806119ac576119ac612057565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610668565b6000915050610668565b600060208284031215611a0357600080fd5b81356001600160e01b031981168114610d4257600080fd5b8015158114610d2757600080fd5b600060208284031215611a3b57600080fd5b8135610d4281611a1b565b600060208284031215611a5857600080fd5b5035919050565b6001600160a01b0381168114610d2757600080fd5b600060208284031215611a8657600080fd5b8135610d4281611a5f565b80356001600160401b0381168114611aa857600080fd5b919050565b600080600060608486031215611ac257600080fd5b8335611acd81611a5f565b925060208401359150611ae260408501611a91565b90509250925092565b60008060408385031215611afe57600080fd5b611b0783611a91565b91506020830135611b1781611a5f565b809150509250929050565b60008060408385031215611b3557600080fd5b823591506020830135611b1781611a5f565b60008060408385031215611b5a57600080fd5b611b6383611a91565b91506020830135611b1781611a1b565b600060208284031215611b8557600080fd5b610d4282611a91565b600060208284031215611ba057600080fd5b81356001600160401b03811115611bb657600080fd5b820160a08185031215610d4257600080fd5b60008060408385031215611bdb57600080fd5b50508035926020909101359150565b600080600060608486031215611bff57600080fd5b611c0884611a91565b92506020840135611c1881611a5f565b929592945050506040919091013590565b600060208284031215611c3b57600080fd5b8151610d4281611a1b565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715611c7e57611c7e611c46565b60405290565b60405160a081016001600160401b0381118282101715611c7e57611c7e611c46565b604051601f8201601f191681016001600160401b0381118282101715611cce57611cce611c46565b604052919050565b600082601f830112611ce757600080fd5b81356001600160401b03811115611d0057611d00611c46565b611d13601f8201601f1916602001611ca6565b818152846020838601011115611d2857600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112611d5657600080fd5b813560206001600160401b03821115611d7157611d71611c46565b611d7f818360051b01611ca6565b82815260069290921b84018101918181019086841115611d9e57600080fd5b8286015b84811015611de65760408189031215611dbb5760008081fd5b611dc3611c5c565b8135611dce81611a5f565b81528185013585820152835291830191604001611da2565b509695505050505050565b600060a08236031215611e0357600080fd5b611e0b611c84565b82358152611e1b60208401611a91565b602082015260408301356001600160401b0380821115611e3a57600080fd5b611e4636838701611cd6565b60408401526060850135915080821115611e5f57600080fd5b611e6b36838701611cd6565b60608401526080850135915080821115611e8457600080fd5b50611e9136828601611d45565b60808301525092915050565b6000815180845260005b81811015611ec357602081850181015186830182015201611ea7565b506000602082860101526020601f19601f83011685010191505092915050565b600060406001600160401b038516835260208181850152845160a083860152611f0f60e0860182611e9d565b905081860151603f1980878403016060880152611f2c8383611e9d565b88860151888203830160808a01528051808352908601945060009350908501905b80841015611f7f57845180516001600160a01b0316835286015186830152938501936001939093019290860190611f4d565b5060608901516001600160a01b031660a08901526080890151888203830160c08a01529550611fae8187611e9d565b9a9950505050505050505050565b600060208284031215611fce57600080fd5b5051919050565b600060208284031215611fe757600080fd5b8151610d4281611a5f565b6000806040838503121561200557600080fd5b825161201081611a5f565b6020939093015192949293505050565b634e487b7160e01b600052603260045260246000fd5b8181038181111561066857634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fdfea26469706673582212204e8f3ed574a28b6c1be8d4366a9d4881f22830e5662cf4c90c47ceaea732fcf864736f6c634300081400330000000000000000000000009132a1598b277555d8029b59f638c48b9194a34200000000000000000000000080226fc0ee2b096224eeac085bb9a8cba1146f7d000000000000000000000000c86338c95eec3d022ec9d166788bcbed7599a1410000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000de0b6b3a7640000
Deployed Bytecode
0x6080604052600436106101ee5760003560e01c8063626bd2831161010d57806391d14854116100a0578063b04bc9d81161006f578063b04bc9d8146105c1578063ca15c873146105d7578063d547741f146105f7578063d5ed71bc14610617578063fc0c546a1461063757600080fd5b806391d148541461053c578063937d2e5d1461055c5780639d3cd4c81461058c578063a217fddf146105ac57600080fd5b806380a4a40f116100dc57806380a4a40f146104c657806385572ffb146104e65780638abdf5aa146105065780639010d07c1461051c57600080fd5b8063626bd2831461043d57806367c210df146104505780636d1414dd14610470578063769d35d31461049057600080fd5b80632ec2a612116101855780633a1811ca116101545780633a1811ca146103a9578063481e443d146103c9578063562a7a54146103e95780635cdf76f81461041d57600080fd5b80632ec2a612146103295780632f2ff15d1461034957806336568abe14610369578063388a62fe1461038957600080fd5b8063248a9ca3116101c1578063248a9ca3146102a6578063274027e1146102d657806327bf9b44146102f65780632b9b5f181461031657600080fd5b806301ffc9a7146101f35780630de22984146102285780630e047ea61461026057806310123ddc14610284575b600080fd5b3480156101ff57600080fd5b5061021361020e3660046119f1565b61065d565b60405190151581526020015b60405180910390f35b34801561023457600080fd5b50600554610248906001600160a01b031681565b6040516001600160a01b03909116815260200161021f565b34801561026c57600080fd5b5061027660075481565b60405190815260200161021f565b34801561029057600080fd5b506102a461029f366004611a29565b61066e565b005b3480156102b257600080fd5b506102766102c1366004611a46565b60009081526020819052604090206001015490565b3480156102e257600080fd5b506102a46102f1366004611a74565b61068d565b34801561030257600080fd5b506102a4610311366004611a74565b6106bb565b6102a4610324366004611aad565b6106e9565b34801561033557600080fd5b506102a4610344366004611aeb565b6108a0565b34801561035557600080fd5b506102a4610364366004611b22565b61092c565b34801561037557600080fd5b506102a4610384366004611b22565b610951565b34801561039557600080fd5b506102a46103a4366004611a46565b610989565b3480156103b557600080fd5b506102a46103c4366004611a74565b61099a565b3480156103d557600080fd5b506102a46103e4366004611a46565b6109c8565b3480156103f557600080fd5b506102767f11f34962d73cf2abb1f455b18b9e623b91e4dc168e9ccd5765f5b567db9d5b3281565b34801561042957600080fd5b506102a4610438366004611a46565b6109d9565b6102a461044b366004611aad565b6109ea565b34801561045c57600080fd5b506102a461046b366004611b47565b610be2565b34801561047c57600080fd5b50600654610248906001600160a01b031681565b34801561049c57600080fd5b506102486104ab366004611b73565b6009602052600090815260409020546001600160a01b031681565b3480156104d257600080fd5b506102766104e1366004611b73565b610c19565b3480156104f257600080fd5b506102a4610501366004611b8e565b610c93565b34801561051257600080fd5b5061027660035481565b34801561052857600080fd5b50610248610537366004611bc8565b610d2a565b34801561054857600080fd5b50610213610557366004611b22565b610d49565b34801561056857600080fd5b50610213610577366004611b73565b60086020526000908152604090205460ff1681565b34801561059857600080fd5b506102a46105a7366004611bea565b610d72565b3480156105b857600080fd5b50610276600081565b3480156105cd57600080fd5b5061027660045481565b3480156105e357600080fd5b506102766105f2366004611a46565b610eb5565b34801561060357600080fd5b506102a4610612366004611b22565b610ecc565b34801561062357600080fd5b506102a4610632366004611a29565b610ef1565b34801561064357600080fd5b50600b54610248906201000090046001600160a01b031681565b600061066882610f17565b92915050565b600061067981610f68565b50600b805460ff1916911515919091179055565b600061069881610f68565b50600280546001600160a01b0319166001600160a01b0392909216919091179055565b60006106c681610f68565b50600580546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160401b038116600090815260086020526040902054819060ff166107345760405163900d29db60e01b81526001600160401b03821660048201526024015b60405180910390fd5b600b5460ff166107575760405163449b1e0560e01b815260040160405180910390fd5b61075f610f72565b600b546040516323b872dd60e01b815233600482015230602482015260448101859052620100009091046001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107df9190611c29565b50816001600160401b0316846001600160a01b0316336001600160a01b03167f02bce4780eb34df717d5d40a3fa6c9f128938b3a0aa4c6bd382fd2a579974d1e8660405161082f91815260200190565b60405180910390a46001600160401b0382166000908152600960209081526040918290205482516001600160a01b038881169382019390935292830186905261088f92859290911690606001604051602081830303815290604052610f9c565b5061089a6001600a55565b50505050565b6001600160401b038216600090815260086020526040902054829060ff166108e65760405163900d29db60e01b81526001600160401b038216600482015260240161072b565b60006108f181610f68565b50506001600160401b0391909116600090815260096020526040902080546001600160a01b0319166001600160a01b03909216919091179055565b60008281526020819052604090206001015461094781610f68565b61089a838361132f565b6001600160a01b038116331461097a5760405163334bd91960e11b815260040160405180910390fd5b6109848282611364565b505050565b600061099481610f68565b50600455565b60006109a581610f68565b50600680546001600160a01b0319166001600160a01b0392909216919091179055565b60006109d381610f68565b50600755565b60006109e481610f68565b50600355565b6001600160401b038116600090815260086020526040902054819060ff16610a305760405163900d29db60e01b81526001600160401b038216600482015260240161072b565b600b54610100900460ff16610a5857604051631b7def5360e01b815260040160405180910390fd5b82600454811015610a8757600480546040516315f9724f60e11b8152918201839052602482015260440161072b565b600354341015610ab75760035460405163028a4b4760e41b8152346004820152602481019190915260440161072b565b6002546040516001600160a01b03909116903480156108fc02916000818181858888f19350505050158015610af0573d6000803e3d6000fd5b50610af9610f72565b600b546040516323b872dd60e01b815233600482015230602482015260448101869052620100009091046001600160a01b0316906323b872dd906064016020604051808303816000875af1158015610b55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b799190611c29565b50826001600160401b0316856001600160a01b0316336001600160a01b03167f06f05b76452c95072eef5574f395bd492c98b74e3887ea6af620ace7702afbc787604051610bc991815260200190565b60405180910390a4610bdb6001600a55565b5050505050565b6000610bed81610f68565b506001600160401b03919091166000908152600860205260409020805460ff1916911515919091179055565b6001600160401b038116600090815260086020526040812054829060ff16610c5f5760405163900d29db60e01b81526001600160401b038216600482015260240161072b565b60408051600060208201819052818301528151808203830181526060909101909152610c8b8482611391565b949350505050565b6005546001600160a01b03163314610cc0576040516335fdcccd60e21b815233600482015260240161072b565b610cd06040820160208301611b73565b6001600160401b03167ff73c9844657a686f2ee76b0b0d0a68248c35db7964b89e167b8b6ec8eb7b0db18260000135604051610d0e91815260200190565b60405180910390a2610d27610d2282611df1565b611413565b50565b6000828152600160205260408120610d4290836115e7565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b7f11f34962d73cf2abb1f455b18b9e623b91e4dc168e9ccd5765f5b567db9d5b32610d9c81610f68565b6001600160401b038416600090815260086020526040902054849060ff16610de25760405163900d29db60e01b81526001600160401b038216600482015260240161072b565b600b5460405163a9059cbb60e01b81526001600160a01b03868116600483015260248201869052620100009092049091169063a9059cbb906044016020604051808303816000875af1158015610e3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e609190611c29565b50846001600160401b0316846001600160a01b03167f25497b32c71ad1d4c74c17c7cbe5d107e530962a6955fc9143a344457a9955e585604051610ea691815260200190565b60405180910390a35050505050565b6000818152600160205260408120610668906115f3565b600082815260208190526040902060010154610ee781610f68565b61089a8383611364565b6000610efc81610f68565b50600b80549115156101000261ff0019909216919091179055565b60006001600160e01b031982166385572ffb60e01b1480610f4857506001600160e01b031982166301ffc9a760e01b145b8061066857506001600160e01b03198216630b7f5a3560e31b1492915050565b610d2781336115fd565b6002600a5403610f9557604051633ee5aeb560e01b815260040160405180910390fd5b6002600a55565b600080610fa9848461163a565b6005546040516320487ded60e01b81529192506000916001600160a01b03909116906320487ded90610fe19089908690600401611ee3565b602060405180830381865afa158015610ffe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110229190611fbc565b6006549091506001600160a01b031661112d5747811115611066576040516309585ebd60e41b8152600060048201524760248201526044810182905260640161072b565b6005546040516396f4e9f960e01b81526000916001600160a01b0316906396f4e9f990849061109b908b908890600401611ee3565b60206040518083038185885af11580156110b9573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906110de9190611fbc565b9050866001600160401b03167f85d86ea9e5ad05d3e8b2e36b9eeacb7009a413889b842f7c5ce4ba5eb7ae1bcc8260405161111b91815260200190565b60405180910390a29250610d42915050565b6006546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611175573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111999190611fbc565b81111561123f576006546040516370a0823160e01b81523060048201526001600160a01b039091169081906370a0823190602401602060405180830381865afa1580156111ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120e9190611fbc565b6040516309585ebd60e41b81526001600160a01b03909216600483015260248201526044810182905260640161072b565b60065460055460405163095ea7b360e01b81526001600160a01b0391821660048201526024810184905291169063095ea7b3906044016020604051808303816000875af1158015611294573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b89190611c29565b506005546040516396f4e9f960e01b81526000916001600160a01b0316906396f4e9f9906112ec908a908790600401611ee3565b6020604051808303816000875af115801561130b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110de9190611fbc565b60008061133c8484611766565b90508015610d4257600084815260016020526040902061135c90846117f8565b509392505050565b600080611371848461180d565b90508015610d4257600084815260016020526040902061135c9084611878565b60008061139f60008461163a565b6005546040516320487ded60e01b81529192506001600160a01b0316906320487ded906113d29087908590600401611ee3565b602060405180830381865afa1580156113ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8b9190611fbc565b6020808201516001600160401b0381166000908152600890925260409091205460ff1661145e5760405163900d29db60e01b81526001600160401b038216600482015260240161072b565b600082604001518060200190518101906114789190611fd5565b6020808501516001600160401b03166000908152600990915260409020549091506001600160a01b038083169116146114ff576020838101516001600160401b0316600081815260099092526040918290205491516307c22cd360e41b815260048101919091526001600160a01b039182166024820152908216604482015260640161072b565b600080846060015180602001905181019061151a9190611ff2565b600b5460405163a9059cbb60e01b81526001600160a01b038085166004830152602482018490529395509193506201000090049091169063a9059cbb906044016020604051808303816000875af1158015611579573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159d9190611c29565b5084602001516001600160401b0316826001600160a01b03167f15675fd7e3a643c9323adc305c813839c80f0eca329a7402536f617a3ecd1ca083604051610ea691815260200190565b6000610d42838361188d565b6000610668825490565b6116078282610d49565b6116365760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440161072b565b5050565b6116756040518060a0016040528060608152602001606081526020016060815260200160006001600160a01b03168152602001606081525090565b6040805160a0810182526001600160a01b03851660c0808301919091528251808303909101815260e082018352815260208082018590528251600080825291810184529092820190836116ea565b60408051808201909152600080825260208201528152602001906001900390816116c35790505b5081526006546001600160a01b031660208083019190915260408051808201825260075480825260009184019182528251602481019190915290511515604480830191909152825180830390910181526064909101825291820180516001600160e01b03166397a657c960e01b17905290910152949350505050565b60006117728383610d49565b6117f0576000838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556117a83390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610668565b506000610668565b6000610d42836001600160a01b0384166118b7565b60006118198383610d49565b156117f0576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610668565b6000610d42836001600160a01b0384166118fe565b60008260000182815481106118a4576118a4612020565b9060005260206000200154905092915050565b60008181526001830160205260408120546117f057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610668565b600081815260018301602052604081205480156119e7576000611922600183612036565b855490915060009061193690600190612036565b905080821461199b57600086600001828154811061195657611956612020565b906000526020600020015490508087600001848154811061197957611979612020565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806119ac576119ac612057565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610668565b6000915050610668565b600060208284031215611a0357600080fd5b81356001600160e01b031981168114610d4257600080fd5b8015158114610d2757600080fd5b600060208284031215611a3b57600080fd5b8135610d4281611a1b565b600060208284031215611a5857600080fd5b5035919050565b6001600160a01b0381168114610d2757600080fd5b600060208284031215611a8657600080fd5b8135610d4281611a5f565b80356001600160401b0381168114611aa857600080fd5b919050565b600080600060608486031215611ac257600080fd5b8335611acd81611a5f565b925060208401359150611ae260408501611a91565b90509250925092565b60008060408385031215611afe57600080fd5b611b0783611a91565b91506020830135611b1781611a5f565b809150509250929050565b60008060408385031215611b3557600080fd5b823591506020830135611b1781611a5f565b60008060408385031215611b5a57600080fd5b611b6383611a91565b91506020830135611b1781611a1b565b600060208284031215611b8557600080fd5b610d4282611a91565b600060208284031215611ba057600080fd5b81356001600160401b03811115611bb657600080fd5b820160a08185031215610d4257600080fd5b60008060408385031215611bdb57600080fd5b50508035926020909101359150565b600080600060608486031215611bff57600080fd5b611c0884611a91565b92506020840135611c1881611a5f565b929592945050506040919091013590565b600060208284031215611c3b57600080fd5b8151610d4281611a1b565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715611c7e57611c7e611c46565b60405290565b60405160a081016001600160401b0381118282101715611c7e57611c7e611c46565b604051601f8201601f191681016001600160401b0381118282101715611cce57611cce611c46565b604052919050565b600082601f830112611ce757600080fd5b81356001600160401b03811115611d0057611d00611c46565b611d13601f8201601f1916602001611ca6565b818152846020838601011115611d2857600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112611d5657600080fd5b813560206001600160401b03821115611d7157611d71611c46565b611d7f818360051b01611ca6565b82815260069290921b84018101918181019086841115611d9e57600080fd5b8286015b84811015611de65760408189031215611dbb5760008081fd5b611dc3611c5c565b8135611dce81611a5f565b81528185013585820152835291830191604001611da2565b509695505050505050565b600060a08236031215611e0357600080fd5b611e0b611c84565b82358152611e1b60208401611a91565b602082015260408301356001600160401b0380821115611e3a57600080fd5b611e4636838701611cd6565b60408401526060850135915080821115611e5f57600080fd5b611e6b36838701611cd6565b60608401526080850135915080821115611e8457600080fd5b50611e9136828601611d45565b60808301525092915050565b6000815180845260005b81811015611ec357602081850181015186830182015201611ea7565b506000602082860101526020601f19601f83011685010191505092915050565b600060406001600160401b038516835260208181850152845160a083860152611f0f60e0860182611e9d565b905081860151603f1980878403016060880152611f2c8383611e9d565b88860151888203830160808a01528051808352908601945060009350908501905b80841015611f7f57845180516001600160a01b0316835286015186830152938501936001939093019290860190611f4d565b5060608901516001600160a01b031660a08901526080890151888203830160c08a01529550611fae8187611e9d565b9a9950505050505050505050565b600060208284031215611fce57600080fd5b5051919050565b600060208284031215611fe757600080fd5b8151610d4281611a5f565b6000806040838503121561200557600080fd5b825161201081611a5f565b6020939093015192949293505050565b634e487b7160e01b600052603260045260246000fd5b8181038181111561066857634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fdfea26469706673582212204e8f3ed574a28b6c1be8d4366a9d4881f22830e5662cf4c90c47ceaea732fcf864736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000009132a1598b277555d8029b59f638c48b9194a34200000000000000000000000080226fc0ee2b096224eeac085bb9a8cba1146f7d000000000000000000000000c86338c95eec3d022ec9d166788bcbed7599a1410000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000de0b6b3a7640000
-----Decoded View---------------
Arg [0] : _tokenAddress (address): 0x9132A1598b277555d8029b59F638c48B9194a342
Arg [1] : _ccipRouter (address): 0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D
Arg [2] : _serviceFeeRecipient (address): 0xc86338c95eec3D022Ec9D166788BcbeD7599a141
Arg [3] : _serviceFee (uint256): 5000000000000000
Arg [4] : _minServiceAmount (uint256): 1000000000000000000
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000009132a1598b277555d8029b59f638c48b9194a342
Arg [1] : 00000000000000000000000080226fc0ee2b096224eeac085bb9a8cba1146f7d
Arg [2] : 000000000000000000000000c86338c95eec3d022ec9d166788bcbed7599a141
Arg [3] : 0000000000000000000000000000000000000000000000000011c37937e08000
Arg [4] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | Ether (ETH) | 100.00% | $3,403.23 | 0.00091428 | $3.11 |
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.