Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0x2391Fc8f5E417526338F5aa3968b1851C16D894E
Balance 0 ETH
Nonce 1
Code Size 3240 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

3240 bytes
0x6003361161000c576104b0565b60003560e01c34610c565763811a40fe811861004d5760043610610c5657600454620151808101818110610c56579050421115610c565761004b6104b6565b005b63b21ed502811861006a5760043610610c565761006861075f565b005b634e71d92d81186100875760043610610c5657336102a0526100aa565b631e83409a81186101d15760243610610c56576004358060a01c610c56576102a0525b600054600214610c5657600260005560025442106100ca576100ca61075f565b6004546102c0526102c051620151808101818110610c565790504211156100f9576100f36104b6565b426102c0525b6102c05162093a808104905062093a8081028162093a80820418610c565790506102c0526102a0516040526102c051606052610136610300610984565b610300516102e0526102e051156101c5576020610c6860003960005163a9059cbb610300526102a051610320526102e051610340526020610300604461031c6000855af1610189573d600060003e3d6000fd5b60203d10610c5657610300518060011c610c56576103605261036090505115610c56576006546102e051808203828111610c5657905090506006555b60206102e06003600055f35b6344df8e70811861020e5760043610610c56577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61014052610229565b6342966c68811861034f5760243610610c5657600435610140525b61014051610160526101605119610287576020610c6860003960005163dd62ed3e61018052336101a052306101c0526020610180604461019c845afa610274573d600060003e3d6000fd5b60203d10610c5657610180905051610160525b6101605115610342576020610c686000396000516323b872dd61018052336101a052306101c052610160516101e0526020610180606461019c6000855af16102d4573d600060003e3d6000fd5b60203d10610c5657610180518060011c610c5657610200526102005050337f9ac954606f877c9c9e6deec30e9265abff5a57c7123a34777ca9321eb6c26d8e61016051610180526020610180a2600454620151808101818110610c56579050421115610342576103426104b6565b6001610180526020610180f35b63fc0c546a81186103765760043610610c56576020610c6860003960005160405260206040f35b634068aba3811861039d5760043610610c56576020610c8860003960005160405260206040f35b63834ee41781186103bc5760043610610c565760015460405260206040f35b63127dcbd381186103db5760043610610c565760025460405260206040f35b632a2a314b81186104165760243610610c56576004358060a01c610c5657604052600360405160205260005260406000205460605260206060f35b637f58e8f881186104355760043610610c565760045460405260206040f35b63edf5999781186104625760243610610c5657600560043560205260005260406000205460405260206040f35b6322b04bfc81186104815760043610610c565760065460405260206040f35b63d4dafba881186104ae5760243610610c5657600760043560205260005260406000205460405260206040f35b505b60006000fd5b6020610c686000396000516370a0823160605230608052602060606024607c845afa6104e7573d600060003e3d6000fd5b60203d10610c56576060905051604052604051600654808203828111610c56579050905060605260605161054d57426004557fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d642608052600060a05260406080a161075d565b60405160065560045460805242608051808203828111610c56579050905060a0524260045560805162093a808104905062093a8081028162093a80820418610c5657905060c052600060e05260006028905b806101005260c05162093a808101818110610c5657905060e05260e051421061066b5760a0516105d65760805160e05118156105d9565b60005b61064057600560c0516020526000526040600020805460605160e051608051808203828111610c565790509050808202811583838304141715610c56579050905060a0518015610c565780820490509050808201828110610c565790509050815550610710565b600560c05160205260005260406000208054606051808201828110610c565790509050815550610710565b60a05161067d57608051421815610680565b60005b6106e557600560c0516020526000526040600020805460605142608051808203828111610c565790509050808202811583838304141715610c56579050905060a0518015610c565780820490509050808201828110610c565790509050815550610727565b600560c05160205260005260406000208054606051808201828110610c565790509050815550610727565b60e05160805260e05160c05260010181811861059f575b50507fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d64261010052606051610120526040610100a15b565b6002546040524262093a808104905062093a8081028162093a80820418610c565790506060526020610c8860003960005163c2c4c5c1608052803b15610c5657600060806004609c6000855af16107bb573d600060003e3d6000fd5b5060006028905b806080526060516040511161097a576020610c8860003960005163b5418e3f60c0526020610c8860003960005160e05260405161010052602060c0604460dc845afa610813573d600060003e3d6000fd5b60203d10610c565760c090505160a0526020610c8860003960005163613a6bea610140526020610c886000396000516101605260a051610180526080610140604461015c845afa610869573d600060003e3d6000fd5b60803d10610c56576101405180600f0b8118610c56576101e0526101605180600f0b8118610c56576102005261018051610220526101a051610240526101e09050805160c052602081015160e052604081015161010052606081015161012052506000610140526101005160405111156108ff5760405161010051808203828111610c56579050905080607f1c610c5657610140525b60c05160e0516101405180820280600f0b8118610c56579050905080820380600f0b8118610c5657905090506000818118600083130218905060008112610c5657600760405160205260005260406000205561095a5661097a565b60405162093a808101818110610c565790506040526001018181186107c2575b5050604051600255565b60006080526020610c88600039600051638b810c3660c05260405160e052602060c0602460dc845afa6109bc573d600060003e3d6000fd5b60203d10610c565760c090505160a05260015460c05260a0516109e3576000815250610c54565b600360405160205260005260406000205460e05260e051610ade576020610c8860003960005163613a6bea610180526040516101a05260016101c0526080610180604461019c845afa610a3b573d600060003e3d6000fd5b60803d10610c56576101805180600f0b8118610c5657610220526101a05180600f0b8118610c5657610240526101c051610260526101e051610280526102209050805161010052602081015161012052604081015161014052606081015161016052506101405162093a808101818110610c5657905060018103818111610c5657905062093a808104905062093a8081028162093a80820418610c5657905060e0525b60605160e05110610af3576000815250610c54565b60c05160e0511015610b065760c05160e0525b60006032905b806101005260605160e05110610b2157610bf8565b6020610c8860003960005162fdd58e610140526040516101605260e051610180526020610140604461015c845afa610b5e573d600060003e3d6000fd5b60203d10610c56576101409050516101205261012051610b7d57610bf8565b60805161012051600560e051602052600052604060002054808202811583838304141715610c565790509050600760e0516020526000526040600020548015610c565780820490509050808201828110610c56579050905060805260e05162093a808101818110610c5657905060e052600101818118610b0c575b505060e05160036040516020526000526040600020556040517f9cdcf2f7714cca3508c7f0110b04a90a80a3a8dd0e35de99689db74d28c5383e6080516101005260e0516101205260a051610140526060610100a26080518152505b565b600080fda165767970657283000307000b00000000000000000000000041252e8691e964f7de35156b68493bab6797a27500000000000000000000000090c1f9220d90d3966fbee24045edd73e1d588ad5

Verified Source Code Partial Match

Compiler: v0.3.7+commit.6020b8bb EVM: paris
dYFIRewardPool.vy 261 lines
# @version 0.3.7
"""
@title dYFI Reward Pool
@author Curve Finance, Yearn Finance
@license MIT
"""
from vyper.interfaces import ERC20

interface VotingYFI:
    def epoch(add: address) -> uint256: view
    def point_history(addr: address, loc: uint256) -> Point: view
    def checkpoint(): nonpayable
    def token() -> ERC20: view
    def balanceOf(addr: address, epoch: uint256) -> uint256: view
    def find_epoch_by_timestamp(user: address, ts: uint256) -> uint256: view 

event Initialized:
    veyfi: VotingYFI
    start_time: uint256

event CheckpointToken:
    time: uint256
    tokens: uint256

event Claimed:
    recipient: indexed(address)
    amount: uint256
    week_cursor: uint256
    max_epoch: uint256

event RewardReceived:
    sender: indexed(address)
    amount: uint256

struct Point:
    bias: int128
    slope: int128  # - dweight / dt
    ts: uint256
    blk: uint256  # block

struct LockedBalance:
    amount: uint256
    end: uint256


WEEK: constant(uint256) = 7 * 86400
TOKEN_CHECKPOINT_DEADLINE: constant(uint256) = 86400

DYFI: immutable(ERC20)
VEYFI: immutable(VotingYFI)

start_time: public(uint256)
time_cursor: public(uint256)
time_cursor_of: public(HashMap[address, uint256])

last_token_time: public(uint256)
tokens_per_week: public(HashMap[uint256, uint256])

token_last_balance: public(uint256)
ve_supply: public(HashMap[uint256, uint256])


@external
def __init__(veyfi: VotingYFI, dyfi: address, start_time: uint256):
    """
    @notice Contract constructor
    @param veyfi VotingYFI contract address
    @param start_time Epoch time for fee distribution to start
    """
    t: uint256 = start_time / WEEK * WEEK
    self.start_time = t
    self.last_token_time = t
    self.time_cursor = t
    VEYFI = veyfi
    DYFI = ERC20(dyfi)

    log Initialized(veyfi, start_time)


@internal
def _checkpoint_token():
    token_balance: uint256 = DYFI.balanceOf(self)
    to_distribute: uint256 = token_balance - self.token_last_balance
    # @dev gas optimization
    if to_distribute == 0:
        self.last_token_time = block.timestamp
        log CheckpointToken(block.timestamp, 0)
        return
    
    self.token_last_balance = token_balance
    t: uint256 = self.last_token_time
    since_last: uint256 = block.timestamp - t
    self.last_token_time = block.timestamp
    this_week: uint256 = t / WEEK * WEEK
    next_week: uint256 = 0

    for i in range(40):
        next_week = this_week + WEEK
        if block.timestamp < next_week:
            if since_last == 0 and block.timestamp == t:
                self.tokens_per_week[this_week] += to_distribute
            else:
                self.tokens_per_week[this_week] += to_distribute * (block.timestamp - t) / since_last
            break
        else:
            if since_last == 0 and next_week == t:
                self.tokens_per_week[this_week] += to_distribute
            else:
                self.tokens_per_week[this_week] += to_distribute * (next_week - t) / since_last
        t = next_week
        this_week = next_week

    log CheckpointToken(block.timestamp, to_distribute)


@external
def checkpoint_token():
    """
    @notice Update the token checkpoint
    @dev Calculates the total number of tokens to be distributed in a given week.
    """
    assert block.timestamp > self.last_token_time + TOKEN_CHECKPOINT_DEADLINE
    self._checkpoint_token()


@internal
def _checkpoint_total_supply():
    t: uint256 = self.time_cursor
    rounded_timestamp: uint256 = block.timestamp / WEEK * WEEK
    VEYFI.checkpoint()

    for i in range(40):
        if t > rounded_timestamp:
            break
        else:
            epoch: uint256 = VEYFI.find_epoch_by_timestamp(VEYFI.address, t)
            pt: Point = VEYFI.point_history(VEYFI.address, epoch)
            dt: int128 = 0
            if t > pt.ts:
                # If the point is at 0 epoch, it can actually be earlier than the first deposit
                # Then make dt 0
                dt = convert(t - pt.ts, int128)
            self.ve_supply[t] = convert(max(pt.bias - pt.slope * dt, 0), uint256)
        t += WEEK

    self.time_cursor = t


@external
def checkpoint_total_supply():
    """
    @notice Update the veYFI total supply checkpoint
    @dev The checkpoint is also updated by the first claimant each
         new epoch week. This function may be called independently
         of a claim, to reduce claiming gas costs.
    """
    self._checkpoint_total_supply()


@internal
def _claim(addr: address, last_token_time: uint256) -> uint256:
    to_distribute: uint256 = 0

    max_user_epoch: uint256 = VEYFI.epoch(addr)
    _start_time: uint256 = self.start_time

    if max_user_epoch == 0:
        # No lock = no fees
        return 0

    week_cursor: uint256 = self.time_cursor_of[addr]

    if week_cursor == 0:
        user_point: Point = VEYFI.point_history(addr, 1)
        week_cursor = (user_point.ts + WEEK - 1) / WEEK * WEEK

    if week_cursor >= last_token_time:
        return 0

    if week_cursor < _start_time:
        week_cursor = _start_time

    # Iterate over weeks
    for i in range(50):
        if week_cursor >= last_token_time:
            break
        balance_of: uint256 = VEYFI.balanceOf(addr, week_cursor)
        if balance_of == 0:
            break
        to_distribute += balance_of * self.tokens_per_week[week_cursor] / self.ve_supply[week_cursor]
        week_cursor += WEEK

    self.time_cursor_of[addr] = week_cursor

    log Claimed(addr, to_distribute, week_cursor, max_user_epoch)

    return to_distribute


@external
@nonreentrant('lock')
def claim(user: address = msg.sender) -> uint256:
    """
    @notice Claim fees for a user
    @dev 
        Each call to claim looks at a maximum of 50 user veYFI points.
        For accounts with many veYFI related actions, this function
        may need to be called more than once to claim all available
        fees. In the `Claimed` event that fires, if `claim_epoch` is
        less than `max_epoch`, the account may claim again.
    @param user account to claim the fees for
    @return uint256 amount of the claimed fees
    """
    if block.timestamp >= self.time_cursor:
        self._checkpoint_total_supply()

    last_token_time: uint256 = self.last_token_time

    if block.timestamp > last_token_time + TOKEN_CHECKPOINT_DEADLINE:
        self._checkpoint_token()
        last_token_time = block.timestamp

    last_token_time = last_token_time / WEEK * WEEK

    amount: uint256 = self._claim(user, last_token_time)
    if amount != 0:
        assert DYFI.transfer(user, amount)
        self.token_last_balance -= amount

    return amount


@external
def burn(amount: uint256 = max_value(uint256)) -> bool:
    """
    @notice Receive dYFI into the contract and trigger a token checkpoint
    @param amount Amount of tokens to pull [default: allowance]
    @return bool success
    """
    _amount: uint256 = amount
    if _amount == max_value(uint256):
        _amount = DYFI.allowance(msg.sender, self)
    if _amount > 0:
        DYFI.transferFrom(msg.sender, self, _amount)
        log RewardReceived(msg.sender, _amount)
        if block.timestamp > self.last_token_time + TOKEN_CHECKPOINT_DEADLINE:
            self._checkpoint_token()

    return True


@view
@external
def token() -> ERC20:
    return DYFI


@view
@external
def veyfi() -> VotingYFI:
    return VEYFI

Read Contract

last_token_time 0x7f58e8f8 → uint256
start_time 0x834ee417 → uint256
time_cursor 0x127dcbd3 → uint256
time_cursor_of 0x2a2a314b → uint256
token 0xfc0c546a → address
token_last_balance 0x22b04bfc → uint256
tokens_per_week 0xedf59997 → uint256
ve_supply 0xd4dafba8 → uint256
veyfi 0x4068aba3 → address

Write Contract 6 functions

These functions modify contract state and require a wallet transaction to execute.

burn 0x44df8e70
No parameters
returns: bool
burn 0x42966c68
uint256 amount
returns: bool
checkpoint_token 0x811a40fe
No parameters
checkpoint_total_supply 0xb21ed502
No parameters
claim 0x4e71d92d
No parameters
returns: uint256
claim 0x1e83409a
address user
returns: uint256

Recent Transactions

No transactions found for this address