-
Notifications
You must be signed in to change notification settings - Fork 22
/
VestingEscrowFactory.vy
119 lines (104 loc) · 3.5 KB
/
VestingEscrowFactory.vy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# @version 0.3.10
"""
@title Vesting Escrow Factory
@author Curve Finance, Yearn Finance
@license MIT
@notice Stores and distributes ERC20 tokens by deploying `VestingEscrowSimple` contracts
"""
from vyper.interfaces import ERC20
interface VestingEscrowSimple:
def initialize(
owner: address,
token: ERC20,
recipient: address,
amount: uint256,
start_time: uint256,
end_time: uint256,
cliff_length: uint256,
open_claim: bool,
) -> bool: nonpayable
event VestingEscrowCreated:
funder: indexed(address)
token: indexed(ERC20)
recipient: indexed(address)
escrow: address
amount: uint256
vesting_start: uint256
vesting_duration: uint256
cliff_length: uint256
open_claim: bool
TARGET: public(immutable(address))
VYPER: public(immutable(address))
@external
def __init__(target: address, vyper_donate: address):
"""
@notice Contract constructor
@dev Prior to deployment you must deploy one copy of `VestingEscrowSimple` which
is used as a library for vesting contracts deployed by this factory
@param target `VestingEscrowSimple` contract address
@param vyper_donate Vyper Safe address for donations (vyperlang.eth on mainnet)
"""
TARGET = target
VYPER = vyper_donate
@external
def deploy_vesting_contract(
token: ERC20,
recipient: address,
amount: uint256,
vesting_duration: uint256,
vesting_start: uint256 = block.timestamp,
cliff_length: uint256 = 0,
open_claim: bool = True,
support_vyper: uint256 = 100,
owner: address = msg.sender,
) -> address:
"""
@notice Deploy a new vesting contract
@dev Prior to deployment you must approve `amount` + `amount` * `support_vyper` / 10_000
tokens
@param token ERC20 token being distributed
@param recipient Address to vest tokens for
@param amount Amount of tokens being vested for `recipient`
@param vesting_duration Time period (in seconds) over which tokens are released
@param vesting_start Epoch time when tokens begin to vest
@param open_claim Switch if anyone can claim for `recipient`
@param support_vyper Donation percentage in bps, 1% by default
@param owner Vesting contract owner
"""
assert cliff_length <= vesting_duration # dev: incorrect vesting cliff
assert vesting_start + vesting_duration > block.timestamp # dev: just use a transfer, dummy
assert vesting_duration > 0 # dev: duration must be > 0
assert recipient not in [self, empty(address), token.address, owner] # dev: wrong recipient
escrow: address = create_minimal_proxy_to(TARGET)
VestingEscrowSimple(escrow).initialize(
owner,
token,
recipient,
amount,
vesting_start,
vesting_start + vesting_duration,
cliff_length,
open_claim,
)
# skip transferFrom and approve and send directly to escrow
assert token.transferFrom(msg.sender, escrow, amount, default_return_value=True) # dev: funding failed
if support_vyper > 0:
assert VYPER != empty(address) # dev: lost donation
assert token.transferFrom(
msg.sender,
VYPER,
amount * support_vyper / 10_000,
default_return_value=True
) # dev: donation failed
log VestingEscrowCreated(
msg.sender,
token,
recipient,
escrow,
amount,
vesting_start,
vesting_duration,
cliff_length,
open_claim,
)
return escrow