Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
BackedCCIPReceiver
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
No with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol"; import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import {IRouterClient} from "@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IRouterClient.sol"; import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol"; import {IERC20} from "@chainlink/contracts-ccip/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@chainlink/contracts-ccip/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; import {CCIPReceiverUpgradeable} from "./ccip-upgradeable/CCIPReceiverUpgradeable.sol"; import {IBackedAutoFeeTokenImplementation} from './interfaces/IBackedAutoFeeTokenImplementation.sol'; /** * @dev * The BackedCCIPReceiver contract is designed to facilitate cross-chain token transfers and messaging using Chainlink's Cross-Chain Interoperability Protocol (CCIP). * It allows users to send tokens to a custody wallet on the source chain and receive equivalent tokens on the destination chain, leveraging CCIP to relay messages between chains. * This contract assumes that custody wallet approval for this contract to transfer tokens will be managed off-chain. */ contract BackedCCIPReceiver is CCIPReceiverUpgradeable, OwnableUpgradeable, PausableUpgradeable, ReentrancyGuardUpgradeable { using SafeERC20 for IERC20; /// CCIP message consumption fail that we should not revert and consume messages. enum InvalidMessageReason { SOURCE_CHAIN_SELECTOR_NOT_ALLOWLISTED, SOURCE_SENDER_NOT_ALLOWLISTED, TOKEN_NOT_REGISTERED, TOKEN_RECEIVER_INVALID, TOKEN_VARIANT_MISMATCH, TOKEN_VARIANT_NOT_SUPPORTED, MULTIPLIER_MISMATCH } /// Variants of tokens that are supported by this bridge. enum TokenVariant { REGULAR, AUTO_FEE } // Custom errors to provide more descriptive revert messages. error InsufficientMessageValue(uint256 value, uint256 calculatedFees); // Used to make sure client has sent enough to cover the fees. error NothingToWithdraw(); // Used when trying to withdraw but there's nothing to withdraw. error FailedToWithdrawEth(address owner, address target, uint256 value); // Used when the withdrawal of Ether fails. error DestinationChainNotAllowlisted(uint64 destinationChainSelector); // Used when the destination chain has not been allowlisted by the contract owner. error SourceChainNotAllowlisted(uint64 sourceChainSelector); // Used when the source chain has not been allowlisted by the contract owner. error SenderNotAllowlisted(address sender); // Used when the sender has not been allowlisted by the contract owner. error InvalidAddress(); // Used when the address is 0. error TokenNotRegistered(address token); // Used when the token has not been registered by the contract owner. error InvalidTokenId(); // Used when token id is zero address or already registered. error InvalidTokenAddress(); // Used when token address is zero address or already registered. error TokenVariantNotSupported(); // Used when token variant is not recognized. error InvalidMultiplierNonce(); // Used when source chain multiplier nonce is ahead of current chain nonce. // Event emitted when a message is sent to another chain. event MessageSent( bytes32 indexed messageId, // The unique ID of the CCIP message. uint64 indexed destinationChainSelector, // The chain selector of the destination chain. address receiver, // The address of the CCIP message receiver on the destination chain. address tokenReceiver, // The address of the token receiver on the destination chain uint64 tokenId, // The token being sent. uint256 amount, // The amount being sent. TokenVariant variant, // The token variant. bytes payload // Token type specific payload ); // Event emitted when a message is received from another chain. event MessageReceived( bytes32 indexed messageId, // The unique ID of the CCIP message. uint64 indexed sourceChainSelector, // The chain selector of the source chain. address sender, // The address of the sender from the source chain. address token, // The token that was received. uint256 amount, // The amount that was received. TokenVariant variant, // The token variant. address tokenReceiver, // The receiver of the tokens. bytes payload // ABI-encoded CCIP message data payload ); event InvalidMessageReceived( bytes32 indexed messageId, // The unique ID of the CCIP message. InvalidMessageReason reason // The reason why ccip message consume was skipped ); event DestinationChainRegistered( uint64 destinationChainSelector, // The selector of the destination chain address destinationChainReceiver // The receiver of the CCIP message on the destination chain ); event DestinationChainRemoved( uint64 destinationChainSelector // The selector of the destination chain ); event SourceChainRegistered( uint64 sourceChainSelector, // The selector of the source chain address sourceChainSender // The address of the CCIP message sender on the source chain ); event SourceChainRemoved( uint64 sourceChainSelector // The selector of the source chain ); event CustodyWalletUpdated( address newCustodywallet // The address of new custody wallet. ); event GasLimitUpdated( uint256 newGasLimit // CCIP execution gas limit on destination chain ); event TokenRegistered( address token, // The address of the token uint64 tokenId ); event TokenRemoved( address token, // The address of the token uint64 tokenId ); struct TokenInfo { uint64 id; TokenVariant variant; } address private _custodyWallet; // Custody wallet. uint256 private _defaultGasLimitOnDestinationChain; // Gas limit for CCIP execution on destination chain // Mapping to keep track of allowlisted destination chains and it's receiver addresses. mapping(uint64 => address) public allowlistedDestinationChains; // Mapping to keep track of allowlisted source chains and it's sender addresses. mapping(uint64 => address) public allowlistedSourceChains; // Mapping from token address to token information. mapping(address => TokenInfo) public tokenInfos; // Mapping from tokenId to token address mapping(uint64 => address) public tokens; /// @notice BackedCCIPReceiver constructor; prevent initialize() from being invoked on the implementation contract /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /// @notice Constructor initializes the contract with the router address. /// @param _router The address of the router contract. /// @param _custody The address of the custody wallet. /// @param _gasLimit Initial value for default CCIP execution gas limit on destination chain. function initialize(address _router, address _custody, uint256 _gasLimit) public initializer { __CCIPReceiverUpgradeable_init(_router); __Ownable_init(msg.sender); __Pausable_init(); __ReentrancyGuard_init(); updateGasLimit(_gasLimit); updateCustodyWallet(_custody); } /// @dev Modifier that checks if the chain with the given destinationChainSelector is allowlisted. /// @param _destinationChainSelector The selector of the destination chain. modifier onlyAllowlistedDestinationChain(uint64 _destinationChainSelector) { if (allowlistedDestinationChains[_destinationChainSelector] == address(0)) revert DestinationChainNotAllowlisted(_destinationChainSelector); _; } /// @dev Modifier that checks if the chain with the given _sourceChainSelector is allowlisted. /// @param _sourceChainSelector The selector of the source chain. modifier onlyAllowlistedSourceChain(uint64 _sourceChainSelector) { if (allowlistedSourceChains[_sourceChainSelector] == address(0)) revert SourceChainNotAllowlisted(_sourceChainSelector); _; } /// @dev Modifier that checks if token is registered /// @param _token The address of the token. modifier onlyAllowRegisteredTokens(address _token) { if (_token == address(0)) revert InvalidTokenAddress(); if (tokenInfos[_token].id == 0) revert TokenNotRegistered(_token); _; } /// @dev Modifier that checks the address is not zero address. /// @param _address The address to be registered. modifier validateAddress(address _address) { if (_address == address(0)) revert InvalidAddress(); _; } /// @dev Modifier that checks the token address is not zero address or is not registered. /// @param _token The token address. modifier validateToken(address _token) { if (_token == address(0) || tokenInfos[_token].id != 0) revert InvalidTokenAddress(); _; } /// @dev Modifier that checks the _tokenId not 0 and is not registered. /// @param _tokenId The arbitrary id of the token. modifier validateTokenId(uint64 _tokenId) { if (_tokenId == 0 || tokens[_tokenId] != address(0)) revert InvalidTokenId(); _; } /// @dev Returns the address of the current custody wallet. function custodyWallet() public view virtual returns (address) { return _custodyWallet; } /// @dev Returns the default gas limit. function gasLimit() public view virtual returns (uint256) { return _defaultGasLimitOnDestinationChain; } /// @dev Adds _destinationChainSelector the the allowlist and registers receiver address. /// @param _destinationChainSelector The identifier (aka selector) for the destination blockchain. /// @param _destinationChainReceiver The address of the CCIP receiver on the destination blockchain. function registerDestinationChain(uint64 _destinationChainSelector, address _destinationChainReceiver) external onlyOwner validateAddress(_destinationChainReceiver) { allowlistedDestinationChains[_destinationChainSelector] = _destinationChainReceiver; emit DestinationChainRegistered(_destinationChainSelector, _destinationChainReceiver); } /// @dev Removes _destinationChainSelector from the allowlist. /// @param _destinationChainSelector The identifier (aka selector) for the destination blockchain. function removeDestinationChain(uint64 _destinationChainSelector) external onlyOwner onlyAllowlistedDestinationChain(_destinationChainSelector) { allowlistedDestinationChains[_destinationChainSelector] = address(0); emit DestinationChainRemoved(_destinationChainSelector); } /// @dev Adds _sourceChainSelector the the allowlist and registers sender address. /// @param _sourceChainSelector The identifier (aka selector) of the source blockchain. /// @param _sourceChainSender The address of the CCIP sender on the source blockchain. function registerSourceChain(uint64 _sourceChainSelector, address _sourceChainSender) external onlyOwner validateAddress(_sourceChainSender) { allowlistedSourceChains[_sourceChainSelector] = _sourceChainSender; emit SourceChainRegistered(_sourceChainSelector, _sourceChainSender); } /// @dev Removes _sourceChainSelector from the allowlist. /// @param _sourceChainSelector The identifier (aka selector) for the source blockchain. function removeSourceChain(uint64 _sourceChainSelector) external onlyOwner onlyAllowlistedSourceChain(_sourceChainSelector) { allowlistedSourceChains[_sourceChainSelector] = address(0); emit SourceChainRemoved(_sourceChainSelector); } /// @dev Updates the allowlist status of a _token under _tokenId. /// @param _token The address of the token. /// @param _tokenId The arbitrary id of the the token. /// @param _variant The variant of token. function registerToken(address _token, uint64 _tokenId, TokenVariant _variant) external onlyOwner validateToken(_token) validateTokenId(_tokenId) { tokenInfos[_token] = TokenInfo(_tokenId, _variant); tokens[_tokenId] = _token; emit TokenRegistered(_token, _tokenId); } /// @dev Removes token from the allowlist. /// @param _token The address of the token. function removeToken(address _token) external onlyOwner onlyAllowRegisteredTokens(_token) { TokenInfo memory tokenInfo = tokenInfos[_token]; tokens[tokenInfo.id] = address(0); delete tokenInfos[_token]; emit TokenRemoved(_token, tokenInfo.id); } /// @dev Updates the custody wallet. /// @param _custody new custody wallet address function updateCustodyWallet(address _custody) public onlyOwner { _custodyWallet = _custody; emit CustodyWalletUpdated(_custody); } /// @dev Updates default gas limit for CCIP. /// @param _gasLimit New default gas limit function updateGasLimit(uint256 _gasLimit) public onlyOwner { _defaultGasLimitOnDestinationChain = _gasLimit; emit GasLimitUpdated(_gasLimit); } /// @notice Sends tokens to custody wallet and sends information to destination chain. /// @param _destinationChainSelector The identifier (aka selector) for the destination blockchain. /// @param _tokenReceiver The address that will be receiver of the tokens on destination blockchain. /// @param _token The address of the token to be sent. /// @param _amount The amount to be sent. function send(uint64 _destinationChainSelector, address _tokenReceiver, address _token, uint256 _amount) external payable whenNotPaused onlyAllowlistedDestinationChain(_destinationChainSelector) onlyAllowRegisteredTokens(_token) returns (bytes32 messageId) { IERC20(_token).safeTransferFrom( msg.sender, _custodyWallet, _amount ); TokenInfo memory tokenInfo = tokenInfos[_token]; address receiver = allowlistedDestinationChains[_destinationChainSelector]; bytes memory data; bytes memory payload; if (tokenInfo.variant == TokenVariant.REGULAR) { payload = bytes(""); } else if (tokenInfo.variant == TokenVariant.AUTO_FEE) { (uint256 multiplier, , uint256 multiplierNonce) = IBackedAutoFeeTokenImplementation(_token).getCurrentMultiplier(); payload = abi.encode(multiplier, multiplierNonce); } else { revert TokenVariantNotSupported(); } data = abi.encode(_tokenReceiver, tokenInfo.id, _amount, tokenInfo.variant, payload); messageId = _sendMessagePayNative(_destinationChainSelector, receiver, data, _defaultGasLimitOnDestinationChain); // Emit an event with message details emit MessageSent( messageId, _destinationChainSelector, receiver, _tokenReceiver, tokenInfo.id, _amount, tokenInfo.variant, payload ); } /// @notice Returns the calculated delivery fee on the given `_destinationChainSelector` /// @param _destinationChainSelector: The identifier (aka selector) for the destination blockchain. /// @param _tokenReceiver The address that will be receiver of the tokens on destination blockchain. /// @param _token The address of the token to sent. /// @param _amount The amount to be sent. /// @return The calculated delivery fee cost function getDeliveryFeeCost(uint64 _destinationChainSelector, address _tokenReceiver, address _token, uint256 _amount) external view returns (uint256) { address receiver = allowlistedDestinationChains[_destinationChainSelector]; TokenInfo memory tokenInfo = tokenInfos[_token]; bytes memory data; bytes memory payload; if (tokenInfo.variant == TokenVariant.REGULAR) { payload = bytes(""); } else if (tokenInfo.variant == TokenVariant.AUTO_FEE) { (uint256 multiplier, , uint256 multiplierNonce) = IBackedAutoFeeTokenImplementation(_token).getCurrentMultiplier(); payload = abi.encode(multiplier, multiplierNonce); } data = abi.encode(_tokenReceiver, tokenInfo.id, _amount, tokenInfo.variant, payload); Client.EVM2AnyMessage memory evm2AnyMessage = _buildCCIPMessage( receiver, data, _defaultGasLimitOnDestinationChain ); return _getDeliveryCost(_destinationChainSelector, evm2AnyMessage); } function _getDeliveryCost(uint64 _destinationChainSelector, Client.EVM2AnyMessage memory _evm2AnyMessage) internal view returns (uint256) { IRouterClient router = IRouterClient(this.getRouter()); // Get the fee required to send the CCIP message return router.getFee(_destinationChainSelector, _evm2AnyMessage); } /// @notice Sends data to receiver on the destination chain. /// @notice Pay for fees in native gas. /// @dev Assumes your contract has sufficient native gas tokens. /// @param _destinationChainSelector The identifier (aka selector) for the destination blockchain. /// @param _receiver The address of the recipient of the message on the destination blockchain. /// @param _data ABI encoded CCIP message data. /// @param _gasLimit Gas limit for transaction on destination chain. /// @return messageId The ID of the CCIP message that was sent. function _sendMessagePayNative( uint64 _destinationChainSelector, address _receiver, bytes memory _data, uint256 _gasLimit ) internal returns (bytes32 messageId) { // Create an EVM2AnyMessage struct in memory with necessary information for sending a cross-chain message Client.EVM2AnyMessage memory evm2AnyMessage = _buildCCIPMessage( _receiver, _data, _gasLimit ); uint256 fees = _getDeliveryCost(_destinationChainSelector, evm2AnyMessage); if (fees > msg.value) revert InsufficientMessageValue(msg.value, fees); // Initialize a router client instance to interact with cross-chain router IRouterClient router = IRouterClient(this.getRouter()); // Send the CCIP message through the router and store the returned CCIP message ID messageId = router.ccipSend{value: fees}( _destinationChainSelector, evm2AnyMessage ); // Return the CCIP message ID return messageId; } /// @notice This function assumes that the approval for token transfers from custody wallet is properly managed off-chain. /// @notice Handles received CCIP message, sents out encoded token transfer from custody wallet to receiver. /// @notice We do not revert in some cases and succesfully consume CCIP messages to not allow retries. function _ccipReceive(Client.Any2EVMMessage memory any2EvmMessage) internal override nonReentrant { if (allowlistedSourceChains[any2EvmMessage.sourceChainSelector] == address(0)) { emit InvalidMessageReceived(any2EvmMessage.messageId, InvalidMessageReason.SOURCE_CHAIN_SELECTOR_NOT_ALLOWLISTED); return; } (address tokenReceiver, uint64 tokenId, uint256 amount, TokenVariant variant, bytes memory payload) = abi.decode(any2EvmMessage.data, (address, uint64, uint256, TokenVariant, bytes)); if (allowlistedSourceChains[any2EvmMessage.sourceChainSelector] != abi.decode(any2EvmMessage.sender, (address))) { emit InvalidMessageReceived(any2EvmMessage.messageId, InvalidMessageReason.SOURCE_SENDER_NOT_ALLOWLISTED); return; } address token = tokens[tokenId]; if (token == address(0)) { emit InvalidMessageReceived(any2EvmMessage.messageId, InvalidMessageReason.TOKEN_NOT_REGISTERED); return; } if (tokenReceiver == address(0)) { emit InvalidMessageReceived(any2EvmMessage.messageId, InvalidMessageReason.TOKEN_RECEIVER_INVALID); return; } TokenInfo memory tokenInfo = tokenInfos[token]; if (variant != tokenInfo.variant) { emit InvalidMessageReceived(any2EvmMessage.messageId, InvalidMessageReason.TOKEN_VARIANT_MISMATCH); return; } uint256 underlyingAmount; if (variant == TokenVariant.REGULAR) { underlyingAmount = amount; } else if (variant == TokenVariant.AUTO_FEE) { (uint256 sourceMultiplier, uint256 sourceMultiplierNonce) = abi.decode(payload, (uint256, uint256)); (uint256 multiplier, , uint256 multiplierNonce) = IBackedAutoFeeTokenImplementation(token).getCurrentMultiplier(); if (sourceMultiplierNonce > multiplierNonce) { // Revert to be able to re-try CCIP message once the nonce on the destination chain catches up. revert InvalidMultiplierNonce(); } else if (sourceMultiplierNonce < multiplierNonce) underlyingAmount = amount * multiplier / sourceMultiplier; else { if (multiplier != sourceMultiplier) { emit InvalidMessageReceived(any2EvmMessage.messageId, InvalidMessageReason.MULTIPLIER_MISMATCH); return; } underlyingAmount = amount; } } else { emit InvalidMessageReceived(any2EvmMessage.messageId, InvalidMessageReason.TOKEN_VARIANT_NOT_SUPPORTED); return; } IERC20(token).safeTransferFrom( _custodyWallet, tokenReceiver, underlyingAmount ); emit MessageReceived( any2EvmMessage.messageId, any2EvmMessage.sourceChainSelector, // fetch the source chain identifier (aka selector) abi.decode(any2EvmMessage.sender, (address)), // abi-decoding of the sender address, token, amount, tokenInfo.variant, tokenReceiver, payload ); } /// @notice Construct a CCIP message. /// @dev This function will create an EVM2AnyMessage struct with all the necessary information for sending a text. /// @param _receiver The address of the message receiver. /// @param _data ABI encoded message CCIP payload. /// @param _gasLimit Gas limit for transaction on destination chain /// @return Client.EVM2AnyMessage Returns an EVM2AnyMessage struct which contains information for sending a CCIP message. function _buildCCIPMessage( address _receiver, bytes memory _data, uint256 _gasLimit ) private pure returns (Client.EVM2AnyMessage memory) { // Create an EVM2AnyMessage struct in memory with necessary information for sending a cross-chain message return Client.EVM2AnyMessage({ receiver: abi.encode(_receiver), // ABI-encoded receiver address data: _data, // ABI-encoded message data tokenAmounts: new Client.EVMTokenAmount[](0), // Empty array as no tokens are transferred extraArgs: Client._argsToBytes( // Additional arguments, setting gas limit Client.EVMExtraArgsV1({gasLimit: _gasLimit}) ), feeToken: address(0) }); } /// @notice Allows the contract owner to withdraw the entire balance of Ether from the contract. /// @dev This function reverts if there are no funds to withdraw or if the transfer fails. /// It should only be callable by the owner of the contract. /// @param _beneficiary The address to which the Ether should be sent. function withdraw(address _beneficiary) external onlyOwner { // Retrieve the balance of this contract uint256 amount = address(this).balance; // Revert if there is nothing to withdraw if (amount == 0) revert NothingToWithdraw(); // Attempt to send the funds, capturing the success status and discarding any return data (bool sent, ) = _beneficiary.call{value: amount}(""); // Revert if the send failed, with information about the attempted transfer if (!sent) revert FailedToWithdrawEth(msg.sender, _beneficiary, amount); } /// @notice Allows the owner of the contract to withdraw all tokens of a specific ERC20 token. /// @dev This function reverts with a 'NothingToWithdraw' error if there are no tokens to withdraw. /// @param _beneficiary The address to which the tokens will be sent. /// @param _token The contract address of the ERC20 token to be withdrawn. function withdrawToken( address _beneficiary, address _token ) external onlyOwner { // Retrieve the balance of this contract uint256 amount = IERC20(_token).balanceOf(address(this)); // Revert if there is nothing to withdraw if (amount == 0) revert NothingToWithdraw(); IERC20(_token).safeTransfer(_beneficiary, amount); } /// @notice Pauses the contract function pause() external onlyOwner { _pause(); } /// @notice Pauses the contract function unpause() external onlyOwner { _unpause(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Client} from "../libraries/Client.sol"; /// @notice Application contracts that intend to receive messages from /// the router should implement this interface. interface IAny2EVMMessageReceiver { /// @notice Called by the Router to deliver a message. /// If this reverts, any token transfers also revert. The message /// will move to a FAILED state and become available for manual execution. /// @param message CCIP Message /// @dev Note ensure you check the msg.sender is the OffRampRouter function ccipReceive(Client.Any2EVMMessage calldata message) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Client} from "../libraries/Client.sol"; interface IRouterClient { error UnsupportedDestinationChain(uint64 destChainSelector); error InsufficientFeeTokenAmount(); error InvalidMsgValue(); /// @notice Checks if the given chain ID is supported for sending/receiving. /// @param chainSelector The chain to check. /// @return supported is true if it is supported, false if not. function isChainSupported(uint64 chainSelector) external view returns (bool supported); /// @notice Gets a list of all supported tokens which can be sent or received /// to/from a given chain id. /// @param chainSelector The chainSelector. /// @return tokens The addresses of all tokens that are supported. function getSupportedTokens(uint64 chainSelector) external view returns (address[] memory tokens); /// @param destinationChainSelector The destination chainSelector /// @param message The cross-chain CCIP message including data and/or tokens /// @return fee returns execution fee for the message /// delivery to destination chain, denominated in the feeToken specified in the message. /// @dev Reverts with appropriate reason upon invalid message. function getFee( uint64 destinationChainSelector, Client.EVM2AnyMessage memory message ) external view returns (uint256 fee); /// @notice Request a message to be sent to the destination chain /// @param destinationChainSelector The destination chain ID /// @param message The cross-chain CCIP message including data and/or tokens /// @return messageId The message ID /// @dev Note if msg.value is larger than the required fee (from getFee) we accept /// the overpayment with no refund. /// @dev Reverts with appropriate reason upon invalid message. function ccipSend( uint64 destinationChainSelector, Client.EVM2AnyMessage calldata message ) external payable returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // End consumer library. library Client { /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. struct EVMTokenAmount { address token; // token address on the local chain. uint256 amount; // Amount of tokens. } struct Any2EVMMessage { bytes32 messageId; // MessageId corresponding to ccipSend on source. uint64 sourceChainSelector; // Source chain selector. bytes sender; // abi.decode(sender) if coming from an EVM chain. bytes data; // payload sent in original message. EVMTokenAmount[] destTokenAmounts; // Tokens and their amounts in their destination chain representation. } // If extraArgs is empty bytes, the default is 200k gas limit. struct EVM2AnyMessage { bytes receiver; // abi.encode(receiver address) for dest EVM chains bytes data; // Data payload EVMTokenAmount[] tokenAmounts; // Token transfers address feeToken; // Address of feeToken. address(0) means you will send msg.value. bytes extraArgs; // Populate this with _argsToBytes(EVMExtraArgsV1) } // bytes4(keccak256("CCIP EVMExtraArgsV1")); bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9; struct EVMExtraArgsV1 { uint256 gasLimit; } function _argsToBytes(EVMExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) { return abi.encodeWithSelector(EVM_EXTRA_ARGS_V1_TAG, extraArgs); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.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. * * The initial owner is set to the address provided by the deployer. 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 OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @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) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling 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 { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.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 PausableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Pausable struct PausableStorage { bool _paused; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Pausable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300; function _getPausableStorage() private pure returns (PausableStorage storage $) { assembly { $.slot := PausableStorageLocation } } /** * @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); /** * @dev The operation failed because the contract is paused. */ error EnforcedPause(); /** * @dev The operation failed because the contract is not paused. */ error ExpectedPause(); /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal onlyInitializing { __Pausable_init_unchained(); } function __Pausable_init_unchained() internal onlyInitializing { PausableStorage storage $ = _getPausableStorage(); $._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) { PausableStorage storage $ = _getPausableStorage(); return $._paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { if (paused()) { revert EnforcedPause(); } } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { if (!paused()) { revert ExpectedPause(); } } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { PausableStorage storage $ = _getPausableStorage(); $._paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { PausableStorage storage $ = _getPausableStorage(); $._paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @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 ReentrancyGuardUpgradeable is Initializable { // 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; /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard struct ReentrancyGuardStorage { uint256 _status; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ReentrancyGuardStorageLocation = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00; function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) { assembly { $.slot := ReentrancyGuardStorageLocation } } /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); $._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 { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // On the first call to nonReentrant, _status will be NOT_ENTERED if ($._status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail $._status = ENTERED; } function _nonReentrantAfter() private { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) $._status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); return $._status == ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol"; import {IAny2EVMMessageReceiver} from "@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol"; import {IERC165} from "@chainlink/contracts-ccip/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; /// @title CCIPReceiverUpgradeable - Base upgradeable contract for CCIP applications that can receive messages. abstract contract CCIPReceiverUpgradeable is IAny2EVMMessageReceiver, IERC165, Initializable { address private i_ccipRouter; function __CCIPReceiverUpgradeable_init(address router) internal onlyInitializing { if (router == address(0)) revert InvalidRouter(address(0)); i_ccipRouter = router; } /// @notice IERC165 supports an interfaceId /// @param interfaceId The interfaceId to check /// @return true if the interfaceId is supported /// @dev Should indicate whether the contract implements IAny2EVMMessageReceiver /// e.g. return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || interfaceId == type(IERC165).interfaceId /// This allows CCIP to check if ccipReceive is available before calling it. /// If this returns false or reverts, only tokens are transferred to the receiver. /// If this returns true, tokens are transferred and ccipReceive is called atomically. /// Additionally, if the receiver address does not have code associated with /// it at the time of execution (EXTCODESIZE returns 0), only tokens will be transferred. function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; } /// @inheritdoc IAny2EVMMessageReceiver function ccipReceive(Client.Any2EVMMessage calldata message) external virtual override onlyRouter { _ccipReceive(message); } /// @notice Override this function in your implementation. /// @param message Any2EVMMessage function _ccipReceive(Client.Any2EVMMessage memory message) internal virtual; ///////////////////////////////////////////////////////////////////// // Plumbing ///////////////////////////////////////////////////////////////////// /// @notice Return the current router /// @return CCIP router address function getRouter() public view returns (address) { return address(i_ccipRouter); } error InvalidRouter(address router); /// @dev only calls from the set router are accepted. modifier onlyRouter() { if (msg.sender != address(i_ccipRouter)) revert InvalidRouter(msg.sender); _; } /// @dev This empty reserved space is put in place to allow future versions to add new /// variables without shifting down storage in the inheritance chain. /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps uint256[49] private __gap; }
/** * SPDX-License-Identifier: MIT * * Copyright (c) 2021-2024 Backed Finance AG * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /** * Disclaimer and Terms of Use * * These ERC-20 tokens have not been registered under the U.S. Securities Act of 1933, as * amended or with any securities regulatory authority of any State or other jurisdiction * of the United States and (i) may not be offered, sold or delivered within the United States * to, or for the account or benefit of U.S. Persons, and (ii) may be offered, sold or otherwise * delivered at any time only to transferees that are Non-United States Persons (as defined by * the U.S. Commodities Futures Trading Commission). * For more information and restrictions please refer to the issuer's [Website](https://www.backedassets.fi/legal-documentation) */ pragma solidity ^0.8.23; /** * @dev * * This token contract is following the ERC20 standard. * It inherits BackedTokenImplementation.sol, which is base Backed token implementation. BackedAutoFeeTokenImplementation extends it * with logic of multiplier, which is used for rebasing logic of the token, thus becoming rebase token itself. Additionally, it contains * mechanism, which changes this multiplier per configured fee periodically, on defined period length. * It contains one additional role: * - A multiplierUpdater, that can update value of a multiplier. * */ interface IBackedAutoFeeTokenImplementation { /** * @dev See {IERC20-totalSupply}. */ function totalSupply() external view returns (uint256); /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) external view returns (uint256); /** * @dev Retrieves most up to date value of multiplier * */ function getCurrentMultiplier() external view returns (uint256 newMultiplier, uint256 periodsPassed, uint256 newMultiplierNonce); /** * @dev Returns amount of shares owned by given account */ function sharesOf(address account) external view returns (uint256); /** * @return the amount of shares that corresponds to `_underlyingAmount` underlying amount. */ function getSharesByUnderlyingAmount(uint256 _underlyingAmount) external view returns (uint256); /** * @return the amount of underlying that corresponds to `_sharesAmount` token shares. */ function getUnderlyingAmountByShares(uint256 _sharesAmount) external view returns (uint256); /** * @dev Delegated Transfer Shares, transfer shares via a sign message, using erc712. */ function delegatedTransferShares( address owner, address to, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Transfers underlying shares to destination account * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `sharesAmount`. */ function transferShares(address to, uint256 sharesAmount) external returns (bool); /** * @dev Function to set the new fee. Allowed only for owner * * @param newFeePerPeriod The new fee per period value */ function updateFeePerPeriod(uint256 newFeePerPeriod) external; /** * @dev Function to change the contract multiplier updater. Allowed only for owner * * Emits a { NewMultiplierUpdater } event * * @param newMultiplierUpdater The address of the new multiplier updater */ function setMultiplierUpdater(address newMultiplierUpdater) external; /** * @dev Function to change the time of last fee accrual. Allowed only for owner * * @param newLastTimeFeeApplied A timestamp of last time fee was applied */ function setLastTimeFeeApplied(uint256 newLastTimeFeeApplied) external; /** * @dev Function to change period length. Allowed only for owner * * @param newPeriodLength Length of a single accrual period in seconds */ function setPeriodLength(uint256 newPeriodLength) external; /** * @dev Function to change the contract multiplier, only if oldMultiplier did not change in the meantime. Allowed only for owner * * Emits a { MultiplierChanged } event * * @param newMultiplier New multiplier value */ function updateMultiplierValue(uint256 newMultiplier, uint256 oldMultiplier) external; }
{ "evmVersion": "paris", "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint64","name":"destinationChainSelector","type":"uint64"}],"name":"DestinationChainNotAllowlisted","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"FailedToWithdrawEth","type":"error"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"calculatedFees","type":"uint256"}],"name":"InsufficientMessageValue","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidMultiplierNonce","type":"error"},{"inputs":[{"internalType":"address","name":"router","type":"address"}],"name":"InvalidRouter","type":"error"},{"inputs":[],"name":"InvalidTokenAddress","type":"error"},{"inputs":[],"name":"InvalidTokenId","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"NothingToWithdraw","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"SenderNotAllowlisted","type":"error"},{"inputs":[{"internalType":"uint64","name":"sourceChainSelector","type":"uint64"}],"name":"SourceChainNotAllowlisted","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"TokenNotRegistered","type":"error"},{"inputs":[],"name":"TokenVariantNotSupported","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newCustodywallet","type":"address"}],"name":"CustodyWalletUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"destinationChainSelector","type":"uint64"},{"indexed":false,"internalType":"address","name":"destinationChainReceiver","type":"address"}],"name":"DestinationChainRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"destinationChainSelector","type":"uint64"}],"name":"DestinationChainRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newGasLimit","type":"uint256"}],"name":"GasLimitUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"messageId","type":"bytes32"},{"indexed":false,"internalType":"enum BackedCCIPReceiver.InvalidMessageReason","name":"reason","type":"uint8"}],"name":"InvalidMessageReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"messageId","type":"bytes32"},{"indexed":true,"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"enum BackedCCIPReceiver.TokenVariant","name":"variant","type":"uint8"},{"indexed":false,"internalType":"address","name":"tokenReceiver","type":"address"},{"indexed":false,"internalType":"bytes","name":"payload","type":"bytes"}],"name":"MessageReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"messageId","type":"bytes32"},{"indexed":true,"internalType":"uint64","name":"destinationChainSelector","type":"uint64"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"address","name":"tokenReceiver","type":"address"},{"indexed":false,"internalType":"uint64","name":"tokenId","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"enum BackedCCIPReceiver.TokenVariant","name":"variant","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"payload","type":"bytes"}],"name":"MessageSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"indexed":false,"internalType":"address","name":"sourceChainSender","type":"address"}],"name":"SourceChainRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"sourceChainSelector","type":"uint64"}],"name":"SourceChainRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint64","name":"tokenId","type":"uint64"}],"name":"TokenRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint64","name":"tokenId","type":"uint64"}],"name":"TokenRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"allowlistedDestinationChains","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"allowlistedSourceChains","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"messageId","type":"bytes32"},{"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"internalType":"bytes","name":"sender","type":"bytes"},{"internalType":"bytes","name":"data","type":"bytes"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Client.EVMTokenAmount[]","name":"destTokenAmounts","type":"tuple[]"}],"internalType":"struct Client.Any2EVMMessage","name":"message","type":"tuple"}],"name":"ccipReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"custodyWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"_destinationChainSelector","type":"uint64"},{"internalType":"address","name":"_tokenReceiver","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"getDeliveryFeeCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_router","type":"address"},{"internalType":"address","name":"_custody","type":"address"},{"internalType":"uint256","name":"_gasLimit","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":"uint64","name":"_destinationChainSelector","type":"uint64"},{"internalType":"address","name":"_destinationChainReceiver","type":"address"}],"name":"registerDestinationChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_sourceChainSelector","type":"uint64"},{"internalType":"address","name":"_sourceChainSender","type":"address"}],"name":"registerSourceChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint64","name":"_tokenId","type":"uint64"},{"internalType":"enum BackedCCIPReceiver.TokenVariant","name":"_variant","type":"uint8"}],"name":"registerToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_destinationChainSelector","type":"uint64"}],"name":"removeDestinationChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_sourceChainSelector","type":"uint64"}],"name":"removeSourceChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"removeToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_destinationChainSelector","type":"uint64"},{"internalType":"address","name":"_tokenReceiver","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"send","outputs":[{"internalType":"bytes32","name":"messageId","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenInfos","outputs":[{"internalType":"uint64","name":"id","type":"uint64"},{"internalType":"enum BackedCCIPReceiver.TokenVariant","name":"variant","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"tokens","outputs":[{"internalType":"address","name":"","type":"address"}],"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":[{"internalType":"address","name":"_custody","type":"address"}],"name":"updateCustodyWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_gasLimit","type":"uint256"}],"name":"updateGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_beneficiary","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_beneficiary","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b50620000226200002860201b60201c565b6200019c565b60006200003a6200013260201b60201c565b90508060000160089054906101000a900460ff161562000086576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff80168160000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff16146200012f5767ffffffffffffffff8160000160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d267ffffffffffffffff6040516200012691906200017f565b60405180910390a15b50565b60007ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00905090565b600067ffffffffffffffff82169050919050565b62000179816200015a565b82525050565b60006020820190506200019660008301846200016e565b92915050565b614c2480620001ac6000396000f3fe6080604052600436106101b75760003560e01c8063715018a6116100ec578063b0f479a11161008a578063c36b4a4411610064578063c36b4a44146105e6578063f2fde38b1461060f578063f68016b714610638578063f687d12a14610663576101b7565b8063b0f479a114610552578063b9f7ce951461057d578063ba46ae72146105a8576101b7565b806385572ffb116100c657806385572ffb146104845780638da5cb5b146104ad5780639848f93f146104d8578063a8f3fdb814610515576101b7565b8063715018a61461041957806375c67c66146104305780638456cb591461046d576101b7565b80634030d5211161015957806358474aab1161013357806358474aab146103735780635b0bcb5c1461039c5780635c975abb146103c55780635fa7b584146103f0576101b7565b80634030d521146102e457806350bf4a2e1461032157806351cff8d91461034a576101b7565b80631794bb3c116101955780631794bb3c146102525780633208761a1461027b5780633aeac4e1146102a45780633f4ba83a146102cd576101b7565b806301ffc9a7146101bc5780630246d4de146101f95780630f32b98514610222575b600080fd5b3480156101c857600080fd5b506101e360048036038101906101de91906136b0565b61068c565b6040516101f091906136f8565b60405180910390f35b34801561020557600080fd5b50610220600480360381019061021b9190613753565b61075e565b005b61023c60048036038101906102379190613814565b6108c1565b6040516102499190613894565b60405180910390f35b34801561025e57600080fd5b50610279600480360381019061027491906138af565b610dd9565b005b34801561028757600080fd5b506102a2600480360381019061029d9190613753565b610f95565b005b3480156102b057600080fd5b506102cb60048036038101906102c69190613902565b6110f8565b005b3480156102d957600080fd5b506102e26111e8565b005b3480156102f057600080fd5b5061030b60048036038101906103069190613753565b6111fa565b6040516103189190613951565b60405180910390f35b34801561032d57600080fd5b506103486004803603810190610343919061396c565b61122d565b005b34801561035657600080fd5b50610371600480360381019061036c91906139ac565b611340565b005b34801561037f57600080fd5b5061039a6004803603810190610395919061396c565b61143e565b005b3480156103a857600080fd5b506103c360048036038101906103be91906139fe565b611551565b005b3480156103d157600080fd5b506103da61186a565b6040516103e791906136f8565b60405180910390f35b3480156103fc57600080fd5b50610417600480360381019061041291906139ac565b61188f565b005b34801561042557600080fd5b5061042e611b7c565b005b34801561043c57600080fd5b5061045760048036038101906104529190613753565b611b90565b6040516104649190613951565b60405180910390f35b34801561047957600080fd5b50610482611bc3565b005b34801561049057600080fd5b506104ab60048036038101906104a69190613a75565b611bd5565b005b3480156104b957600080fd5b506104c2611c7a565b6040516104cf9190613951565b60405180910390f35b3480156104e457600080fd5b506104ff60048036038101906104fa9190613814565b611cb2565b60405161050c9190613acd565b60405180910390f35b34801561052157600080fd5b5061053c60048036038101906105379190613753565b611f2e565b6040516105499190613951565b60405180910390f35b34801561055e57600080fd5b50610567611f61565b6040516105749190613951565b60405180910390f35b34801561058957600080fd5b50610592611f8a565b60405161059f9190613951565b60405180910390f35b3480156105b457600080fd5b506105cf60048036038101906105ca91906139ac565b611fb4565b6040516105dd929190613b6e565b60405180910390f35b3480156105f257600080fd5b5061060d600480360381019061060891906139ac565b611ff9565b005b34801561061b57600080fd5b50610636600480360381019061063191906139ac565b61207c565b005b34801561064457600080fd5b5061064d612102565b60405161065a9190613acd565b60405180910390f35b34801561066f57600080fd5b5061068a60048036038101906106859190613b97565b61210c565b005b60007f85572ffb000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061075757507f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b610766612155565b80600073ffffffffffffffffffffffffffffffffffffffff16603560008367ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361081f57806040517f9afeb6440000000000000000000000000000000000000000000000000000000081526004016108169190613bc4565b60405180910390fd5b6000603560008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fcf69c433bd554f1ffda9f7b290eabf9ececb7a601fc357e69f5fce2350653179826040516108b59190613bc4565b60405180910390a15050565b60006108cb6121dc565b84600073ffffffffffffffffffffffffffffffffffffffff16603460008367ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361098457806040517f0a503cdb00000000000000000000000000000000000000000000000000000000815260040161097b9190613bc4565b60405180910390fd5b83600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036109eb576040517f1eb00b0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000603660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1603610a9057806040517fddef98d7000000000000000000000000000000000000000000000000000000008152600401610a879190613951565b60405180910390fd5b610adf33603260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16868873ffffffffffffffffffffffffffffffffffffffff1661221d909392919063ffffffff16565b6000603660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016000820160089054906101000a900460ff166001811115610b8257610b81613af7565b5b6001811115610b9457610b93613af7565b5b8152505090506000603460008a67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060608060006001811115610bfd57610bfc613af7565b5b84602001516001811115610c1457610c13613af7565b5b03610c3057604051806020016040528060008152509050610d34565b600180811115610c4357610c42613af7565b5b84602001516001811115610c5a57610c59613af7565b5b03610d01576000808a73ffffffffffffffffffffffffffffffffffffffff16632b63c3006040518163ffffffff1660e01b8152600401606060405180830381865afa158015610cad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd19190613bf4565b92505091508181604051602001610ce9929190613c47565b60405160208183030381529060405292505050610d33565b6040517f7359cddd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b89846000015189866020015184604051602001610d55959493929190613d00565b6040516020818303038152906040529150610d748b84846033546122a6565b96508a67ffffffffffffffff16877f9ff0d23befc3c138237a568b1c617bd29960ad475fd8cf27b481d04d435b1310858d88600001518d8a6020015188604051610dc396959493929190613d5a565b60405180910390a3505050505050949350505050565b6000610de361240a565b905060008160000160089054906101000a900460ff1615905060008260000160009054906101000a900467ffffffffffffffff1690506000808267ffffffffffffffff16148015610e315750825b9050600060018367ffffffffffffffff16148015610e66575060003073ffffffffffffffffffffffffffffffffffffffff163b145b905081158015610e74575080155b15610eab576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018560000160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508315610efb5760018560000160086101000a81548160ff0219169083151502179055505b610f0488612432565b610f0d336124ef565b610f15612503565b610f1d612515565b610f268661210c565b610f2f87611ff9565b8315610f8b5760008560000160086101000a81548160ff0219169083151502179055507fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d26001604051610f829190613e07565b60405180910390a15b5050505050505050565b610f9d612155565b80600073ffffffffffffffffffffffffffffffffffffffff16603460008367ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361105657806040517f0a503cdb00000000000000000000000000000000000000000000000000000000815260040161104d9190613bc4565b60405180910390fd5b6000603460008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f3768462f4f3d26a7e81893d9581c506e2bf58f93cc0dc588ace91dec57489fb6826040516110ec9190613bc4565b60405180910390a15050565b611100612155565b60008173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161113b9190613951565b602060405180830381865afa158015611158573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117c9190613e22565b9050600081036111b8576040517fd0d04f6000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111e383828473ffffffffffffffffffffffffffffffffffffffff166125279092919063ffffffff16565b505050565b6111f0612155565b6111f86125ad565b565b60356020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611235612155565b80600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361129c576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81603460008567ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fe0419dd2aeb6c5bddaf27d0c857a2a507dae8f0bb299c33dd034a912e884ecdf8383604051611333929190613e4f565b60405180910390a1505050565b611348612155565b600047905060008103611387576040517fd0d04f6000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff16826040516113ad90613ea9565b60006040518083038185875af1925050503d80600081146113ea576040519150601f19603f3d011682016040523d82523d6000602084013e6113ef565b606091505b5050905080611439573383836040517f9d11f56300000000000000000000000000000000000000000000000000000000815260040161143093929190613ebe565b60405180910390fd5b505050565b611446612155565b80600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036114ad576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81603560008567ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f1ac6c9ffd0f10ec75bb428be94c3273738724ef1245fafea7ac5d93b4c7f98508383604051611544929190613e4f565b60405180910390a1505050565b611559612155565b82600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806115f657506000603660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1614155b1561162d576040517f1eb00b0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260008167ffffffffffffffff1614806116bb5750600073ffffffffffffffffffffffffffffffffffffffff16603760008367ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b156116f2576040517f3f6cc76800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808567ffffffffffffffff1681526020018460018111156117205761171f613af7565b5b815250603660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060208201518160000160086101000a81548160ff021916908360018111156117bc576117bb613af7565b5b021790555090505084603760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f15822f68d84c220b712eb1e0ed7c13e6af9e050f0883c213d76fb956c2cbc762858560405161185b929190613ef5565b60405180910390a15050505050565b60008061187561261f565b90508060000160009054906101000a900460ff1691505090565b611897612155565b80600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036118fe576040517f1eb00b0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000603660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff16036119a357806040517fddef98d700000000000000000000000000000000000000000000000000000000815260040161199a9190613951565b60405180910390fd5b6000603660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016000820160089054906101000a900460ff166001811115611a4657611a45613af7565b5b6001811115611a5857611a57613af7565b5b815250509050600060376000836000015167ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550603660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080820160006101000a81549067ffffffffffffffff02191690556000820160086101000a81549060ff021916905550507fd04ed67bb8d5a1e9a327f210f612c4e3c0e48626a4fa8d6d4230748c085ceefc838260000151604051611b6f929190613ef5565b60405180910390a1505050565b611b84612155565b611b8e6000612647565b565b60346020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611bcb612155565b611bd361271e565b565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611c6557336040517fd7f73334000000000000000000000000000000000000000000000000000000008152600401611c5c9190613951565b60405180910390fd5b611c7781611c7290614281565b612790565b50565b600080611c85612ea8565b90508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505090565b600080603460008767ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000603660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016000820160089054906101000a900460ff166001811115611da257611da1613af7565b5b6001811115611db457611db3613af7565b5b81525050905060608060006001811115611dd157611dd0613af7565b5b83602001516001811115611de857611de7613af7565b5b03611e0457604051806020016040528060008152509050611ed2565b600180811115611e1757611e16613af7565b5b83602001516001811115611e2e57611e2d613af7565b5b03611ed1576000808873ffffffffffffffffffffffffffffffffffffffff16632b63c3006040518163ffffffff1660e01b8152600401606060405180830381865afa158015611e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea59190613bf4565b92505091508181604051602001611ebd929190613c47565b604051602081830303815290604052925050505b5b87836000015187856020015184604051602001611ef3959493929190613d00565b60405160208183030381529060405291506000611f138584603354612ed0565b9050611f1f8a82612fa8565b95505050505050949350505050565b60376020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000603260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60366020528060005260406000206000915090508060000160009054906101000a900467ffffffffffffffff16908060000160089054906101000a900460ff16905082565b612001612155565b80603260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f7f832e1dce6f22aadbfc3d4ed34bcc3e5c50c358537e68b8a545bda5a541b28d816040516120719190613951565b60405180910390a150565b612084612155565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036120f65760006040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016120ed9190613951565b60405180910390fd5b6120ff81612647565b50565b6000603354905090565b612114612155565b806033819055507f3d1394ba0f6fca9c1e344f10a3efe1bfca63bc591232bb0d76755690f409450c8160405161214a9190613acd565b60405180910390a150565b61215d6130a1565b73ffffffffffffffffffffffffffffffffffffffff1661217b611c7a565b73ffffffffffffffffffffffffffffffffffffffff16146121da5761219e6130a1565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016121d19190613951565b60405180910390fd5b565b6121e461186a565b1561221b576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6122a0846323b872dd60e01b85858560405160240161223e93929190613ebe565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506130a9565b50505050565b6000806122b4858585612ed0565b905060006122c28783612fa8565b90503481111561230b5734816040517f785fa129000000000000000000000000000000000000000000000000000000008152600401612302929190613c47565b60405180910390fd5b60003073ffffffffffffffffffffffffffffffffffffffff1663b0f479a16040518163ffffffff1660e01b8152600401602060405180830381865afa158015612358573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061237c91906142a9565b90508073ffffffffffffffffffffffffffffffffffffffff166396f4e9f9838a866040518463ffffffff1660e01b81526004016123ba9291906144a7565b60206040518083038185885af11580156123d8573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906123fd91906144ec565b9350505050949350505050565b60007ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00905090565b61243a613170565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036124ac5760006040517fd7f733340000000000000000000000000000000000000000000000000000000081526004016124a39190613951565b60405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6124f7613170565b612500816131b0565b50565b61250b613170565b612513613236565b565b61251d613170565b61252561326a565b565b6125a88363a9059cbb60e01b8484604051602401612546929190614519565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506130a9565b505050565b6125b561328b565b60006125bf61261f565b905060008160000160006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6126076130a1565b6040516126149190613951565b60405180910390a150565b60007fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300905090565b6000612651612ea8565b905060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050828260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3505050565b6127266121dc565b600061273061261f565b905060018160000160006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586127786130a1565b6040516127859190613951565b60405180910390a150565b6127986132cb565b600073ffffffffffffffffffffffffffffffffffffffff1660356000836020015167ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036128595780600001517fcb7ec3fb739a296b4fc56620544ba4a4aef0b18e27b2982d0daac00e92f619f3600060405161284c919061458a565b60405180910390a2612e9d565b60008060008060008560600151806020019051810190612879919061467d565b94509450945094509450856040015180602001905181019061289b9190614714565b73ffffffffffffffffffffffffffffffffffffffff1660356000886020015167ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461295f5785600001517fcb7ec3fb739a296b4fc56620544ba4a4aef0b18e27b2982d0daac00e92f619f3600160405161294d919061458a565b60405180910390a25050505050612e9d565b6000603760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612a275786600001517fcb7ec3fb739a296b4fc56620544ba4a4aef0b18e27b2982d0daac00e92f619f36002604051612a14919061458a565b60405180910390a2505050505050612e9d565b600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1603612aa35786600001517fcb7ec3fb739a296b4fc56620544ba4a4aef0b18e27b2982d0daac00e92f619f36003604051612a90919061458a565b60405180910390a2505050505050612e9d565b6000603660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016000820160089054906101000a900460ff166001811115612b4657612b45613af7565b5b6001811115612b5857612b57613af7565b5b81525050905080602001516001811115612b7557612b74613af7565b5b846001811115612b8857612b87613af7565b5b14612bd65787600001517fcb7ec3fb739a296b4fc56620544ba4a4aef0b18e27b2982d0daac00e92f619f36004604051612bc2919061458a565b60405180910390a250505050505050612e9d565b6000806001811115612beb57612bea613af7565b5b856001811115612bfe57612bfd613af7565b5b03612c0b57859050612dd5565b600180811115612c1e57612c1d613af7565b5b856001811115612c3157612c30613af7565b5b03612d8a5760008085806020019051810190612c4d9190614741565b915091506000808673ffffffffffffffffffffffffffffffffffffffff16632b63c3006040518163ffffffff1660e01b8152600401606060405180830381865afa158015612c9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc39190613bf4565b925050915080831115612d02576040517f8824243b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80831015612d285783828b612d1791906147b0565b612d219190614821565b9450612d81565b838214612d7d578c600001517fcb7ec3fb739a296b4fc56620544ba4a4aef0b18e27b2982d0daac00e92f619f36006604051612d64919061458a565b60405180910390a2505050505050505050505050612e9d565b8994505b50505050612dd4565b88600001517fcb7ec3fb739a296b4fc56620544ba4a4aef0b18e27b2982d0daac00e92f619f36005604051612dbf919061458a565b60405180910390a25050505050505050612e9d565b5b612e24603260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1689838673ffffffffffffffffffffffffffffffffffffffff1661221d909392919063ffffffff16565b886020015167ffffffffffffffff1689600001517f322883e25779a905a46fd907cb7c3a005f32615fca088534119e0c2458a8c91c8b60400151806020019051810190612e719190614714565b868a87602001518e8b604051612e8c969594939291906148a7565b60405180910390a350505050505050505b612ea5613322565b50565b60007f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300905090565b612ed86135cf565b6040518060a0016040528085604051602001612ef49190613951565b6040516020818303038152906040528152602001848152602001600067ffffffffffffffff811115612f2957612f28613f23565b5b604051908082528060200260200182016040528015612f6257816020015b612f4f613614565b815260200190600190039081612f475790505b508152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001612f9c60405180602001604052808681525061333b565b81525090509392505050565b6000803073ffffffffffffffffffffffffffffffffffffffff1663b0f479a16040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ff6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061301a91906142a9565b90508073ffffffffffffffffffffffffffffffffffffffff166320487ded85856040518363ffffffff1660e01b81526004016130579291906144a7565b602060405180830381865afa158015613074573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130989190613e22565b91505092915050565b600033905090565b600061310b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166133ba9092919063ffffffff16565b905060008151111561316b578080602001905181019061312b919061493b565b61316a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613161906149eb565b60405180910390fd5b5b505050565b6131786133d2565b6131ae576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6131b8613170565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361322a5760006040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016132219190613951565b60405180910390fd5b61323381612647565b50565b61323e613170565b600061324861261f565b905060008160000160006101000a81548160ff02191690831515021790555050565b613272613170565b600061327c6133f2565b90506001816000018190555050565b61329361186a565b6132c9576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60006132d56133f2565b90506002816000015403613315576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002816000018190555050565b600061332c6133f2565b90506001816000018190555050565b60606397a657c960e01b826040516024016133569190614a27565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050919050565b60606133c9848460008561341a565b90509392505050565b60006133dc61240a565b60000160089054906101000a900460ff16905090565b60007f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00905090565b60608247101561345f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161345690614ab4565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516134889190614b05565b60006040518083038185875af1925050503d80600081146134c5576040519150601f19603f3d011682016040523d82523d6000602084013e6134ca565b606091505b50915091506134db878383876134e7565b92505050949350505050565b60608315613549576000835103613541576135018561355c565b613540576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161353790614b68565b60405180910390fd5b5b829050613554565b613553838361357f565b5b949350505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000825111156135925781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016135c69190614bcc565b60405180910390fd5b6040518060a00160405280606081526020016060815260200160608152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b6040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61368d81613658565b811461369857600080fd5b50565b6000813590506136aa81613684565b92915050565b6000602082840312156136c6576136c561364e565b5b60006136d48482850161369b565b91505092915050565b60008115159050919050565b6136f2816136dd565b82525050565b600060208201905061370d60008301846136e9565b92915050565b600067ffffffffffffffff82169050919050565b61373081613713565b811461373b57600080fd5b50565b60008135905061374d81613727565b92915050565b6000602082840312156137695761376861364e565b5b60006137778482850161373e565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006137ab82613780565b9050919050565b6137bb816137a0565b81146137c657600080fd5b50565b6000813590506137d8816137b2565b92915050565b6000819050919050565b6137f1816137de565b81146137fc57600080fd5b50565b60008135905061380e816137e8565b92915050565b6000806000806080858703121561382e5761382d61364e565b5b600061383c8782880161373e565b945050602061384d878288016137c9565b935050604061385e878288016137c9565b925050606061386f878288016137ff565b91505092959194509250565b6000819050919050565b61388e8161387b565b82525050565b60006020820190506138a96000830184613885565b92915050565b6000806000606084860312156138c8576138c761364e565b5b60006138d6868287016137c9565b93505060206138e7868287016137c9565b92505060406138f8868287016137ff565b9150509250925092565b600080604083850312156139195761391861364e565b5b6000613927858286016137c9565b9250506020613938858286016137c9565b9150509250929050565b61394b816137a0565b82525050565b60006020820190506139666000830184613942565b92915050565b600080604083850312156139835761398261364e565b5b60006139918582860161373e565b92505060206139a2858286016137c9565b9150509250929050565b6000602082840312156139c2576139c161364e565b5b60006139d0848285016137c9565b91505092915050565b600281106139e657600080fd5b50565b6000813590506139f8816139d9565b92915050565b600080600060608486031215613a1757613a1661364e565b5b6000613a25868287016137c9565b9350506020613a368682870161373e565b9250506040613a47868287016139e9565b9150509250925092565b600080fd5b600060a08284031215613a6c57613a6b613a51565b5b81905092915050565b600060208284031215613a8b57613a8a61364e565b5b600082013567ffffffffffffffff811115613aa957613aa8613653565b5b613ab584828501613a56565b91505092915050565b613ac7816137de565b82525050565b6000602082019050613ae26000830184613abe565b92915050565b613af181613713565b82525050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110613b3757613b36613af7565b5b50565b6000819050613b4882613b26565b919050565b6000613b5882613b3a565b9050919050565b613b6881613b4d565b82525050565b6000604082019050613b836000830185613ae8565b613b906020830184613b5f565b9392505050565b600060208284031215613bad57613bac61364e565b5b6000613bbb848285016137ff565b91505092915050565b6000602082019050613bd96000830184613ae8565b92915050565b600081519050613bee816137e8565b92915050565b600080600060608486031215613c0d57613c0c61364e565b5b6000613c1b86828701613bdf565b9350506020613c2c86828701613bdf565b9250506040613c3d86828701613bdf565b9150509250925092565b6000604082019050613c5c6000830185613abe565b613c696020830184613abe565b9392505050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613caa578082015181840152602081019050613c8f565b60008484015250505050565b6000601f19601f8301169050919050565b6000613cd282613c70565b613cdc8185613c7b565b9350613cec818560208601613c8c565b613cf581613cb6565b840191505092915050565b600060a082019050613d156000830188613942565b613d226020830187613ae8565b613d2f6040830186613abe565b613d3c6060830185613b5f565b8181036080830152613d4e8184613cc7565b90509695505050505050565b600060c082019050613d6f6000830189613942565b613d7c6020830188613942565b613d896040830187613ae8565b613d966060830186613abe565b613da36080830185613b5f565b81810360a0830152613db58184613cc7565b9050979650505050505050565b6000819050919050565b6000819050919050565b6000613df1613dec613de784613dc2565b613dcc565b613713565b9050919050565b613e0181613dd6565b82525050565b6000602082019050613e1c6000830184613df8565b92915050565b600060208284031215613e3857613e3761364e565b5b6000613e4684828501613bdf565b91505092915050565b6000604082019050613e646000830185613ae8565b613e716020830184613942565b9392505050565b600081905092915050565b50565b6000613e93600083613e78565b9150613e9e82613e83565b600082019050919050565b6000613eb482613e86565b9150819050919050565b6000606082019050613ed36000830186613942565b613ee06020830185613942565b613eed6040830184613abe565b949350505050565b6000604082019050613f0a6000830185613942565b613f176020830184613ae8565b9392505050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613f5b82613cb6565b810181811067ffffffffffffffff82111715613f7a57613f79613f23565b5b80604052505050565b6000613f8d613644565b9050613f998282613f52565b919050565b600080fd5b613fac8161387b565b8114613fb757600080fd5b50565b600081359050613fc981613fa3565b92915050565b600080fd5b600080fd5b600067ffffffffffffffff821115613ff457613ff3613f23565b5b613ffd82613cb6565b9050602081019050919050565b82818337600083830152505050565b600061402c61402784613fd9565b613f83565b90508281526020810184848401111561404857614047613fd4565b5b61405384828561400a565b509392505050565b600082601f8301126140705761406f613fcf565b5b8135614080848260208601614019565b91505092915050565b600067ffffffffffffffff8211156140a4576140a3613f23565b5b602082029050602081019050919050565b600080fd5b6000604082840312156140d0576140cf613f1e565b5b6140da6040613f83565b905060006140ea848285016137c9565b60008301525060206140fe848285016137ff565b60208301525092915050565b600061411d61411884614089565b613f83565b905080838252602082019050604084028301858111156141405761413f6140b5565b5b835b81811015614169578061415588826140ba565b845260208401935050604081019050614142565b5050509392505050565b600082601f83011261418857614187613fcf565b5b813561419884826020860161410a565b91505092915050565b600060a082840312156141b7576141b6613f1e565b5b6141c160a0613f83565b905060006141d184828501613fba565b60008301525060206141e58482850161373e565b602083015250604082013567ffffffffffffffff81111561420957614208613f9e565b5b6142158482850161405b565b604083015250606082013567ffffffffffffffff81111561423957614238613f9e565b5b6142458482850161405b565b606083015250608082013567ffffffffffffffff81111561426957614268613f9e565b5b61427584828501614173565b60808301525092915050565b600061428d36836141a1565b9050919050565b6000815190506142a3816137b2565b92915050565b6000602082840312156142bf576142be61364e565b5b60006142cd84828501614294565b91505092915050565b600082825260208201905092915050565b60006142f282613c70565b6142fc81856142d6565b935061430c818560208601613c8c565b61431581613cb6565b840191505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b614355816137a0565b82525050565b614364816137de565b82525050565b604082016000820151614380600085018261434c565b506020820151614393602085018261435b565b50505050565b60006143a5838361436a565b60408301905092915050565b6000602082019050919050565b60006143c982614320565b6143d3818561432b565b93506143de8361433c565b8060005b8381101561440f5781516143f68882614399565b9750614401836143b1565b9250506001810190506143e2565b5085935050505092915050565b600060a083016000830151848203600086015261443982826142e7565b9150506020830151848203602086015261445382826142e7565b9150506040830151848203604086015261446d82826143be565b9150506060830151614482606086018261434c565b506080830151848203608086015261449a82826142e7565b9150508091505092915050565b60006040820190506144bc6000830185613ae8565b81810360208301526144ce818461441c565b90509392505050565b6000815190506144e681613fa3565b92915050565b6000602082840312156145025761450161364e565b5b6000614510848285016144d7565b91505092915050565b600060408201905061452e6000830185613942565b61453b6020830184613abe565b9392505050565b6007811061455357614552613af7565b5b50565b600081905061456482614542565b919050565b600061457482614556565b9050919050565b61458481614569565b82525050565b600060208201905061459f600083018461457b565b92915050565b60006145b082613780565b9050919050565b6145c0816145a5565b81146145cb57600080fd5b50565b6000815190506145dd816145b7565b92915050565b6000815190506145f281613727565b92915050565b600081519050614607816139d9565b92915050565b600061462061461b84613fd9565b613f83565b90508281526020810184848401111561463c5761463b613fd4565b5b614647848285613c8c565b509392505050565b600082601f83011261466457614663613fcf565b5b815161467484826020860161460d565b91505092915050565b600080600080600060a086880312156146995761469861364e565b5b60006146a7888289016145ce565b95505060206146b8888289016145e3565b94505060406146c988828901613bdf565b93505060606146da888289016145f8565b925050608086015167ffffffffffffffff8111156146fb576146fa613653565b5b6147078882890161464f565b9150509295509295909350565b60006020828403121561472a5761472961364e565b5b6000614738848285016145ce565b91505092915050565b600080604083850312156147585761475761364e565b5b600061476685828601613bdf565b925050602061477785828601613bdf565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006147bb826137de565b91506147c6836137de565b92508282026147d4816137de565b915082820484148315176147eb576147ea614781565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061482c826137de565b9150614837836137de565b925082614847576148466147f2565b5b828204905092915050565b600061486d61486861486384613780565b613dcc565b613780565b9050919050565b600061487f82614852565b9050919050565b600061489182614874565b9050919050565b6148a181614886565b82525050565b600060c0820190506148bc6000830189614898565b6148c96020830188613942565b6148d66040830187613abe565b6148e36060830186613b5f565b6148f06080830185613942565b81810360a08301526149028184613cc7565b9050979650505050505050565b614918816136dd565b811461492357600080fd5b50565b6000815190506149358161490f565b92915050565b6000602082840312156149515761495061364e565b5b600061495f84828501614926565b91505092915050565b600082825260208201905092915050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b60006149d5602a83614968565b91506149e082614979565b604082019050919050565b60006020820190508181036000830152614a04816149c8565b9050919050565b602082016000820151614a21600085018261435b565b50505050565b6000602082019050614a3c6000830184614a0b565b92915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b6000614a9e602683614968565b9150614aa982614a42565b604082019050919050565b60006020820190508181036000830152614acd81614a91565b9050919050565b6000614adf82613c70565b614ae98185613e78565b9350614af9818560208601613c8c565b80840191505092915050565b6000614b118284614ad4565b915081905092915050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000614b52601d83614968565b9150614b5d82614b1c565b602082019050919050565b60006020820190508181036000830152614b8181614b45565b9050919050565b600081519050919050565b6000614b9e82614b88565b614ba88185614968565b9350614bb8818560208601613c8c565b614bc181613cb6565b840191505092915050565b60006020820190508181036000830152614be68184614b93565b90509291505056fea2646970667358221220ef51cdcb4daa08f3f92afe34d57b43ca924779fd08e9d252ca822cb942e1ad7f64736f6c63430008170033
Deployed Bytecode
0x6080604052600436106101b75760003560e01c8063715018a6116100ec578063b0f479a11161008a578063c36b4a4411610064578063c36b4a44146105e6578063f2fde38b1461060f578063f68016b714610638578063f687d12a14610663576101b7565b8063b0f479a114610552578063b9f7ce951461057d578063ba46ae72146105a8576101b7565b806385572ffb116100c657806385572ffb146104845780638da5cb5b146104ad5780639848f93f146104d8578063a8f3fdb814610515576101b7565b8063715018a61461041957806375c67c66146104305780638456cb591461046d576101b7565b80634030d5211161015957806358474aab1161013357806358474aab146103735780635b0bcb5c1461039c5780635c975abb146103c55780635fa7b584146103f0576101b7565b80634030d521146102e457806350bf4a2e1461032157806351cff8d91461034a576101b7565b80631794bb3c116101955780631794bb3c146102525780633208761a1461027b5780633aeac4e1146102a45780633f4ba83a146102cd576101b7565b806301ffc9a7146101bc5780630246d4de146101f95780630f32b98514610222575b600080fd5b3480156101c857600080fd5b506101e360048036038101906101de91906136b0565b61068c565b6040516101f091906136f8565b60405180910390f35b34801561020557600080fd5b50610220600480360381019061021b9190613753565b61075e565b005b61023c60048036038101906102379190613814565b6108c1565b6040516102499190613894565b60405180910390f35b34801561025e57600080fd5b50610279600480360381019061027491906138af565b610dd9565b005b34801561028757600080fd5b506102a2600480360381019061029d9190613753565b610f95565b005b3480156102b057600080fd5b506102cb60048036038101906102c69190613902565b6110f8565b005b3480156102d957600080fd5b506102e26111e8565b005b3480156102f057600080fd5b5061030b60048036038101906103069190613753565b6111fa565b6040516103189190613951565b60405180910390f35b34801561032d57600080fd5b506103486004803603810190610343919061396c565b61122d565b005b34801561035657600080fd5b50610371600480360381019061036c91906139ac565b611340565b005b34801561037f57600080fd5b5061039a6004803603810190610395919061396c565b61143e565b005b3480156103a857600080fd5b506103c360048036038101906103be91906139fe565b611551565b005b3480156103d157600080fd5b506103da61186a565b6040516103e791906136f8565b60405180910390f35b3480156103fc57600080fd5b50610417600480360381019061041291906139ac565b61188f565b005b34801561042557600080fd5b5061042e611b7c565b005b34801561043c57600080fd5b5061045760048036038101906104529190613753565b611b90565b6040516104649190613951565b60405180910390f35b34801561047957600080fd5b50610482611bc3565b005b34801561049057600080fd5b506104ab60048036038101906104a69190613a75565b611bd5565b005b3480156104b957600080fd5b506104c2611c7a565b6040516104cf9190613951565b60405180910390f35b3480156104e457600080fd5b506104ff60048036038101906104fa9190613814565b611cb2565b60405161050c9190613acd565b60405180910390f35b34801561052157600080fd5b5061053c60048036038101906105379190613753565b611f2e565b6040516105499190613951565b60405180910390f35b34801561055e57600080fd5b50610567611f61565b6040516105749190613951565b60405180910390f35b34801561058957600080fd5b50610592611f8a565b60405161059f9190613951565b60405180910390f35b3480156105b457600080fd5b506105cf60048036038101906105ca91906139ac565b611fb4565b6040516105dd929190613b6e565b60405180910390f35b3480156105f257600080fd5b5061060d600480360381019061060891906139ac565b611ff9565b005b34801561061b57600080fd5b50610636600480360381019061063191906139ac565b61207c565b005b34801561064457600080fd5b5061064d612102565b60405161065a9190613acd565b60405180910390f35b34801561066f57600080fd5b5061068a60048036038101906106859190613b97565b61210c565b005b60007f85572ffb000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061075757507f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b610766612155565b80600073ffffffffffffffffffffffffffffffffffffffff16603560008367ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361081f57806040517f9afeb6440000000000000000000000000000000000000000000000000000000081526004016108169190613bc4565b60405180910390fd5b6000603560008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fcf69c433bd554f1ffda9f7b290eabf9ececb7a601fc357e69f5fce2350653179826040516108b59190613bc4565b60405180910390a15050565b60006108cb6121dc565b84600073ffffffffffffffffffffffffffffffffffffffff16603460008367ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361098457806040517f0a503cdb00000000000000000000000000000000000000000000000000000000815260040161097b9190613bc4565b60405180910390fd5b83600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036109eb576040517f1eb00b0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000603660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1603610a9057806040517fddef98d7000000000000000000000000000000000000000000000000000000008152600401610a879190613951565b60405180910390fd5b610adf33603260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16868873ffffffffffffffffffffffffffffffffffffffff1661221d909392919063ffffffff16565b6000603660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016000820160089054906101000a900460ff166001811115610b8257610b81613af7565b5b6001811115610b9457610b93613af7565b5b8152505090506000603460008a67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060608060006001811115610bfd57610bfc613af7565b5b84602001516001811115610c1457610c13613af7565b5b03610c3057604051806020016040528060008152509050610d34565b600180811115610c4357610c42613af7565b5b84602001516001811115610c5a57610c59613af7565b5b03610d01576000808a73ffffffffffffffffffffffffffffffffffffffff16632b63c3006040518163ffffffff1660e01b8152600401606060405180830381865afa158015610cad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd19190613bf4565b92505091508181604051602001610ce9929190613c47565b60405160208183030381529060405292505050610d33565b6040517f7359cddd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b89846000015189866020015184604051602001610d55959493929190613d00565b6040516020818303038152906040529150610d748b84846033546122a6565b96508a67ffffffffffffffff16877f9ff0d23befc3c138237a568b1c617bd29960ad475fd8cf27b481d04d435b1310858d88600001518d8a6020015188604051610dc396959493929190613d5a565b60405180910390a3505050505050949350505050565b6000610de361240a565b905060008160000160089054906101000a900460ff1615905060008260000160009054906101000a900467ffffffffffffffff1690506000808267ffffffffffffffff16148015610e315750825b9050600060018367ffffffffffffffff16148015610e66575060003073ffffffffffffffffffffffffffffffffffffffff163b145b905081158015610e74575080155b15610eab576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018560000160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508315610efb5760018560000160086101000a81548160ff0219169083151502179055505b610f0488612432565b610f0d336124ef565b610f15612503565b610f1d612515565b610f268661210c565b610f2f87611ff9565b8315610f8b5760008560000160086101000a81548160ff0219169083151502179055507fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d26001604051610f829190613e07565b60405180910390a15b5050505050505050565b610f9d612155565b80600073ffffffffffffffffffffffffffffffffffffffff16603460008367ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361105657806040517f0a503cdb00000000000000000000000000000000000000000000000000000000815260040161104d9190613bc4565b60405180910390fd5b6000603460008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f3768462f4f3d26a7e81893d9581c506e2bf58f93cc0dc588ace91dec57489fb6826040516110ec9190613bc4565b60405180910390a15050565b611100612155565b60008173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161113b9190613951565b602060405180830381865afa158015611158573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117c9190613e22565b9050600081036111b8576040517fd0d04f6000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111e383828473ffffffffffffffffffffffffffffffffffffffff166125279092919063ffffffff16565b505050565b6111f0612155565b6111f86125ad565b565b60356020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611235612155565b80600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361129c576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81603460008567ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fe0419dd2aeb6c5bddaf27d0c857a2a507dae8f0bb299c33dd034a912e884ecdf8383604051611333929190613e4f565b60405180910390a1505050565b611348612155565b600047905060008103611387576040517fd0d04f6000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff16826040516113ad90613ea9565b60006040518083038185875af1925050503d80600081146113ea576040519150601f19603f3d011682016040523d82523d6000602084013e6113ef565b606091505b5050905080611439573383836040517f9d11f56300000000000000000000000000000000000000000000000000000000815260040161143093929190613ebe565b60405180910390fd5b505050565b611446612155565b80600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036114ad576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81603560008567ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f1ac6c9ffd0f10ec75bb428be94c3273738724ef1245fafea7ac5d93b4c7f98508383604051611544929190613e4f565b60405180910390a1505050565b611559612155565b82600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806115f657506000603660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1614155b1561162d576040517f1eb00b0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260008167ffffffffffffffff1614806116bb5750600073ffffffffffffffffffffffffffffffffffffffff16603760008367ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b156116f2576040517f3f6cc76800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808567ffffffffffffffff1681526020018460018111156117205761171f613af7565b5b815250603660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060208201518160000160086101000a81548160ff021916908360018111156117bc576117bb613af7565b5b021790555090505084603760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f15822f68d84c220b712eb1e0ed7c13e6af9e050f0883c213d76fb956c2cbc762858560405161185b929190613ef5565b60405180910390a15050505050565b60008061187561261f565b90508060000160009054906101000a900460ff1691505090565b611897612155565b80600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036118fe576040517f1eb00b0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000603660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff16036119a357806040517fddef98d700000000000000000000000000000000000000000000000000000000815260040161199a9190613951565b60405180910390fd5b6000603660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016000820160089054906101000a900460ff166001811115611a4657611a45613af7565b5b6001811115611a5857611a57613af7565b5b815250509050600060376000836000015167ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550603660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080820160006101000a81549067ffffffffffffffff02191690556000820160086101000a81549060ff021916905550507fd04ed67bb8d5a1e9a327f210f612c4e3c0e48626a4fa8d6d4230748c085ceefc838260000151604051611b6f929190613ef5565b60405180910390a1505050565b611b84612155565b611b8e6000612647565b565b60346020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611bcb612155565b611bd361271e565b565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611c6557336040517fd7f73334000000000000000000000000000000000000000000000000000000008152600401611c5c9190613951565b60405180910390fd5b611c7781611c7290614281565b612790565b50565b600080611c85612ea8565b90508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505090565b600080603460008767ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000603660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016000820160089054906101000a900460ff166001811115611da257611da1613af7565b5b6001811115611db457611db3613af7565b5b81525050905060608060006001811115611dd157611dd0613af7565b5b83602001516001811115611de857611de7613af7565b5b03611e0457604051806020016040528060008152509050611ed2565b600180811115611e1757611e16613af7565b5b83602001516001811115611e2e57611e2d613af7565b5b03611ed1576000808873ffffffffffffffffffffffffffffffffffffffff16632b63c3006040518163ffffffff1660e01b8152600401606060405180830381865afa158015611e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea59190613bf4565b92505091508181604051602001611ebd929190613c47565b604051602081830303815290604052925050505b5b87836000015187856020015184604051602001611ef3959493929190613d00565b60405160208183030381529060405291506000611f138584603354612ed0565b9050611f1f8a82612fa8565b95505050505050949350505050565b60376020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000603260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60366020528060005260406000206000915090508060000160009054906101000a900467ffffffffffffffff16908060000160089054906101000a900460ff16905082565b612001612155565b80603260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f7f832e1dce6f22aadbfc3d4ed34bcc3e5c50c358537e68b8a545bda5a541b28d816040516120719190613951565b60405180910390a150565b612084612155565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036120f65760006040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016120ed9190613951565b60405180910390fd5b6120ff81612647565b50565b6000603354905090565b612114612155565b806033819055507f3d1394ba0f6fca9c1e344f10a3efe1bfca63bc591232bb0d76755690f409450c8160405161214a9190613acd565b60405180910390a150565b61215d6130a1565b73ffffffffffffffffffffffffffffffffffffffff1661217b611c7a565b73ffffffffffffffffffffffffffffffffffffffff16146121da5761219e6130a1565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016121d19190613951565b60405180910390fd5b565b6121e461186a565b1561221b576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6122a0846323b872dd60e01b85858560405160240161223e93929190613ebe565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506130a9565b50505050565b6000806122b4858585612ed0565b905060006122c28783612fa8565b90503481111561230b5734816040517f785fa129000000000000000000000000000000000000000000000000000000008152600401612302929190613c47565b60405180910390fd5b60003073ffffffffffffffffffffffffffffffffffffffff1663b0f479a16040518163ffffffff1660e01b8152600401602060405180830381865afa158015612358573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061237c91906142a9565b90508073ffffffffffffffffffffffffffffffffffffffff166396f4e9f9838a866040518463ffffffff1660e01b81526004016123ba9291906144a7565b60206040518083038185885af11580156123d8573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906123fd91906144ec565b9350505050949350505050565b60007ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00905090565b61243a613170565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036124ac5760006040517fd7f733340000000000000000000000000000000000000000000000000000000081526004016124a39190613951565b60405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6124f7613170565b612500816131b0565b50565b61250b613170565b612513613236565b565b61251d613170565b61252561326a565b565b6125a88363a9059cbb60e01b8484604051602401612546929190614519565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506130a9565b505050565b6125b561328b565b60006125bf61261f565b905060008160000160006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6126076130a1565b6040516126149190613951565b60405180910390a150565b60007fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300905090565b6000612651612ea8565b905060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050828260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3505050565b6127266121dc565b600061273061261f565b905060018160000160006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586127786130a1565b6040516127859190613951565b60405180910390a150565b6127986132cb565b600073ffffffffffffffffffffffffffffffffffffffff1660356000836020015167ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036128595780600001517fcb7ec3fb739a296b4fc56620544ba4a4aef0b18e27b2982d0daac00e92f619f3600060405161284c919061458a565b60405180910390a2612e9d565b60008060008060008560600151806020019051810190612879919061467d565b94509450945094509450856040015180602001905181019061289b9190614714565b73ffffffffffffffffffffffffffffffffffffffff1660356000886020015167ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461295f5785600001517fcb7ec3fb739a296b4fc56620544ba4a4aef0b18e27b2982d0daac00e92f619f3600160405161294d919061458a565b60405180910390a25050505050612e9d565b6000603760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612a275786600001517fcb7ec3fb739a296b4fc56620544ba4a4aef0b18e27b2982d0daac00e92f619f36002604051612a14919061458a565b60405180910390a2505050505050612e9d565b600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1603612aa35786600001517fcb7ec3fb739a296b4fc56620544ba4a4aef0b18e27b2982d0daac00e92f619f36003604051612a90919061458a565b60405180910390a2505050505050612e9d565b6000603660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016000820160089054906101000a900460ff166001811115612b4657612b45613af7565b5b6001811115612b5857612b57613af7565b5b81525050905080602001516001811115612b7557612b74613af7565b5b846001811115612b8857612b87613af7565b5b14612bd65787600001517fcb7ec3fb739a296b4fc56620544ba4a4aef0b18e27b2982d0daac00e92f619f36004604051612bc2919061458a565b60405180910390a250505050505050612e9d565b6000806001811115612beb57612bea613af7565b5b856001811115612bfe57612bfd613af7565b5b03612c0b57859050612dd5565b600180811115612c1e57612c1d613af7565b5b856001811115612c3157612c30613af7565b5b03612d8a5760008085806020019051810190612c4d9190614741565b915091506000808673ffffffffffffffffffffffffffffffffffffffff16632b63c3006040518163ffffffff1660e01b8152600401606060405180830381865afa158015612c9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc39190613bf4565b925050915080831115612d02576040517f8824243b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80831015612d285783828b612d1791906147b0565b612d219190614821565b9450612d81565b838214612d7d578c600001517fcb7ec3fb739a296b4fc56620544ba4a4aef0b18e27b2982d0daac00e92f619f36006604051612d64919061458a565b60405180910390a2505050505050505050505050612e9d565b8994505b50505050612dd4565b88600001517fcb7ec3fb739a296b4fc56620544ba4a4aef0b18e27b2982d0daac00e92f619f36005604051612dbf919061458a565b60405180910390a25050505050505050612e9d565b5b612e24603260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1689838673ffffffffffffffffffffffffffffffffffffffff1661221d909392919063ffffffff16565b886020015167ffffffffffffffff1689600001517f322883e25779a905a46fd907cb7c3a005f32615fca088534119e0c2458a8c91c8b60400151806020019051810190612e719190614714565b868a87602001518e8b604051612e8c969594939291906148a7565b60405180910390a350505050505050505b612ea5613322565b50565b60007f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300905090565b612ed86135cf565b6040518060a0016040528085604051602001612ef49190613951565b6040516020818303038152906040528152602001848152602001600067ffffffffffffffff811115612f2957612f28613f23565b5b604051908082528060200260200182016040528015612f6257816020015b612f4f613614565b815260200190600190039081612f475790505b508152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001612f9c60405180602001604052808681525061333b565b81525090509392505050565b6000803073ffffffffffffffffffffffffffffffffffffffff1663b0f479a16040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ff6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061301a91906142a9565b90508073ffffffffffffffffffffffffffffffffffffffff166320487ded85856040518363ffffffff1660e01b81526004016130579291906144a7565b602060405180830381865afa158015613074573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130989190613e22565b91505092915050565b600033905090565b600061310b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166133ba9092919063ffffffff16565b905060008151111561316b578080602001905181019061312b919061493b565b61316a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613161906149eb565b60405180910390fd5b5b505050565b6131786133d2565b6131ae576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6131b8613170565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361322a5760006040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016132219190613951565b60405180910390fd5b61323381612647565b50565b61323e613170565b600061324861261f565b905060008160000160006101000a81548160ff02191690831515021790555050565b613272613170565b600061327c6133f2565b90506001816000018190555050565b61329361186a565b6132c9576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60006132d56133f2565b90506002816000015403613315576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002816000018190555050565b600061332c6133f2565b90506001816000018190555050565b60606397a657c960e01b826040516024016133569190614a27565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050919050565b60606133c9848460008561341a565b90509392505050565b60006133dc61240a565b60000160089054906101000a900460ff16905090565b60007f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00905090565b60608247101561345f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161345690614ab4565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516134889190614b05565b60006040518083038185875af1925050503d80600081146134c5576040519150601f19603f3d011682016040523d82523d6000602084013e6134ca565b606091505b50915091506134db878383876134e7565b92505050949350505050565b60608315613549576000835103613541576135018561355c565b613540576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161353790614b68565b60405180910390fd5b5b829050613554565b613553838361357f565b5b949350505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000825111156135925781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016135c69190614bcc565b60405180910390fd5b6040518060a00160405280606081526020016060815260200160608152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b6040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61368d81613658565b811461369857600080fd5b50565b6000813590506136aa81613684565b92915050565b6000602082840312156136c6576136c561364e565b5b60006136d48482850161369b565b91505092915050565b60008115159050919050565b6136f2816136dd565b82525050565b600060208201905061370d60008301846136e9565b92915050565b600067ffffffffffffffff82169050919050565b61373081613713565b811461373b57600080fd5b50565b60008135905061374d81613727565b92915050565b6000602082840312156137695761376861364e565b5b60006137778482850161373e565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006137ab82613780565b9050919050565b6137bb816137a0565b81146137c657600080fd5b50565b6000813590506137d8816137b2565b92915050565b6000819050919050565b6137f1816137de565b81146137fc57600080fd5b50565b60008135905061380e816137e8565b92915050565b6000806000806080858703121561382e5761382d61364e565b5b600061383c8782880161373e565b945050602061384d878288016137c9565b935050604061385e878288016137c9565b925050606061386f878288016137ff565b91505092959194509250565b6000819050919050565b61388e8161387b565b82525050565b60006020820190506138a96000830184613885565b92915050565b6000806000606084860312156138c8576138c761364e565b5b60006138d6868287016137c9565b93505060206138e7868287016137c9565b92505060406138f8868287016137ff565b9150509250925092565b600080604083850312156139195761391861364e565b5b6000613927858286016137c9565b9250506020613938858286016137c9565b9150509250929050565b61394b816137a0565b82525050565b60006020820190506139666000830184613942565b92915050565b600080604083850312156139835761398261364e565b5b60006139918582860161373e565b92505060206139a2858286016137c9565b9150509250929050565b6000602082840312156139c2576139c161364e565b5b60006139d0848285016137c9565b91505092915050565b600281106139e657600080fd5b50565b6000813590506139f8816139d9565b92915050565b600080600060608486031215613a1757613a1661364e565b5b6000613a25868287016137c9565b9350506020613a368682870161373e565b9250506040613a47868287016139e9565b9150509250925092565b600080fd5b600060a08284031215613a6c57613a6b613a51565b5b81905092915050565b600060208284031215613a8b57613a8a61364e565b5b600082013567ffffffffffffffff811115613aa957613aa8613653565b5b613ab584828501613a56565b91505092915050565b613ac7816137de565b82525050565b6000602082019050613ae26000830184613abe565b92915050565b613af181613713565b82525050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110613b3757613b36613af7565b5b50565b6000819050613b4882613b26565b919050565b6000613b5882613b3a565b9050919050565b613b6881613b4d565b82525050565b6000604082019050613b836000830185613ae8565b613b906020830184613b5f565b9392505050565b600060208284031215613bad57613bac61364e565b5b6000613bbb848285016137ff565b91505092915050565b6000602082019050613bd96000830184613ae8565b92915050565b600081519050613bee816137e8565b92915050565b600080600060608486031215613c0d57613c0c61364e565b5b6000613c1b86828701613bdf565b9350506020613c2c86828701613bdf565b9250506040613c3d86828701613bdf565b9150509250925092565b6000604082019050613c5c6000830185613abe565b613c696020830184613abe565b9392505050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613caa578082015181840152602081019050613c8f565b60008484015250505050565b6000601f19601f8301169050919050565b6000613cd282613c70565b613cdc8185613c7b565b9350613cec818560208601613c8c565b613cf581613cb6565b840191505092915050565b600060a082019050613d156000830188613942565b613d226020830187613ae8565b613d2f6040830186613abe565b613d3c6060830185613b5f565b8181036080830152613d4e8184613cc7565b90509695505050505050565b600060c082019050613d6f6000830189613942565b613d7c6020830188613942565b613d896040830187613ae8565b613d966060830186613abe565b613da36080830185613b5f565b81810360a0830152613db58184613cc7565b9050979650505050505050565b6000819050919050565b6000819050919050565b6000613df1613dec613de784613dc2565b613dcc565b613713565b9050919050565b613e0181613dd6565b82525050565b6000602082019050613e1c6000830184613df8565b92915050565b600060208284031215613e3857613e3761364e565b5b6000613e4684828501613bdf565b91505092915050565b6000604082019050613e646000830185613ae8565b613e716020830184613942565b9392505050565b600081905092915050565b50565b6000613e93600083613e78565b9150613e9e82613e83565b600082019050919050565b6000613eb482613e86565b9150819050919050565b6000606082019050613ed36000830186613942565b613ee06020830185613942565b613eed6040830184613abe565b949350505050565b6000604082019050613f0a6000830185613942565b613f176020830184613ae8565b9392505050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613f5b82613cb6565b810181811067ffffffffffffffff82111715613f7a57613f79613f23565b5b80604052505050565b6000613f8d613644565b9050613f998282613f52565b919050565b600080fd5b613fac8161387b565b8114613fb757600080fd5b50565b600081359050613fc981613fa3565b92915050565b600080fd5b600080fd5b600067ffffffffffffffff821115613ff457613ff3613f23565b5b613ffd82613cb6565b9050602081019050919050565b82818337600083830152505050565b600061402c61402784613fd9565b613f83565b90508281526020810184848401111561404857614047613fd4565b5b61405384828561400a565b509392505050565b600082601f8301126140705761406f613fcf565b5b8135614080848260208601614019565b91505092915050565b600067ffffffffffffffff8211156140a4576140a3613f23565b5b602082029050602081019050919050565b600080fd5b6000604082840312156140d0576140cf613f1e565b5b6140da6040613f83565b905060006140ea848285016137c9565b60008301525060206140fe848285016137ff565b60208301525092915050565b600061411d61411884614089565b613f83565b905080838252602082019050604084028301858111156141405761413f6140b5565b5b835b81811015614169578061415588826140ba565b845260208401935050604081019050614142565b5050509392505050565b600082601f83011261418857614187613fcf565b5b813561419884826020860161410a565b91505092915050565b600060a082840312156141b7576141b6613f1e565b5b6141c160a0613f83565b905060006141d184828501613fba565b60008301525060206141e58482850161373e565b602083015250604082013567ffffffffffffffff81111561420957614208613f9e565b5b6142158482850161405b565b604083015250606082013567ffffffffffffffff81111561423957614238613f9e565b5b6142458482850161405b565b606083015250608082013567ffffffffffffffff81111561426957614268613f9e565b5b61427584828501614173565b60808301525092915050565b600061428d36836141a1565b9050919050565b6000815190506142a3816137b2565b92915050565b6000602082840312156142bf576142be61364e565b5b60006142cd84828501614294565b91505092915050565b600082825260208201905092915050565b60006142f282613c70565b6142fc81856142d6565b935061430c818560208601613c8c565b61431581613cb6565b840191505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b614355816137a0565b82525050565b614364816137de565b82525050565b604082016000820151614380600085018261434c565b506020820151614393602085018261435b565b50505050565b60006143a5838361436a565b60408301905092915050565b6000602082019050919050565b60006143c982614320565b6143d3818561432b565b93506143de8361433c565b8060005b8381101561440f5781516143f68882614399565b9750614401836143b1565b9250506001810190506143e2565b5085935050505092915050565b600060a083016000830151848203600086015261443982826142e7565b9150506020830151848203602086015261445382826142e7565b9150506040830151848203604086015261446d82826143be565b9150506060830151614482606086018261434c565b506080830151848203608086015261449a82826142e7565b9150508091505092915050565b60006040820190506144bc6000830185613ae8565b81810360208301526144ce818461441c565b90509392505050565b6000815190506144e681613fa3565b92915050565b6000602082840312156145025761450161364e565b5b6000614510848285016144d7565b91505092915050565b600060408201905061452e6000830185613942565b61453b6020830184613abe565b9392505050565b6007811061455357614552613af7565b5b50565b600081905061456482614542565b919050565b600061457482614556565b9050919050565b61458481614569565b82525050565b600060208201905061459f600083018461457b565b92915050565b60006145b082613780565b9050919050565b6145c0816145a5565b81146145cb57600080fd5b50565b6000815190506145dd816145b7565b92915050565b6000815190506145f281613727565b92915050565b600081519050614607816139d9565b92915050565b600061462061461b84613fd9565b613f83565b90508281526020810184848401111561463c5761463b613fd4565b5b614647848285613c8c565b509392505050565b600082601f83011261466457614663613fcf565b5b815161467484826020860161460d565b91505092915050565b600080600080600060a086880312156146995761469861364e565b5b60006146a7888289016145ce565b95505060206146b8888289016145e3565b94505060406146c988828901613bdf565b93505060606146da888289016145f8565b925050608086015167ffffffffffffffff8111156146fb576146fa613653565b5b6147078882890161464f565b9150509295509295909350565b60006020828403121561472a5761472961364e565b5b6000614738848285016145ce565b91505092915050565b600080604083850312156147585761475761364e565b5b600061476685828601613bdf565b925050602061477785828601613bdf565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006147bb826137de565b91506147c6836137de565b92508282026147d4816137de565b915082820484148315176147eb576147ea614781565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061482c826137de565b9150614837836137de565b925082614847576148466147f2565b5b828204905092915050565b600061486d61486861486384613780565b613dcc565b613780565b9050919050565b600061487f82614852565b9050919050565b600061489182614874565b9050919050565b6148a181614886565b82525050565b600060c0820190506148bc6000830189614898565b6148c96020830188613942565b6148d66040830187613abe565b6148e36060830186613b5f565b6148f06080830185613942565b81810360a08301526149028184613cc7565b9050979650505050505050565b614918816136dd565b811461492357600080fd5b50565b6000815190506149358161490f565b92915050565b6000602082840312156149515761495061364e565b5b600061495f84828501614926565b91505092915050565b600082825260208201905092915050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b60006149d5602a83614968565b91506149e082614979565b604082019050919050565b60006020820190508181036000830152614a04816149c8565b9050919050565b602082016000820151614a21600085018261435b565b50505050565b6000602082019050614a3c6000830184614a0b565b92915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b6000614a9e602683614968565b9150614aa982614a42565b604082019050919050565b60006020820190508181036000830152614acd81614a91565b9050919050565b6000614adf82613c70565b614ae98185613e78565b9350614af9818560208601613c8c565b80840191505092915050565b6000614b118284614ad4565b915081905092915050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000614b52601d83614968565b9150614b5d82614b1c565b602082019050919050565b60006020820190508181036000830152614b8181614b45565b9050919050565b600081519050919050565b6000614b9e82614b88565b614ba88185614968565b9350614bb8818560208601613c8c565b614bc181613cb6565b840191505092915050565b60006020820190508181036000830152614be68184614b93565b90509291505056fea2646970667358221220ef51cdcb4daa08f3f92afe34d57b43ca924779fd08e9d252ca822cb942e1ad7f64736f6c63430008170033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.