ETH Price: $3,315.65 (+1.95%)
 

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Claim212989012024-11-30 7:07:5954 days ago1732950479IN
0x47287eA8...56E89931A
0 ETH0.001147417.06029033
Claim210483242024-10-26 7:31:5989 days ago1729927919IN
0x47287eA8...56E89931A
0 ETH0.000810084.98464322
Claim209482202024-10-12 8:05:23103 days ago1728720323IN
0x47287eA8...56E89931A
0 ETH0.001883511.58956901
Claim209482172024-10-12 8:04:47103 days ago1728720287IN
0x47287eA8...56E89931A
0 ETH0.0015498111.12656779
Claim207603562024-09-16 2:59:23129 days ago1726455563IN
0x47287eA8...56E89931A
0 ETH0.000448722.76110618
Delegate206847092024-09-05 13:33:11140 days ago1725543191IN
0x47287eA8...56E89931A
0 ETH0.000448443.96783466
Claim205714782024-08-20 17:59:35156 days ago1724176775IN
0x47287eA8...56E89931A
0 ETH0.000379862.33738842
Claim204336392024-08-01 12:16:59175 days ago1722514619IN
0x47287eA8...56E89931A
0 ETH0.001450378.92444376
Claim202387202024-07-05 7:09:35202 days ago1720163375IN
0x47287eA8...56E89931A
0 ETH0.0024413815.02234453
Claim202194542024-07-02 14:33:35205 days ago1719930815IN
0x47287eA8...56E89931A
0 ETH0.001081556.65500063
Claim202194462024-07-02 14:31:59205 days ago1719930719IN
0x47287eA8...56E89931A
0 ETH0.001005477.21859807
Claim201919272024-06-28 18:18:47209 days ago1719598727IN
0x47287eA8...56E89931A
0 ETH0.000811384.99262846
Claim199553952024-05-26 16:58:47242 days ago1716742727IN
0x47287eA8...56E89931A
0 ETH0.00102226.28939703
Aragon_vote197318842024-04-25 10:48:23273 days ago1714042103IN
0x47287eA8...56E89931A
0 ETH0.0012123710.23607613
Aragon_vote192828872024-02-22 11:34:35336 days ago1708601675IN
0x47287eA8...56E89931A
0 ETH0.0044298437.40130301
Claim192638932024-02-19 19:36:11339 days ago1708371371IN
0x47287eA8...56E89931A
0 ETH0.0058049335.71894325
Claim192638862024-02-19 19:34:47339 days ago1708371287IN
0x47287eA8...56E89931A
0 ETH0.0048939635.13507679
Claim190821112024-01-25 7:22:59364 days ago1706167379IN
0x47287eA8...56E89931A
0 ETH0.0018519611.39549602
Claim188615942023-12-25 8:34:47395 days ago1703493287IN
0x47287eA8...56E89931A
0 ETH0.0031360219.29661433
Claim188615892023-12-25 8:33:35395 days ago1703493215IN
0x47287eA8...56E89931A
0 ETH0.0024213517.44138181
Claim186298712023-11-22 21:10:35428 days ago1700687435IN
0x47287eA8...56E89931A
0 ETH0.0072418444.56056033
Claim184941362023-11-03 21:12:59447 days ago1699045979IN
0x47287eA8...56E89931A
0 ETH0.0033501518.86040008
Aragon_vote182827432023-10-05 7:12:59476 days ago1696489979IN
0x47287eA8...56E89931A
0 ETH0.00075346.47026134
Snapshot_set_del...181856132023-09-21 17:03:35490 days ago1695315815IN
0x47287eA8...56E89931A
0 ETH0.0008127112.24517561

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block
From
To
181846942023-09-21 13:57:35490 days ago1695304655  Contract Creation0 ETH
Loading...
Loading

Minimal Proxy Contract for 0x484fd04c598a095360df89bf85ab34c37127aa39

Contract Name:
Vyper_contract

Compiler Version
vyper:0.3.7

Optimization Enabled:
N/A

Other Settings:
default evmVersion, GNU GPLv3 license

Contract Source Code (Vyper language format)

# @version 0.3.7

"""
@title Vesting Escrow
@author Curve Finance, Yearn Finance, Lido Finance
@license GPL-3.0
@notice Vests ERC20 tokens for a single address
@dev Intended to be deployed many times via `VotingEscrowFactory`
"""

from vyper.interfaces import ERC20


interface IVestingEscrowFactory:
    def voting_adapter() -> address: nonpayable
    def owner() -> address: nonpayable
    def manager() -> address: nonpayable


event VestingEscrowInitialized:
    factory: indexed(address)
    recipient: indexed(address)
    token: indexed(address)
    amount: uint256
    start_time: uint256
    end_time: uint256
    cliff_length: uint256
    is_fully_revokable: bool


event Claim:
    beneficiary: indexed(address)
    claimed: uint256


event UnvestedTokensRevoked:
    recoverer: indexed(address)
    revoked: uint256


event VestingFullyRevoked:
    recoverer: indexed(address)
    revoked: uint256


event ERC20Recovered:
    token: address
    amount: uint256


event ETHRecovered:
    amount: uint256


recipient: public(address)
token: public(ERC20)
start_time: public(uint256)
end_time: public(uint256)
cliff_length: public(uint256)
factory: public(IVestingEscrowFactory)
total_locked: public(uint256)
is_fully_revokable: public(bool)

total_claimed: public(uint256)
disabled_at: public(uint256)
initialized: public(bool)
is_fully_revoked: public(bool)


@external
def __init__():
    """
    @notice Initialize source contract implementation.
    """
    # ensure that the original contract cannot be initialized
    self.initialized = True


@external
def initialize(
    token: address,
    amount: uint256,
    recipient: address,
    start_time: uint256,
    end_time: uint256,
    cliff_length: uint256,
    is_fully_revokable: bool,
    factory: address,
) -> bool:
    """
    @notice Initialize the contract.
    @dev This function is separate from `__init__` because of the factory pattern
         used in `VestingEscrowFactory.deploy_vesting_contract`. It may be called
         once per deployment.
    @param token Address of the ERC20 token being distributed
    @param amount Amount of the ERC20 token to be controleed by escrow
    @param recipient Address to vest tokens for
    @param start_time Epoch time at which token distribution starts
    @param end_time Time until everything should be vested
    @param cliff_length Duration after which the first portion vests
    @param factory Address of the parent factory
    """
    assert not self.initialized, "can only initialize once"
    self.initialized = True

    self.token = ERC20(token)
    self.is_fully_revokable = is_fully_revokable
    self.start_time = start_time
    self.end_time = end_time
    self.cliff_length = cliff_length

    assert ERC20(token).balanceOf(self) >= amount, "insufficient balance"

    self.total_locked = amount
    self.recipient = recipient
    self.disabled_at = end_time  # Set to maximum time
    self.factory = IVestingEscrowFactory(factory)
    log VestingEscrowInitialized(
        factory,
        recipient,
        token,
        amount,
        start_time,
        end_time,
        cliff_length,
        is_fully_revokable,
    )

    return True


@internal
@view
def _total_vested_at(time: uint256) -> 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() -> uint256:
    if self.is_fully_revoked:
        return 0
    claim_time: uint256 = min(block.timestamp, self.disabled_at)
    return self._total_vested_at(claim_time) - self.total_claimed


@external
@view
def unclaimed() -> uint256:
    """
    @notice Get the number of unclaimed, vested tokens for recipient
    """
    return self._unclaimed()


@internal
@view
def _locked() -> uint256:
    if block.timestamp >= self.disabled_at:
        return 0
    return self.total_locked - self._total_vested_at(block.timestamp)


@external
@view
def locked() -> uint256:
    """
    @notice Get the number of locked tokens for recipient
    """
    return self._locked()


@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
    """
    self._check_sender_is_recipient()

    claimable: uint256 = min(self._unclaimed(), amount)
    self.total_claimed += claimable

    assert self.token.transfer(
        beneficiary, claimable, default_return_value=True
    ), "transfer failed"

    log Claim(beneficiary, claimable)

    return claimable


@external
def revoke_unvested():
    """
    @notice Disable further flow of tokens and revoke the unvested part to owner
    """
    self._check_sender_is_owner_or_manager()

    revokable: uint256 = self._locked()
    assert revokable > 0, "nothing to revoke"
    self.disabled_at = block.timestamp

    assert self.token.transfer(
        self._owner(), revokable, default_return_value=True
    ), "transfer failed"

    log UnvestedTokensRevoked(msg.sender, revokable)


@external
def revoke_all():
    """
    @notice Disable further flow of tokens and revoke all tokens to owner
    """
    self._check_sender_is_owner()
    assert self.is_fully_revokable, "not allowed for ordinary vesting"
    assert not self.is_fully_revoked, "already fully revoked"

    # NOTE: do not revoke extra tokens
    revokable: uint256 = self._locked() + self._unclaimed()
    assert revokable > 0, "nothing to revoke"

    self.is_fully_revoked = True
    self.disabled_at = block.timestamp

    assert self.token.transfer(
        self._owner(), revokable, default_return_value=True
    ), "transfer failed"

    log VestingFullyRevoked(msg.sender, revokable)


@external
def recover_erc20(token: address, amount: uint256):
    """
    @notice Recover ERC20 tokens to recipient
    @param token Address of the ERC20 token to be recovered
    @param amount Amount of the ERC20 token to be recovered
    """
    recoverable: uint256 = amount
    if token == self.token.address:
        available: uint256 = ERC20(token).balanceOf(self) - (
            self._locked() + self._unclaimed()
        )
        recoverable = min(recoverable, available)
    if recoverable > 0:
        assert ERC20(token).transfer(
            self.recipient, recoverable, default_return_value=True
        ), "transfer failed"
        log ERC20Recovered(token, recoverable)


@external
def recover_ether():
    """
    @notice Recover Ether to recipient
    """
    amount: uint256 = self.balance
    if amount != 0:
        self._safe_send_ether(self.recipient, amount)
        log ETHRecovered(amount)


@external
def aragon_vote(abi_encoded_params: Bytes[1000]):
    """
    @notice Participate Aragon vote using all available tokens on the contract's balance
    @param abi_encoded_params Abi encoded data for call. Can be obtained from VotingAdapter.encode_aragon_vote_calldata
    """
    self._check_sender_is_recipient()
    self._check_voting_adapter_is_set()
    raw_call(
        self.factory.voting_adapter(),
        _abi_encode(
            abi_encoded_params,
            method_id=method_id("aragon_vote(bytes)"),
        ),
        is_delegate_call=True,
    )


@external
def snapshot_set_delegate(abi_encoded_params: Bytes[1000]):
    """
    @notice Delegate Snapshot voting power of all available tokens on the contract's balance
    @param abi_encoded_params Abi encoded data for call. Can be obtained from VotingAdapter.encode_snapshot_set_delegate_calldata
    """
    self._check_sender_is_recipient()
    self._check_voting_adapter_is_set()
    raw_call(
        self.factory.voting_adapter(),
        _abi_encode(
            abi_encoded_params,
            method_id=method_id("snapshot_set_delegate(bytes)"),
        ),
        is_delegate_call=True,
    )


@external
def delegate(abi_encoded_params: Bytes[1000]):
    """
    @notice Delegate voting power of all available tokens on the contract's balance
    @param abi_encoded_params Abi encoded data for call. Can be obtained from VotingAdapter.encode_delegate_calldata
    """
    self._check_sender_is_recipient()
    self._check_voting_adapter_is_set()
    raw_call(
        self.factory.voting_adapter(),
        _abi_encode(
            abi_encoded_params,
            method_id=method_id("delegate(bytes)"),
        ),
        is_delegate_call=True,
    )


@internal
def _owner() -> address:
    return self.factory.owner()


@internal
def _manager() -> address:
    return self.factory.manager()


@internal
def _check_sender_is_owner_or_manager():
    assert (
        msg.sender == self._owner() or msg.sender == self._manager()
    ), "msg.sender not owner or manager"


@internal
def _check_sender_is_owner():
    assert msg.sender == self._owner(), "msg.sender not owner"


@internal
def _check_sender_is_recipient():
    assert msg.sender == self.recipient, "msg.sender not recipient"


@internal
def _check_voting_adapter_is_set():
    assert self.factory.voting_adapter() != empty(
        address
    ), "voting adapter not set"


@internal
def _safe_send_ether(_to: address, _value: uint256):
    """
    @notice Overcome 2300 gas limit on simple send
    """
    _response: Bytes[32] = raw_call(
        _to, empty(bytes32), value=_value, max_outsize=32
    )
    if len(_response) > 0:
        assert convert(_response, bool), "ETH transfer failed"

Contract ABI

[{"name":"VestingEscrowInitialized","inputs":[{"name":"factory","type":"address","indexed":true},{"name":"recipient","type":"address","indexed":true},{"name":"token","type":"address","indexed":true},{"name":"amount","type":"uint256","indexed":false},{"name":"start_time","type":"uint256","indexed":false},{"name":"end_time","type":"uint256","indexed":false},{"name":"cliff_length","type":"uint256","indexed":false},{"name":"is_fully_revokable","type":"bool","indexed":false}],"anonymous":false,"type":"event"},{"name":"Claim","inputs":[{"name":"beneficiary","type":"address","indexed":true},{"name":"claimed","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"UnvestedTokensRevoked","inputs":[{"name":"recoverer","type":"address","indexed":true},{"name":"revoked","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"VestingFullyRevoked","inputs":[{"name":"recoverer","type":"address","indexed":true},{"name":"revoked","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"ERC20Recovered","inputs":[{"name":"token","type":"address","indexed":false},{"name":"amount","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"ETHRecovered","inputs":[{"name":"amount","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"initialize","inputs":[{"name":"token","type":"address"},{"name":"amount","type":"uint256"},{"name":"recipient","type":"address"},{"name":"start_time","type":"uint256"},{"name":"end_time","type":"uint256"},{"name":"cliff_length","type":"uint256"},{"name":"is_fully_revokable","type":"bool"},{"name":"factory","type":"address"}],"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_unvested","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"revoke_all","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"recover_erc20","inputs":[{"name":"token","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"recover_ether","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"aragon_vote","inputs":[{"name":"abi_encoded_params","type":"bytes"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"snapshot_set_delegate","inputs":[{"name":"abi_encoded_params","type":"bytes"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"delegate","inputs":[{"name":"abi_encoded_params","type":"bytes"}],"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":"factory","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"total_locked","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"is_fully_revokable","inputs":[],"outputs":[{"name":"","type":"bool"}]},{"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":"initialized","inputs":[],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"is_fully_revoked","inputs":[],"outputs":[{"name":"","type":"bool"}]}]

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.