More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 96 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Execute Target | 20235202 | 8 hrs ago | IN | 0 ETH | 0.00244108 | ||||
Execute Target | 20235033 | 9 hrs ago | IN | 0 ETH | 0.0023784 | ||||
Execute Target | 20234476 | 11 hrs ago | IN | 0 ETH | 0.00322604 | ||||
Execute Target | 20211384 | 3 days ago | IN | 0 ETH | 0.00173848 | ||||
Execute Target | 20205352 | 4 days ago | IN | 0 ETH | 0.00132775 | ||||
Execute Target | 20177127 | 8 days ago | IN | 0 ETH | 0.00305422 | ||||
Execute Target | 20170822 | 9 days ago | IN | 0 ETH | 0.00212559 | ||||
Execute Target | 20158355 | 11 days ago | IN | 0 ETH | 0.00079631 | ||||
Execute Target | 20157846 | 11 days ago | IN | 0 ETH | 0.0008771 | ||||
Execute Target | 20117535 | 16 days ago | IN | 0 ETH | 0.00191635 | ||||
Execute Target | 20099958 | 19 days ago | IN | 0 ETH | 0.00134654 | ||||
Execute Target | 20072043 | 23 days ago | IN | 0 ETH | 0.00252977 | ||||
Execute Target | 20015269 | 31 days ago | IN | 0 ETH | 0.00222108 | ||||
Execute Target | 19973231 | 36 days ago | IN | 0 ETH | 0.00315522 | ||||
Execute Target | 19954519 | 39 days ago | IN | 0 ETH | 0.0028045 | ||||
Execute Target | 19954048 | 39 days ago | IN | 0 ETH | 0.00182357 | ||||
Execute Target | 19921489 | 44 days ago | IN | 0 ETH | 0.00215542 | ||||
Execute Target | 19894983 | 47 days ago | IN | 0 ETH | 0.00118777 | ||||
Execute Target | 19862359 | 52 days ago | IN | 0 ETH | 0.00655723 | ||||
Execute Target | 19859687 | 52 days ago | IN | 0 ETH | 0.00176569 | ||||
Execute Target | 19858582 | 53 days ago | IN | 0 ETH | 0.00128824 | ||||
Execute Target | 19840886 | 55 days ago | IN | 0 ETH | 0.00245121 | ||||
Execute Target | 19807223 | 60 days ago | IN | 0 ETH | 0.00161228 | ||||
Execute Target | 19775847 | 64 days ago | IN | 0 ETH | 0.00399509 | ||||
Execute Target | 19771078 | 65 days ago | IN | 0 ETH | 0.00241456 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
20163565 | 10 days ago | 0.0045369 ETH | ||||
20163565 | 10 days ago | 0.0045369 ETH | ||||
20132566 | 14 days ago | 0.00365469 ETH | ||||
20132566 | 14 days ago | 0.00365469 ETH | ||||
20131865 | 14 days ago | 0.00419949 ETH | ||||
20131865 | 14 days ago | 0.00419949 ETH | ||||
20070502 | 23 days ago | 0.00023323 ETH | ||||
20070502 | 23 days ago | 0.00023323 ETH | ||||
20056764 | 25 days ago | 0.00013832 ETH | ||||
20056764 | 25 days ago | 0.00013832 ETH | ||||
20012273 | 31 days ago | 0.0031885 ETH | ||||
20012273 | 31 days ago | 0.0031885 ETH | ||||
20011892 | 31 days ago | 0.00395427 ETH | ||||
20011892 | 31 days ago | 0.00395427 ETH | ||||
19769078 | 65 days ago | 0.00010954 ETH | ||||
19769078 | 65 days ago | 0.00010954 ETH | ||||
19464924 | 108 days ago | 0.00056786 ETH | ||||
19464924 | 108 days ago | 0.00056786 ETH | ||||
19323412 | 128 days ago | 0.00042869 ETH | ||||
19323412 | 128 days ago | 0.00042869 ETH | ||||
19154871 | 151 days ago | 0.00015635 ETH | ||||
19154871 | 151 days ago | 0.00015635 ETH | ||||
19129759 | 155 days ago | 0.0000399 ETH | ||||
19129759 | 155 days ago | 0.0000399 ETH | ||||
18969955 | 177 days ago | 0.00015712 ETH |
Loading...
Loading
Contract Name:
CircleCctpGateway
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 { IActionDataStructures } from '../../interfaces/IActionDataStructures.sol'; import { IMessageHandler } from './interfaces/IMessageHandler.sol'; import { IMessageTransmitter } from './interfaces/IMessageTransmitter.sol'; import { ITokenBalance } from '../../interfaces/ITokenBalance.sol'; import { ITokenMessenger } from './interfaces/ITokenMessenger.sol'; import { IVault } from '../../interfaces/IVault.sol'; import { AssetSpenderRole } from '../../roles/AssetSpenderRole.sol'; import { CallerGuard } from '../../CallerGuard.sol'; import { GatewayBase } from '../GatewayBase.sol'; import { SystemVersionId } from '../../SystemVersionId.sol'; import '../../helpers/GasReserveHelper.sol' as GasReserveHelper; import '../../helpers/TransferHelper.sol' as TransferHelper; import '../../DataStructures.sol' as DataStructures; /** * @title CircleCctpGateway * @notice The contract implementing the cross-chain messaging logic specific to Circle CCTP */ contract CircleCctpGateway is SystemVersionId, GatewayBase, CallerGuard, AssetSpenderRole, IActionDataStructures, IVault, IMessageHandler { /** * @notice Chain domain structure * @dev See https://developers.circle.com/stablecoin/docs/cctp-technical-reference#domain * @param chainId The EVM chain ID * @param domain The CCTP domain */ struct ChainDomain { uint256 chainId; uint32 domain; } /** * @notice Variables for the sendMessage function * @param peerAddressBytes32 The peer address as bytes32 * @param targetDomain The target domain * @param assetMessageNonce The asset message nonce * @param dataMessageNonce The data message nonce */ struct SendMessageVariables { bytes32 peerAddressBytes32; uint32 targetDomain; uint64 assetMessageNonce; uint64 dataMessageNonce; bool useTargetExecutor; } /** * @notice CCTP message handler context structure * @param caller The address of the caller * @param assetReceived The received amount of the CCTP asset */ struct MessageHandlerContext { address caller; uint256 assetReceived; } /** * @dev cctpTokenMessenger The CCTP token messenger address */ ITokenMessenger public immutable cctpTokenMessenger; /** * @dev cctpMessageTransmitter The CCTP message transmitter address */ IMessageTransmitter public immutable cctpMessageTransmitter; /** * @dev asset The USDC token address */ address public immutable asset; /** * @dev Chain id to CCTP domain */ mapping(uint256 /*chainId*/ => DataStructures.OptionalValue /*domain*/) public chainIdToDomain; /** * @dev CCTP domain to chain id */ mapping(uint32 /*domain*/ => uint256 /*chainId*/) public domainToChainId; /** * @dev The state of variable token and balance actions */ bool public variableRepaymentEnabled; /** * @dev The address of the processing fee collector */ address public processingFeeCollector; /** * @dev The address of the target executor */ address public targetExecutor; MessageHandlerContext private messageHandlerContext; /** * @notice Emitted when a chain ID and CCTP domain pair is added or updated * @param chainId The chain ID * @param domain The CCTP domain */ event SetChainDomain(uint256 indexed chainId, uint32 indexed domain); /** * @notice Emitted when a chain ID and CCTP domain pair is removed * @param chainId The chain ID * @param domain The CCTP domain */ event RemoveChainDomain(uint256 indexed chainId, uint32 indexed domain); /** * @notice Emitted when the state of variable token and balance actions is updated * @param variableRepaymentEnabled The state of variable token and balance actions */ event SetVariableRepaymentEnabled(bool indexed variableRepaymentEnabled); /** * @notice Emitted when the address of the processing fee collector is set * @param processingFeeCollector The address of the processing fee collector */ event SetProcessingFeeCollector(address indexed processingFeeCollector); /** * @notice Emitted when the address of the target executor is set * @param targetExecutor The address of the target executor */ event SetTargetExecutor(address indexed targetExecutor); /** * @notice Emitted when the call to the CCTP receiveMessage fails * @param sourceChainId The ID of the message source chain */ event TargetCctpMessageFailure(uint256 indexed sourceChainId); /** * @notice Emitted when a gateway action is performed on the source chain * @param actionId The ID of the action * @param targetChainId The ID of the target chain * @param useTargetExecutor The flag to use the target executor * @param assetMessageNonce The nonce of the CCTP asset message * @param dataMessageNonce The nonce of the CCTP data message * @param assetAmount The amount of the asset used for the action * @param processingFee The amount of the processing fee * @param processingGas The amount of the processing gas * @param timestamp The timestamp of the action (in seconds) */ event GatewayActionSource( uint256 indexed actionId, uint256 indexed targetChainId, bool indexed useTargetExecutor, uint64 assetMessageNonce, uint64 dataMessageNonce, uint256 assetAmount, uint256 processingFee, uint256 processingGas, uint256 timestamp ); /** * @notice Emitted when the domain for the specified chain is not set */ error DomainNotSetError(); /** * @notice Emitted when the caller is not an allowed executor */ error ExecutorError(); /** * @notice Emitted when the provided call value is not sufficient for the message processing */ error ProcessingFeeError(); /** * @notice Emitted when a variable token or balance action is not allowed */ error VariableRepaymentNotEnabledError(); /** * @notice Emitted when a variable token action is attempted while the token address is not set */ error VariableTokenNotSetError(); /** * @notice Emitted when the context vault is not the current contract */ error OnlyCurrentVaultError(); /** * @notice Emitted when the caller is not the CCTP message transmitter */ error OnlyMessageTransmitterError(); /** * @notice Emitted when the target chain gateway client contract is not set */ error TargetClientNotSetError(); /** * @notice Emitted when the asset message receiving fails */ error AssetMessageError(); /** * @notice Emitted when the data message receiving fails */ error DataMessageError(); /** * @notice Emitted when the message source address does not match the registered peer gateway on the target chain * @param sourceChainId The ID of the message source chain * @param fromAddress The address of the message source */ error TargetFromAddressError(uint256 sourceChainId, address fromAddress); /** * @notice Emitted when the caller is not allowed to perform the action on the target chain */ error TargetCallerError(); /** * @notice Emitted when the swap amount does not match the received asset amount */ error TargetAssetAmountMismatchError(); /** * @notice Emitted when the gas reserve on the target chain does not allow further action processing */ error TargetGasReserveError(); /** * @dev Modifier to check if the caller is the CCTP message transmitter */ modifier onlyMessageTransmitter() { if (msg.sender != address(cctpMessageTransmitter)) { revert OnlyMessageTransmitterError(); } _; } /** * @notice Deploys the CircleCctpGateway contract * @param _cctpTokenMessenger The CCTP token messenger address * @param _cctpMessageTransmitter The CCTP message transmitter address * @param _chainDomains The list of registered chain domains * @param _asset The USDC token address * @param _variableRepaymentEnabled The state of variable token and balance actions * @param _targetGasReserve The initial gas reserve value for target chain action processing * @param _processingFeeCollector The initial address of the processing fee collector * @param _targetExecutor The address of the target executor * @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( ITokenMessenger _cctpTokenMessenger, IMessageTransmitter _cctpMessageTransmitter, ChainDomain[] memory _chainDomains, address _asset, bool _variableRepaymentEnabled, uint256 _targetGasReserve, address _processingFeeCollector, address _targetExecutor, address _owner, address[] memory _managers, bool _addOwnerToManagers ) { cctpTokenMessenger = _cctpTokenMessenger; cctpMessageTransmitter = _cctpMessageTransmitter; for (uint256 index; index < _chainDomains.length; index++) { ChainDomain memory chainDomain = _chainDomains[index]; _setChainDomain(chainDomain.chainId, chainDomain.domain); } asset = _asset; _setVariableRepaymentEnabled(_variableRepaymentEnabled); _setTargetGasReserve(_targetGasReserve); _setProcessingFeeCollector(_processingFeeCollector); _setTargetExecutor(_targetExecutor); _initRoles(_owner, _managers, _addOwnerToManagers); } /** * @notice The standard "receive" function * @dev Is payable to allow receiving native token funds from the cross-chain endpoint */ receive() external payable {} /** * @notice Updates the Asset Spender role status for the account * @param _account The account address * @param _value The Asset Spender role status flag */ function setAssetSpender(address _account, bool _value) external onlyManager { _setAssetSpender(_account, _value); } /** * @notice Adds or updates registered chain domains (CCTP-specific) * @param _chainDomains The list of registered chain domains */ function setChainDomains(ChainDomain[] calldata _chainDomains) external onlyManager { for (uint256 index; index < _chainDomains.length; index++) { ChainDomain calldata chainDomain = _chainDomains[index]; _setChainDomain(chainDomain.chainId, chainDomain.domain); } } /** * @notice Removes registered chain domains (CCTP-specific) * @param _chainIds The list of EVM chain IDs */ function removeChainDomains(uint256[] calldata _chainIds) external onlyManager { for (uint256 index; index < _chainIds.length; index++) { uint256 chainId = _chainIds[index]; _removeChainDomain(chainId); } } /** * @notice Sets the address of the processing fee collector * @param _processingFeeCollector The address of the processing fee collector */ function setProcessingFeeCollector(address _processingFeeCollector) external onlyManager { _setProcessingFeeCollector(_processingFeeCollector); } /** * @notice Sets the address of the target executor * @param _targetExecutor The address of the target executor */ function setTargetExecutor(address _targetExecutor) external onlyManager { _setTargetExecutor(_targetExecutor); } /** * @notice Send a cross-chain message * @param _targetChainId The message target chain ID * @param _message The message content * @param _settings The gateway-specific settings */ function sendMessage( uint256 _targetChainId, bytes calldata _message, bytes calldata _settings ) external payable onlyClient whenNotPaused { (IVault vault, uint256 assetAmount) = client.getSourceGatewayContext(); if (address(vault) != address(this)) { revert OnlyCurrentVaultError(); } SendMessageVariables memory variables = _prepareSendMessageVariables(); variables.peerAddressBytes32 = _addressToBytes32(_checkPeerAddress(_targetChainId)); variables.targetDomain = _checkTargetDomain(_targetChainId); uint256 processingFee; uint256 processingGas; (variables.useTargetExecutor, processingFee, processingGas) = _decodeSettings(_settings); // - - - Processing fee transfer - - - if (msg.value < processingFee) { revert ProcessingFeeError(); } if (processingFee > 0 && processingFeeCollector != address(0)) { TransferHelper.safeTransferNative(processingFeeCollector, processingFee); } // - - - TargetMessage memory targetMessage = abi.decode(_message, (TargetMessage)); // - - - CCTP - Burn USDC on the source chain - - - TransferHelper.safeApprove(asset, address(cctpTokenMessenger), assetAmount); variables.assetMessageNonce = cctpTokenMessenger.depositForBurnWithCaller( assetAmount, variables.targetDomain, variables.peerAddressBytes32, // _mintRecipient asset, variables.peerAddressBytes32 // _destinationCaller ); TransferHelper.safeApprove(asset, address(cctpTokenMessenger), 0); // - - - // - - - CCTP - Send the message - - - variables.dataMessageNonce = cctpMessageTransmitter.sendMessageWithCaller( variables.targetDomain, variables.peerAddressBytes32, // recipient variables.peerAddressBytes32, // destinationCaller _message ); // - - - emit GatewayActionSource( targetMessage.actionId, _targetChainId, variables.useTargetExecutor, variables.assetMessageNonce, variables.dataMessageNonce, assetAmount, processingFee, processingGas, block.timestamp ); } /** * @notice Executes the target actions * @param _assetMessage The CCTP asset message * @param _assetAttestation The CCTP asset message attestation * @param _dataMessage The CCTP data message * @param _dataAttestation The CCTP data message attestation */ function executeTarget( bytes calldata _assetMessage, bytes calldata _assetAttestation, bytes calldata _dataMessage, bytes calldata _dataAttestation ) external whenNotPaused nonReentrant checkCaller { if (address(client) == address(0)) { revert TargetClientNotSetError(); } uint256 assetBalanceBefore = tokenBalance(asset); bool assetMessageSuccess = cctpMessageTransmitter.receiveMessage( _assetMessage, _assetAttestation ); if (!assetMessageSuccess) { revert AssetMessageError(); } messageHandlerContext = MessageHandlerContext({ caller: msg.sender, assetReceived: tokenBalance(asset) - assetBalanceBefore }); bool dataMessageSuccess = cctpMessageTransmitter.receiveMessage( _dataMessage, _dataAttestation ); if (!dataMessageSuccess) { revert DataMessageError(); } delete messageHandlerContext; } /** * @notice handles an incoming message from a Receiver * @dev IMessageHandler interface * @param _sourceDomain The source domain of the message * @param _sender The sender of the message * @param _messageBody The message raw bytes * @return success bool, true if successful */ function handleReceiveMessage( uint32 _sourceDomain, bytes32 _sender, bytes calldata _messageBody ) external whenNotPaused onlyMessageTransmitter returns (bool) { uint256 sourceChainId = domainToChainId[_sourceDomain]; address fromAddress = _bytes32ToAddress(_sender); { bool fromAddressCondition = sourceChainId != 0 && fromAddress != address(0) && fromAddress == peerMap[sourceChainId]; if (!fromAddressCondition) { revert TargetFromAddressError(sourceChainId, fromAddress); } } TargetMessage memory targetMessage = abi.decode(_messageBody, (TargetMessage)); { address caller = messageHandlerContext.caller; bool targetCallerCondition = caller == targetExecutor || caller == targetMessage.sourceSender || caller == targetMessage.targetRecipient; if (!targetCallerCondition) { revert TargetCallerError(); } } if (targetMessage.targetSwapInfo.fromAmount != messageHandlerContext.assetReceived) { revert TargetAssetAmountMismatchError(); } (bool hasGasReserve, uint256 gasAllowed) = GasReserveHelper.checkGasReserve( targetGasReserve ); if (!hasGasReserve) { revert TargetGasReserveError(); } client.handleExecutionPayload{ gas: gasAllowed }(sourceChainId, _messageBody); return true; } /** * @notice Receives the asset tokens from CCTP and transfers them to the specified account * @param _assetMessage The CCTP asset message * @param _assetAttestation The CCTP asset attestation * @param _to The address of the asset tokens receiver */ function extractCctpAsset( bytes calldata _assetMessage, bytes calldata _assetAttestation, address _to ) external onlyManager { uint256 tokenBalanceBefore = ITokenBalance(asset).balanceOf(address(this)); cctpMessageTransmitter.receiveMessage(_assetMessage, _assetAttestation); uint256 tokenAmount = ITokenBalance(asset).balanceOf(address(this)) - tokenBalanceBefore; if (tokenAmount > 0 && _to != address(this)) { TransferHelper.safeTransfer(asset, _to, tokenAmount); } } /** * @notice Requests the vault asset tokens * @param _amount The amount of the vault asset tokens * @param _to The address of the vault asset tokens receiver * @param _forVariableBalance True if the request is made for a variable balance repayment, otherwise false * @return assetAddress The address of the vault asset token */ function requestAsset( uint256 _amount, address _to, bool _forVariableBalance ) external whenNotPaused onlyAssetSpender returns (address assetAddress) { if (_forVariableBalance && !variableRepaymentEnabled) { revert VariableRepaymentNotEnabledError(); } TransferHelper.safeTransfer(asset, _to, _amount); return asset; } /** * @notice Cross-chain message fee estimation * @param _settings The gateway-specific settings */ function messageFee( uint256 /*_targetChainId*/, bytes calldata /*_message*/, bytes calldata _settings ) external pure returns (uint256) { (, uint256 processingFee, ) = _decodeSettings(_settings); return processingFee; } /** * @notice Checks the status of the variable token and balance actions and the variable token address * @return The address of the variable token */ function checkVariableTokenState() external view returns (address) { if (!variableRepaymentEnabled) { revert VariableRepaymentNotEnabledError(); } revert VariableTokenNotSetError(); } function _setChainDomain(uint256 _chainId, uint32 _domain) private { DataStructures.OptionalValue storage previousDomainEntry = chainIdToDomain[_chainId]; if (previousDomainEntry.isSet) { delete domainToChainId[uint32(previousDomainEntry.value)]; } chainIdToDomain[_chainId] = DataStructures.OptionalValue({ isSet: true, value: _domain }); domainToChainId[_domain] = _chainId; emit SetChainDomain(_chainId, _domain); } function _removeChainDomain(uint256 _chainId) private { DataStructures.OptionalValue storage domainEntry = chainIdToDomain[_chainId]; uint32 domain; if (domainEntry.isSet) { domain = uint32(domainEntry.value); delete domainToChainId[uint32(domainEntry.value)]; } delete chainIdToDomain[_chainId]; emit RemoveChainDomain(_chainId, domain); } function _setVariableRepaymentEnabled(bool _variableRepaymentEnabled) private { variableRepaymentEnabled = _variableRepaymentEnabled; emit SetVariableRepaymentEnabled(_variableRepaymentEnabled); } function _setProcessingFeeCollector(address _processingFeeCollector) private { processingFeeCollector = _processingFeeCollector; emit SetProcessingFeeCollector(_processingFeeCollector); } function _setTargetExecutor(address _targetExecutor) private { targetExecutor = _targetExecutor; emit SetTargetExecutor(_targetExecutor); } function _checkTargetDomain(uint256 _targetChainId) private view returns (uint32) { DataStructures.OptionalValue storage domainEntry = chainIdToDomain[_targetChainId]; if (!domainEntry.isSet) { revert DomainNotSetError(); } return uint32(domainEntry.value); } function _prepareSendMessageVariables() private pure returns (SendMessageVariables memory) { return SendMessageVariables({ peerAddressBytes32: bytes32(0), targetDomain: 0, assetMessageNonce: 0, dataMessageNonce: 0, useTargetExecutor: false }); } function _decodeSettings( bytes calldata _settings ) private pure returns (bool useTargetExecutor, uint256 processingFee, uint256 processingGas) { return abi.decode(_settings, (bool, uint256, uint256)); } function _addressToBytes32(address _address) private pure returns (bytes32) { return bytes32(uint256(uint160(_address))); } function _bytes32ToAddress(bytes32 _buffer) private pure returns (address) { return address(uint160(uint256(_buffer))); } }
// 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 { ITokenBalance } from './interfaces/ITokenBalance.sol'; import { ManagerRole } from './roles/ManagerRole.sol'; import './helpers/TransferHelper.sol' as TransferHelper; import './Constants.sol' as Constants; /** * @title BalanceManagement * @notice Base contract for the withdrawal of tokens, except for reserved ones */ abstract contract BalanceManagement is ManagerRole { /** * @notice Emitted when the specified token is reserved */ error ReservedTokenError(); /** * @notice Performs the withdrawal of tokens, except for reserved ones * @dev Use the "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" address for the native token * @param _tokenAddress The address of the token * @param _tokenAmount The amount of the token */ function cleanup(address _tokenAddress, uint256 _tokenAmount) external onlyManager { if (isReservedToken(_tokenAddress)) { revert ReservedTokenError(); } if (_tokenAddress == Constants.NATIVE_TOKEN_ADDRESS) { TransferHelper.safeTransferNative(msg.sender, _tokenAmount); } else { TransferHelper.safeTransfer(_tokenAddress, msg.sender, _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 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 } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { ManagerRole } from './roles/ManagerRole.sol'; import './helpers/AddressHelper.sol' as AddressHelper; import './Constants.sol' as Constants; import './DataStructures.sol' as DataStructures; /** * @title CallerGuard * @notice Base contract to control access from other contracts */ abstract contract CallerGuard is ManagerRole { /** * @dev Caller guard mode enumeration */ enum CallerGuardMode { ContractForbidden, ContractList, ContractAllowed } /** * @dev Caller guard mode value */ CallerGuardMode public callerGuardMode = CallerGuardMode.ContractForbidden; /** * @dev Registered contract list for "ContractList" mode */ address[] public listedCallerGuardContractList; /** * @dev Registered contract list indices for "ContractList" mode */ mapping(address /*account*/ => DataStructures.OptionalValue /*index*/) public listedCallerGuardContractIndexMap; /** * @notice Emitted when the caller guard mode is set * @param callerGuardMode The caller guard mode */ event SetCallerGuardMode(CallerGuardMode indexed callerGuardMode); /** * @notice Emitted when a registered contract for "ContractList" mode is added or removed * @param contractAddress The contract address * @param isListed The registered contract list inclusion flag */ event SetListedCallerGuardContract(address indexed contractAddress, bool indexed isListed); /** * @notice Emitted when the caller is not allowed to perform the intended action */ error CallerGuardError(address caller); /** * @dev Modifier to check if the caller is allowed to perform the intended action */ modifier checkCaller() { if (msg.sender != tx.origin) { bool condition = (callerGuardMode == CallerGuardMode.ContractAllowed || (callerGuardMode == CallerGuardMode.ContractList && isListedCallerGuardContract(msg.sender))); if (!condition) { revert CallerGuardError(msg.sender); } } _; } /** * @notice Sets the caller guard mode * @param _callerGuardMode The caller guard mode */ function setCallerGuardMode(CallerGuardMode _callerGuardMode) external onlyManager { callerGuardMode = _callerGuardMode; emit SetCallerGuardMode(_callerGuardMode); } /** * @notice Updates the list of registered contracts for the "ContractList" mode * @param _items The addresses and flags for the contracts */ function setListedCallerGuardContracts( DataStructures.AccountToFlag[] calldata _items ) external onlyManager { for (uint256 index; index < _items.length; index++) { DataStructures.AccountToFlag calldata item = _items[index]; if (item.flag) { AddressHelper.requireContract(item.account); } DataStructures.uniqueAddressListUpdate( listedCallerGuardContractList, listedCallerGuardContractIndexMap, item.account, item.flag, Constants.LIST_SIZE_LIMIT_DEFAULT ); emit SetListedCallerGuardContract(item.account, item.flag); } } /** * @notice Getter of the registered contract count * @return The registered contract count */ function listedCallerGuardContractCount() external view returns (uint256) { return listedCallerGuardContractList.length; } /** * @notice Getter of the complete list of registered contracts * @return The complete list of registered contracts */ function fullListedCallerGuardContractList() external view returns (address[] memory) { return listedCallerGuardContractList; } /** * @notice Getter of a listed contract flag * @param _account The contract address * @return The listed contract flag */ function isListedCallerGuardContract(address _account) public view returns (bool) { return listedCallerGuardContractIndexMap[_account].isSet; } }
// 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: Apache-2.0 /* * Copyright (c) 2022, Circle Internet Financial Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity 0.8.19; /** * @title IMessageHandler * @notice Handles messages on destination domain forwarded from * an IReceiver */ interface IMessageHandler { /** * @notice handles an incoming message from a Receiver * @param _sourceDomain the source domain of the message * @param _sender the sender of the message * @param _messageBody The message raw bytes * @return success bool, true if successful */ function handleReceiveMessage( uint32 _sourceDomain, bytes32 _sender, bytes calldata _messageBody ) external returns (bool); }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright (c) 2022, Circle Internet Financial Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity 0.8.19; import './IRelayer.sol'; import './IReceiver.sol'; /** * @title IMessageTransmitter * @notice Interface for message transmitters, which both relay and receive messages. */ interface IMessageTransmitter is IRelayer, IReceiver { }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright (c) 2022, Circle Internet Financial Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity 0.8.19; /** * @title IReceiver * @notice Receives messages on destination chain and forwards them to IMessageDestinationHandler */ interface IReceiver { /** * @notice Receives an incoming message, validating the header and passing * the body to application-specific handler. * @param message The message raw bytes * @param signature The message signature * @return success bool, true if successful */ function receiveMessage( bytes calldata message, bytes calldata signature ) external returns (bool success); }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright (c) 2022, Circle Internet Financial Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity 0.8.19; /** * @title IRelayer * @notice Sends messages from source domain to destination domain */ interface IRelayer { /** * @notice Sends an outgoing message from the source domain. * @dev Increment nonce, format the message, and emit `MessageSent` event with message information. * @param destinationDomain Domain of destination chain * @param recipient Address of message recipient on destination domain as bytes32 * @param messageBody Raw bytes content of message * @return nonce reserved by message */ function sendMessage( uint32 destinationDomain, bytes32 recipient, bytes calldata messageBody ) external returns (uint64); /** * @notice Sends an outgoing message from the source domain, with a specified caller on the * destination domain. * @dev Increment nonce, format the message, and emit `MessageSent` event with message information. * WARNING: if the `destinationCaller` does not represent a valid address as bytes32, then it will not be possible * to broadcast the message on the destination domain. This is an advanced feature, and the standard * sendMessage() should be preferred for use cases where a specific destination caller is not required. * @param destinationDomain Domain of destination chain * @param recipient Address of message recipient on destination domain as bytes32 * @param destinationCaller caller on the destination domain, as bytes32 * @param messageBody Raw bytes content of message * @return nonce reserved by message */ function sendMessageWithCaller( uint32 destinationDomain, bytes32 recipient, bytes32 destinationCaller, bytes calldata messageBody ) external returns (uint64); /** * @notice Replace a message with a new message body and/or destination caller. * @dev The `originalAttestation` must be a valid attestation of `originalMessage`. * @param originalMessage original message to replace * @param originalAttestation attestation of `originalMessage` * @param newMessageBody new message body of replaced message * @param newDestinationCaller the new destination caller */ function replaceMessage( bytes calldata originalMessage, bytes calldata originalAttestation, bytes calldata newMessageBody, bytes32 newDestinationCaller ) external; }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @title ITokenMessenger * @notice Sends messages to MessageTransmitters and to TokenMinters */ interface ITokenMessenger { function depositForBurnWithCaller( uint256 _amount, uint32 _destinationDomain, bytes32 _mintRecipient, address _burnToken, bytes32 _destinationCaller ) external returns (uint64 _nonce); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { ReentrancyGuard } from '@openzeppelin/contracts/security/ReentrancyGuard.sol'; import { IGateway } from './interfaces/IGateway.sol'; import { IGatewayClient } from './interfaces/IGatewayClient.sol'; import { BalanceManagement } from '../BalanceManagement.sol'; import { Pausable } from '../Pausable.sol'; import { TargetGasReserve } from './TargetGasReserve.sol'; import { ZeroAddressError } from '../Errors.sol'; import '../helpers/AddressHelper.sol' as AddressHelper; import '../Constants.sol' as Constants; import '../DataStructures.sol' as DataStructures; /** * @title GatewayBase * @notice Base contract that implements the cross-chain gateway logic */ abstract contract GatewayBase is Pausable, ReentrancyGuard, TargetGasReserve, BalanceManagement, IGateway { /** * @dev Gateway client contract reference */ IGatewayClient public client; /** * @dev Registered peer gateway addresses by the chain ID */ mapping(uint256 /*peerChainId*/ => address /*peerAddress*/) public peerMap; /** * @dev Registered peer gateway chain IDs */ uint256[] public peerChainIdList; /** * @dev Registered peer gateway chain ID indices */ mapping(uint256 /*peerChainId*/ => DataStructures.OptionalValue /*peerChainIdIndex*/) public peerChainIdIndexMap; /** * @notice Emitted when the gateway client contract reference is set * @param clientAddress The gateway client contract address */ event SetClient(address indexed clientAddress); /** * @notice Emitted when a registered peer gateway contract address is added or updated * @param chainId The chain ID of the registered peer gateway * @param peerAddress The address of the registered peer gateway contract */ event SetPeer(uint256 indexed chainId, address indexed peerAddress); /** * @notice Emitted when a registered peer gateway contract address is removed * @param chainId The chain ID of the registered peer gateway */ event RemovePeer(uint256 indexed chainId); /** * @notice Emitted when the target chain gateway is paused */ event TargetPausedFailure(); /** * @notice Emitted when the target chain gateway client contract is not set */ event TargetClientNotSetFailure(); /** * @notice Emitted when the message source address does not match the registered peer gateway on the target chain * @param sourceChainId The ID of the message source chain * @param fromAddress The address of the message source */ event TargetFromAddressFailure(uint256 indexed sourceChainId, address indexed fromAddress); /** * @notice Emitted when the gas reserve on the target chain does not allow further action processing * @param sourceChainId The ID of the message source chain */ event TargetGasReserveFailure(uint256 indexed sourceChainId); /** * @notice Emitted when the gateway client execution on the target chain fails */ event TargetExecutionFailure(); /** * @notice Emitted when the caller is not the gateway client contract */ error OnlyClientError(); /** * @notice Emitted when the peer config address for the current chain does not match the current contract */ error PeerAddressMismatchError(); /** * @notice Emitted when the peer gateway address for the specified chain is not set */ error PeerNotSetError(); /** * @notice Emitted when the chain ID is not set */ error ZeroChainIdError(); /** * @dev Modifier to check if the caller is the gateway client contract */ modifier onlyClient() { if (msg.sender != address(client)) { revert OnlyClientError(); } _; } /** * @notice Sets the gateway client contract reference * @param _clientAddress The gateway client contract address */ function setClient(address payable _clientAddress) external virtual onlyManager { AddressHelper.requireContract(_clientAddress); client = IGatewayClient(_clientAddress); emit SetClient(_clientAddress); } /** * @notice Adds or updates registered peer gateways * @param _peers Chain IDs and addresses of peer gateways */ function setPeers( DataStructures.KeyToAddressValue[] calldata _peers ) external virtual onlyManager { for (uint256 index; index < _peers.length; index++) { DataStructures.KeyToAddressValue calldata item = _peers[index]; uint256 chainId = item.key; address peerAddress = item.value; // Allow the same configuration on multiple chains if (chainId == block.chainid) { if (peerAddress != address(this)) { revert PeerAddressMismatchError(); } } else { _setPeer(chainId, peerAddress); } } } /** * @notice Removes registered peer gateways * @param _chainIds Peer gateway chain IDs */ function removePeers(uint256[] calldata _chainIds) external virtual onlyManager { for (uint256 index; index < _chainIds.length; index++) { uint256 chainId = _chainIds[index]; // Allow the same configuration on multiple chains if (chainId != block.chainid) { _removePeer(chainId); } } } /** * @notice Getter of the peer gateway count * @return The peer gateway count */ function peerCount() external view virtual returns (uint256) { return peerChainIdList.length; } /** * @notice Getter of the complete list of the peer gateway chain IDs * @return The complete list of the peer gateway chain IDs */ function fullPeerChainIdList() external view virtual returns (uint256[] memory) { return peerChainIdList; } function _setPeer(uint256 _chainId, address _peerAddress) internal virtual { if (_chainId == 0) { revert ZeroChainIdError(); } if (_peerAddress == address(0)) { revert ZeroAddressError(); } DataStructures.combinedMapSet( peerMap, peerChainIdList, peerChainIdIndexMap, _chainId, _peerAddress, Constants.LIST_SIZE_LIMIT_DEFAULT ); emit SetPeer(_chainId, _peerAddress); } function _removePeer(uint256 _chainId) internal virtual { if (_chainId == 0) { revert ZeroChainIdError(); } DataStructures.combinedMapRemove(peerMap, peerChainIdList, peerChainIdIndexMap, _chainId); emit RemovePeer(_chainId); } function _checkPeerAddress(uint256 _chainId) internal virtual returns (address) { address peerAddress = peerMap[_chainId]; if (peerAddress == address(0)) { revert PeerNotSetError(); } return peerAddress; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @title IGateway * @notice Cross-chain gateway interface */ interface IGateway { /** * @notice Send a cross-chain message * @param _targetChainId The message target chain ID * @param _message The message content * @param _settings The gateway-specific settings */ function sendMessage( uint256 _targetChainId, bytes calldata _message, bytes calldata _settings ) external payable; /** * @notice Cross-chain message fee estimation * @param _targetChainId The ID of the target chain * @param _message The message content * @param _settings The gateway-specific settings */ function messageFee( uint256 _targetChainId, bytes calldata _message, bytes calldata _settings ) external view returns (uint256); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { IVault } from '../../interfaces/IVault.sol'; /** * @title IGatewayClient * @notice Cross-chain gateway client interface */ interface IGatewayClient { /** * @notice The standard "receive" function */ receive() external payable; /** * @notice Cross-chain message handler on the target chain * @dev The function is called by cross-chain gateways * @param _messageSourceChainId The ID of the message source chain * @param _payloadData The content of the cross-chain message */ function handleExecutionPayload( uint256 _messageSourceChainId, bytes calldata _payloadData ) external; /** * @notice Getter of the source gateway context * @return vault The source vault * @return assetAmount The source vault asset amount */ function getSourceGatewayContext() external view returns (IVault vault, uint256 assetAmount); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { ManagerRole } from '../roles/ManagerRole.sol'; /** * @title TargetGasReserve * @notice Base contract that implements the gas reserve logic for the target chain actions */ abstract contract TargetGasReserve is ManagerRole { /** * @dev The target chain gas reserve value */ uint256 public targetGasReserve; /** * @notice Emitted when the target chain gas reserve value is set * @param gasReserve The target chain gas reserve value */ event SetTargetGasReserve(uint256 gasReserve); /** * @notice Sets the target chain gas reserve value * @param _gasReserve The target chain gas reserve value */ function setTargetGasReserve(uint256 _gasReserve) external onlyManager { _setTargetGasReserve(_gasReserve); } function _setTargetGasReserve(uint256 _gasReserve) internal virtual { targetGasReserve = _gasReserve; emit SetTargetGasReserve(_gasReserve); } }
// 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 an attempt to burn a token fails */ error TokenBurnError(); /** * @notice Emitted when an attempt to mint a token fails */ error TokenMintError(); /** * @notice Emitted when a zero address is specified where it is not allowed */ error ZeroAddressError();
// 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 Function to check if the available gas matches the specified gas reserve value * @param _gasReserve Gas reserve value * @return hasGasReserve Flag of gas reserve availability * @return gasAllowed The remaining gas quantity taking the reserve into account */ function checkGasReserve( uint256 _gasReserve ) view returns (bool hasGasReserve, uint256 gasAllowed) { uint256 gasLeft = gasleft(); hasGasReserve = gasLeft >= _gasReserve; gasAllowed = hasGasReserve ? gasLeft - _gasReserve : 0; }
// 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 IActionDataStructures * @notice Action data structure declarations */ interface IActionDataStructures { /** * @notice Single-chain action data structure * @param fromTokenAddress The address of the input token * @param toTokenAddress The address of the output token * @param swapInfo The data for the single-chain swap * @param recipient The address of the recipient */ struct LocalAction { address fromTokenAddress; address toTokenAddress; SwapInfo swapInfo; address recipient; } /** * @notice Cross-chain action data structure * @param gatewayType The numeric type of the cross-chain gateway * @param vaultType The numeric type of the vault * @param sourceTokenAddress The address of the input token on the source chain * @param sourceSwapInfo The data for the source chain swap * @param targetChainId The action target chain ID * @param targetTokenAddress The address of the output token on the destination chain * @param targetSwapInfoOptions The list of data options for the target chain swap * @param targetRecipient The address of the recipient on the target chain * @param gatewaySettings The gateway-specific settings data */ struct Action { uint256 gatewayType; uint256 vaultType; address sourceTokenAddress; SwapInfo sourceSwapInfo; uint256 targetChainId; address targetTokenAddress; SwapInfo[] targetSwapInfoOptions; address targetRecipient; bytes gatewaySettings; } /** * @notice Token swap data structure * @param fromAmount The quantity of the token * @param routerType The numeric type of the swap router * @param routerData The data for the swap router call */ struct SwapInfo { uint256 fromAmount; uint256 routerType; bytes routerData; } /** * @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 vaultType The numeric type of the vault * @param targetTokenAddress The address of the output token on the target chain * @param targetSwapInfo The data for the target chain swap * @param targetRecipient The address of the recipient on the target chain */ struct TargetMessage { uint256 actionId; address sourceSender; uint256 vaultType; address targetTokenAddress; SwapInfo targetSwapInfo; address targetRecipient; } }
// 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; /** * @title IVault * @notice Vault interface */ interface IVault { /** * @notice The getter of the vault asset address */ function asset() external view returns (address); /** * @notice Checks the status of the variable token and balance actions and the variable token address * @return The address of the variable token */ function checkVariableTokenState() external view returns (address); /** * @notice Requests the vault asset tokens * @param _amount The amount of the vault asset tokens * @param _to The address of the vault asset tokens receiver * @param _forVariableBalance True if the request is made for a variable balance repayment, otherwise false * @return assetAddress The address of the vault asset token */ function requestAsset( uint256 _amount, address _to, bool _forVariableBalance ) external returns (address assetAddress); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { Pausable as PausableBase } from '@openzeppelin/contracts/security/Pausable.sol'; import { ManagerRole } from './roles/ManagerRole.sol'; /** * @title Pausable * @notice Base contract that implements the emergency pause mechanism */ abstract contract Pausable is PausableBase, ManagerRole { /** * @notice Enter pause state */ function pause() external onlyManager whenNotPaused { _pause(); } /** * @notice Exit pause state */ function unpause() external onlyManager whenPaused { _unpause(); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { RoleBearers } from './RoleBearers.sol'; /** * @title AssetSpenderRole * @notice Base contract that implements the Asset Spender role */ abstract contract AssetSpenderRole is RoleBearers { bytes32 private constant ROLE_KEY = keccak256('AssetSpender'); /** * @notice Emitted when the Asset Spender role status for the account is updated * @param account The account address * @param value The Asset Spender role status flag */ event SetAssetSpender(address indexed account, bool indexed value); /** * @notice Emitted when the caller is not an Asset Spender role bearer */ error OnlyAssetSpenderError(); /** * @dev Modifier to check if the caller is an Asset Spender role bearer */ modifier onlyAssetSpender() { if (!isAssetSpender(msg.sender)) { revert OnlyAssetSpenderError(); } _; } /** * @notice Getter of the Asset Spender role bearer count * @return The Asset Spender role bearer count */ function assetSpenderCount() external view returns (uint256) { return _roleBearerCount(ROLE_KEY); } /** * @notice Getter of the complete list of the Asset Spender role bearers * @return The complete list of the Asset Spender role bearers */ function fullAssetSpenderList() external view returns (address[] memory) { return _fullRoleBearerList(ROLE_KEY); } /** * @notice Getter of the Asset Spender role bearer status * @param _account The account address */ function isAssetSpender(address _account) public view returns (bool) { return _isRoleBearer(ROLE_KEY, _account); } function _setAssetSpender(address _account, bool _value) internal { _setRoleBearer(ROLE_KEY, _account, _value); emit SetAssetSpender(_account, _value); } }
// 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('Circle CCTP - 2023-06-26')); }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract ITokenMessenger","name":"_cctpTokenMessenger","type":"address"},{"internalType":"contract IMessageTransmitter","name":"_cctpMessageTransmitter","type":"address"},{"components":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint32","name":"domain","type":"uint32"}],"internalType":"struct CircleCctpGateway.ChainDomain[]","name":"_chainDomains","type":"tuple[]"},{"internalType":"address","name":"_asset","type":"address"},{"internalType":"bool","name":"_variableRepaymentEnabled","type":"bool"},{"internalType":"uint256","name":"_targetGasReserve","type":"uint256"},{"internalType":"address","name":"_processingFeeCollector","type":"address"},{"internalType":"address","name":"_targetExecutor","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address[]","name":"_managers","type":"address[]"},{"internalType":"bool","name":"_addOwnerToManagers","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AssetMessageError","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"CallerGuardError","type":"error"},{"inputs":[],"name":"DataMessageError","type":"error"},{"inputs":[],"name":"DomainNotSetError","type":"error"},{"inputs":[],"name":"ExecutorError","type":"error"},{"inputs":[],"name":"ListSizeLimitError","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NonContractAddressError","type":"error"},{"inputs":[],"name":"OnlyAssetSpenderError","type":"error"},{"inputs":[],"name":"OnlyClientError","type":"error"},{"inputs":[],"name":"OnlyCurrentVaultError","type":"error"},{"inputs":[],"name":"OnlyManagerError","type":"error"},{"inputs":[],"name":"OnlyMessageTransmitterError","type":"error"},{"inputs":[],"name":"PeerAddressMismatchError","type":"error"},{"inputs":[],"name":"PeerNotSetError","type":"error"},{"inputs":[],"name":"ProcessingFeeError","type":"error"},{"inputs":[],"name":"ReservedTokenError","type":"error"},{"inputs":[],"name":"SafeApproveError","type":"error"},{"inputs":[],"name":"SafeTransferError","type":"error"},{"inputs":[],"name":"SafeTransferNativeError","type":"error"},{"inputs":[],"name":"TargetAssetAmountMismatchError","type":"error"},{"inputs":[],"name":"TargetCallerError","type":"error"},{"inputs":[],"name":"TargetClientNotSetError","type":"error"},{"inputs":[{"internalType":"uint256","name":"sourceChainId","type":"uint256"},{"internalType":"address","name":"fromAddress","type":"address"}],"name":"TargetFromAddressError","type":"error"},{"inputs":[],"name":"TargetGasReserveError","type":"error"},{"inputs":[],"name":"VariableRepaymentNotEnabledError","type":"error"},{"inputs":[],"name":"VariableTokenNotSetError","type":"error"},{"inputs":[],"name":"ZeroAddressError","type":"error"},{"inputs":[],"name":"ZeroChainIdError","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"actionId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"targetChainId","type":"uint256"},{"indexed":true,"internalType":"bool","name":"useTargetExecutor","type":"bool"},{"indexed":false,"internalType":"uint64","name":"assetMessageNonce","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"dataMessageNonce","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"assetAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"processingFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"processingGas","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"GatewayActionSource","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":true,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":true,"internalType":"uint32","name":"domain","type":"uint32"}],"name":"RemoveChainDomain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"RemovePeer","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":"account","type":"address"},{"indexed":true,"internalType":"bool","name":"value","type":"bool"}],"name":"SetAssetSpender","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum CallerGuard.CallerGuardMode","name":"callerGuardMode","type":"uint8"}],"name":"SetCallerGuardMode","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":true,"internalType":"uint32","name":"domain","type":"uint32"}],"name":"SetChainDomain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"clientAddress","type":"address"}],"name":"SetClient","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":true,"internalType":"bool","name":"isListed","type":"bool"}],"name":"SetListedCallerGuardContract","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":true,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"peerAddress","type":"address"}],"name":"SetPeer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"processingFeeCollector","type":"address"}],"name":"SetProcessingFeeCollector","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"targetExecutor","type":"address"}],"name":"SetTargetExecutor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"gasReserve","type":"uint256"}],"name":"SetTargetGasReserve","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"variableRepaymentEnabled","type":"bool"}],"name":"SetVariableRepaymentEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"sourceChainId","type":"uint256"}],"name":"TargetCctpMessageFailure","type":"event"},{"anonymous":false,"inputs":[],"name":"TargetClientNotSetFailure","type":"event"},{"anonymous":false,"inputs":[],"name":"TargetExecutionFailure","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"sourceChainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"}],"name":"TargetFromAddressFailure","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"sourceChainId","type":"uint256"}],"name":"TargetGasReserveFailure","type":"event"},{"anonymous":false,"inputs":[],"name":"TargetPausedFailure","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":[],"name":"asset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetSpenderCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"callerGuardMode","outputs":[{"internalType":"enum CallerGuard.CallerGuardMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cctpMessageTransmitter","outputs":[{"internalType":"contract IMessageTransmitter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cctpTokenMessenger","outputs":[{"internalType":"contract ITokenMessenger","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"chainIdToDomain","outputs":[{"internalType":"bool","name":"isSet","type":"bool"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"checkVariableTokenState","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"}],"name":"cleanup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"client","outputs":[{"internalType":"contract IGatewayClient","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"domainToChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_assetMessage","type":"bytes"},{"internalType":"bytes","name":"_assetAttestation","type":"bytes"},{"internalType":"bytes","name":"_dataMessage","type":"bytes"},{"internalType":"bytes","name":"_dataAttestation","type":"bytes"}],"name":"executeTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_assetMessage","type":"bytes"},{"internalType":"bytes","name":"_assetAttestation","type":"bytes"},{"internalType":"address","name":"_to","type":"address"}],"name":"extractCctpAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fullAssetSpenderList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fullListedCallerGuardContractList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fullManagerList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fullPeerChainIdList","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_sourceDomain","type":"uint32"},{"internalType":"bytes32","name":"_sender","type":"bytes32"},{"internalType":"bytes","name":"_messageBody","type":"bytes"}],"name":"handleReceiveMessage","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isAssetSpender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isListedCallerGuardContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"listedCallerGuardContractCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"listedCallerGuardContractIndexMap","outputs":[{"internalType":"bool","name":"isSet","type":"bool"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"listedCallerGuardContractList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"managerCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes","name":"_settings","type":"bytes"}],"name":"messageFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","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":"","type":"uint256"}],"name":"peerChainIdIndexMap","outputs":[{"internalType":"bool","name":"isSet","type":"bool"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"peerChainIdList","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"peerCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"peerMap","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"processingFeeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_chainIds","type":"uint256[]"}],"name":"removeChainDomains","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_chainIds","type":"uint256[]"}],"name":"removePeers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceManagerRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"bool","name":"_forVariableBalance","type":"bool"}],"name":"requestAsset","outputs":[{"internalType":"address","name":"assetAddress","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_targetChainId","type":"uint256"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"bytes","name":"_settings","type":"bytes"}],"name":"sendMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_value","type":"bool"}],"name":"setAssetSpender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum CallerGuard.CallerGuardMode","name":"_callerGuardMode","type":"uint8"}],"name":"setCallerGuardMode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint32","name":"domain","type":"uint32"}],"internalType":"struct CircleCctpGateway.ChainDomain[]","name":"_chainDomains","type":"tuple[]"}],"name":"setChainDomains","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_clientAddress","type":"address"}],"name":"setClient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"flag","type":"bool"}],"internalType":"struct AccountToFlag[]","name":"_items","type":"tuple[]"}],"name":"setListedCallerGuardContracts","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":[{"components":[{"internalType":"uint256","name":"key","type":"uint256"},{"internalType":"address","name":"value","type":"address"}],"internalType":"struct KeyToAddressValue[]","name":"_peers","type":"tuple[]"}],"name":"setPeers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_processingFeeCollector","type":"address"}],"name":"setProcessingFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_targetExecutor","type":"address"}],"name":"setTargetExecutor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_gasReserve","type":"uint256"}],"name":"setTargetGasReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"targetExecutor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"targetGasReserve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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"},{"inputs":[],"name":"variableRepaymentEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60e06040526009805460ff191690553480156200001b57600080fd5b506040516200458e3803806200458e8339810160408190526200003e91620009c4565b6000805460ff19169055620000533362000121565b60016003556001600160a01b03808c166080528a1660a05260005b8951811015620000c95760008a82815181106200008f576200008f62000ad6565b60200260200101519050620000b3816000015182602001516200017a60201b60201c565b5080620000c08162000b02565b9150506200006e565b506001600160a01b03881660c052620000e2876200022c565b620000ed8662000269565b620000f885620002a4565b6200010384620002f6565b6200011083838362000340565b505050505050505050505062000b4a565b600080546001600160a01b03838116610100818102610100600160a81b0319851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b6000828152600c60205260409020805460ff1615620001ae57600181015463ffffffff166000908152600d60205260408120555b604080518082018252600180825263ffffffff851660208084018281526000898152600c83528681209551865460ff191690151517865590519490930193909355808252600d9092528281208690559151909185917f55fdf4a71f93ff89177262ca6b1cfa79f18f4425d1b8e928bb2ef7a18883a33c9190a3505050565b600e805460ff19168215159081179091556040517fdf888ec24e9081be857eb58887c4c9e546edf94ee7dbc643c07f69dd32c0d13590600090a250565b60048190556040518181527fec9e8f9ec7dd2c5310e5b87c7bedeb6ba1c5943cb4d2da1ee80335508a5bc5a49060200160405180910390a150565b600e8054610100600160a81b0319166101006001600160a01b038416908102919091179091556040517f9113819388a87769f8958d74097d68f96e457d5bc25f0168a8ffb3d3a55672a390600090a250565b600f80546001600160a01b0319166001600160a01b0383169081179091556040517f23f86a3e9ecbe238d0d1110e33eeec3ca6121dfd07f56ec10fdbf8aee36cdd3790600090a250565b60006001600160a01b038416156200035957836200035b565b335b905060005b8351811015620003ae576200039984828151811062000383576200038362000ad6565b60200260200101516001620003fa60201b60201c565b80620003a58162000b02565b91505062000360565b50818015620003c55750620003c3816200046d565b155b15620003d857620003d8816001620003fa565b6001600160a01b0381163314620003f457620003f481620004af565b50505050565b6200040462000532565b620004317f6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f838362000596565b604051811515906001600160a01b038416907fbe9474bb3e78da7e315cdffa5cfa30b767fcc95bbf44a6197da60228eea1028690600090a35050565b6001600160a01b03811660009081527f260b29b219d450563ddb0e5ca806bdadb1e125f7e8c506de0443797dd7122728602052604081205460ff165b92915050565b620004b962000532565b6001600160a01b038116620005245760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6200052f8162000121565b50565b6000546001600160a01b03610100909104163314620005945760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016200051b565b565b60008381526001602090815260408083206002909252909120620003f4919084846064600082620005d457620005ce868686620005ec565b620005e2565b620005e28686868562000721565b9695505050505050565b6001600160a01b0381166000908152602083905260409020805460ff169081156200071957600180820154865490916000916200062a919062000b1e565b9050808214620006be5760008782815481106200064b576200064b62000ad6565b9060005260206000200160009054906101000a90046001600160a01b031690508088848154811062000681576200068162000ad6565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905592909116815290879052604090206001018290555b86805480620006d157620006d162000b34565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038716825287905260408120805460ff191681556001015550505b509392505050565b6001600160a01b03821660009081526020849052604090205460ff16158015620007ce5784548211620007675760405163b1655e3360e01b815260040160405180910390fd5b6040805180820182526001808252875460208084019182526001600160a01b03881660008181528a83529586209451855460ff1916901515178555915193830193909355885491820189558884529190922090910180546001600160a01b03191690911790555b949350505050565b6001600160a01b03811681146200052f57600080fd5b8051620007f981620007d6565b919050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715620008395762000839620007fe565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200086a576200086a620007fe565b604052919050565b60006001600160401b038211156200088e576200088e620007fe565b5060051b60200190565b600082601f830112620008aa57600080fd5b81516020620008c3620008bd8362000872565b6200083f565b82815260069290921b84018101918181019086841115620008e357600080fd5b8286015b848110156200093b5760408189031215620009025760008081fd5b6200090c62000814565b815181528482015163ffffffff81168114620009285760008081fd5b81860152835291830191604001620008e7565b509695505050505050565b80518015158114620007f957600080fd5b600082601f8301126200096957600080fd5b815160206200097c620008bd8362000872565b82815260059290921b840181019181810190868411156200099c57600080fd5b8286015b848110156200093b578051620009b681620007d6565b8352918301918301620009a0565b60008060008060008060008060008060006101608c8e031215620009e757600080fd5b620009f28c620007ec565b9a5062000a0260208d01620007ec565b60408d0151909a506001600160401b0381111562000a1f57600080fd5b62000a2d8e828f0162000898565b99505062000a3e60608d01620007ec565b975062000a4e60808d0162000946565b965060a08c0151955062000a6560c08d01620007ec565b945062000a7560e08d01620007ec565b935062000a866101008d01620007ec565b6101208d01519093506001600160401b0381111562000aa457600080fd5b62000ab28e828f0162000957565b92505062000ac46101408d0162000946565b90509295989b509295989b9093969950565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820162000b175762000b1762000aec565b5060010190565b81810381811115620004a957620004a962000aec565b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05161399662000bf8600039600081816105ae01528181610e8f01528181610eb80152818161112b015281816111aa0152818161125a01528181611593015281816116c10152818161175b01528181611ce70152611de4015260008181610833015281816112a3015281816116200152818161179f01528181611d110152611e4d0152600081816108aa0152818161114c015281816111da015261127b01526139966000f3fe60806040526004361061037a5760003560e01c806385013a1b116101d1578063c116a3cb11610102578063ee10bf88116100a0578063f977350c1161006f578063f977350c14610b45578063fd8a177914610b65578063fe14e8c314610b92578063fe8fc8d414610bb257600080fd5b8063ee10bf8814610ac5578063eedc966a14610ae5578063f2fde38b14610b05578063f3ae241514610b2557600080fd5b8063dcd44d71116100dc578063dcd44d7114610a5b578063e3725b1514610a7b578063e81ea59514610a90578063e96fbd6814610aa557600080fd5b8063c116a3cb146109f0578063c2c518e114610a10578063c84e329e14610a2557600080fd5b80639c90dfa11161016f578063aeb2d2d411610149578063aeb2d2d414610969578063b7e2c37e14610989578063bb6e4936146109a9578063bc788169146109ce57600080fd5b80639c90dfa1146108cc578063a5e90eee14610929578063aa4fc83d1461094957600080fd5b80638c73eb04116101ab5780638c73eb04146108215780638da5cb5b1461085557806396abeb70146108785780639748cf7c1461089857600080fd5b806385013a1b146107c15780638526690a146107e15780638a84fa111461080157600080fd5b80634b15b2a9116102ab5780636ea9cec911610249578063786ea0ce11610223578063786ea0ce146107325780637b25b4d41461076c578063832b54911461078c5780638456cb59146107ac57600080fd5b80636ea9cec9146106d0578063715018a6146106e357806377c3a2db146106f857600080fd5b80635c975abb116102855780635c975abb1461065c578063607ab5e514610674578063630eae081461069b5780636b56a691146106bb57600080fd5b80634b15b2a9146106065780635a9fab50146106265780635c56ca351461063c57600080fd5b80632c966a3411610318578063341328c5116102f2578063341328c51461054b57806338d52e0f1461059c5780633f4ba83a146105d0578063440d7248146105e557600080fd5b80632c966a34146104f65780632fac88c01461050b57806330eb12781461052b57600080fd5b8063103b739711610354578063103b739714610408578063109e94cf1461045357806317daf0b41461048b5780631f8800fa146104d457600080fd5b806304e535e214610386578063093f0e27146103b15780630f937410146103f357600080fd5b3661038157005b600080fd5b34801561039257600080fd5b5061039b610bcc565b6040516103a89190612fc3565b60405180910390f35b3480156103bd57600080fd5b506103e57f823c7e20a184791a7512c6f8ac1d42562079dc51f9442abc45d36a3d003127d781565b6040519081526020016103a8565b3480156103ff57600080fd5b5061039b610c2e565b34801561041457600080fd5b5060008051602061394183398151915260005260016020527f3c2285c553468ca8f30447b24bb463c127f1b840e23a0cafa23caa79d906669a546103e5565b34801561045f57600080fd5b50600554610473906001600160a01b031681565b6040516001600160a01b0390911681526020016103a8565b34801561049757600080fd5b506104c46104a6366004613030565b6001600160a01b03166000908152600b602052604090205460ff1690565b60405190151581526020016103a8565b3480156104e057600080fd5b506104f46104ef366004613030565b610c5e565b005b34801561050257600080fd5b50610473610c90565b34801561051757600080fd5b506104f461052636600461309f565b610ccf565b34801561053757600080fd5b506104f46105463660046130e0565b610d90565b34801561055757600080fd5b50610585610566366004613030565b600b602052600090815260409020805460019091015460ff9091169082565b6040805192151583526020830191909152016103a8565b3480156105a857600080fd5b506104737f000000000000000000000000000000000000000000000000000000000000000081565b3480156105dc57600080fd5b506104f4610df4565b3480156105f157600080fd5b506104c4610600366004613030565b50600090565b34801561061257600080fd5b5061047361062136600461311a565b610e2c565b34801561063257600080fd5b506103e560045481565b34801561064857600080fd5b506104c4610657366004613030565b610ede565b34801561066857600080fd5b5060005460ff166104c4565b34801561068057600080fd5b5060095461068e9060ff1681565b6040516103a89190613172565b3480156106a757600080fd5b506104f46106b636600461319a565b610f20565b3480156106c757600080fd5b50600a546103e5565b6104f46106de3660046131f4565b610f4f565b3480156106ef57600080fd5b506104f46113ca565b34801561070457600080fd5b5061058561071336600461319a565b600c602052600090815260409020805460019091015460ff9091169082565b34801561073e57600080fd5b5061058561074d36600461319a565b6008602052600090815260409020805460019091015460ff9091169082565b34801561077857600080fd5b5061047361078736600461319a565b6113dc565b34801561079857600080fd5b506103e56107a736600461319a565b611406565b3480156107b857600080fd5b506104f4611427565b3480156107cd57600080fd5b506104f46107dc36600461309f565b61145d565b3480156107ed57600080fd5b506104f46107fc366004613030565b6114dc565b34801561080d57600080fd5b506104f461081c36600461326d565b611555565b34801561082d57600080fd5b506104737f000000000000000000000000000000000000000000000000000000000000000081565b34801561086157600080fd5b5060005461010090046001600160a01b0316610473565b34801561088457600080fd5b506104c4610893366004613304565b61178a565b3480156108a457600080fd5b506104737f000000000000000000000000000000000000000000000000000000000000000081565b3480156108d857600080fd5b507fab6730ecea49587e6c50637868078921bc389a6c228c95e1c7259ae5a61c217460005260016020527fb6368b31e79ffb73a14a00fbd9c0dbbe43a3a26df7f98e18d14334693e18dfce546103e5565b34801561093557600080fd5b506104f461094436600461335d565b6119c6565b34801561095557600080fd5b506103e56109643660046131f4565b611a23565b34801561097557600080fd5b50600f54610473906001600160a01b031681565b34801561099557600080fd5b506104f46109a4366004613396565b611a3d565b3480156109b557600080fd5b50600e546104739061010090046001600160a01b031681565b3480156109da57600080fd5b506109e3611aa7565b6040516103a8919061340a565b3480156109fc57600080fd5b506104f4610a0b36600461335d565b611afe565b348015610a1c57600080fd5b506104f4611b2e565b348015610a3157600080fd5b50610473610a4036600461319a565b6006602052600090815260409020546001600160a01b031681565b348015610a6757600080fd5b506104f4610a76366004613396565b611b9b565b348015610a8757600080fd5b5061039b611c0c565b348015610a9c57600080fd5b506007546103e5565b348015610ab157600080fd5b506104f4610ac0366004613442565b611c25565b348015610ad157600080fd5b506104f4610ae0366004613030565b611f17565b348015610af157600080fd5b506103e5610b00366004613030565b611f46565b348015610b1157600080fd5b506104f4610b20366004613030565b611fe1565b348015610b3157600080fd5b506104c4610b40366004613030565b612057565b348015610b5157600080fd5b506104f4610b60366004613505565b612097565b348015610b7157600080fd5b506103e5610b80366004613526565b600d6020526000908152604090205481565b348015610b9e57600080fd5b506104f4610bad36600461309f565b61211f565b348015610bbe57600080fd5b50600e546104c49060ff1681565b6060600a805480602002602001604051908101604052809291908181526020018280548015610c2457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c06575b5050505050905090565b6060610c597fab6730ecea49587e6c50637868078921bc389a6c228c95e1c7259ae5a61c217461222b565b905090565b610c6733612057565b610c8457604051637c3ea23f60e01b815260040160405180910390fd5b610c8d81612297565b50565b600e5460009060ff16610cb657604051634dd32fa760e11b815260040160405180910390fd5b604051630d51877360e21b815260040160405180910390fd5b610cd833612057565b610cf557604051637c3ea23f60e01b815260040160405180910390fd5b60005b81811015610d8b5736838383818110610d1357610d13613541565b604090810292909201925050813590600090610d3490840160208501613030565b9050468203610d6b576001600160a01b0381163014610d6657604051631131ed9760e31b815260040160405180910390fd5b610d75565b610d7582826122e1565b5050508080610d839061356d565b915050610cf8565b505050565b610d9933612057565b610db657604051637c3ea23f60e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03831601610de957610de53382612376565b5050565b610de5823383612404565b610dfd33612057565b610e1a57604051637c3ea23f60e01b815260040160405180910390fd5b610e226124f6565b610e2a61253f565b565b6000610e36612591565b610e3f33610ede565b610e5c5760405163085c44cb60e31b815260040160405180910390fd5b818015610e6c5750600e5460ff16155b15610e8a57604051634dd32fa760e11b815260040160405180910390fd5b610eb57f00000000000000000000000000000000000000000000000000000000000000008486612404565b507f00000000000000000000000000000000000000000000000000000000000000009392505050565b6001600160a01b03811660009081527f91fc3844d4d576137f627e112fa2b39fcc5933d06153e6698ea43f81fc70b81b602052604081205460ff165b92915050565b610f2933612057565b610f4657604051637c3ea23f60e01b815260040160405180910390fd5b610c8d816125d7565b6005546001600160a01b03163314610f7a5760405163424029e160e01b815260040160405180910390fd5b610f82612591565b6005546040805163018130df60e51b8152815160009384936001600160a01b03909116926330261be092600480830193928290030181865afa158015610fcc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff09190613586565b90925090506001600160a01b038216301461101e5760405163f5f9a58f60e01b815260040160405180910390fd5b6040805160a080820183526000808352602080840182905283850182905260608085018390526080948501839052855193840186528284529083018290529382018190529281018390529081019190915261108761107b89612612565b6001600160a01b031690565b815261109288612648565b63ffffffff1660208201526000806110aa8787612682565b911515608086015292509050348211156110d7576040516360b5c54960e01b815260040160405180910390fd5b6000821180156110f65750600e5461010090046001600160a01b031615155b1561111657600e546111169061010090046001600160a01b031683612376565b6000611124898b018b613644565b90506111717f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008761269f565b60208401518451604051637c2b6edb60e11b81526004810188905263ffffffff9092166024830152604482018190526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116606484015260848301919091527f0000000000000000000000000000000000000000000000000000000000000000169063f856ddb69060a4016020604051808303816000875af1158015611223573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611247919061378d565b6001600160401b031660408501526112a17f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000600061269f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f7259a758560200151866000015187600001518e8e6040518663ffffffff1660e01b81526004016113019594939291906137df565b6020604051808303816000875af1158015611320573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611344919061378d565b6001600160401b03908116606086810182905260808088015185516040808b015181519716875260208701959095529385018a905291840187905283018590524260a08401521515918d91907f742fc5a2eb8bd42a536089d583f08bf52f3110072f62c20f54468cd81bc1815a9060c00160405180910390a45050505050505050505050565b6113d2612789565b610e2a60006127e9565b600a81815481106113ec57600080fd5b6000918252602090912001546001600160a01b0316905081565b6007818154811061141657600080fd5b600091825260209091200154905081565b61143033612057565b61144d57604051637c3ea23f60e01b815260040160405180910390fd5b611455612591565b610e2a612842565b61146633612057565b61148357604051637c3ea23f60e01b815260040160405180910390fd5b60005b81811015610d8b57368383838181106114a1576114a1613541565b90506040020190506114c981600001358260200160208101906114c49190613526565b61287f565b50806114d48161356d565b915050611486565b6114e533612057565b61150257604051637c3ea23f60e01b815260040160405180910390fd5b61150b81612930565b600580546001600160a01b0319166001600160a01b0383169081179091556040517f764166c557b419ae9f4bca81c505141ce7017b4bdb4c610ad113a50ec7e578a990600090a250565b61155e33612057565b61157b57604051637c3ea23f60e01b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156115e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116069190613816565b604051630afd9fa560e31b81529091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906357ecfd289061165b90899089908990899060040161382f565b6020604051808303816000875af115801561167a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169e9190613856565b506040516370a0823160e01b815230600482015260009082906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611708573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172c9190613816565b6117369190613873565b905060008111801561175157506001600160a01b0383163014155b15611781576117817f00000000000000000000000000000000000000000000000000000000000000008483612404565b50505050505050565b6000611794612591565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146117dd576040516331e4d14960e01b815260040160405180910390fd5b63ffffffff85166000908152600d6020526040812054908590821580159061180d57506001600160a01b03821615155b801561183257506000838152600660205260409020546001600160a01b038381169116145b9050806118685760405162e3894560e01b8152600481018490526001600160a01b03831660248201526044015b60405180910390fd5b50600061187785870187613644565b601054600f549192506001600160a01b0390811691600091168214806118b2575082602001516001600160a01b0316826001600160a01b0316145b806118d257508260a001516001600160a01b0316826001600160a01b0316145b9050806118f25760405163460327af60e11b815260040160405180910390fd5b50506011546080820151511461191b5760405163ec8cb1df60e01b815260040160405180910390fd5b600080611929600454612963565b915091508161194b57604051636d0ea9b360e11b815260040160405180910390fd5b60055460405163032ad3cf60e51b81526001600160a01b039091169063655a79e09083906119819089908d908d90600401613886565b600060405180830381600088803b15801561199b57600080fd5b5087f11580156119af573d6000803e3d6000fd5b50505050506001955050505050505b949350505050565b6119ce612789565b6119e7600080516020613941833981519152838361298f565b604051811515906001600160a01b038416907fbe9474bb3e78da7e315cdffa5cfa30b767fcc95bbf44a6197da60228eea1028690600090a35050565b600080611a308484612682565b5098975050505050505050565b611a4633612057565b611a6357604051637c3ea23f60e01b815260040160405180910390fd5b60005b81811015610d8b576000838383818110611a8257611a82613541565b905060200201359050611a94816129bc565b5080611a9f8161356d565b915050611a66565b60606007805480602002602001604051908101604052809291908181526020018280548015610c2457602002820191906000526020600020905b815481526020019060010190808311611ae1575050505050905090565b611b0733612057565b611b2457604051637c3ea23f60e01b815260040160405180910390fd5b610de58282612a45565b611b3733612057565b611b5457604051637c3ea23f60e01b815260040160405180910390fd5b611b6e60008051602061394183398151915233600061298f565b60405133907f6cc2c67081f55c2fffb7c008fa995fbbf890f48c7c16fba93d8220f00dc84cc590600090a2565b611ba433612057565b611bc157604051637c3ea23f60e01b815260040160405180910390fd5b60005b81811015610d8b576000838383818110611be057611be0613541565b905060200201359050468114611bf957611bf981612aac565b5080611c048161356d565b915050611bc4565b6060610c5960008051602061394183398151915261222b565b611c2d612591565b611c35612b0b565b333214611cb7576000600260095460ff166002811115611c5757611c5761315c565b1480611c935750600160095460ff166002811115611c7757611c7761315c565b148015611c935750336000908152600b602052604090205460ff165b905080611cb557604051630fa0970d60e11b815233600482015260240161185f565b505b6005546001600160a01b0316611ce05760405163bc864a6960e01b815260040160405180910390fd5b6000611d0b7f0000000000000000000000000000000000000000000000000000000000000000611f46565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166357ecfd288b8b8b8b6040518563ffffffff1660e01b8152600401611d61949392919061382f565b6020604051808303816000875af1158015611d80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611da49190613856565b905080611dc45760405163ecf5a8ff60e01b815260040160405180910390fd5b6040518060400160405280336001600160a01b0316815260200183611e087f0000000000000000000000000000000000000000000000000000000000000000611f46565b611e129190613873565b90528051601080546001600160a01b0319166001600160a01b03928316179055602090910151601155604051630afd9fa560e31b81526000917f000000000000000000000000000000000000000000000000000000000000000016906357ecfd2890611e88908a908a908a908a9060040161382f565b6020604051808303816000875af1158015611ea7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ecb9190613856565b905080611eeb57604051631c2f23e960e21b815260040160405180910390fd5b5050601080546001600160a01b0319169055506000601155611f0d6001600355565b5050505050505050565b611f2033612057565b611f3d57604051637c3ea23f60e01b815260040160405180910390fd5b610c8d81612b64565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03831601611f74575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015611fb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1a9190613816565b919050565b611fe9612789565b6001600160a01b03811661204e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161185f565b610c8d816127e9565b6001600160a01b03811660009081527f260b29b219d450563ddb0e5ca806bdadb1e125f7e8c506de0443797dd7122728602052604081205460ff16610f1a565b6120a033612057565b6120bd57604051637c3ea23f60e01b815260040160405180910390fd5b6009805482919060ff191660018360028111156120dc576120dc61315c565b02179055508060028111156120f3576120f361315c565b6040517f332a9f1d3bd9b0f7abbd95838fed6b417589632d0eb33f2d8ae6e2aa17178efd90600090a250565b61212833612057565b61214557604051637c3ea23f60e01b815260040160405180910390fd5b60005b81811015610d8b573683838381811061216357612163613541565b905060400201905080602001602081019061217e91906138a9565b15612198576121986121936020830183613030565b612930565b6121c3600a600b6121ac6020850185613030565b6121bc60408601602087016138a9565b6064612bb6565b506121d460408201602083016138a9565b15156121e36020830183613030565b6001600160a01b03167f1470aed653fa8a8ce4c7b2f41287634199f7ec3c4f5fd0ace97d82cf006beec360405160405180910390a350806122238161356d565b915050612148565b60008181526001602090815260409182902080548351818402810184019094528084526060939283018282801561228b57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161226d575b50505050509050919050565b600f80546001600160a01b0319166001600160a01b0383169081179091556040517f23f86a3e9ecbe238d0d1110e33eeec3ca6121dfd07f56ec10fdbf8aee36cdd3790600090a250565b81600003612302576040516381e7376360e01b815260040160405180910390fd5b6001600160a01b03811661232957604051633efa09af60e01b815260040160405180910390fd5b61233b60066007600885856064612be3565b506040516001600160a01b0382169083907f357d1ebd1dc0d53cc15161206b9a39c9ca30667bd997cf921eb00e4c78a454f590600090a35050565b604080516000808252602082019092526001600160a01b0384169083906040516123a091906138c6565b60006040518083038185875af1925050503d80600081146123dd576040519150601f19603f3d011682016040523d82523d6000602084013e6123e2565b606091505b5050905080610d8b57604051632e05b05360e21b815260040160405180910390fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161246091906138c6565b6000604051808303816000865af19150503d806000811461249d576040519150601f19603f3d011682016040523d82523d6000602084013e6124a2565b606091505b509150915060008280156124ce5750815115806124ce5750818060200190518101906124ce9190613856565b9050806124ee57604051632fdb1b7f60e11b815260040160405180910390fd5b505050505050565b60005460ff16610e2a5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161185f565b6125476124f6565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60005460ff1615610e2a5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161185f565b60048190556040518181527fec9e8f9ec7dd2c5310e5b87c7bedeb6ba1c5943cb4d2da1ee80335508a5bc5a49060200160405180910390a150565b6000818152600660205260408120546001600160a01b031680610f1a57604051631a81634560e01b815260040160405180910390fd5b6000818152600c60205260408120805460ff166126785760405163731da1e960e11b815260040160405180910390fd5b6001015492915050565b60008080612692848601866138f5565b9250925092509250925092565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392908716916126fb91906138c6565b6000604051808303816000865af19150503d8060008114612738576040519150601f19603f3d011682016040523d82523d6000602084013e61273d565b606091505b509150915060008280156127695750815115806127695750818060200190518101906127699190613856565b9050806124ee5760405163b45d44e760e01b815260040160405180910390fd5b6000546001600160a01b03610100909104163314610e2a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161185f565b600080546001600160a01b03838116610100818102610100600160a81b0319851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b61284a612591565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586125743390565b6000828152600c60205260409020805460ff16156128b257600181015463ffffffff166000908152600d60205260408120555b604080518082018252600180825263ffffffff851660208084018281526000898152600c83528681209551865460ff191690151517865590519490930193909355808252600d9092528281208690559151909185917f55fdf4a71f93ff89177262ca6b1cfa79f18f4425d1b8e928bb2ef7a18883a33c9190a3505050565b6001600160a01b0381163b610c8d57604051638c50d7cd60e01b81526001600160a01b038216600482015260240161185f565b60008060005a90508381101592508261297d576000612987565b6129878482613873565b915050915091565b600083815260016020908152604080832060029092529091206129b6919084846064612bb6565b50505050565b6000818152600c60205260408120805490919060ff16156129f45750600181015463ffffffff81166000908152600d60205260408120555b6000838152600c6020526040808220805460ff191681556001018290555163ffffffff83169185917ff79bac28779a4bff7a04c8f64491c5be344a30648bb4539212da26244b0a6e1a9190a3505050565b612a707fab6730ecea49587e6c50637868078921bc389a6c228c95e1c7259ae5a61c2174838361298f565b604051811515906001600160a01b038416907fc6b049f4dc9561b397b0cef913ea5f18165b682b193be62c0bbbf9ca8763aeba90600090a35050565b80600003612acd576040516381e7376360e01b815260040160405180910390fd5b612adc60066007600884612c3f565b5060405181907feb39225b53386d0eb02af9cf2c6b6a0c345a97654f1e67fb21b0b5aaac81ec4a90600090a250565b600260035403612b5d5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161185f565b6002600355565b600e8054610100600160a81b0319166101006001600160a01b038416908102919091179091556040517f9113819388a87769f8958d74097d68f96e457d5bc25f0168a8ffb3d3a55672a390600090a250565b600082612bcd57612bc8868686612c87565b612bd9565b612bd986868685612daf565b9695505050505050565b60008381526020859052604090205460ff16158015612c0a57612c0886868685612e5f565b505b600093845260209690965250604090912080546001600160a01b0319166001600160a01b039092169190911790555090919050565b60008181526020839052604090205460ff1680156119be57600082815260208690526040902080546001600160a01b0319169055612c7e848484612ee8565b50949350505050565b6001600160a01b0381166000908152602083905260409020805460ff16908115612da75760018082015486549091600091612cc29190613873565b9050808214612d4f576000878281548110612cdf57612cdf613541565b9060005260206000200160009054906101000a90046001600160a01b0316905080888481548110612d1257612d12613541565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905592909116815290879052604090206001018290555b86805480612d5f57612d5f61392a565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038716825287905260408120805460ff191681556001015550505b509392505050565b6001600160a01b03821660009081526020849052604090205460ff161580156119be5784548211612df35760405163b1655e3360e01b815260040160405180910390fd5b6040805180820182526001808252875460208084019182526001600160a01b039790971660008181529888529388209251835460ff19169015151783555191810191909155865490810187559585529290932090930180546001600160a01b0319169091179055919050565b60008281526020849052604090205460ff161580156119be5784548211612e995760405163b1655e3360e01b815260040160405180910390fd5b60408051808201825260018082528754602080840191825260008881529881529388209251835460ff191690151517835551918101919091558654908101875595855290932090930155919050565b6000818152602083905260409020805460ff16908115612da75760018082015486549091600091612f199190613873565b9050808214612f78576000878281548110612f3657612f36613541565b9060005260206000200154905080888481548110612f5657612f56613541565b6000918252602080832090910192909255918252879052604090206001018290555b86805480612f8857612f8861392a565b60008281526020808220830160001990810183905590920190925586825287905260408120805460ff19168155600101555050509392505050565b6020808252825182820181905260009190848201906040850190845b818110156130045783516001600160a01b031683529284019291840191600101612fdf565b50909695505050505050565b6001600160a01b0381168114610c8d57600080fd5b8035611fdc81613010565b60006020828403121561304257600080fd5b813561304d81613010565b9392505050565b60008083601f84011261306657600080fd5b5081356001600160401b0381111561307d57600080fd5b6020830191508360208260061b850101111561309857600080fd5b9250929050565b600080602083850312156130b257600080fd5b82356001600160401b038111156130c857600080fd5b6130d485828601613054565b90969095509350505050565b600080604083850312156130f357600080fd5b82356130fe81613010565b946020939093013593505050565b8015158114610c8d57600080fd5b60008060006060848603121561312f57600080fd5b83359250602084013561314181613010565b915060408401356131518161310c565b809150509250925092565b634e487b7160e01b600052602160045260246000fd5b602081016003831061319457634e487b7160e01b600052602160045260246000fd5b91905290565b6000602082840312156131ac57600080fd5b5035919050565b60008083601f8401126131c557600080fd5b5081356001600160401b038111156131dc57600080fd5b60208301915083602082850101111561309857600080fd5b60008060008060006060868803121561320c57600080fd5b8535945060208601356001600160401b038082111561322a57600080fd5b61323689838a016131b3565b9096509450604088013591508082111561324f57600080fd5b5061325c888289016131b3565b969995985093965092949392505050565b60008060008060006060868803121561328557600080fd5b85356001600160401b038082111561329c57600080fd5b6132a889838a016131b3565b909750955060208801359150808211156132c157600080fd5b506132ce888289016131b3565b90945092505060408601356132e281613010565b809150509295509295909350565b803563ffffffff81168114611fdc57600080fd5b6000806000806060858703121561331a57600080fd5b613323856132f0565b93506020850135925060408501356001600160401b0381111561334557600080fd5b613351878288016131b3565b95989497509550505050565b6000806040838503121561337057600080fd5b823561337b81613010565b9150602083013561338b8161310c565b809150509250929050565b600080602083850312156133a957600080fd5b82356001600160401b03808211156133c057600080fd5b818501915085601f8301126133d457600080fd5b8135818111156133e357600080fd5b8660208260051b85010111156133f857600080fd5b60209290920196919550909350505050565b6020808252825182820181905260009190848201906040850190845b8181101561300457835183529284019291840191600101613426565b6000806000806000806000806080898b03121561345e57600080fd5b88356001600160401b038082111561347557600080fd5b6134818c838d016131b3565b909a50985060208b013591508082111561349a57600080fd5b6134a68c838d016131b3565b909850965060408b01359150808211156134bf57600080fd5b6134cb8c838d016131b3565b909650945060608b01359150808211156134e457600080fd5b506134f18b828c016131b3565b999c989b5096995094979396929594505050565b60006020828403121561351757600080fd5b81356003811061304d57600080fd5b60006020828403121561353857600080fd5b61304d826132f0565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161357f5761357f613557565b5060010190565b6000806040838503121561359957600080fd5b82516135a481613010565b6020939093015192949293505050565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b03811182821017156135ec576135ec6135b4565b60405290565b604051606081016001600160401b03811182821017156135ec576135ec6135b4565b604051601f8201601f191681016001600160401b038111828210171561363c5761363c6135b4565b604052919050565b6000602080838503121561365757600080fd5b82356001600160401b038082111561366e57600080fd5b9084019060c0828703121561368257600080fd5b61368a6135ca565b823581528383013561369b81613010565b818501526040838101359082015260608301356136b781613010565b60608201526080830135828111156136ce57600080fd5b8301606081890312156136e057600080fd5b6136e86135f2565b81358152858201358682015260408201358481111561370657600080fd5b80830192505088601f83011261371b57600080fd5b81358481111561372d5761372d6135b4565b61373f601f8201601f19168801613614565b9450808552898782850101111561375557600080fd5b808784018887013760009085018701526040810184905260808301525061377e60a08401613025565b60a08201529695505050505050565b60006020828403121561379f57600080fd5b81516001600160401b038116811461304d57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b63ffffffff8616815284602082015283604082015260806060820152600061380b6080830184866137b6565b979650505050505050565b60006020828403121561382857600080fd5b5051919050565b6040815260006138436040830186886137b6565b828103602084015261380b8185876137b6565b60006020828403121561386857600080fd5b815161304d8161310c565b81810381811115610f1a57610f1a613557565b8381526040602082015260006138a06040830184866137b6565b95945050505050565b6000602082840312156138bb57600080fd5b813561304d8161310c565b6000825160005b818110156138e757602081860181015185830152016138cd565b506000920191825250919050565b60008060006060848603121561390a57600080fd5b83356139158161310c565b95602085013595506040909401359392505050565b634e487b7160e01b600052603160045260246000fdfe6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6fa2646970667358221220910caf4033a37ee4941c3ef69ed6e07b97ef76d851c041e7ead9d01de20c62b764736f6c63430008130033000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af31550000000000000000000000000a992d191deec32afe36203ad87d7d289a738f810000000000000000000000000000000000000000000000000000000000000160000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000271000000000000000000000000054c28fdd59025942fe71545de8c6358c30b3a16a00000000000000000000000054c28fdd59025942fe71545de8c6358c30b3a16a00000000000000000000000072e28c7f34100afefc399fcc0ae041b8fe5841ae000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000a4b10000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000a86a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000006741a38adbd040e9e1a8a9c78ba52987e56a3e78
Deployed Bytecode
0x60806040526004361061037a5760003560e01c806385013a1b116101d1578063c116a3cb11610102578063ee10bf88116100a0578063f977350c1161006f578063f977350c14610b45578063fd8a177914610b65578063fe14e8c314610b92578063fe8fc8d414610bb257600080fd5b8063ee10bf8814610ac5578063eedc966a14610ae5578063f2fde38b14610b05578063f3ae241514610b2557600080fd5b8063dcd44d71116100dc578063dcd44d7114610a5b578063e3725b1514610a7b578063e81ea59514610a90578063e96fbd6814610aa557600080fd5b8063c116a3cb146109f0578063c2c518e114610a10578063c84e329e14610a2557600080fd5b80639c90dfa11161016f578063aeb2d2d411610149578063aeb2d2d414610969578063b7e2c37e14610989578063bb6e4936146109a9578063bc788169146109ce57600080fd5b80639c90dfa1146108cc578063a5e90eee14610929578063aa4fc83d1461094957600080fd5b80638c73eb04116101ab5780638c73eb04146108215780638da5cb5b1461085557806396abeb70146108785780639748cf7c1461089857600080fd5b806385013a1b146107c15780638526690a146107e15780638a84fa111461080157600080fd5b80634b15b2a9116102ab5780636ea9cec911610249578063786ea0ce11610223578063786ea0ce146107325780637b25b4d41461076c578063832b54911461078c5780638456cb59146107ac57600080fd5b80636ea9cec9146106d0578063715018a6146106e357806377c3a2db146106f857600080fd5b80635c975abb116102855780635c975abb1461065c578063607ab5e514610674578063630eae081461069b5780636b56a691146106bb57600080fd5b80634b15b2a9146106065780635a9fab50146106265780635c56ca351461063c57600080fd5b80632c966a3411610318578063341328c5116102f2578063341328c51461054b57806338d52e0f1461059c5780633f4ba83a146105d0578063440d7248146105e557600080fd5b80632c966a34146104f65780632fac88c01461050b57806330eb12781461052b57600080fd5b8063103b739711610354578063103b739714610408578063109e94cf1461045357806317daf0b41461048b5780631f8800fa146104d457600080fd5b806304e535e214610386578063093f0e27146103b15780630f937410146103f357600080fd5b3661038157005b600080fd5b34801561039257600080fd5b5061039b610bcc565b6040516103a89190612fc3565b60405180910390f35b3480156103bd57600080fd5b506103e57f823c7e20a184791a7512c6f8ac1d42562079dc51f9442abc45d36a3d003127d781565b6040519081526020016103a8565b3480156103ff57600080fd5b5061039b610c2e565b34801561041457600080fd5b5060008051602061394183398151915260005260016020527f3c2285c553468ca8f30447b24bb463c127f1b840e23a0cafa23caa79d906669a546103e5565b34801561045f57600080fd5b50600554610473906001600160a01b031681565b6040516001600160a01b0390911681526020016103a8565b34801561049757600080fd5b506104c46104a6366004613030565b6001600160a01b03166000908152600b602052604090205460ff1690565b60405190151581526020016103a8565b3480156104e057600080fd5b506104f46104ef366004613030565b610c5e565b005b34801561050257600080fd5b50610473610c90565b34801561051757600080fd5b506104f461052636600461309f565b610ccf565b34801561053757600080fd5b506104f46105463660046130e0565b610d90565b34801561055757600080fd5b50610585610566366004613030565b600b602052600090815260409020805460019091015460ff9091169082565b6040805192151583526020830191909152016103a8565b3480156105a857600080fd5b506104737f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b3480156105dc57600080fd5b506104f4610df4565b3480156105f157600080fd5b506104c4610600366004613030565b50600090565b34801561061257600080fd5b5061047361062136600461311a565b610e2c565b34801561063257600080fd5b506103e560045481565b34801561064857600080fd5b506104c4610657366004613030565b610ede565b34801561066857600080fd5b5060005460ff166104c4565b34801561068057600080fd5b5060095461068e9060ff1681565b6040516103a89190613172565b3480156106a757600080fd5b506104f46106b636600461319a565b610f20565b3480156106c757600080fd5b50600a546103e5565b6104f46106de3660046131f4565b610f4f565b3480156106ef57600080fd5b506104f46113ca565b34801561070457600080fd5b5061058561071336600461319a565b600c602052600090815260409020805460019091015460ff9091169082565b34801561073e57600080fd5b5061058561074d36600461319a565b6008602052600090815260409020805460019091015460ff9091169082565b34801561077857600080fd5b5061047361078736600461319a565b6113dc565b34801561079857600080fd5b506103e56107a736600461319a565b611406565b3480156107b857600080fd5b506104f4611427565b3480156107cd57600080fd5b506104f46107dc36600461309f565b61145d565b3480156107ed57600080fd5b506104f46107fc366004613030565b6114dc565b34801561080d57600080fd5b506104f461081c36600461326d565b611555565b34801561082d57600080fd5b506104737f0000000000000000000000000a992d191deec32afe36203ad87d7d289a738f8181565b34801561086157600080fd5b5060005461010090046001600160a01b0316610473565b34801561088457600080fd5b506104c4610893366004613304565b61178a565b3480156108a457600080fd5b506104737f000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af315581565b3480156108d857600080fd5b507fab6730ecea49587e6c50637868078921bc389a6c228c95e1c7259ae5a61c217460005260016020527fb6368b31e79ffb73a14a00fbd9c0dbbe43a3a26df7f98e18d14334693e18dfce546103e5565b34801561093557600080fd5b506104f461094436600461335d565b6119c6565b34801561095557600080fd5b506103e56109643660046131f4565b611a23565b34801561097557600080fd5b50600f54610473906001600160a01b031681565b34801561099557600080fd5b506104f46109a4366004613396565b611a3d565b3480156109b557600080fd5b50600e546104739061010090046001600160a01b031681565b3480156109da57600080fd5b506109e3611aa7565b6040516103a8919061340a565b3480156109fc57600080fd5b506104f4610a0b36600461335d565b611afe565b348015610a1c57600080fd5b506104f4611b2e565b348015610a3157600080fd5b50610473610a4036600461319a565b6006602052600090815260409020546001600160a01b031681565b348015610a6757600080fd5b506104f4610a76366004613396565b611b9b565b348015610a8757600080fd5b5061039b611c0c565b348015610a9c57600080fd5b506007546103e5565b348015610ab157600080fd5b506104f4610ac0366004613442565b611c25565b348015610ad157600080fd5b506104f4610ae0366004613030565b611f17565b348015610af157600080fd5b506103e5610b00366004613030565b611f46565b348015610b1157600080fd5b506104f4610b20366004613030565b611fe1565b348015610b3157600080fd5b506104c4610b40366004613030565b612057565b348015610b5157600080fd5b506104f4610b60366004613505565b612097565b348015610b7157600080fd5b506103e5610b80366004613526565b600d6020526000908152604090205481565b348015610b9e57600080fd5b506104f4610bad36600461309f565b61211f565b348015610bbe57600080fd5b50600e546104c49060ff1681565b6060600a805480602002602001604051908101604052809291908181526020018280548015610c2457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c06575b5050505050905090565b6060610c597fab6730ecea49587e6c50637868078921bc389a6c228c95e1c7259ae5a61c217461222b565b905090565b610c6733612057565b610c8457604051637c3ea23f60e01b815260040160405180910390fd5b610c8d81612297565b50565b600e5460009060ff16610cb657604051634dd32fa760e11b815260040160405180910390fd5b604051630d51877360e21b815260040160405180910390fd5b610cd833612057565b610cf557604051637c3ea23f60e01b815260040160405180910390fd5b60005b81811015610d8b5736838383818110610d1357610d13613541565b604090810292909201925050813590600090610d3490840160208501613030565b9050468203610d6b576001600160a01b0381163014610d6657604051631131ed9760e31b815260040160405180910390fd5b610d75565b610d7582826122e1565b5050508080610d839061356d565b915050610cf8565b505050565b610d9933612057565b610db657604051637c3ea23f60e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03831601610de957610de53382612376565b5050565b610de5823383612404565b610dfd33612057565b610e1a57604051637c3ea23f60e01b815260040160405180910390fd5b610e226124f6565b610e2a61253f565b565b6000610e36612591565b610e3f33610ede565b610e5c5760405163085c44cb60e31b815260040160405180910390fd5b818015610e6c5750600e5460ff16155b15610e8a57604051634dd32fa760e11b815260040160405180910390fd5b610eb57f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488486612404565b507f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489392505050565b6001600160a01b03811660009081527f91fc3844d4d576137f627e112fa2b39fcc5933d06153e6698ea43f81fc70b81b602052604081205460ff165b92915050565b610f2933612057565b610f4657604051637c3ea23f60e01b815260040160405180910390fd5b610c8d816125d7565b6005546001600160a01b03163314610f7a5760405163424029e160e01b815260040160405180910390fd5b610f82612591565b6005546040805163018130df60e51b8152815160009384936001600160a01b03909116926330261be092600480830193928290030181865afa158015610fcc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff09190613586565b90925090506001600160a01b038216301461101e5760405163f5f9a58f60e01b815260040160405180910390fd5b6040805160a080820183526000808352602080840182905283850182905260608085018390526080948501839052855193840186528284529083018290529382018190529281018390529081019190915261108761107b89612612565b6001600160a01b031690565b815261109288612648565b63ffffffff1660208201526000806110aa8787612682565b911515608086015292509050348211156110d7576040516360b5c54960e01b815260040160405180910390fd5b6000821180156110f65750600e5461010090046001600160a01b031615155b1561111657600e546111169061010090046001600160a01b031683612376565b6000611124898b018b613644565b90506111717f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb487f000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af31558761269f565b60208401518451604051637c2b6edb60e11b81526004810188905263ffffffff9092166024830152604482018190526001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488116606484015260848301919091527f000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155169063f856ddb69060a4016020604051808303816000875af1158015611223573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611247919061378d565b6001600160401b031660408501526112a17f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb487f000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155600061269f565b7f0000000000000000000000000a992d191deec32afe36203ad87d7d289a738f816001600160a01b031663f7259a758560200151866000015187600001518e8e6040518663ffffffff1660e01b81526004016113019594939291906137df565b6020604051808303816000875af1158015611320573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611344919061378d565b6001600160401b03908116606086810182905260808088015185516040808b015181519716875260208701959095529385018a905291840187905283018590524260a08401521515918d91907f742fc5a2eb8bd42a536089d583f08bf52f3110072f62c20f54468cd81bc1815a9060c00160405180910390a45050505050505050505050565b6113d2612789565b610e2a60006127e9565b600a81815481106113ec57600080fd5b6000918252602090912001546001600160a01b0316905081565b6007818154811061141657600080fd5b600091825260209091200154905081565b61143033612057565b61144d57604051637c3ea23f60e01b815260040160405180910390fd5b611455612591565b610e2a612842565b61146633612057565b61148357604051637c3ea23f60e01b815260040160405180910390fd5b60005b81811015610d8b57368383838181106114a1576114a1613541565b90506040020190506114c981600001358260200160208101906114c49190613526565b61287f565b50806114d48161356d565b915050611486565b6114e533612057565b61150257604051637c3ea23f60e01b815260040160405180910390fd5b61150b81612930565b600580546001600160a01b0319166001600160a01b0383169081179091556040517f764166c557b419ae9f4bca81c505141ce7017b4bdb4c610ad113a50ec7e578a990600090a250565b61155e33612057565b61157b57604051637c3ea23f60e01b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526000907f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316906370a0823190602401602060405180830381865afa1580156115e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116069190613816565b604051630afd9fa560e31b81529091506001600160a01b037f0000000000000000000000000a992d191deec32afe36203ad87d7d289a738f8116906357ecfd289061165b90899089908990899060040161382f565b6020604051808303816000875af115801561167a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169e9190613856565b506040516370a0823160e01b815230600482015260009082906001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4816906370a0823190602401602060405180830381865afa158015611708573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172c9190613816565b6117369190613873565b905060008111801561175157506001600160a01b0383163014155b15611781576117817f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488483612404565b50505050505050565b6000611794612591565b336001600160a01b037f0000000000000000000000000a992d191deec32afe36203ad87d7d289a738f8116146117dd576040516331e4d14960e01b815260040160405180910390fd5b63ffffffff85166000908152600d6020526040812054908590821580159061180d57506001600160a01b03821615155b801561183257506000838152600660205260409020546001600160a01b038381169116145b9050806118685760405162e3894560e01b8152600481018490526001600160a01b03831660248201526044015b60405180910390fd5b50600061187785870187613644565b601054600f549192506001600160a01b0390811691600091168214806118b2575082602001516001600160a01b0316826001600160a01b0316145b806118d257508260a001516001600160a01b0316826001600160a01b0316145b9050806118f25760405163460327af60e11b815260040160405180910390fd5b50506011546080820151511461191b5760405163ec8cb1df60e01b815260040160405180910390fd5b600080611929600454612963565b915091508161194b57604051636d0ea9b360e11b815260040160405180910390fd5b60055460405163032ad3cf60e51b81526001600160a01b039091169063655a79e09083906119819089908d908d90600401613886565b600060405180830381600088803b15801561199b57600080fd5b5087f11580156119af573d6000803e3d6000fd5b50505050506001955050505050505b949350505050565b6119ce612789565b6119e7600080516020613941833981519152838361298f565b604051811515906001600160a01b038416907fbe9474bb3e78da7e315cdffa5cfa30b767fcc95bbf44a6197da60228eea1028690600090a35050565b600080611a308484612682565b5098975050505050505050565b611a4633612057565b611a6357604051637c3ea23f60e01b815260040160405180910390fd5b60005b81811015610d8b576000838383818110611a8257611a82613541565b905060200201359050611a94816129bc565b5080611a9f8161356d565b915050611a66565b60606007805480602002602001604051908101604052809291908181526020018280548015610c2457602002820191906000526020600020905b815481526020019060010190808311611ae1575050505050905090565b611b0733612057565b611b2457604051637c3ea23f60e01b815260040160405180910390fd5b610de58282612a45565b611b3733612057565b611b5457604051637c3ea23f60e01b815260040160405180910390fd5b611b6e60008051602061394183398151915233600061298f565b60405133907f6cc2c67081f55c2fffb7c008fa995fbbf890f48c7c16fba93d8220f00dc84cc590600090a2565b611ba433612057565b611bc157604051637c3ea23f60e01b815260040160405180910390fd5b60005b81811015610d8b576000838383818110611be057611be0613541565b905060200201359050468114611bf957611bf981612aac565b5080611c048161356d565b915050611bc4565b6060610c5960008051602061394183398151915261222b565b611c2d612591565b611c35612b0b565b333214611cb7576000600260095460ff166002811115611c5757611c5761315c565b1480611c935750600160095460ff166002811115611c7757611c7761315c565b148015611c935750336000908152600b602052604090205460ff165b905080611cb557604051630fa0970d60e11b815233600482015260240161185f565b505b6005546001600160a01b0316611ce05760405163bc864a6960e01b815260040160405180910390fd5b6000611d0b7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48611f46565b905060007f0000000000000000000000000a992d191deec32afe36203ad87d7d289a738f816001600160a01b03166357ecfd288b8b8b8b6040518563ffffffff1660e01b8152600401611d61949392919061382f565b6020604051808303816000875af1158015611d80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611da49190613856565b905080611dc45760405163ecf5a8ff60e01b815260040160405180910390fd5b6040518060400160405280336001600160a01b0316815260200183611e087f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48611f46565b611e129190613873565b90528051601080546001600160a01b0319166001600160a01b03928316179055602090910151601155604051630afd9fa560e31b81526000917f0000000000000000000000000a992d191deec32afe36203ad87d7d289a738f8116906357ecfd2890611e88908a908a908a908a9060040161382f565b6020604051808303816000875af1158015611ea7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ecb9190613856565b905080611eeb57604051631c2f23e960e21b815260040160405180910390fd5b5050601080546001600160a01b0319169055506000601155611f0d6001600355565b5050505050505050565b611f2033612057565b611f3d57604051637c3ea23f60e01b815260040160405180910390fd5b610c8d81612b64565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03831601611f74575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015611fb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1a9190613816565b919050565b611fe9612789565b6001600160a01b03811661204e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161185f565b610c8d816127e9565b6001600160a01b03811660009081527f260b29b219d450563ddb0e5ca806bdadb1e125f7e8c506de0443797dd7122728602052604081205460ff16610f1a565b6120a033612057565b6120bd57604051637c3ea23f60e01b815260040160405180910390fd5b6009805482919060ff191660018360028111156120dc576120dc61315c565b02179055508060028111156120f3576120f361315c565b6040517f332a9f1d3bd9b0f7abbd95838fed6b417589632d0eb33f2d8ae6e2aa17178efd90600090a250565b61212833612057565b61214557604051637c3ea23f60e01b815260040160405180910390fd5b60005b81811015610d8b573683838381811061216357612163613541565b905060400201905080602001602081019061217e91906138a9565b15612198576121986121936020830183613030565b612930565b6121c3600a600b6121ac6020850185613030565b6121bc60408601602087016138a9565b6064612bb6565b506121d460408201602083016138a9565b15156121e36020830183613030565b6001600160a01b03167f1470aed653fa8a8ce4c7b2f41287634199f7ec3c4f5fd0ace97d82cf006beec360405160405180910390a350806122238161356d565b915050612148565b60008181526001602090815260409182902080548351818402810184019094528084526060939283018282801561228b57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161226d575b50505050509050919050565b600f80546001600160a01b0319166001600160a01b0383169081179091556040517f23f86a3e9ecbe238d0d1110e33eeec3ca6121dfd07f56ec10fdbf8aee36cdd3790600090a250565b81600003612302576040516381e7376360e01b815260040160405180910390fd5b6001600160a01b03811661232957604051633efa09af60e01b815260040160405180910390fd5b61233b60066007600885856064612be3565b506040516001600160a01b0382169083907f357d1ebd1dc0d53cc15161206b9a39c9ca30667bd997cf921eb00e4c78a454f590600090a35050565b604080516000808252602082019092526001600160a01b0384169083906040516123a091906138c6565b60006040518083038185875af1925050503d80600081146123dd576040519150601f19603f3d011682016040523d82523d6000602084013e6123e2565b606091505b5050905080610d8b57604051632e05b05360e21b815260040160405180910390fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161246091906138c6565b6000604051808303816000865af19150503d806000811461249d576040519150601f19603f3d011682016040523d82523d6000602084013e6124a2565b606091505b509150915060008280156124ce5750815115806124ce5750818060200190518101906124ce9190613856565b9050806124ee57604051632fdb1b7f60e11b815260040160405180910390fd5b505050505050565b60005460ff16610e2a5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161185f565b6125476124f6565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60005460ff1615610e2a5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161185f565b60048190556040518181527fec9e8f9ec7dd2c5310e5b87c7bedeb6ba1c5943cb4d2da1ee80335508a5bc5a49060200160405180910390a150565b6000818152600660205260408120546001600160a01b031680610f1a57604051631a81634560e01b815260040160405180910390fd5b6000818152600c60205260408120805460ff166126785760405163731da1e960e11b815260040160405180910390fd5b6001015492915050565b60008080612692848601866138f5565b9250925092509250925092565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392908716916126fb91906138c6565b6000604051808303816000865af19150503d8060008114612738576040519150601f19603f3d011682016040523d82523d6000602084013e61273d565b606091505b509150915060008280156127695750815115806127695750818060200190518101906127699190613856565b9050806124ee5760405163b45d44e760e01b815260040160405180910390fd5b6000546001600160a01b03610100909104163314610e2a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161185f565b600080546001600160a01b03838116610100818102610100600160a81b0319851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b61284a612591565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586125743390565b6000828152600c60205260409020805460ff16156128b257600181015463ffffffff166000908152600d60205260408120555b604080518082018252600180825263ffffffff851660208084018281526000898152600c83528681209551865460ff191690151517865590519490930193909355808252600d9092528281208690559151909185917f55fdf4a71f93ff89177262ca6b1cfa79f18f4425d1b8e928bb2ef7a18883a33c9190a3505050565b6001600160a01b0381163b610c8d57604051638c50d7cd60e01b81526001600160a01b038216600482015260240161185f565b60008060005a90508381101592508261297d576000612987565b6129878482613873565b915050915091565b600083815260016020908152604080832060029092529091206129b6919084846064612bb6565b50505050565b6000818152600c60205260408120805490919060ff16156129f45750600181015463ffffffff81166000908152600d60205260408120555b6000838152600c6020526040808220805460ff191681556001018290555163ffffffff83169185917ff79bac28779a4bff7a04c8f64491c5be344a30648bb4539212da26244b0a6e1a9190a3505050565b612a707fab6730ecea49587e6c50637868078921bc389a6c228c95e1c7259ae5a61c2174838361298f565b604051811515906001600160a01b038416907fc6b049f4dc9561b397b0cef913ea5f18165b682b193be62c0bbbf9ca8763aeba90600090a35050565b80600003612acd576040516381e7376360e01b815260040160405180910390fd5b612adc60066007600884612c3f565b5060405181907feb39225b53386d0eb02af9cf2c6b6a0c345a97654f1e67fb21b0b5aaac81ec4a90600090a250565b600260035403612b5d5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161185f565b6002600355565b600e8054610100600160a81b0319166101006001600160a01b038416908102919091179091556040517f9113819388a87769f8958d74097d68f96e457d5bc25f0168a8ffb3d3a55672a390600090a250565b600082612bcd57612bc8868686612c87565b612bd9565b612bd986868685612daf565b9695505050505050565b60008381526020859052604090205460ff16158015612c0a57612c0886868685612e5f565b505b600093845260209690965250604090912080546001600160a01b0319166001600160a01b039092169190911790555090919050565b60008181526020839052604090205460ff1680156119be57600082815260208690526040902080546001600160a01b0319169055612c7e848484612ee8565b50949350505050565b6001600160a01b0381166000908152602083905260409020805460ff16908115612da75760018082015486549091600091612cc29190613873565b9050808214612d4f576000878281548110612cdf57612cdf613541565b9060005260206000200160009054906101000a90046001600160a01b0316905080888481548110612d1257612d12613541565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905592909116815290879052604090206001018290555b86805480612d5f57612d5f61392a565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038716825287905260408120805460ff191681556001015550505b509392505050565b6001600160a01b03821660009081526020849052604090205460ff161580156119be5784548211612df35760405163b1655e3360e01b815260040160405180910390fd5b6040805180820182526001808252875460208084019182526001600160a01b039790971660008181529888529388209251835460ff19169015151783555191810191909155865490810187559585529290932090930180546001600160a01b0319169091179055919050565b60008281526020849052604090205460ff161580156119be5784548211612e995760405163b1655e3360e01b815260040160405180910390fd5b60408051808201825260018082528754602080840191825260008881529881529388209251835460ff191690151517835551918101919091558654908101875595855290932090930155919050565b6000818152602083905260409020805460ff16908115612da75760018082015486549091600091612f199190613873565b9050808214612f78576000878281548110612f3657612f36613541565b9060005260206000200154905080888481548110612f5657612f56613541565b6000918252602080832090910192909255918252879052604090206001018290555b86805480612f8857612f8861392a565b60008281526020808220830160001990810183905590920190925586825287905260408120805460ff19168155600101555050509392505050565b6020808252825182820181905260009190848201906040850190845b818110156130045783516001600160a01b031683529284019291840191600101612fdf565b50909695505050505050565b6001600160a01b0381168114610c8d57600080fd5b8035611fdc81613010565b60006020828403121561304257600080fd5b813561304d81613010565b9392505050565b60008083601f84011261306657600080fd5b5081356001600160401b0381111561307d57600080fd5b6020830191508360208260061b850101111561309857600080fd5b9250929050565b600080602083850312156130b257600080fd5b82356001600160401b038111156130c857600080fd5b6130d485828601613054565b90969095509350505050565b600080604083850312156130f357600080fd5b82356130fe81613010565b946020939093013593505050565b8015158114610c8d57600080fd5b60008060006060848603121561312f57600080fd5b83359250602084013561314181613010565b915060408401356131518161310c565b809150509250925092565b634e487b7160e01b600052602160045260246000fd5b602081016003831061319457634e487b7160e01b600052602160045260246000fd5b91905290565b6000602082840312156131ac57600080fd5b5035919050565b60008083601f8401126131c557600080fd5b5081356001600160401b038111156131dc57600080fd5b60208301915083602082850101111561309857600080fd5b60008060008060006060868803121561320c57600080fd5b8535945060208601356001600160401b038082111561322a57600080fd5b61323689838a016131b3565b9096509450604088013591508082111561324f57600080fd5b5061325c888289016131b3565b969995985093965092949392505050565b60008060008060006060868803121561328557600080fd5b85356001600160401b038082111561329c57600080fd5b6132a889838a016131b3565b909750955060208801359150808211156132c157600080fd5b506132ce888289016131b3565b90945092505060408601356132e281613010565b809150509295509295909350565b803563ffffffff81168114611fdc57600080fd5b6000806000806060858703121561331a57600080fd5b613323856132f0565b93506020850135925060408501356001600160401b0381111561334557600080fd5b613351878288016131b3565b95989497509550505050565b6000806040838503121561337057600080fd5b823561337b81613010565b9150602083013561338b8161310c565b809150509250929050565b600080602083850312156133a957600080fd5b82356001600160401b03808211156133c057600080fd5b818501915085601f8301126133d457600080fd5b8135818111156133e357600080fd5b8660208260051b85010111156133f857600080fd5b60209290920196919550909350505050565b6020808252825182820181905260009190848201906040850190845b8181101561300457835183529284019291840191600101613426565b6000806000806000806000806080898b03121561345e57600080fd5b88356001600160401b038082111561347557600080fd5b6134818c838d016131b3565b909a50985060208b013591508082111561349a57600080fd5b6134a68c838d016131b3565b909850965060408b01359150808211156134bf57600080fd5b6134cb8c838d016131b3565b909650945060608b01359150808211156134e457600080fd5b506134f18b828c016131b3565b999c989b5096995094979396929594505050565b60006020828403121561351757600080fd5b81356003811061304d57600080fd5b60006020828403121561353857600080fd5b61304d826132f0565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161357f5761357f613557565b5060010190565b6000806040838503121561359957600080fd5b82516135a481613010565b6020939093015192949293505050565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b03811182821017156135ec576135ec6135b4565b60405290565b604051606081016001600160401b03811182821017156135ec576135ec6135b4565b604051601f8201601f191681016001600160401b038111828210171561363c5761363c6135b4565b604052919050565b6000602080838503121561365757600080fd5b82356001600160401b038082111561366e57600080fd5b9084019060c0828703121561368257600080fd5b61368a6135ca565b823581528383013561369b81613010565b818501526040838101359082015260608301356136b781613010565b60608201526080830135828111156136ce57600080fd5b8301606081890312156136e057600080fd5b6136e86135f2565b81358152858201358682015260408201358481111561370657600080fd5b80830192505088601f83011261371b57600080fd5b81358481111561372d5761372d6135b4565b61373f601f8201601f19168801613614565b9450808552898782850101111561375557600080fd5b808784018887013760009085018701526040810184905260808301525061377e60a08401613025565b60a08201529695505050505050565b60006020828403121561379f57600080fd5b81516001600160401b038116811461304d57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b63ffffffff8616815284602082015283604082015260806060820152600061380b6080830184866137b6565b979650505050505050565b60006020828403121561382857600080fd5b5051919050565b6040815260006138436040830186886137b6565b828103602084015261380b8185876137b6565b60006020828403121561386857600080fd5b815161304d8161310c565b81810381811115610f1a57610f1a613557565b8381526040602082015260006138a06040830184866137b6565b95945050505050565b6000602082840312156138bb57600080fd5b813561304d8161310c565b6000825160005b818110156138e757602081860181015185830152016138cd565b506000920191825250919050565b60008060006060848603121561390a57600080fd5b83356139158161310c565b95602085013595506040909401359392505050565b634e487b7160e01b600052603160045260246000fdfe6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6fa2646970667358221220910caf4033a37ee4941c3ef69ed6e07b97ef76d851c041e7ead9d01de20c62b764736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af31550000000000000000000000000a992d191deec32afe36203ad87d7d289a738f810000000000000000000000000000000000000000000000000000000000000160000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000271000000000000000000000000054c28fdd59025942fe71545de8c6358c30b3a16a00000000000000000000000054c28fdd59025942fe71545de8c6358c30b3a16a00000000000000000000000072e28c7f34100afefc399fcc0ae041b8fe5841ae000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000a4b10000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000a86a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000006741a38adbd040e9e1a8a9c78ba52987e56a3e78
-----Decoded View---------------
Arg [0] : _cctpTokenMessenger (address): 0xBd3fa81B58Ba92a82136038B25aDec7066af3155
Arg [1] : _cctpMessageTransmitter (address): 0x0a992d191DEeC32aFe36203Ad87D7d289a738F81
Arg [2] : _chainDomains (tuple[]): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
Arg [3] : _asset (address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Arg [4] : _variableRepaymentEnabled (bool): True
Arg [5] : _targetGasReserve (uint256): 10000
Arg [6] : _processingFeeCollector (address): 0x54C28fDD59025942Fe71545DE8c6358c30b3a16A
Arg [7] : _targetExecutor (address): 0x54C28fDD59025942Fe71545DE8c6358c30b3a16A
Arg [8] : _owner (address): 0x72E28c7F34100AfefC399fcc0AE041B8fe5841AE
Arg [9] : _managers (address[]): 0x6741a38ADBd040e9e1a8A9C78bA52987e56a3e78
Arg [10] : _addOwnerToManagers (bool): True
-----Encoded View---------------
18 Constructor Arguments found :
Arg [0] : 000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155
Arg [1] : 0000000000000000000000000a992d191deec32afe36203ad87d7d289a738f81
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [3] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [5] : 0000000000000000000000000000000000000000000000000000000000002710
Arg [6] : 00000000000000000000000054c28fdd59025942fe71545de8c6358c30b3a16a
Arg [7] : 00000000000000000000000054c28fdd59025942fe71545de8c6358c30b3a16a
Arg [8] : 00000000000000000000000072e28c7f34100afefc399fcc0ae041b8fe5841ae
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000200
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [12] : 000000000000000000000000000000000000000000000000000000000000a4b1
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [14] : 000000000000000000000000000000000000000000000000000000000000a86a
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [16] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [17] : 0000000000000000000000006741a38adbd040e9e1a8a9c78ba52987e56a3e78
Loading...
Loading
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.