Source Code
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 1,213 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Withdraw | 3949658 | 16 days ago | IN | 0 ETH | 0.00000877 | ||||
| Increase_unlock_... | 3946157 | 16 days ago | IN | 0 ETH | 0.0000058 | ||||
| Create_lock | 3946152 | 16 days ago | IN | 0 ETH | 0.00001425 | ||||
| Increase_unlock_... | 3063309 | 85 days ago | IN | 0 ETH | 0.00000575 | ||||
| Withdraw | 2548875 | 125 days ago | IN | 0 ETH | 0.00000673 | ||||
| Withdraw | 2542921 | 125 days ago | IN | 0 ETH | 0.00000593 | ||||
| Create_lock | 2538449 | 125 days ago | IN | 0 ETH | 0.00001323 | ||||
| Create_lock | 2538280 | 125 days ago | IN | 0 ETH | 0.00001172 | ||||
| Increase_unlock_... | 1532309 | 160 days ago | IN | 0 ETH | 0.00002581 | ||||
| Increase_amount | 1532294 | 160 days ago | IN | 0 ETH | 0.00002582 | ||||
| Increase_amount | 1532277 | 160 days ago | IN | 0 ETH | 0.00002615 | ||||
| Withdraw | 1294353 | 176 days ago | IN | 0 ETH | 0.00006713 | ||||
| Increase_amount | 1286124 | 181 days ago | IN | 0 ETH | 0.0000221 | ||||
| Increase_amount | 1286099 | 181 days ago | IN | 0 ETH | 0.0000221 | ||||
| Create_lock | 1277888 | 184 days ago | IN | 0 ETH | 0.00005011 | ||||
| Create_lock | 1277879 | 184 days ago | IN | 0 ETH | 0.00004657 | ||||
| Transfer From | 1256086 | 197 days ago | IN | 0 ETH | 0.00000258 | ||||
| Increase_amount | 1238442 | 206 days ago | IN | 0 ETH | 0.00002226 | ||||
| Increase_unlock_... | 1236359 | 207 days ago | IN | 0 ETH | 0.00000228 | ||||
| Increase_unlock_... | 1225341 | 213 days ago | IN | 0 ETH | 0.00002522 | ||||
| Increase_amount | 1213892 | 220 days ago | IN | 0 ETH | 0.00002225 | ||||
| Increase_unlock_... | 1194474 | 231 days ago | IN | 0 ETH | 0.00000207 | ||||
| Increase_unlock_... | 1194383 | 231 days ago | IN | 0 ETH | 0.00002293 | ||||
| Increase_amount | 1194381 | 231 days ago | IN | 0 ETH | 0.00002225 | ||||
| Increase_amount | 1189977 | 234 days ago | IN | 0 ETH | 0.00002529 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
VotingEscrow
Compiler Version
v0.8.13+commit.abaa5c0e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;
import {IERC721, IERC721Metadata} from "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol";
import {IVotes} from "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol";
import {IERC721Receiver} from "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol";
import {IERC20} from "contracts/interfaces/IERC20.sol";
import {IVeArtProxy} from "contracts/interfaces/IVeArtProxy.sol";
import {IVotingEscrow} from "contracts/interfaces/IVotingEscrow.sol";
/// @title Voting Escrow
/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT
/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)
/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)
/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)
/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)
/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).
contract VotingEscrow is IERC721, IERC721Metadata, IVotes {
enum DepositType {
DEPOSIT_FOR_TYPE,
CREATE_LOCK_TYPE,
INCREASE_LOCK_AMOUNT,
INCREASE_UNLOCK_TIME,
MERGE_TYPE
}
struct LockedBalance {
int128 amount;
uint end;
}
struct Point {
int128 bias;
int128 slope; // # -dweight / dt
uint ts;
uint blk; // block
}
/* 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 */
/// @notice A checkpoint for marking delegated tokenIds from a given timestamp
struct Checkpoint {
uint timestamp;
uint[] tokenIds;
}
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Deposit(
address indexed provider,
uint tokenId,
uint value,
uint indexed locktime,
DepositType deposit_type,
uint ts
);
event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);
event Supply(uint prevSupply, uint supply);
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
address public immutable token;
address public voter;
address public team;
address public artProxy;
mapping(uint => Point) public point_history; // epoch -> unsigned point
/// @dev Mapping of interface id to bool about whether or not it's supported
mapping(bytes4 => bool) internal supportedInterfaces;
/// @dev ERC165 interface ID of ERC165
bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;
/// @dev ERC165 interface ID of ERC721
bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;
/// @dev ERC165 interface ID of ERC721Metadata
bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;
/// @dev Current count of token
uint internal tokenId;
/// @notice Contract constructor
/// @param token_addr `KODO` token address
constructor(address token_addr, address art_proxy) {
token = token_addr;
voter = msg.sender;
team = msg.sender;
artProxy = art_proxy;
point_history[0].blk = block.number;
point_history[0].ts = block.timestamp;
supportedInterfaces[ERC165_INTERFACE_ID] = true;
supportedInterfaces[ERC721_INTERFACE_ID] = true;
supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;
// mint-ish
emit Transfer(address(0), address(this), tokenId);
// burn-ish
emit Transfer(address(this), address(0), tokenId);
}
/*//////////////////////////////////////////////////////////////
MODIFIERS
//////////////////////////////////////////////////////////////*/
/// @dev reentrancy guard
uint8 internal constant _not_entered = 1;
uint8 internal constant _entered = 2;
uint8 internal _entered_state = 1;
modifier nonreentrant() {
require(_entered_state == _not_entered);
_entered_state = _entered;
_;
_entered_state = _not_entered;
}
/*///////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/
string constant public name = "veKODO";
string constant public symbol = "veKODO";
string constant public version = "1.0.0";
uint8 constant public decimals = 18;
function setTeam(address _team) external {
require(msg.sender == team);
team = _team;
}
function setArtProxy(address _proxy) external {
require(msg.sender == team);
artProxy = _proxy;
}
/// @dev Returns current token URI metadata
/// @param _tokenId Token ID to fetch URI for.
function tokenURI(uint _tokenId) external view returns (string memory) {
require(idToOwner[_tokenId] != address(0), "Query for nonexistent token");
LockedBalance memory _locked = locked[_tokenId];
return IVeArtProxy(artProxy)._tokenURI(
_tokenId,
_balanceOfNFT(_tokenId, block.timestamp),
_locked.end,
uint(int256(_locked.amount))
);
}
/*//////////////////////////////////////////////////////////////
ERC721 BALANCE/OWNER STORAGE
//////////////////////////////////////////////////////////////*/
/// @dev Mapping from NFT ID to the address that owns it.
mapping(uint => address) internal idToOwner;
/// @dev Mapping from owner address to count of his tokens.
mapping(address => uint) internal ownerToNFTokenCount;
/// @dev Returns the address of the owner of the NFT.
/// @param _tokenId The identifier for an NFT.
function ownerOf(uint _tokenId) public view returns (address) {
return idToOwner[_tokenId];
}
/// @dev Returns the number of NFTs owned by `_owner`.
/// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.
/// @param _owner Address for whom to query the balance.
function _balance(address _owner) internal view returns (uint) {
return ownerToNFTokenCount[_owner];
}
/// @dev Returns the number of NFTs owned by `_owner`.
/// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.
/// @param _owner Address for whom to query the balance.
function balanceOf(address _owner) external view returns (uint) {
return _balance(_owner);
}
/*//////////////////////////////////////////////////////////////
ERC721 APPROVAL STORAGE
//////////////////////////////////////////////////////////////*/
/// @dev Mapping from NFT ID to approved address.
mapping(uint => address) internal idToApprovals;
/// @dev Mapping from owner address to mapping of operator addresses.
mapping(address => mapping(address => bool)) internal ownerToOperators;
mapping(uint => uint) public ownership_change;
/// @dev Get the approved address for a single NFT.
/// @param _tokenId ID of the NFT to query the approval of.
function getApproved(uint _tokenId) external view returns (address) {
return idToApprovals[_tokenId];
}
/// @dev Checks if `_operator` is an approved operator for `_owner`.
/// @param _owner The address that owns the NFTs.
/// @param _operator The address that acts on behalf of the owner.
function isApprovedForAll(address _owner, address _operator) external view returns (bool) {
return (ownerToOperators[_owner])[_operator];
}
/*//////////////////////////////////////////////////////////////
ERC721 LOGIC
//////////////////////////////////////////////////////////////*/
/// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.
/// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.
/// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)
/// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)
/// @param _approved Address to be approved for the given NFT ID.
/// @param _tokenId ID of the token to be approved.
function approve(address _approved, uint _tokenId) public {
address owner = idToOwner[_tokenId];
// Throws if `_tokenId` is not a valid NFT
require(owner != address(0));
// Throws if `_approved` is the current owner
require(_approved != owner);
// Check requirements
bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);
bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];
require(senderIsOwner || senderIsApprovedForAll);
// Set the approval
idToApprovals[_tokenId] = _approved;
emit Approval(owner, _approved, _tokenId);
}
/// @dev Enables or disables approval for a third party ("operator") to manage all of
/// `msg.sender`'s assets. It also emits the ApprovalForAll event.
/// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)
/// @notice This works even if sender doesn't own any tokens at the time.
/// @param _operator Address to add to the set of authorized operators.
/// @param _approved True if the operators is approved, false to revoke approval.
function setApprovalForAll(address _operator, bool _approved) external {
// Throws if `_operator` is the `msg.sender`
assert(_operator != msg.sender);
ownerToOperators[msg.sender][_operator] = _approved;
emit ApprovalForAll(msg.sender, _operator, _approved);
}
/* TRANSFER FUNCTIONS */
/// @dev Clear an approval of a given address
/// Throws if `_owner` is not the current owner.
function _clearApproval(address _owner, uint _tokenId) internal {
// Throws if `_owner` is not the current owner
assert(idToOwner[_tokenId] == _owner);
if (idToApprovals[_tokenId] != address(0)) {
// Reset approvals
idToApprovals[_tokenId] = address(0);
}
}
/// @dev Returns whether the given spender can transfer a given token ID
/// @param _spender address of the spender to query
/// @param _tokenId uint ID of the token to be transferred
/// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token
function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {
address owner = idToOwner[_tokenId];
bool spenderIsOwner = owner == _spender;
bool spenderIsApproved = _spender == idToApprovals[_tokenId];
bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];
return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;
}
function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {
return _isApprovedOrOwner(_spender, _tokenId);
}
/// @dev Exeute transfer of a NFT.
/// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved
/// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)
/// Throws if `_to` is the zero address.
/// Throws if `_from` is not the current owner.
/// Throws if `_tokenId` is not a valid NFT.
function _transferFrom(
address _from,
address _to,
uint _tokenId,
address _sender
) internal {
require(attachments[_tokenId] == 0 && !voted[_tokenId], "attached");
// Check requirements
require(_isApprovedOrOwner(_sender, _tokenId));
// Clear approval. Throws if `_from` is not the current owner
_clearApproval(_from, _tokenId);
// Remove NFT. Throws if `_tokenId` is not a valid NFT
_removeTokenFrom(_from, _tokenId);
// auto re-delegate
_moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);
// Add NFT
_addTokenTo(_to, _tokenId);
// Set the block of ownership transfer (for Flash NFT protection)
ownership_change[_tokenId] = block.number;
// Log the transfer
emit Transfer(_from, _to, _tokenId);
}
/// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.
/// Throws if `_from` is not the current owner.
/// Throws if `_to` is the zero address.
/// Throws if `_tokenId` is not a valid NFT.
/// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else
/// they maybe be permanently lost.
/// @param _from The current owner of the NFT.
/// @param _to The new owner.
/// @param _tokenId The NFT to transfer.
function transferFrom(
address _from,
address _to,
uint _tokenId
) external {
_transferFrom(_from, _to, _tokenId, msg.sender);
}
/// @dev Transfers the ownership of an NFT from one address to another address.
/// Throws unless `msg.sender` is the current owner, an authorized operator, or the
/// approved address for this NFT.
/// Throws if `_from` is not the current owner.
/// Throws if `_to` is the zero address.
/// Throws if `_tokenId` is not a valid NFT.
/// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if
/// the return value is not `bytes4(keccak256("onERC721Received(address,address,uint,bytes)"))`.
/// @param _from The current owner of the NFT.
/// @param _to The new owner.
/// @param _tokenId The NFT to transfer.
function safeTransferFrom(
address _from,
address _to,
uint _tokenId
) external {
safeTransferFrom(_from, _to, _tokenId, "");
}
function _isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/// @dev Transfers the ownership of an NFT from one address to another address.
/// Throws unless `msg.sender` is the current owner, an authorized operator, or the
/// approved address for this NFT.
/// Throws if `_from` is not the current owner.
/// Throws if `_to` is the zero address.
/// Throws if `_tokenId` is not a valid NFT.
/// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if
/// the return value is not `bytes4(keccak256("onERC721Received(address,address,uint,bytes)"))`.
/// @param _from The current owner of the NFT.
/// @param _to The new owner.
/// @param _tokenId The NFT to transfer.
/// @param _data Additional data with no specified format, sent in call to `_to`.
function safeTransferFrom(
address _from,
address _to,
uint _tokenId,
bytes memory _data
) public {
_transferFrom(_from, _to, _tokenId, msg.sender);
if (_isContract(_to)) {
// Throws if transfer destination is a contract which does not implement 'onERC721Received'
try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {
if (response != IERC721Receiver(_to).onERC721Received.selector) {
revert("ERC721: ERC721Receiver rejected tokens");
}
} catch (bytes memory reason) {
if (reason.length == 0) {
revert('ERC721: transfer to non ERC721Receiver implementer');
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}
}
/*//////////////////////////////////////////////////////////////
ERC165 LOGIC
//////////////////////////////////////////////////////////////*/
/// @dev Interface identification is specified in ERC-165.
/// @param _interfaceID Id of the interface
function supportsInterface(bytes4 _interfaceID) external view returns (bool) {
return supportedInterfaces[_interfaceID];
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
/// @dev Mapping from owner address to mapping of index to tokenIds
mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;
/// @dev Mapping from NFT ID to index of owner
mapping(uint => uint) internal tokenToOwnerIndex;
/// @dev Get token by index
function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {
return ownerToNFTokenIdList[_owner][_tokenIndex];
}
/// @dev Add a NFT to an index mapping to a given address
/// @param _to address of the receiver
/// @param _tokenId uint ID Of the token to be added
function _addTokenToOwnerList(address _to, uint _tokenId) internal {
uint current_count = _balance(_to);
ownerToNFTokenIdList[_to][current_count] = _tokenId;
tokenToOwnerIndex[_tokenId] = current_count;
}
/// @dev Add a NFT to a given address
/// Throws if `_tokenId` is owned by someone.
function _addTokenTo(address _to, uint _tokenId) internal {
// Throws if `_tokenId` is owned by someone
assert(idToOwner[_tokenId] == address(0));
// Change the owner
idToOwner[_tokenId] = _to;
// Update owner token index tracking
_addTokenToOwnerList(_to, _tokenId);
// Change count tracking
ownerToNFTokenCount[_to] += 1;
}
/// @dev Function to mint tokens
/// Throws if `_to` is zero address.
/// Throws if `_tokenId` is owned by someone.
/// @param _to The address that will receive the minted tokens.
/// @param _tokenId The token id to mint.
/// @return A boolean that indicates if the operation was successful.
function _mint(address _to, uint _tokenId) internal returns (bool) {
// Throws if `_to` is zero address
assert(_to != address(0));
// checkpoint for gov
_moveTokenDelegates(address(0), delegates(_to), _tokenId);
// Add NFT. Throws if `_tokenId` is owned by someone
_addTokenTo(_to, _tokenId);
emit Transfer(address(0), _to, _tokenId);
return true;
}
/// @dev Remove a NFT from an index mapping to a given address
/// @param _from address of the sender
/// @param _tokenId uint ID Of the token to be removed
function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {
// Delete
uint current_count = _balance(_from) - 1;
uint current_index = tokenToOwnerIndex[_tokenId];
if (current_count == current_index) {
// update ownerToNFTokenIdList
ownerToNFTokenIdList[_from][current_count] = 0;
// update tokenToOwnerIndex
tokenToOwnerIndex[_tokenId] = 0;
} else {
uint lastTokenId = ownerToNFTokenIdList[_from][current_count];
// Add
// update ownerToNFTokenIdList
ownerToNFTokenIdList[_from][current_index] = lastTokenId;
// update tokenToOwnerIndex
tokenToOwnerIndex[lastTokenId] = current_index;
// Delete
// update ownerToNFTokenIdList
ownerToNFTokenIdList[_from][current_count] = 0;
// update tokenToOwnerIndex
tokenToOwnerIndex[_tokenId] = 0;
}
}
/// @dev Remove a NFT from a given address
/// Throws if `_from` is not the current owner.
function _removeTokenFrom(address _from, uint _tokenId) internal {
// Throws if `_from` is not the current owner
assert(idToOwner[_tokenId] == _from);
// Change the owner
idToOwner[_tokenId] = address(0);
// Update owner token index tracking
_removeTokenFromOwnerList(_from, _tokenId);
// Change count tracking
ownerToNFTokenCount[_from] -= 1;
}
function _burn(uint _tokenId) internal {
require(_isApprovedOrOwner(msg.sender, _tokenId), "caller is not owner nor approved");
address owner = ownerOf(_tokenId);
// Clear approval
approve(address(0), _tokenId);
// checkpoint for gov
_moveTokenDelegates(delegates(owner), address(0), _tokenId);
// Remove token
_removeTokenFrom(msg.sender, _tokenId);
emit Transfer(owner, address(0), _tokenId);
}
/*//////////////////////////////////////////////////////////////
ESCROW STORAGE
//////////////////////////////////////////////////////////////*/
mapping(uint => uint) public user_point_epoch;
mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]
mapping(uint => LockedBalance) public locked;
uint public epoch;
mapping(uint => int128) public slope_changes; // time -> signed slope change
uint public supply;
uint internal constant WEEK = 1 weeks;
uint internal constant MAXTIME = 4 * 365 * 86400;
int128 internal constant iMAXTIME = 4 * 365 * 86400;
uint internal constant MULTIPLIER = 1 ether;
/*//////////////////////////////////////////////////////////////
ESCROW LOGIC
//////////////////////////////////////////////////////////////*/
/// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`
/// @param _tokenId token of the NFT
/// @return Value of the slope
function get_last_user_slope(uint _tokenId) external view returns (int128) {
uint uepoch = user_point_epoch[_tokenId];
return user_point_history[_tokenId][uepoch].slope;
}
/// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`
/// @param _tokenId token of the NFT
/// @param _idx User epoch number
/// @return Epoch time of the checkpoint
function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {
return user_point_history[_tokenId][_idx].ts;
}
/// @notice Get timestamp when `_tokenId`'s lock finishes
/// @param _tokenId User NFT
/// @return Epoch time of the lock end
function locked__end(uint _tokenId) external view returns (uint) {
return locked[_tokenId].end;
}
/// @notice Record global and per-user data to checkpoint
/// @param _tokenId NFT token ID. No user checkpoint if 0
/// @param old_locked Pevious locked amount / end lock time for the user
/// @param new_locked New locked amount / end lock time for the user
function _checkpoint(
uint _tokenId,
LockedBalance memory old_locked,
LockedBalance memory new_locked
) internal {
Point memory u_old;
Point memory u_new;
int128 old_dslope = 0;
int128 new_dslope = 0;
uint _epoch = epoch;
if (_tokenId != 0) {
// Calculate slopes and biases
// Kept at zero when they have to
if (old_locked.end > block.timestamp && old_locked.amount > 0) {
u_old.slope = old_locked.amount / iMAXTIME;
u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));
}
if (new_locked.end > block.timestamp && new_locked.amount > 0) {
u_new.slope = new_locked.amount / iMAXTIME;
u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));
}
// Read values of scheduled changes in the slope
// old_locked.end can be in the past and in the future
// new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros
old_dslope = slope_changes[old_locked.end];
if (new_locked.end != 0) {
if (new_locked.end == old_locked.end) {
new_dslope = old_dslope;
} else {
new_dslope = slope_changes[new_locked.end];
}
}
}
Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});
if (_epoch > 0) {
last_point = point_history[_epoch];
}
uint last_checkpoint = last_point.ts;
// initial_last_point is used for extrapolation to calculate block number
// (approximately, for *At methods) and save them
// as we cannot figure that out exactly from inside the contract
Point memory initial_last_point = last_point;
uint block_slope = 0; // dblock/dt
if (block.timestamp > last_point.ts) {
block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);
}
// If last point is already recorded in this block, slope=0
// 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
{
uint t_i = (last_checkpoint / WEEK) * WEEK;
for (uint i = 0; i < 255; ++i) {
// Hopefully it won't happen that this won't get used in 5 years!
// If it does, users will be able to withdraw but vote weight will be broken
t_i += WEEK;
int128 d_slope = 0;
if (t_i > block.timestamp) {
t_i = block.timestamp;
} else {
d_slope = slope_changes[t_i];
}
last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));
last_point.slope += d_slope;
if (last_point.bias < 0) {
// This can happen
last_point.bias = 0;
}
if (last_point.slope < 0) {
// This cannot happen - just in case
last_point.slope = 0;
}
last_checkpoint = t_i;
last_point.ts = t_i;
last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;
_epoch += 1;
if (t_i == block.timestamp) {
last_point.blk = block.number;
break;
} else {
point_history[_epoch] = last_point;
}
}
}
epoch = _epoch;
// Now point_history is filled until t=now
if (_tokenId != 0) {
// If last point was in this block, the slope change has been applied already
// But in such case we have 0 slope(s)
last_point.slope += (u_new.slope - u_old.slope);
last_point.bias += (u_new.bias - u_old.bias);
if (last_point.slope < 0) {
last_point.slope = 0;
}
if (last_point.bias < 0) {
last_point.bias = 0;
}
}
// Record the changed point into history
point_history[_epoch] = last_point;
if (_tokenId != 0) {
// 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 (old_locked.end > block.timestamp) {
// old_dslope was <something> - u_old.slope, so we cancel that
old_dslope += u_old.slope;
if (new_locked.end == old_locked.end) {
old_dslope -= u_new.slope; // It was a new deposit, not extension
}
slope_changes[old_locked.end] = old_dslope;
}
if (new_locked.end > block.timestamp) {
if (new_locked.end > old_locked.end) {
new_dslope -= u_new.slope; // old slope disappeared at this point
slope_changes[new_locked.end] = new_dslope;
}
// else: we recorded it already in old_dslope
}
// Now handle user history
uint user_epoch = user_point_epoch[_tokenId] + 1;
user_point_epoch[_tokenId] = user_epoch;
u_new.ts = block.timestamp;
u_new.blk = block.number;
user_point_history[_tokenId][user_epoch] = u_new;
}
}
/// @notice Deposit and lock tokens for a user
/// @param _tokenId NFT that holds lock
/// @param _value Amount to deposit
/// @param unlock_time New time when to unlock the tokens, or 0 if unchanged
/// @param locked_balance Previous locked amount / timestamp
/// @param deposit_type The type of deposit
function _deposit_for(
uint _tokenId,
uint _value,
uint unlock_time,
LockedBalance memory locked_balance,
DepositType deposit_type
) internal {
LockedBalance memory _locked = locked_balance;
uint supply_before = supply;
supply = supply_before + _value;
LockedBalance memory old_locked;
(old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);
// Adding to existing lock, or if a lock is expired - creating a new one
_locked.amount += int128(int256(_value));
if (unlock_time != 0) {
_locked.end = unlock_time;
}
locked[_tokenId] = _locked;
// Possibilities:
// Both old_locked.end could be current or expired (>/< block.timestamp)
// value == 0 (extend lock) or value > 0 (add to lock or extend lock)
// _locked.end > block.timestamp (always)
_checkpoint(_tokenId, old_locked, _locked);
address from = msg.sender;
if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {
assert(IERC20(token).transferFrom(from, address(this), _value));
}
emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);
emit Supply(supply_before, supply_before + _value);
}
function block_number() external view returns (uint) {
return block.number;
}
/// @notice Record global data to checkpoint
function checkpoint() external {
_checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));
}
/// @notice Deposit `_value` tokens for `_tokenId` and add to the lock
/// @dev Anyone (even a smart contract) can deposit for someone else, but
/// cannot extend their locktime and deposit for a brand new user
/// @param _tokenId lock NFT
/// @param _value Amount to add to user's lock
function deposit_for(uint _tokenId, uint _value) external nonreentrant {
LockedBalance memory _locked = locked[_tokenId];
require(_value > 0); // dev: need non-zero value
require(_locked.amount > 0, 'No existing lock found');
require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');
_deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);
}
/// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`
/// @param _value Amount to deposit
/// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)
/// @param _to Address to deposit
function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {
uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks
require(_value > 0); // dev: need non-zero value
require(unlock_time > block.timestamp, 'Can only lock until time in the future');
require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');
++tokenId;
uint _tokenId = tokenId;
_mint(_to, _tokenId);
_deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);
return _tokenId;
}
/// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`
/// @param _value Amount to deposit
/// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)
function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {
return _create_lock(_value, _lock_duration, msg.sender);
}
/// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`
/// @param _value Amount to deposit
/// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)
/// @param _to Address to deposit
function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {
return _create_lock(_value, _lock_duration, _to);
}
/// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time
/// @param _value Amount of tokens to deposit and add to the lock
function increase_amount(uint _tokenId, uint _value) external nonreentrant {
assert(_isApprovedOrOwner(msg.sender, _tokenId));
LockedBalance memory _locked = locked[_tokenId];
assert(_value > 0); // dev: need non-zero value
require(_locked.amount > 0, 'No existing lock found');
require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');
_deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);
}
/// @notice Extend the unlock time for `_tokenId`
/// @param _lock_duration New number of seconds until tokens unlock
function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {
assert(_isApprovedOrOwner(msg.sender, _tokenId));
LockedBalance memory _locked = locked[_tokenId];
uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks
require(_locked.end > block.timestamp, 'Lock expired');
require(_locked.amount > 0, 'Nothing is locked');
require(unlock_time > _locked.end, 'Can only increase lock duration');
require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');
_deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);
}
/// @notice Withdraw all tokens for `_tokenId`
/// @dev Only possible if the lock has expired
function withdraw(uint _tokenId) external nonreentrant {
assert(_isApprovedOrOwner(msg.sender, _tokenId));
require(attachments[_tokenId] == 0 && !voted[_tokenId], "attached");
LockedBalance memory _locked = locked[_tokenId];
require(block.timestamp >= _locked.end, "The lock didn't expire");
uint value = uint(int256(_locked.amount));
locked[_tokenId] = LockedBalance(0,0);
uint supply_before = supply;
supply = supply_before - value;
// old_locked can have either expired <= timestamp or zero end
// _locked has only 0 end
// Both can have >= 0 amount
_checkpoint(_tokenId, _locked, LockedBalance(0,0));
assert(IERC20(token).transfer(msg.sender, value));
// Burn the NFT
_burn(_tokenId);
emit Withdraw(msg.sender, _tokenId, value, block.timestamp);
emit Supply(supply_before, supply_before - value);
}
/*///////////////////////////////////////////////////////////////
GAUGE VOTING STORAGE
//////////////////////////////////////////////////////////////*/
// 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 Binary search to estimate timestamp for block number
/// @param _block Block to find
/// @param max_epoch Don't go beyond this epoch
/// @return Approximate timestamp for block
function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {
// Binary search
uint _min = 0;
uint _max = max_epoch;
for (uint i = 0; i < 128; ++i) {
// Will be always enough for 128-bit numbers
if (_min >= _max) {
break;
}
uint _mid = (_min + _max + 1) / 2;
if (point_history[_mid].blk <= _block) {
_min = _mid;
} else {
_max = _mid - 1;
}
}
return _min;
}
/// @notice Get the current voting power for `_tokenId`
/// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility
/// @param _tokenId NFT for lock
/// @param _t Epoch time to return voting power at
/// @return User voting power
function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {
uint _epoch = user_point_epoch[_tokenId];
if (_epoch == 0) {
return 0;
} else {
Point memory last_point = user_point_history[_tokenId][_epoch];
last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));
if (last_point.bias < 0) {
last_point.bias = 0;
}
return uint(int256(last_point.bias));
}
}
function balanceOfNFT(uint _tokenId) external view returns (uint) {
if (ownership_change[_tokenId] == block.number) return 0;
return _balanceOfNFT(_tokenId, block.timestamp);
}
function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {
return _balanceOfNFT(_tokenId, _t);
}
/// @notice Measure voting power of `_tokenId` at block height `_block`
/// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime
/// @param _tokenId User's wallet NFT
/// @param _block Block to calculate the voting power at
/// @return Voting power
function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {
// Copying and pasting totalSupply code because Vyper cannot pass by
// reference yet
assert(_block <= block.number);
// Binary search
uint _min = 0;
uint _max = user_point_epoch[_tokenId];
for (uint i = 0; i < 128; ++i) {
// Will be always enough for 128-bit numbers
if (_min >= _max) {
break;
}
uint _mid = (_min + _max + 1) / 2;
if (user_point_history[_tokenId][_mid].blk <= _block) {
_min = _mid;
} else {
_max = _mid - 1;
}
}
Point memory upoint = user_point_history[_tokenId][_min];
uint max_epoch = epoch;
uint _epoch = _find_block_epoch(_block, max_epoch);
Point memory point_0 = point_history[_epoch];
uint d_block = 0;
uint d_t = 0;
if (_epoch < max_epoch) {
Point memory point_1 = point_history[_epoch + 1];
d_block = point_1.blk - point_0.blk;
d_t = point_1.ts - point_0.ts;
} else {
d_block = block.number - point_0.blk;
d_t = block.timestamp - point_0.ts;
}
uint block_time = point_0.ts;
if (d_block != 0) {
block_time += (d_t * (_block - point_0.blk)) / d_block;
}
upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));
if (upoint.bias >= 0) {
return uint(uint128(upoint.bias));
} else {
return 0;
}
}
function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {
return _balanceOfAtNFT(_tokenId, _block);
}
/// @notice Calculate total voting power at some point in the past
/// @param _block Block to calculate the total voting power at
/// @return Total voting power at `_block`
function totalSupplyAt(uint _block) external view returns (uint) {
assert(_block <= block.number);
uint _epoch = epoch;
uint target_epoch = _find_block_epoch(_block, _epoch);
Point memory point = point_history[target_epoch];
uint dt = 0;
if (target_epoch < _epoch) {
Point memory point_next = point_history[target_epoch + 1];
if (point.blk != point_next.blk) {
dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);
}
} else {
if (point.blk != block.number) {
dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);
}
}
// Now dt contains info on how far are we beyond point
return _supply_at(point, point.ts + dt);
}
/// @notice Calculate total voting power at some point in the past
/// @param point The point (bias/slope) to start search from
/// @param t Time to calculate the total voting power at
/// @return Total voting power at that time
function _supply_at(Point memory point, uint t) internal view returns (uint) {
Point memory last_point = point;
uint t_i = (last_point.ts / WEEK) * WEEK;
for (uint i = 0; i < 255; ++i) {
t_i += WEEK;
int128 d_slope = 0;
if (t_i > t) {
t_i = t;
} else {
d_slope = slope_changes[t_i];
}
last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));
if (t_i == t) {
break;
}
last_point.slope += d_slope;
last_point.ts = t_i;
}
if (last_point.bias < 0) {
last_point.bias = 0;
}
return uint(uint128(last_point.bias));
}
function totalSupply() external view returns (uint) {
return totalSupplyAtT(block.timestamp);
}
/// @notice Calculate total voting power
/// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility
/// @return Total voting power
function totalSupplyAtT(uint t) public view returns (uint) {
uint _epoch = epoch;
Point memory last_point = point_history[_epoch];
return _supply_at(last_point, t);
}
/*///////////////////////////////////////////////////////////////
GAUGE VOTING LOGIC
//////////////////////////////////////////////////////////////*/
mapping(uint => uint) public attachments;
mapping(uint => bool) public voted;
function setVoter(address _voter) external {
require(msg.sender == voter);
voter = _voter;
}
function voting(uint _tokenId) external {
require(msg.sender == voter);
voted[_tokenId] = true;
}
function abstain(uint _tokenId) external {
require(msg.sender == voter);
voted[_tokenId] = false;
}
function attach(uint _tokenId) external {
require(msg.sender == voter);
attachments[_tokenId] = attachments[_tokenId] + 1;
}
function detach(uint _tokenId) external {
require(msg.sender == voter);
attachments[_tokenId] = attachments[_tokenId] - 1;
}
function merge(uint _from, uint _to) external {
require(attachments[_from] == 0 && !voted[_from], "attached");
require(_from != _to);
require(_isApprovedOrOwner(msg.sender, _from));
require(_isApprovedOrOwner(msg.sender, _to));
LockedBalance memory _locked0 = locked[_from];
LockedBalance memory _locked1 = locked[_to];
uint value0 = uint(int256(_locked0.amount));
uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;
locked[_from] = LockedBalance(0, 0);
_checkpoint(_from, _locked0, LockedBalance(0, 0));
_burn(_from);
_deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);
}
/*///////////////////////////////////////////////////////////////
DAO VOTING STORAGE
//////////////////////////////////////////////////////////////*/
/// @notice The EIP-712 typehash for the contract's domain
bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");
/// @notice The EIP-712 typehash for the delegation struct used by the contract
bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");
/// @notice A record of each accounts delegate
mapping(address => address) private _delegates;
uint public constant MAX_DELEGATES = 1024; // avoid too much gas
/// @notice A record of delegated token checkpoints for each account, by index
mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;
/// @notice The number of checkpoints for each account
mapping(address => uint32) public numCheckpoints;
/// @notice A record of states for signing / validating signatures
mapping(address => uint) public nonces;
/**
* @notice Overrides the standard `Comp.sol` delegates mapping to return
* the delegator's own address if they haven't delegated.
* This avoids having to delegate to oneself.
*/
function delegates(address delegator) public view returns (address) {
address current = _delegates[delegator];
return current == address(0) ? delegator : current;
}
/**
* @notice Gets the current votes balance for `account`
* @param account The address to get votes balance
* @return The number of current votes for `account`
*/
function getVotes(address account) external view returns (uint) {
uint32 nCheckpoints = numCheckpoints[account];
if (nCheckpoints == 0) {
return 0;
}
uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;
uint votes = 0;
for (uint i = 0; i < _tokenIds.length; i++) {
uint tId = _tokenIds[i];
votes = votes + _balanceOfNFT(tId, block.timestamp);
}
return votes;
}
function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {
uint32 nCheckpoints = numCheckpoints[account];
if (nCheckpoints == 0) {
return 0;
}
// First check most recent balance
if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {
return (nCheckpoints - 1);
}
// Next check implicit zero balance
if (checkpoints[account][0].timestamp > timestamp) {
return 0;
}
uint32 lower = 0;
uint32 upper = nCheckpoints - 1;
while (upper > lower) {
uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
Checkpoint storage cp = checkpoints[account][center];
if (cp.timestamp == timestamp) {
return center;
} else if (cp.timestamp < timestamp) {
lower = center;
} else {
upper = center - 1;
}
}
return lower;
}
function getPastVotes(address account, uint timestamp)
public
view
returns (uint)
{
uint32 _checkIndex = getPastVotesIndex(account, timestamp);
// Sum votes
uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;
uint votes = 0;
for (uint i = 0; i < _tokenIds.length; i++) {
uint tId = _tokenIds[i];
// Use the provided input timestamp here to get the right decay
votes = votes + _balanceOfNFT(tId, timestamp);
}
return votes;
}
function getPastTotalSupply(uint256 timestamp) external view returns (uint) {
return totalSupplyAtT(timestamp);
}
/*///////////////////////////////////////////////////////////////
DAO VOTING LOGIC
//////////////////////////////////////////////////////////////*/
function _moveTokenDelegates(
address srcRep,
address dstRep,
uint _tokenId
) internal {
if (srcRep != dstRep && _tokenId > 0) {
if (srcRep != address(0)) {
uint32 srcRepNum = numCheckpoints[srcRep];
uint[] storage srcRepOld = srcRepNum > 0
? checkpoints[srcRep][srcRepNum - 1].tokenIds
: checkpoints[srcRep][0].tokenIds;
uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);
uint[] storage srcRepNew = checkpoints[srcRep][
nextSrcRepNum
].tokenIds;
// All the same except _tokenId
for (uint i = 0; i < srcRepOld.length; i++) {
uint tId = srcRepOld[i];
if (tId != _tokenId) {
srcRepNew.push(tId);
}
}
numCheckpoints[srcRep] = srcRepNum + 1;
}
if (dstRep != address(0)) {
uint32 dstRepNum = numCheckpoints[dstRep];
uint[] storage dstRepOld = dstRepNum > 0
? checkpoints[dstRep][dstRepNum - 1].tokenIds
: checkpoints[dstRep][0].tokenIds;
uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);
uint[] storage dstRepNew = checkpoints[dstRep][
nextDstRepNum
].tokenIds;
// All the same plus _tokenId
require(
dstRepOld.length + 1 <= MAX_DELEGATES,
"dstRep would have too many tokenIds"
);
for (uint i = 0; i < dstRepOld.length; i++) {
uint tId = dstRepOld[i];
dstRepNew.push(tId);
}
dstRepNew.push(_tokenId);
numCheckpoints[dstRep] = dstRepNum + 1;
}
}
}
function _findWhatCheckpointToWrite(address account)
internal
view
returns (uint32)
{
uint _timestamp = block.timestamp;
uint32 _nCheckPoints = numCheckpoints[account];
if (
_nCheckPoints > 0 &&
checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp
) {
return _nCheckPoints - 1;
} else {
return _nCheckPoints;
}
}
function _moveAllDelegates(
address owner,
address srcRep,
address dstRep
) internal {
// You can only redelegate what you own
if (srcRep != dstRep) {
if (srcRep != address(0)) {
uint32 srcRepNum = numCheckpoints[srcRep];
uint[] storage srcRepOld = srcRepNum > 0
? checkpoints[srcRep][srcRepNum - 1].tokenIds
: checkpoints[srcRep][0].tokenIds;
uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);
uint[] storage srcRepNew = checkpoints[srcRep][
nextSrcRepNum
].tokenIds;
// All the same except what owner owns
for (uint i = 0; i < srcRepOld.length; i++) {
uint tId = srcRepOld[i];
if (idToOwner[tId] != owner) {
srcRepNew.push(tId);
}
}
numCheckpoints[srcRep] = srcRepNum + 1;
}
if (dstRep != address(0)) {
uint32 dstRepNum = numCheckpoints[dstRep];
uint[] storage dstRepOld = dstRepNum > 0
? checkpoints[dstRep][dstRepNum - 1].tokenIds
: checkpoints[dstRep][0].tokenIds;
uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);
uint[] storage dstRepNew = checkpoints[dstRep][
nextDstRepNum
].tokenIds;
uint ownerTokenCount = ownerToNFTokenCount[owner];
require(
dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,
"dstRep would have too many tokenIds"
);
// All the same
for (uint i = 0; i < dstRepOld.length; i++) {
uint tId = dstRepOld[i];
dstRepNew.push(tId);
}
// Plus all that's owned
for (uint i = 0; i < ownerTokenCount; i++) {
uint tId = ownerToNFTokenIdList[owner][i];
dstRepNew.push(tId);
}
numCheckpoints[dstRep] = dstRepNum + 1;
}
}
}
function _delegate(address delegator, address delegatee) internal {
/// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation
address currentDelegate = delegates(delegator);
_delegates[delegator] = delegatee;
emit DelegateChanged(delegator, currentDelegate, delegatee);
_moveAllDelegates(delegator, currentDelegate, delegatee);
}
/**
* @notice Delegate votes from `msg.sender` to `delegatee`
* @param delegatee The address to delegate votes to
*/
function delegate(address delegatee) public {
if (delegatee == address(0)) delegatee = msg.sender;
return _delegate(msg.sender, delegatee);
}
function delegateBySig(
address delegatee,
uint nonce,
uint expiry,
uint8 v,
bytes32 r,
bytes32 s
) public {
bytes32 domainSeparator = keccak256(
abi.encode(
DOMAIN_TYPEHASH,
keccak256(bytes(name)),
keccak256(bytes(version)),
block.chainid,
address(this)
)
);
bytes32 structHash = keccak256(
abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)
);
bytes32 digest = keccak256(
abi.encodePacked("\x19\x01", domainSeparator, structHash)
);
address signatory = ecrecover(digest, v, r, s);
require(
signatory != address(0),
"VotingEscrow::delegateBySig: invalid signature"
);
require(
nonce == nonces[signatory]++,
"VotingEscrow::delegateBySig: invalid nonce"
);
require(
block.timestamp <= expiry,
"VotingEscrow::delegateBySig: signature expired"
);
return _delegate(signatory, delegatee);
}
}pragma solidity 0.8.13;
interface IERC20 {
function totalSupply() external view returns (uint256);
function transfer(address recipient, uint amount) external returns (bool);
function decimals() external view returns (uint8);
function symbol() external view returns (string memory);
function balanceOf(address) external view returns (uint);
function transferFrom(address sender, address recipient, uint amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
}pragma solidity 0.8.13;
interface IVeArtProxy {
function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);
}pragma solidity 0.8.13;
interface IVotingEscrow {
struct Point {
int128 bias;
int128 slope; // # -dweight / dt
uint256 ts;
uint256 blk; // block
}
function token() external view returns (address);
function team() external returns (address);
function epoch() external view returns (uint);
function point_history(uint loc) external view returns (Point memory);
function user_point_history(uint tokenId, uint loc) external view returns (Point memory);
function user_point_epoch(uint tokenId) external view returns (uint);
function ownerOf(uint) external view returns (address);
function isApprovedOrOwner(address, uint) external view returns (bool);
function transferFrom(address, address, uint) external;
function voting(uint tokenId) external;
function abstain(uint tokenId) external;
function attach(uint tokenId) external;
function detach(uint tokenId) external;
function checkpoint() external;
function deposit_for(uint tokenId, uint value) external;
function create_lock_for(uint, uint, address) external returns (uint);
function balanceOfNFT(uint) external view returns (uint);
function totalSupply() external view returns (uint);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (governance/utils/IVotes.sol)
pragma solidity ^0.8.0;
/**
* @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.
*
* _Available since v4.5._
*/
interface IVotes {
/**
* @dev Emitted when an account changes their delegate.
*/
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
/**
* @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.
*/
event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);
/**
* @dev Returns the current amount of votes that `account` has.
*/
function getVotes(address account) external view returns (uint256);
/**
* @dev Returns the amount of votes that `account` had at a specific moment in the past. If the `clock()` is
* configured to use block numbers, this will return the value at the end of the corresponding block.
*/
function getPastVotes(address account, uint256 timepoint) external view returns (uint256);
/**
* @dev Returns the total supply of votes available at a specific moment in the past. If the `clock()` is
* configured to use block numbers, this will return the value at the end of the corresponding block.
*
* NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.
* Votes that have not been delegated are still part of total supply, even though they would not participate in a
* vote.
*/
function getPastTotalSupply(uint256 timepoint) external view returns (uint256);
/**
* @dev Returns the delegate that `account` has chosen.
*/
function delegates(address account) external view returns (address);
/**
* @dev Delegates votes from the sender to `delegatee`.
*/
function delegate(address delegatee) external;
/**
* @dev Delegates votes from signer to `delegatee`.
*/
function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"token_addr","type":"address"},{"internalType":"address","name":"art_proxy","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"locktime","type":"uint256"},{"indexed":false,"internalType":"enum VotingEscrow.DepositType","name":"deposit_type","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"}],"name":"Deposit","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":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"DELEGATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_DELEGATES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"abstain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_approved","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"artProxy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"attach","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"attachments","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_block","type":"uint256"}],"name":"balanceOfAtNFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"balanceOfNFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_t","type":"uint256"}],"name":"balanceOfNFTAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"block_number","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"checkpoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"checkpoints","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_lock_duration","type":"uint256"}],"name":"create_lock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_lock_duration","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"create_lock_for","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"delegateBySig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"deposit_for","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"detach","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"epoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getPastTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getPastVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getPastVotesIndex","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"get_last_user_slope","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"increase_amount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_lock_duration","type":"uint256"}],"name":"increase_unlock_time","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"isApprovedOrOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"locked","outputs":[{"internalType":"int128","name":"amount","type":"int128"},{"internalType":"uint256","name":"end","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"locked__end","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_from","type":"uint256"},{"internalType":"uint256","name":"_to","type":"uint256"}],"name":"merge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"numCheckpoints","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"ownership_change","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"point_history","outputs":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"uint256","name":"ts","type":"uint256"},{"internalType":"uint256","name":"blk","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_proxy","type":"address"}],"name":"setArtProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_team","type":"address"}],"name":"setTeam","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_voter","type":"address"}],"name":"setVoter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"slope_changes","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"supply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"team","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_tokenIndex","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_block","type":"uint256"}],"name":"totalSupplyAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"t","type":"uint256"}],"name":"totalSupplyAtT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"user_point_epoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"user_point_history","outputs":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"uint256","name":"ts","type":"uint256"},{"internalType":"uint256","name":"blk","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_idx","type":"uint256"}],"name":"user_point_history__ts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"voted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"voting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1e38038062004a1e8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fe833981519152908290a46005546040516000903090600080516020620049fe833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e46200021a60003960008181610b230152818161101901526133b701526147e46000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abd578063f8a0576314610ae8578063fbd3a29d14610b0b578063fc0c546a14610b1e578063fd4a77f114610b4557600080fd5b8063e7a324dc14610a34578063e7e242d414610a5b578063e985e9c514610a6e578063ee99fe2814610aaa57600080fd5b8063d1c2babb116100ff578063d1c2babb1461099d578063d1febfb9146109b0578063d4e54c3b146109ee578063e0514aba14610a01578063e441135c14610a1457600080fd5b8063c1f0fb9f1461095c578063c2c4c5c11461096f578063c3cda52014610977578063c87b56dd1461098a57600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c8578063a22cb465146108db578063a4d855df146108ee578063b45a3c0e14610901578063b88d4fde1461094957600080fd5b806395d89b4114610465578063981b24d01461088f578063986b7d8a146108a25780639ab24eb0146108b557600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083d5780638e539e8c146108505780638fbb38ff14610863578063900cf0cf1461088657600080fd5b80637116c60c146107d457806371197484146107e75780637ecebe001461080a57806385f2aef21461082a57600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073f57806365fc3873146107685780636f5488371461077b5780636fcfff451461079b57806370a08231146107c157600080fd5b80635594a045146106fd578063587cde1e146107105780635c19a95c146107235780635f5b0c321461073657600080fd5b8063461f711c116102ea578063461f711c1461068d57806346c96aac146106b35780634bc2a657146106c657806354fd4d50146106d957600080fd5b8063313ce5671461063a5780633a46b1a81461065457806342842e0e14610667578063430c20811461067a57600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c557806325a58b56146105d85780632e1a7d4d146105de5780632e720f7d146105f15780632f745c591461060457600080fd5b80631376f3da1461054857806318160ddd146105835780631c984bc31461058b57806320606b701461059e57600080fd5b8063081812fc116103da578063081812fc146104bf578063095cf5c614610500578063095ea7b3146105155780630d6a20331461052857600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610497575b600080fd5b61043961041a366004613f26565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b61048a6040518060400160405280600681526020016576654b4f444f60d01b81525081565b6040516104459190613f9b565b6104aa6104a5366004613fca565b610b58565b60405163ffffffff9091168152602001610445565b6104e86104cd366004613ff4565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051361050e36600461400d565b610ccb565b005b610513610523366004613fca565b610d04565b610457610536366004613ff4565b60146020526000908152604090205481565b61055b610556366004614028565b610dec565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e33565b610457610599366004614028565b610e43565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105136105d336600461404a565b610e75565b43610457565b6105136105ec366004613ff4565b610e86565b6105136105ff36600461400d565b61113c565b610457610612366004613fca565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610642601281565b60405160ff9091168152602001610445565b610457610662366004613fca565b611175565b61051361067536600461404a565b611214565b610439610688366004613fca565b61122f565b6106a061069b366004613ff4565b611242565b604051600f9190910b8152602001610445565b6000546104e8906001600160a01b031681565b6105136106d436600461400d565b611285565b61048a604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e8906001600160a01b031681565b6104e861071e36600461400d565b6112be565b61051361073136600461400d565b6112ee565b61045761040081565b6104e861074d366004613ff4565b6000908152600760205260409020546001600160a01b031690565b610457610776366004614028565b61130c565b610457610789366004613ff4565b600b6020526000908152604090205481565b6104aa6107a936600461400d565b60186020526000908152604090205463ffffffff1681565b6104576107cf36600461400d565b61134e565b6104576107e2366004613ff4565b61136c565b6106a06107f5366004613ff4565b601260205260009081526040902054600f0b81565b61045761081836600461400d565b60196020526000908152604090205481565b6001546104e8906001600160a01b031681565b61045761084b366004614028565b6113cc565b61045761085e366004613ff4565b6113d8565b610439610871366004613ff4565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089d366004613ff4565b6113e3565b6105136108b0366004613ff4565b611585565b6104576108c336600461400d565b6115c9565b6105136108d6366004614028565b61169c565b6105136108e9366004614094565b61179b565b6105136108fc366004614028565b61181f565b61092f61090f366004613ff4565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b61051361095736600461413a565b611a04565b61051361096a366004613ff4565b611ba3565b610513611bd2565b6105136109853660046141e5565b611c12565b61048a610998366004613ff4565b611f53565b6105136109ab366004614028565b61207f565b61055b6109be366004613ff4565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fc366004614245565b6121e4565b610457610a0f366004614028565b612227565b610457610a22366004613ff4565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a69366004613ff4565b612233565b610439610a7c36600461427a565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610513610ab8366004614028565b61225b565b610457610acb3660046142ad565b601760209081526000928352604080842090915290825290205481565b610457610af6366004613ff4565b60009081526010602052604090206001015490565b610513610b19366004613ff4565b61232f565b6104e87f000000000000000000000000000000000000000000000000000000000000000081565b610513610b53366004613ff4565b612360565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b88576000915050610cc5565b6001600160a01b03841660009081526017602052604081208491610bad6001856142f8565b63ffffffff16815260208101919091526040016000205411610bdc57610bd46001826142f8565b915050610cc5565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c11576000915050610cc5565b600080610c1f6001846142f8565b90505b8163ffffffff168163ffffffff161115610cc05760006002610c4484846142f8565b610c4e9190614333565b610c5890836142f8565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9a57509350610cc592505050565b8054871115610cab57819350610cb9565b610cb66001836142f8565b92505b5050610c22565b509150505b92915050565b6001546001600160a01b03163314610ce257600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2657600080fd5b806001600160a01b0316836001600160a01b031603610d4457600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d855750805b610d8e57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0b57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3e4261136c565b905090565b6000828152600f6020526040812082633b9aca008110610e6557610e65614356565b6003020160010154905092915050565b610e8183838333612392565b505050565b60065460ff16600114610e9857600080fd5b6006805460ff19166002179055610eaf3382612473565b610ebb57610ebb61436c565b600081815260146020526040902054158015610ee6575060008181526015602052604090205460ff16155b610f0b5760405162461bcd60e51b8152600401610f0290614382565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7e5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f02565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd982826143a4565b6013556040805180820190915260008082526020820152610ffd90859085906124d9565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af115801561106a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108e91906143bb565b61109a5761109a61436c565b6110a384612af5565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111184826143a4565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115357600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111828484610b58565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b825481101561120a5760008382815481106111d3576111d3614356565b906000526020600020015490506111ea8188612bc8565b6111f490846143d8565b9250508080611202906143f0565b9150506111b6565b5095945050505050565b610e8183838360405180602001604052806000815250611a04565b600061123b8383612473565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126f5761126f614356565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129c57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e7578061123b565b5090919050565b6001600160a01b0381166112ff5750335b6113093382612c9c565b50565b60065460009060ff1660011461132157600080fd5b6006805460ff19166002179055611339838333612d0f565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc5565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c48185612e66565b949350505050565b600061123b8383612f67565b6000610cc58261136c565b6000438211156113f5576113f561436c565b60115460006114048483613240565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115135760006003816114678660016143d8565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150d57826060015181606001516114d391906143a4565b836040015182604001516114e791906143a4565b60608501516114f6908a6143a4565b6115009190614409565b61150a9190614428565b91505b50611562565b4382606001511461156257606082015161152d90436143a4565b604083015161153c90426143a4565b606084015161154b90896143a4565b6115559190614409565b61155f9190614428565b90505b61157b8282846040015161157691906143d8565b612e66565b9695505050505050565b6000546001600160a01b0316331461159c57600080fd5b6000818152601460205260409020546115b7906001906143a4565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f85750600092915050565b6001600160a01b03831660009081526017602052604081208161161c6001856142f8565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169357600083828154811061165c5761165c614356565b906000526020600020015490506116738142612bc8565b61167d90846143d8565b925050808061168b906143f0565b91505061163f565b50949350505050565b60065460ff166001146116ae57600080fd5b6006805460ff191660021790556116c53383612473565b6116d1576116d161436c565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117075761170761436c565b60008160000151600f0b136117575760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f02565b4281602001511161177a5760405162461bcd60e51b8152600401610f029061443c565b611789838360008460026132c6565b50506006805460ff1916600117905550565b336001600160a01b038316036117b3576117b361436c565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183157600080fd5b6006805460ff191660021790556118483383612473565b6118545761185461436c565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188f85426143d8565b6118999190614428565b6118a39190614409565b9050428260200151116118e75760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f02565b60008260000151600f0b136119325760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f02565b816020015181116119855760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f02565b611993630784ce00426143d8565b8111156119e25760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f02565b6119f1846000838560036132c6565b50506006805460ff191660011790555050565b611a1084848433612392565b823b15611b9d57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a49903390889087908790600401614480565b6020604051808303816000875af1925050508015611a84575060408051601f3d908101601f19168201909252611a81918101906144b3565b60015b611b2c573d808015611ab2576040519150601f19603f3d011682016040523d82523d6000602084013e611ab7565b606091505b508051600003611b245760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f02565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9b5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f02565b505b50505050565b6000546001600160a01b03163314611bba57600080fd5b6000908152601560205260409020805460ff19169055565b611c10600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d9565b565b604080518082018252600681526576654b4f444f60d01b6020918201528151808301835260058152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fbb881b1d9567c992114fc1b95ec42f6a93bc377c1a15e7de035d76d822c0035b818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd2573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4c5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f02565b6001600160a01b0381166000908152601960205260408120805491611e70836143f0565b919050558914611ed55760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f02565b87421115611f3c5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f02565b611f46818b612c9c565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fba5760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f02565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611fff8142612bc8565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612057573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123b91908101906144d0565b6000828152601460205260409020541580156120aa575060008281526015602052604090205460ff16155b6120c65760405162461bcd60e51b8152600401610f0290614382565b8082036120d257600080fd5b6120dc3383612473565b6120e557600080fd5b6120ef3382612473565b6120f857600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612162578260200151612168565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cd90879086906124d9565b6121d686612af5565b611f4b8583838660046132c6565b60065460009060ff166001146121f957600080fd5b6006805460ff19166002179055612211848484612d0f565b90506006805460ff191660011790559392505050565b600061123b8383612bc8565b6000818152600b602052604081205443900361225157506000919050565b610cc58242612bc8565b60065460ff1660011461226d57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ad57600080fd5b60008160000151600f0b136122fd5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f02565b428160200151116123205760405162461bcd60e51b8152600401610f029061443c565b611789838360008460006132c6565b6000546001600160a01b0316331461234657600080fd5b6000818152601460205260409020546115b79060016143d8565b6000546001600160a01b0316331461237757600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bd575060008281526015602052604090205460ff16155b6123d95760405162461bcd60e51b8152600401610f0290614382565b6123e38183612473565b6123ec57600080fd5b6123f684836134cb565b6124008483613532565b61241b61240c856112be565b612415856112be565b846135b3565b6124258383613915565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c65750815b806124ce5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264457428760200151118015612549575060008760000151600f0b135b1561258e57865161255f90630784ce009061453e565b600f0b6020808701919091528701516125799042906143a4565b8560200151612588919061457c565b600f0b85525b4286602001511180156125a8575060008660000151600f0b135b156125ed5785516125be90630784ce009061453e565b600f0b6020808601919091528601516125d89042906143a4565b84602001516125e7919061457c565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264457866020015186602001510361262957829150612644565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b9575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127065760408401516126d890426143a4565b60608501516126e790436143a4565b6126f990670de0b6b3a7640000614409565b6127039190614428565b90505b600062093a806127168186614428565b6127209190614409565b905060005b60ff81101561289a5761273b62093a80836143d8565b915060004283111561274f57429250612763565b50600082815260126020526040902054600f0b5b61276d86846143a4565b876020015161277c919061457c565b8751889061278b908390614611565b600f0b9052506020870180518291906127a5908390614661565b600f90810b90915288516000910b121590506127c057600087525b60008760200151600f0b12156127d857600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fc90856143a4565b6128069086614409565b6128109190614428565b856060015161281f91906143d8565b606088015261282f6001896143d8565b9750428303612844575043606087015261289a565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612893816143f0565b9050612725565b505060118590558b1561292557886020015188602001516128bb9190614611565b846020018181516128cc9190614661565b600f0b905250885188516128e09190614611565b845185906128ef908390614661565b600f90810b90915260208601516000910b1215905061291057600060208501525b60008460000151600f0b121561292557600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae757428b6020015111156129dc57602089015161298b9088614661565b96508a602001518a60200151036129ae5760208801516129ab9088614611565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a37578a602001518a602001511115612a37576020880151612a079087614611565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a519060016143d8565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa757612aa7614356565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612aff3382612473565b612b4b5760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f02565b6000818152600760205260408120546001600160a01b031690612b6e9083610d04565b612b82612b7a826112be565b6000846135b3565b612b8c3383613532565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be8576000915050610cc5565b6000848152600f6020526040812082633b9aca008110612c0a57612c0a614356565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5690856146b0565b8160200151612c65919061457c565b81518290612c74908390614611565b600f90810b90915282516000910b12159050612c8f57600081525b51600f0b9150610cc59050565b6000612ca7836112be565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e818382846139ab565b60008062093a8080612d2186426143d8565b612d2b9190614428565b612d359190614409565b905060008511612d4457600080fd5b428111612da25760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f02565b612db0630784ce00426143d8565b811115612dff5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f02565b600560008154612e0e906143f0565b90915550600554612e1f8482613d67565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5d918391899186916132c6565b95945050505050565b600080839050600062093a80808360400151612e829190614428565b612e8c9190614409565b905060005b60ff811015612f3f57612ea762093a80836143d8565b9150600085831115612ebb57859250612ecf565b50600082815260126020526040902054600f0b5b6040840151612ede90846143a4565b8460200151612eed919061457c565b84518590612efc908390614611565b600f0b905250858303612f0f5750612f3f565b8084602001818151612f219190614661565b600f0b9052505060408301829052612f38816143f0565b9050612e91565b5060008260000151600f0b1215612f5557600082525b50516001600160801b03169392505050565b600043821115612f7957612f7961436c565b6000838152600e6020526040812054815b608081101561301957818310156130195760006002612fa984866143d8565b612fb49060016143d8565b612fbe9190614428565b6000888152600f60205260409020909150869082633b9aca008110612fe557612fe5614356565b600302016002015411612ffa57809350613008565b6130056001826143a4565b92505b50613012816143f0565b9050612f8a565b506000858152600f6020526040812083633b9aca00811061303c5761303c614356565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b6020830152600181015492820192909252600290910154606082015260115490915060006130918783613240565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606082015291925080848410156131705760006003816130f58760016143d8565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315291906143a4565b92508360400151816040015161316891906143a4565b915050613194565b606083015161317f90436143a4565b915082604001514261319191906143a4565b90505b604083015182156131d1578284606001518c6131b091906143a4565b6131ba9084614409565b6131c49190614428565b6131ce90826143d8565b90505b60408701516131e090826143a4565b87602001516131ef919061457c565b875188906131fe908390614611565b600f90810b90915288516000910b12905061322e57505093516001600160801b03169650610cc595505050505050565b60009950505050505050505050610cc5565b60008082815b60808110156132bc57818310156132bc576000600261326584866143d8565b6132709060016143d8565b61327a9190614428565b600081815260036020526040902060020154909150871061329d578093506132ab565b6132a86001826143a4565b92505b506132b5816143f0565b9050613246565b5090949350505050565b60135482906132d586826143d8565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330e908390614661565b600f0b905250851561332257602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133648882856124d9565b33871580159061338657506004856004811115613383576133836146ef565b14155b15613430576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af1158015613400573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342491906143bb565b6134305761343061436c565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134749493929190614705565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a88a826143d8565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f4576134f461436c565b6000818152600960205260409020546001600160a01b03161561352e57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b0383811691161461355b5761355b61436c565b600081815260076020526040902080546001600160a01b03191690556135818282613dd8565b6001600160a01b03821660009081526008602052604081208054600192906135aa9084906143a4565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d55750600081115b15610e81576001600160a01b03831615613756576001600160a01b03831660009081526018602052604081205463ffffffff169081613639576001600160a01b0385166000908152601760209081526040808320838052909152902060010161367b565b6001600160a01b03851660009081526017602052604081209061365d6001856142f8565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368886613e97565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137155760008482815481106136d8576136d8614356565b90600052602060002001549050868114613702578254600181018455600084815260209020018190555b508061370d816143f0565b9150506136bb565b50613721846001614743565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e81576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b5576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f7565b6001600160a01b0384166000908152601760205260408120906137d96001856142f8565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380485613e97565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384691906143d8565b11156138645760405162461bcd60e51b8152600401610f029061476b565b60005b83548110156138b657600084828154811061388457613884614356565b6000918252602080832090910154855460018101875586845291909220015550806138ae816143f0565b915050613867565b508054600181810183556000838152602090209091018690556138da908590614743565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b03161561393a5761393a61436c565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135aa9084906143d8565b806001600160a01b0316826001600160a01b031614610e81576001600160a01b03821615613b5e576001600160a01b03821660009081526018602052604081205463ffffffff169081613a23576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a65565b6001600160a01b038416600090815260176020526040812090613a476001856142f8565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7285613e97565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1d576000848281548110613ac257613ac2614356565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b0a578254600181018455600084815260209020018190555b5080613b15816143f0565b915050613aa5565b50613b29846001614743565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e81576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbd576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bff565b6001600160a01b038316600090815260176020526040812090613be16001856142f8565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0c84613e97565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5d9083906143d8565b1115613c7b5760405162461bcd60e51b8152600401610f029061476b565b60005b8454811015613ccd576000858281548110613c9b57613c9b614356565b600091825260208083209091015486546001810188558784529190922001555080613cc5816143f0565b915050613c7e565b5060005b81811015613d1f576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d17816143f0565b915050613cd1565b50613d2b856001614743565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7f57613d7f61436c565b613d8d6000612415856112be565b613d978383613915565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfd906001906143a4565b6000838152600d6020526040902054909150808203613e4c576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9d565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613f0057506001600160a01b03841660009081526017602052604081208391613ee76001856142f8565b63ffffffff168152602081019190915260400160002054145b1561123b576113c46001826142f8565b6001600160e01b03198116811461130957600080fd5b600060208284031215613f3857600080fd5b813561123b81613f10565b60005b83811015613f5e578181015183820152602001613f46565b83811115611b9d5750506000910152565b60008151808452613f87816020860160208601613f43565b601f01601f19169290920160200192915050565b60208152600061123b6020830184613f6f565b80356001600160a01b0381168114613fc557600080fd5b919050565b60008060408385031215613fdd57600080fd5b613fe683613fae565b946020939093013593505050565b60006020828403121561400657600080fd5b5035919050565b60006020828403121561401f57600080fd5b61123b82613fae565b6000806040838503121561403b57600080fd5b50508035926020909101359150565b60008060006060848603121561405f57600080fd5b61406884613fae565b925061407660208501613fae565b9150604084013590509250925092565b801515811461130957600080fd5b600080604083850312156140a757600080fd5b6140b083613fae565b915060208301356140c081614086565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561410a5761410a6140cb565b604052919050565b600067ffffffffffffffff82111561412c5761412c6140cb565b50601f01601f191660200190565b6000806000806080858703121561415057600080fd5b61415985613fae565b935061416760208601613fae565b925060408501359150606085013567ffffffffffffffff81111561418a57600080fd5b8501601f8101871361419b57600080fd5b80356141ae6141a982614112565b6140e1565b8181528860208385010111156141c357600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fe57600080fd5b61420787613fae565b95506020870135945060408701359350606087013560ff8116811461422b57600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425a57600080fd5b833592506020840135915061427160408501613fae565b90509250925092565b6000806040838503121561428d57600080fd5b61429683613fae565b91506142a460208401613fae565b90509250929050565b600080604083850312156142c057600080fd5b6142c983613fae565b9150602083013563ffffffff811681146140c057600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614315576143156142e2565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff8084168061434a5761434a61431d565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b6576143b66142e2565b500390565b6000602082840312156143cd57600080fd5b815161123b81614086565b600082198211156143eb576143eb6142e2565b500190565b600060018201614402576144026142e2565b5060010190565b6000816000190483118215151615614423576144236142e2565b500290565b6000826144375761443761431d565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157b90830184613f6f565b6000602082840312156144c557600080fd5b815161123b81613f10565b6000602082840312156144e257600080fd5b815167ffffffffffffffff8111156144f957600080fd5b8201601f8101841361450a57600080fd5b80516145186141a982614112565b81815285602083850101111561452d57600080fd5b612e5d826020830160208601613f43565b600081600f0b83600f0b806145555761455561431d565b60016001607f1b0319821460001982141615614573576145736142e2565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145ac576145ac6142e2565b60016001607f1b031960008512828116878305871216156145cf576145cf6142e2565b600087129250858205871284841616156145eb576145eb6142e2565b85850587128184161615614601576146016142e2565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463c5761463c6142e2565b8160016001607f1b03018313811615614657576146576142e2565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b030382138115161561468b5761468b6142e2565b8260016001607f1b03190382128116156146a7576146a76142e2565b50019392505050565b60008083128015600160ff1b8501841216156146ce576146ce6142e2565b6001600160ff1b03840183138116156146e9576146e96142e2565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061473157634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614762576147626142e2565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea2646970667358221220df74770f210e0f32f449671e59b84ee66a0903ee0ce929d7a5f07219755d059764736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef0000000000000000000000007e91f29f8a213c8311712a8fc8c61219fb9477cb0000000000000000000000008ba3c594dc3796c171a1b7f0e143577abe03300f
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abd578063f8a0576314610ae8578063fbd3a29d14610b0b578063fc0c546a14610b1e578063fd4a77f114610b4557600080fd5b8063e7a324dc14610a34578063e7e242d414610a5b578063e985e9c514610a6e578063ee99fe2814610aaa57600080fd5b8063d1c2babb116100ff578063d1c2babb1461099d578063d1febfb9146109b0578063d4e54c3b146109ee578063e0514aba14610a01578063e441135c14610a1457600080fd5b8063c1f0fb9f1461095c578063c2c4c5c11461096f578063c3cda52014610977578063c87b56dd1461098a57600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c8578063a22cb465146108db578063a4d855df146108ee578063b45a3c0e14610901578063b88d4fde1461094957600080fd5b806395d89b4114610465578063981b24d01461088f578063986b7d8a146108a25780639ab24eb0146108b557600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083d5780638e539e8c146108505780638fbb38ff14610863578063900cf0cf1461088657600080fd5b80637116c60c146107d457806371197484146107e75780637ecebe001461080a57806385f2aef21461082a57600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073f57806365fc3873146107685780636f5488371461077b5780636fcfff451461079b57806370a08231146107c157600080fd5b80635594a045146106fd578063587cde1e146107105780635c19a95c146107235780635f5b0c321461073657600080fd5b8063461f711c116102ea578063461f711c1461068d57806346c96aac146106b35780634bc2a657146106c657806354fd4d50146106d957600080fd5b8063313ce5671461063a5780633a46b1a81461065457806342842e0e14610667578063430c20811461067a57600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c557806325a58b56146105d85780632e1a7d4d146105de5780632e720f7d146105f15780632f745c591461060457600080fd5b80631376f3da1461054857806318160ddd146105835780631c984bc31461058b57806320606b701461059e57600080fd5b8063081812fc116103da578063081812fc146104bf578063095cf5c614610500578063095ea7b3146105155780630d6a20331461052857600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610497575b600080fd5b61043961041a366004613f26565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b61048a6040518060400160405280600681526020016576654b4f444f60d01b81525081565b6040516104459190613f9b565b6104aa6104a5366004613fca565b610b58565b60405163ffffffff9091168152602001610445565b6104e86104cd366004613ff4565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051361050e36600461400d565b610ccb565b005b610513610523366004613fca565b610d04565b610457610536366004613ff4565b60146020526000908152604090205481565b61055b610556366004614028565b610dec565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e33565b610457610599366004614028565b610e43565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105136105d336600461404a565b610e75565b43610457565b6105136105ec366004613ff4565b610e86565b6105136105ff36600461400d565b61113c565b610457610612366004613fca565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610642601281565b60405160ff9091168152602001610445565b610457610662366004613fca565b611175565b61051361067536600461404a565b611214565b610439610688366004613fca565b61122f565b6106a061069b366004613ff4565b611242565b604051600f9190910b8152602001610445565b6000546104e8906001600160a01b031681565b6105136106d436600461400d565b611285565b61048a604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e8906001600160a01b031681565b6104e861071e36600461400d565b6112be565b61051361073136600461400d565b6112ee565b61045761040081565b6104e861074d366004613ff4565b6000908152600760205260409020546001600160a01b031690565b610457610776366004614028565b61130c565b610457610789366004613ff4565b600b6020526000908152604090205481565b6104aa6107a936600461400d565b60186020526000908152604090205463ffffffff1681565b6104576107cf36600461400d565b61134e565b6104576107e2366004613ff4565b61136c565b6106a06107f5366004613ff4565b601260205260009081526040902054600f0b81565b61045761081836600461400d565b60196020526000908152604090205481565b6001546104e8906001600160a01b031681565b61045761084b366004614028565b6113cc565b61045761085e366004613ff4565b6113d8565b610439610871366004613ff4565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089d366004613ff4565b6113e3565b6105136108b0366004613ff4565b611585565b6104576108c336600461400d565b6115c9565b6105136108d6366004614028565b61169c565b6105136108e9366004614094565b61179b565b6105136108fc366004614028565b61181f565b61092f61090f366004613ff4565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b61051361095736600461413a565b611a04565b61051361096a366004613ff4565b611ba3565b610513611bd2565b6105136109853660046141e5565b611c12565b61048a610998366004613ff4565b611f53565b6105136109ab366004614028565b61207f565b61055b6109be366004613ff4565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fc366004614245565b6121e4565b610457610a0f366004614028565b612227565b610457610a22366004613ff4565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a69366004613ff4565b612233565b610439610a7c36600461427a565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610513610ab8366004614028565b61225b565b610457610acb3660046142ad565b601760209081526000928352604080842090915290825290205481565b610457610af6366004613ff4565b60009081526010602052604090206001015490565b610513610b19366004613ff4565b61232f565b6104e87f0000000000000000000000007e91f29f8a213c8311712a8fc8c61219fb9477cb81565b610513610b53366004613ff4565b612360565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b88576000915050610cc5565b6001600160a01b03841660009081526017602052604081208491610bad6001856142f8565b63ffffffff16815260208101919091526040016000205411610bdc57610bd46001826142f8565b915050610cc5565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c11576000915050610cc5565b600080610c1f6001846142f8565b90505b8163ffffffff168163ffffffff161115610cc05760006002610c4484846142f8565b610c4e9190614333565b610c5890836142f8565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9a57509350610cc592505050565b8054871115610cab57819350610cb9565b610cb66001836142f8565b92505b5050610c22565b509150505b92915050565b6001546001600160a01b03163314610ce257600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2657600080fd5b806001600160a01b0316836001600160a01b031603610d4457600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d855750805b610d8e57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0b57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3e4261136c565b905090565b6000828152600f6020526040812082633b9aca008110610e6557610e65614356565b6003020160010154905092915050565b610e8183838333612392565b505050565b60065460ff16600114610e9857600080fd5b6006805460ff19166002179055610eaf3382612473565b610ebb57610ebb61436c565b600081815260146020526040902054158015610ee6575060008181526015602052604090205460ff16155b610f0b5760405162461bcd60e51b8152600401610f0290614382565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7e5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f02565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd982826143a4565b6013556040805180820190915260008082526020820152610ffd90859085906124d9565b60405163a9059cbb60e01b8152336004820152602481018390527f0000000000000000000000007e91f29f8a213c8311712a8fc8c61219fb9477cb6001600160a01b03169063a9059cbb906044016020604051808303816000875af115801561106a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108e91906143bb565b61109a5761109a61436c565b6110a384612af5565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111184826143a4565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115357600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111828484610b58565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b825481101561120a5760008382815481106111d3576111d3614356565b906000526020600020015490506111ea8188612bc8565b6111f490846143d8565b9250508080611202906143f0565b9150506111b6565b5095945050505050565b610e8183838360405180602001604052806000815250611a04565b600061123b8383612473565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126f5761126f614356565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129c57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e7578061123b565b5090919050565b6001600160a01b0381166112ff5750335b6113093382612c9c565b50565b60065460009060ff1660011461132157600080fd5b6006805460ff19166002179055611339838333612d0f565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc5565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c48185612e66565b949350505050565b600061123b8383612f67565b6000610cc58261136c565b6000438211156113f5576113f561436c565b60115460006114048483613240565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115135760006003816114678660016143d8565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150d57826060015181606001516114d391906143a4565b836040015182604001516114e791906143a4565b60608501516114f6908a6143a4565b6115009190614409565b61150a9190614428565b91505b50611562565b4382606001511461156257606082015161152d90436143a4565b604083015161153c90426143a4565b606084015161154b90896143a4565b6115559190614409565b61155f9190614428565b90505b61157b8282846040015161157691906143d8565b612e66565b9695505050505050565b6000546001600160a01b0316331461159c57600080fd5b6000818152601460205260409020546115b7906001906143a4565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f85750600092915050565b6001600160a01b03831660009081526017602052604081208161161c6001856142f8565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169357600083828154811061165c5761165c614356565b906000526020600020015490506116738142612bc8565b61167d90846143d8565b925050808061168b906143f0565b91505061163f565b50949350505050565b60065460ff166001146116ae57600080fd5b6006805460ff191660021790556116c53383612473565b6116d1576116d161436c565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117075761170761436c565b60008160000151600f0b136117575760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f02565b4281602001511161177a5760405162461bcd60e51b8152600401610f029061443c565b611789838360008460026132c6565b50506006805460ff1916600117905550565b336001600160a01b038316036117b3576117b361436c565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183157600080fd5b6006805460ff191660021790556118483383612473565b6118545761185461436c565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188f85426143d8565b6118999190614428565b6118a39190614409565b9050428260200151116118e75760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f02565b60008260000151600f0b136119325760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f02565b816020015181116119855760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f02565b611993630784ce00426143d8565b8111156119e25760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f02565b6119f1846000838560036132c6565b50506006805460ff191660011790555050565b611a1084848433612392565b823b15611b9d57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a49903390889087908790600401614480565b6020604051808303816000875af1925050508015611a84575060408051601f3d908101601f19168201909252611a81918101906144b3565b60015b611b2c573d808015611ab2576040519150601f19603f3d011682016040523d82523d6000602084013e611ab7565b606091505b508051600003611b245760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f02565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9b5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f02565b505b50505050565b6000546001600160a01b03163314611bba57600080fd5b6000908152601560205260409020805460ff19169055565b611c10600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d9565b565b604080518082018252600681526576654b4f444f60d01b6020918201528151808301835260058152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fbb881b1d9567c992114fc1b95ec42f6a93bc377c1a15e7de035d76d822c0035b818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd2573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4c5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f02565b6001600160a01b0381166000908152601960205260408120805491611e70836143f0565b919050558914611ed55760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f02565b87421115611f3c5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f02565b611f46818b612c9c565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fba5760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f02565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611fff8142612bc8565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612057573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123b91908101906144d0565b6000828152601460205260409020541580156120aa575060008281526015602052604090205460ff16155b6120c65760405162461bcd60e51b8152600401610f0290614382565b8082036120d257600080fd5b6120dc3383612473565b6120e557600080fd5b6120ef3382612473565b6120f857600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612162578260200151612168565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cd90879086906124d9565b6121d686612af5565b611f4b8583838660046132c6565b60065460009060ff166001146121f957600080fd5b6006805460ff19166002179055612211848484612d0f565b90506006805460ff191660011790559392505050565b600061123b8383612bc8565b6000818152600b602052604081205443900361225157506000919050565b610cc58242612bc8565b60065460ff1660011461226d57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ad57600080fd5b60008160000151600f0b136122fd5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f02565b428160200151116123205760405162461bcd60e51b8152600401610f029061443c565b611789838360008460006132c6565b6000546001600160a01b0316331461234657600080fd5b6000818152601460205260409020546115b79060016143d8565b6000546001600160a01b0316331461237757600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bd575060008281526015602052604090205460ff16155b6123d95760405162461bcd60e51b8152600401610f0290614382565b6123e38183612473565b6123ec57600080fd5b6123f684836134cb565b6124008483613532565b61241b61240c856112be565b612415856112be565b846135b3565b6124258383613915565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c65750815b806124ce5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264457428760200151118015612549575060008760000151600f0b135b1561258e57865161255f90630784ce009061453e565b600f0b6020808701919091528701516125799042906143a4565b8560200151612588919061457c565b600f0b85525b4286602001511180156125a8575060008660000151600f0b135b156125ed5785516125be90630784ce009061453e565b600f0b6020808601919091528601516125d89042906143a4565b84602001516125e7919061457c565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264457866020015186602001510361262957829150612644565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b9575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127065760408401516126d890426143a4565b60608501516126e790436143a4565b6126f990670de0b6b3a7640000614409565b6127039190614428565b90505b600062093a806127168186614428565b6127209190614409565b905060005b60ff81101561289a5761273b62093a80836143d8565b915060004283111561274f57429250612763565b50600082815260126020526040902054600f0b5b61276d86846143a4565b876020015161277c919061457c565b8751889061278b908390614611565b600f0b9052506020870180518291906127a5908390614661565b600f90810b90915288516000910b121590506127c057600087525b60008760200151600f0b12156127d857600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fc90856143a4565b6128069086614409565b6128109190614428565b856060015161281f91906143d8565b606088015261282f6001896143d8565b9750428303612844575043606087015261289a565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612893816143f0565b9050612725565b505060118590558b1561292557886020015188602001516128bb9190614611565b846020018181516128cc9190614661565b600f0b905250885188516128e09190614611565b845185906128ef908390614661565b600f90810b90915260208601516000910b1215905061291057600060208501525b60008460000151600f0b121561292557600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae757428b6020015111156129dc57602089015161298b9088614661565b96508a602001518a60200151036129ae5760208801516129ab9088614611565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a37578a602001518a602001511115612a37576020880151612a079087614611565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a519060016143d8565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa757612aa7614356565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612aff3382612473565b612b4b5760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f02565b6000818152600760205260408120546001600160a01b031690612b6e9083610d04565b612b82612b7a826112be565b6000846135b3565b612b8c3383613532565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be8576000915050610cc5565b6000848152600f6020526040812082633b9aca008110612c0a57612c0a614356565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5690856146b0565b8160200151612c65919061457c565b81518290612c74908390614611565b600f90810b90915282516000910b12159050612c8f57600081525b51600f0b9150610cc59050565b6000612ca7836112be565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e818382846139ab565b60008062093a8080612d2186426143d8565b612d2b9190614428565b612d359190614409565b905060008511612d4457600080fd5b428111612da25760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f02565b612db0630784ce00426143d8565b811115612dff5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f02565b600560008154612e0e906143f0565b90915550600554612e1f8482613d67565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5d918391899186916132c6565b95945050505050565b600080839050600062093a80808360400151612e829190614428565b612e8c9190614409565b905060005b60ff811015612f3f57612ea762093a80836143d8565b9150600085831115612ebb57859250612ecf565b50600082815260126020526040902054600f0b5b6040840151612ede90846143a4565b8460200151612eed919061457c565b84518590612efc908390614611565b600f0b905250858303612f0f5750612f3f565b8084602001818151612f219190614661565b600f0b9052505060408301829052612f38816143f0565b9050612e91565b5060008260000151600f0b1215612f5557600082525b50516001600160801b03169392505050565b600043821115612f7957612f7961436c565b6000838152600e6020526040812054815b608081101561301957818310156130195760006002612fa984866143d8565b612fb49060016143d8565b612fbe9190614428565b6000888152600f60205260409020909150869082633b9aca008110612fe557612fe5614356565b600302016002015411612ffa57809350613008565b6130056001826143a4565b92505b50613012816143f0565b9050612f8a565b506000858152600f6020526040812083633b9aca00811061303c5761303c614356565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b6020830152600181015492820192909252600290910154606082015260115490915060006130918783613240565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606082015291925080848410156131705760006003816130f58760016143d8565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315291906143a4565b92508360400151816040015161316891906143a4565b915050613194565b606083015161317f90436143a4565b915082604001514261319191906143a4565b90505b604083015182156131d1578284606001518c6131b091906143a4565b6131ba9084614409565b6131c49190614428565b6131ce90826143d8565b90505b60408701516131e090826143a4565b87602001516131ef919061457c565b875188906131fe908390614611565b600f90810b90915288516000910b12905061322e57505093516001600160801b03169650610cc595505050505050565b60009950505050505050505050610cc5565b60008082815b60808110156132bc57818310156132bc576000600261326584866143d8565b6132709060016143d8565b61327a9190614428565b600081815260036020526040902060020154909150871061329d578093506132ab565b6132a86001826143a4565b92505b506132b5816143f0565b9050613246565b5090949350505050565b60135482906132d586826143d8565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330e908390614661565b600f0b905250851561332257602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133648882856124d9565b33871580159061338657506004856004811115613383576133836146ef565b14155b15613430576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f0000000000000000000000007e91f29f8a213c8311712a8fc8c61219fb9477cb16906323b872dd906064016020604051808303816000875af1158015613400573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342491906143bb565b6134305761343061436c565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134749493929190614705565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a88a826143d8565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f4576134f461436c565b6000818152600960205260409020546001600160a01b03161561352e57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b0383811691161461355b5761355b61436c565b600081815260076020526040902080546001600160a01b03191690556135818282613dd8565b6001600160a01b03821660009081526008602052604081208054600192906135aa9084906143a4565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d55750600081115b15610e81576001600160a01b03831615613756576001600160a01b03831660009081526018602052604081205463ffffffff169081613639576001600160a01b0385166000908152601760209081526040808320838052909152902060010161367b565b6001600160a01b03851660009081526017602052604081209061365d6001856142f8565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368886613e97565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137155760008482815481106136d8576136d8614356565b90600052602060002001549050868114613702578254600181018455600084815260209020018190555b508061370d816143f0565b9150506136bb565b50613721846001614743565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e81576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b5576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f7565b6001600160a01b0384166000908152601760205260408120906137d96001856142f8565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380485613e97565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384691906143d8565b11156138645760405162461bcd60e51b8152600401610f029061476b565b60005b83548110156138b657600084828154811061388457613884614356565b6000918252602080832090910154855460018101875586845291909220015550806138ae816143f0565b915050613867565b508054600181810183556000838152602090209091018690556138da908590614743565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b03161561393a5761393a61436c565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135aa9084906143d8565b806001600160a01b0316826001600160a01b031614610e81576001600160a01b03821615613b5e576001600160a01b03821660009081526018602052604081205463ffffffff169081613a23576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a65565b6001600160a01b038416600090815260176020526040812090613a476001856142f8565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7285613e97565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1d576000848281548110613ac257613ac2614356565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b0a578254600181018455600084815260209020018190555b5080613b15816143f0565b915050613aa5565b50613b29846001614743565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e81576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbd576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bff565b6001600160a01b038316600090815260176020526040812090613be16001856142f8565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0c84613e97565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5d9083906143d8565b1115613c7b5760405162461bcd60e51b8152600401610f029061476b565b60005b8454811015613ccd576000858281548110613c9b57613c9b614356565b600091825260208083209091015486546001810188558784529190922001555080613cc5816143f0565b915050613c7e565b5060005b81811015613d1f576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d17816143f0565b915050613cd1565b50613d2b856001614743565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7f57613d7f61436c565b613d8d6000612415856112be565b613d978383613915565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfd906001906143a4565b6000838152600d6020526040902054909150808203613e4c576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9d565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613f0057506001600160a01b03841660009081526017602052604081208391613ee76001856142f8565b63ffffffff168152602081019190915260400160002054145b1561123b576113c46001826142f8565b6001600160e01b03198116811461130957600080fd5b600060208284031215613f3857600080fd5b813561123b81613f10565b60005b83811015613f5e578181015183820152602001613f46565b83811115611b9d5750506000910152565b60008151808452613f87816020860160208601613f43565b601f01601f19169290920160200192915050565b60208152600061123b6020830184613f6f565b80356001600160a01b0381168114613fc557600080fd5b919050565b60008060408385031215613fdd57600080fd5b613fe683613fae565b946020939093013593505050565b60006020828403121561400657600080fd5b5035919050565b60006020828403121561401f57600080fd5b61123b82613fae565b6000806040838503121561403b57600080fd5b50508035926020909101359150565b60008060006060848603121561405f57600080fd5b61406884613fae565b925061407660208501613fae565b9150604084013590509250925092565b801515811461130957600080fd5b600080604083850312156140a757600080fd5b6140b083613fae565b915060208301356140c081614086565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561410a5761410a6140cb565b604052919050565b600067ffffffffffffffff82111561412c5761412c6140cb565b50601f01601f191660200190565b6000806000806080858703121561415057600080fd5b61415985613fae565b935061416760208601613fae565b925060408501359150606085013567ffffffffffffffff81111561418a57600080fd5b8501601f8101871361419b57600080fd5b80356141ae6141a982614112565b6140e1565b8181528860208385010111156141c357600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fe57600080fd5b61420787613fae565b95506020870135945060408701359350606087013560ff8116811461422b57600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425a57600080fd5b833592506020840135915061427160408501613fae565b90509250925092565b6000806040838503121561428d57600080fd5b61429683613fae565b91506142a460208401613fae565b90509250929050565b600080604083850312156142c057600080fd5b6142c983613fae565b9150602083013563ffffffff811681146140c057600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614315576143156142e2565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff8084168061434a5761434a61431d565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b6576143b66142e2565b500390565b6000602082840312156143cd57600080fd5b815161123b81614086565b600082198211156143eb576143eb6142e2565b500190565b600060018201614402576144026142e2565b5060010190565b6000816000190483118215151615614423576144236142e2565b500290565b6000826144375761443761431d565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157b90830184613f6f565b6000602082840312156144c557600080fd5b815161123b81613f10565b6000602082840312156144e257600080fd5b815167ffffffffffffffff8111156144f957600080fd5b8201601f8101841361450a57600080fd5b80516145186141a982614112565b81815285602083850101111561452d57600080fd5b612e5d826020830160208601613f43565b600081600f0b83600f0b806145555761455561431d565b60016001607f1b0319821460001982141615614573576145736142e2565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145ac576145ac6142e2565b60016001607f1b031960008512828116878305871216156145cf576145cf6142e2565b600087129250858205871284841616156145eb576145eb6142e2565b85850587128184161615614601576146016142e2565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463c5761463c6142e2565b8160016001607f1b03018313811615614657576146576142e2565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b030382138115161561468b5761468b6142e2565b8260016001607f1b03190382128116156146a7576146a76142e2565b50019392505050565b60008083128015600160ff1b8501841216156146ce576146ce6142e2565b6001600160ff1b03840183138116156146e9576146e96142e2565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061473157634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614762576147626142e2565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea2646970667358221220df74770f210e0f32f449671e59b84ee66a0903ee0ce929d7a5f07219755d059764736f6c634300080d0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000007e91f29f8a213c8311712a8fc8c61219fb9477cb0000000000000000000000008ba3c594dc3796c171a1b7f0e143577abe03300f
-----Decoded View---------------
Arg [0] : token_addr (address): 0x7e91F29F8a213c8311712A8FC8c61219fb9477CB
Arg [1] : art_proxy (address): 0x8ba3C594Dc3796c171a1B7F0e143577abE03300F
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000007e91f29f8a213c8311712a8fc8c61219fb9477cb
Arg [1] : 0000000000000000000000008ba3c594dc3796c171a1b7f0e143577abe03300f
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.