Overview
ETH Balance
0 ETH
Eth Value
$0.00Token Holdings
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 1,418 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw | 21403987 | 2 days ago | IN | 0 ETH | 0.00187463 | ||||
Withdraw | 21396885 | 3 days ago | IN | 0 ETH | 0.00416049 | ||||
Withdraw | 21337078 | 11 days ago | IN | 0 ETH | 0.01108761 | ||||
Withdraw | 21319948 | 13 days ago | IN | 0 ETH | 0.00367388 | ||||
Withdraw | 21284277 | 18 days ago | IN | 0 ETH | 0.00231975 | ||||
Withdraw | 21282940 | 18 days ago | IN | 0 ETH | 0.00603523 | ||||
Withdraw | 21150872 | 37 days ago | IN | 0 ETH | 0.00371593 | ||||
Withdraw | 21143053 | 38 days ago | IN | 0 ETH | 0.00467057 | ||||
Withdraw | 21141070 | 38 days ago | IN | 0 ETH | 0.00278236 | ||||
Withdraw | 21107633 | 43 days ago | IN | 0 ETH | 0.00395051 | ||||
Withdraw | 21104115 | 43 days ago | IN | 0 ETH | 0.00112555 | ||||
Withdraw | 21082548 | 46 days ago | IN | 0 ETH | 0.00415946 | ||||
Withdraw | 21013079 | 56 days ago | IN | 0 ETH | 0.00187794 | ||||
Withdraw | 21002596 | 58 days ago | IN | 0 ETH | 0.00172185 | ||||
Withdraw | 20997562 | 58 days ago | IN | 0 ETH | 0.00373288 | ||||
Withdraw | 20989052 | 59 days ago | IN | 0 ETH | 0.00499016 | ||||
Withdraw | 20978538 | 61 days ago | IN | 0 ETH | 0.00478753 | ||||
Withdraw | 20977941 | 61 days ago | IN | 0 ETH | 0.00403834 | ||||
Withdraw | 20977534 | 61 days ago | IN | 0 ETH | 0.00320203 | ||||
Withdraw | 20977419 | 61 days ago | IN | 0 ETH | 0.00277295 | ||||
Withdraw | 20965723 | 63 days ago | IN | 0 ETH | 0.01397158 | ||||
Withdraw | 20880131 | 75 days ago | IN | 0 ETH | 0.00713592 | ||||
Withdraw | 20746363 | 93 days ago | IN | 0 ETH | 0.00060559 | ||||
Withdraw | 20666883 | 104 days ago | IN | 0 ETH | 0.00035154 | ||||
Withdraw | 20644372 | 108 days ago | IN | 0 ETH | 0.00036138 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Vyper_contract
Compiler Version
vyper:0.3.7
Contract Source Code (Vyper language format)
# @version 0.3.7 """ @title Voting Escrow @author Curve Finance @license MIT @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for) @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years). """ # ==================================================================== # | ______ _______ | # | / _____________ __ __ / ____(_____ ____ _____ ________ | # | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | # | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | # | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | # | | # ==================================================================== # ============================== veFPIS ============================== # ==================================================================== # Frax Finance: https://github.com/FraxFinance # Original idea and credit: # Curve Finance's veCRV # https://curve.readthedocs.io/dao-vecrv.html # https://resources.curve.fi/faq/vote-locking-boost # https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy # veFPIS is basically a fork, with the key difference that 1 FPIS locked for 1 second would be ~ 1 veFPIS, # As opposed to ~ 0 veFPIS (as it is with veCRV) # Frax Primary Forker(s) / Modifier(s) # Travis Moore: https://github.com/FortisFortuna # Frax Reviewer(s) / Contributor(s) # Dennis: https://github.com/denett # Jamie Turley: https://github.com/jyturley # Drake Evans: https://github.com/DrakeEvans # Rich Gee: https://github.com/zer0blockchain # Sam Kazemian: https://github.com/samkazemian # 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 ^ # 4 + / # | / # | / # | / # |/ # 1 +--------+------> time # maxtime (4 years) struct Point: bias: int128 # principal FPIS amount locked slope: int128 # - dweight / dt ts: uint256 blk: uint256 # block fpis_amt: uint256 # 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: amount: int128 end: uint256 interface ERC20: def decimals() -> uint256: view def balanceOf(addr: address) -> uint256: view def name() -> String[64]: view def symbol() -> String[32]: view def transfer(to: address, amount: uint256) -> bool: nonpayable def transferFrom(spender: address, to: address, amount: uint256) -> bool: nonpayable # Interface for checking whether address belongs to a whitelisted # type of a smart wallet. # When new types are added - the whole contract is changed # The check() method is modifying to be able to use caching # for individual wallet addresses interface SmartWalletChecker: def check(addr: address) -> bool: nonpayable # Flags CREATE_LOCK_TYPE: constant(int128) = 0 INCREASE_LOCK_AMOUNT: constant(int128) = 1 INCREASE_UNLOCK_TIME: constant(int128) = 2 USER_WITHDRAW: constant(int128) = 3 TRANSFER_FROM_APP: constant(int128) = 4 TRANSFER_TO_APP: constant(int128) = 5 PROXY_ADD: constant(int128) = 6 PROXY_SLASH: constant(int128) = 7 CHECKPOINT_ONLY: constant(int128) = 8 event NominateOwnership: admin: address event AcceptOwnership: admin: address event Deposit: provider: indexed(address) payer_addr: indexed(address) value: uint256 locktime: indexed(uint256) type: int128 ts: uint256 event Withdraw: provider: indexed(address) to_addr: indexed(address) value: uint256 ts: uint256 event Supply: prevSupply: uint256 supply: uint256 event TransferToApp: staker_addr: indexed(address) app_addr: indexed(address) transfer_amt: uint256 event TransferFromApp: app_addr: indexed(address) staker_addr: indexed(address) transfer_amt: uint256 event ProxyAdd: staker_addr: indexed(address) proxy_addr: indexed(address) add_amt: uint256 event ProxySlash: staker_addr: indexed(address) proxy_addr: indexed(address) slash_amt: uint256 event SmartWalletCheckerComitted: future_smart_wallet_checker: address event SmartWalletCheckerApplied: smart_wallet_checker: address event EmergencyUnlockToggled: emergencyUnlockActive: bool event AppIncreaseAmountForsToggled: appIncreaseAmountForsEnabled: bool event ProxyTransferFromsToggled: appTransferFromsEnabled: bool event ProxyTransferTosToggled: appTransferTosEnabled: bool event ProxyAddsToggled: proxyAddsEnabled: bool event ProxySlashesToggled: proxySlashesEnabled: bool event LendingProxySet: proxy_address: address event HistoricalProxyToggled: proxy_address: address enabled: bool event StakerProxySet: proxy_address: address WEEK: constant(uint256) = 7 * 86400 # all future times are rounded by week MAXTIME: constant(uint256) = 4 * 365 * 86400 # 4 years MAXTIME_I128: constant(int128) = 4 * 365 * 86400 # 4 years MULTIPLIER: constant(uint256) = 10 ** 18 VOTE_WEIGHT_MULTIPLIER: constant(uint256) = 4 - 1 # 4x gives 300% boost at 4 years VOTE_WEIGHT_MULTIPLIER_I128: constant(int128) = 4 - 1 # 4x gives 300% boost at 4 years token: public(address) supply: public(uint256) # Tracked FPIS in the contract locked: public(HashMap[address, LockedBalance]) # user -> locked balance position info epoch: public(uint256) point_history: public(Point[100000000000000000000000000000]) # epoch -> unsigned point user_point_history: public(HashMap[address, Point[1000000000]]) # user -> Point[user_epoch] user_point_epoch: public(HashMap[address, uint256]) # user -> last week epoch their slope and bias were checkpointed # time -> signed slope change. Stored ahead of time so we can keep track of expiring users. # Time will always be a multiple of 1 week slope_changes: public(HashMap[uint256, int128]) # Misc appIncreaseAmountForsEnabled: public(bool) # Whether the proxy can directly deposit FPIS and increase a particular user's stake appTransferFromsEnabled: public(bool) # Whether FPIS can be received from apps or not appTransferTosEnabled: public(bool) # Whether FPIS can be sent to apps or not proxyAddsEnabled: public(bool) # Whether the proxy can add to the user's position proxySlashesEnabled: public(bool) # Whether the proxy can slash the user's position # Emergency Unlock emergencyUnlockActive: public(bool) # Proxies (allow withdrawal / deposits for lending protocols, etc.) current_proxy: public(address) # Set by admin. Can only be one at any given time historical_proxies: public(HashMap[address, bool]) # Set by admin. Used for paying back / liquidating after the main current_proxy changes staker_whitelisted_proxy: public(HashMap[address, address]) # user -> proxy. Set by user user_proxy_balance: public(HashMap[address, uint256]) # user -> amount held in proxy # ERC20 related name: public(String[64]) symbol: public(String[32]) version: public(String[32]) decimals: public(uint256) # Checker for whitelisted (smart contract) wallets which are allowed to deposit # The goal is to prevent tokenizing the escrow future_smart_wallet_checker: public(address) smart_wallet_checker: public(address) admin: public(address) # Can and will be a smart contract future_admin: public(address) @external def __init__(): """ @notice Contract constructor. No constructor args due to Etherscan verification issues """ token_addr: address = 0xc2544A32872A91F4A553b404C6950e89De901fdb self.admin = msg.sender self.token = token_addr self.point_history[0].blk = block.number self.point_history[0].ts = block.timestamp self.point_history[0].fpis_amt = 0 self.appTransferFromsEnabled = False self.appTransferTosEnabled = False self.proxyAddsEnabled = False self.proxySlashesEnabled = False _decimals: uint256 = ERC20(token_addr).decimals() assert _decimals <= 255 self.decimals = _decimals self.name = "veFPIS" self.symbol = "veFPIS" self.version = "veFPIS_1.0.0" @external def nominate_ownership(addr: address): """ @notice Transfer ownership of this contract to `addr` @param addr Address of the new owner """ assert msg.sender == self.admin # dev: admin only self.future_admin = addr log NominateOwnership(addr) @external def accept_transfer_ownership(): """ @notice Accept a pending ownership transfer @dev Only callable by the new owner """ _admin: address = self.future_admin assert msg.sender == _admin # dev: future admin only self.admin = _admin self.future_admin = empty(address) log AcceptOwnership(_admin) @external def commit_smart_wallet_checker(addr: address): """ @notice Set an external contract to check for approved smart contract wallets @param addr Address of Smart contract checker """ assert msg.sender == self.admin self.future_smart_wallet_checker = addr log SmartWalletCheckerComitted(self.future_smart_wallet_checker) @external def apply_smart_wallet_checker(): """ @notice Apply setting external contract to check approved smart contract wallets """ assert msg.sender == self.admin self.smart_wallet_checker = self.future_smart_wallet_checker log SmartWalletCheckerApplied(self.smart_wallet_checker) @external def recoverERC20(token_addr: address, amount: uint256): """ @dev Used to recover non-FPIS ERC20 tokens """ assert msg.sender == self.admin # dev: admin only assert token_addr != self.token # Cannot recover FPIS. Use toggleEmergencyUnlock instead and have users pull theirs out individually ERC20(token_addr).transfer(self.admin, amount) @internal def assert_not_contract(addr: address): """ @notice Check if the call is from a whitelisted smart contract, revert if not @param addr Address to be checked """ if addr != tx.origin: checker: address = self.smart_wallet_checker if checker != empty(address): if SmartWalletChecker(checker).check(addr): return raise "Smart contract depositors not allowed" @external @view def get_last_user_slope(addr: address) -> int128: """ @notice Get the most recently recorded rate of voting power decrease for `addr` @param addr Address of the user wallet @return Value of the slope """ uepoch: uint256 = self.user_point_epoch[addr] return self.user_point_history[addr][uepoch].slope @external @view def get_last_user_bias(addr: address) -> int128: """ @notice Get the most recently recorded bias (principal) @param addr Address of the user wallet @return Value of the bias """ uepoch: uint256 = self.user_point_epoch[addr] return self.user_point_history[addr][uepoch].bias @external @view def get_last_user_point(addr: address) -> Point: """ @notice Get the most recently recorded Point for `addr` @param addr Address of the user wallet @return Latest Point for the user """ uepoch: uint256 = self.user_point_epoch[addr] return self.user_point_history[addr][uepoch] @external @view def user_point_history__ts(_addr: address, _idx: uint256) -> uint256: """ @notice Get the timestamp for checkpoint `_idx` for `_addr` @param _addr User wallet address @param _idx User epoch number @return Epoch time of the checkpoint """ return self.user_point_history[_addr][_idx].ts @external @view def get_last_point() -> Point: """ @notice Get the most recently recorded Point for the contract @return Latest Point for the contract """ return self.point_history[self.epoch] @external @view def locked__end(_addr: address) -> uint256: """ @notice Get timestamp when `_addr`'s lock finishes @param _addr User wallet @return Epoch time of the lock end """ return self.locked[_addr].end @external @view def locked__amount(_addr: address) -> int128: """ @notice Get amount of `_addr`'s locked FPIS @param _addr User wallet @return FPIS amount locked by `_addr` """ return self.locked[_addr].amount @external @view def curr_period_start() -> uint256: """ @notice Get the start timestamp of this week's period @return Epoch time of the period start """ return (block.timestamp / WEEK * WEEK) @external @view def next_period_start() -> uint256: """ @notice Get the start timestamp of next week's period @return Epoch time of next week's period start """ return (WEEK + (block.timestamp / WEEK * WEEK)) @internal def _checkpoint(addr: address, old_locked: LockedBalance, new_locked: LockedBalance, flag: int128): """ @notice Record global and per-user data to checkpoint @param addr User's wallet address. No user checkpoint if 0x0 @param old_locked Previous locked amount / end lock time for the user @param new_locked New locked amount / end lock time for the user @param flag Used for downstream logic """ usr_old_pt: Point = empty(Point) usr_new_pt: Point = empty(Point) old_gbl_dslope: int128 = 0 # Old global slope change new_gbl_dslope: int128 = 0 # New global slope change _epoch: uint256 = self.epoch # ////////////////////////////////// STEP 1 ////////////////////////////////// # Take note of any user bias and slope changes # Also note previous global slope and point # //////////////////////////////////////////////////////////////////////////// # Skip if a user isn't being checkpointed if addr != empty(address): # Calculate slopes and biases # Kept at zero when they have to # ============================================================================== # -------------------------------- Old veCRV method -------------------------------- # if old_locked.end > block.timestamp and old_locked.amount > 0: # usr_old_pt.slope = old_locked.amount / MAXTIME_I128 # usr_old_pt.bias = usr_old_pt.slope * convert(old_locked.end - block.timestamp, int128) # if new_locked.end > block.timestamp and new_locked.amount > 0: # usr_new_pt.slope = new_locked.amount / MAXTIME_I128 # usr_new_pt.bias = usr_new_pt.slope * convert(new_locked.end - block.timestamp, int128) # -------------------------------- New method for veFPIS -------------------------------- if old_locked.end > block.timestamp and old_locked.amount > 0: usr_old_pt.slope = (old_locked.amount * VOTE_WEIGHT_MULTIPLIER_I128) / MAXTIME_I128 usr_old_pt.bias = old_locked.amount + (usr_old_pt.slope * convert(old_locked.end - block.timestamp, int128)) if new_locked.end > block.timestamp and new_locked.amount > 0: usr_new_pt.slope = (new_locked.amount * VOTE_WEIGHT_MULTIPLIER_I128) / MAXTIME_I128 usr_new_pt.bias = new_locked.amount + (usr_new_pt.slope * convert(new_locked.end - block.timestamp, int128)) # ============================================================================== # 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_gbl_dslope = self.slope_changes[old_locked.end] if new_locked.end != 0: if new_locked.end == old_locked.end: new_gbl_dslope = old_gbl_dslope else: new_gbl_dslope = self.slope_changes[new_locked.end] # Get last global point and checkpoint time last_point: Point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number, fpis_amt: 0}) if _epoch > 0: last_point = self.point_history[_epoch] last_checkpoint: uint256 = 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 initial_last_point: Point = last_point # Calculate the average blocks per second since the last checkpoint # Will use this to estimate block numbers at intermediate points in Step 2 block_slope: uint256 = 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 # ////////////////////////////////// STEP 2 ////////////////////////////////// # Go over past weeks to fill history and calculate what the current point is # Basically "catches up" the global state # Ignore user-specific deltas right now, they will be handled later # //////////////////////////////////////////////////////////////////////////// latest_checkpoint_ts: uint256 = (last_checkpoint / WEEK) * WEEK for i in range(255): # 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 latest_checkpoint_ts += WEEK d_slope: int128 = 0 if latest_checkpoint_ts > block.timestamp: latest_checkpoint_ts = block.timestamp else: d_slope = self.slope_changes[latest_checkpoint_ts] # Subtract the elapsed bias (slope * elapsed time) from the bias total last_point.bias -= last_point.slope * convert(latest_checkpoint_ts - last_checkpoint, int128) # Add / Subtract the pre-recorded change in slope (d_slope) for this epoch to the total slope # d_slope can be either positive or negative last_point.slope += d_slope # Safety checks 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 # Update the latest checkpoint, last_point info, and epoch last_checkpoint = latest_checkpoint_ts last_point.ts = latest_checkpoint_ts # This block number is an estimate last_point.blk = initial_last_point.blk + block_slope * (latest_checkpoint_ts - initial_last_point.ts) / MULTIPLIER _epoch += 1 # Fill for the current block, if applicable if latest_checkpoint_ts == block.timestamp: last_point.blk = block.number break else: self.point_history[_epoch] = last_point self.epoch = _epoch # Now point_history is filled until t=now # ////////////////////////////////// STEP 3 ////////////////////////////////// # Handle some special cases # //////////////////////////////////////////////////////////////////////////// # Skip if a user isn't being checkpointed if addr != empty(address): # 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 += (usr_new_pt.slope - usr_old_pt.slope) last_point.bias += (usr_new_pt.bias - usr_old_pt.bias) # ============================================================================== # Handle FPIS balance change (withdrawals and deposits) if (new_locked.amount > old_locked.amount): last_point.fpis_amt += convert(new_locked.amount - old_locked.amount, uint256) if (new_locked.amount < old_locked.amount): last_point.fpis_amt -= convert(old_locked.amount - new_locked.amount, uint256) # Subtract the bias if you are slashing after expiry if ((flag == PROXY_SLASH) and (new_locked.end < block.timestamp)): # Net change is the delta last_point.bias += new_locked.amount last_point.bias -= old_locked.amount # Remove the offset # Corner case to fix issue because emergency unlock allows withdrawal before expiry and disrupts the math if (new_locked.amount == 0): if (not (self.emergencyUnlockActive)): # Net change is the delta # last_point.bias += new_locked.amount WILL BE ZERO last_point.bias -= old_locked.amount # ============================================================================== # Check for zeroes if last_point.slope < 0: last_point.slope = 0 if last_point.bias < 0: last_point.bias = 0 # Record the changed point into history self.point_history[_epoch] = last_point # ////////////////////////////////// STEP 4 ////////////////////////////////// # Handle global slope changes and user point historical info # //////////////////////////////////////////////////////////////////////////// # Skip if a user isn't being checkpointed if addr != empty(address): # 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_gbl_dslope was <something> - usr_old_pt.slope, so we cancel that old_gbl_dslope += usr_old_pt.slope if new_locked.end == old_locked.end: old_gbl_dslope -= usr_new_pt.slope # It was a new deposit, not extension self.slope_changes[old_locked.end] = old_gbl_dslope if new_locked.end > block.timestamp: if new_locked.end > old_locked.end: new_gbl_dslope -= usr_new_pt.slope # old slope disappeared at this point self.slope_changes[new_locked.end] = new_gbl_dslope # else: we recorded it already in old_gbl_dslope # Now handle user history user_epoch: uint256 = self.user_point_epoch[addr] + 1 # Update tracked info for user self.user_point_epoch[addr] = user_epoch usr_new_pt.ts = block.timestamp usr_new_pt.blk = block.number usr_new_pt.fpis_amt = convert(self.locked[addr].amount, uint256) # Final check # At the end of the day, if the user is expired, their bias should be self.locked[addr].amount (fpis_amt) # And their slope, 0 if new_locked.end < block.timestamp: usr_new_pt.bias = self.locked[addr].amount usr_new_pt.slope = 0 self.user_point_history[addr][user_epoch] = usr_new_pt @internal def _deposit_for(_staker_addr: address, _payer_addr: address, _value: uint256, unlock_time: uint256, locked_balance: LockedBalance, flag: int128): """ @notice Deposit and lock tokens for a user @param _staker_addr User's wallet address @param _payer_addr Payer address for the deposit @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 """ # Pull in the tokens first before modifying state assert ERC20(self.token).transferFrom(_payer_addr, self, _value) # Note original data old_locked: LockedBalance = locked_balance supply_before: uint256 = self.supply # Get the staker's balance and the total supply new_locked: LockedBalance = old_locked # Will be incremented soon # Increase the supply self.supply = supply_before + _value # Add to an existing lock, or if the lock is expired - create a new one new_locked.amount += convert(_value, int128) if unlock_time != 0: new_locked.end = unlock_time self.locked[_staker_addr] = new_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) # new_locked.end > block.timestamp (always) self._checkpoint(_staker_addr, old_locked, new_locked, flag) log Deposit(_staker_addr, _payer_addr, _value, new_locked.end, flag, block.timestamp) log Supply(supply_before, supply_before + _value) @external def checkpoint(): """ @notice Record global data to checkpoint """ self._checkpoint(empty(address), empty(LockedBalance), empty(LockedBalance), 0) @external @nonreentrant('lock') def create_lock(_value: uint256, _unlock_time: uint256): """ @notice Deposit `_value` tokens for `msg.sender` and lock until `_unlock_time` @param _value Amount to deposit @param _unlock_time Epoch time when tokens unlock, rounded down to whole weeks """ self.assert_not_contract(msg.sender) unlock_time: uint256 = (_unlock_time / WEEK) * WEEK # Locktime is rounded down to weeks _locked: LockedBalance = self.locked[msg.sender] assert _value > 0, "Value must be > 0" # dev: need non-zero value assert _locked.amount == 0, "Withdraw old tokens first" assert unlock_time > block.timestamp, "Can only lock until time in the future" assert unlock_time <= block.timestamp + MAXTIME, "Voting lock can be 4 years max" self._deposit_for(msg.sender, msg.sender, _value, unlock_time, _locked, CREATE_LOCK_TYPE) @internal def _increase_amount(_staker_addr: address, _payer_addr: address, _value: uint256): """ @notice Deposit `_value` additional tokens for `_staker_addr` without modifying the unlock time or creating a new stake @param _staker_addr The user that the tokens should be credited to @param _staker_addr Payer of the FPIS @param _value Amount of tokens to deposit and add to the lock """ if ((_payer_addr != self.current_proxy) and (not self.historical_proxies[_payer_addr])): self.assert_not_contract(_payer_addr) # Payer should either be a proxy, EOA, or authorized contract self.assert_not_contract(_staker_addr) # The staker should not be unauthorized _locked: LockedBalance = self.locked[_staker_addr] assert _value > 0, "Value must be > 0" # dev: need non-zero value assert _locked.amount > 0, "No existing lock found" assert _locked.end > block.timestamp, "Cannot add to expired lock. Withdraw" self._deposit_for(_staker_addr, _payer_addr, _value, 0, _locked, INCREASE_LOCK_AMOUNT) @external @nonreentrant('lock') def increase_amount(_value: uint256): """ @notice Deposit `_value` additional tokens for `msg.sender` without modifying the unlock time @param _value Amount of tokens to deposit and add to the lock """ self._increase_amount(msg.sender, msg.sender, _value) @external @nonreentrant('lock') def increase_amount_for(_staker_addr: address, _value: uint256): """ @notice Deposit `_value` additional tokens for `_staker_addr` without modifying the unlock time or creating a new stake. msg.sender is payer. @param _staker_addr The user that the tokens should be credited to @param _value Amount of tokens to deposit and add to the lock """ assert (self.appIncreaseAmountForsEnabled), "Currently disabled" # Sender is payer. Make sure to have it approve to veFPIS first self._increase_amount(_staker_addr, msg.sender, _value) @external @nonreentrant('lock') def checkpoint_user(_staker_addr: address): """ @notice Simply updates the slope, bias, etc for a user. @param _staker_addr The user to update """ _locked: LockedBalance = self.locked[_staker_addr] assert _locked.amount > 0, "No existing lock found" # assert _locked.end > block.timestamp, "Expired lock" self._deposit_for(_staker_addr, _staker_addr, 0, 0, _locked, CHECKPOINT_ONLY) @external @nonreentrant('lock') def increase_unlock_time(_unlock_time: uint256): """ @notice Extend the unlock time for `msg.sender` to `_unlock_time` @param _unlock_time New epoch time for unlocking """ self.assert_not_contract(msg.sender) _locked: LockedBalance = self.locked[msg.sender] unlock_time: uint256 = (_unlock_time / WEEK) * WEEK # Locktime is rounded down to weeks assert _locked.end > block.timestamp, "Lock expired" assert _locked.amount > 0, "Nothing is locked" assert unlock_time > _locked.end, "Can only increase lock duration" assert unlock_time <= block.timestamp + MAXTIME, "Voting lock can be 4 years max" self._deposit_for(msg.sender, msg.sender, 0, unlock_time, _locked, INCREASE_UNLOCK_TIME) @internal def _withdraw(staker_addr: address, addr_out: address, locked_in: LockedBalance, amount_in: int128, flag: int128): """ @notice Withdraw tokens for `staker_addr` @dev Must be greater than 0 and less than the user's locked amount @dev Only special users can withdraw less than the full locked amount (namely lending platforms, etc) """ assert ((amount_in >= 0) and (amount_in <= locked_in.amount)), "Cannot withdraw more than the user has" _locked: LockedBalance = locked_in value: uint256 = convert(amount_in, uint256) old_locked: LockedBalance = _locked if (amount_in == _locked.amount): _locked.end = 0 # End the position if doing a full withdrawal _locked.amount -= amount_in self.locked[staker_addr] = _locked supply_before: uint256 = self.supply self.supply = supply_before - value # old_locked can have either expired <= timestamp or zero end # _locked has only 0 end # Both can have >= 0 amount # addr: address, old_locked: LockedBalance, new_locked: LockedBalance self._checkpoint(staker_addr, old_locked, _locked, flag) # Transfer out the tokens at the very end assert ERC20(self.token).transfer(addr_out, value), "ERC20 transfer out failed" log Withdraw(staker_addr, addr_out, value, block.timestamp) log Supply(supply_before, supply_before - value) @external @nonreentrant('proxy') def proxy_add( _staker_addr: address, _add_amt: uint256, ): """ @notice Proxy increaes `_staker_addr`'s veFPIS base / bias. Usually due to rewards on an app @param _staker_addr The target veFPIS staker address to act on """ # Make sure that the function isn't disabled, and also that the proxy is valid assert (self.proxyAddsEnabled), "Currently disabled" assert (msg.sender == self.current_proxy or self.historical_proxies[msg.sender]), "Proxy not whitelisted [admin level]" assert (msg.sender == self.staker_whitelisted_proxy[_staker_addr]), "Proxy not whitelisted [staker level]" # NOTE: IF YOU ACTUALLY WANT TO TRANSFER TOKENS, YOU CAN USE # _deposit_for() instead of below # Get the staker's locked position and proxy balance old_locked: LockedBalance = self.locked[_staker_addr] _proxy_balance: uint256 = self.user_proxy_balance[_staker_addr] # Validate some things assert old_locked.amount > 0, "No existing lock found" assert (_add_amt) > 0, "Amount must be non-zero" # Increase the proxy balance self.user_proxy_balance[_staker_addr] += _add_amt # Note original data supply_before: uint256 = self.supply # Get the staker's balance and the total supply new_locked: LockedBalance = old_locked # Will be incremented soon # Increase the supply self.supply += _add_amt # Add to an existing lock new_locked.amount += convert(_add_amt, int128) self.locked[_staker_addr] = new_locked # Checkpoint: self._checkpoint(_staker_addr, old_locked, new_locked, PROXY_ADD) # Events log ProxyAdd(_staker_addr, msg.sender, _add_amt) log Supply(supply_before, supply_before + _add_amt) @external @nonreentrant('proxy') def proxy_slash( _staker_addr: address, _slash_amt: uint256, ): """ @notice Proxy increaes `_staker_addr`'s veFPIS base / bias. Usually due to rewards on an app @param _staker_addr The target veFPIS staker address to act on """ # Make sure that the function isn't disabled, and also that the proxy is valid assert (self.proxyAddsEnabled), "Currently disabled" assert (msg.sender == self.current_proxy or self.historical_proxies[msg.sender]), "Proxy not whitelisted [admin level]" assert (msg.sender == self.staker_whitelisted_proxy[_staker_addr]), "Proxy not whitelisted [staker level]" # NOTE: IF YOU ACTUALLY WANT TO TRANSFER TOKENS, YOU CAN USE # _deposit_for() instead of below # Get the staker's locked position and proxy balance old_locked: LockedBalance = self.locked[_staker_addr] _proxy_balance: uint256 = self.user_proxy_balance[_staker_addr] # Validate some things assert old_locked.amount > 0, "No existing lock found" assert (_slash_amt) > 0, "Amount must be non-zero" # Decrease the proxy balance assert (self.user_proxy_balance[_staker_addr] >= _slash_amt), "Trying to slash too much" self.user_proxy_balance[_staker_addr] -= _slash_amt # Note original data supply_before: uint256 = self.supply # Get the staker's balance and the total supply new_locked: LockedBalance = old_locked # Will be decremented soon # Decrease the supply self.supply -= _slash_amt # Remove from an existing lock new_locked.amount -= convert(_slash_amt, int128) self.locked[_staker_addr] = new_locked # Checkpoint: self._checkpoint(_staker_addr, old_locked, new_locked, PROXY_SLASH) # Events log ProxyAdd(_staker_addr, msg.sender, _slash_amt) log Supply(supply_before, supply_before - _slash_amt) @external @nonreentrant('lock') def withdraw(): """ @notice Withdraw all tokens for `msg.sender` @dev Only possible if the lock has expired or the emergency unlock is active @dev Also need to make sure all debts to the proxy, if any, are paid off first """ # Get the staker's locked position _locked: LockedBalance = self.locked[msg.sender] # Validate some things assert ((block.timestamp >= _locked.end) or (self.emergencyUnlockActive)), "The lock didn't expire" assert (self.user_proxy_balance[msg.sender] == 0), "Outstanding FPIS in proxy" # Allow the withdrawal self._withdraw(msg.sender, msg.sender, _locked, _locked.amount, USER_WITHDRAW) @external @nonreentrant('proxy') def transfer_from_app(_staker_addr: address, _app_addr: address, _transfer_amt: int128): """ @notice Transfer tokens from a proxy-connected app to the veFPIS contract @dev Only possible for whitelisted proxies, both by the admin and by the staker @dev Only proxy and staker are checked, not the app, so make sure to do that at the proxy level @dev Make sure app does the approval to veFPIS first """ # Make sure that the function isn't disabled, and also that the proxy is valid assert (self.appTransferFromsEnabled), "Currently disabled" assert (msg.sender == self.current_proxy or self.historical_proxies[msg.sender]), "Proxy not whitelisted [admin level]" assert (msg.sender == self.staker_whitelisted_proxy[_staker_addr]), "Proxy not whitelisted [staker level]" # Get the staker's locked position _locked: LockedBalance = self.locked[_staker_addr] assert _locked.amount > 0, "No existing lock found" # Note the amount to be moved to the veFPIS contract _value: uint256 = convert(_transfer_amt, uint256) assert (self.user_proxy_balance[_staker_addr] >= _value), "Trying to transfer back too much" self.user_proxy_balance[_staker_addr] -= _value # Allow the transfer to the app. # This will not reduce the user's veFPIS balance assert ERC20(self.token).transferFrom(_app_addr, self, _value) # Checkpoint self._checkpoint(_staker_addr, _locked, _locked, TRANSFER_FROM_APP) log TransferFromApp(_app_addr, _staker_addr, _value) @external @nonreentrant('proxy') def transfer_to_app(_staker_addr: address, _app_addr: address, _transfer_amt: int128): """ @notice Transfer tokens for `_staker_addr` to a proxy-connected app directly, to be loaned or otherwise used @dev Only possible for whitelisted proxies, both by the admin and by the staker @dev Only proxy and staker are checked, not the app, so make sure to do that at the proxy level """ # Make sure that the function isn't disabled, and also that the proxy is valid assert (self.appTransferTosEnabled), "Currently disabled" assert (msg.sender == self.current_proxy or self.historical_proxies[msg.sender]), "Proxy not whitelisted [admin level]" assert (msg.sender == self.staker_whitelisted_proxy[_staker_addr]), "Proxy not whitelisted [staker level]" # Get the staker's locked position _locked: LockedBalance = self.locked[_staker_addr] _locked_amt: uint256 = convert(_locked.amount, uint256) # Make sure the position isn't expired (no outbound transfers after expiry) assert (block.timestamp < _locked.end), "No transfers after expiration" # Note the amount to be moved to the app _value: uint256 = convert(_transfer_amt, uint256) self.user_proxy_balance[_staker_addr] += _value # Make sure total user transfers do not surpass user locked balance assert (self.user_proxy_balance[_staker_addr] <= _locked_amt), "Amount exceeds locked balance" # Allow the transfer to the app. # This will not reduce the user's veFPIS balance assert ERC20(self.token).transfer(_app_addr, _value) # Checkpoint self._checkpoint(_staker_addr, _locked, _locked, TRANSFER_TO_APP) log TransferToApp(_staker_addr, _app_addr, _value) @internal @view def find_block_epoch(_block: uint256, max_epoch: uint256) -> uint256: """ @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 """ # Binary search _min: uint256 = 0 _max: uint256 = max_epoch for i in range(128): # Will be always enough for 128-bit numbers if _min >= _max: break _mid: uint256 = (_min + _max + 1) / 2 if self.point_history[_mid].blk <= _block: _min = _mid else: _max = _mid - 1 return _min @external @view def balanceOf(addr: address, _t: uint256 = block.timestamp) -> uint256: """ @notice Get the current voting power for `msg.sender` @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility @param addr User wallet address @param _t Epoch time to return voting power at @return User voting power """ _epoch: uint256 = self.user_point_epoch[addr] if _epoch == 0: return 0 else: # Just leave this alone. It is fine if it decays to 1 veFPIS = 1 bias # Otherwise it would be inconsistent with totalSupply and totalSupplyAt # _locked: LockedBalance = self.locked[addr] # if (block.timestamp >= _locked.end): return 0 last_point: Point = self.user_point_history[addr][_epoch] last_point.bias -= last_point.slope * convert(_t - last_point.ts, int128) if last_point.bias < 0: last_point.bias = 0 # ============================================================================== # -------------------------------- veCRV method -------------------------------- # weighted_supply: uint256 = convert(last_point.bias, uint256) # -------------------------------- veFPIS -------------------------------- # Mainly used to counter negative biases weighted_supply: uint256 = convert(last_point.bias, uint256) if weighted_supply < last_point.fpis_amt: weighted_supply = last_point.fpis_amt # ============================================================================== return weighted_supply @external @view def balanceOfAt(addr: address, _block: uint256) -> uint256: """ @notice Measure voting power of `addr` at block height `_block` @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime @param addr User's wallet address @param _block Block to calculate the voting power at @return Voting power """ # Copying and pasting totalSupply code because Vyper cannot pass by # reference yet assert _block <= block.number # Binary search _min: uint256 = 0 _max: uint256 = self.user_point_epoch[addr] for i in range(128): # Will be always enough for 128-bit numbers if _min >= _max: break _mid: uint256 = (_min + _max + 1) / 2 if self.user_point_history[addr][_mid].blk <= _block: _min = _mid else: _max = _mid - 1 upoint: Point = self.user_point_history[addr][_min] max_epoch: uint256 = self.epoch _epoch: uint256 = self.find_block_epoch(_block, max_epoch) point_0: Point = self.point_history[_epoch] d_block: uint256 = 0 d_t: uint256 = 0 if _epoch < max_epoch: point_1: Point = self.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 block_time: uint256 = point_0.ts if d_block != 0: block_time += d_t * (_block - point_0.blk) / d_block upoint.bias -= upoint.slope * convert(block_time - upoint.ts, int128) # ============================================================================== # -------------------------------- veCRV method -------------------------------- # if upoint.bias >= 0: # return convert(upoint.bias, uint256) # else: # return 0 # ----------------------------------- veFPIS ----------------------------------- if ((upoint.bias >= 0) or (upoint.fpis_amt >= 0)): return convert(upoint.bias, uint256) else: return 0 # ============================================================================== @internal @view def supply_at(point: Point, t: uint256) -> uint256: """ @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 """ last_point: Point = point t_i: uint256 = (last_point.ts / WEEK) * WEEK for i in range(255): t_i += WEEK d_slope: int128 = 0 if t_i > t: t_i = t else: d_slope = self.slope_changes[t_i] last_point.bias -= last_point.slope * convert(t_i - last_point.ts, int128) if t_i == t: break last_point.slope += d_slope last_point.ts = t_i if last_point.bias < 0: last_point.bias = 0 # ============================================================================== # ----------------------------------- veCRV ------------------------------------ # weighted_supply: uint256 = convert(last_point.bias, uint256) # ----------------------------------- veFPIS ----------------------------------- weighted_supply: uint256 = convert(last_point.bias, uint256) if weighted_supply < last_point.fpis_amt: weighted_supply = last_point.fpis_amt # ============================================================================== return weighted_supply @external @view def totalSupply(t: uint256 = block.timestamp) -> uint256: """ @notice Calculate total voting power @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility @return Total voting power """ _epoch: uint256 = self.epoch last_point: Point = self.point_history[_epoch] return self.supply_at(last_point, t) @external @view def totalSupplyAt(_block: uint256) -> uint256: """ @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` """ assert _block <= block.number _epoch: uint256 = self.epoch target_epoch: uint256 = self.find_block_epoch(_block, _epoch) point: Point = self.point_history[target_epoch] dt: uint256 = 0 if target_epoch < _epoch: point_next: Point = self.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 self.supply_at(point, point.ts + dt) @external @view def totalFPISSupply() -> uint256: """ @notice Calculate FPIS supply @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility @return Total FPIS supply """ return self.supply # Don't use ERC20(self.token).balanceOf(self) @external @view def totalFPISSupplyAt(_block: uint256) -> uint256: """ @notice Calculate total FPIS at some point in the past @param _block Block to calculate the total voting power at @return Total FPIS supply at `_block` """ assert _block <= block.number _epoch: uint256 = self.epoch target_epoch: uint256 = self.find_block_epoch(_block, _epoch) point: Point = self.point_history[target_epoch] return point.fpis_amt @external def toggleEmergencyUnlock(): """ @dev Used to allow early withdrawals of veFPIS back into FPIS, in case of an emergency """ assert msg.sender == self.admin # dev: admin only self.emergencyUnlockActive = not (self.emergencyUnlockActive) self._checkpoint(empty(address), empty(LockedBalance), empty(LockedBalance), 0) log EmergencyUnlockToggled(self.emergencyUnlockActive) @external def toggleAppIncreaseAmountFors(): """ @dev Toggles the ability for the proxy to directly deposit FPIS for a user, increasing their existing stake only """ assert msg.sender == self.admin # dev: admin only self.appIncreaseAmountForsEnabled = not (self.appIncreaseAmountForsEnabled) self._checkpoint(empty(address), empty(LockedBalance), empty(LockedBalance), 0) log AppIncreaseAmountForsToggled(self.appIncreaseAmountForsEnabled) @external def toggleTransferFromApp(): """ @dev Toggles the ability to receive FPIS from apps """ assert msg.sender == self.admin # dev: admin only self.appTransferFromsEnabled = not (self.appTransferFromsEnabled) self._checkpoint(empty(address), empty(LockedBalance), empty(LockedBalance), 0) log ProxyTransferFromsToggled(self.appTransferFromsEnabled) @external def toggleTransferToApp(): """ @dev Toggles the ability to send FPIS to apps """ assert msg.sender == self.admin # dev: admin only self.appTransferTosEnabled = not (self.appTransferTosEnabled) self._checkpoint(empty(address), empty(LockedBalance), empty(LockedBalance), 0) log ProxyTransferTosToggled(self.appTransferTosEnabled) @external def toggleProxyAdds(): """ @dev Toggles the ability for the proxy to add FPIS credit to user """ assert msg.sender == self.admin # dev: admin only self.proxyAddsEnabled = not (self.proxyAddsEnabled) self._checkpoint(empty(address), empty(LockedBalance), empty(LockedBalance), 0) log ProxyAddsToggled(self.proxyAddsEnabled) @external def toggleProxySlashes(): """ @dev Toggles the ability for the proxy to subtract FPIS from a user """ assert msg.sender == self.admin # dev: admin only self.proxySlashesEnabled = not (self.proxySlashesEnabled) self._checkpoint(empty(address), empty(LockedBalance), empty(LockedBalance), 0) log ProxySlashesToggled(self.proxySlashesEnabled) @external def adminSetProxy(_proxy: address): """ @dev Admin sets the lending proxy @param _proxy The lending proxy address """ assert msg.sender == self.admin, "Admin only" # dev: admin only self.current_proxy = _proxy self.historical_proxies[_proxy] = True log LendingProxySet(_proxy) @external def adminToggleHistoricalProxy(_proxy: address): """ @dev Admin can manipulate a historical proxy if needed (normally done automatically in adminSetProxy) @dev This is needed if the main current_proxy changes and and old proxy needs to pay back or liquidate a user @dev Or if there is something wrong with an older proxy @param _proxy The lending proxy address """ assert msg.sender == self.admin, "Admin only" # dev: admin only self.historical_proxies[_proxy] = not self.historical_proxies[_proxy] log HistoricalProxyToggled(_proxy, self.historical_proxies[_proxy]) @external def stakerSetProxy(_proxy: address): """ @dev Staker lets a particular address do activities on their behalf @dev Each staker can only have one proxy, to keep things / collateral / LTC calculations simple @param _proxy The address the staker will let withdraw/deposit for them """ # Do some checks assert (_proxy == empty(address) or self.current_proxy == _proxy), "Proxy not whitelisted [admin level]" assert (self.user_proxy_balance[msg.sender] == 0), "Outstanding FPIS in proxy" # Set the proxy self.staker_whitelisted_proxy[msg.sender] = _proxy log StakerProxySet(_proxy)
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"name":"NominateOwnership","inputs":[{"name":"admin","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"AcceptOwnership","inputs":[{"name":"admin","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"Deposit","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"payer_addr","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false},{"name":"locktime","type":"uint256","indexed":true},{"name":"type","type":"int128","indexed":false},{"name":"ts","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"Withdraw","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"to_addr","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false},{"name":"ts","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"Supply","inputs":[{"name":"prevSupply","type":"uint256","indexed":false},{"name":"supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"TransferToApp","inputs":[{"name":"staker_addr","type":"address","indexed":true},{"name":"app_addr","type":"address","indexed":true},{"name":"transfer_amt","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"TransferFromApp","inputs":[{"name":"app_addr","type":"address","indexed":true},{"name":"staker_addr","type":"address","indexed":true},{"name":"transfer_amt","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"ProxyAdd","inputs":[{"name":"staker_addr","type":"address","indexed":true},{"name":"proxy_addr","type":"address","indexed":true},{"name":"add_amt","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"ProxySlash","inputs":[{"name":"staker_addr","type":"address","indexed":true},{"name":"proxy_addr","type":"address","indexed":true},{"name":"slash_amt","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"SmartWalletCheckerComitted","inputs":[{"name":"future_smart_wallet_checker","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"SmartWalletCheckerApplied","inputs":[{"name":"smart_wallet_checker","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"EmergencyUnlockToggled","inputs":[{"name":"emergencyUnlockActive","type":"bool","indexed":false}],"anonymous":false,"type":"event"},{"name":"AppIncreaseAmountForsToggled","inputs":[{"name":"appIncreaseAmountForsEnabled","type":"bool","indexed":false}],"anonymous":false,"type":"event"},{"name":"ProxyTransferFromsToggled","inputs":[{"name":"appTransferFromsEnabled","type":"bool","indexed":false}],"anonymous":false,"type":"event"},{"name":"ProxyTransferTosToggled","inputs":[{"name":"appTransferTosEnabled","type":"bool","indexed":false}],"anonymous":false,"type":"event"},{"name":"ProxyAddsToggled","inputs":[{"name":"proxyAddsEnabled","type":"bool","indexed":false}],"anonymous":false,"type":"event"},{"name":"ProxySlashesToggled","inputs":[{"name":"proxySlashesEnabled","type":"bool","indexed":false}],"anonymous":false,"type":"event"},{"name":"LendingProxySet","inputs":[{"name":"proxy_address","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"HistoricalProxyToggled","inputs":[{"name":"proxy_address","type":"address","indexed":false},{"name":"enabled","type":"bool","indexed":false}],"anonymous":false,"type":"event"},{"name":"StakerProxySet","inputs":[{"name":"proxy_address","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"nominate_ownership","inputs":[{"name":"addr","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"accept_transfer_ownership","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"commit_smart_wallet_checker","inputs":[{"name":"addr","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"apply_smart_wallet_checker","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"recoverERC20","inputs":[{"name":"token_addr","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"get_last_user_slope","inputs":[{"name":"addr","type":"address"}],"outputs":[{"name":"","type":"int128"}]},{"stateMutability":"view","type":"function","name":"get_last_user_bias","inputs":[{"name":"addr","type":"address"}],"outputs":[{"name":"","type":"int128"}]},{"stateMutability":"view","type":"function","name":"get_last_user_point","inputs":[{"name":"addr","type":"address"}],"outputs":[{"name":"","type":"tuple","components":[{"name":"bias","type":"int128"},{"name":"slope","type":"int128"},{"name":"ts","type":"uint256"},{"name":"blk","type":"uint256"},{"name":"fpis_amt","type":"uint256"}]}]},{"stateMutability":"view","type":"function","name":"user_point_history__ts","inputs":[{"name":"_addr","type":"address"},{"name":"_idx","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_last_point","inputs":[],"outputs":[{"name":"","type":"tuple","components":[{"name":"bias","type":"int128"},{"name":"slope","type":"int128"},{"name":"ts","type":"uint256"},{"name":"blk","type":"uint256"},{"name":"fpis_amt","type":"uint256"}]}]},{"stateMutability":"view","type":"function","name":"locked__end","inputs":[{"name":"_addr","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"locked__amount","inputs":[{"name":"_addr","type":"address"}],"outputs":[{"name":"","type":"int128"}]},{"stateMutability":"view","type":"function","name":"curr_period_start","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"next_period_start","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"checkpoint","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"create_lock","inputs":[{"name":"_value","type":"uint256"},{"name":"_unlock_time","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"increase_amount","inputs":[{"name":"_value","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"increase_amount_for","inputs":[{"name":"_staker_addr","type":"address"},{"name":"_value","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"checkpoint_user","inputs":[{"name":"_staker_addr","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"increase_unlock_time","inputs":[{"name":"_unlock_time","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"proxy_add","inputs":[{"name":"_staker_addr","type":"address"},{"name":"_add_amt","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"proxy_slash","inputs":[{"name":"_staker_addr","type":"address"},{"name":"_slash_amt","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"withdraw","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"transfer_from_app","inputs":[{"name":"_staker_addr","type":"address"},{"name":"_app_addr","type":"address"},{"name":"_transfer_amt","type":"int128"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"transfer_to_app","inputs":[{"name":"_staker_addr","type":"address"},{"name":"_app_addr","type":"address"},{"name":"_transfer_amt","type":"int128"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"balanceOf","inputs":[{"name":"addr","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"balanceOf","inputs":[{"name":"addr","type":"address"},{"name":"_t","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"balanceOfAt","inputs":[{"name":"addr","type":"address"},{"name":"_block","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"totalSupply","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"totalSupply","inputs":[{"name":"t","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"totalSupplyAt","inputs":[{"name":"_block","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"totalFPISSupply","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"totalFPISSupplyAt","inputs":[{"name":"_block","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"toggleEmergencyUnlock","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"toggleAppIncreaseAmountFors","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"toggleTransferFromApp","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"toggleTransferToApp","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"toggleProxyAdds","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"toggleProxySlashes","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"adminSetProxy","inputs":[{"name":"_proxy","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"adminToggleHistoricalProxy","inputs":[{"name":"_proxy","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"stakerSetProxy","inputs":[{"name":"_proxy","type":"address"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"token","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"supply","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"locked","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"tuple","components":[{"name":"amount","type":"int128"},{"name":"end","type":"uint256"}]}]},{"stateMutability":"view","type":"function","name":"epoch","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"point_history","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"tuple","components":[{"name":"bias","type":"int128"},{"name":"slope","type":"int128"},{"name":"ts","type":"uint256"},{"name":"blk","type":"uint256"},{"name":"fpis_amt","type":"uint256"}]}]},{"stateMutability":"view","type":"function","name":"user_point_history","inputs":[{"name":"arg0","type":"address"},{"name":"arg1","type":"uint256"}],"outputs":[{"name":"","type":"tuple","components":[{"name":"bias","type":"int128"},{"name":"slope","type":"int128"},{"name":"ts","type":"uint256"},{"name":"blk","type":"uint256"},{"name":"fpis_amt","type":"uint256"}]}]},{"stateMutability":"view","type":"function","name":"user_point_epoch","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"slope_changes","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"int128"}]},{"stateMutability":"view","type":"function","name":"appIncreaseAmountForsEnabled","inputs":[],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"appTransferFromsEnabled","inputs":[],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"appTransferTosEnabled","inputs":[],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"proxyAddsEnabled","inputs":[],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"proxySlashesEnabled","inputs":[],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"emergencyUnlockActive","inputs":[],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"current_proxy","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"historical_proxies","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"staker_whitelisted_proxy","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"user_proxy_balance","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"name","inputs":[],"outputs":[{"name":"","type":"string"}]},{"stateMutability":"view","type":"function","name":"symbol","inputs":[],"outputs":[{"name":"","type":"string"}]},{"stateMutability":"view","type":"function","name":"version","inputs":[],"outputs":[{"name":"","type":"string"}]},{"stateMutability":"view","type":"function","name":"decimals","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_smart_wallet_checker","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"smart_wallet_checker","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"admin","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"future_admin","inputs":[],"outputs":[{"name":"","type":"address"}]}]
Contract Creation Code
34614c675773c2544a32872a91f4a553b404c6950e89de901fdb604052336c064f964e68233a80000000001d5560405160025543600955426008556000600a5560006c064f964e68233a80000000000a5560006c064f964e68233a80000000000b5560006c064f964e68233a80000000000c5560006c064f964e68233a80000000000d5560405163313ce567608052602060806004609c845afa6100a8573d600060003e3d6000fd5b60203d10614c6757608090505160605260ff60605111614c67576060516c064f964e68233a80000000001a5560066080527f766546504953000000000000000000000000000000000000000000000000000060a05260808051806c064f964e68233a800000000013556020820180516c064f964e68233a8000000000145550505060066080527f766546504953000000000000000000000000000000000000000000000000000060a05260808051806c064f964e68233a800000000016556020820180516c064f964e68233a80000000001755505050600c6080527f7665465049535f312e302e30000000000000000000000000000000000000000060a05260808051806c064f964e68233a800000000018556020820180516c064f964e68233a80000000001955505050614a816101e561000039614a81610000f36003361161000c576137b8565b60003560e01c34614a6f5763c35ce48d811861008d5760243610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000001d543318614a6f576040516c064f964e68233a80000000001e557fd663c3b63b25bf73d75a842070d8f5c8194612f2f6483a9e5a900d9f49af63f060405160605260206060a1005b63e5ea47b8811861010c5760043610614a6f576c064f964e68233a80000000001e546040526040513318614a6f576040516c064f964e68233a80000000001d5560006c064f964e68233a80000000001e557f7f877120c72766f4eac00144c86c9e57ed52f31bac01ef5c4c223c4768a8767360405160605260206060a1005b6357f901e2811861018e5760243610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000001d543318614a6f576040516c064f964e68233a80000000001b557f25ae06665d3dcefda7253511ee45f88500aab9b3ea061845a747baad51121c1e6c064f964e68233a80000000001b5460605260206060a1005b638e5b490f811861020e5760043610614a6f576c064f964e68233a80000000001d543318614a6f576c064f964e68233a80000000001b546c064f964e68233a80000000001c557f5000294582547ee919f4908d785ff270cd38f6cc318e730199ae00c65548f2ee6c064f964e68233a80000000001c5460405260206040a1005b638980f11f81186102aa5760443610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000001d543318614a6f5760025460405114614a6f5760405163a9059cbb6060526c064f964e68233a80000000001d5460805260243560a052602060606044607c6000855af161028e573d600060003e3d6000fd5b60203d10614a6f576060518060011c614a6f5760c05260c05050005b637c74a174811861032c5760243610614a6f576004358060a01c614a6f576040526c064f964e68233a8000000000076040516020526000526040600020546060526c064f964e68233a80000000000660405160205260005260406000206005606051633b9ac9ff8111614a6f5702810190506001810190505460805260206080f35b631e45529b81186103a85760243610614a6f576004358060a01c614a6f576040526c064f964e68233a8000000000076040516020526000526040600020546060526c064f964e68233a80000000000660405160205260005260406000206005606051633b9ac9ff8111614a6f5702810190505460805260206080f35b63a7afdcae81186104475760243610614a6f576004358060a01c614a6f576040526c064f964e68233a8000000000076040516020526000526040600020546060526c064f964e68233a80000000000660405160205260005260406000206005606051633b9ac9ff8111614a6f5702810190508054608052600181015460a052600281015460c052600381015460e0526004810154610100525060a06080f35b63da020a1881186104a95760443610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000000660405160205260005260406000206005602435633b9ac9ff8111614a6f5702810190506002810190505460605260206060f35b634181ac2781186105055760043610614a6f5760056005546c01431e0fae6d7217ca9fffffff8111614a6f5702600601805460405260018101546060526002810154608052600381015460a052600481015460c0525060a06040f35b63adc6358981186105465760243610614a6f576004358060a01c614a6f57604052600460405160205260005260406000206001810190505460605260206060f35b63570a30b781186105815760243610614a6f576004358060a01c614a6f57604052600460405160205260005260406000205460605260206060f35b63534b730e81186105ba5760043610614a6f574262093a808104905062093a8081028162093a80820418614a6f57905060405260206040f35b6308a2bc3b81186106055760043610614a6f574262093a808104905062093a8081028162093a80820418614a6f5790508062093a800162093a808110614a6f57905060405260206040f35b63c2c4c5c181186106285760043610614a6f5760c0366040376106266138b6565b005b6365fc387381186108c75760443610614a6f57600054600214614a6f576002600055336040526106566137be565b60243562093a808104905062093a8081028162093a80820418614a6f57905061066052600433602052600052604060002080546106805260018101546106a052506004356107045760116106c0527f56616c7565206d757374206265203e20300000000000000000000000000000006106e0526106c0506106c051806106e001601f826000031636823750506308c379a06106805260206106a052601f19601f6106c051011660440161069cfd5b61068051156107735760196106c0527f5769746864726177206f6c6420746f6b656e73206669727374000000000000006106e0526106c0506106c051806106e001601f826000031636823750506308c379a06106805260206106a052601f19601f6106c051011660440161069cfd5b4261066051116108085760266106c0527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e20746865206106e0527f6675747572650000000000000000000000000000000000000000000000000000610700526106c0506106c051806106e001601f826000031636823750506308c379a06106805260206106a052601f19601f6106c051011660440161069cfd5b42630784ce008101818110614a6f57905061066051111561088957601e6106c0527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006106e0526106c0506106c051806106e001601f826000031636823750506308c379a06106805260206106a052601f19601f6106c051011660440161069cfd5b3361048052336104a0526004356104c052610660516104e05261068051610500526106a051610520526000610540526108c0614166565b6003600055005b634957677c81186109095760243610614a6f57600054600214614a6f576002600055336106605233610680526004356106a052610902614325565b6003600055005b63e864837681186109d65760443610614a6f576004358060a01c614a6f5761076052600054600214614a6f5760026000556c064f964e68233a800000000009546109b3576012610780527f43757272656e746c792064697361626c656400000000000000000000000000006107a0526107805061078051806107a001601f826000031636823750506308c379a061074052602061076052601f19601f61078051011660440161075cfd5b610760516106605233610680526024356106a0526109cf614325565b6003600055005b637de680618118610ad65760243610614a6f576004358060a01c614a6f5761066052600054600214614a6f576002600055600461066051602052600052604060002080546106805260018101546106a052506001610680511215610a9a5760166106c0527f4e6f206578697374696e67206c6f636b20666f756e64000000000000000000006106e0526106c0506106c051806106e001601f826000031636823750506308c379a06106805260206106a052601f19601f6106c051011660440161069cfd5b6106605161048052610660516104a0526040366104c03761068051610500526106a05161052052600861054052610acf614166565b6003600055005b63eff7a6128118610d585760243610614a6f57600054600214614a6f57600260005533604052610b046137be565b60043360205260005260406000208054610660526001810154610680525060043562093a808104905062093a8081028162093a80820418614a6f5790506106a052426106805111610bb557600c6106c0527f4c6f636b206578706972656400000000000000000000000000000000000000006106e0526106c0506106c051806106e001601f826000031636823750506308c379a06106805260206106a052601f19601f6106c051011660440161069cfd5b6001610660511215610c275760116106c0527f4e6f7468696e67206973206c6f636b65640000000000000000000000000000006106e0526106c0506106c051806106e001601f826000031636823750506308c379a06106805260206106a052601f19601f6106c051011660440161069cfd5b610680516106a05111610c9a57601f6106c0527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006106e0526106c0506106c051806106e001601f826000031636823750506308c379a06106805260206106a052601f19601f6106c051011660440161069cfd5b42630784ce008101818110614a6f5790506106a0511115610d1b57601e6106c0527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006106e0526106c0506106c051806106e001601f826000031636823750506308c379a06106805260206106a052601f19601f6106c051011660440161069cfd5b3361048052336104a05260006104c0526106a0516104e05261066051610500526106805161052052600261054052610d51614166565b6003600055005b6361c44a7381186111f35760443610614a6f576004358060a01c614a6f5761048052600154600214614a6f5760026001556c064f964e68233a80000000000c54610e025760126104a0527f43757272656e746c792064697361626c656400000000000000000000000000006104c0526104a0506104a051806104c001601f826000031636823750506308c379a061046052602061048052601f19601f6104a051011660440161047cfd5b6c064f964e68233a80000000000f543318610e1e576001610e3a565b6c064f964e68233a800000000010336020526000526040600020545b610ec95760236104a0527f50726f7879206e6f742077686974656c6973746564205b61646d696e206c65766104c0527f656c5d00000000000000000000000000000000000000000000000000000000006104e0526104a0506104a051806104c001601f826000031636823750506308c379a061046052602061048052601f19601f6104a051011660440161047cfd5b6c064f964e68233a80000000001161048051602052600052604060002054331815610f795760246104a0527f50726f7879206e6f742077686974656c6973746564205b7374616b6572206c656104c0527f76656c5d000000000000000000000000000000000000000000000000000000006104e0526104a0506104a051806104c001601f826000031636823750506308c379a061046052602061048052601f19601f6104a051011660440161047cfd5b600461048051602052600052604060002080546104a05260018101546104c052506c064f964e68233a800000000012610480516020526000526040600020546104e05260016104a051121561102e576016610500527f4e6f206578697374696e67206c6f636b20666f756e64000000000000000000006105205261050050610500518061052001601f826000031636823750506308c379a06104c05260206104e052601f19601f6105005101166044016104dcfd5b60243561109b576017610500527f416d6f756e74206d757374206265206e6f6e2d7a65726f0000000000000000006105205261050050610500518061052001601f826000031636823750506308c379a06104c05260206104e052601f19601f6105005101166044016104dcfd5b6c064f964e68233a8000000000126104805160205260005260406000208054602435808201828110614a6f5790509050815550600354610500526104a051610520526104c05161054052600354602435808201828110614a6f57905090506003556105205160243580607f1c614a6f5780820180600f0b8118614a6f579050905061052052600461048051602052600052604060002061052051815561054051600182015550610480516040526104a0516060526104c0516080526105205160a0526105405160c052600660e0526111716138b6565b33610480517f5ac729958bdffbbceb1d50f714f86dafb13969e2023c00390189fbec3c83fc26602435610560526020610560a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c610500516105605261050051602435808201828110614a6f5790509050610580526040610560a16003600155005b630ce0853f811861171b5760443610614a6f576004358060a01c614a6f5761048052600154600214614a6f5760026001556c064f964e68233a80000000000c5461129d5760126104a0527f43757272656e746c792064697361626c656400000000000000000000000000006104c0526104a0506104a051806104c001601f826000031636823750506308c379a061046052602061048052601f19601f6104a051011660440161047cfd5b6c064f964e68233a80000000000f5433186112b95760016112d5565b6c064f964e68233a800000000010336020526000526040600020545b6113645760236104a0527f50726f7879206e6f742077686974656c6973746564205b61646d696e206c65766104c0527f656c5d00000000000000000000000000000000000000000000000000000000006104e0526104a0506104a051806104c001601f826000031636823750506308c379a061046052602061048052601f19601f6104a051011660440161047cfd5b6c064f964e68233a800000000011610480516020526000526040600020543318156114145760246104a0527f50726f7879206e6f742077686974656c6973746564205b7374616b6572206c656104c0527f76656c5d000000000000000000000000000000000000000000000000000000006104e0526104a0506104a051806104c001601f826000031636823750506308c379a061046052602061048052601f19601f6104a051011660440161047cfd5b600461048051602052600052604060002080546104a05260018101546104c052506c064f964e68233a800000000012610480516020526000526040600020546104e05260016104a05112156114c9576016610500527f4e6f206578697374696e67206c6f636b20666f756e64000000000000000000006105205261050050610500518061052001601f826000031636823750506308c379a06104c05260206104e052601f19601f6105005101166044016104dcfd5b602435611536576017610500527f416d6f756e74206d757374206265206e6f6e2d7a65726f0000000000000000006105205261050050610500518061052001601f826000031636823750506308c379a06104c05260206104e052601f19601f6105005101166044016104dcfd5b6024356c064f964e68233a8000000000126104805160205260005260406000205410156115c3576018610500527f547279696e6720746f20736c61736820746f6f206d75636800000000000000006105205261050050610500518061052001601f826000031636823750506308c379a06104c05260206104e052601f19601f6105005101166044016104dcfd5b6c064f964e68233a8000000000126104805160205260005260406000208054602435808203828111614a6f5790509050815550600354610500526104a051610520526104c05161054052600354602435808203828111614a6f57905090506003556105205160243580607f1c614a6f5780820380600f0b8118614a6f579050905061052052600461048051602052600052604060002061052051815561054051600182015550610480516040526104a0516060526104c0516080526105205160a0526105405160c052600760e0526116996138b6565b33610480517f5ac729958bdffbbceb1d50f714f86dafb13969e2023c00390189fbec3c83fc26602435610560526020610560a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c610500516105605261050051602435808203828111614a6f5790509050610580526040610560a16003600155005b633ccfd60b81186118a45760043610614a6f57600054600214614a6f576002600055600433602052600052604060002080546106c05260018101546106e052506106e05142101561177a576c064f964e68233a80000000000e5461177d565b60015b6117e7576016610700527f546865206c6f636b206469646e277420657870697265000000000000000000006107205261070050610700518061072001601f826000031636823750506308c379a06106c05260206106e052601f19601f6107005101166044016106dcfd5b6c064f964e68233a800000000012336020526000526040600020541561186d576019610700527f4f75747374616e64696e67204650495320696e2070726f7879000000000000006107205261070050610700518061072001601f826000031636823750506308c379a06106c05260206106e052601f19601f6107005101166044016106dcfd5b3361048052336104a0526106c0516104c0526106e0516104e0526106c0516105005260036105205261189d61455b565b6003600055005b63e081eec98118611d1a5760643610614a6f576004358060a01c614a6f57610480526024358060a01c614a6f576104a05260443580600f0b8118614a6f576104c052600154600214614a6f5760026001556c064f964e68233a80000000000a5461196e5760126104e0527f43757272656e746c792064697361626c65640000000000000000000000000000610500526104e0506104e0518061050001601f826000031636823750506308c379a06104a05260206104c052601f19601f6104e05101166044016104bcfd5b6c064f964e68233a80000000000f54331861198a5760016119a6565b6c064f964e68233a800000000010336020526000526040600020545b611a355760236104e0527f50726f7879206e6f742077686974656c6973746564205b61646d696e206c6576610500527f656c5d0000000000000000000000000000000000000000000000000000000000610520526104e0506104e0518061050001601f826000031636823750506308c379a06104a05260206104c052601f19601f6104e05101166044016104bcfd5b6c064f964e68233a80000000001161048051602052600052604060002054331815611ae55760246104e0527f50726f7879206e6f742077686974656c6973746564205b7374616b6572206c65610500527f76656c5d00000000000000000000000000000000000000000000000000000000610520526104e0506104e0518061050001601f826000031636823750506308c379a06104a05260206104c052601f19601f6104e05101166044016104bcfd5b600461048051602052600052604060002080546104e0526001810154610500525060016104e0511215611b78576016610520527f4e6f206578697374696e67206c6f636b20666f756e64000000000000000000006105405261052050610520518061054001601f826000031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b6104c05160008112614a6f5761052052610520516c064f964e68233a800000000012610480516020526000526040600020541015611c16576020610540527f547279696e6720746f207472616e73666572206261636b20746f6f206d7563686105605261054050610540518061056001601f826000031636823750506308c379a061050052602061052052601f19601f61054051011660440161051cfd5b6c064f964e68233a800000000012610480516020526000526040600020805461052051808203828111614a6f57905090508155506002546323b872dd610540526104a051610560523061058052610520516105a0526020610540606461055c6000855af1611c89573d600060003e3d6000fd5b60203d10614a6f57610540518060011c614a6f576105c0526105c090505115614a6f57610480516040526104e051606052610500516080526104e05160a0526105005160c052600460e052611cdc6138b6565b610480516104a0517fbd02ce585321c0e9e7b7c479d640b5e41c559c615f32449f741727c6162f4ac861052051610540526020610540a36003600155005b632bcbc3ef81186121995760643610614a6f576004358060a01c614a6f57610480526024358060a01c614a6f576104a05260443580600f0b8118614a6f576104c052600154600214614a6f5760026001556c064f964e68233a80000000000b54611de45760126104e0527f43757272656e746c792064697361626c65640000000000000000000000000000610500526104e0506104e0518061050001601f826000031636823750506308c379a06104a05260206104c052601f19601f6104e05101166044016104bcfd5b6c064f964e68233a80000000000f543318611e00576001611e1c565b6c064f964e68233a800000000010336020526000526040600020545b611eab5760236104e0527f50726f7879206e6f742077686974656c6973746564205b61646d696e206c6576610500527f656c5d0000000000000000000000000000000000000000000000000000000000610520526104e0506104e0518061050001601f826000031636823750506308c379a06104a05260206104c052601f19601f6104e05101166044016104bcfd5b6c064f964e68233a80000000001161048051602052600052604060002054331815611f5b5760246104e0527f50726f7879206e6f742077686974656c6973746564205b7374616b6572206c65610500527f76656c5d00000000000000000000000000000000000000000000000000000000610520526104e0506104e0518061050001601f826000031636823750506308c379a06104a05260206104c052601f19601f6104e05101166044016104bcfd5b600461048051602052600052604060002080546104e052600181015461050052506104e05160008112614a6f5761052052610500514210611ffc57601d610540527f4e6f207472616e73666572732061667465722065787069726174696f6e0000006105605261054050610540518061056001601f826000031636823750506308c379a061050052602061052052601f19601f61054051011660440161051cfd5b6104c05160008112614a6f57610540526c064f964e68233a800000000012610480516020526000526040600020805461054051808201828110614a6f5790509050815550610520516c064f964e68233a8000000000126104805160205260005260406000205411156120ce57601d610560527f416d6f756e742065786365656473206c6f636b65642062616c616e63650000006105805261056050610560518061058001601f826000031636823750506308c379a061052052602061054052601f19601f61056051011660440161053cfd5b60025463a9059cbb610560526104a05161058052610540516105a0526020610560604461057c6000855af1612108573d600060003e3d6000fd5b60203d10614a6f57610560518060011c614a6f576105c0526105c090505115614a6f57610480516040526104e051606052610500516080526104e05160a0526105005160c052600560e05261215b6138b6565b6104a051610480517f9b4385b7a76ef579e481bdac2c47bfd58d1bb8635d3898165499b2326f1f0f8a61054051610560526020610560a36003600155005b6370a0823181186121b55760243610614a6f57426060526121ce565b62fdd58e81186123125760443610614a6f576024356060525b6004358060a01c614a6f576040526c064f964e68233a80000000000760405160205260005260406000205460805260805161221557600060a052602060a061231056612310565b6c064f964e68233a80000000000660405160205260005260406000206005608051633b9ac9ff8111614a6f570281019050805460a052600181015460c052600281015460e0526003810154610100526004810154610120525060a05160c05160605160e051808203828111614a6f579050905080607f1c614a6f5780820280600f0b8118614a6f579050905080820380600f0b8118614a6f579050905060a0527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60a051136122e457600060a0525b60a05160008112614a6f57610140526101205161014051101561230a5761012051610140525b60206101405bf35b634ee2cd7e81186126c05760443610614a6f576004358060a01c614a6f57610100524360243511614a6f576000610120526c064f964e68233a800000000007610100516020526000526040600020546101405260006080905b806101605261014051610120511061238257612420565b6101205161014051808201828110614a6f579050905060018101818110614a6f5790508060011c9050610180526024356c064f964e68233a800000000006610100516020526000526040600020600561018051633b9ac9ff8111614a6f57028101905060038101905054111561240c576101805160018103818111614a6f57905061014052612415565b61018051610120525b60010181811861236b575b50506c064f964e68233a800000000006610100516020526000526040600020600561012051633b9ac9ff8111614a6f57028101905080546101605260018101546101805260028101546101a05260038101546101c05260048101546101e05250600554610200526024356040526102005160605261249f610240614825565b61024051610220526005610220516c01431e0fae6d7217ca9fffffff8111614a6f570260060180546102405260018101546102605260028101546102805260038101546102a05260048101546102c052506040366102e03761020051610220511061253757436102a051808203828111614a6f57905090506102e0524261028051808203828111614a6f5790509050610300526125c2565b60056102205160018101818110614a6f5790506c01431e0fae6d7217ca9fffffff8111614a6f570260060180546103205260018101546103405260028101546103605260038101546103805260048101546103a05250610380516102a051808203828111614a6f57905090506102e0526103605161028051808203828111614a6f5790509050610300525b61028051610320526102e051156126285761032051610300516024356102a051808203828111614a6f5790509050808202811583838304141715614a6f57905090506102e0518015614a6f5780820490509050808201828110614a6f5790509050610320525b6101605161018051610320516101a051808203828111614a6f579050905080607f1c614a6f5780820280600f0b8118614a6f579050905080820380600f0b8118614a6f579050905061016052600061016051121561268d5760006101e0511015612690565b60015b6126a85760006103405260206103406126be566126be565b6101605160008112614a6f576103405260206103405bf35b6318160ddd81186126dd5760043610614a6f5742610200526126f8565b63bd85b03981186127845760243610614a6f57600435610200525b600554610220526005610220516c01431e0fae6d7217ca9fffffff8111614a6f570260060180546102405260018101546102605260028101546102805260038101546102a05260048101546102c0525060206102405160405261026051606052610280516080526102a05160a0526102c05160c0526102005160e05261277f6102e06148d5565b6102e0f35b63981b24d081186129aa5760243610614a6f574360043511614a6f5760055461020052600435604052610200516060526127bf610240614825565b61024051610220526005610220516c01431e0fae6d7217ca9fffffff8111614a6f570260060180546102405260018101546102605260028101546102805260038101546102a05260048101546102c0525060006102e05261020051610220511061289257436102a0511461295c576004356102a051808203828111614a6f57905090504261028051808203828111614a6f5790509050808202811583838304141715614a6f5790509050436102a051808203828111614a6f57905090508015614a6f57808204905090506102e05261295c565b60056102205160018101818110614a6f5790506c01431e0fae6d7217ca9fffffff8111614a6f570260060180546103005260018101546103205260028101546103405260038101546103605260048101546103805250610360516102a0511461295c576004356102a051808203828111614a6f57905090506103405161028051808203828111614a6f5790509050808202811583838304141715614a6f5790509050610360516102a051808203828111614a6f57905090508015614a6f57808204905090506102e0525b60206102405160405261026051606052610280516080526102a05160a0526102c05160c052610280516102e051808201828110614a6f579050905060e0526129a56103006148d5565b610300f35b6347c7341e81186129c95760043610614a6f5760035460405260206040f35b630f4174a08118612a5c5760243610614a6f574360043511614a6f576005546101005260043560405261010051606052612a04610140614825565b61014051610120526005610120516c01431e0fae6d7217ca9fffffff8111614a6f570260060180546101405260018101546101605260028101546101805260038101546101a05260048101546101c0525060206101c0f35b6388c2b3e38118612aed5760043610614a6f576c064f964e68233a80000000001d543318614a6f576c064f964e68233a80000000000e54156c064f964e68233a80000000000e5560c036604037612ab16138b6565b7feab47e2228a51fa30e80a103a8e0105cb452653bb433513d6bf11e3e3f3637a36c064f964e68233a80000000000e54610480526020610480a1005b6316f616728118612b7e5760043610614a6f576c064f964e68233a80000000001d543318614a6f576c064f964e68233a80000000000954156c064f964e68233a8000000000095560c036604037612b426138b6565b7fdf5e6b6b37885e5046023bc28abaf4fa317db98e6c992dbba3830fd69f0f03d46c064f964e68233a80000000000954610480526020610480a1005b630b33ac488118612c0f5760043610614a6f576c064f964e68233a80000000001d543318614a6f576c064f964e68233a80000000000a54156c064f964e68233a80000000000a5560c036604037612bd36138b6565b7f924855749e6db89374eeb6d4f88b5c3f2c3f4efff48671af2f5ebab4a558faf66c064f964e68233a80000000000a54610480526020610480a1005b63e8ff7e828118612ca05760043610614a6f576c064f964e68233a80000000001d543318614a6f576c064f964e68233a80000000000b54156c064f964e68233a80000000000b5560c036604037612c646138b6565b7f2e0793e6a4f1baa7980928be0706d6246f765c4c1038e17ef46dd004504b65fa6c064f964e68233a80000000000b54610480526020610480a1005b63172cb9998118612d315760043610614a6f576c064f964e68233a80000000001d543318614a6f576c064f964e68233a80000000000c54156c064f964e68233a80000000000c5560c036604037612cf56138b6565b7f0e9338cb371255221e6df7c319bbd0290c0a544046aaf2d21b42ff796e6f71746c064f964e68233a80000000000c54610480526020610480a1005b630929f36f8118612dc25760043610614a6f576c064f964e68233a80000000001d543318614a6f576c064f964e68233a80000000000d54156c064f964e68233a80000000000d5560c036604037612d866138b6565b7f3f6a71816fba143945ad3184a7c46790c48e516749eb3cc736342f5bb3eb88cb6c064f964e68233a80000000000d54610480526020610480a1005b63bacec9678118612eb55760243610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000001d54331815612e5657600a6060527f41646d696e206f6e6c790000000000000000000000000000000000000000000060805260605060605180608001601f826000031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b6040516c064f964e68233a80000000000f5560016c064f964e68233a8000000000106040516020526000526040600020557f3c3597bbc034da275532ab551a8916a9bade58914700b6aa1ab96f16243bafaa60405160605260206060a1005b63417f25c98118612fd25760243610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000001d54331815612f4957600a6060527f41646d696e206f6e6c790000000000000000000000000000000000000000000060805260605060605180608001601f826000031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b6c064f964e68233a800000000010604051602052600052604060002054156c064f964e68233a8000000000106040516020526000526040600020557f94fd3c4f99e5feb7efd85143b048ed68169886a015308a163bfdc9b36a8188596040516060526c064f964e68233a80000000001060405160205260005260406000205460805260406060a1005b634d857d0c81186131645760243610614a6f576004358060a01c614a6f57604052604051613001576001613016565b6040516c064f964e68233a80000000000f5418155b61309b5760236060527f50726f7879206e6f742077686974656c6973746564205b61646d696e206c65766080527f656c5d000000000000000000000000000000000000000000000000000000000060a05260605060605180608001601f826000031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b6c064f964e68233a80000000001233602052600052604060002054156131185760196060527f4f75747374616e64696e67204650495320696e2070726f78790000000000000060805260605060605180608001601f826000031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b6040516c064f964e68233a800000000011336020526000526040600020557f0c5eabcbebbb87a106d2bdf51ee002efdd0f1b547dae5f9d6d0e28b15af217db60405160605260206060a1005b63fc0c546a81186131835760043610614a6f5760025460405260206040f35b63047fc9aa81186131a25760043610614a6f5760035460405260206040f35b63cbf9fe5f81186131e75760243610614a6f576004358060a01c614a6f5760405260046040516020526000526040600020805460605260018101546080525060406060f35b63900cf0cf81186132065760043610614a6f5760055460405260206040f35b63d1febfb981186132625760243610614a6f5760056004356c01431e0fae6d7217ca9fffffff8111614a6f5702600601805460405260018101546060526002810154608052600381015460a052600481015460c0525060a06040f35b6328d09d4781186132e05760443610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000000660405160205260005260406000206005602435633b9ac9ff8111614a6f57028101905080546060526001810154608052600281015460a052600381015460c052600481015460e0525060a06060f35b63010ae75781186133275760243610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000000760405160205260005260406000205460605260206060f35b637119748481186133605760243610614a6f576c064f964e68233a80000000000860043560205260005260406000205460405260206040f35b63702254a1811861338b5760043610614a6f576c064f964e68233a8000000000095460405260206040f35b63811d35ba81186133b65760043610614a6f576c064f964e68233a80000000000a5460405260206040f35b63a61f15c481186133e15760043610614a6f576c064f964e68233a80000000000b5460405260206040f35b6395957b57811861340c5760043610614a6f576c064f964e68233a80000000000c5460405260206040f35b632e67535d81186134375760043610614a6f576c064f964e68233a80000000000d5460405260206040f35b63f894648581186134625760043610614a6f576c064f964e68233a80000000000e5460405260206040f35b630a5de864811861348d5760043610614a6f576c064f964e68233a80000000000f5460405260206040f35b63d5a7505081186134d45760243610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000001060405160205260005260406000205460605260206060f35b638d94781a811861351b5760243610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000001160405160205260005260406000205460605260206060f35b63312afb0381186135625760243610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000001260405160205260005260406000205460605260206060f35b6306fdde0381186135ff5760043610614a6f57602080604052806040016c064f964e68233a8000000000135480825260208201600082601f0160051c60028111614a6f5780156135d157905b806c064f964e68233a80000000001401548160051b8401526001018181186135ae575b505050508051806020830101601f82600003163682375050601f19601f825160200101169050810190506040f35b6395d89b41811861366f5760043610614a6f57602080604052806040016c064f964e68233a80000000001654808252602082016c064f964e68233a80000000001754815250508051806020830101601f82600003163682375050601f19601f825160200101169050810190506040f35b6354fd4d5081186136df5760043610614a6f57602080604052806040016c064f964e68233a80000000001854808252602082016c064f964e68233a80000000001954815250508051806020830101601f82600003163682375050601f19601f825160200101169050810190506040f35b63313ce567811861370a5760043610614a6f576c064f964e68233a80000000001a5460405260206040f35b638ff36fd181186137355760043610614a6f576c064f964e68233a80000000001b5460405260206040f35b637175d4f781186137605760043610614a6f576c064f964e68233a80000000001c5460405260206040f35b63f851a440811861378b5760043610614a6f576c064f964e68233a80000000001d5460405260206040f35b6317f7182a81186137b65760043610614a6f576c064f964e68233a80000000001e5460405260206040f35b505b60006000fd5b32604051146138b4576c064f964e68233a80000000001c54606052606051156138335760605163c23697a860805260405160a052602060806024609c6000855af161380e573d600060003e3d6000fd5b60203d10614a6f576080518060011c614a6f5760c05260c090505115613833576138b4565b60256080527f536d61727420636f6e7472616374206465706f7369746f7273206e6f7420616c60a0527f6c6f77656400000000000000000000000000000000000000000000000000000060c0526080506080518060a001601f826000031636823750506308c379a06040526020606052601f19601f6080510116604401605cfd5b565b61018036610100376005546102805260405115613a3a5742608051116138dd5760006138e5565b600160605112155b15613952576060516003810280600f0b8118614a6f579050630784ce0081059050610120526060516101205160805142808203828111614a6f579050905080607f1c614a6f5780820280600f0b8118614a6f579050905080820180600f0b8118614a6f5790509050610100525b4260c0511161396257600061396a565b600160a05112155b156139d75760a0516003810280600f0b8118614a6f579050630784ce00810590506101c05260a0516101c05160c05142808203828111614a6f579050905080607f1c614a6f5780820280600f0b8118614a6f579050905080820180600f0b8118614a6f57905090506101a0525b6c064f964e68233a8000000000086080516020526000526040600020546102405260c05115613a3a5760805160c05118613a18576102405161026052613a3a565b6c064f964e68233a80000000000860c051602052600052604060002054610260525b6040366102a037426102e05243610300526000610320526102805115613aa4576005610280516c01431e0fae6d7217ca9fffffff8111614a6f570260060180546102a05260018101546102c05260028101546102e052600381015461030052600481015461032052505b6102e051610340526102a051610360526102c051610380526102e0516103a052610300516103c052610320516103e0526000610400526102e051421115613b3b574361030051808203828111614a6f5790509050670de0b6b3a7640000810281670de0b6b3a7640000820418614a6f579050426102e051808203828111614a6f57905090508015614a6f5780820490509050610400525b6103405162093a808104905062093a8081028162093a80820418614a6f57905061042052600060ff905b80610440526104205162093a808101818110614a6f57905061042052600061046052426104205111613bb8576c064f964e68233a8000000000086104205160205260005260406000205461046052613bbe565b42610420525b6102a0516102c0516104205161034051808203828111614a6f579050905080607f1c614a6f5780820280600f0b8118614a6f579050905080820380600f0b8118614a6f57905090506102a0526102c0516104605180820180600f0b8118614a6f57905090506102c0527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6102a05113613c585760006102a0525b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6102c05113613c895760006102c0525b6104205161034052610420516102e0526103c05161040051610420516103a051808203828111614a6f5790509050808202811583838304141715614a6f5790509050670de0b6b3a764000081049050808201828110614a6f5790509050610300526102805160018101818110614a6f57905061028052426104205118613d17574361030052613d6c56613d61565b6005610280516c01431e0fae6d7217ca9fffffff8111614a6f57026006016102a05181556102c05160018201556102e0516002820155610300516003820155610320516004820155505b600101818118613b65575b50506102805160055560405115613f52576102c0516101c0516101205180820380600f0b8118614a6f579050905080820180600f0b8118614a6f57905090506102c0526102a0516101a0516101005180820380600f0b8118614a6f579050905080820180600f0b8118614a6f57905090506102a05260605160a0511315613e23576103205160a05160605180820380600f0b8118614a6f579050905060008112614a6f57808201828110614a6f5790509050610320525b60605160a0511215613ef0576103205160605160a05180820380600f0b8118614a6f579050905060008112614a6f57808203828111614a6f579050905061032052600760e05118613e78574260c05110613e7b565b60005b15613eb9576102a05160a05180820180600f0b8118614a6f57905090506102a0526102a05160605180820380600f0b8118614a6f57905090506102a0525b60a051613ef0576c064f964e68233a80000000000e54613ef0576102a05160605180820380600f0b8118614a6f57905090506102a0525b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6102c05113613f215760006102c0525b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6102a05113613f525760006102a0525b6005610280516c01431e0fae6d7217ca9fffffff8111614a6f57026006016102a05181556102c05160018201556102e051600282015561030051600382015561032051600482015550604051156141645742608051111561401557610240516101205180820180600f0b8118614a6f57905090506102405260805160c05118613ff357610240516101c05180820380600f0b8118614a6f5790509050610240525b610240516c064f964e68233a8000000000086080516020526000526040600020555b4260c051111561406a5760805160c051111561406a57610260516101c05180820380600f0b8118614a6f579050905061026052610260516c064f964e68233a80000000000860c0516020526000526040600020555b6c064f964e68233a80000000000760405160205260005260406000205460018101818110614a6f57905061044052610440516c064f964e68233a800000000007604051602052600052604060002055426101e0524361020052600460405160205260005260406000205460008112614a6f57610220524260c05110156141065760046040516020526000526040600020546101a05260006101c0525b6c064f964e68233a8000000000066040516020526000526040600020600561044051633b9ac9ff8111614a6f5702810190506101a05181556101c05160018201556101e0516002820155610200516003820155610220516004820155505b565b6002546323b872dd610560526104a05161058052306105a0526104c0516105c0526020610560606461057c6000855af16141a5573d600060003e3d6000fd5b60203d10614a6f57610560518060011c614a6f576105e0526105e090505115614a6f57610500516105605261052051610580526003546105a052610560516105c052610580516105e0526105a0516104c051808201828110614a6f57905090506003556105c0516104c05180607f1c614a6f5780820180600f0b8118614a6f57905090506105c0526104e0511561423f576104e0516105e0525b60046104805160205260005260406000206105c05181556105e0516001820155506104805160405261056051606052610580516080526105c05160a0526105e05160c0526105405160e0526142926138b6565b6105e0516104a051610480517f4ace3cb811d903eba44ce1721d1a1d79232246711977f44236000551f8c11cc16104c05161060052610540516106205242610640526060610600a47f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c6105a051610600526105a0516104c051808201828110614a6f5790509050610620526040610600a1565b6c064f964e68233a80000000000f546106805114614361576c064f964e68233a8000000000106106805160205260005260406000205415614364565b60005b1561437857610680516040526143786137be565b610660516040526143876137be565b600461066051602052600052604060002080546106c05260018101546106e052506106a051614416576011610700527f56616c7565206d757374206265203e20300000000000000000000000000000006107205261070050610700518061072001601f826000031636823750506308c379a06106c05260206106e052601f19601f6107005101166044016106dcfd5b60016106c0511215614488576016610700527f4e6f206578697374696e67206c6f636b20666f756e64000000000000000000006107205261070050610700518061072001601f826000031636823750506308c379a06106c05260206106e052601f19601f6107005101166044016106dcfd5b426106e0511161451d576024610700527f43616e6e6f742061646420746f2065787069726564206c6f636b2e2057697468610720527f64726177000000000000000000000000000000000000000000000000000000006107405261070050610700518061072001601f826000031636823750506308c379a06106c05260206106e052601f19601f6107005101166044016106dcfd5b6106605161048052610680516104a0526106a0516104c05260006104e0526106c051610500526106e05161052052600161054052614559614166565b565b600061050051121561456e576000614579565b6104c0516105005113155b614608576026610540527f43616e6e6f74207769746864726177206d6f7265207468616e20746865207573610560527f65722068617300000000000000000000000000000000000000000000000000006105805261054050610540518061056001601f826000031636823750506308c379a061050052602061052052601f19601f61054051011660440161051cfd5b6104c051610540526104e051610560526105005160008112614a6f5761058052610540516105a052610560516105c05261054051610500511861464c576000610560525b610540516105005180820380600f0b8118614a6f5790509050610540526004610480516020526000526040600020610540518155610560516001820155506003546105e0526105e05161058051808203828111614a6f5790509050600355610480516040526105a0516060526105c0516080526105405160a0526105605160c0526105205160e0526146dc6138b6565b60025463a9059cbb610600526104a0516106205261058051610640526020610600604461061c6000855af1614716573d600060003e3d6000fd5b60203d10614a6f57610600518060011c614a6f576106605261066090505161479e576019610680527f4552433230207472616e73666572206f7574206661696c6564000000000000006106a0526106805061068051806106a001601f826000031636823750506308c379a061064052602061066052601f19601f61068051011660440161065cfd5b6104a051610480517ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567610580516106005242610620526040610600a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c6105e051610600526105e05161058051808203828111614a6f5790509050610620526040610600a1565b600060805260605160a05260006080905b8060c05260a0516080511061484a576148cb565b60805160a051808201828110614a6f579050905060018101818110614a6f5790508060011c905060e052604051600560e0516c01431e0fae6d7217ca9fffffff8111614a6f57026006016003810190505411156148b95760e05160018103818111614a6f57905060a0526148c0565b60e0516080525b600101818118614836575b5050608051815250565b60405161010052606051610120526080516101405260a0516101605260c051610180526101405162093a808104905062093a8081028162093a80820418614a6f5790506101a052600060ff905b806101c0526101a05162093a808101818110614a6f5790506101a05260006101e05260e0516101a05111614977576c064f964e68233a8000000000086101a0516020526000526040600020546101e05261497f565b60e0516101a0525b61010051610120516101a05161014051808203828111614a6f579050905080607f1c614a6f5780820280600f0b8118614a6f579050905080820380600f0b8118614a6f57905090506101005260e0516101a051186149dc57614a0c565b610120516101e05180820180600f0b8118614a6f5790509050610120526101a05161014052600101818118614922575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101005113614a3f576000610100525b6101005160008112614a6f576101c052610180516101c0511015614a6657610180516101c0525b6101c051815250565b600080fda165767970657283000307000b005b600080fd
Deployed Bytecode
0x6003361161000c576137b8565b60003560e01c34614a6f5763c35ce48d811861008d5760243610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000001d543318614a6f576040516c064f964e68233a80000000001e557fd663c3b63b25bf73d75a842070d8f5c8194612f2f6483a9e5a900d9f49af63f060405160605260206060a1005b63e5ea47b8811861010c5760043610614a6f576c064f964e68233a80000000001e546040526040513318614a6f576040516c064f964e68233a80000000001d5560006c064f964e68233a80000000001e557f7f877120c72766f4eac00144c86c9e57ed52f31bac01ef5c4c223c4768a8767360405160605260206060a1005b6357f901e2811861018e5760243610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000001d543318614a6f576040516c064f964e68233a80000000001b557f25ae06665d3dcefda7253511ee45f88500aab9b3ea061845a747baad51121c1e6c064f964e68233a80000000001b5460605260206060a1005b638e5b490f811861020e5760043610614a6f576c064f964e68233a80000000001d543318614a6f576c064f964e68233a80000000001b546c064f964e68233a80000000001c557f5000294582547ee919f4908d785ff270cd38f6cc318e730199ae00c65548f2ee6c064f964e68233a80000000001c5460405260206040a1005b638980f11f81186102aa5760443610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000001d543318614a6f5760025460405114614a6f5760405163a9059cbb6060526c064f964e68233a80000000001d5460805260243560a052602060606044607c6000855af161028e573d600060003e3d6000fd5b60203d10614a6f576060518060011c614a6f5760c05260c05050005b637c74a174811861032c5760243610614a6f576004358060a01c614a6f576040526c064f964e68233a8000000000076040516020526000526040600020546060526c064f964e68233a80000000000660405160205260005260406000206005606051633b9ac9ff8111614a6f5702810190506001810190505460805260206080f35b631e45529b81186103a85760243610614a6f576004358060a01c614a6f576040526c064f964e68233a8000000000076040516020526000526040600020546060526c064f964e68233a80000000000660405160205260005260406000206005606051633b9ac9ff8111614a6f5702810190505460805260206080f35b63a7afdcae81186104475760243610614a6f576004358060a01c614a6f576040526c064f964e68233a8000000000076040516020526000526040600020546060526c064f964e68233a80000000000660405160205260005260406000206005606051633b9ac9ff8111614a6f5702810190508054608052600181015460a052600281015460c052600381015460e0526004810154610100525060a06080f35b63da020a1881186104a95760443610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000000660405160205260005260406000206005602435633b9ac9ff8111614a6f5702810190506002810190505460605260206060f35b634181ac2781186105055760043610614a6f5760056005546c01431e0fae6d7217ca9fffffff8111614a6f5702600601805460405260018101546060526002810154608052600381015460a052600481015460c0525060a06040f35b63adc6358981186105465760243610614a6f576004358060a01c614a6f57604052600460405160205260005260406000206001810190505460605260206060f35b63570a30b781186105815760243610614a6f576004358060a01c614a6f57604052600460405160205260005260406000205460605260206060f35b63534b730e81186105ba5760043610614a6f574262093a808104905062093a8081028162093a80820418614a6f57905060405260206040f35b6308a2bc3b81186106055760043610614a6f574262093a808104905062093a8081028162093a80820418614a6f5790508062093a800162093a808110614a6f57905060405260206040f35b63c2c4c5c181186106285760043610614a6f5760c0366040376106266138b6565b005b6365fc387381186108c75760443610614a6f57600054600214614a6f576002600055336040526106566137be565b60243562093a808104905062093a8081028162093a80820418614a6f57905061066052600433602052600052604060002080546106805260018101546106a052506004356107045760116106c0527f56616c7565206d757374206265203e20300000000000000000000000000000006106e0526106c0506106c051806106e001601f826000031636823750506308c379a06106805260206106a052601f19601f6106c051011660440161069cfd5b61068051156107735760196106c0527f5769746864726177206f6c6420746f6b656e73206669727374000000000000006106e0526106c0506106c051806106e001601f826000031636823750506308c379a06106805260206106a052601f19601f6106c051011660440161069cfd5b4261066051116108085760266106c0527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e20746865206106e0527f6675747572650000000000000000000000000000000000000000000000000000610700526106c0506106c051806106e001601f826000031636823750506308c379a06106805260206106a052601f19601f6106c051011660440161069cfd5b42630784ce008101818110614a6f57905061066051111561088957601e6106c0527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006106e0526106c0506106c051806106e001601f826000031636823750506308c379a06106805260206106a052601f19601f6106c051011660440161069cfd5b3361048052336104a0526004356104c052610660516104e05261068051610500526106a051610520526000610540526108c0614166565b6003600055005b634957677c81186109095760243610614a6f57600054600214614a6f576002600055336106605233610680526004356106a052610902614325565b6003600055005b63e864837681186109d65760443610614a6f576004358060a01c614a6f5761076052600054600214614a6f5760026000556c064f964e68233a800000000009546109b3576012610780527f43757272656e746c792064697361626c656400000000000000000000000000006107a0526107805061078051806107a001601f826000031636823750506308c379a061074052602061076052601f19601f61078051011660440161075cfd5b610760516106605233610680526024356106a0526109cf614325565b6003600055005b637de680618118610ad65760243610614a6f576004358060a01c614a6f5761066052600054600214614a6f576002600055600461066051602052600052604060002080546106805260018101546106a052506001610680511215610a9a5760166106c0527f4e6f206578697374696e67206c6f636b20666f756e64000000000000000000006106e0526106c0506106c051806106e001601f826000031636823750506308c379a06106805260206106a052601f19601f6106c051011660440161069cfd5b6106605161048052610660516104a0526040366104c03761068051610500526106a05161052052600861054052610acf614166565b6003600055005b63eff7a6128118610d585760243610614a6f57600054600214614a6f57600260005533604052610b046137be565b60043360205260005260406000208054610660526001810154610680525060043562093a808104905062093a8081028162093a80820418614a6f5790506106a052426106805111610bb557600c6106c0527f4c6f636b206578706972656400000000000000000000000000000000000000006106e0526106c0506106c051806106e001601f826000031636823750506308c379a06106805260206106a052601f19601f6106c051011660440161069cfd5b6001610660511215610c275760116106c0527f4e6f7468696e67206973206c6f636b65640000000000000000000000000000006106e0526106c0506106c051806106e001601f826000031636823750506308c379a06106805260206106a052601f19601f6106c051011660440161069cfd5b610680516106a05111610c9a57601f6106c0527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006106e0526106c0506106c051806106e001601f826000031636823750506308c379a06106805260206106a052601f19601f6106c051011660440161069cfd5b42630784ce008101818110614a6f5790506106a0511115610d1b57601e6106c0527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006106e0526106c0506106c051806106e001601f826000031636823750506308c379a06106805260206106a052601f19601f6106c051011660440161069cfd5b3361048052336104a05260006104c0526106a0516104e05261066051610500526106805161052052600261054052610d51614166565b6003600055005b6361c44a7381186111f35760443610614a6f576004358060a01c614a6f5761048052600154600214614a6f5760026001556c064f964e68233a80000000000c54610e025760126104a0527f43757272656e746c792064697361626c656400000000000000000000000000006104c0526104a0506104a051806104c001601f826000031636823750506308c379a061046052602061048052601f19601f6104a051011660440161047cfd5b6c064f964e68233a80000000000f543318610e1e576001610e3a565b6c064f964e68233a800000000010336020526000526040600020545b610ec95760236104a0527f50726f7879206e6f742077686974656c6973746564205b61646d696e206c65766104c0527f656c5d00000000000000000000000000000000000000000000000000000000006104e0526104a0506104a051806104c001601f826000031636823750506308c379a061046052602061048052601f19601f6104a051011660440161047cfd5b6c064f964e68233a80000000001161048051602052600052604060002054331815610f795760246104a0527f50726f7879206e6f742077686974656c6973746564205b7374616b6572206c656104c0527f76656c5d000000000000000000000000000000000000000000000000000000006104e0526104a0506104a051806104c001601f826000031636823750506308c379a061046052602061048052601f19601f6104a051011660440161047cfd5b600461048051602052600052604060002080546104a05260018101546104c052506c064f964e68233a800000000012610480516020526000526040600020546104e05260016104a051121561102e576016610500527f4e6f206578697374696e67206c6f636b20666f756e64000000000000000000006105205261050050610500518061052001601f826000031636823750506308c379a06104c05260206104e052601f19601f6105005101166044016104dcfd5b60243561109b576017610500527f416d6f756e74206d757374206265206e6f6e2d7a65726f0000000000000000006105205261050050610500518061052001601f826000031636823750506308c379a06104c05260206104e052601f19601f6105005101166044016104dcfd5b6c064f964e68233a8000000000126104805160205260005260406000208054602435808201828110614a6f5790509050815550600354610500526104a051610520526104c05161054052600354602435808201828110614a6f57905090506003556105205160243580607f1c614a6f5780820180600f0b8118614a6f579050905061052052600461048051602052600052604060002061052051815561054051600182015550610480516040526104a0516060526104c0516080526105205160a0526105405160c052600660e0526111716138b6565b33610480517f5ac729958bdffbbceb1d50f714f86dafb13969e2023c00390189fbec3c83fc26602435610560526020610560a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c610500516105605261050051602435808201828110614a6f5790509050610580526040610560a16003600155005b630ce0853f811861171b5760443610614a6f576004358060a01c614a6f5761048052600154600214614a6f5760026001556c064f964e68233a80000000000c5461129d5760126104a0527f43757272656e746c792064697361626c656400000000000000000000000000006104c0526104a0506104a051806104c001601f826000031636823750506308c379a061046052602061048052601f19601f6104a051011660440161047cfd5b6c064f964e68233a80000000000f5433186112b95760016112d5565b6c064f964e68233a800000000010336020526000526040600020545b6113645760236104a0527f50726f7879206e6f742077686974656c6973746564205b61646d696e206c65766104c0527f656c5d00000000000000000000000000000000000000000000000000000000006104e0526104a0506104a051806104c001601f826000031636823750506308c379a061046052602061048052601f19601f6104a051011660440161047cfd5b6c064f964e68233a800000000011610480516020526000526040600020543318156114145760246104a0527f50726f7879206e6f742077686974656c6973746564205b7374616b6572206c656104c0527f76656c5d000000000000000000000000000000000000000000000000000000006104e0526104a0506104a051806104c001601f826000031636823750506308c379a061046052602061048052601f19601f6104a051011660440161047cfd5b600461048051602052600052604060002080546104a05260018101546104c052506c064f964e68233a800000000012610480516020526000526040600020546104e05260016104a05112156114c9576016610500527f4e6f206578697374696e67206c6f636b20666f756e64000000000000000000006105205261050050610500518061052001601f826000031636823750506308c379a06104c05260206104e052601f19601f6105005101166044016104dcfd5b602435611536576017610500527f416d6f756e74206d757374206265206e6f6e2d7a65726f0000000000000000006105205261050050610500518061052001601f826000031636823750506308c379a06104c05260206104e052601f19601f6105005101166044016104dcfd5b6024356c064f964e68233a8000000000126104805160205260005260406000205410156115c3576018610500527f547279696e6720746f20736c61736820746f6f206d75636800000000000000006105205261050050610500518061052001601f826000031636823750506308c379a06104c05260206104e052601f19601f6105005101166044016104dcfd5b6c064f964e68233a8000000000126104805160205260005260406000208054602435808203828111614a6f5790509050815550600354610500526104a051610520526104c05161054052600354602435808203828111614a6f57905090506003556105205160243580607f1c614a6f5780820380600f0b8118614a6f579050905061052052600461048051602052600052604060002061052051815561054051600182015550610480516040526104a0516060526104c0516080526105205160a0526105405160c052600760e0526116996138b6565b33610480517f5ac729958bdffbbceb1d50f714f86dafb13969e2023c00390189fbec3c83fc26602435610560526020610560a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c610500516105605261050051602435808203828111614a6f5790509050610580526040610560a16003600155005b633ccfd60b81186118a45760043610614a6f57600054600214614a6f576002600055600433602052600052604060002080546106c05260018101546106e052506106e05142101561177a576c064f964e68233a80000000000e5461177d565b60015b6117e7576016610700527f546865206c6f636b206469646e277420657870697265000000000000000000006107205261070050610700518061072001601f826000031636823750506308c379a06106c05260206106e052601f19601f6107005101166044016106dcfd5b6c064f964e68233a800000000012336020526000526040600020541561186d576019610700527f4f75747374616e64696e67204650495320696e2070726f7879000000000000006107205261070050610700518061072001601f826000031636823750506308c379a06106c05260206106e052601f19601f6107005101166044016106dcfd5b3361048052336104a0526106c0516104c0526106e0516104e0526106c0516105005260036105205261189d61455b565b6003600055005b63e081eec98118611d1a5760643610614a6f576004358060a01c614a6f57610480526024358060a01c614a6f576104a05260443580600f0b8118614a6f576104c052600154600214614a6f5760026001556c064f964e68233a80000000000a5461196e5760126104e0527f43757272656e746c792064697361626c65640000000000000000000000000000610500526104e0506104e0518061050001601f826000031636823750506308c379a06104a05260206104c052601f19601f6104e05101166044016104bcfd5b6c064f964e68233a80000000000f54331861198a5760016119a6565b6c064f964e68233a800000000010336020526000526040600020545b611a355760236104e0527f50726f7879206e6f742077686974656c6973746564205b61646d696e206c6576610500527f656c5d0000000000000000000000000000000000000000000000000000000000610520526104e0506104e0518061050001601f826000031636823750506308c379a06104a05260206104c052601f19601f6104e05101166044016104bcfd5b6c064f964e68233a80000000001161048051602052600052604060002054331815611ae55760246104e0527f50726f7879206e6f742077686974656c6973746564205b7374616b6572206c65610500527f76656c5d00000000000000000000000000000000000000000000000000000000610520526104e0506104e0518061050001601f826000031636823750506308c379a06104a05260206104c052601f19601f6104e05101166044016104bcfd5b600461048051602052600052604060002080546104e0526001810154610500525060016104e0511215611b78576016610520527f4e6f206578697374696e67206c6f636b20666f756e64000000000000000000006105405261052050610520518061054001601f826000031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b6104c05160008112614a6f5761052052610520516c064f964e68233a800000000012610480516020526000526040600020541015611c16576020610540527f547279696e6720746f207472616e73666572206261636b20746f6f206d7563686105605261054050610540518061056001601f826000031636823750506308c379a061050052602061052052601f19601f61054051011660440161051cfd5b6c064f964e68233a800000000012610480516020526000526040600020805461052051808203828111614a6f57905090508155506002546323b872dd610540526104a051610560523061058052610520516105a0526020610540606461055c6000855af1611c89573d600060003e3d6000fd5b60203d10614a6f57610540518060011c614a6f576105c0526105c090505115614a6f57610480516040526104e051606052610500516080526104e05160a0526105005160c052600460e052611cdc6138b6565b610480516104a0517fbd02ce585321c0e9e7b7c479d640b5e41c559c615f32449f741727c6162f4ac861052051610540526020610540a36003600155005b632bcbc3ef81186121995760643610614a6f576004358060a01c614a6f57610480526024358060a01c614a6f576104a05260443580600f0b8118614a6f576104c052600154600214614a6f5760026001556c064f964e68233a80000000000b54611de45760126104e0527f43757272656e746c792064697361626c65640000000000000000000000000000610500526104e0506104e0518061050001601f826000031636823750506308c379a06104a05260206104c052601f19601f6104e05101166044016104bcfd5b6c064f964e68233a80000000000f543318611e00576001611e1c565b6c064f964e68233a800000000010336020526000526040600020545b611eab5760236104e0527f50726f7879206e6f742077686974656c6973746564205b61646d696e206c6576610500527f656c5d0000000000000000000000000000000000000000000000000000000000610520526104e0506104e0518061050001601f826000031636823750506308c379a06104a05260206104c052601f19601f6104e05101166044016104bcfd5b6c064f964e68233a80000000001161048051602052600052604060002054331815611f5b5760246104e0527f50726f7879206e6f742077686974656c6973746564205b7374616b6572206c65610500527f76656c5d00000000000000000000000000000000000000000000000000000000610520526104e0506104e0518061050001601f826000031636823750506308c379a06104a05260206104c052601f19601f6104e05101166044016104bcfd5b600461048051602052600052604060002080546104e052600181015461050052506104e05160008112614a6f5761052052610500514210611ffc57601d610540527f4e6f207472616e73666572732061667465722065787069726174696f6e0000006105605261054050610540518061056001601f826000031636823750506308c379a061050052602061052052601f19601f61054051011660440161051cfd5b6104c05160008112614a6f57610540526c064f964e68233a800000000012610480516020526000526040600020805461054051808201828110614a6f5790509050815550610520516c064f964e68233a8000000000126104805160205260005260406000205411156120ce57601d610560527f416d6f756e742065786365656473206c6f636b65642062616c616e63650000006105805261056050610560518061058001601f826000031636823750506308c379a061052052602061054052601f19601f61056051011660440161053cfd5b60025463a9059cbb610560526104a05161058052610540516105a0526020610560604461057c6000855af1612108573d600060003e3d6000fd5b60203d10614a6f57610560518060011c614a6f576105c0526105c090505115614a6f57610480516040526104e051606052610500516080526104e05160a0526105005160c052600560e05261215b6138b6565b6104a051610480517f9b4385b7a76ef579e481bdac2c47bfd58d1bb8635d3898165499b2326f1f0f8a61054051610560526020610560a36003600155005b6370a0823181186121b55760243610614a6f57426060526121ce565b62fdd58e81186123125760443610614a6f576024356060525b6004358060a01c614a6f576040526c064f964e68233a80000000000760405160205260005260406000205460805260805161221557600060a052602060a061231056612310565b6c064f964e68233a80000000000660405160205260005260406000206005608051633b9ac9ff8111614a6f570281019050805460a052600181015460c052600281015460e0526003810154610100526004810154610120525060a05160c05160605160e051808203828111614a6f579050905080607f1c614a6f5780820280600f0b8118614a6f579050905080820380600f0b8118614a6f579050905060a0527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60a051136122e457600060a0525b60a05160008112614a6f57610140526101205161014051101561230a5761012051610140525b60206101405bf35b634ee2cd7e81186126c05760443610614a6f576004358060a01c614a6f57610100524360243511614a6f576000610120526c064f964e68233a800000000007610100516020526000526040600020546101405260006080905b806101605261014051610120511061238257612420565b6101205161014051808201828110614a6f579050905060018101818110614a6f5790508060011c9050610180526024356c064f964e68233a800000000006610100516020526000526040600020600561018051633b9ac9ff8111614a6f57028101905060038101905054111561240c576101805160018103818111614a6f57905061014052612415565b61018051610120525b60010181811861236b575b50506c064f964e68233a800000000006610100516020526000526040600020600561012051633b9ac9ff8111614a6f57028101905080546101605260018101546101805260028101546101a05260038101546101c05260048101546101e05250600554610200526024356040526102005160605261249f610240614825565b61024051610220526005610220516c01431e0fae6d7217ca9fffffff8111614a6f570260060180546102405260018101546102605260028101546102805260038101546102a05260048101546102c052506040366102e03761020051610220511061253757436102a051808203828111614a6f57905090506102e0524261028051808203828111614a6f5790509050610300526125c2565b60056102205160018101818110614a6f5790506c01431e0fae6d7217ca9fffffff8111614a6f570260060180546103205260018101546103405260028101546103605260038101546103805260048101546103a05250610380516102a051808203828111614a6f57905090506102e0526103605161028051808203828111614a6f5790509050610300525b61028051610320526102e051156126285761032051610300516024356102a051808203828111614a6f5790509050808202811583838304141715614a6f57905090506102e0518015614a6f5780820490509050808201828110614a6f5790509050610320525b6101605161018051610320516101a051808203828111614a6f579050905080607f1c614a6f5780820280600f0b8118614a6f579050905080820380600f0b8118614a6f579050905061016052600061016051121561268d5760006101e0511015612690565b60015b6126a85760006103405260206103406126be566126be565b6101605160008112614a6f576103405260206103405bf35b6318160ddd81186126dd5760043610614a6f5742610200526126f8565b63bd85b03981186127845760243610614a6f57600435610200525b600554610220526005610220516c01431e0fae6d7217ca9fffffff8111614a6f570260060180546102405260018101546102605260028101546102805260038101546102a05260048101546102c0525060206102405160405261026051606052610280516080526102a05160a0526102c05160c0526102005160e05261277f6102e06148d5565b6102e0f35b63981b24d081186129aa5760243610614a6f574360043511614a6f5760055461020052600435604052610200516060526127bf610240614825565b61024051610220526005610220516c01431e0fae6d7217ca9fffffff8111614a6f570260060180546102405260018101546102605260028101546102805260038101546102a05260048101546102c0525060006102e05261020051610220511061289257436102a0511461295c576004356102a051808203828111614a6f57905090504261028051808203828111614a6f5790509050808202811583838304141715614a6f5790509050436102a051808203828111614a6f57905090508015614a6f57808204905090506102e05261295c565b60056102205160018101818110614a6f5790506c01431e0fae6d7217ca9fffffff8111614a6f570260060180546103005260018101546103205260028101546103405260038101546103605260048101546103805250610360516102a0511461295c576004356102a051808203828111614a6f57905090506103405161028051808203828111614a6f5790509050808202811583838304141715614a6f5790509050610360516102a051808203828111614a6f57905090508015614a6f57808204905090506102e0525b60206102405160405261026051606052610280516080526102a05160a0526102c05160c052610280516102e051808201828110614a6f579050905060e0526129a56103006148d5565b610300f35b6347c7341e81186129c95760043610614a6f5760035460405260206040f35b630f4174a08118612a5c5760243610614a6f574360043511614a6f576005546101005260043560405261010051606052612a04610140614825565b61014051610120526005610120516c01431e0fae6d7217ca9fffffff8111614a6f570260060180546101405260018101546101605260028101546101805260038101546101a05260048101546101c0525060206101c0f35b6388c2b3e38118612aed5760043610614a6f576c064f964e68233a80000000001d543318614a6f576c064f964e68233a80000000000e54156c064f964e68233a80000000000e5560c036604037612ab16138b6565b7feab47e2228a51fa30e80a103a8e0105cb452653bb433513d6bf11e3e3f3637a36c064f964e68233a80000000000e54610480526020610480a1005b6316f616728118612b7e5760043610614a6f576c064f964e68233a80000000001d543318614a6f576c064f964e68233a80000000000954156c064f964e68233a8000000000095560c036604037612b426138b6565b7fdf5e6b6b37885e5046023bc28abaf4fa317db98e6c992dbba3830fd69f0f03d46c064f964e68233a80000000000954610480526020610480a1005b630b33ac488118612c0f5760043610614a6f576c064f964e68233a80000000001d543318614a6f576c064f964e68233a80000000000a54156c064f964e68233a80000000000a5560c036604037612bd36138b6565b7f924855749e6db89374eeb6d4f88b5c3f2c3f4efff48671af2f5ebab4a558faf66c064f964e68233a80000000000a54610480526020610480a1005b63e8ff7e828118612ca05760043610614a6f576c064f964e68233a80000000001d543318614a6f576c064f964e68233a80000000000b54156c064f964e68233a80000000000b5560c036604037612c646138b6565b7f2e0793e6a4f1baa7980928be0706d6246f765c4c1038e17ef46dd004504b65fa6c064f964e68233a80000000000b54610480526020610480a1005b63172cb9998118612d315760043610614a6f576c064f964e68233a80000000001d543318614a6f576c064f964e68233a80000000000c54156c064f964e68233a80000000000c5560c036604037612cf56138b6565b7f0e9338cb371255221e6df7c319bbd0290c0a544046aaf2d21b42ff796e6f71746c064f964e68233a80000000000c54610480526020610480a1005b630929f36f8118612dc25760043610614a6f576c064f964e68233a80000000001d543318614a6f576c064f964e68233a80000000000d54156c064f964e68233a80000000000d5560c036604037612d866138b6565b7f3f6a71816fba143945ad3184a7c46790c48e516749eb3cc736342f5bb3eb88cb6c064f964e68233a80000000000d54610480526020610480a1005b63bacec9678118612eb55760243610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000001d54331815612e5657600a6060527f41646d696e206f6e6c790000000000000000000000000000000000000000000060805260605060605180608001601f826000031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b6040516c064f964e68233a80000000000f5560016c064f964e68233a8000000000106040516020526000526040600020557f3c3597bbc034da275532ab551a8916a9bade58914700b6aa1ab96f16243bafaa60405160605260206060a1005b63417f25c98118612fd25760243610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000001d54331815612f4957600a6060527f41646d696e206f6e6c790000000000000000000000000000000000000000000060805260605060605180608001601f826000031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b6c064f964e68233a800000000010604051602052600052604060002054156c064f964e68233a8000000000106040516020526000526040600020557f94fd3c4f99e5feb7efd85143b048ed68169886a015308a163bfdc9b36a8188596040516060526c064f964e68233a80000000001060405160205260005260406000205460805260406060a1005b634d857d0c81186131645760243610614a6f576004358060a01c614a6f57604052604051613001576001613016565b6040516c064f964e68233a80000000000f5418155b61309b5760236060527f50726f7879206e6f742077686974656c6973746564205b61646d696e206c65766080527f656c5d000000000000000000000000000000000000000000000000000000000060a05260605060605180608001601f826000031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b6c064f964e68233a80000000001233602052600052604060002054156131185760196060527f4f75747374616e64696e67204650495320696e2070726f78790000000000000060805260605060605180608001601f826000031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b6040516c064f964e68233a800000000011336020526000526040600020557f0c5eabcbebbb87a106d2bdf51ee002efdd0f1b547dae5f9d6d0e28b15af217db60405160605260206060a1005b63fc0c546a81186131835760043610614a6f5760025460405260206040f35b63047fc9aa81186131a25760043610614a6f5760035460405260206040f35b63cbf9fe5f81186131e75760243610614a6f576004358060a01c614a6f5760405260046040516020526000526040600020805460605260018101546080525060406060f35b63900cf0cf81186132065760043610614a6f5760055460405260206040f35b63d1febfb981186132625760243610614a6f5760056004356c01431e0fae6d7217ca9fffffff8111614a6f5702600601805460405260018101546060526002810154608052600381015460a052600481015460c0525060a06040f35b6328d09d4781186132e05760443610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000000660405160205260005260406000206005602435633b9ac9ff8111614a6f57028101905080546060526001810154608052600281015460a052600381015460c052600481015460e0525060a06060f35b63010ae75781186133275760243610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000000760405160205260005260406000205460605260206060f35b637119748481186133605760243610614a6f576c064f964e68233a80000000000860043560205260005260406000205460405260206040f35b63702254a1811861338b5760043610614a6f576c064f964e68233a8000000000095460405260206040f35b63811d35ba81186133b65760043610614a6f576c064f964e68233a80000000000a5460405260206040f35b63a61f15c481186133e15760043610614a6f576c064f964e68233a80000000000b5460405260206040f35b6395957b57811861340c5760043610614a6f576c064f964e68233a80000000000c5460405260206040f35b632e67535d81186134375760043610614a6f576c064f964e68233a80000000000d5460405260206040f35b63f894648581186134625760043610614a6f576c064f964e68233a80000000000e5460405260206040f35b630a5de864811861348d5760043610614a6f576c064f964e68233a80000000000f5460405260206040f35b63d5a7505081186134d45760243610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000001060405160205260005260406000205460605260206060f35b638d94781a811861351b5760243610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000001160405160205260005260406000205460605260206060f35b63312afb0381186135625760243610614a6f576004358060a01c614a6f576040526c064f964e68233a80000000001260405160205260005260406000205460605260206060f35b6306fdde0381186135ff5760043610614a6f57602080604052806040016c064f964e68233a8000000000135480825260208201600082601f0160051c60028111614a6f5780156135d157905b806c064f964e68233a80000000001401548160051b8401526001018181186135ae575b505050508051806020830101601f82600003163682375050601f19601f825160200101169050810190506040f35b6395d89b41811861366f5760043610614a6f57602080604052806040016c064f964e68233a80000000001654808252602082016c064f964e68233a80000000001754815250508051806020830101601f82600003163682375050601f19601f825160200101169050810190506040f35b6354fd4d5081186136df5760043610614a6f57602080604052806040016c064f964e68233a80000000001854808252602082016c064f964e68233a80000000001954815250508051806020830101601f82600003163682375050601f19601f825160200101169050810190506040f35b63313ce567811861370a5760043610614a6f576c064f964e68233a80000000001a5460405260206040f35b638ff36fd181186137355760043610614a6f576c064f964e68233a80000000001b5460405260206040f35b637175d4f781186137605760043610614a6f576c064f964e68233a80000000001c5460405260206040f35b63f851a440811861378b5760043610614a6f576c064f964e68233a80000000001d5460405260206040f35b6317f7182a81186137b65760043610614a6f576c064f964e68233a80000000001e5460405260206040f35b505b60006000fd5b32604051146138b4576c064f964e68233a80000000001c54606052606051156138335760605163c23697a860805260405160a052602060806024609c6000855af161380e573d600060003e3d6000fd5b60203d10614a6f576080518060011c614a6f5760c05260c090505115613833576138b4565b60256080527f536d61727420636f6e7472616374206465706f7369746f7273206e6f7420616c60a0527f6c6f77656400000000000000000000000000000000000000000000000000000060c0526080506080518060a001601f826000031636823750506308c379a06040526020606052601f19601f6080510116604401605cfd5b565b61018036610100376005546102805260405115613a3a5742608051116138dd5760006138e5565b600160605112155b15613952576060516003810280600f0b8118614a6f579050630784ce0081059050610120526060516101205160805142808203828111614a6f579050905080607f1c614a6f5780820280600f0b8118614a6f579050905080820180600f0b8118614a6f5790509050610100525b4260c0511161396257600061396a565b600160a05112155b156139d75760a0516003810280600f0b8118614a6f579050630784ce00810590506101c05260a0516101c05160c05142808203828111614a6f579050905080607f1c614a6f5780820280600f0b8118614a6f579050905080820180600f0b8118614a6f57905090506101a0525b6c064f964e68233a8000000000086080516020526000526040600020546102405260c05115613a3a5760805160c05118613a18576102405161026052613a3a565b6c064f964e68233a80000000000860c051602052600052604060002054610260525b6040366102a037426102e05243610300526000610320526102805115613aa4576005610280516c01431e0fae6d7217ca9fffffff8111614a6f570260060180546102a05260018101546102c05260028101546102e052600381015461030052600481015461032052505b6102e051610340526102a051610360526102c051610380526102e0516103a052610300516103c052610320516103e0526000610400526102e051421115613b3b574361030051808203828111614a6f5790509050670de0b6b3a7640000810281670de0b6b3a7640000820418614a6f579050426102e051808203828111614a6f57905090508015614a6f5780820490509050610400525b6103405162093a808104905062093a8081028162093a80820418614a6f57905061042052600060ff905b80610440526104205162093a808101818110614a6f57905061042052600061046052426104205111613bb8576c064f964e68233a8000000000086104205160205260005260406000205461046052613bbe565b42610420525b6102a0516102c0516104205161034051808203828111614a6f579050905080607f1c614a6f5780820280600f0b8118614a6f579050905080820380600f0b8118614a6f57905090506102a0526102c0516104605180820180600f0b8118614a6f57905090506102c0527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6102a05113613c585760006102a0525b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6102c05113613c895760006102c0525b6104205161034052610420516102e0526103c05161040051610420516103a051808203828111614a6f5790509050808202811583838304141715614a6f5790509050670de0b6b3a764000081049050808201828110614a6f5790509050610300526102805160018101818110614a6f57905061028052426104205118613d17574361030052613d6c56613d61565b6005610280516c01431e0fae6d7217ca9fffffff8111614a6f57026006016102a05181556102c05160018201556102e0516002820155610300516003820155610320516004820155505b600101818118613b65575b50506102805160055560405115613f52576102c0516101c0516101205180820380600f0b8118614a6f579050905080820180600f0b8118614a6f57905090506102c0526102a0516101a0516101005180820380600f0b8118614a6f579050905080820180600f0b8118614a6f57905090506102a05260605160a0511315613e23576103205160a05160605180820380600f0b8118614a6f579050905060008112614a6f57808201828110614a6f5790509050610320525b60605160a0511215613ef0576103205160605160a05180820380600f0b8118614a6f579050905060008112614a6f57808203828111614a6f579050905061032052600760e05118613e78574260c05110613e7b565b60005b15613eb9576102a05160a05180820180600f0b8118614a6f57905090506102a0526102a05160605180820380600f0b8118614a6f57905090506102a0525b60a051613ef0576c064f964e68233a80000000000e54613ef0576102a05160605180820380600f0b8118614a6f57905090506102a0525b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6102c05113613f215760006102c0525b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6102a05113613f525760006102a0525b6005610280516c01431e0fae6d7217ca9fffffff8111614a6f57026006016102a05181556102c05160018201556102e051600282015561030051600382015561032051600482015550604051156141645742608051111561401557610240516101205180820180600f0b8118614a6f57905090506102405260805160c05118613ff357610240516101c05180820380600f0b8118614a6f5790509050610240525b610240516c064f964e68233a8000000000086080516020526000526040600020555b4260c051111561406a5760805160c051111561406a57610260516101c05180820380600f0b8118614a6f579050905061026052610260516c064f964e68233a80000000000860c0516020526000526040600020555b6c064f964e68233a80000000000760405160205260005260406000205460018101818110614a6f57905061044052610440516c064f964e68233a800000000007604051602052600052604060002055426101e0524361020052600460405160205260005260406000205460008112614a6f57610220524260c05110156141065760046040516020526000526040600020546101a05260006101c0525b6c064f964e68233a8000000000066040516020526000526040600020600561044051633b9ac9ff8111614a6f5702810190506101a05181556101c05160018201556101e0516002820155610200516003820155610220516004820155505b565b6002546323b872dd610560526104a05161058052306105a0526104c0516105c0526020610560606461057c6000855af16141a5573d600060003e3d6000fd5b60203d10614a6f57610560518060011c614a6f576105e0526105e090505115614a6f57610500516105605261052051610580526003546105a052610560516105c052610580516105e0526105a0516104c051808201828110614a6f57905090506003556105c0516104c05180607f1c614a6f5780820180600f0b8118614a6f57905090506105c0526104e0511561423f576104e0516105e0525b60046104805160205260005260406000206105c05181556105e0516001820155506104805160405261056051606052610580516080526105c05160a0526105e05160c0526105405160e0526142926138b6565b6105e0516104a051610480517f4ace3cb811d903eba44ce1721d1a1d79232246711977f44236000551f8c11cc16104c05161060052610540516106205242610640526060610600a47f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c6105a051610600526105a0516104c051808201828110614a6f5790509050610620526040610600a1565b6c064f964e68233a80000000000f546106805114614361576c064f964e68233a8000000000106106805160205260005260406000205415614364565b60005b1561437857610680516040526143786137be565b610660516040526143876137be565b600461066051602052600052604060002080546106c05260018101546106e052506106a051614416576011610700527f56616c7565206d757374206265203e20300000000000000000000000000000006107205261070050610700518061072001601f826000031636823750506308c379a06106c05260206106e052601f19601f6107005101166044016106dcfd5b60016106c0511215614488576016610700527f4e6f206578697374696e67206c6f636b20666f756e64000000000000000000006107205261070050610700518061072001601f826000031636823750506308c379a06106c05260206106e052601f19601f6107005101166044016106dcfd5b426106e0511161451d576024610700527f43616e6e6f742061646420746f2065787069726564206c6f636b2e2057697468610720527f64726177000000000000000000000000000000000000000000000000000000006107405261070050610700518061072001601f826000031636823750506308c379a06106c05260206106e052601f19601f6107005101166044016106dcfd5b6106605161048052610680516104a0526106a0516104c05260006104e0526106c051610500526106e05161052052600161054052614559614166565b565b600061050051121561456e576000614579565b6104c0516105005113155b614608576026610540527f43616e6e6f74207769746864726177206d6f7265207468616e20746865207573610560527f65722068617300000000000000000000000000000000000000000000000000006105805261054050610540518061056001601f826000031636823750506308c379a061050052602061052052601f19601f61054051011660440161051cfd5b6104c051610540526104e051610560526105005160008112614a6f5761058052610540516105a052610560516105c05261054051610500511861464c576000610560525b610540516105005180820380600f0b8118614a6f5790509050610540526004610480516020526000526040600020610540518155610560516001820155506003546105e0526105e05161058051808203828111614a6f5790509050600355610480516040526105a0516060526105c0516080526105405160a0526105605160c0526105205160e0526146dc6138b6565b60025463a9059cbb610600526104a0516106205261058051610640526020610600604461061c6000855af1614716573d600060003e3d6000fd5b60203d10614a6f57610600518060011c614a6f576106605261066090505161479e576019610680527f4552433230207472616e73666572206f7574206661696c6564000000000000006106a0526106805061068051806106a001601f826000031636823750506308c379a061064052602061066052601f19601f61068051011660440161065cfd5b6104a051610480517ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567610580516106005242610620526040610600a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c6105e051610600526105e05161058051808203828111614a6f5790509050610620526040610600a1565b600060805260605160a05260006080905b8060c05260a0516080511061484a576148cb565b60805160a051808201828110614a6f579050905060018101818110614a6f5790508060011c905060e052604051600560e0516c01431e0fae6d7217ca9fffffff8111614a6f57026006016003810190505411156148b95760e05160018103818111614a6f57905060a0526148c0565b60e0516080525b600101818118614836575b5050608051815250565b60405161010052606051610120526080516101405260a0516101605260c051610180526101405162093a808104905062093a8081028162093a80820418614a6f5790506101a052600060ff905b806101c0526101a05162093a808101818110614a6f5790506101a05260006101e05260e0516101a05111614977576c064f964e68233a8000000000086101a0516020526000526040600020546101e05261497f565b60e0516101a0525b61010051610120516101a05161014051808203828111614a6f579050905080607f1c614a6f5780820280600f0b8118614a6f579050905080820380600f0b8118614a6f57905090506101005260e0516101a051186149dc57614a0c565b610120516101e05180820180600f0b8118614a6f5790509050610120526101a05161014052600101818118614922575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101005113614a3f576000610100525b6101005160008112614a6f576101c052610180516101c0511015614a6657610180516101c0525b6101c051815250565b600080fda165767970657283000307000b
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $0.707235 | 1,013,969.7486 | $717,114.9 |
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.