Overview
ETH Balance
ETH Value
$0.37 (@ $2,837.53/ETH)Latest 1 from a total of 1 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Bridge Tokens | 14477775 | 31 days ago | IN | 0.00019604 ETH | 0.00000184 |
Latest 1 internal transaction
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 14477775 | 31 days ago | 0.0000671 ETH |
Cross-Chain Transactions
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.19;
import { ReentrancyGuard } from '@openzeppelin/contracts/security/ReentrancyGuard.sol';
import { Client } from '@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol';
import { ITokenBalance } from '../../interfaces/ITokenBalance.sol';
import { InterportCCIPBridgeV2Core } from './core/InterportCCIPBridgeV2Core.sol';
import '../../helpers/TransferHelper.sol' as TransferHelper;
/**
* @title InterportCCIPTokenBridgeV2
* @notice The contract bridges ERC-20 tokens with Chainlink CCIP
*/
contract InterportCCIPTokenBridgeV2 is InterportCCIPBridgeV2Core, ReentrancyGuard {
/**
* @notice The "bridgeTokens" action parameters
* @param targetChainId The message target chain ID (EVM)
* @param targetChainSelector The message target chain selector (CCIP)
* @param targetRecipient The address of the recipient on the target chain
* @param tokenAmounts Token amount data
* @param extraArgs The extraArgs (CCIP EVM2AnyMessage)
*/
struct TokenBridgeAction {
uint256 targetChainId;
uint64 targetChainSelector;
bytes targetRecipient;
Client.EVMTokenAmount[] tokenAmounts;
bytes extraArgs;
}
/**
* @notice Token bridge action source event
* @param targetChainId The ID of the target chain
* @param sourceSender The address of the user on the source chain
* @param targetRecipient The address of the recipient on the target chain
* @param tokenAmounts Token amount data
* @param ccipMessageId The CCIP message ID
* @param timestamp The timestamp of the action (in seconds)
*/
event TokenBridgeActionSource(
uint256 targetChainId,
address indexed sourceSender,
bytes targetRecipient,
Client.EVMTokenAmount[] tokenAmounts,
bytes32 indexed ccipMessageId,
uint256 timestamp
);
/**
* @notice Emitted when the received token amount is less than expected
* @param expectedAmount Expected amount
* @param actualAmount Actual amount
*/
error FeeOnTransferError(uint256 expectedAmount, uint256 actualAmount);
/**
* @notice Initializes the contract
* @param _endpointAddress The cross-chain endpoint address
* @param _owner The address of the initial owner of the contract
* @param _managers The addresses of initial managers of the contract
* @param _addOwnerToManagers The flag to optionally add the owner to the list of managers
*/
constructor(
address _endpointAddress,
address _owner,
address[] memory _managers,
bool _addOwnerToManagers
) InterportCCIPBridgeV2Core(_endpointAddress, _owner, _managers, _addOwnerToManagers) {}
/**
* @notice Cross-chain bridging of ERC-20 tokens
* @param _action The action parameters
* @param _messagingTokenInfo The messaging token info
*/
function bridgeTokens(
TokenBridgeAction calldata _action,
MessagingTokenInfo calldata _messagingTokenInfo
) external payable whenNotPaused nonReentrant returns (bytes32 ccipMessageId) {
(bool isNativeMessagingToken, uint256 ccipSendValue) = _checkMessagingTokenInfo(
_messagingTokenInfo,
0
);
Client.EVMTokenAmount[] memory ccipTokenAmounts = _action.tokenAmounts;
bool messagingTokenIncluded;
for (uint256 index; index < ccipTokenAmounts.length; index++) {
Client.EVMTokenAmount memory ccipTokenAmount = ccipTokenAmounts[index];
uint256 amountToReceive = ccipTokenAmount.amount;
bool isMessagingToken = !messagingTokenIncluded &&
_messagingTokenInfo.token == ccipTokenAmount.token;
if (isMessagingToken) {
messagingTokenIncluded = true;
amountToReceive += _messagingTokenInfo.amount;
}
(uint256 amountReceived, bool hasFeeOnTransfer) = _transferFromCaller(
ccipTokenAmount.token,
amountToReceive,
isMessagingToken
);
if (hasFeeOnTransfer) {
ccipTokenAmount.amount = amountReceived;
}
uint256 amountToApprove = ccipTokenAmount.amount;
if (isMessagingToken) {
amountToApprove += _messagingTokenInfo.messagingAmount;
}
TransferHelper.safeApprove(ccipTokenAmount.token, endpoint, amountToApprove);
}
if (!messagingTokenIncluded && !isNativeMessagingToken) {
_transferFromCaller(_messagingTokenInfo.token, _messagingTokenInfo.amount, true);
TransferHelper.safeApprove(
_messagingTokenInfo.token,
endpoint,
_messagingTokenInfo.messagingAmount
);
}
// Create an EVM2AnyMessage struct in memory with necessary information for sending a cross-chain message
Client.EVM2AnyMessage memory ccipMessage = Client.EVM2AnyMessage({
receiver: _action.targetRecipient,
data: new bytes(0),
tokenAmounts: ccipTokenAmounts,
feeToken: _messagingTokenInfo.token,
extraArgs: _action.extraArgs
});
// Send the message
ccipMessageId = _ccipSend(_action.targetChainSelector, ccipMessage, ccipSendValue);
for (uint256 index; index < _action.tokenAmounts.length; index++) {
TransferHelper.safeApprove(_action.tokenAmounts[index].token, endpoint, 0);
}
if (!messagingTokenIncluded && !isNativeMessagingToken) {
TransferHelper.safeApprove(_messagingTokenInfo.token, endpoint, 0);
}
emit TokenBridgeActionSource(
_action.targetChainId,
msg.sender,
_action.targetRecipient,
_action.tokenAmounts,
ccipMessageId,
block.timestamp
);
}
/**
* @notice Cross-chain message fee estimation
* @param _action The action parameters
* @return Message fee
*/
function messageFee(
TokenBridgeAction calldata _action,
address _messagingToken
) external view returns (uint256) {
Client.EVM2AnyMessage memory ccipMessage = Client.EVM2AnyMessage({
receiver: _action.targetRecipient,
data: new bytes(0),
tokenAmounts: _action.tokenAmounts,
feeToken: _messagingToken,
extraArgs: _action.extraArgs
});
return _ccipGetFee(_action.targetChainSelector, ccipMessage);
}
function _transferFromCaller(
address _token,
uint256 _amount,
bool _strict
) internal virtual returns (uint256 amountReceived, bool hasFeeOnTransfer) {
uint256 tokenBalanceBefore = ITokenBalance(_token).balanceOf(address(this));
TransferHelper.safeTransferFrom(_token, msg.sender, address(this), _amount);
amountReceived = ITokenBalance(_token).balanceOf(address(this)) - tokenBalanceBefore;
if (amountReceived < _amount) {
if (_strict) {
revert FeeOnTransferError(_amount, amountReceived);
} else {
hasFeeOnTransfer = true;
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
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 destChainSelector The chain to check.
/// @return supported is true if it is supported, false if not.
function isChainSupported(uint64 destChainSelector) external view returns (bool supported);
/// @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(EVMExtraArgsV2)
}
// 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);
}
// bytes4(keccak256("CCIP EVMExtraArgsV2"));
bytes4 public constant EVM_EXTRA_ARGS_V2_TAG = 0x181dcf10;
/// @param gasLimit: gas limit for the callback on the destination chain.
/// @param allowOutOfOrderExecution: if true, it indicates that the message can be executed in any order relative to other messages from the same sender.
/// This value's default varies by chain. On some chains, a particular value is enforced, meaning if the expected value
/// is not set, the message request will revert.
struct EVMExtraArgsV2 {
uint256 gasLimit;
bool allowOutOfOrderExecution;
}
function _argsToBytes(EVMExtraArgsV2 memory extraArgs) internal pure returns (bytes memory bts) {
return abi.encodeWithSelector(EVM_EXTRA_ARGS_V2_TAG, extraArgs);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. 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 {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.19;
import { Pausable } from '@openzeppelin/contracts/security/Pausable.sol';
import { IRouterClient } from '@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IRouterClient.sol';
import { Client } from '@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol';
import { BalanceManagementMixin } from '../../../mixins/BalanceManagementMixin.sol';
import { SystemVersionId } from '../../../SystemVersionId.sol';
import '../../../helpers/AddressHelper.sol' as AddressHelper;
/**
* @title InterportCCIPBridgeV2Core
* @notice The core logic of the cross-chain bridging with Chainlink CCIP
*/
abstract contract InterportCCIPBridgeV2Core is SystemVersionId, Pausable, BalanceManagementMixin {
/**
* @notice Messaging token info structure
* @param token The token address
* @param amount The token amount
* @param messagingAmount The messaging amount
*/
struct MessagingTokenInfo {
address token;
uint256 amount;
uint256 messagingAmount;
}
/**
* @dev CCIP endpoint address
*/
address public endpoint;
/**
* @notice Emitted when the cross-chain endpoint contract reference is set
* @param endpointAddress The address of the cross-chain endpoint contract
*/
event SetEndpoint(address indexed endpointAddress);
/**
* @notice Emitted when the messaging token amount is invalid
*/
error MessagingTokenAmountError();
/**
* @notice Emitted when the native token value is invalid
*/
error NativeTokenValueError();
/**
* @notice Emitted when the caller is not the CCIP endpoint
*/
error OnlyEndpointError();
/**
* @dev Modifier to check if the caller is the CCIP endpoint
*/
modifier onlyEndpoint() {
if (msg.sender != endpoint) {
revert OnlyEndpointError();
}
_;
}
/**
* @notice Initializes the contract
* @param _endpointAddress The cross-chain endpoint address
* @param _owner The address of the initial owner of the contract
* @param _managers The addresses of initial managers of the contract
* @param _addOwnerToManagers The flag to optionally add the owner to the list of managers
*/
constructor(
address _endpointAddress,
address _owner,
address[] memory _managers,
bool _addOwnerToManagers
) {
AddressHelper.requireContractOrZeroAddress(_endpointAddress);
_setEndpoint(_endpointAddress);
_initRoles(_owner, _managers, _addOwnerToManagers);
}
/**
* @notice The standard "receive" function
* @dev Is payable to allow receiving native token funds
*/
receive() external payable {}
/**
* @notice Sets the cross-chain endpoint contract reference
* @param _endpointAddress The address of the cross-chain endpoint contract
*/
function setEndpoint(address _endpointAddress) external onlyManager {
AddressHelper.requireContract(_endpointAddress);
_setEndpoint(_endpointAddress);
}
/**
* @notice Enter pause state
*/
function pause() external onlyManager {
_pause();
}
/**
* @notice Exit pause state
*/
function unpause() external onlyManager {
_unpause();
}
function _ccipSend(
uint64 _targetChainSelector,
Client.EVM2AnyMessage memory _ccipMessage,
uint256 _ccipSendValue
) internal virtual returns (bytes32 ccipMessageId) {
return
IRouterClient(endpoint).ccipSend{ value: _ccipSendValue }(
_targetChainSelector,
_ccipMessage
);
}
function _setEndpoint(address _endpoint) internal virtual {
endpoint = _endpoint;
emit SetEndpoint(_endpoint);
}
function _checkMessagingTokenInfo(
MessagingTokenInfo calldata _messagingTokenInfo,
uint256 _fromNativeTokenAmount
) internal view virtual returns (bool isNativeMessagingToken, uint256 ccipSendValue) {
if (_messagingTokenInfo.amount < _messagingTokenInfo.messagingAmount) {
revert MessagingTokenAmountError();
}
isNativeMessagingToken = (_messagingTokenInfo.token == address(0));
uint256 expectedMsgValue = isNativeMessagingToken
? (_messagingTokenInfo.amount + _fromNativeTokenAmount)
: _fromNativeTokenAmount;
if (msg.value < expectedMsgValue) {
revert NativeTokenValueError();
}
ccipSendValue = isNativeMessagingToken ? _messagingTokenInfo.messagingAmount : 0;
}
function _ccipGetFee(
uint64 _targetChainSelector,
Client.EVM2AnyMessage memory _ccipMessage
) internal view virtual returns (uint256 fee) {
return IRouterClient(endpoint).getFee(_targetChainSelector, _ccipMessage);
}
}// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @dev The default token decimals value */ uint256 constant DECIMALS_DEFAULT = 18; /** * @dev The maximum uint256 value */ uint256 constant INFINITY = type(uint256).max; /** * @dev The default limit of account list size */ uint256 constant LIST_SIZE_LIMIT_DEFAULT = 200; /** * @dev The factor for percentage settings. Example: 100 is 0.1% */ uint256 constant MILLIPERCENT_FACTOR = 100_000; /** * @dev The de facto standard address to denote the native token */ address constant NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.19;
/**
* @notice Optional value structure
* @dev Is used in mappings to allow zero values
* @param isSet Value presence flag
* @param value Numeric value
*/
struct OptionalValue {
bool isSet;
uint256 value;
}
/**
* @notice Key-to-value structure
* @dev Is used as an array parameter item to perform multiple key-value settings
* @param key Numeric key
* @param value Numeric value
*/
struct KeyToValue {
uint256 key;
uint256 value;
}
/**
* @notice Key-to-value structure for address values
* @dev Is used as an array parameter item to perform multiple key-value settings with address values
* @param key Numeric key
* @param value Address value
*/
struct KeyToAddressValue {
uint256 key;
address value;
}
/**
* @notice Address-to-flag structure
* @dev Is used as an array parameter item to perform multiple settings
* @param account Account address
* @param flag Flag value
*/
struct AccountToFlag {
address account;
bool flag;
}
/**
* @notice Emitted when a list exceeds the size limit
*/
error ListSizeLimitError();
/**
* @notice Sets or updates a value in a combined map (a mapping with a key list and key index mapping)
* @param _map The mapping reference
* @param _keyList The key list reference
* @param _keyIndexMap The key list index mapping reference
* @param _key The numeric key
* @param _value The address value
* @param _sizeLimit The map and list size limit
* @return isNewKey True if the key was just added, otherwise false
*/
function combinedMapSet(
mapping(uint256 => address) storage _map,
uint256[] storage _keyList,
mapping(uint256 => OptionalValue) storage _keyIndexMap,
uint256 _key,
address _value,
uint256 _sizeLimit
) returns (bool isNewKey) {
isNewKey = !_keyIndexMap[_key].isSet;
if (isNewKey) {
uniqueListAdd(_keyList, _keyIndexMap, _key, _sizeLimit);
}
_map[_key] = _value;
}
/**
* @notice Removes a value from a combined map (a mapping with a key list and key index mapping)
* @param _map The mapping reference
* @param _keyList The key list reference
* @param _keyIndexMap The key list index mapping reference
* @param _key The numeric key
* @return isChanged True if the combined map was changed, otherwise false
*/
function combinedMapRemove(
mapping(uint256 => address) storage _map,
uint256[] storage _keyList,
mapping(uint256 => OptionalValue) storage _keyIndexMap,
uint256 _key
) returns (bool isChanged) {
isChanged = _keyIndexMap[_key].isSet;
if (isChanged) {
delete _map[_key];
uniqueListRemove(_keyList, _keyIndexMap, _key);
}
}
/**
* @notice Adds a value to a unique value list (a list with value index mapping)
* @param _list The list reference
* @param _indexMap The value index mapping reference
* @param _value The numeric value
* @param _sizeLimit The list size limit
* @return isChanged True if the list was changed, otherwise false
*/
function uniqueListAdd(
uint256[] storage _list,
mapping(uint256 => OptionalValue) storage _indexMap,
uint256 _value,
uint256 _sizeLimit
) returns (bool isChanged) {
isChanged = !_indexMap[_value].isSet;
if (isChanged) {
if (_list.length >= _sizeLimit) {
revert ListSizeLimitError();
}
_indexMap[_value] = OptionalValue(true, _list.length);
_list.push(_value);
}
}
/**
* @notice Removes a value from a unique value list (a list with value index mapping)
* @param _list The list reference
* @param _indexMap The value index mapping reference
* @param _value The numeric value
* @return isChanged True if the list was changed, otherwise false
*/
function uniqueListRemove(
uint256[] storage _list,
mapping(uint256 => OptionalValue) storage _indexMap,
uint256 _value
) returns (bool isChanged) {
OptionalValue storage indexItem = _indexMap[_value];
isChanged = indexItem.isSet;
if (isChanged) {
uint256 itemIndex = indexItem.value;
uint256 lastIndex = _list.length - 1;
if (itemIndex != lastIndex) {
uint256 lastValue = _list[lastIndex];
_list[itemIndex] = lastValue;
_indexMap[lastValue].value = itemIndex;
}
_list.pop();
delete _indexMap[_value];
}
}
/**
* @notice Adds a value to a unique address value list (a list with value index mapping)
* @param _list The list reference
* @param _indexMap The value index mapping reference
* @param _value The address value
* @param _sizeLimit The list size limit
* @return isChanged True if the list was changed, otherwise false
*/
function uniqueAddressListAdd(
address[] storage _list,
mapping(address => OptionalValue) storage _indexMap,
address _value,
uint256 _sizeLimit
) returns (bool isChanged) {
isChanged = !_indexMap[_value].isSet;
if (isChanged) {
if (_list.length >= _sizeLimit) {
revert ListSizeLimitError();
}
_indexMap[_value] = OptionalValue(true, _list.length);
_list.push(_value);
}
}
/**
* @notice Removes a value from a unique address value list (a list with value index mapping)
* @param _list The list reference
* @param _indexMap The value index mapping reference
* @param _value The address value
* @return isChanged True if the list was changed, otherwise false
*/
function uniqueAddressListRemove(
address[] storage _list,
mapping(address => OptionalValue) storage _indexMap,
address _value
) returns (bool isChanged) {
OptionalValue storage indexItem = _indexMap[_value];
isChanged = indexItem.isSet;
if (isChanged) {
uint256 itemIndex = indexItem.value;
uint256 lastIndex = _list.length - 1;
if (itemIndex != lastIndex) {
address lastValue = _list[lastIndex];
_list[itemIndex] = lastValue;
_indexMap[lastValue].value = itemIndex;
}
_list.pop();
delete _indexMap[_value];
}
}
/**
* @notice Adds or removes a value to/from a unique address value list (a list with value index mapping)
* @dev The list size limit is checked on items adding only
* @param _list The list reference
* @param _indexMap The value index mapping reference
* @param _value The address value
* @param _flag The value inclusion flag
* @param _sizeLimit The list size limit
* @return isChanged True if the list was changed, otherwise false
*/
function uniqueAddressListUpdate(
address[] storage _list,
mapping(address => OptionalValue) storage _indexMap,
address _value,
bool _flag,
uint256 _sizeLimit
) returns (bool isChanged) {
return
_flag
? uniqueAddressListAdd(_list, _indexMap, _value, _sizeLimit)
: uniqueAddressListRemove(_list, _indexMap, _value);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.19;
/**
* @notice Emitted when the account is not a contract
* @param account The account address
*/
error NonContractAddressError(address account);
/**
* @notice Function to check if the account is a contract
* @return The account contract status flag
*/
function isContract(address _account) view returns (bool) {
return _account.code.length > 0;
}
/**
* @notice Function to require an account to be a contract
*/
function requireContract(address _account) view {
if (!isContract(_account)) {
revert NonContractAddressError(_account);
}
}
/**
* @notice Function to require an account to be a contract or a zero address
*/
function requireContractOrZeroAddress(address _account) view {
if (_account != address(0)) {
requireContract(_account);
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.19;
/**
* @notice Emitted when an approval action fails
*/
error SafeApproveError();
/**
* @notice Emitted when a transfer action fails
*/
error SafeTransferError();
/**
* @notice Emitted when a transferFrom action fails
*/
error SafeTransferFromError();
/**
* @notice Emitted when a transfer of the native token fails
*/
error SafeTransferNativeError();
/**
* @notice Safely approve the token to the account
* @param _token The token address
* @param _to The token approval recipient address
* @param _value The token approval amount
*/
function safeApprove(address _token, address _to, uint256 _value) {
// 0x095ea7b3 is the selector for "approve(address,uint256)"
(bool success, bytes memory data) = _token.call(
abi.encodeWithSelector(0x095ea7b3, _to, _value)
);
bool condition = success && (data.length == 0 || abi.decode(data, (bool)));
if (!condition) {
revert SafeApproveError();
}
}
/**
* @notice Safely transfer the token to the account
* @param _token The token address
* @param _to The token transfer recipient address
* @param _value The token transfer amount
*/
function safeTransfer(address _token, address _to, uint256 _value) {
// 0xa9059cbb is the selector for "transfer(address,uint256)"
(bool success, bytes memory data) = _token.call(
abi.encodeWithSelector(0xa9059cbb, _to, _value)
);
bool condition = success && (data.length == 0 || abi.decode(data, (bool)));
if (!condition) {
revert SafeTransferError();
}
}
/**
* @notice Safely transfer the token between the accounts
* @param _token The token address
* @param _from The token transfer source address
* @param _to The token transfer recipient address
* @param _value The token transfer amount
*/
function safeTransferFrom(address _token, address _from, address _to, uint256 _value) {
// 0x23b872dd is the selector for "transferFrom(address,address,uint256)"
(bool success, bytes memory data) = _token.call(
abi.encodeWithSelector(0x23b872dd, _from, _to, _value)
);
bool condition = success && (data.length == 0 || abi.decode(data, (bool)));
if (!condition) {
revert SafeTransferFromError();
}
}
/**
* @notice Safely transfer the native token to the account
* @param _to The native token transfer recipient address
* @param _value The native token transfer amount
*/
function safeTransferNative(address _to, uint256 _value) {
(bool success, ) = _to.call{ value: _value }(new bytes(0));
if (!success) {
revert SafeTransferNativeError();
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.19;
/**
* @title ITokenBalance
* @notice Token balance interface
*/
interface ITokenBalance {
/**
* @notice Getter of the token balance by the account
* @param _account The account address
* @return Token balance
*/
function balanceOf(address _account) external view returns (uint256);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.19;
import { ITokenBalance } from '../interfaces/ITokenBalance.sol';
import { ManagerRole } from '../roles/ManagerRole.sol';
import '../helpers/TransferHelper.sol' as TransferHelper;
import '../Constants.sol' as Constants;
/**
* @title BalanceManagementMixin
* @notice The balance management mix-in logic
*/
abstract contract BalanceManagementMixin is ManagerRole {
/**
* @notice Emitted when the specified token is reserved
*/
error ReservedTokenError();
/**
* @notice Performs the token cleanup
* @dev Use the "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" address for the native token
* @param _tokenAddress The address of the token
* @param _to The token transfer recipient address
*/
function cleanup(address _tokenAddress, address _to) external virtual onlyManager {
_cleanupWithAmount(_tokenAddress, _to, tokenBalance(_tokenAddress));
}
/**
* @notice Performs the token cleanup using the provided amount
* @dev Use the "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" address for the native token
* @param _tokenAddress The address of the token
* @param _to The token transfer recipient address
* @param _tokenAmount The amount of the token
*/
function cleanupWithAmount(
address _tokenAddress,
address _to,
uint256 _tokenAmount
) external virtual onlyManager {
_cleanupWithAmount(_tokenAddress, _to, _tokenAmount);
}
/**
* @notice Getter of the token balance of the current contract
* @dev Use the "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" address for the native token
* @param _tokenAddress The address of the token
* @return The token balance of the current contract
*/
function tokenBalance(address _tokenAddress) public view virtual returns (uint256) {
if (_tokenAddress == Constants.NATIVE_TOKEN_ADDRESS) {
return address(this).balance;
} else {
return ITokenBalance(_tokenAddress).balanceOf(address(this));
}
}
/**
* @notice Getter of the reserved token flag
* @dev Override to add reserved token addresses
* @param _tokenAddress The address of the token
* @return The reserved token flag
*/
function isReservedToken(address _tokenAddress) public view virtual returns (bool) {
// The function returns false by default.
// The explicit return statement is omitted to avoid the unused parameter warning.
// See https://github.com/ethereum/solidity/issues/5295
}
function _cleanupWithAmount(
address _tokenAddress,
address _to,
uint256 _tokenAmount
) internal virtual {
if (isReservedToken(_tokenAddress)) {
revert ReservedTokenError();
}
if (_tokenAddress == Constants.NATIVE_TOKEN_ADDRESS) {
TransferHelper.safeTransferNative(_to, _tokenAmount);
} else {
TransferHelper.safeTransfer(_tokenAddress, _to, _tokenAmount);
}
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.19;
import { Ownable } from '@openzeppelin/contracts/access/Ownable.sol';
import { RoleBearers } from './RoleBearers.sol';
/**
* @title ManagerRole
* @notice Base contract that implements the Manager role.
* The manager role is a high-permission role for core team members only.
* Managers can set vaults and routers addresses, fees, cross-chain protocols,
* and other parameters for Interchain (cross-chain) swaps and single-network swaps.
* Please note, the manager role is unique for every contract,
* hence different addresses may be assigned as managers for different contracts.
*/
abstract contract ManagerRole is Ownable, RoleBearers {
bytes32 private constant ROLE_KEY = keccak256('Manager');
/**
* @notice Emitted when the Manager role status for the account is updated
* @param account The account address
* @param value The Manager role status flag
*/
event SetManager(address indexed account, bool indexed value);
/**
* @notice Emitted when the Manager role status for the account is renounced
* @param account The account address
*/
event RenounceManagerRole(address indexed account);
/**
* @notice Emitted when the caller is not a Manager role bearer
*/
error OnlyManagerError();
/**
* @dev Modifier to check if the caller is a Manager role bearer
*/
modifier onlyManager() {
if (!isManager(msg.sender)) {
revert OnlyManagerError();
}
_;
}
/**
* @notice Updates the Manager role status for the account
* @param _account The account address
* @param _value The Manager role status flag
*/
function setManager(address _account, bool _value) public onlyOwner {
_setRoleBearer(ROLE_KEY, _account, _value);
emit SetManager(_account, _value);
}
/**
* @notice Renounces the Manager role
*/
function renounceManagerRole() external onlyManager {
_setRoleBearer(ROLE_KEY, msg.sender, false);
emit RenounceManagerRole(msg.sender);
}
/**
* @notice Getter of the Manager role bearer count
* @return The Manager role bearer count
*/
function managerCount() external view returns (uint256) {
return _roleBearerCount(ROLE_KEY);
}
/**
* @notice Getter of the complete list of the Manager role bearers
* @return The complete list of the Manager role bearers
*/
function fullManagerList() external view returns (address[] memory) {
return _fullRoleBearerList(ROLE_KEY);
}
/**
* @notice Getter of the Manager role bearer status
* @param _account The account address
*/
function isManager(address _account) public view returns (bool) {
return _isRoleBearer(ROLE_KEY, _account);
}
function _initRoles(
address _owner,
address[] memory _managers,
bool _addOwnerToManagers
) internal {
address ownerAddress = _owner == address(0) ? msg.sender : _owner;
for (uint256 index; index < _managers.length; index++) {
setManager(_managers[index], true);
}
if (_addOwnerToManagers && !isManager(ownerAddress)) {
setManager(ownerAddress, true);
}
if (ownerAddress != msg.sender) {
transferOwnership(ownerAddress);
}
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.19;
import '../Constants.sol' as Constants;
import '../DataStructures.sol' as DataStructures;
/**
* @title RoleBearers
* @notice Base contract that implements role-based access control
* @dev A custom implementation providing full role bearer lists
*/
abstract contract RoleBearers {
mapping(bytes32 /*roleKey*/ => address[] /*roleBearers*/) private roleBearerTable;
mapping(bytes32 /*roleKey*/ => mapping(address /*account*/ => DataStructures.OptionalValue /*status*/))
private roleBearerIndexTable;
function _setRoleBearer(bytes32 _roleKey, address _account, bool _value) internal {
DataStructures.uniqueAddressListUpdate(
roleBearerTable[_roleKey],
roleBearerIndexTable[_roleKey],
_account,
_value,
Constants.LIST_SIZE_LIMIT_DEFAULT
);
}
function _isRoleBearer(bytes32 _roleKey, address _account) internal view returns (bool) {
return roleBearerIndexTable[_roleKey][_account].isSet;
}
function _roleBearerCount(bytes32 _roleKey) internal view returns (uint256) {
return roleBearerTable[_roleKey].length;
}
function _fullRoleBearerList(bytes32 _roleKey) internal view returns (address[] memory) {
return roleBearerTable[_roleKey];
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.19;
/**
* @title SystemVersionId
* @notice Base contract providing the system version identifier
*/
abstract contract SystemVersionId {
/**
* @dev The system version identifier
*/
uint256 public constant SYSTEM_VERSION_ID = uint256(keccak256('V2-Initial'));
}{
"optimizer": {
"enabled": false,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_endpointAddress","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address[]","name":"_managers","type":"address[]"},{"internalType":"bool","name":"_addOwnerToManagers","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"expectedAmount","type":"uint256"},{"internalType":"uint256","name":"actualAmount","type":"uint256"}],"name":"FeeOnTransferError","type":"error"},{"inputs":[],"name":"ListSizeLimitError","type":"error"},{"inputs":[],"name":"MessagingTokenAmountError","type":"error"},{"inputs":[],"name":"NativeTokenValueError","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NonContractAddressError","type":"error"},{"inputs":[],"name":"OnlyEndpointError","type":"error"},{"inputs":[],"name":"OnlyManagerError","type":"error"},{"inputs":[],"name":"ReservedTokenError","type":"error"},{"inputs":[],"name":"SafeApproveError","type":"error"},{"inputs":[],"name":"SafeTransferError","type":"error"},{"inputs":[],"name":"SafeTransferFromError","type":"error"},{"inputs":[],"name":"SafeTransferNativeError","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"RenounceManagerRole","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"endpointAddress","type":"address"}],"name":"SetEndpoint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"bool","name":"value","type":"bool"}],"name":"SetManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"targetChainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"sourceSender","type":"address"},{"indexed":false,"internalType":"bytes","name":"targetRecipient","type":"bytes"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"indexed":false,"internalType":"struct Client.EVMTokenAmount[]","name":"tokenAmounts","type":"tuple[]"},{"indexed":true,"internalType":"bytes32","name":"ccipMessageId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"TokenBridgeActionSource","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"SYSTEM_VERSION_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"targetChainId","type":"uint256"},{"internalType":"uint64","name":"targetChainSelector","type":"uint64"},{"internalType":"bytes","name":"targetRecipient","type":"bytes"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Client.EVMTokenAmount[]","name":"tokenAmounts","type":"tuple[]"},{"internalType":"bytes","name":"extraArgs","type":"bytes"}],"internalType":"struct InterportCCIPTokenBridgeV2.TokenBridgeAction","name":"_action","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"messagingAmount","type":"uint256"}],"internalType":"struct InterportCCIPBridgeV2Core.MessagingTokenInfo","name":"_messagingTokenInfo","type":"tuple"}],"name":"bridgeTokens","outputs":[{"internalType":"bytes32","name":"ccipMessageId","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"address","name":"_to","type":"address"}],"name":"cleanup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"}],"name":"cleanupWithAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"endpoint","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fullManagerList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isManager","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"isReservedToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"managerCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"targetChainId","type":"uint256"},{"internalType":"uint64","name":"targetChainSelector","type":"uint64"},{"internalType":"bytes","name":"targetRecipient","type":"bytes"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Client.EVMTokenAmount[]","name":"tokenAmounts","type":"tuple[]"},{"internalType":"bytes","name":"extraArgs","type":"bytes"}],"internalType":"struct InterportCCIPTokenBridgeV2.TokenBridgeAction","name":"_action","type":"tuple"},{"internalType":"address","name":"_messagingToken","type":"address"}],"name":"messageFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceManagerRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_endpointAddress","type":"address"}],"name":"setEndpoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_value","type":"bool"}],"name":"setManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"tokenBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60806040523480156200001157600080fd5b50604051620042b8380380620042b8833981810160405281019062000037919062000ccd565b8383838360008060006101000a81548160ff0219169083151502179055506200007562000069620000c060201b60201c565b620000c860201b60201c565b62000086846200018d60201b60201c565b6200009784620001d760201b60201c565b620000aa8383836200025e60201b60201c565b5050505060016004819055505050505062000fc6565b600033905090565b60008060019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600060016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614620001d457620001d3816200037560201b60201c565b5b50565b80600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fc8e81a4efc849969069ec6aae575cf7a6bc5f9d3abac59f4ed190a6f7e05fc6f60405160405180910390a250565b60008073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146200029b57836200029d565b335b905060005b8351811015620002f257620002dc848281518110620002c657620002c562000d5e565b5b60200260200101516001620003cd60201b60201c565b8080620002e99062000dc6565b915050620002a2565b508180156200030f57506200030d816200045a60201b60201c565b155b15620003295762000328816001620003cd60201b60201c565b5b3373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146200036f576200036e816200049560201b60201c565b5b50505050565b62000386816200052b60201b60201c565b620003ca57806040517f8c50d7cd000000000000000000000000000000000000000000000000000000008152600401620003c1919062000e24565b60405180910390fd5b50565b620003dd6200054e60201b60201c565b620004107f6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f8383620005df60201b60201c565b8015158273ffffffffffffffffffffffffffffffffffffffff167fbe9474bb3e78da7e315cdffa5cfa30b767fcc95bbf44a6197da60228eea1028660405160405180910390a35050565b60006200048e7f6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f836200061f60201b60201c565b9050919050565b620004a56200054e60201b60201c565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160362000517576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200050e9062000ec8565b60405180910390fd5b6200052881620000c860201b60201c565b50565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6200055e620000c060201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620005846200068a60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1614620005dd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620005d49062000f3a565b60405180910390fd5b565b620006196001600085815260200190815260200160002060026000868152602001908152602001600020848460c8620006b360201b60201c565b50505050565b60006002600084815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16905092915050565b60008060019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600082620006d457620006ce868686620006f460201b60201c565b620006e9565b620006e8868686856200091760201b60201c565b5b905095945050505050565b6000808360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060000160009054906101000a900460ff16915081156200090f5760008160010154905060006001878054905062000770919062000f5c565b90508082146200086657600087828154811062000792576200079162000d5e565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905080888481548110620007d657620007d562000d5e565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550828760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010181905550505b868054806200087a576200087962000f97565b5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905590558560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080820160006101000a81549060ff02191690556001820160009055505050505b509392505050565b60008360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16159050801562000a9a5781858054905010620009b0576040517fb1655e3300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604051806040016040528060011515815260200186805490508152508460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015590505084839080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b949350505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600062000ae38262000ab6565b9050919050565b62000af58162000ad6565b811462000b0157600080fd5b50565b60008151905062000b158162000aea565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b62000b6b8262000b20565b810181811067ffffffffffffffff8211171562000b8d5762000b8c62000b31565b5b80604052505050565b600062000ba262000aa2565b905062000bb0828262000b60565b919050565b600067ffffffffffffffff82111562000bd35762000bd262000b31565b5b602082029050602081019050919050565b600080fd5b600062000c0062000bfa8462000bb5565b62000b96565b9050808382526020820190506020840283018581111562000c265762000c2562000be4565b5b835b8181101562000c53578062000c3e888262000b04565b84526020840193505060208101905062000c28565b5050509392505050565b600082601f83011262000c755762000c7462000b1b565b5b815162000c8784826020860162000be9565b91505092915050565b60008115159050919050565b62000ca78162000c90565b811462000cb357600080fd5b50565b60008151905062000cc78162000c9c565b92915050565b6000806000806080858703121562000cea5762000ce962000aac565b5b600062000cfa8782880162000b04565b945050602062000d0d8782880162000b04565b935050604085015167ffffffffffffffff81111562000d315762000d3062000ab1565b5b62000d3f8782880162000c5d565b925050606062000d528782880162000cb6565b91505092959194509250565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000819050919050565b600062000dd38262000dbc565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362000e085762000e0762000d8d565b5b600182019050919050565b62000e1e8162000ad6565b82525050565b600060208201905062000e3b600083018462000e13565b92915050565b600082825260208201905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600062000eb060268362000e41565b915062000ebd8262000e52565b604082019050919050565b6000602082019050818103600083015262000ee38162000ea1565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600062000f2260208362000e41565b915062000f2f8262000eea565b602082019050919050565b6000602082019050818103600083015262000f558162000f13565b9050919050565b600062000f698262000dbc565b915062000f768362000dbc565b925082820390508181111562000f915762000f9062000d8d565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6132e28062000fd66000396000f3fe6080604052600436106101225760003560e01c806383d85346116100a0578063dbbb415511610064578063dbbb415514610386578063e3725b15146103af578063eedc966a146103da578063f2fde38b14610417578063f3ae24151461044057610129565b806383d85346146102db5780638456cb59146103045780638da5cb5b1461031b578063a5e90eee14610346578063c2c518e11461036f57610129565b8063440d7248116100e7578063440d7248146102085780635c975abb146102455780635d2251d5146102705780635e280f1114610299578063715018a6146102c457610129565b806235e0121461012e578063093f0e271461015e578063103b73971461018957806330c7d333146101b45780633f4ba83a146101f157610129565b3661012957005b600080fd5b6101486004803603810190610143919061230e565b61047d565b6040516101559190612383565b60405180910390f35b34801561016a57600080fd5b50610173610993565b60405161018091906123b7565b60405180910390f35b34801561019557600080fd5b5061019e6109ba565b6040516101ab91906123b7565b60405180910390f35b3480156101c057600080fd5b506101db60048036038101906101d69190612430565b6109ea565b6040516101e891906123b7565b60405180910390f35b3480156101fd57600080fd5b50610206610ba6565b005b34801561021457600080fd5b5061022f600480360381019061022a919061248c565b610bef565b60405161023c91906124d4565b60405180910390f35b34801561025157600080fd5b5061025a610bf6565b60405161026791906124d4565b60405180910390f35b34801561027c57600080fd5b506102976004803603810190610292919061251b565b610c0c565b005b3480156102a557600080fd5b506102ae610c5b565b6040516102bb919061257d565b60405180910390f35b3480156102d057600080fd5b506102d9610c81565b005b3480156102e757600080fd5b5061030260048036038101906102fd9190612598565b610c95565b005b34801561031057600080fd5b50610319610ceb565b005b34801561032757600080fd5b50610330610d34565b60405161033d919061257d565b60405180910390f35b34801561035257600080fd5b5061036d60048036038101906103689190612604565b610d5d565b005b34801561037b57600080fd5b50610384610dda565b005b34801561039257600080fd5b506103ad60048036038101906103a8919061248c565b610e8a565b005b3480156103bb57600080fd5b506103c4610ede565b6040516103d19190612702565b60405180910390f35b3480156103e657600080fd5b5061040160048036038101906103fc919061248c565b610f0e565b60405161040e91906123b7565b60405180910390f35b34801561042357600080fd5b5061043e6004803603810190610439919061248c565b610fe1565b005b34801561044c57600080fd5b506104676004803603810190610462919061248c565b611064565b60405161047491906124d4565b60405180910390f35b6000610487611097565b61048f6110e1565b60008061049d846000611130565b9150915060008580606001906104b39190612733565b808060200260200160405190810160405280939291908181526020016000905b82821015610503578484839050604002018036038101906104f49190612877565b815260200190600101906104d3565b505050505090506000805b825181101561064257600083828151811061052c5761052b6128a4565b5b602002602001015190506000816020015190506000841580156105905750826000015173ffffffffffffffffffffffffffffffffffffffff168a6000016020810190610578919061248c565b73ffffffffffffffffffffffffffffffffffffffff16145b905080156105af57600194508960200135826105ac9190612902565b91505b6000806105c18560000151858561122f565b9150915080156105d657818560200181815250505b60008560200151905083156105f8578c60400135816105f59190612902565b90505b6106298660000151600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168361139e565b505050505050808061063a90612936565b91505061050e565b508015801561064f575083155b156106bc5761067686600001602081019061066a919061248c565b8760200135600161122f565b50506106bb86600001602081019061068e919061248c565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16886040013561139e565b5b60006040518060a001604052808980604001906106d9919061297e565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508152602001600067ffffffffffffffff81111561073c5761073b6127ac565b5b6040519080825280601f01601f19166020018201604052801561076e5781602001600182028036833780820191505090505b50815260200184815260200188600001602081019061078d919061248c565b73ffffffffffffffffffffffffffffffffffffffff1681526020018980608001906107b8919061297e565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050815250905061081d8860200160208101906108169190612a21565b82866114d1565b955060005b8880606001906108329190612733565b90508110156108b4576108a189806060019061084e9190612733565b8381811061085f5761085e6128a4565b5b9050604002016000016020810190610877919061248c565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600061139e565b80806108ac90612936565b915050610822565b50811580156108c1575084155b15610907576109068760000160208101906108dc919061248c565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600061139e565b5b853373ffffffffffffffffffffffffffffffffffffffff167f70b730e6021ca63af6d83d1a39a35189078ad7702fe56fcea0e24594f3fd933f8a600001358b8060400190610955919061297e565b8d80606001906109659190612733565b4260405161097896959493929190612bbf565b60405180910390a3505050505061098d61157d565b92915050565b7f129af2746e019ad4a5ea363fc9e58e70953711dffe04830e9b286598c48acbc160001c81565b60006109e57f6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f611587565b905090565b6000806040518060a00160405280858060400190610a08919061297e565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508152602001600067ffffffffffffffff811115610a6b57610a6a6127ac565b5b6040519080825280601f01601f191660200182016040528015610a9d5781602001600182028036833780820191505090505b508152602001858060600190610ab39190612733565b808060200260200160405190810160405280939291908181526020016000905b82821015610b0357848483905060400201803603810190610af49190612877565b81526020019060010190610ad3565b505050505081526020018473ffffffffffffffffffffffffffffffffffffffff168152602001858060800190610b39919061297e565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508152509050610b9d846020016020810190610b979190612a21565b826115a7565b91505092915050565b610baf33611064565b610be5576040517f7c3ea23f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610bed61164f565b565b6000919050565b60008060009054906101000a900460ff16905090565b610c1533611064565b610c4b576040517f7c3ea23f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c568383836116b1565b505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610c89611758565b610c9360006117d6565b565b610c9e33611064565b610cd4576040517f7c3ea23f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ce78282610ce285610f0e565b6116b1565b5050565b610cf433611064565b610d2a576040517f7c3ea23f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d3261189b565b565b60008060019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610d65611758565b610d907f6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f83836118fd565b8015158273ffffffffffffffffffffffffffffffffffffffff167fbe9474bb3e78da7e315cdffa5cfa30b767fcc95bbf44a6197da60228eea1028660405160405180910390a35050565b610de333611064565b610e19576040517f7c3ea23f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e457f6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f3360006118fd565b3373ffffffffffffffffffffffffffffffffffffffff167f6cc2c67081f55c2fffb7c008fa995fbbf890f48c7c16fba93d8220f00dc84cc560405160405180910390a2565b610e9333611064565b610ec9576040517f7c3ea23f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ed281611935565b610edb81611982565b50565b6060610f097f6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f611a09565b905090565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610f5f57479050610fdc565b8173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610f98919061257d565b602060405180830381865afa158015610fb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd99190612c2b565b90505b919050565b610fe9611758565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611058576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161104f90612cdb565b60405180910390fd5b611061816117d6565b50565b60006110907f6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f83611aaa565b9050919050565b61109f610bf6565b156110df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110d690612d47565b60405180910390fd5b565b600260045403611126576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161111d90612db3565b60405180910390fd5b6002600481905550565b600080836040013584602001351015611175576040517f7367509b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168460000160208101906111a0919061248c565b73ffffffffffffffffffffffffffffffffffffffff161491506000826111c657836111d7565b8385602001356111d69190612902565b5b905080341015611213576040517f7dd7aa2100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8261121f576000611225565b84604001355b9150509250929050565b60008060008573ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161126d919061257d565b602060405180830381865afa15801561128a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ae9190612c2b565b90506112bc86333088611b15565b808673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016112f6919061257d565b602060405180830381865afa158015611313573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113379190612c2b565b6113419190612dd3565b9250848310156113955783156113905784836040517fccee4258000000000000000000000000000000000000000000000000000000008152600401611387929190612e07565b60405180910390fd5b600191505b50935093915050565b6000808473ffffffffffffffffffffffffffffffffffffffff1663095ea7b385856040516024016113d0929190612e30565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161141e9190612eca565b6000604051808303816000865af19150503d806000811461145b576040519150601f19603f3d011682016040523d82523d6000602084013e611460565b606091505b50915091506000828015611490575060008251148061148f57508180602001905181019061148e9190612ef6565b5b5b9050806114c9576040517fb45d44e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166396f4e9f98386866040518463ffffffff1660e01b81526004016115319291906130e5565b60206040518083038185885af115801561154f573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906115749190613141565b90509392505050565b6001600481905550565b600060016000838152602001908152602001600020805490509050919050565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166320487ded84846040518363ffffffff1660e01b81526004016116069291906130e5565b602060405180830381865afa158015611623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116479190612c2b565b905092915050565b611657611c4b565b60008060006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61169a611c94565b6040516116a7919061257d565b60405180910390a1565b6116ba83610bef565b156116f1576040517f88eed33200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611747576117428282611c9c565b611753565b611752838383611d93565b5b505050565b611760611c94565b73ffffffffffffffffffffffffffffffffffffffff1661177e610d34565b73ffffffffffffffffffffffffffffffffffffffff16146117d4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117cb906131ba565b60405180910390fd5b565b60008060019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600060016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6118a3611097565b60016000806101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586118e6611c94565b6040516118f3919061257d565b60405180910390a1565b61192f6001600085815260200190815260200160002060026000868152602001908152602001600020848460c8611ec6565b50505050565b61193e81611ef5565b61197f57806040517f8c50d7cd000000000000000000000000000000000000000000000000000000008152600401611976919061257d565b60405180910390fd5b50565b80600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fc8e81a4efc849969069ec6aae575cf7a6bc5f9d3abac59f4ed190a6f7e05fc6f60405160405180910390a250565b606060016000838152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015611a9e57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611a54575b50505050509050919050565b60006002600084815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16905092915050565b6000808573ffffffffffffffffffffffffffffffffffffffff166323b872dd868686604051602401611b49939291906131da565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051611b979190612eca565b6000604051808303816000865af19150503d8060008114611bd4576040519150601f19603f3d011682016040523d82523d6000602084013e611bd9565b606091505b50915091506000828015611c095750600082511480611c08575081806020019051810190611c079190612ef6565b5b5b905080611c42576040517f2d9d5b4100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050565b611c53610bf6565b611c92576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c899061325d565b60405180910390fd5b565b600033905090565b60008273ffffffffffffffffffffffffffffffffffffffff1682600067ffffffffffffffff811115611cd157611cd06127ac565b5b6040519080825280601f01601f191660200182016040528015611d035781602001600182028036833780820191505090505b50604051611d119190612eca565b60006040518083038185875af1925050503d8060008114611d4e576040519150601f19603f3d011682016040523d82523d6000602084013e611d53565b606091505b5050905080611d8e576040517fb816c14c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b6000808473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8585604051602401611dc5929190612e30565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051611e139190612eca565b6000604051808303816000865af19150503d8060008114611e50576040519150601f19603f3d011682016040523d82523d6000602084013e611e55565b606091505b50915091506000828015611e855750600082511480611e84575081806020019051810190611e839190612ef6565b5b5b905080611ebe576040517f5fb636fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b600082611edd57611ed8868686611f18565b611eea565b611ee98686868561212e565b5b905095945050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000808360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060000160009054906101000a900460ff169150811561212657600081600101549050600060018780549050611f919190612dd3565b9050808214612080576000878281548110611faf57611fae6128a4565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905080888481548110611ff057611fef6128a4565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550828760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010181905550505b868054806120915761209061327d565b5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905590558560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080820160006101000a81549060ff02191690556001820160009055505050505b509392505050565b60008360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1615905080156122af57818580549050106121c5576040517fb1655e3300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604051806040016040528060011515815260200186805490508152508460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015590505084839080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b949350505050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600060a082840312156122e6576122e56122cb565b5b81905092915050565b600060608284031215612305576123046122cb565b5b81905092915050565b60008060808385031215612325576123246122c1565b5b600083013567ffffffffffffffff811115612343576123426122c6565b5b61234f858286016122d0565b9250506020612360858286016122ef565b9150509250929050565b6000819050919050565b61237d8161236a565b82525050565b60006020820190506123986000830184612374565b92915050565b6000819050919050565b6123b18161239e565b82525050565b60006020820190506123cc60008301846123a8565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006123fd826123d2565b9050919050565b61240d816123f2565b811461241857600080fd5b50565b60008135905061242a81612404565b92915050565b60008060408385031215612447576124466122c1565b5b600083013567ffffffffffffffff811115612465576124646122c6565b5b612471858286016122d0565b92505060206124828582860161241b565b9150509250929050565b6000602082840312156124a2576124a16122c1565b5b60006124b08482850161241b565b91505092915050565b60008115159050919050565b6124ce816124b9565b82525050565b60006020820190506124e960008301846124c5565b92915050565b6124f88161239e565b811461250357600080fd5b50565b600081359050612515816124ef565b92915050565b600080600060608486031215612534576125336122c1565b5b60006125428682870161241b565b93505060206125538682870161241b565b925050604061256486828701612506565b9150509250925092565b612577816123f2565b82525050565b6000602082019050612592600083018461256e565b92915050565b600080604083850312156125af576125ae6122c1565b5b60006125bd8582860161241b565b92505060206125ce8582860161241b565b9150509250929050565b6125e1816124b9565b81146125ec57600080fd5b50565b6000813590506125fe816125d8565b92915050565b6000806040838503121561261b5761261a6122c1565b5b60006126298582860161241b565b925050602061263a858286016125ef565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612679816123f2565b82525050565b600061268b8383612670565b60208301905092915050565b6000602082019050919050565b60006126af82612644565b6126b9818561264f565b93506126c483612660565b8060005b838110156126f55781516126dc888261267f565b97506126e783612697565b9250506001810190506126c8565b5085935050505092915050565b6000602082019050818103600083015261271c81846126a4565b905092915050565b600080fd5b600080fd5b600080fd5b600080833560016020038436030381126127505761274f612724565b5b80840192508235915067ffffffffffffffff82111561277257612771612729565b5b60208301925060408202360383131561278e5761278d61272e565b5b509250929050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6127e48261279b565b810181811067ffffffffffffffff82111715612803576128026127ac565b5b80604052505050565b60006128166122b7565b905061282282826127db565b919050565b60006040828403121561283d5761283c612796565b5b612847604061280c565b905060006128578482850161241b565b600083015250602061286b84828501612506565b60208301525092915050565b60006040828403121561288d5761288c6122c1565b5b600061289b84828501612827565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061290d8261239e565b91506129188361239e565b92508282019050808211156129305761292f6128d3565b5b92915050565b60006129418261239e565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612973576129726128d3565b5b600182019050919050565b6000808335600160200384360303811261299b5761299a612724565b5b80840192508235915067ffffffffffffffff8211156129bd576129bc612729565b5b6020830192506001820236038313156129d9576129d861272e565b5b509250929050565b600067ffffffffffffffff82169050919050565b6129fe816129e1565b8114612a0957600080fd5b50565b600081359050612a1b816129f5565b92915050565b600060208284031215612a3757612a366122c1565b5b6000612a4584828501612a0c565b91505092915050565b600082825260208201905092915050565b82818337600083830152505050565b6000612a7a8385612a4e565b9350612a87838584612a5f565b612a908361279b565b840190509392505050565b600082825260208201905092915050565b6000819050919050565b6000612ac5602084018461241b565b905092915050565b6000612adc6020840184612506565b905092915050565b612aed8161239e565b82525050565b60408201612b046000830183612ab6565b612b116000850182612670565b50612b1f6020830183612acd565b612b2c6020850182612ae4565b50505050565b6000612b3e8383612af3565b60408301905092915050565b600082905092915050565b6000604082019050919050565b6000612b6e8385612a9b565b9350612b7982612aac565b8060005b85811015612bb257612b8f8284612b4a565b612b998882612b32565b9750612ba483612b55565b925050600181019050612b7d565b5085925050509392505050565b6000608082019050612bd460008301896123a8565b8181036020830152612be7818789612a6e565b90508181036040830152612bfc818587612b62565b9050612c0b60608301846123a8565b979650505050505050565b600081519050612c25816124ef565b92915050565b600060208284031215612c4157612c406122c1565b5b6000612c4f84828501612c16565b91505092915050565b600082825260208201905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000612cc5602683612c58565b9150612cd082612c69565b604082019050919050565b60006020820190508181036000830152612cf481612cb8565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b6000612d31601083612c58565b9150612d3c82612cfb565b602082019050919050565b60006020820190508181036000830152612d6081612d24565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000612d9d601f83612c58565b9150612da882612d67565b602082019050919050565b60006020820190508181036000830152612dcc81612d90565b9050919050565b6000612dde8261239e565b9150612de98361239e565b9250828203905081811115612e0157612e006128d3565b5b92915050565b6000604082019050612e1c60008301856123a8565b612e2960208301846123a8565b9392505050565b6000604082019050612e45600083018561256e565b612e5260208301846123a8565b9392505050565b600081519050919050565b600081905092915050565b60005b83811015612e8d578082015181840152602081019050612e72565b60008484015250505050565b6000612ea482612e59565b612eae8185612e64565b9350612ebe818560208601612e6f565b80840191505092915050565b6000612ed68284612e99565b915081905092915050565b600081519050612ef0816125d8565b92915050565b600060208284031215612f0c57612f0b6122c1565b5b6000612f1a84828501612ee1565b91505092915050565b612f2c816129e1565b82525050565b600082825260208201905092915050565b6000612f4e82612e59565b612f588185612f32565b9350612f68818560208601612e6f565b612f718161279b565b840191505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b604082016000820151612fbe6000850182612670565b506020820151612fd16020850182612ae4565b50505050565b6000612fe38383612fa8565b60408301905092915050565b6000602082019050919050565b600061300782612f7c565b6130118185612f87565b935061301c83612f98565b8060005b8381101561304d5781516130348882612fd7565b975061303f83612fef565b925050600181019050613020565b5085935050505092915050565b600060a08301600083015184820360008601526130778282612f43565b915050602083015184820360208601526130918282612f43565b915050604083015184820360408601526130ab8282612ffc565b91505060608301516130c06060860182612670565b50608083015184820360808601526130d88282612f43565b9150508091505092915050565b60006040820190506130fa6000830185612f23565b818103602083015261310c818461305a565b90509392505050565b61311e8161236a565b811461312957600080fd5b50565b60008151905061313b81613115565b92915050565b600060208284031215613157576131566122c1565b5b60006131658482850161312c565b91505092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006131a4602083612c58565b91506131af8261316e565b602082019050919050565b600060208201905081810360008301526131d381613197565b9050919050565b60006060820190506131ef600083018661256e565b6131fc602083018561256e565b61320960408301846123a8565b949350505050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b6000613247601483612c58565b915061325282613211565b602082019050919050565b600060208201905081810360008301526132768161323a565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220866be312f9b4b905715ea259bc07022d58e8145958f4a62d5aa8418cf4ac3a3b64736f6c634300081300330000000000000000000000007c19b79d2a054114ab36ad758a36e92376e267da00000000000000000000000072e28c7f34100afefc399fcc0ae041b8fe5841ae000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106101225760003560e01c806383d85346116100a0578063dbbb415511610064578063dbbb415514610386578063e3725b15146103af578063eedc966a146103da578063f2fde38b14610417578063f3ae24151461044057610129565b806383d85346146102db5780638456cb59146103045780638da5cb5b1461031b578063a5e90eee14610346578063c2c518e11461036f57610129565b8063440d7248116100e7578063440d7248146102085780635c975abb146102455780635d2251d5146102705780635e280f1114610299578063715018a6146102c457610129565b806235e0121461012e578063093f0e271461015e578063103b73971461018957806330c7d333146101b45780633f4ba83a146101f157610129565b3661012957005b600080fd5b6101486004803603810190610143919061230e565b61047d565b6040516101559190612383565b60405180910390f35b34801561016a57600080fd5b50610173610993565b60405161018091906123b7565b60405180910390f35b34801561019557600080fd5b5061019e6109ba565b6040516101ab91906123b7565b60405180910390f35b3480156101c057600080fd5b506101db60048036038101906101d69190612430565b6109ea565b6040516101e891906123b7565b60405180910390f35b3480156101fd57600080fd5b50610206610ba6565b005b34801561021457600080fd5b5061022f600480360381019061022a919061248c565b610bef565b60405161023c91906124d4565b60405180910390f35b34801561025157600080fd5b5061025a610bf6565b60405161026791906124d4565b60405180910390f35b34801561027c57600080fd5b506102976004803603810190610292919061251b565b610c0c565b005b3480156102a557600080fd5b506102ae610c5b565b6040516102bb919061257d565b60405180910390f35b3480156102d057600080fd5b506102d9610c81565b005b3480156102e757600080fd5b5061030260048036038101906102fd9190612598565b610c95565b005b34801561031057600080fd5b50610319610ceb565b005b34801561032757600080fd5b50610330610d34565b60405161033d919061257d565b60405180910390f35b34801561035257600080fd5b5061036d60048036038101906103689190612604565b610d5d565b005b34801561037b57600080fd5b50610384610dda565b005b34801561039257600080fd5b506103ad60048036038101906103a8919061248c565b610e8a565b005b3480156103bb57600080fd5b506103c4610ede565b6040516103d19190612702565b60405180910390f35b3480156103e657600080fd5b5061040160048036038101906103fc919061248c565b610f0e565b60405161040e91906123b7565b60405180910390f35b34801561042357600080fd5b5061043e6004803603810190610439919061248c565b610fe1565b005b34801561044c57600080fd5b506104676004803603810190610462919061248c565b611064565b60405161047491906124d4565b60405180910390f35b6000610487611097565b61048f6110e1565b60008061049d846000611130565b9150915060008580606001906104b39190612733565b808060200260200160405190810160405280939291908181526020016000905b82821015610503578484839050604002018036038101906104f49190612877565b815260200190600101906104d3565b505050505090506000805b825181101561064257600083828151811061052c5761052b6128a4565b5b602002602001015190506000816020015190506000841580156105905750826000015173ffffffffffffffffffffffffffffffffffffffff168a6000016020810190610578919061248c565b73ffffffffffffffffffffffffffffffffffffffff16145b905080156105af57600194508960200135826105ac9190612902565b91505b6000806105c18560000151858561122f565b9150915080156105d657818560200181815250505b60008560200151905083156105f8578c60400135816105f59190612902565b90505b6106298660000151600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168361139e565b505050505050808061063a90612936565b91505061050e565b508015801561064f575083155b156106bc5761067686600001602081019061066a919061248c565b8760200135600161122f565b50506106bb86600001602081019061068e919061248c565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16886040013561139e565b5b60006040518060a001604052808980604001906106d9919061297e565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508152602001600067ffffffffffffffff81111561073c5761073b6127ac565b5b6040519080825280601f01601f19166020018201604052801561076e5781602001600182028036833780820191505090505b50815260200184815260200188600001602081019061078d919061248c565b73ffffffffffffffffffffffffffffffffffffffff1681526020018980608001906107b8919061297e565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050815250905061081d8860200160208101906108169190612a21565b82866114d1565b955060005b8880606001906108329190612733565b90508110156108b4576108a189806060019061084e9190612733565b8381811061085f5761085e6128a4565b5b9050604002016000016020810190610877919061248c565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600061139e565b80806108ac90612936565b915050610822565b50811580156108c1575084155b15610907576109068760000160208101906108dc919061248c565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600061139e565b5b853373ffffffffffffffffffffffffffffffffffffffff167f70b730e6021ca63af6d83d1a39a35189078ad7702fe56fcea0e24594f3fd933f8a600001358b8060400190610955919061297e565b8d80606001906109659190612733565b4260405161097896959493929190612bbf565b60405180910390a3505050505061098d61157d565b92915050565b7f129af2746e019ad4a5ea363fc9e58e70953711dffe04830e9b286598c48acbc160001c81565b60006109e57f6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f611587565b905090565b6000806040518060a00160405280858060400190610a08919061297e565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508152602001600067ffffffffffffffff811115610a6b57610a6a6127ac565b5b6040519080825280601f01601f191660200182016040528015610a9d5781602001600182028036833780820191505090505b508152602001858060600190610ab39190612733565b808060200260200160405190810160405280939291908181526020016000905b82821015610b0357848483905060400201803603810190610af49190612877565b81526020019060010190610ad3565b505050505081526020018473ffffffffffffffffffffffffffffffffffffffff168152602001858060800190610b39919061297e565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508152509050610b9d846020016020810190610b979190612a21565b826115a7565b91505092915050565b610baf33611064565b610be5576040517f7c3ea23f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610bed61164f565b565b6000919050565b60008060009054906101000a900460ff16905090565b610c1533611064565b610c4b576040517f7c3ea23f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c568383836116b1565b505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610c89611758565b610c9360006117d6565b565b610c9e33611064565b610cd4576040517f7c3ea23f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ce78282610ce285610f0e565b6116b1565b5050565b610cf433611064565b610d2a576040517f7c3ea23f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d3261189b565b565b60008060019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610d65611758565b610d907f6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f83836118fd565b8015158273ffffffffffffffffffffffffffffffffffffffff167fbe9474bb3e78da7e315cdffa5cfa30b767fcc95bbf44a6197da60228eea1028660405160405180910390a35050565b610de333611064565b610e19576040517f7c3ea23f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e457f6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f3360006118fd565b3373ffffffffffffffffffffffffffffffffffffffff167f6cc2c67081f55c2fffb7c008fa995fbbf890f48c7c16fba93d8220f00dc84cc560405160405180910390a2565b610e9333611064565b610ec9576040517f7c3ea23f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ed281611935565b610edb81611982565b50565b6060610f097f6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f611a09565b905090565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610f5f57479050610fdc565b8173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610f98919061257d565b602060405180830381865afa158015610fb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd99190612c2b565b90505b919050565b610fe9611758565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611058576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161104f90612cdb565b60405180910390fd5b611061816117d6565b50565b60006110907f6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f83611aaa565b9050919050565b61109f610bf6565b156110df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110d690612d47565b60405180910390fd5b565b600260045403611126576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161111d90612db3565b60405180910390fd5b6002600481905550565b600080836040013584602001351015611175576040517f7367509b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168460000160208101906111a0919061248c565b73ffffffffffffffffffffffffffffffffffffffff161491506000826111c657836111d7565b8385602001356111d69190612902565b5b905080341015611213576040517f7dd7aa2100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8261121f576000611225565b84604001355b9150509250929050565b60008060008573ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161126d919061257d565b602060405180830381865afa15801561128a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ae9190612c2b565b90506112bc86333088611b15565b808673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016112f6919061257d565b602060405180830381865afa158015611313573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113379190612c2b565b6113419190612dd3565b9250848310156113955783156113905784836040517fccee4258000000000000000000000000000000000000000000000000000000008152600401611387929190612e07565b60405180910390fd5b600191505b50935093915050565b6000808473ffffffffffffffffffffffffffffffffffffffff1663095ea7b385856040516024016113d0929190612e30565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161141e9190612eca565b6000604051808303816000865af19150503d806000811461145b576040519150601f19603f3d011682016040523d82523d6000602084013e611460565b606091505b50915091506000828015611490575060008251148061148f57508180602001905181019061148e9190612ef6565b5b5b9050806114c9576040517fb45d44e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166396f4e9f98386866040518463ffffffff1660e01b81526004016115319291906130e5565b60206040518083038185885af115801561154f573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906115749190613141565b90509392505050565b6001600481905550565b600060016000838152602001908152602001600020805490509050919050565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166320487ded84846040518363ffffffff1660e01b81526004016116069291906130e5565b602060405180830381865afa158015611623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116479190612c2b565b905092915050565b611657611c4b565b60008060006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61169a611c94565b6040516116a7919061257d565b60405180910390a1565b6116ba83610bef565b156116f1576040517f88eed33200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611747576117428282611c9c565b611753565b611752838383611d93565b5b505050565b611760611c94565b73ffffffffffffffffffffffffffffffffffffffff1661177e610d34565b73ffffffffffffffffffffffffffffffffffffffff16146117d4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117cb906131ba565b60405180910390fd5b565b60008060019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600060016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6118a3611097565b60016000806101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586118e6611c94565b6040516118f3919061257d565b60405180910390a1565b61192f6001600085815260200190815260200160002060026000868152602001908152602001600020848460c8611ec6565b50505050565b61193e81611ef5565b61197f57806040517f8c50d7cd000000000000000000000000000000000000000000000000000000008152600401611976919061257d565b60405180910390fd5b50565b80600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fc8e81a4efc849969069ec6aae575cf7a6bc5f9d3abac59f4ed190a6f7e05fc6f60405160405180910390a250565b606060016000838152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015611a9e57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611a54575b50505050509050919050565b60006002600084815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16905092915050565b6000808573ffffffffffffffffffffffffffffffffffffffff166323b872dd868686604051602401611b49939291906131da565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051611b979190612eca565b6000604051808303816000865af19150503d8060008114611bd4576040519150601f19603f3d011682016040523d82523d6000602084013e611bd9565b606091505b50915091506000828015611c095750600082511480611c08575081806020019051810190611c079190612ef6565b5b5b905080611c42576040517f2d9d5b4100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050565b611c53610bf6565b611c92576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c899061325d565b60405180910390fd5b565b600033905090565b60008273ffffffffffffffffffffffffffffffffffffffff1682600067ffffffffffffffff811115611cd157611cd06127ac565b5b6040519080825280601f01601f191660200182016040528015611d035781602001600182028036833780820191505090505b50604051611d119190612eca565b60006040518083038185875af1925050503d8060008114611d4e576040519150601f19603f3d011682016040523d82523d6000602084013e611d53565b606091505b5050905080611d8e576040517fb816c14c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b6000808473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8585604051602401611dc5929190612e30565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051611e139190612eca565b6000604051808303816000865af19150503d8060008114611e50576040519150601f19603f3d011682016040523d82523d6000602084013e611e55565b606091505b50915091506000828015611e855750600082511480611e84575081806020019051810190611e839190612ef6565b5b5b905080611ebe576040517f5fb636fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b600082611edd57611ed8868686611f18565b611eea565b611ee98686868561212e565b5b905095945050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000808360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060000160009054906101000a900460ff169150811561212657600081600101549050600060018780549050611f919190612dd3565b9050808214612080576000878281548110611faf57611fae6128a4565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905080888481548110611ff057611fef6128a4565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550828760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010181905550505b868054806120915761209061327d565b5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905590558560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080820160006101000a81549060ff02191690556001820160009055505050505b509392505050565b60008360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1615905080156122af57818580549050106121c5576040517fb1655e3300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604051806040016040528060011515815260200186805490508152508460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015590505084839080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b949350505050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600060a082840312156122e6576122e56122cb565b5b81905092915050565b600060608284031215612305576123046122cb565b5b81905092915050565b60008060808385031215612325576123246122c1565b5b600083013567ffffffffffffffff811115612343576123426122c6565b5b61234f858286016122d0565b9250506020612360858286016122ef565b9150509250929050565b6000819050919050565b61237d8161236a565b82525050565b60006020820190506123986000830184612374565b92915050565b6000819050919050565b6123b18161239e565b82525050565b60006020820190506123cc60008301846123a8565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006123fd826123d2565b9050919050565b61240d816123f2565b811461241857600080fd5b50565b60008135905061242a81612404565b92915050565b60008060408385031215612447576124466122c1565b5b600083013567ffffffffffffffff811115612465576124646122c6565b5b612471858286016122d0565b92505060206124828582860161241b565b9150509250929050565b6000602082840312156124a2576124a16122c1565b5b60006124b08482850161241b565b91505092915050565b60008115159050919050565b6124ce816124b9565b82525050565b60006020820190506124e960008301846124c5565b92915050565b6124f88161239e565b811461250357600080fd5b50565b600081359050612515816124ef565b92915050565b600080600060608486031215612534576125336122c1565b5b60006125428682870161241b565b93505060206125538682870161241b565b925050604061256486828701612506565b9150509250925092565b612577816123f2565b82525050565b6000602082019050612592600083018461256e565b92915050565b600080604083850312156125af576125ae6122c1565b5b60006125bd8582860161241b565b92505060206125ce8582860161241b565b9150509250929050565b6125e1816124b9565b81146125ec57600080fd5b50565b6000813590506125fe816125d8565b92915050565b6000806040838503121561261b5761261a6122c1565b5b60006126298582860161241b565b925050602061263a858286016125ef565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612679816123f2565b82525050565b600061268b8383612670565b60208301905092915050565b6000602082019050919050565b60006126af82612644565b6126b9818561264f565b93506126c483612660565b8060005b838110156126f55781516126dc888261267f565b97506126e783612697565b9250506001810190506126c8565b5085935050505092915050565b6000602082019050818103600083015261271c81846126a4565b905092915050565b600080fd5b600080fd5b600080fd5b600080833560016020038436030381126127505761274f612724565b5b80840192508235915067ffffffffffffffff82111561277257612771612729565b5b60208301925060408202360383131561278e5761278d61272e565b5b509250929050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6127e48261279b565b810181811067ffffffffffffffff82111715612803576128026127ac565b5b80604052505050565b60006128166122b7565b905061282282826127db565b919050565b60006040828403121561283d5761283c612796565b5b612847604061280c565b905060006128578482850161241b565b600083015250602061286b84828501612506565b60208301525092915050565b60006040828403121561288d5761288c6122c1565b5b600061289b84828501612827565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061290d8261239e565b91506129188361239e565b92508282019050808211156129305761292f6128d3565b5b92915050565b60006129418261239e565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612973576129726128d3565b5b600182019050919050565b6000808335600160200384360303811261299b5761299a612724565b5b80840192508235915067ffffffffffffffff8211156129bd576129bc612729565b5b6020830192506001820236038313156129d9576129d861272e565b5b509250929050565b600067ffffffffffffffff82169050919050565b6129fe816129e1565b8114612a0957600080fd5b50565b600081359050612a1b816129f5565b92915050565b600060208284031215612a3757612a366122c1565b5b6000612a4584828501612a0c565b91505092915050565b600082825260208201905092915050565b82818337600083830152505050565b6000612a7a8385612a4e565b9350612a87838584612a5f565b612a908361279b565b840190509392505050565b600082825260208201905092915050565b6000819050919050565b6000612ac5602084018461241b565b905092915050565b6000612adc6020840184612506565b905092915050565b612aed8161239e565b82525050565b60408201612b046000830183612ab6565b612b116000850182612670565b50612b1f6020830183612acd565b612b2c6020850182612ae4565b50505050565b6000612b3e8383612af3565b60408301905092915050565b600082905092915050565b6000604082019050919050565b6000612b6e8385612a9b565b9350612b7982612aac565b8060005b85811015612bb257612b8f8284612b4a565b612b998882612b32565b9750612ba483612b55565b925050600181019050612b7d565b5085925050509392505050565b6000608082019050612bd460008301896123a8565b8181036020830152612be7818789612a6e565b90508181036040830152612bfc818587612b62565b9050612c0b60608301846123a8565b979650505050505050565b600081519050612c25816124ef565b92915050565b600060208284031215612c4157612c406122c1565b5b6000612c4f84828501612c16565b91505092915050565b600082825260208201905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000612cc5602683612c58565b9150612cd082612c69565b604082019050919050565b60006020820190508181036000830152612cf481612cb8565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b6000612d31601083612c58565b9150612d3c82612cfb565b602082019050919050565b60006020820190508181036000830152612d6081612d24565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000612d9d601f83612c58565b9150612da882612d67565b602082019050919050565b60006020820190508181036000830152612dcc81612d90565b9050919050565b6000612dde8261239e565b9150612de98361239e565b9250828203905081811115612e0157612e006128d3565b5b92915050565b6000604082019050612e1c60008301856123a8565b612e2960208301846123a8565b9392505050565b6000604082019050612e45600083018561256e565b612e5260208301846123a8565b9392505050565b600081519050919050565b600081905092915050565b60005b83811015612e8d578082015181840152602081019050612e72565b60008484015250505050565b6000612ea482612e59565b612eae8185612e64565b9350612ebe818560208601612e6f565b80840191505092915050565b6000612ed68284612e99565b915081905092915050565b600081519050612ef0816125d8565b92915050565b600060208284031215612f0c57612f0b6122c1565b5b6000612f1a84828501612ee1565b91505092915050565b612f2c816129e1565b82525050565b600082825260208201905092915050565b6000612f4e82612e59565b612f588185612f32565b9350612f68818560208601612e6f565b612f718161279b565b840191505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b604082016000820151612fbe6000850182612670565b506020820151612fd16020850182612ae4565b50505050565b6000612fe38383612fa8565b60408301905092915050565b6000602082019050919050565b600061300782612f7c565b6130118185612f87565b935061301c83612f98565b8060005b8381101561304d5781516130348882612fd7565b975061303f83612fef565b925050600181019050613020565b5085935050505092915050565b600060a08301600083015184820360008601526130778282612f43565b915050602083015184820360208601526130918282612f43565b915050604083015184820360408601526130ab8282612ffc565b91505060608301516130c06060860182612670565b50608083015184820360808601526130d88282612f43565b9150508091505092915050565b60006040820190506130fa6000830185612f23565b818103602083015261310c818461305a565b90509392505050565b61311e8161236a565b811461312957600080fd5b50565b60008151905061313b81613115565b92915050565b600060208284031215613157576131566122c1565b5b60006131658482850161312c565b91505092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006131a4602083612c58565b91506131af8261316e565b602082019050919050565b600060208201905081810360008301526131d381613197565b9050919050565b60006060820190506131ef600083018661256e565b6131fc602083018561256e565b61320960408301846123a8565b949350505050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b6000613247601483612c58565b915061325282613211565b602082019050919050565b600060208201905081810360008301526132768161323a565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220866be312f9b4b905715ea259bc07022d58e8145958f4a62d5aa8418cf4ac3a3b64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000007c19b79d2a054114ab36ad758a36e92376e267da00000000000000000000000072e28c7f34100afefc399fcc0ae041b8fe5841ae000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _endpointAddress (address): 0x7c19b79D2a054114Ab36ad758A36e92376e267DA
Arg [1] : _owner (address): 0x72E28c7F34100AfefC399fcc0AE041B8fe5841AE
Arg [2] : _managers (address[]):
Arg [3] : _addOwnerToManagers (bool): True
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000007c19b79d2a054114ab36ad758a36e92376e267da
Arg [1] : 00000000000000000000000072e28c7f34100afefc399fcc0ae041b8fe5841ae
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 53.54% | $2,837.96 | 0.1264 | $358.81 | |
| BSC | 37.29% | $853.8 | 0.2927 | $249.89 | |
| BASE | 4.53% | $2,838.61 | 0.0107 | $30.34 | |
| ARB | 1.71% | $2,837.12 | 0.00404983 | $11.49 | |
| HYPEREVM | 0.82% | $31.32 | 0.1763 | $5.52 | |
| AVAX | 0.74% | $13.46 | 0.3696 | $4.97 | |
| POL | 0.40% | $0.134516 | 20.1063 | $2.7 | |
| BERA | 0.38% | $1.03 | 2.4451 | $2.53 | |
| SONIC | 0.21% | $0.105308 | 13.0634 | $1.38 | |
| OP | 0.16% | $2,837.4 | 0.00038049 | $1.08 | |
| LINEA | 0.11% | $2,837.96 | 0.0002599 | $0.737597 | |
| KATANA | 0.05% | $2,837.53 | 0.00012894 | $0.365859 | |
| UNI | 0.05% | $2,837.12 | 0.0001238 | $0.351247 |
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.