Source Code
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 3 internal transactions
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 9518767 | 503 days ago | Contract Creation | 0 FRAX | |||
| 2408076 | 667 days ago | Contract Creation | 0 FRAX | |||
| 1999674 | 677 days ago | Contract Creation | 0 FRAX |
Cross-Chain Transactions
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
Contract ABI
API[{"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
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in FRAX
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.