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 Source Code Verified (Exact Match)
Contract Name:
IdleTokenGovernance
Compiler Version
v0.5.16+commit.9c3226ce
Optimization Enabled:
Yes with 1 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
/** * @title: Idle Token Governance main contract * @summary: ERC20 that holds pooled user funds together * Each token rapresent a share of the underlying pools * and with each token user have the right to redeem a portion of these pools * @author: Idle Labs Inc., idle.finance */ pragma solidity 0.5.16; import "@openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/SafeERC20.sol"; import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/ERC20Detailed.sol"; import "@openzeppelin/contracts-ethereum-package/contracts/utils/ReentrancyGuard.sol"; import "@openzeppelin/contracts-ethereum-package/contracts/ownership/Ownable.sol"; import "@openzeppelin/contracts-ethereum-package/contracts/lifecycle/Pausable.sol"; import "@openzeppelin/upgrades/contracts/Initializable.sol"; import "./interfaces/iERC20Fulcrum.sol"; import "./interfaces/ILendingProtocol.sol"; import "./interfaces/IGovToken.sol"; import "./interfaces/IIdleTokenV3_1.sol"; import "./interfaces/IERC3156FlashBorrower.sol"; import "./interfaces/IAaveIncentivesController.sol"; import "./interfaces/Comptroller.sol"; import "./interfaces/CERC20.sol"; import "./interfaces/AToken.sol"; import "./interfaces/IdleController.sol"; import "./interfaces/IIdleTokenHelper.sol"; import "./GST2ConsumerV2.sol"; contract IdleTokenGovernance is Initializable, ERC20, ERC20Detailed, ReentrancyGuard, Ownable, Pausable, IIdleTokenV3_1, GST2ConsumerV2 { using SafeERC20 for IERC20; using SafeMath for uint256; uint256 private constant ONE_18 = 10**18; // State variables // eg. DAI address address public token; // eg. iDAI address address private iToken; // eg. cDAI address address private cToken; // Idle rebalancer current implementation address address public rebalancer; // Address collecting underlying fees address public feeAddress; // Last iToken price, used to pause contract in case of a black swan event uint256 public lastITokenPrice; // eg. 18 for DAI uint256 private tokenDecimals; // Max unlent assets percentage for gas friendly swaps uint256 public maxUnlentPerc; // 100000 == 100% -> 1000 == 1% // Current fee on interest gained uint256 public fee; // eg. [cTokenAddress, iTokenAddress, ...] address[] public allAvailableTokens; // eg. [COMPAddress, CRVAddress, ...] address[] public govTokens; // last fully applied allocations (ie when all liquidity has been correctly placed) // eg. [5000, 0, 5000, 0] for 50% in compound, 0% fulcrum, 50% aave, 0 dydx. same order of allAvailableTokens uint256[] public lastAllocations; // Map that saves avg idleToken price paid for each user, used to calculate earnings mapping(address => uint256) public userAvgPrices; // eg. cTokenAddress => IdleCompoundAddress mapping(address => address) public protocolWrappers; // array with last balance recorded for each gov tokens mapping (address => uint256) public govTokensLastBalances; // govToken -> user_address -> user_index eg. usersGovTokensIndexes[govTokens[0]][msg.sender] = 1111123; mapping (address => mapping (address => uint256)) public usersGovTokensIndexes; // global indices for each gov tokens used as a reference to calculate a fair share for each user mapping (address => uint256) public govTokensIndexes; // Map that saves amount with no fee for each user mapping(address => uint256) private userNoFeeQty; // variable used for avoid the call of mint and redeem in the same tx bytes32 private _minterBlock; // Events event Rebalance(address _rebalancer, uint256 _amount); event Referral(uint256 _amount, address _ref); // ########## IdleToken V4_1 updates // Idle governance token address public constant IDLE = address(0x875773784Af8135eA0ef43b5a374AaD105c5D39e); // Compound governance token address public constant COMP = address(0xc00e94Cb662C3520282E6f5717214004A7f26888); uint256 private constant FULL_ALLOC = 100000; // Idle distribution controller address public constant idleController = address(0x275DA8e61ea8E02d51EDd8d0DC5c0E62b4CDB0BE); // oracle used for calculating the avgAPR with gov tokens address public oracle; // eg cDAI -> COMP mapping(address => address) private protocolTokenToGov; // Whether openRebalance is enabled or not bool public isRiskAdjusted; // last allocations submitted by rebalancer uint256[] private lastRebalancerAllocations; // ########## IdleToken V5 updates // Fee for flash loan uint256 public flashLoanFee; // IdleToken helper address address public tokenHelper; /** * @dev Emitted on flashLoan() * @param target The address of the flash loan receiver contract * @param initiator The address initiating the flash loan * @param amount The amount flash borrowed * @param premium The flash loan fee **/ event FlashLoan( address indexed target, address indexed initiator, uint256 amount, uint256 premium ); // Addresses for stkAAVE distribution from Aave address public constant stkAAVE = address(0x4da27a545c0c5B758a6BA100e3a049001de870f5); address private aToken; // ########## End IdleToken V5 updates // ERROR MESSAGES: // 0 = is 0 // 1 = already initialized // 2 = length is different // 3 = Not greater then // 4 = lt // 5 = too high // 6 = not authorized // 7 = not equal // 8 = error on flash loan execution // 9 = Reentrancy function _init() public { require(oracle == 0xB5A8f07dD4c3D315869405d702ee8F6EA695E8C5); oracle = 0x758C10272A15f0E9D50Cbc035ff9a046945da0F2; flashLoanFee = 20; } // onlyOwner /** * It allows owner to modify allAvailableTokens array in case of emergency * ie if a bug on a interest bearing token is discovered and reset protocolWrappers * associated with those tokens. * * @param protocolTokens : array of protocolTokens addresses (eg [cDAI, iDAI, ...]) * @param wrappers : array of wrapper addresses (eg [IdleCompound, IdleFulcrum, ...]) * @param _newGovTokens : array of governance token addresses * @param _newGovTokensEqualLen : array of governance token addresses for each * protocolToken (addr0 should be used for protocols with no govToken) */ function setAllAvailableTokensAndWrappers( address[] calldata protocolTokens, address[] calldata wrappers, address[] calldata _newGovTokens, address[] calldata _newGovTokensEqualLen ) external onlyOwner { require(protocolTokens.length == wrappers.length, "2"); require(_newGovTokensEqualLen.length >= protocolTokens.length, '3'); govTokens = _newGovTokens; address newGov; address protToken; for (uint256 i = 0; i < protocolTokens.length; i++) { protToken = protocolTokens[i]; require(protToken != address(0) && wrappers[i] != address(0), "0"); protocolWrappers[protToken] = wrappers[i]; // set protocol token to gov token mapping newGov = _newGovTokensEqualLen[i]; if (newGov != IDLE) { protocolTokenToGov[protToken] = newGov; } } allAvailableTokens = protocolTokens; } /** * It allows owner to set the cToken address * * @param _cToken : new cToken address */ function setCToken(address _cToken) external onlyOwner { require((cToken = _cToken) != address(0), "0"); } /** * It allows owner to set the aToken address * * @param _aToken : new aToken address */ function setAToken(address _aToken) external onlyOwner { require((aToken = _aToken) != address(0), "0"); } /** * It allows owner to set the tokenHelper address * * @param _tokenHelper : new tokenHelper address */ function setTokenHelper(address _tokenHelper) external onlyOwner { require((tokenHelper = _tokenHelper) != address(0), "0"); } /** * It allows owner to set the IdleRebalancerV3_1 address * * @param _rebalancer : new IdleRebalancerV3_1 address */ function setRebalancer(address _rebalancer) external onlyOwner { require((rebalancer = _rebalancer) != address(0), "0"); } /** * It allows owner to set the fee (1000 == 10% of gained interest) * * @param _fee : fee amount where 100000 is 100%, max settable is 10% */ function setFee(uint256 _fee) external onlyOwner { // 100000 == 100% -> 10000 == 10% require((fee = _fee) <= FULL_ALLOC / 10, "5"); } /** * It allows owner to set the fee address * * @param _feeAddress : fee address */ function setFeeAddress(address _feeAddress) external onlyOwner { require((feeAddress = _feeAddress) != address(0), "0"); } /** * It allows owner to set the oracle address for getting avgAPR * * @param _oracle : new oracle address */ function setOracleAddress(address _oracle) external onlyOwner { require((oracle = _oracle) != address(0), "0"); } /** * It allows owner to set the max unlent asset percentage (1000 == 1% of unlent asset max) * * @param _perc : max unlent perc where 100000 is 100% */ function setMaxUnlentPerc(uint256 _perc) external onlyOwner { require((maxUnlentPerc = _perc) <= 100000, "5"); } /** * Used by Rebalancer to set the new allocations * * @param _allocations : array with allocations in percentages (100% => 100000) */ function setAllocations(uint256[] calldata _allocations) external { require(msg.sender == rebalancer || msg.sender == owner(), "6"); _setAllocations(_allocations); } /** * Used by Rebalancer or in openRebalance to set the new allocations * * @param _allocations : array with allocations in percentages (100% => 100000) */ function _setAllocations(uint256[] memory _allocations) internal { require(_allocations.length == allAvailableTokens.length, "2"); uint256 total; for (uint256 i = 0; i < _allocations.length; i++) { total = total.add(_allocations[i]); } lastRebalancerAllocations = _allocations; require(total == FULL_ALLOC, "7"); } // view /** * Get latest allocations submitted by rebalancer * * @return : array of allocations ordered as allAvailableTokens */ function getAllocations() external view returns (uint256[] memory) { return lastRebalancerAllocations; } /** * Get currently used gov tokens * * @return : array of govTokens supported */ function getGovTokens() external view returns (address[] memory) { return govTokens; } /** * Get currently used protocol tokens (cDAI, aDAI, ...) * * @return : array of protocol tokens supported */ function getAllAvailableTokens() external view returns (address[] memory) { return allAvailableTokens; } /** * Get gov token associated to a protocol token eg protocolTokenToGov[cDAI] = COMP * * @return : address of the gov token */ function getProtocolTokenToGov(address _protocolToken) external view returns (address) { return protocolTokenToGov[_protocolToken]; } /** * IdleToken price for a user considering fees, in underlying * this is useful when you need to redeem exactly X underlying * * @return : price in underlying token counting fees for a specific user */ function tokenPriceWithFee(address user) external view returns (uint256 priceWFee) { uint256 userAvgPrice = userAvgPrices[user]; priceWFee = _tokenPrice(); if (userAvgPrice != 0 && priceWFee > userAvgPrice) { priceWFee = priceWFee.mul(FULL_ALLOC).sub(fee.mul(priceWFee.sub(userAvgPrice))).div(FULL_ALLOC); } } /** * IdleToken price calculation, in underlying * * @return : price in underlying token */ function tokenPrice() external view returns (uint256) { return _tokenPrice(); } /** * Get APR of every ILendingProtocol * * @return addresses: array of token addresses * @return aprs: array of aprs (ordered in respect to the `addresses` array) */ function getAPRs() external view returns (address[] memory, uint256[] memory) { return IIdleTokenHelper(tokenHelper).getAPRs(address(this)); } /** * Get current avg APR of this IdleToken * * @return avgApr: current weighted avg apr */ function getAvgAPR() external view returns (uint256) { return IIdleTokenHelper(tokenHelper).getAPR(address(this), cToken, aToken); } /** * ERC20 modified transferFrom that also update the avgPrice paid for the recipient and * updates user gov idx * * @param sender : sender account * @param recipient : recipient account * @param amount : value to transfer * @return : flag whether transfer was successful or not */ function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { _updateUserGovIdxTransfer(sender, recipient, amount); _transfer(sender, recipient, amount); _approve(sender, msg.sender, allowance(sender, msg.sender).sub(amount, "ERC20: transfer amount exceeds allowance")); _updateUserFeeInfo(recipient, amount, userAvgPrices[sender]); return true; } /** * ERC20 modified transfer that also update the avgPrice paid for the recipient and * updates user gov idx * * @param recipient : recipient account * @param amount : value to transfer * @return : flag whether transfer was successful or not */ function transfer(address recipient, uint256 amount) public returns (bool) { _updateUserGovIdxTransfer(msg.sender, recipient, amount); _transfer(msg.sender, recipient, amount); _updateUserFeeInfo(recipient, amount, userAvgPrices[msg.sender]); return true; } /** * Helper method for transfer and transferFrom, updates recipient gov indexes * * @param _from : sender account * @param _to : recipient account * @param amount : value to transfer */ function _updateUserGovIdxTransfer(address _from, address _to, uint256 amount) internal { address govToken; uint256 govTokenIdx; uint256 sharePerTokenFrom; uint256 shareTo; uint256 balanceTo = balanceOf(_to); for (uint256 i = 0; i < govTokens.length; i++) { govToken = govTokens[i]; if (balanceTo == 0) { usersGovTokensIndexes[govToken][_to] = usersGovTokensIndexes[govToken][_from]; } else { govTokenIdx = govTokensIndexes[govToken]; // calc 1 idleToken value in gov shares for user `_from` sharePerTokenFrom = govTokenIdx.sub(usersGovTokensIndexes[govToken][_from]); // calc current gov shares (before transfer) for user `_to` shareTo = balanceTo.mul(govTokenIdx.sub(usersGovTokensIndexes[govToken][_to])).div(ONE_18); // user `_to` should have -> shareTo + (sharePerTokenFrom * amount / 1e18) = (balanceTo + amount) * (govTokenIdx - userIdx) / 1e18 // so userIdx = govTokenIdx - ((shareTo * 1e18 + (sharePerTokenFrom * amount)) / (balanceTo + amount)) usersGovTokensIndexes[govToken][_to] = govTokenIdx.sub( shareTo.mul(ONE_18).add(sharePerTokenFrom.mul(amount)).div( balanceTo.add(amount) ) ); } } } /** * Get how many gov tokens a user is entitled to (this may not include eventual undistributed tokens) * * @param _usr : user address * @return : array of amounts for each gov token */ function getGovTokensAmounts(address _usr) external view returns (uint256[] memory _amounts) { address govToken; uint256 usrBal = balanceOf(_usr); _amounts = new uint256[](govTokens.length); for (uint256 i = 0; i < _amounts.length; i++) { govToken = govTokens[i]; _amounts[i] = usrBal.mul(govTokensIndexes[govToken].sub(usersGovTokensIndexes[govToken][_usr])).div(ONE_18); } } // external /** * Used to mint IdleTokens, given an underlying amount (eg. DAI). * This method triggers a rebalance of the pools if _skipRebalance is set to false * NOTE: User should 'approve' _amount of tokens before calling mintIdleToken * NOTE 2: this method can be paused * * @param _amount : amount of underlying token to be lended * @param : not used anymore * @param _referral : referral address * @return mintedTokens : amount of IdleTokens minted */ function mintIdleToken(uint256 _amount, bool, address _referral) external nonReentrant whenNotPaused returns (uint256 mintedTokens) { _minterBlock = keccak256(abi.encodePacked(tx.origin, block.number)); _redeemGovTokens(msg.sender); // Get current IdleToken price uint256 idlePrice = _tokenPrice(); // transfer tokens to this contract IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); mintedTokens = _amount.mul(ONE_18).div(idlePrice); _mint(msg.sender, mintedTokens); // Update avg price and user idx for each gov tokens _updateUserInfo(msg.sender, mintedTokens); _updateUserFeeInfo(msg.sender, mintedTokens, idlePrice); if (_referral != address(0)) { emit Referral(_amount, _referral); } } /** * Helper method for mintIdleToken, updates minter gov indexes and avg price * * @param _to : minter account * @param _mintedTokens : number of newly minted tokens */ function _updateUserInfo(address _to, uint256 _mintedTokens) internal { address govToken; uint256 usrBal = balanceOf(_to); uint256 _usrIdx; for (uint256 i = 0; i < govTokens.length; i++) { govToken = govTokens[i]; _usrIdx = usersGovTokensIndexes[govToken][_to]; // calculate user idx usersGovTokensIndexes[govToken][_to] = _usrIdx.add( _mintedTokens.mul(govTokensIndexes[govToken].sub(_usrIdx)).div(usrBal) ); } } /** * Here we calc the pool share one can withdraw given the amount of IdleToken they want to burn * * @param _amount : amount of IdleTokens to be burned * @return redeemedTokens : amount of underlying tokens redeemed */ function redeemIdleToken(uint256 _amount) external returns (uint256) { return _redeemIdleToken(_amount, new bool[](govTokens.length)); } /** * Here we calc the pool share one can withdraw given the amount of IdleToken they want to burn * WARNING: if elements in the `_skipGovTokenRedeem` are set to `true` then the rewards will be GIFTED to the pool * * @param _amount : amount of IdleTokens to be burned * @param _skipGovTokenRedeem : array of flags whether to redeem or not specific gov tokens * @return redeemedTokens : amount of underlying tokens redeemed */ function redeemIdleTokenSkipGov(uint256 _amount, bool[] calldata _skipGovTokenRedeem) external returns (uint256) { return _redeemIdleToken(_amount, _skipGovTokenRedeem); } /** * Here we calc the pool share one can withdraw given the amount of IdleToken they want to burn * * @param _amount : amount of IdleTokens to be burned * @param _skipGovTokenRedeem : array of flag for redeeming or not gov tokens. Funds will be gifted to the pool * @return redeemedTokens : amount of underlying tokens redeemed */ function _redeemIdleToken(uint256 _amount, bool[] memory _skipGovTokenRedeem) internal nonReentrant returns (uint256 redeemedTokens) { _checkMintRedeemSameTx(); _redeemGovTokensInternal(msg.sender, _skipGovTokenRedeem); if (_amount != 0) { uint256 price = _tokenPrice(); uint256 valueToRedeem = _amount.mul(price).div(ONE_18); uint256 balanceUnderlying = _contractBalanceOf(token); if (valueToRedeem > balanceUnderlying) { redeemedTokens = _redeemHelper(_amount, balanceUnderlying); } else { redeemedTokens = valueToRedeem; } // get eventual performance fee redeemedTokens = _getFee(_amount, redeemedTokens, price); // burn idleTokens _burn(msg.sender, _amount); // send underlying minus fee to msg.sender _transferTokens(token, msg.sender, redeemedTokens); } } function _redeemHelper(uint256 _amount, uint256 _balanceUnderlying) private returns (uint256 redeemedTokens) { address currToken; uint256 idleSupply = totalSupply(); address[] memory _allAvailableTokens = allAvailableTokens; for (uint256 i = 0; i < _allAvailableTokens.length; i++) { currToken = _allAvailableTokens[i]; redeemedTokens = redeemedTokens.add( _redeemProtocolTokens( currToken, // _amount * protocolPoolBalance / idleSupply _amount.mul(_contractBalanceOf(currToken)).div(idleSupply) // amount to redeem ) ); } // and get a portion of the eventual unlent balance redeemedTokens = redeemedTokens.add(_amount.mul(_balanceUnderlying).div(idleSupply)); } /** * Here we calc the pool share one can withdraw given the amount of IdleToken they want to burn * and send interest-bearing tokens (eg. cDAI/iDAI) directly to the user. * Underlying (eg. DAI) is not redeemed here. * * @param _amount : amount of IdleTokens to be burned */ function redeemInterestBearingTokens(uint256 _amount) external nonReentrant whenPaused { _checkMintRedeemSameTx(); _redeemGovTokens(msg.sender); for (uint256 i = 0; i < allAvailableTokens.length; i++) { _transferTokens(allAvailableTokens[i], msg.sender, _amount.mul(_contractBalanceOf(allAvailableTokens[i])).div(totalSupply())); } // Get a portion of the eventual unlent balance _transferTokens(token, msg.sender, _amount.mul(_contractBalanceOf(token)).div(totalSupply())); _burn(msg.sender, _amount); } /** * Dynamic allocate all the pool across different lending protocols if needed, * rebalance without params * * NOTE: this method can be paused * * @return : whether has rebalanced or not */ function rebalance() external returns (bool) { return _rebalance(); } /** * @dev The fee to be charged for a given loan. * @param _token The loan currency. * @param _amount The amount of tokens lent. * @return The amount of `token` to be charged for the loan, on top of the returned principal. */ function flashFee(address _token, uint256 _amount) public view returns (uint256) { require(_token == token, '7'); return _amount.mul(flashLoanFee).div(FULL_ALLOC); } /** * @dev The amount of currency available to be lent. * @param _token The loan currency. * @return The amount of `token` that can be borrowed. */ function maxFlashLoan(address _token) external view returns (uint256) { if (_token == token) { return _tokenPrice().mul(totalSupply()).div(ONE_18); } } /** * Allow any users to borrow funds inside a tx if they return the same amount + `flashLoanFee` * * @param _receiver : flash loan receiver, should have the IERC3156FlashBorrower interface * @param _token : used to check that the requested token is the correct one * @param _amount : amount of `token` to borrow * @param _params : params that should be passed to the _receiverAddress in the `executeOperation` call */ function flashLoan( IERC3156FlashBorrower _receiver, address _token, uint256 _amount, bytes calldata _params ) external whenNotPaused nonReentrant returns (bool) { address receiverAddr = address(_receiver); require(_token == token, "7"); require(receiverAddr != address(0) && _amount > 0, "0"); // get current underlying unlent balance uint256 balance = _contractBalanceOf(token); if (_amount > balance) { // Unlent is not enough, some funds needs to be redeemed from underlying protocols uint256 toRedeem = _amount.sub(balance); uint256 _toRedeemAux; address currToken; uint256 currBalanceUnderlying; uint256 availableLiquidity; uint256 redeemed; uint256 protocolTokenPrice; ILendingProtocol protocol; bool isEnough; bool haveWeInvestedEnough; // We cycle through interest bearing tokens currently in use (eg [cDAI, aDAI]) // (ie we cycle each lending protocol where we have some funds currently deposited) for (uint256 i = 0; i < allAvailableTokens.length; i++) { currToken = allAvailableTokens[i]; protocol = ILendingProtocol(protocolWrappers[currToken]); protocolTokenPrice = protocol.getPriceInToken(); availableLiquidity = protocol.availableLiquidity(); currBalanceUnderlying = _contractBalanceOf(currToken).mul(protocolTokenPrice).div(ONE_18); // We need to check: // 1. if Idle has invested enough in that protocol to cover the user request haveWeInvestedEnough = currBalanceUnderlying >= toRedeem; // 2. if the current lending protocol has enough liquidity available (not borrowed) to cover the user requested amount isEnough = availableLiquidity >= toRedeem; // in order to calculate `_toRedeemAux` which is the amount of underlying (eg DAI) // that we have to redeem from that lending protocol _toRedeemAux = haveWeInvestedEnough ? // if we lent enough and that protocol has enough liquidity we redeem `toRedeem` and we are done, otherwise we redeem `availableLiquidity` (isEnough ? toRedeem : availableLiquidity) : // if we did not lent enough and that liquidity is available then we redeem all what we deposited, otherwise we redeem `availableLiquidity` (currBalanceUnderlying <= availableLiquidity ? currBalanceUnderlying : availableLiquidity); // do the actual redeem on the lending protocol redeemed = _redeemProtocolTokens( currToken, // convert amount from underlying to protocol token _toRedeemAux.mul(ONE_18).div(protocolTokenPrice) ); // tokens are now in this contract if (haveWeInvestedEnough && isEnough) { break; } toRedeem = toRedeem.sub(redeemed); } } require(_contractBalanceOf(token) >= _amount, "3"); // transfer funds _transferTokens(token, receiverAddr, _amount); // calculate fee uint256 _flashFee = flashFee(token, _amount); // call _receiver `onFlashLoan` require( _receiver.onFlashLoan(msg.sender, token, _amount, _flashFee, _params) == keccak256("ERC3156FlashBorrower.onFlashLoan"), "8" ); // transfer _amount + _flashFee from _receiver IERC20(token).safeTransferFrom(receiverAddr, address(this), _amount.add(_flashFee)); // Put underlyings in lending once again with rebalance _rebalance(); emit FlashLoan(receiverAddr, msg.sender, _amount, _flashFee); return true; } // internal /** * Get current idleToken price based on net asset value and totalSupply * * @return price: value of 1 idleToken in underlying */ function _tokenPrice() internal view returns (uint256 price) { uint256 totSupply = totalSupply(); if (totSupply == 0) { return 10**(tokenDecimals); } address currToken; uint256 totNav = _contractBalanceOf(token).mul(ONE_18); // eventual underlying unlent balance address[] memory _allAvailableTokens = allAvailableTokens; for (uint256 i = 0; i < _allAvailableTokens.length; i++) { currToken = _allAvailableTokens[i]; totNav = totNav.add( // NAV = price * poolSupply _getPriceInToken(protocolWrappers[currToken]).mul( _contractBalanceOf(currToken) ) ); } price = totNav.div(totSupply); // idleToken price in token wei } /** * Dynamic allocate all the pool across different lending protocols if needed * * NOTE: this method can be paused * * @return : whether has rebalanced or not */ function _rebalance() internal whenNotPaused returns (bool) { // check if we need to rebalance by looking at the last allocations submitted by rebalancer uint256[] memory rebalancerLastAllocations = lastRebalancerAllocations; uint256[] memory _lastAllocations = lastAllocations; uint256 lastLen = _lastAllocations.length; bool areAllocationsEqual = rebalancerLastAllocations.length == lastLen; if (areAllocationsEqual) { for (uint256 i = 0; i < lastLen || !areAllocationsEqual; i++) { if (_lastAllocations[i] != rebalancerLastAllocations[i]) { areAllocationsEqual = false; break; } } } uint256 balance = _contractBalanceOf(token); if (areAllocationsEqual && balance == 0) { return false; } uint256 maxUnlentBalance = _getCurrentPoolValue().mul(maxUnlentPerc).div(FULL_ALLOC); if (areAllocationsEqual) { if (balance > maxUnlentBalance) { // mint the difference _mintWithAmounts(rebalancerLastAllocations, balance.sub(maxUnlentBalance)); } return false; } // Instead of redeeming everything during rebalance we redeem and mint only what needs // to be reallocated // get current allocations in underlying (it does not count unlent underlying) (uint256[] memory amounts, uint256 totalInUnderlying) = _getCurrentAllocations(); // calculate the total amount in underlying that needs to be reallocated totalInUnderlying = totalInUnderlying.add(balance); (uint256[] memory toMintAllocations, uint256 totalToMint, bool lowLiquidity) = _redeemAllNeeded( amounts, // calculate new allocations given the total (not counting unlent balance) _amountsFromAllocations(rebalancerLastAllocations, totalInUnderlying.sub(maxUnlentBalance)) ); // if some protocol has liquidity that we should redeem, we do not update // lastAllocations to force another rebalance next time if (!lowLiquidity) { // Update lastAllocations with rebalancerLastAllocations delete lastAllocations; lastAllocations = rebalancerLastAllocations; } uint256 totalRedeemd = _contractBalanceOf(token); if (totalRedeemd <= maxUnlentBalance || totalToMint == 0) { return false; } // Do not mint directly using toMintAllocations check with totalRedeemd uint256[] memory tempAllocations = new uint256[](toMintAllocations.length); for (uint256 i = 0; i < toMintAllocations.length; i++) { // Calc what would have been the correct allocations percentage if all was available tempAllocations[i] = toMintAllocations[i].mul(FULL_ALLOC).div(totalToMint); } // partial amounts _mintWithAmounts(tempAllocations, totalRedeemd.sub(maxUnlentBalance)); emit Rebalance(msg.sender, totalInUnderlying); return true; // hasRebalanced } /** * Redeem unclaimed governance tokens and update governance global index and user index if needed * if called during redeem it will send all gov tokens accrued by a user to the user * * @param _to : user address */ function _redeemGovTokens(address _to) internal { _redeemGovTokensInternal(_to, new bool[](govTokens.length)); } /** * Redeem unclaimed governance tokens and update governance global index and user index if needed * if called during redeem it will send all gov tokens accrued by a user to the user * * @param _to : user address * @param _skipGovTokenRedeem : array of flag for redeeming or not gov tokens */ function _redeemGovTokensInternal(address _to, bool[] memory _skipGovTokenRedeem) internal { address[] memory _govTokens = govTokens; if (_govTokens.length == 0) { return; } uint256 supply = totalSupply(); uint256 usrBal = balanceOf(_to); address govToken; if (supply > 0) { for (uint256 i = 0; i < _govTokens.length; i++) { govToken = _govTokens[i]; _redeemGovTokensFromProtocol(govToken); // get current gov token balance uint256 govBal = _contractBalanceOf(govToken); if (govBal > 0) { // update global index with ratio of govTokens per idleToken govTokensIndexes[govToken] = govTokensIndexes[govToken].add( // check how much gov tokens for each idleToken we gained since last update govBal.sub(govTokensLastBalances[govToken]).mul(ONE_18).div(supply) ); // update global var with current govToken balance govTokensLastBalances[govToken] = govBal; } if (usrBal > 0) { uint256 usrIndex = usersGovTokensIndexes[govToken][_to]; // check if user has accrued something uint256 delta = govTokensIndexes[govToken].sub(usrIndex); if (delta != 0) { uint256 share = usrBal.mul(delta).div(ONE_18); uint256 bal = _contractBalanceOf(govToken); // To avoid rounding issue if (share > bal) { share = bal; } if (_skipGovTokenRedeem[i]) { // -> gift govTokens[i] accrued to the pool // update global index with ratio of govTokens per idleToken govTokensIndexes[govToken] = govTokensIndexes[govToken].add( // check how much gov tokens for each idleToken we gained since last update share.mul(ONE_18).div(supply.sub(usrBal)) ); } else { uint256 feeDue; // no fee for IDLE governance token if (feeAddress != address(0) && fee > 0 && govToken != IDLE) { feeDue = share.mul(fee).div(FULL_ALLOC); // Transfer gov token fee to feeAddress _transferTokens(govToken, feeAddress, feeDue); } // Transfer gov token to user _transferTokens(govToken, _to, share.sub(feeDue)); // Update last balance govTokensLastBalances[govToken] = _contractBalanceOf(govToken); } } } // save current index for this gov token usersGovTokensIndexes[govToken][_to] = govTokensIndexes[govToken]; } } } /** * Redeem a specific gov token * * @param _govToken : address of the gov token to redeem */ function _redeemGovTokensFromProtocol(address _govToken) internal { // In case new Gov tokens will be supported this should be updated if (_govToken == COMP || _govToken == IDLE || _govToken == stkAAVE) { address[] memory holders = new address[](1); holders[0] = address(this); if (_govToken == IDLE) { // For IDLE, the distribution is done only to IdleTokens, so `holders` and // `tokens` parameters are the same and equal to address(this) IdleController(idleController).claimIdle(holders, holders); return; } address[] memory tokens = new address[](1); if (_govToken == stkAAVE && aToken != address(0)) { tokens[0] = aToken; IAaveIncentivesController _ctrl = IAaveIncentivesController(AToken(tokens[0]).getIncentivesController()); _ctrl.claimRewards(tokens, _ctrl.getUserUnclaimedRewards(address(this)), address(this)); return; } if (cToken != address(0)) { tokens[0] = cToken; Comptroller(CERC20(tokens[0]).comptroller()).claimComp(holders, tokens, false, true); } } } /** * Update receiver userAvgPrice paid for each idle token, * receiver will pay fees accrued * * @param usr : user that should have balance update * @param qty : new amount deposited / transferred, in idleToken * @param price : sender userAvgPrice */ function _updateUserFeeInfo(address usr, uint256 qty, uint256 price) private { uint256 usrBal = balanceOf(usr); // ((avgPrice * oldBalance) + (senderAvgPrice * newQty)) / totBalance userAvgPrices[usr] = userAvgPrices[usr].mul(usrBal.sub(qty)).add(price.mul(qty)).div(usrBal); } /** * Calculate fee in underlyings and send them to feeAddress * * @param amount : in idleTokens * @param redeemed : in underlying * @param currPrice : current idleToken price * @return : net value in underlying */ function _getFee(uint256 amount, uint256 redeemed, uint256 currPrice) internal returns (uint256) { uint256 avgPrice = userAvgPrices[msg.sender]; if (currPrice < avgPrice) { return redeemed; } // 10**23 -> ONE_18 * FULL_ALLOC uint256 feeDue = amount.mul(currPrice.sub(avgPrice)).mul(fee).div(10**23); _transferTokens(token, feeAddress, feeDue); return redeemed.sub(feeDue); } /** * Mint specific amounts of protocols tokens * * @param allocations : array of amounts to be minted * @param total : total amount * @return : net value in underlying */ function _mintWithAmounts(uint256[] memory allocations, uint256 total) internal { // mint for each protocol and update currentTokensUsed uint256[] memory protocolAmounts = _amountsFromAllocations(allocations, total); uint256 currAmount; address protWrapper; address[] memory _tokens = allAvailableTokens; for (uint256 i = 0; i < protocolAmounts.length; i++) { currAmount = protocolAmounts[i]; if (currAmount != 0) { protWrapper = protocolWrappers[_tokens[i]]; // Transfer _amount underlying token (eg. DAI) to protWrapper _transferTokens(token, protWrapper, currAmount); ILendingProtocol(protWrapper).mint(); } } } /** * Calculate amounts from percentage allocations (100000 => 100%) * * @param allocations : array of protocol allocations in percentage * @param total : total amount * @return : array with amounts */ function _amountsFromAllocations(uint256[] memory allocations, uint256 total) internal pure returns (uint256[] memory newAmounts) { newAmounts = new uint256[](allocations.length); uint256 currBalance; uint256 allocatedBalance; for (uint256 i = 0; i < allocations.length; i++) { if (i == allocations.length - 1) { newAmounts[i] = total.sub(allocatedBalance); } else { currBalance = total.mul(allocations[i]).div(FULL_ALLOC); allocatedBalance = allocatedBalance.add(currBalance); newAmounts[i] = currBalance; } } return newAmounts; } /** * Redeem all underlying needed from each protocol * * @param amounts : array with current allocations in underlying * @param newAmounts : array with new allocations in underlying * @return toMintAllocations : array with amounts to be minted * @return totalToMint : total amount that needs to be minted */ function _redeemAllNeeded( uint256[] memory amounts, uint256[] memory newAmounts ) internal returns ( uint256[] memory toMintAllocations, uint256 totalToMint, bool lowLiquidity ) { toMintAllocations = new uint256[](amounts.length); ILendingProtocol protocol; uint256 currAmount; uint256 newAmount; address currToken; address[] memory _tokens = allAvailableTokens; // check the difference between amounts and newAmounts for (uint256 i = 0; i < amounts.length; i++) { currToken = _tokens[i]; newAmount = newAmounts[i]; currAmount = amounts[i]; protocol = ILendingProtocol(protocolWrappers[currToken]); if (currAmount > newAmount) { uint256 toRedeem = currAmount.sub(newAmount); uint256 availableLiquidity = protocol.availableLiquidity(); if (availableLiquidity < toRedeem) { lowLiquidity = true; // remove 1% to be sure it's really available (eg for compound-like protocols) toRedeem = availableLiquidity.mul(FULL_ALLOC-1000).div(FULL_ALLOC); } // redeem the difference _redeemProtocolTokens( currToken, // convert amount from underlying to protocol token toRedeem.mul(ONE_18).div(protocol.getPriceInToken()) ); // tokens are now in this contract } else { toMintAllocations[i] = newAmount.sub(currAmount); totalToMint = totalToMint.add(toMintAllocations[i]); } } } /** * Get the contract balance of every protocol currently used * * @return amounts : array with all amounts for each protocol in order, * eg [amountCompoundInUnderlying, amountFulcrumInUnderlying] * @return total : total AUM in underlying */ function _getCurrentAllocations() internal view returns (uint256[] memory amounts, uint256 total) { // Get balance of every protocol implemented address currentToken; address[] memory _tokens = allAvailableTokens; uint256 tokensLen = _tokens.length; amounts = new uint256[](tokensLen); for (uint256 i = 0; i < tokensLen; i++) { currentToken = _tokens[i]; amounts[i] = _getPriceInToken(protocolWrappers[currentToken]).mul( _contractBalanceOf(currentToken) ).div(ONE_18); total = total.add(amounts[i]); } } /** * Get the current pool value in underlying * * @return total : total AUM in underlying */ function _getCurrentPoolValue() internal view returns (uint256 total) { // Get balance of every protocol implemented address currentToken; address[] memory _tokens = allAvailableTokens; for (uint256 i = 0; i < _tokens.length; i++) { currentToken = _tokens[i]; total = total.add(_getPriceInToken(protocolWrappers[currentToken]).mul( _contractBalanceOf(currentToken) ).div(ONE_18)); } // add unlent balance total = total.add(_contractBalanceOf(token)); } /** * Get contract balance of _token * * @param _token : address of the token to read balance * @return total : balance of _token in this contract */ function _contractBalanceOf(address _token) private view returns (uint256) { // Original implementation: // // return IERC20(_token).balanceOf(address(this)); // Optimized implementation inspired by uniswap https://github.com/Uniswap/uniswap-v3-core/blob/main/contracts/UniswapV3Pool.sol#L144 // // 0x70a08231 -> selector for 'function balanceOf(address) returns (uint256)' (bool success, bytes memory data) = _token.staticcall(abi.encodeWithSelector(0x70a08231, address(this))); require(success); return abi.decode(data, (uint256)); } /** * Get price of 1 protocol token in underlyings * * @param _token : address of the protocol token * @return price : price of protocol token */ function _getPriceInToken(address _token) private view returns (uint256) { return ILendingProtocol(_token).getPriceInToken(); } /** * Check that no mint has been made in the same block from the same EOA */ function _checkMintRedeemSameTx() private view { require(keccak256(abi.encodePacked(tx.origin, block.number)) != _minterBlock, "9"); } // ILendingProtocols calls /** * Redeem underlying tokens through protocol wrapper * * @param _amount : amount of `_token` to redeem * @param _token : protocol token address * @return tokens : new tokens minted */ function _redeemProtocolTokens(address _token, uint256 _amount) internal returns (uint256 tokens) { if (_amount != 0) { // Transfer _amount of _protocolToken (eg. cDAI) to _wrapperAddr address _wrapperAddr = protocolWrappers[_token]; _transferTokens(_token, _wrapperAddr, _amount); tokens = ILendingProtocol(_wrapperAddr).redeem(address(this)); } } function _transferTokens(address _token, address _to, uint256 _amount) internal { IERC20(_token).safeTransfer(_to, _amount); } }
pragma solidity 0.5.16; import "./interfaces/GasToken.sol"; import "@openzeppelin/upgrades/contracts/Initializable.sol"; contract GST2ConsumerV2 is Initializable { GasToken public gst2; // Kept for reference // // function initialize() initializer public { // gst2 = GasToken(0x0000000000b3F879cb30FE243b4Dfee438691c04); // } // // modifier gasDiscountFrom(address from) { // uint256 initialGasLeft = gasleft(); // _; // _makeGasDiscount(initialGasLeft - gasleft(), from); // } // // function _makeGasDiscount(uint256 gasSpent, address from) internal { // // For more info https://gastoken.io/ // // 14154 -> FREE_BASE -> base cost of freeing // // 41130 -> 2 * REIMBURSE - FREE_TOKEN -> 2 * 24000 - 6870 // uint256 tokens = (gasSpent + 14154) / 41130; // uint256 safeNumTokens; // uint256 gas = gasleft(); // // // For more info https://github.com/projectchicago/gastoken/blob/master/contract/gst2_free_example.sol // if (gas >= 27710) { // safeNumTokens = (gas - 27710) / 7020; // } // // if (tokens > safeNumTokens) { // tokens = safeNumTokens; // } // // if (tokens > 0) { // gst2.freeFromUpTo(from, tokens); // } // } }
pragma solidity 0.5.16; interface AToken { function getIncentivesController() external view returns (address); function redeem(uint256 amount) external; function burn(address user, address receiverOfUnderlying, uint256 amount, uint256 index) external; function balanceOf(address account) external view returns (uint256); }
pragma solidity 0.5.16; interface CERC20 { function mint(uint256 mintAmount) external returns (uint256); function comptroller() external view returns (address); function redeem(uint256 redeemTokens) external returns (uint256); function exchangeRateStored() external view returns (uint256); function supplyRatePerBlock() external view returns (uint256); function borrowRatePerBlock() external view returns (uint256); function totalReserves() external view returns (uint256); function getCash() external view returns (uint256); function totalBorrows() external view returns (uint256); function reserveFactorMantissa() external view returns (uint256); function interestRateModel() external view returns (address); function underlying() external view returns (address); }
pragma solidity 0.5.16; interface Comptroller { function claimComp(address) external; function compSpeeds(address _cToken) external view returns (uint256); function claimComp(address[] calldata holders, address[] calldata cTokens, bool borrowers, bool suppliers) external; }
pragma solidity 0.5.16; interface GasToken { function freeUpTo(uint256 value) external returns (uint256 freed); function freeFromUpTo(address from, uint256 value) external returns (uint256 freed); function balanceOf(address from) external returns (uint256 balance); }
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.5.16; interface IAaveIncentivesController { /** * @dev Claims reward for an user, on all the assets of the lending pool, accumulating the pending rewards * @param amount Amount of rewards to claim * @param to Address that will be receiving the rewards * @return Rewards claimed **/ function claimRewards( address[] calldata assets, uint256 amount, address to ) external returns (uint256); /** * @dev returns the unclaimed rewards of the user * @param user the address of the user * @return the unclaimed user rewards */ function getUserUnclaimedRewards(address user) external view returns (uint256); function getAssetData(address asset) external view returns (uint256, uint256, uint256); function getRewardsBalance(address[] calldata assets, address user) external view returns(uint256); }
pragma solidity 0.5.16; interface IERC3156FlashBorrower { /** * @dev Receive a flash loan. * @param initiator The initiator of the loan. * @param token The loan currency. * @param amount The amount of tokens lent. * @param fee The additional amount of tokens to repay. * @param data Arbitrary data structure, intended to contain user-defined parameters. * @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan" */ function onFlashLoan( address initiator, address token, uint256 amount, uint256 fee, bytes calldata data ) external returns (bytes32); }
pragma solidity 0.5.16; interface IGovToken { function redeemGovTokens() external; }
pragma solidity 0.5.16; interface IIdleTokenHelper { function setIdleTokens(address[] calldata _newIdleTokens) external; function getAPR(address _idleToken, address _cToken, address _aToken) external view returns (uint256 avgApr); function getCurrentAllocations(address _idleToken) external view returns (uint256[] memory amounts, uint256 total); function getAPRs(address _idleToken) external view returns (address[] memory addresses, uint256[] memory aprs); function sellGovTokens(address _idleToken, uint256[] calldata _minTokenOut) external; function emergencyWithdrawToken(address _token, address _to) external; }
/** * @title: Idle Token interface * @author: Idle Labs Inc., idle.finance */ pragma solidity 0.5.16; interface IIdleTokenV3_1 { // view /** * IdleToken price calculation, in underlying * * @return : price in underlying token */ function tokenPrice() external view returns (uint256 price); /** * @return : underlying token address */ function token() external view returns (address); /** * Get APR of every ILendingProtocol * * @return addresses: array of token addresses * @return aprs: array of aprs (ordered in respect to the `addresses` array) */ function getAPRs() external view returns (address[] memory addresses, uint256[] memory aprs); // external // We should save the amount one has deposited to calc interests /** * Used to mint IdleTokens, given an underlying amount (eg. DAI). * This method triggers a rebalance of the pools if needed * NOTE: User should 'approve' _amount of tokens before calling mintIdleToken * NOTE 2: this method can be paused * * @param _amount : amount of underlying token to be lended * @param _skipRebalance : flag for skipping rebalance for lower gas price * @param _referral : referral address * @return mintedTokens : amount of IdleTokens minted */ function mintIdleToken(uint256 _amount, bool _skipRebalance, address _referral) external returns (uint256 mintedTokens); /** * Here we calc the pool share one can withdraw given the amount of IdleToken they want to burn * This method triggers a rebalance of the pools if needed * NOTE: If the contract is paused or iToken price has decreased one can still redeem but no rebalance happens. * NOTE 2: If iToken price has decresed one should not redeem (but can do it) otherwise he would capitalize the loss. * Ideally one should wait until the black swan event is terminated * * @param _amount : amount of IdleTokens to be burned * @return redeemedTokens : amount of underlying tokens redeemed */ function redeemIdleToken(uint256 _amount) external returns (uint256 redeemedTokens); /** * Here we calc the pool share one can withdraw given the amount of IdleToken they want to burn * and send interest-bearing tokens (eg. cDAI/iDAI) directly to the user. * Underlying (eg. DAI) is not redeemed here. * * @param _amount : amount of IdleTokens to be burned */ function redeemInterestBearingTokens(uint256 _amount) external; /** * @return : whether has rebalanced or not */ function rebalance() external returns (bool); }
pragma solidity 0.5.16; interface ILendingProtocol { function mint() external returns (uint256); function redeem(address account) external returns (uint256); function nextSupplyRate(uint256 amount) external view returns (uint256); function getAPR() external view returns (uint256); function getPriceInToken() external view returns (uint256); function token() external view returns (address); function underlying() external view returns (address); function availableLiquidity() external view returns (uint256); }
pragma solidity 0.5.16; interface IdleController { function idleSpeeds(address _idleToken) external view returns (uint256); function claimIdle(address[] calldata holders, address[] calldata idleTokens) external; function getAllMarkets() external view returns (address[] memory); function _addIdleMarkets(address[] calldata) external; function _supportMarkets(address[] calldata) external; function _setPriceOracle(address) external; function admin() external view returns(address); }
pragma solidity 0.5.16; interface iERC20Fulcrum { function mint( address receiver, uint256 depositAmount) external returns (uint256 mintAmount); function burn( address receiver, uint256 burnAmount) external returns (uint256 loanAmountPaid); function tokenPrice() external view returns (uint256 price); function supplyInterestRate() external view returns (uint256); function rateMultiplier() external view returns (uint256); function baseRate() external view returns (uint256); function borrowInterestRate() external view returns (uint256); function avgBorrowInterestRate() external view returns (uint256); function protocolInterestRate() external view returns (uint256); function spreadMultiplier() external view returns (uint256); function totalAssetBorrow() external view returns (uint256); function totalAssetSupply() external view returns (uint256); function nextSupplyInterestRate(uint256) external view returns (uint256); function nextBorrowInterestRate(uint256) external view returns (uint256); function nextLoanInterestRate(uint256) external view returns (uint256); function totalSupplyInterestRate(uint256) external view returns (uint256); function claimLoanToken() external returns (uint256 claimedAmount); function dsr() external view returns (uint256); function chaiPrice() external view returns (uint256); }
pragma solidity ^0.5.0; import "@openzeppelin/upgrades/contracts/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 GSN 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. */ contract Context is Initializable { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } // solhint-disable-previous-line no-empty-blocks function _msgSender() internal view returns (address payable) { return msg.sender; } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
pragma solidity ^0.5.0; /** * @title Roles * @dev Library for managing addresses assigned to a Role. */ library Roles { struct Role { mapping (address => bool) bearer; } /** * @dev Give an account access to this role. */ function add(Role storage role, address account) internal { require(!has(role, account), "Roles: account already has role"); role.bearer[account] = true; } /** * @dev Remove an account's access to this role. */ function remove(Role storage role, address account) internal { require(has(role, account), "Roles: account does not have role"); role.bearer[account] = false; } /** * @dev Check if an account has this role. * @return bool */ function has(Role storage role, address account) internal view returns (bool) { require(account != address(0), "Roles: account is the zero address"); return role.bearer[account]; } }
pragma solidity ^0.5.0; import "@openzeppelin/upgrades/contracts/Initializable.sol"; import "../../GSN/Context.sol"; import "../Roles.sol"; contract PauserRole is Initializable, Context { using Roles for Roles.Role; event PauserAdded(address indexed account); event PauserRemoved(address indexed account); Roles.Role private _pausers; function initialize(address sender) public initializer { if (!isPauser(sender)) { _addPauser(sender); } } modifier onlyPauser() { require(isPauser(_msgSender()), "PauserRole: caller does not have the Pauser role"); _; } function isPauser(address account) public view returns (bool) { return _pausers.has(account); } function addPauser(address account) public onlyPauser { _addPauser(account); } function renouncePauser() public { _removePauser(_msgSender()); } function _addPauser(address account) internal { _pausers.add(account); emit PauserAdded(account); } function _removePauser(address account) internal { _pausers.remove(account); emit PauserRemoved(account); } uint256[50] private ______gap; }
pragma solidity ^0.5.0; import "@openzeppelin/upgrades/contracts/Initializable.sol"; import "../GSN/Context.sol"; import "../access/roles/PauserRole.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ contract Pausable is Initializable, Context, PauserRole { /** * @dev Emitted when the pause is triggered by a pauser (`account`). */ event Paused(address account); /** * @dev Emitted when the pause is lifted by a pauser (`account`). */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. Assigns the Pauser role * to the deployer. */ function initialize(address sender) public initializer { PauserRole.initialize(sender); _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. */ modifier whenNotPaused() { require(!_paused, "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. */ modifier whenPaused() { require(_paused, "Pausable: not paused"); _; } /** * @dev Called by a pauser to pause, triggers stopped state. */ function pause() public onlyPauser whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Called by a pauser to unpause, returns to normal state. */ function unpause() public onlyPauser whenPaused { _paused = false; emit Unpaused(_msgSender()); } uint256[50] private ______gap; }
pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
pragma solidity ^0.5.0; import "@openzeppelin/upgrades/contracts/Initializable.sol"; import "../GSN/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be aplied to your functions to restrict their use to * the owner. */ contract Ownable is Initializable, Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function initialize(address sender) public initializer { _owner = sender; emit OwnershipTransferred(address(0), _owner); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner(), "Ownable: caller is not the owner"); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return _msgSender() == _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 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 onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } uint256[50] private ______gap; }
pragma solidity ^0.5.0; import "@openzeppelin/upgrades/contracts/Initializable.sol"; import "../../GSN/Context.sol"; import "./IERC20.sol"; import "../../math/SafeMath.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 {ERC20Mintable}. * * 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 ERC20 is Initializable, Context, IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view 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 returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public 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 returns (bool) { _transfer(sender, recipient, amount); _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 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 returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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 returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 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 { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(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 { require(account != address(0), "ERC20: mint to the zero address"); _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(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 { require(account != address(0), "ERC20: burn from the zero address"); _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * This is 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 { 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 Destroys `amount` tokens from `account`.`amount` is then deducted * from the caller's allowance. * * See {_burn} and {_approve}. */ function _burnFrom(address account, uint256 amount) internal { _burn(account, amount); _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance")); } uint256[50] private ______gap; }
pragma solidity ^0.5.0; import "@openzeppelin/upgrades/contracts/Initializable.sol"; import "./IERC20.sol"; /** * @dev Optional functions from the ERC20 standard. */ contract ERC20Detailed is Initializable, IERC20 { string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of * these values are immutable: they can only be set once during * construction. */ function initialize(string memory name, string memory symbol, uint8 decimals) public initializer { _name = name; _symbol = symbol; _decimals = decimals; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view 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. * * 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 returns (uint8) { return _decimals; } uint256[50] private ______gap; }
pragma solidity ^0.5.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ interface IERC20 { /** * @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.5.0; import "./IERC20.sol"; import "../../math/SafeMath.sol"; import "../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // 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(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 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(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. // A Solidity high level call has three parts: // 1. The target address is checked to verify it contains contract code // 2. The call itself is made, and success asserted // 3. The return value is decoded, which in turn checks the size of the returned data. // solhint-disable-next-line max-line-length require(address(token).isContract(), "SafeERC20: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success, "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"); } } }
pragma solidity ^0.5.5; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Converts an `address` into `address payable`. Note that this is * simply a type cast: the actual underlying value is not changed. * * _Available since v2.4.0._ */ function toPayable(address account) internal pure returns (address payable) { return address(uint160(account)); } /** * @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]. * * _Available since v2.4.0._ */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-call-value (bool success, ) = recipient.call.value(amount)(""); require(success, "Address: unable to send value, recipient may have reverted"); } }
pragma solidity ^0.5.0; import "@openzeppelin/upgrades/contracts/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. */ contract ReentrancyGuard is Initializable { // counter to allow mutex lock with only one SSTORE operation uint256 private _guardCounter; function initialize() public initializer { // The counter starts at one to prevent changing it from zero to a non-zero // value, which is a more expensive operation. _guardCounter = 1; } /** * @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() { _guardCounter += 1; uint256 localCounter = _guardCounter; _; require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call"); } uint256[50] private ______gap; }
pragma solidity >=0.4.24 <0.7.0; /** * @title Initializable * * @dev Helper contract to support initializer functions. To use it, replace * the constructor with a function that has the `initializer` modifier. * WARNING: Unlike constructors, initializer functions must be manually * invoked. This applies both to deploying an Initializable contract, as well * as extending an Initializable contract via inheritance. * WARNING: When used with inheritance, manual care must be taken to not invoke * a parent initializer twice, or ensure that all initializers are idempotent, * because this is not dealt with automatically as with constructors. */ 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 use in the initializer function of a contract. */ modifier initializer() { require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized"); bool isTopLevelCall = !initializing; if (isTopLevelCall) { initializing = true; initialized = true; } _; if (isTopLevelCall) { initializing = false; } } /// @dev Returns true if and only if the function is running in the constructor function isConstructor() private view returns (bool) { // extcodesize checks the size of the code stored in an address, and // address returns the current address. Since the code is still not // deployed when running a constructor, any checks on its code size will // yield zero, making it an effective way to detect if a contract is // under construction or not. address self = address(this); uint256 cs; assembly { cs := extcodesize(self) } return cs == 0; } // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; }
{ "remappings": [], "optimizer": { "enabled": true, "runs": 1 }, "evmVersion": "istanbul", "libraries": {}, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } } }
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":"target","type":"address"},{"indexed":true,"internalType":"address","name":"initiator","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"premium","type":"uint256"}],"name":"FlashLoan","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"PauserAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"PauserRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_rebalancer","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"Rebalance","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"_ref","type":"address"}],"name":"Referral","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"constant":true,"inputs":[],"name":"COMP","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"IDLE","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"_init","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addPauser","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allAvailableTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"feeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"flashFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IERC3156FlashBorrower","name":"_receiver","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_params","type":"bytes"}],"name":"flashLoan","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"flashLoanFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getAPRs","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getAllAvailableTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getAllocations","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getAvgAPR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getGovTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_usr","type":"address"}],"name":"getGovTokensAmounts","outputs":[{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_protocolToken","type":"address"}],"name":"getProtocolTokenToGov","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"govTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"govTokensIndexes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"govTokensLastBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"gst2","outputs":[{"internalType":"contract GasToken","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"idleController","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isPauser","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isRiskAdjusted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lastAllocations","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastITokenPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"maxFlashLoan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxUnlentPerc","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"address","name":"_referral","type":"address"}],"name":"mintIdleToken","outputs":[{"internalType":"uint256","name":"mintedTokens","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"oracle","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"protocolWrappers","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"rebalance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"rebalancer","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"redeemIdleToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool[]","name":"_skipGovTokenRedeem","type":"bool[]"}],"name":"redeemIdleTokenSkipGov","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"redeemInterestBearingTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renouncePauser","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_aToken","type":"address"}],"name":"setAToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address[]","name":"protocolTokens","type":"address[]"},{"internalType":"address[]","name":"wrappers","type":"address[]"},{"internalType":"address[]","name":"_newGovTokens","type":"address[]"},{"internalType":"address[]","name":"_newGovTokensEqualLen","type":"address[]"}],"name":"setAllAvailableTokensAndWrappers","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256[]","name":"_allocations","type":"uint256[]"}],"name":"setAllocations","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_cToken","type":"address"}],"name":"setCToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_feeAddress","type":"address"}],"name":"setFeeAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_perc","type":"uint256"}],"name":"setMaxUnlentPerc","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_oracle","type":"address"}],"name":"setOracleAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_rebalancer","type":"address"}],"name":"setRebalancer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_tokenHelper","type":"address"}],"name":"setTokenHelper","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"stkAAVE","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokenHelper","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokenPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"tokenPriceWithFee","outputs":[{"internalType":"uint256","name":"priceWFee","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"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"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userAvgPrices","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"usersGovTokensIndexes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]
Contract Creation Code
6080604052615fa0806100136000396000f3fe608060405234801561001057600080fd5b50600436106103595760003560e01c806301d22ccd1461035e57806306fdde0314610382578063095ea7b3146103ff5780630b56d1571461043f5780630df94ef21461045e57806312ea5c7e146104965780631624f6c6146104ee57806318160ddd1461061c578063194a62a8146106245780631f80b18a146106415780631fc29c011461064957806323b872dd1461065157806323d39ab5146106875780632b1b4bb01461068f5780632befabbf146106b55780632fdc91ee146106e9578063313ce567146106f157806336a000821461070f578063395093511461072c5780633f4ba83a14610758578063412753581461076057806345c8026c1461076857806346fbf68e1461078e5780634847cdc8146107b45780634c69c00f146107bc5780634cb71222146107e257806350b28af7146108085780635478786c1461082e57806354924507146108365780635c975abb1461083e5780635cffe9de146108465780635f09d84c146108d4578063613255ab146108fa5780636287fe211461092057806365ed6e231461094657806369fe0e2d1461094e5780636c11ec961461096b5780636cfd1553146109915780636ef8d66d146109b757806370a08231146109bf578063715018a6146109e5578063746daa4e146109ed5780637d7c2a1c14610a0a5780637dc0d1d014610a125780637ff9b59614610a1a5780638129fc1c14610a2257806382dc1ec414610a2a5780638456cb5914610a505780638705fcd414610a585780638a279e8a14610a7e5780638b30b51614610aac5780638cba144414610ac95780638da5cb5b14610aef5780638f32d59b14610af757806395d89b4114610aff5780639602e9f814610b07578063a457c2d714610b0f578063a6ea311c14610b3b578063a9059cbb14610b43578063aaa48e9f14610b6f578063afdd3fc314610b95578063b13bd49114610bb2578063b349b97314610c53578063b616b63d14610c5b578063b71501bc14610cd0578063c498c51514610cd8578063c4d66de814610d46578063cb390f9714610d6c578063d9d98ce414610d74578063dd62ed3e14610da0578063ddca3f4314610dce578063f16c88db14610dd6578063f2d50ba614610f34578063f2fde38b14610f3c578063fc0c546a14610f62575b600080fd5b610366610f6a565b604080516001600160a01b039092168252519081900360200190f35b61038a610f7a565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103c45781810151838201526020016103ac565b50505050905090810190601f1680156103f15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61042b6004803603604081101561041557600080fd5b506001600160a01b038135169060200135611011565b604080519115158252519081900360200190f35b61045c6004803603602081101561045557600080fd5b503561102f565b005b6104846004803603602081101561047457600080fd5b50356001600160a01b03166110bb565b60408051918252519081900360200190f35b61049e6110ce565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156104da5781810151838201526020016104c2565b505050509050019250505060405180910390f35b61045c6004803603606081101561050457600080fd5b810190602081018135600160201b81111561051e57600080fd5b82018360208201111561053057600080fd5b803590602001918460018302840111600160201b8311171561055157600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b8111156105a357600080fd5b8201836020820111156105b557600080fd5b803590602001918460018302840111600160201b831117156105d657600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903560ff1691506111309050565b61048461120c565b61045c6004803603602081101561063a57600080fd5b5035611212565b6104846113a8565b610366611440565b61042b6004803603606081101561066757600080fd5b506001600160a01b03813581169160208101359091169060400135611458565b6103666114e0565b610366600480360360208110156106a557600080fd5b50356001600160a01b03166114f0565b610484600480360360608110156106cb57600080fd5b508035906020810135151590604001356001600160a01b0316611512565b6103666116b5565b6106f96116c5565b6040805160ff9092168252519081900360200190f35b6103666004803603602081101561072557600080fd5b50356116ce565b61042b6004803603604081101561074257600080fd5b506001600160a01b0381351690602001356116f6565b61045c61174a565b610366611835565b6103666004803603602081101561077e57600080fd5b50356001600160a01b0316611845565b61042b600480360360208110156107a457600080fd5b50356001600160a01b0316611861565b610484611875565b61045c600480360360208110156107d257600080fd5b50356001600160a01b031661187c565b61045c600480360360208110156107f857600080fd5b50356001600160a01b0316611917565b61049e6004803603602081101561081e57600080fd5b50356001600160a01b03166119b2565b610366611aa2565b610484611aba565b61042b611ac1565b61042b6004803603608081101561085c57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561089657600080fd5b8201836020820111156108a857600080fd5b803590602001918460018302840111600160201b831117156108c957600080fd5b509092509050611acb565b61045c600480360360208110156108ea57600080fd5b50356001600160a01b0316612091565b6104846004803603602081101561091057600080fd5b50356001600160a01b031661212c565b6104846004803603602081101561093657600080fd5b50356001600160a01b031661216c565b61049e61217f565b61045c6004803603602081101561096457600080fd5b50356121d7565b61045c6004803603602081101561098157600080fd5b50356001600160a01b031661225f565b61045c600480360360208110156109a757600080fd5b50356001600160a01b03166122fa565b61045c612395565b610484600480360360208110156109d557600080fd5b50356001600160a01b03166123a7565b61045c6123c2565b61036660048036036020811015610a0357600080fd5b5035612441565b61042b61244f565b61036661245e565b61048461246e565b61045c612478565b61045c60048036036020811015610a4057600080fd5b50356001600160a01b031661251e565b61045c61256d565b61045c60048036036020811015610a6e57600080fd5b50356001600160a01b0316612636565b61048460048036036040811015610a9457600080fd5b506001600160a01b03813581169160200135166126d1565b61048460048036036020811015610ac257600080fd5b50356126ef565b61048460048036036020811015610adf57600080fd5b50356001600160a01b031661272b565b6103666127b7565b61042b6127c6565b61038a6127ec565b61036661284d565b61042b60048036036040811015610b2557600080fd5b506001600160a01b038135169060200135612865565b61049e6128d3565b61042b60048036036040811015610b5957600080fd5b506001600160a01b038135169060200135612934565b61048460048036036020811015610b8557600080fd5b50356001600160a01b031661296a565b61048460048036036020811015610bab57600080fd5b503561297d565b610bba61299c565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015610bfe578181015183820152602001610be6565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015610c3d578181015183820152602001610c25565b5050505090500194505050505060405180910390f35b61045c612b42565b61048460048036036040811015610c7157600080fd5b81359190810190604081016020820135600160201b811115610c9257600080fd5b820183602082011115610ca457600080fd5b803590602001918460208302840111600160201b83111715610cc557600080fd5b509092509050612b9d565b610366612be4565b61045c60048036036020811015610cee57600080fd5b810190602081018135600160201b811115610d0857600080fd5b820183602082011115610d1a57600080fd5b803590602001918460208302840111600160201b83111715610d3b57600080fd5b509092509050612bfc565b61045c60048036036020811015610d5c57600080fd5b50356001600160a01b0316612c9f565b61042b612d55565b61048460048036036040811015610d8a57600080fd5b506001600160a01b038135169060200135612d5f565b61048460048036036040811015610db657600080fd5b506001600160a01b0381358116916020013516612dc6565b610484612df1565b61045c60048036036080811015610dec57600080fd5b810190602081018135600160201b811115610e0657600080fd5b820183602082011115610e1857600080fd5b803590602001918460208302840111600160201b83111715610e3957600080fd5b919390929091602081019035600160201b811115610e5657600080fd5b820183602082011115610e6857600080fd5b803590602001918460208302840111600160201b83111715610e8957600080fd5b919390929091602081019035600160201b811115610ea657600080fd5b820183602082011115610eb857600080fd5b803590602001918460208302840111600160201b83111715610ed957600080fd5b919390929091602081019035600160201b811115610ef657600080fd5b820183602082011115610f0857600080fd5b803590602001918460208302840111600160201b83111715610f2957600080fd5b509092509050612df8565b610484613048565b61045c60048036036020811015610f5257600080fd5b50356001600160a01b031661304f565b61036661309f565b61016d546001600160a01b031681565b60688054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156110065780601f10610fdb57610100808354040283529160200191611006565b820191906000526020600020905b815481529060010190602001808311610fe957829003601f168201915b505050505090505b90565b600061102561101e6130af565b84846130b3565b5060015b92915050565b6110376127c6565b611076576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b620186a08161017181905511156110b8576040805162461bcd60e51b81526020600482015260016024820152603560f81b604482015290519081900360640190fd5b50565b6101766020526000908152604090205481565b606061017380548060200260200160405190810160405280929190818152602001828054801561100657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611109575050505050905090565b600054610100900460ff1680611149575061114961319f565b80611157575060005460ff16155b6111925760405162461bcd60e51b815260040180806020018281038252602e815260200180615e65602e913960400191505060405180910390fd5b600054610100900460ff161580156111bd576000805460ff1961ff0019909116610100171660011790555b83516111d0906068906020870190615b22565b5082516111e4906069906020860190615b22565b50606a805460ff191660ff84161790558015611206576000805461ff00191690555b50505050565b60355490565b609d8054600101908190556101365460ff1661126c576040805162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015290519081900360640190fd5b6112746131a5565b61127d33613224565b60005b6101735481101561131157611309610173828154811061129c57fe5b6000918252602090912001546001600160a01b0316336113046112bd61120c565b6112f86112eb61017388815481106112d157fe5b6000918252602090912001546001600160a01b031661325e565b899063ffffffff61336b16565b9063ffffffff6133c416565b613403565b600101611280565b5061016a54611356906001600160a01b03163361130461132f61120c565b61016a546112f890611349906001600160a01b031661325e565b889063ffffffff61336b16565b6113603383613422565b609d5481146113a4576040805162461bcd60e51b815260206004820152601f6024820152600080516020615cb9833981519152604482015290519081900360640190fd5b5050565b6101825461016c546101835460408051635ad5aadf60e01b81523060048201526001600160a01b0393841660248201529183166044830152516000939290921691635ad5aadf91606480820192602092909190829003018186803b15801561140f57600080fd5b505afa158015611423573d6000803e3d6000fd5b505050506040513d602081101561143957600080fd5b5051905090565b734da27a545c0c5b758a6ba100e3a049001de870f581565b600061146584848461350c565b6114708484846136b7565b6114ae84336114a985604051806060016040528060288152602001615ddb6028913961149c8a33612dc6565b919063ffffffff61380316565b6130b3565b6001600160a01b038416600090815261017660205260409020546114d5908490849061389a565b5060015b9392505050565b610169546001600160a01b031681565b6001600160a01b03808216600090815261017e6020526040902054165b919050565b609d805460010190819055610136546000919060ff161561156d576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b604080513260601b60208083019190915243603480840191909152835180840390910181526054909201909252805191012061017c556115ac33613224565b60006115b661391a565b61016a549091506115d8906001600160a01b031633308963ffffffff613a4e16565b6115f4816112f888670de0b6b3a764000063ffffffff61336b16565b92506116003384613aa8565b61160a3384613b88565b61161533848361389a565b6001600160a01b0384161561166857604080518781526001600160a01b038616602082015281517f496d589d8b7eb829a8d7b30e24a326ac33991f5cea96429b69231a6b15b54b1d929181900390910190a15b50609d5481146116ad576040805162461bcd60e51b815260206004820152601f6024820152600080516020615cb9833981519152604482015290519081900360640190fd5b509392505050565b610182546001600160a01b031681565b606a5460ff1690565b61017381815481106116dc57fe5b6000918252602090912001546001600160a01b0316905081565b60006110256117036130af565b846114a985603460006117146130af565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff613c5816565b61175a6117556130af565b611861565b6117955760405162461bcd60e51b8152600401808060200182810382526030815260200180615cfb6030913960400191505060405180910390fd5b6101365460ff166117e4576040805162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015290519081900360640190fd5b610136805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6118186130af565b604080516001600160a01b039092168252519081900360200190a1565b61016e546001600160a01b031681565b610177602052600090815260409020546001600160a01b031681565b60006110296101038363ffffffff613cb016565b6101815481565b6118846127c6565b6118c3576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b61017d80546001600160a01b0319166001600160a01b0383169081179091556110b8576040805162461bcd60e51b81526020600482015260016024820152600360fc1b604482015290519081900360640190fd5b61191f6127c6565b61195e576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b61016c80546001600160a01b0319166001600160a01b0383169081179091556110b8576040805162461bcd60e51b81526020600482015260016024820152600360fc1b604482015290519081900360640190fd5b60606000806119c0846123a7565b6101745460408051828152602080840282010190915291925080156119ef578160200160208202803883390190505b50925060005b8351811015611a9a576101748181548110611a0c57fe5b60009182526020808320909101546001600160a01b0390811680845261017983526040808520928a1685529183528184205481855261017a909352922054919450611a7b91670de0b6b3a7640000916112f891611a6e9163ffffffff613d1716565b859063ffffffff61336b16565b848281518110611a8757fe5b60209081029190910101526001016119f5565b505050919050565b73875773784af8135ea0ef43b5a374aad105c5d39e81565b6101715481565b6101365460ff1690565b6101365460009060ff1615611b1a576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b609d80546001019081905561016a5487906001600160a01b03888116911614611b6e576040805162461bcd60e51b81526020600482015260016024820152603760f81b604482015290519081900360640190fd5b6001600160a01b03811615801590611b865750600086115b611bbb576040805162461bcd60e51b81526020600482015260016024820152600360fc1b604482015290519081900360640190fd5b61016a54600090611bd4906001600160a01b031661325e565b905080871115611dd4576000611bf0888363ffffffff613d1716565b905060008080808080808080805b61017354811015611dc8576101738181548110611c1757fe5b60009182526020808320909101546001600160a01b03908116808452610177835260409384902054845163015de72360e11b81529451919d50909116965086926302bbce46926004808301939192829003018186803b158015611c7957600080fd5b505afa158015611c8d573d6000803e3d6000fd5b505050506040513d6020811015611ca357600080fd5b505160408051637437535960e01b815290519196506001600160a01b03861691637437535991600480820192602092909190829003018186803b158015611ce957600080fd5b505afa158015611cfd573d6000803e3d6000fd5b505050506040513d6020811015611d1357600080fd5b50519650611d3c670de0b6b3a76400006112f887611d308d61325e565b9063ffffffff61336b16565b97508a88101591508a871015925081611d645786881115611d5d5786611d5f565b875b611d71565b82611d6f5786611d71565b8a5b9950611d9889611d93876112f88e670de0b6b3a764000063ffffffff61336b16565b613d59565b9550818015611da45750825b15611dae57611dc8565b611dbe8b8763ffffffff613d1716565b9a50600101611bfe565b50505050505050505050505b61016a548790611dec906001600160a01b031661325e565b1015611e23576040805162461bcd60e51b81526020600482015260016024820152603360f81b604482015290519081900360640190fd5b61016a54611e3b906001600160a01b03168389613403565b61016a54600090611e55906001600160a01b031689612d5f565b905060405180807f45524333313536466c617368426f72726f7765722e6f6e466c6173684c6f616e815250602001905060405180910390208a6001600160a01b03166323e30c8b3361016a60009054906101000a90046001600160a01b03168c868d8d6040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050975050505050505050602060405180830381600087803b158015611f5957600080fd5b505af1158015611f6d573d6000803e3d6000fd5b505050506040513d6020811015611f8357600080fd5b505114611fbb576040805162461bcd60e51b81526020600482015260016024820152600760fb1b604482015290519081900360640190fd5b611feb8330611fd08b8563ffffffff613c5816565b61016a546001600160a01b031692919063ffffffff613a4e16565b611ff3613dfa565b506040805189815260208101839052815133926001600160a01b038716927f0d7d75e01ab95780d3cd1c8ec0dd6c2ce19e3a20427eec8bf53283b6fb8e95f0929081900390910190a360019450505050609d548114612087576040805162461bcd60e51b815260206004820152601f6024820152600080516020615cb9833981519152604482015290519081900360640190fd5b5095945050505050565b6120996127c6565b6120d8576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b61018380546001600160a01b0319166001600160a01b0383169081179091556110b8576040805162461bcd60e51b81526020600482015260016024820152600360fc1b604482015290519081900360640190fd5b61016a546000906001600160a01b038381169116141561150d57612165670de0b6b3a76400006112f861215d61120c565b611d3061391a565b905061150d565b6101786020526000908152604090205481565b606061018080548060200260200160405190810160405280929190818152602001828054801561100657602002820191906000526020600020905b8154815260200190600101908083116121ba575050505050905090565b6121df6127c6565b61221e576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b6101728190556127108111156110b8576040805162461bcd60e51b81526020600482015260016024820152603560f81b604482015290519081900360640190fd5b6122676127c6565b6122a6576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b61018280546001600160a01b0319166001600160a01b0383169081179091556110b8576040805162461bcd60e51b81526020600482015260016024820152600360fc1b604482015290519081900360640190fd5b6123026127c6565b612341576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b61016d80546001600160a01b0319166001600160a01b0383169081179091556110b8576040805162461bcd60e51b81526020600482015260016024820152600360fc1b604482015290519081900360640190fd5b6123a56123a06130af565b614188565b565b6001600160a01b031660009081526033602052604090205490565b6123ca6127c6565b612409576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b60d0546040516000916001600160a01b031690600080516020615e23833981519152908390a360d080546001600160a01b0319169055565b61017481815481106116dc57fe5b6000612459613dfa565b905090565b61017d546001600160a01b031681565b600061245961391a565b600054610100900460ff1680612491575061249161319f565b8061249f575060005460ff16155b6124da5760405162461bcd60e51b815260040180806020018281038252602e815260200180615e65602e913960400191505060405180910390fd5b600054610100900460ff16158015612505576000805460ff1961ff0019909116610100171660011790555b6001609d5580156110b8576000805461ff001916905550565b6125296117556130af565b6125645760405162461bcd60e51b8152600401808060200182810382526030815260200180615cfb6030913960400191505060405180910390fd5b6110b8816141d1565b6125786117556130af565b6125b35760405162461bcd60e51b8152600401808060200182810382526030815260200180615cfb6030913960400191505060405180910390fd5b6101365460ff16156125ff576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b610136805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586118186130af565b61263e6127c6565b61267d576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b61016e80546001600160a01b0319166001600160a01b0383169081179091556110b8576040805162461bcd60e51b81526020600482015260016024820152600360fc1b604482015290519081900360640190fd5b61017960209081526000928352604080842090915290825290205481565b60006110298261017480549050604051908082528060200260200182016040528015612725578160200160208202803883390190505b5061421a565b6001600160a01b0381166000908152610176602052604081205461274d61391a565b9150801580159061275d57508082115b156127b1576127ae620186a06112f861278f61277f868663ffffffff613d1716565b610172549063ffffffff61336b16565b6127a286620186a063ffffffff61336b16565b9063ffffffff613d1716565b91505b50919050565b60d0546001600160a01b031690565b60d0546000906001600160a01b03166127dd6130af565b6001600160a01b031614905090565b60698054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156110065780601f10610fdb57610100808354040283529160200191611006565b73275da8e61ea8e02d51edd8d0dc5c0e62b4cdb0be81565b60006110256128726130af565b846114a985604051806060016040528060258152602001615f47602591396034600061289c6130af565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff61380316565b6060610174805480602002602001604051908101604052809291908181526020018280548015611006576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611109575050505050905090565b600061294133848461350c565b61294c3384846136b7565b3360009081526101766020526040902054611025908490849061389a565b61017a6020526000908152604090205481565b610175818154811061298b57fe5b600091825260209091200154905081565b6101825460408051634a4b15d160e01b8152306004820152905160609283926001600160a01b0390911691634a4b15d191602480820192600092909190829003018186803b1580156129ed57600080fd5b505afa158015612a01573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040908152811015612a2a57600080fd5b8101908080516040519392919084600160201b821115612a4957600080fd5b908301906020820185811115612a5e57600080fd5b82518660208202830111600160201b82111715612a7a57600080fd5b82525081516020918201928201910280838360005b83811015612aa7578181015183820152602001612a8f565b5050505090500160405260200180516040519392919084600160201b821115612acf57600080fd5b908301906020820185811115612ae457600080fd5b82518660208202830111600160201b82111715612b0057600080fd5b82525081516020918201928201910280838360005b83811015612b2d578181015183820152602001612b15565b50505050905001604052505050915091509091565b61017d546001600160a01b031673b5a8f07dd4c3d315869405d702ee8f6ea695e8c514612b6e57600080fd5b61017d80546001600160a01b03191673758c10272a15f0e9d50cbc035ff9a046945da0f2179055601461018155565b6000612bdc8484848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061421a92505050565b949350505050565b73c00e94cb662c3520282e6f5717214004a7f2688881565b61016d546001600160a01b0316331480612c2e5750612c196127b7565b6001600160a01b0316336001600160a01b0316145b612c63576040805162461bcd60e51b81526020600482015260016024820152601b60f91b604482015290519081900360640190fd5b6113a482828080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061432392505050565b600054610100900460ff1680612cb85750612cb861319f565b80612cc6575060005460ff16155b612d015760405162461bcd60e51b815260040180806020018281038252602e815260200180615e65602e913960400191505060405180910390fd5b600054610100900460ff16158015612d2c576000805460ff1961ff0019909116610100171660011790555b612d35826143ed565b610136805460ff1916905580156113a4576000805461ff00191690555050565b61017f5460ff1681565b61016a546000906001600160a01b03848116911614612da9576040805162461bcd60e51b81526020600482015260016024820152603760f81b604482015290519081900360640190fd5b6114d9620186a06112f8610181548561336b90919063ffffffff16565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6101725481565b612e006127c6565b612e3f576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b868514612e77576040805162461bcd60e51b81526020600482015260016024820152601960f91b604482015290519081900360640190fd5b86811015612eb0576040805162461bcd60e51b81526020600482015260016024820152603360f81b604482015290519081900360640190fd5b612ebd6101748585615ba0565b50600080805b8981101561302d578a8a82818110612ed757fe5b905060200201356001600160a01b0316915060006001600160a01b0316826001600160a01b031614158015612f3157506000898983818110612f1557fe5b905060200201356001600160a01b03166001600160a01b031614155b612f66576040805162461bcd60e51b81526020600482015260016024820152600360fc1b604482015290519081900360640190fd5b888882818110612f7257fe5b6001600160a01b0385811660009081526101776020908152604090912080546001600160a01b031916939091029490940135161790915550848482818110612fb657fe5b905060200201356001600160a01b0316925073875773784af8135ea0ef43b5a374aad105c5d39e6001600160a01b0316836001600160a01b031614613025576001600160a01b03828116600090815261017e6020526040902080546001600160a01b0319169185169190911790555b600101612ec3565b5061303b6101738b8b615ba0565b5050505050505050505050565b61016f5481565b6130576127c6565b613096576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b6110b8816144a5565b61016a546001600160a01b031681565b3390565b6001600160a01b0383166130f85760405162461bcd60e51b8152600401808060200182810382526024815260200180615ef96024913960400191505060405180910390fd5b6001600160a01b03821661313d5760405162461bcd60e51b8152600401808060200182810382526022815260200180615d516022913960400191505060405180910390fd5b6001600160a01b03808416600081815260346020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b303b1590565b61017c54324360405160200180836001600160a01b03166001600160a01b031660601b8152601401828152602001925050506040516020818303038152906040528051906020012014156123a5576040805162461bcd60e51b81526020600482015260016024820152603960f81b604482015290519081900360640190fd5b6110b88161017480549050604051908082528060200260200182016040528015613258578160200160208202803883390190505b50614534565b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b1781529151815160009384936060936001600160a01b03881693919290918291908083835b602083106132d85780518252601f1990920191602091820191016132b9565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613338576040519150601f19603f3d011682016040523d82523d6000602084013e61333d565b606091505b50915091508161334c57600080fd5b80806020019051602081101561336157600080fd5b5051949350505050565b60008261337a57506000611029565b8282028284828161338757fe5b04146114d95760405162461bcd60e51b8152600401808060200182810382526021815260200180615dba6021913960400191505060405180910390fd5b60006114d983836040518060400160405280601a815260200179536166654d6174683a206469766973696f6e206279207a65726f60301b8152506148bd565b61341d6001600160a01b038416838363ffffffff61492216565b505050565b6001600160a01b0382166134675760405162461bcd60e51b8152600401808060200182810382526021815260200180615eb36021913960400191505060405180910390fd5b6134aa81604051806060016040528060228152602001615cd9602291396001600160a01b038516600090815260336020526040902054919063ffffffff61380316565b6001600160a01b0383166000908152603360205260409020556035546134d6908263ffffffff613d1716565b6035556040805182815290516000916001600160a01b03851691600080516020615e938339815191529181900360200190a35050565b600080600080600061351d876123a7565b905060005b610174548110156136ac57610174818154811061353b57fe5b6000918252602090912001546001600160a01b031695508161358d576001600160a01b038681166000908152610179602090815260408083208d8516845290915280822054928b1682529020556136a4565b6001600160a01b03808716600090815261017a60209081526040808320546101798352818420948e168452939091529020549095506135d390869063ffffffff613d1716565b6001600160a01b03808816600090815261017960209081526040808320938d168352929052205490945061362090670de0b6b3a7640000906112f890611a6e90899063ffffffff613d1716565b925061367c61366f613638848a63ffffffff613c5816565b6112f861364b888c63ffffffff61336b16565b61366388670de0b6b3a764000063ffffffff61336b16565b9063ffffffff613c5816565b869063ffffffff613d1716565b6001600160a01b03808816600090815261017960209081526040808320938d16835292905220555b600101613522565b505050505050505050565b6001600160a01b0383166136fc5760405162461bcd60e51b8152600401808060200182810382526025815260200180615ed46025913960400191505060405180910390fd5b6001600160a01b0382166137415760405162461bcd60e51b8152600401808060200182810382526023815260200180615c966023913960400191505060405180910390fd5b61378481604051806060016040528060268152602001615d73602691396001600160a01b038616600090815260336020526040902054919063ffffffff61380316565b6001600160a01b0380851660009081526033602052604080822093909355908416815220546137b9908263ffffffff613c5816565b6001600160a01b038084166000818152603360209081526040918290209490945580518581529051919392871692600080516020615e9383398151915292918290030190a3505050565b600081848411156138925760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561385757818101518382015260200161383f565b50505050905090810190601f1680156138845780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60006138a5846123a7565b90506138f7816112f86138be858763ffffffff61336b16565b6136636138d1868963ffffffff613d1716565b6001600160a01b038a16600090815261017660205260409020549063ffffffff61336b16565b6001600160a01b0390941660009081526101766020526040902093909355505050565b60008061392561120c565b90508061393a57505061017054600a0a61100e565b61016a54600090819061396390670de0b6b3a764000090611d30906001600160a01b031661325e565b905060606101738054806020026020016040519081016040528092919081815260200182805480156139be57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116139a0575b50939450600093505050505b8151811015613a34578181815181106139df57fe5b60200260200101519350613a2a613a1d6139f88661325e565b6001600160a01b0380881660009081526101776020526040902054611d309116614974565b849063ffffffff613c5816565b92506001016139ca565b50613a45828563ffffffff6133c416565b94505050505090565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526112069085906149e1565b6001600160a01b038216613b03576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b603554613b16908263ffffffff613c5816565b6035556001600160a01b038216600090815260336020526040902054613b42908263ffffffff613c5816565b6001600160a01b0383166000818152603360209081526040808320949094558351858152935192939192600080516020615e938339815191529281900390910190a35050565b600080613b94846123a7565b90506000805b61017454811015613c50576101748181548110613bb357fe5b60009182526020808320909101546001600160a01b0390811680845261017983526040808520928b1685529183528184205481855261017a9093529220549195509250613c2190613c149085906112f8906112eb908763ffffffff613d1716565b839063ffffffff613c5816565b6001600160a01b03808616600090815261017960209081526040808320938b1683529290522055600101613b9a565b505050505050565b6000828201838110156114d9576040805162461bcd60e51b815260206004820152601b60248201527a536166654d6174683a206164646974696f6e206f766572666c6f7760281b604482015290519081900360640190fd5b60006001600160a01b038216613cf75760405162461bcd60e51b8152600401808060200182810382526022815260200180615e436022913960400191505060405180910390fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b60006114d983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613803565b60008115611029576001600160a01b038084166000908152610177602052604090205416613d88848285613403565b604080516395a2251f60e01b815230600482015290516001600160a01b038316916395a2251f9160248083019260209291908290030181600087803b158015613dd057600080fd5b505af1158015613de4573d6000803e3d6000fd5b505050506040513d602081101561336157600080fd5b6101365460009060ff1615613e49576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b6060610180805480602002602001604051908101604052809291908181526020018280548015613e9857602002820191906000526020600020905b815481526020019060010190808311613e84575b505050505090506060610175805480602002602001604051908101604052809291908181526020018280548015613eee57602002820191906000526020600020905b815481526020019060010190808311613eda575b50508351865194955093841492505081159050613f595760005b82811080613f14575081155b15613f5757848181518110613f2557fe5b6020026020010151848281518110613f3957fe5b602002602001015114613f4f5760009150613f57565b600101613f08565b505b61016a54600090613f72906001600160a01b031661325e565b9050818015613f7f575080155b15613f925760009550505050505061100e565b6000613faa620186a06112f861017154611d30614b99565b90508215613fe25780821115613fd357613fd386613fce848463ffffffff613d1716565b614c99565b6000965050505050505061100e565b60606000613fee614df3565b9092509050614003818563ffffffff613c5816565b9050606060008061402c856140278d614022888b63ffffffff613d1716565b614f14565b614ff7565b9250925092508061405a576140446101756000615bff565b8a51614058906101759060208e0190615c1d565b505b61016a54600090614073906001600160a01b031661325e565b90508681111580614082575082155b1561409c5760009c5050505050505050505050505061100e565b606084516040519080825280602002602001820160405280156140c9578160200160208202803883390190505b50905060005b855181101561412457614105856112f8620186a08985815181106140ef57fe5b602002602001015161336b90919063ffffffff16565b82828151811061411157fe5b60209081029190910101526001016140cf565b5061413981613fce848b63ffffffff613d1716565b604080513381526020810188905281517f4217d9fab39dbadacf1dad6c889aec1caa02e8a6cb59ddd4ce34f3e0ef158b55929181900390910190a160019d505050505050505050505050505090565b61419a6101038263ffffffff6152a516565b6040516001600160a01b038216907fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e90600090a250565b6141e36101038263ffffffff61530c16565b6040516001600160a01b038216907f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f890600090a250565b609d8054600101908190556000906142306131a5565b61423a3384614534565b83156142d857600061424a61391a565b9050600061426a670de0b6b3a76400006112f8888563ffffffff61336b16565b61016a54909150600090614286906001600160a01b031661325e565b9050808211156142a15761429a878261538d565b94506142a5565b8194505b6142b087868561547d565b94506142bc3388613422565b61016a546142d4906001600160a01b03163387613403565b5050505b609d54811461431c576040805162461bcd60e51b815260206004820152601f6024820152600080516020615cb9833981519152604482015290519081900360640190fd5b5092915050565b6101735481511461435f576040805162461bcd60e51b81526020600482015260016024820152601960f91b604482015290519081900360640190fd5b6000805b825181101561439c5761439283828151811061437b57fe5b602002602001015183613c5890919063ffffffff16565b9150600101614363565b5081516143b190610180906020850190615c1d565b50620186a081146113a4576040805162461bcd60e51b81526020600482015260016024820152603760f81b604482015290519081900360640190fd5b600054610100900460ff1680614406575061440661319f565b80614414575060005460ff16155b61444f5760405162461bcd60e51b815260040180806020018281038252602e815260200180615e65602e913960400191505060405180910390fd5b600054610100900460ff1615801561447a576000805460ff1961ff0019909116610100171660011790555b61448382611861565b61449057614490826141d1565b80156113a4576000805461ff00191690555050565b6001600160a01b0381166144ea5760405162461bcd60e51b8152600401808060200182810382526026815260200180615d2b6026913960400191505060405180910390fd5b60d0546040516001600160a01b03808416921690600080516020615e2383398151915290600090a360d080546001600160a01b0319166001600160a01b0392909216919091179055565b606061017480548060200260200160405190810160405280929190818152602001828054801561458d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161456f575b505050505090508051600014156145a457506113a4565b60006145ae61120c565b905060006145bb856123a7565b905060008215613c505760005b84518110156148b4578481815181106145dd57fe5b602002602001015191506145f08261550b565b60006145fb8361325e565b90508015614696576001600160a01b0383166000908152610178602052604090205461466c906146469087906112f890670de0b6b3a764000090611d3090879063ffffffff613d1716565b6001600160a01b038516600090815261017a60205260409020549063ffffffff613c5816565b6001600160a01b038416600090815261017a60209081526040808320939093556101789052208190555b8315614879576001600160a01b03808416600081815261017960209081526040808320948d1683529381528382205492825261017a9052918220549091906146e4908363ffffffff613d1716565b9050801561487657600061470a670de0b6b3a76400006112f8898563ffffffff61336b16565b905060006147178761325e565b905080821115614725578091505b8a868151811061473157fe5b6020026020010151156147b15761479261476c6147548b8b63ffffffff613d1716565b6112f885670de0b6b3a764000063ffffffff61336b16565b6001600160a01b038916600090815261017a60205260409020549063ffffffff613c5816565b6001600160a01b038816600090815261017a6020526040902055614873565b61016e546000906001600160a01b0316158015906147d25750600061017254115b80156147fb57506001600160a01b03881673875773784af8135ea0ef43b5a374aad105c5d39e14155b156148395761481d620186a06112f8610172548661336b90919063ffffffff16565b61016e549091506148399089906001600160a01b031683613403565b61484e888e611304868563ffffffff613d1716565b6148578861325e565b6001600160a01b03891660009081526101786020526040902055505b50505b50505b506001600160a01b03808316600090815261017a60209081526040808320546101798352818420948c168452939091529020556001016145c8565b50505050505050565b6000818361490c5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561385757818101518382015260200161383f565b50600083858161491857fe5b0495945050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261341d9084906149e1565b6000816001600160a01b03166302bbce466040518163ffffffff1660e01b815260040160206040518083038186803b1580156149af57600080fd5b505afa1580156149c3573d6000803e3d6000fd5b505050506040513d60208110156149d957600080fd5b505192915050565b6149f3826001600160a01b0316615ae9565b614a44576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310614a825780518252601f199092019160209182019101614a63565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114614ae4576040519150601f19603f3d011682016040523d82523d6000602084013e614ae9565b606091505b509150915081614b40576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b80511561120657808060200190516020811015614b5c57600080fd5b50516112065760405162461bcd60e51b815260040180806020018281038252602a815260200180615f1d602a913960400191505060405180910390fd5b6000806060610173805480602002602001604051908101604052809291908181526020018280548015614bf557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311614bd7575b50939450600093505050505b8151811015614c7757818181518110614c1657fe5b60200260200101519250614c6d614c60670de0b6b3a76400006112f8614c3b8761325e565b6001600160a01b0380891660009081526101776020526040902054611d309116614974565b859063ffffffff613c5816565b9350600101614c01565b5061016a54614c9290613a1d906001600160a01b031661325e565b9250505090565b6060614ca58383614f14565b90506000806060610173805480602002602001604051908101604052809291908181526020018280548015614d0357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311614ce5575b50939450600093505050505b84518110156148b457848181518110614d2457fe5b6020026020010151935083600014614deb576101776000838381518110614d4757fe5b6020908102919091018101516001600160a01b039081168352908201929092526040016000205461016a549082169450614d8391168486613403565b826001600160a01b0316631249c58b6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614dbe57600080fd5b505af1158015614dd2573d6000803e3d6000fd5b505050506040513d6020811015614de857600080fd5b50505b600101614d0f565b60606000806060610173805480602002602001604051908101604052809291908181526020018280548015614e5157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311614e33575b5050505050905060008151905080604051908082528060200260200182016040528015614e88578160200160208202803883390190505b50945060005b81811015614f0c57828181518110614ea257fe5b60200260200101519350614ec4670de0b6b3a76400006112f8614c3b8761325e565b868281518110614ed057fe5b602002602001018181525050614f02868281518110614eeb57fe5b602002602001015186613c5890919063ffffffff16565b9450600101614e8e565b505050509091565b60608251604051908082528060200260200182016040528015614f41578160200160208202803883390190505b509050600080805b8551811015614fee576001865103811415614f8b57614f6e858363ffffffff613d1716565b848281518110614f7a57fe5b602002602001018181525050614fe6565b614fb8620186a06112f8888481518110614fa157fe5b60200260200101518861336b90919063ffffffff16565b9250614fca828463ffffffff613c5816565b915082848281518110614fd957fe5b6020026020010181815250505b600101614f49565b50505092915050565b60606000808451604051908082528060200260200182016040528015615027578160200160208202803883390190505b509250600080600080606061017380548060200260200160405190810160405280929190818152602001828054801561508957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161506b575b50939450600093505050505b8a51811015615298578181815181106150aa57fe5b602002602001015192508981815181106150c057fe5b602002602001015193508a81815181106150d657fe5b6020908102919091018101516001600160a01b038086166000908152610177909352604090922054909116965094508385111561523f57600061511f868663ffffffff613d1716565b90506000876001600160a01b031663743753596040518163ffffffff1660e01b815260040160206040518083038186803b15801561515c57600080fd5b505afa158015615170573d6000803e3d6000fd5b505050506040513d602081101561518657600080fd5b50519050818110156151b357600198506151b0620186a06112f883620182b863ffffffff61336b16565b91505b61523785611d938a6001600160a01b03166302bbce466040518163ffffffff1660e01b815260040160206040518083038186803b1580156151f357600080fd5b505afa158015615207573d6000803e3d6000fd5b505050506040513d602081101561521d57600080fd5b50516112f886670de0b6b3a764000063ffffffff61336b16565b505050615290565b61524f848663ffffffff613d1716565b89828151811061525b57fe5b60200260200101818152505061528d89828151811061527657fe5b602002602001015189613c5890919063ffffffff16565b97505b600101615095565b5050505050509250925092565b6152af8282613cb0565b6152ea5760405162461bcd60e51b8152600401808060200182810382526021815260200180615d996021913960400191505060405180910390fd5b6001600160a01b0316600090815260209190915260409020805460ff19169055565b6153168282613cb0565b15615368576040805162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b600080600061539a61120c565b905060606101738054806020026020016040519081016040528092919081815260200182805480156153f557602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116153d7575b50939450600093505050505b815181101561545b5781818151811061541657fe5b6020026020010151935061545161544485611d93866112f86154378a61325e565b8d9063ffffffff61336b16565b869063ffffffff613c5816565b9450600101615401565b50615473614c60836112f8898963ffffffff61336b16565b9695505050505050565b33600090815261017660205260408120548083101561549f57839150506114d9565b60006154d969152d02c7e14af68000006112f861017254611d306154cc878a613d1790919063ffffffff16565b8b9063ffffffff61336b16565b61016a5461016e549192506154fb916001600160a01b03918216911683613403565b615473858263ffffffff613d1716565b6001600160a01b03811673c00e94cb662c3520282e6f5717214004a7f26888148061555257506001600160a01b03811673875773784af8135ea0ef43b5a374aad105c5d39e145b8061557957506001600160a01b038116734da27a545c0c5b758a6ba100e3a049001de870f5145b156110b8576040805160018082528183019092526060916020808301908038833901905050905030816000815181106155ae57fe5b6001600160a01b039283166020918202929092010152821673875773784af8135ea0ef43b5a374aad105c5d39e14156156d45760408051637e122ea560e11b81526004810191825282516044820152825173275da8e61ea8e02d51edd8d0dc5c0e62b4cdb0be9263fc245d4a92859283929182916024820191606401906020808701910280838360005b83811015615650578181015183820152602001615638565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561568f578181015183820152602001615677565b50505050905001945050505050600060405180830381600087803b1580156156b657600080fd5b505af11580156156ca573d6000803e3d6000fd5b50505050506110b8565b604080516001808252818301909252606091602080830190803883390190505090506001600160a01b038316734da27a545c0c5b758a6ba100e3a049001de870f514801561572d5750610183546001600160a01b031615155b15615929576101835481516001600160a01b0390911690829060009061574f57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060008160008151811061577e57fe5b60200260200101516001600160a01b03166375d264136040518163ffffffff1660e01b815260040160206040518083038186803b1580156157be57600080fd5b505afa1580156157d2573d6000803e3d6000fd5b505050506040513d60208110156157e857600080fd5b505160408051630cc7d40f60e11b815230600482015290519192506001600160a01b03831691633111e7b3918591849163198fa81e916024808301926020929190829003018186803b15801561583d57600080fd5b505afa158015615851573d6000803e3d6000fd5b505050506040513d602081101561586757600080fd5b50516040516001600160e01b031960e085901b168152602481018290523060448201819052606060048301908152845160648401528451919290918291608401906020878101910280838360005b838110156158cd5781810151838201526020016158b5565b50505050905001945050505050602060405180830381600087803b1580156158f457600080fd5b505af1158015615908573d6000803e3d6000fd5b505050506040513d602081101561591e57600080fd5b506110b89350505050565b61016c546001600160a01b03161561341d5761016c5481516001600160a01b0390911690829060009061595857fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508060008151811061598557fe5b60200260200101516001600160a01b0316635fe3b5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156159c557600080fd5b505afa1580156159d9573d6000803e3d6000fd5b505050506040513d60208110156159ef57600080fd5b50516040516334086fd360e11b81526000604482018190526001606483018190526080600484019081528651608485015286516001600160a01b0390951694636810dfa694889488949093909290918291602482019160a40190602089810191028083838a5b83811015615a6d578181015183820152602001615a55565b50505050905001838103825286818151815260200191508051906020019060200280838360005b83811015615aac578181015183820152602001615a94565b505050509050019650505050505050600060405180830381600087803b158015615ad557600080fd5b505af11580156148b4573d6000803e3d6000fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612bdc575050151592915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615b6357805160ff1916838001178555615b90565b82800160010185558215615b90579182015b82811115615b90578251825591602001919060010190615b75565b50615b9c929150615c57565b5090565b828054828255906000526020600020908101928215615bf3579160200282015b82811115615bf35781546001600160a01b0319166001600160a01b03843516178255602090920191600190910190615bc0565b50615b9c929150615c71565b50805460008255906000526020600020908101906110b89190615c57565b828054828255906000526020600020908101928215615b905791602002820182811115615b90578251825591602001919060010190615b75565b61100e91905b80821115615b9c5760008155600101615c5d565b61100e91905b80821115615b9c5780546001600160a01b0319168155600101615c7756fe45524332303a207472616e7366657220746f20746865207a65726f20616464726573735265656e7472616e637947756172643a207265656e7472616e742063616c6c0045524332303a206275726e20616d6f756e7420657863656564732062616c616e6365506175736572526f6c653a2063616c6c657220646f6573206e6f742068617665207468652050617573657220726f6c654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63654f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65728be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0526f6c65733a206163636f756e7420697320746865207a65726f2061646472657373436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef45524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa265627a7a723158208bea1446d21a8c77fad068b81428165d4e5808d7e33b1c7a803c360c6f64361e64736f6c63430005100032
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103595760003560e01c806301d22ccd1461035e57806306fdde0314610382578063095ea7b3146103ff5780630b56d1571461043f5780630df94ef21461045e57806312ea5c7e146104965780631624f6c6146104ee57806318160ddd1461061c578063194a62a8146106245780631f80b18a146106415780631fc29c011461064957806323b872dd1461065157806323d39ab5146106875780632b1b4bb01461068f5780632befabbf146106b55780632fdc91ee146106e9578063313ce567146106f157806336a000821461070f578063395093511461072c5780633f4ba83a14610758578063412753581461076057806345c8026c1461076857806346fbf68e1461078e5780634847cdc8146107b45780634c69c00f146107bc5780634cb71222146107e257806350b28af7146108085780635478786c1461082e57806354924507146108365780635c975abb1461083e5780635cffe9de146108465780635f09d84c146108d4578063613255ab146108fa5780636287fe211461092057806365ed6e231461094657806369fe0e2d1461094e5780636c11ec961461096b5780636cfd1553146109915780636ef8d66d146109b757806370a08231146109bf578063715018a6146109e5578063746daa4e146109ed5780637d7c2a1c14610a0a5780637dc0d1d014610a125780637ff9b59614610a1a5780638129fc1c14610a2257806382dc1ec414610a2a5780638456cb5914610a505780638705fcd414610a585780638a279e8a14610a7e5780638b30b51614610aac5780638cba144414610ac95780638da5cb5b14610aef5780638f32d59b14610af757806395d89b4114610aff5780639602e9f814610b07578063a457c2d714610b0f578063a6ea311c14610b3b578063a9059cbb14610b43578063aaa48e9f14610b6f578063afdd3fc314610b95578063b13bd49114610bb2578063b349b97314610c53578063b616b63d14610c5b578063b71501bc14610cd0578063c498c51514610cd8578063c4d66de814610d46578063cb390f9714610d6c578063d9d98ce414610d74578063dd62ed3e14610da0578063ddca3f4314610dce578063f16c88db14610dd6578063f2d50ba614610f34578063f2fde38b14610f3c578063fc0c546a14610f62575b600080fd5b610366610f6a565b604080516001600160a01b039092168252519081900360200190f35b61038a610f7a565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103c45781810151838201526020016103ac565b50505050905090810190601f1680156103f15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61042b6004803603604081101561041557600080fd5b506001600160a01b038135169060200135611011565b604080519115158252519081900360200190f35b61045c6004803603602081101561045557600080fd5b503561102f565b005b6104846004803603602081101561047457600080fd5b50356001600160a01b03166110bb565b60408051918252519081900360200190f35b61049e6110ce565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156104da5781810151838201526020016104c2565b505050509050019250505060405180910390f35b61045c6004803603606081101561050457600080fd5b810190602081018135600160201b81111561051e57600080fd5b82018360208201111561053057600080fd5b803590602001918460018302840111600160201b8311171561055157600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b8111156105a357600080fd5b8201836020820111156105b557600080fd5b803590602001918460018302840111600160201b831117156105d657600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903560ff1691506111309050565b61048461120c565b61045c6004803603602081101561063a57600080fd5b5035611212565b6104846113a8565b610366611440565b61042b6004803603606081101561066757600080fd5b506001600160a01b03813581169160208101359091169060400135611458565b6103666114e0565b610366600480360360208110156106a557600080fd5b50356001600160a01b03166114f0565b610484600480360360608110156106cb57600080fd5b508035906020810135151590604001356001600160a01b0316611512565b6103666116b5565b6106f96116c5565b6040805160ff9092168252519081900360200190f35b6103666004803603602081101561072557600080fd5b50356116ce565b61042b6004803603604081101561074257600080fd5b506001600160a01b0381351690602001356116f6565b61045c61174a565b610366611835565b6103666004803603602081101561077e57600080fd5b50356001600160a01b0316611845565b61042b600480360360208110156107a457600080fd5b50356001600160a01b0316611861565b610484611875565b61045c600480360360208110156107d257600080fd5b50356001600160a01b031661187c565b61045c600480360360208110156107f857600080fd5b50356001600160a01b0316611917565b61049e6004803603602081101561081e57600080fd5b50356001600160a01b03166119b2565b610366611aa2565b610484611aba565b61042b611ac1565b61042b6004803603608081101561085c57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561089657600080fd5b8201836020820111156108a857600080fd5b803590602001918460018302840111600160201b831117156108c957600080fd5b509092509050611acb565b61045c600480360360208110156108ea57600080fd5b50356001600160a01b0316612091565b6104846004803603602081101561091057600080fd5b50356001600160a01b031661212c565b6104846004803603602081101561093657600080fd5b50356001600160a01b031661216c565b61049e61217f565b61045c6004803603602081101561096457600080fd5b50356121d7565b61045c6004803603602081101561098157600080fd5b50356001600160a01b031661225f565b61045c600480360360208110156109a757600080fd5b50356001600160a01b03166122fa565b61045c612395565b610484600480360360208110156109d557600080fd5b50356001600160a01b03166123a7565b61045c6123c2565b61036660048036036020811015610a0357600080fd5b5035612441565b61042b61244f565b61036661245e565b61048461246e565b61045c612478565b61045c60048036036020811015610a4057600080fd5b50356001600160a01b031661251e565b61045c61256d565b61045c60048036036020811015610a6e57600080fd5b50356001600160a01b0316612636565b61048460048036036040811015610a9457600080fd5b506001600160a01b03813581169160200135166126d1565b61048460048036036020811015610ac257600080fd5b50356126ef565b61048460048036036020811015610adf57600080fd5b50356001600160a01b031661272b565b6103666127b7565b61042b6127c6565b61038a6127ec565b61036661284d565b61042b60048036036040811015610b2557600080fd5b506001600160a01b038135169060200135612865565b61049e6128d3565b61042b60048036036040811015610b5957600080fd5b506001600160a01b038135169060200135612934565b61048460048036036020811015610b8557600080fd5b50356001600160a01b031661296a565b61048460048036036020811015610bab57600080fd5b503561297d565b610bba61299c565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015610bfe578181015183820152602001610be6565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015610c3d578181015183820152602001610c25565b5050505090500194505050505060405180910390f35b61045c612b42565b61048460048036036040811015610c7157600080fd5b81359190810190604081016020820135600160201b811115610c9257600080fd5b820183602082011115610ca457600080fd5b803590602001918460208302840111600160201b83111715610cc557600080fd5b509092509050612b9d565b610366612be4565b61045c60048036036020811015610cee57600080fd5b810190602081018135600160201b811115610d0857600080fd5b820183602082011115610d1a57600080fd5b803590602001918460208302840111600160201b83111715610d3b57600080fd5b509092509050612bfc565b61045c60048036036020811015610d5c57600080fd5b50356001600160a01b0316612c9f565b61042b612d55565b61048460048036036040811015610d8a57600080fd5b506001600160a01b038135169060200135612d5f565b61048460048036036040811015610db657600080fd5b506001600160a01b0381358116916020013516612dc6565b610484612df1565b61045c60048036036080811015610dec57600080fd5b810190602081018135600160201b811115610e0657600080fd5b820183602082011115610e1857600080fd5b803590602001918460208302840111600160201b83111715610e3957600080fd5b919390929091602081019035600160201b811115610e5657600080fd5b820183602082011115610e6857600080fd5b803590602001918460208302840111600160201b83111715610e8957600080fd5b919390929091602081019035600160201b811115610ea657600080fd5b820183602082011115610eb857600080fd5b803590602001918460208302840111600160201b83111715610ed957600080fd5b919390929091602081019035600160201b811115610ef657600080fd5b820183602082011115610f0857600080fd5b803590602001918460208302840111600160201b83111715610f2957600080fd5b509092509050612df8565b610484613048565b61045c60048036036020811015610f5257600080fd5b50356001600160a01b031661304f565b61036661309f565b61016d546001600160a01b031681565b60688054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156110065780601f10610fdb57610100808354040283529160200191611006565b820191906000526020600020905b815481529060010190602001808311610fe957829003601f168201915b505050505090505b90565b600061102561101e6130af565b84846130b3565b5060015b92915050565b6110376127c6565b611076576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b620186a08161017181905511156110b8576040805162461bcd60e51b81526020600482015260016024820152603560f81b604482015290519081900360640190fd5b50565b6101766020526000908152604090205481565b606061017380548060200260200160405190810160405280929190818152602001828054801561100657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611109575050505050905090565b600054610100900460ff1680611149575061114961319f565b80611157575060005460ff16155b6111925760405162461bcd60e51b815260040180806020018281038252602e815260200180615e65602e913960400191505060405180910390fd5b600054610100900460ff161580156111bd576000805460ff1961ff0019909116610100171660011790555b83516111d0906068906020870190615b22565b5082516111e4906069906020860190615b22565b50606a805460ff191660ff84161790558015611206576000805461ff00191690555b50505050565b60355490565b609d8054600101908190556101365460ff1661126c576040805162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015290519081900360640190fd5b6112746131a5565b61127d33613224565b60005b6101735481101561131157611309610173828154811061129c57fe5b6000918252602090912001546001600160a01b0316336113046112bd61120c565b6112f86112eb61017388815481106112d157fe5b6000918252602090912001546001600160a01b031661325e565b899063ffffffff61336b16565b9063ffffffff6133c416565b613403565b600101611280565b5061016a54611356906001600160a01b03163361130461132f61120c565b61016a546112f890611349906001600160a01b031661325e565b889063ffffffff61336b16565b6113603383613422565b609d5481146113a4576040805162461bcd60e51b815260206004820152601f6024820152600080516020615cb9833981519152604482015290519081900360640190fd5b5050565b6101825461016c546101835460408051635ad5aadf60e01b81523060048201526001600160a01b0393841660248201529183166044830152516000939290921691635ad5aadf91606480820192602092909190829003018186803b15801561140f57600080fd5b505afa158015611423573d6000803e3d6000fd5b505050506040513d602081101561143957600080fd5b5051905090565b734da27a545c0c5b758a6ba100e3a049001de870f581565b600061146584848461350c565b6114708484846136b7565b6114ae84336114a985604051806060016040528060288152602001615ddb6028913961149c8a33612dc6565b919063ffffffff61380316565b6130b3565b6001600160a01b038416600090815261017660205260409020546114d5908490849061389a565b5060015b9392505050565b610169546001600160a01b031681565b6001600160a01b03808216600090815261017e6020526040902054165b919050565b609d805460010190819055610136546000919060ff161561156d576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b604080513260601b60208083019190915243603480840191909152835180840390910181526054909201909252805191012061017c556115ac33613224565b60006115b661391a565b61016a549091506115d8906001600160a01b031633308963ffffffff613a4e16565b6115f4816112f888670de0b6b3a764000063ffffffff61336b16565b92506116003384613aa8565b61160a3384613b88565b61161533848361389a565b6001600160a01b0384161561166857604080518781526001600160a01b038616602082015281517f496d589d8b7eb829a8d7b30e24a326ac33991f5cea96429b69231a6b15b54b1d929181900390910190a15b50609d5481146116ad576040805162461bcd60e51b815260206004820152601f6024820152600080516020615cb9833981519152604482015290519081900360640190fd5b509392505050565b610182546001600160a01b031681565b606a5460ff1690565b61017381815481106116dc57fe5b6000918252602090912001546001600160a01b0316905081565b60006110256117036130af565b846114a985603460006117146130af565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff613c5816565b61175a6117556130af565b611861565b6117955760405162461bcd60e51b8152600401808060200182810382526030815260200180615cfb6030913960400191505060405180910390fd5b6101365460ff166117e4576040805162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015290519081900360640190fd5b610136805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6118186130af565b604080516001600160a01b039092168252519081900360200190a1565b61016e546001600160a01b031681565b610177602052600090815260409020546001600160a01b031681565b60006110296101038363ffffffff613cb016565b6101815481565b6118846127c6565b6118c3576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b61017d80546001600160a01b0319166001600160a01b0383169081179091556110b8576040805162461bcd60e51b81526020600482015260016024820152600360fc1b604482015290519081900360640190fd5b61191f6127c6565b61195e576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b61016c80546001600160a01b0319166001600160a01b0383169081179091556110b8576040805162461bcd60e51b81526020600482015260016024820152600360fc1b604482015290519081900360640190fd5b60606000806119c0846123a7565b6101745460408051828152602080840282010190915291925080156119ef578160200160208202803883390190505b50925060005b8351811015611a9a576101748181548110611a0c57fe5b60009182526020808320909101546001600160a01b0390811680845261017983526040808520928a1685529183528184205481855261017a909352922054919450611a7b91670de0b6b3a7640000916112f891611a6e9163ffffffff613d1716565b859063ffffffff61336b16565b848281518110611a8757fe5b60209081029190910101526001016119f5565b505050919050565b73875773784af8135ea0ef43b5a374aad105c5d39e81565b6101715481565b6101365460ff1690565b6101365460009060ff1615611b1a576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b609d80546001019081905561016a5487906001600160a01b03888116911614611b6e576040805162461bcd60e51b81526020600482015260016024820152603760f81b604482015290519081900360640190fd5b6001600160a01b03811615801590611b865750600086115b611bbb576040805162461bcd60e51b81526020600482015260016024820152600360fc1b604482015290519081900360640190fd5b61016a54600090611bd4906001600160a01b031661325e565b905080871115611dd4576000611bf0888363ffffffff613d1716565b905060008080808080808080805b61017354811015611dc8576101738181548110611c1757fe5b60009182526020808320909101546001600160a01b03908116808452610177835260409384902054845163015de72360e11b81529451919d50909116965086926302bbce46926004808301939192829003018186803b158015611c7957600080fd5b505afa158015611c8d573d6000803e3d6000fd5b505050506040513d6020811015611ca357600080fd5b505160408051637437535960e01b815290519196506001600160a01b03861691637437535991600480820192602092909190829003018186803b158015611ce957600080fd5b505afa158015611cfd573d6000803e3d6000fd5b505050506040513d6020811015611d1357600080fd5b50519650611d3c670de0b6b3a76400006112f887611d308d61325e565b9063ffffffff61336b16565b97508a88101591508a871015925081611d645786881115611d5d5786611d5f565b875b611d71565b82611d6f5786611d71565b8a5b9950611d9889611d93876112f88e670de0b6b3a764000063ffffffff61336b16565b613d59565b9550818015611da45750825b15611dae57611dc8565b611dbe8b8763ffffffff613d1716565b9a50600101611bfe565b50505050505050505050505b61016a548790611dec906001600160a01b031661325e565b1015611e23576040805162461bcd60e51b81526020600482015260016024820152603360f81b604482015290519081900360640190fd5b61016a54611e3b906001600160a01b03168389613403565b61016a54600090611e55906001600160a01b031689612d5f565b905060405180807f45524333313536466c617368426f72726f7765722e6f6e466c6173684c6f616e815250602001905060405180910390208a6001600160a01b03166323e30c8b3361016a60009054906101000a90046001600160a01b03168c868d8d6040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050975050505050505050602060405180830381600087803b158015611f5957600080fd5b505af1158015611f6d573d6000803e3d6000fd5b505050506040513d6020811015611f8357600080fd5b505114611fbb576040805162461bcd60e51b81526020600482015260016024820152600760fb1b604482015290519081900360640190fd5b611feb8330611fd08b8563ffffffff613c5816565b61016a546001600160a01b031692919063ffffffff613a4e16565b611ff3613dfa565b506040805189815260208101839052815133926001600160a01b038716927f0d7d75e01ab95780d3cd1c8ec0dd6c2ce19e3a20427eec8bf53283b6fb8e95f0929081900390910190a360019450505050609d548114612087576040805162461bcd60e51b815260206004820152601f6024820152600080516020615cb9833981519152604482015290519081900360640190fd5b5095945050505050565b6120996127c6565b6120d8576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b61018380546001600160a01b0319166001600160a01b0383169081179091556110b8576040805162461bcd60e51b81526020600482015260016024820152600360fc1b604482015290519081900360640190fd5b61016a546000906001600160a01b038381169116141561150d57612165670de0b6b3a76400006112f861215d61120c565b611d3061391a565b905061150d565b6101786020526000908152604090205481565b606061018080548060200260200160405190810160405280929190818152602001828054801561100657602002820191906000526020600020905b8154815260200190600101908083116121ba575050505050905090565b6121df6127c6565b61221e576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b6101728190556127108111156110b8576040805162461bcd60e51b81526020600482015260016024820152603560f81b604482015290519081900360640190fd5b6122676127c6565b6122a6576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b61018280546001600160a01b0319166001600160a01b0383169081179091556110b8576040805162461bcd60e51b81526020600482015260016024820152600360fc1b604482015290519081900360640190fd5b6123026127c6565b612341576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b61016d80546001600160a01b0319166001600160a01b0383169081179091556110b8576040805162461bcd60e51b81526020600482015260016024820152600360fc1b604482015290519081900360640190fd5b6123a56123a06130af565b614188565b565b6001600160a01b031660009081526033602052604090205490565b6123ca6127c6565b612409576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b60d0546040516000916001600160a01b031690600080516020615e23833981519152908390a360d080546001600160a01b0319169055565b61017481815481106116dc57fe5b6000612459613dfa565b905090565b61017d546001600160a01b031681565b600061245961391a565b600054610100900460ff1680612491575061249161319f565b8061249f575060005460ff16155b6124da5760405162461bcd60e51b815260040180806020018281038252602e815260200180615e65602e913960400191505060405180910390fd5b600054610100900460ff16158015612505576000805460ff1961ff0019909116610100171660011790555b6001609d5580156110b8576000805461ff001916905550565b6125296117556130af565b6125645760405162461bcd60e51b8152600401808060200182810382526030815260200180615cfb6030913960400191505060405180910390fd5b6110b8816141d1565b6125786117556130af565b6125b35760405162461bcd60e51b8152600401808060200182810382526030815260200180615cfb6030913960400191505060405180910390fd5b6101365460ff16156125ff576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b610136805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586118186130af565b61263e6127c6565b61267d576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b61016e80546001600160a01b0319166001600160a01b0383169081179091556110b8576040805162461bcd60e51b81526020600482015260016024820152600360fc1b604482015290519081900360640190fd5b61017960209081526000928352604080842090915290825290205481565b60006110298261017480549050604051908082528060200260200182016040528015612725578160200160208202803883390190505b5061421a565b6001600160a01b0381166000908152610176602052604081205461274d61391a565b9150801580159061275d57508082115b156127b1576127ae620186a06112f861278f61277f868663ffffffff613d1716565b610172549063ffffffff61336b16565b6127a286620186a063ffffffff61336b16565b9063ffffffff613d1716565b91505b50919050565b60d0546001600160a01b031690565b60d0546000906001600160a01b03166127dd6130af565b6001600160a01b031614905090565b60698054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156110065780601f10610fdb57610100808354040283529160200191611006565b73275da8e61ea8e02d51edd8d0dc5c0e62b4cdb0be81565b60006110256128726130af565b846114a985604051806060016040528060258152602001615f47602591396034600061289c6130af565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff61380316565b6060610174805480602002602001604051908101604052809291908181526020018280548015611006576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611109575050505050905090565b600061294133848461350c565b61294c3384846136b7565b3360009081526101766020526040902054611025908490849061389a565b61017a6020526000908152604090205481565b610175818154811061298b57fe5b600091825260209091200154905081565b6101825460408051634a4b15d160e01b8152306004820152905160609283926001600160a01b0390911691634a4b15d191602480820192600092909190829003018186803b1580156129ed57600080fd5b505afa158015612a01573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040908152811015612a2a57600080fd5b8101908080516040519392919084600160201b821115612a4957600080fd5b908301906020820185811115612a5e57600080fd5b82518660208202830111600160201b82111715612a7a57600080fd5b82525081516020918201928201910280838360005b83811015612aa7578181015183820152602001612a8f565b5050505090500160405260200180516040519392919084600160201b821115612acf57600080fd5b908301906020820185811115612ae457600080fd5b82518660208202830111600160201b82111715612b0057600080fd5b82525081516020918201928201910280838360005b83811015612b2d578181015183820152602001612b15565b50505050905001604052505050915091509091565b61017d546001600160a01b031673b5a8f07dd4c3d315869405d702ee8f6ea695e8c514612b6e57600080fd5b61017d80546001600160a01b03191673758c10272a15f0e9d50cbc035ff9a046945da0f2179055601461018155565b6000612bdc8484848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061421a92505050565b949350505050565b73c00e94cb662c3520282e6f5717214004a7f2688881565b61016d546001600160a01b0316331480612c2e5750612c196127b7565b6001600160a01b0316336001600160a01b0316145b612c63576040805162461bcd60e51b81526020600482015260016024820152601b60f91b604482015290519081900360640190fd5b6113a482828080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061432392505050565b600054610100900460ff1680612cb85750612cb861319f565b80612cc6575060005460ff16155b612d015760405162461bcd60e51b815260040180806020018281038252602e815260200180615e65602e913960400191505060405180910390fd5b600054610100900460ff16158015612d2c576000805460ff1961ff0019909116610100171660011790555b612d35826143ed565b610136805460ff1916905580156113a4576000805461ff00191690555050565b61017f5460ff1681565b61016a546000906001600160a01b03848116911614612da9576040805162461bcd60e51b81526020600482015260016024820152603760f81b604482015290519081900360640190fd5b6114d9620186a06112f8610181548561336b90919063ffffffff16565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6101725481565b612e006127c6565b612e3f576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b868514612e77576040805162461bcd60e51b81526020600482015260016024820152601960f91b604482015290519081900360640190fd5b86811015612eb0576040805162461bcd60e51b81526020600482015260016024820152603360f81b604482015290519081900360640190fd5b612ebd6101748585615ba0565b50600080805b8981101561302d578a8a82818110612ed757fe5b905060200201356001600160a01b0316915060006001600160a01b0316826001600160a01b031614158015612f3157506000898983818110612f1557fe5b905060200201356001600160a01b03166001600160a01b031614155b612f66576040805162461bcd60e51b81526020600482015260016024820152600360fc1b604482015290519081900360640190fd5b888882818110612f7257fe5b6001600160a01b0385811660009081526101776020908152604090912080546001600160a01b031916939091029490940135161790915550848482818110612fb657fe5b905060200201356001600160a01b0316925073875773784af8135ea0ef43b5a374aad105c5d39e6001600160a01b0316836001600160a01b031614613025576001600160a01b03828116600090815261017e6020526040902080546001600160a01b0319169185169190911790555b600101612ec3565b5061303b6101738b8b615ba0565b5050505050505050505050565b61016f5481565b6130576127c6565b613096576040805162461bcd60e51b81526020600482018190526024820152600080516020615e03833981519152604482015290519081900360640190fd5b6110b8816144a5565b61016a546001600160a01b031681565b3390565b6001600160a01b0383166130f85760405162461bcd60e51b8152600401808060200182810382526024815260200180615ef96024913960400191505060405180910390fd5b6001600160a01b03821661313d5760405162461bcd60e51b8152600401808060200182810382526022815260200180615d516022913960400191505060405180910390fd5b6001600160a01b03808416600081815260346020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b303b1590565b61017c54324360405160200180836001600160a01b03166001600160a01b031660601b8152601401828152602001925050506040516020818303038152906040528051906020012014156123a5576040805162461bcd60e51b81526020600482015260016024820152603960f81b604482015290519081900360640190fd5b6110b88161017480549050604051908082528060200260200182016040528015613258578160200160208202803883390190505b50614534565b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b1781529151815160009384936060936001600160a01b03881693919290918291908083835b602083106132d85780518252601f1990920191602091820191016132b9565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613338576040519150601f19603f3d011682016040523d82523d6000602084013e61333d565b606091505b50915091508161334c57600080fd5b80806020019051602081101561336157600080fd5b5051949350505050565b60008261337a57506000611029565b8282028284828161338757fe5b04146114d95760405162461bcd60e51b8152600401808060200182810382526021815260200180615dba6021913960400191505060405180910390fd5b60006114d983836040518060400160405280601a815260200179536166654d6174683a206469766973696f6e206279207a65726f60301b8152506148bd565b61341d6001600160a01b038416838363ffffffff61492216565b505050565b6001600160a01b0382166134675760405162461bcd60e51b8152600401808060200182810382526021815260200180615eb36021913960400191505060405180910390fd5b6134aa81604051806060016040528060228152602001615cd9602291396001600160a01b038516600090815260336020526040902054919063ffffffff61380316565b6001600160a01b0383166000908152603360205260409020556035546134d6908263ffffffff613d1716565b6035556040805182815290516000916001600160a01b03851691600080516020615e938339815191529181900360200190a35050565b600080600080600061351d876123a7565b905060005b610174548110156136ac57610174818154811061353b57fe5b6000918252602090912001546001600160a01b031695508161358d576001600160a01b038681166000908152610179602090815260408083208d8516845290915280822054928b1682529020556136a4565b6001600160a01b03808716600090815261017a60209081526040808320546101798352818420948e168452939091529020549095506135d390869063ffffffff613d1716565b6001600160a01b03808816600090815261017960209081526040808320938d168352929052205490945061362090670de0b6b3a7640000906112f890611a6e90899063ffffffff613d1716565b925061367c61366f613638848a63ffffffff613c5816565b6112f861364b888c63ffffffff61336b16565b61366388670de0b6b3a764000063ffffffff61336b16565b9063ffffffff613c5816565b869063ffffffff613d1716565b6001600160a01b03808816600090815261017960209081526040808320938d16835292905220555b600101613522565b505050505050505050565b6001600160a01b0383166136fc5760405162461bcd60e51b8152600401808060200182810382526025815260200180615ed46025913960400191505060405180910390fd5b6001600160a01b0382166137415760405162461bcd60e51b8152600401808060200182810382526023815260200180615c966023913960400191505060405180910390fd5b61378481604051806060016040528060268152602001615d73602691396001600160a01b038616600090815260336020526040902054919063ffffffff61380316565b6001600160a01b0380851660009081526033602052604080822093909355908416815220546137b9908263ffffffff613c5816565b6001600160a01b038084166000818152603360209081526040918290209490945580518581529051919392871692600080516020615e9383398151915292918290030190a3505050565b600081848411156138925760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561385757818101518382015260200161383f565b50505050905090810190601f1680156138845780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60006138a5846123a7565b90506138f7816112f86138be858763ffffffff61336b16565b6136636138d1868963ffffffff613d1716565b6001600160a01b038a16600090815261017660205260409020549063ffffffff61336b16565b6001600160a01b0390941660009081526101766020526040902093909355505050565b60008061392561120c565b90508061393a57505061017054600a0a61100e565b61016a54600090819061396390670de0b6b3a764000090611d30906001600160a01b031661325e565b905060606101738054806020026020016040519081016040528092919081815260200182805480156139be57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116139a0575b50939450600093505050505b8151811015613a34578181815181106139df57fe5b60200260200101519350613a2a613a1d6139f88661325e565b6001600160a01b0380881660009081526101776020526040902054611d309116614974565b849063ffffffff613c5816565b92506001016139ca565b50613a45828563ffffffff6133c416565b94505050505090565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526112069085906149e1565b6001600160a01b038216613b03576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b603554613b16908263ffffffff613c5816565b6035556001600160a01b038216600090815260336020526040902054613b42908263ffffffff613c5816565b6001600160a01b0383166000818152603360209081526040808320949094558351858152935192939192600080516020615e938339815191529281900390910190a35050565b600080613b94846123a7565b90506000805b61017454811015613c50576101748181548110613bb357fe5b60009182526020808320909101546001600160a01b0390811680845261017983526040808520928b1685529183528184205481855261017a9093529220549195509250613c2190613c149085906112f8906112eb908763ffffffff613d1716565b839063ffffffff613c5816565b6001600160a01b03808616600090815261017960209081526040808320938b1683529290522055600101613b9a565b505050505050565b6000828201838110156114d9576040805162461bcd60e51b815260206004820152601b60248201527a536166654d6174683a206164646974696f6e206f766572666c6f7760281b604482015290519081900360640190fd5b60006001600160a01b038216613cf75760405162461bcd60e51b8152600401808060200182810382526022815260200180615e436022913960400191505060405180910390fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b60006114d983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613803565b60008115611029576001600160a01b038084166000908152610177602052604090205416613d88848285613403565b604080516395a2251f60e01b815230600482015290516001600160a01b038316916395a2251f9160248083019260209291908290030181600087803b158015613dd057600080fd5b505af1158015613de4573d6000803e3d6000fd5b505050506040513d602081101561336157600080fd5b6101365460009060ff1615613e49576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b6060610180805480602002602001604051908101604052809291908181526020018280548015613e9857602002820191906000526020600020905b815481526020019060010190808311613e84575b505050505090506060610175805480602002602001604051908101604052809291908181526020018280548015613eee57602002820191906000526020600020905b815481526020019060010190808311613eda575b50508351865194955093841492505081159050613f595760005b82811080613f14575081155b15613f5757848181518110613f2557fe5b6020026020010151848281518110613f3957fe5b602002602001015114613f4f5760009150613f57565b600101613f08565b505b61016a54600090613f72906001600160a01b031661325e565b9050818015613f7f575080155b15613f925760009550505050505061100e565b6000613faa620186a06112f861017154611d30614b99565b90508215613fe25780821115613fd357613fd386613fce848463ffffffff613d1716565b614c99565b6000965050505050505061100e565b60606000613fee614df3565b9092509050614003818563ffffffff613c5816565b9050606060008061402c856140278d614022888b63ffffffff613d1716565b614f14565b614ff7565b9250925092508061405a576140446101756000615bff565b8a51614058906101759060208e0190615c1d565b505b61016a54600090614073906001600160a01b031661325e565b90508681111580614082575082155b1561409c5760009c5050505050505050505050505061100e565b606084516040519080825280602002602001820160405280156140c9578160200160208202803883390190505b50905060005b855181101561412457614105856112f8620186a08985815181106140ef57fe5b602002602001015161336b90919063ffffffff16565b82828151811061411157fe5b60209081029190910101526001016140cf565b5061413981613fce848b63ffffffff613d1716565b604080513381526020810188905281517f4217d9fab39dbadacf1dad6c889aec1caa02e8a6cb59ddd4ce34f3e0ef158b55929181900390910190a160019d505050505050505050505050505090565b61419a6101038263ffffffff6152a516565b6040516001600160a01b038216907fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e90600090a250565b6141e36101038263ffffffff61530c16565b6040516001600160a01b038216907f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f890600090a250565b609d8054600101908190556000906142306131a5565b61423a3384614534565b83156142d857600061424a61391a565b9050600061426a670de0b6b3a76400006112f8888563ffffffff61336b16565b61016a54909150600090614286906001600160a01b031661325e565b9050808211156142a15761429a878261538d565b94506142a5565b8194505b6142b087868561547d565b94506142bc3388613422565b61016a546142d4906001600160a01b03163387613403565b5050505b609d54811461431c576040805162461bcd60e51b815260206004820152601f6024820152600080516020615cb9833981519152604482015290519081900360640190fd5b5092915050565b6101735481511461435f576040805162461bcd60e51b81526020600482015260016024820152601960f91b604482015290519081900360640190fd5b6000805b825181101561439c5761439283828151811061437b57fe5b602002602001015183613c5890919063ffffffff16565b9150600101614363565b5081516143b190610180906020850190615c1d565b50620186a081146113a4576040805162461bcd60e51b81526020600482015260016024820152603760f81b604482015290519081900360640190fd5b600054610100900460ff1680614406575061440661319f565b80614414575060005460ff16155b61444f5760405162461bcd60e51b815260040180806020018281038252602e815260200180615e65602e913960400191505060405180910390fd5b600054610100900460ff1615801561447a576000805460ff1961ff0019909116610100171660011790555b61448382611861565b61449057614490826141d1565b80156113a4576000805461ff00191690555050565b6001600160a01b0381166144ea5760405162461bcd60e51b8152600401808060200182810382526026815260200180615d2b6026913960400191505060405180910390fd5b60d0546040516001600160a01b03808416921690600080516020615e2383398151915290600090a360d080546001600160a01b0319166001600160a01b0392909216919091179055565b606061017480548060200260200160405190810160405280929190818152602001828054801561458d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161456f575b505050505090508051600014156145a457506113a4565b60006145ae61120c565b905060006145bb856123a7565b905060008215613c505760005b84518110156148b4578481815181106145dd57fe5b602002602001015191506145f08261550b565b60006145fb8361325e565b90508015614696576001600160a01b0383166000908152610178602052604090205461466c906146469087906112f890670de0b6b3a764000090611d3090879063ffffffff613d1716565b6001600160a01b038516600090815261017a60205260409020549063ffffffff613c5816565b6001600160a01b038416600090815261017a60209081526040808320939093556101789052208190555b8315614879576001600160a01b03808416600081815261017960209081526040808320948d1683529381528382205492825261017a9052918220549091906146e4908363ffffffff613d1716565b9050801561487657600061470a670de0b6b3a76400006112f8898563ffffffff61336b16565b905060006147178761325e565b905080821115614725578091505b8a868151811061473157fe5b6020026020010151156147b15761479261476c6147548b8b63ffffffff613d1716565b6112f885670de0b6b3a764000063ffffffff61336b16565b6001600160a01b038916600090815261017a60205260409020549063ffffffff613c5816565b6001600160a01b038816600090815261017a6020526040902055614873565b61016e546000906001600160a01b0316158015906147d25750600061017254115b80156147fb57506001600160a01b03881673875773784af8135ea0ef43b5a374aad105c5d39e14155b156148395761481d620186a06112f8610172548661336b90919063ffffffff16565b61016e549091506148399089906001600160a01b031683613403565b61484e888e611304868563ffffffff613d1716565b6148578861325e565b6001600160a01b03891660009081526101786020526040902055505b50505b50505b506001600160a01b03808316600090815261017a60209081526040808320546101798352818420948c168452939091529020556001016145c8565b50505050505050565b6000818361490c5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561385757818101518382015260200161383f565b50600083858161491857fe5b0495945050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261341d9084906149e1565b6000816001600160a01b03166302bbce466040518163ffffffff1660e01b815260040160206040518083038186803b1580156149af57600080fd5b505afa1580156149c3573d6000803e3d6000fd5b505050506040513d60208110156149d957600080fd5b505192915050565b6149f3826001600160a01b0316615ae9565b614a44576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310614a825780518252601f199092019160209182019101614a63565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114614ae4576040519150601f19603f3d011682016040523d82523d6000602084013e614ae9565b606091505b509150915081614b40576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b80511561120657808060200190516020811015614b5c57600080fd5b50516112065760405162461bcd60e51b815260040180806020018281038252602a815260200180615f1d602a913960400191505060405180910390fd5b6000806060610173805480602002602001604051908101604052809291908181526020018280548015614bf557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311614bd7575b50939450600093505050505b8151811015614c7757818181518110614c1657fe5b60200260200101519250614c6d614c60670de0b6b3a76400006112f8614c3b8761325e565b6001600160a01b0380891660009081526101776020526040902054611d309116614974565b859063ffffffff613c5816565b9350600101614c01565b5061016a54614c9290613a1d906001600160a01b031661325e565b9250505090565b6060614ca58383614f14565b90506000806060610173805480602002602001604051908101604052809291908181526020018280548015614d0357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311614ce5575b50939450600093505050505b84518110156148b457848181518110614d2457fe5b6020026020010151935083600014614deb576101776000838381518110614d4757fe5b6020908102919091018101516001600160a01b039081168352908201929092526040016000205461016a549082169450614d8391168486613403565b826001600160a01b0316631249c58b6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614dbe57600080fd5b505af1158015614dd2573d6000803e3d6000fd5b505050506040513d6020811015614de857600080fd5b50505b600101614d0f565b60606000806060610173805480602002602001604051908101604052809291908181526020018280548015614e5157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311614e33575b5050505050905060008151905080604051908082528060200260200182016040528015614e88578160200160208202803883390190505b50945060005b81811015614f0c57828181518110614ea257fe5b60200260200101519350614ec4670de0b6b3a76400006112f8614c3b8761325e565b868281518110614ed057fe5b602002602001018181525050614f02868281518110614eeb57fe5b602002602001015186613c5890919063ffffffff16565b9450600101614e8e565b505050509091565b60608251604051908082528060200260200182016040528015614f41578160200160208202803883390190505b509050600080805b8551811015614fee576001865103811415614f8b57614f6e858363ffffffff613d1716565b848281518110614f7a57fe5b602002602001018181525050614fe6565b614fb8620186a06112f8888481518110614fa157fe5b60200260200101518861336b90919063ffffffff16565b9250614fca828463ffffffff613c5816565b915082848281518110614fd957fe5b6020026020010181815250505b600101614f49565b50505092915050565b60606000808451604051908082528060200260200182016040528015615027578160200160208202803883390190505b509250600080600080606061017380548060200260200160405190810160405280929190818152602001828054801561508957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161506b575b50939450600093505050505b8a51811015615298578181815181106150aa57fe5b602002602001015192508981815181106150c057fe5b602002602001015193508a81815181106150d657fe5b6020908102919091018101516001600160a01b038086166000908152610177909352604090922054909116965094508385111561523f57600061511f868663ffffffff613d1716565b90506000876001600160a01b031663743753596040518163ffffffff1660e01b815260040160206040518083038186803b15801561515c57600080fd5b505afa158015615170573d6000803e3d6000fd5b505050506040513d602081101561518657600080fd5b50519050818110156151b357600198506151b0620186a06112f883620182b863ffffffff61336b16565b91505b61523785611d938a6001600160a01b03166302bbce466040518163ffffffff1660e01b815260040160206040518083038186803b1580156151f357600080fd5b505afa158015615207573d6000803e3d6000fd5b505050506040513d602081101561521d57600080fd5b50516112f886670de0b6b3a764000063ffffffff61336b16565b505050615290565b61524f848663ffffffff613d1716565b89828151811061525b57fe5b60200260200101818152505061528d89828151811061527657fe5b602002602001015189613c5890919063ffffffff16565b97505b600101615095565b5050505050509250925092565b6152af8282613cb0565b6152ea5760405162461bcd60e51b8152600401808060200182810382526021815260200180615d996021913960400191505060405180910390fd5b6001600160a01b0316600090815260209190915260409020805460ff19169055565b6153168282613cb0565b15615368576040805162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b600080600061539a61120c565b905060606101738054806020026020016040519081016040528092919081815260200182805480156153f557602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116153d7575b50939450600093505050505b815181101561545b5781818151811061541657fe5b6020026020010151935061545161544485611d93866112f86154378a61325e565b8d9063ffffffff61336b16565b869063ffffffff613c5816565b9450600101615401565b50615473614c60836112f8898963ffffffff61336b16565b9695505050505050565b33600090815261017660205260408120548083101561549f57839150506114d9565b60006154d969152d02c7e14af68000006112f861017254611d306154cc878a613d1790919063ffffffff16565b8b9063ffffffff61336b16565b61016a5461016e549192506154fb916001600160a01b03918216911683613403565b615473858263ffffffff613d1716565b6001600160a01b03811673c00e94cb662c3520282e6f5717214004a7f26888148061555257506001600160a01b03811673875773784af8135ea0ef43b5a374aad105c5d39e145b8061557957506001600160a01b038116734da27a545c0c5b758a6ba100e3a049001de870f5145b156110b8576040805160018082528183019092526060916020808301908038833901905050905030816000815181106155ae57fe5b6001600160a01b039283166020918202929092010152821673875773784af8135ea0ef43b5a374aad105c5d39e14156156d45760408051637e122ea560e11b81526004810191825282516044820152825173275da8e61ea8e02d51edd8d0dc5c0e62b4cdb0be9263fc245d4a92859283929182916024820191606401906020808701910280838360005b83811015615650578181015183820152602001615638565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561568f578181015183820152602001615677565b50505050905001945050505050600060405180830381600087803b1580156156b657600080fd5b505af11580156156ca573d6000803e3d6000fd5b50505050506110b8565b604080516001808252818301909252606091602080830190803883390190505090506001600160a01b038316734da27a545c0c5b758a6ba100e3a049001de870f514801561572d5750610183546001600160a01b031615155b15615929576101835481516001600160a01b0390911690829060009061574f57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060008160008151811061577e57fe5b60200260200101516001600160a01b03166375d264136040518163ffffffff1660e01b815260040160206040518083038186803b1580156157be57600080fd5b505afa1580156157d2573d6000803e3d6000fd5b505050506040513d60208110156157e857600080fd5b505160408051630cc7d40f60e11b815230600482015290519192506001600160a01b03831691633111e7b3918591849163198fa81e916024808301926020929190829003018186803b15801561583d57600080fd5b505afa158015615851573d6000803e3d6000fd5b505050506040513d602081101561586757600080fd5b50516040516001600160e01b031960e085901b168152602481018290523060448201819052606060048301908152845160648401528451919290918291608401906020878101910280838360005b838110156158cd5781810151838201526020016158b5565b50505050905001945050505050602060405180830381600087803b1580156158f457600080fd5b505af1158015615908573d6000803e3d6000fd5b505050506040513d602081101561591e57600080fd5b506110b89350505050565b61016c546001600160a01b03161561341d5761016c5481516001600160a01b0390911690829060009061595857fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508060008151811061598557fe5b60200260200101516001600160a01b0316635fe3b5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156159c557600080fd5b505afa1580156159d9573d6000803e3d6000fd5b505050506040513d60208110156159ef57600080fd5b50516040516334086fd360e11b81526000604482018190526001606483018190526080600484019081528651608485015286516001600160a01b0390951694636810dfa694889488949093909290918291602482019160a40190602089810191028083838a5b83811015615a6d578181015183820152602001615a55565b50505050905001838103825286818151815260200191508051906020019060200280838360005b83811015615aac578181015183820152602001615a94565b505050509050019650505050505050600060405180830381600087803b158015615ad557600080fd5b505af11580156148b4573d6000803e3d6000fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612bdc575050151592915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615b6357805160ff1916838001178555615b90565b82800160010185558215615b90579182015b82811115615b90578251825591602001919060010190615b75565b50615b9c929150615c57565b5090565b828054828255906000526020600020908101928215615bf3579160200282015b82811115615bf35781546001600160a01b0319166001600160a01b03843516178255602090920191600190910190615bc0565b50615b9c929150615c71565b50805460008255906000526020600020908101906110b89190615c57565b828054828255906000526020600020908101928215615b905791602002820182811115615b90578251825591602001919060010190615b75565b61100e91905b80821115615b9c5760008155600101615c5d565b61100e91905b80821115615b9c5780546001600160a01b0319168155600101615c7756fe45524332303a207472616e7366657220746f20746865207a65726f20616464726573735265656e7472616e637947756172643a207265656e7472616e742063616c6c0045524332303a206275726e20616d6f756e7420657863656564732062616c616e6365506175736572526f6c653a2063616c6c657220646f6573206e6f742068617665207468652050617573657220726f6c654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63654f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65728be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0526f6c65733a206163636f756e7420697320746865207a65726f2061646472657373436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef45524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa265627a7a723158208bea1446d21a8c77fad068b81428165d4e5808d7e33b1c7a803c360c6f64361e64736f6c63430005100032
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 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.