Address Contract Partially Verified
Address
0x2391Fc8f5E417526338F5aa3968b1851C16D894E
Balance
0 ETH
Nonce
1
Code Size
3240 bytes
Creator
0xCf28945E...98Cf at tx 0x00f472b3...574f57
Indexed Transactions
0
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