@hyperlane-xyz/sdk 19.5.0 → 19.6.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 (150) hide show
  1. package/dist/core/types.d.ts +430 -0
  2. package/dist/core/types.d.ts.map +1 -1
  3. package/dist/deploy/warp.d.ts.map +1 -1
  4. package/dist/deploy/warp.js +3 -1
  5. package/dist/deploy/warp.js.map +1 -1
  6. package/dist/fee/EvmTokenFeeDeployer.d.ts +16 -0
  7. package/dist/fee/EvmTokenFeeDeployer.d.ts.map +1 -0
  8. package/dist/fee/EvmTokenFeeDeployer.hardhat-test.d.ts +2 -0
  9. package/dist/fee/EvmTokenFeeDeployer.hardhat-test.d.ts.map +1 -0
  10. package/dist/fee/EvmTokenFeeDeployer.hardhat-test.js +133 -0
  11. package/dist/fee/EvmTokenFeeDeployer.hardhat-test.js.map +1 -0
  12. package/dist/fee/EvmTokenFeeDeployer.js +75 -0
  13. package/dist/fee/EvmTokenFeeDeployer.js.map +1 -0
  14. package/dist/fee/EvmTokenFeeModule.d.ts +40 -0
  15. package/dist/fee/EvmTokenFeeModule.d.ts.map +1 -0
  16. package/dist/fee/EvmTokenFeeModule.hardhat-test.d.ts +2 -0
  17. package/dist/fee/EvmTokenFeeModule.hardhat-test.d.ts.map +1 -0
  18. package/dist/fee/EvmTokenFeeModule.hardhat-test.js +215 -0
  19. package/dist/fee/EvmTokenFeeModule.hardhat-test.js.map +1 -0
  20. package/dist/fee/EvmTokenFeeModule.js +182 -0
  21. package/dist/fee/EvmTokenFeeModule.js.map +1 -0
  22. package/dist/fee/EvmTokenFeeReader.d.ts +25 -0
  23. package/dist/fee/EvmTokenFeeReader.d.ts.map +1 -0
  24. package/dist/fee/EvmTokenFeeReader.hardhat-test.d.ts +4 -0
  25. package/dist/fee/EvmTokenFeeReader.hardhat-test.d.ts.map +1 -0
  26. package/dist/fee/EvmTokenFeeReader.hardhat-test.js +133 -0
  27. package/dist/fee/EvmTokenFeeReader.hardhat-test.js.map +1 -0
  28. package/dist/fee/EvmTokenFeeReader.js +116 -0
  29. package/dist/fee/EvmTokenFeeReader.js.map +1 -0
  30. package/dist/fee/contracts.d.ts +9 -0
  31. package/dist/fee/contracts.d.ts.map +1 -0
  32. package/dist/fee/contracts.js +9 -0
  33. package/dist/fee/contracts.js.map +1 -0
  34. package/dist/fee/types.d.ts +386 -0
  35. package/dist/fee/types.d.ts.map +1 -0
  36. package/dist/fee/types.js +107 -0
  37. package/dist/fee/types.js.map +1 -0
  38. package/dist/fee/utils.d.ts +10 -0
  39. package/dist/fee/utils.d.ts.map +1 -0
  40. package/dist/fee/utils.js +16 -0
  41. package/dist/fee/utils.js.map +1 -0
  42. package/dist/fork/types.d.ts +15 -15
  43. package/dist/ica/types.d.ts +322 -0
  44. package/dist/ica/types.d.ts.map +1 -1
  45. package/dist/index.d.ts +8 -3
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +7 -2
  48. package/dist/index.js.map +1 -1
  49. package/dist/ism/serialization.d.ts +37 -0
  50. package/dist/ism/serialization.d.ts.map +1 -0
  51. package/dist/ism/serialization.js +96 -0
  52. package/dist/ism/serialization.js.map +1 -0
  53. package/dist/mailbox/serialization.d.ts +41 -0
  54. package/dist/mailbox/serialization.d.ts.map +1 -0
  55. package/dist/mailbox/serialization.js +104 -0
  56. package/dist/mailbox/serialization.js.map +1 -0
  57. package/dist/metadata/agentConfig.d.ts +4 -4
  58. package/dist/router/HyperlaneRouterDeployer.d.ts +1 -0
  59. package/dist/router/HyperlaneRouterDeployer.d.ts.map +1 -1
  60. package/dist/router/HyperlaneRouterDeployer.js +12 -0
  61. package/dist/router/HyperlaneRouterDeployer.js.map +1 -1
  62. package/dist/router/types.d.ts +326 -1
  63. package/dist/router/types.d.ts.map +1 -1
  64. package/dist/router/types.js +2 -0
  65. package/dist/router/types.js.map +1 -1
  66. package/dist/token/EvmERC20WarpModule.d.ts +14 -1
  67. package/dist/token/EvmERC20WarpModule.d.ts.map +1 -1
  68. package/dist/token/EvmERC20WarpModule.hardhat-test.js +415 -25
  69. package/dist/token/EvmERC20WarpModule.hardhat-test.js.map +1 -1
  70. package/dist/token/EvmERC20WarpModule.js +172 -5
  71. package/dist/token/EvmERC20WarpModule.js.map +1 -1
  72. package/dist/token/EvmERC20WarpRouteReader.d.ts +8 -0
  73. package/dist/token/EvmERC20WarpRouteReader.d.ts.map +1 -1
  74. package/dist/token/EvmERC20WarpRouteReader.hardhat-test.js +141 -3
  75. package/dist/token/EvmERC20WarpRouteReader.hardhat-test.js.map +1 -1
  76. package/dist/token/EvmERC20WarpRouteReader.js +162 -34
  77. package/dist/token/EvmERC20WarpRouteReader.js.map +1 -1
  78. package/dist/token/Token.js +2 -2
  79. package/dist/token/Token.js.map +1 -1
  80. package/dist/token/Token.test.js +6 -0
  81. package/dist/token/Token.test.js.map +1 -1
  82. package/dist/token/TokenStandard.d.ts +2 -0
  83. package/dist/token/TokenStandard.d.ts.map +1 -1
  84. package/dist/token/TokenStandard.js +6 -0
  85. package/dist/token/TokenStandard.js.map +1 -1
  86. package/dist/token/adapters/CosmWasmTokenAdapter.d.ts +3 -3
  87. package/dist/token/adapters/CosmWasmTokenAdapter.d.ts.map +1 -1
  88. package/dist/token/adapters/CosmWasmTokenAdapter.js +7 -7
  89. package/dist/token/adapters/CosmWasmTokenAdapter.js.map +1 -1
  90. package/dist/token/adapters/CosmosModuleTokenAdapter.d.ts +2 -2
  91. package/dist/token/adapters/CosmosModuleTokenAdapter.d.ts.map +1 -1
  92. package/dist/token/adapters/CosmosModuleTokenAdapter.js +13 -7
  93. package/dist/token/adapters/CosmosModuleTokenAdapter.js.map +1 -1
  94. package/dist/token/adapters/CosmosTokenAdapter.d.ts +3 -3
  95. package/dist/token/adapters/CosmosTokenAdapter.d.ts.map +1 -1
  96. package/dist/token/adapters/CosmosTokenAdapter.js +15 -7
  97. package/dist/token/adapters/CosmosTokenAdapter.js.map +1 -1
  98. package/dist/token/adapters/EvmTokenAdapter.d.ts +13 -8
  99. package/dist/token/adapters/EvmTokenAdapter.d.ts.map +1 -1
  100. package/dist/token/adapters/EvmTokenAdapter.js +92 -41
  101. package/dist/token/adapters/EvmTokenAdapter.js.map +1 -1
  102. package/dist/token/adapters/ITokenAdapter.d.ts +14 -3
  103. package/dist/token/adapters/ITokenAdapter.d.ts.map +1 -1
  104. package/dist/token/adapters/M0PortalLiteTokenAdapter.d.ts +2 -2
  105. package/dist/token/adapters/M0PortalLiteTokenAdapter.d.ts.map +1 -1
  106. package/dist/token/adapters/M0PortalLiteTokenAdapter.js +10 -4
  107. package/dist/token/adapters/M0PortalLiteTokenAdapter.js.map +1 -1
  108. package/dist/token/adapters/RadixTokenAdapter.d.ts +2 -2
  109. package/dist/token/adapters/RadixTokenAdapter.d.ts.map +1 -1
  110. package/dist/token/adapters/RadixTokenAdapter.js +11 -7
  111. package/dist/token/adapters/RadixTokenAdapter.js.map +1 -1
  112. package/dist/token/adapters/SealevelTokenAdapter.d.ts +2 -2
  113. package/dist/token/adapters/SealevelTokenAdapter.d.ts.map +1 -1
  114. package/dist/token/adapters/SealevelTokenAdapter.js +5 -6
  115. package/dist/token/adapters/SealevelTokenAdapter.js.map +1 -1
  116. package/dist/token/adapters/StarknetTokenAdapter.d.ts +2 -2
  117. package/dist/token/adapters/StarknetTokenAdapter.d.ts.map +1 -1
  118. package/dist/token/adapters/StarknetTokenAdapter.js +6 -6
  119. package/dist/token/adapters/StarknetTokenAdapter.js.map +1 -1
  120. package/dist/token/config.d.ts +7 -2
  121. package/dist/token/config.d.ts.map +1 -1
  122. package/dist/token/config.js +6 -2
  123. package/dist/token/config.js.map +1 -1
  124. package/dist/token/contracts.d.ts +7 -2
  125. package/dist/token/contracts.d.ts.map +1 -1
  126. package/dist/token/contracts.js +13 -2
  127. package/dist/token/contracts.js.map +1 -1
  128. package/dist/token/deploy.d.ts +7 -3
  129. package/dist/token/deploy.d.ts.map +1 -1
  130. package/dist/token/deploy.js +141 -16
  131. package/dist/token/deploy.js.map +1 -1
  132. package/dist/token/types.d.ts +19993 -1868
  133. package/dist/token/types.d.ts.map +1 -1
  134. package/dist/token/types.js +98 -3
  135. package/dist/token/types.js.map +1 -1
  136. package/dist/token/types.test.js +47 -1
  137. package/dist/token/types.test.js.map +1 -1
  138. package/dist/utils/contract.d.ts +2 -0
  139. package/dist/utils/contract.d.ts.map +1 -0
  140. package/dist/utils/contract.js +5 -0
  141. package/dist/utils/contract.js.map +1 -0
  142. package/dist/warp/WarpCore.d.ts +20 -10
  143. package/dist/warp/WarpCore.d.ts.map +1 -1
  144. package/dist/warp/WarpCore.js +111 -38
  145. package/dist/warp/WarpCore.js.map +1 -1
  146. package/dist/warp/WarpCore.test.js +17 -8
  147. package/dist/warp/WarpCore.test.js.map +1 -1
  148. package/dist/warp/types.d.ts +1 -0
  149. package/dist/warp/types.d.ts.map +1 -1
  150. package/package.json +6 -6
@@ -4,18 +4,19 @@ import { ethers } from 'ethers';
4
4
  import hre from 'hardhat';
5
5
  import sinon from 'sinon';
6
6
  import { UINT_256_MAX } from 'starknet';
7
- import { CONTRACTS_PACKAGE_VERSION, ERC20Test__factory, ERC4626Test__factory, HypERC20__factory, HypERC4626Collateral__factory, HypNative__factory, MailboxClient__factory, Mailbox__factory, MovableCollateralRouter__factory, } from '@hyperlane-xyz/core';
8
- import { EvmIsmModule, HookType, IsmType, TestChainName, proxyAdmin, proxyImplementation, serializeContracts, } from '@hyperlane-xyz/sdk';
9
- import { addressToBytes32, assert, deepCopy, eqAddress, normalizeAddressEvm, randomInt, } from '@hyperlane-xyz/utils';
7
+ import { CONTRACTS_PACKAGE_VERSION, ERC20Test__factory, ERC4626Test__factory, HypERC20__factory, HypERC4626Collateral__factory, HypNative__factory, MailboxClient__factory, Mailbox__factory, MockEverclearAdapter__factory, MovableCollateralRouter__factory, } from '@hyperlane-xyz/core';
8
+ import { EvmIsmModule, HookType, IsmType, TestChainName, TokenFeeType, proxyAdmin, proxyImplementation, serializeContracts, } from '@hyperlane-xyz/sdk';
9
+ import { addressToBytes32, assert, deepCopy, eqAddress, normalizeAddressEvm, objMap, randomInt, } from '@hyperlane-xyz/utils';
10
10
  import { TestCoreDeployer } from '../core/TestCoreDeployer.js';
11
11
  import { HyperlaneProxyFactoryDeployer } from '../deploy/HyperlaneProxyFactoryDeployer.js';
12
+ import { BPS } from '../fee/EvmTokenFeeReader.hardhat-test.js';
12
13
  import { HyperlaneIsmFactory } from '../ism/HyperlaneIsmFactory.js';
13
14
  import { MultiProvider } from '../providers/MultiProvider.js';
14
15
  import { randomAddress } from '../test/testUtils.js';
15
16
  import { normalizeConfig } from '../utils/ism.js';
16
17
  import { EvmERC20WarpModule } from './EvmERC20WarpModule.js';
17
18
  import { TokenType, isMovableCollateralTokenType, } from './config.js';
18
- import { HypTokenRouterConfigSchema, derivedHookAddress, isMovableCollateralTokenConfig, } from './types.js';
19
+ import { HypTokenRouterConfigSchema, derivedHookAddress, isEverclearTokenBridgeConfig, isMovableCollateralTokenConfig, } from './types.js';
19
20
  chai.use(chaiAsPromised);
20
21
  const { expect } = chai;
21
22
  const randomRemoteRouters = (n) => {
@@ -32,6 +33,7 @@ describe('EvmERC20WarpHyperlaneModule', async () => {
32
33
  const TOKEN_SUPPLY = '100000000000000000000';
33
34
  const TOKEN_DECIMALS = 18;
34
35
  const chain = TestChainName.test4;
36
+ const domainId = 31337;
35
37
  let mailbox;
36
38
  let ismAddress;
37
39
  let ismFactory;
@@ -41,6 +43,9 @@ describe('EvmERC20WarpHyperlaneModule', async () => {
41
43
  let vaultFactory;
42
44
  let vault;
43
45
  let token;
46
+ let feeToken;
47
+ let everclearBridgeAdapterMockFactory;
48
+ let everclearBridgeAdapterMock;
44
49
  let signer;
45
50
  let multiProvider;
46
51
  let coreApp;
@@ -66,13 +71,21 @@ describe('EvmERC20WarpHyperlaneModule', async () => {
66
71
  routerConfigMap = coreApp.getRouterConfig(signer.address);
67
72
  erc20Factory = new ERC20Test__factory(signer);
68
73
  token = await erc20Factory.deploy(TOKEN_NAME, TOKEN_NAME, TOKEN_SUPPLY, TOKEN_DECIMALS);
74
+ feeToken = await erc20Factory.deploy(TOKEN_NAME, TOKEN_NAME, TOKEN_SUPPLY, TOKEN_DECIMALS);
69
75
  vaultFactory = new ERC4626Test__factory(signer);
70
76
  vault = await vaultFactory.deploy(token.address, TOKEN_NAME, TOKEN_NAME);
71
77
  baseConfig = routerConfigMap[chain];
72
78
  mailbox = Mailbox__factory.connect(baseConfig.mailbox, signer);
73
79
  ismAddress = await mailbox.defaultIsm();
80
+ everclearBridgeAdapterMockFactory = new MockEverclearAdapter__factory(signer);
81
+ everclearBridgeAdapterMock =
82
+ await everclearBridgeAdapterMockFactory.deploy();
74
83
  });
75
84
  const movableCollateralTypes = Object.values(TokenType).filter(isMovableCollateralTokenType);
85
+ const everclearTokenBridgeTypes = [
86
+ TokenType.ethEverclear,
87
+ TokenType.collateralEverclear,
88
+ ];
76
89
  const assertAllowedRebalancers = async (evmERC20WarpModule, expectedRebalancers) => {
77
90
  const currentConfig = await evmERC20WarpModule.read();
78
91
  if (isMovableCollateralTokenConfig(currentConfig)) {
@@ -89,18 +102,6 @@ describe('EvmERC20WarpHyperlaneModule', async () => {
89
102
  token: token.address,
90
103
  allowedRebalancers,
91
104
  },
92
- [TokenType.collateralVault]: {
93
- ...baseConfig,
94
- type: TokenType.collateralVault,
95
- token: vault.address,
96
- allowedRebalancers,
97
- },
98
- [TokenType.collateralVaultRebase]: {
99
- ...baseConfig,
100
- type: TokenType.collateralVaultRebase,
101
- token: vault.address,
102
- allowedRebalancers,
103
- },
104
105
  [TokenType.native]: {
105
106
  ...baseConfig,
106
107
  type: TokenType.native,
@@ -113,6 +114,42 @@ describe('EvmERC20WarpHyperlaneModule', async () => {
113
114
  },
114
115
  };
115
116
  };
117
+ const getEverclearTokenBridgeTokenConfig = () => {
118
+ const chainId = multiProvider.getChainId(chain);
119
+ const everclearFeeParams = {
120
+ [chainId]: {
121
+ deadline: Date.now(),
122
+ fee: randomInt(1000),
123
+ signature: '0x',
124
+ },
125
+ };
126
+ // Need to "enroll" otherwise the fee won't be set
127
+ const remoteRouters = {
128
+ [chainId]: {
129
+ address: randomAddress(),
130
+ },
131
+ };
132
+ return {
133
+ [TokenType.collateralEverclear]: {
134
+ type: TokenType.collateralEverclear,
135
+ token: token.address,
136
+ ...baseConfig,
137
+ everclearBridgeAddress: everclearBridgeAdapterMock.address,
138
+ everclearFeeParams,
139
+ outputAssets: {},
140
+ remoteRouters,
141
+ },
142
+ [TokenType.ethEverclear]: {
143
+ type: TokenType.ethEverclear,
144
+ wethAddress: token.address,
145
+ ...baseConfig,
146
+ everclearBridgeAddress: everclearBridgeAdapterMock.address,
147
+ everclearFeeParams,
148
+ outputAssets: {},
149
+ remoteRouters,
150
+ },
151
+ };
152
+ };
116
153
  it('should create with a collateral config', async () => {
117
154
  const config = {
118
155
  ...baseConfig,
@@ -233,6 +270,66 @@ describe('EvmERC20WarpHyperlaneModule', async () => {
233
270
  await assertAllowedRebalancers(evmERC20WarpModule, expectedRebalancers);
234
271
  });
235
272
  }
273
+ for (const tokenType of everclearTokenBridgeTypes) {
274
+ it(`should create ${tokenType} token`, async () => {
275
+ const config = getEverclearTokenBridgeTokenConfig()[tokenType];
276
+ // Deploy using WarpModule
277
+ const evmERC20WarpModule = await EvmERC20WarpModule.create({
278
+ chain,
279
+ config,
280
+ multiProvider,
281
+ proxyFactoryFactories: ismFactoryAddresses,
282
+ });
283
+ const currentConfig = await evmERC20WarpModule.read();
284
+ assert(isEverclearTokenBridgeConfig(currentConfig), `Expected token of type ${tokenType}`);
285
+ expect(currentConfig.everclearBridgeAddress).to.deep.equal(config.everclearBridgeAddress);
286
+ expect(currentConfig.everclearFeeParams).to.deep.equal(config.everclearFeeParams);
287
+ });
288
+ it(`should deploy with multiple output assets and fee setting when the token is of type ${tokenType}`, async () => {
289
+ const baseConfig = getEverclearTokenBridgeTokenConfig()[tokenType];
290
+ const domainId1 = randomInt(100, 10);
291
+ const domainId2 = randomInt(1000, 100);
292
+ const updatedConfig = {
293
+ ...baseConfig,
294
+ remoteRouters: {
295
+ [domainId1]: {
296
+ address: randomAddress(),
297
+ },
298
+ [domainId2]: {
299
+ address: randomAddress(),
300
+ },
301
+ },
302
+ everclearFeeParams: {
303
+ [domainId1]: {
304
+ signature: '0x10',
305
+ deadline: Date.now(),
306
+ fee: randomInt(100),
307
+ },
308
+ [domainId2]: {
309
+ signature: '0x10',
310
+ deadline: Date.now(),
311
+ fee: randomInt(100),
312
+ },
313
+ },
314
+ outputAssets: {
315
+ [domainId1]: addressToBytes32(randomAddress()),
316
+ [domainId2]: addressToBytes32(randomAddress()),
317
+ },
318
+ };
319
+ // Deploy using WarpModule
320
+ const evmERC20WarpModule = await EvmERC20WarpModule.create({
321
+ chain,
322
+ config: updatedConfig,
323
+ multiProvider,
324
+ proxyFactoryFactories: ismFactoryAddresses,
325
+ });
326
+ const currentConfig = await evmERC20WarpModule.read();
327
+ assert(isEverclearTokenBridgeConfig(currentConfig), `Expected token of type ${tokenType}`);
328
+ expect(currentConfig.everclearBridgeAddress).to.deep.equal(updatedConfig.everclearBridgeAddress);
329
+ expect(currentConfig.everclearFeeParams).to.deep.equal(updatedConfig.everclearFeeParams);
330
+ expect(currentConfig.outputAssets).to.deep.equal(updatedConfig.outputAssets);
331
+ });
332
+ }
236
333
  describe(EvmERC20WarpModule.prototype.update.name, async () => {
237
334
  const owner = randomAddress();
238
335
  const ismConfigToUpdate = [
@@ -687,7 +784,6 @@ describe('EvmERC20WarpHyperlaneModule', async () => {
687
784
  });
688
785
  it(`should add the specified addresses as rebalancing bridges for tokens of type "${tokenType}"`, async () => {
689
786
  const movableTokenConfigs = getMovableTokenConfig();
690
- const domainId = 31337;
691
787
  const config = {
692
788
  ...movableTokenConfigs[tokenType],
693
789
  remoteRouters: {
@@ -709,7 +805,7 @@ describe('EvmERC20WarpHyperlaneModule', async () => {
709
805
  [domainId]: [
710
806
  {
711
807
  bridge: allowedBridgeToAdd,
712
- approvedTokens: [token.address],
808
+ approvedTokens: [feeToken.address],
713
809
  },
714
810
  ],
715
811
  },
@@ -720,11 +816,10 @@ describe('EvmERC20WarpHyperlaneModule', async () => {
720
816
  const warpTokenInstance = MovableCollateralRouter__factory.connect(evmERC20WarpModule.serialize().deployedTokenRoute, signer);
721
817
  const check = await warpTokenInstance.callStatic.allowedBridges(domainId);
722
818
  expect(check[0]).to.eql(allowedBridgeToAdd);
723
- const allowance = await token.callStatic.allowance(evmERC20WarpModule.serialize().deployedTokenRoute, allowedBridgeToAdd);
819
+ const allowance = await feeToken.callStatic.allowance(evmERC20WarpModule.serialize().deployedTokenRoute, allowedBridgeToAdd);
724
820
  expect(allowance.toBigInt() === UINT_256_MAX).to.be.true;
725
821
  });
726
822
  it(`should remove rebalancing bridges for tokens of type "${tokenType}"`, async () => {
727
- const domainId = 31337;
728
823
  const allowedBridgeToAdd = normalizeAddressEvm(randomAddress());
729
824
  const config = HypTokenRouterConfigSchema.parse({
730
825
  ...getMovableTokenConfig()[tokenType],
@@ -737,7 +832,7 @@ describe('EvmERC20WarpHyperlaneModule', async () => {
737
832
  [domainId]: [
738
833
  {
739
834
  bridge: allowedBridgeToAdd,
740
- approvedTokens: [token.address],
835
+ approvedTokens: [feeToken.address],
741
836
  },
742
837
  ],
743
838
  },
@@ -763,7 +858,6 @@ describe('EvmERC20WarpHyperlaneModule', async () => {
763
858
  });
764
859
  it(`should not generate update transactions for the allowed rebalancing bridges if the address is in a different casing when token is of type "${tokenType}"`, async () => {
765
860
  const movableTokenConfigs = getMovableTokenConfig();
766
- const domainId = 31337;
767
861
  const allowedBridgeToAdd = normalizeAddressEvm(randomAddress());
768
862
  const config = HypTokenRouterConfigSchema.parse({
769
863
  ...movableTokenConfigs[tokenType],
@@ -776,7 +870,7 @@ describe('EvmERC20WarpHyperlaneModule', async () => {
776
870
  [domainId]: [
777
871
  {
778
872
  bridge: allowedBridgeToAdd,
779
- approvedTokens: [token.address],
873
+ approvedTokens: [feeToken.address],
780
874
  },
781
875
  ],
782
876
  },
@@ -793,7 +887,7 @@ describe('EvmERC20WarpHyperlaneModule', async () => {
793
887
  [domainId]: [
794
888
  {
795
889
  bridge: allowedBridgeToAdd.toLowerCase(),
796
- approvedTokens: [token.address],
890
+ approvedTokens: [feeToken.address],
797
891
  },
798
892
  ],
799
893
  },
@@ -809,7 +903,7 @@ describe('EvmERC20WarpHyperlaneModule', async () => {
809
903
  config: {
810
904
  ...config,
811
905
  remoteRouters: {
812
- 31337: {
906
+ [domainId]: {
813
907
  address: remoteRouter,
814
908
  },
815
909
  },
@@ -838,6 +932,276 @@ describe('EvmERC20WarpHyperlaneModule', async () => {
838
932
  }
839
933
  });
840
934
  }
935
+ for (const tokenType of everclearTokenBridgeTypes) {
936
+ it(`should add destination outputAssets if the token is of type ${tokenType}`, async () => {
937
+ const config = getEverclearTokenBridgeTokenConfig()[tokenType];
938
+ const evmERC20WarpModule = await EvmERC20WarpModule.create({
939
+ chain,
940
+ config,
941
+ multiProvider,
942
+ proxyFactoryFactories: ismFactoryAddresses,
943
+ });
944
+ const remoteToken = randomAddress();
945
+ const txs = await evmERC20WarpModule.update({
946
+ ...config,
947
+ outputAssets: {
948
+ [domainId]: remoteToken,
949
+ },
950
+ });
951
+ expect(txs.length).to.equal(1);
952
+ await sendTxs(txs);
953
+ const currentConfig = await evmERC20WarpModule.read();
954
+ assert(isEverclearTokenBridgeConfig(currentConfig), `Expected token of type ${tokenType}`);
955
+ expect(currentConfig.outputAssets[domainId]).to.equal(addressToBytes32(remoteToken));
956
+ });
957
+ it(`should overwrite a destination outputAssets if the token is of type ${tokenType} and a destination token already exists for the given destination`, async () => {
958
+ const config = getEverclearTokenBridgeTokenConfig()[tokenType];
959
+ const evmERC20WarpModule = await EvmERC20WarpModule.create({
960
+ chain,
961
+ config: {
962
+ ...config,
963
+ outputAssets: {
964
+ [domainId]: randomAddress(),
965
+ },
966
+ },
967
+ multiProvider,
968
+ proxyFactoryFactories: ismFactoryAddresses,
969
+ });
970
+ const expectedRemoteOuputToken = randomAddress();
971
+ const txs = await evmERC20WarpModule.update({
972
+ ...config,
973
+ outputAssets: {
974
+ [domainId]: expectedRemoteOuputToken,
975
+ },
976
+ });
977
+ expect(txs.length).to.equal(1);
978
+ await sendTxs(txs);
979
+ const currentConfig = await evmERC20WarpModule.read();
980
+ assert(isEverclearTokenBridgeConfig(currentConfig), `Expected token of type ${tokenType}`);
981
+ expect(currentConfig.outputAssets[domainId]).to.equal(addressToBytes32(expectedRemoteOuputToken));
982
+ });
983
+ it(`should remove destination outputAssets if the token is of type ${tokenType} and a config is set`, async () => {
984
+ const config = getEverclearTokenBridgeTokenConfig()[tokenType];
985
+ const evmERC20WarpModule = await EvmERC20WarpModule.create({
986
+ chain,
987
+ config: {
988
+ ...config,
989
+ outputAssets: {
990
+ [domainId]: randomAddress(),
991
+ },
992
+ },
993
+ multiProvider,
994
+ proxyFactoryFactories: ismFactoryAddresses,
995
+ });
996
+ const txs = await evmERC20WarpModule.update({
997
+ ...config,
998
+ outputAssets: {},
999
+ });
1000
+ expect(txs.length).to.equal(1);
1001
+ await sendTxs(txs);
1002
+ const currentConfig = await evmERC20WarpModule.read();
1003
+ assert(isEverclearTokenBridgeConfig(currentConfig), `Expected token of type ${tokenType}`);
1004
+ expect(currentConfig.outputAssets).to.deep.equal({});
1005
+ });
1006
+ it(`should remove 1 outputAsset and leave the others if the token is of type ${tokenType}`, async () => {
1007
+ const config = getEverclearTokenBridgeTokenConfig()[tokenType];
1008
+ const numOfRouters = randomInt(10, 0);
1009
+ const remoteRoutersToKeep = randomRemoteRouters(numOfRouters);
1010
+ const initialRemoteRouters = {
1011
+ [domainId]: {
1012
+ address: randomAddress(),
1013
+ },
1014
+ ...remoteRoutersToKeep,
1015
+ };
1016
+ const outputAssetsToKeep = objMap(remoteRoutersToKeep, (_domainId, _) => randomAddress());
1017
+ const expectedOutputAssets = objMap(outputAssetsToKeep, (_domainId, address) => addressToBytes32(address));
1018
+ const initialOutputAddresses = {
1019
+ [domainId]: randomAddress(),
1020
+ ...outputAssetsToKeep,
1021
+ };
1022
+ const evmERC20WarpModule = await EvmERC20WarpModule.create({
1023
+ chain,
1024
+ config: {
1025
+ ...config,
1026
+ remoteRouters: initialRemoteRouters,
1027
+ outputAssets: initialOutputAddresses,
1028
+ },
1029
+ multiProvider,
1030
+ proxyFactoryFactories: ismFactoryAddresses,
1031
+ });
1032
+ const txs = await evmERC20WarpModule.update({
1033
+ ...config,
1034
+ remoteRouters: initialRemoteRouters,
1035
+ outputAssets: outputAssetsToKeep,
1036
+ });
1037
+ expect(txs.length).to.equal(1);
1038
+ await sendTxs(txs);
1039
+ const currentConfig = await evmERC20WarpModule.read();
1040
+ assert(isEverclearTokenBridgeConfig(currentConfig), `Expected token of type ${tokenType}`);
1041
+ expect(currentConfig.outputAssets).to.deep.equal(expectedOutputAssets);
1042
+ });
1043
+ it(`should update the fee params if the token is of type ${tokenType}`, async () => {
1044
+ const config = getEverclearTokenBridgeTokenConfig()[tokenType];
1045
+ const evmERC20WarpModule = await EvmERC20WarpModule.create({
1046
+ chain,
1047
+ config,
1048
+ multiProvider,
1049
+ proxyFactoryFactories: ismFactoryAddresses,
1050
+ });
1051
+ const expectedEverclearFeeParams = {
1052
+ [domainId]: {
1053
+ deadline: Date.now(),
1054
+ fee: randomInt(100000000, 100),
1055
+ signature: '0x42',
1056
+ },
1057
+ };
1058
+ const txs = await evmERC20WarpModule.update({
1059
+ ...config,
1060
+ everclearFeeParams: expectedEverclearFeeParams,
1061
+ });
1062
+ expect(txs.length).to.equal(1);
1063
+ await sendTxs(txs);
1064
+ const currentConfig = await evmERC20WarpModule.read();
1065
+ assert(isEverclearTokenBridgeConfig(currentConfig), `Expected token of type ${tokenType}`);
1066
+ expect(currentConfig.everclearFeeParams).to.deep.equal(expectedEverclearFeeParams);
1067
+ });
1068
+ it(`should not generate any update transactions for the fee params if the config did not change and the token is of type ${tokenType}`, async () => {
1069
+ const config = getEverclearTokenBridgeTokenConfig()[tokenType];
1070
+ const expectedEverclearFeeParams = config.everclearFeeParams;
1071
+ const evmERC20WarpModule = await EvmERC20WarpModule.create({
1072
+ chain,
1073
+ config,
1074
+ multiProvider,
1075
+ proxyFactoryFactories: ismFactoryAddresses,
1076
+ });
1077
+ const txs = await evmERC20WarpModule.update(config);
1078
+ expect(txs.length).to.equal(0);
1079
+ const currentConfig = await evmERC20WarpModule.read();
1080
+ assert(isEverclearTokenBridgeConfig(currentConfig), `Expected token of type ${tokenType}`);
1081
+ expect(currentConfig.everclearFeeParams).to.deep.equal(expectedEverclearFeeParams);
1082
+ });
1083
+ it(`should remove everclear fee params if the token is of type ${tokenType}`, async () => {
1084
+ const config = getEverclearTokenBridgeTokenConfig()[tokenType];
1085
+ const evmERC20WarpModule = await EvmERC20WarpModule.create({
1086
+ chain,
1087
+ config,
1088
+ multiProvider,
1089
+ proxyFactoryFactories: ismFactoryAddresses,
1090
+ });
1091
+ // Remove the fee params for the enrolled domain
1092
+ const txs = await evmERC20WarpModule.update({
1093
+ ...config,
1094
+ everclearFeeParams: {},
1095
+ });
1096
+ expect(txs.length).to.equal(1);
1097
+ await sendTxs(txs);
1098
+ const currentConfig = await evmERC20WarpModule.read();
1099
+ assert(isEverclearTokenBridgeConfig(currentConfig), `Expected token of type ${tokenType}`);
1100
+ expect(currentConfig.everclearFeeParams).to.deep.equal({});
1101
+ });
1102
+ it(`should remove 1 everclear fee param and leave the others if the token is of type ${tokenType}`, async () => {
1103
+ const config = getEverclearTokenBridgeTokenConfig()[tokenType];
1104
+ const numOfRouters = randomInt(10, 0);
1105
+ const remoteRoutersToKeep = randomRemoteRouters(numOfRouters);
1106
+ const initialRemoteRouters = {
1107
+ [domainId]: {
1108
+ address: randomAddress(),
1109
+ },
1110
+ ...remoteRoutersToKeep,
1111
+ };
1112
+ const feeParamsToKeep = objMap(remoteRoutersToKeep, (_domainId, _) => ({
1113
+ deadline: Date.now(),
1114
+ fee: randomInt(1000),
1115
+ signature: '0x',
1116
+ }));
1117
+ const initialFeeParams = {
1118
+ [domainId]: {
1119
+ deadline: Date.now(),
1120
+ fee: randomInt(1000),
1121
+ signature: '0x',
1122
+ },
1123
+ ...feeParamsToKeep,
1124
+ };
1125
+ const evmERC20WarpModule = await EvmERC20WarpModule.create({
1126
+ chain,
1127
+ config: {
1128
+ ...config,
1129
+ remoteRouters: initialRemoteRouters,
1130
+ everclearFeeParams: initialFeeParams,
1131
+ },
1132
+ multiProvider,
1133
+ proxyFactoryFactories: ismFactoryAddresses,
1134
+ });
1135
+ const txs = await evmERC20WarpModule.update({
1136
+ ...config,
1137
+ remoteRouters: initialRemoteRouters,
1138
+ everclearFeeParams: feeParamsToKeep,
1139
+ });
1140
+ expect(txs.length).to.equal(1);
1141
+ await sendTxs(txs);
1142
+ const currentConfig = await evmERC20WarpModule.read();
1143
+ assert(isEverclearTokenBridgeConfig(currentConfig), `Expected token of type ${tokenType}`);
1144
+ expect(currentConfig.everclearFeeParams).to.deep.equal(feeParamsToKeep);
1145
+ });
1146
+ it(`should remove all everclear fee params except for explicitly kept domains if the token is of type ${tokenType}`, async () => {
1147
+ const config = getEverclearTokenBridgeTokenConfig()[tokenType];
1148
+ const domainId1 = randomInt(100, 10);
1149
+ const domainId2 = randomInt(1000, 100);
1150
+ const domainId3 = randomInt(10000, 1000);
1151
+ const initialRemoteRouters = {
1152
+ [domainId1]: {
1153
+ address: randomAddress(),
1154
+ },
1155
+ [domainId2]: {
1156
+ address: randomAddress(),
1157
+ },
1158
+ [domainId3]: {
1159
+ address: randomAddress(),
1160
+ },
1161
+ };
1162
+ const initialFeeParams = {
1163
+ [domainId1]: {
1164
+ deadline: Date.now(),
1165
+ fee: randomInt(1000),
1166
+ signature: '0x10',
1167
+ },
1168
+ [domainId2]: {
1169
+ deadline: Date.now(),
1170
+ fee: randomInt(1000),
1171
+ signature: '0x20',
1172
+ },
1173
+ [domainId3]: {
1174
+ deadline: Date.now(),
1175
+ fee: randomInt(1000),
1176
+ signature: '0x30',
1177
+ },
1178
+ };
1179
+ const evmERC20WarpModule = await EvmERC20WarpModule.create({
1180
+ chain,
1181
+ config: {
1182
+ ...config,
1183
+ remoteRouters: initialRemoteRouters,
1184
+ everclearFeeParams: initialFeeParams,
1185
+ },
1186
+ multiProvider,
1187
+ proxyFactoryFactories: ismFactoryAddresses,
1188
+ });
1189
+ // Keep only domainId2
1190
+ const expectedFeeParams = {
1191
+ [domainId2]: initialFeeParams[domainId2],
1192
+ };
1193
+ const txs = await evmERC20WarpModule.update({
1194
+ ...config,
1195
+ remoteRouters: initialRemoteRouters,
1196
+ everclearFeeParams: expectedFeeParams,
1197
+ });
1198
+ expect(txs.length).to.equal(2);
1199
+ await sendTxs(txs);
1200
+ const currentConfig = await evmERC20WarpModule.read();
1201
+ assert(isEverclearTokenBridgeConfig(currentConfig), `Expected token of type ${tokenType}`);
1202
+ expect(currentConfig.everclearFeeParams).to.deep.equal(expectedFeeParams);
1203
+ });
1204
+ }
841
1205
  it('Should deploy and upgrade a new warp route', async () => {
842
1206
  const domain = 3;
843
1207
  const config = {
@@ -915,6 +1279,32 @@ describe('EvmERC20WarpHyperlaneModule', async () => {
915
1279
  // Assert
916
1280
  expect(updatedConfig.contractVersion).to.eq(CONTRACTS_PACKAGE_VERSION);
917
1281
  });
1282
+ it('should deploy a new fee if one does not exist', async () => {
1283
+ const config = {
1284
+ ...baseConfig,
1285
+ type: TokenType.native,
1286
+ };
1287
+ // Deploy using WarpModule
1288
+ const evmERC20WarpModule = await EvmERC20WarpModule.create({
1289
+ chain,
1290
+ config,
1291
+ multiProvider,
1292
+ proxyFactoryFactories: ismFactoryAddresses,
1293
+ });
1294
+ const actualConfig = await evmERC20WarpModule.read();
1295
+ const expectedConfig = HypTokenRouterConfigSchema.parse({
1296
+ ...actualConfig,
1297
+ tokenFee: {
1298
+ type: TokenFeeType.LinearFee,
1299
+ maxFee: 1000000000,
1300
+ halfAmount: 500000000,
1301
+ bps: BPS,
1302
+ },
1303
+ });
1304
+ await sendTxs(await evmERC20WarpModule.update(expectedConfig));
1305
+ const updatedConfig = await evmERC20WarpModule.read();
1306
+ expect(updatedConfig.tokenFee?.type).to.equal(expectedConfig.tokenFee?.type);
1307
+ });
918
1308
  });
919
1309
  });
920
1310
  //# sourceMappingURL=EvmERC20WarpModule.hardhat-test.js.map