More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 189 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Bridge Native | 329262669 | 9 hrs ago | IN | 0.00135851 ETH | 0.00000393 | ||||
Bridge Native | 328527820 | 2 days ago | IN | 0.00131655 ETH | 0.0000027 | ||||
Bridge Native | 328527482 | 2 days ago | IN | 0.00121705 ETH | 0.0000027 | ||||
Bridge Native | 328168130 | 3 days ago | IN | 0.0103811 ETH | 0.00000271 | ||||
Bridge Native | 327045792 | 6 days ago | IN | 0.30554045 ETH | 0.00011698 | ||||
Bridge Native | 326565453 | 8 days ago | IN | 0.00266722 ETH | 0.00000269 | ||||
Bridge Native | 326481094 | 8 days ago | IN | 0.05037166 ETH | 0.00000272 | ||||
Bridge Native | 325593189 | 11 days ago | IN | 0.08037939 ETH | 0.00000273 | ||||
Bridge Native | 324822921 | 13 days ago | IN | 0.00137441 ETH | 0.00000274 | ||||
Bridge Native | 324160975 | 15 days ago | IN | 0.17744538 ETH | 0.00000274 | ||||
Bridge Native | 323960136 | 15 days ago | IN | 0.07639529 ETH | 0.00000317 | ||||
Bridge Native | 323567237 | 16 days ago | IN | 1.00098559 ETH | 0.00000272 | ||||
Bridge Native | 323499998 | 17 days ago | IN | 0.000436 ETH | 0.00000272 | ||||
Bridge Native | 323255642 | 17 days ago | IN | 0.00073634 ETH | 0.00000274 | ||||
Bridge Native | 322949141 | 18 days ago | IN | 0.01033354 ETH | 0.00000273 | ||||
Bridge Native | 322873163 | 18 days ago | IN | 0.08233752 ETH | 0.00002163 | ||||
Bridge Native | 322424748 | 20 days ago | IN | 0.01312896 ETH | 0.00000276 | ||||
Bridge Native | 322172731 | 21 days ago | IN | 0.10033807 ETH | 0.00000676 | ||||
Bridge Native | 322161394 | 21 days ago | IN | 0.00282302 ETH | 0.00000273 | ||||
Bridge Native | 321694503 | 22 days ago | IN | 0.06132739 ETH | 0.00000275 | ||||
Bridge Native | 321413749 | 23 days ago | IN | 0.0118342 ETH | 0.00000277 | ||||
Bridge Native | 320802160 | 24 days ago | IN | 0.0006255 ETH | 0.00000274 | ||||
Bridge Native | 320736981 | 25 days ago | IN | 0.02031964 ETH | 0.00000271 | ||||
Bridge Native | 320584697 | 25 days ago | IN | 36.02605278 ETH | 0.00000271 | ||||
Bridge Native | 318238000 | 32 days ago | IN | 1.00095544 ETH | 0.00000272 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
329262669 | 9 hrs ago | 0.00007906 ETH | ||||
329262669 | 9 hrs ago | 0.001 ETH | ||||
329130440 | 18 hrs ago | 0.004 ETH | ||||
329130440 | 18 hrs ago | 0.004 ETH | ||||
328931160 | 32 hrs ago | 0.001 ETH | ||||
328931160 | 32 hrs ago | 0.001 ETH | ||||
328527820 | 2 days ago | 0.00080677 ETH | ||||
328527820 | 2 days ago | 0.0002 ETH | ||||
328527482 | 2 days ago | 0.00080677 ETH | ||||
328527482 | 2 days ago | 0.0001 ETH | ||||
328168130 | 3 days ago | 0.00007129 ETH | ||||
328168130 | 3 days ago | 0.01 ETH | ||||
327045792 | 6 days ago | 0.00021557 ETH | ||||
327045792 | 6 days ago | 0.30500109 ETH | ||||
326840057 | 7 days ago | 0.036 ETH | ||||
326840057 | 7 days ago | 0.036 ETH | ||||
326568674 | 8 days ago | 0.001 ETH | ||||
326568674 | 8 days ago | 0.001 ETH | ||||
326565453 | 8 days ago | 0.00086271 ETH | ||||
326565453 | 8 days ago | 0.0015 ETH | ||||
326481094 | 8 days ago | 0.00006318 ETH | ||||
326481094 | 8 days ago | 0.05 ETH | ||||
326042966 | 9 days ago | 0.05 ETH | ||||
326042966 | 9 days ago | 0.05 ETH | ||||
325945710 | 10 days ago | 0.0015 ETH |
Loading...
Loading
Contract Name:
InterportCCIPNativeBridge
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 { IERC165 } from '@chainlink/contracts-ccip/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol'; import { IAny2EVMMessageReceiver } from '@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol'; import { IWrappedNative } from '@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IWrappedNative.sol'; import { Client } from '@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol'; import { InterportCCIPBridgeCore } from './core/InterportCCIPBridgeCore.sol'; import { TargetAppGasMixin } from '../../crosschain/mixins/TargetAppGasMixin.sol'; import '../../helpers/TransferHelper.sol' as TransferHelper; import '../../DataStructures.sol' as DataStructures; /** * @title InterportCCIPNativeBridge * @notice The contract bridges the native network currency (regular and wrapped tokens) with Chainlink CCIP */ contract InterportCCIPNativeBridge is InterportCCIPBridgeCore, TargetAppGasMixin, ReentrancyGuard, IAny2EVMMessageReceiver, IERC165 { /** * @notice The "bridgeNative" action parameters * @param targetChainId The message target chain ID (EVM) * @param targetChainSelector The message target chain selector (CCIP) * @param targetChainPeer The message target peer contract address * @param targetRecipient The address of the recipient on the target chain * @param amount The token amount * @param targetAppGas The target app execution gas */ struct NativeBridgeAction { uint256 targetChainId; uint64 targetChainSelector; address targetChainPeer; address targetRecipient; uint256 amount; uint256 targetAppGas; } /** * @notice The "bridgeNative" conversion flag structure * @param fromWrapped The source chain token conversion flag * @param toWrapped The target chain token conversion flag */ struct NativeBridgeFlags { bool fromWrapped; bool toWrapped; } /** * @notice Cross-chain message data structure * @param actionId The unique identifier of the cross-chain action * @param sourceSender The address of the sender on the source chain * @param toWrapped The target chain token conversion flag * @param targetRecipient The address of the recipient on the target chain */ struct NativeBridgeMessage { uint256 actionId; address sourceSender; bool toWrapped; address targetRecipient; } /** * @notice Wrapped native token info structure * @param token The token address * @param isMessagingToken The messaging token flag * @param amountToReceive The amount to receive * @param amountToApprove The amount to approve */ struct WrappedNativeTokenInfo { address token; bool isMessagingToken; uint256 amountToReceive; uint256 amountToApprove; } /** * @dev The native transfer gas limit */ uint256 public nativeTransferGasLimit; uint256 private lastActionId = block.chainid * 1e10 + 56789 ** 2; /** * @notice Native bridge action source event * @param actionId The ID of the action * @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 fromWrapped The source chain token conversion flag * @param toWrapped The target chain token conversion flag * @param amount The amount of the asset used for the action * @param ccipMessageId The CCIP message ID * @param timestamp The timestamp of the action (in seconds) */ event NativeBridgeActionSource( uint256 indexed actionId, uint256 targetChainId, address indexed sourceSender, address targetRecipient, bool fromWrapped, bool toWrapped, uint256 amount, bytes32 indexed ccipMessageId, uint256 timestamp ); /** * @notice Native bridge action target event * @param actionId The ID of the action * @param toWrapped The target chain token conversion flag * @param replacedWithWrapped The replacement conversion flag * @param timestamp The timestamp of the action (in seconds) */ event NativeBridgeActionTarget( uint256 indexed actionId, bool toWrapped, bool replacedWithWrapped, uint256 timestamp ); /** * @notice Emitted when the target chain app is paused */ event TargetPausedFailure(); /** * @notice Emitted when the message token list is not valid */ event TargetTokenListFailure(); /** * @notice Emitted when the native transfer gas limit is set * @param nativeTransferGasLimit The native transfer gas limit */ event SetNativeTransferGasLimit(uint256 nativeTransferGasLimit); /** * @notice Initializes the contract * @param _endpointAddress The cross-chain endpoint address * @param _minTargetAppGasDefault The default value of minimum target app gas * @param _minTargetAppGasCustomData The custom values of minimum target app gas by standard chain IDs * @param _nativeTransferGasLimit The gas limit for the native transfer * @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, uint256 _minTargetAppGasDefault, DataStructures.KeyToValue[] memory _minTargetAppGasCustomData, uint256 _nativeTransferGasLimit, address _owner, address[] memory _managers, bool _addOwnerToManagers ) InterportCCIPBridgeCore(_endpointAddress, _owner, _managers, _addOwnerToManagers) TargetAppGasMixin(_minTargetAppGasDefault, _minTargetAppGasCustomData) { _setNativeTransferGasLimit(_nativeTransferGasLimit); } /** * @notice Cross-chain bridging of the native token (both regular and wrapped) * @param _action The action parameters * @param _flags The action flags * @param _messagingTokenInfo The messaging token info */ function bridgeNative( NativeBridgeAction calldata _action, NativeBridgeFlags calldata _flags, MessagingTokenInfo calldata _messagingTokenInfo ) external payable whenNotPaused nonReentrant returns (uint256 actionId, bytes32 ccipMessageId) { _checkTargetAppGas(_action.targetChainId, _action.targetAppGas); (bool isNativeMessagingToken, uint256 ccipSendValue) = _checkMessagingTokenInfo( _messagingTokenInfo, _flags.fromWrapped ? 0 : _action.amount ); WrappedNativeTokenInfo memory wrappedNativeTokenInfo = WrappedNativeTokenInfo({ token: _getWrappedNative(), isMessagingToken: false, amountToReceive: (_flags.fromWrapped ? _action.amount : 0), amountToApprove: _action.amount }); if (_messagingTokenInfo.token == wrappedNativeTokenInfo.token) { wrappedNativeTokenInfo.isMessagingToken = true; wrappedNativeTokenInfo.amountToReceive += _messagingTokenInfo.amount; wrappedNativeTokenInfo.amountToApprove += _messagingTokenInfo.messagingAmount; } if (wrappedNativeTokenInfo.amountToReceive != 0) { TransferHelper.safeTransferFrom( wrappedNativeTokenInfo.token, msg.sender, address(this), wrappedNativeTokenInfo.amountToReceive ); } if (!_flags.fromWrapped) { IWrappedNative(wrappedNativeTokenInfo.token).deposit{ value: _action.amount }(); } TransferHelper.safeApprove( wrappedNativeTokenInfo.token, endpoint, wrappedNativeTokenInfo.amountToApprove ); if (!wrappedNativeTokenInfo.isMessagingToken && !isNativeMessagingToken) { TransferHelper.safeTransferFrom( _messagingTokenInfo.token, msg.sender, address(this), _messagingTokenInfo.amount ); TransferHelper.safeApprove( _messagingTokenInfo.token, endpoint, _messagingTokenInfo.messagingAmount ); } actionId = ++lastActionId; bytes memory bridgeMessageData = abi.encode( NativeBridgeMessage({ actionId: actionId, sourceSender: msg.sender, toWrapped: _flags.toWrapped, targetRecipient: _action.targetRecipient == address(0) ? msg.sender : _action.targetRecipient }) ); NativeBridgeAction calldata action = _action; // stack too deep // Create an EVM2AnyMessage struct in memory with necessary information for sending a cross-chain message Client.EVM2AnyMessage memory ccipMessage = _createCcipMessage( _action.targetChainPeer, bridgeMessageData, _createTokenAmounts(wrappedNativeTokenInfo.token, action.amount), action.targetAppGas, _messagingTokenInfo.token ); // Send the message ccipMessageId = _ccipSend(_action.targetChainSelector, ccipMessage, ccipSendValue); TransferHelper.safeApprove(wrappedNativeTokenInfo.token, endpoint, 0); if (!wrappedNativeTokenInfo.isMessagingToken && !isNativeMessagingToken) { TransferHelper.safeApprove(_messagingTokenInfo.token, endpoint, 0); } NativeBridgeFlags calldata flags = _flags; // stack too deep emit NativeBridgeActionSource( actionId, action.targetChainId, msg.sender, action.targetRecipient, flags.fromWrapped, flags.toWrapped, action.amount, ccipMessageId, block.timestamp ); } /** * @notice Receives cross-chain messages * @dev The function is called by the cross-chain endpoint * @param _message The structure containing the message data */ function ccipReceive( Client.Any2EVMMessage calldata _message ) external override nonReentrant onlyEndpoint { if (paused()) { emit TargetPausedFailure(); return; } address wrappedNativeToken = _getWrappedNative(); if ( _message.destTokenAmounts.length != 1 || _message.destTokenAmounts[0].token != wrappedNativeToken ) { emit TargetTokenListFailure(); return; } NativeBridgeMessage memory bridgeMessage = abi.decode(_message.data, (NativeBridgeMessage)); uint256 tokenAmount = _message.destTokenAmounts[0].amount; bool replacedWithWrapped; if (bridgeMessage.toWrapped) { TransferHelper.safeTransfer( wrappedNativeToken, bridgeMessage.targetRecipient, tokenAmount ); } else { IWrappedNative(wrappedNativeToken).withdraw(tokenAmount); (bool success, ) = payable(bridgeMessage.targetRecipient).call{ value: tokenAmount, gas: nativeTransferGasLimit }(''); if (!success) { // Send WETH to the recipient address IWrappedNative(wrappedNativeToken).deposit{ value: tokenAmount }(); TransferHelper.safeTransfer( wrappedNativeToken, bridgeMessage.targetRecipient, tokenAmount ); replacedWithWrapped = true; } } emit NativeBridgeActionTarget( bridgeMessage.actionId, bridgeMessage.toWrapped, replacedWithWrapped, block.timestamp ); } /** * @notice Sets the native transfer gas limit * @param _nativeTransferGasLimit The native transfer gas limit */ function setNativeTransferGasLimit(uint256 _nativeTransferGasLimit) external onlyManager { _setNativeTransferGasLimit(_nativeTransferGasLimit); } /** * @notice Cross-chain message fee estimation * @param _action The action parameters * @param _messagingToken The messaging token address * @return Message fee */ function messageFee( NativeBridgeAction calldata _action, address _messagingToken ) external view returns (uint256) { _checkTargetAppGas(_action.targetChainId, _action.targetAppGas); bytes memory bridgeMessageData = abi.encode( NativeBridgeMessage({ actionId: lastActionId + 1, // estimate only sourceSender: msg.sender, toWrapped: true, // estimate only targetRecipient: _action.targetRecipient == address(0) ? msg.sender : _action.targetRecipient }) ); Client.EVM2AnyMessage memory ccipMessage = _createCcipMessage( _action.targetChainPeer, bridgeMessageData, _createTokenAmounts(_getWrappedNative(), _action.amount), _action.targetAppGas, _messagingToken ); return _ccipGetFee(_action.targetChainSelector, ccipMessage); } /** * @notice The interface support query * @param _interfaceId The interface identifier (ERC-165) * @return The interface support flag */ function supportsInterface(bytes4 _interfaceId) external pure override returns (bool) { return _interfaceId == type(IAny2EVMMessageReceiver).interfaceId || _interfaceId == type(IERC165).interfaceId; } function _setNativeTransferGasLimit(uint256 _nativeTransferGasLimit) private { if (_nativeTransferGasLimit == 0) { _nativeTransferGasLimit = type(uint256).max; } nativeTransferGasLimit = _nativeTransferGasLimit; emit SetNativeTransferGasLimit(_nativeTransferGasLimit); } function _getWrappedNative() private view returns (address) { return IEndpointWrappedNative(endpoint).getWrappedNative(); } function _createTokenAmounts( address _wrappedNativeToken, uint256 _amount ) private pure returns (Client.EVMTokenAmount[] memory) { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); tokenAmounts[0] = Client.EVMTokenAmount({ token: _wrappedNativeToken, amount: _amount }); return tokenAmounts; } } interface IEndpointWrappedNative { function getWrappedNative() external view returns (address); }
// 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 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; import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; interface IWrappedNative is IERC20 { function deposit() external payable; function withdraw(uint256 wad) external; }
// 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.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @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 amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` 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 amount) 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 `amount` 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 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` 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 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.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; import { ManagerRole } from '../../roles/ManagerRole.sol'; import '../../DataStructures.sol' as DataStructures; /** * @title TargetAppGasMixin * @notice The target app gas mix-in logic */ abstract contract TargetAppGasMixin is ManagerRole { /** * @dev The default value of minimum target app gas */ uint256 public minTargetAppGasDefault; /** * @dev The custom values of minimum target app gas by standard chain IDs */ mapping(uint256 standardChainId => DataStructures.OptionalValue minTargetAppGas) public minTargetAppGasCustom; /** * @notice Emitted when the default value of minimum target app gas is set * @param minTargetAppGas The value of minimum target app gas */ event SetMinTargetAppGasDefault(uint256 minTargetAppGas); /** * @notice Emitted when the custom value of minimum target app gas is set * @param standardChainId The standard EVM chain ID * @param minTargetAppGas The value of minimum target app gas */ event SetMinTargetAppGasCustom(uint256 standardChainId, uint256 minTargetAppGas); /** * @notice Emitted when the custom value of minimum target app gas is removed * @param standardChainId The standard EVM chain ID */ event RemoveMinTargetAppGasCustom(uint256 standardChainId); /** * @notice Emitted when the provided target app gas value is not sufficient for the message processing */ error MinTargetAppGasError(); /** * @notice Initializes the contract * @param _minTargetAppGasDefault The default value of minimum target app gas * @param _minTargetAppGasCustomData The custom values of minimum target app gas by standard chain IDs */ constructor( uint256 _minTargetAppGasDefault, DataStructures.KeyToValue[] memory _minTargetAppGasCustomData ) { _setMinTargetAppGasDefault(_minTargetAppGasDefault); for (uint256 index; index < _minTargetAppGasCustomData.length; index++) { DataStructures.KeyToValue memory minTargetAppGasCustomEntry = _minTargetAppGasCustomData[index]; _setMinTargetAppGasCustom( minTargetAppGasCustomEntry.key, minTargetAppGasCustomEntry.value ); } } /** * @notice Sets the default value of minimum target app gas * @param _minTargetAppGas The value of minimum target app gas */ function setMinTargetAppGasDefault(uint256 _minTargetAppGas) external virtual onlyManager { _setMinTargetAppGasDefault(_minTargetAppGas); } /** * @notice Sets the custom value of minimum target app gas by the standard chain ID * @param _standardChainId The standard EVM ID of the target chain * @param _minTargetAppGas The value of minimum target app gas */ function setMinTargetAppGasCustom( uint256 _standardChainId, uint256 _minTargetAppGas ) external virtual onlyManager { _setMinTargetAppGasCustom(_standardChainId, _minTargetAppGas); } /** * @notice Removes the custom value of minimum target app gas by the standard chain ID * @param _standardChainId The standard EVM ID of the target chain */ function removeMinTargetAppGasCustom(uint256 _standardChainId) external virtual onlyManager { _removeMinTargetAppGasCustom(_standardChainId); } /** * @notice The value of minimum target app gas by the standard chain ID * @param _standardChainId The standard EVM ID of the target chain * @return The value of minimum target app gas */ function minTargetAppGas(uint256 _standardChainId) public view virtual returns (uint256) { DataStructures.OptionalValue storage optionalValue = minTargetAppGasCustom[ _standardChainId ]; if (optionalValue.isSet) { return optionalValue.value; } return minTargetAppGasDefault; } function _setMinTargetAppGasDefault(uint256 _minTargetAppGas) internal virtual { minTargetAppGasDefault = _minTargetAppGas; emit SetMinTargetAppGasDefault(_minTargetAppGas); } function _setMinTargetAppGasCustom( uint256 _standardChainId, uint256 _minTargetAppGas ) internal virtual { minTargetAppGasCustom[_standardChainId] = DataStructures.OptionalValue({ isSet: true, value: _minTargetAppGas }); emit SetMinTargetAppGasCustom(_standardChainId, _minTargetAppGas); } function _removeMinTargetAppGasCustom(uint256 _standardChainId) internal virtual { delete minTargetAppGasCustom[_standardChainId]; emit RemoveMinTargetAppGasCustom(_standardChainId); } function _checkTargetAppGas( uint256 _targetChainId, uint256 _targetAppGas ) internal view virtual { if (_targetAppGas < minTargetAppGas(_targetChainId)) { revert MinTargetAppGasError(); } } }
// 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
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_endpointAddress","type":"address"},{"internalType":"uint256","name":"_minTargetAppGasDefault","type":"uint256"},{"components":[{"internalType":"uint256","name":"key","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct KeyToValue[]","name":"_minTargetAppGasCustomData","type":"tuple[]"},{"internalType":"uint256","name":"_nativeTransferGasLimit","type":"uint256"},{"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":"MinTargetAppGasError","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":"uint256","name":"actionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"targetChainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"sourceSender","type":"address"},{"indexed":false,"internalType":"address","name":"targetRecipient","type":"address"},{"indexed":false,"internalType":"bool","name":"fromWrapped","type":"bool"},{"indexed":false,"internalType":"bool","name":"toWrapped","type":"bool"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"ccipMessageId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"NativeBridgeActionSource","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"actionId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"toWrapped","type":"bool"},{"indexed":false,"internalType":"bool","name":"replacedWithWrapped","type":"bool"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"NativeBridgeActionTarget","type":"event"},{"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":false,"internalType":"uint256","name":"standardChainId","type":"uint256"}],"name":"RemoveMinTargetAppGasCustom","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":"standardChainId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minTargetAppGas","type":"uint256"}],"name":"SetMinTargetAppGasCustom","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"minTargetAppGas","type":"uint256"}],"name":"SetMinTargetAppGasDefault","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"nativeTransferGasLimit","type":"uint256"}],"name":"SetNativeTransferGasLimit","type":"event"},{"anonymous":false,"inputs":[],"name":"TargetPausedFailure","type":"event"},{"anonymous":false,"inputs":[],"name":"TargetTokenListFailure","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":"targetChainPeer","type":"address"},{"internalType":"address","name":"targetRecipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"targetAppGas","type":"uint256"}],"internalType":"struct InterportCCIPNativeBridge.NativeBridgeAction","name":"_action","type":"tuple"},{"components":[{"internalType":"bool","name":"fromWrapped","type":"bool"},{"internalType":"bool","name":"toWrapped","type":"bool"}],"internalType":"struct InterportCCIPNativeBridge.NativeBridgeFlags","name":"_flags","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":"bridgeNative","outputs":[{"internalType":"uint256","name":"actionId","type":"uint256"},{"internalType":"bytes32","name":"ccipMessageId","type":"bytes32"}],"stateMutability":"payable","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":[{"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":"targetChainPeer","type":"address"},{"internalType":"address","name":"targetRecipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"targetAppGas","type":"uint256"}],"internalType":"struct InterportCCIPNativeBridge.NativeBridgeAction","name":"_action","type":"tuple"},{"internalType":"address","name":"_messagingToken","type":"address"}],"name":"messageFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_standardChainId","type":"uint256"}],"name":"minTargetAppGas","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"standardChainId","type":"uint256"}],"name":"minTargetAppGasCustom","outputs":[{"internalType":"bool","name":"isSet","type":"bool"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minTargetAppGasDefault","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nativeTransferGasLimit","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":[{"internalType":"uint256","name":"_standardChainId","type":"uint256"}],"name":"removeMinTargetAppGasCustom","outputs":[],"stateMutability":"nonpayable","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":"uint256","name":"_standardChainId","type":"uint256"},{"internalType":"uint256","name":"_minTargetAppGas","type":"uint256"}],"name":"setMinTargetAppGasCustom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minTargetAppGas","type":"uint256"}],"name":"setMinTargetAppGasDefault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nativeTransferGasLimit","type":"uint256"}],"name":"setNativeTransferGasLimit","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":[{"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
608060405262000015466402540be400620007a0565b620000259063c0397339620007ba565b6008553480156200003557600080fd5b50604051620031dd380380620031dd833981016040819052620000589162000914565b6000805460ff1916905585858885858562000073336200011e565b6200007e8462000177565b6200008b838383620001cc565b50505050620000a0826200028660201b60201c565b60005b8151811015620000fe576000828281518110620000c457620000c462000a58565b60200260200101519050620000e881600001518260200151620002c260201b60201c565b5080620000f58162000a6e565b915050620000a3565b5050600160065550620001118462000335565b5050505050505062000ab6565b600080546001600160a01b03838116610100818102610100600160a81b0319851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b620001828162000379565b600380546001600160a01b0319166001600160a01b0383169081179091556040517fc8e81a4efc849969069ec6aae575cf7a6bc5f9d3abac59f4ed190a6f7e05fc6f90600090a250565b60006001600160a01b03841615620001e55783620001e7565b335b905060005b83518110156200023a57620002258482815181106200020f576200020f62000a58565b60200260200101516001620003b560201b60201c565b80620002318162000a6e565b915050620001ec565b508180156200025157506200024f8162000428565b155b15620002645762000264816001620003b5565b6001600160a01b0381163314620002805762000280816200046a565b50505050565b60048190556040518181527f7d13ea4e82ca085561ddd42a2f1080d88b527444721ee7803f603decd203ff23906020015b60405180910390a150565b604080518082018252600180825260208083018581526000878152600583528590209351845460ff191690151517845551929091019190915581518481529081018390527f2ee636de87a5f853f736b571d71f38b0eaa7a494ab78d545a4e69975fb3a0e3f910160405180910390a15050565b806000036200034357506000195b60078190556040518181527f07f2da272b0090c4177cfbb7f50d00e3ed4d37c9445216ca7efbc245d7b5b0ac90602001620002b7565b6001600160a01b0381163b620003b257604051638c50d7cd60e01b81526001600160a01b03821660048201526024015b60405180910390fd5b50565b620003bf620004e6565b620003ec7f6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f83836200054a565b604051811515906001600160a01b038416907fbe9474bb3e78da7e315cdffa5cfa30b767fcc95bbf44a6197da60228eea1028690600090a35050565b6001600160a01b03811660009081527f260b29b219d450563ddb0e5ca806bdadb1e125f7e8c506de0443797dd7122728602052604081205460ff165b92915050565b62000474620004e6565b6001600160a01b038116620004db5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620003a9565b620003b2816200011e565b6000546001600160a01b03610100909104163314620005485760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620003a9565b565b6000838152600160209081526040808320600290925290912062000280919084846064600082620005885762000582868686620005a0565b62000596565b6200059686868685620006d5565b9695505050505050565b6001600160a01b0381166000908152602083905260409020805460ff16908115620006cd5760018082015486549091600091620005de919062000a8a565b905080821462000672576000878281548110620005ff57620005ff62000a58565b9060005260206000200160009054906101000a90046001600160a01b031690508088848154811062000635576200063562000a58565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905592909116815290879052604090206001018290555b8680548062000685576200068562000aa0565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038716825287905260408120805460ff191681556001015550505b509392505050565b6001600160a01b03821660009081526020849052604090205460ff161580156200078257845482116200071b5760405163b1655e3360e01b815260040160405180910390fd5b6040805180820182526001808252875460208084019182526001600160a01b03881660008181528a83529586209451855460ff1916901515178555915193830193909355885491820189558884529190922090910180546001600160a01b03191690911790555b949350505050565b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176200046457620004646200078a565b808201808211156200046457620004646200078a565b80516001600160a01b0381168114620007e857600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715620008285762000828620007ed565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620008595762000859620007ed565b604052919050565b60006001600160401b038211156200087d576200087d620007ed565b5060051b60200190565b600082601f8301126200089957600080fd5b81516020620008b2620008ac8362000861565b6200082e565b82815260059290921b84018101918181019086841115620008d257600080fd5b8286015b84811015620008f857620008ea81620007d0565b8352918301918301620008d6565b509695505050505050565b80518015158114620007e857600080fd5b600080600080600080600060e0888a0312156200093057600080fd5b6200093b88620007d0565b602089015160408a015191985096506001600160401b03808211156200096057600080fd5b818a0191508a601f8301126200097557600080fd5b815162000986620008ac8262000861565b8082825260208201915060208360061b86010192508d831115620009a957600080fd5b6020850194505b82851015620009f8576040858f031215620009ca57600080fd5b620009d462000803565b855181526020860151602082015280835250602082019150604085019450620009b0565b80995050505060608a0151955062000a1360808b01620007d0565b945060a08a015191508082111562000a2a57600080fd5b5062000a398a828b0162000887565b92505062000a4a60c0890162000903565b905092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b60006001820162000a835762000a836200078a565b5060010190565b818103818111156200046457620004646200078a565b634e487b7160e01b600052603160045260246000fd5b6127178062000ac66000396000f3fe6080604052600436106101d15760003560e01c806385572ffb116100f7578063c93c48e111610095578063e3725b1511610064578063e3725b151461058e578063eedc966a146105b0578063f2fde38b146105d0578063f3ae2415146105f057600080fd5b8063c93c48e114610522578063d631752614610538578063dbbb41551461054e578063dd31d3941461056e57600080fd5b80639449c655116100d15780639449c655146104ad578063a5e90eee146104cd578063c2c518e1146104ed578063c39044821461050257600080fd5b806385572ffb146104195780638da5cb5b14610439578063908896611461045c57600080fd5b806342e3ff551161016f5780635e280f111161013e5780635e280f1114610397578063715018a6146103cf57806383d85346146103e45780638456cb591461040457600080fd5b806342e3ff551461031e578063440d72481461033e5780635c975abb1461035f5780635d2251d51461037757600080fd5b80630a5ec8cc116101ab5780630a5ec8cc14610276578063103b73971461029657806312bfe175146102e15780633f4ba83a1461030957600080fd5b806301ffc9a7146101dd57806307bce0b414610212578063093f0e271461023457600080fd5b366101d857005b600080fd5b3480156101e957600080fd5b506101fd6101f836600461208c565b610610565b60405190151581526020015b60405180910390f35b34801561021e57600080fd5b5061023261022d3660046120b6565b610647565b005b34801561024057600080fd5b506102687f22ad9585a395edc8067b50da4778cafbb7fa2c4bbd7619fad6aeba403857fd7481565b604051908152602001610209565b34801561028257600080fd5b506102326102913660046120d8565b61067b565b3480156102a257600080fd5b506000805160206126c283398151915260005260016020527f3c2285c553468ca8f30447b24bb463c127f1b840e23a0cafa23caa79d906669a54610268565b6102f46102ef366004612109565b6106b2565b60408051928352602083019190915201610209565b34801561031557600080fd5b50610232610ae3565b34801561032a57600080fd5b5061026861033936600461217a565b610b1b565b34801561034a57600080fd5b506101fd6103593660046121b2565b50600090565b34801561036b57600080fd5b5060005460ff166101fd565b34801561038357600080fd5b506102326103923660046121cf565b610c1e565b3480156103a357600080fd5b506003546103b7906001600160a01b031681565b6040516001600160a01b039091168152602001610209565b3480156103db57600080fd5b50610232610c54565b3480156103f057600080fd5b506102326103ff366004612210565b610c66565b34801561041057600080fd5b50610232610c9f565b34801561042557600080fd5b5061023261043436600461223e565b610cd5565b34801561044557600080fd5b5060005461010090046001600160a01b03166103b7565b34801561046857600080fd5b506104966104773660046120d8565b6005602052600090815260409020805460019091015460ff9091169082565b604080519215158352602083019190915201610209565b3480156104b957600080fd5b506102326104c83660046120d8565b610fcd565b3480156104d957600080fd5b506102326104e8366004612287565b610ffc565b3480156104f957600080fd5b50610232611059565b34801561050e57600080fd5b5061026861051d3660046120d8565b6110c6565b34801561052e57600080fd5b5061026860045481565b34801561054457600080fd5b5061026860075481565b34801561055a57600080fd5b506102326105693660046121b2565b6110f2565b34801561057a57600080fd5b506102326105893660046120d8565b611121565b34801561059a57600080fd5b506105a3611150565b60405161020991906122b5565b3480156105bc57600080fd5b506102686105cb3660046121b2565b611169565b3480156105dc57600080fd5b506102326105eb3660046121b2565b6111ff565b3480156105fc57600080fd5b506101fd61060b3660046121b2565b61127a565b60006001600160e01b031982166385572ffb60e01b148061064157506001600160e01b031982166301ffc9a760e01b145b92915050565b6106503361127a565b61066d57604051637c3ea23f60e01b815260040160405180910390fd5b61067782826112ba565b5050565b6106843361127a565b6106a157604051637c3ea23f60e01b815260040160405180910390fd5b6106aa8161132d565b50565b905090565b6000806106bd611376565b6106c56113bc565b6106d4853560a0870135611415565b6000806106fd856106e86020890189612302565b6106f657886080013561143e565b600061143e565b91509150600060405180608001604052806107166114df565b6001600160a01b031681526020016000151581526020018860000160208101906107409190612302565b61074b576000610751565b89608001355b815260808a013560209182015281519192506001600160a01b039091169061077b908801886121b2565b6001600160a01b0316036107c957600160208083019190915260408201805191880135916107aa908390612335565b905250606081018051604088013591906107c5908390612335565b9052505b6040810151156107e7576107e781600001513330846040015161154d565b6107f46020880188612302565b6108555780600001516001600160a01b031663d0e30db089608001356040518263ffffffff1660e01b81526004016000604051808303818588803b15801561083b57600080fd5b505af115801561084f573d6000803e3d6000fd5b50505050505b8051600354606083015161087392916001600160a01b031690611648565b8060200151158015610883575082155b156108ca576108a461089860208801886121b2565b3330896020013561154d565b6108ca6108b460208801886121b2565b6003546001600160a01b03166040890135611648565b6008600081546108d990612348565b919050819055945060006040518060800160405280878152602001336001600160a01b031681526020018960200160208101906109169190612302565b15158152602001600061092f60808d0160608e016121b2565b6001600160a01b0316146109525761094d60808c0160608d016121b2565b610954565b335b6001600160a01b0316905260405161096f9190602001612361565b60405160208183030381529060405290503689905060006109c68b604001602081019061099c91906121b2565b846109af8760000151866080013561173a565b60a08601356109c160208f018f6121b2565b6117c1565b90506109e26109db60408d0160208e0161239d565b82876118a5565b84516003549198506109fe916001600160a01b03166000611648565b8360200151158015610a0e575085155b15610a3657610a36610a2360208b018b6121b2565b6003546001600160a01b03166000611648565b8987338a7f4047d821f29c05dd3ee1c2410f84e686cafd8c2023d02b40ae8d30fe35c1f5218635610a6d6080890160608a016121b2565b610a7a6020880188612302565b610a8a6040890160208a01612302565b604080519485526001600160a01b039390931660208501529015158383015215156060830152608089810135908301524260a0830152519081900360c00190a450505050505050610adb6001600655565b935093915050565b610aec3361127a565b610b0957604051637c3ea23f60e01b815260040160405180910390fd5b610b11611925565b610b1961196e565b565b6000610b2c833560a0850135611415565b600060405180608001604052806008546001610b489190612335565b815233602082015260016040820152606090810190600090610b7090608089019089016121b2565b6001600160a01b031614610b9357610b8e60808701606088016121b2565b610b95565b335b6001600160a01b03169052604051610bb09190602001612361565b60405160208183030381529060405290506000610bfa856040016020810190610bd991906121b2565b83610bef610be56114df565b896080013561173a565b8860a00135886117c1565b9050610c15610c0f604087016020880161239d565b826119c0565b95945050505050565b610c273361127a565b610c4457604051637c3ea23f60e01b815260040160405180910390fd5b610c4f838383611a3b565b505050565b610c5c611a75565b610b196000611ad5565b610c6f3361127a565b610c8c57604051637c3ea23f60e01b815260040160405180910390fd5b6106778282610c9a85611169565b611a3b565b610ca83361127a565b610cc557604051637c3ea23f60e01b815260040160405180910390fd5b610ccd611376565b610b19611b2e565b610cdd6113bc565b6003546001600160a01b03163314610d085760405163d9b0b35560e01b815260040160405180910390fd5b60005460ff1615610d41576040517febfa14817ead60a20b8a0fc2f6e70025b7414b60eeb0f786c0446e7e543db64b90600090a1610fc3565b6000610d4b6114df565b9050610d5a60808301836123c7565b90506001141580610db057506001600160a01b038116610d7d60808401846123c7565b6000818110610d8e57610d8e612418565b610da492602060409092020190810191506121b2565b6001600160a01b031614155b15610de4576040517f059a1c5131f929faf5414939857c4e1750baf6110d2cbb9b066c50d7be32185590600090a150610fc3565b6000610df3606084018461242e565b810190610e009190612475565b90506000610e1160808501856123c7565b6000818110610e2257610e22612418565b9050604002016020013590506000826040015115610e4e57610e4984846060015184611b6b565b610f76565b604051632e1a7d4d60e01b8152600481018390526001600160a01b03851690632e1a7d4d90602401600060405180830381600087803b158015610e9057600080fd5b505af1158015610ea4573d6000803e3d6000fd5b50505050600083606001516001600160a01b03168360075490604051600060405180830381858888f193505050503d8060008114610efe576040519150601f19603f3d011682016040523d82523d6000602084013e610f03565b606091505b5050905080610f7457846001600160a01b031663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b158015610f4757600080fd5b505af1158015610f5b573d6000803e3d6000fd5b5050505050610f6f85856060015185611b6b565b600191505b505b8251604080850151815190151581528315156020820152428183015290517faf1680666074a12cad20d06bb9b7190e4b9460e835839411024947eb079a7b779181900360600190a2505050505b6106aa6001600655565b610fd63361127a565b610ff357604051637c3ea23f60e01b815260040160405180910390fd5b6106aa81611c55565b611004611a75565b61101d6000805160206126c28339815191528383611ca3565b604051811515906001600160a01b038416907fbe9474bb3e78da7e315cdffa5cfa30b767fcc95bbf44a6197da60228eea1028690600090a35050565b6110623361127a565b61107f57604051637c3ea23f60e01b815260040160405180910390fd5b6110996000805160206126c2833981519152336000611ca3565b60405133907f6cc2c67081f55c2fffb7c008fa995fbbf890f48c7c16fba93d8220f00dc84cc590600090a2565b6000818152600560205260408120805460ff16156110e8576001015492915050565b5050600454919050565b6110fb3361127a565b61111857604051637c3ea23f60e01b815260040160405180910390fd5b6106aa81611cd0565b61112a3361127a565b61114757604051637c3ea23f60e01b815260040160405180910390fd5b6106aa81611d23565b60606106ad6000805160206126c2833981519152611d58565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03831601611197575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa1580156111db573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064191906124ff565b611207611a75565b6001600160a01b0381166112715760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6106aa81611ad5565b6001600160a01b03811660009081527f260b29b219d450563ddb0e5ca806bdadb1e125f7e8c506de0443797dd7122728602052604081205460ff16610641565b604080518082018252600180825260208083018581526000878152600583528590209351845460ff191690151517845551929091019190915581518481529081018390527f2ee636de87a5f853f736b571d71f38b0eaa7a494ab78d545a4e69975fb3a0e3f910160405180910390a15050565b8060000361133a57506000195b60078190556040518181527f07f2da272b0090c4177cfbb7f50d00e3ed4d37c9445216ca7efbc245d7b5b0ac906020015b60405180910390a150565b60005460ff1615610b195760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401611268565b60026006540361140e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611268565b6002600655565b61141e826110c6565b81101561067757604051630acdd10560e31b815260040160405180910390fd5b60008083604001358460200135101561146a57604051637367509b60e01b815260040160405180910390fd5b600061147960208601866121b2565b6001600160a01b031614915060008261149257836114a0565b6114a0846020870135612335565b9050803410156114c357604051637dd7aa2160e01b815260040160405180910390fd5b826114cf5760006114d5565b84604001355b9150509250929050565b6003546040805163e861e90760e01b815290516000926001600160a01b03169163e861e9079160048083019260209291908290030181865afa158015611529573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ad9190612518565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916115b19190612559565b6000604051808303816000865af19150503d80600081146115ee576040519150601f19603f3d011682016040523d82523d6000602084013e6115f3565b606091505b5091509150600082801561161f57508151158061161f57508180602001905181019061161f9190612575565b90508061163f57604051632d9d5b4160e01b815260040160405180910390fd5b50505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392908716916116a49190612559565b6000604051808303816000865af19150503d80600081146116e1576040519150601f19603f3d011682016040523d82523d6000602084013e6116e6565b606091505b509150915060008280156117125750815115806117125750818060200190518101906117129190612575565b9050806117325760405163b45d44e760e01b815260040160405180910390fd5b505050505050565b60408051600180825281830190925260609160009190816020015b60408051808201909152600080825260208201528152602001906001900390816117555790505090506040518060400160405280856001600160a01b0316815260200184815250816000815181106117af576117af612418565b60209081029190910101529392505050565b6117fc6040518060a0016040528060608152602001606081526020016060815260200160006001600160a01b03168152602001606081525090565b6040805160a081019091526001600160a01b03871660c08201528060e081016040516020818303038152906040528152602001868152602001858152602001836001600160a01b0316815260200161189960405180602001604052808781525060408051915160248084019190915281518084039091018152604490920190526020810180516001600160e01b03166397a657c960e01b17905290565b90529695505050505050565b6003546040516396f4e9f960e01b81526000916001600160a01b0316906396f4e9f99084906118da90889088906004016125be565b60206040518083038185885af11580156118f8573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061191d91906124ff565b949350505050565b60005460ff16610b195760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401611268565b611976611925565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6003546040516320487ded60e01b81526000916001600160a01b0316906320487ded906119f390869086906004016125be565b602060405180830381865afa158015611a10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3491906124ff565b9392505050565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03841601611a6a57610c4f8282611dc4565b610c4f838383611b6b565b6000546001600160a01b03610100909104163314610b195760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611268565b600080546001600160a01b03838116610100818102610100600160a81b0319851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b611b36611376565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586119a33390565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691611bc79190612559565b6000604051808303816000865af19150503d8060008114611c04576040519150601f19603f3d011682016040523d82523d6000602084013e611c09565b606091505b50915091506000828015611c35575081511580611c35575081806020019051810190611c359190612575565b90508061173257604051632fdb1b7f60e11b815260040160405180910390fd5b600081815260056020526040808220805460ff1916815560010191909155517f2449b10e63f8d71e042b39939d3c5423f003860c5371eb09ecfd7435d681a78e9061136b9083815260200190565b60008381526001602090815260408083206002909252909120611cca919084846064611e52565b50505050565b611cd981611e7f565b600380546001600160a01b0319166001600160a01b0383169081179091556040517fc8e81a4efc849969069ec6aae575cf7a6bc5f9d3abac59f4ed190a6f7e05fc6f90600090a250565b60048190556040518181527f7d13ea4e82ca085561ddd42a2f1080d88b527444721ee7803f603decd203ff239060200161136b565b600081815260016020908152604091829020805483518184028101840190945280845260609392830182828015611db857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611d9a575b50505050509050919050565b604080516000808252602082019092526001600160a01b038416908390604051611dee9190612559565b60006040518083038185875af1925050503d8060008114611e2b576040519150601f19603f3d011682016040523d82523d6000602084013e611e30565b606091505b5050905080610c4f57604051632e05b05360e21b815260040160405180910390fd5b600082611e6957611e64868686611eb2565b611e75565b611e7586868685611fda565b9695505050505050565b6001600160a01b0381163b6106aa57604051638c50d7cd60e01b81526001600160a01b0382166004820152602401611268565b6001600160a01b0381166000908152602083905260409020805460ff16908115611fd25760018082015486549091600091611eed9190612698565b9050808214611f7a576000878281548110611f0a57611f0a612418565b9060005260206000200160009054906101000a90046001600160a01b0316905080888481548110611f3d57611f3d612418565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905592909116815290879052604090206001018290555b86805480611f8a57611f8a6126ab565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038716825287905260408120805460ff191681556001015550505b509392505050565b6001600160a01b03821660009081526020849052604090205460ff1615801561191d578454821161201e5760405163b1655e3360e01b815260040160405180910390fd5b6040805180820182526001808252875460208084019182526001600160a01b03881660008181528a83529586209451855460ff1916901515178555915193830193909355885491820189558884529190922090910180546001600160a01b0319169091179055949350505050565b60006020828403121561209e57600080fd5b81356001600160e01b031981168114611a3457600080fd5b600080604083850312156120c957600080fd5b50508035926020909101359150565b6000602082840312156120ea57600080fd5b5035919050565b600060c0828403121561210357600080fd5b50919050565b600080600083850361016081121561212057600080fd5b61212a86866120f1565b9350604060bf198201121561213e57600080fd5b60c085019250606060ff198201121561215657600080fd5b50610100840190509250925092565b6001600160a01b03811681146106aa57600080fd5b60008060e0838503121561218d57600080fd5b61219784846120f1565b915060c08301356121a781612165565b809150509250929050565b6000602082840312156121c457600080fd5b8135611a3481612165565b6000806000606084860312156121e457600080fd5b83356121ef81612165565b925060208401356121ff81612165565b929592945050506040919091013590565b6000806040838503121561222357600080fd5b823561222e81612165565b915060208301356121a781612165565b60006020828403121561225057600080fd5b813567ffffffffffffffff81111561226757600080fd5b820160a08185031215611a3457600080fd5b80151581146106aa57600080fd5b6000806040838503121561229a57600080fd5b82356122a581612165565b915060208301356121a781612279565b6020808252825182820181905260009190848201906040850190845b818110156122f65783516001600160a01b0316835292840192918401916001016122d1565b50909695505050505050565b60006020828403121561231457600080fd5b8135611a3481612279565b634e487b7160e01b600052601160045260246000fd5b808201808211156106415761064161231f565b60006001820161235a5761235a61231f565b5060010190565b815181526020808301516001600160a01b0390811691830191909152604080840151151590830152606092830151169181019190915260800190565b6000602082840312156123af57600080fd5b813567ffffffffffffffff81168114611a3457600080fd5b6000808335601e198436030181126123de57600080fd5b83018035915067ffffffffffffffff8211156123f957600080fd5b6020019150600681901b360382131561241157600080fd5b9250929050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261244557600080fd5b83018035915067ffffffffffffffff82111561246057600080fd5b60200191503681900382131561241157600080fd5b60006080828403121561248757600080fd5b6040516080810181811067ffffffffffffffff821117156124b857634e487b7160e01b600052604160045260246000fd5b6040528235815260208301356124cd81612165565b602082015260408301356124e081612279565b604082015260608301356124f381612165565b60608201529392505050565b60006020828403121561251157600080fd5b5051919050565b60006020828403121561252a57600080fd5b8151611a3481612165565b60005b83811015612550578181015183820152602001612538565b50506000910152565b6000825161256b818460208701612535565b9190910192915050565b60006020828403121561258757600080fd5b8151611a3481612279565b600081518084526125aa816020860160208601612535565b601f01601f19169290920160200192915050565b6000604067ffffffffffffffff8516835260208181850152845160a0838601526125eb60e0860182612592565b905081860151603f19808784030160608801526126088383612592565b88860151888203830160808a01528051808352908601945060009350908501905b8084101561265b57845180516001600160a01b0316835286015186830152938501936001939093019290860190612629565b5060608901516001600160a01b031660a08901526080890151888203830160c08a0152955061268a8187612592565b9a9950505050505050505050565b818103818111156106415761064161231f565b634e487b7160e01b600052603160045260246000fdfe6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6fa2646970667358221220f4b0d6e8effb71d20dd9840d2ef24d38185d22720304d0f0103bca7f80ea66cf64736f6c63430008130033000000000000000000000000141fa059441e0ca23ce184b6a78bafd2a517dde8000000000000000000000000000000000000000000000000000000000001d4c000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000300c00000000000000000000000072e28c7f34100afefc399fcc0ae041b8fe5841ae0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106101d15760003560e01c806385572ffb116100f7578063c93c48e111610095578063e3725b1511610064578063e3725b151461058e578063eedc966a146105b0578063f2fde38b146105d0578063f3ae2415146105f057600080fd5b8063c93c48e114610522578063d631752614610538578063dbbb41551461054e578063dd31d3941461056e57600080fd5b80639449c655116100d15780639449c655146104ad578063a5e90eee146104cd578063c2c518e1146104ed578063c39044821461050257600080fd5b806385572ffb146104195780638da5cb5b14610439578063908896611461045c57600080fd5b806342e3ff551161016f5780635e280f111161013e5780635e280f1114610397578063715018a6146103cf57806383d85346146103e45780638456cb591461040457600080fd5b806342e3ff551461031e578063440d72481461033e5780635c975abb1461035f5780635d2251d51461037757600080fd5b80630a5ec8cc116101ab5780630a5ec8cc14610276578063103b73971461029657806312bfe175146102e15780633f4ba83a1461030957600080fd5b806301ffc9a7146101dd57806307bce0b414610212578063093f0e271461023457600080fd5b366101d857005b600080fd5b3480156101e957600080fd5b506101fd6101f836600461208c565b610610565b60405190151581526020015b60405180910390f35b34801561021e57600080fd5b5061023261022d3660046120b6565b610647565b005b34801561024057600080fd5b506102687f22ad9585a395edc8067b50da4778cafbb7fa2c4bbd7619fad6aeba403857fd7481565b604051908152602001610209565b34801561028257600080fd5b506102326102913660046120d8565b61067b565b3480156102a257600080fd5b506000805160206126c283398151915260005260016020527f3c2285c553468ca8f30447b24bb463c127f1b840e23a0cafa23caa79d906669a54610268565b6102f46102ef366004612109565b6106b2565b60408051928352602083019190915201610209565b34801561031557600080fd5b50610232610ae3565b34801561032a57600080fd5b5061026861033936600461217a565b610b1b565b34801561034a57600080fd5b506101fd6103593660046121b2565b50600090565b34801561036b57600080fd5b5060005460ff166101fd565b34801561038357600080fd5b506102326103923660046121cf565b610c1e565b3480156103a357600080fd5b506003546103b7906001600160a01b031681565b6040516001600160a01b039091168152602001610209565b3480156103db57600080fd5b50610232610c54565b3480156103f057600080fd5b506102326103ff366004612210565b610c66565b34801561041057600080fd5b50610232610c9f565b34801561042557600080fd5b5061023261043436600461223e565b610cd5565b34801561044557600080fd5b5060005461010090046001600160a01b03166103b7565b34801561046857600080fd5b506104966104773660046120d8565b6005602052600090815260409020805460019091015460ff9091169082565b604080519215158352602083019190915201610209565b3480156104b957600080fd5b506102326104c83660046120d8565b610fcd565b3480156104d957600080fd5b506102326104e8366004612287565b610ffc565b3480156104f957600080fd5b50610232611059565b34801561050e57600080fd5b5061026861051d3660046120d8565b6110c6565b34801561052e57600080fd5b5061026860045481565b34801561054457600080fd5b5061026860075481565b34801561055a57600080fd5b506102326105693660046121b2565b6110f2565b34801561057a57600080fd5b506102326105893660046120d8565b611121565b34801561059a57600080fd5b506105a3611150565b60405161020991906122b5565b3480156105bc57600080fd5b506102686105cb3660046121b2565b611169565b3480156105dc57600080fd5b506102326105eb3660046121b2565b6111ff565b3480156105fc57600080fd5b506101fd61060b3660046121b2565b61127a565b60006001600160e01b031982166385572ffb60e01b148061064157506001600160e01b031982166301ffc9a760e01b145b92915050565b6106503361127a565b61066d57604051637c3ea23f60e01b815260040160405180910390fd5b61067782826112ba565b5050565b6106843361127a565b6106a157604051637c3ea23f60e01b815260040160405180910390fd5b6106aa8161132d565b50565b905090565b6000806106bd611376565b6106c56113bc565b6106d4853560a0870135611415565b6000806106fd856106e86020890189612302565b6106f657886080013561143e565b600061143e565b91509150600060405180608001604052806107166114df565b6001600160a01b031681526020016000151581526020018860000160208101906107409190612302565b61074b576000610751565b89608001355b815260808a013560209182015281519192506001600160a01b039091169061077b908801886121b2565b6001600160a01b0316036107c957600160208083019190915260408201805191880135916107aa908390612335565b905250606081018051604088013591906107c5908390612335565b9052505b6040810151156107e7576107e781600001513330846040015161154d565b6107f46020880188612302565b6108555780600001516001600160a01b031663d0e30db089608001356040518263ffffffff1660e01b81526004016000604051808303818588803b15801561083b57600080fd5b505af115801561084f573d6000803e3d6000fd5b50505050505b8051600354606083015161087392916001600160a01b031690611648565b8060200151158015610883575082155b156108ca576108a461089860208801886121b2565b3330896020013561154d565b6108ca6108b460208801886121b2565b6003546001600160a01b03166040890135611648565b6008600081546108d990612348565b919050819055945060006040518060800160405280878152602001336001600160a01b031681526020018960200160208101906109169190612302565b15158152602001600061092f60808d0160608e016121b2565b6001600160a01b0316146109525761094d60808c0160608d016121b2565b610954565b335b6001600160a01b0316905260405161096f9190602001612361565b60405160208183030381529060405290503689905060006109c68b604001602081019061099c91906121b2565b846109af8760000151866080013561173a565b60a08601356109c160208f018f6121b2565b6117c1565b90506109e26109db60408d0160208e0161239d565b82876118a5565b84516003549198506109fe916001600160a01b03166000611648565b8360200151158015610a0e575085155b15610a3657610a36610a2360208b018b6121b2565b6003546001600160a01b03166000611648565b8987338a7f4047d821f29c05dd3ee1c2410f84e686cafd8c2023d02b40ae8d30fe35c1f5218635610a6d6080890160608a016121b2565b610a7a6020880188612302565b610a8a6040890160208a01612302565b604080519485526001600160a01b039390931660208501529015158383015215156060830152608089810135908301524260a0830152519081900360c00190a450505050505050610adb6001600655565b935093915050565b610aec3361127a565b610b0957604051637c3ea23f60e01b815260040160405180910390fd5b610b11611925565b610b1961196e565b565b6000610b2c833560a0850135611415565b600060405180608001604052806008546001610b489190612335565b815233602082015260016040820152606090810190600090610b7090608089019089016121b2565b6001600160a01b031614610b9357610b8e60808701606088016121b2565b610b95565b335b6001600160a01b03169052604051610bb09190602001612361565b60405160208183030381529060405290506000610bfa856040016020810190610bd991906121b2565b83610bef610be56114df565b896080013561173a565b8860a00135886117c1565b9050610c15610c0f604087016020880161239d565b826119c0565b95945050505050565b610c273361127a565b610c4457604051637c3ea23f60e01b815260040160405180910390fd5b610c4f838383611a3b565b505050565b610c5c611a75565b610b196000611ad5565b610c6f3361127a565b610c8c57604051637c3ea23f60e01b815260040160405180910390fd5b6106778282610c9a85611169565b611a3b565b610ca83361127a565b610cc557604051637c3ea23f60e01b815260040160405180910390fd5b610ccd611376565b610b19611b2e565b610cdd6113bc565b6003546001600160a01b03163314610d085760405163d9b0b35560e01b815260040160405180910390fd5b60005460ff1615610d41576040517febfa14817ead60a20b8a0fc2f6e70025b7414b60eeb0f786c0446e7e543db64b90600090a1610fc3565b6000610d4b6114df565b9050610d5a60808301836123c7565b90506001141580610db057506001600160a01b038116610d7d60808401846123c7565b6000818110610d8e57610d8e612418565b610da492602060409092020190810191506121b2565b6001600160a01b031614155b15610de4576040517f059a1c5131f929faf5414939857c4e1750baf6110d2cbb9b066c50d7be32185590600090a150610fc3565b6000610df3606084018461242e565b810190610e009190612475565b90506000610e1160808501856123c7565b6000818110610e2257610e22612418565b9050604002016020013590506000826040015115610e4e57610e4984846060015184611b6b565b610f76565b604051632e1a7d4d60e01b8152600481018390526001600160a01b03851690632e1a7d4d90602401600060405180830381600087803b158015610e9057600080fd5b505af1158015610ea4573d6000803e3d6000fd5b50505050600083606001516001600160a01b03168360075490604051600060405180830381858888f193505050503d8060008114610efe576040519150601f19603f3d011682016040523d82523d6000602084013e610f03565b606091505b5050905080610f7457846001600160a01b031663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b158015610f4757600080fd5b505af1158015610f5b573d6000803e3d6000fd5b5050505050610f6f85856060015185611b6b565b600191505b505b8251604080850151815190151581528315156020820152428183015290517faf1680666074a12cad20d06bb9b7190e4b9460e835839411024947eb079a7b779181900360600190a2505050505b6106aa6001600655565b610fd63361127a565b610ff357604051637c3ea23f60e01b815260040160405180910390fd5b6106aa81611c55565b611004611a75565b61101d6000805160206126c28339815191528383611ca3565b604051811515906001600160a01b038416907fbe9474bb3e78da7e315cdffa5cfa30b767fcc95bbf44a6197da60228eea1028690600090a35050565b6110623361127a565b61107f57604051637c3ea23f60e01b815260040160405180910390fd5b6110996000805160206126c2833981519152336000611ca3565b60405133907f6cc2c67081f55c2fffb7c008fa995fbbf890f48c7c16fba93d8220f00dc84cc590600090a2565b6000818152600560205260408120805460ff16156110e8576001015492915050565b5050600454919050565b6110fb3361127a565b61111857604051637c3ea23f60e01b815260040160405180910390fd5b6106aa81611cd0565b61112a3361127a565b61114757604051637c3ea23f60e01b815260040160405180910390fd5b6106aa81611d23565b60606106ad6000805160206126c2833981519152611d58565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03831601611197575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa1580156111db573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064191906124ff565b611207611a75565b6001600160a01b0381166112715760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6106aa81611ad5565b6001600160a01b03811660009081527f260b29b219d450563ddb0e5ca806bdadb1e125f7e8c506de0443797dd7122728602052604081205460ff16610641565b604080518082018252600180825260208083018581526000878152600583528590209351845460ff191690151517845551929091019190915581518481529081018390527f2ee636de87a5f853f736b571d71f38b0eaa7a494ab78d545a4e69975fb3a0e3f910160405180910390a15050565b8060000361133a57506000195b60078190556040518181527f07f2da272b0090c4177cfbb7f50d00e3ed4d37c9445216ca7efbc245d7b5b0ac906020015b60405180910390a150565b60005460ff1615610b195760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401611268565b60026006540361140e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611268565b6002600655565b61141e826110c6565b81101561067757604051630acdd10560e31b815260040160405180910390fd5b60008083604001358460200135101561146a57604051637367509b60e01b815260040160405180910390fd5b600061147960208601866121b2565b6001600160a01b031614915060008261149257836114a0565b6114a0846020870135612335565b9050803410156114c357604051637dd7aa2160e01b815260040160405180910390fd5b826114cf5760006114d5565b84604001355b9150509250929050565b6003546040805163e861e90760e01b815290516000926001600160a01b03169163e861e9079160048083019260209291908290030181865afa158015611529573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ad9190612518565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916115b19190612559565b6000604051808303816000865af19150503d80600081146115ee576040519150601f19603f3d011682016040523d82523d6000602084013e6115f3565b606091505b5091509150600082801561161f57508151158061161f57508180602001905181019061161f9190612575565b90508061163f57604051632d9d5b4160e01b815260040160405180910390fd5b50505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392908716916116a49190612559565b6000604051808303816000865af19150503d80600081146116e1576040519150601f19603f3d011682016040523d82523d6000602084013e6116e6565b606091505b509150915060008280156117125750815115806117125750818060200190518101906117129190612575565b9050806117325760405163b45d44e760e01b815260040160405180910390fd5b505050505050565b60408051600180825281830190925260609160009190816020015b60408051808201909152600080825260208201528152602001906001900390816117555790505090506040518060400160405280856001600160a01b0316815260200184815250816000815181106117af576117af612418565b60209081029190910101529392505050565b6117fc6040518060a0016040528060608152602001606081526020016060815260200160006001600160a01b03168152602001606081525090565b6040805160a081019091526001600160a01b03871660c08201528060e081016040516020818303038152906040528152602001868152602001858152602001836001600160a01b0316815260200161189960405180602001604052808781525060408051915160248084019190915281518084039091018152604490920190526020810180516001600160e01b03166397a657c960e01b17905290565b90529695505050505050565b6003546040516396f4e9f960e01b81526000916001600160a01b0316906396f4e9f99084906118da90889088906004016125be565b60206040518083038185885af11580156118f8573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061191d91906124ff565b949350505050565b60005460ff16610b195760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401611268565b611976611925565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6003546040516320487ded60e01b81526000916001600160a01b0316906320487ded906119f390869086906004016125be565b602060405180830381865afa158015611a10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3491906124ff565b9392505050565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03841601611a6a57610c4f8282611dc4565b610c4f838383611b6b565b6000546001600160a01b03610100909104163314610b195760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611268565b600080546001600160a01b03838116610100818102610100600160a81b0319851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b611b36611376565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586119a33390565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691611bc79190612559565b6000604051808303816000865af19150503d8060008114611c04576040519150601f19603f3d011682016040523d82523d6000602084013e611c09565b606091505b50915091506000828015611c35575081511580611c35575081806020019051810190611c359190612575565b90508061173257604051632fdb1b7f60e11b815260040160405180910390fd5b600081815260056020526040808220805460ff1916815560010191909155517f2449b10e63f8d71e042b39939d3c5423f003860c5371eb09ecfd7435d681a78e9061136b9083815260200190565b60008381526001602090815260408083206002909252909120611cca919084846064611e52565b50505050565b611cd981611e7f565b600380546001600160a01b0319166001600160a01b0383169081179091556040517fc8e81a4efc849969069ec6aae575cf7a6bc5f9d3abac59f4ed190a6f7e05fc6f90600090a250565b60048190556040518181527f7d13ea4e82ca085561ddd42a2f1080d88b527444721ee7803f603decd203ff239060200161136b565b600081815260016020908152604091829020805483518184028101840190945280845260609392830182828015611db857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611d9a575b50505050509050919050565b604080516000808252602082019092526001600160a01b038416908390604051611dee9190612559565b60006040518083038185875af1925050503d8060008114611e2b576040519150601f19603f3d011682016040523d82523d6000602084013e611e30565b606091505b5050905080610c4f57604051632e05b05360e21b815260040160405180910390fd5b600082611e6957611e64868686611eb2565b611e75565b611e7586868685611fda565b9695505050505050565b6001600160a01b0381163b6106aa57604051638c50d7cd60e01b81526001600160a01b0382166004820152602401611268565b6001600160a01b0381166000908152602083905260409020805460ff16908115611fd25760018082015486549091600091611eed9190612698565b9050808214611f7a576000878281548110611f0a57611f0a612418565b9060005260206000200160009054906101000a90046001600160a01b0316905080888481548110611f3d57611f3d612418565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905592909116815290879052604090206001018290555b86805480611f8a57611f8a6126ab565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038716825287905260408120805460ff191681556001015550505b509392505050565b6001600160a01b03821660009081526020849052604090205460ff1615801561191d578454821161201e5760405163b1655e3360e01b815260040160405180910390fd5b6040805180820182526001808252875460208084019182526001600160a01b03881660008181528a83529586209451855460ff1916901515178555915193830193909355885491820189558884529190922090910180546001600160a01b0319169091179055949350505050565b60006020828403121561209e57600080fd5b81356001600160e01b031981168114611a3457600080fd5b600080604083850312156120c957600080fd5b50508035926020909101359150565b6000602082840312156120ea57600080fd5b5035919050565b600060c0828403121561210357600080fd5b50919050565b600080600083850361016081121561212057600080fd5b61212a86866120f1565b9350604060bf198201121561213e57600080fd5b60c085019250606060ff198201121561215657600080fd5b50610100840190509250925092565b6001600160a01b03811681146106aa57600080fd5b60008060e0838503121561218d57600080fd5b61219784846120f1565b915060c08301356121a781612165565b809150509250929050565b6000602082840312156121c457600080fd5b8135611a3481612165565b6000806000606084860312156121e457600080fd5b83356121ef81612165565b925060208401356121ff81612165565b929592945050506040919091013590565b6000806040838503121561222357600080fd5b823561222e81612165565b915060208301356121a781612165565b60006020828403121561225057600080fd5b813567ffffffffffffffff81111561226757600080fd5b820160a08185031215611a3457600080fd5b80151581146106aa57600080fd5b6000806040838503121561229a57600080fd5b82356122a581612165565b915060208301356121a781612279565b6020808252825182820181905260009190848201906040850190845b818110156122f65783516001600160a01b0316835292840192918401916001016122d1565b50909695505050505050565b60006020828403121561231457600080fd5b8135611a3481612279565b634e487b7160e01b600052601160045260246000fd5b808201808211156106415761064161231f565b60006001820161235a5761235a61231f565b5060010190565b815181526020808301516001600160a01b0390811691830191909152604080840151151590830152606092830151169181019190915260800190565b6000602082840312156123af57600080fd5b813567ffffffffffffffff81168114611a3457600080fd5b6000808335601e198436030181126123de57600080fd5b83018035915067ffffffffffffffff8211156123f957600080fd5b6020019150600681901b360382131561241157600080fd5b9250929050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261244557600080fd5b83018035915067ffffffffffffffff82111561246057600080fd5b60200191503681900382131561241157600080fd5b60006080828403121561248757600080fd5b6040516080810181811067ffffffffffffffff821117156124b857634e487b7160e01b600052604160045260246000fd5b6040528235815260208301356124cd81612165565b602082015260408301356124e081612279565b604082015260608301356124f381612165565b60608201529392505050565b60006020828403121561251157600080fd5b5051919050565b60006020828403121561252a57600080fd5b8151611a3481612165565b60005b83811015612550578181015183820152602001612538565b50506000910152565b6000825161256b818460208701612535565b9190910192915050565b60006020828403121561258757600080fd5b8151611a3481612279565b600081518084526125aa816020860160208601612535565b601f01601f19169290920160200192915050565b6000604067ffffffffffffffff8516835260208181850152845160a0838601526125eb60e0860182612592565b905081860151603f19808784030160608801526126088383612592565b88860151888203830160808a01528051808352908601945060009350908501905b8084101561265b57845180516001600160a01b0316835286015186830152938501936001939093019290860190612629565b5060608901516001600160a01b031660a08901526080890151888203830160c08a0152955061268a8187612592565b9a9950505050505050505050565b818103818111156106415761064161231f565b634e487b7160e01b600052603160045260246000fdfe6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6fa2646970667358221220f4b0d6e8effb71d20dd9840d2ef24d38185d22720304d0f0103bca7f80ea66cf64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000141fa059441e0ca23ce184b6a78bafd2a517dde8000000000000000000000000000000000000000000000000000000000001d4c000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000300c00000000000000000000000072e28c7f34100afefc399fcc0ae041b8fe5841ae0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _endpointAddress (address): 0x141fa059441E0ca23ce184B6A78bafD2A517DdE8
Arg [1] : _minTargetAppGasDefault (uint256): 120000
-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 000000000000000000000000141fa059441e0ca23ce184b6a78bafd2a517dde8
Arg [1] : 000000000000000000000000000000000000000000000000000000000001d4c0
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [3] : 000000000000000000000000000000000000000000000000000000000000300c
Arg [4] : 00000000000000000000000072e28c7f34100afefc399fcc0ae041b8fe5841ae
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Loading...
Loading
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.