@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,512 @@
|
|
|
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
|
+
888b d888 888 .d8888b. 888 888
|
|
7
|
+
8888b d8888 888 d88P Y88b 888 888
|
|
8
|
+
88888b.d88888 888 888 888 888 888
|
|
9
|
+
888Y88888P888 .d88b. .d8888b 888 888 888 .d88b. 88888b. 888888 888d888 8888b. .d8888b 888888
|
|
10
|
+
888 Y888P 888 d88""88b d88P" 888 .88P 888 d88""88b 888 "88b 888 888P" "88b d88P" 888
|
|
11
|
+
888 Y8P 888 888 888 888 888888K 888 888 888 888 888 888 888 888 .d888888 888 888
|
|
12
|
+
888 " 888 Y88..88P Y88b. 888 "88b Y88b d88P Y88..88P 888 888 Y88b. 888 888 888 Y88b. Y88b.
|
|
13
|
+
888 888 "Y88P" "Y8888P 888 888 "Y8888P" "Y88P" 888 888 "Y888 888 "Y888888 "Y8888P "Y888
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
17
|
+
import {Evvm} from "@evvm/testnet-contracts/contracts/evvm/Evvm.sol";
|
|
18
|
+
import {ErrorsLib} from "@evvm/testnet-contracts/contracts/treasuryTwoChains/lib/ErrorsLib.sol";
|
|
19
|
+
import {HostChainStationStructs} from "@evvm/testnet-contracts/contracts/treasuryTwoChains/lib/HostChainStationStructs.sol";
|
|
20
|
+
|
|
21
|
+
import {SignatureUtils} from "@evvm/testnet-contracts/contracts/treasuryTwoChains/lib/SignatureUtils.sol";
|
|
22
|
+
|
|
23
|
+
import {IMailbox} from "@hyperlane-xyz/core/contracts/interfaces/IMailbox.sol";
|
|
24
|
+
|
|
25
|
+
import {OApp, Origin, MessagingFee} from "@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol";
|
|
26
|
+
import {OAppOptionsType3} from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol";
|
|
27
|
+
import {OptionsBuilder} from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OptionsBuilder.sol";
|
|
28
|
+
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
|
|
29
|
+
|
|
30
|
+
import {AxelarExecutable} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol";
|
|
31
|
+
import {IAxelarGasService} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol";
|
|
32
|
+
import {IInterchainGasEstimation} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IInterchainGasEstimation.sol";
|
|
33
|
+
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
|
|
34
|
+
|
|
35
|
+
contract TreasuryHostChainStation is
|
|
36
|
+
HostChainStationStructs,
|
|
37
|
+
OApp,
|
|
38
|
+
OAppOptionsType3,
|
|
39
|
+
AxelarExecutable
|
|
40
|
+
{
|
|
41
|
+
/// @notice Address of the EVVM core contract
|
|
42
|
+
address evvmAddress;
|
|
43
|
+
|
|
44
|
+
AddressTypeProposal admin;
|
|
45
|
+
|
|
46
|
+
AddressTypeProposal fisherExecutor;
|
|
47
|
+
|
|
48
|
+
HyperlaneConfig hyperlane;
|
|
49
|
+
|
|
50
|
+
LayerZeroConfig layerZero;
|
|
51
|
+
|
|
52
|
+
AxelarConfig axelar;
|
|
53
|
+
|
|
54
|
+
mapping(address => uint256) nextFisherExecutionNonce;
|
|
55
|
+
|
|
56
|
+
bytes _options =
|
|
57
|
+
OptionsBuilder.addExecutorLzReceiveOption(
|
|
58
|
+
OptionsBuilder.newOptions(),
|
|
59
|
+
50000,
|
|
60
|
+
0
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
event FisherBridgeSend(
|
|
64
|
+
address indexed from,
|
|
65
|
+
address indexed addressToReceive,
|
|
66
|
+
address indexed tokenAddress,
|
|
67
|
+
uint256 priorityFee,
|
|
68
|
+
uint256 amount,
|
|
69
|
+
uint256 nonce
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
modifier onlyAdmin() {
|
|
73
|
+
if (msg.sender != admin.current) {
|
|
74
|
+
revert();
|
|
75
|
+
}
|
|
76
|
+
_;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
modifier onlyFisherExecutor() {
|
|
80
|
+
if (msg.sender != fisherExecutor.current) {
|
|
81
|
+
revert();
|
|
82
|
+
}
|
|
83
|
+
_;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @notice Initialize Treasury with EVVM contract address
|
|
88
|
+
* @param _evvmAddress Address of the EVVM core contract
|
|
89
|
+
*/
|
|
90
|
+
constructor(
|
|
91
|
+
address _evvmAddress,
|
|
92
|
+
address _admin,
|
|
93
|
+
CrosschainConfig memory _crosschainConfig
|
|
94
|
+
)
|
|
95
|
+
OApp(_crosschainConfig.endpointAddress, _admin)
|
|
96
|
+
Ownable(_admin)
|
|
97
|
+
AxelarExecutable(_crosschainConfig.gatewayAddress)
|
|
98
|
+
{
|
|
99
|
+
evvmAddress = _evvmAddress;
|
|
100
|
+
admin = AddressTypeProposal({
|
|
101
|
+
current: _admin,
|
|
102
|
+
proposal: address(0),
|
|
103
|
+
timeToAccept: 0
|
|
104
|
+
});
|
|
105
|
+
hyperlane = HyperlaneConfig({
|
|
106
|
+
externalChainStationDomainId: _crosschainConfig
|
|
107
|
+
.externalChainStationDomainId,
|
|
108
|
+
externalChainStationAddress: "",
|
|
109
|
+
mailboxAddress: _crosschainConfig.mailboxAddress
|
|
110
|
+
});
|
|
111
|
+
layerZero = LayerZeroConfig({
|
|
112
|
+
externalChainStationEid: _crosschainConfig.externalChainStationEid,
|
|
113
|
+
externalChainStationAddress: "",
|
|
114
|
+
endpointAddress: _crosschainConfig.endpointAddress
|
|
115
|
+
});
|
|
116
|
+
axelar = AxelarConfig({
|
|
117
|
+
externalChainStationChainName: _crosschainConfig
|
|
118
|
+
.externalChainStationChainName,
|
|
119
|
+
externalChainStationAddress: "",
|
|
120
|
+
gasServiceAddress: _crosschainConfig.gasServiceAddress,
|
|
121
|
+
gatewayAddress: _crosschainConfig.gatewayAddress
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function setExternalChainAddress(
|
|
126
|
+
address externalChainStationAddress,
|
|
127
|
+
string memory externalChainStationAddressString
|
|
128
|
+
) external onlyAdmin {
|
|
129
|
+
hyperlane.externalChainStationAddress = bytes32(
|
|
130
|
+
uint256(uint160(externalChainStationAddress))
|
|
131
|
+
);
|
|
132
|
+
layerZero.externalChainStationAddress = bytes32(
|
|
133
|
+
uint256(uint160(externalChainStationAddress))
|
|
134
|
+
);
|
|
135
|
+
axelar.externalChainStationAddress = externalChainStationAddressString;
|
|
136
|
+
_setPeer(
|
|
137
|
+
layerZero.externalChainStationEid,
|
|
138
|
+
layerZero.externalChainStationAddress
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* @notice Withdraw ETH or ERC20 tokens
|
|
144
|
+
* @param token Token address (address(0) for ETH)
|
|
145
|
+
* @param amount Amount to withdraw
|
|
146
|
+
*/
|
|
147
|
+
function withdraw(
|
|
148
|
+
address toAddress,
|
|
149
|
+
address token,
|
|
150
|
+
uint256 amount,
|
|
151
|
+
bytes1 protocolToExecute
|
|
152
|
+
) external payable {
|
|
153
|
+
if (token == Evvm(evvmAddress).getEvvmMetadata().principalTokenAddress)
|
|
154
|
+
revert ErrorsLib.PrincipalTokenIsNotWithdrawable();
|
|
155
|
+
|
|
156
|
+
if (Evvm(evvmAddress).getBalance(msg.sender, token) < amount)
|
|
157
|
+
revert ErrorsLib.InsufficientBalance();
|
|
158
|
+
|
|
159
|
+
executerEVVM(false, msg.sender, token, amount);
|
|
160
|
+
|
|
161
|
+
bytes memory payload = encodePayload(token, toAddress, amount);
|
|
162
|
+
|
|
163
|
+
if (protocolToExecute == 0x01) {
|
|
164
|
+
// 0x01 = Hyperlane
|
|
165
|
+
uint256 quote = getQuoteHyperlane(toAddress, token, amount);
|
|
166
|
+
/*messageId = */ IMailbox(hyperlane.mailboxAddress).dispatch{
|
|
167
|
+
value: quote
|
|
168
|
+
}(
|
|
169
|
+
hyperlane.externalChainStationDomainId,
|
|
170
|
+
hyperlane.externalChainStationAddress,
|
|
171
|
+
payload
|
|
172
|
+
);
|
|
173
|
+
} else if (protocolToExecute == 0x02) {
|
|
174
|
+
// 0x02 = LayerZero
|
|
175
|
+
uint256 fee = quoteLayerZero(toAddress, token, amount);
|
|
176
|
+
_lzSend(
|
|
177
|
+
layerZero.externalChainStationEid,
|
|
178
|
+
payload,
|
|
179
|
+
_options,
|
|
180
|
+
MessagingFee(fee, 0),
|
|
181
|
+
msg.sender // Refund any excess fees to the sender.
|
|
182
|
+
);
|
|
183
|
+
} else if (protocolToExecute == 0x03) {
|
|
184
|
+
// 0x03 = Axelar
|
|
185
|
+
IAxelarGasService(axelar.gasServiceAddress)
|
|
186
|
+
.payNativeGasForContractCall{value: msg.value}(
|
|
187
|
+
address(this),
|
|
188
|
+
axelar.externalChainStationChainName,
|
|
189
|
+
axelar.externalChainStationAddress,
|
|
190
|
+
payload,
|
|
191
|
+
msg.sender
|
|
192
|
+
);
|
|
193
|
+
gateway().callContract(
|
|
194
|
+
axelar.externalChainStationChainName,
|
|
195
|
+
axelar.externalChainStationAddress,
|
|
196
|
+
payload
|
|
197
|
+
);
|
|
198
|
+
} else {
|
|
199
|
+
revert();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function fisherBridgeReceive(
|
|
204
|
+
address from,
|
|
205
|
+
address addressToReceive,
|
|
206
|
+
address tokenAddress,
|
|
207
|
+
uint256 priorityFee,
|
|
208
|
+
uint256 amount,
|
|
209
|
+
bytes memory signature
|
|
210
|
+
) external onlyFisherExecutor {
|
|
211
|
+
if (
|
|
212
|
+
!SignatureUtils.verifyMessageSignedForFisherBridge(
|
|
213
|
+
Evvm(evvmAddress).getEvvmID(),
|
|
214
|
+
from,
|
|
215
|
+
addressToReceive,
|
|
216
|
+
nextFisherExecutionNonce[from],
|
|
217
|
+
tokenAddress,
|
|
218
|
+
priorityFee,
|
|
219
|
+
amount,
|
|
220
|
+
signature
|
|
221
|
+
)
|
|
222
|
+
) revert ErrorsLib.InvalidSignature();
|
|
223
|
+
|
|
224
|
+
nextFisherExecutionNonce[from]++;
|
|
225
|
+
|
|
226
|
+
executerEVVM(true, addressToReceive, tokenAddress, amount);
|
|
227
|
+
|
|
228
|
+
if (priorityFee > 0)
|
|
229
|
+
executerEVVM(true, msg.sender, tokenAddress, priorityFee);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function fisherBridgeSend(
|
|
233
|
+
address from,
|
|
234
|
+
address addressToReceive,
|
|
235
|
+
address tokenAddress,
|
|
236
|
+
uint256 priorityFee,
|
|
237
|
+
uint256 amount,
|
|
238
|
+
bytes memory signature
|
|
239
|
+
) external onlyFisherExecutor {
|
|
240
|
+
if (
|
|
241
|
+
tokenAddress ==
|
|
242
|
+
Evvm(evvmAddress).getEvvmMetadata().principalTokenAddress
|
|
243
|
+
) revert ErrorsLib.PrincipalTokenIsNotWithdrawable();
|
|
244
|
+
|
|
245
|
+
if (Evvm(evvmAddress).getBalance(from, tokenAddress) < amount)
|
|
246
|
+
revert ErrorsLib.InsufficientBalance();
|
|
247
|
+
|
|
248
|
+
if (
|
|
249
|
+
!SignatureUtils.verifyMessageSignedForFisherBridge(
|
|
250
|
+
Evvm(evvmAddress).getEvvmID(),
|
|
251
|
+
from,
|
|
252
|
+
addressToReceive,
|
|
253
|
+
nextFisherExecutionNonce[from],
|
|
254
|
+
tokenAddress,
|
|
255
|
+
priorityFee,
|
|
256
|
+
amount,
|
|
257
|
+
signature
|
|
258
|
+
)
|
|
259
|
+
) revert ErrorsLib.InvalidSignature();
|
|
260
|
+
|
|
261
|
+
nextFisherExecutionNonce[from]++;
|
|
262
|
+
|
|
263
|
+
executerEVVM(false, from, tokenAddress, amount + priorityFee);
|
|
264
|
+
|
|
265
|
+
if (priorityFee > 0)
|
|
266
|
+
executerEVVM(true, msg.sender, tokenAddress, priorityFee);
|
|
267
|
+
|
|
268
|
+
emit FisherBridgeSend(
|
|
269
|
+
from,
|
|
270
|
+
addressToReceive,
|
|
271
|
+
tokenAddress,
|
|
272
|
+
priorityFee,
|
|
273
|
+
amount,
|
|
274
|
+
nextFisherExecutionNonce[from] - 1
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Hyperlane Specific Functions //
|
|
279
|
+
function getQuoteHyperlane(
|
|
280
|
+
address toAddress,
|
|
281
|
+
address token,
|
|
282
|
+
uint256 amount
|
|
283
|
+
) public view returns (uint256) {
|
|
284
|
+
return
|
|
285
|
+
IMailbox(hyperlane.mailboxAddress).quoteDispatch(
|
|
286
|
+
hyperlane.externalChainStationDomainId,
|
|
287
|
+
hyperlane.externalChainStationAddress,
|
|
288
|
+
encodePayload(token, toAddress, amount)
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function handle(
|
|
293
|
+
uint32 _origin,
|
|
294
|
+
bytes32 _sender,
|
|
295
|
+
bytes calldata _data
|
|
296
|
+
) external payable virtual {
|
|
297
|
+
if (msg.sender != hyperlane.mailboxAddress)
|
|
298
|
+
revert ErrorsLib.MailboxNotAuthorized();
|
|
299
|
+
|
|
300
|
+
if (_sender != hyperlane.externalChainStationAddress)
|
|
301
|
+
revert ErrorsLib.SenderNotAuthorized();
|
|
302
|
+
|
|
303
|
+
if (_origin != hyperlane.externalChainStationDomainId)
|
|
304
|
+
revert ErrorsLib.ChainIdNotAuthorized();
|
|
305
|
+
|
|
306
|
+
decodeAndDeposit(_data);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// LayerZero Specific Functions //
|
|
310
|
+
|
|
311
|
+
function quoteLayerZero(
|
|
312
|
+
address toAddress,
|
|
313
|
+
address token,
|
|
314
|
+
uint256 amount
|
|
315
|
+
) public view returns (uint256) {
|
|
316
|
+
MessagingFee memory fee = _quote(
|
|
317
|
+
layerZero.externalChainStationEid,
|
|
318
|
+
encodePayload(token, toAddress, amount),
|
|
319
|
+
_options,
|
|
320
|
+
false
|
|
321
|
+
);
|
|
322
|
+
return fee.nativeFee;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function _lzReceive(
|
|
326
|
+
Origin calldata _origin,
|
|
327
|
+
bytes32 /*_guid*/,
|
|
328
|
+
bytes calldata message,
|
|
329
|
+
address /*executor*/, // Executor address as specified by the OApp.
|
|
330
|
+
bytes calldata /*_extraData*/ // Any extra data or options to trigger on receipt.
|
|
331
|
+
) internal override {
|
|
332
|
+
// Decode the payload to get the message
|
|
333
|
+
if (_origin.srcEid != layerZero.externalChainStationEid)
|
|
334
|
+
revert ErrorsLib.ChainIdNotAuthorized();
|
|
335
|
+
|
|
336
|
+
if (_origin.sender != layerZero.externalChainStationAddress)
|
|
337
|
+
revert ErrorsLib.SenderNotAuthorized();
|
|
338
|
+
|
|
339
|
+
decodeAndDeposit(message);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Axelar Specific Functions //
|
|
343
|
+
|
|
344
|
+
function _execute(
|
|
345
|
+
bytes32 /*commandId*/,
|
|
346
|
+
string calldata _sourceChain,
|
|
347
|
+
string calldata _sourceAddress,
|
|
348
|
+
bytes calldata _payload
|
|
349
|
+
) internal override {
|
|
350
|
+
if (!Strings.equal(_sourceChain, axelar.externalChainStationChainName))
|
|
351
|
+
revert ErrorsLib.ChainIdNotAuthorized();
|
|
352
|
+
|
|
353
|
+
if (!Strings.equal(_sourceAddress, axelar.externalChainStationAddress))
|
|
354
|
+
revert ErrorsLib.SenderNotAuthorized();
|
|
355
|
+
|
|
356
|
+
decodeAndDeposit(_payload);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* @notice Proposes a new admin address with 1-day time delay
|
|
361
|
+
* @dev Part of the time-delayed governance system for admin changes
|
|
362
|
+
* @param _newOwner Address of the proposed new admin
|
|
363
|
+
*/
|
|
364
|
+
function proposeAdmin(address _newOwner) external onlyAdmin {
|
|
365
|
+
if (_newOwner == address(0) || _newOwner == admin.current) revert();
|
|
366
|
+
|
|
367
|
+
admin.proposal = _newOwner;
|
|
368
|
+
admin.timeToAccept = block.timestamp + 1 days;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* @notice Cancels a pending admin change proposal
|
|
373
|
+
* @dev Allows current admin to reject proposed admin changes
|
|
374
|
+
*/
|
|
375
|
+
function rejectProposalAdmin() external onlyAdmin {
|
|
376
|
+
admin.proposal = address(0);
|
|
377
|
+
admin.timeToAccept = 0;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* @notice Accepts a pending admin proposal and becomes the new admin
|
|
382
|
+
* @dev Can only be called by the proposed admin after the time delay
|
|
383
|
+
*/
|
|
384
|
+
function acceptAdmin() external {
|
|
385
|
+
if (block.timestamp < admin.timeToAccept) revert();
|
|
386
|
+
|
|
387
|
+
if (msg.sender != admin.proposal) revert();
|
|
388
|
+
|
|
389
|
+
admin.current = admin.proposal;
|
|
390
|
+
|
|
391
|
+
admin.proposal = address(0);
|
|
392
|
+
admin.timeToAccept = 0;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
function proposeFisherExecutor(
|
|
396
|
+
address _newFisherExecutor
|
|
397
|
+
) external onlyAdmin {
|
|
398
|
+
if (
|
|
399
|
+
_newFisherExecutor == address(0) ||
|
|
400
|
+
_newFisherExecutor == fisherExecutor.current
|
|
401
|
+
) revert();
|
|
402
|
+
|
|
403
|
+
fisherExecutor.proposal = _newFisherExecutor;
|
|
404
|
+
fisherExecutor.timeToAccept = block.timestamp + 1 days;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function rejectProposalFisherExecutor() external onlyAdmin {
|
|
408
|
+
fisherExecutor.proposal = address(0);
|
|
409
|
+
fisherExecutor.timeToAccept = 0;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
function acceptFisherExecutor() external {
|
|
413
|
+
if (block.timestamp < fisherExecutor.timeToAccept) revert();
|
|
414
|
+
|
|
415
|
+
if (msg.sender != fisherExecutor.proposal) revert();
|
|
416
|
+
|
|
417
|
+
fisherExecutor.current = fisherExecutor.proposal;
|
|
418
|
+
|
|
419
|
+
fisherExecutor.proposal = address(0);
|
|
420
|
+
fisherExecutor.timeToAccept = 0;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// Getter functions //
|
|
424
|
+
function getAdmin() external view returns (AddressTypeProposal memory) {
|
|
425
|
+
return admin;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
function getFisherExecutor()
|
|
429
|
+
external
|
|
430
|
+
view
|
|
431
|
+
returns (AddressTypeProposal memory)
|
|
432
|
+
{
|
|
433
|
+
return fisherExecutor;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function getNextFisherExecutionNonce(
|
|
437
|
+
address user
|
|
438
|
+
) external view returns (uint256) {
|
|
439
|
+
return nextFisherExecutionNonce[user];
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
function getEvvmAddress() external view returns (address) {
|
|
443
|
+
return evvmAddress;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
function getHyperlaneConfig()
|
|
447
|
+
external
|
|
448
|
+
view
|
|
449
|
+
returns (HyperlaneConfig memory)
|
|
450
|
+
{
|
|
451
|
+
return hyperlane;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
function getLayerZeroConfig()
|
|
455
|
+
external
|
|
456
|
+
view
|
|
457
|
+
returns (LayerZeroConfig memory)
|
|
458
|
+
{
|
|
459
|
+
return layerZero;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
function getAxelarConfig() external view returns (AxelarConfig memory) {
|
|
463
|
+
return axelar;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
function getOptions() external view returns (bytes memory) {
|
|
467
|
+
return _options;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// Internal Functions //
|
|
471
|
+
|
|
472
|
+
function decodeAndDeposit(bytes memory payload) internal {
|
|
473
|
+
(address token, address from, uint256 amount) = decodePayload(payload);
|
|
474
|
+
executerEVVM(true, from, token, amount);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
function encodePayload(
|
|
478
|
+
address token,
|
|
479
|
+
address toAddress,
|
|
480
|
+
uint256 amount
|
|
481
|
+
) internal pure returns (bytes memory payload) {
|
|
482
|
+
payload = abi.encode(token, toAddress, amount);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
function decodePayload(
|
|
486
|
+
bytes memory payload
|
|
487
|
+
) internal pure returns (address token, address toAddress, uint256 amount) {
|
|
488
|
+
(token, toAddress, amount) = abi.decode(
|
|
489
|
+
payload,
|
|
490
|
+
(address, address, uint256)
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
function executerEVVM(
|
|
495
|
+
bool typeOfExecution,
|
|
496
|
+
address userToExecute,
|
|
497
|
+
address token,
|
|
498
|
+
uint256 amount
|
|
499
|
+
) internal {
|
|
500
|
+
if (typeOfExecution) {
|
|
501
|
+
// true = add
|
|
502
|
+
Evvm(evvmAddress).addAmountToUser(userToExecute, token, amount);
|
|
503
|
+
} else {
|
|
504
|
+
// false = remove
|
|
505
|
+
Evvm(evvmAddress).removeAmountFromUser(
|
|
506
|
+
userToExecute,
|
|
507
|
+
token,
|
|
508
|
+
amount
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
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
|
+
library ErrorsLib {
|
|
7
|
+
error InsufficientBalance();
|
|
8
|
+
error PrincipalTokenIsNotWithdrawable();
|
|
9
|
+
error InvalidDepositAmount();
|
|
10
|
+
error DepositAmountMustBeGreaterThanZero();
|
|
11
|
+
error MailboxNotAuthorized();
|
|
12
|
+
error SenderNotAuthorized();
|
|
13
|
+
error ChainIdNotAuthorized();
|
|
14
|
+
error InvalidSignature();
|
|
15
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
abstract contract ExternalChainStationStructs {
|
|
7
|
+
struct AddressTypeProposal {
|
|
8
|
+
address current;
|
|
9
|
+
address proposal;
|
|
10
|
+
uint256 timeToAccept;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
struct HyperlaneConfig {
|
|
14
|
+
uint32 hostChainStationDomainId;
|
|
15
|
+
bytes32 hostChainStationAddress;
|
|
16
|
+
address mailboxAddress;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
struct LayerZeroConfig {
|
|
20
|
+
uint32 hostChainStationEid;
|
|
21
|
+
bytes32 hostChainStationAddress;
|
|
22
|
+
address endpointAddress;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
struct AxelarConfig {
|
|
26
|
+
string hostChainStationChainName;
|
|
27
|
+
string hostChainStationAddress;
|
|
28
|
+
address gasServiceAddress;
|
|
29
|
+
address gatewayAddress;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
struct CrosschainConfig {
|
|
33
|
+
uint32 hostChainStationDomainId;
|
|
34
|
+
address mailboxAddress;
|
|
35
|
+
uint32 hostChainStationEid;
|
|
36
|
+
address endpointAddress;
|
|
37
|
+
string hostChainStationChainName;
|
|
38
|
+
address gasServiceAddress;
|
|
39
|
+
address gatewayAddress;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
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
|
+
/**
|
|
7
|
+
* @title TreasuryStructs
|
|
8
|
+
* @dev Library of common structures used across TreasuryTwoChains.
|
|
9
|
+
* This contract serves as a shared type system for the entire ecosystem,
|
|
10
|
+
* ensuring consistency in data structures between the core TreasuryTwoChains and
|
|
11
|
+
* external service contracts.
|
|
12
|
+
*
|
|
13
|
+
* @notice This contract should be inherited by both TreasuryTwoChains contracts
|
|
14
|
+
* that need to interact with these data structures.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
abstract contract HostChainStationStructs {
|
|
18
|
+
struct AddressTypeProposal {
|
|
19
|
+
address current;
|
|
20
|
+
address proposal;
|
|
21
|
+
uint256 timeToAccept;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
struct HyperlaneConfig {
|
|
25
|
+
uint32 externalChainStationDomainId;
|
|
26
|
+
bytes32 externalChainStationAddress;
|
|
27
|
+
address mailboxAddress;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
struct LayerZeroConfig {
|
|
31
|
+
uint32 externalChainStationEid;
|
|
32
|
+
bytes32 externalChainStationAddress;
|
|
33
|
+
address endpointAddress;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
struct AxelarConfig {
|
|
37
|
+
string externalChainStationChainName;
|
|
38
|
+
string externalChainStationAddress;
|
|
39
|
+
address gasServiceAddress;
|
|
40
|
+
address gatewayAddress;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
struct CrosschainConfig {
|
|
44
|
+
uint32 externalChainStationDomainId;
|
|
45
|
+
address mailboxAddress;
|
|
46
|
+
uint32 externalChainStationEid;
|
|
47
|
+
address endpointAddress;
|
|
48
|
+
string externalChainStationChainName;
|
|
49
|
+
address gasServiceAddress;
|
|
50
|
+
address gatewayAddress;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EVVM-NONCOMMERCIAL-1.0
|
|
2
|
+
// Full license terms available at: https://www.evvm.info/docs/EVVMNoncommercialLicense
|
|
3
|
+
|
|
4
|
+
import {SignatureRecover} from "@evvm/testnet-contracts/lib/SignatureRecover.sol";
|
|
5
|
+
import {AdvancedStrings} from "@evvm/testnet-contracts/lib/AdvancedStrings.sol";
|
|
6
|
+
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
|
|
7
|
+
|
|
8
|
+
pragma solidity ^0.8.0;
|
|
9
|
+
|
|
10
|
+
library SignatureUtils {
|
|
11
|
+
/**
|
|
12
|
+
* @dev using EIP-191 (https://eips.ethereum.org/EIPS/eip-191) can be used to sign and
|
|
13
|
+
* verify messages, the next functions are used to verify the messages signed
|
|
14
|
+
* by the users
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
function verifyMessageSignedForFisherBridge(
|
|
19
|
+
uint256 evvmID,
|
|
20
|
+
address signer,
|
|
21
|
+
address addressToReceive,
|
|
22
|
+
uint256 nonce,
|
|
23
|
+
address tokenAddress,
|
|
24
|
+
uint256 priorityFee,
|
|
25
|
+
uint256 amount,
|
|
26
|
+
bytes memory signature
|
|
27
|
+
) internal pure returns (bool) {
|
|
28
|
+
return
|
|
29
|
+
SignatureRecover.signatureVerification(
|
|
30
|
+
Strings.toString(evvmID),
|
|
31
|
+
"fisherBridge",
|
|
32
|
+
string.concat(
|
|
33
|
+
AdvancedStrings.addressToString(addressToReceive),
|
|
34
|
+
",",
|
|
35
|
+
Strings.toString(nonce),
|
|
36
|
+
",",
|
|
37
|
+
AdvancedStrings.addressToString(tokenAddress),
|
|
38
|
+
",",
|
|
39
|
+
Strings.toString(priorityFee),
|
|
40
|
+
",",
|
|
41
|
+
Strings.toString(amount)
|
|
42
|
+
),
|
|
43
|
+
signature,
|
|
44
|
+
signer
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
}
|