@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.
Files changed (34) hide show
  1. package/LICENSE +166 -0
  2. package/README.md +216 -0
  3. package/package.json +51 -0
  4. package/src/contracts/evvm/Evvm.sol +1327 -0
  5. package/src/contracts/evvm/EvvmLegacy.sol +1553 -0
  6. package/src/contracts/evvm/lib/ErrorsLib.sol +17 -0
  7. package/src/contracts/evvm/lib/EvvmStorage.sol +60 -0
  8. package/src/contracts/evvm/lib/EvvmStructs.sol +64 -0
  9. package/src/contracts/evvm/lib/SignatureUtils.sol +124 -0
  10. package/src/contracts/nameService/NameService.sol +1751 -0
  11. package/src/contracts/nameService/lib/ErrorsLib.sol +27 -0
  12. package/src/contracts/nameService/lib/SignatureUtils.sol +239 -0
  13. package/src/contracts/staking/Estimator.sol +358 -0
  14. package/src/contracts/staking/Staking.sol +1148 -0
  15. package/src/contracts/staking/lib/ErrorsLib.sol +19 -0
  16. package/src/contracts/staking/lib/SignatureUtils.sol +68 -0
  17. package/src/contracts/treasury/Treasury.sol +104 -0
  18. package/src/contracts/treasury/lib/ErrorsLib.sol +11 -0
  19. package/src/contracts/treasuryTwoChains/TreasuryExternalChainStation.sol +551 -0
  20. package/src/contracts/treasuryTwoChains/TreasuryHostChainStation.sol +512 -0
  21. package/src/contracts/treasuryTwoChains/lib/ErrorsLib.sol +15 -0
  22. package/src/contracts/treasuryTwoChains/lib/ExternalChainStationStructs.sol +41 -0
  23. package/src/contracts/treasuryTwoChains/lib/HostChainStationStructs.sol +52 -0
  24. package/src/contracts/treasuryTwoChains/lib/SignatureUtils.sol +47 -0
  25. package/src/interfaces/IEstimator.sol +102 -0
  26. package/src/interfaces/IEvvm.sol +195 -0
  27. package/src/interfaces/INameService.sol +283 -0
  28. package/src/interfaces/IStaking.sol +202 -0
  29. package/src/interfaces/ITreasury.sol +17 -0
  30. package/src/interfaces/ITreasuryExternalChainStation.sol +262 -0
  31. package/src/interfaces/ITreasuryHostChainStation.sol +251 -0
  32. package/src/lib/AdvancedStrings.sol +77 -0
  33. package/src/lib/Erc191TestBuilder.sol +402 -0
  34. 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
+ }