@evvm/testnet-contracts 2.3.0 → 3.0.1

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 (67) hide show
  1. package/README.md +44 -24
  2. package/contracts/core/Core.sol +1392 -0
  3. package/contracts/core/lib/CoreStorage.sol +171 -0
  4. package/contracts/nameService/NameService.sol +613 -543
  5. package/contracts/nameService/lib/IdentityValidation.sol +15 -21
  6. package/contracts/p2pSwap/P2PSwap.sol +258 -145
  7. package/contracts/staking/Estimator.sol +25 -44
  8. package/contracts/staking/Staking.sol +284 -262
  9. package/contracts/treasury/Treasury.sol +40 -47
  10. package/contracts/treasuryTwoChains/TreasuryExternalChainStation.sol +585 -198
  11. package/contracts/treasuryTwoChains/TreasuryHostChainStation.sol +425 -174
  12. package/contracts/treasuryTwoChains/lib/PayloadUtils.sol +2 -4
  13. package/interfaces/{IEvvm.sol → ICore.sol} +58 -25
  14. package/interfaces/IEstimator.sol +1 -1
  15. package/interfaces/INameService.sol +46 -49
  16. package/interfaces/IP2PSwap.sol +16 -17
  17. package/interfaces/IStaking.sol +21 -17
  18. package/interfaces/ITreasury.sol +2 -1
  19. package/interfaces/ITreasuryExternalChainStation.sol +15 -9
  20. package/interfaces/ITreasuryHostChainStation.sol +14 -11
  21. package/interfaces/IUserValidator.sol +6 -0
  22. package/library/Erc191TestBuilder.sol +336 -471
  23. package/library/EvvmService.sol +27 -71
  24. package/library/errors/CoreError.sol +116 -0
  25. package/library/errors/CrossChainTreasuryError.sol +36 -0
  26. package/library/errors/NameServiceError.sol +79 -0
  27. package/library/errors/StakingError.sol +79 -0
  28. package/{contracts/treasury/lib/ErrorsLib.sol → library/errors/TreasuryError.sol} +9 -17
  29. package/library/structs/CoreStructs.sol +146 -0
  30. package/library/structs/ExternalChainStationStructs.sol +92 -0
  31. package/library/structs/HostChainStationStructs.sol +77 -0
  32. package/library/structs/NameServiceStructs.sol +47 -0
  33. package/library/structs/P2PSwapStructs.sol +127 -0
  34. package/library/structs/StakingStructs.sol +67 -0
  35. package/library/utils/AdvancedStrings.sol +62 -44
  36. package/library/utils/CAUtils.sol +29 -0
  37. package/library/utils/governance/Admin.sol +66 -0
  38. package/library/utils/governance/ProposalStructs.sol +49 -0
  39. package/library/utils/service/CoreExecution.sol +158 -0
  40. package/library/utils/service/StakingServiceUtils.sol +20 -37
  41. package/library/utils/signature/CoreHashUtils.sol +73 -0
  42. package/library/utils/signature/NameServiceHashUtils.sol +156 -0
  43. package/library/utils/signature/P2PSwapHashUtils.sol +65 -0
  44. package/library/utils/signature/StakingHashUtils.sol +41 -0
  45. package/library/utils/signature/TreasuryCrossChainHashUtils.sol +40 -0
  46. package/package.json +1 -1
  47. package/contracts/evvm/Evvm.sol +0 -1300
  48. package/contracts/evvm/lib/ErrorsLib.sol +0 -131
  49. package/contracts/evvm/lib/EvvmStorage.sol +0 -217
  50. package/contracts/evvm/lib/EvvmStructs.sol +0 -208
  51. package/contracts/evvm/lib/SignatureUtils.sol +0 -162
  52. package/contracts/nameService/lib/ErrorsLib.sol +0 -155
  53. package/contracts/nameService/lib/NameServiceStructs.sol +0 -125
  54. package/contracts/nameService/lib/SignatureUtils.sol +0 -420
  55. package/contracts/p2pSwap/lib/P2PSwapStructs.sol +0 -59
  56. package/contracts/p2pSwap/lib/SignatureUtils.sol +0 -98
  57. package/contracts/staking/lib/ErrorsLib.sol +0 -98
  58. package/contracts/staking/lib/SignatureUtils.sol +0 -105
  59. package/contracts/staking/lib/StakingStructs.sol +0 -106
  60. package/contracts/treasuryTwoChains/lib/ErrorsLib.sol +0 -48
  61. package/contracts/treasuryTwoChains/lib/ExternalChainStationStructs.sol +0 -80
  62. package/contracts/treasuryTwoChains/lib/HostChainStationStructs.sol +0 -87
  63. package/contracts/treasuryTwoChains/lib/SignatureUtils.sol +0 -79
  64. package/library/utils/GovernanceUtils.sol +0 -81
  65. package/library/utils/nonces/AsyncNonce.sol +0 -74
  66. package/library/utils/nonces/SyncNonce.sol +0 -71
  67. package/library/utils/service/EvvmPayments.sol +0 -144
@@ -3,53 +3,35 @@
3
3
 
4
4
  pragma solidity ^0.8.0;
5
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
- * @title Treasury Cross-Chain Host Station Contract
31
- * @author Mate labs
32
- */
33
-
34
- import {IERC20} from "@evvm/testnet-contracts/library/primitives/IERC20.sol";
35
6
  import {
36
- ErrorsLib
37
- } from "@evvm/testnet-contracts/contracts/treasuryTwoChains/lib/ErrorsLib.sol";
7
+ CrossChainTreasuryError as Error
8
+ } from "@evvm/testnet-contracts/library/errors/CrossChainTreasuryError.sol";
38
9
  import {
39
- ExternalChainStationStructs
40
- } from "@evvm/testnet-contracts/contracts/treasuryTwoChains/lib/ExternalChainStationStructs.sol";
41
-
42
- import {SafeTransferLib} from "@solady/utils/SafeTransferLib.sol";
43
-
10
+ TreasuryCrossChainHashUtils as Hash
11
+ } from "@evvm/testnet-contracts/library/utils/signature/TreasuryCrossChainHashUtils.sol";
44
12
  import {
45
- SignatureUtils
46
- } from "@evvm/testnet-contracts/contracts/treasuryTwoChains/lib/SignatureUtils.sol";
13
+ ExternalChainStationStructs as Structs
14
+ } from "@evvm/testnet-contracts/library/structs/ExternalChainStationStructs.sol";
47
15
  import {
48
16
  PayloadUtils
49
17
  } from "@evvm/testnet-contracts/contracts/treasuryTwoChains/lib/PayloadUtils.sol";
50
18
 
51
- import {IMailbox} from "@hyperlane-xyz/core/contracts/interfaces/IMailbox.sol";
19
+ import {CoreError} from "@evvm/testnet-contracts/library/errors/CoreError.sol";
52
20
 
21
+ import {
22
+ SignatureRecover
23
+ } from "@evvm/testnet-contracts/library/primitives/SignatureRecover.sol";
24
+ import {
25
+ ProposalStructs
26
+ } from "@evvm/testnet-contracts/library/utils/governance/ProposalStructs.sol";
27
+ import {
28
+ AdvancedStrings
29
+ } from "@evvm/testnet-contracts/library/utils/AdvancedStrings.sol";
30
+
31
+ import {IERC20} from "@evvm/testnet-contracts/library/primitives/IERC20.sol";
32
+ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
33
+ import {SafeTransferLib} from "@solady/utils/SafeTransferLib.sol";
34
+ import {IMailbox} from "@hyperlane-xyz/core/contracts/interfaces/IMailbox.sol";
53
35
  import {
54
36
  MessagingParams,
55
37
  MessagingReceipt
@@ -65,8 +47,6 @@ import {
65
47
  import {
66
48
  OptionsBuilder
67
49
  } from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OptionsBuilder.sol";
68
- import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
69
-
70
50
  import {
71
51
  AxelarExecutable
72
52
  } from "@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol";
@@ -76,39 +56,67 @@ import {
76
56
  import {
77
57
  IInterchainGasEstimation
78
58
  } from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IInterchainGasEstimation.sol";
79
- import {
80
- AdvancedStrings
81
- } from "@evvm/testnet-contracts/library/utils/AdvancedStrings.sol";
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
+ * @title EVVM External Chain Station
86
+ * @author Mate labs
87
+ * @notice Manages cross-chain deposits from an external chain to the EVVM host chain.
88
+ * @dev Multi-protocol bridge supporting Hyperlane, LayerZero V2, and Axelar.
89
+ * Facilitates token transfers using a sequential nonce system and ECDSA signatures.
90
+ */
82
91
 
83
92
  contract TreasuryExternalChainStation is
84
- ExternalChainStationStructs,
85
93
  OApp,
86
94
  OAppOptionsType3,
87
95
  AxelarExecutable
88
96
  {
89
97
  /// @notice Admin address management with time-delayed proposals
90
98
  /// @dev Stores current admin, proposed admin, and acceptance timestamp
91
- AddressTypeProposal admin;
99
+ ProposalStructs.AddressTypeProposal admin;
92
100
 
93
101
  /// @notice Fisher executor address management with time-delayed proposals
94
102
  /// @dev Fisher executor can process cross-chain bridge transactions
95
- AddressTypeProposal fisherExecutor;
103
+ ProposalStructs.AddressTypeProposal fisherExecutor;
96
104
 
97
105
  /// @notice Hyperlane protocol configuration for cross-chain messaging
98
106
  /// @dev Contains domain ID, host chain address, and mailbox contract address
99
- HyperlaneConfig hyperlane;
107
+ Structs.HyperlaneConfig hyperlane;
100
108
 
101
109
  /// @notice LayerZero protocol configuration for omnichain messaging
102
110
  /// @dev Contains endpoint ID, host chain address, and endpoint contract address
103
- LayerZeroConfig layerZero;
111
+ Structs.LayerZeroConfig layerZero;
104
112
 
105
113
  /// @notice Axelar protocol configuration for cross-chain communication
106
114
  /// @dev Contains chain name, host chain address, gas service, and gateway addresses
107
- AxelarConfig axelar;
115
+ Structs.AxelarConfig axelar;
108
116
 
109
117
  /// @notice Pending proposal for changing host chain addresses across all protocols
110
118
  /// @dev Used for coordinated updates to host chain addresses with time delay
111
- ChangeHostChainAddressParams hostChainAddressChangeProposal;
119
+ Structs.ChangeHostChainAddressParams hostChainAddress;
112
120
 
113
121
  /// @notice Unique identifier for the EVVM instance this station belongs to
114
122
  /// @dev Immutable value set at deployment for signature verification
@@ -116,9 +124,7 @@ contract TreasuryExternalChainStation is
116
124
 
117
125
  uint256 windowTimeToChangeEvvmID;
118
126
 
119
- /// @notice Tracks the next nonce for Fisher bridge operations per user address
120
- /// @dev Prevents replay attacks in Fisher bridge transactions
121
- mapping(address => uint256) nextFisherExecutionNonce;
127
+ mapping(address user => mapping(uint256 nonce => bool isUsed)) asyncNonce;
122
128
 
123
129
  /// @notice LayerZero execution options with gas limit configuration
124
130
  /// @dev Pre-built options for LayerZero message execution (200k gas limit)
@@ -173,32 +179,32 @@ contract TreasuryExternalChainStation is
173
179
  /// @param _crosschainConfig Configuration struct containing all cross-chain protocol settings
174
180
  constructor(
175
181
  address _admin,
176
- CrosschainConfig memory _crosschainConfig
182
+ Structs.CrosschainConfig memory _crosschainConfig
177
183
  )
178
184
  OApp(_crosschainConfig.layerZero.endpointAddress, _admin)
179
185
  Ownable(_admin)
180
186
  AxelarExecutable(_crosschainConfig.axelar.gatewayAddress)
181
187
  {
182
- admin = AddressTypeProposal({
188
+ admin = ProposalStructs.AddressTypeProposal({
183
189
  current: _admin,
184
190
  proposal: address(0),
185
191
  timeToAccept: 0
186
192
  });
187
- hyperlane = HyperlaneConfig({
193
+ hyperlane = Structs.HyperlaneConfig({
188
194
  hostChainStationDomainId: _crosschainConfig
189
195
  .hyperlane
190
196
  .hostChainStationDomainId,
191
197
  hostChainStationAddress: "",
192
198
  mailboxAddress: _crosschainConfig.hyperlane.mailboxAddress
193
199
  });
194
- layerZero = LayerZeroConfig({
200
+ layerZero = Structs.LayerZeroConfig({
195
201
  hostChainStationEid: _crosschainConfig
196
202
  .layerZero
197
203
  .hostChainStationEid,
198
204
  hostChainStationAddress: "",
199
205
  endpointAddress: _crosschainConfig.layerZero.endpointAddress
200
206
  });
201
- axelar = AxelarConfig({
207
+ axelar = Structs.AxelarConfig({
202
208
  hostChainStationChainName: _crosschainConfig
203
209
  .axelar
204
210
  .hostChainStationChainName,
@@ -230,6 +236,8 @@ contract TreasuryExternalChainStation is
230
236
  layerZero.hostChainStationAddress
231
237
  );
232
238
 
239
+ hostChainAddress.currentAddress = hostChainStationAddress;
240
+
233
241
  fuseSetHostChainAddress = 0x00;
234
242
  }
235
243
 
@@ -240,7 +248,7 @@ contract TreasuryExternalChainStation is
240
248
  function setEvvmID(uint256 newEvvmID) external onlyAdmin {
241
249
  if (evvmID != 0) {
242
250
  if (block.timestamp > windowTimeToChangeEvvmID)
243
- revert ErrorsLib.WindowToChangeEvvmIDExpired();
251
+ revert Error.WindowToChangeEvvmIDExpired();
244
252
  }
245
253
 
246
254
  evvmID = newEvvmID;
@@ -248,12 +256,42 @@ contract TreasuryExternalChainStation is
248
256
  windowTimeToChangeEvvmID = block.timestamp + 24 hours;
249
257
  }
250
258
 
251
- /// @notice Deposits ERC20 tokens and sends them to host chain via selected protocol
252
- /// @dev Supports Hyperlane (0x01), LayerZero (0x02), and Axelar (0x03) protocols
253
- /// @param toAddress Recipient address on the host chain
254
- /// @param token ERC20 token contract address to deposit and transfer
255
- /// @param amount Amount of tokens to deposit and send to host chain
256
- /// @param protocolToExecute Protocol selector: 0x01=Hyperlane, 0x02=LayerZero, 0x03=Axelar
259
+ /**
260
+ * @notice Deposits ERC20 tokens via selected protocol
261
+ * @dev Transfers tokens then bridges to host chain
262
+ *
263
+ * Process:
264
+ * - Transfer: User this contract (via approval)
265
+ * - Encode: PayloadUtils.encodePayload(token, to, amt)
266
+ * - Route: Protocol-specific message dispatch
267
+ * - Receive: Host chain credits Core.sol balance
268
+ *
269
+ * Protocol Routing:
270
+ * - 0x01: Hyperlane (mailbox.dispatch + quote fee)
271
+ * - 0x02: LayerZero (_lzSend + quote fee)
272
+ * - 0x03: Axelar (payNativeGas + callContract)
273
+ *
274
+ * Fee Payment:
275
+ * - Hyperlane: msg.value = quote
276
+ * - LayerZero: msg.value = quote (refund excess)
277
+ * - Axelar: msg.value for gas service
278
+ *
279
+ * Host Chain Integration:
280
+ * - Receives: handle/_lzReceive/_execute
281
+ * - Credits: Core.sol balance for recipient
282
+ * - Fisher Bridge: Independent from Core.sol nonces
283
+ *
284
+ * Security:
285
+ * - Approval: Must approve this contract first
286
+ * - Validation: verifyAndDepositERC20 checks balance
287
+ * - Sender checks: Host validates origin on receive
288
+ *
289
+ * @param toAddress Recipient on host chain
290
+ * @param token ERC20 token address
291
+ * @param amount Token amount to bridge
292
+ * @param protocolToExecute 0x01=Hyperlane, 0x02=LZ,
293
+ * 0x03=Axelar
294
+ */
257
295
  function depositERC20(
258
296
  address toAddress,
259
297
  address token,
@@ -306,17 +344,48 @@ contract TreasuryExternalChainStation is
306
344
  }
307
345
  }
308
346
 
309
- /// @notice Deposits native ETH and sends it to host chain via selected protocol
310
- /// @dev msg.value must cover both the amount and protocol fees
311
- /// @param toAddress Recipient address on the host chain
312
- /// @param amount Amount of ETH to send to host chain (must be <= msg.value - fees)
313
- /// @param protocolToExecute Protocol selector: 0x01=Hyperlane, 0x02=LayerZero, 0x03=Axelar
347
+ /**
348
+ * @notice Deposits native ETH via selected protocol
349
+ * @dev msg.value covers amount + protocol fees
350
+ *
351
+ * Process:
352
+ * - Validate: msg.value >= amount + fees
353
+ * - Encode: PayloadUtils.encodePayload(0x0, to, amt)
354
+ * - Route: Protocol-specific message dispatch
355
+ * - Receive: Host chain credits Core.sol balance
356
+ *
357
+ * Protocol Routing:
358
+ * - 0x01: Hyperlane (dispatch w/ quote + amount)
359
+ * - 0x02: LayerZero (_lzSend w/ fee + amount)
360
+ * - 0x03: Axelar (payNativeGas then callContract)
361
+ *
362
+ * Fee Calculation:
363
+ * - Hyperlane: msg.value = quote + amount
364
+ * - LayerZero: msg.value = fee + amount (refund)
365
+ * - Axelar: msg.value = gasService + amount
366
+ *
367
+ * Host Chain Integration:
368
+ * - Token Representation: address(0) for native ETH
369
+ * - Payload: Encoded with zero address
370
+ * - Credits: Core.sol balance as native token
371
+ * - Fisher Bridge: Independent nonce system
372
+ *
373
+ * Security:
374
+ * - Balance Check: Reverts if insufficient value
375
+ * - Excess Handling: LZ refunds, others use full
376
+ * - Validation: Host validates origin and sender
377
+ *
378
+ * @param toAddress Recipient on host chain
379
+ * @param amount ETH amount to bridge
380
+ * @param protocolToExecute 0x01=Hyperlane, 0x02=LZ,
381
+ * 0x03=Axelar
382
+ */
314
383
  function depositCoin(
315
384
  address toAddress,
316
385
  uint256 amount,
317
386
  bytes1 protocolToExecute
318
387
  ) external payable {
319
- if (msg.value < amount) revert ErrorsLib.InsufficientBalance();
388
+ if (msg.value < amount) revert Error.InsufficientBalance();
320
389
 
321
390
  bytes memory payload = PayloadUtils.encodePayload(
322
391
  address(0),
@@ -327,8 +396,7 @@ contract TreasuryExternalChainStation is
327
396
  if (protocolToExecute == 0x01) {
328
397
  // 0x01 = Hyperlane
329
398
  uint256 quote = getQuoteHyperlane(toAddress, address(0), amount);
330
- if (msg.value < quote + amount)
331
- revert ErrorsLib.InsufficientBalance();
399
+ if (msg.value < quote + amount) revert Error.InsufficientBalance();
332
400
  /*messageId = */ IMailbox(hyperlane.mailboxAddress).dispatch{
333
401
  value: quote
334
402
  }(
@@ -339,8 +407,7 @@ contract TreasuryExternalChainStation is
339
407
  } else if (protocolToExecute == 0x02) {
340
408
  // 0x02 = LayerZero
341
409
  uint256 fee = quoteLayerZero(toAddress, address(0), amount);
342
- if (msg.value < fee + amount)
343
- revert ErrorsLib.InsufficientBalance();
410
+ if (msg.value < fee + amount) revert Error.InsufficientBalance();
344
411
  _lzSend(
345
412
  layerZero.hostChainStationEid,
346
413
  payload,
@@ -368,70 +435,164 @@ contract TreasuryExternalChainStation is
368
435
  }
369
436
  }
370
437
 
371
- /// @notice Receives and validates Fisher bridge transactions from host chain
372
- /// @dev Verifies signature and increments nonce but doesn't transfer tokens (receive-only)
373
- /// @param from Original sender address from host chain
374
- /// @param addressToReceive Intended recipient address on this chain
375
- /// @param tokenAddress Token contract address (address(0) for ETH)
376
- /// @param priorityFee Fee amount for priority processing
377
- /// @param amount Amount of tokens being received
378
- /// @param signature ECDSA signature proving transaction authorization
438
+ /**
439
+ * @notice Validates Fisher bridge receive confirmation
440
+ * @dev Confirms tokens sent FROM host TO external chain
441
+ *
442
+ * Purpose:
443
+ * - Acknowledge: Confirm host sent tokens
444
+ * - Validate: Signature from original sender
445
+ * - Track: Mark nonce as used
446
+ * - Security: Prevent replay attacks
447
+ *
448
+ * Signature Validation:
449
+ * - Payload: AdvancedStrings.buildSignaturePayload
450
+ * - Components: evvmID, host address, hash, nonce
451
+ * - Hash: TreasuryCrossChainHashUtils.hashData...
452
+ * - Recovers: Must match 'from' address
453
+ *
454
+ * Nonce System:
455
+ * - Independent: asyncNonce[from][nonce] mapping
456
+ * - Sequential: User manages nonce ordering
457
+ * - NOT Core.sol: Fisher bridge separate system
458
+ * - Prevention: Revert if nonce already used
459
+ *
460
+ * Integration Context:
461
+ * - Core.sol: NOT used (independent nonces)
462
+ * - Core.sol: NOT on external chain
463
+ * - SignatureRecover: ECDSA signature validation
464
+ * - Host Chain: Sends tokens via protocol messages
465
+ *
466
+ * Security Flow:
467
+ * - Check: Nonce not already used
468
+ * - Recover: Signer from signature payload
469
+ * - Validate: Recovered signer == from address
470
+ * - Mark: asyncNonce[from][nonce] = true
471
+ *
472
+ * @param from Original sender on host chain
473
+ * @param addressToReceive Recipient on external chain
474
+ * @param tokenAddress Token (address(0) for ETH)
475
+ * @param priorityFee Fee for priority processing
476
+ * @param amount Token amount received
477
+ * @param nonce Sequential nonce from user
478
+ * @param signature ECDSA signature from 'from' address
479
+ */
379
480
  function fisherBridgeReceive(
380
481
  address from,
381
482
  address addressToReceive,
382
483
  address tokenAddress,
383
484
  uint256 priorityFee,
384
485
  uint256 amount,
486
+ uint256 nonce,
385
487
  bytes memory signature
386
488
  ) external onlyFisherExecutor {
489
+ if (asyncNonce[from][nonce]) revert CoreError.AsyncNonceAlreadyUsed();
490
+
387
491
  if (
388
- !SignatureUtils.verifyMessageSignedForFisherBridge(
389
- evvmID,
390
- from,
391
- addressToReceive,
392
- nextFisherExecutionNonce[from],
393
- tokenAddress,
394
- priorityFee,
395
- amount,
492
+ SignatureRecover.recoverSigner(
493
+ AdvancedStrings.buildSignaturePayload(
494
+ evvmID,
495
+ hostChainAddress.currentAddress,
496
+ Hash.hashDataForFisherBridge(
497
+ addressToReceive,
498
+ tokenAddress,
499
+ priorityFee,
500
+ amount
501
+ ),
502
+ fisherExecutor.current,
503
+ nonce,
504
+ true
505
+ ),
396
506
  signature
397
- )
398
- ) revert ErrorsLib.InvalidSignature();
507
+ ) != from
508
+ ) revert CoreError.InvalidSignature();
399
509
 
400
- nextFisherExecutionNonce[from]++;
510
+ asyncNonce[from][nonce] = true;
401
511
  }
402
512
 
403
- /// @notice Processes Fisher bridge ERC20 token transfers to host chain
404
- /// @dev Validates signature, deposits tokens, and emits tracking event
405
- /// @param from Original sender address initiating the bridge transaction
406
- /// @param addressToReceive Recipient address on the host chain
407
- /// @param tokenAddress ERC20 token contract address to bridge
408
- /// @param priorityFee Fee amount for priority processing
409
- /// @param amount Amount of tokens to bridge to host chain
410
- /// @param signature ECDSA signature proving transaction authorization
513
+ /**
514
+ * @notice Executes Fisher bridge ERC20 deposit to host
515
+ * @dev Validates signature, deposits, emits event
516
+ *
517
+ * Purpose:
518
+ * - Deposit: Transfer ERC20 from user to contract
519
+ * - Validate: ECDSA signature from sender
520
+ * - Track: Mark nonce as used
521
+ * - Emit: Log for Fisher executor on host chain
522
+ *
523
+ * Fisher Bridge Flow:
524
+ * - External: User signs intent + executor calls this
525
+ * - Deposit: Tokens held in this contract
526
+ * - Event: FisherBridgeSend logged
527
+ * - Host: Fisher monitors events + credits balance
528
+ * - Core.sol: Host chain credits recipient balance
529
+ *
530
+ * Signature Validation:
531
+ * - Payload: evvmID + host address + hash + nonce
532
+ * - Hash: hashDataForFisherBridge(to, token, fee,
533
+ * amt)
534
+ * - Recover: SignatureRecover.recoverSigner
535
+ * - Match: Recovered signer must equal 'from'
536
+ *
537
+ * Nonce System:
538
+ * - Independent: asyncNonce[from][nonce]
539
+ * - NOT Core.sol: Separate from EVVM nonces
540
+ * - Sequential: User manages own nonces
541
+ * - Replay Prevention: Mark used after validation
542
+ *
543
+ * Integration Context:
544
+ * - Core.sol: NOT used (Fisher independent)
545
+ * - Core.sol: Credits balance on host chain
546
+ * - Fisher Executor: Monitors events + processes
547
+ * - Host Station: Receives event + credits user
548
+ *
549
+ * Security:
550
+ * - Approval: Requires token approval first
551
+ * - Signature: ECDSA validation prevents forgery
552
+ * - Nonce: Sequential tracking prevents replays
553
+ * - Executor Only: onlyFisherExecutor modifier
554
+ *
555
+ * @param from Original sender (signer)
556
+ * @param addressToReceive Recipient on host chain
557
+ * @param tokenAddress ERC20 token address
558
+ * @param priorityFee Fee for priority processing
559
+ * @param amount Token amount to bridge
560
+ * @param nonce Sequential nonce from user
561
+ * @param signature ECDSA signature from 'from'
562
+ */
411
563
  function fisherBridgeSendERC20(
412
564
  address from,
413
565
  address addressToReceive,
414
566
  address tokenAddress,
415
567
  uint256 priorityFee,
416
568
  uint256 amount,
569
+ uint256 nonce,
417
570
  bytes memory signature
418
571
  ) external onlyFisherExecutor {
572
+ if (asyncNonce[from][nonce]) revert CoreError.AsyncNonceAlreadyUsed();
573
+
419
574
  if (
420
- !SignatureUtils.verifyMessageSignedForFisherBridge(
421
- evvmID,
422
- from,
423
- addressToReceive,
424
- nextFisherExecutionNonce[from],
425
- tokenAddress,
426
- priorityFee,
427
- amount,
575
+ SignatureRecover.recoverSigner(
576
+ AdvancedStrings.buildSignaturePayload(
577
+ evvmID,
578
+ hostChainAddress.currentAddress,
579
+ Hash.hashDataForFisherBridge(
580
+ addressToReceive,
581
+ tokenAddress,
582
+ priorityFee,
583
+ amount
584
+ ),
585
+ fisherExecutor.current,
586
+ nonce,
587
+ true
588
+ ),
428
589
  signature
429
- )
430
- ) revert ErrorsLib.InvalidSignature();
590
+ ) != from
591
+ ) revert CoreError.InvalidSignature();
431
592
 
432
593
  verifyAndDepositERC20(tokenAddress, amount);
433
594
 
434
- nextFisherExecutionNonce[from]++;
595
+ asyncNonce[from][nonce] = true;
435
596
 
436
597
  emit FisherBridgeSend(
437
598
  from,
@@ -439,41 +600,98 @@ contract TreasuryExternalChainStation is
439
600
  tokenAddress,
440
601
  priorityFee,
441
602
  amount,
442
- nextFisherExecutionNonce[from] - 1
603
+ nonce
443
604
  );
444
605
  }
445
606
 
446
- /// @notice Processes Fisher bridge ETH transfers to host chain
447
- /// @dev Validates signature and exact payment (amount + priority fee)
448
- /// @param from Original sender address initiating the bridge transaction
449
- /// @param addressToReceive Recipient address on the host chain
450
- /// @param priorityFee Fee amount for priority processing
451
- /// @param amount Amount of ETH to bridge to host chain
452
- /// @param signature ECDSA signature proving transaction authorization
607
+ /**
608
+ * @notice Executes Fisher bridge ETH deposit to host
609
+ * @dev Validates signature and exact payment
610
+ *
611
+ * Purpose:
612
+ * - Deposit: Receive ETH from executor caller
613
+ * - Validate: ECDSA signature from original sender
614
+ * - Track: Mark nonce as used
615
+ * - Emit: Log for Fisher executor on host chain
616
+ *
617
+ * Fisher Bridge Flow:
618
+ * - External: User signs intent + pays executor
619
+ * - Deposit: msg.value = amount + priorityFee
620
+ * - Event: FisherBridgeSend with address(0)
621
+ * - Host: Fisher monitors + credits Evvm balance
622
+ * - Core.sol: Host chain credits recipient
623
+ *
624
+ * Payment Validation:
625
+ * - Exact Match: msg.value == amount + priorityFee
626
+ * - No Excess: Prevents overpayment mistakes
627
+ * - Native Token: Represented as address(0)
628
+ * - Host Credits: Full amount to recipient
629
+ *
630
+ * Signature Validation:
631
+ * - Payload: evvmID + host + hash + nonce
632
+ * - Hash: hashDataForFisherBridge(to, 0x0, fee,
633
+ * amt)
634
+ * - Token: address(0) represents native ETH
635
+ * - Recover: Must match 'from' address
636
+ *
637
+ * Nonce System:
638
+ * - Independent: asyncNonce[from][nonce]
639
+ * - NOT Core.sol: Fisher bridge separate
640
+ * - Sequential: User-managed ordering
641
+ * - Anti-Replay: Mark used after validation
642
+ *
643
+ * Integration Context:
644
+ * - Core.sol: NOT used (independent system)
645
+ * - Core.sol: Credits native balance on host
646
+ * - Fisher Executor: Pays ETH + processes
647
+ * - Host Station: Credits recipient balance
648
+ *
649
+ * Security:
650
+ * - Exact Payment: Prevents partial payments
651
+ * - Signature: ECDSA prevents unauthorized sends
652
+ * - Nonce: Sequential tracking prevents replays
653
+ * - Executor Only: onlyFisherExecutor modifier
654
+ *
655
+ * @param from Original sender (signer)
656
+ * @param addressToReceive Recipient on host chain
657
+ * @param priorityFee Fee for priority processing
658
+ * @param amount ETH amount to bridge
659
+ * @param nonce Sequential nonce from user
660
+ * @param signature ECDSA signature from 'from'
661
+ */
453
662
  function fisherBridgeSendCoin(
454
663
  address from,
455
664
  address addressToReceive,
456
665
  uint256 priorityFee,
457
666
  uint256 amount,
667
+ uint256 nonce,
458
668
  bytes memory signature
459
669
  ) external payable onlyFisherExecutor {
670
+ if (asyncNonce[from][nonce]) revert CoreError.AsyncNonceAlreadyUsed();
671
+
460
672
  if (
461
- !SignatureUtils.verifyMessageSignedForFisherBridge(
462
- evvmID,
463
- from,
464
- addressToReceive,
465
- nextFisherExecutionNonce[from],
466
- address(0),
467
- priorityFee,
468
- amount,
673
+ SignatureRecover.recoverSigner(
674
+ AdvancedStrings.buildSignaturePayload(
675
+ evvmID,
676
+ hostChainAddress.currentAddress,
677
+ Hash.hashDataForFisherBridge(
678
+ addressToReceive,
679
+ address(0),
680
+ priorityFee,
681
+ amount
682
+ ),
683
+ fisherExecutor.current,
684
+ nonce,
685
+ true
686
+ ),
469
687
  signature
470
- )
471
- ) revert ErrorsLib.InvalidSignature();
688
+ ) != from
689
+ ) revert CoreError.InvalidSignature();
472
690
 
473
691
  if (msg.value != amount + priorityFee)
474
- revert ErrorsLib.InsufficientBalance();
692
+ revert Error.InsufficientBalance();
475
693
 
476
- nextFisherExecutionNonce[from]++;
694
+ asyncNonce[from][nonce] = true;
477
695
 
478
696
  emit FisherBridgeSend(
479
697
  from,
@@ -481,18 +699,44 @@ contract TreasuryExternalChainStation is
481
699
  address(0),
482
700
  priorityFee,
483
701
  amount,
484
- nextFisherExecutionNonce[from] - 1
702
+ nonce
485
703
  );
486
704
  }
487
705
 
488
706
  // Hyperlane Specific Functions //
489
707
 
490
- /// @notice Calculates the fee required for Hyperlane cross-chain message dispatch
491
- /// @dev Queries the Hyperlane mailbox for accurate fee estimation
492
- /// @param toAddress Recipient address on the destination chain
493
- /// @param token Token contract address being transferred
494
- /// @param amount Amount of tokens being transferred
495
- /// @return Fee amount in native currency required for the Hyperlane message
708
+ /**
709
+ * @notice Quotes Hyperlane cross-chain message fee
710
+ * @dev Queries mailbox for accurate fee estimation
711
+ *
712
+ * Purpose:
713
+ * - Estimate: Calculate native token fee for message
714
+ * - Quote: Query Hyperlane mailbox contract
715
+ * - Planning: Users know cost before depositERC20
716
+ * - Payment: Fee paid in msg.value on deposit
717
+ *
718
+ * Hyperlane Fee Model:
719
+ * - Calculation: mailbox.quoteDispatch
720
+ * - Components: Destination domain + payload size
721
+ * - Payment: Native token to mailbox
722
+ * - Delivery: Relayers submit to destination
723
+ *
724
+ * Quote Components:
725
+ * - Domain ID: hyperlane.hostChainStationDomainId
726
+ * - Recipient: hyperlane.hostChainStationAddress
727
+ * - Payload: PayloadUtils.encodePayload(token, to,
728
+ * amt)
729
+ *
730
+ * Usage:
731
+ * - Pre-Deposit: Call to estimate required msg.value
732
+ * - Display: Show users total cost
733
+ * - Payment: depositERC20 uses quote for dispatch
734
+ *
735
+ * @param toAddress Recipient on host chain
736
+ * @param token Token address (or 0x0 for ETH)
737
+ * @param amount Token amount to bridge
738
+ * @return Native token fee for Hyperlane message
739
+ */
496
740
  function getQuoteHyperlane(
497
741
  address toAddress,
498
742
  address token,
@@ -506,36 +750,97 @@ contract TreasuryExternalChainStation is
506
750
  );
507
751
  }
508
752
 
509
- /// @notice Handles incoming Hyperlane messages from the host chain
510
- /// @dev Validates origin, sender authorization, and processes the payload
511
- /// @param _origin Source chain domain ID where the message originated
512
- /// @param _sender Address of the message sender (must be host chain station)
513
- /// @param _data Encoded payload containing transfer instructions
753
+ /**
754
+ * @notice Handles incoming Hyperlane messages
755
+ * @dev Validates origin, sender, processes payload
756
+ *
757
+ * Purpose:
758
+ * - Receive: Messages from host chain via Hyperlane
759
+ * - Validate: Origin domain + sender address
760
+ * - Process: Decode payload + transfer tokens
761
+ * - Security: Multi-layer validation checks
762
+ *
763
+ * Hyperlane Message Flow:
764
+ * - Host: TreasuryHostChainStation dispatches
765
+ * - Relayer: Submits message to this chain
766
+ * - Mailbox: Calls this handle() function
767
+ * - Process: decodeAndGive transfers tokens
768
+ *
769
+ * Validation Layers:
770
+ * - Caller: Must be hyperlane.mailboxAddress
771
+ * - Sender: Must be hyperlane.hostChainStation...
772
+ * - Origin: Must be hyperlane.hostChainStation
773
+ * DomainId
774
+ * - All checks prevent unauthorized messages
775
+ *
776
+ * Payload Processing:
777
+ * - Decode: PayloadUtils.decodePayload(_data)
778
+ * - Extract: token address, recipient, amount
779
+ * - Transfer: ETH (address 0) or ERC20 tokens
780
+ * - Recipient: Receives tokens on external chain
781
+ *
782
+ * Security:
783
+ * - Mailbox Only: Reverts if caller not mailbox
784
+ * - Sender Check: Reverts if not host station
785
+ * - Domain Check: Reverts if wrong origin
786
+ * - Three-layer validation prevents attacks
787
+ *
788
+ * @param _origin Source chain domain ID
789
+ * @param _sender Sender address (host station)
790
+ * @param _data Encoded payload (token, to, amount)
791
+ */
514
792
  function handle(
515
793
  uint32 _origin,
516
794
  bytes32 _sender,
517
795
  bytes calldata _data
518
796
  ) external payable virtual {
519
797
  if (msg.sender != hyperlane.mailboxAddress)
520
- revert ErrorsLib.MailboxNotAuthorized();
798
+ revert Error.MailboxNotAuthorized();
521
799
 
522
800
  if (_sender != hyperlane.hostChainStationAddress)
523
- revert ErrorsLib.SenderNotAuthorized();
801
+ revert Error.SenderNotAuthorized();
524
802
 
525
803
  if (_origin != hyperlane.hostChainStationDomainId)
526
- revert ErrorsLib.ChainIdNotAuthorized();
804
+ revert Error.ChainIdNotAuthorized();
527
805
 
528
806
  decodeAndGive(_data);
529
807
  }
530
808
 
531
809
  // LayerZero Specific Functions //
532
810
 
533
- /// @notice Calculates the fee required for LayerZero cross-chain message
534
- /// @dev Queries LayerZero endpoint for accurate native fee estimation
535
- /// @param toAddress Recipient address on the destination chain
536
- /// @param token Token contract address being transferred
537
- /// @param amount Amount of tokens being transferred
538
- /// @return Native fee amount required for the LayerZero message
811
+ /**
812
+ * @notice Quotes LayerZero cross-chain message fee
813
+ * @dev Queries endpoint for native fee estimation
814
+ *
815
+ * Purpose:
816
+ * - Estimate: Calculate native token fee for LZ send
817
+ * - Quote: Query LayerZero V2 endpoint
818
+ * - Planning: Users know cost before deposit
819
+ * - Payment: Fee paid in msg.value on deposit
820
+ *
821
+ * LayerZero Fee Model:
822
+ * - Calculation: _quote (internal OApp function)
823
+ * - Components: Destination eid + payload + options
824
+ * - Options: 200k gas limit for execution
825
+ * - Refund: Excess fees returned to sender
826
+ *
827
+ * Quote Components:
828
+ * - Endpoint ID: layerZero.hostChainStationEid
829
+ * - Payload: PayloadUtils.encodePayload
830
+ * - Options: Pre-built with 200k gas limit
831
+ * - Pay ZRO: false (only native token)
832
+ *
833
+ * Usage:
834
+ * - Pre-Deposit: Call to estimate required msg.value
835
+ * - Display: Show users total cost
836
+ * - Payment: depositERC20/Coin uses quote
837
+ * - Refund: LZ returns excess to sender
838
+ *
839
+ * @param toAddress Recipient on host chain
840
+ * @param token Token address (or 0x0 for ETH)
841
+ * @param amount Token amount to bridge
842
+ * @return Native token fee for LayerZero message
843
+ */
539
844
  function quoteLayerZero(
540
845
  address toAddress,
541
846
  address token,
@@ -550,10 +855,46 @@ contract TreasuryExternalChainStation is
550
855
  return fee.nativeFee;
551
856
  }
552
857
 
553
- /// @notice Handles incoming LayerZero messages from the host chain
554
- /// @dev Validates origin chain and sender, then processes the transfer payload
555
- /// @param _origin Origin information containing source endpoint ID and sender
556
- /// @param message Encoded payload containing transfer instructions
858
+ /**
859
+ * @notice Handles incoming LayerZero messages
860
+ * @dev Validates origin + sender, processes payload
861
+ *
862
+ * Purpose:
863
+ * - Receive: Messages from host via LayerZero V2
864
+ * - Validate: Origin eid + sender address
865
+ * - Process: Decode payload + transfer tokens
866
+ * - Security: Multi-layer validation checks
867
+ *
868
+ * LayerZero Message Flow:
869
+ * - Host: TreasuryHostChainStation.lzSend
870
+ * - DVNs: Verify message across networks
871
+ * - Executor: Submits message to this chain
872
+ * - Endpoint: Calls this _lzReceive function
873
+ *
874
+ * Validation Layers:
875
+ * - Origin EID: Must be layerZero.hostChainStation
876
+ * Eid
877
+ * - Sender: Must be layerZero.hostChainStation
878
+ * Address
879
+ * - Peer: OApp validates via _getPeerOrRevert
880
+ * - All checks prevent unauthorized messages
881
+ *
882
+ * Payload Processing:
883
+ * - Decode: PayloadUtils.decodePayload(message)
884
+ * - Extract: token address, recipient, amount
885
+ * - Transfer: ETH (address 0) or ERC20 tokens
886
+ * - Recipient: Receives tokens on external chain
887
+ *
888
+ * Security:
889
+ * - EID Check: Reverts if wrong source endpoint
890
+ * - Sender Check: Reverts if not host station
891
+ * - OApp Pattern: Peer validation built-in
892
+ * - Two-layer validation prevents attacks
893
+ *
894
+ * @param _origin Origin info (srcEid, sender,
895
+ * nonce)
896
+ * @param message Encoded payload (token, to, amount)
897
+ */
557
898
  function _lzReceive(
558
899
  Origin calldata _origin,
559
900
  bytes32 /*_guid*/,
@@ -563,10 +904,10 @@ contract TreasuryExternalChainStation is
563
904
  ) internal override {
564
905
  // Decode the payload to get the message
565
906
  if (_origin.srcEid != layerZero.hostChainStationEid)
566
- revert ErrorsLib.ChainIdNotAuthorized();
907
+ revert Error.ChainIdNotAuthorized();
567
908
 
568
909
  if (_origin.sender != layerZero.hostChainStationAddress)
569
- revert ErrorsLib.SenderNotAuthorized();
910
+ revert Error.SenderNotAuthorized();
570
911
 
571
912
  decodeAndGive(message);
572
913
  }
@@ -606,11 +947,52 @@ contract TreasuryExternalChainStation is
606
947
 
607
948
  // Axelar Specific Functions //
608
949
 
609
- /// @notice Handles incoming Axelar messages from the host chain
610
- /// @dev Validates source chain and address, then processes the transfer payload
611
- /// @param _sourceChain Source blockchain name (must match configured host chain)
612
- /// @param _sourceAddress Source contract address (must match host chain station)
613
- /// @param _payload Encoded payload containing transfer instructions
950
+ /**
951
+ * @notice Handles incoming Axelar messages
952
+ * @dev Validates source chain/address, processes payload
953
+ *
954
+ * Purpose:
955
+ * - Receive: Messages from host via Axelar Network
956
+ * - Validate: Source chain name + sender address
957
+ * - Process: Decode payload + transfer tokens
958
+ * - Security: Multi-layer validation checks
959
+ *
960
+ * Axelar Message Flow:
961
+ * - Host: TreasuryHostChainStation.callContract
962
+ * - Axelar: Validates via validator network
963
+ * - Gateway: Calls this _execute function
964
+ * - Process: decodeAndGive transfers tokens
965
+ *
966
+ * Validation Layers:
967
+ * - Source Chain: Must be axelar.hostChainStation
968
+ * ChainName
969
+ * - Source Address: Must be axelar.hostChainStation
970
+ * Address
971
+ * - Gateway: AxelarExecutable validates caller
972
+ * - All checks prevent unauthorized messages
973
+ *
974
+ * String Comparison:
975
+ * - AdvancedStrings.equal: Chain name validation
976
+ * - Case-Sensitive: Exact match required
977
+ * - Address Format: String type for Axelar
978
+ * - Security: Double validation of source
979
+ *
980
+ * Payload Processing:
981
+ * - Decode: PayloadUtils.decodePayload(_payload)
982
+ * - Extract: token address, recipient, amount
983
+ * - Transfer: ETH (address 0) or ERC20 tokens
984
+ * - Recipient: Receives tokens on external chain
985
+ *
986
+ * Security:
987
+ * - Chain Check: Reverts if wrong source chain
988
+ * - Address Check: Reverts if not host station
989
+ * - Gateway Pattern: AxelarExecutable validation
990
+ * - Two-layer validation prevents attacks
991
+ *
992
+ * @param _sourceChain Source blockchain name
993
+ * @param _sourceAddress Source contract address
994
+ * @param _payload Encoded payload (token, to, amount)
995
+ */
614
996
  function _execute(
615
997
  bytes32 /*commandId*/,
616
998
  string calldata _sourceChain,
@@ -622,14 +1004,14 @@ contract TreasuryExternalChainStation is
622
1004
  _sourceChain,
623
1005
  axelar.hostChainStationChainName
624
1006
  )
625
- ) revert ErrorsLib.ChainIdNotAuthorized();
1007
+ ) revert Error.ChainIdNotAuthorized();
626
1008
 
627
1009
  if (
628
1010
  !AdvancedStrings.equal(
629
1011
  _sourceAddress,
630
1012
  axelar.hostChainStationAddress
631
1013
  )
632
- ) revert ErrorsLib.SenderNotAuthorized();
1014
+ ) revert Error.SenderNotAuthorized();
633
1015
 
634
1016
  decodeAndGive(_payload);
635
1017
  }
@@ -711,9 +1093,10 @@ contract TreasuryExternalChainStation is
711
1093
  ) external onlyAdmin {
712
1094
  if (fuseSetHostChainAddress == 0x01) revert();
713
1095
 
714
- hostChainAddressChangeProposal = ChangeHostChainAddressParams({
1096
+ hostChainAddress = Structs.ChangeHostChainAddressParams({
715
1097
  porposeAddress_AddressType: hostChainStationAddress,
716
1098
  porposeAddress_StringType: hostChainStationAddressString,
1099
+ currentAddress: hostChainAddress.currentAddress,
717
1100
  timeToAccept: block.timestamp + 1 minutes
718
1101
  });
719
1102
  }
@@ -721,9 +1104,10 @@ contract TreasuryExternalChainStation is
721
1104
  /// @notice Cancels a pending host chain address change proposal
722
1105
  /// @dev Resets the host chain address proposal to default state
723
1106
  function rejectProposalHostChainAddress() external onlyAdmin {
724
- hostChainAddressChangeProposal = ChangeHostChainAddressParams({
1107
+ hostChainAddress = Structs.ChangeHostChainAddressParams({
725
1108
  porposeAddress_AddressType: address(0),
726
1109
  porposeAddress_StringType: "",
1110
+ currentAddress: hostChainAddress.currentAddress,
727
1111
  timeToAccept: 0
728
1112
  });
729
1113
  }
@@ -731,37 +1115,39 @@ contract TreasuryExternalChainStation is
731
1115
  /// @notice Accepts pending host chain address changes across all protocols
732
1116
  /// @dev Updates Hyperlane, LayerZero, and Axelar configurations simultaneously
733
1117
  function acceptHostChainAddress() external {
734
- if (block.timestamp < hostChainAddressChangeProposal.timeToAccept)
735
- revert();
1118
+ if (block.timestamp < hostChainAddress.timeToAccept) revert();
736
1119
 
737
1120
  hyperlane.hostChainStationAddress = bytes32(
738
- uint256(
739
- uint160(
740
- hostChainAddressChangeProposal.porposeAddress_AddressType
741
- )
742
- )
1121
+ uint256(uint160(hostChainAddress.porposeAddress_AddressType))
743
1122
  );
744
1123
  layerZero.hostChainStationAddress = bytes32(
745
- uint256(
746
- uint160(
747
- hostChainAddressChangeProposal.porposeAddress_AddressType
748
- )
749
- )
1124
+ uint256(uint160(hostChainAddress.porposeAddress_AddressType))
750
1125
  );
751
- axelar.hostChainStationAddress = hostChainAddressChangeProposal
1126
+ axelar.hostChainStationAddress = hostChainAddress
752
1127
  .porposeAddress_StringType;
753
1128
 
754
1129
  _setPeer(
755
1130
  layerZero.hostChainStationEid,
756
1131
  layerZero.hostChainStationAddress
757
1132
  );
1133
+
1134
+ hostChainAddress = Structs.ChangeHostChainAddressParams({
1135
+ porposeAddress_AddressType: address(0),
1136
+ porposeAddress_StringType: "",
1137
+ currentAddress: hostChainAddress.porposeAddress_AddressType,
1138
+ timeToAccept: 0
1139
+ });
758
1140
  }
759
1141
 
760
1142
  // Getter functions //
761
1143
 
762
1144
  /// @notice Returns the complete admin configuration including proposals and timelock
763
1145
  /// @return Current admin address, proposed admin, and acceptance timestamp
764
- function getAdmin() external view returns (AddressTypeProposal memory) {
1146
+ function getAdmin()
1147
+ external
1148
+ view
1149
+ returns (ProposalStructs.AddressTypeProposal memory)
1150
+ {
765
1151
  return admin;
766
1152
  }
767
1153
 
@@ -770,19 +1156,16 @@ contract TreasuryExternalChainStation is
770
1156
  function getFisherExecutor()
771
1157
  external
772
1158
  view
773
- returns (AddressTypeProposal memory)
1159
+ returns (ProposalStructs.AddressTypeProposal memory)
774
1160
  {
775
1161
  return fisherExecutor;
776
1162
  }
777
1163
 
778
- /// @notice Returns the next nonce for Fisher bridge operations for a specific user
779
- /// @dev Used to prevent replay attacks in cross-chain bridge transactions
780
- /// @param user Address to query the next Fisher execution nonce for
781
- /// @return Next sequential nonce value for the user's Fisher bridge operations
782
- function getNextFisherExecutionNonce(
783
- address user
784
- ) external view returns (uint256) {
785
- return nextFisherExecutionNonce[user];
1164
+ function getIfUsedAsyncNonce(
1165
+ address user,
1166
+ uint256 nonce
1167
+ ) public view virtual returns (bool) {
1168
+ return asyncNonce[user][nonce];
786
1169
  }
787
1170
 
788
1171
  /// @notice Returns the complete Hyperlane protocol configuration
@@ -790,7 +1173,7 @@ contract TreasuryExternalChainStation is
790
1173
  function getHyperlaneConfig()
791
1174
  external
792
1175
  view
793
- returns (HyperlaneConfig memory)
1176
+ returns (Structs.HyperlaneConfig memory)
794
1177
  {
795
1178
  return hyperlane;
796
1179
  }
@@ -800,14 +1183,18 @@ contract TreasuryExternalChainStation is
800
1183
  function getLayerZeroConfig()
801
1184
  external
802
1185
  view
803
- returns (LayerZeroConfig memory)
1186
+ returns (Structs.LayerZeroConfig memory)
804
1187
  {
805
1188
  return layerZero;
806
1189
  }
807
1190
 
808
1191
  /// @notice Returns the complete Axelar protocol configuration
809
1192
  /// @return Axelar configuration including chain name, addresses, gas service, and gateway
810
- function getAxelarConfig() external view returns (AxelarConfig memory) {
1193
+ function getAxelarConfig()
1194
+ external
1195
+ view
1196
+ returns (Structs.AxelarConfig memory)
1197
+ {
811
1198
  return axelar;
812
1199
  }
813
1200
 
@@ -837,7 +1224,7 @@ contract TreasuryExternalChainStation is
837
1224
  function verifyAndDepositERC20(address token, uint256 amount) internal {
838
1225
  if (token == address(0)) revert();
839
1226
  if (IERC20(token).allowance(msg.sender, address(this)) < amount)
840
- revert ErrorsLib.InsufficientBalance();
1227
+ revert Error.InsufficientBalance();
841
1228
 
842
1229
  IERC20(token).transferFrom(msg.sender, address(this), amount);
843
1230
  }
@@ -851,4 +1238,4 @@ contract TreasuryExternalChainStation is
851
1238
  /// @notice Disabled ownership renouncement function for security
852
1239
  /// @dev Prevents accidental loss of administrative control over the contract
853
1240
  function renounceOwnership() public virtual override onlyOwner {}
854
- }
1241
+ }