-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathVotingAdapter.vy
207 lines (164 loc) · 5.36 KB
/
VotingAdapter.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# @version 0.3.7
"""
@title Voting Adapter
@author Lido Finance
@license GPL-3.0
@notice Used to allow voting with tokens under vesting
"""
from vyper.interfaces import ERC20
interface IDelegation:
def setDelegate(
_id: bytes32,
_delegate: address,
): nonpayable
interface IVoting:
def vote(
_voteId: uint256,
_supports: bool,
_executesIfDecided_deprecated: bool,
): nonpayable
def assignDelegate(
_delegate: address,
): nonpayable
def unassignDelegate(): nonpayable
event ERC20Recovered:
token: address
amount: uint256
event ETHRecovered:
amount: uint256
event OwnerChanged:
owner: address
VOTING_CONTRACT_ADDR: immutable(address)
SNAPSHOT_DELEGATE_CONTRACT_ADDR: immutable(address)
owner: public(address)
@external
def __init__(
voting_addr: address,
snapshot_delegate_addr: address,
owner: address,
):
"""
@notice Initialize source contract implementation.
@param voting_addr Address of the Voting contract
@param snapshot_delegate_addr Address of the Shapshot Delegate contract
@param owner Address to recover tokens and ether to
"""
assert owner != empty(address), "zero owner"
assert voting_addr != empty(address), "zero voting_addr"
assert snapshot_delegate_addr != empty(
address
), "zero snapshot_delegate_addr"
self.owner = owner
VOTING_CONTRACT_ADDR = voting_addr
SNAPSHOT_DELEGATE_CONTRACT_ADDR = snapshot_delegate_addr
@external
@view
def encode_aragon_vote_calldata(voteId: uint256, supports: bool) -> Bytes[1000]:
"""
@notice Encode calldata for use in VestingEscrow. Returns type is Bytes[1000] to be compatible with up to 30 args
@param voteId Id of the vote
@param supports Support flag true - yea, false - nay
"""
return _abi_encode(voteId, supports)
@external
def aragon_vote(abi_encoded_params: Bytes[1000]):
"""
@notice Cast vote on Aragon voting
@param abi_encoded_params Abi encoded data for call. Can be obtained from encode_aragon_vote_calldata
"""
vote_id: uint256 = empty(uint256)
supports: bool = empty(bool)
vote_id, supports = _abi_decode(abi_encoded_params, (uint256, bool))
IVoting(VOTING_CONTRACT_ADDR).vote(
vote_id, supports, False
) # dev: third arg is deprecated
@external
@view
def encode_snapshot_set_delegate_calldata(delegate: address) -> Bytes[1000]:
"""
@notice Encode calldata for use in VestingEscrow. Returns type is Bytes[1000] to be compatible with up to 30 args
@param delegate Address of the delegate
"""
return _abi_encode(delegate)
@external
def snapshot_set_delegate(abi_encoded_params: Bytes[1000]):
"""
@notice Delegate Snapshot voting power of all available tokens
@param abi_encoded_params Abi encoded data for call. Can be obtained from encode_snapshot_set_delegate_calldata
"""
delegate: address = empty(address)
delegate = _abi_decode(abi_encoded_params, (address))
IDelegation(SNAPSHOT_DELEGATE_CONTRACT_ADDR).setDelegate(
empty(bytes32), delegate
) # dev: null id allows voting at any snapshot space
@external
@view
def encode_delegate_calldata(delegate: address) -> Bytes[1000]:
"""
@notice Encode calldata for use in VestingEscrow. Returns type is Bytes[1000] to be compatible with up to 30 args
@param delegate Address of the delegate
"""
return _abi_encode(delegate)
@external
def delegate(abi_encoded_params: Bytes[1000]):
"""
@notice Delegate voting power of all available tokens
@param abi_encoded_params Abi encoded data for call. Can be obtained from encode_delegate_calldata
"""
delegate: address = empty(address)
delegate = _abi_decode(abi_encoded_params, (address))
if delegate == empty(address):
IVoting(VOTING_CONTRACT_ADDR).unassignDelegate()
else:
IVoting(VOTING_CONTRACT_ADDR).assignDelegate(delegate)
@external
@view
def voting_contract_addr() -> address:
return VOTING_CONTRACT_ADDR
@external
@view
def snapshot_delegate_contract_addr() -> address:
return SNAPSHOT_DELEGATE_CONTRACT_ADDR
@external
def change_owner(owner: address):
"""
@notice Change contract owner.
@param owner Address of the new owner. Must be non-zero.
"""
self._check_sender_is_owner()
assert owner != empty(address), "zero owner address"
self.owner = owner
log OwnerChanged(owner)
@external
def recover_erc20(token: address, amount: uint256):
"""
@notice Recover ERC20 tokens to owner
@param token Address of the ERC20 token to be recovered
"""
if amount != 0:
assert ERC20(token).transfer(
self.owner, amount, default_return_value=True
), "transfer failed"
log ERC20Recovered(token, amount)
@external
def recover_ether():
"""
@notice Recover Ether to owner
"""
amount: uint256 = self.balance
if amount != 0:
self._safe_send_ether(self.owner, amount)
log ETHRecovered(amount)
@internal
def _check_sender_is_owner():
assert msg.sender == self.owner, "msg.sender not owner"
@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"