Overview
S Balance
0 S
S Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 3 internal transactions
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
6178870 | 28 hrs ago | Contract Creation | 0 S | |||
5182768 | 10 days ago | Contract Creation | 0 S | |||
2336132 | 30 days ago | Contract Creation | 0 S |
Loading...
Loading
Contract Name:
GaugeFactory
Compiler Version
v0.8.22+commit.4fc1097e
Optimization Enabled:
Yes with 10000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; import {Gauge} from "./Gauge.sol"; contract GaugeFactory { address public last_gauge; // @param _stake address of the LP tokens // @param _bribe address of the bribe contract linked to the Gauge // @param _ve address of the VotingEscrow contract // @return the gauge address function createGauge(address _stake, address _bribe, address _ve) external returns (address) { last_gauge = address(new Gauge(_stake, _bribe, _ve, msg.sender)); return last_gauge; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IVotingEscrow} from "./interfaces/IVotingEscrow.sol"; import {IPair} from "./interfaces/IPair.sol"; import {IBribe} from "./interfaces/IBribe.sol"; import {IVoter} from "./interfaces/IVoter.sol"; // Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens contract Gauge { address public immutable stake; // the LP token that needs to be staked for rewards address public immutable _ve; // the ve token used for gauges address public immutable bribe; address public immutable voter; uint public derivedSupply; mapping(address => uint) public derivedBalances; uint internal constant DURATION = 7 days; // rewards are released over 7 days uint internal constant PRECISION = 10 ** 18; uint internal constant MAX_REWARD_TOKENS = 16; // default snx staking contract implementation mapping(address => uint) public rewardRate; mapping(address => uint) public periodFinish; mapping(address => uint) public lastUpdateTime; mapping(address => uint) public rewardPerTokenStored; mapping(address => mapping(address => uint)) public lastEarn; mapping(address => mapping(address => uint)) public userRewardPerTokenStored; mapping(address => uint) public tokenIds; uint public totalSupply; mapping(address => uint) public balanceOf; address[] public rewards; mapping(address => bool) public isReward; /// @notice A checkpoint for marking balance struct Checkpoint { uint timestamp; uint balanceOf; } /// @notice A checkpoint for marking reward rate struct RewardPerTokenCheckpoint { uint timestamp; uint rewardPerToken; } /// @notice A checkpoint for marking supply struct SupplyCheckpoint { uint timestamp; uint supply; } /// @notice A record of balance checkpoints for each account, by index mapping (address => mapping (uint => Checkpoint)) public checkpoints; /// @notice The number of checkpoints for each account mapping (address => uint) public numCheckpoints; /// @notice A record of balance checkpoints for each token, by index mapping (uint => SupplyCheckpoint) public supplyCheckpoints; /// @notice The number of checkpoints uint public supplyNumCheckpoints; /// @notice A record of balance checkpoints for each token, by index mapping (address => mapping (uint => RewardPerTokenCheckpoint)) public rewardPerTokenCheckpoints; /// @notice The number of checkpoints for each token mapping (address => uint) public rewardPerTokenNumCheckpoints; uint public fees0; uint public fees1; event Deposit(address indexed from, uint tokenId, uint amount); event Withdraw(address indexed from, uint tokenId, uint amount); event NotifyReward(address indexed from, address indexed reward, uint amount); event ClaimFees(address indexed from, uint claimed0, uint claimed1); event ClaimRewards(address indexed from, address indexed reward, uint amount); constructor(address _stake, address _bribe, address __ve, address _voter) { require( _stake != address(0) && _bribe != address(0) && __ve != address(0) && _voter != address(0), "Gauge: zero address provided in constructor" ); stake = _stake; bribe = _bribe; _ve = __ve; voter = _voter; } // simple re-entrancy check uint internal _unlocked = 1; modifier lock() { require(_unlocked == 1); _unlocked = 2; _; _unlocked = 1; } /** * @notice Claim fees on its associated pair and send them to its associated bribe */ function claimFees() external lock returns (uint claimed0, uint claimed1) { return _claimFees(); } function _claimFees() internal returns (uint claimed0, uint claimed1) { (claimed0, claimed1) = IPair(stake).claimFees(); if (claimed0 > 0 || claimed1 > 0) { uint _fees0 = fees0 + claimed0; uint _fees1 = fees1 + claimed1; (address _token0, address _token1) = IPair(stake).tokens(); if (_fees0 > IBribe(bribe).left(_token0) && _fees0 / DURATION > 0) { fees0 = 0; _safeApprove(_token0, bribe, _fees0); IBribe(bribe).notifyRewardAmount(_token0, _fees0); } else { fees0 = _fees0; } if (_fees1 > IBribe(bribe).left(_token1) && _fees1 / DURATION > 0) { fees1 = 0; _safeApprove(_token1, bribe, _fees1); IBribe(bribe).notifyRewardAmount(_token1, _fees1); } else { fees1 = _fees1; } emit ClaimFees(msg.sender, claimed0, claimed1); } } /** * @notice Determine the prior balance for an account as of a block number * @dev Block number must be a finalized block or else this function will revert to prevent misinformation. * @param account The address of the account to check * @param timestamp The timestamp to get the balance at * @return The balance the account had as of the given block */ function getPriorBalanceIndex(address account, uint timestamp) public view returns (uint) { uint nCheckpoints = numCheckpoints[account]; if (nCheckpoints == 0) { return 0; } // First check most recent balance if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) { return (nCheckpoints - 1); } // Next check implicit zero balance if (checkpoints[account][0].timestamp > timestamp) { return 0; } uint lower = 0; uint upper = nCheckpoints - 1; while (upper > lower) { uint center = upper - (upper - lower) / 2; // ceil, avoiding overflow Checkpoint memory cp = checkpoints[account][center]; if (cp.timestamp == timestamp) { return center; } else if (cp.timestamp < timestamp) { lower = center; } else { upper = center - 1; } } return lower; } function getPriorSupplyIndex(uint timestamp) public view returns (uint) { uint nCheckpoints = supplyNumCheckpoints; if (nCheckpoints == 0) { return 0; } // First check most recent balance if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) { return (nCheckpoints - 1); } // Next check implicit zero balance if (supplyCheckpoints[0].timestamp > timestamp) { return 0; } uint lower = 0; uint upper = nCheckpoints - 1; while (upper > lower) { uint center = upper - (upper - lower) / 2; // ceil, avoiding overflow SupplyCheckpoint memory cp = supplyCheckpoints[center]; if (cp.timestamp == timestamp) { return center; } else if (cp.timestamp < timestamp) { lower = center; } else { upper = center - 1; } } return lower; } function getPriorRewardPerToken(address token, uint timestamp) public view returns (uint, uint) { uint nCheckpoints = rewardPerTokenNumCheckpoints[token]; if (nCheckpoints == 0) { return (0,0); } // First check most recent balance if (rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <= timestamp) { return (rewardPerTokenCheckpoints[token][nCheckpoints - 1].rewardPerToken, rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp); } // Next check implicit zero balance if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) { return (0,0); } uint lower = 0; uint upper = nCheckpoints - 1; while (upper > lower) { uint center = upper - (upper - lower) / 2; // ceil, avoiding overflow RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[token][center]; if (cp.timestamp == timestamp) { return (cp.rewardPerToken, cp.timestamp); } else if (cp.timestamp < timestamp) { lower = center; } else { upper = center - 1; } } return (rewardPerTokenCheckpoints[token][lower].rewardPerToken, rewardPerTokenCheckpoints[token][lower].timestamp); } function _writeCheckpoint(address account, uint balance) internal { uint _timestamp = block.timestamp; uint _nCheckPoints = numCheckpoints[account]; if (_nCheckPoints > 0 && checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp) { checkpoints[account][_nCheckPoints - 1].balanceOf = balance; } else { checkpoints[account][_nCheckPoints] = Checkpoint(_timestamp, balance); numCheckpoints[account] = _nCheckPoints + 1; } } function _writeRewardPerTokenCheckpoint(address token, uint reward, uint timestamp) internal { uint _nCheckPoints = rewardPerTokenNumCheckpoints[token]; if (_nCheckPoints > 0 && rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp == timestamp) { rewardPerTokenCheckpoints[token][_nCheckPoints - 1].rewardPerToken = reward; } else { rewardPerTokenCheckpoints[token][_nCheckPoints] = RewardPerTokenCheckpoint(timestamp, reward); rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1; } } function _writeSupplyCheckpoint() internal { uint _nCheckPoints = supplyNumCheckpoints; uint _timestamp = block.timestamp; if (_nCheckPoints > 0 && supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp) { supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply; } else { supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(_timestamp, derivedSupply); supplyNumCheckpoints = _nCheckPoints + 1; } } function rewardsListLength() external view returns (uint) { return rewards.length; } /** * @dev Returns the last time the reward was modified or periodFinish if the reward has ended. */ function lastTimeRewardApplicable(address token) public view returns (uint) { return Math.min(block.timestamp, periodFinish[token]); } /** * @dev Claim earned rewards for a depositor. * @param account The address of the account to claim for. * @param tokens A list of the tokens to claim. */ function getReward(address account, address[] memory tokens) external lock { require(msg.sender == account || msg.sender == voter); _unlocked = 1; IVoter(voter).distribute(address(this)); _unlocked = 2; for (uint i = 0; i < tokens.length; i++) { (rewardPerTokenStored[tokens[i]], lastUpdateTime[tokens[i]]) = _updateRewardPerToken(tokens[i], type(uint).max, true); uint _reward = earned(tokens[i], account); lastEarn[tokens[i]][account] = block.timestamp; userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[tokens[i]]; if (_reward > 0) _safeTransfer(tokens[i], account, _reward); emit ClaimRewards(account, tokens[i], _reward); } uint _derivedBalance = derivedBalances[account]; derivedSupply -= _derivedBalance; _derivedBalance = derivedBalance(account); derivedBalances[account] = _derivedBalance; derivedSupply += _derivedBalance; _writeCheckpoint(account, derivedBalances[account]); _writeSupplyCheckpoint(); } function rewardPerToken(address token) public view returns (uint) { if (derivedSupply == 0) { return rewardPerTokenStored[token]; } return rewardPerTokenStored[token] + ((lastTimeRewardApplicable(token) - Math.min(lastUpdateTime[token], periodFinish[token])) * rewardRate[token] * PRECISION / derivedSupply); } function derivedBalance(address account) public view returns (uint) { return balanceOf[account]; } function batchRewardPerToken(address token, uint maxRuns) external { (rewardPerTokenStored[token], lastUpdateTime[token]) = _batchRewardPerToken(token, maxRuns); } function _batchRewardPerToken(address token, uint maxRuns) internal returns (uint, uint) { uint _startTimestamp = lastUpdateTime[token]; uint reward = rewardPerTokenStored[token]; if (supplyNumCheckpoints == 0) { return (reward, _startTimestamp); } if (rewardRate[token] == 0) { return (reward, block.timestamp); } uint _startIndex = getPriorSupplyIndex(_startTimestamp); uint _endIndex = Math.min(supplyNumCheckpoints-1, maxRuns); for (uint i = _startIndex; i < _endIndex; i++) { SupplyCheckpoint memory sp0 = supplyCheckpoints[i]; if (sp0.supply > 0) { SupplyCheckpoint memory sp1 = supplyCheckpoints[i+1]; (uint _reward, uint _endTime) = _calcRewardPerToken(token, sp1.timestamp, sp0.timestamp, sp0.supply, _startTimestamp); reward += _reward; _writeRewardPerTokenCheckpoint(token, reward, _endTime); _startTimestamp = _endTime; } } return (reward, _startTimestamp); } function _calcRewardPerToken(address token, uint timestamp1, uint timestamp0, uint supply, uint startTimestamp) internal view returns (uint, uint) { uint endTime = Math.max(timestamp1, startTimestamp); return (((Math.min(endTime, periodFinish[token]) - Math.min(Math.max(timestamp0, startTimestamp), periodFinish[token])) * rewardRate[token] * PRECISION / supply), endTime); } /// @dev Update stored rewardPerToken values without the last one snapshot /// If the contract will get "out of gas" error on users actions this will be helpful function batchUpdateRewardPerToken(address token, uint maxRuns) external { (rewardPerTokenStored[token], lastUpdateTime[token]) = _updateRewardPerToken(token, maxRuns, false); } function _updateRewardForAllTokens() internal { uint length = rewards.length; for (uint i; i < length; i++) { address token = rewards[i]; (rewardPerTokenStored[token], lastUpdateTime[token]) = _updateRewardPerToken(token, type(uint).max, true); } } function _updateRewardPerToken(address token, uint maxRuns, bool actualLast) internal returns (uint, uint) { uint _startTimestamp = lastUpdateTime[token]; uint reward = rewardPerTokenStored[token]; if (supplyNumCheckpoints == 0) { return (reward, _startTimestamp); } if (rewardRate[token] == 0) { return (reward, block.timestamp); } uint _startIndex = getPriorSupplyIndex(_startTimestamp); uint _endIndex = Math.min(supplyNumCheckpoints - 1, maxRuns); if (_endIndex > 0) { for (uint i = _startIndex; i <= _endIndex - 1; i++) { SupplyCheckpoint memory sp0 = supplyCheckpoints[i]; if (sp0.supply > 0) { SupplyCheckpoint memory sp1 = supplyCheckpoints[i+1]; (uint _reward, uint _endTime) = _calcRewardPerToken(token, sp1.timestamp, sp0.timestamp, sp0.supply, _startTimestamp); reward += _reward; _writeRewardPerTokenCheckpoint(token, reward, _endTime); _startTimestamp = _endTime; } } } if (actualLast) { SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex]; if (sp.supply > 0) { (uint _reward,) = _calcRewardPerToken(token, lastTimeRewardApplicable(token), Math.max(sp.timestamp, _startTimestamp), sp.supply, _startTimestamp); reward += _reward; _writeRewardPerTokenCheckpoint(token, reward, block.timestamp); _startTimestamp = block.timestamp; } } return (reward, _startTimestamp); } // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run function earned(address token, address account) public view returns (uint) { uint _startTimestamp = Math.max(lastEarn[token][account], rewardPerTokenCheckpoints[token][0].timestamp); if (numCheckpoints[account] == 0) { return 0; } uint _startIndex = getPriorBalanceIndex(account, _startTimestamp); uint _endIndex = numCheckpoints[account]-1; uint reward = 0; if (_endIndex > 0) { for (uint i = _startIndex; i <= _endIndex-1; i++) { Checkpoint memory cp0 = checkpoints[account][i]; Checkpoint memory cp1 = checkpoints[account][i+1]; (uint _rewardPerTokenStored0,) = getPriorRewardPerToken(token, cp0.timestamp); (uint _rewardPerTokenStored1,) = getPriorRewardPerToken(token, cp1.timestamp); reward += cp0.balanceOf * (_rewardPerTokenStored1 - _rewardPerTokenStored0) / PRECISION; } } Checkpoint memory cp = checkpoints[account][_endIndex]; (uint _rewardPerTokenStored,) = getPriorRewardPerToken(token, cp.timestamp); reward += cp.balanceOf * (rewardPerToken(token) - Math.max(_rewardPerTokenStored, userRewardPerTokenStored[token][account])) / PRECISION; return reward; } function depositAll(uint tokenId) external { deposit(IERC20(stake).balanceOf(msg.sender), tokenId); } function deposit(uint amount, uint tokenId) public lock { require(amount > 0); _updateRewardForAllTokens(); _safeTransferFrom(stake, msg.sender, address(this), amount); totalSupply += amount; balanceOf[msg.sender] += amount; if (tokenId > 0) { require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender); if (tokenIds[msg.sender] == 0) { tokenIds[msg.sender] = tokenId; IVoter(voter).attachTokenToGauge(tokenId, msg.sender); } require(tokenIds[msg.sender] == tokenId); } else { tokenId = tokenIds[msg.sender]; } uint _derivedBalance = derivedBalances[msg.sender]; derivedSupply -= _derivedBalance; _derivedBalance = derivedBalance(msg.sender); derivedBalances[msg.sender] = _derivedBalance; derivedSupply += _derivedBalance; _writeCheckpoint(msg.sender, _derivedBalance); _writeSupplyCheckpoint(); IVoter(voter).emitDeposit(tokenId, msg.sender, amount); emit Deposit(msg.sender, tokenId, amount); } function withdrawAll() external { withdraw(balanceOf[msg.sender]); } function withdraw(uint amount) public { uint tokenId = 0; if (amount == balanceOf[msg.sender]) { tokenId = tokenIds[msg.sender]; } withdrawToken(amount, tokenId); } function withdrawToken(uint amount, uint tokenId) public lock { _updateRewardForAllTokens(); totalSupply -= amount; balanceOf[msg.sender] -= amount; _safeTransfer(stake, msg.sender, amount); if (tokenId > 0) { require(tokenId == tokenIds[msg.sender]); tokenIds[msg.sender] = 0; IVoter(voter).detachTokenFromGauge(tokenId, msg.sender); } else { tokenId = tokenIds[msg.sender]; } uint _derivedBalance = derivedBalances[msg.sender]; derivedSupply -= _derivedBalance; _derivedBalance = derivedBalance(msg.sender); derivedBalances[msg.sender] = _derivedBalance; derivedSupply += _derivedBalance; _writeCheckpoint(msg.sender, derivedBalances[msg.sender]); _writeSupplyCheckpoint(); IVoter(voter).emitWithdraw(tokenId, msg.sender, amount); emit Withdraw(msg.sender, tokenId, amount); } function left(address token) external view returns (uint) { if (block.timestamp >= periodFinish[token]) return 0; uint _remaining = periodFinish[token] - block.timestamp; return _remaining * rewardRate[token]; } function notifyRewardAmount(address token, uint amount) external lock { require(token != stake, "cannot rewards with stake tokens"); require(amount > 0, "invalid amount"); require(totalSupply > 0, "no tokens staked"); if (!isReward[token]) { require(IVoter(voter).isReward(address(this), token), "rewards tokens must be whitelisted"); require(rewards.length < MAX_REWARD_TOKENS, "too many rewards tokens"); isReward[token] = true; rewards.push(token); } if (rewardRate[token] == 0) _writeRewardPerTokenCheckpoint(token, 0, block.timestamp); (rewardPerTokenStored[token], lastUpdateTime[token]) = _updateRewardPerToken(token, type(uint).max, true); _claimFees(); if (block.timestamp >= periodFinish[token]) { _safeTransferFrom(token, msg.sender, address(this), amount); rewardRate[token] = amount / DURATION; } else { uint _remaining = periodFinish[token] - block.timestamp; uint _left = _remaining * rewardRate[token]; require(amount > _left); _safeTransferFrom(token, msg.sender, address(this), amount); rewardRate[token] = (amount + _left) / DURATION; } require(rewardRate[token] > 0); uint balance = IERC20(token).balanceOf(address(this)); require(rewardRate[token] <= balance / DURATION, "Provided reward too high"); periodFinish[token] = block.timestamp + DURATION; emit NotifyReward(msg.sender, token, amount); } function swapOutReward(uint i, address oldToken, address newToken) external { require(msg.sender == IVoter(voter).admin()); require(rewards[i] == oldToken); isReward[oldToken] = false; isReward[newToken] = true; rewards[i] = newToken; } function _safeTransfer(address token, address to, uint256 value) internal { require(token.code.length > 0); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool)))); } function _safeTransferFrom(address token, address from, address to, uint256 value) internal { require(token.code.length > 0); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool)))); } function _safeApprove(address token, address spender, uint256 value) internal { require(token.code.length > 0); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, spender, value)); require(success && (data.length == 0 || abi.decode(data, (bool)))); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; interface IBribe { function _deposit(uint amount, uint tokenId) external; function _withdraw(uint amount, uint tokenId) external; function getRewardForOwner(uint tokenId, address[] memory tokens) external; function notifyRewardAmount(address token, uint amount) external; function left(address token) external view returns (uint); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; interface IPair { function burn(address to) external returns (uint amount0, uint amount1); function claimFees() external returns (uint, uint); function getAmountOut(uint amountIn, address tokenIn) external view returns (uint); function getReserves() external view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast); function mint(address to) external returns (uint liquidity); function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; function stable() external view returns (bool); function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; function tokens() external returns (address, address); function transferFrom(address src, address dst, uint amount) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; interface IVoter { function attachTokenToGauge(uint tokenId, address account) external; function detachTokenFromGauge(uint tokenId, address account) external; function emitDeposit(uint tokenId, address account, uint amount) external; function emitWithdraw(uint tokenId, address account, uint amount) external; function notifyRewardAmount(uint amount) external; function _ve() external view returns (address); function createGauge(address _pair) external returns (address); function factory() external view returns (address); function whitelistingFee() external view returns (uint256); function setWhitelistingFee(uint256 _fee) external; function whitelist(address _token) external; function isWhitelisted(address _token) external view returns (bool); function delist(address _token) external; function bribeFactory() external view returns (address); function bribes(address gauge) external view returns (address); function gauges(address pair) external view returns (address); function isGauge(address gauge) external view returns (bool); function allGauges(uint index) external view returns (address); function vote(uint tokenId, address[] calldata gaugeVote, uint[] calldata weights) external; function gaugeVote(uint tokenId) external view returns (address[] memory); function votes(uint tokenId, address gauge) external view returns (uint); function weights(address gauge) external view returns (uint); function usedWeights(uint tokenId) external view returns (uint); function claimable(address gauge) external view returns (uint); function totalWeight() external view returns (uint); function reset(uint _tokenId) external; function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external; function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external; function distributeFees(address[] memory _gauges) external; function updateGauge(address _gauge) external; function poke(uint _tokenId) external; function initialize(address[] memory _tokens, address _minter) external; function minter() external view returns (address); function admin() external view returns (address); function feeManagers(address feeManager) external view returns (bool); function claimRewards(address[] memory _gauges, address[][] memory _tokens) external; function isReward(address gauge, address token) external view returns (bool); function isBribe(address bribe, address token) external view returns (bool); function isLive(address gauge) external view returns (bool); function setBribe(address _bribe, address _token, bool _status) external; function setReward(address _gauge, address _token, bool _status) external; function killGauge(address _gauge) external; function reviveGauge(address _gauge) external; function distroFees() external; function distro() external; function distribute(address _gauge) external; function distributeRange(uint start, uint finish) external; function distributeGauges(address[] memory _gauges) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; interface IVotingEscrow { struct Point { int128 bias; int128 slope; // # -dweight / dt uint256 ts; uint256 blk; // block } function user_point_epoch(uint tokenId) external view returns (uint); function epoch() external view returns (uint); function user_point_history(uint tokenId, uint loc) external view returns (Point memory); function point_history(uint loc) external view returns (Point memory); function checkpoint() external; function deposit_for(uint tokenId, uint value) external; function token() external view returns (address); function user_point_history__ts(uint tokenId, uint idx) external view returns (uint); function locked__end(uint _tokenId) external view returns (uint); function locked__amount(uint _tokenId) external view returns (uint); function approve(address spender, uint tokenId) external; function balanceOfNFT(uint) external view returns (uint); function isApprovedOrOwner(address, uint) external view returns (bool); function ownerOf(uint) external view returns (address); function transferFrom(address, address, uint) external; function totalSupply() external view returns (uint); function supply() external view returns (uint); function create_lock_for(uint, uint, address) external returns (uint); function lockVote(uint tokenId) external; function isVoteExpired(uint tokenId) external view returns (bool); function voteExpiry(uint _tokenId) external view returns (uint); function attach(uint tokenId) external; function detach(uint tokenId) external; function voting(uint tokenId) external; function abstain(uint tokenId) external; function voted(uint tokenId) external view returns (bool); function withdraw(uint tokenId) external; function create_lock(uint value, uint duration) external returns (uint); function setVoter(address voter) external; function balanceOf(address owner) external view returns (uint); function safeTransferFrom(address from, address to, uint tokenId) external; function burn(uint _tokenId) external; function setAdmin(address _admin) external; function setArtProxy(address _proxy) external; }
{ "evmVersion": "paris", "optimizer": { "enabled": true, "runs": 10000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_stake","type":"address"},{"internalType":"address","name":"_bribe","type":"address"},{"internalType":"address","name":"_ve","type":"address"}],"name":"createGauge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"last_gauge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50613cbc806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80631c48e0fa1461003b578063730a8bdb14610077575b600080fd5b61004e61004936600461017d565b610097565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b60005461004e9073ffffffffffffffffffffffffffffffffffffffff1681565b6000838383336040516100a990610147565b73ffffffffffffffffffffffffffffffffffffffff9485168152928416602084015290831660408301529091166060820152608001604051809103906000f0801580156100fa573d6000803e3d6000fd5b50600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff929092169182179055949350505050565b613ac6806101c183390190565b803573ffffffffffffffffffffffffffffffffffffffff8116811461017857600080fd5b919050565b60008060006060848603121561019257600080fd5b61019b84610154565b92506101a960208501610154565b91506101b760408501610154565b9050925092509256fe61010060405260016015553480156200001757600080fd5b5060405162003ac638038062003ac68339810160408190526200003a916200012a565b6001600160a01b038416158015906200005b57506001600160a01b03831615155b80156200007057506001600160a01b03821615155b80156200008557506001600160a01b03811615155b620000ea5760405162461bcd60e51b815260206004820152602b60248201527f47617567653a207a65726f20616464726573732070726f766964656420696e2060448201526a31b7b739ba393ab1ba37b960a91b606482015260840160405180910390fd5b6001600160a01b0393841660805291831660c052821660a0521660e05262000187565b80516001600160a01b03811681146200012557600080fd5b919050565b600080600080608085870312156200014157600080fd5b6200014c856200010d565b93506200015c602086016200010d565b92506200016c604086016200010d565b91506200017c606086016200010d565b905092959194509250565b60805160a05160c05160e05161387262000254600039600081816104d0015281816107c901528181610d9a01528181610df8015281816115a001528181611d4801528181611e850152818161232e015261245e01526000818161043f01528181612def01528181612e8601528181612eea01528181612f890152818161301e01526130820152600081816105e70152611c6301526000818161047e015281816113dc01528181611aef01528181611bc20152818161229601528181612c6e0152612d3001526138726000f3fe608060405234801561001057600080fd5b50600436106102ff5760003560e01c806376f4be361161019c578063d35e2544116100ee578063f122977711610097578063fc97a30311610071578063fc97a30314610781578063fd314098146107a1578063fdb483c7146107b457600080fd5b8063f122977714610734578063f301af4214610747578063f7412baf1461075a57600080fd5b8063e2bbb158116100c8578063e2bbb15814610710578063e688639614610723578063e8111a121461072b57600080fd5b8063d35e2544146106be578063d7da4bb0146106e7578063da09d19d146106f057600080fd5b80639ce43f9011610150578063b66503cf1161012a578063b66503cf14610690578063c6f678bd146106a3578063d294f093146106b657600080fd5b80639ce43f9014610625578063a495e5b514610645578063aa4796521461067057600080fd5b80638dd598fb116101815780638dd598fb146105e257806393f1c4421461060957806399bcc0521461061257600080fd5b806376f4be36146105c7578063853828b6146105da57600080fd5b80633a4b66f1116102555780635a45d0521161020957806368fcee1a116101e357806368fcee1a146105745780636fcfff451461058757806370a08231146105a757600080fd5b80635a45d0521461052e578063638634ee1461054157806363fb415b1461055457600080fd5b806346c96aac1161023a57806346c96aac146104cb5780634c02a21c146104f25780634d5ce038146104fb57600080fd5b80633a4b66f1146104795780633ca068b6146104a057600080fd5b8063211dc32d116102b75780632e1a7d4d116102915780632e1a7d4d1461041457806331279d3d1461042757806337d0208c1461043a57600080fd5b8063211dc32d146103c1578063221ca18c146103d45780632ce9aead146103f457600080fd5b80630cdfebfa116102e85780630cdfebfa14610365578063115c6f391461039757806318160ddd146103b857600080fd5b806301316ddf146103045780630b8b192014610350575b600080fd5b61033661031236600461342e565b60116020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61036361035e36600461345a565b6107c7565b005b61033661037336600461342e565b600d6020908152600092835260408084209091529082529020805460019091015482565b6103aa6103a536600461342e565b610940565b604051908152602001610347565b6103aa60095481565b6103aa6103cf36600461349c565b610aaf565b6103aa6103e23660046134d5565b60026020526000908152604090205481565b6103aa6104023660046134d5565b60046020526000908152604090205481565b6103636104223660046134f2565b610d33565b61036361043536600461353a565b610d69565b6104617f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610347565b6104617f000000000000000000000000000000000000000000000000000000000000000081565b6103aa6104ae36600461349c565b600760209081526000928352604080842090915290825290205481565b6104617f000000000000000000000000000000000000000000000000000000000000000081565b6103aa60145481565b61051e6105093660046134d5565b600c6020526000908152604090205460ff1681565b6040519015158152602001610347565b61036361053c36600461342e565b611196565b6103aa61054f3660046134d5565b6111ce565b6103aa6105623660046134d5565b60016020526000908152604090205481565b61036361058236600461342e565b6111f2565b6103aa6105953660046134d5565b600e6020526000908152604090205481565b6103aa6105b53660046134d5565b600a6020526000908152604090205481565b6103aa6105d53660046134f2565b6111fe565b610363611332565b6104617f000000000000000000000000000000000000000000000000000000000000000081565b6103aa60135481565b6103aa6106203660046134d5565b61134d565b6103aa6106333660046134d5565b60056020526000908152604090205481565b6103aa61065336600461349c565b600660209081526000928352604080842090915290825290205481565b6103aa61067e3660046134d5565b60126020526000908152604090205481565b61036361069e36600461342e565b6113be565b6103636106b13660046134f2565b611abd565b610336611b6b565b6103aa6106cc3660046134d5565b6001600160a01b03166000908152600a602052604090205490565b6103aa60005481565b6103aa6106fe3660046134d5565b60036020526000908152604090205481565b61036361071e366004613632565b611b97565b600b546103aa565b6103aa60105481565b6103aa6107423660046134d5565b611f2f565b6104616107553660046134f2565b611fee565b6103366107683660046134f2565b600f602052600090815260409020805460019091015482565b6103aa61078f3660046134d5565b60086020526000908152604090205481565b6103366107af36600461342e565b612018565b6103636107c2366004613632565b612239565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610825573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108499190613654565b6001600160a01b0316336001600160a01b03161461086657600080fd5b816001600160a01b0316600b848154811061088357610883613671565b6000918252602090912001546001600160a01b0316146108a257600080fd5b6001600160a01b038083166000908152600c602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009081169091559284168252902080549091166001179055600b80548291908590811061090d5761090d613671565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0382166000908152600e602052604081205480820361096a576000915050610aa9565b6001600160a01b0384166000908152600d60205260408120849161098f6001856136cf565b815260200190815260200160002060000154116109b9576109b16001826136cf565b915050610aa9565b6001600160a01b0384166000908152600d602090815260408083208380529091529020548310156109ee576000915050610aa9565b6000806109fc6001846136cf565b90505b81811115610aa45760006002610a1584846136cf565b610a1f91906136e2565b610a2990836136cf565b6001600160a01b0388166000908152600d60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610a7e57509350610aa992505050565b8051871115610a8f57819350610a9d565b610a9a6001836136cf565b92505b50506109ff565b509150505b92915050565b6001600160a01b038083166000818152600660209081526040808320948616835293815283822054928252601181528382208280529052918220548291610af5916124fa565b6001600160a01b0384166000908152600e602052604081205491925003610b20576000915050610aa9565b6000610b2c8483610940565b6001600160a01b0385166000908152600e602052604081205491925090610b55906001906136cf565b905060008115610c6757825b610b6c6001846136cf565b8111610c65576001600160a01b0387166000818152600d602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610bc190869061371d565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610c008b8460000151612018565b5090506000610c138c8460000151612018565b509050670de0b6b3a7640000610c2983836136cf565b8560200151610c389190613730565b610c4291906136e2565b610c4c908761371d565b9550505050508080610c5d90613747565b915050610b61565b505b6001600160a01b0386166000908152600d60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610cb1908a90612018565b506001600160a01b03808b166000908152600760209081526040808320938d1683529290522054909150670de0b6b3a764000090610cf09083906124fa565b610cf98b611f2f565b610d0391906136cf565b8360200151610d129190613730565b610d1c91906136e2565b610d26908461371d565b9998505050505050505050565b336000908152600a60205260408120548203610d5b5750336000908152600860205260409020545b610d658282612239565b5050565b601554600114610d7857600080fd5b6002601555336001600160a01b0383161480610dbc5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610dc557600080fd5b60016015556040517f63453ae10000000000000000000000000000000000000000000000000000000081523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610e4457600080fd5b505af1158015610e58573d6000803e3d6000fd5b5050600260155550600090505b81518110156110ef57610eb3828281518110610e8357610e83613671565b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001612510565b60056000858581518110610ec957610ec9613671565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060046000878781518110610f0957610f09613671565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610f64838381518110610f5657610f56613671565b602002602001015185610aaf565b90504260066000858581518110610f7d57610f7d613671565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060056000848481518110610fe257610fe2613671565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546007600085858151811061102157611021613671565b6020908102919091018101516001600160a01b0390811683528282019390935260409182016000908120938916815292905290205580156110805761108083838151811061107157611071613671565b60200260200101518583612700565b82828151811061109257611092613671565b60200260200101516001600160a01b0316846001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516110de91815260200190565b60405180910390a350600101610e65565b506001600160a01b038216600090815260016020526040812054815490918291819061111c9084906136cf565b9091555050506001600160a01b0382166000908152600a602090815260408083205460019092528220819055815490918291819061115b90849061371d565b90915550506001600160a01b038316600090815260016020526040902054611184908490612864565b61118c61296f565b5050600160155550565b6111a08282612a12565b6001600160a01b03909316600090815260056020908152604080832060049092529091209390935590915550565b6001600160a01b038116600090815260036020526040812054610aa9904290612b6b565b6111a082826000612510565b6010546000908082036112145750600092915050565b82600f60006112246001856136cf565b8152602001908152602001600020600001541161124d576112466001826136cf565b9392505050565b60008052600f6020527ff4803e074bd026baaf6ed2e288c9515f68c72fb7216eebdd7cae1718a53ec375548310156112885750600092915050565b6000806112966001846136cf565b90505b8181111561132a57600060026112af84846136cf565b6112b991906136e2565b6112c390836136cf565b6000818152600f6020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611304575095945050505050565b805187111561131557819350611323565b6113206001836136cf565b92505b5050611299565b509392505050565b336000908152600a602052604090205461134b90610d33565b565b6001600160a01b038116600090815260036020526040812054421061137457506000919050565b6001600160a01b0382166000908152600360205260408120546113989042906136cf565b6001600160a01b0384166000908152600260205260409020549091506112469082613730565b6015546001146113cd57600080fd5b60026015556001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169083160361146c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f63616e6e6f7420726577617264732077697468207374616b6520746f6b656e7360448201526064015b60405180910390fd5b600081116114d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f696e76616c696420616d6f756e740000000000000000000000000000000000006044820152606401611463565b600060095411611542576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e6f20746f6b656e73207374616b6564000000000000000000000000000000006044820152606401611463565b6001600160a01b0382166000908152600c602052604090205460ff1661179f576040517f1937e58f0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0383811660248301527f00000000000000000000000000000000000000000000000000000000000000001690631937e58f90604401602060405180830381865afa1580156115e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160b919061377f565b611697576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c69737460448201527f65640000000000000000000000000000000000000000000000000000000000006064820152608401611463565b600b54601011611703576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401611463565b6001600160a01b0382166000818152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001908117909155600b805491820181559091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690911790555b6001600160a01b03821660009081526002602052604081205490036117ca576117ca82600042612b7a565b6117f6827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001612510565b6001600160a01b038416600090815260056020908152604080832060049092529091209190915555611826612c69565b50506001600160a01b038216600090815260036020526040902054421061187e576118538233308461312d565b61186062093a80826136e2565b6001600160a01b038316600090815260026020526040902055611917565b6001600160a01b0382166000908152600360205260408120546118a29042906136cf565b6001600160a01b038416600090815260026020526040812054919250906118c99083613730565b90508083116118d757600080fd5b6118e38433308661312d565b62093a806118f1828561371d565b6118fb91906136e2565b6001600160a01b03851660009081526002602052604090205550505b6001600160a01b03821660009081526002602052604090205461193957600080fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119bd91906137a1565b90506119cc62093a80826136e2565b6001600160a01b0384166000908152600260205260409020541115611a4d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401611463565b611a5a62093a804261371d565b6001600160a01b0384166000818152600360205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf5082690611aab9086815260200190565b60405180910390a35050600160155550565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152336004820152611b68907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611b3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6291906137a1565b82611b97565b50565b600080601554600114611b7d57600080fd5b6002601555611b8a612c69565b9150915060016015559091565b601554600114611ba657600080fd5b600260155581611bb557600080fd5b611bbd613253565b611be97f000000000000000000000000000000000000000000000000000000000000000033308561312d565b8160096000828254611bfb919061371d565b9091555050336000908152600a602052604081208054849290611c1f90849061371d565b90915550508015611dc5576040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611caa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cce9190613654565b6001600160a01b031614611ce157600080fd5b336000908152600860205260408120549003611da5573360008181526008602052604090819020839055517f698473e30000000000000000000000000000000000000000000000000000000081526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611d8c57600080fd5b505af1158015611da0573d6000803e3d6000fd5b505050505b336000908152600860205260409020548114611dc057600080fd5b611dd7565b50336000908152600860205260409020545b336000908152600160205260408120548154909182918190611dfa9084906136cf565b9091555050336000908152600a60209081526040808320546001909252822081905581549092508291908190611e3190849061371d565b90915550611e4190503382612864565b611e4961296f565b6040517fa61c713a00000000000000000000000000000000000000000000000000000000815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611ed157600080fd5b505af1158015611ee5573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160155550565b60008054600003611f5657506001600160a01b031660009081526005602052604090205490565b600080546001600160a01b038416825260026020908152604080842054600483528185205460039093529320549192670de0b6b3a7640000929091611f9a91612b6b565b611fa3866111ce565b611fad91906136cf565b611fb79190613730565b611fc19190613730565b611fcb91906136e2565b6001600160a01b038316600090815260056020526040902054610aa9919061371d565b600b8181548110611ffe57600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601260205260408120548190808203612047576000809250925050612232565b6001600160a01b0385166000908152601160205260408120859161206c6001856136cf565b81526020019081526020016000206000015411612109576001600160a01b0385166000908152601160205260408120906120a76001846136cf565b81526020019081526020016000206001015460116000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846120ed91906136cf565b8152602001908152602001600020600001549250925050612232565b6001600160a01b0385166000908152601160209081526040808320838052909152902054841015612141576000809250925050612232565b60008061214f6001846136cf565b90505b81811115612201576000600261216884846136cf565b61217291906136e2565b61217c90836136cf565b6001600160a01b03891660009081526011602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908890036121db576020810151905190965094506122329350505050565b80518811156121ec578193506121fa565b6121f76001836136cf565b92505b5050612152565b506001600160a01b038616600090815260116020908152604080832093835292905220600181015490549093509150505b9250929050565b60155460011461224857600080fd5b6002601555612255613253565b816009600082825461226791906136cf565b9091555050336000908152600a60205260408120805484929061228b9084906136cf565b909155506122bc90507f00000000000000000000000000000000000000000000000000000000000000003384612700565b801561238f573360009081526008602052604090205481146122dd57600080fd5b3360008181526008602052604080822091909155517f411b1f770000000000000000000000000000000000000000000000000000000081526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561237257600080fd5b505af1158015612386573d6000803e3d6000fd5b505050506123a1565b50336000908152600860205260409020545b3360009081526001602052604081205481549091829181906123c49084906136cf565b9091555050336000908152600a602090815260408083205460019092528220819055815490925082919081906123fb90849061371d565b90915550503360008181526001602052604090205461241a9190612864565b61242261296f565b6040517fea94ee4400000000000000000000000000000000000000000000000000000000815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156124aa57600080fd5b505af11580156124be573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611f1d565b60008183116125095781611246565b5090919050565b6001600160a01b038316600090815260046020908152604080832054600590925282205460105483929190830361254a57925090506126f8565b6001600160a01b03871660009081526002602052604081205490036125755792504291506126f89050565b6000612580836111fe565b9050600061259c600160105461259691906136cf565b89612b6b565b9050801561267557815b6125b16001836136cf565b8111612673576000818152600f60209081526040918290208251808401909352805483526001015490820181905215612660576000600f816125f485600161371d565b815260200190815260200160002060405180604001604052908160008201548152602001600182015481525050905060008061263f8e8460000151866000015187602001518d6132eb565b909250905061264e828961371d565b975061265b8e8983612b7a565b975050505b508061266b81613747565b9150506125a6565b505b86156126ef576000818152600f602090815260409182902082518084019093528054835260010154908201819052156126ed5760006126ce8b6126b78d6111ce565b84516126c3908a6124fa565b85602001518a6132eb565b5090506126db818661371d565b94506126e88b8642612b7a565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161271757600080fd5b6040516001600160a01b0383811660248301526044820183905260009182918616907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516127e891906137ba565b6000604051808303816000865af19150503d8060008114612825576040519150601f19603f3d011682016040523d82523d6000602084013e61282a565b606091505b5091509150818015612854575080511580612854575080806020019051810190612854919061377f565b61285d57600080fd5b5050505050565b6001600160a01b0382166000908152600e6020526040902054429080158015906128c257506001600160a01b0384166000908152600d6020526040812083916128ae6001856136cf565b815260200190815260200160002060000154145b15612905576001600160a01b0384166000908152600d6020526040812084916128ec6001856136cf565b8152602081019190915260400160002060010155612969565b60408051808201825283815260208082018681526001600160a01b0388166000908152600d835284812086825290925292902090518155905160019182015561294f90829061371d565b6001600160a01b0385166000908152600e60205260409020555b50505050565b6010544281158015906129a1575080600f600061298d6001866136cf565b815260200190815260200160002060000154145b156129d257600054600f60006001856129ba91906136cf565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600f9052929020905181559051600191820155612a0b90839061371d565b6010555050565b6001600160a01b0382166000908152600460209081526040808320546005909252822054601054839291908303612a4c5792509050612232565b6001600160a01b0386166000908152600260205260408120549003612a775792504291506122329050565b6000612a82836111fe565b90506000612a9e6001601054612a9891906136cf565b88612b6b565b9050815b81811015612b5c576000818152600f60209081526040918290208251808401909352805483526001015490820181905215612b53576000600f81612ae785600161371d565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080612b328d8460000151866000015187602001518d6132eb565b9092509050612b41828961371d565b9750612b4e8d8983612b7a565b975050505b50600101612aa2565b50919792965091945050505050565b60008183106125095781611246565b6001600160a01b0383166000908152601260205260409020548015801590612bd657506001600160a01b03841660009081526011602052604081208391612bc26001856136cf565b815260200190815260200160002060000154145b15612c00576001600160a01b038416600090815260116020526040812084916128ec6001856136cf565b60408051808201825283815260208082018681526001600160a01b038816600090815260118352848120868252909252929020905181559051600191820155612c4a90829061371d565b6001600160a01b03851660009081526012602052604090205550505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612ccb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cef91906137e9565b909250905081151580612d025750600081115b1561312957600082601354612d17919061371d565b9050600082601454612d29919061371d565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612d8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612db1919061380d565b6040517f99bcc0520000000000000000000000000000000000000000000000000000000081526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612e38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e5c91906137a1565b84118015612e7657506000612e7462093a80866136e2565b115b15612f4b576000601355612eab827f0000000000000000000000000000000000000000000000000000000000000000866133a6565b6040517fb66503cf0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612f2e57600080fd5b505af1158015612f42573d6000803e3d6000fd5b50505050612f51565b60138490555b6040517f99bcc0520000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612fd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ff491906137a1565b8311801561300e5750600061300c62093a80856136e2565b115b156130e3576000601455613043817f0000000000000000000000000000000000000000000000000000000000000000856133a6565b6040517fb66503cf0000000000000000000000000000000000000000000000000000000081526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b1580156130c657600080fd5b505af11580156130da573d6000803e3d6000fd5b505050506130e9565b60148390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b1161314457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905291516000928392908816916131d691906137ba565b6000604051808303816000865af19150503d8060008114613213576040519150601f19603f3d011682016040523d82523d6000602084013e613218565b606091505b5091509150818015613242575080511580613242575080806020019051810190613242919061377f565b61324b57600080fd5b505050505050565b600b5460005b81811015610d65576000600b828154811061327657613276613671565b6000918252602090912001546001600160a01b031690506132b9817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001612510565b6001600160a01b0390921660009081526005602090815260408083206004909252909120929092559055600101613259565b60008060006132fa87856124fa565b6001600160a01b0389166000908152600260205260409020549091508590670de0b6b3a76400009061334d61332f8a896124fa565b6001600160a01b038d16600090815260036020526040902054612b6b565b6001600160a01b038c16600090815260036020526040902054613371908690612b6b565b61337b91906136cf565b6133859190613730565b61338f9190613730565b61339991906136e2565b9890975095505050505050565b6000836001600160a01b03163b116133bd57600080fd5b6040516001600160a01b0383811660248301526044820183905260009182918616907f095ea7b3000000000000000000000000000000000000000000000000000000009060640161275f565b6001600160a01b0381168114611b6857600080fd5b803561342981613409565b919050565b6000806040838503121561344157600080fd5b823561344c81613409565b946020939093013593505050565b60008060006060848603121561346f57600080fd5b83359250602084013561348181613409565b9150604084013561349181613409565b809150509250925092565b600080604083850312156134af57600080fd5b82356134ba81613409565b915060208301356134ca81613409565b809150509250929050565b6000602082840312156134e757600080fd5b813561124681613409565b60006020828403121561350457600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806040838503121561354d57600080fd5b823561355881613409565b915060208381013567ffffffffffffffff8082111561357657600080fd5b818601915086601f83011261358a57600080fd5b81358181111561359c5761359c61350b565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f830116810181811085821117156135df576135df61350b565b6040529182528482019250838101850191898311156135fd57600080fd5b938501935b82851015613622576136138561341e565b84529385019392850192613602565b8096505050505050509250929050565b6000806040838503121561364557600080fd5b50508035926020909101359150565b60006020828403121561366657600080fd5b815161124681613409565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610aa957610aa96136a0565b600082613718577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820180821115610aa957610aa96136a0565b8082028115828204841417610aa957610aa96136a0565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613778576137786136a0565b5060010190565b60006020828403121561379157600080fd5b8151801515811461124657600080fd5b6000602082840312156137b357600080fd5b5051919050565b6000825160005b818110156137db57602081860181015185830152016137c1565b506000920191825250919050565b600080604083850312156137fc57600080fd5b505080516020909101519092909150565b6000806040838503121561382057600080fd5b825161382b81613409565b60208401519092506134ca8161340956fea2646970667358221220e682cd7c69c2506de8bd875be51ecaaff92d0083743a51bf135ca21199bedffa64736f6c63430008160033a26469706673582212200aaaf9cf7c6a31dd91e6c96d5da6da24ef3adb6b2b7c9243438efc8035bb781a64736f6c63430008160033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100365760003560e01c80631c48e0fa1461003b578063730a8bdb14610077575b600080fd5b61004e61004936600461017d565b610097565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b60005461004e9073ffffffffffffffffffffffffffffffffffffffff1681565b6000838383336040516100a990610147565b73ffffffffffffffffffffffffffffffffffffffff9485168152928416602084015290831660408301529091166060820152608001604051809103906000f0801580156100fa573d6000803e3d6000fd5b50600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff929092169182179055949350505050565b613ac6806101c183390190565b803573ffffffffffffffffffffffffffffffffffffffff8116811461017857600080fd5b919050565b60008060006060848603121561019257600080fd5b61019b84610154565b92506101a960208501610154565b91506101b760408501610154565b9050925092509256fe61010060405260016015553480156200001757600080fd5b5060405162003ac638038062003ac68339810160408190526200003a916200012a565b6001600160a01b038416158015906200005b57506001600160a01b03831615155b80156200007057506001600160a01b03821615155b80156200008557506001600160a01b03811615155b620000ea5760405162461bcd60e51b815260206004820152602b60248201527f47617567653a207a65726f20616464726573732070726f766964656420696e2060448201526a31b7b739ba393ab1ba37b960a91b606482015260840160405180910390fd5b6001600160a01b0393841660805291831660c052821660a0521660e05262000187565b80516001600160a01b03811681146200012557600080fd5b919050565b600080600080608085870312156200014157600080fd5b6200014c856200010d565b93506200015c602086016200010d565b92506200016c604086016200010d565b91506200017c606086016200010d565b905092959194509250565b60805160a05160c05160e05161387262000254600039600081816104d0015281816107c901528181610d9a01528181610df8015281816115a001528181611d4801528181611e850152818161232e015261245e01526000818161043f01528181612def01528181612e8601528181612eea01528181612f890152818161301e01526130820152600081816105e70152611c6301526000818161047e015281816113dc01528181611aef01528181611bc20152818161229601528181612c6e0152612d3001526138726000f3fe608060405234801561001057600080fd5b50600436106102ff5760003560e01c806376f4be361161019c578063d35e2544116100ee578063f122977711610097578063fc97a30311610071578063fc97a30314610781578063fd314098146107a1578063fdb483c7146107b457600080fd5b8063f122977714610734578063f301af4214610747578063f7412baf1461075a57600080fd5b8063e2bbb158116100c8578063e2bbb15814610710578063e688639614610723578063e8111a121461072b57600080fd5b8063d35e2544146106be578063d7da4bb0146106e7578063da09d19d146106f057600080fd5b80639ce43f9011610150578063b66503cf1161012a578063b66503cf14610690578063c6f678bd146106a3578063d294f093146106b657600080fd5b80639ce43f9014610625578063a495e5b514610645578063aa4796521461067057600080fd5b80638dd598fb116101815780638dd598fb146105e257806393f1c4421461060957806399bcc0521461061257600080fd5b806376f4be36146105c7578063853828b6146105da57600080fd5b80633a4b66f1116102555780635a45d0521161020957806368fcee1a116101e357806368fcee1a146105745780636fcfff451461058757806370a08231146105a757600080fd5b80635a45d0521461052e578063638634ee1461054157806363fb415b1461055457600080fd5b806346c96aac1161023a57806346c96aac146104cb5780634c02a21c146104f25780634d5ce038146104fb57600080fd5b80633a4b66f1146104795780633ca068b6146104a057600080fd5b8063211dc32d116102b75780632e1a7d4d116102915780632e1a7d4d1461041457806331279d3d1461042757806337d0208c1461043a57600080fd5b8063211dc32d146103c1578063221ca18c146103d45780632ce9aead146103f457600080fd5b80630cdfebfa116102e85780630cdfebfa14610365578063115c6f391461039757806318160ddd146103b857600080fd5b806301316ddf146103045780630b8b192014610350575b600080fd5b61033661031236600461342e565b60116020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61036361035e36600461345a565b6107c7565b005b61033661037336600461342e565b600d6020908152600092835260408084209091529082529020805460019091015482565b6103aa6103a536600461342e565b610940565b604051908152602001610347565b6103aa60095481565b6103aa6103cf36600461349c565b610aaf565b6103aa6103e23660046134d5565b60026020526000908152604090205481565b6103aa6104023660046134d5565b60046020526000908152604090205481565b6103636104223660046134f2565b610d33565b61036361043536600461353a565b610d69565b6104617f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610347565b6104617f000000000000000000000000000000000000000000000000000000000000000081565b6103aa6104ae36600461349c565b600760209081526000928352604080842090915290825290205481565b6104617f000000000000000000000000000000000000000000000000000000000000000081565b6103aa60145481565b61051e6105093660046134d5565b600c6020526000908152604090205460ff1681565b6040519015158152602001610347565b61036361053c36600461342e565b611196565b6103aa61054f3660046134d5565b6111ce565b6103aa6105623660046134d5565b60016020526000908152604090205481565b61036361058236600461342e565b6111f2565b6103aa6105953660046134d5565b600e6020526000908152604090205481565b6103aa6105b53660046134d5565b600a6020526000908152604090205481565b6103aa6105d53660046134f2565b6111fe565b610363611332565b6104617f000000000000000000000000000000000000000000000000000000000000000081565b6103aa60135481565b6103aa6106203660046134d5565b61134d565b6103aa6106333660046134d5565b60056020526000908152604090205481565b6103aa61065336600461349c565b600660209081526000928352604080842090915290825290205481565b6103aa61067e3660046134d5565b60126020526000908152604090205481565b61036361069e36600461342e565b6113be565b6103636106b13660046134f2565b611abd565b610336611b6b565b6103aa6106cc3660046134d5565b6001600160a01b03166000908152600a602052604090205490565b6103aa60005481565b6103aa6106fe3660046134d5565b60036020526000908152604090205481565b61036361071e366004613632565b611b97565b600b546103aa565b6103aa60105481565b6103aa6107423660046134d5565b611f2f565b6104616107553660046134f2565b611fee565b6103366107683660046134f2565b600f602052600090815260409020805460019091015482565b6103aa61078f3660046134d5565b60086020526000908152604090205481565b6103366107af36600461342e565b612018565b6103636107c2366004613632565b612239565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610825573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108499190613654565b6001600160a01b0316336001600160a01b03161461086657600080fd5b816001600160a01b0316600b848154811061088357610883613671565b6000918252602090912001546001600160a01b0316146108a257600080fd5b6001600160a01b038083166000908152600c602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009081169091559284168252902080549091166001179055600b80548291908590811061090d5761090d613671565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0382166000908152600e602052604081205480820361096a576000915050610aa9565b6001600160a01b0384166000908152600d60205260408120849161098f6001856136cf565b815260200190815260200160002060000154116109b9576109b16001826136cf565b915050610aa9565b6001600160a01b0384166000908152600d602090815260408083208380529091529020548310156109ee576000915050610aa9565b6000806109fc6001846136cf565b90505b81811115610aa45760006002610a1584846136cf565b610a1f91906136e2565b610a2990836136cf565b6001600160a01b0388166000908152600d60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610a7e57509350610aa992505050565b8051871115610a8f57819350610a9d565b610a9a6001836136cf565b92505b50506109ff565b509150505b92915050565b6001600160a01b038083166000818152600660209081526040808320948616835293815283822054928252601181528382208280529052918220548291610af5916124fa565b6001600160a01b0384166000908152600e602052604081205491925003610b20576000915050610aa9565b6000610b2c8483610940565b6001600160a01b0385166000908152600e602052604081205491925090610b55906001906136cf565b905060008115610c6757825b610b6c6001846136cf565b8111610c65576001600160a01b0387166000818152600d602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610bc190869061371d565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610c008b8460000151612018565b5090506000610c138c8460000151612018565b509050670de0b6b3a7640000610c2983836136cf565b8560200151610c389190613730565b610c4291906136e2565b610c4c908761371d565b9550505050508080610c5d90613747565b915050610b61565b505b6001600160a01b0386166000908152600d60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610cb1908a90612018565b506001600160a01b03808b166000908152600760209081526040808320938d1683529290522054909150670de0b6b3a764000090610cf09083906124fa565b610cf98b611f2f565b610d0391906136cf565b8360200151610d129190613730565b610d1c91906136e2565b610d26908461371d565b9998505050505050505050565b336000908152600a60205260408120548203610d5b5750336000908152600860205260409020545b610d658282612239565b5050565b601554600114610d7857600080fd5b6002601555336001600160a01b0383161480610dbc5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610dc557600080fd5b60016015556040517f63453ae10000000000000000000000000000000000000000000000000000000081523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610e4457600080fd5b505af1158015610e58573d6000803e3d6000fd5b5050600260155550600090505b81518110156110ef57610eb3828281518110610e8357610e83613671565b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001612510565b60056000858581518110610ec957610ec9613671565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060046000878781518110610f0957610f09613671565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610f64838381518110610f5657610f56613671565b602002602001015185610aaf565b90504260066000858581518110610f7d57610f7d613671565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060056000848481518110610fe257610fe2613671565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546007600085858151811061102157611021613671565b6020908102919091018101516001600160a01b0390811683528282019390935260409182016000908120938916815292905290205580156110805761108083838151811061107157611071613671565b60200260200101518583612700565b82828151811061109257611092613671565b60200260200101516001600160a01b0316846001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516110de91815260200190565b60405180910390a350600101610e65565b506001600160a01b038216600090815260016020526040812054815490918291819061111c9084906136cf565b9091555050506001600160a01b0382166000908152600a602090815260408083205460019092528220819055815490918291819061115b90849061371d565b90915550506001600160a01b038316600090815260016020526040902054611184908490612864565b61118c61296f565b5050600160155550565b6111a08282612a12565b6001600160a01b03909316600090815260056020908152604080832060049092529091209390935590915550565b6001600160a01b038116600090815260036020526040812054610aa9904290612b6b565b6111a082826000612510565b6010546000908082036112145750600092915050565b82600f60006112246001856136cf565b8152602001908152602001600020600001541161124d576112466001826136cf565b9392505050565b60008052600f6020527ff4803e074bd026baaf6ed2e288c9515f68c72fb7216eebdd7cae1718a53ec375548310156112885750600092915050565b6000806112966001846136cf565b90505b8181111561132a57600060026112af84846136cf565b6112b991906136e2565b6112c390836136cf565b6000818152600f6020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611304575095945050505050565b805187111561131557819350611323565b6113206001836136cf565b92505b5050611299565b509392505050565b336000908152600a602052604090205461134b90610d33565b565b6001600160a01b038116600090815260036020526040812054421061137457506000919050565b6001600160a01b0382166000908152600360205260408120546113989042906136cf565b6001600160a01b0384166000908152600260205260409020549091506112469082613730565b6015546001146113cd57600080fd5b60026015556001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169083160361146c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f63616e6e6f7420726577617264732077697468207374616b6520746f6b656e7360448201526064015b60405180910390fd5b600081116114d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f696e76616c696420616d6f756e740000000000000000000000000000000000006044820152606401611463565b600060095411611542576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e6f20746f6b656e73207374616b6564000000000000000000000000000000006044820152606401611463565b6001600160a01b0382166000908152600c602052604090205460ff1661179f576040517f1937e58f0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0383811660248301527f00000000000000000000000000000000000000000000000000000000000000001690631937e58f90604401602060405180830381865afa1580156115e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160b919061377f565b611697576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c69737460448201527f65640000000000000000000000000000000000000000000000000000000000006064820152608401611463565b600b54601011611703576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401611463565b6001600160a01b0382166000818152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001908117909155600b805491820181559091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690911790555b6001600160a01b03821660009081526002602052604081205490036117ca576117ca82600042612b7a565b6117f6827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001612510565b6001600160a01b038416600090815260056020908152604080832060049092529091209190915555611826612c69565b50506001600160a01b038216600090815260036020526040902054421061187e576118538233308461312d565b61186062093a80826136e2565b6001600160a01b038316600090815260026020526040902055611917565b6001600160a01b0382166000908152600360205260408120546118a29042906136cf565b6001600160a01b038416600090815260026020526040812054919250906118c99083613730565b90508083116118d757600080fd5b6118e38433308661312d565b62093a806118f1828561371d565b6118fb91906136e2565b6001600160a01b03851660009081526002602052604090205550505b6001600160a01b03821660009081526002602052604090205461193957600080fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119bd91906137a1565b90506119cc62093a80826136e2565b6001600160a01b0384166000908152600260205260409020541115611a4d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401611463565b611a5a62093a804261371d565b6001600160a01b0384166000818152600360205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf5082690611aab9086815260200190565b60405180910390a35050600160155550565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152336004820152611b68907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611b3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6291906137a1565b82611b97565b50565b600080601554600114611b7d57600080fd5b6002601555611b8a612c69565b9150915060016015559091565b601554600114611ba657600080fd5b600260155581611bb557600080fd5b611bbd613253565b611be97f000000000000000000000000000000000000000000000000000000000000000033308561312d565b8160096000828254611bfb919061371d565b9091555050336000908152600a602052604081208054849290611c1f90849061371d565b90915550508015611dc5576040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611caa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cce9190613654565b6001600160a01b031614611ce157600080fd5b336000908152600860205260408120549003611da5573360008181526008602052604090819020839055517f698473e30000000000000000000000000000000000000000000000000000000081526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611d8c57600080fd5b505af1158015611da0573d6000803e3d6000fd5b505050505b336000908152600860205260409020548114611dc057600080fd5b611dd7565b50336000908152600860205260409020545b336000908152600160205260408120548154909182918190611dfa9084906136cf565b9091555050336000908152600a60209081526040808320546001909252822081905581549092508291908190611e3190849061371d565b90915550611e4190503382612864565b611e4961296f565b6040517fa61c713a00000000000000000000000000000000000000000000000000000000815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611ed157600080fd5b505af1158015611ee5573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160155550565b60008054600003611f5657506001600160a01b031660009081526005602052604090205490565b600080546001600160a01b038416825260026020908152604080842054600483528185205460039093529320549192670de0b6b3a7640000929091611f9a91612b6b565b611fa3866111ce565b611fad91906136cf565b611fb79190613730565b611fc19190613730565b611fcb91906136e2565b6001600160a01b038316600090815260056020526040902054610aa9919061371d565b600b8181548110611ffe57600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601260205260408120548190808203612047576000809250925050612232565b6001600160a01b0385166000908152601160205260408120859161206c6001856136cf565b81526020019081526020016000206000015411612109576001600160a01b0385166000908152601160205260408120906120a76001846136cf565b81526020019081526020016000206001015460116000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846120ed91906136cf565b8152602001908152602001600020600001549250925050612232565b6001600160a01b0385166000908152601160209081526040808320838052909152902054841015612141576000809250925050612232565b60008061214f6001846136cf565b90505b81811115612201576000600261216884846136cf565b61217291906136e2565b61217c90836136cf565b6001600160a01b03891660009081526011602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908890036121db576020810151905190965094506122329350505050565b80518811156121ec578193506121fa565b6121f76001836136cf565b92505b5050612152565b506001600160a01b038616600090815260116020908152604080832093835292905220600181015490549093509150505b9250929050565b60155460011461224857600080fd5b6002601555612255613253565b816009600082825461226791906136cf565b9091555050336000908152600a60205260408120805484929061228b9084906136cf565b909155506122bc90507f00000000000000000000000000000000000000000000000000000000000000003384612700565b801561238f573360009081526008602052604090205481146122dd57600080fd5b3360008181526008602052604080822091909155517f411b1f770000000000000000000000000000000000000000000000000000000081526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561237257600080fd5b505af1158015612386573d6000803e3d6000fd5b505050506123a1565b50336000908152600860205260409020545b3360009081526001602052604081205481549091829181906123c49084906136cf565b9091555050336000908152600a602090815260408083205460019092528220819055815490925082919081906123fb90849061371d565b90915550503360008181526001602052604090205461241a9190612864565b61242261296f565b6040517fea94ee4400000000000000000000000000000000000000000000000000000000815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156124aa57600080fd5b505af11580156124be573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611f1d565b60008183116125095781611246565b5090919050565b6001600160a01b038316600090815260046020908152604080832054600590925282205460105483929190830361254a57925090506126f8565b6001600160a01b03871660009081526002602052604081205490036125755792504291506126f89050565b6000612580836111fe565b9050600061259c600160105461259691906136cf565b89612b6b565b9050801561267557815b6125b16001836136cf565b8111612673576000818152600f60209081526040918290208251808401909352805483526001015490820181905215612660576000600f816125f485600161371d565b815260200190815260200160002060405180604001604052908160008201548152602001600182015481525050905060008061263f8e8460000151866000015187602001518d6132eb565b909250905061264e828961371d565b975061265b8e8983612b7a565b975050505b508061266b81613747565b9150506125a6565b505b86156126ef576000818152600f602090815260409182902082518084019093528054835260010154908201819052156126ed5760006126ce8b6126b78d6111ce565b84516126c3908a6124fa565b85602001518a6132eb565b5090506126db818661371d565b94506126e88b8642612b7a565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161271757600080fd5b6040516001600160a01b0383811660248301526044820183905260009182918616907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516127e891906137ba565b6000604051808303816000865af19150503d8060008114612825576040519150601f19603f3d011682016040523d82523d6000602084013e61282a565b606091505b5091509150818015612854575080511580612854575080806020019051810190612854919061377f565b61285d57600080fd5b5050505050565b6001600160a01b0382166000908152600e6020526040902054429080158015906128c257506001600160a01b0384166000908152600d6020526040812083916128ae6001856136cf565b815260200190815260200160002060000154145b15612905576001600160a01b0384166000908152600d6020526040812084916128ec6001856136cf565b8152602081019190915260400160002060010155612969565b60408051808201825283815260208082018681526001600160a01b0388166000908152600d835284812086825290925292902090518155905160019182015561294f90829061371d565b6001600160a01b0385166000908152600e60205260409020555b50505050565b6010544281158015906129a1575080600f600061298d6001866136cf565b815260200190815260200160002060000154145b156129d257600054600f60006001856129ba91906136cf565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600f9052929020905181559051600191820155612a0b90839061371d565b6010555050565b6001600160a01b0382166000908152600460209081526040808320546005909252822054601054839291908303612a4c5792509050612232565b6001600160a01b0386166000908152600260205260408120549003612a775792504291506122329050565b6000612a82836111fe565b90506000612a9e6001601054612a9891906136cf565b88612b6b565b9050815b81811015612b5c576000818152600f60209081526040918290208251808401909352805483526001015490820181905215612b53576000600f81612ae785600161371d565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080612b328d8460000151866000015187602001518d6132eb565b9092509050612b41828961371d565b9750612b4e8d8983612b7a565b975050505b50600101612aa2565b50919792965091945050505050565b60008183106125095781611246565b6001600160a01b0383166000908152601260205260409020548015801590612bd657506001600160a01b03841660009081526011602052604081208391612bc26001856136cf565b815260200190815260200160002060000154145b15612c00576001600160a01b038416600090815260116020526040812084916128ec6001856136cf565b60408051808201825283815260208082018681526001600160a01b038816600090815260118352848120868252909252929020905181559051600191820155612c4a90829061371d565b6001600160a01b03851660009081526012602052604090205550505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612ccb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cef91906137e9565b909250905081151580612d025750600081115b1561312957600082601354612d17919061371d565b9050600082601454612d29919061371d565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612d8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612db1919061380d565b6040517f99bcc0520000000000000000000000000000000000000000000000000000000081526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612e38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e5c91906137a1565b84118015612e7657506000612e7462093a80866136e2565b115b15612f4b576000601355612eab827f0000000000000000000000000000000000000000000000000000000000000000866133a6565b6040517fb66503cf0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612f2e57600080fd5b505af1158015612f42573d6000803e3d6000fd5b50505050612f51565b60138490555b6040517f99bcc0520000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612fd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ff491906137a1565b8311801561300e5750600061300c62093a80856136e2565b115b156130e3576000601455613043817f0000000000000000000000000000000000000000000000000000000000000000856133a6565b6040517fb66503cf0000000000000000000000000000000000000000000000000000000081526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b1580156130c657600080fd5b505af11580156130da573d6000803e3d6000fd5b505050506130e9565b60148390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b1161314457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905291516000928392908816916131d691906137ba565b6000604051808303816000865af19150503d8060008114613213576040519150601f19603f3d011682016040523d82523d6000602084013e613218565b606091505b5091509150818015613242575080511580613242575080806020019051810190613242919061377f565b61324b57600080fd5b505050505050565b600b5460005b81811015610d65576000600b828154811061327657613276613671565b6000918252602090912001546001600160a01b031690506132b9817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001612510565b6001600160a01b0390921660009081526005602090815260408083206004909252909120929092559055600101613259565b60008060006132fa87856124fa565b6001600160a01b0389166000908152600260205260409020549091508590670de0b6b3a76400009061334d61332f8a896124fa565b6001600160a01b038d16600090815260036020526040902054612b6b565b6001600160a01b038c16600090815260036020526040902054613371908690612b6b565b61337b91906136cf565b6133859190613730565b61338f9190613730565b61339991906136e2565b9890975095505050505050565b6000836001600160a01b03163b116133bd57600080fd5b6040516001600160a01b0383811660248301526044820183905260009182918616907f095ea7b3000000000000000000000000000000000000000000000000000000009060640161275f565b6001600160a01b0381168114611b6857600080fd5b803561342981613409565b919050565b6000806040838503121561344157600080fd5b823561344c81613409565b946020939093013593505050565b60008060006060848603121561346f57600080fd5b83359250602084013561348181613409565b9150604084013561349181613409565b809150509250925092565b600080604083850312156134af57600080fd5b82356134ba81613409565b915060208301356134ca81613409565b809150509250929050565b6000602082840312156134e757600080fd5b813561124681613409565b60006020828403121561350457600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806040838503121561354d57600080fd5b823561355881613409565b915060208381013567ffffffffffffffff8082111561357657600080fd5b818601915086601f83011261358a57600080fd5b81358181111561359c5761359c61350b565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f830116810181811085821117156135df576135df61350b565b6040529182528482019250838101850191898311156135fd57600080fd5b938501935b82851015613622576136138561341e565b84529385019392850192613602565b8096505050505050509250929050565b6000806040838503121561364557600080fd5b50508035926020909101359150565b60006020828403121561366657600080fd5b815161124681613409565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610aa957610aa96136a0565b600082613718577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820180821115610aa957610aa96136a0565b8082028115828204841417610aa957610aa96136a0565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613778576137786136a0565b5060010190565b60006020828403121561379157600080fd5b8151801515811461124657600080fd5b6000602082840312156137b357600080fd5b5051919050565b6000825160005b818110156137db57602081860181015185830152016137c1565b506000920191825250919050565b600080604083850312156137fc57600080fd5b505080516020909101519092909150565b6000806040838503121561382057600080fd5b825161382b81613409565b60208401519092506134ca8161340956fea2646970667358221220e682cd7c69c2506de8bd875be51ecaaff92d0083743a51bf135ca21199bedffa64736f6c63430008160033a26469706673582212200aaaf9cf7c6a31dd91e6c96d5da6da24ef3adb6b2b7c9243438efc8035bb781a64736f6c63430008160033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.