@evvm/testnet-contracts 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +166 -0
- package/README.md +216 -0
- package/package.json +51 -0
- package/src/contracts/evvm/Evvm.sol +1327 -0
- package/src/contracts/evvm/EvvmLegacy.sol +1553 -0
- package/src/contracts/evvm/lib/ErrorsLib.sol +17 -0
- package/src/contracts/evvm/lib/EvvmStorage.sol +60 -0
- package/src/contracts/evvm/lib/EvvmStructs.sol +64 -0
- package/src/contracts/evvm/lib/SignatureUtils.sol +124 -0
- package/src/contracts/nameService/NameService.sol +1751 -0
- package/src/contracts/nameService/lib/ErrorsLib.sol +27 -0
- package/src/contracts/nameService/lib/SignatureUtils.sol +239 -0
- package/src/contracts/staking/Estimator.sol +358 -0
- package/src/contracts/staking/Staking.sol +1148 -0
- package/src/contracts/staking/lib/ErrorsLib.sol +19 -0
- package/src/contracts/staking/lib/SignatureUtils.sol +68 -0
- package/src/contracts/treasury/Treasury.sol +104 -0
- package/src/contracts/treasury/lib/ErrorsLib.sol +11 -0
- package/src/contracts/treasuryTwoChains/TreasuryExternalChainStation.sol +551 -0
- package/src/contracts/treasuryTwoChains/TreasuryHostChainStation.sol +512 -0
- package/src/contracts/treasuryTwoChains/lib/ErrorsLib.sol +15 -0
- package/src/contracts/treasuryTwoChains/lib/ExternalChainStationStructs.sol +41 -0
- package/src/contracts/treasuryTwoChains/lib/HostChainStationStructs.sol +52 -0
- package/src/contracts/treasuryTwoChains/lib/SignatureUtils.sol +47 -0
- package/src/interfaces/IEstimator.sol +102 -0
- package/src/interfaces/IEvvm.sol +195 -0
- package/src/interfaces/INameService.sol +283 -0
- package/src/interfaces/IStaking.sol +202 -0
- package/src/interfaces/ITreasury.sol +17 -0
- package/src/interfaces/ITreasuryExternalChainStation.sol +262 -0
- package/src/interfaces/ITreasuryHostChainStation.sol +251 -0
- package/src/lib/AdvancedStrings.sol +77 -0
- package/src/lib/Erc191TestBuilder.sol +402 -0
- package/src/lib/SignatureRecover.sol +56 -0
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EVVM-NONCOMMERCIAL-1.0
|
|
2
|
+
// Full license terms available at: https://www.evvm.info/docs/EVVMNoncommercialLicense
|
|
3
|
+
|
|
4
|
+
pragma solidity ^0.8.0;
|
|
5
|
+
|
|
6
|
+
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
7
|
+
import {ErrorsLib} from "@evvm/testnet-contracts/contracts/treasuryTwoChains/lib/ErrorsLib.sol";
|
|
8
|
+
import {ExternalChainStationStructs} from "@evvm/testnet-contracts/contracts/treasuryTwoChains/lib/ExternalChainStationStructs.sol";
|
|
9
|
+
|
|
10
|
+
import {SafeTransferLib} from "@solady/utils/SafeTransferLib.sol";
|
|
11
|
+
|
|
12
|
+
import {SignatureUtils} from "@evvm/testnet-contracts/contracts/treasuryTwoChains/lib/SignatureUtils.sol";
|
|
13
|
+
|
|
14
|
+
import {IMailbox} from "@hyperlane-xyz/core/contracts/interfaces/IMailbox.sol";
|
|
15
|
+
|
|
16
|
+
import {OApp, Origin, MessagingFee} from "@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol";
|
|
17
|
+
import {OAppOptionsType3} from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol";
|
|
18
|
+
import {OptionsBuilder} from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OptionsBuilder.sol";
|
|
19
|
+
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
|
|
20
|
+
|
|
21
|
+
import {AxelarExecutable} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol";
|
|
22
|
+
import {IAxelarGasService} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol";
|
|
23
|
+
import {IInterchainGasEstimation} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IInterchainGasEstimation.sol";
|
|
24
|
+
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
|
|
25
|
+
|
|
26
|
+
contract TreasuryExternalChainStation is
|
|
27
|
+
ExternalChainStationStructs,
|
|
28
|
+
OApp,
|
|
29
|
+
OAppOptionsType3,
|
|
30
|
+
AxelarExecutable
|
|
31
|
+
{
|
|
32
|
+
AddressTypeProposal admin;
|
|
33
|
+
|
|
34
|
+
AddressTypeProposal fisherExecutor;
|
|
35
|
+
|
|
36
|
+
HyperlaneConfig hyperlane;
|
|
37
|
+
|
|
38
|
+
LayerZeroConfig layerZero;
|
|
39
|
+
|
|
40
|
+
AxelarConfig axelar;
|
|
41
|
+
|
|
42
|
+
uint256 immutable EVVM_ID;
|
|
43
|
+
|
|
44
|
+
mapping(address => uint256) nextFisherExecutionNonce;
|
|
45
|
+
|
|
46
|
+
bytes _options =
|
|
47
|
+
OptionsBuilder.addExecutorLzReceiveOption(
|
|
48
|
+
OptionsBuilder.newOptions(),
|
|
49
|
+
50000,
|
|
50
|
+
0
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
event FisherBridgeSend(
|
|
54
|
+
address indexed from,
|
|
55
|
+
address indexed addressToReceive,
|
|
56
|
+
address indexed tokenAddress,
|
|
57
|
+
uint256 priorityFee,
|
|
58
|
+
uint256 amount,
|
|
59
|
+
uint256 nonce
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
modifier onlyAdmin() {
|
|
63
|
+
if (msg.sender != admin.current) {
|
|
64
|
+
revert();
|
|
65
|
+
}
|
|
66
|
+
_;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
modifier onlyFisherExecutor() {
|
|
70
|
+
if (msg.sender != fisherExecutor.current) {
|
|
71
|
+
revert();
|
|
72
|
+
}
|
|
73
|
+
_;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
constructor(
|
|
77
|
+
address _admin,
|
|
78
|
+
CrosschainConfig memory _crosschainConfig,
|
|
79
|
+
uint256 _evvmId
|
|
80
|
+
)
|
|
81
|
+
OApp(_crosschainConfig.endpointAddress, _admin)
|
|
82
|
+
Ownable(_admin)
|
|
83
|
+
AxelarExecutable(_crosschainConfig.gatewayAddress)
|
|
84
|
+
{
|
|
85
|
+
admin = AddressTypeProposal({
|
|
86
|
+
current: _admin,
|
|
87
|
+
proposal: address(0),
|
|
88
|
+
timeToAccept: 0
|
|
89
|
+
});
|
|
90
|
+
hyperlane = HyperlaneConfig({
|
|
91
|
+
hostChainStationDomainId: _crosschainConfig
|
|
92
|
+
.hostChainStationDomainId,
|
|
93
|
+
hostChainStationAddress: "",
|
|
94
|
+
mailboxAddress: _crosschainConfig.mailboxAddress
|
|
95
|
+
});
|
|
96
|
+
layerZero = LayerZeroConfig({
|
|
97
|
+
hostChainStationEid: _crosschainConfig.hostChainStationEid,
|
|
98
|
+
hostChainStationAddress: "",
|
|
99
|
+
endpointAddress: _crosschainConfig.endpointAddress
|
|
100
|
+
});
|
|
101
|
+
axelar = AxelarConfig({
|
|
102
|
+
hostChainStationChainName: _crosschainConfig
|
|
103
|
+
.hostChainStationChainName,
|
|
104
|
+
hostChainStationAddress: "",
|
|
105
|
+
gasServiceAddress: _crosschainConfig.gasServiceAddress,
|
|
106
|
+
gatewayAddress: _crosschainConfig.gatewayAddress
|
|
107
|
+
});
|
|
108
|
+
EVVM_ID = _evvmId;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function setHostChainAddress(
|
|
112
|
+
address hostChainStationAddress,
|
|
113
|
+
string memory hostChainStationAddressString
|
|
114
|
+
) external onlyAdmin {
|
|
115
|
+
hyperlane.hostChainStationAddress = bytes32(
|
|
116
|
+
uint256(uint160(hostChainStationAddress))
|
|
117
|
+
);
|
|
118
|
+
layerZero.hostChainStationAddress = bytes32(
|
|
119
|
+
uint256(uint160(hostChainStationAddress))
|
|
120
|
+
);
|
|
121
|
+
axelar.hostChainStationAddress = hostChainStationAddressString;
|
|
122
|
+
_setPeer(
|
|
123
|
+
layerZero.hostChainStationEid,
|
|
124
|
+
layerZero.hostChainStationAddress
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @notice Withdraw ETH or ERC20 tokens
|
|
130
|
+
* @param token Token address (address(0) for ETH)
|
|
131
|
+
* @param amount Amount to withdraw
|
|
132
|
+
*/
|
|
133
|
+
function depositERC20(
|
|
134
|
+
address toAddress,
|
|
135
|
+
address token,
|
|
136
|
+
uint256 amount,
|
|
137
|
+
bytes1 protocolToExecute
|
|
138
|
+
) external payable {
|
|
139
|
+
bytes memory payload = encodePayload(token, toAddress, amount);
|
|
140
|
+
verifyAndDepositERC20(token, amount);
|
|
141
|
+
if (protocolToExecute == 0x01) {
|
|
142
|
+
// 0x01 = Hyperlane
|
|
143
|
+
uint256 quote = getQuoteHyperlane(toAddress, token, amount);
|
|
144
|
+
/*messageId = */ IMailbox(hyperlane.mailboxAddress).dispatch{
|
|
145
|
+
value: quote
|
|
146
|
+
}(
|
|
147
|
+
hyperlane.hostChainStationDomainId,
|
|
148
|
+
hyperlane.hostChainStationAddress,
|
|
149
|
+
payload
|
|
150
|
+
);
|
|
151
|
+
} else if (protocolToExecute == 0x02) {
|
|
152
|
+
// 0x02 = LayerZero
|
|
153
|
+
uint256 fee = quoteLayerZero(toAddress, token, amount);
|
|
154
|
+
_lzSend(
|
|
155
|
+
layerZero.hostChainStationEid,
|
|
156
|
+
payload,
|
|
157
|
+
_options,
|
|
158
|
+
MessagingFee(fee, 0),
|
|
159
|
+
msg.sender // Refund any excess fees to the sender.
|
|
160
|
+
);
|
|
161
|
+
} else if (protocolToExecute == 0x03) {
|
|
162
|
+
// 0x03 = Axelar
|
|
163
|
+
IAxelarGasService(axelar.gasServiceAddress)
|
|
164
|
+
.payNativeGasForContractCall{value: msg.value}(
|
|
165
|
+
address(this),
|
|
166
|
+
axelar.hostChainStationChainName,
|
|
167
|
+
axelar.hostChainStationAddress,
|
|
168
|
+
payload,
|
|
169
|
+
msg.sender
|
|
170
|
+
);
|
|
171
|
+
gateway().callContract(
|
|
172
|
+
axelar.hostChainStationChainName,
|
|
173
|
+
axelar.hostChainStationAddress,
|
|
174
|
+
payload
|
|
175
|
+
);
|
|
176
|
+
} else {
|
|
177
|
+
revert();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function depositCoin(
|
|
182
|
+
address toAddress,
|
|
183
|
+
uint256 amount,
|
|
184
|
+
bytes1 protocolToExecute
|
|
185
|
+
) external payable {
|
|
186
|
+
if (msg.value < amount) revert ErrorsLib.InsufficientBalance();
|
|
187
|
+
|
|
188
|
+
bytes memory payload = encodePayload(address(0), toAddress, amount);
|
|
189
|
+
|
|
190
|
+
if (protocolToExecute == 0x01) {
|
|
191
|
+
// 0x01 = Hyperlane
|
|
192
|
+
uint256 quote = getQuoteHyperlane(toAddress, address(0), amount);
|
|
193
|
+
if (msg.value < quote + amount)
|
|
194
|
+
revert ErrorsLib.InsufficientBalance();
|
|
195
|
+
/*messageId = */ IMailbox(hyperlane.mailboxAddress).dispatch{
|
|
196
|
+
value: quote
|
|
197
|
+
}(
|
|
198
|
+
hyperlane.hostChainStationDomainId,
|
|
199
|
+
hyperlane.hostChainStationAddress,
|
|
200
|
+
payload
|
|
201
|
+
);
|
|
202
|
+
} else if (protocolToExecute == 0x02) {
|
|
203
|
+
// 0x02 = LayerZero
|
|
204
|
+
uint256 fee = quoteLayerZero(toAddress, address(0), amount);
|
|
205
|
+
if (msg.value < fee + amount)
|
|
206
|
+
revert ErrorsLib.InsufficientBalance();
|
|
207
|
+
_lzSend(
|
|
208
|
+
layerZero.hostChainStationEid,
|
|
209
|
+
payload,
|
|
210
|
+
_options,
|
|
211
|
+
MessagingFee(fee, 0),
|
|
212
|
+
msg.sender // Refund any excess fees to the sender.
|
|
213
|
+
);
|
|
214
|
+
} else if (protocolToExecute == 0x03) {
|
|
215
|
+
// 0x03 = Axelar
|
|
216
|
+
IAxelarGasService(axelar.gasServiceAddress)
|
|
217
|
+
.payNativeGasForContractCall{value: msg.value - amount}(
|
|
218
|
+
address(this),
|
|
219
|
+
axelar.hostChainStationChainName,
|
|
220
|
+
axelar.hostChainStationAddress,
|
|
221
|
+
payload,
|
|
222
|
+
msg.sender
|
|
223
|
+
);
|
|
224
|
+
gateway().callContract(
|
|
225
|
+
axelar.hostChainStationChainName,
|
|
226
|
+
axelar.hostChainStationAddress,
|
|
227
|
+
payload
|
|
228
|
+
);
|
|
229
|
+
} else {
|
|
230
|
+
revert();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function fisherBridgeReceive(
|
|
235
|
+
address from,
|
|
236
|
+
address addressToReceive,
|
|
237
|
+
address tokenAddress,
|
|
238
|
+
uint256 priorityFee,
|
|
239
|
+
uint256 amount,
|
|
240
|
+
bytes memory signature
|
|
241
|
+
) external onlyFisherExecutor {
|
|
242
|
+
if (
|
|
243
|
+
!SignatureUtils.verifyMessageSignedForFisherBridge(
|
|
244
|
+
EVVM_ID,
|
|
245
|
+
from,
|
|
246
|
+
addressToReceive,
|
|
247
|
+
nextFisherExecutionNonce[from],
|
|
248
|
+
tokenAddress,
|
|
249
|
+
priorityFee,
|
|
250
|
+
amount,
|
|
251
|
+
signature
|
|
252
|
+
)
|
|
253
|
+
) revert ErrorsLib.InvalidSignature();
|
|
254
|
+
|
|
255
|
+
nextFisherExecutionNonce[from]++;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function fisherBridgeSendERC20(
|
|
259
|
+
address from,
|
|
260
|
+
address addressToReceive,
|
|
261
|
+
address tokenAddress,
|
|
262
|
+
uint256 priorityFee,
|
|
263
|
+
uint256 amount,
|
|
264
|
+
bytes memory signature
|
|
265
|
+
) external onlyFisherExecutor {
|
|
266
|
+
if (
|
|
267
|
+
!SignatureUtils.verifyMessageSignedForFisherBridge(
|
|
268
|
+
EVVM_ID,
|
|
269
|
+
from,
|
|
270
|
+
addressToReceive,
|
|
271
|
+
nextFisherExecutionNonce[from],
|
|
272
|
+
tokenAddress,
|
|
273
|
+
priorityFee,
|
|
274
|
+
amount,
|
|
275
|
+
signature
|
|
276
|
+
)
|
|
277
|
+
) revert ErrorsLib.InvalidSignature();
|
|
278
|
+
|
|
279
|
+
verifyAndDepositERC20(tokenAddress, amount);
|
|
280
|
+
|
|
281
|
+
nextFisherExecutionNonce[from]++;
|
|
282
|
+
|
|
283
|
+
emit FisherBridgeSend(
|
|
284
|
+
from,
|
|
285
|
+
addressToReceive,
|
|
286
|
+
tokenAddress,
|
|
287
|
+
priorityFee,
|
|
288
|
+
amount,
|
|
289
|
+
nextFisherExecutionNonce[from] - 1
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function fisherBridgeSendCoin(
|
|
294
|
+
address from,
|
|
295
|
+
address addressToReceive,
|
|
296
|
+
uint256 priorityFee,
|
|
297
|
+
uint256 amount,
|
|
298
|
+
bytes memory signature
|
|
299
|
+
) external payable onlyFisherExecutor {
|
|
300
|
+
if (
|
|
301
|
+
!SignatureUtils.verifyMessageSignedForFisherBridge(
|
|
302
|
+
EVVM_ID,
|
|
303
|
+
from,
|
|
304
|
+
addressToReceive,
|
|
305
|
+
nextFisherExecutionNonce[from],
|
|
306
|
+
address(0),
|
|
307
|
+
priorityFee,
|
|
308
|
+
amount,
|
|
309
|
+
signature
|
|
310
|
+
)
|
|
311
|
+
) revert ErrorsLib.InvalidSignature();
|
|
312
|
+
|
|
313
|
+
if (msg.value != amount + priorityFee)
|
|
314
|
+
revert ErrorsLib.InsufficientBalance();
|
|
315
|
+
|
|
316
|
+
nextFisherExecutionNonce[from]++;
|
|
317
|
+
|
|
318
|
+
emit FisherBridgeSend(
|
|
319
|
+
from,
|
|
320
|
+
addressToReceive,
|
|
321
|
+
address(0),
|
|
322
|
+
priorityFee,
|
|
323
|
+
amount,
|
|
324
|
+
nextFisherExecutionNonce[from] - 1
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Hyperlane Specific Functions //
|
|
329
|
+
function getQuoteHyperlane(
|
|
330
|
+
address toAddress,
|
|
331
|
+
address token,
|
|
332
|
+
uint256 amount
|
|
333
|
+
) public view returns (uint256) {
|
|
334
|
+
return
|
|
335
|
+
IMailbox(hyperlane.mailboxAddress).quoteDispatch(
|
|
336
|
+
hyperlane.hostChainStationDomainId,
|
|
337
|
+
hyperlane.hostChainStationAddress,
|
|
338
|
+
encodePayload(token, toAddress, amount)
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function handle(
|
|
343
|
+
uint32 _origin,
|
|
344
|
+
bytes32 _sender,
|
|
345
|
+
bytes calldata _data
|
|
346
|
+
) external payable virtual {
|
|
347
|
+
if (msg.sender != hyperlane.mailboxAddress)
|
|
348
|
+
revert ErrorsLib.MailboxNotAuthorized();
|
|
349
|
+
|
|
350
|
+
if (_sender != hyperlane.hostChainStationAddress)
|
|
351
|
+
revert ErrorsLib.SenderNotAuthorized();
|
|
352
|
+
|
|
353
|
+
if (_origin != hyperlane.hostChainStationDomainId)
|
|
354
|
+
revert ErrorsLib.ChainIdNotAuthorized();
|
|
355
|
+
|
|
356
|
+
decodeAndGive(_data);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// LayerZero Specific Functions //
|
|
360
|
+
|
|
361
|
+
function quoteLayerZero(
|
|
362
|
+
address toAddress,
|
|
363
|
+
address token,
|
|
364
|
+
uint256 amount
|
|
365
|
+
) public view returns (uint256) {
|
|
366
|
+
MessagingFee memory fee = _quote(
|
|
367
|
+
layerZero.hostChainStationEid,
|
|
368
|
+
encodePayload(token, toAddress, amount),
|
|
369
|
+
_options,
|
|
370
|
+
false
|
|
371
|
+
);
|
|
372
|
+
return fee.nativeFee;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function _lzReceive(
|
|
376
|
+
Origin calldata _origin,
|
|
377
|
+
bytes32 /*_guid*/,
|
|
378
|
+
bytes calldata message,
|
|
379
|
+
address /*executor*/, // Executor address as specified by the OApp.
|
|
380
|
+
bytes calldata /*_extraData*/ // Any extra data or options to trigger on receipt.
|
|
381
|
+
) internal override {
|
|
382
|
+
// Decode the payload to get the message
|
|
383
|
+
if (_origin.srcEid != layerZero.hostChainStationEid)
|
|
384
|
+
revert ErrorsLib.ChainIdNotAuthorized();
|
|
385
|
+
|
|
386
|
+
if (_origin.sender != layerZero.hostChainStationAddress)
|
|
387
|
+
revert ErrorsLib.SenderNotAuthorized();
|
|
388
|
+
|
|
389
|
+
decodeAndGive(message);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Axelar Specific Functions //
|
|
393
|
+
|
|
394
|
+
function _execute(
|
|
395
|
+
bytes32 /*commandId*/,
|
|
396
|
+
string calldata _sourceChain,
|
|
397
|
+
string calldata _sourceAddress,
|
|
398
|
+
bytes calldata _payload
|
|
399
|
+
) internal override {
|
|
400
|
+
if (!Strings.equal(_sourceChain, axelar.hostChainStationChainName))
|
|
401
|
+
revert ErrorsLib.ChainIdNotAuthorized();
|
|
402
|
+
|
|
403
|
+
if (!Strings.equal(_sourceAddress, axelar.hostChainStationAddress))
|
|
404
|
+
revert ErrorsLib.SenderNotAuthorized();
|
|
405
|
+
|
|
406
|
+
decodeAndGive(_payload);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* @notice Proposes a new admin address with 1-day time delay
|
|
411
|
+
* @dev Part of the time-delayed governance system for admin changes
|
|
412
|
+
* @param _newOwner Address of the proposed new admin
|
|
413
|
+
*/
|
|
414
|
+
function proposeAdmin(address _newOwner) external onlyAdmin {
|
|
415
|
+
if (_newOwner == address(0) || _newOwner == admin.current) revert();
|
|
416
|
+
|
|
417
|
+
admin.proposal = _newOwner;
|
|
418
|
+
admin.timeToAccept = block.timestamp + 1 days;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* @notice Cancels a pending admin change proposal
|
|
423
|
+
* @dev Allows current admin to reject proposed admin changes
|
|
424
|
+
*/
|
|
425
|
+
function rejectProposalAdmin() external onlyAdmin {
|
|
426
|
+
admin.proposal = address(0);
|
|
427
|
+
admin.timeToAccept = 0;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* @notice Accepts a pending admin proposal and becomes the new admin
|
|
432
|
+
* @dev Can only be called by the proposed admin after the time delay
|
|
433
|
+
*/
|
|
434
|
+
function acceptAdmin() external {
|
|
435
|
+
if (block.timestamp < admin.timeToAccept) revert();
|
|
436
|
+
|
|
437
|
+
if (msg.sender != admin.proposal) revert();
|
|
438
|
+
|
|
439
|
+
admin.current = admin.proposal;
|
|
440
|
+
|
|
441
|
+
admin.proposal = address(0);
|
|
442
|
+
admin.timeToAccept = 0;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function proposeFisherExecutor(
|
|
446
|
+
address _newFisherExecutor
|
|
447
|
+
) external onlyAdmin {
|
|
448
|
+
if (
|
|
449
|
+
_newFisherExecutor == address(0) ||
|
|
450
|
+
_newFisherExecutor == fisherExecutor.current
|
|
451
|
+
) revert();
|
|
452
|
+
|
|
453
|
+
fisherExecutor.proposal = _newFisherExecutor;
|
|
454
|
+
fisherExecutor.timeToAccept = block.timestamp + 1 days;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
function rejectProposalFisherExecutor() external onlyAdmin {
|
|
458
|
+
fisherExecutor.proposal = address(0);
|
|
459
|
+
fisherExecutor.timeToAccept = 0;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
function acceptFisherExecutor() external {
|
|
463
|
+
if (block.timestamp < fisherExecutor.timeToAccept) revert();
|
|
464
|
+
|
|
465
|
+
if (msg.sender != fisherExecutor.proposal) revert();
|
|
466
|
+
|
|
467
|
+
fisherExecutor.current = fisherExecutor.proposal;
|
|
468
|
+
|
|
469
|
+
fisherExecutor.proposal = address(0);
|
|
470
|
+
fisherExecutor.timeToAccept = 0;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// Getter functions //
|
|
474
|
+
function getAdmin() external view returns (AddressTypeProposal memory) {
|
|
475
|
+
return admin;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function getFisherExecutor()
|
|
479
|
+
external
|
|
480
|
+
view
|
|
481
|
+
returns (AddressTypeProposal memory)
|
|
482
|
+
{
|
|
483
|
+
return fisherExecutor;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function getNextFisherExecutionNonce(
|
|
487
|
+
address user
|
|
488
|
+
) external view returns (uint256) {
|
|
489
|
+
return nextFisherExecutionNonce[user];
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
function getHyperlaneConfig()
|
|
493
|
+
external
|
|
494
|
+
view
|
|
495
|
+
returns (HyperlaneConfig memory)
|
|
496
|
+
{
|
|
497
|
+
return hyperlane;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
function getLayerZeroConfig()
|
|
501
|
+
external
|
|
502
|
+
view
|
|
503
|
+
returns (LayerZeroConfig memory)
|
|
504
|
+
{
|
|
505
|
+
return layerZero;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
function getAxelarConfig() external view returns (AxelarConfig memory) {
|
|
509
|
+
return axelar;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
function getOptions() external view returns (bytes memory) {
|
|
513
|
+
return _options;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Internal Functions //
|
|
517
|
+
|
|
518
|
+
function decodeAndGive(bytes memory payload) internal {
|
|
519
|
+
(address token, address toAddress, uint256 amount) = decodePayload(
|
|
520
|
+
payload
|
|
521
|
+
);
|
|
522
|
+
if (token == address(0))
|
|
523
|
+
SafeTransferLib.safeTransferETH(msg.sender, amount);
|
|
524
|
+
else IERC20(token).transfer(toAddress, amount);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
function verifyAndDepositERC20(address token, uint256 amount) internal {
|
|
528
|
+
if (token == address(0)) revert();
|
|
529
|
+
if (IERC20(token).allowance(msg.sender, address(this)) < amount)
|
|
530
|
+
revert ErrorsLib.InsufficientBalance();
|
|
531
|
+
|
|
532
|
+
IERC20(token).transferFrom(msg.sender, address(this), amount);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
function encodePayload(
|
|
536
|
+
address token,
|
|
537
|
+
address toAddress,
|
|
538
|
+
uint256 amount
|
|
539
|
+
) internal pure returns (bytes memory payload) {
|
|
540
|
+
payload = abi.encode(token, toAddress, amount);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
function decodePayload(
|
|
544
|
+
bytes memory payload
|
|
545
|
+
) internal pure returns (address token, address toAddress, uint256 amount) {
|
|
546
|
+
(token, toAddress, amount) = abi.decode(
|
|
547
|
+
payload,
|
|
548
|
+
(address, address, uint256)
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
}
|