Source Code
Overview
ETH Balance
ETH Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 3596228 | 654 days ago | 0 ETH | ||||
| 3596105 | 654 days ago | 0 ETH | ||||
| 3595856 | 654 days ago | 0 ETH | ||||
| 3595464 | 654 days ago | 0 ETH | ||||
| 3595464 | 654 days ago | 0 ETH | ||||
| 3595464 | 654 days ago | 0 ETH | ||||
| 3595464 | 654 days ago | 0 ETH | ||||
| 3595362 | 654 days ago | 0 ETH | ||||
| 3595357 | 654 days ago | 0 ETH | ||||
| 3595349 | 654 days ago | 0 ETH | ||||
| 3595198 | 654 days ago | 0 ETH | ||||
| 3595085 | 654 days ago | 0 ETH | ||||
| 3595066 | 654 days ago | 0 ETH | ||||
| 3594948 | 654 days ago | 0 ETH | ||||
| 3594771 | 654 days ago | 0 ETH | ||||
| 3594747 | 654 days ago | 0 ETH | ||||
| 3594391 | 654 days ago | 0 ETH | ||||
| 3594351 | 654 days ago | 0 ETH | ||||
| 3594338 | 654 days ago | 0 ETH | ||||
| 3594338 | 654 days ago | 0 ETH | ||||
| 3594338 | 654 days ago | 0 ETH | ||||
| 3594338 | 654 days ago | 0 ETH | ||||
| 3594338 | 654 days ago | 0 ETH | ||||
| 3594283 | 654 days ago | 0 ETH | ||||
| 3594247 | 654 days ago | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Gauge
Compiler Version
v0.8.22+commit.4fc1097e
Optimization Enabled:
Yes with 800 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol";
import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import "./interfaces/IFeeDistributor.sol";
import "./interfaces/IERC20.sol";
import "./interfaces/IPair.sol";
import "./interfaces/IVoter.sol";
import "./interfaces/IVotingEscrow.sol";
import "./interfaces/IGauge.sol";
/// @notice Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens
contract Gauge is IGauge, Initializable {
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;
address public stake; /// @notice the LP token that needs to be staked for rewards
address public ve; /// @notice the ve token used for gauges
address public feeDistributor;
address public voter;
EnumerableSetUpgradeable.AddressSet rewards;
address[] public initialRewards; /// @notice emissionsToken and xToken as initial reward tokens
uint256 public totalSupply;
uint256 internal constant DURATION = 7 days; /// @notice rewards are released over 7 days
uint256 internal constant PRECISION = 10 ** 18;
uint256 internal _unlocked;
bool isForPair;
mapping(address => EnumerableSetUpgradeable.AddressSet) registeredRewards; /// @notice rewards user wants to receive
mapping(address => uint256) public derivedSupplyPerReward;
mapping(address => uint256) public tokenIds;
mapping(address => uint256) public derivedBalances;
mapping(address => uint256) public balanceOf;
mapping(address => Reward) internal _rewardData;
mapping(address => mapping(address => uint256))
public userRewardPerTokenStored;
mapping(address => mapping(address => uint256)) public storedRewardsPerUser;
event Deposit(address indexed from, uint256 tokenId, uint256 amount);
event Withdraw(address indexed from, uint256 tokenId, uint256 amount);
event NotifyReward(
address indexed from,
address indexed reward,
uint256 amount
);
event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);
event ClaimRewards(
address indexed from,
address indexed reward,
uint256 amount
);
constructor() {
_disableInitializers();
}
function initialize(
address _stake,
address _feeDist,
address _ve,
address _voter,
bool _forPair,
address[] calldata _initialRewards
) external initializer {
stake = _stake;
feeDistributor = _feeDist;
ve = _ve;
voter = _voter;
isForPair = _forPair;
initialRewards = _initialRewards;
for (uint256 i; i < _initialRewards.length; i++) {
rewards.add(_initialRewards[i]);
}
_unlocked = 1;
}
/// @notice simple re-entrancy check
modifier lock() {
require(_unlocked == 1);
_unlocked = 2;
_;
_unlocked = 1;
}
modifier updateReward(address account) {
address[] memory _rewards = registeredRewards[account].values();
uint256 len = _rewards.length;
for (uint256 i; i < len; ) {
address token = _rewards[i];
_rewardData[token].rewardPerTokenStored = rewardPerToken(token);
_rewardData[token].lastUpdateTime = lastTimeRewardApplicable(token);
if (account != address(0)) {
storedRewardsPerUser[account][token] = _earned(token, account);
userRewardPerTokenStored[account][token] = _rewardData[token]
.rewardPerTokenStored;
}
unchecked {
i++;
}
}
_;
}
function claimFees()
external
lock
returns (uint256 claimed0, uint256 claimed1)
{
return _claimFees();
}
/// @notice claim fees from the V1 pair
function _claimFees()
internal
returns (uint256 claimed0, uint256 claimed1)
{
if (!isForPair) {
return (0, 0);
}
(claimed0, claimed1) = IPair(stake).claimFees();
emit ClaimFees(msg.sender, claimed0, claimed1);
}
function rewardsList() external view returns (address[] memory _rewards) {
_rewards = rewards.values();
}
function rewardsListLength() external view returns (uint256 _length) {
_length = rewards.length();
}
/// @notice returns rewards a user has registered to receive
function getRegisteredRewards(
address user
) external view returns (address[] memory _rewards) {
_rewards = registeredRewards[user].values();
}
/// @notice returns the last time the reward was modified or periodFinish if the reward has ended
function lastTimeRewardApplicable(
address token
) public view returns (uint256) {
return
MathUpgradeable.min(
block.timestamp,
_rewardData[token].periodFinish
);
}
function rewardData(
address token
) external view override returns (Reward memory data) {
data = _rewardData[token];
}
/**
* @dev earned was split in two so we don't need to do an extra SLOAD to check if user is registered
* @dev other functions that call the internal _earned() already checks registeredRewards beforehand
*/
function earned(
address token,
address account
) external view returns (uint256 _reward) {
if (registeredRewards[account].contains(token)) {
_reward = _earned(token, account);
} else {
_reward = storedRewardsPerUser[account][token];
}
}
function _earned(
address token,
address account
) internal view returns (uint256 _reward) {
_reward =
((derivedBalances[account] *
(rewardPerToken(token) -
userRewardPerTokenStored[account][token])) / PRECISION) +
storedRewardsPerUser[account][token];
}
function getReward(
address account,
address[] calldata tokens
) public updateReward(account) lock {
require(msg.sender == account || msg.sender == voter);
_unlocked = 1;
/// @notice call distribute in case the emissions have not been sent from the voter yet
IVoter(voter).distribute(address(this));
_unlocked = 2;
for (uint256 i; i < tokens.length; ) {
uint256 _reward = storedRewardsPerUser[account][tokens[i]];
if (_reward > 0) {
storedRewardsPerUser[account][tokens[i]] = 0;
_safeTransfer(tokens[i], account, _reward);
emit ClaimRewards(account, tokens[i], _reward);
}
unchecked {
i++;
}
}
address[] memory _rewards = registeredRewards[account].values();
uint256 len = _rewards.length;
uint256 _derivedBalanceBefore = derivedBalances[account];
uint256 _derivedBalanceAfter = derivedBalance(account);
derivedBalances[account] = _derivedBalanceAfter;
for (uint256 i; i < len; ) {
derivedSupplyPerReward[_rewards[i]] -= _derivedBalanceBefore;
derivedSupplyPerReward[_rewards[i]] += _derivedBalanceAfter;
unchecked {
i++;
}
}
}
function rewardPerToken(address token) public view returns (uint256) {
if (derivedSupplyPerReward[token] == 0) {
return _rewardData[token].rewardPerTokenStored;
}
return
_rewardData[token].rewardPerTokenStored +
((lastTimeRewardApplicable(token) -
_rewardData[token].lastUpdateTime) *
_rewardData[token].rewardRate *
PRECISION) /
derivedSupplyPerReward[token];
}
/// @notice return current balance of an account
function derivedBalance(address account) public view returns (uint256) {
return balanceOf[account];
}
function depositAll(uint256 tokenId) external {
deposit(IERC20(stake).balanceOf(msg.sender), tokenId, initialRewards);
}
/**
* @notice deposit without manually specifying requestedRewards
*/
function deposit(uint256 amount, uint256 tokenId) external {
deposit(amount, tokenId, initialRewards);
}
/**
* @notice stake tokens
* @param requestedRewards array of reward tokens user wants to receive
*/
function deposit(
uint256 amount,
uint256 tokenId,
address[] memory requestedRewards
) public updateReward(msg.sender) lock {
require(amount > 0);
_safeTransferFrom(stake, msg.sender, address(this), amount);
totalSupply += amount;
balanceOf[msg.sender] += amount;
if (tokenId > 0) {
require(IVotingEscrow(ve).ownerOf(tokenId) == msg.sender, "!owner");
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];
}
uint256 _derivedBalanceBefore = derivedBalances[msg.sender];
uint256 _derivedBalanceAfter = derivedBalance(msg.sender);
derivedBalances[msg.sender] = _derivedBalanceAfter;
/// @dev update all derivedSupplyPerReward for user
address[] memory _stakes = registeredRewards[msg.sender].values();
uint256 len = _stakes.length;
for (uint256 i; i < len; ) {
derivedSupplyPerReward[_stakes[i]] -= _derivedBalanceBefore;
derivedSupplyPerReward[_stakes[i]] += _derivedBalanceAfter;
unchecked {
i++;
}
}
for (uint256 i; i < requestedRewards.length; ) {
bool newlyJoined = registeredRewards[msg.sender].add(
requestedRewards[i]
);
/// @dev only update if the user has not joined the pool yet
if (newlyJoined) {
_rewardData[requestedRewards[i]]
.rewardPerTokenStored = rewardPerToken(requestedRewards[i]);
_rewardData[requestedRewards[i]]
.lastUpdateTime = lastTimeRewardApplicable(
requestedRewards[i]
);
userRewardPerTokenStored[msg.sender][
requestedRewards[i]
] = _rewardData[requestedRewards[i]].rewardPerTokenStored;
derivedSupplyPerReward[
requestedRewards[i]
] += _derivedBalanceAfter;
}
unchecked {
i++;
}
}
IVoter(voter).emitDeposit(tokenId, msg.sender, amount);
emit Deposit(msg.sender, tokenId, amount);
}
/// @notice withdraws all fungible LP tokens from V1 gauges
function withdrawAll() external {
withdraw(balanceOf[msg.sender]);
}
function withdraw(uint256 amount) public {
uint256 tokenId;
if (amount == balanceOf[msg.sender]) {
tokenId = tokenIds[msg.sender];
}
withdrawToken(amount, tokenId);
}
function withdrawToken(
uint256 amount,
uint256 tokenId
) internal updateReward(msg.sender) lock {
require(amount > 0, "Can't withdraw 0!");
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];
}
address[] memory _rewards = registeredRewards[msg.sender].values();
uint256 len = _rewards.length;
uint256 _derivedBalanceBefore = derivedBalances[msg.sender];
uint256 _derivedBalanceAfter = derivedBalance(msg.sender);
derivedBalances[msg.sender] = _derivedBalanceAfter;
for (uint256 i; i < len; ) {
derivedSupplyPerReward[_rewards[i]] -= _derivedBalanceBefore;
derivedSupplyPerReward[_rewards[i]] += _derivedBalanceAfter;
unchecked {
i++;
}
}
IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);
emit Withdraw(msg.sender, tokenId, amount);
}
/**
* @notice join to receive newly notified rewards
* @notice users will not receive new rewards that they haven't already opted into
*/
function joinRewardPool(address token) external updateReward(msg.sender) {
address[] memory _rewards = registeredRewards[msg.sender].values();
uint256 len = _rewards.length;
uint256 _derivedBalanceBefore = derivedBalances[msg.sender];
uint256 _derivedBalanceAfter = derivedBalance(msg.sender);
derivedBalances[msg.sender] = _derivedBalanceAfter;
for (uint256 i; i < len; ) {
// update user's derivedSupplyPerReward
derivedSupplyPerReward[_rewards[i]] -= _derivedBalanceBefore;
derivedSupplyPerReward[_rewards[i]] += _derivedBalanceAfter;
unchecked {
i++;
}
}
bool newlyJoined = registeredRewards[msg.sender].add(token); // if it already exists it won't get added
if (newlyJoined) {
_rewardData[token].rewardPerTokenStored = rewardPerToken(token);
_rewardData[token].lastUpdateTime = lastTimeRewardApplicable(token);
userRewardPerTokenStored[msg.sender][token] = _rewardData[token]
.rewardPerTokenStored;
derivedSupplyPerReward[token] += _derivedBalanceAfter;
}
}
/// @notice exit reward pool to stop receiving a given reward
function exitRewardPool(address token) external updateReward(msg.sender) {
address[] memory _rewards = registeredRewards[msg.sender].values();
uint256 len = _rewards.length;
uint256 _derivedBalanceBefore = derivedBalances[msg.sender];
uint256 _derivedBalanceAfter = derivedBalance(msg.sender);
derivedBalances[msg.sender] = _derivedBalanceAfter;
for (uint256 i; i < len; ) {
derivedSupplyPerReward[_rewards[i]] -= _derivedBalanceBefore;
derivedSupplyPerReward[_rewards[i]] += _derivedBalanceAfter;
unchecked {
i++;
}
}
bool newlyRemoved = registeredRewards[msg.sender].remove(token);
if (newlyRemoved) {
derivedSupplyPerReward[token] -= _derivedBalanceAfter;
}
}
function left(address token) public view returns (uint256) {
if (block.timestamp >= _rewardData[token].periodFinish) return 0;
uint256 _remaining = _rewardData[token].periodFinish - block.timestamp;
return _remaining * _rewardData[token].rewardRate;
}
/**
* @notice amount must be greater than left() for the token, this is to prevent greifing attacks
* @notice notifying rewards is completely permissionless
* @notice if nobody registers for a newly added reward for the period it will remain in the contract indefinitely
*/
function notifyRewardAmount(
address token,
uint256 amount
) external updateReward(address(0)) lock {
require(token != stake);
require(amount > 0);
_claimFees();
_rewardData[token].rewardPerTokenStored = rewardPerToken(token);
rewards.add(token);
// Check actual amount transferred for compatibility with fee on transfer tokens.
uint256 balanceBefore = IERC20(token).balanceOf(address(this));
_safeTransferFrom(token, msg.sender, address(this), amount);
uint256 balanceAfter = IERC20(token).balanceOf(address(this));
amount = balanceAfter - balanceBefore;
if (block.timestamp >= _rewardData[token].periodFinish) {
_rewardData[token].rewardRate = amount / DURATION;
} else {
uint256 remaining = _rewardData[token].periodFinish -
block.timestamp;
uint256 _left = remaining * _rewardData[token].rewardRate;
require(amount > _left);
_rewardData[token].rewardRate = (amount + _left) / DURATION;
}
_rewardData[token].lastUpdateTime = block.timestamp;
_rewardData[token].periodFinish = block.timestamp + DURATION;
uint256 balance = IERC20(token).balanceOf(address(this));
require(
_rewardData[token].rewardRate <= balance / DURATION,
"Provided reward too high"
);
emit NotifyReward(msg.sender, token, amount);
}
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))));
}
}// 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 MathUpgradeable {
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
// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```solidity
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSetUpgradeable {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/Address.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IERC20 {
function totalSupply() external view returns (uint256);
function transfer(
address recipient,
uint256 amount
) external returns (bool);
function decimals() external view returns (uint8);
function symbol() external view returns (string memory);
function balanceOf(address) external view returns (uint256);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
function allowance(
address owner,
address spender
) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
function name() external view returns (string memory);
function burn(uint256 amount) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IFeeDistributor {
function initialize(address _voter, address _pairFees) external;
function _deposit(uint256 amount, uint256 tokenId) external;
function _withdraw(uint256 amount, uint256 tokenId) external;
function getRewardForOwner(
uint256 tokenId,
address[] memory tokens
) external;
function notifyRewardAmount(address token, uint256 amount) external;
function getRewardTokens() external view returns (address[] memory);
function earned(
address token,
uint256 tokenId
) external view returns (uint256 reward);
function incentivize(address token, uint256 amount) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IGauge {
function initialize(
address _stake,
address _feeDist,
address _ve,
address _voter,
bool _forPair,
address[] memory _initialRewards
) external;
function getReward(address account, address[] calldata tokens) external;
function claimFees() external returns (uint256 claimed0, uint256 claimed1);
function left(address token) external view returns (uint256);
function rewardsListLength() external view returns (uint256);
function rewardsList() external view returns (address[] memory);
function earned(
address token,
address account
) external view returns (uint256);
function balanceOf(address) external view returns (uint256);
function derivedBalances(address) external view returns (uint256);
function notifyRewardAmount(address token, uint256 amount) external;
struct Reward {
uint256 rewardRate;
uint256 periodFinish;
uint256 lastUpdateTime;
uint256 rewardPerTokenStored;
}
function rewardData(address token) external view returns (Reward memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13 || =0.7.6;
interface IPair {
function initialize(
address _factory,
address _token0,
address _token1,
bool _stable,
address _voter
) external;
function metadata()
external
view
returns (
uint256 dec0,
uint256 dec1,
uint256 r0,
uint256 r1,
bool st,
address t0,
address t1
);
function claimFees() external returns (uint256, uint256);
function tokens() external view returns (address, address);
function transferFrom(
address src,
address dst,
uint256 amount
) external returns (bool);
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function swap(
uint256 amount0Out,
uint256 amount1Out,
address to,
bytes calldata data
) external;
function burn(
address to
) external returns (uint256 amount0, uint256 amount1);
function mint(address to) external returns (uint256 liquidity);
function getReserves()
external
view
returns (
uint256 _reserve0,
uint256 _reserve1,
uint256 _blockTimestampLast
);
function getAmountOut(
uint256 amountIn,
address tokenIn
) external view returns (uint256);
function symbol() external view returns (string memory);
function fees() external view returns (address);
function setActiveGauge(bool isActive) external;
function setFeeSplit() external;
function feeSplit() external view returns (uint8 _feeSplit);
function stable() external view returns (bool stable);
function current(
address tokenIn,
uint256 amountIn
) external view returns (uint256 amountOut);
}// SPDX-License-Identifier: MIT
pragma solidity =0.7.6 || ^0.8.13;
pragma abicoder v2;
interface IVoter {
function _ve() external view returns (address);
function governor() external view returns (address);
function emergencyCouncil() external view returns (address);
function attachTokenToGauge(uint256 _tokenId, address account) external;
function detachTokenFromGauge(uint256 _tokenId, address account) external;
function emitDeposit(
uint256 _tokenId,
address account,
uint256 amount
) external;
function emitWithdraw(
uint256 _tokenId,
address account,
uint256 amount
) external;
function isWhitelisted(address token) external view returns (bool);
function notifyRewardAmount(uint256 amount) external;
function distribute(address _gauge) external;
function gauges(address pool) external view returns (address);
function feeDistributors(address gauge) external view returns (address);
function gaugefactory() external view returns (address);
function feeDistributorFactory() external view returns (address);
function minter() external view returns (address);
function factory() external view returns (address);
function length() external view returns (uint256);
function pools(uint256) external view returns (address);
function isAlive(address) external view returns (bool);
function setXRatio(uint256 _xRatio) external;
function setPoolXRatio(
address[] calldata _gauges,
uint256[] calldata _xRaRatios
) external;
function resetGaugeXRatio(address[] calldata _gauges) external;
function whitelist(address _token) external;
function forbid(address _token, bool _status) external;
function whitelistOperator() external view returns (address);
function gaugeXRatio(address gauge) external view returns (uint256);
function isGauge(address gauge) external view returns (bool);
function killGauge(address _gauge) external;
function reviveGauge(address _gauge) external;
function stale(uint256 _tokenID) external view returns (bool);
function poolForGauge(address gauge) external view returns (address pool);
function recoverFees(
address[] calldata fees,
address[][] calldata tokens
) external;
function designateStale(uint256 _tokenId, bool _status) external;
function base() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity =0.7.6 || ^0.8.13;
pragma abicoder v2;
interface IVotingEscrow {
struct Point {
int128 bias;
int128 slope; // # -dweight / dt
uint256 ts;
uint256 blk; // block
}
struct LockedBalance {
int128 amount;
uint256 end;
}
function emissionsToken() external view returns (address);
function team() external returns (address);
function epoch() external view returns (uint256);
function pointHistory(uint256 loc) external view returns (Point memory);
function userPointHistory(
uint256 tokenId,
uint256 loc
) external view returns (Point memory);
function userPointEpoch(uint256 tokenId) external view returns (uint256);
function ownerOf(uint256) external view returns (address);
function isApprovedOrOwner(address, uint256) external view returns (bool);
function transferFrom(address, address, uint256) external;
function voting(uint256 tokenId) external;
function abstain(uint256 tokenId) external;
function attach(uint256 tokenId) external;
function detach(uint256 tokenId) external;
function checkpoint() external;
function depositFor(uint256 tokenId, uint256 value) external;
function createLockFor(
uint256,
uint256,
address
) external returns (uint256);
function balanceOfNFT(uint256) external view returns (uint256);
function balanceOfNFTAt(uint256, uint256) external view returns (uint256);
function totalSupply() external view returns (uint256);
function locked__end(uint256) external view returns (uint256);
function balanceOf(address) external view returns (uint256);
function tokenOfOwnerByIndex(
address,
uint256
) external view returns (uint256);
function increaseUnlockTime(uint256 tokenID, uint256 duration) external;
function locked(
uint256 tokenID
) external view returns (uint256 amount, uint256 unlockTime);
function increaseAmount(uint256 _tokenId, uint256 _value) external;
function isDelegate(
address _operator,
uint256 _tokenId
) external view returns (bool);
}{
"optimizer": {
"enabled": true,
"runs": 800
},
"evmVersion": "paris",
"viaIR": true,
"metadata": {
"bytecodeHash": "none"
},
"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":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"claimed0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"claimed1","type":"uint256"}],"name":"ClaimFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"reward","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ClaimRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"reward","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"NotifyReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimFees","outputs":[{"internalType":"uint256","name":"claimed0","type":"uint256"},{"internalType":"uint256","name":"claimed1","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address[]","name":"requestedRewards","type":"address[]"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"depositAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"derivedBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"derivedBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"derivedSupplyPerReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"_reward","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"exitRewardPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeDistributor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getRegisteredRewards","outputs":[{"internalType":"address[]","name":"_rewards","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"getReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"initialRewards","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_stake","type":"address"},{"internalType":"address","name":"_feeDist","type":"address"},{"internalType":"address","name":"_ve","type":"address"},{"internalType":"address","name":"_voter","type":"address"},{"internalType":"bool","name":"_forPair","type":"bool"},{"internalType":"address[]","name":"_initialRewards","type":"address[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"joinRewardPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"lastTimeRewardApplicable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"left","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"rewardData","outputs":[{"components":[{"internalType":"uint256","name":"rewardRate","type":"uint256"},{"internalType":"uint256","name":"periodFinish","type":"uint256"},{"internalType":"uint256","name":"lastUpdateTime","type":"uint256"},{"internalType":"uint256","name":"rewardPerTokenStored","type":"uint256"}],"internalType":"struct IGauge.Reward","name":"data","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"rewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsList","outputs":[{"internalType":"address[]","name":"_rewards","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsListLength","outputs":[{"internalType":"uint256","name":"_length","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stake","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"storedRewardsPerUser","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"userRewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60808060405234620000c6576000549060ff8260081c1662000074575060ff8082160362000038575b6040516133789081620000cc8239f35b60ff90811916176000557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160ff8152a13862000028565b62461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b6064820152608490fd5b600080fdfe608080604052600436101561001357600080fd5b600090813560e01c9081630d43e8ad146127885750806318160ddd1461276a5780631f85071614612743578063211dc32d146126bb5780632e1a7d4d1461269e57806331279d3d1461233957806336925259146122e95780633a4b66f1146122c05780633ca068b61461227057806346c96aac1461224957806348e5d9f8146121ab578063638634ee1461218757806363fb415b1461214f57806369af57f014611f1057806370a0823114611349578063736fc25514611e9a5780638003b61414611e14578063853828b614611deb578063907d2aaa14611db357806399bcc05214611d8f578063a933d5b914611d33578063b66503cf1461199f578063c6f678bd146113bc578063d294f09314611381578063d35e254414611349578063dee2c33914611012578063e2bbb15814610b08578063e688639614610aea578063f0ff49081461085f578063f122977714610833578063f8e8e99f146101bb5763fc97a3031461018157600080fd5b346101b85760203660031901126101b85760406020916001600160a01b036101a76127ad565b168152600c83522054604051908152f35b80fd5b50346101b85760603660031901126101b857602480359067ffffffffffffffff906044358281116107005736602382011215610700578060040135928311610820578260051b906040519361021360208401866128c3565b84528260208501928201019036821161081c578301915b8183106107f757505050338452600a602052604084206040518082602082945493848152019088526020882092885b8181106107de57505061026e925003826128c3565b80519033151590865b838110610730575050505060016008540361072c5760026008558260043515610700576102b885546004359030906001600160a01b03339160101c1661311c565b6102c6600435600754612d12565b600755338552600e602052604085206102e26004358254612d12565b905515610717578060206001600160a01b0360015416604051928380926331a9108f60e11b82528860048301525afa90811561070c5785916106c6575b506001600160a01b03339116036106995750338352600c6020528160408420805415610635575b5050338352600c60205281604084205403610631575b338352600d602052604083205490600e602052604084205491600d602052826040862055600a60205260408520906040518083602082955493848152019089526020892092895b8181106106185750506103b8925003836128c3565b815191865b8381106105b85750505050835b815181101561050657600190338652600a6020526103ff604087206001600160a01b036103f78487612cb7565b511690613316565b61040a575b016103ca565b6104266001600160a01b0361041f8386612cb7565b5116612e25565b6001600160a01b036104388386612cb7565b51168752600f806020526003918260408a2001556104686001600160a01b036104618588612cb7565b5116612d1f565b6001600160a01b0361047a8588612cb7565b5116895281602052600260408a2001556001600160a01b0361049c8487612cb7565b511688526020526040872001543387526010602052604087206001600160a01b036104c78487612cb7565b51166000526020526040600020556001600160a01b036104e78285612cb7565b51168652600b602052604086206104ff858254612d12565b9055610404565b505050816001600160a01b0360035416803b156105a95760405163530e389d60e11b815260048082018590523360248301523560448201529082908290606490829084905af180156105ad57610595575b505060405190815260043560208201527f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a1560403392a2600160085580f35b61059e9061287d565b6105a9578138610557565b5080fd5b6040513d84823e3d90fd5b806001600160a01b036105cd60019385612cb7565b51168952600b8060205260408a206105e6868254612cef565b90556001600160a01b036105fa8386612cb7565b51168a5260205260408920610610888254612d12565b9055016103bd565b84548352600194850194879450602090930192016103a3565b8280fd5b55826001600160a01b0360035416803b156105a95760405163698473e360e01b8152600481018590523360248201529082908290604490829084905af180156105ad57610685575b839150610346565b61068e9061287d565b61063157823861067d565b60649060066040519162461bcd60e51b8352602060048401528201526510b7bbb732b960d11b6044820152fd5b90506020813d602011610704575b816106e1602093836128c3565b8101031261070057516001600160a01b0381168103610700573861031f565b8480fd5b3d91506106d4565b6040513d87823e3d90fd5b50338352600c6020526040832054915061035c565b8380fd5b806001600160a01b0361074560019385612cb7565b5116604061075282612e25565b828c52600f90816020528c6003938491200155868c6002604061077487612d1f565b928781528560205220015561078d575b50505001610277565b6107973384612ef8565b338d52601160205260408d2084600052602052604060002055828c5260205260408b20015490338b52601060205260408b2090600052602052604060002055388080610784565b8454835260019485019486945060209093019201610259565b82356001600160a01b03811681036108175781526020928301920161022a565b600080fd5b8680fd5b50634e487b7160e01b8452604160045283fd5b50346101b85760203660031901126101b85760206108576108526127ad565b612e25565b604051908152f35b50346101b8576020806003193601126105a95761087a6127ad565b338352600a825260408320604051808285829454938481520190875285872092875b87828210610ad4575050506108b3925003826128c3565b80519033151590855b838110610a2f5750505050338352600a82526040832091604051808483829654938481520190875283872092875b85828210610a1957505050610901925003846128c3565b8251338552600d82526040852054600e8352604086205494600d8452856040882055865b8381106109c15750505050338452600a81526040842061094f6001600160a01b0384168092613316565b610957578480f35b600361097b84610968600b96612e25565b848952600f86528360408a200155612d1f565b828752600f845260408720906002820155015433865260108352604086208260005283526040600020558452526109b760408320918254612d12565b9055388080808480f35b6001906001600160a01b03806109d78386612cb7565b51168a52600b9081885260408b206109f0878254612cef565b90556109fc8386612cb7565b51168a52865260408920610a11898254612d12565b905501610925565b85548452600195860195899550930192016108ea565b806001600160a01b03610a4460019385612cb7565b5116610a4f81612e25565b818a5289868a60026040600f9485845260039687838320015585610a7289612d1f565b9489835252200155610a88575b505050016108bc565b610a923384612ef8565b338c5260118b5260408c20846000528b52604060002055828b52895260408a20015490338a526010895260408a20906000528852604060002055388080610a7f565b855484526001958601958795509301920161089c565b50346101b857806003193601126101b8576020600454604051908152f35b50346101b85760403660031901126101b857602435610b25612dac565b338352600a602052604083206040518082602082945493848152019087526020872092875b818110610ff9575050610b5f925003826128c3565b80519033151590855b838110610f4d5750505050600160085403610631576002600855816004351561072c57610ba984546004359030906001600160a01b03339160101c1661311c565b610bb7600435600754612d12565b600755338452600e60205260408420610bd36004358254612d12565b905515610f3957602460206001600160a01b0360015416604051928380926331a9108f60e11b82528760048301525afa908115610f2e578491610eec575b506001600160a01b0333911603610ebe57338352600c6020528160408420805415610e5a575b5050338352600c60205281604084205403610631575b338352600d602052604083205490600e602052604084205491600d602052826040862055600a60205260408520906040518083602082955493848152019089526020892092895b818110610e41575050610ca9925003836128c3565b815191865b838110610de15750505050835b815181101561050657600190338652600a602052610ce8604087206001600160a01b036103f78487612cb7565b610cf3575b01610cbb565b610d086001600160a01b0361041f8386612cb7565b6001600160a01b03610d1a8386612cb7565b51168752600f806020526003918260408a200155610d436001600160a01b036104618588612cb7565b6001600160a01b03610d558588612cb7565b5116895281602052600260408a2001556001600160a01b03610d778487612cb7565b511688526020526040872001543387526010602052604087206001600160a01b03610da28487612cb7565b51166000526020526040600020556001600160a01b03610dc28285612cb7565b51168652600b60205260408620610dda858254612d12565b9055610ced565b806001600160a01b03610df660019385612cb7565b51168952600b8060205260408a20610e0f868254612cef565b90556001600160a01b03610e238386612cb7565b51168a5260205260408920610e39888254612d12565b905501610cae565b8454835260019485019487945060209093019201610c94565b55826001600160a01b0360035416803b156105a95760405163698473e360e01b8152600481018590523360248201529082908290604490829084905af180156105ad57610eaa575b839150610c37565b610eb39061287d565b610631578238610ea2565b60405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606490fd5b90506020813d602011610f26575b81610f07602093836128c3565b8101031261072c57516001600160a01b038116810361072c5738610c11565b3d9150610efa565b6040513d86823e3d90fd5b338352600c60205260408320549150610c4d565b806001600160a01b03610f6260019385612cb7565b5116610f6d81612e25565b818a52600f806020526003918260408d200155868b60026040610f8f87612d1f565b9287815285602052200155610fa8575b50505001610b68565b610fb23384612ef8565b338c52601160205260408c2084600052602052604060002055828b5260205260408a20015490338a52601060205260408a2090600052602052604060002055388080610f9f565b8454835260019485019486945060209093019201610b4a565b50346101b85760c03660031901126101b85761102c6127ad565b6110346127c3565b90604435916001600160a01b03831680930361081757606435916001600160a01b038316809303610817576084359081151582036113455760a43567ffffffffffffffff811161081c5761108c9036906004016127d9565b93909487549160ff8360081c161597888099611338575b8015611321575b156112b65760ff948519948a6001878316178d556112a5575b507fffffffffffffffffffff0000000000000000000000000000000000000000ffff75ffffffffffffffffffffffffffffffffffffffff00008c549260101b169116178a556001600160a01b037fffffffffffffffffffffffff00000000000000000000000000000000000000009216826002541617600255816001541617600155600354161760035560095416911515161760095567ffffffffffffffff8111611291576801000000000000000081116112915760065481600655808210611250575b508160068552845b828110611215575050835b8181106111e75750505060016008556111b05780f35b61ff001981541681557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160018152a180f35b8061120e6001600160a01b036112086112036001958789612ccb565b612cdb565b16613279565b500161119a565b600190602061122384612cdb565b930192817ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01550161118f565b817ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f91820191015b8181106112855750611187565b60008155600101611278565b634e487b7160e01b84526041600452602484fd5b61ffff1916610101178b55386110c3565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608490fd5b50303b1580156110aa5750600160ff8516146110aa565b50600160ff8516106110a3565b8580fd5b50346101b85760203660031901126101b85760406020916001600160a01b036113706127ad565b168152600e83522054604051908152f35b50346101b857806003193601126101b8576001600854036101b857600260085560406113ab613055565b600160085582519182526020820152f35b50346101b85760203660031901126101b8576001600160a01b03600435602083546024604051809581936370a0823160e01b835233600484015260101c165afa918215611994578392611960575b50611413612dac565b338452600a602052604084206040518082602082945493848152019088526020882092885b81811061194757505061144d925003826128c3565b80519033151590865b838110611899575050505060016008540361072c57600260085581831561070057611492846001600160a01b03875460101c163090339061311c565b61149e84600754612d12565b600755338552600e602052604085206114b8858254612d12565b90551561188557602460206001600160a01b0360015416604051928380926331a9108f60e11b82528760048301525afa90811561070c578591611843575b506001600160a01b0333911603610ebe57338452600c60205281604085208054156117df575b5050338452600c6020528160408520540361072c575b338452600d602052604084205491600e602052604085205492600d602052836040872055600a6020526040862090604051808360208295549384815201908a5260208a20928a5b8181106117c657505061158e925003836128c3565b815191875b8381106117665750505050845b82518110156116c657600190338752600a6020526115cd604088206001600160a01b036103f78488612cb7565b6115d8575b016115a0565b6115ed6001600160a01b0361041f8387612cb7565b6001600160a01b036115ff8387612cb7565b51168852600f806020526003918260408b2001556116286001600160a01b036104618589612cb7565b6001600160a01b0361163a8589612cb7565b51168a5281602052600260408b2001556001600160a01b0361165c8488612cb7565b511689526020526040882001543388526010602052604088206001600160a01b036116878488612cb7565b51166000526020526040600020556001600160a01b036116a78286612cb7565b51168752600b602052604087206116bf868254612d12565b90556115d2565b858286826001600160a01b0360035416803b156105a95760405163530e389d60e11b815260048101859052336024820152604481018490529082908290606490829084905af180156105ad57611752575b505060405191825260208201527f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a1560403392a2600160085580f35b61175b9061287d565b610631578284611717565b806001600160a01b0361177b60019385612cb7565b51168a52600b8060205260408b20611794868254612cef565b90556001600160a01b036117a88386612cb7565b51168b5260205260408a206117be898254612d12565b905501611593565b8454835260019485019487945060209093019201611579565b55836001600160a01b0360035416803b156105a95760405163698473e360e01b8152600481018590523360248201529082908290604490829084905af180156105ad5761182f575b83915061151c565b6118389061287d565b61072c578338611827565b90506020813d60201161187d575b8161185e602093836128c3565b8101031261070057516001600160a01b038116810361070057386114f6565b3d9150611851565b338452600c60205260408420549150611532565b806001600160a01b036118ae60019385612cb7565b511660406118bb82612e25565b828c52600f90816020528c6003938491200155868c600260406118dd87612d1f565b92878152856020522001556118f6575b50505001611456565b6119003384612ef8565b338d52601160205260408d2084600052602052604060002055828c5260205260408b20015490338b52601060205260408b20906000526020526040600020553880806118ed565b8454835260019485019486945060209093019201611438565b9091506020813d60201161198c575b8161197c602093836128c3565b810103126108175751903861140a565b3d915061196f565b6040513d85823e3d90fd5b50346101b85760403660031901126101b8576119b96127ad565b602490813591838052602090600a825260408520604051808285829454938481520190895285892092895b87828210611d1d575050506119fb925003826128c3565b805190865b828110611cd05750505060016008540361070057600260085584546001600160a01b03848116959160101c16851461134557801561134557611a40613055565b5050611a4b84612e25565b93858752600f948585526003604089200155611a6686613279565b506040516370a0823160e01b80825230600483015292858286818b5afa918215611cc5578992611c94575b50611aa091923090339061311c565b60405190828252306004830152848285818a5afa8015611bfd578890611c65575b611acb9250612cef565b93858752808452600160408820015480421015600014611c1b575085875280845262093a80850460408820555b85875280845242600260408920015562093a8090814201804211611c0857878952818652600160408a200155604051928352306004840152848385818a5afa928315611bfd578893611bce575b5086885284526040872054910410611b8b57507ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906040519283523392a3600160085580f35b9060186064926040519262461bcd60e51b845260048401528201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152fd5b9092508481813d8311611bf6575b611be681836128c3565b8101031261081757519138611b45565b503d611bdc565b6040513d8a823e3d90fd5b634e487b7160e01b895260116004528489fd5b611c29611c3a914290612cef565b878952828652604089205490612d4b565b80861115611c6157611c5062093a809187612d12565b048688528185526040882055611af8565b8780fd5b508482813d8311611c8d575b611c7b81836128c3565b8101031261081757611acb9151611ac1565b503d611c71565b91508582813d8311611cbe575b611cab81836128c3565b8101031261081757611aa0915191611a91565b503d611ca1565b6040513d8b823e3d90fd5b806001600160a01b03611ce560019385612cb7565b5116611cf081612e25565b818b52600f90818952600360408d200155611d0a82612d1f565b918b528752600260408b20015501611a00565b85548452600195860195879550930192016119e4565b50346101b85760203660031901126101b857600435906006548210156101b85760206001600160a01b038360066000527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f015416604051908152f35b50346101b85760203660031901126101b8576020610857611dae6127ad565b612d5e565b50346101b85760203660031901126101b85760406020916001600160a01b03611dda6127ad565b168152600b83522054604051908152f35b50346101b857806003193601126101b857338152600e602052611e1160408220546128e5565b80f35b50346101b857806003193601126101b857604051600480548083529083526020808301937f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b92915b828210611e8357611e7f85611e73818903826128c3565b6040519182918261280a565b0390f35b835486529485019460019384019390910190611e5c565b50346101b8576020806003193601126105a9576001600160a01b03611ebd6127ad565b168252600a602052604082209160405180926020855492838152019483526020832092905b828210611ef957611e7f85611e73818903826128c3565b835486529485019460019384019390910190611ee2565b50346101b8576020806003193601126105a957611f2b6127ad565b338352600a825260408320604051808285829454938481520190875285872092875b8782821061213957505050611f64925003826128c3565b80519033151590855b8381106120945750505050338352600a82526040832091604051808483829654938481520190875283872092875b8582821061207e57505050611fb2925003846128c3565b8251338552600d82526040852054600e8352604086205494600d8452856040882055865b8381106120265750505050338452600a81526120006001600160a01b036040862093168093613186565b612008578380f35b600b9184525261201d60408320918254612cef565b90553880808380f35b6001906001600160a01b038061203c8386612cb7565b51168a52600b9081885260408b20612055878254612cef565b90556120618386612cb7565b51168a52865260408920612076898254612d12565b905501611fd6565b8554845260019586019589955093019201611f9b565b806001600160a01b036120a960019385612cb7565b51166120b481612e25565b818a5289868a60026040600f94858452600396878383200155856120d789612d1f565b94898352522001556120ed575b50505001611f6d565b6120f73384612ef8565b338c5260118b5260408c20846000528b52604060002055828b52895260408a20015490338a526010895260408a209060005288526040600020553880806120e4565b8554845260019586019587955093019201611f4d565b50346101b85760203660031901126101b85760406020916001600160a01b036121766127ad565b168152600d83522054604051908152f35b50346101b85760203660031901126101b85760206108576121a66127ad565b612d1f565b50346101b85760203660031901126101b85760406080916001600160a01b036121d26127ad565b82606085516121e0816128a7565b82815282602082015282878201520152168152600f60205220604051612205816128a7565b815491828252600181015460208301908152606060036002840154936040860194855201549301928352604051938452516020840152516040830152516060820152f35b50346101b857806003193601126101b85760206001600160a01b0360035416604051908152f35b50346101b85760403660031901126101b85761228a6127ad565b60406122946127c3565b926001600160a01b03809316815260106020522091166000526020526020604060002054604051908152f35b50346101b857806003193601126101b8576001600160a01b036020915460101c16604051908152f35b50346101b85760403660031901126101b8576123036127ad565b604061230d6127c3565b926001600160a01b03809316815260116020522091166000526020526020604060002054604051908152f35b50346101b85760403660031901126101b8576123536127ad565b60243567ffffffffffffffff8111610631576123739036906004016127d9565b91906001600160a01b0380831692838652602092600a8452604087206040518082878294549384815201908b52878b20928b5b89828210612688575050506123bd925003826128c3565b80519086151590895b8381106125e657505050506001958660085403611c615785331480156125d9575b15611c615786600855878460035416803b156105a95781906024604051809481936363453ae160e01b83523060048401525af18015611cc5576125c6575b50600260085586885b82811061250f575050505050828552600a82526040852091604051808483829654938481520190895283892092895b89868383106124fa5750505050612476925003846128c3565b8251938652600d8152604086205491600e8252604087205493600d835284604089205586885b8781106124ab57898260085580f35b836124b68285612cb7565b51168a52600b80865260408b206124ce888254612cef565b9055846124db8386612cb7565b51168b52855260408a206124f0888254612d12565b905501879061249c565b8654855295810195899550909301920161245d565b878a52601180885260408b208761252a61120385888a612ccb565b1660005288526040600020549081612547575b505001879061242e565b898c52885260408b208761255f61120385888a612ccb565b1660005288528a604060002055612584818761257f61120386898b612ccb565b612fc9565b887f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc989896125b6611203878a8c612ccb565b1693604051908152a3388061253d565b6125d29098919861287d565b9638612425565b50836003541633146123e7565b80876125f460019385612cb7565b51168c61260082612e25565b8282528b8d8b600f92838152600394856040882001558a61262088612d1f565b8888528583526002604089200155612640575b50505050505050016123c6565b61264c60119288612ef8565b928652528d60408520908686525260408420558c52604082200154918c825260108c526040822091528a5260408d2055388c81808d8b8e612633565b85548452600195860195879550930192016123a6565b50346101b85760203660031901126101b857611e116004356128e5565b50346101b85760403660031901126101b8576020906126d86127ad565b6126e06127c3565b906001600160a01b039283831693848252600a865261271660408320918416809260019160005201602052604060002054151590565b156127275750506108579250612ef8565b9150915060409282526011845282822090825283522054610857565b50346101b857806003193601126101b85760206001600160a01b0360015416604051908152f35b50346101b857806003193601126101b8576020600754604051908152f35b9050346105a957816003193601126105a9576020906001600160a01b03600254168152f35b600435906001600160a01b038216820361081757565b602435906001600160a01b038216820361081757565b9181601f840112156108175782359167ffffffffffffffff8311610817576020808501948460051b01011161081757565b602090602060408183019282815285518094520193019160005b828110612832575050505090565b83516001600160a01b031685529381019392810192600101612824565b80548210156128675760005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b67ffffffffffffffff811161289157604052565b634e487b7160e01b600052604160045260246000fd5b6080810190811067ffffffffffffffff82111761289157604052565b90601f8019910116810190811067ffffffffffffffff82111761289157604052565b90600091829033600052602090600e825260409182600020548214612ca6575b600a8152826000208351808284829454938481520190600052846000209260005b86828210612c905750505061293d925003826128c3565b8051903315159060005b838110612bed575050505060019360016008540361081757600260085580948315612ba95761297884600754612cef565b60075533600052600e835284600020612992858254612cef565b90556001600160a01b03916129af85338560005460101c16612fc9565b15612b945733600052600c8352846000208054870361081757600090558160035416803b1561081757855163411b1f7760e01b815260048101889052336024820152906000908290604490829084905af18015612b8957612b75575b505b338852600a835284882085518082868294549384815201908c52868c20928c5b8689838310612b605750505050612a46925003826128c3565b805190338a52600d8552868a2054600e8652878b205491600d875282898d20558b805b8a868210612b1357505050505050505060035416803b1561081c578351633aa53b9160e21b815260048101869052336024820152604481018490529087908290606490829084905af18015612b0957612af5575b507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b5689394955082519485528401523392a26001600855565b612aff879161287d565b6113455785612abd565b84513d89823e3d90fd5b879289612b208487612cb7565b51168152600b808c52828220612b37888254612cef565b90558a612b448588612cb7565b511682528b5220612b56868254612d12565b9055018c90612a69565b86548552958101958795509093019201612a2d565b612b8091985061287d565b60009638612a0b565b86513d6000823e3d90fd5b945033600052600c8252836000205494612a0d565b845162461bcd60e51b815260048101849052601160248201527f43616e27742077697468647261772030210000000000000000000000000000006044820152606490fd5b806001600160a01b03612c0260019385612cb7565b5116612c0d81612e25565b81600052600f808952600391828c600020015586612c2a84612d1f565b84600052828b5260028d6000200155612c47575b50505001612947565b612c513384612ef8565b3360005260118a528b600020846000528a528b600020558852896000200154903360005260108852896000209060005287528860002055388080612c3e565b8554845260019586019587955093019201612926565b9250600c8352816000205492612905565b80518210156128675760209160051b010190565b91908110156128675760051b0190565b356001600160a01b03811681036108175790565b91908203918211612cfc57565b634e487b7160e01b600052601160045260246000fd5b91908201809211612cfc57565b6001600160a01b0316600052600f602052600160406000200154804210600014612d4857504290565b90565b81810292918115918404141715612cfc57565b6001600160a01b031680600052600f6020526001604060002001549081421015612da557612d90612d48924290612cef565b90600052600f60205260406000205490612d4b565b5050600090565b6040519060065480835282602091602082019060066000527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f936000905b828210612e0257505050612e00925003836128c3565b565b85546001600160a01b031684526001958601958895509381019390910190612dea565b906001600160a01b038216916000928084526020600b81526040908186205415612ee857600f8152612e88612e77612e636003858a20015496612d1f565b858952600f84526002858a20015490612cef565b848852600f83528388205490612d4b565b92670de0b6b3a764000093848102948186041490151715612ed4578652600b9052842054908115612ec057612d489394500490612d12565b634e487b7160e01b85526012600452602485fd5b634e487b7160e01b87526011600452602487fd5b600f905290932060030154925050565b6040612d48926001600160a01b0380911692670de0b6b3a7640000612f57600093868552600d602052612f518686205491612f3286612e25565b9089885260106020528888209616958688526020528787205490612cef565b90612d4b565b049382526011602052828220908252602052205490612d12565b3d15612fac573d9067ffffffffffffffff82116128915760405191612fa0601f8201601f1916602001846128c3565b82523d6000602084013e565b606090565b90816020910312610817575180151581036108175790565b919091803b1561081757600092838093604051906001600160a01b03602083019463a9059cbb60e01b865216602483015260448201526044815261300c816128a7565b51925af1613018612f71565b81613026575b501561081757565b805180159250821561303b575b50503861301e565b61304e9250602080918301019101612fb1565b3880613033565b60ff6009541615613114576000906001600160a01b03825460101c16908260408093600482518097819363d294f09360e01b83525af1938415613108578180956130d0575b50507fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa384938295815193845260208401523392a2565b915093508284813d8311613101575b6130e981836128c3565b810103126101b857506020835193015192388061309a565b503d6130df565b508251903d90823e3d90fd5b600090600090565b909192813b15610817576040519260208401946323b872dd60e01b86526001600160a01b03809216602486015216604484015260648301526064825260a082019282841067ffffffffffffffff851117612891576000809493819460405251925af1613018612f71565b906001820190600092818452826020526040842054908115156000146132725760001991808301818111612ed45782549084820191821161325e57808203613212575b505050805480156131fe578201916131e1838361284f565b909182549160031b1b191690555582526020526040812055600190565b634e487b7160e01b86526031600452602486fd5b613249613222613232938661284f565b90549060031b1c9283928661284f565b819391549060031b91821b91600019901b19161790565b905586528460205260408620553880806131c9565b634e487b7160e01b88526011600452602488fd5b5050505090565b60008181526005602052604081205461331157600454680100000000000000008110156132fd5760018101806004558110156132e95790826040927f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b015560045492815260056020522055600190565b634e487b7160e01b82526032600452602482fd5b634e487b7160e01b82526041600452602482fd5b905090565b6000828152600182016020526040902054612da55780549068010000000000000000821015612891578261335461323284600180960185558461284f565b90558054926000520160205260406000205560019056fea164736f6c6343000816000a
Deployed Bytecode
0x608080604052600436101561001357600080fd5b600090813560e01c9081630d43e8ad146127885750806318160ddd1461276a5780631f85071614612743578063211dc32d146126bb5780632e1a7d4d1461269e57806331279d3d1461233957806336925259146122e95780633a4b66f1146122c05780633ca068b61461227057806346c96aac1461224957806348e5d9f8146121ab578063638634ee1461218757806363fb415b1461214f57806369af57f014611f1057806370a0823114611349578063736fc25514611e9a5780638003b61414611e14578063853828b614611deb578063907d2aaa14611db357806399bcc05214611d8f578063a933d5b914611d33578063b66503cf1461199f578063c6f678bd146113bc578063d294f09314611381578063d35e254414611349578063dee2c33914611012578063e2bbb15814610b08578063e688639614610aea578063f0ff49081461085f578063f122977714610833578063f8e8e99f146101bb5763fc97a3031461018157600080fd5b346101b85760203660031901126101b85760406020916001600160a01b036101a76127ad565b168152600c83522054604051908152f35b80fd5b50346101b85760603660031901126101b857602480359067ffffffffffffffff906044358281116107005736602382011215610700578060040135928311610820578260051b906040519361021360208401866128c3565b84528260208501928201019036821161081c578301915b8183106107f757505050338452600a602052604084206040518082602082945493848152019088526020882092885b8181106107de57505061026e925003826128c3565b80519033151590865b838110610730575050505060016008540361072c5760026008558260043515610700576102b885546004359030906001600160a01b03339160101c1661311c565b6102c6600435600754612d12565b600755338552600e602052604085206102e26004358254612d12565b905515610717578060206001600160a01b0360015416604051928380926331a9108f60e11b82528860048301525afa90811561070c5785916106c6575b506001600160a01b03339116036106995750338352600c6020528160408420805415610635575b5050338352600c60205281604084205403610631575b338352600d602052604083205490600e602052604084205491600d602052826040862055600a60205260408520906040518083602082955493848152019089526020892092895b8181106106185750506103b8925003836128c3565b815191865b8381106105b85750505050835b815181101561050657600190338652600a6020526103ff604087206001600160a01b036103f78487612cb7565b511690613316565b61040a575b016103ca565b6104266001600160a01b0361041f8386612cb7565b5116612e25565b6001600160a01b036104388386612cb7565b51168752600f806020526003918260408a2001556104686001600160a01b036104618588612cb7565b5116612d1f565b6001600160a01b0361047a8588612cb7565b5116895281602052600260408a2001556001600160a01b0361049c8487612cb7565b511688526020526040872001543387526010602052604087206001600160a01b036104c78487612cb7565b51166000526020526040600020556001600160a01b036104e78285612cb7565b51168652600b602052604086206104ff858254612d12565b9055610404565b505050816001600160a01b0360035416803b156105a95760405163530e389d60e11b815260048082018590523360248301523560448201529082908290606490829084905af180156105ad57610595575b505060405190815260043560208201527f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a1560403392a2600160085580f35b61059e9061287d565b6105a9578138610557565b5080fd5b6040513d84823e3d90fd5b806001600160a01b036105cd60019385612cb7565b51168952600b8060205260408a206105e6868254612cef565b90556001600160a01b036105fa8386612cb7565b51168a5260205260408920610610888254612d12565b9055016103bd565b84548352600194850194879450602090930192016103a3565b8280fd5b55826001600160a01b0360035416803b156105a95760405163698473e360e01b8152600481018590523360248201529082908290604490829084905af180156105ad57610685575b839150610346565b61068e9061287d565b61063157823861067d565b60649060066040519162461bcd60e51b8352602060048401528201526510b7bbb732b960d11b6044820152fd5b90506020813d602011610704575b816106e1602093836128c3565b8101031261070057516001600160a01b0381168103610700573861031f565b8480fd5b3d91506106d4565b6040513d87823e3d90fd5b50338352600c6020526040832054915061035c565b8380fd5b806001600160a01b0361074560019385612cb7565b5116604061075282612e25565b828c52600f90816020528c6003938491200155868c6002604061077487612d1f565b928781528560205220015561078d575b50505001610277565b6107973384612ef8565b338d52601160205260408d2084600052602052604060002055828c5260205260408b20015490338b52601060205260408b2090600052602052604060002055388080610784565b8454835260019485019486945060209093019201610259565b82356001600160a01b03811681036108175781526020928301920161022a565b600080fd5b8680fd5b50634e487b7160e01b8452604160045283fd5b50346101b85760203660031901126101b85760206108576108526127ad565b612e25565b604051908152f35b50346101b8576020806003193601126105a95761087a6127ad565b338352600a825260408320604051808285829454938481520190875285872092875b87828210610ad4575050506108b3925003826128c3565b80519033151590855b838110610a2f5750505050338352600a82526040832091604051808483829654938481520190875283872092875b85828210610a1957505050610901925003846128c3565b8251338552600d82526040852054600e8352604086205494600d8452856040882055865b8381106109c15750505050338452600a81526040842061094f6001600160a01b0384168092613316565b610957578480f35b600361097b84610968600b96612e25565b848952600f86528360408a200155612d1f565b828752600f845260408720906002820155015433865260108352604086208260005283526040600020558452526109b760408320918254612d12565b9055388080808480f35b6001906001600160a01b03806109d78386612cb7565b51168a52600b9081885260408b206109f0878254612cef565b90556109fc8386612cb7565b51168a52865260408920610a11898254612d12565b905501610925565b85548452600195860195899550930192016108ea565b806001600160a01b03610a4460019385612cb7565b5116610a4f81612e25565b818a5289868a60026040600f9485845260039687838320015585610a7289612d1f565b9489835252200155610a88575b505050016108bc565b610a923384612ef8565b338c5260118b5260408c20846000528b52604060002055828b52895260408a20015490338a526010895260408a20906000528852604060002055388080610a7f565b855484526001958601958795509301920161089c565b50346101b857806003193601126101b8576020600454604051908152f35b50346101b85760403660031901126101b857602435610b25612dac565b338352600a602052604083206040518082602082945493848152019087526020872092875b818110610ff9575050610b5f925003826128c3565b80519033151590855b838110610f4d5750505050600160085403610631576002600855816004351561072c57610ba984546004359030906001600160a01b03339160101c1661311c565b610bb7600435600754612d12565b600755338452600e60205260408420610bd36004358254612d12565b905515610f3957602460206001600160a01b0360015416604051928380926331a9108f60e11b82528760048301525afa908115610f2e578491610eec575b506001600160a01b0333911603610ebe57338352600c6020528160408420805415610e5a575b5050338352600c60205281604084205403610631575b338352600d602052604083205490600e602052604084205491600d602052826040862055600a60205260408520906040518083602082955493848152019089526020892092895b818110610e41575050610ca9925003836128c3565b815191865b838110610de15750505050835b815181101561050657600190338652600a602052610ce8604087206001600160a01b036103f78487612cb7565b610cf3575b01610cbb565b610d086001600160a01b0361041f8386612cb7565b6001600160a01b03610d1a8386612cb7565b51168752600f806020526003918260408a200155610d436001600160a01b036104618588612cb7565b6001600160a01b03610d558588612cb7565b5116895281602052600260408a2001556001600160a01b03610d778487612cb7565b511688526020526040872001543387526010602052604087206001600160a01b03610da28487612cb7565b51166000526020526040600020556001600160a01b03610dc28285612cb7565b51168652600b60205260408620610dda858254612d12565b9055610ced565b806001600160a01b03610df660019385612cb7565b51168952600b8060205260408a20610e0f868254612cef565b90556001600160a01b03610e238386612cb7565b51168a5260205260408920610e39888254612d12565b905501610cae565b8454835260019485019487945060209093019201610c94565b55826001600160a01b0360035416803b156105a95760405163698473e360e01b8152600481018590523360248201529082908290604490829084905af180156105ad57610eaa575b839150610c37565b610eb39061287d565b610631578238610ea2565b60405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606490fd5b90506020813d602011610f26575b81610f07602093836128c3565b8101031261072c57516001600160a01b038116810361072c5738610c11565b3d9150610efa565b6040513d86823e3d90fd5b338352600c60205260408320549150610c4d565b806001600160a01b03610f6260019385612cb7565b5116610f6d81612e25565b818a52600f806020526003918260408d200155868b60026040610f8f87612d1f565b9287815285602052200155610fa8575b50505001610b68565b610fb23384612ef8565b338c52601160205260408c2084600052602052604060002055828b5260205260408a20015490338a52601060205260408a2090600052602052604060002055388080610f9f565b8454835260019485019486945060209093019201610b4a565b50346101b85760c03660031901126101b85761102c6127ad565b6110346127c3565b90604435916001600160a01b03831680930361081757606435916001600160a01b038316809303610817576084359081151582036113455760a43567ffffffffffffffff811161081c5761108c9036906004016127d9565b93909487549160ff8360081c161597888099611338575b8015611321575b156112b65760ff948519948a6001878316178d556112a5575b507fffffffffffffffffffff0000000000000000000000000000000000000000ffff75ffffffffffffffffffffffffffffffffffffffff00008c549260101b169116178a556001600160a01b037fffffffffffffffffffffffff00000000000000000000000000000000000000009216826002541617600255816001541617600155600354161760035560095416911515161760095567ffffffffffffffff8111611291576801000000000000000081116112915760065481600655808210611250575b508160068552845b828110611215575050835b8181106111e75750505060016008556111b05780f35b61ff001981541681557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160018152a180f35b8061120e6001600160a01b036112086112036001958789612ccb565b612cdb565b16613279565b500161119a565b600190602061122384612cdb565b930192817ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01550161118f565b817ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f91820191015b8181106112855750611187565b60008155600101611278565b634e487b7160e01b84526041600452602484fd5b61ffff1916610101178b55386110c3565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608490fd5b50303b1580156110aa5750600160ff8516146110aa565b50600160ff8516106110a3565b8580fd5b50346101b85760203660031901126101b85760406020916001600160a01b036113706127ad565b168152600e83522054604051908152f35b50346101b857806003193601126101b8576001600854036101b857600260085560406113ab613055565b600160085582519182526020820152f35b50346101b85760203660031901126101b8576001600160a01b03600435602083546024604051809581936370a0823160e01b835233600484015260101c165afa918215611994578392611960575b50611413612dac565b338452600a602052604084206040518082602082945493848152019088526020882092885b81811061194757505061144d925003826128c3565b80519033151590865b838110611899575050505060016008540361072c57600260085581831561070057611492846001600160a01b03875460101c163090339061311c565b61149e84600754612d12565b600755338552600e602052604085206114b8858254612d12565b90551561188557602460206001600160a01b0360015416604051928380926331a9108f60e11b82528760048301525afa90811561070c578591611843575b506001600160a01b0333911603610ebe57338452600c60205281604085208054156117df575b5050338452600c6020528160408520540361072c575b338452600d602052604084205491600e602052604085205492600d602052836040872055600a6020526040862090604051808360208295549384815201908a5260208a20928a5b8181106117c657505061158e925003836128c3565b815191875b8381106117665750505050845b82518110156116c657600190338752600a6020526115cd604088206001600160a01b036103f78488612cb7565b6115d8575b016115a0565b6115ed6001600160a01b0361041f8387612cb7565b6001600160a01b036115ff8387612cb7565b51168852600f806020526003918260408b2001556116286001600160a01b036104618589612cb7565b6001600160a01b0361163a8589612cb7565b51168a5281602052600260408b2001556001600160a01b0361165c8488612cb7565b511689526020526040882001543388526010602052604088206001600160a01b036116878488612cb7565b51166000526020526040600020556001600160a01b036116a78286612cb7565b51168752600b602052604087206116bf868254612d12565b90556115d2565b858286826001600160a01b0360035416803b156105a95760405163530e389d60e11b815260048101859052336024820152604481018490529082908290606490829084905af180156105ad57611752575b505060405191825260208201527f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a1560403392a2600160085580f35b61175b9061287d565b610631578284611717565b806001600160a01b0361177b60019385612cb7565b51168a52600b8060205260408b20611794868254612cef565b90556001600160a01b036117a88386612cb7565b51168b5260205260408a206117be898254612d12565b905501611593565b8454835260019485019487945060209093019201611579565b55836001600160a01b0360035416803b156105a95760405163698473e360e01b8152600481018590523360248201529082908290604490829084905af180156105ad5761182f575b83915061151c565b6118389061287d565b61072c578338611827565b90506020813d60201161187d575b8161185e602093836128c3565b8101031261070057516001600160a01b038116810361070057386114f6565b3d9150611851565b338452600c60205260408420549150611532565b806001600160a01b036118ae60019385612cb7565b511660406118bb82612e25565b828c52600f90816020528c6003938491200155868c600260406118dd87612d1f565b92878152856020522001556118f6575b50505001611456565b6119003384612ef8565b338d52601160205260408d2084600052602052604060002055828c5260205260408b20015490338b52601060205260408b20906000526020526040600020553880806118ed565b8454835260019485019486945060209093019201611438565b9091506020813d60201161198c575b8161197c602093836128c3565b810103126108175751903861140a565b3d915061196f565b6040513d85823e3d90fd5b50346101b85760403660031901126101b8576119b96127ad565b602490813591838052602090600a825260408520604051808285829454938481520190895285892092895b87828210611d1d575050506119fb925003826128c3565b805190865b828110611cd05750505060016008540361070057600260085584546001600160a01b03848116959160101c16851461134557801561134557611a40613055565b5050611a4b84612e25565b93858752600f948585526003604089200155611a6686613279565b506040516370a0823160e01b80825230600483015292858286818b5afa918215611cc5578992611c94575b50611aa091923090339061311c565b60405190828252306004830152848285818a5afa8015611bfd578890611c65575b611acb9250612cef565b93858752808452600160408820015480421015600014611c1b575085875280845262093a80850460408820555b85875280845242600260408920015562093a8090814201804211611c0857878952818652600160408a200155604051928352306004840152848385818a5afa928315611bfd578893611bce575b5086885284526040872054910410611b8b57507ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906040519283523392a3600160085580f35b9060186064926040519262461bcd60e51b845260048401528201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152fd5b9092508481813d8311611bf6575b611be681836128c3565b8101031261081757519138611b45565b503d611bdc565b6040513d8a823e3d90fd5b634e487b7160e01b895260116004528489fd5b611c29611c3a914290612cef565b878952828652604089205490612d4b565b80861115611c6157611c5062093a809187612d12565b048688528185526040882055611af8565b8780fd5b508482813d8311611c8d575b611c7b81836128c3565b8101031261081757611acb9151611ac1565b503d611c71565b91508582813d8311611cbe575b611cab81836128c3565b8101031261081757611aa0915191611a91565b503d611ca1565b6040513d8b823e3d90fd5b806001600160a01b03611ce560019385612cb7565b5116611cf081612e25565b818b52600f90818952600360408d200155611d0a82612d1f565b918b528752600260408b20015501611a00565b85548452600195860195879550930192016119e4565b50346101b85760203660031901126101b857600435906006548210156101b85760206001600160a01b038360066000527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f015416604051908152f35b50346101b85760203660031901126101b8576020610857611dae6127ad565b612d5e565b50346101b85760203660031901126101b85760406020916001600160a01b03611dda6127ad565b168152600b83522054604051908152f35b50346101b857806003193601126101b857338152600e602052611e1160408220546128e5565b80f35b50346101b857806003193601126101b857604051600480548083529083526020808301937f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b92915b828210611e8357611e7f85611e73818903826128c3565b6040519182918261280a565b0390f35b835486529485019460019384019390910190611e5c565b50346101b8576020806003193601126105a9576001600160a01b03611ebd6127ad565b168252600a602052604082209160405180926020855492838152019483526020832092905b828210611ef957611e7f85611e73818903826128c3565b835486529485019460019384019390910190611ee2565b50346101b8576020806003193601126105a957611f2b6127ad565b338352600a825260408320604051808285829454938481520190875285872092875b8782821061213957505050611f64925003826128c3565b80519033151590855b8381106120945750505050338352600a82526040832091604051808483829654938481520190875283872092875b8582821061207e57505050611fb2925003846128c3565b8251338552600d82526040852054600e8352604086205494600d8452856040882055865b8381106120265750505050338452600a81526120006001600160a01b036040862093168093613186565b612008578380f35b600b9184525261201d60408320918254612cef565b90553880808380f35b6001906001600160a01b038061203c8386612cb7565b51168a52600b9081885260408b20612055878254612cef565b90556120618386612cb7565b51168a52865260408920612076898254612d12565b905501611fd6565b8554845260019586019589955093019201611f9b565b806001600160a01b036120a960019385612cb7565b51166120b481612e25565b818a5289868a60026040600f94858452600396878383200155856120d789612d1f565b94898352522001556120ed575b50505001611f6d565b6120f73384612ef8565b338c5260118b5260408c20846000528b52604060002055828b52895260408a20015490338a526010895260408a209060005288526040600020553880806120e4565b8554845260019586019587955093019201611f4d565b50346101b85760203660031901126101b85760406020916001600160a01b036121766127ad565b168152600d83522054604051908152f35b50346101b85760203660031901126101b85760206108576121a66127ad565b612d1f565b50346101b85760203660031901126101b85760406080916001600160a01b036121d26127ad565b82606085516121e0816128a7565b82815282602082015282878201520152168152600f60205220604051612205816128a7565b815491828252600181015460208301908152606060036002840154936040860194855201549301928352604051938452516020840152516040830152516060820152f35b50346101b857806003193601126101b85760206001600160a01b0360035416604051908152f35b50346101b85760403660031901126101b85761228a6127ad565b60406122946127c3565b926001600160a01b03809316815260106020522091166000526020526020604060002054604051908152f35b50346101b857806003193601126101b8576001600160a01b036020915460101c16604051908152f35b50346101b85760403660031901126101b8576123036127ad565b604061230d6127c3565b926001600160a01b03809316815260116020522091166000526020526020604060002054604051908152f35b50346101b85760403660031901126101b8576123536127ad565b60243567ffffffffffffffff8111610631576123739036906004016127d9565b91906001600160a01b0380831692838652602092600a8452604087206040518082878294549384815201908b52878b20928b5b89828210612688575050506123bd925003826128c3565b80519086151590895b8381106125e657505050506001958660085403611c615785331480156125d9575b15611c615786600855878460035416803b156105a95781906024604051809481936363453ae160e01b83523060048401525af18015611cc5576125c6575b50600260085586885b82811061250f575050505050828552600a82526040852091604051808483829654938481520190895283892092895b89868383106124fa5750505050612476925003846128c3565b8251938652600d8152604086205491600e8252604087205493600d835284604089205586885b8781106124ab57898260085580f35b836124b68285612cb7565b51168a52600b80865260408b206124ce888254612cef565b9055846124db8386612cb7565b51168b52855260408a206124f0888254612d12565b905501879061249c565b8654855295810195899550909301920161245d565b878a52601180885260408b208761252a61120385888a612ccb565b1660005288526040600020549081612547575b505001879061242e565b898c52885260408b208761255f61120385888a612ccb565b1660005288528a604060002055612584818761257f61120386898b612ccb565b612fc9565b887f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc989896125b6611203878a8c612ccb565b1693604051908152a3388061253d565b6125d29098919861287d565b9638612425565b50836003541633146123e7565b80876125f460019385612cb7565b51168c61260082612e25565b8282528b8d8b600f92838152600394856040882001558a61262088612d1f565b8888528583526002604089200155612640575b50505050505050016123c6565b61264c60119288612ef8565b928652528d60408520908686525260408420558c52604082200154918c825260108c526040822091528a5260408d2055388c81808d8b8e612633565b85548452600195860195879550930192016123a6565b50346101b85760203660031901126101b857611e116004356128e5565b50346101b85760403660031901126101b8576020906126d86127ad565b6126e06127c3565b906001600160a01b039283831693848252600a865261271660408320918416809260019160005201602052604060002054151590565b156127275750506108579250612ef8565b9150915060409282526011845282822090825283522054610857565b50346101b857806003193601126101b85760206001600160a01b0360015416604051908152f35b50346101b857806003193601126101b8576020600754604051908152f35b9050346105a957816003193601126105a9576020906001600160a01b03600254168152f35b600435906001600160a01b038216820361081757565b602435906001600160a01b038216820361081757565b9181601f840112156108175782359167ffffffffffffffff8311610817576020808501948460051b01011161081757565b602090602060408183019282815285518094520193019160005b828110612832575050505090565b83516001600160a01b031685529381019392810192600101612824565b80548210156128675760005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b67ffffffffffffffff811161289157604052565b634e487b7160e01b600052604160045260246000fd5b6080810190811067ffffffffffffffff82111761289157604052565b90601f8019910116810190811067ffffffffffffffff82111761289157604052565b90600091829033600052602090600e825260409182600020548214612ca6575b600a8152826000208351808284829454938481520190600052846000209260005b86828210612c905750505061293d925003826128c3565b8051903315159060005b838110612bed575050505060019360016008540361081757600260085580948315612ba95761297884600754612cef565b60075533600052600e835284600020612992858254612cef565b90556001600160a01b03916129af85338560005460101c16612fc9565b15612b945733600052600c8352846000208054870361081757600090558160035416803b1561081757855163411b1f7760e01b815260048101889052336024820152906000908290604490829084905af18015612b8957612b75575b505b338852600a835284882085518082868294549384815201908c52868c20928c5b8689838310612b605750505050612a46925003826128c3565b805190338a52600d8552868a2054600e8652878b205491600d875282898d20558b805b8a868210612b1357505050505050505060035416803b1561081c578351633aa53b9160e21b815260048101869052336024820152604481018490529087908290606490829084905af18015612b0957612af5575b507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b5689394955082519485528401523392a26001600855565b612aff879161287d565b6113455785612abd565b84513d89823e3d90fd5b879289612b208487612cb7565b51168152600b808c52828220612b37888254612cef565b90558a612b448588612cb7565b511682528b5220612b56868254612d12565b9055018c90612a69565b86548552958101958795509093019201612a2d565b612b8091985061287d565b60009638612a0b565b86513d6000823e3d90fd5b945033600052600c8252836000205494612a0d565b845162461bcd60e51b815260048101849052601160248201527f43616e27742077697468647261772030210000000000000000000000000000006044820152606490fd5b806001600160a01b03612c0260019385612cb7565b5116612c0d81612e25565b81600052600f808952600391828c600020015586612c2a84612d1f565b84600052828b5260028d6000200155612c47575b50505001612947565b612c513384612ef8565b3360005260118a528b600020846000528a528b600020558852896000200154903360005260108852896000209060005287528860002055388080612c3e565b8554845260019586019587955093019201612926565b9250600c8352816000205492612905565b80518210156128675760209160051b010190565b91908110156128675760051b0190565b356001600160a01b03811681036108175790565b91908203918211612cfc57565b634e487b7160e01b600052601160045260246000fd5b91908201809211612cfc57565b6001600160a01b0316600052600f602052600160406000200154804210600014612d4857504290565b90565b81810292918115918404141715612cfc57565b6001600160a01b031680600052600f6020526001604060002001549081421015612da557612d90612d48924290612cef565b90600052600f60205260406000205490612d4b565b5050600090565b6040519060065480835282602091602082019060066000527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f936000905b828210612e0257505050612e00925003836128c3565b565b85546001600160a01b031684526001958601958895509381019390910190612dea565b906001600160a01b038216916000928084526020600b81526040908186205415612ee857600f8152612e88612e77612e636003858a20015496612d1f565b858952600f84526002858a20015490612cef565b848852600f83528388205490612d4b565b92670de0b6b3a764000093848102948186041490151715612ed4578652600b9052842054908115612ec057612d489394500490612d12565b634e487b7160e01b85526012600452602485fd5b634e487b7160e01b87526011600452602487fd5b600f905290932060030154925050565b6040612d48926001600160a01b0380911692670de0b6b3a7640000612f57600093868552600d602052612f518686205491612f3286612e25565b9089885260106020528888209616958688526020528787205490612cef565b90612d4b565b049382526011602052828220908252602052205490612d12565b3d15612fac573d9067ffffffffffffffff82116128915760405191612fa0601f8201601f1916602001846128c3565b82523d6000602084013e565b606090565b90816020910312610817575180151581036108175790565b919091803b1561081757600092838093604051906001600160a01b03602083019463a9059cbb60e01b865216602483015260448201526044815261300c816128a7565b51925af1613018612f71565b81613026575b501561081757565b805180159250821561303b575b50503861301e565b61304e9250602080918301019101612fb1565b3880613033565b60ff6009541615613114576000906001600160a01b03825460101c16908260408093600482518097819363d294f09360e01b83525af1938415613108578180956130d0575b50507fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa384938295815193845260208401523392a2565b915093508284813d8311613101575b6130e981836128c3565b810103126101b857506020835193015192388061309a565b503d6130df565b508251903d90823e3d90fd5b600090600090565b909192813b15610817576040519260208401946323b872dd60e01b86526001600160a01b03809216602486015216604484015260648301526064825260a082019282841067ffffffffffffffff851117612891576000809493819460405251925af1613018612f71565b906001820190600092818452826020526040842054908115156000146132725760001991808301818111612ed45782549084820191821161325e57808203613212575b505050805480156131fe578201916131e1838361284f565b909182549160031b1b191690555582526020526040812055600190565b634e487b7160e01b86526031600452602486fd5b613249613222613232938661284f565b90549060031b1c9283928661284f565b819391549060031b91821b91600019901b19161790565b905586528460205260408620553880806131c9565b634e487b7160e01b88526011600452602488fd5b5050505090565b60008181526005602052604081205461331157600454680100000000000000008110156132fd5760018101806004558110156132e95790826040927f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b015560045492815260056020522055600190565b634e487b7160e01b82526032600452602482fd5b634e487b7160e01b82526041600452602482fd5b905090565b6000828152600182016020526040902054612da55780549068010000000000000000821015612891578261335461323284600180960185558461284f565b90558054926000520160205260406000205560019056fea164736f6c6343000816000a
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.01
Net Worth in ETH
Token Allocations
POL
100.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| POL | 100.00% | $0.120518 | 0.1 | $0.012052 |
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.