Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 4 internal transactions
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
12856685 | 2 days ago | Contract Creation | 0 S | |||
12821498 | 2 days ago | Contract Creation | 0 S | |||
12821388 | 2 days ago | Contract Creation | 0 S | |||
12817611 | 2 days ago | Contract Creation | 0 S |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Factory
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 1000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.28; import {Enums} from "./lib/Enums.sol"; import {Strategy} from "./Strategy.sol"; import {IFactory} from "./interfaces/IFactory.sol"; contract Factory is IFactory { address internal _revenue; address internal _dataFeed; address internal _swapRouter; address internal constant EDGER = 0x3E646e062F05e01e1860eA53a6DC81e7E9162DE6; constructor(address revenue_, address dataFeed_, address swapRouter_) { _revenue = revenue_; _dataFeed = dataFeed_; _swapRouter = swapRouter_; } function createStrategy( address[] memory tokens, uint256[] memory splitRatio, Enums.Visibility visibility, uint256 depositUsdMin, uint256 forkCost, Enums.ActionCall[] memory allowedActions ) external returns (address) { Strategy strategy = new Strategy( address(this), msg.sender, visibility, depositUsdMin, forkCost, tokens, splitRatio, allowedActions ); emit StrategyCreated( address(strategy), msg.sender, tokens, splitRatio, visibility, depositUsdMin, forkCost, allowedActions ); return address(strategy); } function forkStrategy(address strategy) external payable returns (address) { Strategy base = Strategy(payable(strategy)); Strategy fork = new Strategy( address(this), msg.sender, Enums.Visibility.Private, base.getDepositUsdMin(), 0, // forkCost base.getTokens(), base.getSplitRatio(), base.getAllowedActions() ); base.onFork{value: msg.value}(); emit StrategyForked(strategy, address(fork), msg.sender); return address(strategy); } function getRevenueAddress() external view override returns (address) { return _revenue; } function getSwapRouterAddress() external view override returns (address) { return _swapRouter; } function getPriceOracleAddress() external view override returns (address) { return _dataFeed; } function edger() external pure override returns (address) { return EDGER; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../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. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC-20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC-721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC-1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.2.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC20Metadata} from "./extensions/IERC20Metadata.sol"; import {Context} from "../../utils/Context.sol"; import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC-20 * applications. */ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { mapping(address account => uint256) private _balances; mapping(address account => mapping(address spender => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Skips emitting an {Approval} event indicating an allowance update. This is not * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows _totalSupply += value; } else { uint256 fromBalance = _balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. _balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. _totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. _balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * * ```solidity * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } _allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner` s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance < type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC-20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @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; } }
pragma solidity >=0.6.2; interface IUniswapV2Router01 { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB, uint liquidity); function addLiquidityETH( address token, uint amountTokenDesired, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external payable returns (uint amountToken, uint amountETH, uint liquidity); function removeLiquidity( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB); function removeLiquidityETH( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountToken, uint amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountA, uint amountB); function removeLiquidityETHWithPermit( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountToken, uint amountETH); function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapTokensForExactTokens( uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); }
pragma solidity >=0.6.2; import './IUniswapV2Router01.sol'; interface IUniswapV2Router02 is IUniswapV2Router01 { function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountETH); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint amountOutMin, address[] calldata path, address to, uint deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.28; import {Enums} from "../lib/Enums.sol"; interface IFactory { event StrategyCreated( address strategy, address creator, address[] tokens, uint256[] splitRatio, Enums.Visibility visibility, uint256 depositUsdMin, uint256 forkCost, Enums.ActionCall[] allowedActions ); event StrategyForked(address base, address fork, address forker); function createStrategy( address[] memory tokens, uint256[] memory splitRatio, Enums.Visibility visibility, uint256 depositUsdMin, uint256 forkCost, Enums.ActionCall[] memory allowedActions ) external returns (address); function forkStrategy(address strategy) external payable returns (address); function getRevenueAddress() external view returns (address); function getSwapRouterAddress() external view returns (address); function getPriceOracleAddress() external view returns (address); function edger() external view returns (address); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.28; import {Enums} from "../lib/Enums.sol"; import {IPoolAdmin} from "./IPoolAdmin.sol"; interface IMultiTokenPool is IPoolAdmin { event TokensDeposited(address indexed lp, address token, uint256 amount); event TokensWithdrawn( address indexed lp, address[] tokens, uint256[] amounts ); event TokensDonated(address indexed donor, address token, uint256 amount); function deposit(address token, uint256 amount) external; function depositETH(uint256 amount) external payable; function withdraw(uint256 lpAmount) external; function withdrawSingle(address tokenOut, uint256 lpAmount) external; function withdrawSingleETH(uint256 lpAmount) external; function donate(address token, uint256 amount) external; function donateETH(uint256 amount) external payable; function getTokens() external view returns (address[] memory); function getBalances() external view returns (uint256[] memory); function getSplitRatio() external view returns (uint256[] memory); function getDepositUsdMin() external view returns (uint256); function getAllowedActions() external view returns (Enums.ActionCall[] memory); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.28; interface IPoolAdmin { function addToken(address token, uint256 ratio) external; function removeToken(address token) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.28; interface IPriceOracle { function getAmountOutInUsd( uint256 amountIn, address tokenIn ) external view returns (uint256 amountOut); function getAmountsOutInUsd( uint256[] memory amountIns, address[] memory tokenIns ) external view returns (uint256 amountOut); function getAmountOut( uint256 amountIn, address tokenIn, address tokenOut ) external view returns (uint256 amountOut); function getAmountsOut( uint256[] memory amountIns, address[] memory tokenIns, address tokenOut ) external view returns (uint256 amountOut); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.28; import {Types} from "../lib/Types.sol"; interface IRevenue { event Funded(address indexed user, uint256 amount); event Withdrawn(address indexed user, uint256 amount); function fund(address to) external payable; function withdraw(uint256 amount) external; function balanceOf( address user ) external view returns (Types.Revenue memory); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.28; import {Enums} from "../lib/Enums.sol"; import {Params} from "../lib/Params.sol"; interface IStrategy { event ExecuteCalled(Params.ExecuteCall call); function onFork() external payable; function executeCall(Params.ExecuteCall memory call) external; function creator() external view returns (address); function factory() external view returns (address); function getForkCost() external view returns (uint256); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.28; interface IWETH { function withdraw(uint value) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.28; library Enums { enum Visibility { Public, Private } enum ActionCall { AdjustSplitRatio, SwapToSingle, SwapToMany, None // SupplyToAave, // BorrowFromAave, // BridgeToken } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.28; import {Enums} from "./Enums.sol"; library Params { struct ExecuteCall { Enums.ActionCall action; bytes data; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.28; library Types { struct Revenue { uint256 claimed; uint256 unClaimed; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.28; import {Enums} from "../lib/Enums.sol"; import {IFactory} from "../interfaces/IFactory.sol"; import {IPriceOracle} from "../interfaces/IPriceOracle.sol"; import {IMultiTokenPool} from "../interfaces/IMultiTokenPool.sol"; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {IUniswapV2Router02} from "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; import {PoolActions} from "./PoolActions.sol"; contract MultiTokenPool is ERC20, PoolActions, IMultiTokenPool, Ownable { constructor( address factory_, address creator_, uint256 depositUsdMin_, address[] memory initialTokens_, uint256[] memory initialSplitRatio_, Enums.ActionCall[] memory allowedActions_ ) ERC20("LPToken", "LP") Ownable(creator_) { require( initialTokens_.length == initialSplitRatio_.length, "Mismatched arrays" ); _factory = factory_; address swapRouter = IFactory(_factory).getSwapRouterAddress(); _swapRouter = IUniswapV2Router02(swapRouter); _depositUsdMin = depositUsdMin_; _underlyingTokens = initialTokens_; _splitRatio = initialSplitRatio_; _allowedActions = allowedActions_; uint256 totalRatio = 0; for (uint256 i = 0; i < initialSplitRatio_.length; i++) { totalRatio += initialSplitRatio_[i]; _isUnderlyingToken[initialTokens_[i]] = true; } require(totalRatio == DIVISOR, "Invalid ratio sum"); } //////////////////////////////////////////////// //// POOL FUNCTIONS //// //////////////////////////////////////////////// function deposit( address token, uint256 amount ) external override onlyOwner { require(_isUnderlyingToken[token], "ETH not supported"); address priceOracle = IFactory(_factory).getPriceOracleAddress(); uint256 amountUsd = IPriceOracle(priceOracle).getAmountOutInUsd( amount, token ); require( amountUsd >= _depositUsdMin, "Insufficient deposit amount in usd" ); IERC20(token).transferFrom(msg.sender, address(this), amount); _mint(msg.sender, amountUsd); emit TokensDeposited(msg.sender, token, amount); } function depositETH(uint256 amount) external payable override onlyOwner { require(msg.value == amount, "Incorrect ETH amount"); require(_isUnderlyingToken[SONIC_COIN], "ETH not supported"); address priceOracle = IFactory(_factory).getPriceOracleAddress(); uint256 amountUsd = IPriceOracle(priceOracle).getAmountOutInUsd( amount, SONIC_COIN ); require( amountUsd >= _depositUsdMin, "Insufficient deposit amount in usd" ); _mint(msg.sender, amountUsd); emit TokensDeposited(msg.sender, SONIC_COIN, amount); } function withdraw(uint256 lpAmount) external override { require(lpAmount > 0, "Invalid amount"); uint256 totalSupply = totalSupply(); require(totalSupply > 0, "No liquidity"); for (uint256 i = 0; i < _underlyingTokens.length; i++) { address tokenOut = _underlyingTokens[i]; uint256 amountOut = (getBalance(tokenOut) * lpAmount) / totalSupply; if (tokenOut == SONIC_COIN) { (bool _success, ) = payable(msg.sender).call{value: amountOut}( "" ); require(_success, "ETH transfer failed"); } else { IERC20(tokenOut).transfer(msg.sender, amountOut); } } _burn(msg.sender, lpAmount); } function withdrawSingle(address token, uint256 lpAmount) external override { _withdrawSingle(token, lpAmount); } function withdrawSingleETH(uint256 lpAmount) external override { _withdrawSingle(SONIC_COIN, lpAmount); } function _withdrawSingle(address tokenOut, uint256 lpAmount) internal { require(lpAmount > 0, "Invalid amount"); require(_isUnderlyingToken[tokenOut], "Invalid token"); uint256 totalSupply = totalSupply(); require(totalSupply > 0, "No liquidity"); for (uint256 i = 0; i < _underlyingTokens.length; i++) { address tokenIn = _underlyingTokens[i]; uint256 amountIn = (getBalance(tokenIn) * lpAmount) / totalSupply; address[] memory path = new address[](2); path[0] = tokenIn == SONIC_COIN ? _swapRouter.WETH() : tokenIn; path[1] = tokenOut == SONIC_COIN ? _swapRouter.WETH() : tokenOut; if (tokenIn == tokenOut && tokenOut == SONIC_COIN) { (bool _success, ) = payable(msg.sender).call{value: amountIn}( "" ); require(_success, "ETH transfer failed"); } else if (tokenIn == tokenOut) { IERC20(tokenIn).transfer(msg.sender, amountIn); } else if (tokenIn == SONIC_COIN) { _swapRouter.swapExactETHForTokens{value: amountIn}( 0, // amountOutMin path, msg.sender, block.timestamp + 1 ); } else { IERC20(tokenIn).approve(address(_swapRouter), amountIn); _swapRouter.swapExactTokensForTokens( amountIn, 0, // amountOutMin path, msg.sender, block.timestamp + 1 ); } } _burn(msg.sender, lpAmount); } function donate(address token, uint256 amount) external override { require(_isUnderlyingToken[token], "Invalid token"); IERC20(token).transferFrom(msg.sender, address(this), amount); emit TokensDonated(msg.sender, token, amount); } function donateETH(uint256 amount) external payable override { require(_isUnderlyingToken[SONIC_COIN], "ETH not supported"); require(msg.value == amount, "Incorrect ETH amount"); emit TokensDonated(msg.sender, SONIC_COIN, amount); } //////////////////////////////////////////////// //// VIEW FUNCTIONS //// //////////////////////////////////////////////// // Get the list of underlying tokens in the pool function getTokens() external view override returns (address[] memory) { return _underlyingTokens; } // Get the balances of all underlying tokens in the pool function getBalances() external view override returns (uint256[] memory) { uint256[] memory balances = new uint256[](_underlyingTokens.length); for (uint256 i = 0; i < _underlyingTokens.length; i++) { balances[i] = getBalance(_underlyingTokens[i]); } return balances; } function getSplitRatio() external view override returns (uint256[] memory) { return _splitRatio; } function getDepositUsdMin() external view override returns (uint256) { return _depositUsdMin; } function getAllowedActions() external view override returns (Enums.ActionCall[] memory) { return _allowedActions; } //////////////////////////////////////////////// //// ADMIN FUNCTIONS //// //////////////////////////////////////////////// function addToken( address token, uint256 ratio ) external override onlyOwner { require(!_isUnderlyingToken[token], "Token exists"); _underlyingTokens.push(token); _splitRatio.push(ratio); _isUnderlyingToken[token] = true; } function removeToken(address token) external override onlyOwner { require(_isUnderlyingToken[token], "Token not found"); require( IERC20(token).balanceOf(address(this)) == 0, "Non-zero balance" ); for (uint256 i = 0; i < _underlyingTokens.length; i++) { if (_underlyingTokens[i] == token) { _underlyingTokens[i] = _underlyingTokens[ _underlyingTokens.length - 1 ]; _underlyingTokens.pop(); _splitRatio[i] = _splitRatio[_splitRatio.length - 1]; _splitRatio.pop(); _isUnderlyingToken[token] = false; break; } } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.28; import {Enums} from "../lib/Enums.sol"; import {IWETH} from "../interfaces/IWETH.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IUniswapV2Router02} from "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; abstract contract PoolActions { IUniswapV2Router02 internal immutable _swapRouter; address internal immutable _factory; uint256 internal _depositUsdMin; uint256[] internal _splitRatio; address[] internal _underlyingTokens; Enums.ActionCall[] internal _allowedActions; mapping(address => bool) internal _isUnderlyingToken; uint256 constant DIVISOR = 10_000; address constant SONIC_COIN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; receive() external payable {} function _swapToSingle( address[] memory tokensIn, address tokenOut ) internal { require(_isUnderlyingToken[tokenOut], "Invalid token"); for (uint256 i = 0; i < tokensIn.length; i++) { address tokenIn = tokensIn[i]; uint256 amountIn = getBalance(tokenIn); if (amountIn == 0) continue; address[] memory path = new address[](2); path[0] = tokenIn == SONIC_COIN ? _swapRouter.WETH() : tokenIn; path[1] = tokenOut == SONIC_COIN ? _swapRouter.WETH() : tokenOut; if (tokenIn == tokenOut) { continue; } else if (tokenIn == SONIC_COIN) { _swapRouter.swapExactETHForTokens{value: amountIn}( 0, // amountOutMin path, address(this), block.timestamp + 1 ); } else if (tokenOut == SONIC_COIN) { IERC20(tokenIn).approve(address(_swapRouter), amountIn); _swapRouter.swapExactTokensForETH( amountIn, 0, // amountOutMin path, address(this), block.timestamp + 1 ); } else { IERC20(tokenIn).approve(address(_swapRouter), amountIn); _swapRouter.swapExactTokensForTokens( amountIn, 0, // amountOutMin path, address(this), block.timestamp + 1 ); } } } function _swapToMany(address tokenIn, address[] memory tokensOut) internal { require(_isUnderlyingToken[tokenIn], "Invalid token"); uint256 amountIns = tokenIn == SONIC_COIN ? address(this).balance : IERC20(tokenIn).balanceOf(address(this)); if (amountIns == 0) return; uint256 amountIn = (amountIns / tokensOut.length); for (uint256 i = 0; i < tokensOut.length; i++) { address tokenOut = tokensOut[i]; require(_isUnderlyingToken[tokenOut], "Invalid token"); address[] memory path = new address[](2); path[0] = tokenIn == SONIC_COIN ? _swapRouter.WETH() : tokenIn; path[1] = tokenOut == SONIC_COIN ? _swapRouter.WETH() : tokenOut; if (tokenIn == tokenOut) { continue; } else if (tokenIn == SONIC_COIN) { _swapRouter.swapExactETHForTokens{value: amountIn}( 0, // amountOutMin path, address(this), block.timestamp + 1 ); } else if (tokenOut == SONIC_COIN) { IERC20(tokenIn).approve(address(_swapRouter), amountIn); _swapRouter.swapExactTokensForETH( amountIn, 0, // amountOutMin path, address(this), block.timestamp + 1 ); } else { IERC20(tokenIn).approve(address(_swapRouter), amountIn); _swapRouter.swapExactTokensForTokens( amountIn, 0, // amountOutMin path, address(this), block.timestamp + 1 ); } } } function _adjustSplitRatio(uint256[] memory newRatios) internal { require(newRatios.length == _underlyingTokens.length, "Invalid length"); uint256 totalRatio = 0; for (uint256 i = 0; i < newRatios.length; i++) { totalRatio += newRatios[i]; } require(totalRatio == DIVISOR, "Invalid ratio sum"); _splitRatio = newRatios; } function getBalance(address token) internal view returns (uint256) { return token == SONIC_COIN ? address(this).balance : IERC20(token).balanceOf(address(this)); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.28; import {Enums} from "./lib/Enums.sol"; import {Types} from "./lib/Types.sol"; import {Params} from "./lib/Params.sol"; import {IStrategy} from "./interfaces/IStrategy.sol"; import {MultiTokenPool} from "./pool/MultiTokenPool.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {IFactory} from "./interfaces/IFactory.sol"; import {IRevenue} from "./interfaces/IRevenue.sol"; contract Strategy is MultiTokenPool, IStrategy { uint256 internal _forkCost; Enums.Visibility internal _visibility; constructor( address factory_, address creator_, Enums.Visibility visibility_, uint256 depositUsdMin_, uint256 forkCost_, address[] memory initialTokens_, uint256[] memory initialSplitRatio_, Enums.ActionCall[] memory allowedActions_ ) MultiTokenPool( factory_, creator_, depositUsdMin_, initialTokens_, initialSplitRatio_, allowedActions_ ) { _visibility = visibility_; _forkCost = forkCost_; } function onFork() external payable override onlyFactor { require(_visibility == Enums.Visibility.Public, "Disallowed"); require(_forkCost <= msg.value, "Insufficient fork cost"); IRevenue(IFactory(_factory).getRevenueAddress()).fund{value: msg.value}( owner() ); } function executeCall( Params.ExecuteCall memory call ) external override onlyEdger { require(_isAllowedAction(call.action), "Action not allowed"); if (call.action == Enums.ActionCall.AdjustSplitRatio) { uint256[] memory ratio = abi.decode(call.data, (uint256[])); super._adjustSplitRatio(ratio); } if (call.action == Enums.ActionCall.SwapToSingle) { (address[] memory tokensIn, address tokenOut) = abi.decode( call.data, (address[], address) ); super._swapToSingle(tokensIn, tokenOut); } if (call.action == Enums.ActionCall.SwapToMany) { (address tokenIn, address[] memory tokensOut) = abi.decode( call.data, (address, address[]) ); super._swapToMany(tokenIn, tokensOut); } emit ExecuteCalled(call); } //////////////////////////////////////////////// //// INTERNAL FUNCTIONS //// //////////////////////////////////////////////// function _isAllowedAction( Enums.ActionCall action ) internal view returns (bool allowed) { allowed = false; for (uint i = 0; i < _allowedActions.length; i++) { if (_allowedActions[i] == action) { allowed = true; break; } } } //////////////////////////////////////////////// //// VIEW FUNCTIONS //// //////////////////////////////////////////////// function creator() external view override returns (address) { return owner(); } function factory() external view override returns (address) { return _factory; } function getForkCost() external view override returns (uint256) { return _forkCost; } //////////////////////////////////////////////// //// MODIFIERS //// //////////////////////////////////////////////// modifier onlyFactor() { require(msg.sender == _factory, "Only factory is allowed"); _; } modifier onlyEdger() { require( msg.sender == IFactory(_factory).edger(), "Only edger is allowed" ); _; } }
{ "viaIR": true, "optimizer": { "enabled": true, "runs": 1000 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"revenue_","type":"address"},{"internalType":"address","name":"dataFeed_","type":"address"},{"internalType":"address","name":"swapRouter_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"strategy","type":"address"},{"indexed":false,"internalType":"address","name":"creator","type":"address"},{"indexed":false,"internalType":"address[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"splitRatio","type":"uint256[]"},{"indexed":false,"internalType":"enum Enums.Visibility","name":"visibility","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"depositUsdMin","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"forkCost","type":"uint256"},{"indexed":false,"internalType":"enum Enums.ActionCall[]","name":"allowedActions","type":"uint8[]"}],"name":"StrategyCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"base","type":"address"},{"indexed":false,"internalType":"address","name":"fork","type":"address"},{"indexed":false,"internalType":"address","name":"forker","type":"address"}],"name":"StrategyForked","type":"event"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"splitRatio","type":"uint256[]"},{"internalType":"enum Enums.Visibility","name":"visibility","type":"uint8"},{"internalType":"uint256","name":"depositUsdMin","type":"uint256"},{"internalType":"uint256","name":"forkCost","type":"uint256"},{"internalType":"enum Enums.ActionCall[]","name":"allowedActions","type":"uint8[]"}],"name":"createStrategy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"edger","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"strategy","type":"address"}],"name":"forkStrategy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getPriceOracleAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRevenueAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSwapRouterAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60803460a357601f61533638819003918201601f19168301916001600160401b0383118484101760a85780849260609460405283398101031260a35760428160be565b906057604060516020840160be565b920160be565b600080546001600160a01b039485166001600160a01b03199182161790915560018054938516938216939093179092556002805491909316911617905560405161526490816100d28239f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b038216820360a35756fe608080604052600436101561001357600080fd5b600090813560e01c90816364f079e1146103ea5750806378d1c86d146103c45780638403ef08146100e25780638b5350cc146100bb578063f5c8ba93146100945763f94f657c1461006357600080fd5b346100915780600319360112610091576020604051733e646e062f05e01e1860ea53a6dc81e7e9162de68152f35b80fd5b503461009157806003193601126100915760206001600160a01b0360025416604051908152f35b503461009157806003193601126100915760206001600160a01b0360015416604051908152f35b50346100915760c0366003190112610091576004359067ffffffffffffffff82116100915736602383011215610091578160040135610120816108cb565b9261012e6040519485610893565b8184526024602085019260051b8201019036821161039057602401915b8183106103a4575050506024359067ffffffffffffffff8211610091573660238301121561009157816004013591610182836108cb565b926101906040519485610893565b8084526024602085019160051b8301019136831161039057602401905b82821061039457505050604435906002821015610091576064356084359060a4359267ffffffffffffffff841161009157366023850112156100915783600401356101f7816108cb565b946102056040519687610893565b8186526024602087019260051b8201019036821161039057602401915b818310610373575050506040516148758082019082821067ffffffffffffffff83111761035f5782916102ac916109ba843930815233602082015261026a604082018a6108e3565b85606082015286608082015261010060a082015261029d61028f61010083018d610906565b82810360c08401528b610943565b9060e081830391015287610977565b039082f09081156103535750936103189360209793610348936103316103266001600160a01b037f7c752b9113b23f79161cc728ca055e06564fd3019bfc3663d04ad659cc7082649a169a604051998a998d8b52338f8c015261010060408c01526101008b0190610906565b9089820360608b0152610943565b9460808801906108e3565b60a086015260c085015283820360e0850152610977565b0390a1604051908152f35b604051903d90823e3d90fd5b602484634e487b7160e01b81526041600452fd5b8235600481101561038c57815260209283019201610222565b8480fd5b8380fd5b81358152602091820191016101ad565b82356001600160a01b038116810361038c5781526020928301920161014b565b50346100915780600319360112610091576001600160a01b036020915416604051908152f35b9050602036600319011261088f57600435906001600160a01b038216809203610633577f8e4e9018000000000000000000000000000000000000000000000000000000008152602081600481855afa908115610884578391610852575b50604051907faa6ca8080000000000000000000000000000000000000000000000000000000082528382600481865afa9182156106285784926107ae575b506040517f4eadcca80000000000000000000000000000000000000000000000000000000081528481600481875afa9081156107a357859161070e575b50604051907f2494452d0000000000000000000000000000000000000000000000000000000082528582600481885afa918215610703578692610656575b5060405193614875938486019486861067ffffffffffffffff871117610642579261056361057f9593610571938998966109ba8a393087523360208801526001604088015260608701528a608087015261010060a0870152610100860190610906565b9084820360c0860152610943565b9160e0818403910152610977565b039083f0801561063757813b15610633576040517f8769b449000000000000000000000000000000000000000000000000000000008152838160048134875af1801561062857916020946060927fd41cbc93f20efdc0e7c08e245f3f4b52a335efa799019f8e94b49bff570b28b494610618575b50506001600160a01b03604051918583521685820152336040820152a1604051908152f35b8161062291610893565b386105f3565b6040513d86823e3d90fd5b8280fd5b6040513d84823e3d90fd5b602489634e487b7160e01b81526041600452fd5b9091503d8087833e6106688183610893565b8101906020818303126106fb5780519067ffffffffffffffff82116106ff57019080601f830112156106fb578151906106a0826108cb565b926106ae6040519485610893565b82845260208085019360051b8201019182116106f757602001915b8183106106da575050509038610500565b825160048110156106f3578152602092830192016106c9565b8980fd5b8880fd5b8680fd5b8780fd5b6040513d88823e3d90fd5b90503d8086833e61071f8183610893565b81019060208183031261079f5780519067ffffffffffffffff82116106fb57019080601f8301121561079f578151610756816108cb565b926107646040519485610893565b81845260208085019260051b8201019283116106ff57602001905b82821061078f57505050386104c2565b815181526020918201910161077f565b8580fd5b6040513d87823e3d90fd5b9091503d8085833e6107c08183610893565b81019060208183031261038c5780519067ffffffffffffffff821161079f57019080601f8301121561038c578151906107f8826108cb565b926108066040519485610893565b82845260208085019360051b8201019182116106fb57602001915b818310610832575050509038610485565b82516001600160a01b03811681036106ff57815260209283019201610821565b90506020813d60201161087c575b8161086d60209383610893565b81010312610633575138610447565b3d9150610860565b6040513d85823e3d90fd5b5080fd5b90601f8019910116810190811067ffffffffffffffff8211176108b557604052565b634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff81116108b55760051b60200190565b9060028210156108f05752565b634e487b7160e01b600052602160045260246000fd5b906020808351928381520192019060005b8181106109245750505090565b82516001600160a01b0316845260209384019390920191600101610917565b906020808351928381520192019060005b8181106109615750505090565b8251845260209384019390920191600101610954565b90602080835192838152019201906000905b8082106109965750505090565b90919283519060048210156108f05760208160019382935201940192019061098956fe60c0806040523461077d57614875803803809161001c82856109dc565b833981016101008282031261077d57610034826109ff565b90610041602084016109ff565b91604084015192600284101561077d5760608501519260808601519560a081015160018060401b03811161077d5781019482601f8701121561077d5785519061008982610a13565b9661009760405198896109dc565b828852602088016020819460051b8301019186831161077d57602001905b8282106109c45750505060c08301516001600160401b03811161077d5783019584601f8801121561077d578651936100ec85610a13565b976100fa604051998a6109dc565b858952602089016020819760051b8301019188831161077d57602001905b8282106109b45750505060e0810151906001600160401b03821161077d57019585601f8801121561077d5786519661014f88610a13565b9661015d60405198896109dc565b88885260208801916020839a60051b82010191821161077d57602001915b81831061099b575050506040516101936040826109dc565b600781526626282a37b5b2b760c91b6020820152604051906101b66040836109dc565b600282526104c560f41b60208301528051906001600160401b03821161068e5760035490600182811c92168015610991575b60208310146108af5781601f849311610942575b50602090601f83116001146108da576000926108cf575b50508160011b916000199060031b1c1916176003555b8051906001600160401b03821161068e5760045490600182811c921680156108c5575b60208310146108af5781601f849311610855575b50602090601f83116001146107ed576000926107e2575b50508160011b916000199060031b1c1916176004555b6001600160a01b031680156107cc57600a80546001600160a01b03198116831790915560405191906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a38851885103610796575060a081905260405163f5c8ba9360e01b815290602090829060049082906001600160a01b03165afa90811561078a5760009161074b575b506001600160a01b03166080526005558551906001600160401b03821161068e5768010000000000000000821161068e5760075482600755808310610710575b506007600052602060002060005b8381106106f35750508551929150506001600160401b03821161068e5768010000000000000000821161068e57600654826006558083106106b8575b506006600052602060002060005b8381106106a45750509151929150506001600160401b03821161068e5768010000000000000000821161068e576008548260085580831061063d575b5090600860005260206000208160051c9160005b8381106105f05750601f198116900380610588575b505050506000936000945b82518610156104955761043f8684610a41565b51810180911161047f57946001906001600160a01b0361045f8287610a41565b5116600052600960205260406000208260ff19825416179055019461042c565b634e487b7160e01b600052601160045260246000fd5b61271085910361054f5760ff8019600c5416911617600c55600b55604051613e099081610a6c8239608051818181610287015281816102f10152818161043a015281816104aa01528181610c6601528181610cd001528181610d6f01528181610dfe01528181610ee601528181611603015281816139e601528181613a6901528181613b0701528181613b810152613c46015260a0518181816108520152818161097001528181611a4b0152818161200b01526122690152f35b60405162461bcd60e51b8152602060048201526011602482015270496e76616c696420726174696f2073756d60781b6044820152606490fd5b9260009360005b8181106105a457505050015538808080610421565b909194855160048110156105da576105d0602091846001949060ff809160031b9316831b921b19161790565b960192910161058f565b634e487b7160e01b600052602160045260246000fd5b6000805b6020811061060957508382015560010161040c565b9590815160048110156105da57610634602091896001949060ff809160031b9316831b921b19161790565b920196016105f4565b61066b9060086000526020600020601f80860160051c82019281871680610671575b500160051c0190610a2a565b386103f8565b6000198501908154906000199060200360031b1c1690553861065f565b634e487b7160e01b600052604160045260246000fd5b6001906020845194019381840155016103bc565b60066000526106ed907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f908101908401610a2a565b386103ae565b82516001600160a01b031681830155602090920191600101610372565b6007600052610745907fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688908101908401610a2a565b38610364565b90506020813d602011610782575b81610766602093836109dc565b8101031261077d57610777906109ff565b38610324565b600080fd5b3d9150610759565b6040513d6000823e3d90fd5b62461bcd60e51b81526020600482015260116024820152704d69736d6174636865642061727261797360781b6044820152606490fd5b631e4fbdf760e01b600052600060045260246000fd5b015190503880610277565b600460009081528281209350601f198516905b81811061083d5750908460019594939210610824575b505050811b0160045561028d565b015160001960f88460031b161c19169055388080610816565b92936020600181928786015181550195019301610800565b600460005261089f907f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b601f850160051c810191602086106108a5575b601f0160051c0190610a2a565b38610260565b9091508190610892565b634e487b7160e01b600052602260045260246000fd5b91607f169161024c565b015190503880610213565b600360009081528281209350601f198516905b81811061092a5750908460019594939210610911575b505050811b01600355610229565b015160001960f88460031b161c19169055388080610903565b929360206001819287860151815501950193016108ed565b600360005261098b907fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b601f850160051c810191602086106108a557601f0160051c0190610a2a565b386101fc565b91607f16916101e8565b8251600481101561077d5781526020928301920161017b565b8151815260209182019101610118565b602080916109d1846109ff565b8152019101906100b5565b601f909101601f19168101906001600160401b0382119082101761068e57604052565b51906001600160a01b038216820361077d57565b6001600160401b03811161068e5760051b60200190565b818110610a35575050565b60008155600101610a2a565b8051821015610a555760209160051b010190565b634e487b7160e01b600052603260045260246000fdfe6080604052600436101561001b575b361561001957600080fd5b005b6000803560e01c8062113e0814612fa957806302d05d3f14611a0e57806306fdde0314612eec578063095ea7b314612e4457806318160ddd14612e2657806323b872dd14612d255780632494452d146125385780632e1a7d4d14612430578063313ce5671461241457806347e7ef24146122045780634eadcca814612183578063531bcdb3146121655780635358fbda14611f9f5780635fa7b58414611d1457806370a0823114611cdd578063715018a614611c755780638769b44914611a355780638da5cb5b14611a0e5780638e4e9018146119f057806395d89b41146118e3578063a216aa06146115a1578063a9059cbb1461156f578063aa6ca808146114d9578063ab83f98a14611449578063af81c5b91461130f578063b317650b14610876578063c45a015514610832578063dd62ed3e146107e2578063e69d849d146106ee578063f2fde38b146106415763f9c4d3db1461017b575061000e565b3461063e57604036600319011261063e576101946130b0565b6024356101a281151561322a565b6001600160a01b0382169081845260096020526101c560ff604086205416613596565b600254926101d4841515613275565b6040926060919073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81149087805b600754811015610630576001600160a01b03610211826131ad565b90549060031b1c166102348a61022f8a61022a856135e1565b6132c0565b6132e9565b906040516102428982613141565b600281528a36602083013773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8214801561062a576040516315ab88c960e31b81526020816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa9081156105e05787916105f1575b505b6001600160a01b036102ca846131f9565b9116905287156105eb576040516315ab88c960e31b81526020816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa9081156105e05787916105a3575b505b6001600160a01b0361033484613206565b91169052828714808061059c575b1561036e575050505082808060019561036694335af1610360613321565b50613351565b0188906101f6565b929392156103ef57505060405163a9059cbb60e01b815233600482015260248101919091529260209184916044918391905af19182156103e4576001926103b6575b50610366565b6103d69060203d81116103dd575b6103ce8183613141565b810190613309565b50386103b0565b503d6103c4565b6040513d8c823e3d90fd5b939450929091901561049f5750600142019182421161048b57918b9161042e9493604051809681948293637ff36ab560e01b84523390600485016138d9565b03916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af19182156103e4576001926104705750610366565b6103d6903d808d833e6104838183613141565b8101906134b7565b60248c634e487b7160e01b81526011600452fd5b906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169160208d6040519283809263095ea7b360e01b825281610504888a60048401602090939291936001600160a01b0360408201951681520152565b03925af1801561059157610575575b50600142019283421161056157916105499493918d8094604051978895869485936338ed173960e01b85523391600486016138a0565b03925af19182156103e4576001926104705750610366565b60248d634e487b7160e01b81526011600452fd5b61058c9060203d81116103dd576103ce8183613141565b610513565b6040513d8f823e3d90fd5b5088610342565b90506020813d82116105d8575b816105bd60209383613141565b810103126105d4576105ce906133e7565b38610321565b8680fd5b3d91506105b0565b6040513d89823e3d90fd5b88610323565b90506020813d8211610622575b8161060b60209383613141565b810103126105d45761061c906133e7565b386102b7565b3d91506105fe565b826102b9565b5061063b8633613772565b80f35b80fd5b503461063e57602036600319011261063e576001600160a01b036106636130b0565b61066b6137f3565b1680156106c2576001600160a01b03600a548273ffffffffffffffffffffffffffffffffffffffff19821617600a55167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b6024827f1e4fbdf700000000000000000000000000000000000000000000000000000000815280600452fd5b503461063e57604036600319011261063e576107086130b0565b6024356001600160a01b03821690818452600960205261072e60ff604086205416613596565b6040516323b872dd60e01b815233600482015230602482015260448101829052916020908390606490829088905af19081156107d7577f16e2dd942e4846acb6770151f8c5ed72a9949242b893bb783112d656ab171f74926107b4926107ba575b50604051918291339583602090939291936001600160a01b0360408201951681520152565b0390a280f35b6107d29060203d6020116103dd576103ce8183613141565b61078f565b6040513d86823e3d90fd5b503461063e57604036600319011261063e576001600160a01b0360406108066130b0565b92826108106130cb565b9416815260016020522091166000526020526020604060002054604051908152f35b503461063e578060031936011261063e5760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461063e57602036600319011261063e5760043567ffffffffffffffff811161130b576040600319823603011261130b57604051906040820182811067ffffffffffffffff8211176112f7576040528060040135600481101561102457825260248101359067ffffffffffffffff8211611024570136602382011215611028578260048201359161090783613179565b926109156040519485613141565b808452366024838301011161102857806024602093018386013783010152602082019081526040517ff94f657c0000000000000000000000000000000000000000000000000000000081526020816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa80156107d75784906112b7575b6001600160a01b039150163303611273578151916004831015928361125f576008549385805b8681101561125357600888528260ff8260051c7ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee3015460f88460031b161c169061123f57600481101561123f578414610a20576001016109c5565b5050505090915060015b156111fb5780516004811015610b49571561102c575b80516004811015610b4957600114610b5d575b80516004811015610b4957600214610abb575b610aa490610ab57f2dbb4029cc94c05452861994b3d66ab5d4b3f2b45418116b370c7981f2eebb9093604051938493602085526020850190516130e1565b51604080840152606083019061306f565b0390a180f35b8151908151820191604081840312610b4557610ad9602082016133e7565b9360408201519167ffffffffffffffff83116105d4577f2dbb4029cc94c05452861994b3d66ab5d4b3f2b45418116b370c7981f2eebb90956001600160a01b03610b34610b3b936020610ab59781610aa49b01920101613531565b911661390b565b9350509050610a66565b8480fd5b602484634e487b7160e01b81526021600452fd5b9091825191825183016040848203126110285760208401519067ffffffffffffffff8211611024576040610ba76001600160a01b0393602080610bae959997990191870101613531565b93016133e7565b168083526009602052610bc760ff604085205416613596565b60609460409273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee831491855b8251811015611016576001600160a01b03610c028285613216565b5116610c0d816135e1565b801561100c5760405191610c218c84613141565b600283528836602085013773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81148015611006576040516315ab88c960e31b81526020816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa908115610fbc578c91610fcd575b505b6001600160a01b03610ca9866131f9565b911690528715610fc7576040516315ab88c960e31b81526020816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa908115610fbc578c91610f7f575b505b6001600160a01b03610d1386613206565b91169052818903610d2c57505050506001905b01610be7565b15610de057506001420191824211610dcc57918991610d6393604051809581948293637ff36ab560e01b84523090600485016138d9565b03916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af18015610dc1579060019291610da7575b50610d26565b610dba903d808b833e6104838183613141565b5038610da1565b6040513d8a823e3d90fd5b60248a634e487b7160e01b81526011600452fd5b908615610ecf5760405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016600482018190526024820183905292602090829060449082908f905af18015610ec457610ea8575b506001420192834211610e945791610e7b93918b8094604051968795869485936318cbafe560e01b85523091600486016138a0565b03925af18015610dc1579060019291610da75750610d26565b60248b634e487b7160e01b81526011600452fd5b610ebf9060203d81116103dd576103ce8183613141565b610e46565b6040513d8d823e3d90fd5b60405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016600482018190526024820183905292602090829060449082908f905af18015610ec457610f63575b506001420192834211610e945791610e7b93918b8094604051968795869485936338ed173960e01b85523091600486016138a0565b610f7a9060203d81116103dd576103ce8183613141565b610f2e565b90506020813d8211610fb4575b81610f9960209383613141565b81010312610fb057610faa906133e7565b38610d00565b8b80fd5b3d9150610f8c565b6040513d8e823e3d90fd5b88610d02565b90506020813d8211610ffe575b81610fe760209383613141565b81010312610fb057610ff8906133e7565b38610c96565b3d9150610fda565b81610c98565b5050600190610d26565b509594965050505050610a53565b8380fd5b8280fd5b906110418151602080825183010191016134b7565b8051600754036111b7578391825b82518410156110775761106f6001916110688686613216565b5190613893565b93019261104f565b61271091949350036111735780519067ffffffffffffffff821161115f5768010000000000000000821161115f5760065482600655808310611101575b5060200160068552845b8281106110cd57505050610a40565b60019060208351930192817ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f0155016110be565b7ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01827ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f015b81811061115457506110b4565b868155600101611147565b602485634e487b7160e01b81526041600452fd5b606460405162461bcd60e51b815260206004820152601160248201527f496e76616c696420726174696f2073756d0000000000000000000000000000006044820152fd5b606460405162461bcd60e51b815260206004820152600e60248201527f496e76616c6964206c656e6774680000000000000000000000000000000000006044820152fd5b606460405162461bcd60e51b815260206004820152601260248201527f416374696f6e206e6f7420616c6c6f77656400000000000000000000000000006044820152fd5b602489634e487b7160e01b81526021600452fd5b50929394505050610a2a565b602485634e487b7160e01b81526021600452fd5b606460405162461bcd60e51b815260206004820152601560248201527f4f6e6c7920656467657220697320616c6c6f77656400000000000000000000006044820152fd5b506020813d6020116112ef575b816112d160209383613141565b81010312611024576112ea6001600160a01b03916133e7565b61099f565b3d91506112c4565b602484634e487b7160e01b81526041600452fd5b5080fd5b503461063e57604036600319011261063e576113296130b0565b6113316137f3565b6001600160a01b03811690818352600960205260ff60408420541661140557600754680100000000000000008110156112f7579061137882600161139794016007556131ad565b9091906001600160a01b038084549260031b9316831b921b1916179055565b600654680100000000000000008110156113f1576113be8160016113d893016006556131de565b6024359082549060031b91821b91600019901b1916179055565b8152600960205260408120805460ff1916600117905580f35b602483634e487b7160e01b81526041600452fd5b606460405162461bcd60e51b815260206004820152600c60248201527f546f6b656e2065786973747300000000000000000000000000000000000000006044820152fd5b50602036600319011261063e5760043573eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8252600960205261148560ff60408420541661339c565b61149081341461346c565b6040519073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee825260208201527f16e2dd942e4846acb6770151f8c5ed72a9949242b893bb783112d656ab171f7460403392a280f35b503461063e578060031936011261063e5760405180916020600754928381520191600782527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688915b8181106115505761154c8561153881870382613141565b604051918291602083526020830190613104565b0390f35b82546001600160a01b0316845260209093019260019283019201611521565b503461063e57604036600319011261063e5761159661158c6130b0565b602435903361367b565b602060405160018152f35b503461063e57602036600319011261063e576004356115c181151561322a565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee825260096020526115ed60ff604084205416613596565b600254906115fc821515613275565b60409060607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031685805b6007548110156118d8576001600160a01b03611649826131ad565b90549060031b1c166116628861022f8861022a856135e1565b906040516116708782613141565b600281528836602083013773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee821480156118d2576040516315ab88c960e31b81526020816004818b5afa9081156105e0578791611899575b505b6001600160a01b036116cf846131f9565b911690526040516315ab88c960e31b81526020816004818b5afa9081156105e0578791611860575b506001600160a01b0361170984613206565b911690528080611858575b156117395750505082808060019561173194335af1610360613321565b01869061162e565b9192911561179e575060405163a9059cbb60e01b815233600482015260248101919091529260209184916044918391905af1918215610dc157600192611780575b50611731565b6117979060203d81116103dd576103ce8183613141565b503861177a565b60405163095ea7b360e01b81526001600160a01b0387166004820152602481018390529094509091602090829060449082908e905af180156103e45761183c575b506001420192834211610dcc5790899161180f60405195869384936338ed173960e01b85523391600486016138a0565b038183875af1918215610dc1576001926118295750611731565b611797903d808b833e6104838183613141565b6118539060203d81116103dd576103ce8183613141565b6117df565b506001611714565b90506020813d8211611891575b8161187a60209383613141565b810103126105d45761188b906133e7565b386116f7565b3d915061186d565b90506020813d82116118ca575b816118b360209383613141565b810103126105d4576118c4906133e7565b386116bc565b3d91506118a6565b826116be565b5061063b8433613772565b503461063e578060031936011261063e576040519080600454908160011c916001811680156119e6575b6020841081146119d2578386529081156119ab575060011461194e575b61154c8461193a81860382613141565b60405191829160208352602083019061306f565b600481527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b939250905b8082106119915750909150810160200161193a8261192a565b919260018160209254838588010152019101909291611978565b60ff191660208087019190915292151560051b8501909201925061193a915083905061192a565b602483634e487b7160e01b81526022600452fd5b92607f169261190d565b503461063e578060031936011261063e576020600554604051908152f35b503461063e578060031936011261063e5760206001600160a01b03600a5416604051908152f35b508060031936011261063e576001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016803303611c315760ff600c54166002811015611c1d57611bd957600b543410611b95576020600491604051928380927f78d1c86d0000000000000000000000000000000000000000000000000000000082525afa8015611b8a578290611b4a575b6001600160a01b03915016816001600160a01b03600a5416823b1561130b5781906024604051809581937f23024408000000000000000000000000000000000000000000000000000000008352600483015234905af18015611b3d57611b2f5780f35b611b3891613141565b388180f35b50604051903d90823e3d90fd5b506020813d602011611b82575b81611b6460209383613141565b8101031261130b57611b7d6001600160a01b03916133e7565b611acc565b3d9150611b57565b6040513d84823e3d90fd5b606460405162461bcd60e51b815260206004820152601660248201527f496e73756666696369656e7420666f726b20636f7374000000000000000000006044820152fd5b606460405162461bcd60e51b815260206004820152600a60248201527f446973616c6c6f776564000000000000000000000000000000000000000000006044820152fd5b602483634e487b7160e01b81526021600452fd5b606460405162461bcd60e51b815260206004820152601760248201527f4f6e6c7920666163746f727920697320616c6c6f7765640000000000000000006044820152fd5b503461063e578060031936011261063e57611c8e6137f3565b806001600160a01b03600a5473ffffffffffffffffffffffffffffffffffffffff198116600a55167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b503461063e57602036600319011261063e5760406020916001600160a01b03611d046130b0565b1681528083522054604051908152f35b503461063e57602036600319011261063e576001600160a01b03611d366130b0565b611d3e6137f3565b16808252600960205260ff60408320541615611f5b576040516370a0823160e01b8152306004820152602081602481855afa908115611f50578391611f1e575b50611eda57815b60075480821015611ed457826001600160a01b03611da2846131ad565b90549060031b1c1614611db85750600101611d85565b6000198101908111611eac576001600160a01b03611dd8611de9926131ad565b90549060031b1c16611378836131ad565b6007548015611ec05760001901611dff816131ad565b6001600160a01b0382549160031b1b191690556007556006546000198101908111611eac5790611e41611e34611e5a936131de565b90549060031b1c916131de565b90919082549060031b91821b91600019901b1916179055565b6006548015611e985760001901611e70816131de565b8154906000199060031b1b19169055600655815260096020526040812060ff19815416905580f35b602483634e487b7160e01b81526031600452fd5b602484634e487b7160e01b81526011600452fd5b602484634e487b7160e01b81526031600452fd5b50505080f35b606460405162461bcd60e51b815260206004820152601060248201527f4e6f6e2d7a65726f2062616c616e6365000000000000000000000000000000006044820152fd5b90506020813d602011611f48575b81611f3960209383613141565b81010312611028575138611d7e565b3d9150611f2c565b6040513d85823e3d90fd5b606460405162461bcd60e51b815260206004820152600f60248201527f546f6b656e206e6f7420666f756e6400000000000000000000000000000000006044820152fd5b50602036600319011261063e57600435611fb76137f3565b611fc281341461346c565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee82526009602052611fee60ff60408420541661339c565b6040516322d4d43360e21b81526020816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa908115611f50578391612120575b5060206001600160a01b03916044604051809481936333fa33cb60e11b835287600484015273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6024840152165afa8015611f505783906120ec575b6120a3915061209d6005548210156133fb565b33613835565b6040519073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee825260208201527fcbc4a4091b012bb1329c38bbbb15455f5cac5aa3673da0a7f38cd61a4f49551760403392a280f35b506020813d602011612118575b8161210660209383613141565b81010312611028576120a3905161208a565b3d91506120f9565b90506020813d60201161215d575b8161213b60209383613141565b810103126110285760206121566001600160a01b03926133e7565b915061203b565b3d915061212e565b503461063e578060031936011261063e576020600b54604051908152f35b503461063e578060031936011261063e5760405180916020600654928381520191600682527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f915b8181106121ee5761154c856121e281870382613141565b60405191829182613035565b82548452602090930192600192830192016121cb565b503461063e57604036600319011261063e5761221e6130b0565b6024356122296137f3565b6001600160a01b038216808452600960205261224b60ff60408620541661339c565b604051916322d4d43360e21b83526020836004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa9283156123905785936123cf575b5060206001600160a01b03936044604051809681936333fa33cb60e11b8352866004840152876024840152165afa92831561239057859361239b575b506122e46005548410156133fb565b6040516323b872dd60e01b815233600482015230602482015260448101829052916020908390606490829089905af18015612390577fcbc4a4091b012bb1329c38bbbb15455f5cac5aa3673da0a7f38cd61a4f495517936107b49361234f92612373575b5033613835565b604051918291339583602090939291936001600160a01b0360408201951681520152565b61238b9060203d6020116103dd576103ce8183613141565b612348565b6040513d87823e3d90fd5b9092506020813d6020116123c7575b816123b760209383613141565b81010312610b45575191386122d5565b3d91506123aa565b92506020833d60201161240c575b816123ea60209383613141565b81010312610b455760206124056001600160a01b03946133e7565b9350612299565b3d91506123dd565b503461063e578060031936011261063e57602060405160128152f35b503461063e57602036600319011261063e5760043561245081151561322a565b6002549061245f821515613275565b82805b60075481101561252d576001600160a01b0361247d826131ad565b90549060031b1c166124968561022f8661022a856135e1565b9073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81036124d057508280806001956124c894335af1610360613321565b018390612462565b60405163a9059cbb60e01b81523360048201526024810192909252909260209184916044918391905af19182156123905760019261250f575b506124c8565b6125269060203d81116103dd576103ce8183613141565b5038612509565b5061063b8233613772565b503461063e578060031936011261063e576040518060206008549283815201918183600886527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee39286905b80601f830110612a9c5761269c945491818110612a81575b818110612a63575b818110612a45575b818110612a27575b818110612a0a575b8181106129ec575b8181106129ce575b8181106129b0575b818110612992575b818110612974575b818110612956575b818110612938575b81811061291a575b8181106128fc575b8181106128de575b8181106128c0575b8181106128a2575b818110612884575b818110612866575b818110612848575b81811061282a575b81811061280c575b8181106127ee575b8181106127d0575b8181106127b2575b818110612794575b818110612776575b818110612758575b81811061273a575b81811061271c575b8181106126fe575b106126e7575b509392930383613141565b604051928392602084019060208552518091526040840192915b8181106126c4575050500390f35b91935091602080826126d960019488516130e1565b0194019101918493926126b6565b906126f78160209360f81c6130e1565b0138612691565b9260208161271460019360ff8760f01c166130e1565b01930161268b565b9260208161273260019360ff8760e81c166130e1565b019301612683565b9260208161275060019360ff8760e01c166130e1565b01930161267b565b9260208161276e60019360ff8760d81c166130e1565b019301612673565b9260208161278c60019360ff8760d01c166130e1565b01930161266b565b926020816127aa60019360ff8760c81c166130e1565b019301612663565b926020816127c860019360ff8760c01c166130e1565b01930161265b565b926020816127e660019360ff8760b81c166130e1565b019301612653565b9260208161280460019360ff8760b01c166130e1565b01930161264b565b9260208161282260019360ff8760a81c166130e1565b019301612643565b9260208161284060019360ff8760a01c166130e1565b01930161263b565b9260208161285e60019360ff8760981c166130e1565b019301612633565b9260208161287c60019360ff8760901c166130e1565b01930161262b565b9260208161289a60019360ff8760881c166130e1565b019301612623565b926020816128b860019360ff8760801c166130e1565b01930161261b565b926020816128d660019360ff8760781c166130e1565b019301612613565b926020816128f460019360ff8760701c166130e1565b01930161260b565b9260208161291260019360ff8760681c166130e1565b019301612603565b9260208161293060019360ff8760601c166130e1565b0193016125fb565b9260208161294e60019360ff8760581c166130e1565b0193016125f3565b9260208161296c60019360ff8760501c166130e1565b0193016125eb565b9260208161298a60019360ff8760481c166130e1565b0193016125e3565b926020816129a860019360ff8760401c166130e1565b0193016125db565b926020816129c660019360ff8760381c166130e1565b0193016125d3565b926020816129e460019360ff8760301c166130e1565b0193016125cb565b92602081612a0260019360ff8760281c166130e1565b0193016125c3565b92602081612a1f60019360ff87851c166130e1565b0193016125bb565b92602081612a3d60019360ff8760181c166130e1565b0193016125b3565b92602081612a5b60019360ff8760101c166130e1565b0193016125ab565b92602081612a7960019360ff8760081c166130e1565b0193016125a3565b92602081612a9460019360ff87166130e1565b01930161259b565b916020919350610400600191612d178754612aba8360ff83166130e1565b612acc86840160ff8360081c166130e1565b612adf6040840160ff8360101c166130e1565b612af26060840160ff8360181c166130e1565b612b046080840160ff83891c166130e1565b612b1760a0840160ff8360281c166130e1565b612b2a60c0840160ff8360301c166130e1565b612b3d60e0840160ff8360381c166130e1565b612b51610100840160ff8360401c166130e1565b612b65610120840160ff8360481c166130e1565b612b79610140840160ff8360501c166130e1565b612b8d610160840160ff8360581c166130e1565b612ba1610180840160ff8360601c166130e1565b612bb56101a0840160ff8360681c166130e1565b612bc96101c0840160ff8360701c166130e1565b612bdd6101e0840160ff8360781c166130e1565b612bf1610200840160ff8360801c166130e1565b612c05610220840160ff8360881c166130e1565b612c19610240840160ff8360901c166130e1565b612c2d610260840160ff8360981c166130e1565b612c41610280840160ff8360a01c166130e1565b612c556102a0840160ff8360a81c166130e1565b612c696102c0840160ff8360b01c166130e1565b612c7d6102e0840160ff8360b81c166130e1565b612c91610300840160ff8360c01c166130e1565b612ca5610320840160ff8360c81c166130e1565b612cb9610340840160ff8360d01c166130e1565b612ccd610360840160ff8360d81c166130e1565b612ce1610380840160ff8360e01c166130e1565b612cf56103a0840160ff8360e81c166130e1565b612d096103c0840160ff8360f01c166130e1565b6103e083019060f81c6130e1565b019401920184929391612583565b503461063e57606036600319011261063e57612d3f6130b0565b612d476130cb565b604435916001600160a01b0381168085526001602052604085206001600160a01b03331686526020526040852054906000198210612d8c575b5050611596935061367b565b848210612df2578015612ddf573315612dcc576040868692611596985260016020528181206001600160a01b033316825260205220910390553880612d80565b602486634a1406b160e11b815280600452fd5b60248663e602df0560e01b815280600452fd5b60648686847ffb8f41b200000000000000000000000000000000000000000000000000000000835233600452602452604452fd5b503461063e578060031936011261063e576020600254604051908152f35b503461063e57604036600319011261063e57612e5e6130b0565b602435903315612ed9576001600160a01b0316918215612ec65760408291338152600160205281812085825260205220556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b80634a1406b160e11b6024925280600452fd5b60248363e602df0560e01b815280600452fd5b503461063e578060031936011261063e576040519080600354908160011c91600181168015612f9f575b6020841081146119d2578386529081156119ab5750600114612f425761154c8461193a81860382613141565b600381527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b939250905b808210612f855750909150810160200161193a8261192a565b919260018160209254838588010152019101909291612f6c565b92607f1692612f16565b503461063e578060031936011261063e57600754612fc681613195565b91612fd46040519384613141565b818352601f19612fe383613195565b013660208501375b818110613000576040518061154c8582613035565b806130246001600160a01b036130176001946131ad565b90549060031b1c166135e1565b61302e8286613216565b5201612feb565b602060408183019282815284518094520192019060005b8181106130595750505090565b825184526020938401939092019160010161304c565b919082519283825260005b84811061309b575050826000602080949584010152601f8019910116010190565b8060208092840101518282860101520161307a565b600435906001600160a01b03821682036130c657565b600080fd5b602435906001600160a01b03821682036130c657565b9060048210156130ee5752565b634e487b7160e01b600052602160045260246000fd5b906020808351928381520192019060005b8181106131225750505090565b82516001600160a01b0316845260209384019390920191600101613115565b90601f8019910116810190811067ffffffffffffffff82111761316357604052565b634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff811161316357601f01601f191660200190565b67ffffffffffffffff81116131635760051b60200190565b6007548110156131c857600760005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b6006548110156131c857600660005260206000200190600090565b8051156131c85760200190565b8051600110156131c85760400190565b80518210156131c85760209160051b010190565b1561323157565b606460405162461bcd60e51b815260206004820152600e60248201527f496e76616c696420616d6f756e740000000000000000000000000000000000006044820152fd5b1561327c57565b606460405162461bcd60e51b815260206004820152600c60248201527f4e6f206c697175696469747900000000000000000000000000000000000000006044820152fd5b818102929181159184041417156132d357565b634e487b7160e01b600052601160045260246000fd5b81156132f3570490565b634e487b7160e01b600052601260045260246000fd5b908160209103126130c6575180151581036130c65790565b3d1561334c573d9061333282613179565b916133406040519384613141565b82523d6000602084013e565b606090565b1561335857565b606460405162461bcd60e51b815260206004820152601360248201527f455448207472616e73666572206661696c6564000000000000000000000000006044820152fd5b156133a357565b606460405162461bcd60e51b815260206004820152601160248201527f455448206e6f7420737570706f727465640000000000000000000000000000006044820152fd5b51906001600160a01b03821682036130c657565b1561340257565b608460405162461bcd60e51b815260206004820152602260248201527f496e73756666696369656e74206465706f73697420616d6f756e7420696e207560448201527f73640000000000000000000000000000000000000000000000000000000000006064820152fd5b1561347357565b606460405162461bcd60e51b815260206004820152601460248201527f496e636f72726563742045544820616d6f756e740000000000000000000000006044820152fd5b6020818303126130c65780519067ffffffffffffffff82116130c657019080601f830112156130c65781516134eb81613195565b926134f96040519485613141565b81845260208085019260051b8201019283116130c657602001905b8282106135215750505090565b8151815260209182019101613514565b9080601f830112156130c657815161354881613195565b926135566040519485613141565b81845260208085019260051b8201019283116130c657602001905b82821061357e5750505090565b6020809161358b846133e7565b815201910190613571565b1561359d57565b606460405162461bcd60e51b815260206004820152600d60248201527f496e76616c696420746f6b656e000000000000000000000000000000000000006044820152fd5b6000906001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee810361360e5750504790565b6020602491604051928380926370a0823160e01b82523060048301525afa91821561366f57809261363e57505090565b9091506020823d602011613667575b8161365a60209383613141565b8101031261063e57505190565b3d915061364d565b604051903d90823e3d90fd5b6001600160a01b0316908115613743576001600160a01b03169182156137145760008281528060205260408120548281106136fa5791604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef958760209652828652038282205586815280845220818154019055604051908152a3565b60649363391434e360e21b83949352600452602452604452fd5b7fec442f0500000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b7f96c6fd1e00000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b6001600160a01b03168015613743576000918183528260205260408320548181106137da57817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef926020928587528684520360408620558060025403600255604051908152a3565b839263391434e360e21b60649552600452602452604452fd5b6001600160a01b03600a5416330361380757565b7f118cdaa7000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b6001600160a01b03169081156137145761385181600254613893565b6002557fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602060009284845283825260408420818154019055604051908152a3565b919082018092116132d357565b906138ce6080936001600160a01b03929796959784526000602085015260a0604085015260a0840190613104565b951660608201520152565b6001600160a01b036139006060939695949660008452608060208501526080840190613104565b951660408201520152565b906001600160a01b03821680600052600960205261393060ff60406000205416613596565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81149360008515613d6d5750475b8015613d65578351919491613967916132e9565b946060936040929060005b8151811015613d5a576001600160a01b0361398d8284613216565b5116908160005260096020526139aa60ff60406000205416613596565b604051916139b88984613141565b60028352863660208501378515613d54576040516315ab88c960e31b81526020816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa908115613b5957600091613d1b575b505b6001600160a01b03613a2a856131f9565b9116905273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8114908115613d15576040516315ab88c960e31b81526020816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa908115613b5957600091613cdc575b505b6001600160a01b03613aad86613206565b911690528803613ac35750600191505b01613972565b8515613b65575060014201918242116132d357613afa926000916040519485928392637ff36ab560e01b84523090600485016138d9565b03818d6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af1918215613b5957600192613b3e575b50613abd565b613b52903d806000833e6104838183613141565b5038613b38565b6040513d6000823e3d90fd5b15613c2f5760405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660048201819052602482018c9052929060208160448160008d5af18015613b5957613c13575b50600142018042116132d357613bfb938c60008094604051978895869485936318cbafe560e01b85523091600486016138a0565b03925af1918215613b5957600192613b3e5750613abd565b613c2a9060203d81116103dd576103ce8183613141565b613bc7565b60405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660048201819052602482018c9052929060208160448160008d5af18015613b5957613cc0575b50600142018042116132d357613bfb938c60008094604051978895869485936338ed173960e01b85523091600486016138a0565b613cd79060203d81116103dd576103ce8183613141565b613c8c565b906020823d8211613d0d575b81613cf560209383613141565b8101031261063e5750613d07906133e7565b38613a9a565b3d9150613ce8565b80613a9c565b906020823d8211613d4c575b81613d3460209383613141565b8101031261063e5750613d46906133e7565b38613a17565b3d9150613d27565b84613a19565b505050505050509050565b509350505050565b6040516370a0823160e01b8152306004820152602081602481875afa91821561366f578092613d9e575b5050613953565b9091506020823d602011613dcb575b81613dba60209383613141565b8101031261063e5750513880613d97565b3d9150613dad56fea26469706673582212203c3f4a32f13042b341519148a8715900a9db43fc2ffc692cb36fc3773c791bc964736f6c634300081c0033a264697066735822122055deecd749364ef91930e775f13a83b0812e157c064fcb7944d6508ed8b4882164736f6c634300081c00330000000000000000000000003f63e16d1cad611414719e063d3f7cd4ea039c53000000000000000000000000ed79079f86712d439f5d837da13bd5ed1568474e000000000000000000000000a6ad18c2ac47803e193f75c3677b14bf19b94883
Deployed Bytecode
0x608080604052600436101561001357600080fd5b600090813560e01c90816364f079e1146103ea5750806378d1c86d146103c45780638403ef08146100e25780638b5350cc146100bb578063f5c8ba93146100945763f94f657c1461006357600080fd5b346100915780600319360112610091576020604051733e646e062f05e01e1860ea53a6dc81e7e9162de68152f35b80fd5b503461009157806003193601126100915760206001600160a01b0360025416604051908152f35b503461009157806003193601126100915760206001600160a01b0360015416604051908152f35b50346100915760c0366003190112610091576004359067ffffffffffffffff82116100915736602383011215610091578160040135610120816108cb565b9261012e6040519485610893565b8184526024602085019260051b8201019036821161039057602401915b8183106103a4575050506024359067ffffffffffffffff8211610091573660238301121561009157816004013591610182836108cb565b926101906040519485610893565b8084526024602085019160051b8301019136831161039057602401905b82821061039457505050604435906002821015610091576064356084359060a4359267ffffffffffffffff841161009157366023850112156100915783600401356101f7816108cb565b946102056040519687610893565b8186526024602087019260051b8201019036821161039057602401915b818310610373575050506040516148758082019082821067ffffffffffffffff83111761035f5782916102ac916109ba843930815233602082015261026a604082018a6108e3565b85606082015286608082015261010060a082015261029d61028f61010083018d610906565b82810360c08401528b610943565b9060e081830391015287610977565b039082f09081156103535750936103189360209793610348936103316103266001600160a01b037f7c752b9113b23f79161cc728ca055e06564fd3019bfc3663d04ad659cc7082649a169a604051998a998d8b52338f8c015261010060408c01526101008b0190610906565b9089820360608b0152610943565b9460808801906108e3565b60a086015260c085015283820360e0850152610977565b0390a1604051908152f35b604051903d90823e3d90fd5b602484634e487b7160e01b81526041600452fd5b8235600481101561038c57815260209283019201610222565b8480fd5b8380fd5b81358152602091820191016101ad565b82356001600160a01b038116810361038c5781526020928301920161014b565b50346100915780600319360112610091576001600160a01b036020915416604051908152f35b9050602036600319011261088f57600435906001600160a01b038216809203610633577f8e4e9018000000000000000000000000000000000000000000000000000000008152602081600481855afa908115610884578391610852575b50604051907faa6ca8080000000000000000000000000000000000000000000000000000000082528382600481865afa9182156106285784926107ae575b506040517f4eadcca80000000000000000000000000000000000000000000000000000000081528481600481875afa9081156107a357859161070e575b50604051907f2494452d0000000000000000000000000000000000000000000000000000000082528582600481885afa918215610703578692610656575b5060405193614875938486019486861067ffffffffffffffff871117610642579261056361057f9593610571938998966109ba8a393087523360208801526001604088015260608701528a608087015261010060a0870152610100860190610906565b9084820360c0860152610943565b9160e0818403910152610977565b039083f0801561063757813b15610633576040517f8769b449000000000000000000000000000000000000000000000000000000008152838160048134875af1801561062857916020946060927fd41cbc93f20efdc0e7c08e245f3f4b52a335efa799019f8e94b49bff570b28b494610618575b50506001600160a01b03604051918583521685820152336040820152a1604051908152f35b8161062291610893565b386105f3565b6040513d86823e3d90fd5b8280fd5b6040513d84823e3d90fd5b602489634e487b7160e01b81526041600452fd5b9091503d8087833e6106688183610893565b8101906020818303126106fb5780519067ffffffffffffffff82116106ff57019080601f830112156106fb578151906106a0826108cb565b926106ae6040519485610893565b82845260208085019360051b8201019182116106f757602001915b8183106106da575050509038610500565b825160048110156106f3578152602092830192016106c9565b8980fd5b8880fd5b8680fd5b8780fd5b6040513d88823e3d90fd5b90503d8086833e61071f8183610893565b81019060208183031261079f5780519067ffffffffffffffff82116106fb57019080601f8301121561079f578151610756816108cb565b926107646040519485610893565b81845260208085019260051b8201019283116106ff57602001905b82821061078f57505050386104c2565b815181526020918201910161077f565b8580fd5b6040513d87823e3d90fd5b9091503d8085833e6107c08183610893565b81019060208183031261038c5780519067ffffffffffffffff821161079f57019080601f8301121561038c578151906107f8826108cb565b926108066040519485610893565b82845260208085019360051b8201019182116106fb57602001915b818310610832575050509038610485565b82516001600160a01b03811681036106ff57815260209283019201610821565b90506020813d60201161087c575b8161086d60209383610893565b81010312610633575138610447565b3d9150610860565b6040513d85823e3d90fd5b5080fd5b90601f8019910116810190811067ffffffffffffffff8211176108b557604052565b634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff81116108b55760051b60200190565b9060028210156108f05752565b634e487b7160e01b600052602160045260246000fd5b906020808351928381520192019060005b8181106109245750505090565b82516001600160a01b0316845260209384019390920191600101610917565b906020808351928381520192019060005b8181106109615750505090565b8251845260209384019390920191600101610954565b90602080835192838152019201906000905b8082106109965750505090565b90919283519060048210156108f05760208160019382935201940192019061098956fe60c0806040523461077d57614875803803809161001c82856109dc565b833981016101008282031261077d57610034826109ff565b90610041602084016109ff565b91604084015192600284101561077d5760608501519260808601519560a081015160018060401b03811161077d5781019482601f8701121561077d5785519061008982610a13565b9661009760405198896109dc565b828852602088016020819460051b8301019186831161077d57602001905b8282106109c45750505060c08301516001600160401b03811161077d5783019584601f8801121561077d578651936100ec85610a13565b976100fa604051998a6109dc565b858952602089016020819760051b8301019188831161077d57602001905b8282106109b45750505060e0810151906001600160401b03821161077d57019585601f8801121561077d5786519661014f88610a13565b9661015d60405198896109dc565b88885260208801916020839a60051b82010191821161077d57602001915b81831061099b575050506040516101936040826109dc565b600781526626282a37b5b2b760c91b6020820152604051906101b66040836109dc565b600282526104c560f41b60208301528051906001600160401b03821161068e5760035490600182811c92168015610991575b60208310146108af5781601f849311610942575b50602090601f83116001146108da576000926108cf575b50508160011b916000199060031b1c1916176003555b8051906001600160401b03821161068e5760045490600182811c921680156108c5575b60208310146108af5781601f849311610855575b50602090601f83116001146107ed576000926107e2575b50508160011b916000199060031b1c1916176004555b6001600160a01b031680156107cc57600a80546001600160a01b03198116831790915560405191906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a38851885103610796575060a081905260405163f5c8ba9360e01b815290602090829060049082906001600160a01b03165afa90811561078a5760009161074b575b506001600160a01b03166080526005558551906001600160401b03821161068e5768010000000000000000821161068e5760075482600755808310610710575b506007600052602060002060005b8381106106f35750508551929150506001600160401b03821161068e5768010000000000000000821161068e57600654826006558083106106b8575b506006600052602060002060005b8381106106a45750509151929150506001600160401b03821161068e5768010000000000000000821161068e576008548260085580831061063d575b5090600860005260206000208160051c9160005b8381106105f05750601f198116900380610588575b505050506000936000945b82518610156104955761043f8684610a41565b51810180911161047f57946001906001600160a01b0361045f8287610a41565b5116600052600960205260406000208260ff19825416179055019461042c565b634e487b7160e01b600052601160045260246000fd5b61271085910361054f5760ff8019600c5416911617600c55600b55604051613e099081610a6c8239608051818181610287015281816102f10152818161043a015281816104aa01528181610c6601528181610cd001528181610d6f01528181610dfe01528181610ee601528181611603015281816139e601528181613a6901528181613b0701528181613b810152613c46015260a0518181816108520152818161097001528181611a4b0152818161200b01526122690152f35b60405162461bcd60e51b8152602060048201526011602482015270496e76616c696420726174696f2073756d60781b6044820152606490fd5b9260009360005b8181106105a457505050015538808080610421565b909194855160048110156105da576105d0602091846001949060ff809160031b9316831b921b19161790565b960192910161058f565b634e487b7160e01b600052602160045260246000fd5b6000805b6020811061060957508382015560010161040c565b9590815160048110156105da57610634602091896001949060ff809160031b9316831b921b19161790565b920196016105f4565b61066b9060086000526020600020601f80860160051c82019281871680610671575b500160051c0190610a2a565b386103f8565b6000198501908154906000199060200360031b1c1690553861065f565b634e487b7160e01b600052604160045260246000fd5b6001906020845194019381840155016103bc565b60066000526106ed907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f908101908401610a2a565b386103ae565b82516001600160a01b031681830155602090920191600101610372565b6007600052610745907fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688908101908401610a2a565b38610364565b90506020813d602011610782575b81610766602093836109dc565b8101031261077d57610777906109ff565b38610324565b600080fd5b3d9150610759565b6040513d6000823e3d90fd5b62461bcd60e51b81526020600482015260116024820152704d69736d6174636865642061727261797360781b6044820152606490fd5b631e4fbdf760e01b600052600060045260246000fd5b015190503880610277565b600460009081528281209350601f198516905b81811061083d5750908460019594939210610824575b505050811b0160045561028d565b015160001960f88460031b161c19169055388080610816565b92936020600181928786015181550195019301610800565b600460005261089f907f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b601f850160051c810191602086106108a5575b601f0160051c0190610a2a565b38610260565b9091508190610892565b634e487b7160e01b600052602260045260246000fd5b91607f169161024c565b015190503880610213565b600360009081528281209350601f198516905b81811061092a5750908460019594939210610911575b505050811b01600355610229565b015160001960f88460031b161c19169055388080610903565b929360206001819287860151815501950193016108ed565b600360005261098b907fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b601f850160051c810191602086106108a557601f0160051c0190610a2a565b386101fc565b91607f16916101e8565b8251600481101561077d5781526020928301920161017b565b8151815260209182019101610118565b602080916109d1846109ff565b8152019101906100b5565b601f909101601f19168101906001600160401b0382119082101761068e57604052565b51906001600160a01b038216820361077d57565b6001600160401b03811161068e5760051b60200190565b818110610a35575050565b60008155600101610a2a565b8051821015610a555760209160051b010190565b634e487b7160e01b600052603260045260246000fdfe6080604052600436101561001b575b361561001957600080fd5b005b6000803560e01c8062113e0814612fa957806302d05d3f14611a0e57806306fdde0314612eec578063095ea7b314612e4457806318160ddd14612e2657806323b872dd14612d255780632494452d146125385780632e1a7d4d14612430578063313ce5671461241457806347e7ef24146122045780634eadcca814612183578063531bcdb3146121655780635358fbda14611f9f5780635fa7b58414611d1457806370a0823114611cdd578063715018a614611c755780638769b44914611a355780638da5cb5b14611a0e5780638e4e9018146119f057806395d89b41146118e3578063a216aa06146115a1578063a9059cbb1461156f578063aa6ca808146114d9578063ab83f98a14611449578063af81c5b91461130f578063b317650b14610876578063c45a015514610832578063dd62ed3e146107e2578063e69d849d146106ee578063f2fde38b146106415763f9c4d3db1461017b575061000e565b3461063e57604036600319011261063e576101946130b0565b6024356101a281151561322a565b6001600160a01b0382169081845260096020526101c560ff604086205416613596565b600254926101d4841515613275565b6040926060919073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81149087805b600754811015610630576001600160a01b03610211826131ad565b90549060031b1c166102348a61022f8a61022a856135e1565b6132c0565b6132e9565b906040516102428982613141565b600281528a36602083013773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8214801561062a576040516315ab88c960e31b81526020816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa9081156105e05787916105f1575b505b6001600160a01b036102ca846131f9565b9116905287156105eb576040516315ab88c960e31b81526020816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa9081156105e05787916105a3575b505b6001600160a01b0361033484613206565b91169052828714808061059c575b1561036e575050505082808060019561036694335af1610360613321565b50613351565b0188906101f6565b929392156103ef57505060405163a9059cbb60e01b815233600482015260248101919091529260209184916044918391905af19182156103e4576001926103b6575b50610366565b6103d69060203d81116103dd575b6103ce8183613141565b810190613309565b50386103b0565b503d6103c4565b6040513d8c823e3d90fd5b939450929091901561049f5750600142019182421161048b57918b9161042e9493604051809681948293637ff36ab560e01b84523390600485016138d9565b03916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af19182156103e4576001926104705750610366565b6103d6903d808d833e6104838183613141565b8101906134b7565b60248c634e487b7160e01b81526011600452fd5b906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169160208d6040519283809263095ea7b360e01b825281610504888a60048401602090939291936001600160a01b0360408201951681520152565b03925af1801561059157610575575b50600142019283421161056157916105499493918d8094604051978895869485936338ed173960e01b85523391600486016138a0565b03925af19182156103e4576001926104705750610366565b60248d634e487b7160e01b81526011600452fd5b61058c9060203d81116103dd576103ce8183613141565b610513565b6040513d8f823e3d90fd5b5088610342565b90506020813d82116105d8575b816105bd60209383613141565b810103126105d4576105ce906133e7565b38610321565b8680fd5b3d91506105b0565b6040513d89823e3d90fd5b88610323565b90506020813d8211610622575b8161060b60209383613141565b810103126105d45761061c906133e7565b386102b7565b3d91506105fe565b826102b9565b5061063b8633613772565b80f35b80fd5b503461063e57602036600319011261063e576001600160a01b036106636130b0565b61066b6137f3565b1680156106c2576001600160a01b03600a548273ffffffffffffffffffffffffffffffffffffffff19821617600a55167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b6024827f1e4fbdf700000000000000000000000000000000000000000000000000000000815280600452fd5b503461063e57604036600319011261063e576107086130b0565b6024356001600160a01b03821690818452600960205261072e60ff604086205416613596565b6040516323b872dd60e01b815233600482015230602482015260448101829052916020908390606490829088905af19081156107d7577f16e2dd942e4846acb6770151f8c5ed72a9949242b893bb783112d656ab171f74926107b4926107ba575b50604051918291339583602090939291936001600160a01b0360408201951681520152565b0390a280f35b6107d29060203d6020116103dd576103ce8183613141565b61078f565b6040513d86823e3d90fd5b503461063e57604036600319011261063e576001600160a01b0360406108066130b0565b92826108106130cb565b9416815260016020522091166000526020526020604060002054604051908152f35b503461063e578060031936011261063e5760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461063e57602036600319011261063e5760043567ffffffffffffffff811161130b576040600319823603011261130b57604051906040820182811067ffffffffffffffff8211176112f7576040528060040135600481101561102457825260248101359067ffffffffffffffff8211611024570136602382011215611028578260048201359161090783613179565b926109156040519485613141565b808452366024838301011161102857806024602093018386013783010152602082019081526040517ff94f657c0000000000000000000000000000000000000000000000000000000081526020816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa80156107d75784906112b7575b6001600160a01b039150163303611273578151916004831015928361125f576008549385805b8681101561125357600888528260ff8260051c7ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee3015460f88460031b161c169061123f57600481101561123f578414610a20576001016109c5565b5050505090915060015b156111fb5780516004811015610b49571561102c575b80516004811015610b4957600114610b5d575b80516004811015610b4957600214610abb575b610aa490610ab57f2dbb4029cc94c05452861994b3d66ab5d4b3f2b45418116b370c7981f2eebb9093604051938493602085526020850190516130e1565b51604080840152606083019061306f565b0390a180f35b8151908151820191604081840312610b4557610ad9602082016133e7565b9360408201519167ffffffffffffffff83116105d4577f2dbb4029cc94c05452861994b3d66ab5d4b3f2b45418116b370c7981f2eebb90956001600160a01b03610b34610b3b936020610ab59781610aa49b01920101613531565b911661390b565b9350509050610a66565b8480fd5b602484634e487b7160e01b81526021600452fd5b9091825191825183016040848203126110285760208401519067ffffffffffffffff8211611024576040610ba76001600160a01b0393602080610bae959997990191870101613531565b93016133e7565b168083526009602052610bc760ff604085205416613596565b60609460409273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee831491855b8251811015611016576001600160a01b03610c028285613216565b5116610c0d816135e1565b801561100c5760405191610c218c84613141565b600283528836602085013773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81148015611006576040516315ab88c960e31b81526020816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa908115610fbc578c91610fcd575b505b6001600160a01b03610ca9866131f9565b911690528715610fc7576040516315ab88c960e31b81526020816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa908115610fbc578c91610f7f575b505b6001600160a01b03610d1386613206565b91169052818903610d2c57505050506001905b01610be7565b15610de057506001420191824211610dcc57918991610d6393604051809581948293637ff36ab560e01b84523090600485016138d9565b03916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af18015610dc1579060019291610da7575b50610d26565b610dba903d808b833e6104838183613141565b5038610da1565b6040513d8a823e3d90fd5b60248a634e487b7160e01b81526011600452fd5b908615610ecf5760405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016600482018190526024820183905292602090829060449082908f905af18015610ec457610ea8575b506001420192834211610e945791610e7b93918b8094604051968795869485936318cbafe560e01b85523091600486016138a0565b03925af18015610dc1579060019291610da75750610d26565b60248b634e487b7160e01b81526011600452fd5b610ebf9060203d81116103dd576103ce8183613141565b610e46565b6040513d8d823e3d90fd5b60405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016600482018190526024820183905292602090829060449082908f905af18015610ec457610f63575b506001420192834211610e945791610e7b93918b8094604051968795869485936338ed173960e01b85523091600486016138a0565b610f7a9060203d81116103dd576103ce8183613141565b610f2e565b90506020813d8211610fb4575b81610f9960209383613141565b81010312610fb057610faa906133e7565b38610d00565b8b80fd5b3d9150610f8c565b6040513d8e823e3d90fd5b88610d02565b90506020813d8211610ffe575b81610fe760209383613141565b81010312610fb057610ff8906133e7565b38610c96565b3d9150610fda565b81610c98565b5050600190610d26565b509594965050505050610a53565b8380fd5b8280fd5b906110418151602080825183010191016134b7565b8051600754036111b7578391825b82518410156110775761106f6001916110688686613216565b5190613893565b93019261104f565b61271091949350036111735780519067ffffffffffffffff821161115f5768010000000000000000821161115f5760065482600655808310611101575b5060200160068552845b8281106110cd57505050610a40565b60019060208351930192817ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f0155016110be565b7ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01827ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f015b81811061115457506110b4565b868155600101611147565b602485634e487b7160e01b81526041600452fd5b606460405162461bcd60e51b815260206004820152601160248201527f496e76616c696420726174696f2073756d0000000000000000000000000000006044820152fd5b606460405162461bcd60e51b815260206004820152600e60248201527f496e76616c6964206c656e6774680000000000000000000000000000000000006044820152fd5b606460405162461bcd60e51b815260206004820152601260248201527f416374696f6e206e6f7420616c6c6f77656400000000000000000000000000006044820152fd5b602489634e487b7160e01b81526021600452fd5b50929394505050610a2a565b602485634e487b7160e01b81526021600452fd5b606460405162461bcd60e51b815260206004820152601560248201527f4f6e6c7920656467657220697320616c6c6f77656400000000000000000000006044820152fd5b506020813d6020116112ef575b816112d160209383613141565b81010312611024576112ea6001600160a01b03916133e7565b61099f565b3d91506112c4565b602484634e487b7160e01b81526041600452fd5b5080fd5b503461063e57604036600319011261063e576113296130b0565b6113316137f3565b6001600160a01b03811690818352600960205260ff60408420541661140557600754680100000000000000008110156112f7579061137882600161139794016007556131ad565b9091906001600160a01b038084549260031b9316831b921b1916179055565b600654680100000000000000008110156113f1576113be8160016113d893016006556131de565b6024359082549060031b91821b91600019901b1916179055565b8152600960205260408120805460ff1916600117905580f35b602483634e487b7160e01b81526041600452fd5b606460405162461bcd60e51b815260206004820152600c60248201527f546f6b656e2065786973747300000000000000000000000000000000000000006044820152fd5b50602036600319011261063e5760043573eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8252600960205261148560ff60408420541661339c565b61149081341461346c565b6040519073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee825260208201527f16e2dd942e4846acb6770151f8c5ed72a9949242b893bb783112d656ab171f7460403392a280f35b503461063e578060031936011261063e5760405180916020600754928381520191600782527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688915b8181106115505761154c8561153881870382613141565b604051918291602083526020830190613104565b0390f35b82546001600160a01b0316845260209093019260019283019201611521565b503461063e57604036600319011261063e5761159661158c6130b0565b602435903361367b565b602060405160018152f35b503461063e57602036600319011261063e576004356115c181151561322a565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee825260096020526115ed60ff604084205416613596565b600254906115fc821515613275565b60409060607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031685805b6007548110156118d8576001600160a01b03611649826131ad565b90549060031b1c166116628861022f8861022a856135e1565b906040516116708782613141565b600281528836602083013773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee821480156118d2576040516315ab88c960e31b81526020816004818b5afa9081156105e0578791611899575b505b6001600160a01b036116cf846131f9565b911690526040516315ab88c960e31b81526020816004818b5afa9081156105e0578791611860575b506001600160a01b0361170984613206565b911690528080611858575b156117395750505082808060019561173194335af1610360613321565b01869061162e565b9192911561179e575060405163a9059cbb60e01b815233600482015260248101919091529260209184916044918391905af1918215610dc157600192611780575b50611731565b6117979060203d81116103dd576103ce8183613141565b503861177a565b60405163095ea7b360e01b81526001600160a01b0387166004820152602481018390529094509091602090829060449082908e905af180156103e45761183c575b506001420192834211610dcc5790899161180f60405195869384936338ed173960e01b85523391600486016138a0565b038183875af1918215610dc1576001926118295750611731565b611797903d808b833e6104838183613141565b6118539060203d81116103dd576103ce8183613141565b6117df565b506001611714565b90506020813d8211611891575b8161187a60209383613141565b810103126105d45761188b906133e7565b386116f7565b3d915061186d565b90506020813d82116118ca575b816118b360209383613141565b810103126105d4576118c4906133e7565b386116bc565b3d91506118a6565b826116be565b5061063b8433613772565b503461063e578060031936011261063e576040519080600454908160011c916001811680156119e6575b6020841081146119d2578386529081156119ab575060011461194e575b61154c8461193a81860382613141565b60405191829160208352602083019061306f565b600481527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b939250905b8082106119915750909150810160200161193a8261192a565b919260018160209254838588010152019101909291611978565b60ff191660208087019190915292151560051b8501909201925061193a915083905061192a565b602483634e487b7160e01b81526022600452fd5b92607f169261190d565b503461063e578060031936011261063e576020600554604051908152f35b503461063e578060031936011261063e5760206001600160a01b03600a5416604051908152f35b508060031936011261063e576001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016803303611c315760ff600c54166002811015611c1d57611bd957600b543410611b95576020600491604051928380927f78d1c86d0000000000000000000000000000000000000000000000000000000082525afa8015611b8a578290611b4a575b6001600160a01b03915016816001600160a01b03600a5416823b1561130b5781906024604051809581937f23024408000000000000000000000000000000000000000000000000000000008352600483015234905af18015611b3d57611b2f5780f35b611b3891613141565b388180f35b50604051903d90823e3d90fd5b506020813d602011611b82575b81611b6460209383613141565b8101031261130b57611b7d6001600160a01b03916133e7565b611acc565b3d9150611b57565b6040513d84823e3d90fd5b606460405162461bcd60e51b815260206004820152601660248201527f496e73756666696369656e7420666f726b20636f7374000000000000000000006044820152fd5b606460405162461bcd60e51b815260206004820152600a60248201527f446973616c6c6f776564000000000000000000000000000000000000000000006044820152fd5b602483634e487b7160e01b81526021600452fd5b606460405162461bcd60e51b815260206004820152601760248201527f4f6e6c7920666163746f727920697320616c6c6f7765640000000000000000006044820152fd5b503461063e578060031936011261063e57611c8e6137f3565b806001600160a01b03600a5473ffffffffffffffffffffffffffffffffffffffff198116600a55167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b503461063e57602036600319011261063e5760406020916001600160a01b03611d046130b0565b1681528083522054604051908152f35b503461063e57602036600319011261063e576001600160a01b03611d366130b0565b611d3e6137f3565b16808252600960205260ff60408320541615611f5b576040516370a0823160e01b8152306004820152602081602481855afa908115611f50578391611f1e575b50611eda57815b60075480821015611ed457826001600160a01b03611da2846131ad565b90549060031b1c1614611db85750600101611d85565b6000198101908111611eac576001600160a01b03611dd8611de9926131ad565b90549060031b1c16611378836131ad565b6007548015611ec05760001901611dff816131ad565b6001600160a01b0382549160031b1b191690556007556006546000198101908111611eac5790611e41611e34611e5a936131de565b90549060031b1c916131de565b90919082549060031b91821b91600019901b1916179055565b6006548015611e985760001901611e70816131de565b8154906000199060031b1b19169055600655815260096020526040812060ff19815416905580f35b602483634e487b7160e01b81526031600452fd5b602484634e487b7160e01b81526011600452fd5b602484634e487b7160e01b81526031600452fd5b50505080f35b606460405162461bcd60e51b815260206004820152601060248201527f4e6f6e2d7a65726f2062616c616e6365000000000000000000000000000000006044820152fd5b90506020813d602011611f48575b81611f3960209383613141565b81010312611028575138611d7e565b3d9150611f2c565b6040513d85823e3d90fd5b606460405162461bcd60e51b815260206004820152600f60248201527f546f6b656e206e6f7420666f756e6400000000000000000000000000000000006044820152fd5b50602036600319011261063e57600435611fb76137f3565b611fc281341461346c565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee82526009602052611fee60ff60408420541661339c565b6040516322d4d43360e21b81526020816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa908115611f50578391612120575b5060206001600160a01b03916044604051809481936333fa33cb60e11b835287600484015273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6024840152165afa8015611f505783906120ec575b6120a3915061209d6005548210156133fb565b33613835565b6040519073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee825260208201527fcbc4a4091b012bb1329c38bbbb15455f5cac5aa3673da0a7f38cd61a4f49551760403392a280f35b506020813d602011612118575b8161210660209383613141565b81010312611028576120a3905161208a565b3d91506120f9565b90506020813d60201161215d575b8161213b60209383613141565b810103126110285760206121566001600160a01b03926133e7565b915061203b565b3d915061212e565b503461063e578060031936011261063e576020600b54604051908152f35b503461063e578060031936011261063e5760405180916020600654928381520191600682527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f915b8181106121ee5761154c856121e281870382613141565b60405191829182613035565b82548452602090930192600192830192016121cb565b503461063e57604036600319011261063e5761221e6130b0565b6024356122296137f3565b6001600160a01b038216808452600960205261224b60ff60408620541661339c565b604051916322d4d43360e21b83526020836004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa9283156123905785936123cf575b5060206001600160a01b03936044604051809681936333fa33cb60e11b8352866004840152876024840152165afa92831561239057859361239b575b506122e46005548410156133fb565b6040516323b872dd60e01b815233600482015230602482015260448101829052916020908390606490829089905af18015612390577fcbc4a4091b012bb1329c38bbbb15455f5cac5aa3673da0a7f38cd61a4f495517936107b49361234f92612373575b5033613835565b604051918291339583602090939291936001600160a01b0360408201951681520152565b61238b9060203d6020116103dd576103ce8183613141565b612348565b6040513d87823e3d90fd5b9092506020813d6020116123c7575b816123b760209383613141565b81010312610b45575191386122d5565b3d91506123aa565b92506020833d60201161240c575b816123ea60209383613141565b81010312610b455760206124056001600160a01b03946133e7565b9350612299565b3d91506123dd565b503461063e578060031936011261063e57602060405160128152f35b503461063e57602036600319011261063e5760043561245081151561322a565b6002549061245f821515613275565b82805b60075481101561252d576001600160a01b0361247d826131ad565b90549060031b1c166124968561022f8661022a856135e1565b9073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81036124d057508280806001956124c894335af1610360613321565b018390612462565b60405163a9059cbb60e01b81523360048201526024810192909252909260209184916044918391905af19182156123905760019261250f575b506124c8565b6125269060203d81116103dd576103ce8183613141565b5038612509565b5061063b8233613772565b503461063e578060031936011261063e576040518060206008549283815201918183600886527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee39286905b80601f830110612a9c5761269c945491818110612a81575b818110612a63575b818110612a45575b818110612a27575b818110612a0a575b8181106129ec575b8181106129ce575b8181106129b0575b818110612992575b818110612974575b818110612956575b818110612938575b81811061291a575b8181106128fc575b8181106128de575b8181106128c0575b8181106128a2575b818110612884575b818110612866575b818110612848575b81811061282a575b81811061280c575b8181106127ee575b8181106127d0575b8181106127b2575b818110612794575b818110612776575b818110612758575b81811061273a575b81811061271c575b8181106126fe575b106126e7575b509392930383613141565b604051928392602084019060208552518091526040840192915b8181106126c4575050500390f35b91935091602080826126d960019488516130e1565b0194019101918493926126b6565b906126f78160209360f81c6130e1565b0138612691565b9260208161271460019360ff8760f01c166130e1565b01930161268b565b9260208161273260019360ff8760e81c166130e1565b019301612683565b9260208161275060019360ff8760e01c166130e1565b01930161267b565b9260208161276e60019360ff8760d81c166130e1565b019301612673565b9260208161278c60019360ff8760d01c166130e1565b01930161266b565b926020816127aa60019360ff8760c81c166130e1565b019301612663565b926020816127c860019360ff8760c01c166130e1565b01930161265b565b926020816127e660019360ff8760b81c166130e1565b019301612653565b9260208161280460019360ff8760b01c166130e1565b01930161264b565b9260208161282260019360ff8760a81c166130e1565b019301612643565b9260208161284060019360ff8760a01c166130e1565b01930161263b565b9260208161285e60019360ff8760981c166130e1565b019301612633565b9260208161287c60019360ff8760901c166130e1565b01930161262b565b9260208161289a60019360ff8760881c166130e1565b019301612623565b926020816128b860019360ff8760801c166130e1565b01930161261b565b926020816128d660019360ff8760781c166130e1565b019301612613565b926020816128f460019360ff8760701c166130e1565b01930161260b565b9260208161291260019360ff8760681c166130e1565b019301612603565b9260208161293060019360ff8760601c166130e1565b0193016125fb565b9260208161294e60019360ff8760581c166130e1565b0193016125f3565b9260208161296c60019360ff8760501c166130e1565b0193016125eb565b9260208161298a60019360ff8760481c166130e1565b0193016125e3565b926020816129a860019360ff8760401c166130e1565b0193016125db565b926020816129c660019360ff8760381c166130e1565b0193016125d3565b926020816129e460019360ff8760301c166130e1565b0193016125cb565b92602081612a0260019360ff8760281c166130e1565b0193016125c3565b92602081612a1f60019360ff87851c166130e1565b0193016125bb565b92602081612a3d60019360ff8760181c166130e1565b0193016125b3565b92602081612a5b60019360ff8760101c166130e1565b0193016125ab565b92602081612a7960019360ff8760081c166130e1565b0193016125a3565b92602081612a9460019360ff87166130e1565b01930161259b565b916020919350610400600191612d178754612aba8360ff83166130e1565b612acc86840160ff8360081c166130e1565b612adf6040840160ff8360101c166130e1565b612af26060840160ff8360181c166130e1565b612b046080840160ff83891c166130e1565b612b1760a0840160ff8360281c166130e1565b612b2a60c0840160ff8360301c166130e1565b612b3d60e0840160ff8360381c166130e1565b612b51610100840160ff8360401c166130e1565b612b65610120840160ff8360481c166130e1565b612b79610140840160ff8360501c166130e1565b612b8d610160840160ff8360581c166130e1565b612ba1610180840160ff8360601c166130e1565b612bb56101a0840160ff8360681c166130e1565b612bc96101c0840160ff8360701c166130e1565b612bdd6101e0840160ff8360781c166130e1565b612bf1610200840160ff8360801c166130e1565b612c05610220840160ff8360881c166130e1565b612c19610240840160ff8360901c166130e1565b612c2d610260840160ff8360981c166130e1565b612c41610280840160ff8360a01c166130e1565b612c556102a0840160ff8360a81c166130e1565b612c696102c0840160ff8360b01c166130e1565b612c7d6102e0840160ff8360b81c166130e1565b612c91610300840160ff8360c01c166130e1565b612ca5610320840160ff8360c81c166130e1565b612cb9610340840160ff8360d01c166130e1565b612ccd610360840160ff8360d81c166130e1565b612ce1610380840160ff8360e01c166130e1565b612cf56103a0840160ff8360e81c166130e1565b612d096103c0840160ff8360f01c166130e1565b6103e083019060f81c6130e1565b019401920184929391612583565b503461063e57606036600319011261063e57612d3f6130b0565b612d476130cb565b604435916001600160a01b0381168085526001602052604085206001600160a01b03331686526020526040852054906000198210612d8c575b5050611596935061367b565b848210612df2578015612ddf573315612dcc576040868692611596985260016020528181206001600160a01b033316825260205220910390553880612d80565b602486634a1406b160e11b815280600452fd5b60248663e602df0560e01b815280600452fd5b60648686847ffb8f41b200000000000000000000000000000000000000000000000000000000835233600452602452604452fd5b503461063e578060031936011261063e576020600254604051908152f35b503461063e57604036600319011261063e57612e5e6130b0565b602435903315612ed9576001600160a01b0316918215612ec65760408291338152600160205281812085825260205220556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b80634a1406b160e11b6024925280600452fd5b60248363e602df0560e01b815280600452fd5b503461063e578060031936011261063e576040519080600354908160011c91600181168015612f9f575b6020841081146119d2578386529081156119ab5750600114612f425761154c8461193a81860382613141565b600381527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b939250905b808210612f855750909150810160200161193a8261192a565b919260018160209254838588010152019101909291612f6c565b92607f1692612f16565b503461063e578060031936011261063e57600754612fc681613195565b91612fd46040519384613141565b818352601f19612fe383613195565b013660208501375b818110613000576040518061154c8582613035565b806130246001600160a01b036130176001946131ad565b90549060031b1c166135e1565b61302e8286613216565b5201612feb565b602060408183019282815284518094520192019060005b8181106130595750505090565b825184526020938401939092019160010161304c565b919082519283825260005b84811061309b575050826000602080949584010152601f8019910116010190565b8060208092840101518282860101520161307a565b600435906001600160a01b03821682036130c657565b600080fd5b602435906001600160a01b03821682036130c657565b9060048210156130ee5752565b634e487b7160e01b600052602160045260246000fd5b906020808351928381520192019060005b8181106131225750505090565b82516001600160a01b0316845260209384019390920191600101613115565b90601f8019910116810190811067ffffffffffffffff82111761316357604052565b634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff811161316357601f01601f191660200190565b67ffffffffffffffff81116131635760051b60200190565b6007548110156131c857600760005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b6006548110156131c857600660005260206000200190600090565b8051156131c85760200190565b8051600110156131c85760400190565b80518210156131c85760209160051b010190565b1561323157565b606460405162461bcd60e51b815260206004820152600e60248201527f496e76616c696420616d6f756e740000000000000000000000000000000000006044820152fd5b1561327c57565b606460405162461bcd60e51b815260206004820152600c60248201527f4e6f206c697175696469747900000000000000000000000000000000000000006044820152fd5b818102929181159184041417156132d357565b634e487b7160e01b600052601160045260246000fd5b81156132f3570490565b634e487b7160e01b600052601260045260246000fd5b908160209103126130c6575180151581036130c65790565b3d1561334c573d9061333282613179565b916133406040519384613141565b82523d6000602084013e565b606090565b1561335857565b606460405162461bcd60e51b815260206004820152601360248201527f455448207472616e73666572206661696c6564000000000000000000000000006044820152fd5b156133a357565b606460405162461bcd60e51b815260206004820152601160248201527f455448206e6f7420737570706f727465640000000000000000000000000000006044820152fd5b51906001600160a01b03821682036130c657565b1561340257565b608460405162461bcd60e51b815260206004820152602260248201527f496e73756666696369656e74206465706f73697420616d6f756e7420696e207560448201527f73640000000000000000000000000000000000000000000000000000000000006064820152fd5b1561347357565b606460405162461bcd60e51b815260206004820152601460248201527f496e636f72726563742045544820616d6f756e740000000000000000000000006044820152fd5b6020818303126130c65780519067ffffffffffffffff82116130c657019080601f830112156130c65781516134eb81613195565b926134f96040519485613141565b81845260208085019260051b8201019283116130c657602001905b8282106135215750505090565b8151815260209182019101613514565b9080601f830112156130c657815161354881613195565b926135566040519485613141565b81845260208085019260051b8201019283116130c657602001905b82821061357e5750505090565b6020809161358b846133e7565b815201910190613571565b1561359d57565b606460405162461bcd60e51b815260206004820152600d60248201527f496e76616c696420746f6b656e000000000000000000000000000000000000006044820152fd5b6000906001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee810361360e5750504790565b6020602491604051928380926370a0823160e01b82523060048301525afa91821561366f57809261363e57505090565b9091506020823d602011613667575b8161365a60209383613141565b8101031261063e57505190565b3d915061364d565b604051903d90823e3d90fd5b6001600160a01b0316908115613743576001600160a01b03169182156137145760008281528060205260408120548281106136fa5791604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef958760209652828652038282205586815280845220818154019055604051908152a3565b60649363391434e360e21b83949352600452602452604452fd5b7fec442f0500000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b7f96c6fd1e00000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b6001600160a01b03168015613743576000918183528260205260408320548181106137da57817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef926020928587528684520360408620558060025403600255604051908152a3565b839263391434e360e21b60649552600452602452604452fd5b6001600160a01b03600a5416330361380757565b7f118cdaa7000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b6001600160a01b03169081156137145761385181600254613893565b6002557fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602060009284845283825260408420818154019055604051908152a3565b919082018092116132d357565b906138ce6080936001600160a01b03929796959784526000602085015260a0604085015260a0840190613104565b951660608201520152565b6001600160a01b036139006060939695949660008452608060208501526080840190613104565b951660408201520152565b906001600160a01b03821680600052600960205261393060ff60406000205416613596565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81149360008515613d6d5750475b8015613d65578351919491613967916132e9565b946060936040929060005b8151811015613d5a576001600160a01b0361398d8284613216565b5116908160005260096020526139aa60ff60406000205416613596565b604051916139b88984613141565b60028352863660208501378515613d54576040516315ab88c960e31b81526020816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa908115613b5957600091613d1b575b505b6001600160a01b03613a2a856131f9565b9116905273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8114908115613d15576040516315ab88c960e31b81526020816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa908115613b5957600091613cdc575b505b6001600160a01b03613aad86613206565b911690528803613ac35750600191505b01613972565b8515613b65575060014201918242116132d357613afa926000916040519485928392637ff36ab560e01b84523090600485016138d9565b03818d6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af1918215613b5957600192613b3e575b50613abd565b613b52903d806000833e6104838183613141565b5038613b38565b6040513d6000823e3d90fd5b15613c2f5760405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660048201819052602482018c9052929060208160448160008d5af18015613b5957613c13575b50600142018042116132d357613bfb938c60008094604051978895869485936318cbafe560e01b85523091600486016138a0565b03925af1918215613b5957600192613b3e5750613abd565b613c2a9060203d81116103dd576103ce8183613141565b613bc7565b60405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660048201819052602482018c9052929060208160448160008d5af18015613b5957613cc0575b50600142018042116132d357613bfb938c60008094604051978895869485936338ed173960e01b85523091600486016138a0565b613cd79060203d81116103dd576103ce8183613141565b613c8c565b906020823d8211613d0d575b81613cf560209383613141565b8101031261063e5750613d07906133e7565b38613a9a565b3d9150613ce8565b80613a9c565b906020823d8211613d4c575b81613d3460209383613141565b8101031261063e5750613d46906133e7565b38613a17565b3d9150613d27565b84613a19565b505050505050509050565b509350505050565b6040516370a0823160e01b8152306004820152602081602481875afa91821561366f578092613d9e575b5050613953565b9091506020823d602011613dcb575b81613dba60209383613141565b8101031261063e5750513880613d97565b3d9150613dad56fea26469706673582212203c3f4a32f13042b341519148a8715900a9db43fc2ffc692cb36fc3773c791bc964736f6c634300081c0033a264697066735822122055deecd749364ef91930e775f13a83b0812e157c064fcb7944d6508ed8b4882164736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000003f63e16d1cad611414719e063d3f7cd4ea039c53000000000000000000000000ed79079f86712d439f5d837da13bd5ed1568474e000000000000000000000000a6ad18c2ac47803e193f75c3677b14bf19b94883
-----Decoded View---------------
Arg [0] : revenue_ (address): 0x3f63E16D1cAd611414719e063D3f7cD4Ea039c53
Arg [1] : dataFeed_ (address): 0xEd79079F86712d439F5D837DA13bd5Ed1568474e
Arg [2] : swapRouter_ (address): 0xa6AD18C2aC47803E193F75c3677b14BF19B94883
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000003f63e16d1cad611414719e063d3f7cd4ea039c53
Arg [1] : 000000000000000000000000ed79079f86712d439f5d837da13bd5ed1568474e
Arg [2] : 000000000000000000000000a6ad18c2ac47803e193f75c3677b14bf19b94883
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.