Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
ConvexStrategyMeta3Pool
Compiler Version
v0.8.10+commit.fc410830
Optimization Enabled:
Yes with 999999 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import {ConvexBaseStrategy} from "./ConvexBaseStrategy.sol"; import {IDepositZap} from "../../interfaces/curve/IDepositZap.sol"; import {IERC20Detailed} from "../../interfaces/IERC20Detailed.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; contract ConvexStrategyMeta3Pool is ConvexBaseStrategy { using SafeERC20Upgradeable for IERC20Detailed; /// @notice curve N_COINS for the pool uint256 public constant CURVE_UNDERLYINGS_SIZE = 4; /// @notice curve 3pool deposit zap address public constant CRV_3POOL_DEPOSIT_ZAP = address(0xA79828DF1850E8a3A3064576f380D90aECDD3359); /// @return size of the curve deposit array function _curveUnderlyingsSize() internal pure override returns (uint256) { return CURVE_UNDERLYINGS_SIZE; } /// @notice Deposits in Curve for metapools based on 3pool function _depositInCurve(uint256 _minLpTokens) internal override { IERC20Detailed _deposit = IERC20Detailed(curveDeposit); uint256 _balance = _deposit.balanceOf(address(this)); address _pool = _curvePool(curveLpToken); _deposit.safeApprove(CRV_3POOL_DEPOSIT_ZAP, 0); _deposit.safeApprove(CRV_3POOL_DEPOSIT_ZAP, _balance); // we can accept 0 as minimum, this will be called only by trusted roles // we also use the zap to deploy funds into a meta pool uint256[4] memory _depositArray; _depositArray[depositPosition] = _balance; IDepositZap(CRV_3POOL_DEPOSIT_ZAP).add_liquidity( _pool, _depositArray, _minLpTokens ); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; import "../../interfaces/IIdleCDOStrategy.sol"; import "../../interfaces/IERC20Detailed.sol"; import "../../interfaces/convex/IBooster.sol"; import "../../interfaces/convex/IBaseRewardPool.sol"; import "../../interfaces/curve/IMainRegistry.sol"; /// @author @dantop114 /// @title ConvexStrategy /// @notice IIdleCDOStrategy to deploy funds in Convex Finance /// @dev This contract should not have any funds at the end of each tx. /// The contract is upgradable, to add storage slots, add them after the last `###### End of storage VXX` abstract contract ConvexBaseStrategy is Initializable, OwnableUpgradeable, ReentrancyGuardUpgradeable, ERC20Upgradeable, IIdleCDOStrategy { using SafeERC20Upgradeable for IERC20Detailed; /// ###### Storage V1 /// @notice one curve lp token /// @dev we use this as base unit of the strategy token too uint256 public ONE_CURVE_LP_TOKEN; /// @notice convex rewards pool id for the underlying curve lp token uint256 public poolID; /// @notice curve lp token to deposit in convex address public curveLpToken; /// @notice deposit token address to deposit into curve pool address public curveDeposit; /// @notice depositor contract used to deposit underlyings address public depositor; /// @notice deposit token array position uint256 public depositPosition; /// @notice convex crv rewards pool address address public rewardPool; /// @notice decimals of the underlying asset uint256 public curveLpDecimals; /// @notice Curve main registry address public constant MAIN_REGISTRY = address(0x90E00ACe148ca3b23Ac1bC8C240C2a7Dd9c2d7f5); /// @notice convex booster address address public constant BOOSTER = address(0xF403C135812408BFbE8713b5A23a04b3D48AAE31); /// @notice weth token address address public constant WETH = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); /// @notice curve ETH mock address address public constant ETH = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); /// @notice whitelisted CDO for this strategy address public whitelistedCDO; /// @notice convex rewards for this specific lp token (cvx should be included in this list) address[] public convexRewards; /// @notice WETH to deposit token path address[] public weth2DepositPath; /// @notice univ2 router for weth to deposit swap address public weth2DepositRouter; /// @notice reward liquidation to WETH path mapping(address => address[]) public reward2WethPath; /// @notice univ2-like router for each reward mapping(address => address) public rewardRouter; /// @notice total LP tokens staked uint256 public totalLpTokensStaked; /// @notice total LP tokens locked uint256 public totalLpTokensLocked; /// @notice harvested LP tokens release delay uint256 public releaseBlocksPeriod; /// @notice latest harvest uint256 public latestHarvestBlock; /// ###### End of storage V1 /// ###### Storage V2 /// @notice blocks per year uint256 public BLOCKS_PER_YEAR; /// @notice latest harvest price gain in LP tokens uint256 public latestPriceIncrease; /// @notice latest estimated harvest interval uint256 public latestHarvestInterval; // ################### // Modifiers // ################### modifier onlyWhitelistedCDO() { require(msg.sender == whitelistedCDO, "Not whitelisted CDO"); _; } // Used to prevent initialization of the implementation contract /// @custom:oz-upgrades-unsafe-allow constructor constructor() { curveLpToken = address(1); } // ################### // Initializer // ################### // Struct used to set Curve deposits struct CurveArgs { address deposit; address depositor; uint256 depositPosition; } // Struct used to initialize rewards swaps struct Reward { address reward; address router; address[] path; } // Struct used to initialize WETH -> deposit swaps struct Weth2Deposit { address router; address[] path; } /// @notice can only be called once /// @dev Initialize the upgradable contract. If `_deposit` equals WETH address, _weth2Deposit is ignored as param. /// @param _poolID convex pool id /// @param _owner owner address /// @param _curveArgs curve addresses and deposit details /// @param _rewards initial rewards (with paths and routers) /// @param _weth2Deposit initial WETH -> deposit paths and routers function initialize( uint256 _poolID, address _owner, uint256 _releasePeriod, CurveArgs memory _curveArgs, Reward[] memory _rewards, Weth2Deposit memory _weth2Deposit ) public initializer { // Sanity checks require(curveLpToken == address(0), "Initialized"); require(_curveArgs.depositPosition < _curveUnderlyingsSize(), "Deposit token position invalid"); // Initialize contracts OwnableUpgradeable.__Ownable_init(); ReentrancyGuardUpgradeable.__ReentrancyGuard_init(); // Check Curve LP Token and Convex PoolID (address _crvLp, , , address _rewardPool, , bool shutdown) = IBooster(BOOSTER).poolInfo(_poolID); curveLpToken = _crvLp; // Pool and deposit asset checks address _deposit = _curveArgs.deposit == WETH ? ETH : _curveArgs.deposit; require(!shutdown, "Convex Pool is not active"); require(_deposit == _curveUnderlyingCoins(_crvLp, _curveArgs.depositPosition), "Deposit token invalid"); ERC20Upgradeable.__ERC20_init( string(abi.encodePacked("Idle ", IERC20Detailed(_crvLp).name(), " Convex Strategy")), string(abi.encodePacked("idleCvx", IERC20Detailed(_crvLp).symbol())) ); // Set basic parameters poolID = _poolID; rewardPool = _rewardPool; curveLpDecimals = IERC20Detailed(_crvLp).decimals(); ONE_CURVE_LP_TOKEN = 10**(curveLpDecimals); curveDeposit = _curveArgs.deposit; depositor = _curveArgs.depositor; depositPosition = _curveArgs.depositPosition; releaseBlocksPeriod = _releasePeriod; setBlocksPerYear(2465437); // given that blocks are mined at a 13.15s/block rate // set approval for curveLpToken IERC20Detailed(_crvLp).approve(BOOSTER, type(uint256).max); // set initial rewards for (uint256 i = 0; i < _rewards.length; i++) { addReward(_rewards[i].reward, _rewards[i].router, _rewards[i].path); } if (_curveArgs.deposit != WETH) setWeth2Deposit(_weth2Deposit.router, _weth2Deposit.path); // transfer ownership transferOwnership(_owner); } // ################### // Interface implementation // ################### function strategyToken() external view override returns (address) { return address(this); } function oneToken() external view override returns (uint256) { return ONE_CURVE_LP_TOKEN; } // @notice Underlying token function token() external view override returns (address) { return curveLpToken; } // @notice Underlying token decimals function tokenDecimals() external view override returns (uint256) { return curveLpDecimals; } function decimals() public view override returns (uint8) { return uint8(curveLpDecimals); // should be safe } // ################### // Public methods // ################### /// @dev msg.sender should approve this contract first to spend `_amount` of `token` /// @param _amount amount of `token` to deposit /// @return minted amount of strategy tokens minted function deposit(uint256 _amount) external override onlyWhitelistedCDO returns (uint256 minted) { if (_amount > 0) { /// get `tokens` from msg.sender IERC20Detailed(curveLpToken).safeTransferFrom(msg.sender, address(this), _amount); minted = _depositAndMint(msg.sender, _amount, price()); } } /// @dev msg.sender doesn't need to approve the spending of strategy token /// @param _amount amount of strategyTokens to redeem /// @return redeemed amount of underlyings redeemed function redeem(uint256 _amount) external onlyWhitelistedCDO override returns (uint256 redeemed) { if(_amount > 0) { redeemed = _redeem(msg.sender, _amount, price()); } } /// @dev msg.sender should approve this contract first /// to spend `_amount * ONE_IDLE_TOKEN / price()` of `strategyToken` /// @param _amount amount of underlying tokens to redeem /// @return redeemed amount of underlyings redeemed function redeemUnderlying(uint256 _amount) external override onlyWhitelistedCDO returns (uint256 redeemed) { if (_amount > 0) { uint256 _cachedPrice = price(); uint256 _shares = (_amount * ONE_CURVE_LP_TOKEN) / _cachedPrice; redeemed = _redeem(msg.sender, _shares, _cachedPrice); } } /// @notice Anyone can call this because this contract holds no strategy tokens and so no 'old' rewards /// @dev msg.sender should approve this contract first to spend `_amount` of `strategyToken`. /// redeem rewards and transfer them to msg.sender /// @param _extraData extra data to be used when selling rewards for min amounts /// @return _balances array of minAmounts to use for swapping rewards to WETH, then weth to depositToken, then depositToken to curveLpToken function redeemRewards(bytes calldata _extraData) external override onlyWhitelistedCDO returns (uint256[] memory _balances) { address[] memory _convexRewards = convexRewards; // +2 for converting rewards to depositToken and then Curve LP Token _balances = new uint256[](_convexRewards.length + 2); // decode params from _extraData to get the min amount for each convexRewards uint256[] memory _minAmountsWETH = new uint256[](_convexRewards.length); bool[] memory _skipSell = new bool[](_convexRewards.length); uint256 _minDepositToken; uint256 _minLpToken; (_minAmountsWETH, _skipSell, _minDepositToken, _minLpToken) = abi.decode(_extraData, (uint256[], bool[], uint256, uint256)); IBaseRewardPool(rewardPool).getReward(); address _reward; IERC20Detailed _rewardToken; uint256 _rewardBalance; IUniswapV2Router02 _router; for (uint256 i = 0; i < _convexRewards.length; i++) { if (_skipSell[i]) continue; _reward = _convexRewards[i]; // get reward balance and safety check _rewardToken = IERC20Detailed(_reward); _rewardBalance = _rewardToken.balanceOf(address(this)); if (_rewardBalance == 0) continue; _router = IUniswapV2Router02( rewardRouter[_reward] ); // approve to v2 router _rewardToken.safeApprove(address(_router), 0); _rewardToken.safeApprove(address(_router), _rewardBalance); address[] memory _reward2WethPath = reward2WethPath[_reward]; uint256[] memory _res = new uint256[](_reward2WethPath.length); _res = _router.swapExactTokensForTokens( _rewardBalance, _minAmountsWETH[i], _reward2WethPath, address(this), block.timestamp ); // save in returned value the amount of weth receive to use off-chain _balances[i] = _res[_res.length - 1]; } if (curveDeposit != WETH) { IERC20Detailed _weth = IERC20Detailed(WETH); IUniswapV2Router02 _wethRouter = IUniswapV2Router02( weth2DepositRouter ); uint256 _wethBalance = _weth.balanceOf(address(this)); _weth.safeApprove(address(_wethRouter), 0); _weth.safeApprove(address(_wethRouter), _wethBalance); address[] memory _weth2DepositPath = weth2DepositPath; uint256[] memory _res = new uint256[](_weth2DepositPath.length); _res = _wethRouter.swapExactTokensForTokens( _wethBalance, _minDepositToken, _weth2DepositPath, address(this), block.timestamp ); // save in _balances the amount of depositToken to use off-chain _balances[_convexRewards.length] = _res[_res.length - 1]; } IERC20Detailed _curveLpToken = IERC20Detailed(curveLpToken); uint256 _curveLpBalanceBefore = _curveLpToken.balanceOf(address(this)); _depositInCurve(_minLpToken); uint256 _curveLpBalanceAfter = _curveLpToken.balanceOf(address(this)); uint256 _gainedLpTokens = (_curveLpBalanceAfter - _curveLpBalanceBefore); // save in _balances the amount of curveLpTokens received to use off-chain _balances[_convexRewards.length + 1] = _gainedLpTokens; if (_curveLpBalanceAfter > 0) { // deposit in curve and stake on convex _stakeConvex(_curveLpBalanceAfter); // update locked lp tokens and apr computation variables latestHarvestInterval = (block.number - latestHarvestBlock); latestHarvestBlock = block.number; totalLpTokensLocked = _gainedLpTokens; // inline price increase calculation latestPriceIncrease = (_gainedLpTokens * ONE_CURVE_LP_TOKEN) / totalSupply(); } } // ################### // Views // ################### /// @return _price net price in underlyings of 1 strategyToken function price() public view override returns (uint256 _price) { uint256 _totalSupply = totalSupply(); if (_totalSupply == 0) { _price = ONE_CURVE_LP_TOKEN; } else { _price = ((totalLpTokensStaked - _lockedLpTokens()) * ONE_CURVE_LP_TOKEN) / _totalSupply; } } /// @return returns an APR estimation. /// @dev values returned by this method should be taken as an imprecise estimation. /// For client integration something more complex should be done to have a more precise /// estimate (eg. computing APR using historical APR data). /// Also it does not take into account compounding (APY). function getApr() external view override returns (uint256) { // apr = rate * blocks in a year / harvest interval return latestPriceIncrease * (BLOCKS_PER_YEAR / latestHarvestInterval) * 100; } /// @return rewardTokens tokens array of reward token addresses function getRewardTokens() external view override returns (address[] memory rewardTokens) {} // ################### // Protected // ################### /// @notice Allow the CDO to pull stkAAVE rewards. Anyone can call this /// @return 0, this function is a noop in this strategy function pullStkAAVE() external pure override returns (uint256) { return 0; } /// @notice This contract should not have funds at the end of each tx (except for stkAAVE), this method is just for leftovers /// @dev Emergency method /// @param _token address of the token to transfer /// @param value amount of `_token` to transfer /// @param _to receiver address function transferToken( address _token, uint256 value, address _to ) external onlyOwner nonReentrant { IERC20Detailed(_token).safeTransfer(_to, value); } /// @notice This method can be used to change the value of BLOCKS_PER_YEAR /// @param blocksPerYear the new blocks per year value function setBlocksPerYear(uint256 blocksPerYear) public onlyOwner { require(blocksPerYear != 0, "Blocks per year cannot be zero"); BLOCKS_PER_YEAR = blocksPerYear; } function setRouterForReward(address _reward, address _newRouter) external onlyOwner { require(_newRouter != address(0), "Router is address zero"); rewardRouter[_reward] = _newRouter; } function setPathForReward(address _reward, address[] memory _newPath) external onlyOwner { _validPath(_newPath, WETH); reward2WethPath[_reward] = _newPath; } function setWeth2Deposit(address _router, address[] memory _path) public onlyOwner { address _curveDeposit = curveDeposit; require(_curveDeposit != WETH, "Deposit asset is WETH"); _validPath(_path, _curveDeposit); weth2DepositRouter = _router; weth2DepositPath = _path; } function addReward( address _reward, address _router, address[] memory _path ) public onlyOwner { _validPath(_path, WETH); convexRewards.push(_reward); rewardRouter[_reward] = _router; reward2WethPath[_reward] = _path; } function removeReward(address _reward) external onlyOwner { address[] memory _newConvexRewards = new address[]( convexRewards.length - 1 ); uint256 currentI = 0; for (uint256 i = 0; i < convexRewards.length; i++) { if (convexRewards[i] == _reward) continue; _newConvexRewards[currentI] = convexRewards[i]; currentI += 1; } convexRewards = _newConvexRewards; delete rewardRouter[_reward]; delete reward2WethPath[_reward]; } /// @notice allow to update whitelisted address function setWhitelistedCDO(address _cdo) external onlyOwner { require(_cdo != address(0), "IS_0"); whitelistedCDO = _cdo; } function setReleaseBlocksPeriod(uint256 _period) external onlyOwner { releaseBlocksPeriod = _period; } // ################### // Internal // ################### /// @dev Virtual method to override in specific pool implementation. /// @return number of underlying coins depending on Curve pool function _curveUnderlyingsSize() internal pure virtual returns (uint256); /// @dev Virtual method to override in specific pool implementation. /// This method should implement the deposit in the curve pool. function _depositInCurve(uint256 _minLpTokens) internal virtual; /// @dev Virtual method to override if needed (eg. pool address is equal to lp token address) /// @return address of pool from LP token function _curvePool(address _curveLpToken) internal view virtual returns (address) { return IMainRegistry(MAIN_REGISTRY).get_pool_from_lp_token(_curveLpToken); } /// @dev Virtual method to override if needed (eg. pool is not in the main registry) /// @return address of the nth underlying coin for _curveLpToken function _curveUnderlyingCoins(address _curveLpToken, uint256 _position) internal view virtual returns (address) { address[8] memory _coins = IMainRegistry(MAIN_REGISTRY).get_underlying_coins(_curvePool(_curveLpToken)); return _coins[_position]; } /// @notice Internal helper function to deposit in convex and update total LP tokens staked /// @param _lpTokens number of LP tokens to stake function _stakeConvex(uint256 _lpTokens) internal { // update total staked lp tokens and deposit in convex totalLpTokensStaked += _lpTokens; IBooster(BOOSTER).depositAll(poolID, true); } /// @notice Internal function to deposit in the Convex Booster and mint shares /// @dev Used for deposit and during an harvest /// @param _lpTokens amount to mint /// @param _price we give the price as input to save on gas when calculating price function _depositAndMint( address _account, uint256 _lpTokens, uint256 _price ) internal returns (uint256 minted) { // deposit in convex _stakeConvex(_lpTokens); // mint strategy tokens to msg.sender minted = (_lpTokens * ONE_CURVE_LP_TOKEN) / _price; _mint(_account, minted); } /// @dev msg.sender does not need to approve this contract to spend `_amount` of `strategyToken` /// @param _shares amount of strategyTokens to redeem /// @param _price we give the price as input to save on gas when calculating price /// @return redeemed amount of underlyings redeemed function _redeem( address _account, uint256 _shares, uint256 _price ) internal returns (uint256 redeemed) { // update total staked lp tokens redeemed = (_shares * _price) / ONE_CURVE_LP_TOKEN; totalLpTokensStaked -= redeemed; IERC20Detailed _curveLpToken = IERC20Detailed(curveLpToken); // burn strategy tokens for the msg.sender _burn(_account, _shares); // exit reward pool (without claiming) and unwrap staking position IBaseRewardPool(rewardPool).withdraw(redeemed, false); IBooster(BOOSTER).withdraw(poolID, redeemed); // transfer underlying lp tokens to msg.sender _curveLpToken.safeTransfer(_account, redeemed); } function _lockedLpTokens() internal view returns (uint256 _locked) { uint256 _releaseBlocksPeriod = releaseBlocksPeriod; uint256 _blocksSinceLastHarvest = block.number - latestHarvestBlock; uint256 _totalLockedLpTokens = totalLpTokensLocked; if (_totalLockedLpTokens > 0 && _blocksSinceLastHarvest < _releaseBlocksPeriod) { // progressively release harvested rewards _locked = _totalLockedLpTokens * (_releaseBlocksPeriod - _blocksSinceLastHarvest) / _releaseBlocksPeriod; } } function _validPath(address[] memory _path, address _out) internal pure { require(_path.length >= 2, "Path length less than 2"); require(_path[_path.length - 1] == _out, "Last asset should be WETH"); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; interface IDepositZap { /// @notice Wraps underlying coins and deposit them into _pool. /// Returns the amount of LP tokens that were minted in the deposit. function add_liquidity( address _pool, uint256[4] memory _deposit_amounts, uint256 _min_mint_amount ) external returns (uint256); function add_liquidity( uint256[4] memory _deposit_amounts, uint256 _min_mint_amount ) external returns (uint256); }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.10; import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; interface IERC20Detailed is IERC20Upgradeable { function name() external view returns(string memory); function symbol() external view returns(string memory); function decimals() external view returns(uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC20Upgradeable.sol"; import "../../../utils/AddressUpgradeable.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20Upgradeable { using AddressUpgradeable for address; function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal initializer { __Context_init_unchained(); __Ownable_init_unchained(); } function __Ownable_init_unchained() internal initializer { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } uint256[49] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IERC20Upgradeable.sol"; import "../../utils/ContextUpgradeable.sol"; import "../../proxy/utils/Initializable.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}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable { mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The defaut value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All three of these values are immutable: they can only be set once during * construction. */ function __ERC20_init(string memory name_, string memory symbol_) internal initializer { __Context_init_unchained(); __ERC20_init_unchained(name_, symbol_); } function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer { _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 value {ERC20} uses, unless this function is * overloaded; * * 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 override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { _transfer(sender, recipient, amount); uint256 currentAllowance = _allowances[sender][_msgSender()]; require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); _approve(sender, _msgSender(), currentAllowance - amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { uint256 currentAllowance = _allowances[_msgSender()][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); _approve(_msgSender(), spender, currentAllowance - subtractedValue); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); uint256 senderBalance = _balances[sender]; require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); _balances[sender] = senderBalance - amount; _balances[recipient] += amount; emit Transfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); _balances[account] = accountBalance - amount; _totalSupply -= amount; emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` 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. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be to transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } uint256[45] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; function __ReentrancyGuard_init() internal initializer { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal initializer { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } uint256[49] private __gap; }
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: Apache-2.0 pragma solidity 0.8.10; interface IIdleCDOStrategy { function strategyToken() external view returns(address); function token() external view returns(address); function tokenDecimals() external view returns(uint256); function oneToken() external view returns(uint256); function redeemRewards(bytes calldata _extraData) external returns(uint256[] memory); function pullStkAAVE() external returns(uint256); function price() external view returns(uint256); function getRewardTokens() external view returns(address[] memory); function deposit(uint256 _amount) external returns(uint256); // _amount in `strategyToken` function redeem(uint256 _amount) external returns(uint256); // _amount in `token` function redeemUnderlying(uint256 _amount) external returns(uint256); function getApr() external view returns(uint256); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; interface IBooster { function deposit(uint256 _pid, uint256 _amount, bool _stake) external; function depositAll(uint256 _pid, bool _stake) external; function withdraw(uint256 _pid, uint256 _amount) external; function withdrawAll(uint256 _pid) external; function poolInfo(uint256 _pid) external view returns (address lpToken, address, address, address, address, bool); function earmarkRewards(uint256 _pid) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; interface IBaseRewardPool { function balanceOf(address account) external view returns(uint256 amount); function pid() external view returns (uint256 _pid); function stakingToken() external view returns (address _stakingToken); function extraRewardsLength() external view returns (uint256 _length); function rewardToken() external view returns(address _rewardToken); function extraRewards() external view returns(address[] memory _extraRewards); function getReward() external; function stake(uint256 _amount) external; function stakeAll() external; function withdraw(uint256 amount, bool claim) external; function withdrawAll(bool claim) external; function withdrawAndUnwrap(uint256 amount, bool claim) external; function withdrawAllAndUnwrap(bool claim) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; interface IMainRegistry { function get_pool_from_lp_token(address lp_token) external view returns (address); function get_underlying_coins(address pool) external view returns (address[8] memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal initializer { __Context_init_unchained(); } function __Context_init_unchained() internal initializer { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // solhint-disable-next-line compiler-version pragma solidity ^0.8.0; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { require(_initializing || !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Upgradeable { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @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); }
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); }
{ "optimizer": { "enabled": true, "runs": 999999 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"BLOCKS_PER_YEAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BOOSTER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CRV_3POOL_DEPOSIT_ZAP","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CURVE_UNDERLYINGS_SIZE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAIN_REGISTRY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_CURVE_LP_TOKEN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_reward","type":"address"},{"internalType":"address","name":"_router","type":"address"},{"internalType":"address[]","name":"_path","type":"address[]"}],"name":"addReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"convexRewards","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"curveDeposit","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"curveLpDecimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"curveLpToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"minted","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositPosition","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"depositor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getApr","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRewardTokens","outputs":[{"internalType":"address[]","name":"rewardTokens","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_poolID","type":"uint256"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_releasePeriod","type":"uint256"},{"components":[{"internalType":"address","name":"deposit","type":"address"},{"internalType":"address","name":"depositor","type":"address"},{"internalType":"uint256","name":"depositPosition","type":"uint256"}],"internalType":"struct ConvexBaseStrategy.CurveArgs","name":"_curveArgs","type":"tuple"},{"components":[{"internalType":"address","name":"reward","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"address[]","name":"path","type":"address[]"}],"internalType":"struct ConvexBaseStrategy.Reward[]","name":"_rewards","type":"tuple[]"},{"components":[{"internalType":"address","name":"router","type":"address"},{"internalType":"address[]","name":"path","type":"address[]"}],"internalType":"struct ConvexBaseStrategy.Weth2Deposit","name":"_weth2Deposit","type":"tuple"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"latestHarvestBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestHarvestInterval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestPriceIncrease","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oneToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"_price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pullStkAAVE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"redeemed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"redeemRewards","outputs":[{"internalType":"uint256[]","name":"_balances","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"redeemUnderlying","outputs":[{"internalType":"uint256","name":"redeemed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"releaseBlocksPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_reward","type":"address"}],"name":"removeReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"reward2WethPath","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardRouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blocksPerYear","type":"uint256"}],"name":"setBlocksPerYear","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_reward","type":"address"},{"internalType":"address[]","name":"_newPath","type":"address[]"}],"name":"setPathForReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_period","type":"uint256"}],"name":"setReleaseBlocksPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_reward","type":"address"},{"internalType":"address","name":"_newRouter","type":"address"}],"name":"setRouterForReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_router","type":"address"},{"internalType":"address[]","name":"_path","type":"address[]"}],"name":"setWeth2Deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_cdo","type":"address"}],"name":"setWhitelistedCDO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"strategyToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenDecimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalLpTokensLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalLpTokensStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"transferToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"weth2DepositPath","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weth2DepositRouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whitelistedCDO","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5060cb80546001600160a01b0319166001179055615cca80620000346000396000f3fe608060405234801561001057600080fd5b50600436106103c55760003560e01c80638d934485116101ff578063b7e2ce101161011a578063e8fd22d1116100ad578063f2fde38b1161007c578063f2fde38b1461089d578063f640d508146108b0578063f7c69187146108c3578063fc0c546a146108d657600080fd5b8063e8fd22d11461085d578063e98e779c14610870578063ea1cd58d14610879578063edd636fb1461089457600080fd5b8063d37db1d2116100e9578063d37db1d2146107e8578063db006a75146107f1578063dd62ed3e14610804578063e5fa2b701461084a57600080fd5b8063b7e2ce10146107a9578063c4f59f9b146107b2578063c7c4ff46146107c1578063cdfbe9c5146107e157600080fd5b8063a035b1fe11610192578063a9059cbb11610161578063a9059cbb14610755578063ad5c464814610768578063af4a22dc14610783578063b6b55f251461079657600080fd5b8063a035b1fe1461071f578063a27eccc114610727578063a457c2d71461072f578063a4d5e67c1461074257600080fd5b806394929dc1116101ce57806394929dc1146106de57806395d89b41146106f1578063996a70f3146106f95780639a49cb931461070c57600080fd5b80638d9344851461067c5780638da5cb5b146106855780638eaaca57146106a35780638ec71e0c146106be57600080fd5b8063646780df116102ef57806376bfa52f116102825780638322fff2116102515780638322fff214610626578063845bc80414610641578063852a12e314610649578063887ee9711461065c57600080fd5b806376bfa52f146105d757806379623480146105ea5780637d9a8e001461060a57806381f5ae7e1461061d57600080fd5b8063715018a6116102be578063715018a6146105a6578063747efea1146105ae57806375114046146105b457806375b0ffd1146105bc57600080fd5b8063646780df1461052757806366666aa914610547578063704a19271461056757806370a082311461057057600080fd5b8063313ce567116103675780634521e248116103365780634521e248146104cc5780634e0a873a146104df5780635322e60a146104e85780635f783e18146104f157600080fd5b8063313ce567146104935780633145b35c146104a857806339509351146104b15780633b97e856146104c457600080fd5b806318160ddd116103a357806318160ddd146104505780631baaade51461046257806323b872dd1461046b57806325e23ab91461047e57600080fd5b806306fdde03146103ca578063095ea7b3146103e8578063138821421461040b575b600080fd5b6103d26108f4565b6040516103df9190614d8e565b60405180910390f35b6103fb6103f6366004614e01565b610986565b60405190151581526020016103df565b60d15461042b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103df565b6099545b6040519081526020016103df565b61045460dc5481565b6103fb610479366004614e2d565b61099d565b61049161048c366004614fad565b610a91565b005b60d05460405160ff90911681526020016103df565b61045460d85481565b6103fb6104bf366004614e01565b610b6b565b60d054610454565b61042b6104da366004614ffd565b610baf565b61045460d75481565b61045460c95481565b61042b6104ff366004615016565b60d66020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60cb5461042b9073ffffffffffffffffffffffffffffffffffffffff1681565b60cf5461042b9073ffffffffffffffffffffffffffffffffffffffff1681565b61045460dd5481565b61045461057e366004615016565b73ffffffffffffffffffffffffffffffffffffffff1660009081526097602052604090205490565b610491610be6565b3061042b565b610454600481565b61042b73f403c135812408bfbe8713b5a23a04b3d48aae3181565b6104916105e5366004615033565b610cd6565b60d45461042b9073ffffffffffffffffffffffffffffffffffffffff1681565b610491610618366004614fad565b610e27565b61045460da5481565b61042b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b610454610fa2565b610454610657366004614ffd565b610fd1565b60cc5461042b9073ffffffffffffffffffffffffffffffffffffffff1681565b61045460ca5481565b60335473ffffffffffffffffffffffffffffffffffffffff1661042b565b61042b7390e00ace148ca3b23ac1bc8c240c2a7dd9c2d7f581565b6106d16106cc36600461506c565b611099565b6040516103df91906150de565b6104916106ec366004614ffd565b611aef565b6103d2611b75565b610491610707366004615122565b611b84565b61042b61071a366004614e01565b611cc9565b610454611d0e565b60c954610454565b6103fb61073d366004614e01565b611d5d565b610491610750366004615016565b611e37565b6103fb610763366004614e01565b61207b565b61042b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b6104916107913660046152fb565b612088565b6104546107a4366004614ffd565b612915565b61045460d05481565b60606040516103df9190615441565b60cd5461042b9073ffffffffffffffffffffffffffffffffffffffff1681565b6000610454565b61045460db5481565b6104546107ff366004614ffd565b6129d6565b610454610812366004615033565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260986020908152604080832093909416825291909152205490565b610491610858366004614ffd565b612a72565b61042b61086b366004614ffd565b612b5f565b61045460ce5481565b61042b73a79828df1850e8a3a3064576f380d90aecdd335981565b61045460d95481565b6104916108ab366004615016565b612b6f565b6104916108be366004615454565b612d21565b6104916108d1366004615016565b612e3f565b60cb5473ffffffffffffffffffffffffffffffffffffffff1661042b565b6060609a805461090390615496565b80601f016020809104026020016040519081016040528092919081815260200182805461092f90615496565b801561097c5780601f106109515761010080835404028352916020019161097c565b820191906000526020600020905b81548152906001019060200180831161095f57829003601f168201915b5050505050905090565b6000610993338484612f86565b5060015b92915050565b60006109aa84848461313a565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260986020908152604080832033845290915290205482811015610a70576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206160448201527f6c6c6f77616e636500000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610a848533610a7f8685615519565b612f86565b60019150505b9392505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610b12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b610b308173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26133f7565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260d5602090815260409091208251610b6692840190614c17565b505050565b33600081815260986020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091610993918590610a7f908690615530565b60d38181548110610bbf57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60335473ffffffffffffffffffffffffffffffffffffffff163314610c67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b60335460405160009173ffffffffffffffffffffffffffffffffffffffff16907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610d57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b73ffffffffffffffffffffffffffffffffffffffff8116610dd4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f526f757465722069732061646472657373207a65726f000000000000000000006044820152606401610a67565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260d66020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ea8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b60cc5473ffffffffffffffffffffffffffffffffffffffff1673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2811415610f3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4465706f736974206173736574206973205745544800000000000000000000006044820152606401610a67565b610f4982826133f7565b60d480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff85161790558151610f9c9060d3906020850190614c17565b50505050565b600060dd5460db54610fb49190615548565b60dc54610fc19190615583565b610fcc906064615583565b905090565b60d15460009073ffffffffffffffffffffffffffffffffffffffff163314611055576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4e6f742077686974656c69737465642043444f000000000000000000000000006044820152606401610a67565b8115611094576000611065611d0e565b905060008160c954856110789190615583565b6110829190615548565b905061108f338284613522565b925050505b919050565b60d15460609073ffffffffffffffffffffffffffffffffffffffff16331461111d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4e6f742077686974656c69737465642043444f000000000000000000000000006044820152606401610a67565b600060d280548060200260200160405190810160405280929190818152602001828054801561118257602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311611157575b50505050509050805160026111979190615530565b67ffffffffffffffff8111156111af576111af614e6e565b6040519080825280602002602001820160405280156111d8578160200160208202803683370190505b5091506000815167ffffffffffffffff8111156111f7576111f7614e6e565b604051908082528060200260200182016040528015611220578160200160208202803683370190505b5090506000825167ffffffffffffffff81111561123f5761123f614e6e565b604051908082528060200260200182016040528015611268578160200160208202803683370190505b50905060008061127a87890189615632565b60cf54604080517f3d18b9120000000000000000000000000000000000000000000000000000000081529051959950939750919550935073ffffffffffffffffffffffffffffffffffffffff1691633d18b9129160048082019260009290919082900301818387803b1580156112ef57600080fd5b505af1158015611303573d6000803e3d6000fd5b5050505060008060008060005b89518110156116425787818151811061132b5761132b6156fb565b60200260200101511561133d57611630565b89818151811061134f5761134f6156fb565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290955085945073ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa1580156113ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ee919061572a565b9250826113fa57611630565b73ffffffffffffffffffffffffffffffffffffffff808616600090815260d66020526040812054821693506114339186169084906136b6565b61145473ffffffffffffffffffffffffffffffffffffffff851683856136b6565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260d560209081526040808320805482518185028101850190935280835291929091908301828280156114d857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116114ad575b505050505090506000815167ffffffffffffffff8111156114fb576114fb614e6e565b604051908082528060200260200182016040528015611524578160200160208202803683370190505b5090508373ffffffffffffffffffffffffffffffffffffffff166338ed1739868d8681518110611556576115566156fb565b60200260200101518530426040518663ffffffff1660e01b8152600401611581959493929190615743565b6000604051808303816000875af11580156115a0573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526115e6919081019061578c565b905080600182516115f79190615519565b81518110611607576116076156fb565b60200260200101518d8481518110611621576116216156fb565b60200260200101818152505050505b8061163a81615812565b915050611310565b5060cc5473ffffffffffffffffffffffffffffffffffffffff1673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2146119285760d4546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29173ffffffffffffffffffffffffffffffffffffffff169060009083906370a0823190602401602060405180830381865afa1580156116fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611721919061572a565b905061174573ffffffffffffffffffffffffffffffffffffffff84168360006136b6565b61176673ffffffffffffffffffffffffffffffffffffffff841683836136b6565b600060d38054806020026020016040519081016040528092919081815260200182805480156117cb57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116117a0575b505050505090506000815167ffffffffffffffff8111156117ee576117ee614e6e565b604051908082528060200260200182016040528015611817578160200160208202803683370190505b506040517f38ed173900000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8516906338ed1739906118759086908f90879030904290600401615743565b6000604051808303816000875af1158015611894573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526118da919081019061578c565b905080600182516118eb9190615519565b815181106118fb576118fb6156fb565b60200260200101518f8f5181518110611916576119166156fb565b60200260200101818152505050505050505b60cb546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff9091169060009082906370a0823190602401602060405180830381865afa15801561199b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119bf919061572a565b90506119ca876138b6565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611a37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5b919061572a565b90506000611a698383615519565b9050808e8e516001611a7b9190615530565b81518110611a8b57611a8b6156fb565b60209081029190910101528115611adc57611aa582613aa3565b60da54611ab29043615519565b60dd554360da5560d881905560995460c954611ace9083615583565b611ad89190615548565b60dc555b5050505050505050505050505092915050565b60335473ffffffffffffffffffffffffffffffffffffffff163314611b70576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b60d955565b6060609b805461090390615496565b60335473ffffffffffffffffffffffffffffffffffffffff163314611c05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b611c238173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26133f7565b60d28054600181019091557ff2192e1030363415d7b4fb0406540a0060e8e2fc8982f3f32289379e11fa654601805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff00000000000000000000000000000000000000009283168117909355600092835260d6602090815260408085208054938816939094169290921790925560d582529091208251610f9c92840190614c17565b60d56020528160005260406000208181548110611ce557600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169150829050565b600080611d1a60995490565b905080611d2957505060c95490565b8060c954611d35613b46565b60d754611d429190615519565b611d4c9190615583565b611d569190615548565b91505b5090565b33600090815260986020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915281205482811015611e1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610a67565b611e2d3385610a7f8685615519565b5060019392505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314611eb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b60d254600090611eca90600190615519565b67ffffffffffffffff811115611ee257611ee2614e6e565b604051908082528060200260200182016040528015611f0b578160200160208202803683370190505b5090506000805b60d254811015612008578373ffffffffffffffffffffffffffffffffffffffff1660d28281548110611f4657611f466156fb565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff161415611f7357611ff6565b60d28181548110611f8657611f866156fb565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16838381518110611fc357611fc36156fb565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152611ff3600183615530565b91505b8061200081615812565b915050611f12565b50815161201c9060d2906020850190614c17565b5073ffffffffffffffffffffffffffffffffffffffff8316600090815260d66020908152604080832080547fffffffffffffffffffffffff000000000000000000000000000000000000000016905560d59091528120610b6691614c9d565b600061099333848461313a565b600054610100900460ff16806120a1575060005460ff16155b61212d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610a67565b600054610100900460ff1615801561216c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790555b60cb5473ffffffffffffffffffffffffffffffffffffffff16156121ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e697469616c697a65640000000000000000000000000000000000000000006044820152606401610a67565b600484604001511061225a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4465706f73697420746f6b656e20706f736974696f6e20696e76616c696400006044820152606401610a67565b612262613b9d565b61226a613cc3565b6040517f1526fe27000000000000000000000000000000000000000000000000000000008152600481018890526000908190819073f403c135812408bfbe8713b5a23a04b3d48aae3190631526fe279060240160c060405180830381865afa1580156122da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122fe919061584b565b60cb805473ffffffffffffffffffffffffffffffffffffffff8089167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179091558d51969950929750955060009490911673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc214925061237b915050578751612391565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee5b905081156123fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f436f6e76657820506f6f6c206973206e6f7420616374697665000000000000006044820152606401610a67565b612409848960400151613daf565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461249d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4465706f73697420746f6b656e20696e76616c696400000000000000000000006044820152606401610a67565b6126058473ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa1580156124eb573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261253191908101906158d2565b6040516020016125419190615984565b6040516020818303038152906040528573ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801561259b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526125e191908101906158d2565b6040516020016125f191906159f0565b604051602081830303815290604052613e84565b8a60ca819055508260cf60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612698573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126bc919061572a565b60d08190556126cc90600a615b55565b60c955875160cc805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560208a015160cd8054919093169116179055604088015160ce5560d989905561274062259e9d612a72565b6040517f095ea7b300000000000000000000000000000000000000000000000000000000815273f403c135812408bfbe8713b5a23a04b3d48aae3160048201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602482015273ffffffffffffffffffffffffffffffffffffffff85169063095ea7b3906044016020604051808303816000875af11580156127e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280a9190615b61565b5060005b875181101561288b5761287988828151811061282c5761282c6156fb565b60200260200101516000015189838151811061284a5761284a6156fb565b6020026020010151602001518a8481518110612868576128686156fb565b602002602001015160400151611b84565b8061288381615812565b91505061280e565b50875173ffffffffffffffffffffffffffffffffffffffff1673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2146128d0576128d086600001518760200151610e27565b6128d98a612b6f565b50505050801561290c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b50505050505050565b60d15460009073ffffffffffffffffffffffffffffffffffffffff163314612999576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4e6f742077686974656c69737465642043444f000000000000000000000000006044820152606401610a67565b81156110945760cb546129c49073ffffffffffffffffffffffffffffffffffffffff16333085613fad565b61099733836129d1611d0e565b61400b565b60d15460009073ffffffffffffffffffffffffffffffffffffffff163314612a5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4e6f742077686974656c69737465642043444f000000000000000000000000006044820152606401610a67565b8115611094576109973383612a6d611d0e565b613522565b60335473ffffffffffffffffffffffffffffffffffffffff163314612af3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b80612b5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f426c6f636b732070657220796561722063616e6e6f74206265207a65726f00006044820152606401610a67565b60db55565b60d28181548110610bbf57600080fd5b60335473ffffffffffffffffffffffffffffffffffffffff163314612bf0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b73ffffffffffffffffffffffffffffffffffffffff8116612c93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610a67565b60335460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60335473ffffffffffffffffffffffffffffffffffffffff163314612da2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b60026065541415612e0f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a67565b6002606555612e3573ffffffffffffffffffffffffffffffffffffffff8416828461403b565b5050600160655550565b60335473ffffffffffffffffffffffffffffffffffffffff163314612ec0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b73ffffffffffffffffffffffffffffffffffffffff8116612f3f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a679060208082526004908201527f49535f3000000000000000000000000000000000000000000000000000000000604082015260600190565b60d180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff8316613028576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610a67565b73ffffffffffffffffffffffffffffffffffffffff82166130cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610a67565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526098602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff83166131dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610a67565b73ffffffffffffffffffffffffffffffffffffffff8216613280576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610a67565b73ffffffffffffffffffffffffffffffffffffffff831660009081526097602052604090205481811015613336576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610a67565b6133408282615519565b73ffffffffffffffffffffffffffffffffffffffff8086166000908152609760205260408082209390935590851681529081208054849290613383908490615530565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516133e991815260200190565b60405180910390a350505050565b600282511015613463576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50617468206c656e677468206c657373207468616e20320000000000000000006044820152606401610a67565b8073ffffffffffffffffffffffffffffffffffffffff1682600184516134899190615519565b81518110613499576134996156fb565b602002602001015173ffffffffffffffffffffffffffffffffffffffff161461351e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4c6173742061737365742073686f756c642062652057455448000000000000006044820152606401610a67565b5050565b60c9546000906135328385615583565b61353c9190615548565b90508060d760008282546135509190615519565b909155505060cb5473ffffffffffffffffffffffffffffffffffffffff166135788585614091565b60cf546040517f38d07436000000000000000000000000000000000000000000000000000000008152600481018490526000602482015273ffffffffffffffffffffffffffffffffffffffff909116906338d0743690604401600060405180830381600087803b1580156135eb57600080fd5b505af11580156135ff573d6000803e3d6000fd5b505060ca546040517f441a3e7000000000000000000000000000000000000000000000000000000000815260048101919091526024810185905273f403c135812408bfbe8713b5a23a04b3d48aae31925063441a3e709150604401600060405180830381600087803b15801561367457600080fd5b505af1158015613688573d6000803e3d6000fd5b506136ae9250505073ffffffffffffffffffffffffffffffffffffffff8216868461403b565b509392505050565b80158061375657506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa158015613730573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613754919061572a565b155b6137e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610a67565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610b669084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261427f565b60cc546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff9091169060009082906370a0823190602401602060405180830381865afa158015613929573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061394d919061572a565b60cb549091506000906139759073ffffffffffffffffffffffffffffffffffffffff1661438b565b90506139ad73ffffffffffffffffffffffffffffffffffffffff841673a79828df1850e8a3a3064576f380d90aecdd335960006136b6565b6139e273ffffffffffffffffffffffffffffffffffffffff841673a79828df1850e8a3a3064576f380d90aecdd3359846136b6565b6139ea614cbb565b828160ce54600481106139ff576139ff6156fb565b60200201526040517f384e03db00000000000000000000000000000000000000000000000000000000815273a79828df1850e8a3a3064576f380d90aecdd33599063384e03db90613a5890859085908a90600401615b7e565b6020604051808303816000875af1158015613a77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a9b919061572a565b505050505050565b8060d76000828254613ab59190615530565b909155505060ca546040517f60759fce00000000000000000000000000000000000000000000000000000000815260048101919091526001602482015273f403c135812408bfbe8713b5a23a04b3d48aae31906360759fce90604401600060405180830381600087803b158015613b2b57600080fd5b505af1158015613b3f573d6000803e3d6000fd5b5050505050565b60d95460da54600091908290613b5c9043615519565b60d8549091508015801590613b7057508282105b15613b975782613b808382615519565b613b8a9083615583565b613b949190615548565b93505b50505090565b600054610100900460ff1680613bb6575060005460ff16155b613c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610a67565b600054610100900460ff16158015613c8157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790555b613c89614430565b613c91614544565b8015613cc057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b50565b600054610100900460ff1680613cdc575060005460ff16155b613d68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610a67565b600054610100900460ff16158015613da757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790555b613c916146b4565b6000807390e00ace148ca3b23ac1bc8c240c2a7dd9c2d7f563a77576ef613dd58661438b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161010060405180830381865afa158015613e3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e639190615bd3565b9050808360088110613e7757613e776156fb565b6020020151949350505050565b600054610100900460ff1680613e9d575060005460ff16155b613f29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610a67565b600054610100900460ff16158015613f6857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790555b613f70614430565b613f7a83836147ce565b8015610b6657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055505050565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052610f9c9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401613834565b600061401683613aa3565b8160c954846140259190615583565b61402f9190615548565b9050610a8a848261490d565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610b669084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401613834565b73ffffffffffffffffffffffffffffffffffffffff8216614134576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610a67565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260976020526040902054818110156141ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610a67565b6141f48282615519565b73ffffffffffffffffffffffffffffffffffffffff84166000908152609760205260408120919091556099805484929061422f908490615519565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200161312d565b60006142e1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16614a2d9092919063ffffffff16565b805190915015610b6657808060200190518101906142ff9190615b61565b610b66576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a67565b6040517fbdf475c300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526000907390e00ace148ca3b23ac1bc8c240c2a7dd9c2d7f59063bdf475c390602401602060405180830381865afa15801561440c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109979190615c5b565b600054610100900460ff1680614449575060005460ff16155b6144d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610a67565b600054610100900460ff16158015613c9157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790558015613cc057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b600054610100900460ff168061455d575060005460ff16155b6145e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610a67565b600054610100900460ff1615801561462857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790555b603380547fffffffffffffffffffffffff0000000000000000000000000000000000000000163390811790915560405181906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3508015613cc057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b600054610100900460ff16806146cd575060005460ff16155b614759576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610a67565b600054610100900460ff1615801561479857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790555b60016065558015613cc057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b600054610100900460ff16806147e7575060005460ff16155b614873576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610a67565b600054610100900460ff161580156148b257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790555b82516148c590609a906020860190614cd9565b5081516148d990609b906020850190614cd9565b508015610b6657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055505050565b73ffffffffffffffffffffffffffffffffffffffff821661498a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610a67565b806099600082825461499c9190615530565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600090815260976020526040812080548392906149d6908490615530565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6060614a3c8484600085614a44565b949350505050565b606082471015614ad6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610a67565b843b614b3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a67565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051614b679190615c78565b60006040518083038185875af1925050503d8060008114614ba4576040519150601f19603f3d011682016040523d82523d6000602084013e614ba9565b606091505b5091509150614bb9828286614bc4565b979650505050505050565b60608315614bd3575081610a8a565b825115614be35782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a679190614d8e565b828054828255906000526020600020908101928215614c91579160200282015b82811115614c9157825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190614c37565b50611d59929150614d4d565b5080546000825590600052602060002090810190613cc09190614d4d565b60405180608001604052806004906020820280368337509192915050565b828054614ce590615496565b90600052602060002090601f016020900481019282614d075760008555614c91565b82601f10614d2057805160ff1916838001178555614c91565b82800160010185558215614c91579182015b82811115614c91578251825591602001919060010190614d32565b5b80821115611d595760008155600101614d4e565b60005b83811015614d7d578181015183820152602001614d65565b83811115610f9c5750506000910152565b6020815260008251806020840152614dad816040850160208701614d62565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b73ffffffffffffffffffffffffffffffffffffffff81168114613cc057600080fd5b60008060408385031215614e1457600080fd5b8235614e1f81614ddf565b946020939093013593505050565b600080600060608486031215614e4257600080fd5b8335614e4d81614ddf565b92506020840135614e5d81614ddf565b929592945050506040919091013590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715614ec057614ec0614e6e565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614f0d57614f0d614e6e565b604052919050565b600067ffffffffffffffff821115614f2f57614f2f614e6e565b5060051b60200190565b600082601f830112614f4a57600080fd5b81356020614f5f614f5a83614f15565b614ec6565b82815260059290921b84018101918181019086841115614f7e57600080fd5b8286015b84811015614fa2578035614f9581614ddf565b8352918301918301614f82565b509695505050505050565b60008060408385031215614fc057600080fd5b8235614fcb81614ddf565b9150602083013567ffffffffffffffff811115614fe757600080fd5b614ff385828601614f39565b9150509250929050565b60006020828403121561500f57600080fd5b5035919050565b60006020828403121561502857600080fd5b8135610a8a81614ddf565b6000806040838503121561504657600080fd5b823561505181614ddf565b9150602083013561506181614ddf565b809150509250929050565b6000806020838503121561507f57600080fd5b823567ffffffffffffffff8082111561509757600080fd5b818501915085601f8301126150ab57600080fd5b8135818111156150ba57600080fd5b8660208285010111156150cc57600080fd5b60209290920196919550909350505050565b6020808252825182820181905260009190848201906040850190845b81811015615116578351835292840192918401916001016150fa565b50909695505050505050565b60008060006060848603121561513757600080fd5b833561514281614ddf565b9250602084013561515281614ddf565b9150604084013567ffffffffffffffff81111561516e57600080fd5b61517a86828701614f39565b9150509250925092565b600082601f83011261519557600080fd5b813560206151a5614f5a83614f15565b82815260059290921b840181019181810190868411156151c457600080fd5b8286015b84811015614fa257803567ffffffffffffffff808211156151e95760008081fd5b81890191506060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156152225760008081fd5b61522a614e9d565b8784013561523781614ddf565b815260408481013561524881614ddf565b828a015291840135918383111561525f5760008081fd5b61526d8d8a85880101614f39565b9082015286525050509183019183016151c8565b60006040828403121561529357600080fd5b6040516040810167ffffffffffffffff82821081831117156152b7576152b7614e6e565b81604052829350843591506152cb82614ddf565b908252602084013590808211156152e157600080fd5b506152ee85828601614f39565b6020830152505092915050565b60008060008060008086880361010081121561531657600080fd5b87359650602088013561532881614ddf565b95506040880135945060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08201121561536157600080fd5b5061536a614e9d565b606088013561537881614ddf565b8152608088013561538881614ddf565b602082015260a08801356040820152925060c087013567ffffffffffffffff808211156153b457600080fd5b6153c08a838b01615184565b935060e08901359150808211156153d657600080fd5b506153e389828a01615281565b9150509295509295509295565b600081518084526020808501945080840160005b8381101561543657815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101615404565b509495945050505050565b602081526000610a8a60208301846153f0565b60008060006060848603121561546957600080fd5b833561547481614ddf565b925060208401359150604084013561548b81614ddf565b809150509250925092565b600181811c908216806154aa57607f821691505b602082108114156154e4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561552b5761552b6154ea565b500390565b60008219821115615543576155436154ea565b500190565b60008261557e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156155bb576155bb6154ea565b500290565b8015158114613cc057600080fd5b600082601f8301126155df57600080fd5b813560206155ef614f5a83614f15565b82815260059290921b8401810191818101908684111561560e57600080fd5b8286015b84811015614fa2578035615625816155c0565b8352918301918301615612565b6000806000806080858703121561564857600080fd5b843567ffffffffffffffff8082111561566057600080fd5b818701915087601f83011261567457600080fd5b81356020615684614f5a83614f15565b82815260059290921b8401810191818101908b8411156156a357600080fd5b948201945b838610156156c1578535825294820194908201906156a8565b985050880135925050808211156156d757600080fd5b506156e4878288016155ce565b949794965050505060408301359260600135919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561573c57600080fd5b5051919050565b85815284602082015260a06040820152600061576260a08301866153f0565b73ffffffffffffffffffffffffffffffffffffffff94909416606083015250608001529392505050565b6000602080838503121561579f57600080fd5b825167ffffffffffffffff8111156157b657600080fd5b8301601f810185136157c757600080fd5b80516157d5614f5a82614f15565b81815260059190911b820183019083810190878311156157f457600080fd5b928401925b82841015614bb9578351825292840192908401906157f9565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415615844576158446154ea565b5060010190565b60008060008060008060c0878903121561586457600080fd5b865161586f81614ddf565b602088015190965061588081614ddf565b604088015190955061589181614ddf565b60608801519094506158a281614ddf565b60808801519093506158b381614ddf565b60a08801519092506158c4816155c0565b809150509295509295509295565b6000602082840312156158e457600080fd5b815167ffffffffffffffff808211156158fc57600080fd5b818401915084601f83011261591057600080fd5b81518181111561592257615922614e6e565b61595360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614ec6565b915080825285602082850101111561596a57600080fd5b61597b816020840160208601614d62565b50949350505050565b7f49646c65200000000000000000000000000000000000000000000000000000008152600082516159bc816005850160208701614d62565b7f20436f6e766578205374726174656779000000000000000000000000000000006005939091019283015250601501919050565b7f69646c6543767800000000000000000000000000000000000000000000000000815260008251615a28816007850160208701614d62565b9190910160070192915050565b600181815b80851115615a8e57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615a7457615a746154ea565b80851615615a8157918102915b93841c9390800290615a3a565b509250929050565b600082615aa557506001610997565b81615ab257506000610997565b8160018114615ac85760028114615ad257615aee565b6001915050610997565b60ff841115615ae357615ae36154ea565b50506001821b610997565b5060208310610133831016604e8410600b8410161715615b11575081810a610997565b615b1b8383615a35565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615b4d57615b4d6154ea565b029392505050565b6000610a8a8383615a96565b600060208284031215615b7357600080fd5b8151610a8a816155c0565b73ffffffffffffffffffffffffffffffffffffffff8416815260c0810160208083018560005b6004811015615bc157815183529183019190830190600101615ba4565b505050508260a0830152949350505050565b6000610100808385031215615be757600080fd5b83601f840112615bf657600080fd5b60405181810181811067ffffffffffffffff82111715615c1857615c18614e6e565b604052908301908085831115615c2d57600080fd5b845b83811015615c50578051615c4281614ddf565b825260209182019101615c2f565b509095945050505050565b600060208284031215615c6d57600080fd5b8151610a8a81614ddf565b60008251615c8a818460208701614d62565b919091019291505056fea2646970667358221220f626acbfa01f86aa35120bddd6bab78fcfceeb81c2cfb61690447093033c1ac164736f6c634300080a0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103c55760003560e01c80638d934485116101ff578063b7e2ce101161011a578063e8fd22d1116100ad578063f2fde38b1161007c578063f2fde38b1461089d578063f640d508146108b0578063f7c69187146108c3578063fc0c546a146108d657600080fd5b8063e8fd22d11461085d578063e98e779c14610870578063ea1cd58d14610879578063edd636fb1461089457600080fd5b8063d37db1d2116100e9578063d37db1d2146107e8578063db006a75146107f1578063dd62ed3e14610804578063e5fa2b701461084a57600080fd5b8063b7e2ce10146107a9578063c4f59f9b146107b2578063c7c4ff46146107c1578063cdfbe9c5146107e157600080fd5b8063a035b1fe11610192578063a9059cbb11610161578063a9059cbb14610755578063ad5c464814610768578063af4a22dc14610783578063b6b55f251461079657600080fd5b8063a035b1fe1461071f578063a27eccc114610727578063a457c2d71461072f578063a4d5e67c1461074257600080fd5b806394929dc1116101ce57806394929dc1146106de57806395d89b41146106f1578063996a70f3146106f95780639a49cb931461070c57600080fd5b80638d9344851461067c5780638da5cb5b146106855780638eaaca57146106a35780638ec71e0c146106be57600080fd5b8063646780df116102ef57806376bfa52f116102825780638322fff2116102515780638322fff214610626578063845bc80414610641578063852a12e314610649578063887ee9711461065c57600080fd5b806376bfa52f146105d757806379623480146105ea5780637d9a8e001461060a57806381f5ae7e1461061d57600080fd5b8063715018a6116102be578063715018a6146105a6578063747efea1146105ae57806375114046146105b457806375b0ffd1146105bc57600080fd5b8063646780df1461052757806366666aa914610547578063704a19271461056757806370a082311461057057600080fd5b8063313ce567116103675780634521e248116103365780634521e248146104cc5780634e0a873a146104df5780635322e60a146104e85780635f783e18146104f157600080fd5b8063313ce567146104935780633145b35c146104a857806339509351146104b15780633b97e856146104c457600080fd5b806318160ddd116103a357806318160ddd146104505780631baaade51461046257806323b872dd1461046b57806325e23ab91461047e57600080fd5b806306fdde03146103ca578063095ea7b3146103e8578063138821421461040b575b600080fd5b6103d26108f4565b6040516103df9190614d8e565b60405180910390f35b6103fb6103f6366004614e01565b610986565b60405190151581526020016103df565b60d15461042b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103df565b6099545b6040519081526020016103df565b61045460dc5481565b6103fb610479366004614e2d565b61099d565b61049161048c366004614fad565b610a91565b005b60d05460405160ff90911681526020016103df565b61045460d85481565b6103fb6104bf366004614e01565b610b6b565b60d054610454565b61042b6104da366004614ffd565b610baf565b61045460d75481565b61045460c95481565b61042b6104ff366004615016565b60d66020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60cb5461042b9073ffffffffffffffffffffffffffffffffffffffff1681565b60cf5461042b9073ffffffffffffffffffffffffffffffffffffffff1681565b61045460dd5481565b61045461057e366004615016565b73ffffffffffffffffffffffffffffffffffffffff1660009081526097602052604090205490565b610491610be6565b3061042b565b610454600481565b61042b73f403c135812408bfbe8713b5a23a04b3d48aae3181565b6104916105e5366004615033565b610cd6565b60d45461042b9073ffffffffffffffffffffffffffffffffffffffff1681565b610491610618366004614fad565b610e27565b61045460da5481565b61042b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b610454610fa2565b610454610657366004614ffd565b610fd1565b60cc5461042b9073ffffffffffffffffffffffffffffffffffffffff1681565b61045460ca5481565b60335473ffffffffffffffffffffffffffffffffffffffff1661042b565b61042b7390e00ace148ca3b23ac1bc8c240c2a7dd9c2d7f581565b6106d16106cc36600461506c565b611099565b6040516103df91906150de565b6104916106ec366004614ffd565b611aef565b6103d2611b75565b610491610707366004615122565b611b84565b61042b61071a366004614e01565b611cc9565b610454611d0e565b60c954610454565b6103fb61073d366004614e01565b611d5d565b610491610750366004615016565b611e37565b6103fb610763366004614e01565b61207b565b61042b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b6104916107913660046152fb565b612088565b6104546107a4366004614ffd565b612915565b61045460d05481565b60606040516103df9190615441565b60cd5461042b9073ffffffffffffffffffffffffffffffffffffffff1681565b6000610454565b61045460db5481565b6104546107ff366004614ffd565b6129d6565b610454610812366004615033565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260986020908152604080832093909416825291909152205490565b610491610858366004614ffd565b612a72565b61042b61086b366004614ffd565b612b5f565b61045460ce5481565b61042b73a79828df1850e8a3a3064576f380d90aecdd335981565b61045460d95481565b6104916108ab366004615016565b612b6f565b6104916108be366004615454565b612d21565b6104916108d1366004615016565b612e3f565b60cb5473ffffffffffffffffffffffffffffffffffffffff1661042b565b6060609a805461090390615496565b80601f016020809104026020016040519081016040528092919081815260200182805461092f90615496565b801561097c5780601f106109515761010080835404028352916020019161097c565b820191906000526020600020905b81548152906001019060200180831161095f57829003601f168201915b5050505050905090565b6000610993338484612f86565b5060015b92915050565b60006109aa84848461313a565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260986020908152604080832033845290915290205482811015610a70576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206160448201527f6c6c6f77616e636500000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610a848533610a7f8685615519565b612f86565b60019150505b9392505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610b12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b610b308173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26133f7565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260d5602090815260409091208251610b6692840190614c17565b505050565b33600081815260986020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091610993918590610a7f908690615530565b60d38181548110610bbf57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60335473ffffffffffffffffffffffffffffffffffffffff163314610c67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b60335460405160009173ffffffffffffffffffffffffffffffffffffffff16907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610d57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b73ffffffffffffffffffffffffffffffffffffffff8116610dd4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f526f757465722069732061646472657373207a65726f000000000000000000006044820152606401610a67565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260d66020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ea8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b60cc5473ffffffffffffffffffffffffffffffffffffffff1673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2811415610f3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4465706f736974206173736574206973205745544800000000000000000000006044820152606401610a67565b610f4982826133f7565b60d480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff85161790558151610f9c9060d3906020850190614c17565b50505050565b600060dd5460db54610fb49190615548565b60dc54610fc19190615583565b610fcc906064615583565b905090565b60d15460009073ffffffffffffffffffffffffffffffffffffffff163314611055576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4e6f742077686974656c69737465642043444f000000000000000000000000006044820152606401610a67565b8115611094576000611065611d0e565b905060008160c954856110789190615583565b6110829190615548565b905061108f338284613522565b925050505b919050565b60d15460609073ffffffffffffffffffffffffffffffffffffffff16331461111d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4e6f742077686974656c69737465642043444f000000000000000000000000006044820152606401610a67565b600060d280548060200260200160405190810160405280929190818152602001828054801561118257602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311611157575b50505050509050805160026111979190615530565b67ffffffffffffffff8111156111af576111af614e6e565b6040519080825280602002602001820160405280156111d8578160200160208202803683370190505b5091506000815167ffffffffffffffff8111156111f7576111f7614e6e565b604051908082528060200260200182016040528015611220578160200160208202803683370190505b5090506000825167ffffffffffffffff81111561123f5761123f614e6e565b604051908082528060200260200182016040528015611268578160200160208202803683370190505b50905060008061127a87890189615632565b60cf54604080517f3d18b9120000000000000000000000000000000000000000000000000000000081529051959950939750919550935073ffffffffffffffffffffffffffffffffffffffff1691633d18b9129160048082019260009290919082900301818387803b1580156112ef57600080fd5b505af1158015611303573d6000803e3d6000fd5b5050505060008060008060005b89518110156116425787818151811061132b5761132b6156fb565b60200260200101511561133d57611630565b89818151811061134f5761134f6156fb565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290955085945073ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa1580156113ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ee919061572a565b9250826113fa57611630565b73ffffffffffffffffffffffffffffffffffffffff808616600090815260d66020526040812054821693506114339186169084906136b6565b61145473ffffffffffffffffffffffffffffffffffffffff851683856136b6565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260d560209081526040808320805482518185028101850190935280835291929091908301828280156114d857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116114ad575b505050505090506000815167ffffffffffffffff8111156114fb576114fb614e6e565b604051908082528060200260200182016040528015611524578160200160208202803683370190505b5090508373ffffffffffffffffffffffffffffffffffffffff166338ed1739868d8681518110611556576115566156fb565b60200260200101518530426040518663ffffffff1660e01b8152600401611581959493929190615743565b6000604051808303816000875af11580156115a0573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526115e6919081019061578c565b905080600182516115f79190615519565b81518110611607576116076156fb565b60200260200101518d8481518110611621576116216156fb565b60200260200101818152505050505b8061163a81615812565b915050611310565b5060cc5473ffffffffffffffffffffffffffffffffffffffff1673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2146119285760d4546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29173ffffffffffffffffffffffffffffffffffffffff169060009083906370a0823190602401602060405180830381865afa1580156116fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611721919061572a565b905061174573ffffffffffffffffffffffffffffffffffffffff84168360006136b6565b61176673ffffffffffffffffffffffffffffffffffffffff841683836136b6565b600060d38054806020026020016040519081016040528092919081815260200182805480156117cb57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116117a0575b505050505090506000815167ffffffffffffffff8111156117ee576117ee614e6e565b604051908082528060200260200182016040528015611817578160200160208202803683370190505b506040517f38ed173900000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8516906338ed1739906118759086908f90879030904290600401615743565b6000604051808303816000875af1158015611894573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526118da919081019061578c565b905080600182516118eb9190615519565b815181106118fb576118fb6156fb565b60200260200101518f8f5181518110611916576119166156fb565b60200260200101818152505050505050505b60cb546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff9091169060009082906370a0823190602401602060405180830381865afa15801561199b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119bf919061572a565b90506119ca876138b6565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611a37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5b919061572a565b90506000611a698383615519565b9050808e8e516001611a7b9190615530565b81518110611a8b57611a8b6156fb565b60209081029190910101528115611adc57611aa582613aa3565b60da54611ab29043615519565b60dd554360da5560d881905560995460c954611ace9083615583565b611ad89190615548565b60dc555b5050505050505050505050505092915050565b60335473ffffffffffffffffffffffffffffffffffffffff163314611b70576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b60d955565b6060609b805461090390615496565b60335473ffffffffffffffffffffffffffffffffffffffff163314611c05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b611c238173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26133f7565b60d28054600181019091557ff2192e1030363415d7b4fb0406540a0060e8e2fc8982f3f32289379e11fa654601805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff00000000000000000000000000000000000000009283168117909355600092835260d6602090815260408085208054938816939094169290921790925560d582529091208251610f9c92840190614c17565b60d56020528160005260406000208181548110611ce557600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169150829050565b600080611d1a60995490565b905080611d2957505060c95490565b8060c954611d35613b46565b60d754611d429190615519565b611d4c9190615583565b611d569190615548565b91505b5090565b33600090815260986020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915281205482811015611e1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610a67565b611e2d3385610a7f8685615519565b5060019392505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314611eb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b60d254600090611eca90600190615519565b67ffffffffffffffff811115611ee257611ee2614e6e565b604051908082528060200260200182016040528015611f0b578160200160208202803683370190505b5090506000805b60d254811015612008578373ffffffffffffffffffffffffffffffffffffffff1660d28281548110611f4657611f466156fb565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff161415611f7357611ff6565b60d28181548110611f8657611f866156fb565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16838381518110611fc357611fc36156fb565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152611ff3600183615530565b91505b8061200081615812565b915050611f12565b50815161201c9060d2906020850190614c17565b5073ffffffffffffffffffffffffffffffffffffffff8316600090815260d66020908152604080832080547fffffffffffffffffffffffff000000000000000000000000000000000000000016905560d59091528120610b6691614c9d565b600061099333848461313a565b600054610100900460ff16806120a1575060005460ff16155b61212d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610a67565b600054610100900460ff1615801561216c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790555b60cb5473ffffffffffffffffffffffffffffffffffffffff16156121ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e697469616c697a65640000000000000000000000000000000000000000006044820152606401610a67565b600484604001511061225a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4465706f73697420746f6b656e20706f736974696f6e20696e76616c696400006044820152606401610a67565b612262613b9d565b61226a613cc3565b6040517f1526fe27000000000000000000000000000000000000000000000000000000008152600481018890526000908190819073f403c135812408bfbe8713b5a23a04b3d48aae3190631526fe279060240160c060405180830381865afa1580156122da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122fe919061584b565b60cb805473ffffffffffffffffffffffffffffffffffffffff8089167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179091558d51969950929750955060009490911673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc214925061237b915050578751612391565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee5b905081156123fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f436f6e76657820506f6f6c206973206e6f7420616374697665000000000000006044820152606401610a67565b612409848960400151613daf565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461249d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4465706f73697420746f6b656e20696e76616c696400000000000000000000006044820152606401610a67565b6126058473ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa1580156124eb573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261253191908101906158d2565b6040516020016125419190615984565b6040516020818303038152906040528573ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801561259b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526125e191908101906158d2565b6040516020016125f191906159f0565b604051602081830303815290604052613e84565b8a60ca819055508260cf60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612698573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126bc919061572a565b60d08190556126cc90600a615b55565b60c955875160cc805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560208a015160cd8054919093169116179055604088015160ce5560d989905561274062259e9d612a72565b6040517f095ea7b300000000000000000000000000000000000000000000000000000000815273f403c135812408bfbe8713b5a23a04b3d48aae3160048201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602482015273ffffffffffffffffffffffffffffffffffffffff85169063095ea7b3906044016020604051808303816000875af11580156127e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280a9190615b61565b5060005b875181101561288b5761287988828151811061282c5761282c6156fb565b60200260200101516000015189838151811061284a5761284a6156fb565b6020026020010151602001518a8481518110612868576128686156fb565b602002602001015160400151611b84565b8061288381615812565b91505061280e565b50875173ffffffffffffffffffffffffffffffffffffffff1673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2146128d0576128d086600001518760200151610e27565b6128d98a612b6f565b50505050801561290c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b50505050505050565b60d15460009073ffffffffffffffffffffffffffffffffffffffff163314612999576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4e6f742077686974656c69737465642043444f000000000000000000000000006044820152606401610a67565b81156110945760cb546129c49073ffffffffffffffffffffffffffffffffffffffff16333085613fad565b61099733836129d1611d0e565b61400b565b60d15460009073ffffffffffffffffffffffffffffffffffffffff163314612a5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4e6f742077686974656c69737465642043444f000000000000000000000000006044820152606401610a67565b8115611094576109973383612a6d611d0e565b613522565b60335473ffffffffffffffffffffffffffffffffffffffff163314612af3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b80612b5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f426c6f636b732070657220796561722063616e6e6f74206265207a65726f00006044820152606401610a67565b60db55565b60d28181548110610bbf57600080fd5b60335473ffffffffffffffffffffffffffffffffffffffff163314612bf0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b73ffffffffffffffffffffffffffffffffffffffff8116612c93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610a67565b60335460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60335473ffffffffffffffffffffffffffffffffffffffff163314612da2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b60026065541415612e0f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a67565b6002606555612e3573ffffffffffffffffffffffffffffffffffffffff8416828461403b565b5050600160655550565b60335473ffffffffffffffffffffffffffffffffffffffff163314612ec0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a67565b73ffffffffffffffffffffffffffffffffffffffff8116612f3f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a679060208082526004908201527f49535f3000000000000000000000000000000000000000000000000000000000604082015260600190565b60d180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff8316613028576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610a67565b73ffffffffffffffffffffffffffffffffffffffff82166130cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610a67565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526098602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff83166131dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610a67565b73ffffffffffffffffffffffffffffffffffffffff8216613280576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610a67565b73ffffffffffffffffffffffffffffffffffffffff831660009081526097602052604090205481811015613336576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610a67565b6133408282615519565b73ffffffffffffffffffffffffffffffffffffffff8086166000908152609760205260408082209390935590851681529081208054849290613383908490615530565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516133e991815260200190565b60405180910390a350505050565b600282511015613463576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50617468206c656e677468206c657373207468616e20320000000000000000006044820152606401610a67565b8073ffffffffffffffffffffffffffffffffffffffff1682600184516134899190615519565b81518110613499576134996156fb565b602002602001015173ffffffffffffffffffffffffffffffffffffffff161461351e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4c6173742061737365742073686f756c642062652057455448000000000000006044820152606401610a67565b5050565b60c9546000906135328385615583565b61353c9190615548565b90508060d760008282546135509190615519565b909155505060cb5473ffffffffffffffffffffffffffffffffffffffff166135788585614091565b60cf546040517f38d07436000000000000000000000000000000000000000000000000000000008152600481018490526000602482015273ffffffffffffffffffffffffffffffffffffffff909116906338d0743690604401600060405180830381600087803b1580156135eb57600080fd5b505af11580156135ff573d6000803e3d6000fd5b505060ca546040517f441a3e7000000000000000000000000000000000000000000000000000000000815260048101919091526024810185905273f403c135812408bfbe8713b5a23a04b3d48aae31925063441a3e709150604401600060405180830381600087803b15801561367457600080fd5b505af1158015613688573d6000803e3d6000fd5b506136ae9250505073ffffffffffffffffffffffffffffffffffffffff8216868461403b565b509392505050565b80158061375657506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa158015613730573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613754919061572a565b155b6137e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610a67565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610b669084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261427f565b60cc546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff9091169060009082906370a0823190602401602060405180830381865afa158015613929573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061394d919061572a565b60cb549091506000906139759073ffffffffffffffffffffffffffffffffffffffff1661438b565b90506139ad73ffffffffffffffffffffffffffffffffffffffff841673a79828df1850e8a3a3064576f380d90aecdd335960006136b6565b6139e273ffffffffffffffffffffffffffffffffffffffff841673a79828df1850e8a3a3064576f380d90aecdd3359846136b6565b6139ea614cbb565b828160ce54600481106139ff576139ff6156fb565b60200201526040517f384e03db00000000000000000000000000000000000000000000000000000000815273a79828df1850e8a3a3064576f380d90aecdd33599063384e03db90613a5890859085908a90600401615b7e565b6020604051808303816000875af1158015613a77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a9b919061572a565b505050505050565b8060d76000828254613ab59190615530565b909155505060ca546040517f60759fce00000000000000000000000000000000000000000000000000000000815260048101919091526001602482015273f403c135812408bfbe8713b5a23a04b3d48aae31906360759fce90604401600060405180830381600087803b158015613b2b57600080fd5b505af1158015613b3f573d6000803e3d6000fd5b5050505050565b60d95460da54600091908290613b5c9043615519565b60d8549091508015801590613b7057508282105b15613b975782613b808382615519565b613b8a9083615583565b613b949190615548565b93505b50505090565b600054610100900460ff1680613bb6575060005460ff16155b613c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610a67565b600054610100900460ff16158015613c8157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790555b613c89614430565b613c91614544565b8015613cc057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b50565b600054610100900460ff1680613cdc575060005460ff16155b613d68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610a67565b600054610100900460ff16158015613da757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790555b613c916146b4565b6000807390e00ace148ca3b23ac1bc8c240c2a7dd9c2d7f563a77576ef613dd58661438b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161010060405180830381865afa158015613e3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e639190615bd3565b9050808360088110613e7757613e776156fb565b6020020151949350505050565b600054610100900460ff1680613e9d575060005460ff16155b613f29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610a67565b600054610100900460ff16158015613f6857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790555b613f70614430565b613f7a83836147ce565b8015610b6657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055505050565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052610f9c9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401613834565b600061401683613aa3565b8160c954846140259190615583565b61402f9190615548565b9050610a8a848261490d565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610b669084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401613834565b73ffffffffffffffffffffffffffffffffffffffff8216614134576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610a67565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260976020526040902054818110156141ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610a67565b6141f48282615519565b73ffffffffffffffffffffffffffffffffffffffff84166000908152609760205260408120919091556099805484929061422f908490615519565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200161312d565b60006142e1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16614a2d9092919063ffffffff16565b805190915015610b6657808060200190518101906142ff9190615b61565b610b66576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a67565b6040517fbdf475c300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526000907390e00ace148ca3b23ac1bc8c240c2a7dd9c2d7f59063bdf475c390602401602060405180830381865afa15801561440c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109979190615c5b565b600054610100900460ff1680614449575060005460ff16155b6144d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610a67565b600054610100900460ff16158015613c9157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790558015613cc057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b600054610100900460ff168061455d575060005460ff16155b6145e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610a67565b600054610100900460ff1615801561462857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790555b603380547fffffffffffffffffffffffff0000000000000000000000000000000000000000163390811790915560405181906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3508015613cc057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b600054610100900460ff16806146cd575060005460ff16155b614759576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610a67565b600054610100900460ff1615801561479857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790555b60016065558015613cc057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b600054610100900460ff16806147e7575060005460ff16155b614873576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610a67565b600054610100900460ff161580156148b257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790555b82516148c590609a906020860190614cd9565b5081516148d990609b906020850190614cd9565b508015610b6657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055505050565b73ffffffffffffffffffffffffffffffffffffffff821661498a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610a67565b806099600082825461499c9190615530565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600090815260976020526040812080548392906149d6908490615530565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6060614a3c8484600085614a44565b949350505050565b606082471015614ad6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610a67565b843b614b3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a67565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051614b679190615c78565b60006040518083038185875af1925050503d8060008114614ba4576040519150601f19603f3d011682016040523d82523d6000602084013e614ba9565b606091505b5091509150614bb9828286614bc4565b979650505050505050565b60608315614bd3575081610a8a565b825115614be35782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a679190614d8e565b828054828255906000526020600020908101928215614c91579160200282015b82811115614c9157825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190614c37565b50611d59929150614d4d565b5080546000825590600052602060002090810190613cc09190614d4d565b60405180608001604052806004906020820280368337509192915050565b828054614ce590615496565b90600052602060002090601f016020900481019282614d075760008555614c91565b82601f10614d2057805160ff1916838001178555614c91565b82800160010185558215614c91579182015b82811115614c91578251825591602001919060010190614d32565b5b80821115611d595760008155600101614d4e565b60005b83811015614d7d578181015183820152602001614d65565b83811115610f9c5750506000910152565b6020815260008251806020840152614dad816040850160208701614d62565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b73ffffffffffffffffffffffffffffffffffffffff81168114613cc057600080fd5b60008060408385031215614e1457600080fd5b8235614e1f81614ddf565b946020939093013593505050565b600080600060608486031215614e4257600080fd5b8335614e4d81614ddf565b92506020840135614e5d81614ddf565b929592945050506040919091013590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715614ec057614ec0614e6e565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614f0d57614f0d614e6e565b604052919050565b600067ffffffffffffffff821115614f2f57614f2f614e6e565b5060051b60200190565b600082601f830112614f4a57600080fd5b81356020614f5f614f5a83614f15565b614ec6565b82815260059290921b84018101918181019086841115614f7e57600080fd5b8286015b84811015614fa2578035614f9581614ddf565b8352918301918301614f82565b509695505050505050565b60008060408385031215614fc057600080fd5b8235614fcb81614ddf565b9150602083013567ffffffffffffffff811115614fe757600080fd5b614ff385828601614f39565b9150509250929050565b60006020828403121561500f57600080fd5b5035919050565b60006020828403121561502857600080fd5b8135610a8a81614ddf565b6000806040838503121561504657600080fd5b823561505181614ddf565b9150602083013561506181614ddf565b809150509250929050565b6000806020838503121561507f57600080fd5b823567ffffffffffffffff8082111561509757600080fd5b818501915085601f8301126150ab57600080fd5b8135818111156150ba57600080fd5b8660208285010111156150cc57600080fd5b60209290920196919550909350505050565b6020808252825182820181905260009190848201906040850190845b81811015615116578351835292840192918401916001016150fa565b50909695505050505050565b60008060006060848603121561513757600080fd5b833561514281614ddf565b9250602084013561515281614ddf565b9150604084013567ffffffffffffffff81111561516e57600080fd5b61517a86828701614f39565b9150509250925092565b600082601f83011261519557600080fd5b813560206151a5614f5a83614f15565b82815260059290921b840181019181810190868411156151c457600080fd5b8286015b84811015614fa257803567ffffffffffffffff808211156151e95760008081fd5b81890191506060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156152225760008081fd5b61522a614e9d565b8784013561523781614ddf565b815260408481013561524881614ddf565b828a015291840135918383111561525f5760008081fd5b61526d8d8a85880101614f39565b9082015286525050509183019183016151c8565b60006040828403121561529357600080fd5b6040516040810167ffffffffffffffff82821081831117156152b7576152b7614e6e565b81604052829350843591506152cb82614ddf565b908252602084013590808211156152e157600080fd5b506152ee85828601614f39565b6020830152505092915050565b60008060008060008086880361010081121561531657600080fd5b87359650602088013561532881614ddf565b95506040880135945060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08201121561536157600080fd5b5061536a614e9d565b606088013561537881614ddf565b8152608088013561538881614ddf565b602082015260a08801356040820152925060c087013567ffffffffffffffff808211156153b457600080fd5b6153c08a838b01615184565b935060e08901359150808211156153d657600080fd5b506153e389828a01615281565b9150509295509295509295565b600081518084526020808501945080840160005b8381101561543657815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101615404565b509495945050505050565b602081526000610a8a60208301846153f0565b60008060006060848603121561546957600080fd5b833561547481614ddf565b925060208401359150604084013561548b81614ddf565b809150509250925092565b600181811c908216806154aa57607f821691505b602082108114156154e4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561552b5761552b6154ea565b500390565b60008219821115615543576155436154ea565b500190565b60008261557e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156155bb576155bb6154ea565b500290565b8015158114613cc057600080fd5b600082601f8301126155df57600080fd5b813560206155ef614f5a83614f15565b82815260059290921b8401810191818101908684111561560e57600080fd5b8286015b84811015614fa2578035615625816155c0565b8352918301918301615612565b6000806000806080858703121561564857600080fd5b843567ffffffffffffffff8082111561566057600080fd5b818701915087601f83011261567457600080fd5b81356020615684614f5a83614f15565b82815260059290921b8401810191818101908b8411156156a357600080fd5b948201945b838610156156c1578535825294820194908201906156a8565b985050880135925050808211156156d757600080fd5b506156e4878288016155ce565b949794965050505060408301359260600135919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561573c57600080fd5b5051919050565b85815284602082015260a06040820152600061576260a08301866153f0565b73ffffffffffffffffffffffffffffffffffffffff94909416606083015250608001529392505050565b6000602080838503121561579f57600080fd5b825167ffffffffffffffff8111156157b657600080fd5b8301601f810185136157c757600080fd5b80516157d5614f5a82614f15565b81815260059190911b820183019083810190878311156157f457600080fd5b928401925b82841015614bb9578351825292840192908401906157f9565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415615844576158446154ea565b5060010190565b60008060008060008060c0878903121561586457600080fd5b865161586f81614ddf565b602088015190965061588081614ddf565b604088015190955061589181614ddf565b60608801519094506158a281614ddf565b60808801519093506158b381614ddf565b60a08801519092506158c4816155c0565b809150509295509295509295565b6000602082840312156158e457600080fd5b815167ffffffffffffffff808211156158fc57600080fd5b818401915084601f83011261591057600080fd5b81518181111561592257615922614e6e565b61595360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614ec6565b915080825285602082850101111561596a57600080fd5b61597b816020840160208601614d62565b50949350505050565b7f49646c65200000000000000000000000000000000000000000000000000000008152600082516159bc816005850160208701614d62565b7f20436f6e766578205374726174656779000000000000000000000000000000006005939091019283015250601501919050565b7f69646c6543767800000000000000000000000000000000000000000000000000815260008251615a28816007850160208701614d62565b9190910160070192915050565b600181815b80851115615a8e57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615a7457615a746154ea565b80851615615a8157918102915b93841c9390800290615a3a565b509250929050565b600082615aa557506001610997565b81615ab257506000610997565b8160018114615ac85760028114615ad257615aee565b6001915050610997565b60ff841115615ae357615ae36154ea565b50506001821b610997565b5060208310610133831016604e8410600b8410161715615b11575081810a610997565b615b1b8383615a35565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615b4d57615b4d6154ea565b029392505050565b6000610a8a8383615a96565b600060208284031215615b7357600080fd5b8151610a8a816155c0565b73ffffffffffffffffffffffffffffffffffffffff8416815260c0810160208083018560005b6004811015615bc157815183529183019190830190600101615ba4565b505050508260a0830152949350505050565b6000610100808385031215615be757600080fd5b83601f840112615bf657600080fd5b60405181810181811067ffffffffffffffff82111715615c1857615c18614e6e565b604052908301908085831115615c2d57600080fd5b845b83811015615c50578051615c4281614ddf565b825260209182019101615c2f565b509095945050505050565b600060208284031215615c6d57600080fd5b8151610a8a81614ddf565b60008251615c8a818460208701614d62565b919091019291505056fea2646970667358221220f626acbfa01f86aa35120bddd6bab78fcfceeb81c2cfb61690447093033c1ac164736f6c634300080a0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
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.