Overview
S Balance
0.7122650894534438 S
S Value
-More Info
Private Name Tags
ContractCreator
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
3376523 | 26 hrs ago | 16.19466511 S |
Loading...
Loading
Contract Name:
InterportCCIPTokenBridge
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { ReentrancyGuard } from '@openzeppelin/contracts/security/ReentrancyGuard.sol'; import { Client } from '@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol'; import { InterportCCIPBridgeCore } from './core/InterportCCIPBridgeCore.sol'; import '../../helpers/TransferHelper.sol' as TransferHelper; /** * @title InterportCCIPTokenBridge * @notice The contract bridges ERC-20 tokens with Chainlink CCIP */ contract InterportCCIPTokenBridge is InterportCCIPBridgeCore, ReentrancyGuard { /** * @notice The "bridgeTokens" action parameters * @param targetChainId The message target chain ID (EVM) * @param targetChainSelector The message target chain selector (CCIP) * @param targetRecipient The address of the recipient on the target chain * @param tokenAmounts Token amount data * @param messagingToken The messaging token address */ struct TokenBridgeAction { uint256 targetChainId; uint64 targetChainSelector; address targetRecipient; Client.EVMTokenAmount[] tokenAmounts; } /** * @notice Token bridge action source event * @param targetChainId The ID of the target chain * @param sourceSender The address of the user on the source chain * @param targetRecipient The address of the recipient on the target chain * @param tokenAmounts Token amount data * @param ccipMessageId The CCIP message ID * @param timestamp The timestamp of the action (in seconds) */ event TokenBridgeActionSource( uint256 targetChainId, address indexed sourceSender, address targetRecipient, Client.EVMTokenAmount[] tokenAmounts, bytes32 indexed ccipMessageId, uint256 timestamp ); /** * @notice Initializes the contract * @param _endpointAddress The cross-chain endpoint address * @param _owner The address of the initial owner of the contract * @param _managers The addresses of initial managers of the contract * @param _addOwnerToManagers The flag to optionally add the owner to the list of managers */ constructor( address _endpointAddress, address _owner, address[] memory _managers, bool _addOwnerToManagers ) InterportCCIPBridgeCore(_endpointAddress, _owner, _managers, _addOwnerToManagers) {} /** * @notice Cross-chain bridging of ERC-20 tokens * @param _action The action parameters * @param _messagingTokenInfo The messaging token info */ function bridgeTokens( TokenBridgeAction calldata _action, MessagingTokenInfo calldata _messagingTokenInfo ) external payable whenNotPaused nonReentrant returns (bytes32 ccipMessageId) { (bool isNativeMessagingToken, uint256 ccipSendValue) = _checkMessagingTokenInfo( _messagingTokenInfo, 0 ); bool messagingTokenIncluded; for (uint256 index; index < _action.tokenAmounts.length; index++) { Client.EVMTokenAmount calldata tokenAmountData = _action.tokenAmounts[index]; uint256 tokenAmountToReceive = tokenAmountData.amount; uint256 tokenAmountToApprove = tokenAmountData.amount; if (_messagingTokenInfo.token == tokenAmountData.token && !messagingTokenIncluded) { messagingTokenIncluded = true; tokenAmountToReceive += _messagingTokenInfo.amount; tokenAmountToApprove += _messagingTokenInfo.messagingAmount; } TransferHelper.safeTransferFrom( tokenAmountData.token, msg.sender, address(this), tokenAmountToReceive ); TransferHelper.safeApprove(tokenAmountData.token, endpoint, tokenAmountToApprove); } if (!messagingTokenIncluded && !isNativeMessagingToken) { TransferHelper.safeTransferFrom( _messagingTokenInfo.token, msg.sender, address(this), _messagingTokenInfo.amount ); TransferHelper.safeApprove( _messagingTokenInfo.token, endpoint, _messagingTokenInfo.messagingAmount ); } // Create an EVM2AnyMessage struct in memory with necessary information for sending a cross-chain message Client.EVM2AnyMessage memory ccipMessage = _createCcipMessage( _action.targetRecipient, new bytes(0), _action.tokenAmounts, 0, _messagingTokenInfo.token ); // Send the message ccipMessageId = _ccipSend(_action.targetChainSelector, ccipMessage, ccipSendValue); for (uint256 index; index < _action.tokenAmounts.length; index++) { TransferHelper.safeApprove(_action.tokenAmounts[index].token, endpoint, 0); } if (!messagingTokenIncluded && !isNativeMessagingToken) { TransferHelper.safeApprove(_messagingTokenInfo.token, endpoint, 0); } emit TokenBridgeActionSource( _action.targetChainId, msg.sender, _action.targetRecipient, _action.tokenAmounts, ccipMessageId, block.timestamp ); } /** * @notice Cross-chain message fee estimation * @param _action The action parameters * @return Message fee */ function messageFee( TokenBridgeAction calldata _action, address _messagingToken ) external view returns (uint256) { Client.EVM2AnyMessage memory ccipMessage = _createCcipMessage( _action.targetRecipient, new bytes(0), _action.tokenAmounts, 0, _messagingToken ); return _ccipGetFee(_action.targetChainSelector, ccipMessage); } }
// 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 execution fee for the message /// delivery to destination chain, denominated in the feeToken specified in the message. /// @dev Reverts with appropriate reason upon 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. /// @dev Reverts with appropriate reason upon invalid message. 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 { /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. 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. 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) } // bytes4(keccak256("CCIP EVMExtraArgsV1")); bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9; struct EVMExtraArgsV1 { uint256 gasLimit; } 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 v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @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; 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 require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // 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; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { Pausable } from '@openzeppelin/contracts/security/Pausable.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'; import { BalanceManagementMixin } from '../../../mixins/BalanceManagementMixin.sol'; import { SystemVersionId } from '../../../SystemVersionId.sol'; import '../../../helpers/AddressHelper.sol' as AddressHelper; /** * @title InterportCCIPBridgeCore * @notice The core logic of the cross-chain bridging with Chainlink CCIP */ abstract contract InterportCCIPBridgeCore is SystemVersionId, Pausable, BalanceManagementMixin { /** * @notice Messaging token info structure * @param token The token address * @param amount The token amount * @param messagingAmount The messaging amount */ struct MessagingTokenInfo { address token; uint256 amount; uint256 messagingAmount; } /** * @dev CCIP endpoint address */ address public endpoint; /** * @notice Emitted when the cross-chain endpoint contract reference is set * @param endpointAddress The address of the cross-chain endpoint contract */ event SetEndpoint(address indexed endpointAddress); /** * @notice Emitted when the messaging token amount is invalid */ error MessagingTokenAmountError(); /** * @notice Emitted when the native token value is invalid */ error NativeTokenValueError(); /** * @notice Emitted when the caller is not the CCIP endpoint */ error OnlyEndpointError(); /** * @dev Modifier to check if the caller is the CCIP endpoint */ modifier onlyEndpoint() { if (msg.sender != endpoint) { revert OnlyEndpointError(); } _; } /** * @notice Initializes the contract * @param _endpointAddress The cross-chain endpoint address * @param _owner The address of the initial owner of the contract * @param _managers The addresses of initial managers of the contract * @param _addOwnerToManagers The flag to optionally add the owner to the list of managers */ constructor( address _endpointAddress, address _owner, address[] memory _managers, bool _addOwnerToManagers ) { _setEndpoint(_endpointAddress); _initRoles(_owner, _managers, _addOwnerToManagers); } /** * @notice The standard "receive" function * @dev Is payable to allow receiving native token funds */ receive() external payable {} /** * @notice Sets the cross-chain endpoint contract reference * @param _endpointAddress The address of the cross-chain endpoint contract */ function setEndpoint(address _endpointAddress) external onlyManager { _setEndpoint(_endpointAddress); } /** * @notice Enter pause state */ function pause() external onlyManager whenNotPaused { _pause(); } /** * @notice Exit pause state */ function unpause() external onlyManager whenPaused { _unpause(); } function _ccipSend( uint64 _targetChainSelector, Client.EVM2AnyMessage memory _ccipMessage, uint256 _ccipSendValue ) internal virtual returns (bytes32 ccipMessageId) { return IRouterClient(endpoint).ccipSend{ value: _ccipSendValue }( _targetChainSelector, _ccipMessage ); } function _setEndpoint(address _endpoint) internal virtual { AddressHelper.requireContract(_endpoint); endpoint = _endpoint; emit SetEndpoint(_endpoint); } function _checkMessagingTokenInfo( MessagingTokenInfo calldata _messagingTokenInfo, uint256 _fromNativeTokenAmount ) internal view virtual returns (bool isNativeMessagingToken, uint256 ccipSendValue) { if (_messagingTokenInfo.amount < _messagingTokenInfo.messagingAmount) { revert MessagingTokenAmountError(); } isNativeMessagingToken = (_messagingTokenInfo.token == address(0)); uint256 expectedMsgValue = isNativeMessagingToken ? (_messagingTokenInfo.amount + _fromNativeTokenAmount) : _fromNativeTokenAmount; if (msg.value < expectedMsgValue) { revert NativeTokenValueError(); } ccipSendValue = isNativeMessagingToken ? _messagingTokenInfo.messagingAmount : 0; } function _ccipGetFee( uint64 _targetChainSelector, Client.EVM2AnyMessage memory _ccipMessage ) internal view virtual returns (uint256 fee) { return IRouterClient(endpoint).getFee(_targetChainSelector, _ccipMessage); } function _createCcipMessage( address _receiverAddress, // The receiver may be an EOA or a contract bytes memory _data, Client.EVMTokenAmount[] memory _tokenAmounts, uint256 _targetGasLimit, address _feeToken ) internal pure virtual returns (Client.EVM2AnyMessage memory) { return Client.EVM2AnyMessage({ receiver: abi.encode(_receiverAddress), // ABI-encoded receiver address data: _data, tokenAmounts: _tokenAmounts, extraArgs: Client._argsToBytes( Client.EVMExtraArgsV1({ gasLimit: _targetGasLimit }) ), feeToken: _feeToken }); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @dev The default token decimals value */ uint256 constant DECIMALS_DEFAULT = 18; /** * @dev The maximum uint256 value for swap amount limit settings */ uint256 constant INFINITY = type(uint256).max; /** * @dev The default limit of account list size */ uint256 constant LIST_SIZE_LIMIT_DEFAULT = 100; /** * @dev The limit of swap router list size */ uint256 constant LIST_SIZE_LIMIT_ROUTERS = 200; /** * @dev The factor for percentage settings. Example: 100 is 0.1% */ uint256 constant MILLIPERCENT_FACTOR = 100_000; /** * @dev The de facto standard address to denote the native token */ address constant NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @notice Optional value structure * @dev Is used in mappings to allow zero values * @param isSet Value presence flag * @param value Numeric value */ struct OptionalValue { bool isSet; uint256 value; } /** * @notice Key-to-value structure * @dev Is used as an array parameter item to perform multiple key-value settings * @param key Numeric key * @param value Numeric value */ struct KeyToValue { uint256 key; uint256 value; } /** * @notice Key-to-value structure for address values * @dev Is used as an array parameter item to perform multiple key-value settings with address values * @param key Numeric key * @param value Address value */ struct KeyToAddressValue { uint256 key; address value; } /** * @notice Address-to-flag structure * @dev Is used as an array parameter item to perform multiple settings * @param account Account address * @param flag Flag value */ struct AccountToFlag { address account; bool flag; } /** * @notice Emitted when a list exceeds the size limit */ error ListSizeLimitError(); /** * @notice Sets or updates a value in a combined map (a mapping with a key list and key index mapping) * @param _map The mapping reference * @param _keyList The key list reference * @param _keyIndexMap The key list index mapping reference * @param _key The numeric key * @param _value The address value * @param _sizeLimit The map and list size limit * @return isNewKey True if the key was just added, otherwise false */ function combinedMapSet( mapping(uint256 => address) storage _map, uint256[] storage _keyList, mapping(uint256 => OptionalValue) storage _keyIndexMap, uint256 _key, address _value, uint256 _sizeLimit ) returns (bool isNewKey) { isNewKey = !_keyIndexMap[_key].isSet; if (isNewKey) { uniqueListAdd(_keyList, _keyIndexMap, _key, _sizeLimit); } _map[_key] = _value; } /** * @notice Removes a value from a combined map (a mapping with a key list and key index mapping) * @param _map The mapping reference * @param _keyList The key list reference * @param _keyIndexMap The key list index mapping reference * @param _key The numeric key * @return isChanged True if the combined map was changed, otherwise false */ function combinedMapRemove( mapping(uint256 => address) storage _map, uint256[] storage _keyList, mapping(uint256 => OptionalValue) storage _keyIndexMap, uint256 _key ) returns (bool isChanged) { isChanged = _keyIndexMap[_key].isSet; if (isChanged) { delete _map[_key]; uniqueListRemove(_keyList, _keyIndexMap, _key); } } /** * @notice Adds a value to a unique value list (a list with value index mapping) * @param _list The list reference * @param _indexMap The value index mapping reference * @param _value The numeric value * @param _sizeLimit The list size limit * @return isChanged True if the list was changed, otherwise false */ function uniqueListAdd( uint256[] storage _list, mapping(uint256 => OptionalValue) storage _indexMap, uint256 _value, uint256 _sizeLimit ) returns (bool isChanged) { isChanged = !_indexMap[_value].isSet; if (isChanged) { if (_list.length >= _sizeLimit) { revert ListSizeLimitError(); } _indexMap[_value] = OptionalValue(true, _list.length); _list.push(_value); } } /** * @notice Removes a value from a unique value list (a list with value index mapping) * @param _list The list reference * @param _indexMap The value index mapping reference * @param _value The numeric value * @return isChanged True if the list was changed, otherwise false */ function uniqueListRemove( uint256[] storage _list, mapping(uint256 => OptionalValue) storage _indexMap, uint256 _value ) returns (bool isChanged) { OptionalValue storage indexItem = _indexMap[_value]; isChanged = indexItem.isSet; if (isChanged) { uint256 itemIndex = indexItem.value; uint256 lastIndex = _list.length - 1; if (itemIndex != lastIndex) { uint256 lastValue = _list[lastIndex]; _list[itemIndex] = lastValue; _indexMap[lastValue].value = itemIndex; } _list.pop(); delete _indexMap[_value]; } } /** * @notice Adds a value to a unique address value list (a list with value index mapping) * @param _list The list reference * @param _indexMap The value index mapping reference * @param _value The address value * @param _sizeLimit The list size limit * @return isChanged True if the list was changed, otherwise false */ function uniqueAddressListAdd( address[] storage _list, mapping(address => OptionalValue) storage _indexMap, address _value, uint256 _sizeLimit ) returns (bool isChanged) { isChanged = !_indexMap[_value].isSet; if (isChanged) { if (_list.length >= _sizeLimit) { revert ListSizeLimitError(); } _indexMap[_value] = OptionalValue(true, _list.length); _list.push(_value); } } /** * @notice Removes a value from a unique address value list (a list with value index mapping) * @param _list The list reference * @param _indexMap The value index mapping reference * @param _value The address value * @return isChanged True if the list was changed, otherwise false */ function uniqueAddressListRemove( address[] storage _list, mapping(address => OptionalValue) storage _indexMap, address _value ) returns (bool isChanged) { OptionalValue storage indexItem = _indexMap[_value]; isChanged = indexItem.isSet; if (isChanged) { uint256 itemIndex = indexItem.value; uint256 lastIndex = _list.length - 1; if (itemIndex != lastIndex) { address lastValue = _list[lastIndex]; _list[itemIndex] = lastValue; _indexMap[lastValue].value = itemIndex; } _list.pop(); delete _indexMap[_value]; } } /** * @notice Adds or removes a value to/from a unique address value list (a list with value index mapping) * @dev The list size limit is checked on items adding only * @param _list The list reference * @param _indexMap The value index mapping reference * @param _value The address value * @param _flag The value inclusion flag * @param _sizeLimit The list size limit * @return isChanged True if the list was changed, otherwise false */ function uniqueAddressListUpdate( address[] storage _list, mapping(address => OptionalValue) storage _indexMap, address _value, bool _flag, uint256 _sizeLimit ) returns (bool isChanged) { return _flag ? uniqueAddressListAdd(_list, _indexMap, _value, _sizeLimit) : uniqueAddressListRemove(_list, _indexMap, _value); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @notice Emitted when the account is not a contract * @param account The account address */ error NonContractAddressError(address account); /** * @notice Function to check if the account is a contract * @return The account contract status flag */ function isContract(address _account) view returns (bool) { return _account.code.length > 0; } /** * @notice Function to require an account to be a contract */ function requireContract(address _account) view { if (!isContract(_account)) { revert NonContractAddressError(_account); } } /** * @notice Function to require an account to be a contract or a zero address */ function requireContractOrZeroAddress(address _account) view { if (_account != address(0)) { requireContract(_account); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @notice Emitted when an approval action fails */ error SafeApproveError(); /** * @notice Emitted when a transfer action fails */ error SafeTransferError(); /** * @notice Emitted when a transferFrom action fails */ error SafeTransferFromError(); /** * @notice Emitted when a transfer of the native token fails */ error SafeTransferNativeError(); /** * @notice Safely approve the token to the account * @param _token The token address * @param _to The token approval recipient address * @param _value The token approval amount */ function safeApprove(address _token, address _to, uint256 _value) { // 0x095ea7b3 is the selector for "approve(address,uint256)" (bool success, bytes memory data) = _token.call( abi.encodeWithSelector(0x095ea7b3, _to, _value) ); bool condition = success && (data.length == 0 || abi.decode(data, (bool))); if (!condition) { revert SafeApproveError(); } } /** * @notice Safely transfer the token to the account * @param _token The token address * @param _to The token transfer recipient address * @param _value The token transfer amount */ function safeTransfer(address _token, address _to, uint256 _value) { // 0xa9059cbb is the selector for "transfer(address,uint256)" (bool success, bytes memory data) = _token.call( abi.encodeWithSelector(0xa9059cbb, _to, _value) ); bool condition = success && (data.length == 0 || abi.decode(data, (bool))); if (!condition) { revert SafeTransferError(); } } /** * @notice Safely transfer the token between the accounts * @param _token The token address * @param _from The token transfer source address * @param _to The token transfer recipient address * @param _value The token transfer amount */ function safeTransferFrom(address _token, address _from, address _to, uint256 _value) { // 0x23b872dd is the selector for "transferFrom(address,address,uint256)" (bool success, bytes memory data) = _token.call( abi.encodeWithSelector(0x23b872dd, _from, _to, _value) ); bool condition = success && (data.length == 0 || abi.decode(data, (bool))); if (!condition) { revert SafeTransferFromError(); } } /** * @notice Safely transfer the native token to the account * @param _to The native token transfer recipient address * @param _value The native token transfer amount */ function safeTransferNative(address _to, uint256 _value) { (bool success, ) = _to.call{ value: _value }(new bytes(0)); if (!success) { revert SafeTransferNativeError(); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @title ITokenBalance * @notice Token balance interface */ interface ITokenBalance { /** * @notice Getter of the token balance by the account * @param _account The account address * @return Token balance */ function balanceOf(address _account) external view returns (uint256); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { ITokenBalance } from '../interfaces/ITokenBalance.sol'; import { ManagerRole } from '../roles/ManagerRole.sol'; import '../helpers/TransferHelper.sol' as TransferHelper; import '../Constants.sol' as Constants; /** * @title BalanceManagementMixin * @notice The balance management mix-in logic */ abstract contract BalanceManagementMixin is ManagerRole { /** * @notice Emitted when the specified token is reserved */ error ReservedTokenError(); /** * @notice Performs the token cleanup * @dev Use the "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" address for the native token * @param _tokenAddress The address of the token * @param _to The token transfer recipient address */ function cleanup(address _tokenAddress, address _to) external virtual onlyManager { _cleanupWithAmount(_tokenAddress, _to, tokenBalance(_tokenAddress)); } /** * @notice Performs the token cleanup using the provided amount * @dev Use the "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" address for the native token * @param _tokenAddress The address of the token * @param _to The token transfer recipient address * @param _tokenAmount The amount of the token */ function cleanupWithAmount( address _tokenAddress, address _to, uint256 _tokenAmount ) external virtual onlyManager { _cleanupWithAmount(_tokenAddress, _to, _tokenAmount); } /** * @notice Getter of the token balance of the current contract * @dev Use the "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" address for the native token * @param _tokenAddress The address of the token * @return The token balance of the current contract */ function tokenBalance(address _tokenAddress) public view virtual returns (uint256) { if (_tokenAddress == Constants.NATIVE_TOKEN_ADDRESS) { return address(this).balance; } else { return ITokenBalance(_tokenAddress).balanceOf(address(this)); } } /** * @notice Getter of the reserved token flag * @dev Override to add reserved token addresses * @param _tokenAddress The address of the token * @return The reserved token flag */ function isReservedToken(address _tokenAddress) public view virtual returns (bool) { // The function returns false by default. // The explicit return statement is omitted to avoid the unused parameter warning. // See https://github.com/ethereum/solidity/issues/5295 } function _cleanupWithAmount( address _tokenAddress, address _to, uint256 _tokenAmount ) internal virtual { if (isReservedToken(_tokenAddress)) { revert ReservedTokenError(); } if (_tokenAddress == Constants.NATIVE_TOKEN_ADDRESS) { TransferHelper.safeTransferNative(_to, _tokenAmount); } else { TransferHelper.safeTransfer(_tokenAddress, _to, _tokenAmount); } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { Ownable } from '@openzeppelin/contracts/access/Ownable.sol'; import { RoleBearers } from './RoleBearers.sol'; /** * @title ManagerRole * @notice Base contract that implements the Manager role. * The manager role is a high-permission role for core team members only. * Managers can set vaults and routers addresses, fees, cross-chain protocols, * and other parameters for Interchain (cross-chain) swaps and single-network swaps. * Please note, the manager role is unique for every contract, * hence different addresses may be assigned as managers for different contracts. */ abstract contract ManagerRole is Ownable, RoleBearers { bytes32 private constant ROLE_KEY = keccak256('Manager'); /** * @notice Emitted when the Manager role status for the account is updated * @param account The account address * @param value The Manager role status flag */ event SetManager(address indexed account, bool indexed value); /** * @notice Emitted when the Manager role status for the account is renounced * @param account The account address */ event RenounceManagerRole(address indexed account); /** * @notice Emitted when the caller is not a Manager role bearer */ error OnlyManagerError(); /** * @dev Modifier to check if the caller is a Manager role bearer */ modifier onlyManager() { if (!isManager(msg.sender)) { revert OnlyManagerError(); } _; } /** * @notice Updates the Manager role status for the account * @param _account The account address * @param _value The Manager role status flag */ function setManager(address _account, bool _value) public onlyOwner { _setRoleBearer(ROLE_KEY, _account, _value); emit SetManager(_account, _value); } /** * @notice Renounces the Manager role */ function renounceManagerRole() external onlyManager { _setRoleBearer(ROLE_KEY, msg.sender, false); emit RenounceManagerRole(msg.sender); } /** * @notice Getter of the Manager role bearer count * @return The Manager role bearer count */ function managerCount() external view returns (uint256) { return _roleBearerCount(ROLE_KEY); } /** * @notice Getter of the complete list of the Manager role bearers * @return The complete list of the Manager role bearers */ function fullManagerList() external view returns (address[] memory) { return _fullRoleBearerList(ROLE_KEY); } /** * @notice Getter of the Manager role bearer status * @param _account The account address */ function isManager(address _account) public view returns (bool) { return _isRoleBearer(ROLE_KEY, _account); } function _initRoles( address _owner, address[] memory _managers, bool _addOwnerToManagers ) internal { address ownerAddress = _owner == address(0) ? msg.sender : _owner; for (uint256 index; index < _managers.length; index++) { setManager(_managers[index], true); } if (_addOwnerToManagers && !isManager(ownerAddress)) { setManager(ownerAddress, true); } if (ownerAddress != msg.sender) { transferOwnership(ownerAddress); } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import '../Constants.sol' as Constants; import '../DataStructures.sol' as DataStructures; /** * @title RoleBearers * @notice Base contract that implements role-based access control * @dev A custom implementation providing full role bearer lists */ abstract contract RoleBearers { mapping(bytes32 /*roleKey*/ => address[] /*roleBearers*/) private roleBearerTable; mapping(bytes32 /*roleKey*/ => mapping(address /*account*/ => DataStructures.OptionalValue /*status*/)) private roleBearerIndexTable; function _setRoleBearer(bytes32 _roleKey, address _account, bool _value) internal { DataStructures.uniqueAddressListUpdate( roleBearerTable[_roleKey], roleBearerIndexTable[_roleKey], _account, _value, Constants.LIST_SIZE_LIMIT_DEFAULT ); } function _isRoleBearer(bytes32 _roleKey, address _account) internal view returns (bool) { return roleBearerIndexTable[_roleKey][_account].isSet; } function _roleBearerCount(bytes32 _roleKey) internal view returns (uint256) { return roleBearerTable[_roleKey].length; } function _fullRoleBearerList(bytes32 _roleKey) internal view returns (address[] memory) { return roleBearerTable[_roleKey]; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @title SystemVersionId * @notice Base contract providing the system version identifier */ abstract contract SystemVersionId { /** * @dev The system version identifier */ uint256 public constant SYSTEM_VERSION_ID = uint256(keccak256('Initial')); }
{ "optimizer": { "enabled": true, "runs": 200 }, "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":"_endpointAddress","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address[]","name":"_managers","type":"address[]"},{"internalType":"bool","name":"_addOwnerToManagers","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ListSizeLimitError","type":"error"},{"inputs":[],"name":"MessagingTokenAmountError","type":"error"},{"inputs":[],"name":"NativeTokenValueError","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NonContractAddressError","type":"error"},{"inputs":[],"name":"OnlyEndpointError","type":"error"},{"inputs":[],"name":"OnlyManagerError","type":"error"},{"inputs":[],"name":"ReservedTokenError","type":"error"},{"inputs":[],"name":"SafeApproveError","type":"error"},{"inputs":[],"name":"SafeTransferError","type":"error"},{"inputs":[],"name":"SafeTransferFromError","type":"error"},{"inputs":[],"name":"SafeTransferNativeError","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"RenounceManagerRole","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"endpointAddress","type":"address"}],"name":"SetEndpoint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"bool","name":"value","type":"bool"}],"name":"SetManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"targetChainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"sourceSender","type":"address"},{"indexed":false,"internalType":"address","name":"targetRecipient","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"indexed":false,"internalType":"struct Client.EVMTokenAmount[]","name":"tokenAmounts","type":"tuple[]"},{"indexed":true,"internalType":"bytes32","name":"ccipMessageId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"TokenBridgeActionSource","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"SYSTEM_VERSION_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"targetChainId","type":"uint256"},{"internalType":"uint64","name":"targetChainSelector","type":"uint64"},{"internalType":"address","name":"targetRecipient","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Client.EVMTokenAmount[]","name":"tokenAmounts","type":"tuple[]"}],"internalType":"struct InterportCCIPTokenBridge.TokenBridgeAction","name":"_action","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"messagingAmount","type":"uint256"}],"internalType":"struct InterportCCIPBridgeCore.MessagingTokenInfo","name":"_messagingTokenInfo","type":"tuple"}],"name":"bridgeTokens","outputs":[{"internalType":"bytes32","name":"ccipMessageId","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"address","name":"_to","type":"address"}],"name":"cleanup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"}],"name":"cleanupWithAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"endpoint","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fullManagerList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isManager","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"isReservedToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"managerCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"targetChainId","type":"uint256"},{"internalType":"uint64","name":"targetChainSelector","type":"uint64"},{"internalType":"address","name":"targetRecipient","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Client.EVMTokenAmount[]","name":"tokenAmounts","type":"tuple[]"}],"internalType":"struct InterportCCIPTokenBridge.TokenBridgeAction","name":"_action","type":"tuple"},{"internalType":"address","name":"_messagingToken","type":"address"}],"name":"messageFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceManagerRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_endpointAddress","type":"address"}],"name":"setEndpoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_value","type":"bool"}],"name":"setManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"tokenBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040523480156200001157600080fd5b50604051620023fc380380620023fc833981016040819052620000349162000636565b6000805460ff19169055838383836200004d3362000079565b6200005884620000d2565b6200006583838362000127565b5050600160045550620007b7945050505050565b600080546001600160a01b03838116610100818102610100600160a81b0319851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b620000dd81620001e1565b600380546001600160a01b0319166001600160a01b0383169081179091556040517fc8e81a4efc849969069ec6aae575cf7a6bc5f9d3abac59f4ed190a6f7e05fc6f90600090a250565b60006001600160a01b0384161562000140578362000142565b335b905060005b83518110156200019557620001808482815181106200016a576200016a62000743565b602002602001015160016200021d60201b60201c565b806200018c816200076f565b91505062000147565b50818015620001ac5750620001aa8162000290565b155b15620001bf57620001bf8160016200021d565b6001600160a01b0381163314620001db57620001db81620002d2565b50505050565b6001600160a01b0381163b6200021a57604051638c50d7cd60e01b81526001600160a01b03821660048201526024015b60405180910390fd5b50565b620002276200034e565b620002547f6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f8383620003b2565b604051811515906001600160a01b038416907fbe9474bb3e78da7e315cdffa5cfa30b767fcc95bbf44a6197da60228eea1028690600090a35050565b6001600160a01b03811660009081527f260b29b219d450563ddb0e5ca806bdadb1e125f7e8c506de0443797dd7122728602052604081205460ff165b92915050565b620002dc6200034e565b6001600160a01b038116620003435760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000211565b6200021a8162000079565b6000546001600160a01b03610100909104163314620003b05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000211565b565b60008381526001602090815260408083206002909252909120620001db919084846064600082620003f057620003ea86868662000408565b620003fe565b620003fe868686856200053d565b9695505050505050565b6001600160a01b0381166000908152602083905260409020805460ff169081156200053557600180820154865490916000916200044691906200078b565b9050808214620004da57600087828154811062000467576200046762000743565b9060005260206000200160009054906101000a90046001600160a01b03169050808884815481106200049d576200049d62000743565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905592909116815290879052604090206001018290555b86805480620004ed57620004ed620007a1565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038716825287905260408120805460ff191681556001015550505b509392505050565b6001600160a01b03821660009081526020849052604090205460ff16158015620005ea5784548211620005835760405163b1655e3360e01b815260040160405180910390fd5b6040805180820182526001808252875460208084019182526001600160a01b03881660008181528a83529586209451855460ff1916901515178555915193830193909355885491820189558884529190922090910180546001600160a01b03191690911790555b949350505050565b80516001600160a01b03811681146200060a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b805180151581146200060a57600080fd5b600080600080608085870312156200064d57600080fd5b6200065885620005f2565b9350602062000669818701620005f2565b60408701519094506001600160401b03808211156200068757600080fd5b818801915088601f8301126200069c57600080fd5b815181811115620006b157620006b16200060f565b8060051b604051601f19603f83011681018181108582111715620006d957620006d96200060f565b60405291825284820192508381018501918b831115620006f857600080fd5b938501935b8285101562000721576200071185620005f2565b84529385019392850192620006fd565b809750505050505050620007386060860162000625565b905092959194509250565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820162000784576200078462000759565b5060010190565b81810381811115620002cc57620002cc62000759565b634e487b7160e01b600052603160045260246000fd5b611c3580620007c76000396000f3fe6080604052600436106101235760003560e01c806383d85346116100a0578063dbbb415511610064578063dbbb41551461034e578063e3725b151461036e578063eedc966a14610390578063f2fde38b146103b0578063f3ae2415146103d057600080fd5b806383d85346146102c15780638456cb59146102e15780638da5cb5b146102f6578063a5e90eee14610319578063c2c518e11461033957600080fd5b80635d2251d5116100e75780635d2251d5146102215780635e280f1114610241578063715018a6146102795780637e56f0ba1461028e5780637f906b9a146102ae57600080fd5b8063093f0e271461012f578063103b7397146101765780633f4ba83a146101c1578063440d7248146101d85780635c975abb1461020957600080fd5b3661012a57005b600080fd5b34801561013b57600080fd5b506101637f22ad9585a395edc8067b50da4778cafbb7fa2c4bbd7619fad6aeba403857fd7481565b6040519081526020015b60405180910390f35b34801561018257600080fd5b50600080516020611be083398151915260005260016020527f3c2285c553468ca8f30447b24bb463c127f1b840e23a0cafa23caa79d906669a54610163565b3480156101cd57600080fd5b506101d66103f5565b005b3480156101e457600080fd5b506101f96101f33660046116b6565b50600090565b604051901515815260200161016d565b34801561021557600080fd5b5060005460ff166101f9565b34801561022d57600080fd5b506101d661023c3660046116d1565b61042d565b34801561024d57600080fd5b50600354610261906001600160a01b031681565b6040516001600160a01b03909116815260200161016d565b34801561028557600080fd5b506101d6610463565b34801561029a57600080fd5b506101636102a9366004611725565b610475565b6101636102bc366004611773565b610525565b3480156102cd57600080fd5b506101d66102dc3660046117cd565b61084c565b3480156102ed57600080fd5b506101d6610889565b34801561030257600080fd5b5060005461010090046001600160a01b0316610261565b34801561032557600080fd5b506101d6610334366004611805565b6108bf565b34801561034557600080fd5b506101d661091c565b34801561035a57600080fd5b506101d66103693660046116b6565b610989565b34801561037a57600080fd5b506103836109bb565b60405161016d919061183c565b34801561039c57600080fd5b506101636103ab3660046116b6565b6109d4565b3480156103bc57600080fd5b506101d66103cb3660046116b6565b610a6f565b3480156103dc57600080fd5b506101f96103eb3660046116b6565b610aea565b905090565b6103fe33610aea565b61041b57604051637c3ea23f60e01b815260040160405180910390fd5b610423610b2a565b61042b610b73565b565b61043633610aea565b61045357604051637c3ea23f60e01b815260040160405180910390fd5b61045e838383610bc5565b505050565b61046b610bff565b61042b6000610c5f565b60008061050061048b60608601604087016116b6565b6040805160008152602081019091526104a76060880188611889565b808060200260200160405190810160405280939291908181526020016000905b828210156104f3576104e4604083028601368190038101906118da565b815260200190600101906104c7565b5050505050600087610cb8565b905061051b610515604086016020870161193f565b82610d9c565b9150505b92915050565b600061052f610e17565b610537610e5d565b600080610545846000610eb6565b915091506000805b61055a6060880188611889565b905081101561064257366105716060890189611889565b8381811061058157610581611969565b6040029190910191505060208101803590819061059e90846116b6565b6001600160a01b03166105b460208b018b6116b6565b6001600160a01b03161480156105c8575084155b156105f257600194506105df60208a013583611995565b91506105ef60408a013582611995565b90505b61060a61060260208501856116b6565b333085610f57565b61062c61061a60208501856116b6565b6003546001600160a01b031683611052565b505050808061063a906119a8565b91505061054d565b508015801561064f575082155b156106965761067061066460208701876116b6565b33308860200135610f57565b61069661068060208701876116b6565b6003546001600160a01b03166040880135611052565b600061072e6106ab6060890160408a016116b6565b6040805160008152602081019091526106c760608b018b611889565b808060200260200160405190810160405280939291908181526020016000905b8282101561071357610704604083028601368190038101906118da565b815260200190600101906106e7565b50600093506107299250505060208c018c6116b6565b610cb8565b905061074a6107436040890160208a0161193f565b8285611144565b945060005b61075c6060890189611889565b90508110156107c0576107ae61077560608a018a611889565b8381811061078557610785611969565b61079b92602060409092020190810191506116b6565b6003546001600160a01b03166000611052565b806107b8816119a8565b91505061074f565b50811580156107cd575083155b156107e2576107e261079b60208801886116b6565b84337f4aa68b249ed282da7ec233371e67641bd006306e749e65064cf4d4cc5f6b6df0893561081760608c0160408d016116b6565b61082460608d018d611889565b426040516108369594939291906119c1565b60405180910390a35050505061051f6001600455565b61085533610aea565b61087257604051637c3ea23f60e01b815260040160405180910390fd5b6108858282610880856109d4565b610bc5565b5050565b61089233610aea565b6108af57604051637c3ea23f60e01b815260040160405180910390fd5b6108b7610e17565b61042b6111c4565b6108c7610bff565b6108e0600080516020611be08339815191528383611201565b604051811515906001600160a01b038416907fbe9474bb3e78da7e315cdffa5cfa30b767fcc95bbf44a6197da60228eea1028690600090a35050565b61092533610aea565b61094257604051637c3ea23f60e01b815260040160405180910390fd5b61095c600080516020611be0833981519152336000611201565b60405133907f6cc2c67081f55c2fffb7c008fa995fbbf890f48c7c16fba93d8220f00dc84cc590600090a2565b61099233610aea565b6109af57604051637c3ea23f60e01b815260040160405180910390fd5b6109b88161122e565b50565b60606103f0600080516020611be0833981519152611281565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03831601610a02575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a46573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051f9190611a3a565b919050565b610a77610bff565b6001600160a01b038116610ae15760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6109b881610c5f565b6001600160a01b03811660009081527f260b29b219d450563ddb0e5ca806bdadb1e125f7e8c506de0443797dd7122728602052604081205460ff1661051f565b60005460ff1661042b5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610ad8565b610b7b610b2a565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03841601610bf45761045e82826112ed565b61045e83838361137b565b6000546001600160a01b0361010090910416331461042b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610ad8565b600080546001600160a01b03838116610100818102610100600160a81b0319851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b610cf36040518060a0016040528060608152602001606081526020016060815260200160006001600160a01b03168152602001606081525090565b6040805160a081019091526001600160a01b03871660c08201528060e081016040516020818303038152906040528152602001868152602001858152602001836001600160a01b03168152602001610d9060405180602001604052808781525060408051915160248084019190915281518084039091018152604490920190526020810180516001600160e01b03166397a657c960e01b17905290565b90529695505050505050565b6003546040516320487ded60e01b81526000916001600160a01b0316906320487ded90610dcf9086908690600401611aa3565b602060405180830381865afa158015610dec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e109190611a3a565b9392505050565b60005460ff161561042b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ad8565b600260045403610eaf5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ad8565b6002600455565b600080836040013584602001351015610ee257604051637367509b60e01b815260040160405180910390fd5b6000610ef160208601866116b6565b6001600160a01b0316149150600082610f0a5783610f18565b610f18846020870135611995565b905080341015610f3b57604051637dd7aa2160e01b815260040160405180910390fd5b82610f47576000610f4d565b84604001355b9150509250929050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691610fbb9190611b7d565b6000604051808303816000865af19150503d8060008114610ff8576040519150601f19603f3d011682016040523d82523d6000602084013e610ffd565b606091505b509150915060008280156110295750815115806110295750818060200190518101906110299190611b99565b90508061104957604051632d9d5b4160e01b815260040160405180910390fd5b50505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392908716916110ae9190611b7d565b6000604051808303816000865af19150503d80600081146110eb576040519150601f19603f3d011682016040523d82523d6000602084013e6110f0565b606091505b5091509150600082801561111c57508151158061111c57508180602001905181019061111c9190611b99565b90508061113c5760405163b45d44e760e01b815260040160405180910390fd5b505050505050565b6003546040516396f4e9f960e01b81526000916001600160a01b0316906396f4e9f99084906111799088908890600401611aa3565b60206040518083038185885af1158015611197573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906111bc9190611a3a565b949350505050565b6111cc610e17565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610ba83390565b60008381526001602090815260408083206002909252909120611228919084846064611465565b50505050565b61123781611492565b600380546001600160a01b0319166001600160a01b0383169081179091556040517fc8e81a4efc849969069ec6aae575cf7a6bc5f9d3abac59f4ed190a6f7e05fc6f90600090a250565b6000818152600160209081526040918290208054835181840281018401909452808452606093928301828280156112e157602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112c3575b50505050509050919050565b604080516000808252602082019092526001600160a01b0384169083906040516113179190611b7d565b60006040518083038185875af1925050503d8060008114611354576040519150601f19603f3d011682016040523d82523d6000602084013e611359565b606091505b505090508061045e57604051632e05b05360e21b815260040160405180910390fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916113d79190611b7d565b6000604051808303816000865af19150503d8060008114611414576040519150601f19603f3d011682016040523d82523d6000602084013e611419565b606091505b509150915060008280156114455750815115806114455750818060200190518101906114459190611b99565b90508061113c57604051632fdb1b7f60e11b815260040160405180910390fd5b60008261147c576114778686866114c5565b611488565b611488868686856115ed565b9695505050505050565b6001600160a01b0381163b6109b857604051638c50d7cd60e01b81526001600160a01b0382166004820152602401610ad8565b6001600160a01b0381166000908152602083905260409020805460ff169081156115e557600180820154865490916000916115009190611bb6565b905080821461158d57600087828154811061151d5761151d611969565b9060005260206000200160009054906101000a90046001600160a01b031690508088848154811061155057611550611969565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905592909116815290879052604090206001018290555b8680548061159d5761159d611bc9565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038716825287905260408120805460ff191681556001015550505b509392505050565b6001600160a01b03821660009081526020849052604090205460ff161580156111bc57845482116116315760405163b1655e3360e01b815260040160405180910390fd5b6040805180820182526001808252875460208084019182526001600160a01b03881660008181528a83529586209451855460ff1916901515178555915193830193909355885491820189558884529190922090910180546001600160a01b0319169091179055949350505050565b80356001600160a01b0381168114610a6a57600080fd5b6000602082840312156116c857600080fd5b610e108261169f565b6000806000606084860312156116e657600080fd5b6116ef8461169f565b92506116fd6020850161169f565b9150604084013590509250925092565b60006080828403121561171f57600080fd5b50919050565b6000806040838503121561173857600080fd5b823567ffffffffffffffff81111561174f57600080fd5b61175b8582860161170d565b92505061176a6020840161169f565b90509250929050565b600080828403608081121561178757600080fd5b833567ffffffffffffffff81111561179e57600080fd5b6117aa8682870161170d565b9350506060601f19820112156117bf57600080fd5b506020830190509250929050565b600080604083850312156117e057600080fd5b6117e98361169f565b915061176a6020840161169f565b80151581146109b857600080fd5b6000806040838503121561181857600080fd5b6118218361169f565b91506020830135611831816117f7565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b8181101561187d5783516001600160a01b031683529284019291840191600101611858565b50909695505050505050565b6000808335601e198436030181126118a057600080fd5b83018035915067ffffffffffffffff8211156118bb57600080fd5b6020019150600681901b36038213156118d357600080fd5b9250929050565b6000604082840312156118ec57600080fd5b6040516040810181811067ffffffffffffffff8211171561191d57634e487b7160e01b600052604160045260246000fd5b6040526119298361169f565b8152602083013560208201528091505092915050565b60006020828403121561195157600080fd5b813567ffffffffffffffff81168114610e1057600080fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561051f5761051f61197f565b6000600182016119ba576119ba61197f565b5060010190565b8581526001600160a01b038581166020808401919091526080604080850182905290840186905260009287929160a08601855b89811015611a215783611a068761169f565b168252858501358583015294820194908201906001016119f4565b5080955050505050508260608301529695505050505050565b600060208284031215611a4c57600080fd5b5051919050565b60005b83811015611a6e578181015183820152602001611a56565b50506000910152565b60008151808452611a8f816020860160208601611a53565b601f01601f19169290920160200192915050565b6000604067ffffffffffffffff8516835260208181850152845160a083860152611ad060e0860182611a77565b905081860151603f1980878403016060880152611aed8383611a77565b88860151888203830160808a01528051808352908601945060009350908501905b80841015611b4057845180516001600160a01b0316835286015186830152938501936001939093019290860190611b0e565b5060608901516001600160a01b031660a08901526080890151888203830160c08a01529550611b6f8187611a77565b9a9950505050505050505050565b60008251611b8f818460208701611a53565b9190910192915050565b600060208284031215611bab57600080fd5b8151610e10816117f7565b8181038181111561051f5761051f61197f565b634e487b7160e01b600052603160045260246000fdfe6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6fa2646970667358221220459e7a213578f685627af41f1eaca18ec17e0264a90695ffafb88ed81b90f9cc64736f6c63430008130033000000000000000000000000b4e1ff7882474bb93042be9ad5e1fa387949b86000000000000000000000000072e28c7f34100afefc399fcc0ae041b8fe5841ae000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106101235760003560e01c806383d85346116100a0578063dbbb415511610064578063dbbb41551461034e578063e3725b151461036e578063eedc966a14610390578063f2fde38b146103b0578063f3ae2415146103d057600080fd5b806383d85346146102c15780638456cb59146102e15780638da5cb5b146102f6578063a5e90eee14610319578063c2c518e11461033957600080fd5b80635d2251d5116100e75780635d2251d5146102215780635e280f1114610241578063715018a6146102795780637e56f0ba1461028e5780637f906b9a146102ae57600080fd5b8063093f0e271461012f578063103b7397146101765780633f4ba83a146101c1578063440d7248146101d85780635c975abb1461020957600080fd5b3661012a57005b600080fd5b34801561013b57600080fd5b506101637f22ad9585a395edc8067b50da4778cafbb7fa2c4bbd7619fad6aeba403857fd7481565b6040519081526020015b60405180910390f35b34801561018257600080fd5b50600080516020611be083398151915260005260016020527f3c2285c553468ca8f30447b24bb463c127f1b840e23a0cafa23caa79d906669a54610163565b3480156101cd57600080fd5b506101d66103f5565b005b3480156101e457600080fd5b506101f96101f33660046116b6565b50600090565b604051901515815260200161016d565b34801561021557600080fd5b5060005460ff166101f9565b34801561022d57600080fd5b506101d661023c3660046116d1565b61042d565b34801561024d57600080fd5b50600354610261906001600160a01b031681565b6040516001600160a01b03909116815260200161016d565b34801561028557600080fd5b506101d6610463565b34801561029a57600080fd5b506101636102a9366004611725565b610475565b6101636102bc366004611773565b610525565b3480156102cd57600080fd5b506101d66102dc3660046117cd565b61084c565b3480156102ed57600080fd5b506101d6610889565b34801561030257600080fd5b5060005461010090046001600160a01b0316610261565b34801561032557600080fd5b506101d6610334366004611805565b6108bf565b34801561034557600080fd5b506101d661091c565b34801561035a57600080fd5b506101d66103693660046116b6565b610989565b34801561037a57600080fd5b506103836109bb565b60405161016d919061183c565b34801561039c57600080fd5b506101636103ab3660046116b6565b6109d4565b3480156103bc57600080fd5b506101d66103cb3660046116b6565b610a6f565b3480156103dc57600080fd5b506101f96103eb3660046116b6565b610aea565b905090565b6103fe33610aea565b61041b57604051637c3ea23f60e01b815260040160405180910390fd5b610423610b2a565b61042b610b73565b565b61043633610aea565b61045357604051637c3ea23f60e01b815260040160405180910390fd5b61045e838383610bc5565b505050565b61046b610bff565b61042b6000610c5f565b60008061050061048b60608601604087016116b6565b6040805160008152602081019091526104a76060880188611889565b808060200260200160405190810160405280939291908181526020016000905b828210156104f3576104e4604083028601368190038101906118da565b815260200190600101906104c7565b5050505050600087610cb8565b905061051b610515604086016020870161193f565b82610d9c565b9150505b92915050565b600061052f610e17565b610537610e5d565b600080610545846000610eb6565b915091506000805b61055a6060880188611889565b905081101561064257366105716060890189611889565b8381811061058157610581611969565b6040029190910191505060208101803590819061059e90846116b6565b6001600160a01b03166105b460208b018b6116b6565b6001600160a01b03161480156105c8575084155b156105f257600194506105df60208a013583611995565b91506105ef60408a013582611995565b90505b61060a61060260208501856116b6565b333085610f57565b61062c61061a60208501856116b6565b6003546001600160a01b031683611052565b505050808061063a906119a8565b91505061054d565b508015801561064f575082155b156106965761067061066460208701876116b6565b33308860200135610f57565b61069661068060208701876116b6565b6003546001600160a01b03166040880135611052565b600061072e6106ab6060890160408a016116b6565b6040805160008152602081019091526106c760608b018b611889565b808060200260200160405190810160405280939291908181526020016000905b8282101561071357610704604083028601368190038101906118da565b815260200190600101906106e7565b50600093506107299250505060208c018c6116b6565b610cb8565b905061074a6107436040890160208a0161193f565b8285611144565b945060005b61075c6060890189611889565b90508110156107c0576107ae61077560608a018a611889565b8381811061078557610785611969565b61079b92602060409092020190810191506116b6565b6003546001600160a01b03166000611052565b806107b8816119a8565b91505061074f565b50811580156107cd575083155b156107e2576107e261079b60208801886116b6565b84337f4aa68b249ed282da7ec233371e67641bd006306e749e65064cf4d4cc5f6b6df0893561081760608c0160408d016116b6565b61082460608d018d611889565b426040516108369594939291906119c1565b60405180910390a35050505061051f6001600455565b61085533610aea565b61087257604051637c3ea23f60e01b815260040160405180910390fd5b6108858282610880856109d4565b610bc5565b5050565b61089233610aea565b6108af57604051637c3ea23f60e01b815260040160405180910390fd5b6108b7610e17565b61042b6111c4565b6108c7610bff565b6108e0600080516020611be08339815191528383611201565b604051811515906001600160a01b038416907fbe9474bb3e78da7e315cdffa5cfa30b767fcc95bbf44a6197da60228eea1028690600090a35050565b61092533610aea565b61094257604051637c3ea23f60e01b815260040160405180910390fd5b61095c600080516020611be0833981519152336000611201565b60405133907f6cc2c67081f55c2fffb7c008fa995fbbf890f48c7c16fba93d8220f00dc84cc590600090a2565b61099233610aea565b6109af57604051637c3ea23f60e01b815260040160405180910390fd5b6109b88161122e565b50565b60606103f0600080516020611be0833981519152611281565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03831601610a02575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a46573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051f9190611a3a565b919050565b610a77610bff565b6001600160a01b038116610ae15760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6109b881610c5f565b6001600160a01b03811660009081527f260b29b219d450563ddb0e5ca806bdadb1e125f7e8c506de0443797dd7122728602052604081205460ff1661051f565b60005460ff1661042b5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610ad8565b610b7b610b2a565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03841601610bf45761045e82826112ed565b61045e83838361137b565b6000546001600160a01b0361010090910416331461042b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610ad8565b600080546001600160a01b03838116610100818102610100600160a81b0319851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b610cf36040518060a0016040528060608152602001606081526020016060815260200160006001600160a01b03168152602001606081525090565b6040805160a081019091526001600160a01b03871660c08201528060e081016040516020818303038152906040528152602001868152602001858152602001836001600160a01b03168152602001610d9060405180602001604052808781525060408051915160248084019190915281518084039091018152604490920190526020810180516001600160e01b03166397a657c960e01b17905290565b90529695505050505050565b6003546040516320487ded60e01b81526000916001600160a01b0316906320487ded90610dcf9086908690600401611aa3565b602060405180830381865afa158015610dec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e109190611a3a565b9392505050565b60005460ff161561042b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ad8565b600260045403610eaf5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ad8565b6002600455565b600080836040013584602001351015610ee257604051637367509b60e01b815260040160405180910390fd5b6000610ef160208601866116b6565b6001600160a01b0316149150600082610f0a5783610f18565b610f18846020870135611995565b905080341015610f3b57604051637dd7aa2160e01b815260040160405180910390fd5b82610f47576000610f4d565b84604001355b9150509250929050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691610fbb9190611b7d565b6000604051808303816000865af19150503d8060008114610ff8576040519150601f19603f3d011682016040523d82523d6000602084013e610ffd565b606091505b509150915060008280156110295750815115806110295750818060200190518101906110299190611b99565b90508061104957604051632d9d5b4160e01b815260040160405180910390fd5b50505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392908716916110ae9190611b7d565b6000604051808303816000865af19150503d80600081146110eb576040519150601f19603f3d011682016040523d82523d6000602084013e6110f0565b606091505b5091509150600082801561111c57508151158061111c57508180602001905181019061111c9190611b99565b90508061113c5760405163b45d44e760e01b815260040160405180910390fd5b505050505050565b6003546040516396f4e9f960e01b81526000916001600160a01b0316906396f4e9f99084906111799088908890600401611aa3565b60206040518083038185885af1158015611197573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906111bc9190611a3a565b949350505050565b6111cc610e17565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610ba83390565b60008381526001602090815260408083206002909252909120611228919084846064611465565b50505050565b61123781611492565b600380546001600160a01b0319166001600160a01b0383169081179091556040517fc8e81a4efc849969069ec6aae575cf7a6bc5f9d3abac59f4ed190a6f7e05fc6f90600090a250565b6000818152600160209081526040918290208054835181840281018401909452808452606093928301828280156112e157602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112c3575b50505050509050919050565b604080516000808252602082019092526001600160a01b0384169083906040516113179190611b7d565b60006040518083038185875af1925050503d8060008114611354576040519150601f19603f3d011682016040523d82523d6000602084013e611359565b606091505b505090508061045e57604051632e05b05360e21b815260040160405180910390fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916113d79190611b7d565b6000604051808303816000865af19150503d8060008114611414576040519150601f19603f3d011682016040523d82523d6000602084013e611419565b606091505b509150915060008280156114455750815115806114455750818060200190518101906114459190611b99565b90508061113c57604051632fdb1b7f60e11b815260040160405180910390fd5b60008261147c576114778686866114c5565b611488565b611488868686856115ed565b9695505050505050565b6001600160a01b0381163b6109b857604051638c50d7cd60e01b81526001600160a01b0382166004820152602401610ad8565b6001600160a01b0381166000908152602083905260409020805460ff169081156115e557600180820154865490916000916115009190611bb6565b905080821461158d57600087828154811061151d5761151d611969565b9060005260206000200160009054906101000a90046001600160a01b031690508088848154811061155057611550611969565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905592909116815290879052604090206001018290555b8680548061159d5761159d611bc9565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038716825287905260408120805460ff191681556001015550505b509392505050565b6001600160a01b03821660009081526020849052604090205460ff161580156111bc57845482116116315760405163b1655e3360e01b815260040160405180910390fd5b6040805180820182526001808252875460208084019182526001600160a01b03881660008181528a83529586209451855460ff1916901515178555915193830193909355885491820189558884529190922090910180546001600160a01b0319169091179055949350505050565b80356001600160a01b0381168114610a6a57600080fd5b6000602082840312156116c857600080fd5b610e108261169f565b6000806000606084860312156116e657600080fd5b6116ef8461169f565b92506116fd6020850161169f565b9150604084013590509250925092565b60006080828403121561171f57600080fd5b50919050565b6000806040838503121561173857600080fd5b823567ffffffffffffffff81111561174f57600080fd5b61175b8582860161170d565b92505061176a6020840161169f565b90509250929050565b600080828403608081121561178757600080fd5b833567ffffffffffffffff81111561179e57600080fd5b6117aa8682870161170d565b9350506060601f19820112156117bf57600080fd5b506020830190509250929050565b600080604083850312156117e057600080fd5b6117e98361169f565b915061176a6020840161169f565b80151581146109b857600080fd5b6000806040838503121561181857600080fd5b6118218361169f565b91506020830135611831816117f7565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b8181101561187d5783516001600160a01b031683529284019291840191600101611858565b50909695505050505050565b6000808335601e198436030181126118a057600080fd5b83018035915067ffffffffffffffff8211156118bb57600080fd5b6020019150600681901b36038213156118d357600080fd5b9250929050565b6000604082840312156118ec57600080fd5b6040516040810181811067ffffffffffffffff8211171561191d57634e487b7160e01b600052604160045260246000fd5b6040526119298361169f565b8152602083013560208201528091505092915050565b60006020828403121561195157600080fd5b813567ffffffffffffffff81168114610e1057600080fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561051f5761051f61197f565b6000600182016119ba576119ba61197f565b5060010190565b8581526001600160a01b038581166020808401919091526080604080850182905290840186905260009287929160a08601855b89811015611a215783611a068761169f565b168252858501358583015294820194908201906001016119f4565b5080955050505050508260608301529695505050505050565b600060208284031215611a4c57600080fd5b5051919050565b60005b83811015611a6e578181015183820152602001611a56565b50506000910152565b60008151808452611a8f816020860160208601611a53565b601f01601f19169290920160200192915050565b6000604067ffffffffffffffff8516835260208181850152845160a083860152611ad060e0860182611a77565b905081860151603f1980878403016060880152611aed8383611a77565b88860151888203830160808a01528051808352908601945060009350908501905b80841015611b4057845180516001600160a01b0316835286015186830152938501936001939093019290860190611b0e565b5060608901516001600160a01b031660a08901526080890151888203830160c08a01529550611b6f8187611a77565b9a9950505050505050505050565b60008251611b8f818460208701611a53565b9190910192915050565b600060208284031215611bab57600080fd5b8151610e10816117f7565b8181038181111561051f5761051f61197f565b634e487b7160e01b600052603160045260246000fdfe6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6fa2646970667358221220459e7a213578f685627af41f1eaca18ec17e0264a90695ffafb88ed81b90f9cc64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b4e1ff7882474bb93042be9ad5e1fa387949b86000000000000000000000000072e28c7f34100afefc399fcc0ae041b8fe5841ae000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _endpointAddress (address): 0xB4e1Ff7882474BB93042be9AD5E1fA387949B860
Arg [1] : _owner (address): 0x72E28c7F34100AfefC399fcc0AE041B8fe5841AE
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000b4e1ff7882474bb93042be9ad5e1fa387949b860
Arg [1] : 00000000000000000000000072e28c7f34100afefc399fcc0ae041b8fe5841ae
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
BSC | 27.82% | $691.39 | 0.2376 | $164.28 | |
ARB | 24.19% | $3,250.58 | 0.0439 | $142.81 | |
ARB | 0.14% | $19.91 | 0.042 | $0.8362 | |
ETH | 18.64% | $3,250.43 | 0.0339 | $110.08 | |
BASE | 16.10% | $3,249.86 | 0.0293 | $95.07 | |
BASE | 0.08% | $3,248.04 | 0.00014007 | $0.4549 | |
AVAX | 12.30% | $36.76 | 1.9754 | $72.61 | |
LINEA | 0.47% | $3,250.43 | 0.00085156 | $2.77 | |
WEMIX | 0.18% | $0.876239 | 1.2296 | $1.08 | |
OP | 0.08% | $3,250.58 | 0.00014999 | $0.487546 |
[ 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.