Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
21029870 | 74 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Minimal Proxy Contract for 0x9692f652a3048eb7f5074e12b907f20d33f37a01
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 assert self.token.transfer(beneficiary, ruggable, default_return_value=True) self.owner = empty(address) 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)
[{"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"}]}]
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
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.