Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x602d3d81 | 23370958 | 159 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Minimal Proxy Contract for 0x60043a545e22424e73a2debb98f8cd4361fe3da0
Contract Name:
Cliff Escrow
Compiler Version
vyper:0.4.3
Contract Source Code (Vyper Json-Input format)
# @version 0.4.3
"""
@title Cliff Escrow
@author Yield Basis
@license MIT
@notice Limits what one can do with received tokens before the cliff time is over
"""
from ethereum.ercs import IERC20
interface VotingEscrow:
def create_lock(_value: uint256, _unlock_time: uint256): nonpayable
def increase_amount(_value: uint256): nonpayable
def increase_unlock_time(_unlock_time: uint256): nonpayable
def withdraw(): nonpayable
def transferFrom(owner: address, to: address, token_id: uint256): nonpayable
def infinite_lock_toggle(): nonpayable
interface GaugeController:
def vote_for_gauge_weights(_gauge_addrs: DynArray[address, 50], _user_weights: DynArray[uint256, 50]): nonpayable
interface AragonDAO:
def vote(_proposalId: uint256, _voteOption: uint8, _tryEarlyExecution: bool): nonpayable
event TokenRecovered:
token: indexed(address)
to: address
amount: uint256
GC: public(immutable(GaugeController))
YB: public(immutable(IERC20))
VE: public(immutable(VotingEscrow))
unlock_time: public(uint256)
recipient: public(address)
@deploy
def __init__(token: IERC20, ve: VotingEscrow, gc: GaugeController):
"""
@param token Token to be distributed by the CliffEscrow
@param ve VotingEscrow (ve-locker)
@param gc GaugeController
"""
YB = token
VE = ve
GC = gc
self.recipient = self
@external
def initialize(recipient: address, unlock_time: uint256) -> bool:
"""
@notice Initialize an instance created by a factory contract
@param recipient Recipient of the tokens (one per contract!)
@param unlock_time When all the tokens can be released (cliff time)
"""
assert recipient != empty(address), "Empty recipient"
assert self.recipient == empty(address), "Already initialized"
assert unlock_time > block.timestamp
self.recipient = recipient
self.unlock_time = unlock_time
extcall YB.approve(VE.address, max_value(uint256))
return True
@internal
def _access():
assert msg.sender == self.recipient, "Not authorized"
@internal
def _cliff():
assert block.timestamp >= self.unlock_time, "Cliff still applies"
@external
@nonreentrant
def create_lock(_value: uint256, _unlock_time: uint256):
"""
@notice Create a ve-lock while affected by the cliff
@param _value Amount to ve-lock
@param _unlock_time Time for ve-lock to end
"""
self._access()
extcall VE.create_lock(_value, _unlock_time)
@external
@nonreentrant
def increase_amount(_value: uint256):
"""
@notice Increase amount in the ve-lock
@param _value Number of tokens to add to ve-lock
"""
self._access()
extcall VE.increase_amount(_value)
@external
@nonreentrant
def increase_unlock_time(_unlock_time: uint256):
"""
@notice Increase the duration of ve-lock
@param _unlock_time New unlock timestamp (seconds)
"""
self._access()
extcall VE.increase_unlock_time(_unlock_time)
@external
@nonreentrant
def withdraw():
"""
@notice Withdraw all tokens from expired ve-lock back to the CliffEscrow contract
"""
self._access()
extcall VE.withdraw()
@external
@nonreentrant
def transferFrom(owner: address, to: address, token_id: uint256):
"""
@notice Transfer ve-locked NFT which the CliffEscrow has access to anywhere - only after cliff is finished
"""
self._access()
self._cliff()
extcall VE.transferFrom(owner, to, token_id)
@external
@nonreentrant
def vote_for_gauge_weights(_gauge_addrs: DynArray[address, 50], _user_weights: DynArray[uint256, 50]):
"""
@notice Vote for gauge weights from inside the CliffEscrow with a ve-lock we created
@param _gauge_addrs Gauges to vote for
@param _user_weights Voting weights of the gauges
"""
self._access()
extcall GC.vote_for_gauge_weights(_gauge_addrs, _user_weights)
@external
@nonreentrant
def aragon_vote(dao: AragonDAO, proposal_id: uint256, vote_option: uint8, early_execution: bool):
"""
@notice Perform an Aragon vote using ve-lock we have inside CliffEscrow
@param dao Aragon DAO voting plugin address
@param proposal_id Proposal to vote for
@param vote_option Option to choose when voting
@param early_execution Early execution parameter
"""
self._access()
extcall dao.vote(proposal_id, vote_option, early_execution)
@external
@nonreentrant
def infinite_lock_toggle():
"""
@notice Make ve-lock automatically relocking or remove this setting
"""
self._access()
extcall VE.infinite_lock_toggle()
@external
@nonreentrant
def transfer(to: address, amount: uint256):
"""
@notice Transfer the token (not ve-lock!) anywhere. Requires cliff to be finished.
Recipient of CliffEscrow can transfer anywhere, but everyone else only to recipient.
"""
assert self.recipient in [msg.sender, to], "Not authorized"
# If msg.sender is recipient - they can transfer anywhere
# If msg.sender is NOT recipient - they can transfer only to recipient
self._cliff()
extcall YB.transfer(to, amount)
@external
@nonreentrant
def approve(_for: address, amount: uint256):
"""
@notice Approve the cliff-affected tokens for transfering out. Only after cliff is finished.
@param _for Address which can take our tokens
@param amount Amount approved
"""
self._access()
self._cliff()
extcall YB.approve(_for, amount)
@external
@nonreentrant
def recover_token(token: IERC20, to: address, amount: uint256):
"""
@notice Recover (send) any token not affected by cliff
@param token Token to recover
@param to Address to send to
@param amount Amount of token to send
"""
self._access()
assert token != YB, "Cannot recover YB"
assert extcall token.transfer(to, amount, default_return_value=True)
log TokenRecovered(token=token.address, to=to, amount=amount){
"outputSelection": {
"contracts/dao/CliffEscrow.vy": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
},
"search_paths": [
"."
]
}Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"TokenRecovered","type":"event"},{"inputs":[{"name":"recipient","type":"address"},{"name":"unlock_time","type":"uint256"}],"name":"initialize","outputs":[{"name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_value","type":"uint256"},{"name":"_unlock_time","type":"uint256"}],"name":"create_lock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_value","type":"uint256"}],"name":"increase_amount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_unlock_time","type":"uint256"}],"name":"increase_unlock_time","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"owner","type":"address"},{"name":"to","type":"address"},{"name":"token_id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_gauge_addrs","type":"address[]"},{"name":"_user_weights","type":"uint256[]"}],"name":"vote_for_gauge_weights","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"dao","type":"address"},{"name":"proposal_id","type":"uint256"},{"name":"vote_option","type":"uint8"},{"name":"early_execution","type":"bool"}],"name":"aragon_vote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"infinite_lock_toggle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"to","type":"address"},{"name":"amount","type":"uint256"}],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_for","type":"address"},{"name":"amount","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"token","type":"address"},{"name":"to","type":"address"},{"name":"amount","type":"uint256"}],"name":"recover_token","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"GC","outputs":[{"name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"YB","outputs":[{"name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VE","outputs":[{"name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unlock_time","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"recipient","outputs":[{"name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"token","type":"address"},{"name":"ve","type":"address"},{"name":"gc","type":"address"}],"outputs":[],"stateMutability":"nonpayable","type":"constructor"}]Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
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.