Source Code
Overview
ETH Balance
0 ETH
Token Holdings
More Info
ContractCreator
TokenTracker
Multichain Info
N/A
Latest 25 from a total of 93 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
Amount
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Increase_unlock_... | 105822692 | 410 days ago | IN | 0 ETH | 0.00000978 | ||||
| Increase_unlock_... | 105822213 | 410 days ago | IN | 0 ETH | 0.00000978 | ||||
| Increase_unlock_... | 105821751 | 410 days ago | IN | 0 ETH | 0.00000978 | ||||
| Increase_unlock_... | 105821647 | 410 days ago | IN | 0 ETH | 0.00000978 | ||||
| Increase_unlock_... | 105821551 | 410 days ago | IN | 0 ETH | 0.00000978 | ||||
| Increase_unlock_... | 105821218 | 410 days ago | IN | 0 ETH | 0.00001319 | ||||
| Create_lock | 105821134 | 410 days ago | IN | 0 ETH | 0.00004738 | ||||
| Approve | 105794478 | 410 days ago | IN | 0 ETH | 0.00000662 | ||||
| Approve | 105794464 | 410 days ago | IN | 0 ETH | 0.00000662 | ||||
| Approve | 105794448 | 410 days ago | IN | 0 ETH | 0.00000833 | ||||
| Approve | 105794432 | 410 days ago | IN | 0 ETH | 0.00000833 | ||||
| Approve | 105792770 | 410 days ago | IN | 0 ETH | 0.00000598 | ||||
| Increase_amount | 105792407 | 410 days ago | IN | 0 ETH | 0.00002555 | ||||
| Increase_unlock_... | 105792151 | 410 days ago | IN | 0 ETH | 0.00002496 | ||||
| Safe Transfer Fr... | 105760382 | 410 days ago | IN | 0 ETH | 0.00001077 | ||||
| Approve | 105553590 | 411 days ago | IN | 0 ETH | 0.00002165 | ||||
| Approve | 105553574 | 411 days ago | IN | 0 ETH | 0.00002165 | ||||
| Merge | 105553333 | 411 days ago | IN | 0 ETH | 0.00004986 | ||||
| Increase_amount | 105553147 | 411 days ago | IN | 0 ETH | 0.00003621 | ||||
| Increase_unlock_... | 105553041 | 411 days ago | IN | 0 ETH | 0.00003609 | ||||
| Create_lock | 105552515 | 411 days ago | IN | 0 ETH | 0.00005017 | ||||
| Approve | 105458654 | 411 days ago | IN | 0 ETH | 0.00000718 | ||||
| Approve | 105406712 | 411 days ago | IN | 0 ETH | 0.00000677 | ||||
| Approve | 105406415 | 411 days ago | IN | 0 ETH | 0.00000677 | ||||
| Approve | 105406400 | 411 days ago | IN | 0 ETH | 0.00000677 |
Loading...
Loading
Contract Name:
VoteEscrow
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;
import {IERC721} from "../interfaces/IERC721.sol";
import {IERC721Metadata} from "../interfaces/IERC721Metadata.sol";
import {Base64} from "../libraries/Base64.sol";
import {IERC20} from "../interfaces/IERC20.sol";
import {IERC721Receiver} from "../interfaces/IERC721Receiver.sol";
import "../interfaces/ISystemStatus.sol";
import "../Owned.sol";
import "../MixinResolver.sol";
/**
@title Voting Escrow
@author SYNTHR
@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?)
*/
contract VoteEscrow is IERC721, IERC721Metadata, Owned, MixinResolver {
enum DepositType {
DEPOSIT_FOR_TYPE,
CREATE_LOCK_TYPE,
INCREASE_LOCK_AMOUNT,
INCREASE_UNLOCK_TIME,
MERGE_TYPE
}
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;
}
// For FE data
struct NFTInfo {
uint tokenId;
uint balanceOf;
uint locked_end;
uint value;
}
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);
// uint internal constant WEEK = 1 weeks;
// uint internal constant WEEK = 1 minutes;
uint public immutable WEEK;
uint internal constant MAXTIME = 4 * 365 * 86400;
int128 internal constant iMAXTIME = 4 * 365 * 86400;
uint internal constant MULTIPLIER = 1 ether;
address public token;
uint public supply;
uint public nftSupply;
mapping(uint => LockedBalance) public locked;
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 public constant name = "veSYNTH NFT";
string public constant symbol = "veSYNTH";
string public constant version = "1.0.0";
uint8 public constant decimals = 18;
/* ========== ADDRESS RESOLVER CONFIGURATION ========== */
bytes32 public constant CONTRACT_NAME = "VoteEscrow";
bytes32 private constant CONTRACT_SYSTEMSTATUS = "SystemStatus";
/// @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 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;
}
modifier systemActive() {
systemStatus().requireSystemActive();
_;
}
/// @notice Contract constructor
/// @param token_addr `SYNTH` token address
constructor(address token_addr, address _resolver) Owned(msg.sender) MixinResolver(_resolver) {
token = token_addr;
voter = msg.sender;
point_history[0].blk = block.number;
point_history[0].ts = block.timestamp;
WEEK = 1 weeks;
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);
}
// Note: use public visibility so that it can be invoked in a subclass
function resolverAddressesRequired()
public
view
virtual
override
returns (bytes32[] memory addresses)
{
addresses = new bytes32[](1);
addresses[0] = CONTRACT_SYSTEMSTATUS;
}
function systemStatus() internal view returns (ISystemStatus) {
return ISystemStatus(requireAndGetAddress(CONTRACT_SYSTEMSTATUS));
}
/// @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;
}
/// @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);
}
function totalNFTSupply() external view returns (uint) {
return nftSupply;
}
/// @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) {
address owner = idToOwner[_tokenId];
require(owner != address(0), "VE NFT: owner query for nonexistent token");
return owner;
}
/// @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 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 systemActive {
_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 systemActive {
_transferFrom(_from, _to, _tokenId, msg.sender);
if (_isContract(_to)) {
// Throws if transfer destination is a contract which does not implement 'onERC721Received'
try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (
bytes4 retval
) {
require(
retval == IERC721Receiver.onERC721Received.selector,
"ERC721: transfer to non ERC721Receiver implementer"
);
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}
}
/// @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 systemActive {
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 systemActive {
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);
nftSupply++;
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;
// Copy all the data of last point
// Changes as suggested in Bug Report - https://github.com/grGred/Anyswap-staking
Point memory initial_last_point = Point({
bias: last_point.bias,
slope: last_point.slope,
ts: last_point.ts,
blk: last_point.blk
});
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);
}
/**
The following functions are used for voting and delegation. Not required as of now
*/
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;
}
/// @notice The merge function enables users to consolidate two locked NFT positions into one.
/// This can simplify management and voting for users with multiple locks.
function merge(uint _from, uint _to) external systemActive {
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 systemActive {
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");
// require(balanceOf(_to) == 0, "Cannot have more than one lock"); // dev: only one lock per address
++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 systemActive 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 systemActive 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 systemActive {
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 systemActive {
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 systemActive {
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));
address owner = ownerOf(_tokenId);
// Burn the NFT
_burn(_tokenId);
assert(IERC20(token).transfer(owner, value));
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));
}
}
/// @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
_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 for FE to get all NFT info for a given user
function getUserAllNFTs(address _user) external view returns (NFTInfo[] memory) {
uint _totalNFTsOfUser = _balance(_user);
NFTInfo[] memory _nfts = new NFTInfo[](_totalNFTsOfUser);
for (uint i; i < _totalNFTsOfUser; i++) {
uint _tokenId = ownerToNFTokenIdList[_user][i];
LockedBalance memory lockedInfo = locked[_tokenId];
_nfts[i] = NFTInfo({
tokenId: _tokenId,
balanceOf: _balanceOfNFT(_tokenId, block.timestamp),
locked_end: lockedInfo.end,
value: uint(int256(lockedInfo.amount))
});
}
return _nfts;
}
function getNFTsDetails(uint[] calldata _tokenIds) external view returns (NFTInfo[] memory) {
NFTInfo[] memory _nfts = new NFTInfo[](_tokenIds.length);
for (uint i; i < _tokenIds.length; i++) {
uint _tokenId = _tokenIds[i];
LockedBalance memory lockedInfo = locked[_tokenId];
_nfts[i] = NFTInfo({
tokenId: _tokenId,
balanceOf: _balanceOfNFT(_tokenId, block.timestamp),
locked_end: lockedInfo.end,
value: uint(int256(lockedInfo.amount))
});
}
return _nfts;
}
function _tokenURI(
uint _tokenId,
uint _balanceOf,
uint _locked_end,
uint _value
) internal pure returns (string memory output) {
output = '<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 350 350"><style>.base { fill: white; font-family: serif; font-size: 14px; }</style><rect width="100%" height="100%" fill="black" /><text x="10" y="20" class="base">';
output = string(
abi.encodePacked(
output,
"token ",
toString(_tokenId),
'</text><text x="10" y="40" class="base">'
)
);
output = string(
abi.encodePacked(
output,
"balanceOf ",
toString(_balanceOf),
'</text><text x="10" y="60" class="base">'
)
);
output = string(
abi.encodePacked(
output,
"locked_end ",
toString(_locked_end),
'</text><text x="10" y="80" class="base">'
)
);
output = string(abi.encodePacked(output, "value ", toString(_value), "</text></svg>"));
string memory json = Base64.encode(
bytes(
string(
abi.encodePacked(
'{"name": "lock #',
toString(_tokenId),
'", "description": "veSYNTH NFT", "image": "data:image/svg+xml;base64,',
Base64.encode(bytes(output)),
'"}'
)
)
)
);
output = string(abi.encodePacked("data:application/json;base64,", json));
}
function toString(uint value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT license
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint temp = value;
uint digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint(value % 10)));
value /= 10;
}
return string(buffer);
}
function _burn(uint _tokenId) internal {
require(_isApprovedOrOwner(msg.sender, _tokenId), "caller is not owner nor approved");
address owner = ownerOf(_tokenId);
// Clear approval
_clearApproval(owner, _tokenId);
// Remove token
_removeTokenFrom(owner, _tokenId);
nftSupply--;
emit Transfer(owner, address(0), _tokenId);
}
// function set_WEEK(uint _WEEK) external onlyOwner {
// WEEK = _WEEK;
// }
function setToken(address _token) external onlyOwner {
token = _token;
}
}// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;
// Inheritance
import "./Owned.sol";
import "./interfaces/IAddressResolver.sol";
// Internal references
import "./interfaces/IIssuer.sol";
import "./MixinResolver.sol";
contract AddressResolver is Owned, IAddressResolver {
mapping(bytes32 => address) public repository;
mapping(bytes32 => address) public availableBridge;
mapping(address => bool) public isBridge;
bytes32[] public bridgeList;
constructor(address _owner) Owned(_owner) {}
/* ========== RESTRICTED FUNCTIONS ========== */
function importAddresses(
bytes32[] calldata names,
address[] calldata destinations
) external onlyOwner {
require(names.length == destinations.length, "Input lengths must match");
for (uint256 i = 0; i < names.length; i++) {
bytes32 name = names[i];
address destination = destinations[i];
repository[name] = destination;
emit AddressImported(name, destination);
}
}
/**
* @dev Adds an available bridge to the AddressResolver contract.
* @param bridgeName The name of the bridge.
* @param bridgeAddress The address of the bridge.
* Only the contract owner can call this function.
*/
function addAvailableBridge(bytes32 bridgeName, address bridgeAddress) external onlyOwner {
_addAvailableBridge(bridgeName, bridgeAddress);
}
/**
* @dev Removes an available bridge from the AddressResolver contract.
* @param bridgeName The name of the bridge to be removed.
* Only the contract owner can call this function.
*/
function removeAvailableBridge(bytes32 bridgeName) external onlyOwner {
_removeAvailableBridge(bridgeName);
}
/* ========= PUBLIC FUNCTIONS ========== */
function rebuildCaches(MixinResolver[] calldata destinations) external {
for (uint256 i = 0; i < destinations.length; i++) {
destinations[i].rebuildCache();
}
}
/* ========== PRIVATE FUNCTIONS ========== */
function _addAvailableBridge(bytes32 bridgeName, address bridgeAddress) private {
if (availableBridge[bridgeName] != address(0)) {
_removeAvailableBridge(bridgeName);
}
availableBridge[bridgeName] = bridgeAddress;
isBridge[bridgeAddress] = true;
bridgeList.push(bridgeName);
emit AddBridge(bridgeName, bridgeAddress);
}
function _removeAvailableBridge(bytes32 bridgeName) private {
require(availableBridge[bridgeName] != address(0), "The bridge no exist.");
uint lastBridgeNumber = bridgeList.length - 1;
for (uint ii = 0; ii <= lastBridgeNumber; ii++) {
if (bridgeList[ii] == bridgeName) {
bridgeList[ii] = bridgeList[lastBridgeNumber];
bridgeList.pop();
break;
}
}
address bridgeToRemove = availableBridge[bridgeName];
delete availableBridge[bridgeName];
delete isBridge[bridgeToRemove];
emit RemoveBridge(bridgeName, bridgeToRemove);
}
/* ========== VIEWS ========== */
function areAddressesImported(
bytes32[] calldata names,
address[] calldata destinations
) external view returns (bool) {
for (uint256 i = 0; i < names.length; i++) {
if (repository[names[i]] != destinations[i]) {
return false;
}
}
return true;
}
function getAddress(bytes32 name) external view returns (address) {
return repository[name];
}
function requireAndGetAddress(
bytes32 name,
string calldata reason
) external view returns (address) {
address _foundAddress = repository[name];
require(_foundAddress != address(0), reason);
return _foundAddress;
}
function getSynth(bytes32 key) external view returns (address) {
IIssuer issuer = IIssuer(repository["Issuer"]);
require(address(issuer) != address(0), "Cannot find Issuer address");
return address(issuer.synths(key));
}
/**
* @dev Returns the address of the specified bridge.
* @param bridgeName The name of the bridge.
* @return The address of the bridge.
*/
function getAvailableBridge(bytes32 bridgeName) external view returns (address) {
return availableBridge[bridgeName];
}
/**
* @dev Returns the list of all bridge names.
* @return The list of bridge names.
*/
function getBridgeList() external view returns (bytes32[] memory) {
return bridgeList;
}
/* ========== EVENTS ========== */
event AddressImported(bytes32 name, address destination);
event AddBridge(bytes32 indexed bridgeName, address bridgeAddress);
event RemoveBridge(bytes32 indexed bridgeName, address bridgeAddress);
}// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;
interface IAddressResolver {
function getAddress(bytes32 name) external view returns (address);
function getSynth(bytes32 key) external view returns (address);
function getAvailableBridge(bytes32 bridgeName) external view returns (address);
function getBridgeList() external view returns (bytes32[] memory);
function requireAndGetAddress(
bytes32 name,
string calldata reason
) external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;
/**
* @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.24;
interface IERC20 {
// ERC20 Optional Views
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
// Views
function totalSupply() external view returns (uint256);
function balanceOf(address owner) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
// Mutative functions
function transfer(address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
// Events
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;
import {IERC165} from "./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.24;
import {IERC721} from "./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.24;
/**
* @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.24;
import "../interfaces/ISynth.sol";
interface IIssuer {
// Views
function allNetworksDebtInfo() external view returns (uint256 debt, uint256 sharesSupply);
function availableCurrencyKeys() external view returns (bytes32[] memory);
function availableSynthCount() external view returns (uint256);
function availableSynths(uint256 index) external view returns (ISynth);
function canBurnSynths(address account) external view returns (bool);
function collateral(address account) external view returns (uint256);
function collateralisationRatio(address issuer) external view returns (uint256);
function collateralisationRatioAndAnyRatesInvalid(
address _issuer
) external view returns (uint256 cratio, bool anyRateIsInvalid);
function debtBalanceOf(address issuer) external view returns (uint256 debtBalance);
function issuanceRatio() external view returns (uint256);
function lastIssueEvent(address account) external view returns (uint256);
function maxIssuableSynths(address issuer) external view returns (uint256 maxIssuable);
function minimumStakeTime() external view returns (uint256);
function remainingIssuableSynths(
address issuer
) external view returns (uint256 maxIssuable, uint256 alreadyIssued, uint256 totalSystemDebt);
function synths(bytes32 currencyKey) external view returns (ISynth);
function getSynths(bytes32[] calldata currencyKeys) external view returns (ISynth[] memory);
function synthsByAddress(address synthAddress) external view returns (bytes32);
function totalIssuedSynths(bytes32 currencyKey) external view returns (uint256);
function checkFreeCollateral(
address _issuer,
bytes32 _collateralKey,
uint16 _chainId
) external view returns (uint256 withdrawableSynthr);
function issueSynths(
address from,
uint256 amount,
uint256 destChainId
) external returns (uint256 synthAmount, uint256 debtShare);
function issueMaxSynths(
address from,
uint256 destChainId
) external returns (uint256 synthAmount, uint256 debtShare);
function burnSynths(
address from,
bytes32 synthKey,
uint256 amount
)
external
returns (uint256 synthAmount, uint256 debtShare, uint256 reclaimed, uint256 refunded);
function burnSynthsToTarget(
address from,
bytes32 synthKey
)
external
returns (uint256 synthAmount, uint256 debtShare, uint256 reclaimed, uint256 refunded);
function burnForRedemption(
address deprecatedSynthProxy,
address account,
uint256 balance
) external;
function burnSynthsWithoutDebt(
bytes32 currencyKey,
address from,
uint amount
) external returns (uint256 burnAmount);
function synthIssueFromSynthrSwap(
address _account,
bytes32 _synthKey,
uint256 _synthAmount
) external;
function liquidateAccount(
address account,
bytes32 collateralKey,
uint16 chainId,
bool isSelfLiquidation
) external returns (uint256 totalRedeemed, uint256 amountToLiquidate, uint256 sharesToRemove);
function destIssue(address _account, bytes32 _synthKey, uint256 _synthAmount) external;
function destBurn(
address _account,
bytes32 _synthKey,
uint256 _synthAmount
) external returns (uint256);
function transferMargin(address account, uint256 marginDelta) external returns (uint256);
function destTransferMargin(
address _account,
uint256 _marginDelta,
bytes32 _marketKey
) external returns (bool);
function setCurrentPeriodId(uint128 periodId) external;
}// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;
interface ISynth {
// Views
function balanceOf(address _account) external view returns (uint256);
function currencyKey() external view returns (bytes32);
function transferableSynths(address account) external view returns (uint256);
// Mutative functions
function transferAndSettle(address to, uint256 value) external payable returns (bool);
function transferFromAndSettle(
address from,
address to,
uint256 value
) external payable returns (bool);
function burn(address account, uint256 amount) external;
function issue(address account, uint256 amount) external;
}// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;
interface ISystemStatus {
struct Status {
bool canSuspend;
bool canResume;
}
struct Suspension {
bool suspended;
// reason is an integer code,
// 0 => no reason, 1 => upgrading, 2+ => defined by system usage
uint248 reason;
}
// Views
function accessControl(
bytes32 section,
address account
) external view returns (bool canSuspend, bool canResume);
function requireSystemActive() external view;
function systemSuspended() external view returns (bool);
function requireIssuanceActive() external view;
function requireExchangeActive() external view;
function requireFuturesActive() external view;
function requireFuturesMarketActive(bytes32 marketKey) external view;
function requireExchangeBetweenSynthsAllowed(
bytes32 sourceCurrencyKey,
bytes32 destinationCurrencyKey
) external view;
function requireSynthActive(bytes32 currencyKey) external view;
function synthSuspended(bytes32 currencyKey) external view returns (bool);
function requireSynthsActive(
bytes32 sourceCurrencyKey,
bytes32 destinationCurrencyKey
) external view;
function systemSuspension() external view returns (bool suspended, uint248 reason);
function issuanceSuspension() external view returns (bool suspended, uint248 reason);
function exchangeSuspension() external view returns (bool suspended, uint248 reason);
function futuresSuspension() external view returns (bool suspended, uint248 reason);
function synthExchangeSuspension(
bytes32 currencyKey
) external view returns (bool suspended, uint248 reason);
function synthSuspension(
bytes32 currencyKey
) external view returns (bool suspended, uint248 reason);
function futuresMarketSuspension(
bytes32 marketKey
) external view returns (bool suspended, uint248 reason);
function getSynthExchangeSuspensions(
bytes32[] calldata synths
) external view returns (bool[] memory exchangeSuspensions, uint256[] memory reasons);
function getSynthSuspensions(
bytes32[] calldata synths
) external view returns (bool[] memory suspensions, uint256[] memory reasons);
function getFuturesMarketSuspensions(
bytes32[] calldata marketKeys
) external view returns (bool[] memory suspensions, uint256[] memory reasons);
// Restricted functions
function suspendIssuance(uint256 reason) external;
function suspendSynth(bytes32 currencyKey, uint256 reason) external;
function suspendFuturesMarket(bytes32 marketKey, uint256 reason) external;
function updateAccessControl(
bytes32 section,
address account,
bool canSuspend,
bool canResume
) external;
}// SPDX-License-Identifier: MIT pragma solidity =0.8.24; /// [MIT License] /// @title Base64 /// @notice Provides a function for encoding some bytes in base64 /// @author Brecht Devos <[email protected]> library Base64 { bytes internal constant TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /// @notice Encodes some bytes to the base64 representation function encode(bytes memory data) internal pure returns (string memory) { uint len = data.length; if (len == 0) return ""; // multiply by 4/3 rounded up uint encodedLen = 4 * ((len + 2) / 3); // Add some extra buffer at the end bytes memory result = new bytes(encodedLen + 32); bytes memory table = TABLE; assembly { let tablePtr := add(table, 1) let resultPtr := add(result, 32) for { let i := 0 } lt(i, len) {} { i := add(i, 3) let input := and(mload(add(data, i)), 0xffffff) let out := mload(add(tablePtr, and(shr(18, input), 0x3F))) out := shl(8, out) out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF)) out := shl(8, out) out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF)) out := shl(8, out) out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF)) out := shl(224, out) mstore(resultPtr, out) resultPtr := add(resultPtr, 4) } switch mod(len, 3) case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) } case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) } mstore(result, encodedLen) } return string(result); } }
// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;
// Internal references
import "./AddressResolver.sol";
contract MixinResolver {
AddressResolver public resolver;
mapping(bytes32 => address) private addressCache;
constructor(address _resolver) {
resolver = AddressResolver(_resolver);
}
/* ========== INTERNAL FUNCTIONS ========== */
function combineArrays(
bytes32[] memory first,
bytes32[] memory second
) internal pure returns (bytes32[] memory combination) {
combination = new bytes32[](first.length + second.length);
for (uint256 i = 0; i < first.length; i++) {
combination[i] = first[i];
}
for (uint256 j = 0; j < second.length; j++) {
combination[first.length + j] = second[j];
}
}
/* ========== PUBLIC FUNCTIONS ========== */
// Note: this function is public not external in order for it to be overridden and invoked via super in subclasses
function resolverAddressesRequired() public view virtual returns (bytes32[] memory addresses) {}
function rebuildCache() public {
bytes32[] memory requiredAddresses = resolverAddressesRequired();
// The resolver must call this function whenver it updates its state
for (uint256 i = 0; i < requiredAddresses.length; i++) {
bytes32 name = requiredAddresses[i];
// Note: can only be invoked once the resolver has all the targets needed added
address destination = resolver.requireAndGetAddress(
name,
string(abi.encodePacked("Resolver missing target: ", name))
);
addressCache[name] = destination;
emit CacheUpdated(name, destination);
}
}
/* ========== VIEWS ========== */
function isResolverCached() external view returns (bool) {
bytes32[] memory requiredAddresses = resolverAddressesRequired();
for (uint256 i = 0; i < requiredAddresses.length; i++) {
bytes32 name = requiredAddresses[i];
// false if our cache is invalid or if the resolver doesn't have the required address
if (
resolver.getAddress(name) != addressCache[name] || addressCache[name] == address(0)
) {
return false;
}
}
return true;
}
/* ========== INTERNAL FUNCTIONS ========== */
function requireAndGetAddress(bytes32 name) internal view returns (address) {
address _foundAddress = addressCache[name];
require(_foundAddress != address(0), string(abi.encodePacked("Missing address: ", name)));
return _foundAddress;
}
/* ========== EVENTS ========== */
event CacheUpdated(bytes32 name, address destination);
}// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;
contract Owned {
address public owner;
address public nominatedOwner;
constructor(address _owner) {
require(_owner != address(0), "Owner address cannot be 0");
owner = _owner;
emit OwnerChanged(address(0), _owner);
}
function nominateNewOwner(address _owner) external onlyOwner {
nominatedOwner = _owner;
emit OwnerNominated(_owner);
}
function acceptOwnership() external {
require(
msg.sender == nominatedOwner,
"You must be nominated before you can accept ownership"
);
emit OwnerChanged(owner, nominatedOwner);
owner = nominatedOwner;
nominatedOwner = address(0);
}
modifier onlyOwner() {
_onlyOwner();
_;
}
function _onlyOwner() private view {
require(msg.sender == owner, "Only the contract owner may perform this action");
}
event OwnerNominated(address newOwner);
event OwnerChanged(address oldOwner, address newOwner);
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract ABI
API[{"inputs":[{"internalType":"address","name":"token_addr","type":"address"},{"internalType":"address","name":"_resolver","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":false,"internalType":"bytes32","name":"name","type":"bytes32"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"CacheUpdated","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 VoteEscrow.DepositType","name":"deposit_type","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"prevSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"supply","type":"uint256"}],"name":"Supply","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"CONTRACT_NAME","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WEEK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"abstain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_approved","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"attach","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"attachments","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_block","type":"uint256"}],"name":"balanceOfAtNFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"balanceOfNFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_t","type":"uint256"}],"name":"balanceOfNFTAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"block_number","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"checkpoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"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":"_tokenIds","type":"uint256[]"}],"name":"getNFTsDetails","outputs":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"balanceOf","type":"uint256"},{"internalType":"uint256","name":"locked_end","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct VoteEscrow.NFTInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getUserAllNFTs","outputs":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"balanceOf","type":"uint256"},{"internalType":"uint256","name":"locked_end","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct VoteEscrow.NFTInfo[]","name":"","type":"tuple[]"}],"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":[],"name":"isResolverCached","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"locked","outputs":[{"internalType":"int128","name":"amount","type":"int128"},{"internalType":"uint256","name":"end","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"locked__end","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_from","type":"uint256"},{"internalType":"uint256","name":"_to","type":"uint256"}],"name":"merge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nftSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"ownership_change","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"point_history","outputs":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"uint256","name":"ts","type":"uint256"},{"internalType":"uint256","name":"blk","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebuildCache","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resolver","outputs":[{"internalType":"contract AddressResolver","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"resolverAddressesRequired","outputs":[{"internalType":"bytes32[]","name":"addresses","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"setToken","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":[],"name":"totalNFTSupply","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":"","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
60a06040526019805460ff191660011790553480156200001e57600080fd5b5060405162004dbc38038062004dbc83398101604081905262000041916200026e565b803380620000955760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015260640160405180910390fd5b600080546001600160a01b0319166001600160a01b03831690811782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a150600280546001600160a01b039283166001600160a01b03199182161790915560048054928516928216929092179091556010805490911633179055437f13da86008ba1c6922daee3e07db95305ef49ebced9f5467a0b8613fcc6b343e555427f13da86008ba1c6922daee3e07db95305ef49ebced9f5467a0b8613fcc6b343e45562093a8060805260186020527f7870b45acb18b072b8f477632bb6360a123dfe426f9bfb9ebf368ab0b6a8505f805460ff1990811660019081179092557fbf8097e11fbe55e62283cbb89d064d64d4732959e6e218da57a9f4f7b7582e918054821683179055635b5e139f60e01b60009081527f6a897876102a9bb6da5bcde1022507015d90bf773d3e5daeac34d8cb99f63880805490921690921790556011546040519091309160008051602062004d9c833981519152908290a4601154604051600090309060008051602062004d9c833981519152908390a45050620002a6565b80516001600160a01b03811681146200026957600080fd5b919050565b600080604083850312156200028257600080fd5b6200028d8362000251565b91506200029d6020840162000251565b90509250929050565b608051614aa9620002f360003960008181610a2201528181611c8901528181612a2e01528181612a7401528181612ff30152818161316c0152818161318d01526131d80152614aa96000f3fe608060405234801561001057600080fd5b50600436106103f15760003560e01c80637119748411610215578063c2c4c5c111610125578063e7e242d4116100b8578063f4359ce511610087578063f4359ce514610a1d578063f8a0576314610a44578063fbd3a29d14610a67578063fc0c546a14610a7a578063fd4a77f114610a8d57600080fd5b8063e7e242d4146109a8578063e985e9c5146109bb578063ee99fe28146109f7578063f266b58f14610a0a57600080fd5b8063d4e54c3b116100f4578063d4e54c3b1461095a578063e0514aba1461096d578063e2c7928114610980578063e441135c1461098857600080fd5b8063c2c4c5c1146108ee578063c87b56dd146108f6578063d1c2babb14610909578063d1febfb91461091c57600080fd5b806395d89b41116101a8578063a22cb46511610177578063a22cb4651461085a578063a4d855df1461086d578063b45a3c0e14610880578063b88d4fde146108c8578063c1f0fb9f146108db57600080fd5b806395d89b41146107fb578063981b24d014610821578063986b7d8a14610834578063a183af521461084757600080fd5b80638c2c9baf116101e45780638c2c9baf146107a95780638da5cb5b146107bc5780638fbb38ff146107cf578063900cf0cf146107f257600080fd5b80637119748414610761578063741853601461078457806379ba50971461078c578063899ffef41461079457600080fd5b80632e1a7d4d116103105780634bc2a657116102a35780636352211e116102725780636352211e146106f557806365fc3873146107085780636f5488371461071b57806370a082311461073b5780637116c60c1461074e57600080fd5b80634bc2a6571461069757806353a47bb7146106aa57806354fd4d50146106bd578063614d08f8146106e157600080fd5b806342842e0e116102df57806342842e0e14610638578063430c20811461064b578063461f711c1461065e57806346c96aac1461068457600080fd5b80632e1a7d4d146105b55780632f745c59146105c8578063313ce567146105fe57806339fda9d21461061857600080fd5b80631376f3da116103885780631c984bc3116103575780631c984bc31461058157806323b872dd1461059457806325a58b56146105a75780632af64bd3146105ad57600080fd5b80631376f3da14610518578063144fa6d7146105535780631627540c1461056657806318160ddd1461057957600080fd5b806306fdde03116103c457806306fdde0314610483578063081812fc146104ba578063095ea7b3146104e35780630d6a2033146104f857600080fd5b806301790e01146103f657806301ffc9a714610412578063047fc9aa1461044f57806304f3bcec14610458575b600080fd5b6103ff60065481565b6040519081526020015b60405180910390f35b61043f610420366004613ed2565b6001600160e01b03191660009081526018602052604090205460ff1690565b6040519015158152602001610409565b6103ff60055481565b60025461046b906001600160a01b031681565b6040516001600160a01b039091168152602001610409565b6104ad6040518060400160405280600b81526020016a1d9954d65395120813919560aa1b81525081565b6040516104099190613f3f565b61046b6104c8366004613f52565b6000908152601360205260409020546001600160a01b031690565b6104f66104f1366004613f80565b610aa0565b005b6103ff610506366004613f52565b600e6020526000908152604090205481565b61052b610526366004613fac565b610be1565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610409565b6104f6610561366004613fce565b610c28565b6104f6610574366004613fce565b610c52565b6103ff610cae565b6103ff61058f366004613fac565b610cbe565b6104f66105a2366004613feb565b610cf1565b436103ff565b61043f610d5a565b6104f66105c3366004613f52565b610e61565b6103ff6105d6366004613f80565b6001600160a01b03919091166000908152601560209081526040808320938352929052205490565b610606601281565b60405160ff9091168152602001610409565b61062b610626366004613fce565b611165565b604051610409919061402c565b6104f6610646366004613feb565b6112b8565b61043f610659366004613f80565b61132b565b61067161066c366004613f52565b61133e565b604051600f9190910b8152602001610409565b60105461046b906001600160a01b031681565b6104f66106a5366004613fce565b611381565b60015461046b906001600160a01b031681565b6104ad604051806040016040528060058152602001640312e302e360dc1b81525081565b6103ff69566f7465457363726f7760b01b81565b61046b610703366004613f52565b6113ba565b6103ff610716366004613fac565b611431565b6103ff610729366004613f52565b60086020526000908152604090205481565b6103ff610749366004613fce565b6114cb565b6103ff61075c366004613f52565b6114e9565b61067161076f366004613f52565b600d60205260009081526040902054600f0b81565b6104f6611549565b6104f66116c3565b61079c6117ad565b6040516104099190614090565b6103ff6107b7366004613fac565b611801565b60005461046b906001600160a01b031681565b61043f6107dd366004613f52565b600f6020526000908152604090205460ff1681565b6103ff60095481565b6104ad604051806040016040528060078152602001660eccaa6b29ca8960cb1b81525081565b6103ff61082f366004613f52565b61180d565b6104f6610842366004613f52565b6119af565b6104f6610855366004613fac565b6119f3565b6104f66108683660046140e2565b611b4a565b6104f661087b366004613fac565b611bce565b6108ae61088e366004613f52565b60076020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610409565b6104f66108d6366004614131565b611e28565b6104f66108e9366004613f52565b611f95565b6104f6611fc4565b6104ad610904366004613f52565b612004565b6104f6610917366004613fac565b6120b1565b61052b61092a366004613f52565b600a60205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6103ff610968366004614211565b612277565b6103ff61097b366004613fac565b612312565b6006546103ff565b6103ff610996366004613f52565b600c6020526000908152604090205481565b6103ff6109b6366004613f52565b61231e565b61043f6109c936600461424a565b6001600160a01b03918216600090815260176020908152604080832093909416825291909152205460ff1690565b6104f6610a05366004613fac565b612346565b61062b610a18366004614278565b612473565b6103ff7f000000000000000000000000000000000000000000000000000000000000000081565b6103ff610a52366004613f52565b60009081526007602052604090206001015490565b6104f6610a75366004613f52565b6125a0565b60045461046b906001600160a01b031681565b6104f6610a9b366004613f52565b6125d1565b610aa8612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b158015610ae057600080fd5b505afa158015610af4573d6000803e3d6000fd5b5050506000828152601260205260409020546001600160a01b0316905080610b1b57600080fd5b806001600160a01b0316836001600160a01b031603610b3957600080fd5b6000828152601260209081526040808320546001600160a01b0385811685526017845282852033808752945291909320549216149060ff168180610b7a5750805b610b8357600080fd5b60008481526013602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600b60205281600052604060002081633b9aca008110610c0057600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b610c3061261d565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b610c5a61261d565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b6000610cb9426114e9565b905090565b6000828152600b6020526040812082633b9aca008110610ce057610ce06142ed565b600302016001015490505b92915050565b610cf9612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b158015610d3157600080fd5b505afa158015610d45573d6000803e3d6000fd5b50505050610d558383833361268f565b505050565b600080610d656117ad565b905060005b8151811015610e58576000828281518110610d8757610d876142ed565b602090810291909101810151600081815260039092526040918290205460025492516321f8a72160e01b8152600481018390529193506001600160a01b039081169216906321f8a72190602401602060405180830381865afa158015610df1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e159190614303565b6001600160a01b0316141580610e4057506000818152600360205260409020546001600160a01b0316155b15610e4f576000935050505090565b50600101610d6a565b50600191505090565b60195460ff16600114610e7357600080fd5b6019805460ff19166002179055610e88612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b158015610ec057600080fd5b505afa158015610ed4573d6000803e3d6000fd5b50505050610ee23382612755565b610eee57610eee614320565b6000818152600e6020526040902054158015610f1957506000818152600f602052604090205460ff16155b610f3e5760405162461bcd60e51b8152600401610f3590614336565b60405180910390fd5b60008181526007602090815260409182902082518084019093528054600f0b835260010154908201819052421015610fb15760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f35565b8051604080518082018252600080825260208083018281528783526007909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155600554600f9190910b9061100c828261436e565b600555604080518082019091526000808252602082015261103090859085906127bb565b600061103b856113ba565b905061104685612e4b565b6004805460405163a9059cbb60e01b81526001600160a01b03848116938201939093526024810186905291169063a9059cbb906044016020604051808303816000875af115801561109b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110bf9190614381565b6110cb576110cb614320565b60408051868152602081018590524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c82611139858261436e565b6040805192835260208301919091520160405180910390a150506019805460ff19166001179055505050565b60606000611188836001600160a01b031660009081526014602052604090205490565b905060008167ffffffffffffffff8111156111a5576111a561411b565b60405190808252806020026020018201604052801561120157816020015b6111ee6040518060800160405280600081526020016000815260200160008152602001600081525090565b8152602001906001900390816111c35790505b50905060005b828110156112b0576001600160a01b03851660009081526015602090815260408083208484528252808320548084526007835292819020815180830183528154600f0b81526001909101548184015281516080810190925283825291810161126f8442612f13565b8152602001826020015181526020018260000151600f0b81525084848151811061129b5761129b6142ed565b60209081029190910101525050600101611207565b509392505050565b6112c0612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b1580156112f857600080fd5b505afa15801561130c573d6000803e3d6000fd5b50505050610d5583838360405180602001604052806000815250611e28565b60006113378383612755565b9392505050565b6000818152600c6020908152604080832054600b909252822081633b9aca00811061136b5761136b6142ed565b6003020154600160801b9004600f0b9392505050565b6010546001600160a01b0316331461139857600080fd5b601080546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152601260205260408120546001600160a01b031680610ceb5760405162461bcd60e51b815260206004820152602960248201527f5645204e46543a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610f35565b60195460009060ff1660011461144657600080fd5b6019805460ff1916600217905561145b612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b15801561149357600080fd5b505afa1580156114a7573d6000803e3d6000fd5b505050506114b6838333612fee565b90506019805460ff1916600117905592915050565b6001600160a01b038116600090815260146020526040812054610ceb565b6009546000818152600a6020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906115418185613162565b949350505050565b60006115536117ad565b905060005b81518110156116bf576000828281518110611575576115756142ed565b602002602001015190506000600260009054906101000a90046001600160a01b03166001600160a01b031663dacb2d0183846040516020016115e391907f5265736f6c766572206d697373696e67207461726765743a20000000000000008152601981019190915260390190565b6040516020818303038152906040526040518363ffffffff1660e01b815260040161160f92919061439e565b602060405180830381865afa15801561162c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116509190614303565b60008381526003602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251868152918201529192507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68910160405180910390a15050600101611558565b5050565b6001546001600160a01b0316331461173b5760405162461bcd60e51b815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527402063616e20616363657074206f776e65727368697605c1b6064820152608401610f35565b600054600154604080516001600160a01b0393841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b604080516001808252818301909252606091602080830190803683370190505090506b53797374656d53746174757360a01b816000815181106117f2576117f26142ed565b60200260200101818152505090565b600061133783836132b5565b60004382111561181f5761181f614320565b600954600061182e8483613586565b6000818152600a6020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529192508383101561193d576000600a816118918660016143b7565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461193757826060015181606001516118fd919061436e565b83604001518260400151611911919061436e565b6060850151611920908a61436e565b61192a91906143ca565b61193491906143f7565b91505b5061198c565b4382606001511461198c576060820151611957904361436e565b6040830151611966904261436e565b6060840151611975908961436e565b61197f91906143ca565b61198991906143f7565b90505b6119a5828284604001516119a091906143b7565b613162565b9695505050505050565b6010546001600160a01b031633146119c657600080fd5b6000818152600e60205260409020546119e19060019061436e565b6000918252600e602052604090912055565b60195460ff16600114611a0557600080fd5b6019805460ff19166002179055611a1a612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b158015611a5257600080fd5b505afa158015611a66573d6000803e3d6000fd5b50505050611a743383612755565b611a8057611a80614320565b60008281526007602090815260409182902082518084019093528054600f0b8352600101549082015281611ab657611ab6614320565b60008160000151600f0b13611b065760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f35565b42816020015111611b295760405162461bcd60e51b8152600401610f359061440b565b611b3883836000846002613604565b50506019805460ff1916600117905550565b336001600160a01b03831603611b6257611b62614320565b3360008181526017602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60195460ff16600114611be057600080fd5b6019805460ff19166002179055611bf5612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b158015611c2d57600080fd5b505afa158015611c41573d6000803e3d6000fd5b50505050611c4f3383612755565b611c5b57611c5b614320565b600082815260076020908152604080832081518083019092528054600f0b82526001015491810191909152907f000000000000000000000000000000000000000000000000000000000000000080611cb385426143b7565b611cbd91906143f7565b611cc791906143ca565b905042826020015111611d0b5760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f35565b60008260000151600f0b13611d565760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f35565b81602001518111611da95760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f35565b611db7630784ce00426143b7565b811115611e065760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f35565b611e1584600083856003613604565b50506019805460ff191660011790555050565b611e30612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b158015611e6857600080fd5b505afa158015611e7c573d6000803e3d6000fd5b50505050611e8c8484843361268f565b823b15611f8f57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611ec590339088908790879060040161444f565b6020604051808303816000875af1925050508015611f00575060408051601f3d908101601f19168201909252611efd91810190614482565b60015b611f5d573d808015611f2e576040519150601f19603f3d011682016040523d82523d6000602084013e611f33565b606091505b508051600003611f555760405162461bcd60e51b8152600401610f359061449f565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611f8d5760405162461bcd60e51b8152600401610f359061449f565b505b50505050565b6010546001600160a01b03163314611fac57600080fd5b6000908152600f60205260409020805460ff19169055565b612002600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506127bb565b565b6000818152601260205260409020546060906001600160a01b031661206b5760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f35565b60008281526007602090815260409182902082518084019093528054600f0b83526001015490820152611337836120a28142612f13565b60208401518451600f0b6137ef565b6120b9612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b1580156120f157600080fd5b505afa158015612105573d6000803e3d6000fd5b5050506000838152600e6020526040902054159050801561213557506000828152600f602052604090205460ff16155b6121515760405162461bcd60e51b8152600401610f3590614336565b80820361215d57600080fd5b6121673383612755565b61217057600080fd5b61217a3382612755565b61218357600080fd5b6000828152600760208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b9211156121ed5782602001516121f3565b83602001515b604080518082018252600080825260208083018281528b835260078252848320935184546001600160801b0319166001600160801b039091161784555160019093019290925582518084019093528083529082015290915061225890879086906127bb565b61226186612e4b565b61226f858383866004613604565b505050505050565b60195460009060ff1660011461228c57600080fd5b6019805460ff191660021790556122a1612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b1580156122d957600080fd5b505afa1580156122ed573d6000803e3d6000fd5b505050506122fc848484612fee565b90506019805460ff191660011790559392505050565b60006113378383612f13565b60008181526008602052604081205443900361233c57506000919050565b610ceb8242612f13565b60195460ff1660011461235857600080fd5b6019805460ff1916600217905561236d612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b1580156123a557600080fd5b505afa1580156123b9573d6000803e3d6000fd5b50505060008381526007602090815260409182902082518084019093528054600f0b835260010154908201529050816123f157600080fd5b60008160000151600f0b136124415760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f35565b428160200151116124645760405162461bcd60e51b8152600401610f359061440b565b611b3883836000846000613604565b606060008267ffffffffffffffff8111156124905761249061411b565b6040519080825280602002602001820160405280156124ec57816020015b6124d96040518060800160405280600081526020016000815260200160008152602001600081525090565b8152602001906001900390816124ae5790505b50905060005b838110156112b057600085858381811061250e5761250e6142ed565b60209081029290920135600081815260078452604090819020815180830183528154600f0b8152600190910154818601528151608081019092528282529194509092909150810161255f8442612f13565b8152602001826020015181526020018260000151600f0b81525084848151811061258b5761258b6142ed565b602090810291909101015250506001016124f2565b6010546001600160a01b031633146125b757600080fd5b6000818152600e60205260409020546119e19060016143b7565b6010546001600160a01b031633146125e857600080fd5b6000908152600f60205260409020805460ff19166001179055565b6000610cb96b53797374656d53746174757360a01b613926565b6000546001600160a01b031633146120025760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201526e37b936903a3434b99030b1ba34b7b760891b6064820152608401610f35565b6000828152600e60205260409020541580156126ba57506000828152600f602052604090205460ff16155b6126d65760405162461bcd60e51b8152600401610f3590614336565b6126e08183612755565b6126e957600080fd5b6126f3848361399b565b6126fd8483613a00565b6127078383613a81565b6000828152600860205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526012602090815260408083205460138352818420546001600160a01b039182168086526017855283862088841680885295529285205492938085149392909116149060ff1682806127a85750815b806127b05750805b979650505050505050565b604080516080810182526000808252602082018190529181018290526060810191909152604080516080810182526000808252602082018190529181018290526060810191909152600954600090819087156129265742876020015111801561282b575060008760000151600f0b135b1561287057865161284190630784ce00906144f1565b600f0b60208087019190915287015161285b90429061436e565b856020015161286a919061452f565b600f0b85525b42866020015111801561288a575060008660000151600f0b135b156128cf5785516128a090630784ce00906144f1565b600f0b6020808601919091528601516128ba90429061436e565b84602001516128c9919061452f565b600f0b84525b6020808801516000908152600d8252604090205490870151600f9190910b93501561292657866020015186602001510361290b57829150612926565b6020808701516000908152600d9091526040902054600f0b91505b60408051608081018252600080825260208201524291810191909152436060820152811561299b57506000818152600a602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b600081604001519050600060405180608001604052808460000151600f0b81526020018460200151600f0b8152602001846040015181526020018460600151815250905060008360400151421115612a2a5760408401516129fc904261436e565b6060850151612a0b904361436e565b612a1d90670de0b6b3a76400006143ca565b612a2791906143f7565b90505b60007f0000000000000000000000000000000000000000000000000000000000000000612a5781866143f7565b612a6191906143ca565b905060005b60ff811015612bf057612a997f0000000000000000000000000000000000000000000000000000000000000000836143b7565b9150600042831115612aad57429250612ac1565b506000828152600d6020526040902054600f0b5b612acb868461436e565b8760200151612ada919061452f565b87518890612ae990839061454f565b600f0b905250602087018051829190612b0390839061457c565b600f90810b90915288516000910b12159050612b1e57600087525b60008760200151600f0b1215612b3657600060208801525b60408088018490528501519295508592670de0b6b3a764000090612b5a908561436e565b612b6490866143ca565b612b6e91906143f7565b8560600151612b7d91906143b7565b6060880152612b8d6001896143b7565b9750428303612ba25750436060870152612bf0565b6000888152600a60209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550600101612a66565b505060098590558b15612c7b5788602001518860200151612c11919061454f565b84602001818151612c22919061457c565b600f0b90525088518851612c36919061454f565b84518590612c4590839061457c565b600f90810b90915260208601516000910b12159050612c6657600060208501525b60008460000151600f0b1215612c7b57600084525b6000858152600a60209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612e3d57428b602001511115612d32576020890151612ce1908861457c565b96508a602001518a6020015103612d04576020880151612d01908861454f565b96505b60208b8101516000908152600d9091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612d8d578a602001518a602001511115612d8d576020880151612d5d908761454f565b60208b8101516000908152600d9091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600c6020526040812054612da79060016143b7565b905080600c60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600b60008f815260200190815260200160002082633b9aca008110612dfd57612dfd6142ed565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612e553382612755565b612ea15760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f35565b6000612eac826113ba565b9050612eb8818361399b565b612ec28183613a00565b60068054906000612ed2836145a9565b909155505060405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600c6020526040812054808203612f33576000915050610ceb565b6000848152600b6020526040812082633b9aca008110612f5557612f556142ed565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612fa190856145c0565b8160200151612fb0919061452f565b81518290612fbf90839061454f565b600f90810b90915282516000910b12159050612fda57600081525b51600f0b9150610ceb9050565b5092915050565b6000807f00000000000000000000000000000000000000000000000000000000000000008061301d86426143b7565b61302791906143f7565b61303191906143ca565b90506000851161304057600080fd5b42811161309e5760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f35565b6130ac630784ce00426143b7565b8111156130fb5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f35565b60116000815461310a906145e0565b9091555060115461311b8482613b17565b5060008181526007602090815260409182902082518084019093528054600f0b83526001908101549183019190915261315991839189918691613604565b95945050505050565b60008083905060007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083604001516131bb91906143f7565b6131c591906143ca565b905060005b60ff81101561328d576131fd7f0000000000000000000000000000000000000000000000000000000000000000836143b7565b915060008583111561321157859250613225565b506000828152600d6020526040902054600f0b5b6040840151613234908461436e565b8460200151613243919061452f565b8451859061325290839061454f565b600f0b905250858303613265575061328d565b8084602001818151613277919061457c565b600f0b90525050604083018290526001016131ca565b5060008260000151600f0b12156132a357600082525b50516001600160801b03169392505050565b6000438211156132c7576132c7614320565b6000838152600c6020526040812054815b608081101561335f578183101561335f57600060026132f784866143b7565b6133029060016143b7565b61330c91906143f7565b6000888152600b60205260409020909150869082633b9aca008110613333576133336142ed565b60030201600201541161334857809350613356565b61335360018261436e565b92505b506001016132d8565b506000858152600b6020526040812083633b9aca008110613382576133826142ed565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b6020830152600181015492820192909252600290910154606082015260095490915060006133d78783613586565b6000818152600a6020908152604080832081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606082015291925080848410156134b6576000600a8161343b8760016143b7565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060808301829052860151919250613498919061436e565b9250836040015181604001516134ae919061436e565b9150506134da565b60608301516134c5904361436e565b91508260400151426134d7919061436e565b90505b60408301518215613517578284606001518c6134f6919061436e565b61350090846143ca565b61350a91906143f7565b61351490826143b7565b90505b6040870151613526908261436e565b8760200151613535919061452f565b8751889061354490839061454f565b600f90810b90915288516000910b12905061357457505093516001600160801b03169650610ceb95505050505050565b60009950505050505050505050610ceb565b60008082815b60808110156135fa57818310156135fa57600060026135ab84866143b7565b6135b69060016143b7565b6135c091906143f7565b6000818152600a602052604090206002015490915087106135e3578093506135f1565b6135ee60018261436e565b92505b5060010161358c565b5090949350505050565b600554829061361386826143b7565b6005556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061364c90839061457c565b600f0b905250851561366057602083018690525b6000888152600760209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556136a28882856127bb565b3387158015906136c4575060048560048111156136c1576136c16145f9565b14155b1561375457600480546040516323b872dd60e01b81526001600160a01b0384811693820193909352306024820152604481018b90529116906323b872dd906064016020604051808303816000875af1158015613724573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137489190614381565b61375457613754614320565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b8942604051613798949392919061460f565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836137cc8a826143b7565b6040805192835260208301919091520160405180910390a1505050505050505050565b606060405180610120016040528060fd815260200161493760fd913990508061381786613b8f565b60405160200161382892919061464d565b60405160208183030381529060405290508061384385613b8f565b6040516020016138549291906146c9565b60405160208183030381529060405290508061386f84613b8f565b604051602001613880929190614749565b60405160208183030381529060405290508061389b83613b8f565b6040516020016138ac9291906147ca565b604051602081830303815290604052905060006138f96138cb87613b8f565b6138d484613c90565b6040516020016138e5929190614825565b604051602081830303815290604052613c90565b90508060405160200161390c91906148dd565b604051602081830303815290604052915050949350505050565b600081815260036020908152604080832054905170026b4b9b9b4b7339030b2323932b9b99d1607d1b92810192909252603182018490526001600160a01b0316908115159060510160405160208183030381529060405290612fe75760405162461bcd60e51b8152600401610f359190613f3f565b6000818152601260205260409020546001600160a01b038381169116146139c4576139c4614320565b6000818152601360205260409020546001600160a01b0316156116bf57600090815260136020526040902080546001600160a01b031916905550565b6000818152601260205260409020546001600160a01b03838116911614613a2957613a29614320565b600081815260126020526040902080546001600160a01b0319169055613a4f8282613dfa565b6001600160a01b0382166000908152601460205260408120805460019290613a7890849061436e565b90915550505050565b6000818152601260205260409020546001600160a01b031615613aa657613aa6614320565b600081815260126020908152604080832080546001600160a01b0319166001600160a01b038716908117909155808452601480845282852080546015865284872081885286528487208890558787526016865293862093909355908452909152805460019290613a789084906143b7565b60006001600160a01b038316613b2f57613b2f614320565b613b398383613a81565b60068054906000613b49836145e0565b909155505060405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b606081600003613bb65750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613be05780613bca816145e0565b9150613bd99050600a836143f7565b9150613bba565b60008167ffffffffffffffff811115613bfb57613bfb61411b565b6040519080825280601f01601f191660200182016040528015613c25576020820181803683370190505b5090505b841561154157613c3a60018361436e565b9150613c47600a86614922565b613c529060306143b7565b60f81b818381518110613c6757613c676142ed565b60200101906001600160f81b031916908160001a905350613c89600a866143f7565b9450613c29565b80516060906000819003613cb4575050604080516020810190915260008152919050565b60006003613cc38360026143b7565b613ccd91906143f7565b613cd89060046143ca565b90506000613ce78260206143b7565b67ffffffffffffffff811115613cff57613cff61411b565b6040519080825280601f01601f191660200182016040528015613d29576020820181803683370190505b5090506000604051806060016040528060408152602001614a34604091399050600181016020830160005b86811015613db5576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b835260049092019101613d54565b506003860660018114613dcf5760028114613de057613dec565b613d3d60f01b600119830152613dec565b603d60f81b6000198301525b505050918152949350505050565b6001600160a01b038216600090815260146020526040812054613e1f9060019061436e565b600083815260166020526040902054909150808203613e6e576001600160a01b038416600090815260156020908152604080832085845282528083208390558583526016909152812055611f8f565b6001600160a01b039390931660009081526015602090815260408083209383529281528282208054868452848420819055835260169091528282209490945592839055908252812055565b6001600160e01b031981168114613ecf57600080fd5b50565b600060208284031215613ee457600080fd5b813561133781613eb9565b60005b83811015613f0a578181015183820152602001613ef2565b50506000910152565b60008151808452613f2b816020860160208601613eef565b601f01601f19169290920160200192915050565b6020815260006113376020830184613f13565b600060208284031215613f6457600080fd5b5035919050565b6001600160a01b0381168114613ecf57600080fd5b60008060408385031215613f9357600080fd5b8235613f9e81613f6b565b946020939093013593505050565b60008060408385031215613fbf57600080fd5b50508035926020909101359150565b600060208284031215613fe057600080fd5b813561133781613f6b565b60008060006060848603121561400057600080fd5b833561400b81613f6b565b9250602084013561401b81613f6b565b929592945050506040919091013590565b602080825282518282018190526000919060409081850190868401855b8281101561408357815180518552868101518786015285810151868601526060908101519085015260809093019290850190600101614049565b5091979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156140c8578351835292840192918401916001016140ac565b50909695505050505050565b8015158114613ecf57600080fd5b600080604083850312156140f557600080fd5b823561410081613f6b565b91506020830135614110816140d4565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561414757600080fd5b843561415281613f6b565b9350602085013561416281613f6b565b925060408501359150606085013567ffffffffffffffff8082111561418657600080fd5b818701915087601f83011261419a57600080fd5b8135818111156141ac576141ac61411b565b604051601f8201601f19908116603f011681019083821181831017156141d4576141d461411b565b816040528281528a60208487010111156141ed57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b60008060006060848603121561422657600080fd5b8335925060208401359150604084013561423f81613f6b565b809150509250925092565b6000806040838503121561425d57600080fd5b823561426881613f6b565b9150602083013561411081613f6b565b6000806020838503121561428b57600080fd5b823567ffffffffffffffff808211156142a357600080fd5b818501915085601f8301126142b757600080fd5b8135818111156142c657600080fd5b8660208260051b85010111156142db57600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561431557600080fd5b815161133781613f6b565b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b81810381811115610ceb57610ceb614358565b60006020828403121561439357600080fd5b8151611337816140d4565b8281526040602082015260006115416040830184613f13565b80820180821115610ceb57610ceb614358565b8082028115828204841417610ceb57610ceb614358565b634e487b7160e01b600052601260045260246000fd5b600082614406576144066143e1565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906119a590830184613f13565b60006020828403121561449457600080fd5b815161133781613eb9565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b600081600f0b83600f0b80614508576145086143e1565b60016001607f1b031982146000198214161561452657614526614358565b90059392505050565b600082600f0b82600f0b0280600f0b9150808214612fe757612fe7614358565b600f82810b9082900b0360016001607f1b0319811260016001607f1b0382131715610ceb57610ceb614358565b600f81810b9083900b0160016001607f1b03811360016001607f1b031982121715610ceb57610ceb614358565b6000816145b8576145b8614358565b506000190190565b8181036000831280158383131683831282161715612fe757612fe7614358565b6000600182016145f2576145f2614358565b5060010190565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061463b57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b6000835161465f818460208801613eef565b6503a37b5b2b7160d51b9083019081528351614682816006840160208801613eef565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b600083516146db818460208801613eef565b6903130b630b731b2a7b3160b51b908301908152835161470281600a840160208801613eef565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b6000835161475b818460208801613eef565b6a03637b1b5b2b22fb2b732160ad1b908301908152835161478381600b840160208801613eef565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b600083516147dc818460208801613eef565b6503b30b63ab2960d51b90830190815283516147ff816006840160208801613eef565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b81528251600090614851816010850160208801613eef565b7f222c20226465736372697074696f6e223a2022766553594e5448204e4654222c6010918401918201527f2022696d616765223a2022646174613a696d6167652f7376672b786d6c3b62616030820152641cd94d8d0b60da1b605082015283516148c2816055840160208801613eef565b61227d60f01b60559290910191820152605701949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161491581601d850160208701613eef565b91909101601d0192915050565b600082614931576149316143e1565b50069056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212206af31cf7619474f4b9975c4395c1798f0f692c6a18731d390f5f1858a229b47c64736f6c63430008180033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef00000000000000000000000086f25b91ca7591f3b1f321aaca091b2de060eec10000000000000000000000006b83131b2f6dc24e70443921bb43a5357a4c99bd
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103f15760003560e01c80637119748411610215578063c2c4c5c111610125578063e7e242d4116100b8578063f4359ce511610087578063f4359ce514610a1d578063f8a0576314610a44578063fbd3a29d14610a67578063fc0c546a14610a7a578063fd4a77f114610a8d57600080fd5b8063e7e242d4146109a8578063e985e9c5146109bb578063ee99fe28146109f7578063f266b58f14610a0a57600080fd5b8063d4e54c3b116100f4578063d4e54c3b1461095a578063e0514aba1461096d578063e2c7928114610980578063e441135c1461098857600080fd5b8063c2c4c5c1146108ee578063c87b56dd146108f6578063d1c2babb14610909578063d1febfb91461091c57600080fd5b806395d89b41116101a8578063a22cb46511610177578063a22cb4651461085a578063a4d855df1461086d578063b45a3c0e14610880578063b88d4fde146108c8578063c1f0fb9f146108db57600080fd5b806395d89b41146107fb578063981b24d014610821578063986b7d8a14610834578063a183af521461084757600080fd5b80638c2c9baf116101e45780638c2c9baf146107a95780638da5cb5b146107bc5780638fbb38ff146107cf578063900cf0cf146107f257600080fd5b80637119748414610761578063741853601461078457806379ba50971461078c578063899ffef41461079457600080fd5b80632e1a7d4d116103105780634bc2a657116102a35780636352211e116102725780636352211e146106f557806365fc3873146107085780636f5488371461071b57806370a082311461073b5780637116c60c1461074e57600080fd5b80634bc2a6571461069757806353a47bb7146106aa57806354fd4d50146106bd578063614d08f8146106e157600080fd5b806342842e0e116102df57806342842e0e14610638578063430c20811461064b578063461f711c1461065e57806346c96aac1461068457600080fd5b80632e1a7d4d146105b55780632f745c59146105c8578063313ce567146105fe57806339fda9d21461061857600080fd5b80631376f3da116103885780631c984bc3116103575780631c984bc31461058157806323b872dd1461059457806325a58b56146105a75780632af64bd3146105ad57600080fd5b80631376f3da14610518578063144fa6d7146105535780631627540c1461056657806318160ddd1461057957600080fd5b806306fdde03116103c457806306fdde0314610483578063081812fc146104ba578063095ea7b3146104e35780630d6a2033146104f857600080fd5b806301790e01146103f657806301ffc9a714610412578063047fc9aa1461044f57806304f3bcec14610458575b600080fd5b6103ff60065481565b6040519081526020015b60405180910390f35b61043f610420366004613ed2565b6001600160e01b03191660009081526018602052604090205460ff1690565b6040519015158152602001610409565b6103ff60055481565b60025461046b906001600160a01b031681565b6040516001600160a01b039091168152602001610409565b6104ad6040518060400160405280600b81526020016a1d9954d65395120813919560aa1b81525081565b6040516104099190613f3f565b61046b6104c8366004613f52565b6000908152601360205260409020546001600160a01b031690565b6104f66104f1366004613f80565b610aa0565b005b6103ff610506366004613f52565b600e6020526000908152604090205481565b61052b610526366004613fac565b610be1565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610409565b6104f6610561366004613fce565b610c28565b6104f6610574366004613fce565b610c52565b6103ff610cae565b6103ff61058f366004613fac565b610cbe565b6104f66105a2366004613feb565b610cf1565b436103ff565b61043f610d5a565b6104f66105c3366004613f52565b610e61565b6103ff6105d6366004613f80565b6001600160a01b03919091166000908152601560209081526040808320938352929052205490565b610606601281565b60405160ff9091168152602001610409565b61062b610626366004613fce565b611165565b604051610409919061402c565b6104f6610646366004613feb565b6112b8565b61043f610659366004613f80565b61132b565b61067161066c366004613f52565b61133e565b604051600f9190910b8152602001610409565b60105461046b906001600160a01b031681565b6104f66106a5366004613fce565b611381565b60015461046b906001600160a01b031681565b6104ad604051806040016040528060058152602001640312e302e360dc1b81525081565b6103ff69566f7465457363726f7760b01b81565b61046b610703366004613f52565b6113ba565b6103ff610716366004613fac565b611431565b6103ff610729366004613f52565b60086020526000908152604090205481565b6103ff610749366004613fce565b6114cb565b6103ff61075c366004613f52565b6114e9565b61067161076f366004613f52565b600d60205260009081526040902054600f0b81565b6104f6611549565b6104f66116c3565b61079c6117ad565b6040516104099190614090565b6103ff6107b7366004613fac565b611801565b60005461046b906001600160a01b031681565b61043f6107dd366004613f52565b600f6020526000908152604090205460ff1681565b6103ff60095481565b6104ad604051806040016040528060078152602001660eccaa6b29ca8960cb1b81525081565b6103ff61082f366004613f52565b61180d565b6104f6610842366004613f52565b6119af565b6104f6610855366004613fac565b6119f3565b6104f66108683660046140e2565b611b4a565b6104f661087b366004613fac565b611bce565b6108ae61088e366004613f52565b60076020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610409565b6104f66108d6366004614131565b611e28565b6104f66108e9366004613f52565b611f95565b6104f6611fc4565b6104ad610904366004613f52565b612004565b6104f6610917366004613fac565b6120b1565b61052b61092a366004613f52565b600a60205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6103ff610968366004614211565b612277565b6103ff61097b366004613fac565b612312565b6006546103ff565b6103ff610996366004613f52565b600c6020526000908152604090205481565b6103ff6109b6366004613f52565b61231e565b61043f6109c936600461424a565b6001600160a01b03918216600090815260176020908152604080832093909416825291909152205460ff1690565b6104f6610a05366004613fac565b612346565b61062b610a18366004614278565b612473565b6103ff7f0000000000000000000000000000000000000000000000000000000000093a8081565b6103ff610a52366004613f52565b60009081526007602052604090206001015490565b6104f6610a75366004613f52565b6125a0565b60045461046b906001600160a01b031681565b6104f6610a9b366004613f52565b6125d1565b610aa8612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b158015610ae057600080fd5b505afa158015610af4573d6000803e3d6000fd5b5050506000828152601260205260409020546001600160a01b0316905080610b1b57600080fd5b806001600160a01b0316836001600160a01b031603610b3957600080fd5b6000828152601260209081526040808320546001600160a01b0385811685526017845282852033808752945291909320549216149060ff168180610b7a5750805b610b8357600080fd5b60008481526013602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600b60205281600052604060002081633b9aca008110610c0057600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b610c3061261d565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b610c5a61261d565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b6000610cb9426114e9565b905090565b6000828152600b6020526040812082633b9aca008110610ce057610ce06142ed565b600302016001015490505b92915050565b610cf9612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b158015610d3157600080fd5b505afa158015610d45573d6000803e3d6000fd5b50505050610d558383833361268f565b505050565b600080610d656117ad565b905060005b8151811015610e58576000828281518110610d8757610d876142ed565b602090810291909101810151600081815260039092526040918290205460025492516321f8a72160e01b8152600481018390529193506001600160a01b039081169216906321f8a72190602401602060405180830381865afa158015610df1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e159190614303565b6001600160a01b0316141580610e4057506000818152600360205260409020546001600160a01b0316155b15610e4f576000935050505090565b50600101610d6a565b50600191505090565b60195460ff16600114610e7357600080fd5b6019805460ff19166002179055610e88612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b158015610ec057600080fd5b505afa158015610ed4573d6000803e3d6000fd5b50505050610ee23382612755565b610eee57610eee614320565b6000818152600e6020526040902054158015610f1957506000818152600f602052604090205460ff16155b610f3e5760405162461bcd60e51b8152600401610f3590614336565b60405180910390fd5b60008181526007602090815260409182902082518084019093528054600f0b835260010154908201819052421015610fb15760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f35565b8051604080518082018252600080825260208083018281528783526007909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155600554600f9190910b9061100c828261436e565b600555604080518082019091526000808252602082015261103090859085906127bb565b600061103b856113ba565b905061104685612e4b565b6004805460405163a9059cbb60e01b81526001600160a01b03848116938201939093526024810186905291169063a9059cbb906044016020604051808303816000875af115801561109b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110bf9190614381565b6110cb576110cb614320565b60408051868152602081018590524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c82611139858261436e565b6040805192835260208301919091520160405180910390a150506019805460ff19166001179055505050565b60606000611188836001600160a01b031660009081526014602052604090205490565b905060008167ffffffffffffffff8111156111a5576111a561411b565b60405190808252806020026020018201604052801561120157816020015b6111ee6040518060800160405280600081526020016000815260200160008152602001600081525090565b8152602001906001900390816111c35790505b50905060005b828110156112b0576001600160a01b03851660009081526015602090815260408083208484528252808320548084526007835292819020815180830183528154600f0b81526001909101548184015281516080810190925283825291810161126f8442612f13565b8152602001826020015181526020018260000151600f0b81525084848151811061129b5761129b6142ed565b60209081029190910101525050600101611207565b509392505050565b6112c0612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b1580156112f857600080fd5b505afa15801561130c573d6000803e3d6000fd5b50505050610d5583838360405180602001604052806000815250611e28565b60006113378383612755565b9392505050565b6000818152600c6020908152604080832054600b909252822081633b9aca00811061136b5761136b6142ed565b6003020154600160801b9004600f0b9392505050565b6010546001600160a01b0316331461139857600080fd5b601080546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152601260205260408120546001600160a01b031680610ceb5760405162461bcd60e51b815260206004820152602960248201527f5645204e46543a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610f35565b60195460009060ff1660011461144657600080fd5b6019805460ff1916600217905561145b612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b15801561149357600080fd5b505afa1580156114a7573d6000803e3d6000fd5b505050506114b6838333612fee565b90506019805460ff1916600117905592915050565b6001600160a01b038116600090815260146020526040812054610ceb565b6009546000818152600a6020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906115418185613162565b949350505050565b60006115536117ad565b905060005b81518110156116bf576000828281518110611575576115756142ed565b602002602001015190506000600260009054906101000a90046001600160a01b03166001600160a01b031663dacb2d0183846040516020016115e391907f5265736f6c766572206d697373696e67207461726765743a20000000000000008152601981019190915260390190565b6040516020818303038152906040526040518363ffffffff1660e01b815260040161160f92919061439e565b602060405180830381865afa15801561162c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116509190614303565b60008381526003602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251868152918201529192507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68910160405180910390a15050600101611558565b5050565b6001546001600160a01b0316331461173b5760405162461bcd60e51b815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527402063616e20616363657074206f776e65727368697605c1b6064820152608401610f35565b600054600154604080516001600160a01b0393841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b604080516001808252818301909252606091602080830190803683370190505090506b53797374656d53746174757360a01b816000815181106117f2576117f26142ed565b60200260200101818152505090565b600061133783836132b5565b60004382111561181f5761181f614320565b600954600061182e8483613586565b6000818152600a6020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529192508383101561193d576000600a816118918660016143b7565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461193757826060015181606001516118fd919061436e565b83604001518260400151611911919061436e565b6060850151611920908a61436e565b61192a91906143ca565b61193491906143f7565b91505b5061198c565b4382606001511461198c576060820151611957904361436e565b6040830151611966904261436e565b6060840151611975908961436e565b61197f91906143ca565b61198991906143f7565b90505b6119a5828284604001516119a091906143b7565b613162565b9695505050505050565b6010546001600160a01b031633146119c657600080fd5b6000818152600e60205260409020546119e19060019061436e565b6000918252600e602052604090912055565b60195460ff16600114611a0557600080fd5b6019805460ff19166002179055611a1a612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b158015611a5257600080fd5b505afa158015611a66573d6000803e3d6000fd5b50505050611a743383612755565b611a8057611a80614320565b60008281526007602090815260409182902082518084019093528054600f0b8352600101549082015281611ab657611ab6614320565b60008160000151600f0b13611b065760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f35565b42816020015111611b295760405162461bcd60e51b8152600401610f359061440b565b611b3883836000846002613604565b50506019805460ff1916600117905550565b336001600160a01b03831603611b6257611b62614320565b3360008181526017602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60195460ff16600114611be057600080fd5b6019805460ff19166002179055611bf5612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b158015611c2d57600080fd5b505afa158015611c41573d6000803e3d6000fd5b50505050611c4f3383612755565b611c5b57611c5b614320565b600082815260076020908152604080832081518083019092528054600f0b82526001015491810191909152907f0000000000000000000000000000000000000000000000000000000000093a8080611cb385426143b7565b611cbd91906143f7565b611cc791906143ca565b905042826020015111611d0b5760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f35565b60008260000151600f0b13611d565760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f35565b81602001518111611da95760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f35565b611db7630784ce00426143b7565b811115611e065760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f35565b611e1584600083856003613604565b50506019805460ff191660011790555050565b611e30612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b158015611e6857600080fd5b505afa158015611e7c573d6000803e3d6000fd5b50505050611e8c8484843361268f565b823b15611f8f57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611ec590339088908790879060040161444f565b6020604051808303816000875af1925050508015611f00575060408051601f3d908101601f19168201909252611efd91810190614482565b60015b611f5d573d808015611f2e576040519150601f19603f3d011682016040523d82523d6000602084013e611f33565b606091505b508051600003611f555760405162461bcd60e51b8152600401610f359061449f565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611f8d5760405162461bcd60e51b8152600401610f359061449f565b505b50505050565b6010546001600160a01b03163314611fac57600080fd5b6000908152600f60205260409020805460ff19169055565b612002600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506127bb565b565b6000818152601260205260409020546060906001600160a01b031661206b5760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f35565b60008281526007602090815260409182902082518084019093528054600f0b83526001015490820152611337836120a28142612f13565b60208401518451600f0b6137ef565b6120b9612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b1580156120f157600080fd5b505afa158015612105573d6000803e3d6000fd5b5050506000838152600e6020526040902054159050801561213557506000828152600f602052604090205460ff16155b6121515760405162461bcd60e51b8152600401610f3590614336565b80820361215d57600080fd5b6121673383612755565b61217057600080fd5b61217a3382612755565b61218357600080fd5b6000828152600760208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b9211156121ed5782602001516121f3565b83602001515b604080518082018252600080825260208083018281528b835260078252848320935184546001600160801b0319166001600160801b039091161784555160019093019290925582518084019093528083529082015290915061225890879086906127bb565b61226186612e4b565b61226f858383866004613604565b505050505050565b60195460009060ff1660011461228c57600080fd5b6019805460ff191660021790556122a1612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b1580156122d957600080fd5b505afa1580156122ed573d6000803e3d6000fd5b505050506122fc848484612fee565b90506019805460ff191660011790559392505050565b60006113378383612f13565b60008181526008602052604081205443900361233c57506000919050565b610ceb8242612f13565b60195460ff1660011461235857600080fd5b6019805460ff1916600217905561236d612603565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b1580156123a557600080fd5b505afa1580156123b9573d6000803e3d6000fd5b50505060008381526007602090815260409182902082518084019093528054600f0b835260010154908201529050816123f157600080fd5b60008160000151600f0b136124415760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f35565b428160200151116124645760405162461bcd60e51b8152600401610f359061440b565b611b3883836000846000613604565b606060008267ffffffffffffffff8111156124905761249061411b565b6040519080825280602002602001820160405280156124ec57816020015b6124d96040518060800160405280600081526020016000815260200160008152602001600081525090565b8152602001906001900390816124ae5790505b50905060005b838110156112b057600085858381811061250e5761250e6142ed565b60209081029290920135600081815260078452604090819020815180830183528154600f0b8152600190910154818601528151608081019092528282529194509092909150810161255f8442612f13565b8152602001826020015181526020018260000151600f0b81525084848151811061258b5761258b6142ed565b602090810291909101015250506001016124f2565b6010546001600160a01b031633146125b757600080fd5b6000818152600e60205260409020546119e19060016143b7565b6010546001600160a01b031633146125e857600080fd5b6000908152600f60205260409020805460ff19166001179055565b6000610cb96b53797374656d53746174757360a01b613926565b6000546001600160a01b031633146120025760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201526e37b936903a3434b99030b1ba34b7b760891b6064820152608401610f35565b6000828152600e60205260409020541580156126ba57506000828152600f602052604090205460ff16155b6126d65760405162461bcd60e51b8152600401610f3590614336565b6126e08183612755565b6126e957600080fd5b6126f3848361399b565b6126fd8483613a00565b6127078383613a81565b6000828152600860205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526012602090815260408083205460138352818420546001600160a01b039182168086526017855283862088841680885295529285205492938085149392909116149060ff1682806127a85750815b806127b05750805b979650505050505050565b604080516080810182526000808252602082018190529181018290526060810191909152604080516080810182526000808252602082018190529181018290526060810191909152600954600090819087156129265742876020015111801561282b575060008760000151600f0b135b1561287057865161284190630784ce00906144f1565b600f0b60208087019190915287015161285b90429061436e565b856020015161286a919061452f565b600f0b85525b42866020015111801561288a575060008660000151600f0b135b156128cf5785516128a090630784ce00906144f1565b600f0b6020808601919091528601516128ba90429061436e565b84602001516128c9919061452f565b600f0b84525b6020808801516000908152600d8252604090205490870151600f9190910b93501561292657866020015186602001510361290b57829150612926565b6020808701516000908152600d9091526040902054600f0b91505b60408051608081018252600080825260208201524291810191909152436060820152811561299b57506000818152600a602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b600081604001519050600060405180608001604052808460000151600f0b81526020018460200151600f0b8152602001846040015181526020018460600151815250905060008360400151421115612a2a5760408401516129fc904261436e565b6060850151612a0b904361436e565b612a1d90670de0b6b3a76400006143ca565b612a2791906143f7565b90505b60007f0000000000000000000000000000000000000000000000000000000000093a80612a5781866143f7565b612a6191906143ca565b905060005b60ff811015612bf057612a997f0000000000000000000000000000000000000000000000000000000000093a80836143b7565b9150600042831115612aad57429250612ac1565b506000828152600d6020526040902054600f0b5b612acb868461436e565b8760200151612ada919061452f565b87518890612ae990839061454f565b600f0b905250602087018051829190612b0390839061457c565b600f90810b90915288516000910b12159050612b1e57600087525b60008760200151600f0b1215612b3657600060208801525b60408088018490528501519295508592670de0b6b3a764000090612b5a908561436e565b612b6490866143ca565b612b6e91906143f7565b8560600151612b7d91906143b7565b6060880152612b8d6001896143b7565b9750428303612ba25750436060870152612bf0565b6000888152600a60209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550600101612a66565b505060098590558b15612c7b5788602001518860200151612c11919061454f565b84602001818151612c22919061457c565b600f0b90525088518851612c36919061454f565b84518590612c4590839061457c565b600f90810b90915260208601516000910b12159050612c6657600060208501525b60008460000151600f0b1215612c7b57600084525b6000858152600a60209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612e3d57428b602001511115612d32576020890151612ce1908861457c565b96508a602001518a6020015103612d04576020880151612d01908861454f565b96505b60208b8101516000908152600d9091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612d8d578a602001518a602001511115612d8d576020880151612d5d908761454f565b60208b8101516000908152600d9091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600c6020526040812054612da79060016143b7565b905080600c60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600b60008f815260200190815260200160002082633b9aca008110612dfd57612dfd6142ed565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612e553382612755565b612ea15760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f35565b6000612eac826113ba565b9050612eb8818361399b565b612ec28183613a00565b60068054906000612ed2836145a9565b909155505060405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600c6020526040812054808203612f33576000915050610ceb565b6000848152600b6020526040812082633b9aca008110612f5557612f556142ed565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612fa190856145c0565b8160200151612fb0919061452f565b81518290612fbf90839061454f565b600f90810b90915282516000910b12159050612fda57600081525b51600f0b9150610ceb9050565b5092915050565b6000807f0000000000000000000000000000000000000000000000000000000000093a808061301d86426143b7565b61302791906143f7565b61303191906143ca565b90506000851161304057600080fd5b42811161309e5760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f35565b6130ac630784ce00426143b7565b8111156130fb5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f35565b60116000815461310a906145e0565b9091555060115461311b8482613b17565b5060008181526007602090815260409182902082518084019093528054600f0b83526001908101549183019190915261315991839189918691613604565b95945050505050565b60008083905060007f0000000000000000000000000000000000000000000000000000000000093a807f0000000000000000000000000000000000000000000000000000000000093a8083604001516131bb91906143f7565b6131c591906143ca565b905060005b60ff81101561328d576131fd7f0000000000000000000000000000000000000000000000000000000000093a80836143b7565b915060008583111561321157859250613225565b506000828152600d6020526040902054600f0b5b6040840151613234908461436e565b8460200151613243919061452f565b8451859061325290839061454f565b600f0b905250858303613265575061328d565b8084602001818151613277919061457c565b600f0b90525050604083018290526001016131ca565b5060008260000151600f0b12156132a357600082525b50516001600160801b03169392505050565b6000438211156132c7576132c7614320565b6000838152600c6020526040812054815b608081101561335f578183101561335f57600060026132f784866143b7565b6133029060016143b7565b61330c91906143f7565b6000888152600b60205260409020909150869082633b9aca008110613333576133336142ed565b60030201600201541161334857809350613356565b61335360018261436e565b92505b506001016132d8565b506000858152600b6020526040812083633b9aca008110613382576133826142ed565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b6020830152600181015492820192909252600290910154606082015260095490915060006133d78783613586565b6000818152600a6020908152604080832081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606082015291925080848410156134b6576000600a8161343b8760016143b7565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060808301829052860151919250613498919061436e565b9250836040015181604001516134ae919061436e565b9150506134da565b60608301516134c5904361436e565b91508260400151426134d7919061436e565b90505b60408301518215613517578284606001518c6134f6919061436e565b61350090846143ca565b61350a91906143f7565b61351490826143b7565b90505b6040870151613526908261436e565b8760200151613535919061452f565b8751889061354490839061454f565b600f90810b90915288516000910b12905061357457505093516001600160801b03169650610ceb95505050505050565b60009950505050505050505050610ceb565b60008082815b60808110156135fa57818310156135fa57600060026135ab84866143b7565b6135b69060016143b7565b6135c091906143f7565b6000818152600a602052604090206002015490915087106135e3578093506135f1565b6135ee60018261436e565b92505b5060010161358c565b5090949350505050565b600554829061361386826143b7565b6005556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061364c90839061457c565b600f0b905250851561366057602083018690525b6000888152600760209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556136a28882856127bb565b3387158015906136c4575060048560048111156136c1576136c16145f9565b14155b1561375457600480546040516323b872dd60e01b81526001600160a01b0384811693820193909352306024820152604481018b90529116906323b872dd906064016020604051808303816000875af1158015613724573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137489190614381565b61375457613754614320565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b8942604051613798949392919061460f565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836137cc8a826143b7565b6040805192835260208301919091520160405180910390a1505050505050505050565b606060405180610120016040528060fd815260200161493760fd913990508061381786613b8f565b60405160200161382892919061464d565b60405160208183030381529060405290508061384385613b8f565b6040516020016138549291906146c9565b60405160208183030381529060405290508061386f84613b8f565b604051602001613880929190614749565b60405160208183030381529060405290508061389b83613b8f565b6040516020016138ac9291906147ca565b604051602081830303815290604052905060006138f96138cb87613b8f565b6138d484613c90565b6040516020016138e5929190614825565b604051602081830303815290604052613c90565b90508060405160200161390c91906148dd565b604051602081830303815290604052915050949350505050565b600081815260036020908152604080832054905170026b4b9b9b4b7339030b2323932b9b99d1607d1b92810192909252603182018490526001600160a01b0316908115159060510160405160208183030381529060405290612fe75760405162461bcd60e51b8152600401610f359190613f3f565b6000818152601260205260409020546001600160a01b038381169116146139c4576139c4614320565b6000818152601360205260409020546001600160a01b0316156116bf57600090815260136020526040902080546001600160a01b031916905550565b6000818152601260205260409020546001600160a01b03838116911614613a2957613a29614320565b600081815260126020526040902080546001600160a01b0319169055613a4f8282613dfa565b6001600160a01b0382166000908152601460205260408120805460019290613a7890849061436e565b90915550505050565b6000818152601260205260409020546001600160a01b031615613aa657613aa6614320565b600081815260126020908152604080832080546001600160a01b0319166001600160a01b038716908117909155808452601480845282852080546015865284872081885286528487208890558787526016865293862093909355908452909152805460019290613a789084906143b7565b60006001600160a01b038316613b2f57613b2f614320565b613b398383613a81565b60068054906000613b49836145e0565b909155505060405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b606081600003613bb65750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613be05780613bca816145e0565b9150613bd99050600a836143f7565b9150613bba565b60008167ffffffffffffffff811115613bfb57613bfb61411b565b6040519080825280601f01601f191660200182016040528015613c25576020820181803683370190505b5090505b841561154157613c3a60018361436e565b9150613c47600a86614922565b613c529060306143b7565b60f81b818381518110613c6757613c676142ed565b60200101906001600160f81b031916908160001a905350613c89600a866143f7565b9450613c29565b80516060906000819003613cb4575050604080516020810190915260008152919050565b60006003613cc38360026143b7565b613ccd91906143f7565b613cd89060046143ca565b90506000613ce78260206143b7565b67ffffffffffffffff811115613cff57613cff61411b565b6040519080825280601f01601f191660200182016040528015613d29576020820181803683370190505b5090506000604051806060016040528060408152602001614a34604091399050600181016020830160005b86811015613db5576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b835260049092019101613d54565b506003860660018114613dcf5760028114613de057613dec565b613d3d60f01b600119830152613dec565b603d60f81b6000198301525b505050918152949350505050565b6001600160a01b038216600090815260146020526040812054613e1f9060019061436e565b600083815260166020526040902054909150808203613e6e576001600160a01b038416600090815260156020908152604080832085845282528083208390558583526016909152812055611f8f565b6001600160a01b039390931660009081526015602090815260408083209383529281528282208054868452848420819055835260169091528282209490945592839055908252812055565b6001600160e01b031981168114613ecf57600080fd5b50565b600060208284031215613ee457600080fd5b813561133781613eb9565b60005b83811015613f0a578181015183820152602001613ef2565b50506000910152565b60008151808452613f2b816020860160208601613eef565b601f01601f19169290920160200192915050565b6020815260006113376020830184613f13565b600060208284031215613f6457600080fd5b5035919050565b6001600160a01b0381168114613ecf57600080fd5b60008060408385031215613f9357600080fd5b8235613f9e81613f6b565b946020939093013593505050565b60008060408385031215613fbf57600080fd5b50508035926020909101359150565b600060208284031215613fe057600080fd5b813561133781613f6b565b60008060006060848603121561400057600080fd5b833561400b81613f6b565b9250602084013561401b81613f6b565b929592945050506040919091013590565b602080825282518282018190526000919060409081850190868401855b8281101561408357815180518552868101518786015285810151868601526060908101519085015260809093019290850190600101614049565b5091979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156140c8578351835292840192918401916001016140ac565b50909695505050505050565b8015158114613ecf57600080fd5b600080604083850312156140f557600080fd5b823561410081613f6b565b91506020830135614110816140d4565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561414757600080fd5b843561415281613f6b565b9350602085013561416281613f6b565b925060408501359150606085013567ffffffffffffffff8082111561418657600080fd5b818701915087601f83011261419a57600080fd5b8135818111156141ac576141ac61411b565b604051601f8201601f19908116603f011681019083821181831017156141d4576141d461411b565b816040528281528a60208487010111156141ed57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b60008060006060848603121561422657600080fd5b8335925060208401359150604084013561423f81613f6b565b809150509250925092565b6000806040838503121561425d57600080fd5b823561426881613f6b565b9150602083013561411081613f6b565b6000806020838503121561428b57600080fd5b823567ffffffffffffffff808211156142a357600080fd5b818501915085601f8301126142b757600080fd5b8135818111156142c657600080fd5b8660208260051b85010111156142db57600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561431557600080fd5b815161133781613f6b565b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b81810381811115610ceb57610ceb614358565b60006020828403121561439357600080fd5b8151611337816140d4565b8281526040602082015260006115416040830184613f13565b80820180821115610ceb57610ceb614358565b8082028115828204841417610ceb57610ceb614358565b634e487b7160e01b600052601260045260246000fd5b600082614406576144066143e1565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906119a590830184613f13565b60006020828403121561449457600080fd5b815161133781613eb9565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b600081600f0b83600f0b80614508576145086143e1565b60016001607f1b031982146000198214161561452657614526614358565b90059392505050565b600082600f0b82600f0b0280600f0b9150808214612fe757612fe7614358565b600f82810b9082900b0360016001607f1b0319811260016001607f1b0382131715610ceb57610ceb614358565b600f81810b9083900b0160016001607f1b03811360016001607f1b031982121715610ceb57610ceb614358565b6000816145b8576145b8614358565b506000190190565b8181036000831280158383131683831282161715612fe757612fe7614358565b6000600182016145f2576145f2614358565b5060010190565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061463b57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b6000835161465f818460208801613eef565b6503a37b5b2b7160d51b9083019081528351614682816006840160208801613eef565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b600083516146db818460208801613eef565b6903130b630b731b2a7b3160b51b908301908152835161470281600a840160208801613eef565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b6000835161475b818460208801613eef565b6a03637b1b5b2b22fb2b732160ad1b908301908152835161478381600b840160208801613eef565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b600083516147dc818460208801613eef565b6503b30b63ab2960d51b90830190815283516147ff816006840160208801613eef565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b81528251600090614851816010850160208801613eef565b7f222c20226465736372697074696f6e223a2022766553594e5448204e4654222c6010918401918201527f2022696d616765223a2022646174613a696d6167652f7376672b786d6c3b62616030820152641cd94d8d0b60da1b605082015283516148c2816055840160208801613eef565b61227d60f01b60559290910191820152605701949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161491581601d850160208701613eef565b91909101601d0192915050565b600082614931576149316143e1565b50069056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212206af31cf7619474f4b9975c4395c1798f0f692c6a18731d390f5f1858a229b47c64736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000086f25b91ca7591f3b1f321aaca091b2de060eec10000000000000000000000006b83131b2f6dc24e70443921bb43a5357a4c99bd
-----Decoded View---------------
Arg [0] : token_addr (address): 0x86F25B91CA7591f3b1f321AaCA091B2dE060eEc1
Arg [1] : _resolver (address): 0x6B83131B2f6dc24e70443921Bb43a5357a4C99bD
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000086f25b91ca7591f3b1f321aaca091b2de060eec1
Arg [1] : 0000000000000000000000006b83131b2f6dc24e70443921bb43a5357a4c99bd
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.