Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Simple Vesting Escrow
Compiler Version
vyper:0.3.10
Contract Source Code (Vyper language format)
# @version 0.3.10 """ @title Simple Vesting Escrow @author Curve Finance, Yearn Finance @license MIT @notice Vests ERC20 tokens for a single address @dev Intended to be deployed many times via `VotingEscrowFactory` """ from vyper.interfaces import ERC20 event Claim: recipient: indexed(address) claimed: uint256 event Revoked: recipient: address owner: address rugged: uint256 ts: uint256 event Disowned: owner: address event SetOpenClaim: state: bool recipient: public(address) token: public(ERC20) start_time: public(uint256) end_time: public(uint256) cliff_length: public(uint256) total_locked: public(uint256) total_claimed: public(uint256) disabled_at: public(uint256) open_claim: public(bool) initialized: public(bool) owner: public(address) @external def __init__(): # ensure that the original contract cannot be initialized self.initialized = True @external def initialize( owner: address, token: ERC20, recipient: address, amount: uint256, start_time: uint256, end_time: uint256, cliff_length: uint256, open_claim: bool, ) -> bool: """ @notice Initialize the contract @dev This function is seperate from `__init__` because of the factory pattern used in `VestingEscrowFactory.deploy_vesting_contract`. It may be called once per deployment @param owner Owner address @param token Address of the ERC20 token being distributed @param recipient Address to vest tokens for @param amount Amount of tokens being vested for `recipient` @param start_time Epoch time at which token distribution starts @param end_time Time until everything should be vested @param cliff_length Duration (in seconds) after which the first portion vests @param open_claim Switch if anyone can claim for `recipient` """ assert not self.initialized # dev: can only initialize once self.initialized = True self.token = token self.owner = owner self.start_time = start_time self.end_time = end_time self.cliff_length = cliff_length self.recipient = recipient self.disabled_at = end_time # Set to maximum time self.total_locked = amount self.open_claim = open_claim return True @internal @view def _total_vested_at(time: uint256 = block.timestamp) -> uint256: start: uint256 = self.start_time end: uint256 = self.end_time locked: uint256 = self.total_locked if time < start + self.cliff_length: return 0 return min(locked * (time - start) / (end - start), locked) @internal @view def _unclaimed(time: uint256 = block.timestamp) -> uint256: return self._total_vested_at(time) - self.total_claimed @external @view def unclaimed() -> uint256: """ @notice Get the number of unclaimed, vested tokens for recipient @dev If `revoke` is activated, limit by the activation timestamp """ return self._unclaimed(min(block.timestamp, self.disabled_at)) @internal @view def _locked(time: uint256 = block.timestamp) -> uint256: return self._total_vested_at(self.disabled_at) - self._total_vested_at(time) @external @view def locked() -> uint256: """ @notice Get the number of locked tokens for recipient @dev If `revoke` is activated, limit by the activation timestamp """ return self._locked(min(block.timestamp, self.disabled_at)) @external def claim(beneficiary: address = msg.sender, amount: uint256 = max_value(uint256)) -> uint256: """ @notice Claim tokens which have vested @param beneficiary Address to transfer claimed tokens to @param amount Amount of tokens to claim """ recipient: address = self.recipient assert msg.sender == recipient or self.open_claim and recipient == beneficiary # dev: not authorized claim_period_end: uint256 = min(block.timestamp, self.disabled_at) claimable: uint256 = min(self._unclaimed(claim_period_end), amount) self.total_claimed += claimable assert self.token.transfer(beneficiary, claimable, default_return_value=True) log Claim(beneficiary, claimable) return claimable @external def revoke(ts: uint256 = block.timestamp, beneficiary: address = msg.sender): """ @notice Disable further flow of tokens and clawback the unvested part to `beneficiary` Revoking more than once is futile @dev Owner is set to zero address @param ts Timestamp of the clawback @param beneficiary Recipient of the unvested part """ owner: address = self.owner assert msg.sender == owner # dev: not owner assert ts >= block.timestamp and ts < self.end_time # dev: no back to the future ruggable: uint256 = self._locked(ts) self.disabled_at = ts self.owner = empty(address) assert self.token.transfer(beneficiary, ruggable, default_return_value=True) log Disowned(owner) log Revoked(self.recipient, owner, ruggable, ts) @external def disown(): """ @notice Renounce owner control of the escrow """ owner: address = self.owner assert msg.sender == owner # dev: not owner self.owner = empty(address) log Disowned(owner) @external def set_open_claim(open_claim: bool): """ @notice Disallow or let anyone claim tokens for `recipient` """ assert msg.sender == self.recipient # dev: not recipient self.open_claim = open_claim log SetOpenClaim(open_claim) @external def collect_dust(token: ERC20, beneficiary: address = msg.sender): recipient: address = self.recipient assert msg.sender == recipient or self.open_claim and recipient == beneficiary # dev: not authorized amount: uint256 = token.balanceOf(self) if token == self.token: amount = amount + self.total_claimed - self._total_vested_at(self.disabled_at) assert token.transfer(beneficiary, amount, default_return_value=True) assert self.token.balanceOf(self) >= (self._total_vested_at(self.disabled_at) - self.total_claimed)
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"name":"Claim","inputs":[{"name":"recipient","type":"address","indexed":true},{"name":"claimed","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"Revoked","inputs":[{"name":"recipient","type":"address","indexed":false},{"name":"owner","type":"address","indexed":false},{"name":"rugged","type":"uint256","indexed":false},{"name":"ts","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"Disowned","inputs":[{"name":"owner","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"SetOpenClaim","inputs":[{"name":"state","type":"bool","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"initialize","inputs":[{"name":"owner","type":"address"},{"name":"token","type":"address"},{"name":"recipient","type":"address"},{"name":"amount","type":"uint256"},{"name":"start_time","type":"uint256"},{"name":"end_time","type":"uint256"},{"name":"cliff_length","type":"uint256"},{"name":"open_claim","type":"bool"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"unclaimed","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"locked","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"claim","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"claim","inputs":[{"name":"beneficiary","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"claim","inputs":[{"name":"beneficiary","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"revoke","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"revoke","inputs":[{"name":"ts","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"revoke","inputs":[{"name":"ts","type":"uint256"},{"name":"beneficiary","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"disown","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"set_open_claim","inputs":[{"name":"open_claim","type":"bool"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"collect_dust","inputs":[{"name":"token","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"collect_dust","inputs":[{"name":"token","type":"address"},{"name":"beneficiary","type":"address"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"recipient","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"token","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"start_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"end_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"cliff_length","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"total_locked","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"total_claimed","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"disabled_at","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"open_claim","inputs":[],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"initialized","inputs":[],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address"}]}]
Contract Creation Code
3461001b5760016009556109e261001f610000396109e2610000f35b5f80fd5f3560e01c60026017820660011b6109b401601e395f51565b6366d003ac811861003357346109b0575f5460405260206040f35b636af904c6811861004f57346109b05760065460405260206040f35b6320c5429b81186108ae576024361034176109b0576004356101205233610140526101ed566108ae565b63fc0c546a81186108ae57346109b05760015460405260206040f36108ae565b63834ee41781186100b557346109b05760025460405260206040f35b6394abf76081186100d157346109b05760045460405260206040f35b634e71d92d81186108ae57346109b05733610100527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61012052610552566108ae565b631624335681186108ae57346109b05760035460405260206040f36108ae565b633c48a620811861015057346109b05760055460405260206040f35b631e9bf0da81186108ae57346109b057600a5460405260405133186109b0575f600a557fcf205606725a75744e28493139759507ffff2197fec2eafab0c70c8f126d819d60405160605260206060a1006108ae565b63ac1a2f6981186101c157346109b05760075460405260206040f35b6320d154da81186108ae576044361034176109b057600435610120526024358060a01c6109b057610140525b600a54610160526101605133186109b0574261012051101561020f575f610218565b60035461012051105b156109b0576101205160c05261022f6101a0610975565b6101a05161018052610120516007555f600a5560015463a9059cbb6101a052610140516101c052610180516101e05260206101a060446101bc5f855af1610278573d5f5f3e3d5ffd5b3d61028f57803b156109b0576001610200526102a8565b60203d106109b0576101a0518060011c6109b057610200525b610200905051156109b0577fcf205606725a75744e28493139759507ffff2197fec2eafab0c70c8f126d819d610160516101a05260206101a0a17f425a9d51f657355700ba416a4e9e606a23b8c5831a992441ddf42544656e3a8e5f546101a052610160516101c052610180516101e052610120516102005260806101a0a1006108ae565b632b584faa81186108ae57346109b05760085460405260206040f36108ae565b63158ef93e811861036957346109b05760095460405260206040f35b638956c98381186108ae576024361034176109b0573360e052610714566108ae565b638da5cb5b81186103a757346109b057600a5460405260206040f35b63669416b881186103dd57346109b0576020426007548082811882841002189050905060c0526103d861010061094c565b610100f35b631e83409a81186108ae576024361034176109b0576004358060a01c6109b057610100527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61012052610552566108ae565b63f586c19f81186108ae57610104361034176109b0576004358060a01c6109b0576040526024358060a01c6109b0576060526044358060a01c6109b05760805260e4358060011c6109b05760a0526009546109b0576001600955606051600155604051600a5560843560025560a43560035560c4356004556080515f5560a43560075560643560055560a051600855600160c052602060c0f36108ae565b63cf309012811861050357346109b0576020426007548082811882841002189050905060c0526104fe610120610975565b610120f35b63b6549f7581186108ae57346109b057426101205233610140526101ed566108ae565b63aad3ec9681186108ae576044361034176109b0576004358060a01c6109b05761010052602435610120525b5f5461014052610140513318610569576001610581565b600854610576575f610581565b610100516101405118155b156109b0574260075480828118828410021890509050610160526101605160c0526105ad6101a061094c565b6101a051610120518082811882841002189050905061018052600654610180518082018281106109b0579050905060065560015463a9059cbb6101a052610100516101c052610180516101e05260206101a060446101bc5f855af1610614573d5f5f3e3d5ffd5b3d61062b57803b156109b057600161020052610644565b60203d106109b0576101a0518060011c6109b057610200525b610200905051156109b057610100517f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4610180516101a05260206101a0a26020610180f36108ae565b63ff8a013081186108ae576024361034176109b0576004358060011c6109b0576040525f5433186109b0576040516008557f4e27d92a6c1bca4eaeb233e05bac94da829072d2af2e4506ab986834d0be08f860405160605260206060a1006108ae565b639d4c2f6981186108ae576044361034176109b0576024358060a01c6109b05760e0525b6004358060a01c6109b05760c0525f5461010052610100513318610739576001610750565b600854610746575f610750565b60e0516101005118155b156109b05760c0516370a082316101405230610160526020610140602461015c845afa61077f573d5f5f3e3d5ffd5b60203d106109b0576101409050516101205260015460c051186107d957610120516006548082018281106109b057905090506007546040526107c26101406108b2565b610140518082038281116109b05790509050610120525b60c05163a9059cbb6101405260e0516101605261012051610180526020610140604461015c5f855af161080e573d5f5f3e3d5ffd5b3d61082557803b156109b05760016101a05261083e565b60203d106109b057610140518060011c6109b0576101a0525b6101a0905051156109b05760075460405261085a6101806108b2565b610180516006548082038281116109b057905090506001546370a082316101405230610160526020610140602461015c845afa610899573d5f5f3e3d5ffd5b60203d106109b057610140905051106109b057005b5f5ffd5b60025460605260035460805260055460a0526060516004548082018281106109b0579050905060405110156108ea575f81525061094a565b60a0516040516060518082038281116109b057905090508082028115838383041417156109b057905090506080516060518082038281116109b0579050905080156109b0578082049050905060a051808281188284100218905090508152505b565b60c05160405261095c60e06108b2565b60e0516006548082038281116109b05790509050815250565b60075460405261098560e06108b2565b60e05160c0516040526109996101006108b2565b610100518082038281116109b05790509050815250565b5f80fd001800990079042f08ae08ae08ae011404cd034d052608ae038b068d032d013408ae06f001a508ae08ae08ae08ae841909e281182e00a16576797065728300030a0015
Deployed Bytecode
0x5f3560e01c60026017820660011b6109b401601e395f51565b6366d003ac811861003357346109b0575f5460405260206040f35b636af904c6811861004f57346109b05760065460405260206040f35b6320c5429b81186108ae576024361034176109b0576004356101205233610140526101ed566108ae565b63fc0c546a81186108ae57346109b05760015460405260206040f36108ae565b63834ee41781186100b557346109b05760025460405260206040f35b6394abf76081186100d157346109b05760045460405260206040f35b634e71d92d81186108ae57346109b05733610100527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61012052610552566108ae565b631624335681186108ae57346109b05760035460405260206040f36108ae565b633c48a620811861015057346109b05760055460405260206040f35b631e9bf0da81186108ae57346109b057600a5460405260405133186109b0575f600a557fcf205606725a75744e28493139759507ffff2197fec2eafab0c70c8f126d819d60405160605260206060a1006108ae565b63ac1a2f6981186101c157346109b05760075460405260206040f35b6320d154da81186108ae576044361034176109b057600435610120526024358060a01c6109b057610140525b600a54610160526101605133186109b0574261012051101561020f575f610218565b60035461012051105b156109b0576101205160c05261022f6101a0610975565b6101a05161018052610120516007555f600a5560015463a9059cbb6101a052610140516101c052610180516101e05260206101a060446101bc5f855af1610278573d5f5f3e3d5ffd5b3d61028f57803b156109b0576001610200526102a8565b60203d106109b0576101a0518060011c6109b057610200525b610200905051156109b0577fcf205606725a75744e28493139759507ffff2197fec2eafab0c70c8f126d819d610160516101a05260206101a0a17f425a9d51f657355700ba416a4e9e606a23b8c5831a992441ddf42544656e3a8e5f546101a052610160516101c052610180516101e052610120516102005260806101a0a1006108ae565b632b584faa81186108ae57346109b05760085460405260206040f36108ae565b63158ef93e811861036957346109b05760095460405260206040f35b638956c98381186108ae576024361034176109b0573360e052610714566108ae565b638da5cb5b81186103a757346109b057600a5460405260206040f35b63669416b881186103dd57346109b0576020426007548082811882841002189050905060c0526103d861010061094c565b610100f35b631e83409a81186108ae576024361034176109b0576004358060a01c6109b057610100527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61012052610552566108ae565b63f586c19f81186108ae57610104361034176109b0576004358060a01c6109b0576040526024358060a01c6109b0576060526044358060a01c6109b05760805260e4358060011c6109b05760a0526009546109b0576001600955606051600155604051600a5560843560025560a43560035560c4356004556080515f5560a43560075560643560055560a051600855600160c052602060c0f36108ae565b63cf309012811861050357346109b0576020426007548082811882841002189050905060c0526104fe610120610975565b610120f35b63b6549f7581186108ae57346109b057426101205233610140526101ed566108ae565b63aad3ec9681186108ae576044361034176109b0576004358060a01c6109b05761010052602435610120525b5f5461014052610140513318610569576001610581565b600854610576575f610581565b610100516101405118155b156109b0574260075480828118828410021890509050610160526101605160c0526105ad6101a061094c565b6101a051610120518082811882841002189050905061018052600654610180518082018281106109b0579050905060065560015463a9059cbb6101a052610100516101c052610180516101e05260206101a060446101bc5f855af1610614573d5f5f3e3d5ffd5b3d61062b57803b156109b057600161020052610644565b60203d106109b0576101a0518060011c6109b057610200525b610200905051156109b057610100517f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4610180516101a05260206101a0a26020610180f36108ae565b63ff8a013081186108ae576024361034176109b0576004358060011c6109b0576040525f5433186109b0576040516008557f4e27d92a6c1bca4eaeb233e05bac94da829072d2af2e4506ab986834d0be08f860405160605260206060a1006108ae565b639d4c2f6981186108ae576044361034176109b0576024358060a01c6109b05760e0525b6004358060a01c6109b05760c0525f5461010052610100513318610739576001610750565b600854610746575f610750565b60e0516101005118155b156109b05760c0516370a082316101405230610160526020610140602461015c845afa61077f573d5f5f3e3d5ffd5b60203d106109b0576101409050516101205260015460c051186107d957610120516006548082018281106109b057905090506007546040526107c26101406108b2565b610140518082038281116109b05790509050610120525b60c05163a9059cbb6101405260e0516101605261012051610180526020610140604461015c5f855af161080e573d5f5f3e3d5ffd5b3d61082557803b156109b05760016101a05261083e565b60203d106109b057610140518060011c6109b0576101a0525b6101a0905051156109b05760075460405261085a6101806108b2565b610180516006548082038281116109b057905090506001546370a082316101405230610160526020610140602461015c845afa610899573d5f5f3e3d5ffd5b60203d106109b057610140905051106109b057005b5f5ffd5b60025460605260035460805260055460a0526060516004548082018281106109b0579050905060405110156108ea575f81525061094a565b60a0516040516060518082038281116109b057905090508082028115838383041417156109b057905090506080516060518082038281116109b0579050905080156109b0578082049050905060a051808281188284100218905090508152505b565b60c05160405261095c60e06108b2565b60e0516006548082038281116109b05790509050815250565b60075460405261098560e06108b2565b60e05160c0516040526109996101006108b2565b610100518082038281116109b05790509050815250565b5f80fd001800990079042f08ae08ae08ae011404cd034d052608ae038b068d032d013408ae06f001a508ae08ae08ae08ae
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.