Address Contract Partially Verified
Address
0x583019fF0f430721aDa9cfb4fac8F06cA104d0B4
Balance
0 ETH
Nonce
1
Code Size
9224 bytes
Creator
0xD5d935c2...2888 at tx 0x15e2c529...dc91eb
Indexed Transactions
0
Contract Bytecode
9224 bytes
0x6003361161000c57611487565b60003560e01c346123d65763a9059cbb81186100d157604436106123d6576004358060a01c6123d65761028052610280511561004e5730610280511415610051565b60005b156123d65760243515610091573360c05260243560e05260006101005261007661155a565b6102805160c05260243560e05260016101005261009161155a565b61028051337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6024356102a05260206102a0a360016102a05260206102a0f35b6323b872dd81186101d657606436106123d6576004358060a01c6123d657610280526024358060a01c6123d6576102a0526102a0511561011757306102a051141561011a565b60005b156123d657600d61028051602052600052604060002080336020526000526040600020905080546044358082038281116123d6579050905081555060443515610193576102805160c05260443560e05260006101005261017861155a565b6102a05160c05260443560e05260016101005261019361155a565b6102a051610280517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6044356102c05260206102c0a360016102c05260206102c0f35b63095ea7b3811861025d57604436106123d6576004358060a01c6123d657604052604051156123d657602435600d336020526000526040600020806040516020526000526040600020905055604051337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560243560605260206060a3600160605260206060f35b6339509351811861031857604436106123d6576004358060a01c6123d657604052604051156123d657600d3360205260005260406000208060405160205260005260406000209050546024358082018281106123d65790509050606052606051600d336020526000526040600020806040516020526000526040600020905055604051337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560605160805260206080a3600160805260206080f35b63a457c2d781186103ef57604436106123d6576004358060a01c6123d657604052604051156123d657600d3360205260005260406000208060405160205260005260406000209050546060526060516024351161038b576060516024358082038281116123d65790509050606052610391565b60006060525b606051600d336020526000526040600020806040516020526000526040600020905055604051337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560605160805260206080a3600160805260206080f35b6301e1d114811861042e57600436106123d6576040366103a0376104146103e0611d6f565b6103e080516103a05260208101516103c0525060206103c0f35b63c6e6f59281186104cf57602436106123d6576040366103a0376104536103e0611d6f565b6103e080516103a05260208101516103c052506103a05161047f576004356103e05260206103e06104cd565b6103c0516104975760006103e05260206103e06104cd565b6004356103a0518082028115838383041417156123d657905090506103c05180156123d657808204905090506103e05260206103e05bf35b6307a2d13a811861057057602436106123d6576040366103a0376104f46103e0611d6f565b6103e080516103a05260208101516103c052506103a051610520576004356103e05260206103e061056e565b6103c0516105385760006103e05260206103e061056e565b6004356103c0518082028115838383041417156123d657905090506103a05180156123d657808204905090506103e05260206103e05bf35b63402d267d81186105bb57602436106123d6576004358060a01c6123d6576040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60605260206060f35b63ef8b30f7811861061957602436106123d6576040366103a0376105e06103e0611d6f565b6103e080516103a05260208101516103c0525060206004356040526103a0516060526103c0516080526106146103e0611e18565b6103e0f35b63b6b55f25811861063657602436106123d657336103e052610659565b636e553f6581186106dc57604436106123d6576024358060a01c6123d6576103e0525b600435156123d65760403661040037610673610440611e7b565b6104408051610400526020810151610420525060043560405261040051606052610420516080526106a5610460611e18565b610460516104405261044051156123d65760043561028052610440516102a0526103e0516102c0526106d561200f565b6020610440f35b63c63d75b6811861072757602436106123d6576004358060a01c6123d6576040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60605260206060f35b63b3d7f6b9811861078557602436106123d6576040366103a03761074c6103e0611d6f565b6103e080516103a05260208101516103c0525060206004356040526103a0516060526103c0516080526107806103e061214d565b6103e0f35b63a0712d6881186107a257602436106123d657336103e0526107c5565b6394bf804d811861084857604436106123d6576024358060a01c6123d6576103e0525b600435156123d657604036610400376107df610440611e7b565b61044080516104005260208101516104205250600435604052610400516060526104205160805261081161046061214d565b610460516104405261044051156123d65761044051610280526004356102a0526103e0516102c05261084161200f565b6020610440f35b63ce96cb77811861092757602436106123d6576004358060a01c6123d6576103a0526040366103c03761087c610400611d6f565b61040080516103c05260208101516103e05250600c6103a051602052600052604060002054610400526103c051610400518082038281116123d657905090506104205266038d7ea4c67fff6104205111156108d85760006108df565b6104205115155b15610900576103c05166038d7ea4c6800081038181116123d6579050610400525b6020610400516040526103c0516060526103e0516080526109226104406121b0565b610440f35b630a28a477811861098557602436106123d6576040366103a03761094c6103e0611d6f565b6103e080516103a05260208101516103c0525060206004356040526103a0516060526103c0516080526109806103e06121f1565b6103e0f35b632e1a7d4d81186109a757602436106123d657336103e0523361040052610a04565b62f714ce81186109d257604436106123d6576024358060a01c6123d6576103e0523361040052610a04565b63b460af948118610a8f57606436106123d6576024358060a01c6123d6576103e0526044358060a01c6123d657610400525b600435156123d65760403661042037610a1e610460611e7b565b610460805161042052602081015161044052506004356040526104205160605261044051608052610a506104806121f1565b610480516104605261046051156123d65760043561028052610460516102a0526103e0516102c052610400516102e052610a88612232565b6020610460f35b63d905777e8118610b4e57602436106123d6576004358060a01c6123d6576103a0526040366103c037610ac3610400611d6f565b61040080516103c05260208101516103e05250600c6103a051602052600052604060002054610400526103c051610400518082038281116123d657905090506104205266038d7ea4c67fff610420511115610b1f576000610b26565b6104205115155b15610b47576103c05166038d7ea4c6800081038181116123d6579050610400525b6020610400f35b634cdad5068118610bac57602436106123d6576040366103a037610b736103e0611d6f565b6103e080516103a05260208101516103c0525060206004356040526103a0516060526103c051608052610ba76103e06121b0565b6103e0f35b63db006a758118610bce57602436106123d657336103e0523361040052610c2c565b637bde82f28118610bfa57604436106123d6576024358060a01c6123d6576103e0523361040052610c2c565b63ba0876528118610cb757606436106123d6576024358060a01c6123d6576103e0526044358060a01c6123d657610400525b600435156123d65760403661042037610c46610460611e7b565b610460805161042052602081015161044052506004356040526104205160605261044051608052610c786104806121b0565b610480516104605261046051156123d65761046051610280526004356102a0526103e0516102c052610400516102e052610cb0612232565b6020610460f35b633ee352fc8118610cf557600436106123d657610cd56103e0611e7b565b6103e0506001546103e052600254610400526003546104205260606103e0f35b63ccaf0c308118610d6057600436106123d65760a060206123e86000396000516370a082316102205230610240526020610220602461023c845afa610d3f573d600060003e3d6000fd5b60203d106123d657610220905051604052610d5b61026061179b565b610260f35b63f49ec3108118610ea657602436106123d6576004358060a01c6123d6576060524262093a8081049050600181038181116123d6579050608052600a60605160205260005260406000205460a05261ffff60a0511660c05260805160c0511115610dd957600960605160205260005260406000205460a0525b60603660e03760a051604052610df061014061148d565b610140805160c052602081015160e0526040810151610100526060810151610120525060c05115610e5f5760e0514262093a808104905062093a8081028162093a808204186123d6579050610100518082038281116123d657905090508082018281106123d6579050905060e0525b6101205160e0518082028115838383041417156123d6579050905060e0516008548082018281106123d6579050905080156123d65780820490509050610140526020610140f35b63c445c9388118610ee757600436106123d6576001546002548082018281106123d657905090506003548082018281106123d6579050905060405260206040f35b634fdf5d1d8118610fda57604436106123d6576004358060a01c6123d6576040526024358060a01c6123d65760605260045433186123d65760206123e8600039600051604051146123d6576040516370a0823160a0523060c052602060a0602460bc845afa610f5b573d600060003e3d6000fd5b60203d106123d65760a090505160805260405163a9059cbb60a05260605160c05260805160e052602060a0604460bc6000855af1610f9e573d600060003e3d6000fd5b3d610fb557803b156123d657600161010052610fcd565b60203d106123d65760a0518060011c6123d657610100525b610100905051156123d657005b633047ce9d811861104b57602436106123d65760045433186123d6576101f46004351015611009576000611012565b6107d060043511155b156123d6576004356006557f6717373928cccf59cc9912055cfa8db86e7085b95c94c15862b121114aa333be60043560405260206040a1005b631bf93f8681186110a357602436106123d65760045433186123d657600435156123d6576004356008557fa1eced997ca08ff4a574f4f14ce5dfcb37e8bde7f90a609f48f0c86edf1224ee60043560405260206040a1005b63fd066ecc81186110fe57602436106123d6576004358060a01c6123d65760405260045433186123d6576040516005556040517fe7b5cc087e6e47e33e86bdfe4720b7e849891938b18ff6e0c3f92299de79e60c60006060a2005b63759be10c811861114c57600436106123d65760055433186123d657600060055533600455337fafe23f9e1f603b288748a507d5a993957e9f14313a5889d5a070851299939d5960006040a2005b6330bcd67b81186111c257602436106123d6576004358060a01c6123d657604052600454331861117d576001611184565b6007543318155b156123d657604051156123d6576040516007556040517fcb7ef3e545f5cdb893f5c568ba710fe08f336375a2d9fd66e161033f8fc09ef360006060a2005b637b2aab0381186111e157600436106123d65760005460405260206040f35b6388a8d602811861120057600436106123d65760045460405260206040f35b63770817ec811861121f57600436106123d65760055460405260206040f35b6318f7b782811861123e57600436106123d65760065460405260206040f35b6361d027b3811861125d57600436106123d65760075460405260206040f35b63c5c91533811861127c57600436106123d65760085460405260206040f35b6318160ddd811861129b57600436106123d657600b5460405260206040f35b6370a0823181186112d657602436106123d6576004358060a01c6123d657604052600c60405160205260005260406000205460605260206060f35b63dd62ed3e811861133057604436106123d6576004358060a01c6123d6576040526024358060a01c6123d657606052600d604051602052600052604060002080606051602052600052604060002090505460805260206080f35b6306fdde0381186113b857600436106123d65760208060805260126040527f5374616b656420596561726e204574686572000000000000000000000000000060605260408160800181518082526020830160208301815181525050508051806020830101601f82600003163682375050601f19601f8251602001011690509050810190506080f35b6395d89b41811861144057600436106123d65760208060805260076040527f73742d794554480000000000000000000000000000000000000000000000000060605260408160800181518082526020830160208301815181525050508051806020830101601f82600003163682375050601f19601f8251602001011690509050810190506080f35b63313ce567811861145e57600436106123d657601260405260206040f35b6338d52e0f811861148557600436106123d65760206123e860003960005160405260206040f35b505b60006000fd5b61ffff60405116815266ffffffffffffff6040518060101c905016602082015266ffffffffffffff6040518060481c90501660408201526040518060801c9050606082015250565b61ffff60405111156114e857600061152f565b66ffffffffffffff606051111561150057600061152f565b66ffffffffffffff608051111561151857600061152f565b6fffffffffffffffffffffffffffffffff60a05111155b156123d65760a0518060801b90506080518060481b90506060518060101b9050604051171717815250565b600c60c051602052600052604060002054610120526101205161014052600161010051186115a0576101405160e0518082018281106123d65790509050610140526115ba565b6101405160e0518082038281116123d65790509050610140525b61014051600c60c0516020526000526040600020554262093a80810490506101605260803661018037600a60c05160205260005260406000205460405261160261020061148d565b61020080516101805260208101516101a05260408101516101c05260608101516101e05250610180511561163e57610180516101605111611641565b60005b1561166957600a60c051602052600052604060002054600960c0516020526000526040600020555b6101405161167e5760006101a05260006101e0525b6101e05115611760576101a051426101c0518082038281116123d657905090508082018281106123d657905090506101a052600161010051186117605760085461020052610120516101a0518082028115838383041417156123d65790509050610200518082028115838383041417156123d65790509050610140516101a051610200518082018281106123d657905090508082028115838383041417156123d65790509050610120516101a0518082028115838383041417156123d657905090508082038281116123d6579050905080156123d657808204905090506101a0525b610160516040526101a051606052426080526101405160a0526117846102006114d5565b61020051600a60c051602052600052604060002055565b60005460605242606051186117d357600154815260025460208201526003546040820152600060608201526000608082015250611d6d565b600060805260405160a05260015460c05260025460e0526003546101005260c05160e0518082018281106123d65790509050610100518082018281106123d65790509050610120526000610140524262093a808104905060605162093a80810490508082038281116123d65790509050610160526101605115611a4d5760016101605118611884576101005160e0518082018281106123d657905090506101005260c05160e052600060c052611a2c565b426060518082038281116123d65790509050610180526101005160e05160c0518082018281106123d657905090508082018281106123d65790509050610100526101205160a051116118df57600060e052600060c052611a2c565b60a051610120518082038281116123d657905090506101a0526101a0516006548082028115838383041417156123d65790509050612710810490506101c0526101a0516101c0518082038281116123d657905090506101a0526080516101c0518082018281106123d657905090506080526101a0518060ff1c6123d6576101405260a051610120526101a05162093a8081028162093a808204186123d65790506101805180156123d6578082049050905060e0526101805162093a8081038181116123d6579050610180526101a05160e0518082038281116123d657905090506101a0526101a0514262093a80810690508082028115838383041417156123d657905090506101805180156123d6578082049050905060c0526101a05160c0518082038281116123d657905090506101a052610100516101a0518082018281106123d65790509050610100525b4262093a808104905062093a8081028162093a808204186123d65790506060525b60605162093a80810690508062093a800362093a8081116123d657905061018052426060518082038281116123d657905090506101a05260e0516101a0518082028115838383041417156123d657905090506101805180156123d657808204905090506101c05260e0516101c0518082038281116123d6579050905060e052610100516101c0518082018281106123d65790509050610100526101205160a0511015611be2576101205160a0518082038281116123d657905090506101e052610140516101e0518060ff1c6123d65780820382811360008312186123d65790509050610140526101e05160c0511015611bc5576101e05160c0518082038281116123d657905090506101e052600060c0526101e05160e0511015611ba8576101e05160e0518082038281116123d657905090506101e052600060e052610100516101e0518082038281116123d6579050905061010052611cd7565b60e0516101e0518082038281116123d6579050905060e052611cd7565b60c0516101e0518082038281116123d6579050905060c052611cd7565b60a051610120518082038281116123d657905090506101e0526101e0516006548082028115838383041417156123d6579050905061271081049050610200526101e051610200518082038281116123d657905090506101e052608051610200518082018281106123d6579050905060805260016101605118611c7257620151804262093a80810690501115611c75565b60005b611c965760c0516101e0518082018281106123d6579050905060c052611caf565b60e0516101e0518082018281106123d6579050905060e0525b610140516101e0518060ff1c6123d65780820182811260008312186123d65790509050610140525b60006101e05260805115611d435761010051611cf9576080516101e052611d29565b608051600b548082028115838383041417156123d657905090506101005180156123d657808204905090506101e0525b610100516080518082018281106123d65790509050610100525b60c051815260e05160208201526101005160408201526101e0516060820152610140516080820152505b565b60a0366102203760206123e86000396000516370a082316102c052306102e05260206102c060246102dc845afa611dab573d600060003e3d6000fd5b60203d106123d6576102c0905051604052611dc761030061179b565b61030080516102205260208101516102405260408101516102605260608101516102805260808101516102a05250600b54610280518082018281106123d65790509050815261026051602082015250565b606051611e3a5766038d7ea4c68000604051106123d657604051815250611e79565b608051611e4b576000815250611e79565b6040516060518082028115838383041417156123d6579050905060805180156123d657808204905090508152505b565b60206123e86000396000516370a082316102a052306102c05260206102a060246102bc845afa611eb0573d600060003e3d6000fd5b60203d106123d6576102a09050516102805260a0366102a03761028051604052611edb61034061179b565b61034080516102a05260208101516102c05260408101516102e052606081015161030052608081015161032052506103205115611f5a577fabf5b9a9abf080b67be5bfa614a827845afc366da18173be4db7bf2761f2517e6102a051610340526102c051610360526102e05161038052610320516103a0526080610340a15b426000556102a0516001556102c0516002556102e051600355600b54610340526103005115611ffd5761034051610300518082018281106123d657905090506103405261034051600b55600754610360526103605160c0526103005160e052600161010052611fc761155a565b6103605160007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef61030051610380526020610380a35b6103405181526102e051602082015250565b600354610280518082018281106123d65790509050600355600b546102a0518082018281106123d65790509050600b556102c05160c0526102a05160e05260016101005261205b61155a565b60206123e86000396000516323b872dd6102e05233610300523061032052610280516103405260206102e060646102fc6000855af161209f573d600060003e3d6000fd5b3d6120b657803b156123d6576001610360526120cf565b60203d106123d6576102e0518060011c6123d657610360525b610360905051156123d6576102c051337fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7610280516102e0526102a0516103005260406102e0a36102c05160007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6102a0516102e05260206102e0a3565b60605161216f5766038d7ea4c68000604051106123d6576040518152506121ae565b6080516121805760008152506121ae565b6040516080518082028115838383041417156123d6579050905060605180156123d657808204905090508152505b565b6060516121c15760008152506121ef565b6040516080518082028115838383041417156123d6579050905060605180156123d657808204905090508152505b565b608051612202576000815250612230565b6040516060518082028115838383041417156123d6579050905060805180156123d657808204905090508152505b565b336102e0511461227457600d6102e051602052600052604060002080336020526000526040600020905080546102a0518082038281116123d657905090508155505b600354610280518082038281116123d65790509050600355600b546102a0518082038281116123d657905090506103005261030051600b556102e05160c0526102a05160e0526000610100526122c861155a565b66038d7ea4c67fff61030051116122e257610300516123d6575b60206123e860003960005163a9059cbb610320526102c0516103405261028051610360526020610320604461033c6000855af1612324573d600060003e3d6000fd5b3d61233b57803b156123d657600161038052612354565b60203d106123d657610320518060011c6123d657610380525b610380905051156123d65760006102e0517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6102a051610320526020610320a36102e0516102c051337ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db61028051610320526102a051610340526040610320a4565b600080fda165767970657283000307000b0000000000000000000000001bed97cbc3c24a4fb5c069c6e311a967386131f7
Verified Source Code Partial Match
Compiler: v0.3.7+commit.6020b8bb
yETHstakingcontract.vy 873 lines
# @version 0.3.7
"""
@title yETH staking contract
@author 0xkorin, Yearn Finance
@license Copyright (c) Yearn Finance, 2023 - all rights reserved
"""
from vyper.interfaces import ERC20
from vyper.interfaces import ERC4626
implements: ERC20
implements: ERC4626
updated: public(uint256)
pending: uint256
streaming: uint256
unlocked: uint256
management: public(address)
pending_management: public(address)
# fees
performance_fee_rate: public(uint256)
treasury: public(address)
# voting
half_time: public(uint256)
previous_packed_weights: HashMap[address, uint256]
packed_weights: HashMap[address, uint256]
# ERC20 state
totalSupply: public(uint256)
balanceOf: public(HashMap[address, uint256])
allowance: public(HashMap[address, HashMap[address, uint256]])
name: public(constant(String[18])) = "Staked Yearn Ether"
symbol: public(constant(String[7])) = "st-yETH"
decimals: public(constant(uint8)) = 18
# ERC4626 state
asset: public(immutable(address))
event Rewards:
pending: uint256
streaming: uint256
unlocked: uint256
delta: int256
event SetFeeRate:
fee_rate: uint256
event SetHalfTime:
half_time: uint256
event PendingManagement:
management: indexed(address)
event SetManagement:
management: indexed(address)
event SetTreasury:
treasury: indexed(address)
# ERC20 events
event Transfer:
sender: indexed(address)
receiver: indexed(address)
value: uint256
event Approval:
owner: indexed(address)
spender: indexed(address)
value: uint256
# ERC4626 events
event Deposit:
sender: indexed(address)
owner: indexed(address)
assets: uint256
shares: uint256
event Withdraw:
sender: indexed(address)
receiver: indexed(address)
owner: indexed(address)
assets: uint256
shares: uint256
FEE_PRECISION: constant(uint256) = 10_000
MINIMUM_INITIAL_DEPOSIT: constant(uint256) = 1_000_000_000_000_000
DAY_LENGTH: constant(uint256) = 24 * 60 * 60
WEEK_LENGTH: constant(uint256) = 7 * DAY_LENGTH
MIN_FEE_RATE: constant(uint256) = 500
MAX_FEE_RATE: constant(uint256) = 2_000
INCREMENT: constant(bool) = True
DECREMENT: constant(bool) = False
WEEK_MASK: constant(uint256) = 2**16 - 1
TIME_MASK: constant(uint256) = 2**56 - 1
TIME_SHIFT: constant(int128) = -16
UPDATED_MASK: constant(uint256) = 2**56 - 1
UPDATED_SHIFT: constant(int128) = -72
SHARES_MASK: constant(uint256) = 2**128 - 1
SHARES_SHIFT: constant(int128) = -128
@external
def __init__(_asset: address):
"""
@notice Constructor
@param _asset The underlying asset
"""
assert _asset != empty(address)
asset = _asset
self.updated = block.timestamp
self.half_time = WEEK_LENGTH
self.management = msg.sender
self.treasury = msg.sender
log Transfer(empty(address), msg.sender, 0)
# ERC20 functions
@external
def transfer(_to: address, _value: uint256) -> bool:
"""
@notice Transfer to another account
@param _to Account to transfer to
@param _value Amount to transfer
@return True
"""
assert _to != empty(address) and _to != self
if _value > 0:
self._update_account_shares(msg.sender, _value, DECREMENT)
self._update_account_shares(_to, _value, INCREMENT)
log Transfer(msg.sender, _to, _value)
return True
@external
def transferFrom(_from: address, _to: address, _value: uint256) -> bool:
"""
@notice Transfer from one account to another account
@param _from Account to transfe from
@param _to Account to transfer to
@param _value Amount to transfer
@return True
"""
assert _to != empty(address) and _to != self
self.allowance[_from][msg.sender] -= _value
if _value > 0:
self._update_account_shares(_from, _value, DECREMENT)
self._update_account_shares(_to, _value, INCREMENT)
log Transfer(_from, _to, _value)
return True
@external
def approve(_spender: address, _value: uint256) -> bool:
"""
@notice Approve another account to spend. Beware that changing an allowance
with this method brings the risk that someone may use both the old and
the new allowance by unfortunate transaction ordering.
See https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
@param _spender Account that is allowed to spend
@param _value Amount that the spender is allowed to transfer
@return Flag indicating whether the approval was successful
"""
assert _spender != empty(address)
self.allowance[msg.sender][_spender] = _value
log Approval(msg.sender, _spender, _value)
return True
@external
def increaseAllowance(_spender: address, _value: uint256) -> bool:
"""
@notice Increase the allowance of another account to spend. This method mitigates
the risk that someone may use both the old and the new allowance by unfortunate
transaction ordering.
See https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
@param _spender Account that is allowed to spend
@param _value The amount of tokens to increase the allowance by
@return True
"""
assert _spender != empty(address)
allowance: uint256 = self.allowance[msg.sender][_spender] + _value
self.allowance[msg.sender][_spender] = allowance
log Approval(msg.sender, _spender, allowance)
return True
@external
def decreaseAllowance(_spender: address, _value: uint256) -> bool:
"""
@notice Decrease the allowance of another account to spend. This method mitigates
the risk that someone may use both the old and the new allowance by unfortunate
transaction ordering.
See https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
@param _spender Account that is allowed to spend
@param _value The amount of tokens to decrease the allowance by
@return True
"""
assert _spender != empty(address)
allowance: uint256 = self.allowance[msg.sender][_spender]
if _value > allowance:
allowance = 0
else:
allowance -= _value
self.allowance[msg.sender][_spender] = allowance
log Approval(msg.sender, _spender, allowance)
return True
# ERC4626 functions
@external
@view
def totalAssets() -> uint256:
"""
@notice Get the total assets in the contract
@return Total assets in the contract
"""
total_shares: uint256 = 0
total_assets: uint256 = 0
total_shares, total_assets = self._get_totals()
return total_assets
@external
@view
def convertToShares(_assets: uint256) -> uint256:
"""
@notice Convert amount of assets to amount of shares
@param _assets Amount of assets
@return Amount of shares
"""
total_shares: uint256 = 0
total_assets: uint256 = 0
total_shares, total_assets = self._get_totals()
if total_shares == 0:
return _assets
if total_assets == 0:
return 0
return _assets * total_shares / total_assets
@external
@view
def convertToAssets(_shares: uint256) -> uint256:
"""
@notice Convert amount of shares to amount of assets
@param _shares Amount of shares
@return Amount of assets
"""
total_shares: uint256 = 0
total_assets: uint256 = 0
total_shares, total_assets = self._get_totals()
if total_shares == 0:
return _shares
if total_assets == 0:
return 0
return _shares * total_assets / total_shares
@external
@view
def maxDeposit(_receiver: address) -> uint256:
"""
@notice Get the maximum amount of assets an account is allowed to deposit
@param _receiver Account
@return Maximum amount the account is allowed to deposit
"""
return max_value(uint256)
@external
@view
def previewDeposit(_assets: uint256) -> uint256:
"""
@notice Simulate the effect of a deposit
@param _assets Amount of assets to deposit
@return Amount of shares that will be minted
"""
total_shares: uint256 = 0
total_assets: uint256 = 0
total_shares, total_assets = self._get_totals()
return self._preview_deposit(_assets, total_shares, total_assets)
@external
def deposit(_assets: uint256, _receiver: address = msg.sender) -> uint256:
"""
@notice Deposit assets
@param _assets Amount of assets to deposit
@param _receiver Account that will receive the shares
@return Amount of shares minted
"""
assert _assets > 0
total_shares: uint256 = 0
total_assets: uint256 = 0
total_shares, total_assets = self._update_totals()
shares: uint256 = self._preview_deposit(_assets, total_shares, total_assets)
assert shares > 0
self._deposit(_assets, shares, _receiver)
return shares
@external
@view
def maxMint(_receiver: address) -> uint256:
"""
@notice Get the maximum amount of shares an account is allowed to mint
@param _receiver Account
@return Maximum amount the account is allowed to mint
"""
return max_value(uint256)
@external
@view
def previewMint(_shares: uint256) -> uint256:
"""
@notice Simulate the effect of a mint
@param _shares Amount of shares to mint
@return Amount of assets that will be taken
"""
total_shares: uint256 = 0
total_assets: uint256 = 0
total_shares, total_assets = self._get_totals()
return self._preview_mint(_shares, total_shares, total_assets)
@external
def mint(_shares: uint256, _receiver: address = msg.sender) -> uint256:
"""
@notice Mint shares
@param _shares Amount of shares to mint
@param _receiver Account that will receive the shares
@return Amount of assets taken
"""
assert _shares > 0
total_shares: uint256 = 0
total_assets: uint256 = 0
total_shares, total_assets = self._update_totals()
assets: uint256 = self._preview_mint(_shares, total_shares, total_assets)
assert assets > 0
self._deposit(assets, _shares, _receiver)
return assets
@external
@view
def maxWithdraw(_owner: address) -> uint256:
"""
@notice Get the maximum amount of assets an account is allowed to withdraw
@param _owner Account
@return Maximum amount the account is allowed to withdraw
"""
total_shares: uint256 = 0
total_assets: uint256 = 0
total_shares, total_assets = self._get_totals()
shares: uint256 = self.balanceOf[_owner]
left: uint256 = total_shares - shares
if left < MINIMUM_INITIAL_DEPOSIT and left > 0:
shares = total_shares - MINIMUM_INITIAL_DEPOSIT
return self._preview_redeem(shares, total_shares, total_assets)
@external
@view
def previewWithdraw(_assets: uint256) -> uint256:
"""
@notice Simulate the effect of a withdrawal
@param _assets Amount of assets to withdraw
@return Amount of shares that will be redeemed
"""
total_shares: uint256 = 0
total_assets: uint256 = 0
total_shares, total_assets = self._get_totals()
return self._preview_withdraw(_assets, total_shares, total_assets)
@external
def withdraw(_assets: uint256, _receiver: address = msg.sender, _owner: address = msg.sender) -> uint256:
"""
@notice Withdraw assets
@param _assets Amount of assets to withdraw
@param _receiver Account that will receive the assets
@param _owner Owner of the shares that will be redeemed
@return Amount of shares redeemed
"""
assert _assets > 0
total_shares: uint256 = 0
total_assets: uint256 = 0
total_shares, total_assets = self._update_totals()
shares: uint256 = self._preview_withdraw(_assets, total_shares, total_assets)
assert shares > 0
self._withdraw(_assets, shares, _receiver, _owner)
return shares
@external
@view
def maxRedeem(_owner: address) -> uint256:
"""
@notice Get the maximum amount of shares an account is allowed to redeem
@param _owner Account
@return Maximum amount the account is allowed to redeem
"""
total_shares: uint256 = 0
total_assets: uint256 = 0
total_shares, total_assets = self._get_totals()
shares: uint256 = self.balanceOf[_owner]
left: uint256 = total_shares - shares
if left < MINIMUM_INITIAL_DEPOSIT and left > 0:
shares = total_shares - MINIMUM_INITIAL_DEPOSIT
return shares
@external
@view
def previewRedeem(_shares: uint256) -> uint256:
"""
@notice Simulate the effect of a redemption
@param _shares Amount of shares to redeem
@return Amount of assets that will be withdrawn
"""
total_shares: uint256 = 0
total_assets: uint256 = 0
total_shares, total_assets = self._get_totals()
return self._preview_redeem(_shares, total_shares, total_assets)
@external
def redeem(_shares: uint256, _receiver: address = msg.sender, _owner: address = msg.sender) -> uint256:
"""
@notice Redeem shares
@param _shares Amount of shares to redeem
@param _receiver Account that will receive the assets
@param _owner Owner of the shares that will be redeemed
@return Amount of assets withdrawn
"""
assert _shares > 0
total_shares: uint256 = 0
total_assets: uint256 = 0
total_shares, total_assets = self._update_totals()
assets: uint256 = self._preview_redeem(_shares, total_shares, total_assets)
assert assets > 0
self._withdraw(assets, _shares, _receiver, _owner)
return assets
# external functions
@external
def update_amounts() -> (uint256, uint256, uint256):
"""
@notice Update the amount in each bucket
@return Tuple with pending, streaming and unlocked amounts
"""
self._update_totals()
return self.pending, self.streaming, self.unlocked
@external
@view
def get_amounts() -> (uint256, uint256, uint256, uint256, int256):
"""
@notice Simulate an update to the buckets
@return Tuple with pending, streaming, unlocked amounts, new fee shares and balance changes since last update
"""
return self._get_amounts(ERC20(asset).balanceOf(self))
@external
@view
def vote_weight(_account: address) -> uint256:
"""
@notice Get the voting weight of an account
@dev Vote weights are always evaluated at the end of last week
@param _account Account to find get the vote weight for
@return Vote weight
"""
current_week: uint256 = block.timestamp / WEEK_LENGTH - 1
packed_weight: uint256 = self.packed_weights[_account]
week: uint256 = packed_weight & WEEK_MASK
if week > current_week:
packed_weight = self.previous_packed_weights[_account]
t: uint256 = 0
updated: uint256 = 0
shares: uint256 = 0
week, t, updated, shares = self._unpack_weight(packed_weight)
if week > 0:
t += block.timestamp / WEEK_LENGTH * WEEK_LENGTH - updated
return shares * t / (t + self.half_time)
@external
@view
def known() -> uint256:
return self.pending + self.streaming + self.unlocked
@external
def rescue(_token: address, _receiver: address):
assert msg.sender == self.management
assert _token != asset # dev: cant rescue vault asset
amount: uint256 = ERC20(_token).balanceOf(self)
assert ERC20(_token).transfer(_receiver, amount, default_return_value=True)
@external
def set_performance_fee_rate(_fee_rate: uint256):
"""
@notice Set the performance fee rate
@param _fee_rate Performance fee rate (in basispoints)
"""
assert msg.sender == self.management
assert _fee_rate >= MIN_FEE_RATE and _fee_rate <= MAX_FEE_RATE
self.performance_fee_rate = _fee_rate
log SetFeeRate(_fee_rate)
@external
def set_half_time(_half_time: uint256):
"""
@notice Set the time to reach half the voting weights
@param _half_time Time to reach half voting weight (in seconds)
"""
assert msg.sender == self.management
assert _half_time > 0
self.half_time = _half_time
log SetHalfTime(_half_time)
@external
def set_management(_management: address):
"""
@notice Set the pending management address. Needs to be accepted
by that account separately to transfer management over
@param _management New pending management address
"""
assert msg.sender == self.management
self.pending_management = _management
log PendingManagement(_management)
@external
def accept_management():
"""
@notice Accept management role. Can only be called by account
previously marked as pending management by current management
"""
assert msg.sender == self.pending_management
self.pending_management = empty(address)
self.management = msg.sender
log SetManagement(msg.sender)
@external
def set_treasury(_treasury: address):
"""
@notice Set the performance fee beneficiary
@param _treasury The new treasury address
"""
assert msg.sender == self.management or msg.sender == self.treasury
assert _treasury != empty(address)
self.treasury = _treasury
log SetTreasury(_treasury)
@internal
@view
def _preview_deposit(_assets: uint256, _total_shares: uint256, _total_assets: uint256) -> uint256:
"""
@notice Calculate amount of shares that will be minted on deposit of a specific amount of assets
@param _assets Amount of assets to deposit
@param _total_shares Amount of vault shares prior to deposit
@param _total_assets Amount of assets in vault prior to deposit
@return Amount of shares to be minted
"""
if _total_shares == 0:
assert _assets >= MINIMUM_INITIAL_DEPOSIT # dev: minimum initial deposit size
return _assets
if _total_assets == 0:
return 0
return _assets * _total_shares / _total_assets
@internal
@view
def _preview_mint(_shares: uint256, _total_shares: uint256, _total_assets: uint256) -> uint256:
"""
@notice Calculate amount of assets deposited to mint a specific amount of shares
@param _assets Amount of shares to mint
@param _total_shares Amount of vault shares prior to deposit
@param _total_assets Amount of assets in vault prior to deposit
@return Amount of assets to deposit
"""
if _total_shares == 0:
assert _shares >= MINIMUM_INITIAL_DEPOSIT # dev: minimum initial deposit size
return _shares
if _total_assets == 0:
return 0
return _shares * _total_assets / _total_shares
@internal
def _deposit(_assets: uint256, _shares: uint256, _receiver: address):
"""
@notice Deposit assets and mint shares
@param _assets Amount of assets deposited
@param _shares Amount of shares minted
@param _receiver Receiver of minted shares
"""
self.unlocked += _assets
self.totalSupply += _shares
self._update_account_shares(_receiver, _shares, INCREMENT)
assert ERC20(asset).transferFrom(msg.sender, self, _assets, default_return_value=True)
log Deposit(msg.sender, _receiver, _assets, _shares)
log Transfer(empty(address), _receiver, _shares)
@internal
@view
def _preview_withdraw(_assets: uint256, _total_shares: uint256, _total_assets: uint256) -> uint256:
"""
@notice Calculate amount of shares that will be burned on withdrawal of a specific amount of assets
@param _assets Amount of assets to withdraw
@param _total_shares Amount of vault shares prior to withdrawal
@param _total_assets Amount of assets in vault prior to withdrawal
@return Amount of shares to be burned
"""
if _total_assets == 0:
return 0
return _assets * _total_shares / _total_assets
@internal
@view
def _preview_redeem(_shares: uint256, _total_shares: uint256, _total_assets: uint256) -> uint256:
"""
@notice Calculate amount of assets withdrawn to burn a specific amount of shares
@param _assets Amount of shares to burn
@param _total_shares Amount of vault shares prior to withdrawal
@param _total_assets Amount of assets in vault prior to withdrawal
@return Amount of assets to withdraw
"""
if _total_shares == 0:
return 0
return _shares * _total_assets / _total_shares
@internal
def _withdraw(_assets: uint256, _shares: uint256, _receiver: address, _owner: address):
"""
@notice Withdraw assets and burn shares
@param _assets Amount of assets withdrawn
@param _shares Amount of shares burned
@param _receiver Receiver of withdrawn assets
@param _owner Account to burn shares from
"""
if _owner != msg.sender:
self.allowance[_owner][msg.sender] -= _shares # dev: allowance
self.unlocked -= _assets
total_shares: uint256 = self.totalSupply - _shares
self.totalSupply = total_shares
self._update_account_shares(_owner, _shares, DECREMENT)
if total_shares < MINIMUM_INITIAL_DEPOSIT:
assert total_shares == 0
assert ERC20(asset).transfer(_receiver, _assets, default_return_value=True)
log Transfer(_owner, empty(address), _shares)
log Withdraw(msg.sender, _receiver, _owner, _assets, _shares)
@internal
@view
def _get_totals() -> (uint256, uint256):
"""
@notice Simulate an update to the buckets and return total number of shares and assets
@return Tuple with total number of shares and total number of assets
"""
pending: uint256 = 0
streaming: uint256 = 0
unlocked: uint256 = 0
new_fee_shares: uint256 = 0
delta: int256 = 0
pending, streaming, unlocked, new_fee_shares, delta = self._get_amounts(ERC20(asset).balanceOf(self))
return self.totalSupply + new_fee_shares, unlocked
@internal
def _update_totals() -> (uint256, uint256):
"""
@notice Update the buckets and return total number of shares and assets
@return Tuple with total number of shares and total number of assets
"""
current: uint256 = ERC20(asset).balanceOf(self)
pending: uint256 = 0
streaming: uint256 = 0
unlocked: uint256 = 0
new_fee_shares: uint256 = 0
delta: int256 = 0
pending, streaming, unlocked, new_fee_shares, delta = self._get_amounts(current)
if delta != 0:
log Rewards(pending, streaming, unlocked, delta)
self.updated = block.timestamp
self.pending = pending
self.streaming = streaming
self.unlocked = unlocked
total_shares: uint256 = self.totalSupply
if new_fee_shares > 0:
total_shares += new_fee_shares
self.totalSupply = total_shares
treasury: address = self.treasury
self._update_account_shares(treasury, new_fee_shares, INCREMENT)
log Transfer(empty(address), treasury, new_fee_shares)
return total_shares, unlocked
@internal
@view
def _get_amounts(_current: uint256) -> (uint256, uint256, uint256, uint256, int256):
"""
@notice Calculate latest bucket amounts
@param _current Asset token balance of contract
@return Tuple with pending, streaming, unlocked amounts, new fee shares and balance changes since last update
@dev
New assets not from deposits during a week are added to the pending bucket.
Streaming bucket gradually streams into the unlocked bucket during the week.
At the end of the week, the pending bucket becomes the streaming bucket and a new pending bucket is created.
Slashings are taken from the pending, streaming and unlocked bucket, in that order.
User deposits and withdrawals only ever affect the unlocked bucket
"""
updated: uint256 = self.updated
if updated == block.timestamp:
return self.pending, self.streaming, self.unlocked, 0, 0
new_fee: uint256 = 0
current: uint256 = _current
pending: uint256 = self.pending
streaming: uint256 = self.streaming
unlocked: uint256 = self.unlocked
last: uint256 = pending + streaming + unlocked
delta: int256 = 0
weeks: uint256 = block.timestamp / WEEK_LENGTH - updated / WEEK_LENGTH
if weeks > 0:
if weeks == 1:
# new week
unlocked += streaming
streaming = pending
pending = 0
else:
# week number has changed by at least 2 - function hasnt been called in at least a week
span: uint256 = block.timestamp - updated
unlocked += streaming + pending
if current > last:
# net rewards generated, distribute over buckets
rewards: uint256 = current - last
fee: uint256 = rewards * self.performance_fee_rate / FEE_PRECISION
rewards -= fee
new_fee += fee
delta = convert(rewards, int256)
last = current
# streaming bucket: 7 days
streaming = rewards * WEEK_LENGTH / span
span -= WEEK_LENGTH
rewards -= streaming
# pending bucket: time since new week
pending = rewards * (block.timestamp % WEEK_LENGTH) / span
rewards -= pending
# unlocked bucket: rest
unlocked += rewards
else:
# net penalty - deal with it below
streaming = 0
pending = 0
# set to beginning of the week
updated = block.timestamp / WEEK_LENGTH * WEEK_LENGTH
# time between last update and end of week
duration: uint256 = WEEK_LENGTH - (updated % WEEK_LENGTH)
# time that has passed since last update
span: uint256 = block.timestamp - updated
# unlock funds
streamed: uint256 = streaming * span / duration
streaming -= streamed
unlocked += streamed
if current >= last:
# rewards
rewards: uint256 = current - last
fee: uint256 = rewards * self.performance_fee_rate / FEE_PRECISION
rewards -= fee
new_fee += fee
if weeks == 1 and block.timestamp % WEEK_LENGTH <= DAY_LENGTH:
# if first update in new week is in first day, add to streaming
streaming += rewards
else:
pending += rewards
delta += convert(rewards, int256)
else:
# penalty
shortage: uint256 = last - current
delta -= convert(shortage, int256)
if pending >= shortage:
# there are enough pending assets to cover the penalty
pending -= shortage
else:
shortage -= pending
pending = 0
if streaming >= shortage:
# there are enough streaming assets to cover the penalty
streaming -= shortage
else:
# as a last resort, take from unlocked funds
shortage -= streaming
streaming = 0
unlocked -= shortage
new_fee_shares: uint256 = 0
if new_fee > 0:
if unlocked == 0:
new_fee_shares = new_fee
else:
new_fee_shares = new_fee * self.totalSupply / unlocked
unlocked += new_fee
return pending, streaming, unlocked, new_fee_shares, delta
@internal
def _update_account_shares(_account: address, _change: uint256, _add: bool):
"""
@notice Increase or decrease user shares and vote weight accordingly
@param _account Account to update shares and vote weight for
@param _change Amount of shares to add or remove
@param _add True if shares are added, False if removed
@dev
Vote weight is the same immediately before and immediately after a deposit.
A withdrawal reduces the vote weight proportionally
"""
prev_shares: uint256 = self.balanceOf[_account]
shares: uint256 = prev_shares
if _add == INCREMENT:
shares += _change
else:
shares -= _change
self.balanceOf[_account] = shares
current_week: uint256 = block.timestamp / WEEK_LENGTH
week: uint256 = 0
t: uint256 = 0
updated: uint256 = 0
last_shares: uint256 = 0
week, t, updated, last_shares = self._unpack_weight(self.packed_weights[_account])
if week > 0 and current_week > week:
self.previous_packed_weights[_account] = self.packed_weights[_account]
if shares == 0:
t = 0
last_shares = 0
if last_shares > 0:
t += block.timestamp - updated
if _add == INCREMENT:
# amount has increased, calculate effective time that results in same weight
half_time: uint256 = self.half_time
t = prev_shares * t * half_time / (shares * (t + half_time) - prev_shares * t)
self.packed_weights[_account] = self._pack_weight(current_week, t, block.timestamp, shares)
@internal
@pure
def _pack_weight(_week: uint256, _t: uint256, _updated: uint256, _shares: uint256) -> uint256:
"""
@notice Pack voting weight parameters into a single word
@param _week Week number
@param _t Time staked
@param _updated Time last updated
@param _shares Amount of shares
@return Packed vote weight
"""
assert _week <= WEEK_MASK and _t <= TIME_MASK and _updated <= UPDATED_MASK and _shares <= SHARES_MASK
return _week | shift(_t, -TIME_SHIFT) | shift(_updated, -UPDATED_SHIFT) | shift(_shares, -SHARES_SHIFT)
@internal
@pure
def _unpack_weight(_packed: uint256) -> (uint256, uint256, uint256, uint256):
"""
@notice Unpack voting weight into its parameters
@param _packed Packed voting weight
@return Tuple of week number, time staked, time last updated,amount of shares
"""
return _packed & WEEK_MASK, shift(_packed, TIME_SHIFT) & TIME_MASK, shift(_packed, UPDATED_SHIFT) & UPDATED_MASK, shift(_packed, SHARES_SHIFT)
Read Contract
allowance 0xdd62ed3e → uint256
asset 0x38d52e0f → address
balanceOf 0x70a08231 → uint256
convertToAssets 0x07a2d13a → uint256
convertToShares 0xc6e6f592 → uint256
decimals 0x313ce567 → uint8
get_amounts 0xccaf0c30 → uint256, uint256, uint256, uint256, int256
half_time 0xc5c91533 → uint256
known 0xc445c938 → uint256
management 0x88a8d602 → address
maxDeposit 0x402d267d → uint256
maxMint 0xc63d75b6 → uint256
maxRedeem 0xd905777e → uint256
maxWithdraw 0xce96cb77 → uint256
name 0x06fdde03 → string
pending_management 0x770817ec → address
performance_fee_rate 0x18f7b782 → uint256
previewDeposit 0xef8b30f7 → uint256
previewMint 0xb3d7f6b9 → uint256
previewRedeem 0x4cdad506 → uint256
previewWithdraw 0x0a28a477 → uint256
symbol 0x95d89b41 → string
totalAssets 0x01e1d114 → uint256
totalSupply 0x18160ddd → uint256
treasury 0x61d027b3 → address
updated 0x7b2aab03 → uint256
vote_weight 0xf49ec310 → uint256
Write Contract 22 functions
These functions modify contract state and require a wallet transaction to execute.
accept_management 0x759be10c
No parameters
approve 0x095ea7b3
address _spender
uint256 _value
returns: bool
decreaseAllowance 0xa457c2d7
address _spender
uint256 _value
returns: bool
deposit 0xb6b55f25
uint256 _assets
returns: uint256
deposit 0x6e553f65
uint256 _assets
address _receiver
returns: uint256
increaseAllowance 0x39509351
address _spender
uint256 _value
returns: bool
mint 0xa0712d68
uint256 _shares
returns: uint256
mint 0x94bf804d
uint256 _shares
address _receiver
returns: uint256
redeem 0xdb006a75
uint256 _shares
returns: uint256
redeem 0x7bde82f2
uint256 _shares
address _receiver
returns: uint256
redeem 0xba087652
uint256 _shares
address _receiver
address _owner
returns: uint256
rescue 0x4fdf5d1d
address _token
address _receiver
set_half_time 0x1bf93f86
uint256 _half_time
set_management 0xfd066ecc
address _management
set_performance_fee_rate 0x3047ce9d
uint256 _fee_rate
set_treasury 0x30bcd67b
address _treasury
transfer 0xa9059cbb
address _to
uint256 _value
returns: bool
transferFrom 0x23b872dd
address _from
address _to
uint256 _value
returns: bool
update_amounts 0x3ee352fc
No parameters
returns: uint256, uint256, uint256
withdraw 0x2e1a7d4d
uint256 _assets
returns: uint256
withdraw 0x00f714ce
uint256 _assets
address _receiver
returns: uint256
withdraw 0xb460af94
uint256 _assets
address _receiver
address _owner
returns: uint256
Recent Transactions
No transactions found for this address