Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Cross-Chain Transactions
Loading...
Loading
Contract Name:
veSPA
Compiler Version
v0.8.10+commit.fc410830
Contract Source Code (Solidity Multiple files format)
//SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@//
//@@@@@@@@&....(@@@@@@@@@@@@@..../@@@@@@@@@//
//@@@@@@........../@@@@@@@........../@@@@@@//
//@@@@@............(@@@@@............(@@@@@//
//@@@@@(............@@@@@(...........&@@@@@//
//@@@@@@@...........&@@@@@@.........@@@@@@@//
//@@@@@@@@@@@@@@%..../@@@@@@@@@@@@@@@@@@@@@//
//@@@@@@@@@@@@@@@@@@@...@@@@@@@@@@@@@@@@@@@//
//@@@@@@@@@@@@@@@@@@@@@......(&@@@@@@@@@@@@//
//@@@@@@#.........@@@@@@#...........@@@@@@@//
//@@@@@/...........%@@@@@............%@@@@@//
//@@@@@............#@@@@@............%@@@@@//
//@@@@@@..........#@@@@@@@/.........#@@@@@@//
//@@@@@@@@@&/.(@@@@@@@@@@@@@@&/.(&@@@@@@@@@//
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@//
import "./ReentrancyGuardUpgradeable.sol";
import "./OwnableUpgradeable.sol";
import "./SafeERC20Upgradeable.sol";
import "./IveSPA.sol";
/// @title Voting Escrow
/// @notice Cooldown logic is added in the contract
/// @notice veSPA_v2: Manual cooldown option is deprecated.
/// @notice Make contract upgradeable
/// @notice This is a Solidity implementation of the CURVE's voting escrow.
/// @notice Votes have a weight depending on time, so that users are
/// committed to the future of (whatever they are voting for)
/// @dev Vote weight decays linearly over time. Lock time cannot be
/// more than `MAX_TIME` (4 years).
/**
# Voting escrow to have time-weighted votes
# w ^
# 1 + /
# | /
# | /
# | /
# |/
# 0 +--------+------> time
# maxtime (4 years?)
*/
contract veSPA is IveSPA, OwnableUpgradeable, ReentrancyGuardUpgradeable {
using SafeERC20Upgradeable for IERC20Upgradeable;
enum ActionType {
DEPOSIT_FOR,
CREATE_LOCK,
INCREASE_AMOUNT,
INCREASE_LOCK_TIME,
INITIATE_COOLDOWN
}
struct Point {
int128 bias; // veSPA value at this point
int128 slope; // slope at this point
int128 residue; // residue calculated at this point
uint256 ts; // timestamp of this point
uint256 blk; // block number of this point
}
/* We cannot really do block numbers per se b/c slope is per time, not per block
* and per block could be fairly bad b/c Ethereum changes blocktimes.
* What we can do is to extrapolate ***At functions */
struct LockedBalance {
bool autoCooldown; // if true, the user's deposit will have a default cooldown.
bool cooldownInitiated; // Determines if the cooldown has been initiated.
uint128 amount; // amount of SPA locked for a user.
uint256 end; // the expiry time of the deposit.
}
// veSPA token related
string public version;
string public constant name = "Vote-escrow SPA";
string public constant symbol = "veSPA";
uint8 public constant decimals = 18;
uint256 public totalSPALocked;
uint256 public constant WEEK = 1 weeks;
uint256 public constant MAX_TIME = 4 * 365 days;
uint256 public constant MIN_TIME = 1 * WEEK;
uint256 public constant MULTIPLIER = 10**18;
int128 public constant I_YEAR = int128(uint128(365 days));
int128 public constant I_MIN_TIME = int128(uint128(WEEK));
/// SPA related information
address public SPA;
/// @dev Mappings to store global point information
uint256 public epoch;
mapping(uint256 => Point) public pointHistory; // epoch -> unsigned point
mapping(uint256 => int128) public slopeChanges; // time -> signed slope change
/// @dev Mappings to store user deposit information
mapping(address => LockedBalance) public lockedBalances; // user Deposits
mapping(address => mapping(uint256 => Point)) public userPointHistory; // user -> point[userEpoch]
mapping(address => uint256) public override userPointEpoch;
event UserCheckpoint(
ActionType indexed actionType,
bool autoCooldown,
address indexed provider,
uint256 value,
uint256 indexed locktime
);
event GlobalCheckpoint(address caller, uint256 epoch);
event Withdraw(address indexed provider, uint256 value, uint256 ts);
event Supply(uint256 prevSupply, uint256 supply);
event AccountMigratedToAutoCooldown(address indexed account);
constructor() public initializer {}
/// @notice Record global data to checkpoint
function checkpoint() external override {
_updateGlobalPoint();
emit GlobalCheckpoint(_msgSender(), epoch);
}
/// @notice Deposit and lock tokens for a user
/// @dev Anyone (even a smart contract) can deposit tokens for someone else, but
/// cannot extend their locktime and deposit for a user that is not locked
/// @param addr Address of the user
/// @param value Amount of tokens to deposit
function depositFor(address addr, uint128 value)
external
override
nonReentrant
{
LockedBalance memory existingDeposit = lockedBalances[addr];
require(value > 0, "Cannot deposit 0 tokens");
require(existingDeposit.amount > 0, "No existing lock");
if (!existingDeposit.autoCooldown) {
require(
!existingDeposit.cooldownInitiated,
"Cannot deposit during cooldown"
);
}
// else: auto-cooldown is on, so user can deposit anytime prior to expiry
require(
existingDeposit.end > block.timestamp,
"Lock expired. Withdraw"
);
_depositFor(
addr,
existingDeposit.autoCooldown,
existingDeposit.cooldownInitiated,
value,
0,
existingDeposit,
ActionType.DEPOSIT_FOR
);
}
/// @notice Deposit `value` for `msg.sender` and lock until `unlockTime`
/// @param value Amount of tokens to deposit
/// @param unlockTime Time when the tokens will be unlocked
/// @param autoCooldown Choose to opt in to auto-cooldown
/// @dev if autoCooldown is true, the user's veSPA balance will
/// decay to 0 after `unlockTime` else the user's veSPA balance
/// will remain = residual balance till user initiates cooldown
/// @dev unlockTime is rounded down to whole weeks
function createLock(
uint128 value,
uint256 unlockTime,
bool autoCooldown
) external override nonReentrant {
require(autoCooldown, "Manual cooldown deprecated");
address account = _msgSender();
uint256 roundedUnlockTime = (unlockTime / WEEK) * WEEK;
LockedBalance memory existingDeposit = lockedBalances[account];
require(value > 0, "Cannot lock 0 tokens");
require(existingDeposit.amount == 0, "Withdraw old tokens first");
require(roundedUnlockTime > block.timestamp, "Cannot lock in the past");
require(
roundedUnlockTime <= block.timestamp + MAX_TIME,
"Voting lock can be 4 years max"
);
_depositFor(
account,
autoCooldown,
autoCooldown,
value,
roundedUnlockTime,
existingDeposit,
ActionType.CREATE_LOCK
);
}
/// @notice Deposit `value` additional tokens for `msg.sender` without
/// modifying the locktime
/// @param value Amount of tokens to deposit
function increaseAmount(uint128 value) external override nonReentrant {
address account = _msgSender();
LockedBalance memory existingDeposit = lockedBalances[account];
require(value > 0, "Cannot deposit 0 tokens");
require(existingDeposit.amount > 0, "No existing lock found");
if (!existingDeposit.autoCooldown) {
require(
!existingDeposit.cooldownInitiated,
"Cannot deposit during cooldown"
);
}
// else: auto-cooldown is on, so user can deposit anytime prior to expiry
require(
existingDeposit.end > block.timestamp,
"Lock expired. Withdraw"
);
_depositFor(
account,
existingDeposit.autoCooldown,
existingDeposit.cooldownInitiated,
value,
0,
existingDeposit,
ActionType.INCREASE_AMOUNT
);
}
/// @notice Extend the locktime of `msg.sender`'s tokens to `unlockTime`
/// @param unlockTime New locktime
function increaseUnlockTime(uint256 unlockTime) external override {
address account = _msgSender();
LockedBalance memory existingDeposit = lockedBalances[account];
uint256 roundedUnlockTime = (unlockTime / WEEK) * WEEK; // Locktime is rounded down to weeks
require(existingDeposit.amount > 0, "No existing lock found");
if (!existingDeposit.autoCooldown) {
require(
!existingDeposit.cooldownInitiated,
"Deposit is in cooldown"
);
}
// else: auto-cooldown is on, so user can increase unlocktime anytime prior to expiry
require(
existingDeposit.end > block.timestamp,
"Lock expired. Withdraw"
);
require(
roundedUnlockTime > existingDeposit.end,
"Can only increase lock duration"
);
require(
roundedUnlockTime <= block.timestamp + MAX_TIME,
"Voting lock can be 4 years max"
);
_depositFor(
account,
existingDeposit.autoCooldown,
existingDeposit.cooldownInitiated,
0,
roundedUnlockTime,
existingDeposit,
ActionType.INCREASE_LOCK_TIME
);
}
/// @notice Initiate the cooldown period for `msg.sender`'s deposit
function initiateCooldown() external override {
address account = _msgSender();
LockedBalance memory existingDeposit = lockedBalances[account];
require(existingDeposit.amount > 0, "No existing lock found");
require(
!existingDeposit.cooldownInitiated,
"Cooldown already initiated"
);
// migrateToAutoCooldown
uint256 roundedUnlockTime = existingDeposit.end;
// initiate the cooldown.
if (block.timestamp >= existingDeposit.end - MIN_TIME) {
roundedUnlockTime = ((block.timestamp + MIN_TIME) / WEEK) * WEEK;
} else {
emit AccountMigratedToAutoCooldown(account);
}
_depositFor(
account,
true,
true,
0,
roundedUnlockTime,
existingDeposit,
ActionType.INITIATE_COOLDOWN
);
}
/// @notice Function to migrate manual-cooldown deposits to autoCooldown
/// @param _accounts array of addresses to be migrated.
function migrateToAutoCooldown(address[] calldata _accounts) external {
for (uint8 i = 0; i < _accounts.length; ) {
LockedBalance memory existingDeposit = lockedBalances[_accounts[i]];
if (
existingDeposit.amount > 0 && !existingDeposit.cooldownInitiated
) {
uint256 roundedUnlockTime = existingDeposit.end;
if (block.timestamp >= existingDeposit.end - MIN_TIME) {
roundedUnlockTime =
((block.timestamp + MIN_TIME) / WEEK) *
WEEK;
}
_depositFor(
_accounts[i],
true,
true,
0,
roundedUnlockTime,
existingDeposit,
ActionType.INITIATE_COOLDOWN
);
emit AccountMigratedToAutoCooldown(_accounts[i]);
}
unchecked {
++i;
}
}
}
/// @notice Withdraw tokens for `msg.sender`
/// @dev Only possible if the locktime has expired
function withdraw() external override nonReentrant {
address account = _msgSender();
LockedBalance memory existingDeposit = lockedBalances[account];
require(existingDeposit.amount > 0, "No existing lock found");
require(existingDeposit.cooldownInitiated, "No cooldown initiated");
require(block.timestamp >= existingDeposit.end, "Lock not expired.");
uint128 value = existingDeposit.amount;
LockedBalance memory oldDeposit = lockedBalances[account];
lockedBalances[account] = LockedBalance(false, false, 0, 0);
uint256 prevSupply = totalSPALocked;
totalSPALocked -= value;
// oldDeposit can have either expired <= timestamp or 0 end
// existingDeposit has 0 end
// Both can have >= 0 amount
_checkpoint(account, oldDeposit, LockedBalance(false, false, 0, 0));
IERC20Upgradeable(SPA).safeTransfer(account, value);
emit Withdraw(account, value, block.timestamp);
emit Supply(prevSupply, totalSPALocked);
}
// ----------------------VIEW functions----------------------
/// NOTE:The following ERC20/minime-compatible methods are not real balanceOf and supply!!
/// They measure the weights for the purpose of voting, so they don't represent real coins.
/// @notice Get the most recently recorded rate of voting power decrease for `addr`
/// @param addr The address to get the rate for
/// @return value of the slope
function getLastUserSlope(address addr)
external
view
override
returns (int128)
{
uint256 uEpoch = userPointEpoch[addr];
if (uEpoch == 0) {
return 0;
}
return userPointHistory[addr][uEpoch].slope;
}
/// @notice Get the timestamp for checkpoint `idx` for `addr`
/// @param addr User wallet address
/// @param idx User epoch number
/// @return Epoch time of the checkpoint
function getUserPointHistoryTS(address addr, uint256 idx)
external
view
override
returns (uint256)
{
return userPointHistory[addr][idx].ts;
}
/// @notice Get timestamp when `addr`'s lock finishes
/// @param addr User wallet address
/// @return Timestamp when lock finishes
function lockedEnd(address addr) external view override returns (uint256) {
return lockedBalances[addr].end;
}
/// @notice Calculate total voting power at a given block number in past
/// @param blockNumber Block number to calculate total voting power at
/// @return Total voting power at block number
function totalSupplyAt(uint256 blockNumber)
external
view
override
returns (uint256)
{
require(blockNumber <= block.number);
uint256 _epoch = epoch;
uint256 targetEpoch = _findBlockEpoch(blockNumber, _epoch);
Point memory point0 = pointHistory[targetEpoch];
uint256 dt = 0;
if (targetEpoch < _epoch) {
Point memory point1 = pointHistory[targetEpoch + 1];
dt =
((blockNumber - point0.blk) * (point1.ts - point0.ts)) /
(point1.blk - point0.blk);
} else {
if (point0.blk != block.number) {
dt =
((blockNumber - point0.blk) *
(block.timestamp - point0.ts)) /
(block.number - point0.blk);
}
}
// Now dt contains info on how far we are beyond point0
return supplyAt(point0, point0.ts + dt);
}
/// @notice Function to estimate the user deposit
/// @param autoCooldown Choose to opt in to auto-cooldown
/// @param value Amount of SPA to deposit
/// @param expectedUnlockTime The expected unlock time
/// @dev if autoCooldown is true, the user's veSPA balance will
/// decay to 0 after `unlockTime` else the user's veSPA balance
/// will remain = residual balance till user initiates cooldown
/// @return Estimated deposit
function estimateDeposit(
bool autoCooldown,
uint128 value,
uint256 expectedUnlockTime
)
public
view
returns (
bool,
int128 initialVespaBalance, // initial veSPA balance
int128 slope, // slope of the user's graph
int128 bias, // bias of the user's graph
int128 residue, // residual balance
uint256 actualUnlockTime, // actual rounded unlock time
uint256 providedUnlockTime, // expected unlock time
uint256 residuePeriodStart
)
{
actualUnlockTime = (expectedUnlockTime / WEEK) * WEEK;
require(actualUnlockTime > block.timestamp, "Cannot lock in the past");
require(
actualUnlockTime <= block.timestamp + MAX_TIME,
"Voting lock can be 4 years max"
);
int128 amt = int128(value);
slope = amt / I_YEAR;
if (!autoCooldown) {
residue = (amt * I_MIN_TIME) / I_YEAR;
residuePeriodStart = actualUnlockTime - WEEK;
bias =
slope *
int128(
int256(actualUnlockTime - WEEK) - int256(block.timestamp)
);
} else {
bias =
slope *
int128(int256(actualUnlockTime) - int256(block.timestamp));
}
if (bias <= 0) {
bias = 0;
}
initialVespaBalance = bias + residue;
return (
autoCooldown,
initialVespaBalance,
slope,
bias,
residue,
actualUnlockTime,
expectedUnlockTime,
residuePeriodStart
);
}
/// @notice Get the voting power for a user at the specified timestamp
/// @dev Adheres to ERC20 `balanceOf` interface for Aragon compatibility
/// @param addr User wallet address
/// @param ts Timestamp to get voting power at
/// @return Voting power of user at timestamp
function balanceOf(address addr, uint256 ts)
public
view
override
returns (uint256)
{
uint256 _epoch = _findUserTimestampEpoch(addr, ts);
if (_epoch == 0) {
return 0;
} else {
Point memory lastPoint = userPointHistory[addr][_epoch];
lastPoint.bias -=
lastPoint.slope *
int128(int256(ts) - int256(lastPoint.ts));
if (lastPoint.bias < 0) {
lastPoint.bias = 0;
}
lastPoint.bias += lastPoint.residue;
return uint256(int256(lastPoint.bias));
}
}
/// @notice Get the current voting power for a user
/// @param addr User wallet address
/// @return Voting power of user at current timestamp
function balanceOf(address addr) public view override returns (uint256) {
return balanceOf(addr, block.timestamp);
}
/// @notice Get the voting power of `addr` at block `blockNumber`
/// @param addr User wallet address
/// @param blockNumber Block number to get voting power at
/// @return Voting power of user at block number
function balanceOfAt(address addr, uint256 blockNumber)
public
view
override
returns (uint256)
{
uint256 min = 0;
uint256 max = userPointEpoch[addr];
// Find the approximate timestamp for the block number
for (uint256 i = 0; i < 128; i++) {
if (min >= max) {
break;
}
uint256 mid = (min + max + 1) / 2;
if (userPointHistory[addr][mid].blk <= blockNumber) {
min = mid;
} else {
max = mid - 1;
}
}
// min is the userEpoch nearest to the block number
Point memory uPoint = userPointHistory[addr][min];
uint256 maxEpoch = epoch;
// blocktime using the global point history
uint256 _epoch = _findBlockEpoch(blockNumber, maxEpoch);
Point memory point0 = pointHistory[_epoch];
uint256 dBlock = 0;
uint256 dt = 0;
if (_epoch < maxEpoch) {
Point memory point1 = pointHistory[_epoch + 1];
dBlock = point1.blk - point0.blk;
dt = point1.ts - point0.ts;
} else {
dBlock = blockNumber - point0.blk;
dt = block.timestamp - point0.ts;
}
uint256 blockTime = point0.ts;
if (dBlock != 0) {
blockTime += (dt * (blockNumber - point0.blk)) / dBlock;
}
uPoint.bias -=
uPoint.slope *
int128(int256(blockTime) - int256(uPoint.ts));
if (uPoint.bias < 0) {
uPoint.bias = 0;
}
uPoint.bias += uPoint.residue;
return uint256(int256(uPoint.bias));
}
/// @notice Calculate total voting power at a given timestamp
/// @return Total voting power at timestamp
function totalSupply(uint256 ts) public view override returns (uint256) {
uint256 _epoch = _findGlobalTimestampEpoch(ts);
Point memory lastPoint = pointHistory[_epoch];
return supplyAt(lastPoint, ts);
}
/// @notice Calculate total voting power at current timestamp
/// @return Total voting power at current timestamp
function totalSupply() public view override returns (uint256) {
return totalSupply(block.timestamp);
}
/// @notice Deposit and lock tokens for a user
/// @param addr Address of the user
/// @param value Amount of tokens to deposit
/// @param unlockTime Time when the tokens will be unlocked
/// @param oldDeposit Previous locked balance of the user / timestamp
function _depositFor(
address addr,
bool autoCooldown,
bool enableCooldown,
uint128 value,
uint256 unlockTime,
LockedBalance memory oldDeposit,
ActionType _type
) internal {
LockedBalance memory newDeposit = lockedBalances[addr];
uint256 prevSupply = totalSPALocked;
// Adding to existing lock, or if a lock is expired - creating a new one
newDeposit.amount += value;
newDeposit.autoCooldown = autoCooldown;
newDeposit.cooldownInitiated = enableCooldown;
if (unlockTime != 0) {
newDeposit.end = unlockTime;
}
lockedBalances[addr] = newDeposit;
/// Possibilities:
// Both oldDeposit.end could be current or expired (>/<block.timestamp)
// value == 0 (extend lock) or value > 0 (add to lock or extend lock)
// newDeposit.end > block.timestamp (always)
_checkpoint(addr, oldDeposit, newDeposit);
if (value != 0) {
totalSPALocked += value;
IERC20Upgradeable(SPA).safeTransferFrom(
_msgSender(),
address(this),
value
);
emit Supply(prevSupply, totalSPALocked);
}
emit UserCheckpoint(_type, autoCooldown, addr, value, newDeposit.end);
}
/// @notice Record global and per-user data to checkpoint
/// @param addr User wallet address. No user checkpoint if 0x0
/// @param oldDeposit Previous locked balance / end lock time for the user
/// @param newDeposit New locked balance / end lock time for the user
function _checkpoint(
address addr,
LockedBalance memory oldDeposit,
LockedBalance memory newDeposit
) internal {
Point memory uOld = Point(0, 0, 0, 0, 0);
Point memory uNew = Point(0, 0, 0, 0, 0);
int128 dSlopeOld = 0;
int128 dSlopeNew = 0;
// Calculate slopes and biases for oldDeposit
// Skipped in case of createLock
if (oldDeposit.amount > 0) {
int128 amt = int128(oldDeposit.amount);
if (!oldDeposit.cooldownInitiated) {
uOld.residue = (amt * I_MIN_TIME) / I_YEAR;
oldDeposit.end -= WEEK; // move back one week since oldDeposit.end is not a slope-change point
}
if (oldDeposit.end > block.timestamp) {
uOld.slope = amt / I_YEAR;
uOld.bias =
uOld.slope *
int128(int256(oldDeposit.end) - int256(block.timestamp));
}
}
// Calculate slopes and biases for newDeposit
// Skipped in case of withdraw
if ((newDeposit.end > block.timestamp) && (newDeposit.amount > 0)) {
int128 amt = int128(newDeposit.amount);
if (!newDeposit.cooldownInitiated) {
uNew.residue = (amt * I_MIN_TIME) / I_YEAR;
newDeposit.end -= WEEK; // move back one week since oldDeposit.end is not a slope-change point
}
if (newDeposit.end > block.timestamp) {
uNew.slope = amt / I_YEAR;
uNew.bias =
uNew.slope *
int128(int256(newDeposit.end) - int256(block.timestamp));
}
}
// Read values of scheduled changes in the slope
// oldDeposit.end can be in the past and in the future
// newDeposit.end can ONLY be in the future, unless everything expired: than zeros //TODO: wrong comment. CAN BE IN THE PAST
dSlopeOld = slopeChanges[oldDeposit.end];
if (newDeposit.end != 0) {
// if not "withdraw"
dSlopeNew = slopeChanges[newDeposit.end];
}
// add all global checkpoints from last added global check point until now
Point memory lastPoint = _updateGlobalPoint();
// If last point was in this block, the slope change has been applied already //TODO: how can it not be in this block?
// But in such case we have 0 slope(s)
// update the last global checkpoint (now) with user action's consequences
lastPoint.slope += (uNew.slope - uOld.slope); //TODO: why we can just add slopes up?
lastPoint.bias += (uNew.bias - uOld.bias);
lastPoint.residue += (uNew.residue - uOld.residue);
if (lastPoint.slope < 0) {
// it will never happen if everything works correctly
lastPoint.slope = 0;
}
if (lastPoint.bias < 0) {
// TODO: why it can be < 0?
lastPoint.bias = 0;
}
pointHistory[epoch] = lastPoint; // Record the changed point into the global history by replacement
// Schedule the slope changes (slope is going down)
// We subtract new_user_slope from [new_locked.end]
// and add old_user_slope to [old_locked.end]
if (oldDeposit.end > block.timestamp) {
// old_dslope was <something> - u_old.slope, so we cancel that
dSlopeOld += uOld.slope;
if (newDeposit.end == oldDeposit.end) {
// It was a new deposit, not extension
dSlopeOld -= uNew.slope;
}
slopeChanges[oldDeposit.end] = dSlopeOld;
}
if (newDeposit.end > block.timestamp) {
if (newDeposit.end > oldDeposit.end) {
dSlopeNew -= uNew.slope;
// old slope disappeared at this point
slopeChanges[newDeposit.end] = dSlopeNew;
}
// else: we recorded it already in old_dslopes̄
}
// Now handle user history
uint256 userEpc = userPointEpoch[addr] + 1;
userPointEpoch[addr] = userEpc;
uNew.ts = block.timestamp;
uNew.blk = block.number;
userPointHistory[addr][userEpc] = uNew;
}
/// @notice Binary search to estimate timestamp for block number
/// @param blockNumber Block number to estimate timestamp for
/// @param maxEpoch Don't go beyond this epoch
/// @return Estimated timestamp for block number
function _findBlockEpoch(uint256 blockNumber, uint256 maxEpoch)
internal
view
returns (uint256)
{
uint256 min = 0;
uint256 max = maxEpoch;
for (uint256 i = 0; i < 128; i++) {
if (min >= max) {
break;
}
uint256 mid = (min + max + 1) / 2;
if (pointHistory[mid].blk <= blockNumber) {
min = mid;
} else {
max = mid - 1;
}
}
return min;
}
function _findUserTimestampEpoch(address addr, uint256 ts)
internal
view
returns (uint256)
{
uint256 min = 0;
uint256 max = userPointEpoch[addr];
for (uint256 i = 0; i < 128; i++) {
if (min >= max) {
break;
}
uint256 mid = (min + max + 1) / 2;
if (userPointHistory[addr][mid].ts <= ts) {
min = mid;
} else {
max = mid - 1;
}
}
return min;
}
function _findGlobalTimestampEpoch(uint256 ts)
internal
view
returns (uint256)
{
uint256 min = 0;
uint256 max = epoch;
for (uint256 i = 0; i < 128; i++) {
if (min >= max) {
break;
}
uint256 mid = (min + max + 1) / 2;
if (pointHistory[mid].ts <= ts) {
min = mid;
} else {
max = mid - 1;
}
}
return min;
}
/// @notice Calculate total voting power at some point in the past
/// @param point The point (bias/slope) to start search from
/// @param ts Timestamp to calculate total voting power at
/// @return Total voting power at timestamp
function supplyAt(Point memory point, uint256 ts)
internal
view
returns (uint256)
{
Point memory lastPoint = point;
uint256 ti = (lastPoint.ts / WEEK) * WEEK;
// Calculate the missing checkpoints
for (uint256 i = 0; i < 255; i++) {
ti += WEEK;
int128 dSlope = 0;
if (ti > ts) {
ti = ts;
} else {
dSlope = slopeChanges[ti];
}
lastPoint.bias -=
lastPoint.slope *
int128(int256(ti) - int256(lastPoint.ts));
if (ti == ts) {
break;
}
lastPoint.slope += dSlope;
lastPoint.ts = ti;
}
if (lastPoint.bias < 0) {
lastPoint.bias = 0;
}
lastPoint.bias += lastPoint.residue;
return uint256(int256(lastPoint.bias));
}
/// @notice add checkpoints to pointHistory for every week from last added checkpoint until now
/// @dev block number for each added checkpoint is estimated by their respective timestamp and the blockslope
/// where the blockslope is estimated by the last added time/block point and the current time/block point
/// @dev pointHistory include all weekly global checkpoints and some additional in-week global checkpoints
/// @return lastPoint by calling this function
function _updateGlobalPoint() private returns (Point memory lastPoint) {
uint256 _epoch = epoch;
lastPoint = Point({
bias: 0,
slope: 0,
residue: 0,
ts: block.timestamp,
blk: block.number //TODO: arbi-main-fork cannot test it
});
Point memory initialLastPoint = Point({
bias: 0,
slope: 0,
residue: 0,
ts: block.timestamp,
blk: block.number //TODO: arbi-main-fork cannot test it
});
if (_epoch > 0) {
lastPoint = pointHistory[_epoch];
initialLastPoint = pointHistory[_epoch];
}
uint256 lastCheckpoint = lastPoint.ts;
// initialLastPoint is used for extrapolation to calculate block number
// (approximately, for *At functions) and save them
// as we cannot figure that out exactly from inside the contract
uint256 blockSlope = 0; // dblock/dt
if (block.timestamp > lastPoint.ts) {
//TODO: 1. what situations are covered by this condition? e.g. 1st point, line 179? 2. when false, two identical global checkpoints?
blockSlope =
(MULTIPLIER * (block.number - lastPoint.blk)) /
(block.timestamp - lastPoint.ts);
}
// If last point is already recorded in this block, blockSlope is zero
// But that's ok b/c we know the block in such case.
// Go over weeks to fill history and calculate what the current point is
{
uint256 ti = (lastCheckpoint / WEEK) * WEEK;
for (uint256 i = 0; i < 255; i++) {
// Hopefully it won't happen that this won't get used in 4 years!
// If it does, users will be able to withdraw but vote weight will be broken
ti += WEEK;
int128 dslope = 0;
if (ti > block.timestamp) {
ti = block.timestamp;
} else {
dslope = slopeChanges[ti]; //TODO: check if possible that dslope = zerovalue
}
// calculate the slope and bia of the new last point
lastPoint.bias -=
lastPoint.slope *
int128(int256(ti) - int256(lastCheckpoint));
lastPoint.slope += dslope;
// check sanity
if (lastPoint.bias < 0) {
// This can happen //TODO: why it can happen?
lastPoint.bias = 0;
}
if (lastPoint.slope < 0) {
// This cannot happen, but just in case //TODO: why it cannot < 0?
lastPoint.slope = 0;
}
lastCheckpoint = ti;
lastPoint.ts = ti;
lastPoint.blk =
initialLastPoint.blk +
(blockSlope * (ti - initialLastPoint.ts)) /
MULTIPLIER;
_epoch += 1;
if (ti == block.timestamp) {
lastPoint.blk = block.number;
pointHistory[_epoch] = lastPoint;
break;
}
pointHistory[_epoch] = lastPoint;
}
}
epoch = _epoch;
return lastPoint;
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [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://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason 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 {
// 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
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
import "./Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Upgradeable {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.0;
import "./AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since 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.
*
* 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 initialize the implementation contract, you can either invoke the
* initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() initializer {}
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
// If the contract is initializing we ignore whether _initialized is set in order to support multiple
// inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
// contract may have been reentered.
require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} modifier, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
function _isConstructor() private view returns (bool) {
return !AddressUpgradeable.isContract(address(this));
}
}
pragma solidity 0.8.10;
interface IveSPA {
function getLastUserSlope(address addr) external view returns (int128);
function getUserPointHistoryTS(address addr, uint256 idx)
external
view
returns (uint256);
function userPointEpoch(address addr) external view returns (uint256);
function checkpoint() external;
function lockedEnd(address addr) external view returns (uint256);
function depositFor(address addr, uint128 value) external;
function createLock(
uint128 value,
uint256 unlockTime,
bool autoCooldown
) external;
function increaseAmount(uint128 value) external;
function increaseUnlockTime(uint256 unlockTime) external;
function initiateCooldown() external;
function withdraw() external;
function balanceOf(address addr, uint256 ts)
external
view
returns (uint256);
function balanceOf(address addr) external view returns (uint256);
function balanceOfAt(address, uint256 blockNumber)
external
view
returns (uint256);
function totalSupply(uint256 ts) external view returns (uint256);
function totalSupply() external view returns (uint256);
function totalSupplyAt(uint256 blockNumber) external view returns (uint256);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
pragma solidity ^0.8.0;
import "./ContextUpgradeable.sol";
import "./Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
import "./Initializable.sol";
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuardUpgradeable is Initializable {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal onlyInitializing {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "./IERC20Upgradeable.sol";
import "./AddressUpgradeable.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20Upgradeable {
using AddressUpgradeable for address;
function safeTransfer(
IERC20Upgradeable token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20Upgradeable token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20Upgradeable token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20Upgradeable token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20Upgradeable token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
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":"account","type":"address"}],"name":"AccountMigratedToAutoCooldown","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"GlobalCheckpoint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"prevSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"supply","type":"uint256"}],"name":"Supply","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum veSPA.ActionType","name":"actionType","type":"uint8"},{"indexed":false,"internalType":"bool","name":"autoCooldown","type":"bool"},{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"locktime","type":"uint256"}],"name":"UserCheckpoint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"I_MIN_TIME","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"I_YEAR","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MULTIPLIER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SPA","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WEEK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"ts","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"balanceOfAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"checkpoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"value","type":"uint128"},{"internalType":"uint256","name":"unlockTime","type":"uint256"},{"internalType":"bool","name":"autoCooldown","type":"bool"}],"name":"createLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint128","name":"value","type":"uint128"}],"name":"depositFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"epoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"autoCooldown","type":"bool"},{"internalType":"uint128","name":"value","type":"uint128"},{"internalType":"uint256","name":"expectedUnlockTime","type":"uint256"}],"name":"estimateDeposit","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"int128","name":"initialVespaBalance","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"residue","type":"int128"},{"internalType":"uint256","name":"actualUnlockTime","type":"uint256"},{"internalType":"uint256","name":"providedUnlockTime","type":"uint256"},{"internalType":"uint256","name":"residuePeriodStart","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getLastUserSlope","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"idx","type":"uint256"}],"name":"getUserPointHistoryTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"value","type":"uint128"}],"name":"increaseAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"unlockTime","type":"uint256"}],"name":"increaseUnlockTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initiateCooldown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lockedBalances","outputs":[{"internalType":"bool","name":"autoCooldown","type":"bool"},{"internalType":"bool","name":"cooldownInitiated","type":"bool"},{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint256","name":"end","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"lockedEnd","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_accounts","type":"address[]"}],"name":"migrateToAutoCooldown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pointHistory","outputs":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"int128","name":"residue","type":"int128"},{"internalType":"uint256","name":"ts","type":"uint256"},{"internalType":"uint256","name":"blk","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"slopeChanges","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSPALocked","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":"uint256","name":"ts","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"totalSupplyAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userPointEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userPointHistory","outputs":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"int128","name":"residue","type":"int128"},{"internalType":"uint256","name":"ts","type":"uint256"},{"internalType":"uint256","name":"blk","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b50600054610100900460ff166200002f5760005460ff161562000039565b62000039620000de565b620000a15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b600054610100900460ff16158015620000c4576000805461ffff19166101011790555b8015620000d7576000805461ff00191690555b506200010b565b6000620000f630620000fc60201b62001df31760201c565b15905090565b6001600160a01b03163b151590565b6134ba806200011b6000396000f3fe608060405234801561001057600080fd5b506004361061023c5760003560e01c806381fc83bb1161013b578063bd85b039116100b8578063eda2108d1161007c578063eda2108d14610670578063f2fde38b1461067b578063f3a6d6081461068e578063f4359ce5146106a1578063f52a36f7146106ab57600080fd5b8063bd85b03914610601578063c2c4c5c114610614578063cd48098e1461061c578063e2c5b4d214610624578063ebc65dbd1461065d57600080fd5b8063911dcf5c116100ff578063911dcf5c1461058757806395d89b41146105a4578063981b24d0146105c85780639a3f14f7146105db5780639cdd6fa5146105ee57600080fd5b806381fc83bb146104fe5780638ad4c4471461051e5780638da5cb5b146105655780638ff07b5b14610576578063900cf0cf1461057e57600080fd5b80633ccfd60b116101c9578063538daac41161018d578063538daac41461049d57806354fd4d50146104c857806370a08231146104d0578063715018a6146104e35780637c616fe6146104eb57600080fd5b80633ccfd60b1461043857806344e83ccf146104425780634deafcae1461044b5780634e3430ca146104775780634ee2cd7e1461048a57600080fd5b806306fdde031161021057806306fdde031461034b57806318160ddd14610386578063269499841461038e578063313ce5671461039957806334d901a4146103b357600080fd5b8062fdd58e14610241578063034a2c36146102675780630483a7f6146102c4578063059f8b161461033c575b600080fd5b61025461024f366004612e6e565b6106ce565b6040519081526020015b60405180910390f35b61027a610275366004612ebd565b6107cd565b604080519815158952600f97880b60208a015295870b9588019590955292850b6060870152930b608085015260a084019290925260c083019190915260e08201526101000161025e565b61030b6102d2366004612efb565b609d602052600090815260409020805460019091015460ff80831692610100810490911691620100009091046001600160801b03169084565b60405161025e9493929190931515845291151560208401526001600160801b03166040830152606082015260800190565b610254670de0b6b3a764000081565b6103796040518060400160405280600f81526020016e566f74652d657363726f772053504160881b81525081565b60405161025e9190612f42565b61025461091e565b610254630784ce0081565b6103a1601281565b60405160ff909116815260200161025e565b6104056103c1366004612e6e565b609e6020908152600092835260408084209091529082529020805460018201546002830154600390930154600f83810b94600160801b909404810b9392900b919085565b60408051600f96870b815294860b60208601529290940b918301919091526060820152608081019190915260a00161025e565b61044061092e565b005b61025460985481565b610254610459366004612efb565b6001600160a01b03166000908152609d602052604090206001015490565b610440610485366004612f75565b610c21565b610254610498366004612e6e565b610db2565b6099546104b0906001600160a01b031681565b6040516001600160a01b03909116815260200161025e565b6103796110aa565b6102546104de366004612efb565b611138565b610440611144565b6104406104f9366004612f90565b6111aa565b61025461050c366004612efb565b609f6020526000908152604090205481565b61040561052c366004612f90565b609b602052600090815260409020805460018201546002830154600390930154600f83810b94600160801b909404810b9392900b919085565b6033546001600160a01b03166104b0565b610254611359565b610254609a5481565b61059162093a8081565b604051600f9190910b815260200161025e565b61037960405180604001604052806005815260200164766553504160d81b81525081565b6102546105d6366004612f90565b61136a565b6104406105e9366004612fa9565b611513565b6104406105fc366004612fdc565b6116c6565b61025461060f366004612f90565b61187c565b6104406118f5565b61044061193e565b610254610632366004612e6e565b6001600160a01b03919091166000908152609e60209081526040808320938352929052206002015490565b61044061066b366004613051565b611aa5565b6105916301e1338081565b610440610689366004612efb565b611ccb565b61059161069c366004612efb565b611d96565b61025462093a8081565b6105916106b9366004612f90565b609c60205260009081526040902054600f0b81565b6000806106db8484611e02565b9050806106ec5760009150506107c7565b6001600160a01b0384166000908152609e60209081526040808320848452825291829020825160a0810184528154600f81810b8352600160801b909104810b93820193909352600182015490920b9282019290925260028201546060820181905260039092015460808201529061076390856130a7565b816020015161077291906130e6565b8151829061078190839061317b565b600f90810b90915282516000910b1215905061079c57600081525b6040810151815182906107b09083906131cb565b600f90810b909152915190910b92506107c7915050565b92915050565b60008080808080808062093a806107e4818b613230565b6107ee9190613244565b925042831161083e5760405162461bcd60e51b815260206004820152601760248201527610d85b9b9bdd081b1bd8dac81a5b881d1a19481c185cdd604a1b60448201526064015b60405180910390fd5b61084c630784ce0042613263565b83111561086b5760405162461bcd60e51b81526004016108359061327b565b8961087a6301e13380826132b2565b96508b6108d7576301e1338061089362093a80836130e6565b61089d91906132b2565b94506108ac62093a80856132f0565b9150426108bc62093a80866132f0565b6108c691906130a7565b6108d090886130e6565b95506108ee565b6108e142856130a7565b6108eb90886130e6565b95505b600086600f0b136108fe57600095505b61090885876131cb565b8c99509750899250509397509397509397509397565b60006109294261187c565b905090565b600260655414156109515760405162461bcd60e51b815260040161083590613307565b6002606555336000818152609d60209081526040918290208251608081018452815460ff80821615158352610100820416151593820193909352620100009092046001600160801b0316928201839052600101546060820152906109c75760405162461bcd60e51b81526004016108359061333e565b8060200151610a105760405162461bcd60e51b8152602060048201526015602482015274139bc818dbdbdb191bdddb881a5b9a5d1a585d1959605a1b6044820152606401610835565b8060600151421015610a585760405162461bcd60e51b81526020600482015260116024820152702637b1b5903737ba1032bc3834b932b21760791b6044820152606401610835565b6040818101516001600160a01b0384166000818152609d6020818152858320865160808082018952825460ff80821615158452610100808304909116151584870152620100008083046001600160801b03908116868e01526001870180546060808901919091528e519687018f528b8752868a018c81529e87018c81529087018c81529c8c529990985293519b51975161ffff199093169b151561ff0019169b909b17961515029590951762010000600160901b0319169481169098029390931790559251909255609880549394929392851691610b3683856132f0565b9091555050604080516080810182526000808252602082018190529181018290526060810191909152610b6c9086908490611eba565b609954610b8c906001600160a01b0316866001600160801b038616612351565b604080516001600160801b03851681524260208201526001600160a01b038716917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568910160405180910390a26098546040805183815260208101929092527f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c910160405180910390a150506001606555505050565b60026065541415610c445760405162461bcd60e51b815260040161083590613307565b6002606555336000818152609d60209081526040918290208251608081018452815460ff808216151583526101008204161515938201939093526001600160801b03620100009093048316938101939093526001015460608301528316610ce75760405162461bcd60e51b815260206004820152601760248201527643616e6e6f74206465706f736974203020746f6b656e7360481b6044820152606401610835565b600081604001516001600160801b031611610d145760405162461bcd60e51b81526004016108359061333e565b8051610d6c57806020015115610d6c5760405162461bcd60e51b815260206004820152601e60248201527f43616e6e6f74206465706f73697420647572696e6720636f6f6c646f776e00006044820152606401610835565b42816060015111610d8f5760405162461bcd60e51b81526004016108359061336e565b610da882826000015183602001518660008660026123b4565b5050600160655550565b6001600160a01b0382166000908152609f60205260408120548190815b6080811015610e6057818310610de457610e60565b60006002610df28486613263565b610dfd906001613263565b610e079190613230565b6001600160a01b0388166000908152609e602090815260408083208484529091529020600301549091508610610e3f57809350610e4d565b610e4a6001826132f0565b92505b5080610e588161339e565b915050610dcf565b506001600160a01b0385166000908152609e602090815260408083208584528252808320815160a0810183528154600f81810b8352600160801b909104810b94820194909452600182015490930b9183019190915260028101546060830152600301546080820152609a549091610ed787836125c6565b6000818152609b60209081526040808320815160a0810183528154600f81810b8352600160801b909104810b94820194909452600182015490930b91830191909152600281015460608301526003015460808201529192508084841015610fd0576000609b81610f48876001613263565b81526020808201929092526040908101600020815160a0810183528154600f81810b8352600160801b909104810b94820194909452600182015490930b9183019190915260028101546060830152600301546080808301829052860151919250610fb291906132f0565b925083606001518160600151610fc891906132f0565b915050610ff4565b6080830151610fdf908b6132f0565b9150826060015142610ff191906132f0565b90505b60608301518215611031578284608001518c61101091906132f0565b61101a9084613244565b6110249190613230565b61102e9082613263565b90505b606087015161104090826130a7565b876020015161104f91906130e6565b8751889061105e90839061317b565b600f90810b90915288516000910b1215905061107957600087525b60408701518751889061108d9083906131cb565b600f90810b909152975190970b9c9b505050505050505050505050565b609780546110b7906133b9565b80601f01602080910402602001604051908101604052809291908181526020018280546110e3906133b9565b80156111305780601f1061110557610100808354040283529160200191611130565b820191906000526020600020905b81548152906001019060200180831161111357829003601f168201915b505050505081565b60006107c782426106ce565b6033546001600160a01b0316331461119e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610835565b6111a86000612648565b565b336000818152609d602090815260408083208151608081018352815460ff80821615158352610100820416151594820194909452620100009093046001600160801b0316918301919091526001015460608201529062093a8061120d8186613230565b6112179190613244565b9050600082604001516001600160801b0316116112465760405162461bcd60e51b81526004016108359061333e565b8151611297578160200151156112975760405162461bcd60e51b81526020600482015260166024820152752232b837b9b4ba1034b99034b71031b7b7b63237bbb760511b6044820152606401610835565b428260600151116112ba5760405162461bcd60e51b81526004016108359061336e565b8160600151811161130d5760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610835565b61131b630784ce0042613263565b81111561133a5760405162461bcd60e51b81526004016108359061327b565b61135383836000015184602001516000858760036123b4565b50505050565b61136762093a806001613244565b81565b60004382111561137957600080fd5b609a54600061138884836125c6565b6000818152609b60209081526040808320815160a0810183528154600f81810b8352600160801b909104810b94820194909452600182015490930b9183019190915260028101546060830152600301546080820152919250838310156114a1576000609b816113f8866001613263565b81526020808201929092526040908101600020815160a0810183528154600f81810b8352600160801b909104810b94820194909452600182015490930b918301919091526002810154606083015260030154608080830182905285015191925061146291906132f0565b8360600151826060015161147691906132f0565b6080850151611485908a6132f0565b61148f9190613244565b6114999190613230565b9150506114f0565b438260800151146114f05760808201516114bb90436132f0565b60608301516114ca90426132f0565b60808401516114d990896132f0565b6114e39190613244565b6114ed9190613230565b90505b611509828284606001516115049190613263565b61269a565b9695505050505050565b600260655414156115365760405162461bcd60e51b815260040161083590613307565b60026065556001600160a01b0382166000908152609d60209081526040918290208251608081018452815460ff808216151583526101008204161515938201939093526001600160801b036201000090930483169381019390935260010154606083015282166115e25760405162461bcd60e51b815260206004820152601760248201527643616e6e6f74206465706f736974203020746f6b656e7360481b6044820152606401610835565b600081604001516001600160801b0316116116325760405162461bcd60e51b815260206004820152601060248201526f4e6f206578697374696e67206c6f636b60801b6044820152606401610835565b805161168a5780602001511561168a5760405162461bcd60e51b815260206004820152601e60248201527f43616e6e6f74206465706f73697420647572696e6720636f6f6c646f776e00006044820152606401610835565b428160600151116116ad5760405162461bcd60e51b81526004016108359061336e565b610da883826000015183602001518560008660006123b4565b60005b60ff8116821115611877576000609d600085858560ff168181106116ef576116ef6133f4565b90506020020160208101906117049190612efb565b6001600160a01b0316815260208082019290925260409081016000208151608081018352815460ff80821615158352610100820416151594820194909452620100009093046001600160801b03169183018290526001015460608301529091501580159061177457508060200151155b1561186e57606081015161178c62093a806001613244565b826060015161179b91906132f0565b42106117d25762093a80806117b1816001613244565b6117bb9042613263565b6117c59190613230565b6117cf9190613244565b90505b61180d85858560ff168181106117ea576117ea6133f4565b90506020020160208101906117ff9190612efb565b6001806000858760046123b4565b84848460ff16818110611822576118226133f4565b90506020020160208101906118379190612efb565b6001600160a01b03167f81952138acbb5225a661a862f9c3a02f7d897698881ae015580a86d334007ef960405160405180910390a2505b506001016116c9565b505050565b600080611888836127b6565b6000818152609b6020908152604091829020825160a0810184528154600f81810b8352600160801b909104810b93820193909352600182015490920b928201929092526002820154606082015260039091015460808201529091506118ed818561269a565b949350505050565b6118fd612845565b50609a5460408051338152602081019290925280517fb2f2e419d90cdd327434f0dcf95856b4393cdeca3bb6506d39d9619e2572a55d9281900390910190a1565b336000818152609d60209081526040918290208251608081018452815460ff80821615158352610100820416151593820193909352620100009092046001600160801b0316928201839052600101546060820152906119af5760405162461bcd60e51b81526004016108359061333e565b806020015115611a015760405162461bcd60e51b815260206004820152601a60248201527f436f6f6c646f776e20616c726561647920696e697469617465640000000000006044820152606401610835565b6060810151611a1462093a806001613244565b8260600151611a2391906132f0565b4210611a5e5762093a8080611a39816001613244565b611a439042613263565b611a4d9190613230565b611a579190613244565b9050611a93565b6040516001600160a01b038416907f81952138acbb5225a661a862f9c3a02f7d897698881ae015580a86d334007ef990600090a25b611877836001806000858760046123b4565b60026065541415611ac85760405162461bcd60e51b815260040161083590613307565b600260655580611b1a5760405162461bcd60e51b815260206004820152601a60248201527f4d616e75616c20636f6f6c646f776e20646570726563617465640000000000006044820152606401610835565b33600062093a80611b2b8186613230565b611b359190613244565b6001600160a01b0383166000908152609d60209081526040918290208251608081018452815460ff808216151583526101008204161515938201939093526001600160801b0362010000909304831693810193909352600101546060830152919250908616611bdd5760405162461bcd60e51b815260206004820152601460248201527343616e6e6f74206c6f636b203020746f6b656e7360601b6044820152606401610835565b60408101516001600160801b031615611c385760405162461bcd60e51b815260206004820152601960248201527f5769746864726177206f6c6420746f6b656e73206669727374000000000000006044820152606401610835565b428211611c815760405162461bcd60e51b815260206004820152601760248201527610d85b9b9bdd081b1bd8dac81a5b881d1a19481c185cdd604a1b6044820152606401610835565b611c8f630784ce0042613263565b821115611cae5760405162461bcd60e51b81526004016108359061327b565b611cbe83858689868660016123b4565b5050600160655550505050565b6033546001600160a01b03163314611d255760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610835565b6001600160a01b038116611d8a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610835565b611d9381612648565b50565b6001600160a01b0381166000908152609f602052604081205480611dbd5750600092915050565b6001600160a01b039092166000908152609e602090815260408083209483529390529190912054600160801b9004600f0b919050565b6001600160a01b03163b151590565b6001600160a01b0382166000908152609f60205260408120548190815b6080811015611eb057818310611e3457611eb0565b60006002611e428486613263565b611e4d906001613263565b611e579190613230565b6001600160a01b0388166000908152609e602090815260408083208484529091529020600201549091508610611e8f57809350611e9d565b611e9a6001826132f0565b92505b5080611ea88161339e565b915050611e1f565b5090949350505050565b6040805160a0808201835260008083526020808401829052838501829052606080850183905260808086018490528651948501875283855291840183905283860183905283018290528201819052928501519192909181906001600160801b031615611fb65760408601516020870151611f6d576301e13380611f4062093a80836130e6565b611f4a91906132b2565b600f0b604086015260608701805162093a809190611f699083906132f0565b9052505b4287606001511115611fb457611f876301e13380826132b2565b600f0b60208601526060870151611f9f9042906130a7565b8560200151611fae91906130e6565b600f0b85525b505b428560600151118015611fd65750600085604001516001600160801b0316115b156120715760408501516020860151612028576301e13380611ffb62093a80836130e6565b61200591906132b2565b600f0b604085015260608601805162093a8091906120249083906132f0565b9052505b428660600151111561206f576120426301e13380826132b2565b600f0b6020850152606086015161205a9042906130a7565b846020015161206991906130e6565b600f0b84525b505b6060808701516000908152609c602052604090205490860151600f9190910b9250156120b0575060608401516000908152609c6020526040902054600f0b5b60006120ba612845565b9050846020015184602001516120d0919061317b565b816020018181516120e191906131cb565b600f0b905250845184516120f5919061317b565b815182906121049083906131cb565b600f0b9052506040808601519085015161211e919061317b565b8160400181815161212f91906131cb565b600f90810b90915260208301516000910b1215905061215057600060208201525b60008160000151600f0b121561216557600081525b609a546000908152609b60209081526040918290208351918401516001600160801b03928316600160801b91841691909102178155918301516001830180546001600160801b03191691909216179055606080830151600283015560808301516003909201919091558701514210156122385760208501516121e790846131cb565b925086606001518660600151141561220b576020840151612208908461317b565b92505b60608701516000908152609c6020526040902080546001600160801b0319166001600160801b0385161790555b428660600151111561229257866060015186606001511115612292576020840151612263908361317b565b60608701516000908152609c6020526040902080546001600160801b0319166001600160801b03831617905591505b6001600160a01b0388166000908152609f60205260408120546122b6906001613263565b6001600160a01b03999099166000818152609f602090815260408083208d90554260608a019081524360808b01908152948452609e83528184209d84529c8252918290208851918901516001600160801b03928316600160801b9184169190910217815597909101516001880180546001600160801b0319169190921617905598516002860155505095516003909201919091555050505050565b6040516001600160a01b03831660248201526044810182905261187790849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612bc5565b6001600160a01b0387166000908152609d60209081526040918290208251608081018452815460ff80821615158352610100820416151593820193909352620100009092046001600160801b03169282018381526001909101546060830152609854919287919061242690839061340a565b6001600160801b031690525087151582528615156020830152841561244d57606082018590525b6001600160a01b0389166000908152609d60209081526040918290208451815492860151938601516001600160801b0316620100000262010000600160901b03199415156101000261ff00199215159290921661ffff1990941693909317179290921617815560608301516001909101556124c9898584611eba565b6001600160801b0386161561255757856001600160801b0316609860008282546124f39190613263565b9091555050609954612519906001600160a01b031633306001600160801b038a16612c97565b6098546040805183815260208101929092527f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c910160405180910390a15b8160600151896001600160a01b031684600481111561257857612578613435565b604080518c151581526001600160801b038b1660208201527f9a7b21c193646897f8def2fc65f28a8f447f652977be32b571ce38ce787529a7910160405180910390a4505050505050505050565b60008082815b6080811015611eb0578183106125e157611eb0565b600060026125ef8486613263565b6125fa906001613263565b6126049190613230565b6000818152609b6020526040902060030154909150871061262757809350612635565b6126326001826132f0565b92505b50806126408161339e565b9150506125cc565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600080839050600062093a808083606001516126b69190613230565b6126c09190613244565b905060005b60ff811015612776576126db62093a8083613263565b91506000858311156126ef57859250612703565b506000828152609c6020526040902054600f0b5b606084015161271290846130a7565b846020015161272191906130e6565b8451859061273090839061317b565b600f0b905250828614156127445750612776565b808460200181815161275691906131cb565b600f0b90525050606083018290528061276e8161339e565b9150506126c5565b5060008260000151600f0b121561278c57600082525b6040820151825183906127a09083906131cb565b600f90810b909152925190920b95945050505050565b609a546000908190815b608081101561283c578183106127d55761283c565b600060026127e38486613263565b6127ee906001613263565b6127f89190613230565b6000818152609b6020526040902060020154909150861061281b57809350612829565b6128266001826132f0565b92505b50806128348161339e565b9150506127c0565b50909392505050565b6040805160a080820183526000808352602080840182905283850182905260608085018390526080948501839052609a5486518086018852848152808401859052808801859052428184018190524382890181905289519788018a52868852948701869052978601949094529084019590955292820192909252909190811561295457506000818152609b60208181526040808420815160a080820184528254600f81810b808552600160801b909204810b848801819052600186015490910b8487018190526002860154606080870182905260039097015460808088018290529b8d905299895287519485018852928452968301529381019490945290830191909152928101919091529092505b60608301516000428210156129a057606085015161297290426132f0565b608086015161298190436132f0565b61299390670de0b6b3a7640000613244565b61299d9190613230565b90505b600062093a806129b08185613230565b6129ba9190613244565b905060005b60ff811015612bb5576129d562093a8083613263565b91506000428311156129e9574292506129fd565b506000828152609c6020526040902054600f0b5b612a0785846130a7565b8860200151612a1691906130e6565b88518990612a2590839061317b565b600f0b905250602088018051829190612a3f9083906131cb565b600f90810b90915289516000910b12159050612a5a57600088525b60008860200151600f0b1215612a7257600060208901525b60608089018490528601519294508492670de0b6b3a764000090612a9690856132f0565b612aa09086613244565b612aaa9190613230565b8660800151612ab99190613263565b6080890152612ac9600188613263565b965042831415612b40575043608088019081526000878152609b60209081526040918290208a51918b01516001600160801b03928316600160801b91841691909102178155918a01516001830180546001600160801b03191691909216179055606089015160028201559051600390910155612bb5565b506000868152609b60209081526040918290208951918a01516001600160801b03928316600160801b91841691909102178155918901516001830180546001600160801b0319169190921617905560608801516002820155608088015160039091015580612bad8161339e565b9150506129bf565b505083609a819055505050505090565b6000612c1a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612ccf9092919063ffffffff16565b8051909150156118775780806020019051810190612c38919061344b565b6118775760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610835565b6040516001600160a01b03808516602483015283166044820152606481018290526113539085906323b872dd60e01b9060840161237d565b6060612cde8484600085612ce8565b90505b9392505050565b606082471015612d495760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610835565b6001600160a01b0385163b612da05760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610835565b600080866001600160a01b03168587604051612dbc9190613468565b60006040518083038185875af1925050503d8060008114612df9576040519150601f19603f3d011682016040523d82523d6000602084013e612dfe565b606091505b5091509150612e0e828286612e19565b979650505050505050565b60608315612e28575081612ce1565b825115612e385782518084602001fd5b8160405162461bcd60e51b81526004016108359190612f42565b80356001600160a01b0381168114612e6957600080fd5b919050565b60008060408385031215612e8157600080fd5b612e8a83612e52565b946020939093013593505050565b8015158114611d9357600080fd5b80356001600160801b0381168114612e6957600080fd5b600080600060608486031215612ed257600080fd5b8335612edd81612e98565b9250612eeb60208501612ea6565b9150604084013590509250925092565b600060208284031215612f0d57600080fd5b612ce182612e52565b60005b83811015612f31578181015183820152602001612f19565b838111156113535750506000910152565b6020815260008251806020840152612f61816040850160208701612f16565b601f01601f19169190910160400192915050565b600060208284031215612f8757600080fd5b612ce182612ea6565b600060208284031215612fa257600080fd5b5035919050565b60008060408385031215612fbc57600080fd5b612fc583612e52565b9150612fd360208401612ea6565b90509250929050565b60008060208385031215612fef57600080fd5b823567ffffffffffffffff8082111561300757600080fd5b818501915085601f83011261301b57600080fd5b81358181111561302a57600080fd5b8660208260051b850101111561303f57600080fd5b60209290920196919550909350505050565b60008060006060848603121561306657600080fd5b61306f84612ea6565b925060208401359150604084013561308681612e98565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b60008083128015600160ff1b8501841216156130c5576130c5613091565b6001600160ff1b03840183138116156130e0576130e0613091565b50500390565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561311657613116613091565b60016001607f1b0319600085128281168783058712161561313957613139613091565b6000871292508582058712848416161561315557613155613091565b8585058712818416161561316b5761316b613091565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156131a6576131a6613091565b8160016001607f1b030183138116156131c1576131c1613091565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b03038213811516156131f5576131f5613091565b8260016001607f1b031903821281161561321157613211613091565b50019392505050565b634e487b7160e01b600052601260045260246000fd5b60008261323f5761323f61321a565b500490565b600081600019048311821515161561325e5761325e613091565b500290565b6000821982111561327657613276613091565b500190565b6020808252601e908201527f566f74696e67206c6f636b2063616e2062652034207965617273206d61780000604082015260600190565b600081600f0b83600f0b806132c9576132c961321a565b60016001607f1b03198214600019821416156132e7576132e7613091565b90059392505050565b60008282101561330257613302613091565b500390565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b602080825260169082015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b604082015260600190565b6020808252601690820152754c6f636b20657870697265642e20576974686472617760501b604082015260600190565b60006000198214156133b2576133b2613091565b5060010190565b600181811c908216806133cd57607f821691505b602082108114156133ee57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b60006001600160801b0380831681851680830382111561342c5761342c613091565b01949350505050565b634e487b7160e01b600052602160045260246000fd5b60006020828403121561345d57600080fd5b8151612ce181612e98565b6000825161347a818460208701612f16565b919091019291505056fea2646970667358221220a61c67c2ca99138567813b6e0746a7dd4651ae50d0a8694935b7c0f8febfb12364736f6c634300080a0033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061023c5760003560e01c806381fc83bb1161013b578063bd85b039116100b8578063eda2108d1161007c578063eda2108d14610670578063f2fde38b1461067b578063f3a6d6081461068e578063f4359ce5146106a1578063f52a36f7146106ab57600080fd5b8063bd85b03914610601578063c2c4c5c114610614578063cd48098e1461061c578063e2c5b4d214610624578063ebc65dbd1461065d57600080fd5b8063911dcf5c116100ff578063911dcf5c1461058757806395d89b41146105a4578063981b24d0146105c85780639a3f14f7146105db5780639cdd6fa5146105ee57600080fd5b806381fc83bb146104fe5780638ad4c4471461051e5780638da5cb5b146105655780638ff07b5b14610576578063900cf0cf1461057e57600080fd5b80633ccfd60b116101c9578063538daac41161018d578063538daac41461049d57806354fd4d50146104c857806370a08231146104d0578063715018a6146104e35780637c616fe6146104eb57600080fd5b80633ccfd60b1461043857806344e83ccf146104425780634deafcae1461044b5780634e3430ca146104775780634ee2cd7e1461048a57600080fd5b806306fdde031161021057806306fdde031461034b57806318160ddd14610386578063269499841461038e578063313ce5671461039957806334d901a4146103b357600080fd5b8062fdd58e14610241578063034a2c36146102675780630483a7f6146102c4578063059f8b161461033c575b600080fd5b61025461024f366004612e6e565b6106ce565b6040519081526020015b60405180910390f35b61027a610275366004612ebd565b6107cd565b604080519815158952600f97880b60208a015295870b9588019590955292850b6060870152930b608085015260a084019290925260c083019190915260e08201526101000161025e565b61030b6102d2366004612efb565b609d602052600090815260409020805460019091015460ff80831692610100810490911691620100009091046001600160801b03169084565b60405161025e9493929190931515845291151560208401526001600160801b03166040830152606082015260800190565b610254670de0b6b3a764000081565b6103796040518060400160405280600f81526020016e566f74652d657363726f772053504160881b81525081565b60405161025e9190612f42565b61025461091e565b610254630784ce0081565b6103a1601281565b60405160ff909116815260200161025e565b6104056103c1366004612e6e565b609e6020908152600092835260408084209091529082529020805460018201546002830154600390930154600f83810b94600160801b909404810b9392900b919085565b60408051600f96870b815294860b60208601529290940b918301919091526060820152608081019190915260a00161025e565b61044061092e565b005b61025460985481565b610254610459366004612efb565b6001600160a01b03166000908152609d602052604090206001015490565b610440610485366004612f75565b610c21565b610254610498366004612e6e565b610db2565b6099546104b0906001600160a01b031681565b6040516001600160a01b03909116815260200161025e565b6103796110aa565b6102546104de366004612efb565b611138565b610440611144565b6104406104f9366004612f90565b6111aa565b61025461050c366004612efb565b609f6020526000908152604090205481565b61040561052c366004612f90565b609b602052600090815260409020805460018201546002830154600390930154600f83810b94600160801b909404810b9392900b919085565b6033546001600160a01b03166104b0565b610254611359565b610254609a5481565b61059162093a8081565b604051600f9190910b815260200161025e565b61037960405180604001604052806005815260200164766553504160d81b81525081565b6102546105d6366004612f90565b61136a565b6104406105e9366004612fa9565b611513565b6104406105fc366004612fdc565b6116c6565b61025461060f366004612f90565b61187c565b6104406118f5565b61044061193e565b610254610632366004612e6e565b6001600160a01b03919091166000908152609e60209081526040808320938352929052206002015490565b61044061066b366004613051565b611aa5565b6105916301e1338081565b610440610689366004612efb565b611ccb565b61059161069c366004612efb565b611d96565b61025462093a8081565b6105916106b9366004612f90565b609c60205260009081526040902054600f0b81565b6000806106db8484611e02565b9050806106ec5760009150506107c7565b6001600160a01b0384166000908152609e60209081526040808320848452825291829020825160a0810184528154600f81810b8352600160801b909104810b93820193909352600182015490920b9282019290925260028201546060820181905260039092015460808201529061076390856130a7565b816020015161077291906130e6565b8151829061078190839061317b565b600f90810b90915282516000910b1215905061079c57600081525b6040810151815182906107b09083906131cb565b600f90810b909152915190910b92506107c7915050565b92915050565b60008080808080808062093a806107e4818b613230565b6107ee9190613244565b925042831161083e5760405162461bcd60e51b815260206004820152601760248201527610d85b9b9bdd081b1bd8dac81a5b881d1a19481c185cdd604a1b60448201526064015b60405180910390fd5b61084c630784ce0042613263565b83111561086b5760405162461bcd60e51b81526004016108359061327b565b8961087a6301e13380826132b2565b96508b6108d7576301e1338061089362093a80836130e6565b61089d91906132b2565b94506108ac62093a80856132f0565b9150426108bc62093a80866132f0565b6108c691906130a7565b6108d090886130e6565b95506108ee565b6108e142856130a7565b6108eb90886130e6565b95505b600086600f0b136108fe57600095505b61090885876131cb565b8c99509750899250509397509397509397509397565b60006109294261187c565b905090565b600260655414156109515760405162461bcd60e51b815260040161083590613307565b6002606555336000818152609d60209081526040918290208251608081018452815460ff80821615158352610100820416151593820193909352620100009092046001600160801b0316928201839052600101546060820152906109c75760405162461bcd60e51b81526004016108359061333e565b8060200151610a105760405162461bcd60e51b8152602060048201526015602482015274139bc818dbdbdb191bdddb881a5b9a5d1a585d1959605a1b6044820152606401610835565b8060600151421015610a585760405162461bcd60e51b81526020600482015260116024820152702637b1b5903737ba1032bc3834b932b21760791b6044820152606401610835565b6040818101516001600160a01b0384166000818152609d6020818152858320865160808082018952825460ff80821615158452610100808304909116151584870152620100008083046001600160801b03908116868e01526001870180546060808901919091528e519687018f528b8752868a018c81529e87018c81529087018c81529c8c529990985293519b51975161ffff199093169b151561ff0019169b909b17961515029590951762010000600160901b0319169481169098029390931790559251909255609880549394929392851691610b3683856132f0565b9091555050604080516080810182526000808252602082018190529181018290526060810191909152610b6c9086908490611eba565b609954610b8c906001600160a01b0316866001600160801b038616612351565b604080516001600160801b03851681524260208201526001600160a01b038716917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568910160405180910390a26098546040805183815260208101929092527f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c910160405180910390a150506001606555505050565b60026065541415610c445760405162461bcd60e51b815260040161083590613307565b6002606555336000818152609d60209081526040918290208251608081018452815460ff808216151583526101008204161515938201939093526001600160801b03620100009093048316938101939093526001015460608301528316610ce75760405162461bcd60e51b815260206004820152601760248201527643616e6e6f74206465706f736974203020746f6b656e7360481b6044820152606401610835565b600081604001516001600160801b031611610d145760405162461bcd60e51b81526004016108359061333e565b8051610d6c57806020015115610d6c5760405162461bcd60e51b815260206004820152601e60248201527f43616e6e6f74206465706f73697420647572696e6720636f6f6c646f776e00006044820152606401610835565b42816060015111610d8f5760405162461bcd60e51b81526004016108359061336e565b610da882826000015183602001518660008660026123b4565b5050600160655550565b6001600160a01b0382166000908152609f60205260408120548190815b6080811015610e6057818310610de457610e60565b60006002610df28486613263565b610dfd906001613263565b610e079190613230565b6001600160a01b0388166000908152609e602090815260408083208484529091529020600301549091508610610e3f57809350610e4d565b610e4a6001826132f0565b92505b5080610e588161339e565b915050610dcf565b506001600160a01b0385166000908152609e602090815260408083208584528252808320815160a0810183528154600f81810b8352600160801b909104810b94820194909452600182015490930b9183019190915260028101546060830152600301546080820152609a549091610ed787836125c6565b6000818152609b60209081526040808320815160a0810183528154600f81810b8352600160801b909104810b94820194909452600182015490930b91830191909152600281015460608301526003015460808201529192508084841015610fd0576000609b81610f48876001613263565b81526020808201929092526040908101600020815160a0810183528154600f81810b8352600160801b909104810b94820194909452600182015490930b9183019190915260028101546060830152600301546080808301829052860151919250610fb291906132f0565b925083606001518160600151610fc891906132f0565b915050610ff4565b6080830151610fdf908b6132f0565b9150826060015142610ff191906132f0565b90505b60608301518215611031578284608001518c61101091906132f0565b61101a9084613244565b6110249190613230565b61102e9082613263565b90505b606087015161104090826130a7565b876020015161104f91906130e6565b8751889061105e90839061317b565b600f90810b90915288516000910b1215905061107957600087525b60408701518751889061108d9083906131cb565b600f90810b909152975190970b9c9b505050505050505050505050565b609780546110b7906133b9565b80601f01602080910402602001604051908101604052809291908181526020018280546110e3906133b9565b80156111305780601f1061110557610100808354040283529160200191611130565b820191906000526020600020905b81548152906001019060200180831161111357829003601f168201915b505050505081565b60006107c782426106ce565b6033546001600160a01b0316331461119e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610835565b6111a86000612648565b565b336000818152609d602090815260408083208151608081018352815460ff80821615158352610100820416151594820194909452620100009093046001600160801b0316918301919091526001015460608201529062093a8061120d8186613230565b6112179190613244565b9050600082604001516001600160801b0316116112465760405162461bcd60e51b81526004016108359061333e565b8151611297578160200151156112975760405162461bcd60e51b81526020600482015260166024820152752232b837b9b4ba1034b99034b71031b7b7b63237bbb760511b6044820152606401610835565b428260600151116112ba5760405162461bcd60e51b81526004016108359061336e565b8160600151811161130d5760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610835565b61131b630784ce0042613263565b81111561133a5760405162461bcd60e51b81526004016108359061327b565b61135383836000015184602001516000858760036123b4565b50505050565b61136762093a806001613244565b81565b60004382111561137957600080fd5b609a54600061138884836125c6565b6000818152609b60209081526040808320815160a0810183528154600f81810b8352600160801b909104810b94820194909452600182015490930b9183019190915260028101546060830152600301546080820152919250838310156114a1576000609b816113f8866001613263565b81526020808201929092526040908101600020815160a0810183528154600f81810b8352600160801b909104810b94820194909452600182015490930b918301919091526002810154606083015260030154608080830182905285015191925061146291906132f0565b8360600151826060015161147691906132f0565b6080850151611485908a6132f0565b61148f9190613244565b6114999190613230565b9150506114f0565b438260800151146114f05760808201516114bb90436132f0565b60608301516114ca90426132f0565b60808401516114d990896132f0565b6114e39190613244565b6114ed9190613230565b90505b611509828284606001516115049190613263565b61269a565b9695505050505050565b600260655414156115365760405162461bcd60e51b815260040161083590613307565b60026065556001600160a01b0382166000908152609d60209081526040918290208251608081018452815460ff808216151583526101008204161515938201939093526001600160801b036201000090930483169381019390935260010154606083015282166115e25760405162461bcd60e51b815260206004820152601760248201527643616e6e6f74206465706f736974203020746f6b656e7360481b6044820152606401610835565b600081604001516001600160801b0316116116325760405162461bcd60e51b815260206004820152601060248201526f4e6f206578697374696e67206c6f636b60801b6044820152606401610835565b805161168a5780602001511561168a5760405162461bcd60e51b815260206004820152601e60248201527f43616e6e6f74206465706f73697420647572696e6720636f6f6c646f776e00006044820152606401610835565b428160600151116116ad5760405162461bcd60e51b81526004016108359061336e565b610da883826000015183602001518560008660006123b4565b60005b60ff8116821115611877576000609d600085858560ff168181106116ef576116ef6133f4565b90506020020160208101906117049190612efb565b6001600160a01b0316815260208082019290925260409081016000208151608081018352815460ff80821615158352610100820416151594820194909452620100009093046001600160801b03169183018290526001015460608301529091501580159061177457508060200151155b1561186e57606081015161178c62093a806001613244565b826060015161179b91906132f0565b42106117d25762093a80806117b1816001613244565b6117bb9042613263565b6117c59190613230565b6117cf9190613244565b90505b61180d85858560ff168181106117ea576117ea6133f4565b90506020020160208101906117ff9190612efb565b6001806000858760046123b4565b84848460ff16818110611822576118226133f4565b90506020020160208101906118379190612efb565b6001600160a01b03167f81952138acbb5225a661a862f9c3a02f7d897698881ae015580a86d334007ef960405160405180910390a2505b506001016116c9565b505050565b600080611888836127b6565b6000818152609b6020908152604091829020825160a0810184528154600f81810b8352600160801b909104810b93820193909352600182015490920b928201929092526002820154606082015260039091015460808201529091506118ed818561269a565b949350505050565b6118fd612845565b50609a5460408051338152602081019290925280517fb2f2e419d90cdd327434f0dcf95856b4393cdeca3bb6506d39d9619e2572a55d9281900390910190a1565b336000818152609d60209081526040918290208251608081018452815460ff80821615158352610100820416151593820193909352620100009092046001600160801b0316928201839052600101546060820152906119af5760405162461bcd60e51b81526004016108359061333e565b806020015115611a015760405162461bcd60e51b815260206004820152601a60248201527f436f6f6c646f776e20616c726561647920696e697469617465640000000000006044820152606401610835565b6060810151611a1462093a806001613244565b8260600151611a2391906132f0565b4210611a5e5762093a8080611a39816001613244565b611a439042613263565b611a4d9190613230565b611a579190613244565b9050611a93565b6040516001600160a01b038416907f81952138acbb5225a661a862f9c3a02f7d897698881ae015580a86d334007ef990600090a25b611877836001806000858760046123b4565b60026065541415611ac85760405162461bcd60e51b815260040161083590613307565b600260655580611b1a5760405162461bcd60e51b815260206004820152601a60248201527f4d616e75616c20636f6f6c646f776e20646570726563617465640000000000006044820152606401610835565b33600062093a80611b2b8186613230565b611b359190613244565b6001600160a01b0383166000908152609d60209081526040918290208251608081018452815460ff808216151583526101008204161515938201939093526001600160801b0362010000909304831693810193909352600101546060830152919250908616611bdd5760405162461bcd60e51b815260206004820152601460248201527343616e6e6f74206c6f636b203020746f6b656e7360601b6044820152606401610835565b60408101516001600160801b031615611c385760405162461bcd60e51b815260206004820152601960248201527f5769746864726177206f6c6420746f6b656e73206669727374000000000000006044820152606401610835565b428211611c815760405162461bcd60e51b815260206004820152601760248201527610d85b9b9bdd081b1bd8dac81a5b881d1a19481c185cdd604a1b6044820152606401610835565b611c8f630784ce0042613263565b821115611cae5760405162461bcd60e51b81526004016108359061327b565b611cbe83858689868660016123b4565b5050600160655550505050565b6033546001600160a01b03163314611d255760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610835565b6001600160a01b038116611d8a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610835565b611d9381612648565b50565b6001600160a01b0381166000908152609f602052604081205480611dbd5750600092915050565b6001600160a01b039092166000908152609e602090815260408083209483529390529190912054600160801b9004600f0b919050565b6001600160a01b03163b151590565b6001600160a01b0382166000908152609f60205260408120548190815b6080811015611eb057818310611e3457611eb0565b60006002611e428486613263565b611e4d906001613263565b611e579190613230565b6001600160a01b0388166000908152609e602090815260408083208484529091529020600201549091508610611e8f57809350611e9d565b611e9a6001826132f0565b92505b5080611ea88161339e565b915050611e1f565b5090949350505050565b6040805160a0808201835260008083526020808401829052838501829052606080850183905260808086018490528651948501875283855291840183905283860183905283018290528201819052928501519192909181906001600160801b031615611fb65760408601516020870151611f6d576301e13380611f4062093a80836130e6565b611f4a91906132b2565b600f0b604086015260608701805162093a809190611f699083906132f0565b9052505b4287606001511115611fb457611f876301e13380826132b2565b600f0b60208601526060870151611f9f9042906130a7565b8560200151611fae91906130e6565b600f0b85525b505b428560600151118015611fd65750600085604001516001600160801b0316115b156120715760408501516020860151612028576301e13380611ffb62093a80836130e6565b61200591906132b2565b600f0b604085015260608601805162093a8091906120249083906132f0565b9052505b428660600151111561206f576120426301e13380826132b2565b600f0b6020850152606086015161205a9042906130a7565b846020015161206991906130e6565b600f0b84525b505b6060808701516000908152609c602052604090205490860151600f9190910b9250156120b0575060608401516000908152609c6020526040902054600f0b5b60006120ba612845565b9050846020015184602001516120d0919061317b565b816020018181516120e191906131cb565b600f0b905250845184516120f5919061317b565b815182906121049083906131cb565b600f0b9052506040808601519085015161211e919061317b565b8160400181815161212f91906131cb565b600f90810b90915260208301516000910b1215905061215057600060208201525b60008160000151600f0b121561216557600081525b609a546000908152609b60209081526040918290208351918401516001600160801b03928316600160801b91841691909102178155918301516001830180546001600160801b03191691909216179055606080830151600283015560808301516003909201919091558701514210156122385760208501516121e790846131cb565b925086606001518660600151141561220b576020840151612208908461317b565b92505b60608701516000908152609c6020526040902080546001600160801b0319166001600160801b0385161790555b428660600151111561229257866060015186606001511115612292576020840151612263908361317b565b60608701516000908152609c6020526040902080546001600160801b0319166001600160801b03831617905591505b6001600160a01b0388166000908152609f60205260408120546122b6906001613263565b6001600160a01b03999099166000818152609f602090815260408083208d90554260608a019081524360808b01908152948452609e83528184209d84529c8252918290208851918901516001600160801b03928316600160801b9184169190910217815597909101516001880180546001600160801b0319169190921617905598516002860155505095516003909201919091555050505050565b6040516001600160a01b03831660248201526044810182905261187790849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612bc5565b6001600160a01b0387166000908152609d60209081526040918290208251608081018452815460ff80821615158352610100820416151593820193909352620100009092046001600160801b03169282018381526001909101546060830152609854919287919061242690839061340a565b6001600160801b031690525087151582528615156020830152841561244d57606082018590525b6001600160a01b0389166000908152609d60209081526040918290208451815492860151938601516001600160801b0316620100000262010000600160901b03199415156101000261ff00199215159290921661ffff1990941693909317179290921617815560608301516001909101556124c9898584611eba565b6001600160801b0386161561255757856001600160801b0316609860008282546124f39190613263565b9091555050609954612519906001600160a01b031633306001600160801b038a16612c97565b6098546040805183815260208101929092527f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c910160405180910390a15b8160600151896001600160a01b031684600481111561257857612578613435565b604080518c151581526001600160801b038b1660208201527f9a7b21c193646897f8def2fc65f28a8f447f652977be32b571ce38ce787529a7910160405180910390a4505050505050505050565b60008082815b6080811015611eb0578183106125e157611eb0565b600060026125ef8486613263565b6125fa906001613263565b6126049190613230565b6000818152609b6020526040902060030154909150871061262757809350612635565b6126326001826132f0565b92505b50806126408161339e565b9150506125cc565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600080839050600062093a808083606001516126b69190613230565b6126c09190613244565b905060005b60ff811015612776576126db62093a8083613263565b91506000858311156126ef57859250612703565b506000828152609c6020526040902054600f0b5b606084015161271290846130a7565b846020015161272191906130e6565b8451859061273090839061317b565b600f0b905250828614156127445750612776565b808460200181815161275691906131cb565b600f0b90525050606083018290528061276e8161339e565b9150506126c5565b5060008260000151600f0b121561278c57600082525b6040820151825183906127a09083906131cb565b600f90810b909152925190920b95945050505050565b609a546000908190815b608081101561283c578183106127d55761283c565b600060026127e38486613263565b6127ee906001613263565b6127f89190613230565b6000818152609b6020526040902060020154909150861061281b57809350612829565b6128266001826132f0565b92505b50806128348161339e565b9150506127c0565b50909392505050565b6040805160a080820183526000808352602080840182905283850182905260608085018390526080948501839052609a5486518086018852848152808401859052808801859052428184018190524382890181905289519788018a52868852948701869052978601949094529084019590955292820192909252909190811561295457506000818152609b60208181526040808420815160a080820184528254600f81810b808552600160801b909204810b848801819052600186015490910b8487018190526002860154606080870182905260039097015460808088018290529b8d905299895287519485018852928452968301529381019490945290830191909152928101919091529092505b60608301516000428210156129a057606085015161297290426132f0565b608086015161298190436132f0565b61299390670de0b6b3a7640000613244565b61299d9190613230565b90505b600062093a806129b08185613230565b6129ba9190613244565b905060005b60ff811015612bb5576129d562093a8083613263565b91506000428311156129e9574292506129fd565b506000828152609c6020526040902054600f0b5b612a0785846130a7565b8860200151612a1691906130e6565b88518990612a2590839061317b565b600f0b905250602088018051829190612a3f9083906131cb565b600f90810b90915289516000910b12159050612a5a57600088525b60008860200151600f0b1215612a7257600060208901525b60608089018490528601519294508492670de0b6b3a764000090612a9690856132f0565b612aa09086613244565b612aaa9190613230565b8660800151612ab99190613263565b6080890152612ac9600188613263565b965042831415612b40575043608088019081526000878152609b60209081526040918290208a51918b01516001600160801b03928316600160801b91841691909102178155918a01516001830180546001600160801b03191691909216179055606089015160028201559051600390910155612bb5565b506000868152609b60209081526040918290208951918a01516001600160801b03928316600160801b91841691909102178155918901516001830180546001600160801b0319169190921617905560608801516002820155608088015160039091015580612bad8161339e565b9150506129bf565b505083609a819055505050505090565b6000612c1a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612ccf9092919063ffffffff16565b8051909150156118775780806020019051810190612c38919061344b565b6118775760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610835565b6040516001600160a01b03808516602483015283166044820152606481018290526113539085906323b872dd60e01b9060840161237d565b6060612cde8484600085612ce8565b90505b9392505050565b606082471015612d495760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610835565b6001600160a01b0385163b612da05760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610835565b600080866001600160a01b03168587604051612dbc9190613468565b60006040518083038185875af1925050503d8060008114612df9576040519150601f19603f3d011682016040523d82523d6000602084013e612dfe565b606091505b5091509150612e0e828286612e19565b979650505050505050565b60608315612e28575081612ce1565b825115612e385782518084602001fd5b8160405162461bcd60e51b81526004016108359190612f42565b80356001600160a01b0381168114612e6957600080fd5b919050565b60008060408385031215612e8157600080fd5b612e8a83612e52565b946020939093013593505050565b8015158114611d9357600080fd5b80356001600160801b0381168114612e6957600080fd5b600080600060608486031215612ed257600080fd5b8335612edd81612e98565b9250612eeb60208501612ea6565b9150604084013590509250925092565b600060208284031215612f0d57600080fd5b612ce182612e52565b60005b83811015612f31578181015183820152602001612f19565b838111156113535750506000910152565b6020815260008251806020840152612f61816040850160208701612f16565b601f01601f19169190910160400192915050565b600060208284031215612f8757600080fd5b612ce182612ea6565b600060208284031215612fa257600080fd5b5035919050565b60008060408385031215612fbc57600080fd5b612fc583612e52565b9150612fd360208401612ea6565b90509250929050565b60008060208385031215612fef57600080fd5b823567ffffffffffffffff8082111561300757600080fd5b818501915085601f83011261301b57600080fd5b81358181111561302a57600080fd5b8660208260051b850101111561303f57600080fd5b60209290920196919550909350505050565b60008060006060848603121561306657600080fd5b61306f84612ea6565b925060208401359150604084013561308681612e98565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b60008083128015600160ff1b8501841216156130c5576130c5613091565b6001600160ff1b03840183138116156130e0576130e0613091565b50500390565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561311657613116613091565b60016001607f1b0319600085128281168783058712161561313957613139613091565b6000871292508582058712848416161561315557613155613091565b8585058712818416161561316b5761316b613091565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156131a6576131a6613091565b8160016001607f1b030183138116156131c1576131c1613091565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b03038213811516156131f5576131f5613091565b8260016001607f1b031903821281161561321157613211613091565b50019392505050565b634e487b7160e01b600052601260045260246000fd5b60008261323f5761323f61321a565b500490565b600081600019048311821515161561325e5761325e613091565b500290565b6000821982111561327657613276613091565b500190565b6020808252601e908201527f566f74696e67206c6f636b2063616e2062652034207965617273206d61780000604082015260600190565b600081600f0b83600f0b806132c9576132c961321a565b60016001607f1b03198214600019821416156132e7576132e7613091565b90059392505050565b60008282101561330257613302613091565b500390565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b602080825260169082015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b604082015260600190565b6020808252601690820152754c6f636b20657870697265642e20576974686472617760501b604082015260600190565b60006000198214156133b2576133b2613091565b5060010190565b600181811c908216806133cd57607f821691505b602082108114156133ee57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b60006001600160801b0380831681851680830382111561342c5761342c613091565b01949350505050565b634e487b7160e01b600052602160045260246000fd5b60006020828403121561345d57600080fd5b8151612ce181612e98565b6000825161347a818460208701612f16565b919091019291505056fea2646970667358221220a61c67c2ca99138567813b6e0746a7dd4651ae50d0a8694935b7c0f8febfb12364736f6c634300080a0033
Deployed Bytecode Sourcemap
1548:32982:8:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18083:644;;;;;;:::i;:::-;;:::i;:::-;;;597:25:9;;;585:2;570:18;18083:644:8;;;;;;;;16055:1729;;;;;;:::i;:::-;;:::i;:::-;;;;1691:14:9;;1684:22;1666:41;;1754:2;1743:22;;;1738:2;1723:18;;1716:50;1802:22;;;1782:18;;;1775:50;;;;1861:22;;;1856:2;1841:18;;1834:50;1921:22;;1915:3;1900:19;;1893:51;1975:3;1960:19;;1953:35;;;;2019:3;2004:19;;1997:35;;;;2063:3;2048:19;;2041:35;1653:3;1638:19;16055:1729:8;1337:745:9;3557:55:8;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3557:55:8;;;;;;;;;;;;;2522:14:9;;2515:22;2497:41;;2581:14;;2574:22;2569:2;2554:18;;2547:50;-1:-1:-1;;;;;2633:47:9;2628:2;2613:18;;2606:75;2712:2;2697:18;;2690:34;2484:3;2469:19;;2278:452;3024:43:8;;3061:6;3024:43;;2703:47;;;;;;;;;;;;;;;-1:-1:-1;;;2703:47:8;;;;;;;;;;;;:::i;21409:114::-;;;:::i;2922:47::-;;2957:12;2922:47;;2801:35;;2834:2;2801:35;;;;;3558:4:9;3546:17;;;3528:36;;3516:2;3501:18;2801:35:8;3386:184:9;3635:69:8;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;3635:69:8;;;;;;;;;;;;;;;;;3857:2:9;3846:22;;;3828:41;;3905:22;;;3900:2;3885:18;;3878:50;3964:22;;;;3944:18;;;3937:50;;;;4018:2;4003:18;;3996:34;4061:3;4046:19;;4039:35;;;;3815:3;3800:19;3635:69:8;3575:505:9;11982:1046:8;;;:::i;:::-;;2843:29;;;;;;14281:122;;;;;;:::i;:::-;-1:-1:-1;;;;;14372:20:8;14346:7;14372:20;;;:14;:20;;;;;:24;;;;14281:122;7348:952;;;;;;:::i;:::-;;:::i;19247:1684::-;;;;;;:::i;:::-;;:::i;3232:18::-;;;;;-1:-1:-1;;;;;3232:18:8;;;;;;-1:-1:-1;;;;;4440:32:9;;;4422:51;;4410:2;4395:18;3232::8;4276:203:9;2676:21:8;;;:::i;18887:128::-;;;;;;:::i;:::-;;:::i;1888:101:5:-;;;:::i;8422:1273:8:-;;;;;;:::i;:::-;;:::i;3738:58::-;;;;;;:::i;:::-;;;;;;;;;;;;;;3339:45;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;3339:45:8;;;;;;;;;;;;;1256:85:5;1328:6;;-1:-1:-1;;;;;1328:6:5;1256:85;;2975:43:8;;;:::i;3313:20::-;;;;;;3136:57;;2909:7;3136:57;;;;;4842:2:9;4831:22;;;;4813:41;;4801:2;4786:18;3136:57:8;4669:191:9;2756:39:8;;;;;;;;;;;;;;;-1:-1:-1;;;2756:39:8;;;;;14612:968;;;;;;:::i;:::-;;:::i;4779:932::-;;;;;;:::i;:::-;;:::i;10827:1045::-;;;;;;:::i;:::-;;:::i;21051:230::-;;;;;;:::i;:::-;;:::i;4335:129::-;;;:::i;9773:911::-;;;:::i;13943:189::-;;;;;;:::i;:::-;-1:-1:-1;;;;;14095:22:8;;;;14065:7;14095:22;;;:16;:22;;;;;;;;:27;;;;;;;:30;;;;13943:189;6238:941;;;;;;:::i;:::-;;:::i;3073:57::-;;3120:8;3073:57;;2138:198:5;;;;;;:::i;:::-;;:::i;13467:282:8:-;;;;;;:::i;:::-;;:::i;2878:38::-;;2909:7;2878:38;;3417:46;;;;;;:::i;:::-;;;;;;;;;;;;;;;;18083:644;18190:7;18213:14;18230:33;18254:4;18260:2;18230:23;:33::i;:::-;18213:50;-1:-1:-1;18277:11:8;18273:448;;18311:1;18304:8;;;;;18273:448;-1:-1:-1;;;;;18368:22:8;;18343;18368;;;:16;:22;;;;;;;;:30;;;;;;;;;18343:55;;;;;;;;;;;;;;;-1:-1:-1;;;18343:55:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18487:33;;18494:2;18487:33;:::i;:::-;18446:9;:15;;;:75;;;;:::i;:::-;18412:109;;:9;;:109;;;;;:::i;:::-;;;;;;;;18539:14;;18556:1;18539:18;;;18535:75;;-1:-1:-1;18535:75:8;;18594:1;18577:18;;18535:75;18641:17;;;;18623:35;;18641:9;;18623:35;;18641:17;;18623:35;:::i;:::-;;;;;;;;18694:14;;18687:22;;;;-1:-1:-1;18672:38:8;;-1:-1:-1;;18672:38:8;18083:644;;;;;:::o;16055:1729::-;16230:4;;;;;;;;2909:7;16672:25;2909:7;16672:18;:25;:::i;:::-;16671:34;;;;:::i;:::-;16652:53;;16743:15;16724:16;:34;16716:70;;;;-1:-1:-1;;;16716:70:8;;8681:2:9;16716:70:8;;;8663:21:9;8720:2;8700:18;;;8693:30;-1:-1:-1;;;8739:18:9;;;8732:53;8802:18;;16716:70:8;;;;;;;;;16837:26;2957:12;16837:15;:26;:::i;:::-;16817:16;:46;;16796:123;;;;-1:-1:-1;;;16796:123:8;;;;;;;:::i;:::-;16950:5;16974:12;3120:8;16950:5;16974:12;:::i;:::-;16966:20;;17002:12;16997:439;;3120:8;17041:16;2909:7;17041:3;:16;:::i;:::-;17040:27;;;;:::i;:::-;17030:37;-1:-1:-1;17102:23:8;2909:7;17102:16;:23;:::i;:::-;17081:44;-1:-1:-1;17255:15:8;17221:23;2909:7;17221:16;:23;:::i;:::-;17214:57;;;;:::i;:::-;17162:127;;:5;:127;:::i;:::-;17139:150;;16997:439;;;17374:50;17408:15;17381:16;17374:50;:::i;:::-;17343:82;;:5;:82;:::i;:::-;17320:105;;16997:439;17457:1;17449:4;:9;;;17445:48;;17481:1;17474:8;;17445:48;17524:14;17531:7;17524:4;:14;:::i;:::-;17570:12;;-1:-1:-1;17502:36:8;-1:-1:-1;17717:18:8;;-1:-1:-1;;16055:1729:8;;;;;;;;;;;:::o;21409:114::-;21462:7;21488:28;21500:15;21488:11;:28::i;:::-;21481:35;;21409:114;:::o;11982:1046::-;1802:1:6;2556:7;;:19;;2548:63;;;;-1:-1:-1;;;2548:63:6;;;;;;;:::i;:::-;1802:1;2686:7;:18;916:10:1;12043:15:8::1;12122:23:::0;;;:14:::1;:23;::::0;;;;;;;;12083:62;;::::1;::::0;::::1;::::0;;;;::::1;::::0;;::::1;;;::::0;;::::1;::::0;::::1;;;;::::0;;::::1;::::0;;;;;;;::::1;-1:-1:-1::0;;;;;12083:62:8::1;::::0;;;;;;;::::1;::::0;;;;;;12155:61:::1;;;;-1:-1:-1::0;;;12155:61:8::1;;;;;;;:::i;:::-;12234:15;:33;;;12226:67;;;::::0;-1:-1:-1;;;12226:67:8;;10676:2:9;12226:67:8::1;::::0;::::1;10658:21:9::0;10715:2;10695:18;;;10688:30;-1:-1:-1;;;10734:18:9;;;10727:51;10795:18;;12226:67:8::1;10474:345:9::0;12226:67:8::1;12330:15;:19;;;12311:15;:38;;12303:68;;;::::0;-1:-1:-1;;;12303:68:8;;11026:2:9;12303:68:8::1;::::0;::::1;11008:21:9::0;11065:2;11045:18;;;11038:30;-1:-1:-1;;;11084:18:9;;;11077:47;11141:18;;12303:68:8::1;10824:341:9::0;12303:68:8::1;12397:22;::::0;;::::1;::::0;-1:-1:-1;;;;;12464:23:8;::::1;12381:13;12464:23:::0;;;:14:::1;:23;::::0;;;;;;12430:57;;::::1;::::0;;::::1;::::0;;;;::::1;::::0;;::::1;;;::::0;;::::1;::::0;;::::1;::::0;;::::1;;;::::0;;::::1;::::0;;;;::::1;-1:-1:-1::0;;;;;12430:57:8;;::::1;::::0;;;;;;::::1;::::0;;;;;;;;;;12523:33;;;;::::1;::::0;;;;;;;::::1;::::0;;;;;;;;;;;;;;;12497:23;;;;;;;:59;;;;;;-1:-1:-1;;12497:59:8;;;;::::1;;-1:-1:-1::0;;12497:59:8;;;;;;::::1;;;::::0;;;::::1;-1:-1:-1::0;;;;;;12497:59:8::1;::::0;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;;;;;12587:14:::1;::::0;;12397:22;;12430:57;;12587:14;12611:23;::::1;::::0;::::1;::::0;12587:14;12611:23:::1;:::i;:::-;::::0;;;-1:-1:-1;;12820:33:8::1;::::0;;::::1;::::0;::::1;::::0;;-1:-1:-1;12820:33:8;;;::::1;::::0;::::1;::::0;;;;;;;;;;;;;;;;12787:67:::1;::::0;12799:7;;12808:10;;12787:11:::1;:67::i;:::-;12883:3;::::0;12865:51:::1;::::0;-1:-1:-1;;;;;12883:3:8::1;12901:7:::0;-1:-1:-1;;;;;12865:51:8;::::1;:35;:51::i;:::-;12931:41;::::0;;-1:-1:-1;;;;;11362:47:9;;11344:66;;12956:15:8::1;11441:2:9::0;11426:18;;11419:34;-1:-1:-1;;;;;12931:41:8;::::1;::::0;::::1;::::0;11317:18:9;12931:41:8::1;;;;;;;13006:14;::::0;12987:34:::1;::::0;;11638:25:9;;;11694:2;11679:18;;11672:34;;;;12987::8::1;::::0;11611:18:9;12987:34:8::1;;;;;;;-1:-1:-1::0;;1759:1:6;2859:7;:22;-1:-1:-1;;;11982:1046:8:o;7348:952::-;1802:1:6;2556:7;;:19;;2548:63;;;;-1:-1:-1;;;2548:63:6;;;;;;;:::i;:::-;1802:1;2686:7;:18;916:10:1;7428:15:8::1;7507:23:::0;;;:14:::1;:23;::::0;;;;;;;;7468:62;;::::1;::::0;::::1;::::0;;;;::::1;::::0;;::::1;;;::::0;;::::1;::::0;::::1;;;;::::0;;::::1;::::0;;;;-1:-1:-1;;;;;7468:62:8;;;::::1;::::0;::::1;::::0;;;;;;;;::::1;::::0;;;;;7549:9;::::1;7541:45;;;::::0;-1:-1:-1;;;7541:45:8;;11919:2:9;7541:45:8::1;::::0;::::1;11901:21:9::0;11958:2;11938:18;;;11931:30;-1:-1:-1;;;11977:18:9;;;11970:53;12040:18;;7541:45:8::1;11717:347:9::0;7541:45:8::1;7629:1;7604:15;:22;;;-1:-1:-1::0;;;;;7604:26:8::1;;7596:61;;;;-1:-1:-1::0;;;7596:61:8::1;;;;;;;:::i;:::-;7673:28:::0;;7668:183:::1;;7743:15;:33;;;7742:34;7717:123;;;::::0;-1:-1:-1;;;7717:123:8;;12271:2:9;7717:123:8::1;::::0;::::1;12253:21:9::0;12310:2;12290:18;;;12283:30;12349:32;12329:18;;;12322:60;12399:18;;7717:123:8::1;12069:354:9::0;7717:123:8::1;7986:15;7964;:19;;;:37;7943:106;;;;-1:-1:-1::0;;;7943:106:8::1;;;;;;;:::i;:::-;8059:234;8084:7;8105:15;:28;;;8147:15;:33;;;8194:5;8213:1;8228:15;8257:26;8059:11;:234::i;:::-;-1:-1:-1::0;;1759:1:6;2859:7;:22;-1:-1:-1;7348:952:8:o;19247:1684::-;-1:-1:-1;;;;;19427:20:8;;19365:7;19427:20;;;:14;:20;;;;;;19365:7;;;19521:318;19545:3;19541:1;:7;19521:318;;;19580:3;19573;:10;19569:54;;19603:5;;19569:54;19636:11;19668:1;19651:9;19657:3;19651;:9;:::i;:::-;:13;;19663:1;19651:13;:::i;:::-;19650:19;;;;:::i;:::-;-1:-1:-1;;;;;19687:22:8;;;;;;:16;:22;;;;;;;;:27;;;;;;;;:31;;;19636:33;;-1:-1:-1;19687:46:8;-1:-1:-1;19683:146:8;;19759:3;19753:9;;19683:146;;;19807:7;19813:1;19807:3;:7;:::i;:::-;19801:13;;19683:146;-1:-1:-1;19550:3:8;;;;:::i;:::-;;;;19521:318;;;-1:-1:-1;;;;;;19931:22:8;;19909:19;19931:22;;;:16;:22;;;;;;;;:27;;;;;;;;19909:49;;;;;;;;;;;;;;;-1:-1:-1;;;19909:49:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19987:5;;19909:49;;20072:38;20088:11;19987:5;20072:15;:38::i;:::-;20120:19;20142:20;;;:12;:20;;;;;;;;20120:42;;;;;;;;;;;;;;;-1:-1:-1;;;20120:42:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20055:55;;-1:-1:-1;20120:19:8;20229:17;;;20225:290;;;20262:19;20284:12;20262:19;20297:10;:6;20306:1;20297:10;:::i;:::-;20284:24;;;;;;;;;;;;;;-1:-1:-1;20284:24:8;20262:46;;;;;;;;;;;;;;;-1:-1:-1;;;20262:46:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20344:10;;;20262:46;;-1:-1:-1;20331:23:8;;20344:10;20331:23;:::i;:::-;20322:32;;20385:6;:9;;;20373:6;:9;;;:21;;;;:::i;:::-;20368:26;;20248:157;20225:290;;;20448:10;;;;20434:24;;:11;:24;:::i;:::-;20425:33;;20495:6;:9;;;20477:15;:27;;;;:::i;:::-;20472:32;;20225:290;20545:9;;;;20568:11;;20564:97;;20644:6;20629;:10;;;20615:11;:24;;;;:::i;:::-;20609:31;;:2;:31;:::i;:::-;20608:42;;;;:::i;:::-;20595:55;;;;:::i;:::-;;;20564:97;20759:9;;;;20732:37;;20739:9;20732:37;:::i;:::-;20698:6;:12;;;:72;;;;:::i;:::-;20671:99;;:6;;:99;;;;;:::i;:::-;;;;;;;;20784:11;;20798:1;20784:15;;;20780:61;;-1:-1:-1;20780:61:8;;20829:1;20815:15;;20780:61;20865:14;;;;20850:29;;20865:6;;20850:29;;20865:14;;20850:29;:::i;:::-;;;;;;;;20911:11;;20904:19;;;;19247:1684;-1:-1:-1;;;;;;;;;;;;19247:1684:8:o;2676:21::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;18887:128::-;18950:7;18976:32;18986:4;18992:15;18976:9;:32::i;1888:101:5:-;1328:6;;-1:-1:-1;;;;;1328:6:5;916:10:1;1468:23:5;1460:68;;;;-1:-1:-1;;;1460:68:5;;13506:2:9;1460:68:5;;;13488:21:9;;;13525:18;;;13518:30;13584:34;13564:18;;;13557:62;13636:18;;1460:68:5;13304:356:9;1460:68:5;1952:30:::1;1979:1;1952:18;:30::i;:::-;1888:101::o:0;8422:1273:8:-;916:10:1;8498:15:8;8577:23;;;:14;:23;;;;;;;;8538:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;8538:62:8;;;;;;;;;;;;;;;;2909:7;8639:17;2909:7;8639:10;:17;:::i;:::-;8638:26;;;;:::i;:::-;8610:54;;8745:1;8720:15;:22;;;-1:-1:-1;;;;;8720:26:8;;8712:61;;;;-1:-1:-1;;;8712:61:8;;;;;;;:::i;:::-;8788:28;;8783:175;;8858:15;:33;;;8857:34;8832:115;;;;-1:-1:-1;;;8832:115:8;;13867:2:9;8832:115:8;;;13849:21:9;13906:2;13886:18;;;13879:30;-1:-1:-1;;;13925:18:9;;;13918:52;13987:18;;8832:115:8;13665:346:9;8832:115:8;9104:15;9082;:19;;;:37;9061:106;;;;-1:-1:-1;;;9061:106:8;;;;;;;:::i;:::-;9218:15;:19;;;9198:17;:39;9177:117;;;;-1:-1:-1;;;9177:117:8;;14218:2:9;9177:117:8;;;14200:21:9;14257:2;14237:18;;;14230:30;14296:33;14276:18;;;14269:61;14347:18;;9177:117:8;14016:355:9;9177:117:8;9346:26;2957:12;9346:15;:26;:::i;:::-;9325:17;:47;;9304:124;;;;-1:-1:-1;;;9304:124:8;;;;;;;:::i;:::-;9439:249;9464:7;9485:15;:28;;;9527:15;:33;;;9574:1;9589:17;9620:15;9649:29;9439:11;:249::i;:::-;8488:1207;;;8422:1273;:::o;2975:43::-;3010:8;2909:7;3010:1;:8;:::i;:::-;2975:43;:::o;14612:968::-;14720:7;14766:12;14751:11;:27;;14743:36;;;;;;14806:5;;14789:14;14843:36;14859:11;14806:5;14843:15;:36::i;:::-;14890:19;14912:25;;;:12;:25;;;;;;;;14890:47;;;;;;;;;;;;;;;-1:-1:-1;;;14890:47:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14821:58;;-1:-1:-1;14976:20:8;;;14972:489;;;15012:19;15034:12;15012:19;15047:15;:11;15061:1;15047:15;:::i;:::-;15034:29;;;;;;;;;;;;;;-1:-1:-1;15034:29:8;15012:51;;;;;;;;;;;;;;;-1:-1:-1;;;15012:51:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15185:10;;;15012:51;;-1:-1:-1;15172:23:8;;15185:10;15172:23;:::i;:::-;15141:6;:9;;;15129:6;:9;;;:21;;;;:::i;:::-;15114:10;;;;15100:24;;:11;:24;:::i;:::-;15099:52;;;;:::i;:::-;15098:98;;;;:::i;:::-;15077:119;;14998:209;14972:489;;;15245:12;15231:6;:10;;;:26;15227:224;;15425:10;;;;15410:25;;:12;:25;:::i;:::-;15375:9;;;;15357:27;;:15;:27;:::i;:::-;15318:10;;;;15304:24;;:11;:24;:::i;:::-;15303:82;;;;:::i;:::-;15302:134;;;;:::i;:::-;15277:159;;15227:224;15541:32;15550:6;15570:2;15558:6;:9;;;:14;;;;:::i;:::-;15541:8;:32::i;:::-;15534:39;14612:968;-1:-1:-1;;;;;;14612:968:8:o;4779:932::-;1802:1:6;2556:7;;:19;;2548:63;;;;-1:-1:-1;;;2548:63:6;;;;;;;:::i;:::-;1802:1;2686:7;:18;-1:-1:-1;;;;;4936:20:8;::::1;4897:36;4936:20:::0;;;:14:::1;:20;::::0;;;;;;;;4897:59;;::::1;::::0;::::1;::::0;;;;::::1;::::0;;::::1;;;::::0;;::::1;::::0;::::1;;;;::::0;;::::1;::::0;;;;-1:-1:-1;;;;;4897:59:8;;;::::1;::::0;::::1;::::0;;;;;;;;::::1;::::0;;;;;4974:9;::::1;4966:45;;;::::0;-1:-1:-1;;;4966:45:8;;11919:2:9;4966:45:8::1;::::0;::::1;11901:21:9::0;11958:2;11938:18;;;11931:30;-1:-1:-1;;;11977:18:9;;;11970:53;12040:18;;4966:45:8::1;11717:347:9::0;4966:45:8::1;5054:1;5029:15;:22;;;-1:-1:-1::0;;;;;5029:26:8::1;;5021:55;;;::::0;-1:-1:-1;;;5021:55:8;;14578:2:9;5021:55:8::1;::::0;::::1;14560:21:9::0;14617:2;14597:18;;;14590:30;-1:-1:-1;;;14636:18:9;;;14629:46;14692:18;;5021:55:8::1;14376:340:9::0;5021:55:8::1;5092:28:::0;;5087:183:::1;;5162:15;:33;;;5161:34;5136:123;;;::::0;-1:-1:-1;;;5136:123:8;;12271:2:9;5136:123:8::1;::::0;::::1;12253:21:9::0;12310:2;12290:18;;;12283:30;12349:32;12329:18;;;12322:60;12399:18;;5136:123:8::1;12069:354:9::0;5136:123:8::1;5404:15;5382;:19;;;:37;5361:106;;;;-1:-1:-1::0;;;5361:106:8::1;;;;;;;:::i;:::-;5477:227;5502:4;5520:15;:28;;;5562:15;:33;;;5609:5;5628:1;5643:15;5672:22;5477:11;:227::i;10827:1045::-:0;10912:7;10907:959;10925:20;;;;-1:-1:-1;10907:959:8;;;10963:36;11002:14;:28;11017:9;;11027:1;11017:12;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;11002:28:8;;;;;;;;;;;;;;;-1:-1:-1;11002:28:8;10963:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;10963:67:8;;;;;;;;;;;;;;;;-1:-1:-1;11065:26:8;;;;:64;;;11096:15;:33;;;11095:34;11065:64;11044:753;;;11190:19;;;;3010:8;2909:7;3010:1;:8;:::i;:::-;11250:15;:19;;;:30;;;;:::i;:::-;11231:15;:49;11227:208;;2909:7;;3010:8;2909:7;3010:1;:8;:::i;:::-;11350:26;;:15;:26;:::i;:::-;11349:35;;;;:::i;:::-;11348:68;;;;:::i;:::-;11304:112;;11227:208;11452:264;11485:9;;11495:1;11485:12;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;11519:4;11545;11571:1;11594:17;11633:15;11670:28;11452:11;:264::i;:::-;11769:9;;11779:1;11769:12;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;11739:43:8;;;;;;;;;;;11144:653;11044:753;-1:-1:-1;11838:3:8;;10907:959;;;;10827:1045;;:::o;21051:230::-;21114:7;21133:14;21150:29;21176:2;21150:25;:29::i;:::-;21189:22;21214:20;;;:12;:20;;;;;;;;;21189:45;;;;;;;;;;;;;;;-1:-1:-1;;;21189:45:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21133:46;;-1:-1:-1;21251:23:8;21189:45;21271:2;21251:8;:23::i;:::-;21244:30;21051:230;-1:-1:-1;;;;21051:230:8:o;4335:129::-;4385:20;:18;:20::i;:::-;-1:-1:-1;4451:5:8;;4420:37;;;916:10:1;15027:51:9;;15109:2;15094:18;;15087:34;;;;4420:37:8;;;;;;;;;;;;4335:129::o;9773:911::-;916:10:1;9829:15:8;9908:23;;;:14;:23;;;;;;;;;9869:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;9869:62:8;;;;;;;;;;;;;;;9941:61;;;;-1:-1:-1;;;9941:61:8;;;;;;;:::i;:::-;10034:15;:33;;;10033:34;10012:107;;;;-1:-1:-1;;;10012:107:8;;15334:2:9;10012:107:8;;;15316:21:9;15373:2;15353:18;;;15346:30;15412:28;15392:18;;;15385:56;15458:18;;10012:107:8;15132:350:9;10012:107:8;10190:19;;;;3010:8;2909:7;3010:1;:8;:::i;:::-;10277:15;:19;;;:30;;;;:::i;:::-;10258:15;:49;10254:218;;2909:7;;3010:8;2909:7;3010:1;:8;:::i;:::-;10345:26;;:15;:26;:::i;:::-;10344:35;;;;:::i;:::-;10343:44;;;;:::i;:::-;10323:64;;10254:218;;;10423:38;;-1:-1:-1;;;;;10423:38:8;;;;;;;;10254:218;10482:195;10507:7;10528:4;10546;10564:1;10579:17;10610:15;10639:28;10482:11;:195::i;6238:941::-;1802:1:6;2556:7;;:19;;2548:63;;;;-1:-1:-1;;;2548:63:6;;;;;;;:::i;:::-;1802:1;2686:7;:18;6391:12:8;6383:51:::1;;;::::0;-1:-1:-1;;;6383:51:8;;15689:2:9;6383:51:8::1;::::0;::::1;15671:21:9::0;15728:2;15708:18;;;15701:30;15767:28;15747:18;;;15740:56;15813:18;;6383:51:8::1;15487:350:9::0;6383:51:8::1;916:10:1::0;6444:15:8::1;2909:7;6513:17;2909:7:::0;6513:10;:17:::1;:::i;:::-;6512:26;;;;:::i;:::-;-1:-1:-1::0;;;;;6587:23:8;::::1;6548:36;6587:23:::0;;;:14:::1;:23;::::0;;;;;;;;6548:62;;::::1;::::0;::::1;::::0;;;;::::1;::::0;;::::1;;;::::0;;::::1;::::0;::::1;;;;::::0;;::::1;::::0;;;;-1:-1:-1;;;;;6548:62:8;;;::::1;::::0;::::1;::::0;;;;;;;;::::1;::::0;;;;;6484:54;;-1:-1:-1;6548:62:8;6629:9;::::1;6621:42;;;::::0;-1:-1:-1;;;6621:42:8;;16044:2:9;6621:42:8::1;::::0;::::1;16026:21:9::0;16083:2;16063:18;;;16056:30;-1:-1:-1;;;16102:18:9;;;16095:50;16162:18;;6621:42:8::1;15842:344:9::0;6621:42:8::1;6681:22;::::0;::::1;::::0;-1:-1:-1;;;;;6681:27:8::1;::::0;6673:65:::1;;;::::0;-1:-1:-1;;;6673:65:8;;16393:2:9;6673:65:8::1;::::0;::::1;16375:21:9::0;16432:2;16412:18;;;16405:30;16471:27;16451:18;;;16444:55;16516:18;;6673:65:8::1;16191:349:9::0;6673:65:8::1;6776:15;6756:17;:35;6748:71;;;::::0;-1:-1:-1;;;6748:71:8;;8681:2:9;6748:71:8::1;::::0;::::1;8663:21:9::0;8720:2;8700:18;;;8693:30;-1:-1:-1;;;8739:18:9;;;8732:53;8802:18;;6748:71:8::1;8479:347:9::0;6748:71:8::1;6871:26;2957:12;6871:15;:26;:::i;:::-;6850:17;:47;;6829:124;;;;-1:-1:-1::0;;;6829:124:8::1;;;;;;;:::i;:::-;6963:209;6988:7;7009:12;7035;7061:5;7080:17;7111:15;7140:22;6963:11;:209::i;:::-;-1:-1:-1::0;;1759:1:6;2859:7;:22;-1:-1:-1;;;;6238:941:8:o;2138:198:5:-;1328:6;;-1:-1:-1;;;;;1328:6:5;916:10:1;1468:23:5;1460:68;;;;-1:-1:-1;;;1460:68:5;;13506:2:9;1460:68:5;;;13488:21:9;;;13525:18;;;13518:30;13584:34;13564:18;;;13557:62;13636:18;;1460:68:5;13304:356:9;1460:68:5;-1:-1:-1;;;;;2226:22:5;::::1;2218:73;;;::::0;-1:-1:-1;;;2218:73:5;;16747:2:9;2218:73:5::1;::::0;::::1;16729:21:9::0;16786:2;16766:18;;;16759:30;16825:34;16805:18;;;16798:62;-1:-1:-1;;;16876:18:9;;;16869:36;16922:19;;2218:73:5::1;16545:402:9::0;2218:73:5::1;2301:28;2320:8;2301:18;:28::i;:::-;2138:198:::0;:::o;13467:282:8:-;-1:-1:-1;;;;;13610:20:8;;13571:6;13610:20;;;:14;:20;;;;;;13644:11;13640:50;;-1:-1:-1;13678:1:8;;13467:282;-1:-1:-1;;13467:282:8:o;13640:50::-;-1:-1:-1;;;;;13706:22:8;;;;;;;:16;:22;;;;;;;;:30;;;;;;;;;;:36;-1:-1:-1;;;13706:36:8;;;;;13467:282;-1:-1:-1;13467:282:8:o;1186:320:0:-;-1:-1:-1;;;;;1476:19:0;;:23;;;1186:320::o;28462:533:8:-;-1:-1:-1;;;;;28630:20:8;;28568:7;28630:20;;;:14;:20;;;;;;28568:7;;;28661:308;28685:3;28681:1;:7;28661:308;;;28720:3;28713;:10;28709:54;;28743:5;;28709:54;28776:11;28808:1;28791:9;28797:3;28791;:9;:::i;:::-;:13;;28803:1;28791:13;:::i;:::-;28790:19;;;;:::i;:::-;-1:-1:-1;;;;;28827:22:8;;;;;;:16;:22;;;;;;;;:27;;;;;;;;:30;;;28776:33;;-1:-1:-1;28827:36:8;-1:-1:-1;28823:136:8;;28889:3;28883:9;;28823:136;;;28937:7;28943:1;28937:3;:7;:::i;:::-;28931:13;;28823:136;-1:-1:-1;28690:3:8;;;;:::i;:::-;;;;28661:308;;;-1:-1:-1;28985:3:8;;28462:533;-1:-1:-1;;;;28462:533:8:o;23437:4248::-;23607:20;;;;;;;;;23587:17;23607:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23657;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23847:17;;;;23607:20;;23657;;23587:17;;-1:-1:-1;;;;;23847:21:8;;23843:573;;23904:17;;;;23941:28;;;;23936:221;;3120:8;24005:16;2909:7;24005:3;:16;:::i;:::-;24004:27;;;;:::i;:::-;23989:42;;:12;;;:42;24049:14;;;:22;;2909:7;;24049:14;:22;;2909:7;;24049:22;:::i;:::-;;;-1:-1:-1;23936:221:8;24191:15;24174:10;:14;;;:32;24170:236;;;24239:12;3120:8;24239:3;:12;:::i;:::-;24226:25;;:10;;;:25;24349:14;;;;24342:48;;24374:15;;24342:48;:::i;:::-;24302:4;:10;;;:89;;;;:::i;:::-;24270:121;;;;24170:236;23870:546;23843:573;24540:15;24523:10;:14;;;:32;24522:61;;;;;24581:1;24561:10;:17;;;-1:-1:-1;;;;;24561:21:8;;24522:61;24518:612;;;24619:17;;;;24656:28;;;;24651:221;;3120:8;24720:16;2909:7;24720:3;:16;:::i;:::-;24719:27;;;;:::i;:::-;24704:42;;:12;;;:42;24764:14;;;:22;;2909:7;;24764:14;:22;;2909:7;;24764:22;:::i;:::-;;;-1:-1:-1;24651:221:8;24906:15;24889:10;:14;;;:32;24885:235;;;24954:12;3120:8;24954:3;:12;:::i;:::-;24941:25;;:10;;;:25;25063:14;;;;25056:48;;25088:15;;25056:48;:::i;:::-;25016:4;:10;;;:89;;;;:::i;:::-;24984:121;;;;24885:235;24585:545;24518:612;25418:14;;;;;25405:28;;;;:12;:28;;;;;;25447:14;;;;25405:28;;;;;;-1:-1:-1;25447:19:8;25443:123;;-1:-1:-1;25540:14:8;;;;25527:28;;;;:12;:28;;;;;;;;25443:123;25659:22;25684:20;:18;:20::i;:::-;25659:45;;26006:4;:10;;;25993:4;:10;;;:23;;;;:::i;:::-;25973:9;:15;;:44;;;;;;;:::i;:::-;;;;;-1:-1:-1;26097:9:8;;26085;;:21;;26097:9;26085:21;:::i;:::-;26066:41;;:9;;:41;;;;;:::i;:::-;;;;;-1:-1:-1;26154:12:8;;;;;26139;;;;:27;;26154:12;26139:27;:::i;:::-;26117:9;:17;;:50;;;;;;;:::i;:::-;;;;;;;;26181:15;;;;26199:1;26181:19;;;26177:135;;-1:-1:-1;26177:135:8;;26300:1;26282:15;;;:19;26177:135;26342:1;26325:9;:14;;;:18;;;26321:107;;;26416:1;26399:18;;26321:107;26450:5;;26437:19;;;;:12;:19;;;;;;;;;:31;;;;;;-1:-1:-1;;;;;26437:31:8;;;-1:-1:-1;;;26437:31:8;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;26437:31:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26724:14;;;26741:15;-1:-1:-1;26720:377:8;;;26860:10;;;;26847:23;;;;:::i;:::-;;;26906:10;:14;;;26888:10;:14;;;:32;26884:149;;;27008:10;;;;26995:23;;;;:::i;:::-;;;26884:149;27059:14;;;;27046:28;;;;:12;:28;;;;;:40;;-1:-1:-1;;;;;;27046:40:8;-1:-1:-1;;;;;27046:40:8;;;;;26720:377;27128:15;27111:10;:14;;;:32;27107:329;;;27180:10;:14;;;27163:10;:14;;;:31;27159:206;;;27227:10;;;;27214:23;;;;:::i;:::-;27323:14;;;;27310:28;;;;:12;:28;;;;;:40;;-1:-1:-1;;;;;;27310:40:8;-1:-1:-1;;;;;27310:40:8;;;;;;-1:-1:-1;27159:206:8;-1:-1:-1;;;;;27498:20:8;;27480:15;27498:20;;;:14;:20;;;;;;:24;;27521:1;27498:24;:::i;:::-;-1:-1:-1;;;;;27532:20:8;;;;;;;;:14;:20;;;;;;;;:30;;;27582:15;27572:7;;;:25;;;27618:12;27607:8;;;:23;;;27640:22;;;:16;:22;;;;;:31;;;;;;;;;;:38;;;;;;-1:-1:-1;;;;;27640:38:8;;;-1:-1:-1;;;27640:38:8;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;27640:38:8;;;;;;;;;;;;;;-1:-1:-1;;27640:38:8;;;;;;;;;;-1:-1:-1;;;;;23437:4248:8:o;731:216:7:-;881:58;;-1:-1:-1;;;;;15045:32:9;;881:58:7;;;15027:51:9;15094:18;;;15087:34;;;854:86:7;;874:5;;-1:-1:-1;;;904:23:7;15000:18:9;;881:58:7;;;;-1:-1:-1;;881:58:7;;;;;;;;;;;;;;-1:-1:-1;;;;;881:58:7;-1:-1:-1;;;;;;881:58:7;;;;;;;;;;854:19;:86::i;21807:1342:8:-;-1:-1:-1;;;;;22083:20:8;;22049:31;22083:20;;;:14;:20;;;;;;;;;22049:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;22049:54:8;;;;;;;;;;;;;;;;22134:14;;22049:54;;22261:5;;22049:54;22240:26;;22261:5;;22240:26;:::i;:::-;-1:-1:-1;;;;;22240:26:8;;;-1:-1:-1;22276:38:8;;;;;22324:45;;;:28;;;:45;22383:15;;22379:73;;22414:14;;;:27;;;22379:73;-1:-1:-1;;;;;22461:20:8;;;;;;:14;:20;;;;;;;;;:33;;;;;;;;;;;;-1:-1:-1;;;;;22461:33:8;;;-1:-1:-1;;;;;;22461:33:8;;;;;-1:-1:-1;;22461:33:8;;;;;;;-1:-1:-1;;22461:33:8;;;;;;;;;;;;;;;;;;;;;;;;22743:41;22476:4;22761:10;22484;22743:11;:41::i;:::-;-1:-1:-1;;;;;22799:10:8;;;22795:268;;22843:5;-1:-1:-1;;;;;22825:23:8;:14;;:23;;;;;;;:::i;:::-;;;;-1:-1:-1;;22880:3:8;;22862:137;;-1:-1:-1;;;;;22880:3:8;916:10:1;22957:4:8;-1:-1:-1;;;;;22862:137:8;;:39;:137::i;:::-;23037:14;;23018:34;;;11638:25:9;;;11694:2;11679:18;;11672:34;;;;23018::8;;11611:18:9;23018:34:8;;;;;;;22795:268;23127:10;:14;;;23114:4;-1:-1:-1;;;;;23078:64:8;23093:5;23078:64;;;;;;;;:::i;:::-;;;;17535:14:9;;17528:22;17510:41;;-1:-1:-1;;;;;17587:47:9;;17582:2;17567:18;;17560:75;23078:64:8;;17483:18:9;23078:64:8;;;;;;;22039:1110;;21807:1342;;;;;;;:::o;27930:526::-;28041:7;;28103:8;28041:7;28122:308;28146:3;28142:1;:7;28122:308;;;28181:3;28174;:10;28170:54;;28204:5;;28170:54;28237:11;28269:1;28252:9;28258:3;28252;:9;:::i;:::-;:13;;28264:1;28252:13;:::i;:::-;28251:19;;;;:::i;:::-;28288:17;;;;:12;:17;;;;;:21;;;28237:33;;-1:-1:-1;28288:36:8;-1:-1:-1;28284:136:8;;28350:3;28344:9;;28284:136;;;28398:7;28404:1;28398:3;:7;:::i;:::-;28392:13;;28284:136;-1:-1:-1;28151:3:8;;;;:::i;:::-;;;;28122:308;;2490:187:5;2582:6;;;-1:-1:-1;;;;;2598:17:5;;;-1:-1:-1;;;;;;2598:17:5;;;;;;;2630:40;;2582:6;;;2598:17;2582:6;;2630:40;;2563:16;;2630:40;2553:124;2490:187;:::o;29750:921:8:-;29847:7;29870:22;29895:5;29870:30;;29910:10;2909:7;;29924:9;:12;;;:19;;;;:::i;:::-;29923:28;;;;:::i;:::-;29910:41;;30012:9;30007:488;30031:3;30027:1;:7;30007:488;;;30055:10;2909:7;30055:10;;:::i;:::-;;;30079:13;30119:2;30114;:7;30110:117;;;30146:2;30141:7;;30110:117;;;-1:-1:-1;30196:16:8;;;;:12;:16;;;;;;;;30110:117;30335:12;;;;30315:33;;30322:2;30315:33;:::i;:::-;30274:9;:15;;;:75;;;;:::i;:::-;30240:109;;:9;;:109;;;;;:::i;:::-;;;;;-1:-1:-1;30367:8:8;;;30363:52;;;30395:5;;;30363:52;30447:6;30428:9;:15;;:25;;;;;;;:::i;:::-;;;;;-1:-1:-1;;30467:12:8;;;:17;;;30036:3;;;;:::i;:::-;;;;30007:488;;;;30526:1;30509:9;:14;;;:18;;;30505:67;;;30560:1;30543:18;;30505:67;30599:17;;;;30581:35;;30599:9;;30581:35;;30599:17;;30581:35;:::i;:::-;;;;;;;;30648:14;;30641:22;;;;29750:921;-1:-1:-1;;;;;29750:921:8:o;29001:496::-;29157:5;;29095:7;;;;;29173:298;29197:3;29193:1;:7;29173:298;;;29232:3;29225;:10;29221:54;;29255:5;;29221:54;29288:11;29320:1;29303:9;29309:3;29303;:9;:::i;:::-;:13;;29315:1;29303:13;:::i;:::-;29302:19;;;;:::i;:::-;29339:17;;;;:12;:17;;;;;:20;;;29288:33;;-1:-1:-1;29339:26:8;-1:-1:-1;29335:126:8;;29391:3;29385:9;;29335:126;;;29439:7;29445:1;29439:3;:7;:::i;:::-;29433:13;;29335:126;-1:-1:-1;29202:3:8;;;;:::i;:::-;;;;29173:298;;;-1:-1:-1;29487:3:8;;29001:496;-1:-1:-1;;;29001:496:8:o;31171:3357::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31269:5:8;;31296:186;;;;;;;;;;;;;;;;;;;;;;31387:15;31296:186;;;;;;31421:12;31296:186;;;;;;31524;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31296;;31269:5;31724:10;;31720:126;;-1:-1:-1;31762:20:8;;;;:12;:20;;;;;;;;31750:32;;;;;;;;;;;;;;;;;-1:-1:-1;;;31750:32:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31815:20;;;;;;;31796:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31750:32;;-1:-1:-1;31720:126:8;31880:12;;;;31855:22;32165:15;:30;-1:-1:-1;32161:331:8;;;32468:12;;;;32450:30;;:15;:30;:::i;:::-;32415:13;;;;32400:28;;:12;:28;:::i;:::-;32386:43;;3061:6;32386:43;:::i;:::-;32385:96;;;;:::i;:::-;32356:125;;32161:331;32737:10;2909:7;32751:21;2909:7;32751:14;:21;:::i;:::-;32750:30;;;;:::i;:::-;32737:43;;32799:9;32794:1667;32818:3;32814:1;:7;32794:1667;;;33022:10;2909:7;33022:10;;:::i;:::-;;;33050:13;33094:15;33089:2;:20;33085:209;;;33138:15;33133:20;;33085:209;;;-1:-1:-1;33209:16:8;;;;:12;:16;;;;;;;;33085:209;33463:35;33483:14;33470:2;33463:35;:::i;:::-;33418:9;:15;;;:81;;;;:::i;:::-;33380:119;;:9;;:119;;;;;:::i;:::-;;;;;-1:-1:-1;33517:15:8;;;:25;;33536:6;;33517:15;:25;;33536:6;;33517:25;:::i;:::-;;;;;;;;33596:14;;33613:1;33596:18;;;33592:149;;-1:-1:-1;33592:149:8;;33721:1;33704:18;;33592:149;33780:1;33762:9;:15;;;:19;;;33758:172;;;33910:1;33892:15;;;:19;33758:172;33985:12;;;;:17;;;34119:19;;;33965:2;;-1:-1:-1;33965:2:8;;3061:6;;34114:24;;33965:2;34114:24;:::i;:::-;34100:39;;:10;:39;:::i;:::-;34099:74;;;;:::i;:::-;34056:16;:20;;;:117;;;;:::i;:::-;34020:13;;;:153;34191:11;34201:1;34191:11;;:::i;:::-;;;34230:15;34224:2;:21;34220:177;;;-1:-1:-1;34285:12:8;34269:13;;;:28;;;34319:20;;;;:12;:20;;;;;;;;;:32;;;;;;-1:-1:-1;;;;;34319:32:8;;;-1:-1:-1;;;34319:32:8;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;34319:32:8;;;;;;;;;;;;;;;;;;;;;;;34373:5;;34220:177;-1:-1:-1;34414:20:8;;;;:12;:20;;;;;;;;;:32;;;;;;-1:-1:-1;;;;;34414:32:8;;;-1:-1:-1;;;34414:32:8;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;34414:32:8;;;;;;;;;;;;;;;;;;;;;;;;;32823:3;;;;:::i;:::-;;;;32794:1667;;;;32723:1748;34489:6;34481:5;:14;;;;34505:16;;;;31171:3357;:::o;3292:717:7:-;3722:23;3748:69;3776:4;3748:69;;;;;;;;;;;;;;;;;3756:5;-1:-1:-1;;;;;3748:27:7;;;:69;;;;;:::i;:::-;3831:17;;3722:95;;-1:-1:-1;3831:21:7;3827:176;;3926:10;3915:30;;;;;;;;;;;;:::i;:::-;3907:85;;;;-1:-1:-1;;;3907:85:7;;18098:2:9;3907:85:7;;;18080:21:9;18137:2;18117:18;;;18110:30;18176:34;18156:18;;;18149:62;-1:-1:-1;;;18227:18:9;;;18220:40;18277:19;;3907:85:7;17896:406:9;953:252:7;1129:68;;-1:-1:-1;;;;;18565:15:9;;;1129:68:7;;;18547:34:9;18617:15;;18597:18;;;18590:43;18649:18;;;18642:34;;;1102:96:7;;1122:5;;-1:-1:-1;;;1152:27:7;18482:18:9;;1129:68:7;18307:375:9;3872:223:0;4005:12;4036:52;4058:6;4066:4;4072:1;4075:12;4036:21;:52::i;:::-;4029:59;;3872:223;;;;;;:::o;4959:499::-;5124:12;5181:5;5156:21;:30;;5148:81;;;;-1:-1:-1;;;5148:81:0;;18889:2:9;5148:81:0;;;18871:21:9;18928:2;18908:18;;;18901:30;18967:34;18947:18;;;18940:62;-1:-1:-1;;;19018:18:9;;;19011:36;19064:19;;5148:81:0;18687:402:9;5148:81:0;-1:-1:-1;;;;;1476:19:0;;;5239:60;;;;-1:-1:-1;;;5239:60:0;;19296:2:9;5239:60:0;;;19278:21:9;19335:2;19315:18;;;19308:30;19374:31;19354:18;;;19347:59;19423:18;;5239:60:0;19094:353:9;5239:60:0;5311:12;5325:23;5352:6;-1:-1:-1;;;;;5352:11:0;5371:5;5378:4;5352:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5310:73;;;;5400:51;5417:7;5426:10;5438:12;5400:16;:51::i;:::-;5393:58;4959:499;-1:-1:-1;;;;;;;4959:499:0:o;6622:692::-;6768:12;6796:7;6792:516;;;-1:-1:-1;6826:10:0;6819:17;;6792:516;6937:17;;:21;6933:365;;7131:10;7125:17;7191:15;7178:10;7174:2;7170:19;7163:44;6933:365;7270:12;7263:20;;-1:-1:-1;;;7263:20:0;;;;;;;;:::i;14:173:9:-;82:20;;-1:-1:-1;;;;;131:31:9;;121:42;;111:70;;177:1;174;167:12;111:70;14:173;;;:::o;192:254::-;260:6;268;321:2;309:9;300:7;296:23;292:32;289:52;;;337:1;334;327:12;289:52;360:29;379:9;360:29;:::i;:::-;350:39;436:2;421:18;;;;408:32;;-1:-1:-1;;;192:254:9:o;633:118::-;719:5;712:13;705:21;698:5;695:32;685:60;;741:1;738;731:12;756:188;824:20;;-1:-1:-1;;;;;873:46:9;;863:57;;853:85;;934:1;931;924:12;949:383;1023:6;1031;1039;1092:2;1080:9;1071:7;1067:23;1063:32;1060:52;;;1108:1;1105;1098:12;1060:52;1147:9;1134:23;1166:28;1188:5;1166:28;:::i;:::-;1213:5;-1:-1:-1;1237:38:9;1271:2;1256:18;;1237:38;:::i;:::-;1227:48;;1322:2;1311:9;1307:18;1294:32;1284:42;;949:383;;;;;:::o;2087:186::-;2146:6;2199:2;2187:9;2178:7;2174:23;2170:32;2167:52;;;2215:1;2212;2205:12;2167:52;2238:29;2257:9;2238:29;:::i;2735:258::-;2807:1;2817:113;2831:6;2828:1;2825:13;2817:113;;;2907:11;;;2901:18;2888:11;;;2881:39;2853:2;2846:10;2817:113;;;2948:6;2945:1;2942:13;2939:48;;;-1:-1:-1;;2983:1:9;2965:16;;2958:27;2735:258::o;2998:383::-;3147:2;3136:9;3129:21;3110:4;3179:6;3173:13;3222:6;3217:2;3206:9;3202:18;3195:34;3238:66;3297:6;3292:2;3281:9;3277:18;3272:2;3264:6;3260:15;3238:66;:::i;:::-;3365:2;3344:15;-1:-1:-1;;3340:29:9;3325:45;;;;3372:2;3321:54;;2998:383;-1:-1:-1;;2998:383:9:o;4085:186::-;4144:6;4197:2;4185:9;4176:7;4172:23;4168:32;4165:52;;;4213:1;4210;4203:12;4165:52;4236:29;4255:9;4236:29;:::i;4484:180::-;4543:6;4596:2;4584:9;4575:7;4571:23;4567:32;4564:52;;;4612:1;4609;4602:12;4564:52;-1:-1:-1;4635:23:9;;4484:180;-1:-1:-1;4484:180:9:o;4865:260::-;4933:6;4941;4994:2;4982:9;4973:7;4969:23;4965:32;4962:52;;;5010:1;5007;5000:12;4962:52;5033:29;5052:9;5033:29;:::i;:::-;5023:39;;5081:38;5115:2;5104:9;5100:18;5081:38;:::i;:::-;5071:48;;4865:260;;;;;:::o;5130:615::-;5216:6;5224;5277:2;5265:9;5256:7;5252:23;5248:32;5245:52;;;5293:1;5290;5283:12;5245:52;5333:9;5320:23;5362:18;5403:2;5395:6;5392:14;5389:34;;;5419:1;5416;5409:12;5389:34;5457:6;5446:9;5442:22;5432:32;;5502:7;5495:4;5491:2;5487:13;5483:27;5473:55;;5524:1;5521;5514:12;5473:55;5564:2;5551:16;5590:2;5582:6;5579:14;5576:34;;;5606:1;5603;5596:12;5576:34;5659:7;5654:2;5644:6;5641:1;5637:14;5633:2;5629:23;5625:32;5622:45;5619:65;;;5680:1;5677;5670:12;5619:65;5711:2;5703:11;;;;;5733:6;;-1:-1:-1;5130:615:9;;-1:-1:-1;;;;5130:615:9:o;5750:383::-;5824:6;5832;5840;5893:2;5881:9;5872:7;5868:23;5864:32;5861:52;;;5909:1;5906;5899:12;5861:52;5932:29;5951:9;5932:29;:::i;:::-;5922:39;;6008:2;5997:9;5993:18;5980:32;5970:42;;6062:2;6051:9;6047:18;6034:32;6075:28;6097:5;6075:28;:::i;:::-;6122:5;6112:15;;;5750:383;;;;;:::o;6138:127::-;6199:10;6194:3;6190:20;6187:1;6180:31;6230:4;6227:1;6220:15;6254:4;6251:1;6244:15;6270:267;6309:4;6338:9;;;6363:10;;-1:-1:-1;;;6382:19:9;;6375:27;;6359:44;6356:70;;;6406:18;;:::i;:::-;-1:-1:-1;;;;;6453:27:9;;6446:35;;6438:44;;6435:70;;;6485:18;;:::i;:::-;-1:-1:-1;;6522:9:9;;6270:267::o;6542:698::-;6581:7;6629:1;6625:2;6614:17;6666:1;6662:2;6651:17;-1:-1:-1;;;;;6749:1:9;6744:3;6740:11;6779:1;6774:3;6770:11;6826:3;6822:2;6818:12;6813:3;6810:21;6805:2;6801;6797:11;6793:39;6790:65;;;6835:18;;:::i;:::-;-1:-1:-1;;;;;;6941:1:9;6932:11;;6959;;;6981:13;;;6972:23;;6955:41;6952:67;;;6999:18;;:::i;:::-;7047:1;7042:3;7038:11;7028:21;;7096:3;7092:2;7087:13;7082:3;7078:23;7073:2;7069;7065:11;7061:41;7058:67;;;7105:18;;:::i;:::-;7172:3;7168:2;7163:13;7158:3;7154:23;7149:2;7145;7141:11;7137:41;7134:67;;;7181:18;;:::i;:::-;-1:-1:-1;;;7221:13:9;;;;;6542:698;-1:-1:-1;;;;;6542:698:9:o;7245:398::-;7284:4;7329:1;7325:2;7314:17;7366:1;7362:2;7351:17;7396:1;7391:3;7387:11;7480:3;-1:-1:-1;;;;;7439:39:9;7435:49;7430:3;7426:59;7421:2;7414:10;7410:76;7407:102;;;7489:18;;:::i;:::-;7578:3;-1:-1:-1;;;;;7538:44:9;7533:3;7529:54;7525:2;7521:63;7518:89;;;7587:18;;:::i;:::-;-1:-1:-1;7624:13:9;;;7245:398;-1:-1:-1;;;7245:398:9:o;7648:396::-;7687:3;7731:1;7727:2;7716:17;7768:1;7764:2;7753:17;7798:1;7793:3;7789:11;7877:3;-1:-1:-1;;;;;7837:44:9;7832:3;7828:54;7823:2;7816:10;7812:71;7809:97;;;7886:18;;:::i;:::-;7980:3;-1:-1:-1;;;;;7939:39:9;7935:49;7930:3;7926:59;7922:2;7918:68;7915:94;;;7989:18;;:::i;:::-;-1:-1:-1;8025:13:9;;7648:396;-1:-1:-1;;;7648:396:9:o;8049:127::-;8110:10;8105:3;8101:20;8098:1;8091:31;8141:4;8138:1;8131:15;8165:4;8162:1;8155:15;8181:120;8221:1;8247;8237:35;;8252:18;;:::i;:::-;-1:-1:-1;8286:9:9;;8181:120::o;8306:168::-;8346:7;8412:1;8408;8404:6;8400:14;8397:1;8394:21;8389:1;8382:9;8375:17;8371:45;8368:71;;;8419:18;;:::i;:::-;-1:-1:-1;8459:9:9;;8306:168::o;8831:128::-;8871:3;8902:1;8898:6;8895:1;8892:13;8889:39;;;8908:18;;:::i;:::-;-1:-1:-1;8944:9:9;;8831:128::o;8964:354::-;9166:2;9148:21;;;9205:2;9185:18;;;9178:30;9244:32;9239:2;9224:18;;9217:60;9309:2;9294:18;;8964:354::o;9323:305::-;9362:1;9404;9400:2;9389:17;9441:1;9437:2;9426:17;9462:3;9452:37;;9469:18;;:::i;:::-;-1:-1:-1;;;;;;9505:48:9;;-1:-1:-1;;9555:15:9;;9501:70;9498:96;;;9574:18;;:::i;:::-;9608:14;;;9323:305;-1:-1:-1;;;9323:305:9:o;9633:125::-;9673:4;9701:1;9698;9695:8;9692:34;;;9706:18;;:::i;:::-;-1:-1:-1;9743:9:9;;9633:125::o;9763:355::-;9965:2;9947:21;;;10004:2;9984:18;;;9977:30;10043:33;10038:2;10023:18;;10016:61;10109:2;10094:18;;9763:355::o;10123:346::-;10325:2;10307:21;;;10364:2;10344:18;;;10337:30;-1:-1:-1;;;10398:2:9;10383:18;;10376:52;10460:2;10445:18;;10123:346::o;12428:::-;12630:2;12612:21;;;12669:2;12649:18;;;12642:30;-1:-1:-1;;;12703:2:9;12688:18;;12681:52;12765:2;12750:18;;12428:346::o;12779:135::-;12818:3;-1:-1:-1;;12839:17:9;;12836:43;;;12859:18;;:::i;:::-;-1:-1:-1;12906:1:9;12895:13;;12779:135::o;12919:380::-;12998:1;12994:12;;;;13041;;;13062:61;;13116:4;13108:6;13104:17;13094:27;;13062:61;13169:2;13161:6;13158:14;13138:18;13135:38;13132:161;;;13215:10;13210:3;13206:20;13203:1;13196:31;13250:4;13247:1;13240:15;13278:4;13275:1;13268:15;13132:161;;12919:380;;;:::o;14721:127::-;14782:10;14777:3;14773:20;14770:1;14763:31;14813:4;14810:1;14803:15;14837:4;14834:1;14827:15;16952:253;16992:3;-1:-1:-1;;;;;17081:2:9;17078:1;17074:10;17111:2;17108:1;17104:10;17142:3;17138:2;17134:12;17129:3;17126:21;17123:47;;;17150:18;;:::i;:::-;17186:13;;16952:253;-1:-1:-1;;;;16952:253:9:o;17210:127::-;17271:10;17266:3;17262:20;17259:1;17252:31;17302:4;17299:1;17292:15;17326:4;17323:1;17316:15;17646:245;17713:6;17766:2;17754:9;17745:7;17741:23;17737:32;17734:52;;;17782:1;17779;17772:12;17734:52;17814:9;17808:16;17833:28;17855:5;17833:28;:::i;19452:274::-;19581:3;19619:6;19613:13;19635:53;19681:6;19676:3;19669:4;19661:6;19657:17;19635:53;:::i;:::-;19704:16;;;;;19452:274;-1:-1:-1;;19452:274:9:o
Swarm Source
ipfs://a61c67c2ca99138567813b6e0746a7dd4651ae50d0a8694935b7c0f8febfb123
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.