ETH Price: $2,421.76 (-8.43%)
 

Overview

Max Total Supply

20,268,612.40425396622022979 veBUNNI

Holders

0

Transfers

-
0

Market

Onchain Market Cap

-

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
Voting Escrow

Compiler Version
vyper:0.4.0

Optimization Enabled:
N/A

Other Settings:
default evmVersion, MIT license

Contract Source Code (Vyper language format)

#pragma version ^0.4.0

"""
@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` (1 year).
"""

MULTICALLER_WITH_SENDER: constant(address) = 0x00000000002Fd5Aeb385D324B580FCa7c83823A0
MULTICALLER_WITH_SIGNER: constant(address) = 0x000000000000D9ECebf3C23529de49815Dac1c4c

@internal
@view
def sender_or_signer() -> address:
    if msg.sender in [MULTICALLER_WITH_SENDER, MULTICALLER_WITH_SIGNER]:
        response: Bytes[32] = raw_call(msg.sender, b"", max_outsize=32, is_static_call=True)
        # the sender is encoded in the last 20 bytes of the response
        return extract32(response, 0, output_type=address)
    else:
        return msg.sender

# Voting escrow to have time-weighted votes
# Votes have a weight depending on time, so that users are committed
# to the future of (whatever they are voting for).
# The weight in this implementation is linear, and lock cannot be more than maxtime:
# w ^
# 1 +        /
#   |      /
#   |    /
#   |  /
#   |/
# 0 +--------+------> time
#       maxtime (1 year)


##
# SECTION INTERFACES
##

from ethereum.ercs import IERC20 as ERC20
from ethereum.ercs import IERC20Detailed

# 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

implements: IERC20Detailed

# !SECTION INTERFACES


##
# SECTION STRUCTS
##

# 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 Point:
    bias: int128
    slope: int128  # - dweight // dt
    ts: uint256
    blk: uint256  # block

struct LockedBalance:
    amount: int128
    end: uint256

# !SECTION STRUCTS


##
# SECTION EVENTS
##

CREATE_LOCK_TYPE: constant(int128) = 1
INCREASE_LOCK_AMOUNT: constant(int128) = 2
INCREASE_UNLOCK_TIME: constant(int128) = 3
AIRDROP_LOCK_TYPE: constant(int128) = 4

event Deposit:
    provider: indexed(address)
    value: uint256
    locktime: indexed(uint256)
    type: int128
    ts: uint256

event Withdraw:
    provider: indexed(address)
    value: uint256
    ts: uint256

event Supply:
    prevSupply: uint256
    supply: uint256

event NewPendingAdmin:
    new_pending_admin: address

event NewAdmin:
    new_admin: address

event NewPendingSmartWalletChecker:
    new_pending_smart_wallet_checker: indexed(address)

event NewSmartWalletChecker:
    new_smart_wallet_checker: indexed(address)

event BurnUnlockFuse: pass

event ApproveAirdrop:
    locker: indexed(address)
    airdropper: indexed(address)

# !SECTION EVENTS


##
# SECTION CONSTANTS
##

WEEK: constant(uint256) = 7 * 86400  # all future times are rounded by week
MAXTIME: constant(uint256) = 365 * 86400  # 1 year
MULTIPLIER: constant(uint256) = 10 ** 18

# !SECTION CONSTANTS


##
# SECTION IMMUTABLES
##

TOKEN: immutable(address)
NAME: immutable(String[64])
SYMBOL: immutable(String[32])
DECIMALS: immutable(uint8)

# !SECTION IMMUTABLES


##
# SECTION STORAGE
##

pending_admin: public(address)
admin: public(address)

supply: public(uint256)
locked: public(HashMap[address, LockedBalance])

# 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)

epoch: public(uint256)
user_point_history: public(HashMap[address, Point[1000000000]])  # user -> Point[user_epoch]
user_point_epoch: public(HashMap[address, uint256])
slope_changes: public(HashMap[uint256, int128])  # time -> signed slope change
point_history: public(Point[100000000000000000000000000000])  # epoch -> unsigned point

unlock_fuse: public(bool) # Can be permanently set to true to unlock all positions

# !SECTION STORAGE


##
# SECTION TRANSIENT STORAGE
##

# Lockers can allow another address to airdrop locked tokens to them and increase their lock time to the maximum.
# Transient storage is used so that such approvals only last for the duration of the transaction.
allow_airdrop: public(transient(HashMap[address, HashMap[address, bool]])) # locker -> airdropper -> allowed

# !SECTION TRANSIENT STORAGE


##
# SECTION CONSTRUCTOR
##

@deploy
def __init__(token_addr: address, _name: String[64], _symbol: String[32], _admin: address, _smart_wallet_checker: address):
    """
    @notice Contract constructor
    @param token_addr The token to escrow
    @param _name Token name
    @param _symbol Token symbol
    @param _admin The admin address
    """
    assert _admin != empty(address)

    TOKEN = token_addr
    self.admin = _admin
    self.point_history[0].blk = block.number
    self.point_history[0].ts = block.timestamp
    self.smart_wallet_checker = _smart_wallet_checker

    _decimals: uint8 = staticcall IERC20Detailed(token_addr).decimals()

    NAME = _name
    SYMBOL = _symbol
    DECIMALS = _decimals

# !SECTION CONSTRUCTOR


##
# SECTION PUBLIC GETTERS
##

@external
@view
def token() -> address:
    return TOKEN


@external
@view
def name() -> String[64]:
    return NAME


@external
@view
def symbol() -> String[32]:
    return SYMBOL


@external
@view
def decimals() -> uint8:
    return DECIMALS


@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 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 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 balanceOf(addr: address, _t: uint256 = block.timestamp) -> uint256:
    """
    @notice Get the current voting power for `addr`
    @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 = 0
    if _t == block.timestamp:
        # No need to do binary search, will always live in current epoch
        _epoch = self.user_point_epoch[addr]
    else:
        _epoch = self.find_timestamp_user_epoch(addr, _t, self.user_point_epoch[addr])

    if _epoch == 0:
        return 0
    else:
        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
        return convert(last_point.bias, uint256)


@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

    _user_epoch: uint256 = self.find_block_user_epoch(addr, _block, self.user_point_epoch[addr])
    upoint: Point = self.user_point_history[addr][_user_epoch]

    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)
    if upoint.bias >= 0:
        return convert(upoint.bias, uint256)
    else:
        return 0


@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 = 0
    if t == block.timestamp:
        # No need to do binary search, will always live in current epoch
        _epoch = self.epoch
    else:
        _epoch = self.find_timestamp_epoch(t, self.epoch)

    if _epoch == 0:
        return 0
    else:
        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)

# !SECTION PUBLIC GETTERS


##
# SECTION LOCKER ACTIONS
#

@external
def checkpoint():
    """
    @notice Record global data to checkpoint
    """
    self._checkpoint(empty(address), empty(LockedBalance), empty(LockedBalance))


@external
@nonreentrant
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
    """
    msg_sender: address = self.sender_or_signer()
    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  # 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 1 year max"

    self._deposit_for(msg_sender, _value, unlock_time, _locked, CREATE_LOCK_TYPE)


@external
@nonreentrant
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
    """
    msg_sender: address = self.sender_or_signer()
    self.assert_not_contract(msg_sender)
    _locked: LockedBalance = self.locked[msg_sender]

    assert _value > 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(msg_sender, _value, 0, _locked, INCREASE_LOCK_AMOUNT)


@external
@nonreentrant
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
    """
    msg_sender: address = self.sender_or_signer()
    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 1 year max"

    self._deposit_for(msg_sender, 0, unlock_time, _locked, INCREASE_UNLOCK_TIME)


@external
@nonreentrant
def withdraw():
    """
    @notice Withdraw all tokens for `msg.sender`
    @dev Only possible if the lock has expired
    """
    msg_sender: address = self.sender_or_signer()
    _locked: LockedBalance = self.locked[msg_sender]
    assert (block.timestamp >= _locked.end) or self.unlock_fuse, "The lock didn't expire or the unlock fuse has not been burnt"
    value: uint256 = convert(_locked.amount, uint256)

    old_locked: LockedBalance = _locked
    _locked.end = 0
    _locked.amount = 0
    self.locked[msg_sender] = _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
    self._checkpoint(msg_sender, old_locked, _locked)

    assert extcall ERC20(TOKEN).transfer(msg_sender, value)

    log Withdraw(msg_sender, value, block.timestamp)
    log Supply(supply_before, supply_before - value)


@external
def approve_airdrop(airdropper: address):
    """
    @notice Approve an address to airdrop locked tokens to the caller for the duration of the transaction.
    @param airdropper The address that will be allowed to airdrop tokens.
    """
    msg_sender: address = self.sender_or_signer()
    self.allow_airdrop[msg_sender][airdropper] = True
    log ApproveAirdrop(msg_sender, airdropper)

# !SECTION LOCKER ACTIONS


##
# SECTION AIRDROPPER ACTIONS
##

@external
@nonreentrant
def airdrop(_to: address, _value: uint256, _unlock_time: uint256):
    msg_sender: address = self.sender_or_signer()
    self.assert_not_contract(_to)
    unlock_time: uint256 = (_unlock_time // WEEK) * WEEK  # Locktime is rounded down to weeks
    _locked: LockedBalance = self.locked[_to]

    assert _value > 0  # dev: need non-zero value
    assert unlock_time > block.timestamp, "Can only lock until time in the future"
    assert unlock_time <= block.timestamp + MAXTIME, "Voting lock can be 1 year max"
    assert self.allow_airdrop[_to][msg_sender], "Airdrop not allowed"

    # update supply
    supply_before: uint256 = self.supply
    self.supply = supply_before + _value

    # update locked balance
    old_locked: LockedBalance = _locked
    # airdropper can only extend the lock time, not decrease it
    _locked.amount += convert(_value, int128)
    _locked.end = max(unlock_time, _locked.end)
    self.locked[_to] = _locked

    # checkpoint the user's locked balance
    self._checkpoint(_to, old_locked, _locked)

    # transfer tokens from the airdropper
    assert extcall ERC20(TOKEN).transferFrom(msg_sender, self, _value)

    log Deposit(_to, _value, _locked.end, AIRDROP_LOCK_TYPE, block.timestamp)
    log Supply(supply_before, supply_before + _value)


# !SECTION AIRDROPPER ACTIONS


##
# SECTION ADMIN ACTIONS
##

@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 NewPendingSmartWalletChecker(addr)


@external
def apply_smart_wallet_checker():
    """
    @notice Apply setting external contract to check approved smart contract wallets
    """
    assert msg.sender == self.admin
    new_checker: address = self.future_smart_wallet_checker
    self.smart_wallet_checker = new_checker

    log NewSmartWalletChecker(new_checker)


@external
def burn_unlock_fuse():
    """
    @notice Burn unlock fuse permanently and allow all users to withdraw
    """
    assert msg.sender == self.admin
    self.unlock_fuse = True

    log BurnUnlockFuse()


@external
def change_pending_admin(new_pending_admin: address):
    """
    @notice Change pending_admin to `new_pending_admin`
    @param new_pending_admin The new pending_admin address
    """
    assert msg.sender == self.admin

    self.pending_admin = new_pending_admin

    log NewPendingAdmin(new_pending_admin)


@external
def claim_admin():
    """
    @notice Called by pending_admin to set admin to pending_admin
    """
    assert msg.sender == self.pending_admin

    self.admin = msg.sender
    self.pending_admin = empty(address)

    log NewAdmin(msg.sender)

# !SECTION ADMIN ACTIONS


##
# SECTION INTERNAL UTILITIES
##

@internal
@view
def find_block_epoch(_block: uint256, max_epoch: uint256) -> uint256:
    """
    @notice Binary search to find epoch containing block number
    @param _block Block to find
    @param max_epoch Don't go beyond this epoch
    @return Epoch which contains _block
    """
    # Binary search
    _min: uint256 = 0
    _max: uint256 = max_epoch
    for i: uint256 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


@internal
@view
def find_timestamp_epoch(_timestamp: uint256, max_epoch: uint256) -> uint256:
    """
    @notice Binary search to find epoch for timestamp
    @param _timestamp timestamp to find
    @param max_epoch Don't go beyond this epoch
    @return Epoch which contains _timestamp
    """
    # Binary search
    _min: uint256 = 0
    _max: uint256 = max_epoch
    for i: uint256 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].ts <= _timestamp:
            _min = _mid
        else:
            _max = _mid - 1
    return _min


@internal
@view
def find_block_user_epoch(_addr: address, _block: uint256, max_epoch: uint256) -> uint256:
    """
    @notice Binary search to find epoch for block number
    @param _addr User for which to find user epoch for
    @param _block Block to find
    @param max_epoch Don't go beyond this epoch
    @return Epoch which contains _block
    """
    # Binary search
    _min: uint256 = 0
    _max: uint256 = max_epoch
    for i: uint256 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
    return _min


@internal
@view
def find_timestamp_user_epoch(_addr: address, _timestamp: uint256, max_epoch: uint256) -> uint256:
    """
    @notice Binary search to find user epoch for timestamp
    @param _addr User for which to find user epoch for
    @param _timestamp timestamp to find
    @param max_epoch Don't go beyond this epoch
    @return Epoch which contains _timestamp
    """
    # Binary search
    _min: uint256 = 0
    _max: uint256 = max_epoch
    for i: uint256 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].ts <= _timestamp:
            _min = _mid
        else:
            _max = _mid - 1
    return _min


@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: uint256 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
    return convert(last_point.bias, uint256)


@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 extcall SmartWalletChecker(checker).check(addr):
                return
        raise "Smart contract depositors not allowed"


@internal
def _checkpoint(addr: address, old_locked: LockedBalance, new_locked: LockedBalance):
    """
    @notice Record global and per-user data to checkpoint
    @param addr User's wallet address. No user checkpoint if 0x0
    @param old_locked Pevious locked amount / end lock time for the user
    @param new_locked New locked amount / end lock time for the user
    """
    u_old: Point = empty(Point)
    u_new: Point = empty(Point)
    old_dslope: int128 = 0
    new_dslope: int128 = 0
    _epoch: uint256 = self.epoch

    if addr != empty(address):
        # Calculate slopes and biases
        # Kept at zero when they have to
        if old_locked.end > block.timestamp and old_locked.amount > 0:
            u_old.slope = old_locked.amount // convert(MAXTIME, int128)
            u_old.bias = u_old.slope * convert(old_locked.end - block.timestamp, int128)
        if new_locked.end > block.timestamp and new_locked.amount > 0:
            u_new.slope = new_locked.amount // convert(MAXTIME, int128)
            u_new.bias = u_new.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_dslope = self.slope_changes[old_locked.end]
        if new_locked.end != 0:
            if new_locked.end == old_locked.end:
                new_dslope = old_dslope
            else:
                new_dslope = self.slope_changes[new_locked.end]

    last_point: Point = Point(bias=0, slope=0, ts=block.timestamp, blk=block.number)
    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
    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

    # Go over weeks to fill history and calculate what the current point is
    t_i: uint256 = (last_checkpoint // WEEK) * WEEK
    for i: uint256 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
        t_i += WEEK
        d_slope: int128 = 0
        if t_i > block.timestamp:
            t_i = block.timestamp
        else:
            d_slope = self.slope_changes[t_i]
        last_point.bias -= last_point.slope * convert(t_i - last_checkpoint, int128)
        last_point.slope += d_slope
        if last_point.bias < 0:  # This can happen
            last_point.bias = 0
        if last_point.slope < 0:  # This cannot happen - just in case
            last_point.slope = 0
        last_checkpoint = t_i
        last_point.ts = t_i
        last_point.blk = initial_last_point.blk + block_slope * (t_i - initial_last_point.ts) // MULTIPLIER
        _epoch += 1
        if t_i == block.timestamp:
            last_point.blk = block.number
            break
        else:
            self.point_history[_epoch] = last_point

    self.epoch = _epoch
    # Now point_history is filled until t=now

    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 += (u_new.slope - u_old.slope)
        last_point.bias += (u_new.bias - u_old.bias)
        if last_point.slope < 0:
            last_point.slope = 0
        if last_point.bias < 0:
            last_point.bias = 0

    # Record the changed point into history
    self.point_history[_epoch] = last_point

    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_dslope was <something> - u_old.slope, so we cancel that
            old_dslope += u_old.slope
            if new_locked.end == old_locked.end:
                old_dslope -= u_new.slope  # It was a new deposit, not extension
            self.slope_changes[old_locked.end] = old_dslope

        if new_locked.end > block.timestamp:
            if new_locked.end > old_locked.end:
                new_dslope -= u_new.slope  # old slope disappeared at this point
                self.slope_changes[new_locked.end] = new_dslope
            # else: we recorded it already in old_dslope

        # Now handle user history
        user_epoch: uint256 = self.user_point_epoch[addr] + 1

        self.user_point_epoch[addr] = user_epoch
        u_new.ts = block.timestamp
        u_new.blk = block.number
        self.user_point_history[addr][user_epoch] = u_new


@internal
def _deposit_for(_addr: address, _value: uint256, unlock_time: uint256, locked_balance: LockedBalance, type: int128):
    """
    @notice Deposit and lock tokens for a user
    @param _addr User's wallet address
    @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
    """
    _locked: LockedBalance = locked_balance
    supply_before: uint256 = self.supply

    self.supply = supply_before + _value
    old_locked: LockedBalance = _locked
    # Adding to existing lock, or if a lock is expired - creating a new one
    _locked.amount += convert(_value, int128)
    if unlock_time != 0:
        _locked.end = unlock_time
    self.locked[_addr] = _locked

    # Possibilities:
    # Both old_locked.end could be current or expired (>/< block.timestamp)
    # value == 0 (extend lock) or value > 0 (add to lock or extend lock)
    # _locked.end > block.timestamp (always)
    self._checkpoint(_addr, old_locked, _locked)

    if _value != 0:
        assert extcall ERC20(TOKEN).transferFrom(_addr, self, _value)

    log Deposit(_addr, _value, _locked.end, type, block.timestamp)
    log Supply(supply_before, supply_before + _value)

# !SECTION INTERNAL UTILITIES

Contract Security Audit

Contract ABI

API
[{"name":"Deposit","inputs":[{"name":"provider","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":"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":"NewPendingAdmin","inputs":[{"name":"new_pending_admin","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"NewAdmin","inputs":[{"name":"new_admin","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"NewPendingSmartWalletChecker","inputs":[{"name":"new_pending_smart_wallet_checker","type":"address","indexed":true}],"anonymous":false,"type":"event"},{"name":"NewSmartWalletChecker","inputs":[{"name":"new_smart_wallet_checker","type":"address","indexed":true}],"anonymous":false,"type":"event"},{"name":"BurnUnlockFuse","inputs":[],"anonymous":false,"type":"event"},{"name":"ApproveAirdrop","inputs":[{"name":"locker","type":"address","indexed":true},{"name":"airdropper","type":"address","indexed":true}],"anonymous":false,"type":"event"},{"stateMutability":"view","type":"function","name":"token","inputs":[],"outputs":[{"name":"","type":"address"}]},{"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":"decimals","inputs":[],"outputs":[{"name":"","type":"uint8"}]},{"stateMutability":"view","type":"function","name":"get_last_user_slope","inputs":[{"name":"addr","type":"address"}],"outputs":[{"name":"","type":"int128"}]},{"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":"locked__end","inputs":[{"name":"_addr","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"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":"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_unlock_time","inputs":[{"name":"_unlock_time","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"withdraw","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"approve_airdrop","inputs":[{"name":"airdropper","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"airdrop","inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_unlock_time","type":"uint256"}],"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":"burn_unlock_fuse","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"change_pending_admin","inputs":[{"name":"new_pending_admin","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"claim_admin","inputs":[],"outputs":[]},{"stateMutability":"view","type":"function","name":"pending_admin","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"admin","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":"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":"epoch","inputs":[],"outputs":[{"name":"","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"}]}]},{"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":"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"}]}]},{"stateMutability":"view","type":"function","name":"unlock_fuse","inputs":[],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"allow_airdrop","inputs":[{"name":"arg0","type":"address"},{"name":"arg1","type":"address"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"token_addr","type":"address"},{"name":"_name","type":"string"},{"name":"_symbol","type":"string"},{"name":"_admin","type":"address"},{"name":"_smart_wallet_checker","type":"address"}],"outputs":[]}]

612b3c515034610199576020612c2f5f395f518060a01c610199576040526020612c4f5f395f51602081612c2f015f395f516040811161019957506020602082612c2f015f395f51018082612c2f0160603950506020612c6f5f395f51602081612c2f015f395f516020811161019957506020602082612c2f015f395f51018082612c2f0160c03950506020612c8f5f395f518060a01c61019957610100526020612caf5f395f518060a01c6101995761012052610100511561019957604051612a7c526101005160015543600d5542600c556101205160055560405163313ce567610160526020610160600461017c845afa6100fe573d5f5f3e3d5ffd5b3d602081183d602010021880610160016101801161019957610160518060081c610199576101a052506101a0905051610140526020606051015f81601f0160051c6003811161019957801561016e57905b8060051b606001518160051b602001612a7c015260010181811861014f575b50505060c051612afc5260e051612b1c5261014051612b3c52612a7c61019d61000039612b5c610000f35b5f80fd5f3560e01c60026021820660011b612a3a01601e395f51565b63fc0c546a8118611c175734612a36576020612a7c60403960206040f35b6306fdde03811861008c5734612a36576020806040528060400160206020612a9c5f395f510180612a9c8339508051806020830101601f825f03163682375050601f19601f825160200101169050810190506040f35b6318160ddd81186100a65734612a3657426101c052610c5f565b63a3ce42d08118611c175734612a36575f543318612a3657336001555f5f557f71614071b88dee5e0b2ae578a9dd7b2ebbe9ae832ba419dc0242cd065a290b6c3360405260206040a1005b6395d89b418118611c175734612a36576020806040528060400160206020612afc5f395f510180612afc8339508051806020830101601f825f03163682375050601f19601f825160200101169050810190506040f35b63313ce5678118611c175734612a36576020612b3c60403960206040f35b637c74a17481186101ce57602436103417612a36576004358060a01c612a365760405260086040516020525f5260405f205460605260076040516020525f5260405f20606051633b9aca00811015612a365760021b810190506001810190505460805260206080f35b6370a0823181186101ed57602436103417612a36574261014052610777565b636cf492d38118611c175734612a36576c050c783eb9b5c85f2a8000000a5460405260206040f35b63da020a18811861026c57604436103417612a36576004358060a01c612a365760405260076040516020525f5260405f20602435633b9aca00811015612a365760021b810190506002810190505460605260206060f35b63e1bc2967811861069357606436103417612a36576004358060a01c612a36576103e0525f5c600114612a365760015f5d6102a86104206126ad565b61042051610400526103e0516040526102bf612774565b60443562093a808104905062093a8081028162093a80820418612a365790506104205260036103e0516020525f5260405f208054610440526001810154610460525060243515612a36574261042051116103b557602080610500526026610480527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e20746865206104a0527f66757475726500000000000000000000000000000000000000000000000000006104c052610480816105000160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06104e052806004016104fcfd5b426301e133808101818110612a3657905061042051111561044d576020806104e052601d610480527f566f74696e67206c6f636b2063616e20626520312079656172206d61780000006104a052610480816104e00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06104c052806004016104dcfd5b60016103e0516020525f5260405f2080610400516020525f5260405f2090505c6104ee576020806104e0526013610480527f41697264726f70206e6f7420616c6c6f776564000000000000000000000000006104a052610480816104e00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06104c052806004016104dcfd5b6002546104805261048051602435808201828110612a36579050905060025560406104406104a05e6104405160243580607f1c612a365780820180600f0b8118612a365790509050610440526104205161046051808281188284110218905090506104605260036103e0516020525f5260405f20610440518155610460516001820155506103e05160405260406104a060605e604061044060a05e61059161201f565b6020612a7c5f395f516323b872dd6104e052610400516105005230610520526024356105405260206104e060646104fc5f855af16105d1573d5f5f3e3d5ffd5b3d602081183d6020100218806104e00161050011612a36576104e0518060011c612a3657610560525061056090505115612a3657610460516103e0517f4566dfc29f6f11d13a418c26a02bef7c28bae749d4de47e4e6a7cddea6730d596024356104e052600461050052426105205260606104e0a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c610480516104e05261048051602435808201828110612a3657905090506105005260406104e0a15f5f5d005b6328d09d478118611c1757604436103417612a36576004358060a01c612a365760405260076040516020525f5260405f20602435633b9aca00811015612a365760021b8101905080546060526001810154608052600281015460a052600381015460c0525060806060f35b63adc63589811861073f57602436103417612a36576004358060a01c612a365760405260036040516020525f5260405f206001810190505460605260206060f35b63900cf0cf8118611c175734612a365760065460405260206040f35b62fdd58e81186108cf57604436103417612a3657602435610140525b6004358060a01c612a3657610120525f610160524261014051186107ae576008610120516020525f5260405f2054610160526107dd565b604061012060405e6008610120516020525f5260405f20546080526107d4610180611c1b565b61018051610160525b610160516107f4575f6101805260206101806108cd565b6007610120516020525f5260405f2061016051633b9aca00811015612a365760021b8101905080546101805260018101546101a05260028101546101c05260038101546101e05250610180516101a051610140516101c051808203828111612a36579050905080607f1c612a365780820280600f0b8118612a36579050905080820380600f0b8118612a365790509050610180527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61018051136108b8575f610180525b610180515f8112612a36576102005260206102005bf35b63eb1b68ad8118611c1757602436103417612a36576004358060a01c612a36576040526001543318612a36576040515f557f69d78e38a01985fbb1462961809b4b2d65531bc93b2b94037f3334b82ca4a75660405160605260206060a1005b634ee2cd7e8118610beb57604436103417612a36576004358060a01c612a3657610120524360243511612a3657610120516040526024356060526008610120516020525f5260405f2054608052610986610160611cd0565b61016051610140526007610120516020525f5260405f2061014051633b9aca00811015612a365760021b8101905080546101605260018101546101805260028101546101a05260038101546101c052506006546101e0526024356040526101e0516060526109f5610220611d85565b6102205161020052610200516c01431e0fae6d7217caa0000000811015612a365760021b600a01805461022052600181015461024052600281015461026052600381015461028052506040366102a0376101e0516102005110610a85574361028051808203828111612a3657905090506102a0524261026051808203828111612a3657905090506102c052610b08565b6102005160018101818110612a365790506c01431e0fae6d7217caa0000000811015612a365760021b600a0180546102e052600181015461030052600281015461032052600381015461034052506103405161028051808203828111612a3657905090506102a0526103205161026051808203828111612a3657905090506102c0525b610260516102e0526102a05115610b6e576102e0516102c05160243561028051808203828111612a365790509050808202811583838304141715612a3657905090506102a0518015612a365780820490509050808201828110612a3657905090506102e0525b61016051610180516102e0516101a051808203828111612a36579050905080607f1c612a365780820280600f0b8118612a36579050905080820380600f0b8118612a365790509050610160525f610160511215610bd4575f610300526020610300610be9565b610160515f8112612a36576103005260206103005bf35b63d1febfb98118611c1757602436103417612a36576004356c01431e0fae6d7217caa0000000811015612a365760021b600a01805460405260018101546060526002810154608052600381015460a0525060806040f35b63bd85b0398118610d1557602436103417612a36576004356101c0525b5f6101e052426101c05118610c7a576006546101e052610c9b565b6101c051604052600654606052610c92610200611e30565b610200516101e0525b6101e051610cb2575f610200526020610200610d13565b6101e0516c01431e0fae6d7217caa0000000811015612a365760021b600a01805461020052600181015461022052600281015461024052600381015461026052506020608061020060405e6101c05160c052610d0f610280611edb565b6102805bf35b63981b24d08118610f1157602436103417612a36574360043511612a36576006546101c0526004356040526101c051606052610d52610200611d85565b610200516101e0526101e0516c01431e0fae6d7217caa0000000811015612a365760021b600a01805461020052600181015461022052600281015461024052600381015461026052505f610280526101c0516101e05110610e1c57436102605114610ede5760043561026051808203828111612a3657905090504261024051808203828111612a365790509050808202811583838304141715612a3657905090504361026051808203828111612a3657905090508015612a36578082049050905061028052610ede565b6101e05160018101818110612a365790506c01431e0fae6d7217caa0000000811015612a365760021b600a0180546102a05260018101546102c05260028101546102e05260038101546103005250610300516102605114610ede5760043561026051808203828111612a3657905090506102e05161024051808203828111612a365790509050808202811583838304141715612a3657905090506103005161026051808203828111612a3657905090508015612a365780820490509050610280525b6020608061020060405e6102405161028051808201828110612a36579050905060c052610f0c6102a0611edb565b6102a0f35b63cbf9fe5f8118611c1757602436103417612a36576004358060a01c612a365760405260036040516020525f5260405f20805460605260018101546080525060406060f35b63c2c4c5c18118611c175734612a365760a036604037610f7461201f565b005b6365fc3873811861120157604436103417612a36575f5c600114612a365760015f5d610fa36106006126ad565b610600516105e0526105e051604052610fba612774565b60243562093a808104905062093a8081028162093a80820418612a365790506106005260036105e0516020525f5260405f208054610620526001810154610640525060043515612a3657610620511561108a576020806106c0526019610660527f5769746864726177206f6c6420746f6b656e732066697273740000000000000061068052610660816106c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06106a052806004016106bcfd5b426106005111611136576020806106e0526026610660527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e2074686520610680527f66757475726500000000000000000000000000000000000000000000000000006106a052610660816106e00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06106c052806004016106dcfd5b426301e133808101818110612a365790506106005111156111ce576020806106c052601d610660527f566f74696e67206c6f636b2063616e20626520312079656172206d617800000061068052610660816106c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06106a052806004016106bcfd5b6105e0516103e05260043561040052610600516104205260406106206104405e6001610480526111fc612881565b5f5f5d005b6384782ac88118611c1757604436103417612a36576004358060a01c612a36576040526024358060a01c612a365760605260016040516020525f5260405f20806060516020525f5260405f2090505c60805260206080f35b634957677c8118611c1757602436103417612a36575f5c600114612a365760015f5d6112866106006126ad565b610600516105e0526105e05160405261129d612774565b60036105e0516020525f5260405f208054610600526001810154610620525060043515612a3657600161060051121561134d576020806106a0526016610640527f4e6f206578697374696e67206c6f636b20666f756e640000000000000000000061066052610640816106a00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0610680528060040161069cfd5b4261062051116113f9576020806106c0526024610640527f43616e6e6f742061646420746f2065787069726564206c6f636b2e2057697468610660527f647261770000000000000000000000000000000000000000000000000000000061068052610640816106c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06106a052806004016106bcfd5b6105e0516103e052600435610400525f6104205260406106006104405e600261048052611424612881565b5f5f5d005b63eff7a6128118611c1757602436103417612a36575f5c600114612a365760015f5d6114566106006126ad565b610600516105e0526105e05160405261146d612774565b60036105e0516020525f5260405f208054610600526001810154610620525060043562093a808104905062093a8081028162093a80820418612a3657905061064052426106205111611536576020806106c052600c610660527f4c6f636b2065787069726564000000000000000000000000000000000000000061068052610660816106c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06106a052806004016106bcfd5b60016106005112156115bf576020806106c0526011610660527f4e6f7468696e67206973206c6f636b656400000000000000000000000000000061068052610660816106c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06106a052806004016106bcfd5b610620516106405111611649576020806106c052601f610660527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e0061068052610660816106c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06106a052806004016106bcfd5b426301e133808101818110612a365790506106405111156116e1576020806106c052601d610660527f566f74696e67206c6f636b2063616e20626520312079656172206d617800000061068052610660816106c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06106a052806004016106bcfd5b6105e0516103e0525f61040052610640516104205260406106006104405e60036104805261170d612881565b5f5f5d005b633ccfd60b8118611c175734612a36575f5c600114612a365760015f5d61173a6104006126ad565b610400516103e05260036103e0516020525f5260405f208054610400526001810154610420525061042051421015611780576c050c783eb9b5c85f2a8000000a54611783565b60015b611829576020806104c052603c610440527f546865206c6f636b206469646e277420657870697265206f722074686520756e610460527f6c6f636b206675736520686173206e6f74206265656e206275726e740000000061048052610440816104c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06104a052806004016104bcfd5b610400515f8112612a36576104405260406104006104605e5f610420525f6104005260036103e0516020525f5260405f20610400518155610420516001820155506002546104a0526104a05161044051808203828111612a3657905090506002556103e051604052604061046060605e604061040060a05e6118a961201f565b6020612a7c5f395f5163a9059cbb6104c0526103e0516104e052610440516105005260206104c060446104dc5f855af16118e5573d5f5f3e3d5ffd5b3d602081183d6020100218806104c0016104e011612a36576104c0518060011c612a3657610520525061052090505115612a36576103e0517ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568610440516104c052426104e05260406104c0a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c6104a0516104c0526104a05161044051808203828111612a3657905090506104e05260406104c0a15f5f5d005b632280c1318118611c1757602436103417612a36576004358060a01c612a3657610100526119ce6101406126ad565b610140516101205260016001610120516020525f5260405f2080610100516020525f5260405f2090505d61010051610120517fde36889f835a400f5f83816b33e0db11b37fbc69cea08db9877f7f86b5b383045f610140a3005b6357f901e28118611c1757602436103417612a36576004358060a01c612a36576040526001543318612a36576040516004556040517f4f81a6dc9d272c26f62c023b68dad221344ba9b3f4c45536021c13f81a3d984a5f6060a2005b638e5b490f8118611c175734612a36576001543318612a36576004546040526040516005556040517f5cbaa8f81c60615da12ac3c0a38416550eb1c316758654aa707a3062c7b5fe7e5f6060a2005b63d6ecc5508118611c175734612a36576001543318612a365760016c050c783eb9b5c85f2a8000000a557fec2f25d7843f1f9cc8328c327fb0b7184fbba070875a4e644ee18cb3ae39100e5f6040a1005b63e67192878118611c175734612a36575f5460405260206040f35b63f851a4408118611b5b5734612a365760015460405260206040f35b63010ae7578118611c1757602436103417612a36576004358060a01c612a365760405260086040516020525f5260405f205460605260206060f35b63047fc9aa8118611c175734612a365760025460405260206040f35b638ff36fd18118611c175734612a365760045460405260206040f35b637175d4f78118611c175734612a365760055460405260206040f35b63711974848118611c1757602436103417612a365760096004356020525f5260405f205460405260206040f35b5f5ffd5b5f60a05260805160c0525f6080905b8060e05260c05160a0511015611cc65760a05160c051808201828110612a36579050905060018101818110612a365790508060011c90506101005260605160076040516020525f5260405f2061010051633b9aca00811015612a365760021b81019050600281019050541115611cb3576101005160018103818111612a3657905060c052611cbb565b6101005160a0525b600101818118611c2a575b505060a051815250565b5f60a05260805160c0525f6080905b8060e05260c05160a0511015611d7b5760a05160c051808201828110612a36579050905060018101818110612a365790508060011c90506101005260605160076040516020525f5260405f2061010051633b9aca00811015612a365760021b81019050600381019050541115611d68576101005160018103818111612a3657905060c052611d70565b6101005160a0525b600101818118611cdf575b505060a051815250565b5f60805260605160a0525f6080905b8060c05260a0516080511015611e265760805160a051808201828110612a36579050905060018101818110612a365790508060011c905060e05260405160e0516c01431e0fae6d7217caa0000000811015612a365760021b600a01600381019050541115611e145760e05160018103818111612a3657905060a052611e1b565b60e0516080525b600101818118611d94575b5050608051815250565b5f60805260605160a0525f6080905b8060c05260a0516080511015611ed15760805160a051808201828110612a36579050905060018101818110612a365790508060011c905060e05260405160e0516c01431e0fae6d7217caa0000000811015612a365760021b600a01600281019050541115611ebf5760e05160018103818111612a3657905060a052611ec6565b60e0516080525b600101818118611e3f575b5050608051815250565b6080604060e05e6101205162093a808104905062093a8081028162093a80820418612a36579050610160525f60ff905b80610180526101605162093a808101818110612a36579050610160525f6101a05260c0516101605111611f51576009610160516020525f5260405f20546101a052611f59565b60c051610160525b60e051610100516101605161012051808203828111612a36579050905080607f1c612a365780820280600f0b8118612a36579050905080820380600f0b8118612a36579050905060e05260c051610160511815611fe057610100516101a05180820180600f0b8118612a365790509050610100526101605161012052600101818118611f0b575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60e05113612010575f60e0525b60e0515f8112612a3657815250565b6101403660e0376006546102205260405115612179574260805111612044575f61204c565b600160605112155b156120b3576060516301e13380607f1c612a36576301e133808015612a365780820580600f0b8118612a365790509050610100526101005160805142808203828111612a36579050905080607f1c612a365780820280600f0b8118612a36579050905060e0525b4260c051116120c2575f6120ca565b600160a05112155b156121325760a0516301e13380607f1c612a36576301e133808015612a365780820580600f0b8118612a365790509050610180526101805160c05142808203828111612a36579050905080607f1c612a365780820280600f0b8118612a365790509050610160525b60096080516020525f5260405f20546101e05260c051156121795760805160c05118612165576101e05161020052612179565b600960c0516020525f5260405f2054610200525b604036610240374261028052436102a05261022051156121d557610220516c01431e0fae6d7217caa0000000811015612a365760021b600a0180546102405260018101546102605260028101546102805260038101546102a052505b610280516102c05260806102406102e05e5f610360526102805142111561224c57436102a051808203828111612a365790509050670de0b6b3a7640000810281670de0b6b3a7640000820418612a365790504261028051808203828111612a3657905090508015612a365780820490509050610360525b6102c05162093a808104905062093a8081028162093a80820418612a36579050610380525f60ff905b806103a0526103805162093a808101818110612a36579050610380525f6103c0524261038051116122b9576009610380516020525f5260405f20546103c0526122bf565b42610380525b6102405161026051610380516102c051808203828111612a36579050905080607f1c612a365780820280600f0b8118612a36579050905080820380600f0b8118612a36579050905061024052610260516103c05180820180600f0b8118612a365790509050610260527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6102405113612358575f610240525b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6102605113612388575f610260525b610380516102c052610380516102805261034051610360516103805161032051808203828111612a365790509050808202811583838304141715612a365790509050670de0b6b3a764000081049050808201828110612a3657905090506102a0526102205160018101818110612a365790506102205242610380511861241257436102a05261245e565b610220516c01431e0fae6d7217caa0000000811015612a365760021b600a016102405181556102605160018201556102805160028201556102a051600382015550600101818118612275575b505061022051600655604051156125325761026051610180516101005180820380600f0b8118612a36579050905080820180600f0b8118612a36579050905061026052610240516101605160e05180820380600f0b8118612a36579050905080820180600f0b8118612a365790509050610240527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6102605113612502575f610260525b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6102405113612532575f610240525b610220516c01431e0fae6d7217caa0000000811015612a365760021b600a016102405181556102605160018201556102805160028201556102a051600382015550604051156126ab574260805111156125df576101e0516101005180820180600f0b8118612a3657905090506101e05260805160c051186125cb576101e0516101805180820380600f0b8118612a3657905090506101e0525b6101e05160096080516020525f5260405f20555b4260c05111156126265760805160c051111561262657610200516101805180820380600f0b8118612a3657905090506102005261020051600960c0516020525f5260405f20555b60086040516020525f5260405f205460018101818110612a365790506103a0526103a05160086040516020525f5260405f2055426101a052436101c05260076040516020525f5260405f206103a051633b9aca00811015612a365760021b810190506101605181556101805160018201556101a05160028201556101c0516003820155505b565b336e2fd5aeb385d324b580fca7c83823a081186126cb5760016126de565b6dd9ecebf3c23529de49815dac1c4c8118155b90506126ed5733815250612772565b335a5f60a05260a050602060e060a05160c08585fa90509050612712573d5f5f3e3d5ffd5b3d602081183d602010021860c05260c06020815101808260605e50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020606051031360011615612a36575f806080015190508060a01c612a36578152505b565b326040511461287f57600554606052606051156127e35760605163c23697a860805260405160a052602060806024609c5f855af16127b4573d5f5f3e3d5ffd5b3d602081183d60201002188060800160a011612a36576080518060011c612a365760c0525060c090505161287f575b6020806101005260256080527f536d61727420636f6e7472616374206465706f7369746f7273206e6f7420616c60a0527f6c6f77656400000000000000000000000000000000000000000000000000000060c0526080816101000160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a060e0528060040160fcfd5b565b60406104406104a05e6002546104e0526104e05161040051808201828110612a36579050905060025560406104a06105005e6104a0516104005180607f1c612a365780820180600f0b8118612a3657905090506104a05261042051156128ea57610420516104c0525b60036103e0516020525f5260405f206104a05181556104c0516001820155506103e051604052604061050060605e60406104a060a05e61292861201f565b61040051156129a7576020612a7c5f395f516323b872dd610540526103e051610560523061058052610400516105a0526020610540606461055c5f855af1612972573d5f5f3e3d5ffd5b3d602081183d6020100218806105400161056011612a3657610540518060011c612a36576105c052506105c090505115612a36575b6104c0516103e0517f4566dfc29f6f11d13a418c26a02bef7c28bae749d4de47e4e6a7cddea6730d596104005161054052610480516105605242610580526060610540a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c6104e051610540526104e05161040051808201828110612a365790509050610560526040610540a1565b5f80fd17121bb21c171a841ad31bea06fe1429092e0f560018075b1b241c17199f1c171c171b3f00f101650f760c421b961a2801471c171bce1c170036021512591c171c1784192a7c81184218e0a1657679706572830004000016000000000000000000000000000000c396558ffbab5ea628f39658bdf61345b300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000009a8fee232dcf73060af348a1b62cdb0a19852d1300000000000000000000000000000041cb569fdbac52b95b91c52263cea3f3ce0000000000000000000000000000000000000000000000000000000000000013566f746520457363726f7765642042554e4e49000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007766542554e4e4900000000000000000000000000000000000000000000000000

Deployed Bytecode

0x5f3560e01c60026021820660011b612a3a01601e395f51565b63fc0c546a8118611c175734612a36576020612a7c60403960206040f35b6306fdde03811861008c5734612a36576020806040528060400160206020612a9c5f395f510180612a9c8339508051806020830101601f825f03163682375050601f19601f825160200101169050810190506040f35b6318160ddd81186100a65734612a3657426101c052610c5f565b63a3ce42d08118611c175734612a36575f543318612a3657336001555f5f557f71614071b88dee5e0b2ae578a9dd7b2ebbe9ae832ba419dc0242cd065a290b6c3360405260206040a1005b6395d89b418118611c175734612a36576020806040528060400160206020612afc5f395f510180612afc8339508051806020830101601f825f03163682375050601f19601f825160200101169050810190506040f35b63313ce5678118611c175734612a36576020612b3c60403960206040f35b637c74a17481186101ce57602436103417612a36576004358060a01c612a365760405260086040516020525f5260405f205460605260076040516020525f5260405f20606051633b9aca00811015612a365760021b810190506001810190505460805260206080f35b6370a0823181186101ed57602436103417612a36574261014052610777565b636cf492d38118611c175734612a36576c050c783eb9b5c85f2a8000000a5460405260206040f35b63da020a18811861026c57604436103417612a36576004358060a01c612a365760405260076040516020525f5260405f20602435633b9aca00811015612a365760021b810190506002810190505460605260206060f35b63e1bc2967811861069357606436103417612a36576004358060a01c612a36576103e0525f5c600114612a365760015f5d6102a86104206126ad565b61042051610400526103e0516040526102bf612774565b60443562093a808104905062093a8081028162093a80820418612a365790506104205260036103e0516020525f5260405f208054610440526001810154610460525060243515612a36574261042051116103b557602080610500526026610480527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e20746865206104a0527f66757475726500000000000000000000000000000000000000000000000000006104c052610480816105000160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06104e052806004016104fcfd5b426301e133808101818110612a3657905061042051111561044d576020806104e052601d610480527f566f74696e67206c6f636b2063616e20626520312079656172206d61780000006104a052610480816104e00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06104c052806004016104dcfd5b60016103e0516020525f5260405f2080610400516020525f5260405f2090505c6104ee576020806104e0526013610480527f41697264726f70206e6f7420616c6c6f776564000000000000000000000000006104a052610480816104e00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06104c052806004016104dcfd5b6002546104805261048051602435808201828110612a36579050905060025560406104406104a05e6104405160243580607f1c612a365780820180600f0b8118612a365790509050610440526104205161046051808281188284110218905090506104605260036103e0516020525f5260405f20610440518155610460516001820155506103e05160405260406104a060605e604061044060a05e61059161201f565b6020612a7c5f395f516323b872dd6104e052610400516105005230610520526024356105405260206104e060646104fc5f855af16105d1573d5f5f3e3d5ffd5b3d602081183d6020100218806104e00161050011612a36576104e0518060011c612a3657610560525061056090505115612a3657610460516103e0517f4566dfc29f6f11d13a418c26a02bef7c28bae749d4de47e4e6a7cddea6730d596024356104e052600461050052426105205260606104e0a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c610480516104e05261048051602435808201828110612a3657905090506105005260406104e0a15f5f5d005b6328d09d478118611c1757604436103417612a36576004358060a01c612a365760405260076040516020525f5260405f20602435633b9aca00811015612a365760021b8101905080546060526001810154608052600281015460a052600381015460c0525060806060f35b63adc63589811861073f57602436103417612a36576004358060a01c612a365760405260036040516020525f5260405f206001810190505460605260206060f35b63900cf0cf8118611c175734612a365760065460405260206040f35b62fdd58e81186108cf57604436103417612a3657602435610140525b6004358060a01c612a3657610120525f610160524261014051186107ae576008610120516020525f5260405f2054610160526107dd565b604061012060405e6008610120516020525f5260405f20546080526107d4610180611c1b565b61018051610160525b610160516107f4575f6101805260206101806108cd565b6007610120516020525f5260405f2061016051633b9aca00811015612a365760021b8101905080546101805260018101546101a05260028101546101c05260038101546101e05250610180516101a051610140516101c051808203828111612a36579050905080607f1c612a365780820280600f0b8118612a36579050905080820380600f0b8118612a365790509050610180527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61018051136108b8575f610180525b610180515f8112612a36576102005260206102005bf35b63eb1b68ad8118611c1757602436103417612a36576004358060a01c612a36576040526001543318612a36576040515f557f69d78e38a01985fbb1462961809b4b2d65531bc93b2b94037f3334b82ca4a75660405160605260206060a1005b634ee2cd7e8118610beb57604436103417612a36576004358060a01c612a3657610120524360243511612a3657610120516040526024356060526008610120516020525f5260405f2054608052610986610160611cd0565b61016051610140526007610120516020525f5260405f2061014051633b9aca00811015612a365760021b8101905080546101605260018101546101805260028101546101a05260038101546101c052506006546101e0526024356040526101e0516060526109f5610220611d85565b6102205161020052610200516c01431e0fae6d7217caa0000000811015612a365760021b600a01805461022052600181015461024052600281015461026052600381015461028052506040366102a0376101e0516102005110610a85574361028051808203828111612a3657905090506102a0524261026051808203828111612a3657905090506102c052610b08565b6102005160018101818110612a365790506c01431e0fae6d7217caa0000000811015612a365760021b600a0180546102e052600181015461030052600281015461032052600381015461034052506103405161028051808203828111612a3657905090506102a0526103205161026051808203828111612a3657905090506102c0525b610260516102e0526102a05115610b6e576102e0516102c05160243561028051808203828111612a365790509050808202811583838304141715612a3657905090506102a0518015612a365780820490509050808201828110612a3657905090506102e0525b61016051610180516102e0516101a051808203828111612a36579050905080607f1c612a365780820280600f0b8118612a36579050905080820380600f0b8118612a365790509050610160525f610160511215610bd4575f610300526020610300610be9565b610160515f8112612a36576103005260206103005bf35b63d1febfb98118611c1757602436103417612a36576004356c01431e0fae6d7217caa0000000811015612a365760021b600a01805460405260018101546060526002810154608052600381015460a0525060806040f35b63bd85b0398118610d1557602436103417612a36576004356101c0525b5f6101e052426101c05118610c7a576006546101e052610c9b565b6101c051604052600654606052610c92610200611e30565b610200516101e0525b6101e051610cb2575f610200526020610200610d13565b6101e0516c01431e0fae6d7217caa0000000811015612a365760021b600a01805461020052600181015461022052600281015461024052600381015461026052506020608061020060405e6101c05160c052610d0f610280611edb565b6102805bf35b63981b24d08118610f1157602436103417612a36574360043511612a36576006546101c0526004356040526101c051606052610d52610200611d85565b610200516101e0526101e0516c01431e0fae6d7217caa0000000811015612a365760021b600a01805461020052600181015461022052600281015461024052600381015461026052505f610280526101c0516101e05110610e1c57436102605114610ede5760043561026051808203828111612a3657905090504261024051808203828111612a365790509050808202811583838304141715612a3657905090504361026051808203828111612a3657905090508015612a36578082049050905061028052610ede565b6101e05160018101818110612a365790506c01431e0fae6d7217caa0000000811015612a365760021b600a0180546102a05260018101546102c05260028101546102e05260038101546103005250610300516102605114610ede5760043561026051808203828111612a3657905090506102e05161024051808203828111612a365790509050808202811583838304141715612a3657905090506103005161026051808203828111612a3657905090508015612a365780820490509050610280525b6020608061020060405e6102405161028051808201828110612a36579050905060c052610f0c6102a0611edb565b6102a0f35b63cbf9fe5f8118611c1757602436103417612a36576004358060a01c612a365760405260036040516020525f5260405f20805460605260018101546080525060406060f35b63c2c4c5c18118611c175734612a365760a036604037610f7461201f565b005b6365fc3873811861120157604436103417612a36575f5c600114612a365760015f5d610fa36106006126ad565b610600516105e0526105e051604052610fba612774565b60243562093a808104905062093a8081028162093a80820418612a365790506106005260036105e0516020525f5260405f208054610620526001810154610640525060043515612a3657610620511561108a576020806106c0526019610660527f5769746864726177206f6c6420746f6b656e732066697273740000000000000061068052610660816106c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06106a052806004016106bcfd5b426106005111611136576020806106e0526026610660527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e2074686520610680527f66757475726500000000000000000000000000000000000000000000000000006106a052610660816106e00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06106c052806004016106dcfd5b426301e133808101818110612a365790506106005111156111ce576020806106c052601d610660527f566f74696e67206c6f636b2063616e20626520312079656172206d617800000061068052610660816106c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06106a052806004016106bcfd5b6105e0516103e05260043561040052610600516104205260406106206104405e6001610480526111fc612881565b5f5f5d005b6384782ac88118611c1757604436103417612a36576004358060a01c612a36576040526024358060a01c612a365760605260016040516020525f5260405f20806060516020525f5260405f2090505c60805260206080f35b634957677c8118611c1757602436103417612a36575f5c600114612a365760015f5d6112866106006126ad565b610600516105e0526105e05160405261129d612774565b60036105e0516020525f5260405f208054610600526001810154610620525060043515612a3657600161060051121561134d576020806106a0526016610640527f4e6f206578697374696e67206c6f636b20666f756e640000000000000000000061066052610640816106a00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0610680528060040161069cfd5b4261062051116113f9576020806106c0526024610640527f43616e6e6f742061646420746f2065787069726564206c6f636b2e2057697468610660527f647261770000000000000000000000000000000000000000000000000000000061068052610640816106c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06106a052806004016106bcfd5b6105e0516103e052600435610400525f6104205260406106006104405e600261048052611424612881565b5f5f5d005b63eff7a6128118611c1757602436103417612a36575f5c600114612a365760015f5d6114566106006126ad565b610600516105e0526105e05160405261146d612774565b60036105e0516020525f5260405f208054610600526001810154610620525060043562093a808104905062093a8081028162093a80820418612a3657905061064052426106205111611536576020806106c052600c610660527f4c6f636b2065787069726564000000000000000000000000000000000000000061068052610660816106c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06106a052806004016106bcfd5b60016106005112156115bf576020806106c0526011610660527f4e6f7468696e67206973206c6f636b656400000000000000000000000000000061068052610660816106c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06106a052806004016106bcfd5b610620516106405111611649576020806106c052601f610660527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e0061068052610660816106c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06106a052806004016106bcfd5b426301e133808101818110612a365790506106405111156116e1576020806106c052601d610660527f566f74696e67206c6f636b2063616e20626520312079656172206d617800000061068052610660816106c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06106a052806004016106bcfd5b6105e0516103e0525f61040052610640516104205260406106006104405e60036104805261170d612881565b5f5f5d005b633ccfd60b8118611c175734612a36575f5c600114612a365760015f5d61173a6104006126ad565b610400516103e05260036103e0516020525f5260405f208054610400526001810154610420525061042051421015611780576c050c783eb9b5c85f2a8000000a54611783565b60015b611829576020806104c052603c610440527f546865206c6f636b206469646e277420657870697265206f722074686520756e610460527f6c6f636b206675736520686173206e6f74206265656e206275726e740000000061048052610440816104c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06104a052806004016104bcfd5b610400515f8112612a36576104405260406104006104605e5f610420525f6104005260036103e0516020525f5260405f20610400518155610420516001820155506002546104a0526104a05161044051808203828111612a3657905090506002556103e051604052604061046060605e604061040060a05e6118a961201f565b6020612a7c5f395f5163a9059cbb6104c0526103e0516104e052610440516105005260206104c060446104dc5f855af16118e5573d5f5f3e3d5ffd5b3d602081183d6020100218806104c0016104e011612a36576104c0518060011c612a3657610520525061052090505115612a36576103e0517ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568610440516104c052426104e05260406104c0a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c6104a0516104c0526104a05161044051808203828111612a3657905090506104e05260406104c0a15f5f5d005b632280c1318118611c1757602436103417612a36576004358060a01c612a3657610100526119ce6101406126ad565b610140516101205260016001610120516020525f5260405f2080610100516020525f5260405f2090505d61010051610120517fde36889f835a400f5f83816b33e0db11b37fbc69cea08db9877f7f86b5b383045f610140a3005b6357f901e28118611c1757602436103417612a36576004358060a01c612a36576040526001543318612a36576040516004556040517f4f81a6dc9d272c26f62c023b68dad221344ba9b3f4c45536021c13f81a3d984a5f6060a2005b638e5b490f8118611c175734612a36576001543318612a36576004546040526040516005556040517f5cbaa8f81c60615da12ac3c0a38416550eb1c316758654aa707a3062c7b5fe7e5f6060a2005b63d6ecc5508118611c175734612a36576001543318612a365760016c050c783eb9b5c85f2a8000000a557fec2f25d7843f1f9cc8328c327fb0b7184fbba070875a4e644ee18cb3ae39100e5f6040a1005b63e67192878118611c175734612a36575f5460405260206040f35b63f851a4408118611b5b5734612a365760015460405260206040f35b63010ae7578118611c1757602436103417612a36576004358060a01c612a365760405260086040516020525f5260405f205460605260206060f35b63047fc9aa8118611c175734612a365760025460405260206040f35b638ff36fd18118611c175734612a365760045460405260206040f35b637175d4f78118611c175734612a365760055460405260206040f35b63711974848118611c1757602436103417612a365760096004356020525f5260405f205460405260206040f35b5f5ffd5b5f60a05260805160c0525f6080905b8060e05260c05160a0511015611cc65760a05160c051808201828110612a36579050905060018101818110612a365790508060011c90506101005260605160076040516020525f5260405f2061010051633b9aca00811015612a365760021b81019050600281019050541115611cb3576101005160018103818111612a3657905060c052611cbb565b6101005160a0525b600101818118611c2a575b505060a051815250565b5f60a05260805160c0525f6080905b8060e05260c05160a0511015611d7b5760a05160c051808201828110612a36579050905060018101818110612a365790508060011c90506101005260605160076040516020525f5260405f2061010051633b9aca00811015612a365760021b81019050600381019050541115611d68576101005160018103818111612a3657905060c052611d70565b6101005160a0525b600101818118611cdf575b505060a051815250565b5f60805260605160a0525f6080905b8060c05260a0516080511015611e265760805160a051808201828110612a36579050905060018101818110612a365790508060011c905060e05260405160e0516c01431e0fae6d7217caa0000000811015612a365760021b600a01600381019050541115611e145760e05160018103818111612a3657905060a052611e1b565b60e0516080525b600101818118611d94575b5050608051815250565b5f60805260605160a0525f6080905b8060c05260a0516080511015611ed15760805160a051808201828110612a36579050905060018101818110612a365790508060011c905060e05260405160e0516c01431e0fae6d7217caa0000000811015612a365760021b600a01600281019050541115611ebf5760e05160018103818111612a3657905060a052611ec6565b60e0516080525b600101818118611e3f575b5050608051815250565b6080604060e05e6101205162093a808104905062093a8081028162093a80820418612a36579050610160525f60ff905b80610180526101605162093a808101818110612a36579050610160525f6101a05260c0516101605111611f51576009610160516020525f5260405f20546101a052611f59565b60c051610160525b60e051610100516101605161012051808203828111612a36579050905080607f1c612a365780820280600f0b8118612a36579050905080820380600f0b8118612a36579050905060e05260c051610160511815611fe057610100516101a05180820180600f0b8118612a365790509050610100526101605161012052600101818118611f0b575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60e05113612010575f60e0525b60e0515f8112612a3657815250565b6101403660e0376006546102205260405115612179574260805111612044575f61204c565b600160605112155b156120b3576060516301e13380607f1c612a36576301e133808015612a365780820580600f0b8118612a365790509050610100526101005160805142808203828111612a36579050905080607f1c612a365780820280600f0b8118612a36579050905060e0525b4260c051116120c2575f6120ca565b600160a05112155b156121325760a0516301e13380607f1c612a36576301e133808015612a365780820580600f0b8118612a365790509050610180526101805160c05142808203828111612a36579050905080607f1c612a365780820280600f0b8118612a365790509050610160525b60096080516020525f5260405f20546101e05260c051156121795760805160c05118612165576101e05161020052612179565b600960c0516020525f5260405f2054610200525b604036610240374261028052436102a05261022051156121d557610220516c01431e0fae6d7217caa0000000811015612a365760021b600a0180546102405260018101546102605260028101546102805260038101546102a052505b610280516102c05260806102406102e05e5f610360526102805142111561224c57436102a051808203828111612a365790509050670de0b6b3a7640000810281670de0b6b3a7640000820418612a365790504261028051808203828111612a3657905090508015612a365780820490509050610360525b6102c05162093a808104905062093a8081028162093a80820418612a36579050610380525f60ff905b806103a0526103805162093a808101818110612a36579050610380525f6103c0524261038051116122b9576009610380516020525f5260405f20546103c0526122bf565b42610380525b6102405161026051610380516102c051808203828111612a36579050905080607f1c612a365780820280600f0b8118612a36579050905080820380600f0b8118612a36579050905061024052610260516103c05180820180600f0b8118612a365790509050610260527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6102405113612358575f610240525b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6102605113612388575f610260525b610380516102c052610380516102805261034051610360516103805161032051808203828111612a365790509050808202811583838304141715612a365790509050670de0b6b3a764000081049050808201828110612a3657905090506102a0526102205160018101818110612a365790506102205242610380511861241257436102a05261245e565b610220516c01431e0fae6d7217caa0000000811015612a365760021b600a016102405181556102605160018201556102805160028201556102a051600382015550600101818118612275575b505061022051600655604051156125325761026051610180516101005180820380600f0b8118612a36579050905080820180600f0b8118612a36579050905061026052610240516101605160e05180820380600f0b8118612a36579050905080820180600f0b8118612a365790509050610240527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6102605113612502575f610260525b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6102405113612532575f610240525b610220516c01431e0fae6d7217caa0000000811015612a365760021b600a016102405181556102605160018201556102805160028201556102a051600382015550604051156126ab574260805111156125df576101e0516101005180820180600f0b8118612a3657905090506101e05260805160c051186125cb576101e0516101805180820380600f0b8118612a3657905090506101e0525b6101e05160096080516020525f5260405f20555b4260c05111156126265760805160c051111561262657610200516101805180820380600f0b8118612a3657905090506102005261020051600960c0516020525f5260405f20555b60086040516020525f5260405f205460018101818110612a365790506103a0526103a05160086040516020525f5260405f2055426101a052436101c05260076040516020525f5260405f206103a051633b9aca00811015612a365760021b810190506101605181556101805160018201556101a05160028201556101c0516003820155505b565b336e2fd5aeb385d324b580fca7c83823a081186126cb5760016126de565b6dd9ecebf3c23529de49815dac1c4c8118155b90506126ed5733815250612772565b335a5f60a05260a050602060e060a05160c08585fa90509050612712573d5f5f3e3d5ffd5b3d602081183d602010021860c05260c06020815101808260605e50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020606051031360011615612a36575f806080015190508060a01c612a36578152505b565b326040511461287f57600554606052606051156127e35760605163c23697a860805260405160a052602060806024609c5f855af16127b4573d5f5f3e3d5ffd5b3d602081183d60201002188060800160a011612a36576080518060011c612a365760c0525060c090505161287f575b6020806101005260256080527f536d61727420636f6e7472616374206465706f7369746f7273206e6f7420616c60a0527f6c6f77656400000000000000000000000000000000000000000000000000000060c0526080816101000160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a060e0528060040160fcfd5b565b60406104406104a05e6002546104e0526104e05161040051808201828110612a36579050905060025560406104a06105005e6104a0516104005180607f1c612a365780820180600f0b8118612a3657905090506104a05261042051156128ea57610420516104c0525b60036103e0516020525f5260405f206104a05181556104c0516001820155506103e051604052604061050060605e60406104a060a05e61292861201f565b61040051156129a7576020612a7c5f395f516323b872dd610540526103e051610560523061058052610400516105a0526020610540606461055c5f855af1612972573d5f5f3e3d5ffd5b3d602081183d6020100218806105400161056011612a3657610540518060011c612a36576105c052506105c090505115612a36575b6104c0516103e0517f4566dfc29f6f11d13a418c26a02bef7c28bae749d4de47e4e6a7cddea6730d596104005161054052610480516105605242610580526060610540a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c6104e051610540526104e05161040051808201828110612a365790509050610560526040610540a1565b5f80fd17121bb21c171a841ad31bea06fe1429092e0f560018075b1b241c17199f1c171c171b3f00f101650f760c421b961a2801471c171bce1c170036021512591c171c17000000000000000000000000000000c396558ffbab5ea628f39658bdf61345b30000000000000000000000000000000000000000000000000000000000000013566f746520457363726f7765642042554e4e490000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007766542554e4e49000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000000000c396558ffbab5ea628f39658bdf61345b300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000009a8fee232dcf73060af348a1b62cdb0a19852d1300000000000000000000000000000041cb569fdbac52b95b91c52263cea3f3ce0000000000000000000000000000000000000000000000000000000000000013566f746520457363726f7765642042554e4e49000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007766542554e4e4900000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : token_addr (address): 0x000000C396558ffbAB5Ea628f39658Bdf61345b3
Arg [1] : _name (string): Vote Escrowed BUNNI
Arg [2] : _symbol (string): veBUNNI
Arg [3] : _admin (address): 0x9a8FEe232DCF73060Af348a1B62Cdb0a19852d13
Arg [4] : _smart_wallet_checker (address): 0x00000041Cb569fdBAC52b95B91c52263cea3f3cE

-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 000000000000000000000000000000c396558ffbab5ea628f39658bdf61345b3
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [3] : 0000000000000000000000009a8fee232dcf73060af348a1b62cdb0a19852d13
Arg [4] : 00000000000000000000000000000041cb569fdbac52b95b91c52263cea3f3ce
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000013
Arg [6] : 566f746520457363726f7765642042554e4e4900000000000000000000000000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000007
Arg [8] : 766542554e4e4900000000000000000000000000000000000000000000000000


Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.