ERC-721
Overview
Max Total Supply
994.715658295263184692 veArc
Holders
1
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract
Balance
0 veArcLoading...
Loading
Loading...
Loading
Loading...
Loading
Contract Name:
veArc
Compiler Version
v0.8.22+commit.4fc1097e
Optimization Enabled:
Yes with 10000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IERC721} from "./interfaces/IERC721.sol"; import {IERC721Receiver} from "./interfaces/IERC721Receiver.sol"; import {IERC721Metadata} from "./interfaces/IERC721Metadata.sol"; import {IVeArtProxy} from "./interfaces/IVeArtProxy.sol"; /** @title Voting Escrow @author Curve Finance @license MIT @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for) @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years). # Voting escrow to have time-weighted votes # Votes have a weight depending on time, so that users are committed # to the future of (whatever they are voting for). # The weight in this implementation is linear, and lock cannot be more than maxtime: # w ^ # 1 + / # | / # | / # | / # |/ # 0 +--------+------> time # maxtime (4 years?) */ 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 */ struct LockedBalance { int128 amount; uint end; } contract veArc is IERC721, IERC721Metadata { enum DepositType { DEPOSIT_FOR_TYPE, CREATE_LOCK_TYPE, INCREASE_LOCK_AMOUNT, INCREASE_UNLOCK_TIME, MERGE_TYPE } 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); event Burn(address indexed provider, uint tokenId, uint value, uint ts); 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; address immutable public token; uint public supply; mapping(uint => LockedBalance) public locked; address public admin; address public pendingAdmin; address public artProxy; mapping(uint => uint) public ownership_change; uint public epoch; mapping(uint => Point) public point_history; // epoch -> unsigned point mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch] mapping(uint => uint) public user_point_epoch; mapping(uint => int128) public slope_changes; // time -> signed slope change mapping(uint => uint) public attachments; mapping(uint => bool) public voted; address public voter; string constant public name = "veArc"; string constant public symbol = "veArc"; string constant public version = "2.0.0"; uint8 constant public decimals = 18; /// @dev Current count of token uint internal tokenId; /// @dev Mapping from NFT ID to the address that owns it. mapping(uint => address) internal idToOwner; /// @dev Mapping from NFT ID to approved address. mapping(uint => address) internal idToApprovals; /// @dev Mapping from owner address to count of his tokens. mapping(address => uint) internal ownerToNFTokenCount; /// @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 Mapping of vote expiry date per NFT ID mapping(uint => uint) internal idToVoteExpiry; /// @dev Mapping from owner address to mapping of operator addresses. mapping(address => mapping(address => bool)) internal ownerToOperators; /// @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 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; } /// @notice Contract constructor /// @param token_addr `ERC20CRV` token address constructor( address token_addr, address art_proxy ) { require( token_addr != address(0), "VotingEscrow: zero address provided in constructor" ); token = token_addr; voter = msg.sender; point_history[0].blk = block.number; point_history[0].ts = block.timestamp; admin = msg.sender; artProxy = art_proxy; 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); } /// @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]; } /// @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 Get `_tokenId`'s locked amount /// @param _tokenId User NFT function locked__amount(uint _tokenId) external view returns (uint) { return uint(int256(locked[_tokenId].amount)); } /// @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); } /// @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 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]; } /// @dev Get token by index function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) { return ownerToNFTokenIdList[_owner][_tokenIndex]; } /// @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 Returns true if NFT is unlocked, false if locked in vote. /// @param _tokenId The identifier for an NFT. function isVoteExpired(uint _tokenId) external view returns (bool) { return _isVoteExpired(_tokenId); } /// @dev Returns true if NFT is unlocked, false if locked in vote. /// @param _tokenId The identifier for an NFT. function _isVoteExpired(uint _tokenId) internal view returns (bool) { return idToVoteExpiry[_tokenId] < block.timestamp; } /// @dev Returns remaining vote lock for an NFT. /// @param _tokenId The identifier for an NFT. function voteExpiry(uint _tokenId) external view returns (uint) { return idToVoteExpiry[_tokenId]; } /// @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 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 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 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; } /// @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 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); // 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); } /* TRANSFER FUNCTIONS */ /// @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); } 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); // Check if recipient is contract if (_isContract(_to)) { bytes4 retval = IERC721Receiver(_to).onERC721Received( msg.sender, _from, _tokenId, _data ); require(retval == IERC721Receiver.onERC721Received.selector, "ERC721: transfer rejected"); } } /// @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, ''); } /// @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); } /// @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)); // Add NFT. Throws if `_tokenId` is owned by someone _addTokenTo(_to, _tokenId); if (_isContract(_to)) { bytes4 retval = IERC721Receiver(_to).onERC721Received( msg.sender, address(0), _tokenId, '' ); require(retval == IERC721Receiver.onERC721Received.selector); } emit Transfer(address(0), _to, _tokenId); return true; } /// @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); } /// @notice Locks tokenID vote for 1 week. /// @param _tokenId The identifier for an NFT. function lockVote(uint _tokenId) external { require(msg.sender == voter); require(_isVoteExpired(_tokenId),"Vote Locked!"); idToVoteExpiry[_tokenId] = block.timestamp + WEEK; } 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); } 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 `_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` 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` 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); } // 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)); } } modifier onlyAdmin() { require(msg.sender == admin, "veArc: only admin"); _; } function setAdmin(address _admin) external onlyAdmin { pendingAdmin = _admin; } function acceptAdmin() external { require(msg.sender == pendingAdmin); admin = pendingAdmin; } function setArtProxy(address _proxy) external onlyAdmin { 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)) ); } 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 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)); } /// @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); } function totalSupply() external view returns (uint) { return totalSupplyAtT(block.timestamp); } /// @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); } 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); // Remove token _removeTokenFrom(owner, _tokenId); emit Transfer(owner, address(0), _tokenId); } function tokensOfOwner(address _owner) external view returns (uint256[] memory) { uint256 tokenCount = _balance(_owner); uint256[] memory tokensId = new uint256[](tokenCount); for (uint256 i = 0; i < tokenCount; i++) { tokensId[i] = ownerToNFTokenIdList[_owner][i]; } return tokensId; } /// @notice Burn all tokens for `_tokenId` /// @dev Only possible if not vote locked function burn(uint _tokenId) external nonreentrant { assert(_isApprovedOrOwner(msg.sender, _tokenId)); require(attachments[_tokenId] == 0 && !voted[_tokenId], "attached"); require(_isVoteExpired(_tokenId), "Vote Locked!"); LockedBalance memory _locked = locked[_tokenId]; 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(address(0), value)); // Burn the NFT _burn(_tokenId); emit Burn(msg.sender, _tokenId, value, block.timestamp); emit Supply(supply_before, supply_before - value); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; /** * @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); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; import './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, uint indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint 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 (uint balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint tokenId) external view returns (address owner); /** * @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 be 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, uint tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * 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, uint 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, uint tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint tokenId) external view returns (address operator); /** * @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 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); /** * @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, uint tokenId, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; 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(uint tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; /** * @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 `IERC721.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; interface IVeArtProxy { function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output); }
{ "evmVersion": "paris", "optimizer": { "enabled": true, "runs": 10000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"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":"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":"Burn","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 veArc.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":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"abstain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","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":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"checkpoint","outputs":[],"stateMutability":"nonpayable","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":"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":"_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":"_tokenId","type":"uint256"}],"name":"isVoteExpired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"lockVote","outputs":[],"stateMutability":"nonpayable","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__amount","outputs":[{"internalType":"uint256","name":"","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":"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":[],"name":"pendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"_admin","type":"address"}],"name":"setAdmin","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":"_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":"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":[{"internalType":"address","name":"_owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_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":"_tokenId","type":"uint256"}],"name":"voteExpiry","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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
60a06040526017805460ff191660011790553480156200001e57600080fd5b506040516200445338038062004453833981016040819052620000419162000236565b6001600160a01b038216620000b75760405162461bcd60e51b815260206004820152603260248201527f566f74696e67457363726f773a207a65726f20616464726573732070726f76696044820152713232b21034b71031b7b739ba393ab1ba37b960711b606482015260840160405180910390fd5b6001600160a01b03828116608052600d8054336001600160a01b03199182168117909255437f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6e155427f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6e0556002805482169092179091556004805490911691831691909117905560166020527f9cc639f29250291fcbb6248883e1a95f95e699a88d257d48b111a34ed1ab2d24805460ff1990811660019081179092557f775982a8949a539cb4ab001182e8be95f56a8c0f4add6c647c9c34f1c6d7f34a8054821683179055635b5e139f60e01b60009081527fe7a9e5f85cf49d98d5a5d60d4201bc065774d31024dee5390463b37c7c0d043680549092169092179055600e546040519091309160008051602062004433833981519152908290a4600e54604051600090309060008051602062004433833981519152908390a450506200026e565b80516001600160a01b03811681146200023157600080fd5b919050565b600080604083850312156200024a57600080fd5b620002558362000219565b9150620002656020840162000219565b90509250929050565b6080516141946200029f60003960008181610a9601528181610eca0152818161129c015261338301526141946000f3fe608060405234801561001057600080fd5b50600436106103d05760003560e01c80637116c60c116101ff578063c26defcd1161011a578063e7e242d4116100ad578063f8a057631161007c578063f8a0576314610a5a578063fbd3a29d14610a7e578063fc0c546a14610a91578063fd4a77f114610ab857600080fd5b8063e7e242d4146109e5578063e985e9c5146109f8578063ee99fe2814610a34578063f851a44014610a4757600080fd5b8063d1febfb9116100e9578063d1febfb914610954578063d4e54c3b1461099f578063e0514aba146109b2578063e441135c146109c557600080fd5b8063c26defcd14610913578063c2c4c5c114610926578063c87b56dd1461092e578063d1c2babb1461094157600080fd5b8063981b24d011610192578063a4d855df11610161578063a4d855df14610892578063b45a3c0e146108a5578063b88d4fde146108ed578063c1f0fb9f1461090057600080fd5b8063981b24d014610846578063986b7d8a14610859578063a183af521461086c578063a22cb4651461087f57600080fd5b80638fbb38ff116101ce5780638fbb38ff146107f7578063900cf0cf1461081a57806395d89b41146104465780639700ad3a1461082357600080fd5b80637116c60c1461078e57806371197484146107a15780638462151c146107c45780638c2c9baf146107e457600080fd5b80632f745c59116102ef57806354fd4d5011610282578063672790541161025157806367279054146107355780636f54883714610748578063704b6c021461076857806370a082311461077b57600080fd5b806354fd4d50146106aa5780635594a045146106e65780636352211e146106f957806365fc38731461072257600080fd5b8063430c2081116102be578063430c20811461064b578063461f711c1461065e57806346c96aac146106845780634bc2a6571461069757600080fd5b80632f745c59146105d5578063313ce5671461060b57806342842e0e1461062557806342966c681461063857600080fd5b80631376f3da1161036757806325a58b561161033657806325a58b5614610596578063267822471461059c5780632e1a7d4d146105af5780632e720f7d146105c257600080fd5b80631376f3da1461052d57806318160ddd146105685780631c984bc31461057057806323b872dd1461058357600080fd5b8063095ea7b3116103a3578063095ea7b3146104d057806309a934bb146104e55780630d6a2033146105055780630e18b6811461052557600080fd5b806301ffc9a7146103d5578063047fc9aa1461042f57806306fdde0314610446578063081812fc1461048f575b600080fd5b61041a6103e3366004613993565b7fffffffff000000000000000000000000000000000000000000000000000000001660009081526016602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61043860005481565b604051908152602001610426565b6104826040518060400160405280600581526020017f766541726300000000000000000000000000000000000000000000000000000081525081565b6040516104269190613a1e565b6104b861049d366004613a31565b6000908152601060205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610426565b6104e36104de366004613a66565b610acb565b005b6104386104f3366004613a31565b60009081526014602052604090205490565b610438610513366004613a31565b600b6020526000908152604090205481565b6104e3610bcb565b61054061053b366004613a90565b610c1e565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610426565b610438610c72565b61043861057e366004613a90565b610c82565b6104e3610591366004613ab2565b610cb5565b43610438565b6003546104b8906001600160a01b031681565b6104e36105bd366004613a31565b610cc6565b6104e36105d0366004613aee565b610ff1565b6104386105e3366004613a66565b6001600160a01b03919091166000908152601260209081526040808320938352929052205490565b610613601281565b60405160ff9091168152602001610426565b6104e3610633366004613ab2565b611085565b6104e3610646366004613a31565b6110a0565b61041a610659366004613a66565b611368565b61067161066c366004613a31565b61137b565b604051600f9190910b8152602001610426565b600d546104b8906001600160a01b031681565b6104e36106a5366004613aee565b6113cb565b6104826040518060400160405280600581526020017f322e302e3000000000000000000000000000000000000000000000000000000081525081565b6004546104b8906001600160a01b031681565b6104b8610707366004613a31565b6000908152600f60205260409020546001600160a01b031690565b610438610730366004613a90565b61141c565b6104e3610743366004613a31565b61145e565b610438610756366004613a31565b60056020526000908152604090205481565b6104e3610776366004613aee565b6114f1565b610438610789366004613aee565b611585565b61043861079c366004613a31565b6115a3565b6106716107af366004613a31565b600a60205260009081526040902054600f0b81565b6107d76107d2366004613aee565b611610565b6040516104269190613b09565b6104386107f2366004613a90565b6116da565b61041a610805366004613a31565b600c6020526000908152604090205460ff1681565b61043860065481565b610438610831366004613a31565b600090815260016020526040902054600f0b90565b610438610854366004613a31565b6116e6565b6104e3610867366004613a31565b6118a2565b6104e361087a366004613a90565b6118e6565b6104e361088d366004613b5b565b611a41565b6104e36108a0366004613a90565b611ac5565b6108d36108b3366004613a31565b60016020819052600091825260409091208054910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610426565b6104e36108fb366004613c56565b611cc4565b6104e361090e366004613a31565b611e03565b61041a610921366004613a31565b611e32565b6104e3611e48565b61048261093c366004613a31565b611e88565b6104e361094f366004613a90565b611fea565b610540610962366004613a31565b600760205260009081526040902080546001820154600290920154600f82810b93700100000000000000000000000000000000909304900b919084565b6104386109ad366004613d01565b6121a5565b6104386109c0366004613a90565b6121e8565b6104386109d3366004613a31565b60096020526000908152604090205481565b6104386109f3366004613a31565b6121f4565b61041a610a06366004613d36565b6001600160a01b03918216600090815260156020908152604080832093909416825291909152205460ff1690565b6104e3610a42366004613a90565b61221c565b6002546104b8906001600160a01b031681565b610438610a68366004613a31565b6000908152600160208190526040909120015490565b6104e3610a8c366004613a31565b61234c565b6104b87f000000000000000000000000000000000000000000000000000000000000000081565b6104e3610ac6366004613a31565b61237d565b6000818152600f60205260409020546001600160a01b031680610aed57600080fd5b806001600160a01b0316836001600160a01b031603610b0b57600080fd5b6000828152600f60209081526040808320546001600160a01b0385811685526015845282852033808752945291909320549216149060ff168180610b4c5750805b610b5557600080fd5b60008481526010602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b6003546001600160a01b03163314610be257600080fd5b600354600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03909216919091179055565b600860205281600052604060002081633b9aca008110610c3d57600080fd5b6003020180546001820154600290920154600f82810b955070010000000000000000000000000000000090920490910b925084565b6000610c7d426115a3565b905090565b600082815260086020526040812082633b9aca008110610ca457610ca4613d69565b600302016001015490505b92915050565b610cc1838383336123af565b505050565b60175460ff16600114610cd857600080fd5b6017805460ff19166002179055610cef33826124a5565b610cfb57610cfb613d98565b6000818152600b6020526040902054158015610d2657506000818152600c602052604090205460ff16155b610d775760405162461bcd60e51b815260206004820152600860248201527f617474616368656400000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b60008181526001602081815260409283902083518085019094528054600f0b845290910154908201819052421015610df15760405162461bcd60e51b815260206004820152601660248201527f546865206c6f636b206469646e277420657870697265000000000000000000006044820152606401610d6e565b805160408051808201825260008082526020808301828152878352600191829052938220925183547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff9091161783559251919092015554600f9190910b90610e6b8282613df6565b600081905550610e95848460405180604001604052806000600f0b8152602001600081525061250b565b6040517fa9059cbb000000000000000000000000000000000000000000000000000000008152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015610f1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3f9190613e09565b610f4b57610f4b613d98565b610f5484612bb0565b6040805185815260208101849052429181019190915233907f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94906060015b60405180910390a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c81610fc68482613df6565b6040805192835260208301919091520160405180910390a150506017805460ff191660011790555050565b6002546001600160a01b0316331461104b5760405162461bcd60e51b815260206004820152601160248201527f76654172633a206f6e6c792061646d696e0000000000000000000000000000006044820152606401610d6e565b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610cc183838360405180602001604052806000815250611cc4565b60175460ff166001146110b257600080fd5b6017805460ff191660021790556110c933826124a5565b6110d5576110d5613d98565b6000818152600b602052604090205415801561110057506000818152600c602052604090205460ff16155b61114c5760405162461bcd60e51b815260206004820152600860248201527f61747461636865640000000000000000000000000000000000000000000000006044820152606401610d6e565b60008181526014602052604090205442116111a95760405162461bcd60e51b815260206004820152600c60248201527f566f7465204c6f636b65642100000000000000000000000000000000000000006044820152606401610d6e565b6000818152600160208181526040808420815180830183528154600f81900b80835283870180548488015285518087019096528886528587018981528a8a529790965293516fffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116179091559251909155915490919061123c8282613df6565b600081905550611266848460405180604001604052806000600f0b8152602001600081525061250b565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815260006004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af11580156112ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113119190613e09565b61131d5761131d613d98565b61132684612bb0565b6040805185815260208101849052429181019190915233907f743033787f4738ff4d6a7225ce2bd0977ee5f86b91a902a58f5e4d0b297b464490606001610f92565b600061137483836124a5565b9392505050565b6000818152600960209081526040808320546008909252822081633b9aca0081106113a8576113a8613d69565b60030201547001000000000000000000000000000000009004600f0b9392505050565b600d546001600160a01b031633146113e257600080fd5b600d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60175460009060ff1660011461143157600080fd5b6017805460ff19166002179055611449838333612c6f565b90506017805460ff1916600117905592915050565b600d546001600160a01b0316331461147557600080fd5b60008181526014602052604090205442116114d25760405162461bcd60e51b815260206004820152600c60248201527f566f7465204c6f636b65642100000000000000000000000000000000000000006044820152606401610d6e565b6114df62093a8042613e26565b60009182526014602052604090912055565b6002546001600160a01b0316331461154b5760405162461bcd60e51b815260206004820152601160248201527f76654172633a206f6e6c792061646d696e0000000000000000000000000000006044820152606401610d6e565b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6001600160a01b038116600090815260116020526040812054610caf565b600654600081815260076020908152604080832081516080810183528154600f81810b8352700100000000000000000000000000000000909104900b938101939093526001810154918301919091526002015460608201529091906116088185612dd7565b949350505050565b60606000611633836001600160a01b031660009081526011602052604090205490565b905060008167ffffffffffffffff81111561165057611650613b92565b604051908082528060200260200182016040528015611679578160200160208202803683370190505b50905060005b828110156116d2576001600160a01b038516600090815260126020908152604080832084845290915290205482518390839081106116bf576116bf613d69565b602090810291909101015260010161167f565b509392505050565b60006113748383612ed9565b6000438211156116f8576116f8613d98565b600654600061170784836131da565b600081815260076020908152604080832081516080810183528154600f81810b8352700100000000000000000000000000000000909104900b9381019390935260018101549183019190915260020154606082015291925083831015611830576000600781611777866001613e26565b8152602080820192909252604090810160002081516080810183528154600f81810b8352700100000000000000000000000000000000909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461182a57826060015181606001516117f09190613df6565b836040015182604001516118049190613df6565b6060850151611813908a613df6565b61181d9190613e39565b6118279190613e7f565b91505b5061187f565b4382606001511461187f57606082015161184a9043613df6565b60408301516118599042613df6565b60608401516118689089613df6565b6118729190613e39565b61187c9190613e7f565b90505b611898828284604001516118939190613e26565b612dd7565b9695505050505050565b600d546001600160a01b031633146118b957600080fd5b6000818152600b60205260409020546118d490600190613df6565b6000918252600b602052604090912055565b60175460ff166001146118f857600080fd5b6017805460ff1916600217905561190f33836124a5565b61191b5761191b613d98565b60008281526001602081815260409283902083518085019094528054600f0b845290910154908201528161195157611951613d98565b60008160000151600f0b136119a85760405162461bcd60e51b815260206004820152601660248201527f4e6f206578697374696e67206c6f636b20666f756e64000000000000000000006044820152606401610d6e565b42816020015111611a205760405162461bcd60e51b8152602060048201526024808201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e205769746860448201527f64726177000000000000000000000000000000000000000000000000000000006064820152608401610d6e565b611a2f83836000846002613258565b50506017805460ff1916600117905550565b336001600160a01b03831603611a5957611a59613d98565b3360008181526015602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60175460ff16600114611ad757600080fd5b6017805460ff19166002179055611aee33836124a5565b611afa57611afa613d98565b600082815260016020818152604080842081518083019092528054600f0b825290920154908201529062093a8080611b328542613e26565b611b3c9190613e7f565b611b469190613e39565b905042826020015111611b9b5760405162461bcd60e51b815260206004820152600c60248201527f4c6f636b206578706972656400000000000000000000000000000000000000006044820152606401610d6e565b60008260000151600f0b13611bf25760405162461bcd60e51b815260206004820152601160248201527f4e6f7468696e67206973206c6f636b65640000000000000000000000000000006044820152606401610d6e565b81602001518111611c455760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610d6e565b611c53630784ce0042613e26565b811115611ca25760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610d6e565b611cb184600083856003613258565b50506017805460ff191660011790555050565b611cd0848484336123af565b823b15611dfd576040517f150b7a020000000000000000000000000000000000000000000000000000000081526000906001600160a01b0385169063150b7a0290611d25903390899088908890600401613e93565b6020604051808303816000875af1158015611d44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d689190613ec5565b90507fffffffff0000000000000000000000000000000000000000000000000000000081167f150b7a020000000000000000000000000000000000000000000000000000000014611dfb5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a207472616e736665722072656a6563746564000000000000006044820152606401610d6e565b505b50505050565b600d546001600160a01b03163314611e1a57600080fd5b6000908152600c60205260409020805460ff19169055565b6000818152601460205260408120544211610caf565b611e86600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b8152602001600081525061250b565b565b6000818152600f60205260409020546060906001600160a01b0316611eef5760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610d6e565b60008281526001602081815260409283902083518085019094528054600f0b845290910154908201526004546001600160a01b031663dd9ec14984611f348142613497565b6020850151855160405160e086901b7fffffffff00000000000000000000000000000000000000000000000000000000168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015611fa4573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526113749190810190613ee2565b6000828152600b602052604090205415801561201557506000828152600c602052604090205460ff16155b6120615760405162461bcd60e51b815260206004820152600860248201527f61747461636865640000000000000000000000000000000000000000000000006044820152606401610d6e565b80820361206d57600080fd5b61207733836124a5565b61208057600080fd5b61208a33826124a5565b61209357600080fd5b6000828152600160208181526040808420815180830183528154600f90810b82529185015481850190815287875285855283872084518086019095528054840b855290950154938301849052805194519095929490910b9211156120fb578260200151612101565b83602001515b604080518082018252600080825260208083018281528b83526001808352858420945185547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff9091161785559051930192909255825180840190935280835290820152909150612186908790869061250b565b61218f86612bb0565b61219d858383866004613258565b505050505050565b60175460009060ff166001146121ba57600080fd5b6017805460ff191660021790556121d2848484612c6f565b90506017805460ff191660011790559392505050565b60006113748383613497565b60008181526005602052604081205443900361221257506000919050565b610caf8242613497565b60175460ff1660011461222e57600080fd5b6017805460ff1916600217905560008281526001602081815260409283902083518085019094528054600f0b845290910154908201528161226e57600080fd5b60008160000151600f0b136122c55760405162461bcd60e51b815260206004820152601660248201527f4e6f206578697374696e67206c6f636b20666f756e64000000000000000000006044820152606401610d6e565b4281602001511161233d5760405162461bcd60e51b8152602060048201526024808201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e205769746860448201527f64726177000000000000000000000000000000000000000000000000000000006064820152608401610d6e565b611a2f83836000846000613258565b600d546001600160a01b0316331461236357600080fd5b6000818152600b60205260409020546118d4906001613e26565b600d546001600160a01b0316331461239457600080fd5b6000908152600c60205260409020805460ff19166001179055565b6000828152600b60205260409020541580156123da57506000828152600c602052604090205460ff16155b6124265760405162461bcd60e51b815260206004820152600860248201527f61747461636865640000000000000000000000000000000000000000000000006044820152606401610d6e565b61243081836124a5565b61243957600080fd5b612443848361357f565b61244d84836135fe565b6124578383613697565b6000828152600560205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b6000818152600f602090815260408083205460108352818420546001600160a01b039182168086526015855283862088841680885295529285205492938085149392909116149060ff1682806124f85750815b806125005750805b979650505050505050565b604080516080810182526000808252602082018190529181018290526060810191909152604080516080810182526000808252602082018190529181018290526060810191909152600654600090819087156126765742876020015111801561257b575060008760000151600f0b135b156125c057865161259190630784ce0090613f50565b600f0b6020808701919091528701516125ab904290613df6565b85602001516125ba9190613fc4565b600f0b85525b4286602001511180156125da575060008660000151600f0b135b1561261f5785516125f090630784ce0090613f50565b600f0b60208086019190915286015161260a904290613df6565b84602001516126199190613fc4565b600f0b84525b6020808801516000908152600a8252604090205490870151600f9190910b93501561267657866020015186602001510361265b57829150612676565b6020808701516000908152600a9091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126f8575060008181526007602090815260409182902082516080810184528154600f81810b8352700100000000000000000000000000000000909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127455760408401516127179042613df6565b60608501516127269043613df6565b61273890670de0b6b3a7640000613e39565b6127429190613e7f565b90505b600062093a806127558186613e7f565b61275f9190613e39565b905060005b60ff8110156128e75761277a62093a8083613e26565b915060004283111561278e574292506127a2565b506000828152600a6020526040902054600f0b5b6127ac8684613df6565b87602001516127bb9190613fc4565b875188906127ca908390613fe4565b600f0b9052506020870180518291906127e4908390614032565b600f90810b90915288516000910b121590506127ff57600087525b60008760200151600f0b121561281757600060208801525b60408088018490528501519295508592670de0b6b3a76400009061283b9085613df6565b6128459086613e39565b61284f9190613e7f565b856060015161285e9190613e26565b606088015261286e600189613e26565b975042830361288357504360608701526128e7565b6000888152600760209081526040918290208951918a01516fffffffffffffffffffffffffffffffff908116700100000000000000000000000000000000029216919091178155908801516001820155606088015160029091015550600101612764565b505060068590558b1561297257886020015188602001516129089190613fe4565b846020018181516129199190614032565b600f0b9052508851885161292d9190613fe4565b8451859061293c908390614032565b600f90810b90915260208601516000910b1215905061295d57600060208501525b60008460000151600f0b121561297257600084525b6000858152600760209081526040918290208651918701516fffffffffffffffffffffffffffffffff90811670010000000000000000000000000000000002921691909117815590850151600182015560608501516002909101558b15612ba257428b602001511115612a605760208901516129ee9088614032565b96508a602001518a6020015103612a11576020880151612a0e9088613fe4565b96505b60208b8101516000908152600a9091526040902080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff89161790555b428a602001511115612adc578a602001518a602001511115612adc576020880151612a8b9087613fe4565b60208b8101516000908152600a9091526040902080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff831617905595505b60008c815260096020526040812054612af6906001613e26565b905080600960008f815260200190815260200160002081905550428960400181815250504389606001818152505088600860008f815260200190815260200160002082633b9aca008110612b4c57612b4c613d69565b825160208401516fffffffffffffffffffffffffffffffff908116700100000000000000000000000000000000029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612bba33826124a5565b612c065760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610d6e565b6000818152600f60205260408120546001600160a01b031690612c299083610acb565b612c3381836135fe565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b60008062093a8080612c818642613e26565b612c8b9190613e7f565b612c959190613e39565b905060008511612ca457600080fd5b428111612d195760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201527f66757475726500000000000000000000000000000000000000000000000000006064820152608401610d6e565b612d27630784ce0042613e26565b811115612d765760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610d6e565b600e60008154612d8590614080565b90915550600e54612d968482613745565b5060008181526001602081815260409283902083518085019094528054600f0b845282015490830152612dce91839189918691613258565b95945050505050565b600080839050600062093a80808360400151612df39190613e7f565b612dfd9190613e39565b905060005b60ff811015612ea857612e1862093a8083613e26565b9150600085831115612e2c57859250612e40565b506000828152600a6020526040902054600f0b5b6040840151612e4f9084613df6565b8460200151612e5e9190613fc4565b84518590612e6d908390613fe4565b600f0b905250858303612e805750612ea8565b8084602001818151612e929190614032565b600f0b9052505060408301829052600101612e02565b5060008260000151600f0b1215612ebe57600082525b50516fffffffffffffffffffffffffffffffff169392505050565b600043821115612eeb57612eeb613d98565b600083815260096020526040812054815b6080811015612f835781831015612f835760006002612f1b8486613e26565b612f26906001613e26565b612f309190613e7f565b6000888152600860205260409020909150869082633b9aca008110612f5757612f57613d69565b600302016002015411612f6c57809350612f7a565b612f77600182613df6565b92505b50600101612efc565b50600085815260086020526040812083633b9aca008110612fa657612fa6613d69565b60408051608081018252600392909202929092018054600f81810b8452700100000000000000000000000000000000909104900b60208301526001810154928201929092526002909101546060820152600654909150600061300887836131da565b600081815260076020908152604080832081516080810183528154600f81810b8352700100000000000000000000000000000000909104900b938101939093526001810154918301919091526002015460608201529192508084841015613101576000600781613079876001613e26565b8152602080820192909252604090810160002081516080810183528154600f81810b8352700100000000000000000000000000000000909104900b938101939093526001810154918301919091526002015460608083018290528601519192506130e39190613df6565b9250836040015181604001516130f99190613df6565b915050613125565b60608301516131109043613df6565b91508260400151426131229190613df6565b90505b60408301518215613162578284606001518c6131419190613df6565b61314b9084613e39565b6131559190613e7f565b61315f9082613e26565b90505b60408701516131719082613df6565b87602001516131809190613fc4565b8751889061318f908390613fe4565b600f90810b90915288516000910b1290506131c857505093516fffffffffffffffffffffffffffffffff169650610caf95505050505050565b60009950505050505050505050610caf565b60008082815b608081101561324e578183101561324e57600060026131ff8486613e26565b61320a906001613e26565b6132149190613e7f565b600081815260076020526040902060020154909150871061323757809350613245565b613242600182613df6565b92505b506001016131e0565b5090949350505050565b60005482906132678682613e26565b6000908155604080518082019091528181526020810191909152825160208085015190830152600f0b81528251879084906132a3908390614032565b600f0b90525085156132b757602083018690525b6000888152600160208181526040909220855181547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff9091161781559185015191015561331788828561250b565b33871580159061333957506004856004811115613336576133366140b8565b14155b156133fc576040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133f09190613e09565b6133fc576133fc613d98565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b894260405161344094939291906140e7565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134748a82613e26565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000828152600960205260408120548082036134b7576000915050610caf565b600084815260086020526040812082633b9aca0081106134d9576134d9613d69565b60408051608081018252600392909202929092018054600f81810b8452700100000000000000000000000000000000909104900b602083015260018101549282018390526002015460608201529150613532908561413e565b81602001516135419190613fc4565b81518290613550908390613fe4565b600f90810b90915282516000910b1215905061356b57600081525b51600f0b9150610caf9050565b5092915050565b6000818152600f60205260409020546001600160a01b038381169116146135a8576135a8613d98565b6000818152601060205260409020546001600160a01b0316156135fa57600081815260106020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555b5050565b6000818152600f60205260409020546001600160a01b0383811691161461362757613627613d98565b6000818152600f6020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561366582826138a3565b6001600160a01b038216600090815260116020526040812080546001929061368e908490613df6565b90915550505050565b6000818152600f60205260409020546001600160a01b0316156136bc576136bc613d98565b6000818152600f6020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03871690811790915580845260118084528285208054601286528487208188528652848720889055878752601386529386209390935590845290915280546001929061368e908490613e26565b60006001600160a01b03831661375d5761375d613d98565b6137678383613697565b823b15613862576040517f150b7a02000000000000000000000000000000000000000000000000000000008152336004820152600060248201819052604482018490526080606483015260848201819052906001600160a01b0385169063150b7a029060a4016020604051808303816000875af11580156137ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138109190613ec5565b90507fffffffff0000000000000000000000000000000000000000000000000000000081167f150b7a02000000000000000000000000000000000000000000000000000000001461386057600080fd5b505b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b0382166000908152601160205260408120546138c890600190613df6565b600083815260136020526040902054909150808203613917576001600160a01b038416600090815260126020908152604080832085845282528083208390558583526013909152812055611dfd565b6001600160a01b039390931660009081526012602090815260408083209383529281528282208054868452848420819055835260139091528282209490945592839055908252812055565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461399057600080fd5b50565b6000602082840312156139a557600080fd5b813561137481613962565b60005b838110156139cb5781810151838201526020016139b3565b50506000910152565b600081518084526139ec8160208601602086016139b0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061137460208301846139d4565b600060208284031215613a4357600080fd5b5035919050565b80356001600160a01b0381168114613a6157600080fd5b919050565b60008060408385031215613a7957600080fd5b613a8283613a4a565b946020939093013593505050565b60008060408385031215613aa357600080fd5b50508035926020909101359150565b600080600060608486031215613ac757600080fd5b613ad084613a4a565b9250613ade60208501613a4a565b9150604084013590509250925092565b600060208284031215613b0057600080fd5b61137482613a4a565b6020808252825182820181905260009190848201906040850190845b81811015613b4157835183529284019291840191600101613b25565b50909695505050505050565b801515811461399057600080fd5b60008060408385031215613b6e57600080fd5b613b7783613a4a565b91506020830135613b8781613b4d565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613c0857613c08613b92565b604052919050565b600067ffffffffffffffff821115613c2a57613c2a613b92565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60008060008060808587031215613c6c57600080fd5b613c7585613a4a565b9350613c8360208601613a4a565b925060408501359150606085013567ffffffffffffffff811115613ca657600080fd5b8501601f81018713613cb757600080fd5b8035613cca613cc582613c10565b613bc1565b818152886020838501011115613cdf57600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b600080600060608486031215613d1657600080fd5b8335925060208401359150613d2d60408501613a4a565b90509250925092565b60008060408385031215613d4957600080fd5b613d5283613a4a565b9150613d6060208401613a4a565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610caf57610caf613dc7565b600060208284031215613e1b57600080fd5b815161137481613b4d565b80820180821115610caf57610caf613dc7565b8082028115828204841417610caf57610caf613dc7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613e8e57613e8e613e50565b500490565b60006001600160a01b0380871683528086166020840152508360408301526080606083015261189860808301846139d4565b600060208284031215613ed757600080fd5b815161137481613962565b600060208284031215613ef457600080fd5b815167ffffffffffffffff811115613f0b57600080fd5b8201601f81018413613f1c57600080fd5b8051613f2a613cc582613c10565b818152856020838501011115613f3f57600080fd5b612dce8260208301602086016139b0565b600081600f0b83600f0b80613f6757613f67613e50565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81147fffffffffffffffffffffffffffffffff8000000000000000000000000000000083141615613fbb57613fbb613dc7565b90059392505050565b600082600f0b82600f0b0280600f0b915080821461357857613578613dc7565b600f82810b9082900b037fffffffffffffffffffffffffffffffff8000000000000000000000000000000081126f7fffffffffffffffffffffffffffffff82131715610caf57610caf613dc7565b600f81810b9083900b016f7fffffffffffffffffffffffffffffff81137fffffffffffffffffffffffffffffffff8000000000000000000000000000000082121715610caf57610caf613dc7565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036140b1576140b1613dc7565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b84815260208101849052608081016005841061412c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60408201939093526060015292915050565b818103600083128015838313168383128216171561357857613578613dc756fea2646970667358221220cb363f2ca7ceaee0a60b003e1a14572a594b8b94fc37e6cb989ee571313cc93764736f6c63430008160033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef000000000000000000000000e8876189a80b2079d8c0a7867e46c50361d972c100000000000000000000000036c530a35e7f2ea46bf1c3d9d0b12ece2a8dcba2
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103d05760003560e01c80637116c60c116101ff578063c26defcd1161011a578063e7e242d4116100ad578063f8a057631161007c578063f8a0576314610a5a578063fbd3a29d14610a7e578063fc0c546a14610a91578063fd4a77f114610ab857600080fd5b8063e7e242d4146109e5578063e985e9c5146109f8578063ee99fe2814610a34578063f851a44014610a4757600080fd5b8063d1febfb9116100e9578063d1febfb914610954578063d4e54c3b1461099f578063e0514aba146109b2578063e441135c146109c557600080fd5b8063c26defcd14610913578063c2c4c5c114610926578063c87b56dd1461092e578063d1c2babb1461094157600080fd5b8063981b24d011610192578063a4d855df11610161578063a4d855df14610892578063b45a3c0e146108a5578063b88d4fde146108ed578063c1f0fb9f1461090057600080fd5b8063981b24d014610846578063986b7d8a14610859578063a183af521461086c578063a22cb4651461087f57600080fd5b80638fbb38ff116101ce5780638fbb38ff146107f7578063900cf0cf1461081a57806395d89b41146104465780639700ad3a1461082357600080fd5b80637116c60c1461078e57806371197484146107a15780638462151c146107c45780638c2c9baf146107e457600080fd5b80632f745c59116102ef57806354fd4d5011610282578063672790541161025157806367279054146107355780636f54883714610748578063704b6c021461076857806370a082311461077b57600080fd5b806354fd4d50146106aa5780635594a045146106e65780636352211e146106f957806365fc38731461072257600080fd5b8063430c2081116102be578063430c20811461064b578063461f711c1461065e57806346c96aac146106845780634bc2a6571461069757600080fd5b80632f745c59146105d5578063313ce5671461060b57806342842e0e1461062557806342966c681461063857600080fd5b80631376f3da1161036757806325a58b561161033657806325a58b5614610596578063267822471461059c5780632e1a7d4d146105af5780632e720f7d146105c257600080fd5b80631376f3da1461052d57806318160ddd146105685780631c984bc31461057057806323b872dd1461058357600080fd5b8063095ea7b3116103a3578063095ea7b3146104d057806309a934bb146104e55780630d6a2033146105055780630e18b6811461052557600080fd5b806301ffc9a7146103d5578063047fc9aa1461042f57806306fdde0314610446578063081812fc1461048f575b600080fd5b61041a6103e3366004613993565b7fffffffff000000000000000000000000000000000000000000000000000000001660009081526016602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61043860005481565b604051908152602001610426565b6104826040518060400160405280600581526020017f766541726300000000000000000000000000000000000000000000000000000081525081565b6040516104269190613a1e565b6104b861049d366004613a31565b6000908152601060205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610426565b6104e36104de366004613a66565b610acb565b005b6104386104f3366004613a31565b60009081526014602052604090205490565b610438610513366004613a31565b600b6020526000908152604090205481565b6104e3610bcb565b61054061053b366004613a90565b610c1e565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610426565b610438610c72565b61043861057e366004613a90565b610c82565b6104e3610591366004613ab2565b610cb5565b43610438565b6003546104b8906001600160a01b031681565b6104e36105bd366004613a31565b610cc6565b6104e36105d0366004613aee565b610ff1565b6104386105e3366004613a66565b6001600160a01b03919091166000908152601260209081526040808320938352929052205490565b610613601281565b60405160ff9091168152602001610426565b6104e3610633366004613ab2565b611085565b6104e3610646366004613a31565b6110a0565b61041a610659366004613a66565b611368565b61067161066c366004613a31565b61137b565b604051600f9190910b8152602001610426565b600d546104b8906001600160a01b031681565b6104e36106a5366004613aee565b6113cb565b6104826040518060400160405280600581526020017f322e302e3000000000000000000000000000000000000000000000000000000081525081565b6004546104b8906001600160a01b031681565b6104b8610707366004613a31565b6000908152600f60205260409020546001600160a01b031690565b610438610730366004613a90565b61141c565b6104e3610743366004613a31565b61145e565b610438610756366004613a31565b60056020526000908152604090205481565b6104e3610776366004613aee565b6114f1565b610438610789366004613aee565b611585565b61043861079c366004613a31565b6115a3565b6106716107af366004613a31565b600a60205260009081526040902054600f0b81565b6107d76107d2366004613aee565b611610565b6040516104269190613b09565b6104386107f2366004613a90565b6116da565b61041a610805366004613a31565b600c6020526000908152604090205460ff1681565b61043860065481565b610438610831366004613a31565b600090815260016020526040902054600f0b90565b610438610854366004613a31565b6116e6565b6104e3610867366004613a31565b6118a2565b6104e361087a366004613a90565b6118e6565b6104e361088d366004613b5b565b611a41565b6104e36108a0366004613a90565b611ac5565b6108d36108b3366004613a31565b60016020819052600091825260409091208054910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610426565b6104e36108fb366004613c56565b611cc4565b6104e361090e366004613a31565b611e03565b61041a610921366004613a31565b611e32565b6104e3611e48565b61048261093c366004613a31565b611e88565b6104e361094f366004613a90565b611fea565b610540610962366004613a31565b600760205260009081526040902080546001820154600290920154600f82810b93700100000000000000000000000000000000909304900b919084565b6104386109ad366004613d01565b6121a5565b6104386109c0366004613a90565b6121e8565b6104386109d3366004613a31565b60096020526000908152604090205481565b6104386109f3366004613a31565b6121f4565b61041a610a06366004613d36565b6001600160a01b03918216600090815260156020908152604080832093909416825291909152205460ff1690565b6104e3610a42366004613a90565b61221c565b6002546104b8906001600160a01b031681565b610438610a68366004613a31565b6000908152600160208190526040909120015490565b6104e3610a8c366004613a31565b61234c565b6104b87f000000000000000000000000e8876189a80b2079d8c0a7867e46c50361d972c181565b6104e3610ac6366004613a31565b61237d565b6000818152600f60205260409020546001600160a01b031680610aed57600080fd5b806001600160a01b0316836001600160a01b031603610b0b57600080fd5b6000828152600f60209081526040808320546001600160a01b0385811685526015845282852033808752945291909320549216149060ff168180610b4c5750805b610b5557600080fd5b60008481526010602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b6003546001600160a01b03163314610be257600080fd5b600354600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03909216919091179055565b600860205281600052604060002081633b9aca008110610c3d57600080fd5b6003020180546001820154600290920154600f82810b955070010000000000000000000000000000000090920490910b925084565b6000610c7d426115a3565b905090565b600082815260086020526040812082633b9aca008110610ca457610ca4613d69565b600302016001015490505b92915050565b610cc1838383336123af565b505050565b60175460ff16600114610cd857600080fd5b6017805460ff19166002179055610cef33826124a5565b610cfb57610cfb613d98565b6000818152600b6020526040902054158015610d2657506000818152600c602052604090205460ff16155b610d775760405162461bcd60e51b815260206004820152600860248201527f617474616368656400000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b60008181526001602081815260409283902083518085019094528054600f0b845290910154908201819052421015610df15760405162461bcd60e51b815260206004820152601660248201527f546865206c6f636b206469646e277420657870697265000000000000000000006044820152606401610d6e565b805160408051808201825260008082526020808301828152878352600191829052938220925183547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff9091161783559251919092015554600f9190910b90610e6b8282613df6565b600081905550610e95848460405180604001604052806000600f0b8152602001600081525061250b565b6040517fa9059cbb000000000000000000000000000000000000000000000000000000008152336004820152602481018390527f000000000000000000000000e8876189a80b2079d8c0a7867e46c50361d972c16001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015610f1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3f9190613e09565b610f4b57610f4b613d98565b610f5484612bb0565b6040805185815260208101849052429181019190915233907f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94906060015b60405180910390a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c81610fc68482613df6565b6040805192835260208301919091520160405180910390a150506017805460ff191660011790555050565b6002546001600160a01b0316331461104b5760405162461bcd60e51b815260206004820152601160248201527f76654172633a206f6e6c792061646d696e0000000000000000000000000000006044820152606401610d6e565b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610cc183838360405180602001604052806000815250611cc4565b60175460ff166001146110b257600080fd5b6017805460ff191660021790556110c933826124a5565b6110d5576110d5613d98565b6000818152600b602052604090205415801561110057506000818152600c602052604090205460ff16155b61114c5760405162461bcd60e51b815260206004820152600860248201527f61747461636865640000000000000000000000000000000000000000000000006044820152606401610d6e565b60008181526014602052604090205442116111a95760405162461bcd60e51b815260206004820152600c60248201527f566f7465204c6f636b65642100000000000000000000000000000000000000006044820152606401610d6e565b6000818152600160208181526040808420815180830183528154600f81900b80835283870180548488015285518087019096528886528587018981528a8a529790965293516fffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116179091559251909155915490919061123c8282613df6565b600081905550611266848460405180604001604052806000600f0b8152602001600081525061250b565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815260006004820152602481018390527f000000000000000000000000e8876189a80b2079d8c0a7867e46c50361d972c16001600160a01b03169063a9059cbb906044016020604051808303816000875af11580156112ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113119190613e09565b61131d5761131d613d98565b61132684612bb0565b6040805185815260208101849052429181019190915233907f743033787f4738ff4d6a7225ce2bd0977ee5f86b91a902a58f5e4d0b297b464490606001610f92565b600061137483836124a5565b9392505050565b6000818152600960209081526040808320546008909252822081633b9aca0081106113a8576113a8613d69565b60030201547001000000000000000000000000000000009004600f0b9392505050565b600d546001600160a01b031633146113e257600080fd5b600d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60175460009060ff1660011461143157600080fd5b6017805460ff19166002179055611449838333612c6f565b90506017805460ff1916600117905592915050565b600d546001600160a01b0316331461147557600080fd5b60008181526014602052604090205442116114d25760405162461bcd60e51b815260206004820152600c60248201527f566f7465204c6f636b65642100000000000000000000000000000000000000006044820152606401610d6e565b6114df62093a8042613e26565b60009182526014602052604090912055565b6002546001600160a01b0316331461154b5760405162461bcd60e51b815260206004820152601160248201527f76654172633a206f6e6c792061646d696e0000000000000000000000000000006044820152606401610d6e565b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6001600160a01b038116600090815260116020526040812054610caf565b600654600081815260076020908152604080832081516080810183528154600f81810b8352700100000000000000000000000000000000909104900b938101939093526001810154918301919091526002015460608201529091906116088185612dd7565b949350505050565b60606000611633836001600160a01b031660009081526011602052604090205490565b905060008167ffffffffffffffff81111561165057611650613b92565b604051908082528060200260200182016040528015611679578160200160208202803683370190505b50905060005b828110156116d2576001600160a01b038516600090815260126020908152604080832084845290915290205482518390839081106116bf576116bf613d69565b602090810291909101015260010161167f565b509392505050565b60006113748383612ed9565b6000438211156116f8576116f8613d98565b600654600061170784836131da565b600081815260076020908152604080832081516080810183528154600f81810b8352700100000000000000000000000000000000909104900b9381019390935260018101549183019190915260020154606082015291925083831015611830576000600781611777866001613e26565b8152602080820192909252604090810160002081516080810183528154600f81810b8352700100000000000000000000000000000000909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461182a57826060015181606001516117f09190613df6565b836040015182604001516118049190613df6565b6060850151611813908a613df6565b61181d9190613e39565b6118279190613e7f565b91505b5061187f565b4382606001511461187f57606082015161184a9043613df6565b60408301516118599042613df6565b60608401516118689089613df6565b6118729190613e39565b61187c9190613e7f565b90505b611898828284604001516118939190613e26565b612dd7565b9695505050505050565b600d546001600160a01b031633146118b957600080fd5b6000818152600b60205260409020546118d490600190613df6565b6000918252600b602052604090912055565b60175460ff166001146118f857600080fd5b6017805460ff1916600217905561190f33836124a5565b61191b5761191b613d98565b60008281526001602081815260409283902083518085019094528054600f0b845290910154908201528161195157611951613d98565b60008160000151600f0b136119a85760405162461bcd60e51b815260206004820152601660248201527f4e6f206578697374696e67206c6f636b20666f756e64000000000000000000006044820152606401610d6e565b42816020015111611a205760405162461bcd60e51b8152602060048201526024808201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e205769746860448201527f64726177000000000000000000000000000000000000000000000000000000006064820152608401610d6e565b611a2f83836000846002613258565b50506017805460ff1916600117905550565b336001600160a01b03831603611a5957611a59613d98565b3360008181526015602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60175460ff16600114611ad757600080fd5b6017805460ff19166002179055611aee33836124a5565b611afa57611afa613d98565b600082815260016020818152604080842081518083019092528054600f0b825290920154908201529062093a8080611b328542613e26565b611b3c9190613e7f565b611b469190613e39565b905042826020015111611b9b5760405162461bcd60e51b815260206004820152600c60248201527f4c6f636b206578706972656400000000000000000000000000000000000000006044820152606401610d6e565b60008260000151600f0b13611bf25760405162461bcd60e51b815260206004820152601160248201527f4e6f7468696e67206973206c6f636b65640000000000000000000000000000006044820152606401610d6e565b81602001518111611c455760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610d6e565b611c53630784ce0042613e26565b811115611ca25760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610d6e565b611cb184600083856003613258565b50506017805460ff191660011790555050565b611cd0848484336123af565b823b15611dfd576040517f150b7a020000000000000000000000000000000000000000000000000000000081526000906001600160a01b0385169063150b7a0290611d25903390899088908890600401613e93565b6020604051808303816000875af1158015611d44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d689190613ec5565b90507fffffffff0000000000000000000000000000000000000000000000000000000081167f150b7a020000000000000000000000000000000000000000000000000000000014611dfb5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a207472616e736665722072656a6563746564000000000000006044820152606401610d6e565b505b50505050565b600d546001600160a01b03163314611e1a57600080fd5b6000908152600c60205260409020805460ff19169055565b6000818152601460205260408120544211610caf565b611e86600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b8152602001600081525061250b565b565b6000818152600f60205260409020546060906001600160a01b0316611eef5760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610d6e565b60008281526001602081815260409283902083518085019094528054600f0b845290910154908201526004546001600160a01b031663dd9ec14984611f348142613497565b6020850151855160405160e086901b7fffffffff00000000000000000000000000000000000000000000000000000000168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015611fa4573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526113749190810190613ee2565b6000828152600b602052604090205415801561201557506000828152600c602052604090205460ff16155b6120615760405162461bcd60e51b815260206004820152600860248201527f61747461636865640000000000000000000000000000000000000000000000006044820152606401610d6e565b80820361206d57600080fd5b61207733836124a5565b61208057600080fd5b61208a33826124a5565b61209357600080fd5b6000828152600160208181526040808420815180830183528154600f90810b82529185015481850190815287875285855283872084518086019095528054840b855290950154938301849052805194519095929490910b9211156120fb578260200151612101565b83602001515b604080518082018252600080825260208083018281528b83526001808352858420945185547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff9091161785559051930192909255825180840190935280835290820152909150612186908790869061250b565b61218f86612bb0565b61219d858383866004613258565b505050505050565b60175460009060ff166001146121ba57600080fd5b6017805460ff191660021790556121d2848484612c6f565b90506017805460ff191660011790559392505050565b60006113748383613497565b60008181526005602052604081205443900361221257506000919050565b610caf8242613497565b60175460ff1660011461222e57600080fd5b6017805460ff1916600217905560008281526001602081815260409283902083518085019094528054600f0b845290910154908201528161226e57600080fd5b60008160000151600f0b136122c55760405162461bcd60e51b815260206004820152601660248201527f4e6f206578697374696e67206c6f636b20666f756e64000000000000000000006044820152606401610d6e565b4281602001511161233d5760405162461bcd60e51b8152602060048201526024808201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e205769746860448201527f64726177000000000000000000000000000000000000000000000000000000006064820152608401610d6e565b611a2f83836000846000613258565b600d546001600160a01b0316331461236357600080fd5b6000818152600b60205260409020546118d4906001613e26565b600d546001600160a01b0316331461239457600080fd5b6000908152600c60205260409020805460ff19166001179055565b6000828152600b60205260409020541580156123da57506000828152600c602052604090205460ff16155b6124265760405162461bcd60e51b815260206004820152600860248201527f61747461636865640000000000000000000000000000000000000000000000006044820152606401610d6e565b61243081836124a5565b61243957600080fd5b612443848361357f565b61244d84836135fe565b6124578383613697565b6000828152600560205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b6000818152600f602090815260408083205460108352818420546001600160a01b039182168086526015855283862088841680885295529285205492938085149392909116149060ff1682806124f85750815b806125005750805b979650505050505050565b604080516080810182526000808252602082018190529181018290526060810191909152604080516080810182526000808252602082018190529181018290526060810191909152600654600090819087156126765742876020015111801561257b575060008760000151600f0b135b156125c057865161259190630784ce0090613f50565b600f0b6020808701919091528701516125ab904290613df6565b85602001516125ba9190613fc4565b600f0b85525b4286602001511180156125da575060008660000151600f0b135b1561261f5785516125f090630784ce0090613f50565b600f0b60208086019190915286015161260a904290613df6565b84602001516126199190613fc4565b600f0b84525b6020808801516000908152600a8252604090205490870151600f9190910b93501561267657866020015186602001510361265b57829150612676565b6020808701516000908152600a9091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126f8575060008181526007602090815260409182902082516080810184528154600f81810b8352700100000000000000000000000000000000909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127455760408401516127179042613df6565b60608501516127269043613df6565b61273890670de0b6b3a7640000613e39565b6127429190613e7f565b90505b600062093a806127558186613e7f565b61275f9190613e39565b905060005b60ff8110156128e75761277a62093a8083613e26565b915060004283111561278e574292506127a2565b506000828152600a6020526040902054600f0b5b6127ac8684613df6565b87602001516127bb9190613fc4565b875188906127ca908390613fe4565b600f0b9052506020870180518291906127e4908390614032565b600f90810b90915288516000910b121590506127ff57600087525b60008760200151600f0b121561281757600060208801525b60408088018490528501519295508592670de0b6b3a76400009061283b9085613df6565b6128459086613e39565b61284f9190613e7f565b856060015161285e9190613e26565b606088015261286e600189613e26565b975042830361288357504360608701526128e7565b6000888152600760209081526040918290208951918a01516fffffffffffffffffffffffffffffffff908116700100000000000000000000000000000000029216919091178155908801516001820155606088015160029091015550600101612764565b505060068590558b1561297257886020015188602001516129089190613fe4565b846020018181516129199190614032565b600f0b9052508851885161292d9190613fe4565b8451859061293c908390614032565b600f90810b90915260208601516000910b1215905061295d57600060208501525b60008460000151600f0b121561297257600084525b6000858152600760209081526040918290208651918701516fffffffffffffffffffffffffffffffff90811670010000000000000000000000000000000002921691909117815590850151600182015560608501516002909101558b15612ba257428b602001511115612a605760208901516129ee9088614032565b96508a602001518a6020015103612a11576020880151612a0e9088613fe4565b96505b60208b8101516000908152600a9091526040902080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff89161790555b428a602001511115612adc578a602001518a602001511115612adc576020880151612a8b9087613fe4565b60208b8101516000908152600a9091526040902080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff831617905595505b60008c815260096020526040812054612af6906001613e26565b905080600960008f815260200190815260200160002081905550428960400181815250504389606001818152505088600860008f815260200190815260200160002082633b9aca008110612b4c57612b4c613d69565b825160208401516fffffffffffffffffffffffffffffffff908116700100000000000000000000000000000000029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612bba33826124a5565b612c065760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610d6e565b6000818152600f60205260408120546001600160a01b031690612c299083610acb565b612c3381836135fe565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b60008062093a8080612c818642613e26565b612c8b9190613e7f565b612c959190613e39565b905060008511612ca457600080fd5b428111612d195760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201527f66757475726500000000000000000000000000000000000000000000000000006064820152608401610d6e565b612d27630784ce0042613e26565b811115612d765760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610d6e565b600e60008154612d8590614080565b90915550600e54612d968482613745565b5060008181526001602081815260409283902083518085019094528054600f0b845282015490830152612dce91839189918691613258565b95945050505050565b600080839050600062093a80808360400151612df39190613e7f565b612dfd9190613e39565b905060005b60ff811015612ea857612e1862093a8083613e26565b9150600085831115612e2c57859250612e40565b506000828152600a6020526040902054600f0b5b6040840151612e4f9084613df6565b8460200151612e5e9190613fc4565b84518590612e6d908390613fe4565b600f0b905250858303612e805750612ea8565b8084602001818151612e929190614032565b600f0b9052505060408301829052600101612e02565b5060008260000151600f0b1215612ebe57600082525b50516fffffffffffffffffffffffffffffffff169392505050565b600043821115612eeb57612eeb613d98565b600083815260096020526040812054815b6080811015612f835781831015612f835760006002612f1b8486613e26565b612f26906001613e26565b612f309190613e7f565b6000888152600860205260409020909150869082633b9aca008110612f5757612f57613d69565b600302016002015411612f6c57809350612f7a565b612f77600182613df6565b92505b50600101612efc565b50600085815260086020526040812083633b9aca008110612fa657612fa6613d69565b60408051608081018252600392909202929092018054600f81810b8452700100000000000000000000000000000000909104900b60208301526001810154928201929092526002909101546060820152600654909150600061300887836131da565b600081815260076020908152604080832081516080810183528154600f81810b8352700100000000000000000000000000000000909104900b938101939093526001810154918301919091526002015460608201529192508084841015613101576000600781613079876001613e26565b8152602080820192909252604090810160002081516080810183528154600f81810b8352700100000000000000000000000000000000909104900b938101939093526001810154918301919091526002015460608083018290528601519192506130e39190613df6565b9250836040015181604001516130f99190613df6565b915050613125565b60608301516131109043613df6565b91508260400151426131229190613df6565b90505b60408301518215613162578284606001518c6131419190613df6565b61314b9084613e39565b6131559190613e7f565b61315f9082613e26565b90505b60408701516131719082613df6565b87602001516131809190613fc4565b8751889061318f908390613fe4565b600f90810b90915288516000910b1290506131c857505093516fffffffffffffffffffffffffffffffff169650610caf95505050505050565b60009950505050505050505050610caf565b60008082815b608081101561324e578183101561324e57600060026131ff8486613e26565b61320a906001613e26565b6132149190613e7f565b600081815260076020526040902060020154909150871061323757809350613245565b613242600182613df6565b92505b506001016131e0565b5090949350505050565b60005482906132678682613e26565b6000908155604080518082019091528181526020810191909152825160208085015190830152600f0b81528251879084906132a3908390614032565b600f0b90525085156132b757602083018690525b6000888152600160208181526040909220855181547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff9091161781559185015191015561331788828561250b565b33871580159061333957506004856004811115613336576133366140b8565b14155b156133fc576040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000e8876189a80b2079d8c0a7867e46c50361d972c116906323b872dd906064016020604051808303816000875af11580156133cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133f09190613e09565b6133fc576133fc613d98565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b894260405161344094939291906140e7565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134748a82613e26565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000828152600960205260408120548082036134b7576000915050610caf565b600084815260086020526040812082633b9aca0081106134d9576134d9613d69565b60408051608081018252600392909202929092018054600f81810b8452700100000000000000000000000000000000909104900b602083015260018101549282018390526002015460608201529150613532908561413e565b81602001516135419190613fc4565b81518290613550908390613fe4565b600f90810b90915282516000910b1215905061356b57600081525b51600f0b9150610caf9050565b5092915050565b6000818152600f60205260409020546001600160a01b038381169116146135a8576135a8613d98565b6000818152601060205260409020546001600160a01b0316156135fa57600081815260106020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555b5050565b6000818152600f60205260409020546001600160a01b0383811691161461362757613627613d98565b6000818152600f6020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561366582826138a3565b6001600160a01b038216600090815260116020526040812080546001929061368e908490613df6565b90915550505050565b6000818152600f60205260409020546001600160a01b0316156136bc576136bc613d98565b6000818152600f6020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03871690811790915580845260118084528285208054601286528487208188528652848720889055878752601386529386209390935590845290915280546001929061368e908490613e26565b60006001600160a01b03831661375d5761375d613d98565b6137678383613697565b823b15613862576040517f150b7a02000000000000000000000000000000000000000000000000000000008152336004820152600060248201819052604482018490526080606483015260848201819052906001600160a01b0385169063150b7a029060a4016020604051808303816000875af11580156137ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138109190613ec5565b90507fffffffff0000000000000000000000000000000000000000000000000000000081167f150b7a02000000000000000000000000000000000000000000000000000000001461386057600080fd5b505b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b0382166000908152601160205260408120546138c890600190613df6565b600083815260136020526040902054909150808203613917576001600160a01b038416600090815260126020908152604080832085845282528083208390558583526013909152812055611dfd565b6001600160a01b039390931660009081526012602090815260408083209383529281528282208054868452848420819055835260139091528282209490945592839055908252812055565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461399057600080fd5b50565b6000602082840312156139a557600080fd5b813561137481613962565b60005b838110156139cb5781810151838201526020016139b3565b50506000910152565b600081518084526139ec8160208601602086016139b0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061137460208301846139d4565b600060208284031215613a4357600080fd5b5035919050565b80356001600160a01b0381168114613a6157600080fd5b919050565b60008060408385031215613a7957600080fd5b613a8283613a4a565b946020939093013593505050565b60008060408385031215613aa357600080fd5b50508035926020909101359150565b600080600060608486031215613ac757600080fd5b613ad084613a4a565b9250613ade60208501613a4a565b9150604084013590509250925092565b600060208284031215613b0057600080fd5b61137482613a4a565b6020808252825182820181905260009190848201906040850190845b81811015613b4157835183529284019291840191600101613b25565b50909695505050505050565b801515811461399057600080fd5b60008060408385031215613b6e57600080fd5b613b7783613a4a565b91506020830135613b8781613b4d565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613c0857613c08613b92565b604052919050565b600067ffffffffffffffff821115613c2a57613c2a613b92565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60008060008060808587031215613c6c57600080fd5b613c7585613a4a565b9350613c8360208601613a4a565b925060408501359150606085013567ffffffffffffffff811115613ca657600080fd5b8501601f81018713613cb757600080fd5b8035613cca613cc582613c10565b613bc1565b818152886020838501011115613cdf57600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b600080600060608486031215613d1657600080fd5b8335925060208401359150613d2d60408501613a4a565b90509250925092565b60008060408385031215613d4957600080fd5b613d5283613a4a565b9150613d6060208401613a4a565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610caf57610caf613dc7565b600060208284031215613e1b57600080fd5b815161137481613b4d565b80820180821115610caf57610caf613dc7565b8082028115828204841417610caf57610caf613dc7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613e8e57613e8e613e50565b500490565b60006001600160a01b0380871683528086166020840152508360408301526080606083015261189860808301846139d4565b600060208284031215613ed757600080fd5b815161137481613962565b600060208284031215613ef457600080fd5b815167ffffffffffffffff811115613f0b57600080fd5b8201601f81018413613f1c57600080fd5b8051613f2a613cc582613c10565b818152856020838501011115613f3f57600080fd5b612dce8260208301602086016139b0565b600081600f0b83600f0b80613f6757613f67613e50565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81147fffffffffffffffffffffffffffffffff8000000000000000000000000000000083141615613fbb57613fbb613dc7565b90059392505050565b600082600f0b82600f0b0280600f0b915080821461357857613578613dc7565b600f82810b9082900b037fffffffffffffffffffffffffffffffff8000000000000000000000000000000081126f7fffffffffffffffffffffffffffffff82131715610caf57610caf613dc7565b600f81810b9083900b016f7fffffffffffffffffffffffffffffff81137fffffffffffffffffffffffffffffffff8000000000000000000000000000000082121715610caf57610caf613dc7565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036140b1576140b1613dc7565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b84815260208101849052608081016005841061412c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60408201939093526060015292915050565b818103600083128015838313168383128216171561357857613578613dc756fea2646970667358221220cb363f2ca7ceaee0a60b003e1a14572a594b8b94fc37e6cb989ee571313cc93764736f6c63430008160033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000e8876189a80b2079d8c0a7867e46c50361d972c100000000000000000000000036c530a35e7f2ea46bf1c3d9d0b12ece2a8dcba2
-----Decoded View---------------
Arg [0] : token_addr (address): 0xe8876189A80B2079D8C0a7867e46c50361D972c1
Arg [1] : art_proxy (address): 0x36C530a35e7F2ea46bf1c3d9d0b12ECe2a8DCBa2
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000e8876189a80b2079d8c0a7867e46c50361d972c1
Arg [1] : 00000000000000000000000036c530a35e7f2ea46bf1c3d9d0b12ece2a8dcba2
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.