@hyperlane-xyz/sdk 41.3.1 → 43.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ccip/consts.d.ts.map +1 -1
- package/dist/ccip/consts.js +20 -0
- package/dist/ccip/consts.js.map +1 -1
- package/dist/consts/multisigIsm.d.ts.map +1 -1
- package/dist/consts/multisigIsm.js +32 -0
- package/dist/consts/multisigIsm.js.map +1 -1
- package/dist/contracts/contracts.d.ts.map +1 -1
- package/dist/contracts/contracts.js +15 -0
- package/dist/contracts/contracts.js.map +1 -1
- package/dist/contracts/contracts.test.d.ts +2 -0
- package/dist/contracts/contracts.test.d.ts.map +1 -0
- package/dist/contracts/contracts.test.js +88 -0
- package/dist/contracts/contracts.test.js.map +1 -0
- package/dist/core/types.d.ts +48 -4158
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +21 -3
- package/dist/core/types.js.map +1 -1
- package/dist/core/types.test.js +58 -0
- package/dist/core/types.test.js.map +1 -1
- package/dist/deploy/HyperlaneDeployer.js +1 -1
- package/dist/deploy/proxy.d.ts +8 -40
- package/dist/deploy/proxy.d.ts.map +1 -1
- package/dist/deploy/proxy.js +4 -4
- package/dist/deploy/proxy.js.map +1 -1
- package/dist/deploy/types.d.ts +1 -19
- package/dist/deploy/types.d.ts.map +1 -1
- package/dist/deploy/warp.d.ts +119 -3
- package/dist/deploy/warp.d.ts.map +1 -1
- package/dist/deploy/warp.js +696 -33
- package/dist/deploy/warp.js.map +1 -1
- package/dist/deploy/warp.test.d.ts +2 -0
- package/dist/deploy/warp.test.d.ts.map +1 -0
- package/dist/deploy/warp.test.js +358 -0
- package/dist/deploy/warp.test.js.map +1 -0
- package/dist/deploy/warpHybridPlan.d.ts +104 -0
- package/dist/deploy/warpHybridPlan.d.ts.map +1 -0
- package/dist/deploy/warpHybridPlan.js +178 -0
- package/dist/deploy/warpHybridPlan.js.map +1 -0
- package/dist/deploy/warpHybridPlan.test.d.ts +2 -0
- package/dist/deploy/warpHybridPlan.test.d.ts.map +1 -0
- package/dist/deploy/warpHybridPlan.test.js +141 -0
- package/dist/deploy/warpHybridPlan.test.js.map +1 -0
- package/dist/fee/EvmTokenFeeDeployer.d.ts.map +1 -1
- package/dist/fee/EvmTokenFeeDeployer.hardhat-test.js +68 -0
- package/dist/fee/EvmTokenFeeDeployer.hardhat-test.js.map +1 -1
- package/dist/fee/EvmTokenFeeDeployer.js +18 -10
- package/dist/fee/EvmTokenFeeDeployer.js.map +1 -1
- package/dist/fee/EvmTokenFeeModule.d.ts.map +1 -1
- package/dist/fee/EvmTokenFeeModule.hardhat-test.js +18 -8
- package/dist/fee/EvmTokenFeeModule.hardhat-test.js.map +1 -1
- package/dist/fee/EvmTokenFeeModule.js +8 -1
- package/dist/fee/EvmTokenFeeModule.js.map +1 -1
- package/dist/fee/EvmTokenFeeReader.d.ts +2 -2
- package/dist/fee/EvmTokenFeeReader.d.ts.map +1 -1
- package/dist/fee/EvmTokenFeeReader.js.map +1 -1
- package/dist/fee/feeConfigMapping.d.ts.map +1 -1
- package/dist/fee/feeConfigMapping.js +1 -0
- package/dist/fee/feeConfigMapping.js.map +1 -1
- package/dist/fee/types.d.ts +147 -646
- package/dist/fee/types.d.ts.map +1 -1
- package/dist/fee/types.js +26 -17
- package/dist/fee/types.js.map +1 -1
- package/dist/fork/types.d.ts +125 -1924
- package/dist/fork/types.d.ts.map +1 -1
- package/dist/fork/types.js +3 -3
- package/dist/fork/types.js.map +1 -1
- package/dist/gas/oracle/types.d.ts +5 -56
- package/dist/gas/oracle/types.d.ts.map +1 -1
- package/dist/hook/EvmHookModule.d.ts +1 -1
- package/dist/hook/EvmHookModule.d.ts.map +1 -1
- package/dist/hook/EvmHookModule.hardhat-test.js +12 -1
- package/dist/hook/EvmHookModule.hardhat-test.js.map +1 -1
- package/dist/hook/EvmHookModule.js +19 -3
- package/dist/hook/EvmHookModule.js.map +1 -1
- package/dist/hook/EvmHookReader.d.ts +10 -0
- package/dist/hook/EvmHookReader.d.ts.map +1 -1
- package/dist/hook/EvmHookReader.js +92 -11
- package/dist/hook/EvmHookReader.js.map +1 -1
- package/dist/hook/EvmHookReader.test.js +155 -1
- package/dist/hook/EvmHookReader.test.js.map +1 -1
- package/dist/hook/HyperlaneHookDeployer.d.ts +12 -0
- package/dist/hook/HyperlaneHookDeployer.d.ts.map +1 -1
- package/dist/hook/HyperlaneHookDeployer.hardhat-test.d.ts +2 -0
- package/dist/hook/HyperlaneHookDeployer.hardhat-test.d.ts.map +1 -0
- package/dist/hook/HyperlaneHookDeployer.hardhat-test.js +322 -0
- package/dist/hook/HyperlaneHookDeployer.hardhat-test.js.map +1 -0
- package/dist/hook/HyperlaneHookDeployer.js +262 -5
- package/dist/hook/HyperlaneHookDeployer.js.map +1 -1
- package/dist/hook/types.d.ts +72 -2223
- package/dist/hook/types.d.ts.map +1 -1
- package/dist/hook/types.js +66 -10
- package/dist/hook/types.js.map +1 -1
- package/dist/hook/types.test.js +21 -1
- package/dist/hook/types.test.js.map +1 -1
- package/dist/hook/updates.d.ts +1 -0
- package/dist/hook/updates.d.ts.map +1 -1
- package/dist/hook/updates.js +2 -2
- package/dist/hook/updates.js.map +1 -1
- package/dist/hook/utils.d.ts +28 -1
- package/dist/hook/utils.d.ts.map +1 -1
- package/dist/hook/utils.js +89 -0
- package/dist/hook/utils.js.map +1 -1
- package/dist/ica/types.d.ts +35 -1570
- package/dist/ica/types.d.ts.map +1 -1
- package/dist/ica/types.js +1 -1
- package/dist/ica/types.js.map +1 -1
- package/dist/index.d.ts +7 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -6
- package/dist/index.js.map +1 -1
- package/dist/ism/EvmIsmModule.d.ts +29 -3
- package/dist/ism/EvmIsmModule.d.ts.map +1 -1
- package/dist/ism/EvmIsmModule.hardhat-test.js +512 -3
- package/dist/ism/EvmIsmModule.hardhat-test.js.map +1 -1
- package/dist/ism/EvmIsmModule.js +239 -21
- package/dist/ism/EvmIsmModule.js.map +1 -1
- package/dist/ism/EvmIsmReader.d.ts.map +1 -1
- package/dist/ism/EvmIsmReader.js +77 -1
- package/dist/ism/EvmIsmReader.js.map +1 -1
- package/dist/ism/EvmIsmReader.test.js +245 -4
- package/dist/ism/EvmIsmReader.test.js.map +1 -1
- package/dist/ism/HyperlaneIsmFactory.d.ts +17 -5
- package/dist/ism/HyperlaneIsmFactory.d.ts.map +1 -1
- package/dist/ism/HyperlaneIsmFactory.hardhat-test.js +431 -4
- package/dist/ism/HyperlaneIsmFactory.hardhat-test.js.map +1 -1
- package/dist/ism/HyperlaneIsmFactory.js +121 -11
- package/dist/ism/HyperlaneIsmFactory.js.map +1 -1
- package/dist/ism/delayedFlow.d.ts +31 -0
- package/dist/ism/delayedFlow.d.ts.map +1 -0
- package/dist/ism/delayedFlow.js +33 -0
- package/dist/ism/delayedFlow.js.map +1 -0
- package/dist/ism/types.d.ts +86 -237
- package/dist/ism/types.d.ts.map +1 -1
- package/dist/ism/types.js +270 -20
- package/dist/ism/types.js.map +1 -1
- package/dist/ism/types.test.js +433 -1
- package/dist/ism/types.test.js.map +1 -1
- package/dist/ism/utils.d.ts.map +1 -1
- package/dist/ism/utils.js +113 -3
- package/dist/ism/utils.js.map +1 -1
- package/dist/ism/utils.test.js +44 -0
- package/dist/ism/utils.test.js.map +1 -1
- package/dist/metadata/agentConfig.d.ts +537 -10384
- package/dist/metadata/agentConfig.d.ts.map +1 -1
- package/dist/metadata/agentConfig.js +14 -16
- package/dist/metadata/agentConfig.js.map +1 -1
- package/dist/metadata/chainMetadataTypes.d.ts +70 -4678
- package/dist/metadata/chainMetadataTypes.d.ts.map +1 -1
- package/dist/metadata/chainMetadataTypes.js +5 -5
- package/dist/metadata/chainMetadataTypes.js.map +1 -1
- package/dist/metadata/customZodTypes.d.ts +5 -5
- package/dist/metadata/customZodTypes.d.ts.map +1 -1
- package/dist/metadata/customZodTypes.js +4 -5
- package/dist/metadata/customZodTypes.js.map +1 -1
- package/dist/metadata/deploymentArtifacts.d.ts +1 -13
- package/dist/metadata/deploymentArtifacts.d.ts.map +1 -1
- package/dist/metadata/matchingList.d.ts +12 -40
- package/dist/metadata/matchingList.d.ts.map +1 -1
- package/dist/metadata/warpRouteConfig.d.ts +8 -114
- package/dist/metadata/warpRouteConfig.d.ts.map +1 -1
- package/dist/metadata/warpRouteConfig.js +3 -3
- package/dist/metadata/warpRouteConfig.js.map +1 -1
- package/dist/middleware/account/InterchainAccount.d.ts.map +1 -1
- package/dist/middleware/account/InterchainAccount.js +12 -8
- package/dist/middleware/account/InterchainAccount.js.map +1 -1
- package/dist/middleware/account/InterchainAccount.test.js +22 -3
- package/dist/middleware/account/InterchainAccount.test.js.map +1 -1
- package/dist/middleware/account/icaCalls.d.ts +13 -145
- package/dist/middleware/account/icaCalls.d.ts.map +1 -1
- package/dist/middleware/account/types.d.ts +11 -105
- package/dist/middleware/account/types.d.ts.map +1 -1
- package/dist/predicate/PredicateApiClient.d.ts +1 -11
- package/dist/predicate/PredicateApiClient.d.ts.map +1 -1
- package/dist/providers/MultiProvider.d.ts.map +1 -1
- package/dist/providers/MultiProvider.js +3 -2
- package/dist/providers/MultiProvider.js.map +1 -1
- package/dist/providers/MultiProviderAdapter.d.ts +3 -3
- package/dist/providers/MultiProviderAdapter.d.ts.map +1 -1
- package/dist/providers/MultiProviderAdapter.js +2 -1
- package/dist/providers/MultiProviderAdapter.js.map +1 -1
- package/dist/providers/SmartProvider/HyperlaneJsonRpcProvider.d.ts.map +1 -1
- package/dist/providers/SmartProvider/HyperlaneJsonRpcProvider.js +4 -0
- package/dist/providers/SmartProvider/HyperlaneJsonRpcProvider.js.map +1 -1
- package/dist/providers/transactionFeeEstimators.d.ts +16 -9
- package/dist/providers/transactionFeeEstimators.d.ts.map +1 -1
- package/dist/providers/transactionFeeEstimators.js +66 -17
- package/dist/providers/transactionFeeEstimators.js.map +1 -1
- package/dist/providers/transactionFeeEstimators.test.js +153 -1
- package/dist/providers/transactionFeeEstimators.test.js.map +1 -1
- package/dist/providers/transactions/submitter/builder/types.d.ts +13 -280
- package/dist/providers/transactions/submitter/builder/types.d.ts.map +1 -1
- package/dist/providers/transactions/submitter/builder/types.js +2 -4
- package/dist/providers/transactions/submitter/builder/types.js.map +1 -1
- package/dist/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.d.ts +2 -0
- package/dist/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.d.ts.map +1 -1
- package/dist/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.js +15 -7
- package/dist/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.js.map +1 -1
- package/dist/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.test.d.ts +2 -0
- package/dist/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.test.d.ts.map +1 -0
- package/dist/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.test.js +145 -0
- package/dist/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.test.js.map +1 -0
- package/dist/providers/transactions/submitter/ethersV5/EV5JsonRpcTxSubmitter.d.ts +14 -1
- package/dist/providers/transactions/submitter/ethersV5/EV5JsonRpcTxSubmitter.d.ts.map +1 -1
- package/dist/providers/transactions/submitter/ethersV5/EV5JsonRpcTxSubmitter.js +46 -5
- package/dist/providers/transactions/submitter/ethersV5/EV5JsonRpcTxSubmitter.js.map +1 -1
- package/dist/providers/transactions/submitter/ethersV5/EV5JsonRpcTxSubmitter.test.d.ts +2 -0
- package/dist/providers/transactions/submitter/ethersV5/EV5JsonRpcTxSubmitter.test.d.ts.map +1 -0
- package/dist/providers/transactions/submitter/ethersV5/EV5JsonRpcTxSubmitter.test.js +125 -0
- package/dist/providers/transactions/submitter/ethersV5/EV5JsonRpcTxSubmitter.test.js.map +1 -0
- package/dist/providers/transactions/submitter/ethersV5/types.d.ts +30 -102
- package/dist/providers/transactions/submitter/ethersV5/types.d.ts.map +1 -1
- package/dist/providers/transactions/submitter/ethersV5/types.js +3 -21
- package/dist/providers/transactions/submitter/ethersV5/types.js.map +1 -1
- package/dist/providers/transactions/submitter/types.d.ts +5 -51
- package/dist/providers/transactions/submitter/types.d.ts.map +1 -1
- package/dist/providers/transactions/types.d.ts +1 -9
- package/dist/providers/transactions/types.d.ts.map +1 -1
- package/dist/router/HyperlaneRouterDeployer.d.ts +3 -1
- package/dist/router/HyperlaneRouterDeployer.d.ts.map +1 -1
- package/dist/router/HyperlaneRouterDeployer.js +4 -2
- package/dist/router/HyperlaneRouterDeployer.js.map +1 -1
- package/dist/router/types.d.ts +33 -1824
- package/dist/router/types.d.ts.map +1 -1
- package/dist/router/types.js +4 -4
- package/dist/router/types.js.map +1 -1
- package/dist/rpc/evm/EvmEventLogsReader.d.ts +19 -27
- package/dist/rpc/evm/EvmEventLogsReader.d.ts.map +1 -1
- package/dist/rpc/evm/EvmEventLogsReader.js +23 -0
- package/dist/rpc/evm/EvmEventLogsReader.js.map +1 -1
- package/dist/rpc/evm/EvmEventLogsReader.test.js +53 -1
- package/dist/rpc/evm/EvmEventLogsReader.test.js.map +1 -1
- package/dist/signers/turnkeyClient.d.ts +1 -15
- package/dist/signers/turnkeyClient.d.ts.map +1 -1
- package/dist/test/testUtils.d.ts +1 -1
- package/dist/test/testUtils.d.ts.map +1 -1
- package/dist/test/testUtils.js +17 -0
- package/dist/test/testUtils.js.map +1 -1
- package/dist/test/testUtils.test.d.ts +2 -0
- package/dist/test/testUtils.test.d.ts.map +1 -0
- package/dist/test/testUtils.test.js +28 -0
- package/dist/test/testUtils.test.js.map +1 -0
- package/dist/timelock/types.d.ts +8 -32
- package/dist/timelock/types.d.ts.map +1 -1
- package/dist/token/EvmWarpModule.d.ts +44 -8
- package/dist/token/EvmWarpModule.d.ts.map +1 -1
- package/dist/token/EvmWarpModule.hardhat-test.js +574 -4
- package/dist/token/EvmWarpModule.hardhat-test.js.map +1 -1
- package/dist/token/EvmWarpModule.js +237 -25
- package/dist/token/EvmWarpModule.js.map +1 -1
- package/dist/token/EvmWarpRouteReader.d.ts.map +1 -1
- package/dist/token/EvmWarpRouteReader.js +36 -19
- package/dist/token/EvmWarpRouteReader.js.map +1 -1
- package/dist/token/EvmWarpRouteReader.test.js +219 -2
- package/dist/token/EvmWarpRouteReader.test.js.map +1 -1
- package/dist/token/EvmXERC20Reader.d.ts +9 -21
- package/dist/token/EvmXERC20Reader.d.ts.map +1 -1
- package/dist/token/EvmXERC20Reader.js +24 -48
- package/dist/token/EvmXERC20Reader.js.map +1 -1
- package/dist/token/EvmXERC20Reader.test.js +97 -0
- package/dist/token/EvmXERC20Reader.test.js.map +1 -1
- package/dist/token/ITokenMetadata.d.ts +12 -130
- package/dist/token/ITokenMetadata.d.ts.map +1 -1
- package/dist/token/ITokenMetadata.js +2 -2
- package/dist/token/ITokenMetadata.js.map +1 -1
- package/dist/token/TokenConnection.d.ts +3 -35
- package/dist/token/TokenConnection.d.ts.map +1 -1
- package/dist/token/configUtils.d.ts +17 -7
- package/dist/token/configUtils.d.ts.map +1 -1
- package/dist/token/configUtils.js +124 -0
- package/dist/token/configUtils.js.map +1 -1
- package/dist/token/configUtils.test.js +212 -11
- package/dist/token/configUtils.test.js.map +1 -1
- package/dist/token/deploy.d.ts +3 -1
- package/dist/token/deploy.d.ts.map +1 -1
- package/dist/token/deploy.hardhat-test.js +617 -6
- package/dist/token/deploy.hardhat-test.js.map +1 -1
- package/dist/token/deploy.js +25 -6
- package/dist/token/deploy.js.map +1 -1
- package/dist/token/types.d.ts +4373 -25929
- package/dist/token/types.d.ts.map +1 -1
- package/dist/token/types.js +10 -12
- package/dist/token/types.js.map +1 -1
- package/dist/token/types.test.js +48 -0
- package/dist/token/types.test.js.map +1 -1
- package/dist/token/warpCheck.d.ts.map +1 -1
- package/dist/token/warpCheck.js +36 -1
- package/dist/token/warpCheck.js.map +1 -1
- package/dist/token/xerc20-abi.d.ts +31 -0
- package/dist/token/xerc20-abi.d.ts.map +1 -1
- package/dist/token/xerc20-abi.js +40 -0
- package/dist/token/xerc20-abi.js.map +1 -1
- package/dist/token/xerc20-limits.d.ts +63 -0
- package/dist/token/xerc20-limits.d.ts.map +1 -0
- package/dist/token/xerc20-limits.js +80 -0
- package/dist/token/xerc20-limits.js.map +1 -0
- package/dist/token/xerc20.d.ts +30 -1
- package/dist/token/xerc20.d.ts.map +1 -1
- package/dist/token/xerc20.js +137 -54
- package/dist/token/xerc20.js.map +1 -1
- package/dist/token/xerc20.test.js +461 -169
- package/dist/token/xerc20.test.js.map +1 -1
- package/dist/types.d.ts +6 -36
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/cosmos.d.ts +113 -844
- package/dist/utils/cosmos.d.ts.map +1 -1
- package/dist/utils/cosmos.js +50 -91
- package/dist/utils/cosmos.js.map +1 -1
- package/dist/utils/ism.d.ts +167 -1
- package/dist/utils/ism.d.ts.map +1 -1
- package/dist/utils/ism.js +412 -2
- package/dist/utils/ism.js.map +1 -1
- package/dist/utils/ism.test.d.ts +2 -0
- package/dist/utils/ism.test.d.ts.map +1 -0
- package/dist/utils/ism.test.js +372 -0
- package/dist/utils/ism.test.js.map +1 -0
- package/dist/utils/schemas.d.ts +3 -3
- package/dist/utils/schemas.d.ts.map +1 -1
- package/dist/utils/schemas.js +2 -1
- package/dist/utils/schemas.js.map +1 -1
- package/dist/warp/types.d.ts +25 -367
- package/dist/warp/types.d.ts.map +1 -1
- package/package.json +11 -11
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
import { expect } from 'chai';
|
|
2
2
|
import { ethers } from 'ethers';
|
|
3
3
|
import hre from 'hardhat';
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
4
|
+
import sinon from 'sinon';
|
|
5
|
+
import { AtomicLocalRebalancingBridge__factory, CrossCollateralRouter__factory, DelayedFlowRouterHookIsm__factory, ERC20Test__factory, GasRouter__factory, HypXERC20Lockbox__factory, LinearFee__factory, MailboxClient__factory, NetFlowRateLimitedHookIsm__factory, ProxyAdmin__factory, RateLimitedIsm__factory, RoutingFee__factory, StaticAggregationIsm__factory, TokenRouter__factory, TransparentUpgradeableProxy__factory, XERC20LockboxTest__factory, XERC20Test__factory, XERC20VSTest__factory, } from '@hyperlane-xyz/core';
|
|
6
|
+
import { ProtocolType, addressToBytes32, assert, deepCopy, eqAddress, isNullish, isZeroishAddress, objMap, } from '@hyperlane-xyz/utils';
|
|
6
7
|
import { TestChainName } from '../consts/testChains.js';
|
|
7
8
|
import { TestCoreDeployer } from '../core/TestCoreDeployer.js';
|
|
8
9
|
import { HyperlaneProxyFactoryDeployer } from '../deploy/HyperlaneProxyFactoryDeployer.js';
|
|
9
|
-
import { executeWarpDeploy } from '../deploy/warp.js';
|
|
10
|
+
import { enrollCrossChainRouters, executeWarpDeploy } from '../deploy/warp.js';
|
|
10
11
|
import { TokenFeeType } from '../fee/types.js';
|
|
12
|
+
import { HookType } from '../hook/types.js';
|
|
11
13
|
import { HyperlaneIsmFactory } from '../ism/HyperlaneIsmFactory.js';
|
|
12
14
|
import { IsmType, } from '../ism/types.js';
|
|
13
15
|
import { MultiProvider } from '../providers/MultiProvider.js';
|
|
16
|
+
import { randomAddress } from '../test/testUtils.js';
|
|
17
|
+
import { collectHybridIsmNodes } from '../utils/ism.js';
|
|
14
18
|
import { EvmWarpRouteReader } from './EvmWarpRouteReader.js';
|
|
15
19
|
import { TokenStandard } from './TokenStandard.js';
|
|
16
20
|
import { TokenType } from './config.js';
|
|
17
21
|
import { checkWarpRouteDeployConfig } from './warpCheck.js';
|
|
18
22
|
import { HypERC20Deployer } from './deploy.js';
|
|
19
|
-
import { isAtomicLocalRebalancingBridgeTokenConfig, isDepositAddressTokenConfig, } from './types.js';
|
|
23
|
+
import { XERC20Type, isAtomicLocalRebalancingBridgeTokenConfig, isDepositAddressTokenConfig, } from './types.js';
|
|
20
24
|
const chain = TestChainName.test1;
|
|
21
25
|
function addOverridesToConfig(config, ownerOverrides) {
|
|
22
26
|
return Object.fromEntries(Object.entries(config).map(([chain, config]) => {
|
|
@@ -29,6 +33,12 @@ function addOverridesToConfig(config, ownerOverrides) {
|
|
|
29
33
|
];
|
|
30
34
|
}));
|
|
31
35
|
}
|
|
36
|
+
function assertEvmTransaction(transaction, chain) {
|
|
37
|
+
assert('to' in transaction &&
|
|
38
|
+
typeof transaction.to === 'string' &&
|
|
39
|
+
'data' in transaction &&
|
|
40
|
+
typeof transaction.data === 'string', `Expected an EVM transaction for ${chain}`);
|
|
41
|
+
}
|
|
32
42
|
describe('TokenDeployer', async () => {
|
|
33
43
|
let signer;
|
|
34
44
|
let deployer;
|
|
@@ -289,12 +299,25 @@ describe('TokenDeployer', async () => {
|
|
|
289
299
|
chainName: currentChain,
|
|
290
300
|
})),
|
|
291
301
|
});
|
|
302
|
+
// XERC20Test answers mintingMaxLimitOf/burningMaxLimitOf with the uint256
|
|
303
|
+
// max for every bridge, so a deploy config declaring no limits reads as
|
|
304
|
+
// drift against what the token holds.
|
|
305
|
+
const MAX_UINT256 = '115792089237316195423570985008687907853269984665640564039457584007913129639935';
|
|
292
306
|
beforeEach(async () => {
|
|
293
|
-
// @ts-expect-error - Test assigns varying token types to config
|
|
294
307
|
config[chain] = {
|
|
295
308
|
...config[chain],
|
|
296
309
|
type,
|
|
310
|
+
// @ts-expect-error - Test assigns varying token types to config
|
|
297
311
|
token: token(),
|
|
312
|
+
xERC20: type === TokenType.XERC20
|
|
313
|
+
? {
|
|
314
|
+
warpRouteLimits: {
|
|
315
|
+
type: XERC20Type.Standard,
|
|
316
|
+
mint: MAX_UINT256,
|
|
317
|
+
burn: MAX_UINT256,
|
|
318
|
+
},
|
|
319
|
+
}
|
|
320
|
+
: undefined,
|
|
298
321
|
};
|
|
299
322
|
contractsMap = await deployer.deploy(config);
|
|
300
323
|
});
|
|
@@ -563,10 +586,10 @@ describe('TokenDeployer', async () => {
|
|
|
563
586
|
reader = new EvmWarpRouteReader(multiProvider, TestChainName.test1);
|
|
564
587
|
});
|
|
565
588
|
beforeEach(async () => {
|
|
566
|
-
// @ts-expect-error - Test assigns varying token types to config
|
|
567
589
|
config[chain] = {
|
|
568
590
|
...config[chain],
|
|
569
591
|
type,
|
|
592
|
+
// @ts-expect-error - Test assigns varying token types to config
|
|
570
593
|
token: token(),
|
|
571
594
|
};
|
|
572
595
|
const warpRoute = await deployer.deploy(config);
|
|
@@ -578,6 +601,153 @@ describe('TokenDeployer', async () => {
|
|
|
578
601
|
});
|
|
579
602
|
});
|
|
580
603
|
}
|
|
604
|
+
describe('checkWarpRouteDeployConfig for a Velodrome xERC20', () => {
|
|
605
|
+
// The values the CLI e2e uses, which XERC20VSTest accepts for addBridge.
|
|
606
|
+
const BUFFER_CAP = '1000000000000000000000';
|
|
607
|
+
const RATE_LIMIT_PER_SECOND = '1000000000000000000';
|
|
608
|
+
const VELO_LIMITS = {
|
|
609
|
+
type: XERC20Type.Velo,
|
|
610
|
+
bufferCap: BUFFER_CAP,
|
|
611
|
+
rateLimitPerSecond: RATE_LIMIT_PER_SECOND,
|
|
612
|
+
};
|
|
613
|
+
let sandbox;
|
|
614
|
+
let veloToken;
|
|
615
|
+
let extraBridge;
|
|
616
|
+
let contractsMap;
|
|
617
|
+
const veloConfig = (extraBridges) => ({
|
|
618
|
+
...config,
|
|
619
|
+
[chain]: {
|
|
620
|
+
...config[chain],
|
|
621
|
+
type: TokenType.XERC20,
|
|
622
|
+
token: veloToken.address,
|
|
623
|
+
xERC20: { warpRouteLimits: VELO_LIMITS, extraBridges },
|
|
624
|
+
},
|
|
625
|
+
});
|
|
626
|
+
// CAST: the check only reads chainName and addressOrDenom off each token,
|
|
627
|
+
// and filling in the rest of WarpCoreConfig's token metadata would state
|
|
628
|
+
// things about the deployment this test does not know.
|
|
629
|
+
const getWarpCoreConfig = () => ({
|
|
630
|
+
tokens: Object.keys(config).map((currentChain) => ({
|
|
631
|
+
addressOrDenom: contractsMap[currentChain][currentChain === chain
|
|
632
|
+
? TokenType.XERC20
|
|
633
|
+
: config[currentChain].type].address,
|
|
634
|
+
chainName: currentChain,
|
|
635
|
+
})),
|
|
636
|
+
});
|
|
637
|
+
beforeEach(async () => {
|
|
638
|
+
sandbox = sinon.createSandbox();
|
|
639
|
+
// The test chains declare a placeholder Etherscan explorer, and the bridge
|
|
640
|
+
// scan would spend a network round trip on it before falling through. The
|
|
641
|
+
// RPC is the path this exercises.
|
|
642
|
+
sandbox.stub(multiProvider, 'tryGetEvmExplorerMetadataList').returns([]);
|
|
643
|
+
const { name, decimals, symbol } = config[chain];
|
|
644
|
+
assert(name && symbol && !isNullish(decimals), `Missing token metadata for ${chain}`);
|
|
645
|
+
veloToken = await new XERC20VSTest__factory(signer).deploy(name, symbol, totalSupply, decimals);
|
|
646
|
+
contractsMap = await deployer.deploy(veloConfig());
|
|
647
|
+
// The route's own router is a bridge of the token like any other, and the
|
|
648
|
+
// extra bridge is an address nothing but the token's events knows about.
|
|
649
|
+
extraBridge = randomAddress();
|
|
650
|
+
for (const bridge of [
|
|
651
|
+
contractsMap[chain][TokenType.XERC20].address,
|
|
652
|
+
extraBridge,
|
|
653
|
+
]) {
|
|
654
|
+
await veloToken
|
|
655
|
+
.addBridge({
|
|
656
|
+
bridge,
|
|
657
|
+
bufferCap: BUFFER_CAP,
|
|
658
|
+
rateLimitPerSecond: RATE_LIMIT_PER_SECOND,
|
|
659
|
+
})
|
|
660
|
+
.then((tx) => tx.wait());
|
|
661
|
+
}
|
|
662
|
+
});
|
|
663
|
+
afterEach(() => {
|
|
664
|
+
sandbox.restore();
|
|
665
|
+
});
|
|
666
|
+
it('reports no violations for a bridge discovered from the token', async () => {
|
|
667
|
+
const result = await checkWarpRouteDeployConfig({
|
|
668
|
+
multiProvider,
|
|
669
|
+
warpCoreConfig: getWarpCoreConfig(),
|
|
670
|
+
warpDeployConfig: veloConfig([
|
|
671
|
+
{ lockbox: extraBridge, limits: VELO_LIMITS },
|
|
672
|
+
]),
|
|
673
|
+
});
|
|
674
|
+
expect(result.diff).to.deep.equal({});
|
|
675
|
+
expect(result.violations).to.deep.equal([]);
|
|
676
|
+
expect(result.isValid).to.equal(true);
|
|
677
|
+
});
|
|
678
|
+
// Discovery follows the order the token announced its bridges in and the
|
|
679
|
+
// deploy config follows whoever wrote it. Comparing the two index by index
|
|
680
|
+
// reports the same set of bridges in two orders as drift.
|
|
681
|
+
it('reports no violations when the deploy config names the bridges in another order', async () => {
|
|
682
|
+
const laterBridge = randomAddress();
|
|
683
|
+
await veloToken
|
|
684
|
+
.addBridge({
|
|
685
|
+
bridge: laterBridge,
|
|
686
|
+
bufferCap: BUFFER_CAP,
|
|
687
|
+
rateLimitPerSecond: RATE_LIMIT_PER_SECOND,
|
|
688
|
+
})
|
|
689
|
+
.then((tx) => tx.wait());
|
|
690
|
+
const result = await checkWarpRouteDeployConfig({
|
|
691
|
+
multiProvider,
|
|
692
|
+
warpCoreConfig: getWarpCoreConfig(),
|
|
693
|
+
// Announced extraBridge first, so name it last.
|
|
694
|
+
warpDeployConfig: veloConfig([
|
|
695
|
+
{ lockbox: laterBridge, limits: VELO_LIMITS },
|
|
696
|
+
{ lockbox: extraBridge, limits: VELO_LIMITS },
|
|
697
|
+
]),
|
|
698
|
+
});
|
|
699
|
+
expect(result.diff).to.deep.equal({});
|
|
700
|
+
expect(result.violations).to.deep.equal([]);
|
|
701
|
+
expect(result.isValid).to.equal(true);
|
|
702
|
+
});
|
|
703
|
+
// Guards the assertion above against passing because the declared limits
|
|
704
|
+
// were echoed back rather than read: declare the same bridge with limits
|
|
705
|
+
// the token does not hold and the check has to report it.
|
|
706
|
+
it('reports drift when the declared limits are not the ones the token holds', async () => {
|
|
707
|
+
const result = await checkWarpRouteDeployConfig({
|
|
708
|
+
multiProvider,
|
|
709
|
+
warpCoreConfig: getWarpCoreConfig(),
|
|
710
|
+
warpDeployConfig: veloConfig([
|
|
711
|
+
{
|
|
712
|
+
lockbox: extraBridge,
|
|
713
|
+
limits: {
|
|
714
|
+
type: XERC20Type.Velo,
|
|
715
|
+
bufferCap: '1',
|
|
716
|
+
rateLimitPerSecond: '1',
|
|
717
|
+
},
|
|
718
|
+
},
|
|
719
|
+
]),
|
|
720
|
+
});
|
|
721
|
+
expect(result.isValid).to.equal(false);
|
|
722
|
+
expect(result.violations.map(({ chain: violationChain, name }) => ({
|
|
723
|
+
chain: violationChain,
|
|
724
|
+
name,
|
|
725
|
+
}))).to.deep.equal([
|
|
726
|
+
{ chain, name: 'xERC20.extraBridges.0.limits.bufferCap' },
|
|
727
|
+
{ chain, name: 'xERC20.extraBridges.0.limits.rateLimitPerSecond' },
|
|
728
|
+
]);
|
|
729
|
+
});
|
|
730
|
+
// A bridge on chain that the deploy config does not name is drift the check
|
|
731
|
+
// exists to surface, and it is only visible because the bridge set is read
|
|
732
|
+
// from the token rather than from the config.
|
|
733
|
+
it('reports a bridge the deploy config does not name', async () => {
|
|
734
|
+
const result = await checkWarpRouteDeployConfig({
|
|
735
|
+
multiProvider,
|
|
736
|
+
warpCoreConfig: getWarpCoreConfig(),
|
|
737
|
+
warpDeployConfig: veloConfig(),
|
|
738
|
+
});
|
|
739
|
+
expect(result.isValid).to.equal(false);
|
|
740
|
+
// isValid alone is true of any drift on any field, so the violation has
|
|
741
|
+
// to name the bridge for this to be about the bridge.
|
|
742
|
+
expect(result.violations.map(({ chain: violationChain, name, actual }) => ({
|
|
743
|
+
chain: violationChain,
|
|
744
|
+
name,
|
|
745
|
+
namesTheBridge: actual.includes(extraBridge.toLowerCase()),
|
|
746
|
+
}))).to.deep.equal([
|
|
747
|
+
{ chain, name: 'xERC20.extraBridges', namesTheBridge: true },
|
|
748
|
+
]);
|
|
749
|
+
});
|
|
750
|
+
});
|
|
581
751
|
describe('RateLimitedIsm with non-deployer warp owner', () => {
|
|
582
752
|
let ismDeployer;
|
|
583
753
|
let ismFactory;
|
|
@@ -683,6 +853,447 @@ describe('TokenDeployer', async () => {
|
|
|
683
853
|
expect((await router.owner()).toLowerCase()).to.equal(warpOwner.toLowerCase());
|
|
684
854
|
});
|
|
685
855
|
});
|
|
856
|
+
describe('Hybrid hook/ISM deferred deploy', () => {
|
|
857
|
+
let registryAddresses;
|
|
858
|
+
const remoteChain = TestChainName.test2;
|
|
859
|
+
before(async () => {
|
|
860
|
+
const pfd = new HyperlaneProxyFactoryDeployer(multiProvider);
|
|
861
|
+
const factories = await pfd.deploy(multiProvider.mapKnownChains(() => ({})));
|
|
862
|
+
registryAddresses = {};
|
|
863
|
+
for (const chainName of [chain, remoteChain]) {
|
|
864
|
+
registryAddresses[chainName] = {
|
|
865
|
+
...objMap(factories[chainName], (_, contract) => contract.address),
|
|
866
|
+
mailbox: coreApp.getContracts(chainName).mailbox.address,
|
|
867
|
+
};
|
|
868
|
+
}
|
|
869
|
+
// DELAYED_FLOW_ROUTER refuses nonce-0 mailboxes. Seed both test
|
|
870
|
+
// mailboxes before any staged deploy spends gas.
|
|
871
|
+
for (const [origin, destination] of [
|
|
872
|
+
[chain, remoteChain],
|
|
873
|
+
[remoteChain, chain],
|
|
874
|
+
]) {
|
|
875
|
+
const mailbox = coreApp.getContracts(origin).mailbox;
|
|
876
|
+
if ((await mailbox.nonce()) !== 0)
|
|
877
|
+
continue;
|
|
878
|
+
const recipient = addressToBytes32(signer.address);
|
|
879
|
+
const quote = await mailbox['quoteDispatch(uint32,bytes32,bytes)'](multiProvider.getDomainId(destination), recipient, '0x');
|
|
880
|
+
await multiProvider.handleTx(origin, mailbox['dispatch(uint32,bytes32,bytes)'](multiProvider.getDomainId(destination), recipient, '0x', { value: quote }));
|
|
881
|
+
}
|
|
882
|
+
});
|
|
883
|
+
function delayedFlowTree(owner) {
|
|
884
|
+
return {
|
|
885
|
+
type: IsmType.AGGREGATION,
|
|
886
|
+
threshold: 2,
|
|
887
|
+
modules: [
|
|
888
|
+
{
|
|
889
|
+
type: IsmType.TRUSTED_RELAYER,
|
|
890
|
+
relayer: signer.address,
|
|
891
|
+
},
|
|
892
|
+
{
|
|
893
|
+
type: IsmType.DELAYED_FLOW_ROUTER,
|
|
894
|
+
thresholdBps: 10000,
|
|
895
|
+
maxDelay: 3600,
|
|
896
|
+
duration: 86400n,
|
|
897
|
+
owner,
|
|
898
|
+
},
|
|
899
|
+
],
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
const hookView = (ism) => {
|
|
903
|
+
const nodes = collectHybridIsmNodes(ism);
|
|
904
|
+
assert(nodes.length === 1, `Expected one hybrid node, found ${nodes.length}`);
|
|
905
|
+
const node = nodes[0];
|
|
906
|
+
return node.type === IsmType.DELAYED_FLOW_ROUTER
|
|
907
|
+
? { ...node, type: HookType.DELAYED_FLOW_ROUTER }
|
|
908
|
+
: { ...node, type: HookType.NET_FLOW_RATE_LIMITED };
|
|
909
|
+
};
|
|
910
|
+
async function deployHybridRoute(warpConfig, isms) {
|
|
911
|
+
const planned = objMap(warpConfig, (chainName, chainConfig) => {
|
|
912
|
+
const ism = isms[chainName];
|
|
913
|
+
assert(ism, `Missing hybrid ISM tree for ${chainName}`);
|
|
914
|
+
return {
|
|
915
|
+
...chainConfig,
|
|
916
|
+
interchainSecurityModule: ism,
|
|
917
|
+
hook: hookView(ism),
|
|
918
|
+
};
|
|
919
|
+
});
|
|
920
|
+
const routers = await executeWarpDeploy(planned, multiProvider, {}, registryAddresses, {});
|
|
921
|
+
return objMap(routers, (_, address) => ({
|
|
922
|
+
synthetic: { address },
|
|
923
|
+
}));
|
|
924
|
+
}
|
|
925
|
+
async function expectDeployRejection(promise, message) {
|
|
926
|
+
const error = await promise.then(() => undefined, (thrown) => thrown instanceof Error ? thrown : new Error(String(thrown)));
|
|
927
|
+
assert(error, 'Expected staged deploy to reject');
|
|
928
|
+
expect(error.message).to.include(message);
|
|
929
|
+
}
|
|
930
|
+
it('wires a nested delayedFlowRouterHookIsm as ISM member AND hook, keeping deployer ownership for enrollment', async () => {
|
|
931
|
+
const warpOwner = ethers.Wallet.createRandom().address;
|
|
932
|
+
const warpConfig = {
|
|
933
|
+
[chain]: {
|
|
934
|
+
...config[chain],
|
|
935
|
+
type: TokenType.synthetic,
|
|
936
|
+
owner: warpOwner,
|
|
937
|
+
},
|
|
938
|
+
};
|
|
939
|
+
const contracts = await deployHybridRoute(warpConfig, {
|
|
940
|
+
[chain]: delayedFlowTree(warpOwner),
|
|
941
|
+
});
|
|
942
|
+
const routerAddress = contracts[chain].synthetic.address;
|
|
943
|
+
const provider = multiProvider.getProvider(chain);
|
|
944
|
+
const tokenClient = MailboxClient__factory.connect(routerAddress, provider);
|
|
945
|
+
const ismAddress = await tokenClient.interchainSecurityModule();
|
|
946
|
+
expect(isZeroishAddress(ismAddress)).to.be.false;
|
|
947
|
+
// hook must be wired to the hybrid instance
|
|
948
|
+
const hookAddress = await tokenClient.hook();
|
|
949
|
+
expect(isZeroishAddress(hookAddress)).to.be.false;
|
|
950
|
+
// the hook is the DelayedFlowRouterHookIsm paired with this router
|
|
951
|
+
const delayedIsm = DelayedFlowRouterHookIsm__factory.connect(hookAddress, provider);
|
|
952
|
+
expect(eqAddress(await delayedIsm.warpRouter(), routerAddress)).to.be
|
|
953
|
+
.true;
|
|
954
|
+
expect(await delayedIsm.maxDelay()).to.equal(3600);
|
|
955
|
+
// the same instance must be a member of the aggregation ISM
|
|
956
|
+
const aggregationIsm = StaticAggregationIsm__factory.connect(ismAddress, provider);
|
|
957
|
+
const [modules] = await aggregationIsm.modulesAndThreshold(ethers.constants.AddressZero);
|
|
958
|
+
expect(modules.map((m) => m.toLowerCase())).to.include(hookAddress.toLowerCase());
|
|
959
|
+
// Both stay with the deployer until the final router-enrollment pass.
|
|
960
|
+
expect(eqAddress(await delayedIsm.owner(), signer.address)).to.be.true;
|
|
961
|
+
const router = GasRouter__factory.connect(routerAddress, provider);
|
|
962
|
+
expect((await router.owner()).toLowerCase()).to.equal(signer.address.toLowerCase());
|
|
963
|
+
});
|
|
964
|
+
it('does not proceed to the ISM phase when installing the hook fails', async () => {
|
|
965
|
+
const setHookSighash = MailboxClient__factory.createInterface().getSighash('setHook');
|
|
966
|
+
const setIsmSighash = MailboxClient__factory.createInterface().getSighash('setInterchainSecurityModule');
|
|
967
|
+
let sawIsmInstall = false;
|
|
968
|
+
const sendTransaction = multiProvider.sendTransaction.bind(multiProvider);
|
|
969
|
+
const sandbox = sinon.createSandbox();
|
|
970
|
+
sandbox
|
|
971
|
+
.stub(multiProvider, 'sendTransaction')
|
|
972
|
+
.callsFake(async (txChain, txProm, options) => {
|
|
973
|
+
const tx = await txProm;
|
|
974
|
+
if (typeof tx.data === 'string' &&
|
|
975
|
+
tx.data.startsWith(setIsmSighash)) {
|
|
976
|
+
sawIsmInstall = true;
|
|
977
|
+
}
|
|
978
|
+
if (typeof tx.data === 'string' &&
|
|
979
|
+
tx.data.startsWith(setHookSighash)) {
|
|
980
|
+
throw new Error('execution reverted: setHook');
|
|
981
|
+
}
|
|
982
|
+
return sendTransaction(txChain, tx, options);
|
|
983
|
+
});
|
|
984
|
+
try {
|
|
985
|
+
const warpConfig = {
|
|
986
|
+
[chain]: {
|
|
987
|
+
...config[chain],
|
|
988
|
+
type: TokenType.synthetic,
|
|
989
|
+
owner: signer.address,
|
|
990
|
+
},
|
|
991
|
+
};
|
|
992
|
+
const error = await deployHybridRoute(warpConfig, {
|
|
993
|
+
[chain]: delayedFlowTree(signer.address),
|
|
994
|
+
}).then(() => undefined, (thrown) => thrown instanceof Error ? thrown : new Error(String(thrown)));
|
|
995
|
+
assert(error, 'expected the deploy to fail');
|
|
996
|
+
expect(error.message).to.include('execution reverted: setHook');
|
|
997
|
+
expect(sawIsmInstall).to.be.false;
|
|
998
|
+
}
|
|
999
|
+
finally {
|
|
1000
|
+
sandbox.restore();
|
|
1001
|
+
}
|
|
1002
|
+
});
|
|
1003
|
+
it('rejects a hybrid on an unmeterable router type before staged deploy', async () => {
|
|
1004
|
+
const warpConfig = {
|
|
1005
|
+
[chain]: {
|
|
1006
|
+
...config[chain],
|
|
1007
|
+
type: TokenType.collateralVault,
|
|
1008
|
+
token: erc20.address,
|
|
1009
|
+
owner: signer.address,
|
|
1010
|
+
},
|
|
1011
|
+
};
|
|
1012
|
+
await expectDeployRejection(deployHybridRoute(warpConfig, {
|
|
1013
|
+
[chain]: delayedFlowTree(signer.address),
|
|
1014
|
+
}), 'cannot meter');
|
|
1015
|
+
});
|
|
1016
|
+
it('rejects a hybrid combined with a predicateWrapper before staged deploy', async () => {
|
|
1017
|
+
const warpConfig = {
|
|
1018
|
+
[chain]: {
|
|
1019
|
+
...config[chain],
|
|
1020
|
+
type: TokenType.synthetic,
|
|
1021
|
+
owner: signer.address,
|
|
1022
|
+
predicateWrapper: {
|
|
1023
|
+
predicateRegistry: randomAddress(),
|
|
1024
|
+
policyId: 'test-policy',
|
|
1025
|
+
owner: signer.address,
|
|
1026
|
+
},
|
|
1027
|
+
},
|
|
1028
|
+
};
|
|
1029
|
+
await expectDeployRejection(deployHybridRoute(warpConfig, {
|
|
1030
|
+
[chain]: delayedFlowTree(signer.address),
|
|
1031
|
+
}), 'both must own');
|
|
1032
|
+
});
|
|
1033
|
+
it('rejects a top-level netFlowRateLimitedHookIsm (no authenticating ISM)', async () => {
|
|
1034
|
+
const warpOwner = ethers.Wallet.createRandom().address;
|
|
1035
|
+
const warpConfig = {
|
|
1036
|
+
[chain]: {
|
|
1037
|
+
...config[chain],
|
|
1038
|
+
type: TokenType.synthetic,
|
|
1039
|
+
owner: warpOwner,
|
|
1040
|
+
},
|
|
1041
|
+
};
|
|
1042
|
+
// moduleType() is NULL: alone it authenticates nothing, so a forged
|
|
1043
|
+
// message would mint on this synthetic leg subject only to bucket
|
|
1044
|
+
// capacity. The composition rule must reject it.
|
|
1045
|
+
const netFlowConfig = {
|
|
1046
|
+
type: IsmType.NET_FLOW_RATE_LIMITED,
|
|
1047
|
+
thresholdBps: 500,
|
|
1048
|
+
duration: 86400n,
|
|
1049
|
+
owner: warpOwner,
|
|
1050
|
+
};
|
|
1051
|
+
await expectDeployRejection(deployHybridRoute(warpConfig, { [chain]: netFlowConfig }), 'verifies flow, not message authenticity');
|
|
1052
|
+
});
|
|
1053
|
+
it('wires a netFlowRateLimitedHookIsm composed under an authenticating aggregation as both hook and ISM', async () => {
|
|
1054
|
+
const warpOwner = ethers.Wallet.createRandom().address;
|
|
1055
|
+
const warpConfig = {
|
|
1056
|
+
[chain]: {
|
|
1057
|
+
...config[chain],
|
|
1058
|
+
type: TokenType.synthetic,
|
|
1059
|
+
owner: warpOwner,
|
|
1060
|
+
},
|
|
1061
|
+
};
|
|
1062
|
+
const netFlowConfig = {
|
|
1063
|
+
type: IsmType.AGGREGATION,
|
|
1064
|
+
threshold: 2,
|
|
1065
|
+
modules: [
|
|
1066
|
+
{ type: IsmType.TRUSTED_RELAYER, relayer: signer.address },
|
|
1067
|
+
{
|
|
1068
|
+
type: IsmType.NET_FLOW_RATE_LIMITED,
|
|
1069
|
+
thresholdBps: 500,
|
|
1070
|
+
duration: 86400n,
|
|
1071
|
+
owner: warpOwner,
|
|
1072
|
+
},
|
|
1073
|
+
],
|
|
1074
|
+
};
|
|
1075
|
+
const contracts = await deployHybridRoute(warpConfig, {
|
|
1076
|
+
[chain]: netFlowConfig,
|
|
1077
|
+
});
|
|
1078
|
+
const routerAddress = contracts[chain].synthetic.address;
|
|
1079
|
+
const provider = multiProvider.getProvider(chain);
|
|
1080
|
+
// Mirror the CLI's post-deploy pass. It enrolls route peers and hands
|
|
1081
|
+
// the router, ProxyAdmin, and shared hybrid to their final owner.
|
|
1082
|
+
const enrollmentTxs = await enrollCrossChainRouters({
|
|
1083
|
+
multiProvider,
|
|
1084
|
+
altVmSigners: {},
|
|
1085
|
+
registryAddresses,
|
|
1086
|
+
warpDeployConfig: warpConfig,
|
|
1087
|
+
}, { [chain]: routerAddress });
|
|
1088
|
+
for (const rawTx of enrollmentTxs[chain] ?? []) {
|
|
1089
|
+
assertEvmTransaction(rawTx, chain);
|
|
1090
|
+
await multiProvider.sendTransaction(chain, {
|
|
1091
|
+
to: rawTx.to,
|
|
1092
|
+
data: rawTx.data,
|
|
1093
|
+
value: rawTx.value,
|
|
1094
|
+
});
|
|
1095
|
+
}
|
|
1096
|
+
const tokenClient = MailboxClient__factory.connect(routerAddress, provider);
|
|
1097
|
+
const ismAddress = await tokenClient.interchainSecurityModule();
|
|
1098
|
+
const hookAddress = await tokenClient.hook();
|
|
1099
|
+
expect(isZeroishAddress(hookAddress)).to.be.false;
|
|
1100
|
+
// The hook is the hybrid leaf inside the installed aggregation, not the
|
|
1101
|
+
// aggregation itself.
|
|
1102
|
+
const [modules] = await StaticAggregationIsm__factory.connect(ismAddress, provider).modulesAndThreshold(ethers.constants.AddressZero);
|
|
1103
|
+
expect(modules.map((m) => m.toLowerCase())).to.include(hookAddress.toLowerCase());
|
|
1104
|
+
const netFlowIsm = NetFlowRateLimitedHookIsm__factory.connect(hookAddress, provider);
|
|
1105
|
+
expect(eqAddress(await netFlowIsm.warpRouter(), routerAddress)).to.be
|
|
1106
|
+
.true;
|
|
1107
|
+
// Ownership transfers only after all route wiring is complete.
|
|
1108
|
+
expect((await netFlowIsm.owner()).toLowerCase()).to.equal(warpOwner.toLowerCase());
|
|
1109
|
+
expect((await TokenRouter__factory.connect(routerAddress, provider).owner()).toLowerCase()).to.equal(warpOwner.toLowerCase());
|
|
1110
|
+
const secondEnrollmentTxs = await enrollCrossChainRouters({
|
|
1111
|
+
multiProvider,
|
|
1112
|
+
altVmSigners: {},
|
|
1113
|
+
registryAddresses,
|
|
1114
|
+
warpDeployConfig: warpConfig,
|
|
1115
|
+
}, { [chain]: routerAddress });
|
|
1116
|
+
expect(Object.keys(secondEnrollmentTxs)).to.have.length(0);
|
|
1117
|
+
});
|
|
1118
|
+
it('defaults an omitted netFlowRateLimitedHookIsm owner to the chain config owner', async () => {
|
|
1119
|
+
const warpOwner = ethers.Wallet.createRandom().address;
|
|
1120
|
+
const warpConfig = {
|
|
1121
|
+
[chain]: {
|
|
1122
|
+
...config[chain],
|
|
1123
|
+
type: TokenType.synthetic,
|
|
1124
|
+
owner: warpOwner,
|
|
1125
|
+
},
|
|
1126
|
+
};
|
|
1127
|
+
const ownerlessNetFlow = {
|
|
1128
|
+
type: IsmType.AGGREGATION,
|
|
1129
|
+
threshold: 2,
|
|
1130
|
+
modules: [
|
|
1131
|
+
{ type: IsmType.TRUSTED_RELAYER, relayer: signer.address },
|
|
1132
|
+
{
|
|
1133
|
+
type: IsmType.NET_FLOW_RATE_LIMITED,
|
|
1134
|
+
thresholdBps: 500,
|
|
1135
|
+
duration: 86400n,
|
|
1136
|
+
},
|
|
1137
|
+
],
|
|
1138
|
+
};
|
|
1139
|
+
const contracts = await deployHybridRoute(warpConfig, {
|
|
1140
|
+
[chain]: ownerlessNetFlow,
|
|
1141
|
+
});
|
|
1142
|
+
const routerAddress = contracts[chain].synthetic.address;
|
|
1143
|
+
const provider = multiProvider.getProvider(chain);
|
|
1144
|
+
const enrollmentTxs = await enrollCrossChainRouters({
|
|
1145
|
+
multiProvider,
|
|
1146
|
+
altVmSigners: {},
|
|
1147
|
+
registryAddresses,
|
|
1148
|
+
warpDeployConfig: warpConfig,
|
|
1149
|
+
}, { [chain]: routerAddress });
|
|
1150
|
+
for (const rawTx of enrollmentTxs[chain] ?? []) {
|
|
1151
|
+
assertEvmTransaction(rawTx, chain);
|
|
1152
|
+
await multiProvider.sendTransaction(chain, {
|
|
1153
|
+
to: rawTx.to,
|
|
1154
|
+
data: rawTx.data,
|
|
1155
|
+
value: rawTx.value,
|
|
1156
|
+
});
|
|
1157
|
+
}
|
|
1158
|
+
// the hybrid leaf is the router's hook; the ISM is the aggregation
|
|
1159
|
+
const hookAddress = await MailboxClient__factory.connect(routerAddress, provider).hook();
|
|
1160
|
+
const netFlowIsm = NetFlowRateLimitedHookIsm__factory.connect(hookAddress, provider);
|
|
1161
|
+
// The final pass defaults an omitted hybrid owner to the chain owner.
|
|
1162
|
+
expect((await netFlowIsm.owner()).toLowerCase()).to.equal(warpOwner.toLowerCase());
|
|
1163
|
+
});
|
|
1164
|
+
it('enrolls delayedFlowRouterHookIsm counterparts cross-chain and transfers ownership last', async () => {
|
|
1165
|
+
const warpOwner = ethers.Wallet.createRandom().address;
|
|
1166
|
+
const warpDeployConfig = {
|
|
1167
|
+
[chain]: {
|
|
1168
|
+
...config[chain],
|
|
1169
|
+
type: TokenType.synthetic,
|
|
1170
|
+
owner: warpOwner,
|
|
1171
|
+
interchainSecurityModule: delayedFlowTree(warpOwner),
|
|
1172
|
+
},
|
|
1173
|
+
[remoteChain]: {
|
|
1174
|
+
...config[remoteChain],
|
|
1175
|
+
type: TokenType.synthetic,
|
|
1176
|
+
owner: warpOwner,
|
|
1177
|
+
interchainSecurityModule: delayedFlowTree(warpOwner),
|
|
1178
|
+
},
|
|
1179
|
+
};
|
|
1180
|
+
const contracts = await deployHybridRoute(warpDeployConfig, {
|
|
1181
|
+
[chain]: delayedFlowTree(warpOwner),
|
|
1182
|
+
[remoteChain]: delayedFlowTree(warpOwner),
|
|
1183
|
+
});
|
|
1184
|
+
const deployedContracts = objMap(contracts, (_, c) => c.synthetic.address);
|
|
1185
|
+
const enrollTxs = await enrollCrossChainRouters({
|
|
1186
|
+
multiProvider,
|
|
1187
|
+
altVmSigners: {},
|
|
1188
|
+
registryAddresses,
|
|
1189
|
+
warpDeployConfig,
|
|
1190
|
+
}, deployedContracts);
|
|
1191
|
+
for (const [txChain, txs] of Object.entries(enrollTxs)) {
|
|
1192
|
+
for (const rawTx of txs) {
|
|
1193
|
+
assertEvmTransaction(rawTx, txChain);
|
|
1194
|
+
// drop the annotated chainId: every hardhat test chain shares one
|
|
1195
|
+
// node (chainId 31337) while test-chain metadata carries fake ids
|
|
1196
|
+
await multiProvider.sendTransaction(txChain, {
|
|
1197
|
+
to: rawTx.to,
|
|
1198
|
+
data: rawTx.data,
|
|
1199
|
+
value: rawTx.value,
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
const localProvider = multiProvider.getProvider(chain);
|
|
1204
|
+
const remoteProvider = multiProvider.getProvider(remoteChain);
|
|
1205
|
+
const localDfr = DelayedFlowRouterHookIsm__factory.connect(await MailboxClient__factory.connect(deployedContracts[chain], localProvider).hook(), localProvider);
|
|
1206
|
+
const remoteDfr = DelayedFlowRouterHookIsm__factory.connect(await MailboxClient__factory.connect(deployedContracts[remoteChain], remoteProvider).hook(), remoteProvider);
|
|
1207
|
+
// mutual DFR enrollment
|
|
1208
|
+
const localDomain = multiProvider.getDomainId(chain);
|
|
1209
|
+
const remoteDomain = multiProvider.getDomainId(remoteChain);
|
|
1210
|
+
expect(await localDfr.routers(remoteDomain)).to.equal(addressToBytes32(remoteDfr.address).toLowerCase());
|
|
1211
|
+
expect(await remoteDfr.routers(localDomain)).to.equal(addressToBytes32(localDfr.address).toLowerCase());
|
|
1212
|
+
// ownership handed to the configured owner after enrollment
|
|
1213
|
+
expect((await localDfr.owner()).toLowerCase()).to.equal(warpOwner.toLowerCase());
|
|
1214
|
+
expect((await remoteDfr.owner()).toLowerCase()).to.equal(warpOwner.toLowerCase());
|
|
1215
|
+
// a second pass converges to zero transactions
|
|
1216
|
+
const secondEnrollTxs = await enrollCrossChainRouters({
|
|
1217
|
+
multiProvider,
|
|
1218
|
+
altVmSigners: {},
|
|
1219
|
+
registryAddresses,
|
|
1220
|
+
warpDeployConfig,
|
|
1221
|
+
}, deployedContracts);
|
|
1222
|
+
expect(Object.keys(secondEnrollTxs)).to.have.length(0);
|
|
1223
|
+
});
|
|
1224
|
+
it('reconciles delayedFlowRouterHookIsm enrollment drift', async () => {
|
|
1225
|
+
// Owner is the deployer so the drift can be introduced directly and the
|
|
1226
|
+
// corrective transactions can be submitted from this test.
|
|
1227
|
+
const owner = signer.address;
|
|
1228
|
+
const warpDeployConfig = {
|
|
1229
|
+
[chain]: {
|
|
1230
|
+
...config[chain],
|
|
1231
|
+
type: TokenType.synthetic,
|
|
1232
|
+
owner,
|
|
1233
|
+
interchainSecurityModule: delayedFlowTree(owner),
|
|
1234
|
+
},
|
|
1235
|
+
[remoteChain]: {
|
|
1236
|
+
...config[remoteChain],
|
|
1237
|
+
type: TokenType.synthetic,
|
|
1238
|
+
owner,
|
|
1239
|
+
interchainSecurityModule: delayedFlowTree(owner),
|
|
1240
|
+
},
|
|
1241
|
+
};
|
|
1242
|
+
const contracts = await deployHybridRoute(objMap(warpDeployConfig, (_, c) => ({
|
|
1243
|
+
...c,
|
|
1244
|
+
interchainSecurityModule: undefined,
|
|
1245
|
+
})), {
|
|
1246
|
+
[chain]: delayedFlowTree(owner),
|
|
1247
|
+
[remoteChain]: delayedFlowTree(owner),
|
|
1248
|
+
});
|
|
1249
|
+
const deployedContracts = objMap(contracts, (_, c) => c.synthetic.address);
|
|
1250
|
+
const submit = async (txs) => {
|
|
1251
|
+
for (const [txChain, chainTxs] of Object.entries(txs)) {
|
|
1252
|
+
for (const rawTx of chainTxs) {
|
|
1253
|
+
assertEvmTransaction(rawTx, txChain);
|
|
1254
|
+
await multiProvider.sendTransaction(txChain, {
|
|
1255
|
+
to: rawTx.to,
|
|
1256
|
+
data: rawTx.data,
|
|
1257
|
+
value: rawTx.value,
|
|
1258
|
+
});
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
};
|
|
1262
|
+
await submit(await enrollCrossChainRouters({
|
|
1263
|
+
multiProvider,
|
|
1264
|
+
altVmSigners: {},
|
|
1265
|
+
registryAddresses,
|
|
1266
|
+
warpDeployConfig,
|
|
1267
|
+
}, deployedContracts));
|
|
1268
|
+
const localProvider = multiProvider.getProvider(chain);
|
|
1269
|
+
const localDfrAddress = await MailboxClient__factory.connect(deployedContracts[chain], localProvider).hook();
|
|
1270
|
+
const localDfr = DelayedFlowRouterHookIsm__factory.connect(localDfrAddress, multiProvider.getSigner(chain));
|
|
1271
|
+
const remoteDomain = multiProvider.getDomainId(remoteChain);
|
|
1272
|
+
// Introduce drift: point the local instance at a bogus counterpart.
|
|
1273
|
+
const bogusRouter = addressToBytes32(randomAddress()).toLowerCase();
|
|
1274
|
+
await multiProvider.handleTx(chain, localDfr.enrollRemoteRouter(remoteDomain, bogusRouter));
|
|
1275
|
+
expect(await localDfr.routers(remoteDomain)).to.equal(bogusRouter);
|
|
1276
|
+
// Re-running enrollment must emit corrective transactions...
|
|
1277
|
+
const driftTxs = await enrollCrossChainRouters({
|
|
1278
|
+
multiProvider,
|
|
1279
|
+
altVmSigners: {},
|
|
1280
|
+
registryAddresses,
|
|
1281
|
+
warpDeployConfig,
|
|
1282
|
+
}, deployedContracts);
|
|
1283
|
+
expect(Object.keys(driftTxs)).to.include(chain);
|
|
1284
|
+
await submit(driftTxs);
|
|
1285
|
+
// ...restoring the real counterpart, and then converging again.
|
|
1286
|
+
const remoteDfrAddress = await MailboxClient__factory.connect(deployedContracts[remoteChain], multiProvider.getProvider(remoteChain)).hook();
|
|
1287
|
+
expect(await localDfr.routers(remoteDomain)).to.equal(addressToBytes32(remoteDfrAddress).toLowerCase());
|
|
1288
|
+
const convergedTxs = await enrollCrossChainRouters({
|
|
1289
|
+
multiProvider,
|
|
1290
|
+
altVmSigners: {},
|
|
1291
|
+
registryAddresses,
|
|
1292
|
+
warpDeployConfig,
|
|
1293
|
+
}, deployedContracts);
|
|
1294
|
+
expect(Object.keys(convergedTxs)).to.have.length(0);
|
|
1295
|
+
});
|
|
1296
|
+
});
|
|
686
1297
|
describe('TokenFee with optional token for synthetic', () => {
|
|
687
1298
|
it('should deploy LinearFee without token and resolve to router address', async () => {
|
|
688
1299
|
const syntheticConfig = {
|