From 1e1fd5880f2b2375269bd4e00cc50466ffa3b774 Mon Sep 17 00:00:00 2001 From: asoliman Date: Tue, 27 Aug 2024 14:17:41 +0400 Subject: [PATCH] Remove liquidity manager --- core/scripts/ccip/liquiditymanager/util.go | 433 --------- .../internal/integration_test.go | 843 ------------------ 2 files changed, 1276 deletions(-) delete mode 100644 core/scripts/ccip/liquiditymanager/util.go delete mode 100644 core/services/ocr2/plugins/liquiditymanager/internal/integration_test.go diff --git a/core/scripts/ccip/liquiditymanager/util.go b/core/scripts/ccip/liquiditymanager/util.go deleted file mode 100644 index 45aa69ddb8a..00000000000 --- a/core/scripts/ccip/liquiditymanager/util.go +++ /dev/null @@ -1,433 +0,0 @@ -package main - -import ( - "context" - "fmt" - "math/big" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - chainsel "github.com/smartcontractkit/chain-selectors" - confighelper2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" - - "github.com/smartcontractkit/chainlink/core/scripts/ccip/liquiditymanager/arb" - "github.com/smartcontractkit/chainlink/core/scripts/ccip/liquiditymanager/multienv" - "github.com/smartcontractkit/chainlink/core/scripts/ccip/liquiditymanager/opstack" - helpers "github.com/smartcontractkit/chainlink/core/scripts/common" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" - cciprouter "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/liquiditymanager/generated/arbitrum_l1_bridge_adapter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/liquiditymanager/generated/arbitrum_l2_bridge_adapter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/liquiditymanager/generated/liquiditymanager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/liquiditymanager/generated/optimism_l1_bridge_adapter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/liquiditymanager/generated/optimism_l2_bridge_adapter" -) - -type universe struct { - L1 struct { - Arm common.Address - ArmProxy common.Address - TokenPool common.Address - LiquidityManager common.Address - BridgeAdapterAddress common.Address - } - L2 struct { - Arm common.Address - ArmProxy common.Address - TokenPool common.Address - LiquidityManager common.Address - BridgeAdapterAddress common.Address - } -} - -func deployUniverse( - env multienv.Env, - l1ChainID, l2ChainID uint64, - l1TokenAddress, l2TokenAddress common.Address, -) universe { - validateEnv(env, l1ChainID, l2ChainID, false) - - l1Client, l2Client := env.Clients[l1ChainID], env.Clients[l2ChainID] - l1Transactor, l2Transactor := env.Transactors[l1ChainID], env.Transactors[l2ChainID] - l1ChainSelector, l2ChainSelector := mustGetChainByEvmID(l1ChainID).Selector, mustGetChainByEvmID(l2ChainID).Selector - - // L1 deploys - // deploy arm and arm proxy. - // required by the token pool. - l1Arm, l1ArmProxy := deployArm(l1Transactor, l1Client, l1ChainID) - - _, tx, _, err := cciprouter.DeployRouter(l1Transactor, l1Client, common.Address{}, l1ArmProxy.Address()) - helpers.PanicErr(err) - l1RouterAddress := helpers.ConfirmContractDeployed(context.Background(), l1Client, tx, int64(l1ChainID)) - - // deploy token pool targeting l1TokenAddress. - l1TokenPool, l1Rebalancer := deployTokenPoolAndRebalancer(l1Transactor, l1Client, l1TokenAddress, l1ArmProxy.Address(), l1ChainSelector, l1RouterAddress) - - // deploy the appropriate L1 bridge adapter depending on the chain. - l1BridgeAdapterAddress := deployL1BridgeAdapter(l1Transactor, l1Client, l1ChainID, l2ChainID) - - // L2 deploys - // deploy arm and arm proxy. - // required by the token pool. - l2Arm, l2ArmProxy := deployArm(l2Transactor, l2Client, l2ChainID) - - _, tx, _, err = cciprouter.DeployRouter(l2Transactor, l2Client, common.Address{}, l2ArmProxy.Address()) - helpers.PanicErr(err) - l2RouterAddress := helpers.ConfirmContractDeployed(context.Background(), l2Client, tx, int64(l2ChainID)) - - // deploy token pool targeting l2TokenAddress - l2TokenPool, l2Rebalancer := deployTokenPoolAndRebalancer(l2Transactor, l2Client, l2TokenAddress, l2ArmProxy.Address(), l2ChainSelector, l2RouterAddress) - - // deploy the L2 bridge adapter to point to the token address - l2BridgeAdapterAddress := deployL2BridgeAdapter(l2Transactor, l2Client, l2ChainID) - - // link the l1 and l2 rebalancers together via the SetCrossChainRebalancer function - tx, err = l1Rebalancer.SetCrossChainRebalancer(l1Transactor, liquiditymanager.ILiquidityManagerCrossChainRebalancerArgs{ - RemoteRebalancer: l2Rebalancer.Address(), - LocalBridge: l1BridgeAdapterAddress, - RemoteToken: l2TokenAddress, - RemoteChainSelector: l2ChainSelector, - Enabled: true, - }) - helpers.PanicErr(err) - helpers.ConfirmTXMined(context.Background(), l1Client, tx, int64(l1ChainID), "setting cross chain liquidityManager on L1 liquidityManager") - // assertion - onchainRebalancer, err := l1Rebalancer.GetCrossChainRebalancer(nil, l2ChainSelector) - helpers.PanicErr(err) - if onchainRebalancer.RemoteRebalancer != l2Rebalancer.Address() || - onchainRebalancer.LocalBridge != l1BridgeAdapterAddress { - panic(fmt.Sprintf("onchain liquidityManager address does not match, expected %s got %s, or local bridge does not match, expected %s got %s", - l2Rebalancer.Address().Hex(), - onchainRebalancer.RemoteRebalancer.Hex(), - l1BridgeAdapterAddress.Hex(), - onchainRebalancer.LocalBridge.Hex())) - } - - tx, err = l2Rebalancer.SetCrossChainRebalancer(l2Transactor, liquiditymanager.ILiquidityManagerCrossChainRebalancerArgs{ - RemoteRebalancer: l1Rebalancer.Address(), - LocalBridge: l2BridgeAdapterAddress, - RemoteToken: l1TokenAddress, - RemoteChainSelector: l1ChainSelector, - Enabled: true, - }) - helpers.PanicErr(err) - helpers.ConfirmTXMined(context.Background(), l2Client, tx, int64(l2ChainID), "setting cross chain liquidityManager on L2 liquidityManager") - // assertion - onchainRebalancer, err = l2Rebalancer.GetCrossChainRebalancer(nil, l1ChainSelector) - helpers.PanicErr(err) - if onchainRebalancer.RemoteRebalancer != l1Rebalancer.Address() || - onchainRebalancer.LocalBridge != l2BridgeAdapterAddress { - panic(fmt.Sprintf("onchain liquidityManager address does not match, expected %s got %s, or local bridge does not match, expected %s got %s", - l1Rebalancer.Address().Hex(), - onchainRebalancer.RemoteRebalancer.Hex(), - l2BridgeAdapterAddress.Hex(), - onchainRebalancer.LocalBridge.Hex())) - } - - fmt.Println("Deployments complete\n", - "L1 Chain ID:", l1ChainID, "\n", - "L1 Chain Selector:", l1ChainSelector, "\n", - "L1 Arm:", helpers.ContractExplorerLink(int64(l1ChainID), l1Arm.Address()), "(", l1Arm.Address().Hex(), ")\n", - "L1 Arm Proxy:", helpers.ContractExplorerLink(int64(l1ChainID), l1ArmProxy.Address()), "(", l1ArmProxy.Address().Hex(), ")\n", - "L1 Token Pool:", helpers.ContractExplorerLink(int64(l1ChainID), l1TokenPool.Address()), "(", l1TokenPool.Address().Hex(), ")\n", - "L1 LiquidityManager:", helpers.ContractExplorerLink(int64(l1ChainID), l1Rebalancer.Address()), "(", l1Rebalancer.Address().Hex(), ")\n", - "L1 Bridge Adapter:", helpers.ContractExplorerLink(int64(l1ChainID), l1BridgeAdapterAddress), "(", l1BridgeAdapterAddress.Hex(), ")\n", - "L2 Chain ID:", l2ChainID, "\n", - "L2 Chain Selector:", l2ChainSelector, "\n", - "L2 Arm:", helpers.ContractExplorerLink(int64(l2ChainID), l2Arm.Address()), "(", l2Arm.Address().Hex(), ")\n", - "L2 Arm Proxy:", helpers.ContractExplorerLink(int64(l2ChainID), l2ArmProxy.Address()), "(", l2ArmProxy.Address().Hex(), ")\n", - "L2 Token Pool:", helpers.ContractExplorerLink(int64(l2ChainID), l2TokenPool.Address()), "(", l2TokenPool.Address().Hex(), ")\n", - "L2 LiquidityManager:", helpers.ContractExplorerLink(int64(l2ChainID), l2Rebalancer.Address()), "(", l2Rebalancer.Address().Hex(), ")\n", - "L2 Bridge Adapter:", helpers.ContractExplorerLink(int64(l2ChainID), l2BridgeAdapterAddress), "(", l2BridgeAdapterAddress.Hex(), ")", - ) - - return universe{ - L1: struct { - Arm common.Address - ArmProxy common.Address - TokenPool common.Address - LiquidityManager common.Address - BridgeAdapterAddress common.Address - }{ - Arm: l1Arm.Address(), - ArmProxy: l1ArmProxy.Address(), - TokenPool: l1TokenPool.Address(), - LiquidityManager: l1Rebalancer.Address(), - BridgeAdapterAddress: l1BridgeAdapterAddress, - }, - L2: struct { - Arm common.Address - ArmProxy common.Address - TokenPool common.Address - LiquidityManager common.Address - BridgeAdapterAddress common.Address - }{ - Arm: l2Arm.Address(), - ArmProxy: l2ArmProxy.Address(), - TokenPool: l2TokenPool.Address(), - LiquidityManager: l2Rebalancer.Address(), - BridgeAdapterAddress: l2BridgeAdapterAddress, - }, - } -} - -func deployL1BridgeAdapter( - l1Transactor *bind.TransactOpts, - l1Client *ethclient.Client, - l1ChainID, l2ChainID uint64, -) common.Address { - if l2ChainID == chainsel.ETHEREUM_MAINNET_ARBITRUM_1.EvmChainID || l2ChainID == chainsel.ETHEREUM_TESTNET_SEPOLIA_ARBITRUM_1.EvmChainID { - _, tx, _, err := arbitrum_l1_bridge_adapter.DeployArbitrumL1BridgeAdapter( - l1Transactor, - l1Client, - arb.ArbitrumContracts[l1ChainID]["L1GatewayRouter"], - arb.ArbitrumContracts[l1ChainID]["L1Outbox"], - ) - helpers.PanicErr(err) - return helpers.ConfirmContractDeployed(context.Background(), l1Client, tx, int64(l1ChainID)) - } else if l2ChainID == chainsel.ETHEREUM_MAINNET_OPTIMISM_1.EvmChainID || l2ChainID == chainsel.ETHEREUM_TESTNET_SEPOLIA_OPTIMISM_1.EvmChainID { - _, tx, _, err := optimism_l1_bridge_adapter.DeployOptimismL1BridgeAdapter( - l1Transactor, - l1Client, - opstack.OptimismContractsByChainID[l1ChainID]["L1StandardBridge"], - opstack.OptimismContractsByChainID[l1ChainID]["WETH"], - opstack.OptimismContractsByChainID[l1ChainID]["OptimismPortalProxy"], - ) - helpers.PanicErr(err) - return helpers.ConfirmContractDeployed(context.Background(), l1Client, tx, int64(l1ChainID)) - } - panic(fmt.Sprintf("unsupported chain id %d", l1ChainID)) -} - -func deployL2BridgeAdapter( - l2Transactor *bind.TransactOpts, - l2Client *ethclient.Client, - l2ChainID uint64, -) common.Address { - if l2ChainID == chainsel.ETHEREUM_MAINNET_ARBITRUM_1.EvmChainID || l2ChainID == chainsel.ETHEREUM_TESTNET_SEPOLIA_ARBITRUM_1.EvmChainID { - _, tx, _, err := arbitrum_l2_bridge_adapter.DeployArbitrumL2BridgeAdapter( - l2Transactor, - l2Client, - arb.ArbitrumContracts[l2ChainID]["L2GatewayRouter"], - ) - helpers.PanicErr(err) - return helpers.ConfirmContractDeployed(context.Background(), l2Client, tx, int64(l2ChainID)) - } else if l2ChainID == chainsel.ETHEREUM_MAINNET_OPTIMISM_1.EvmChainID || l2ChainID == chainsel.ETHEREUM_TESTNET_SEPOLIA_OPTIMISM_1.EvmChainID { - _, tx, _, err := optimism_l2_bridge_adapter.DeployOptimismL2BridgeAdapter( - l2Transactor, - l2Client, - opstack.OptimismContractsByChainID[l2ChainID]["WETH"], - ) - helpers.PanicErr(err) - return helpers.ConfirmContractDeployed(context.Background(), l2Client, tx, int64(l2ChainID)) - } - panic(fmt.Sprintf("unsupported l2 chain id %d", l2ChainID)) -} - -func deployTokenPoolAndRebalancer( - transactor *bind.TransactOpts, - client *ethclient.Client, - tokenAddress, - armProxyAddress common.Address, - chainID uint64, - router common.Address, -) (*lock_release_token_pool.LockReleaseTokenPool, *liquiditymanager.LiquidityManager) { - _, tx, _, err := lock_release_token_pool.DeployLockReleaseTokenPool( - transactor, - client, - tokenAddress, - []common.Address{}, - armProxyAddress, - true, - router, - ) - helpers.PanicErr(err) - tokenPoolAddress := helpers.ConfirmContractDeployed(context.Background(), client, tx, int64(chainID)) - tokenPool, err := lock_release_token_pool.NewLockReleaseTokenPool(tokenPoolAddress, client) - helpers.PanicErr(err) - - _, tx, _, err = liquiditymanager.DeployLiquidityManager( - transactor, - client, - tokenAddress, - chainID, - tokenPoolAddress, - big.NewInt(0), - common.Address{}, - ) - helpers.PanicErr(err) - rebalancerAddress := helpers.ConfirmContractDeployed(context.Background(), client, tx, int64(chainID)) - liquidityManager, err := liquiditymanager.NewLiquidityManager(rebalancerAddress, client) - helpers.PanicErr(err) - tx, err = tokenPool.SetRebalancer(transactor, rebalancerAddress) - helpers.PanicErr(err) - helpers.ConfirmTXMined(context.Background(), client, tx, int64(chainID), - "setting liquidityManager on token pool") - onchainRebalancer, err := tokenPool.GetRebalancer(nil) - helpers.PanicErr(err) - if onchainRebalancer != rebalancerAddress { - panic(fmt.Sprintf("onchain liquidityManager address does not match, expected %s got %s", - rebalancerAddress.Hex(), onchainRebalancer.Hex())) - } - return tokenPool, liquidityManager -} - -func deployArm( - transactor *bind.TransactOpts, - client *ethclient.Client, - chainID uint64) (*mock_rmn_contract.MockRMNContract, *rmn_proxy_contract.RMNProxyContract) { - _, tx, _, err := mock_rmn_contract.DeployMockRMNContract(transactor, client) - helpers.PanicErr(err) - armAddress := helpers.ConfirmContractDeployed(context.Background(), client, tx, int64(chainID)) - arm, err := mock_rmn_contract.NewMockRMNContract(armAddress, client) - helpers.PanicErr(err) - - _, tx, _, err = rmn_proxy_contract.DeployRMNProxyContract(transactor, client, arm.Address()) - helpers.PanicErr(err) - armProxyAddress := helpers.ConfirmContractDeployed(context.Background(), client, tx, int64(chainID)) - armProxy, err := rmn_proxy_contract.NewRMNProxyContract(armProxyAddress, client) - helpers.PanicErr(err) - - return arm, armProxy -} - -// sum of MaxDurationQuery/MaxDurationObservation/DeltaGrace must be less than DeltaProgress -func setConfig( - e multienv.Env, - args setConfigArgs, -) { - validateEnv(e, args.l1ChainID, args.l2ChainID, false) - - l1Transactor, l2Transactor := e.Transactors[args.l1ChainID], e.Transactors[args.l2ChainID] - - // lengths of all the arrays must be equal - if len(args.signers) != len(args.offchainPubKeys) || - len(args.signers) != len(args.configPubKeys) || - len(args.signers) != len(args.l1Transmitters) || - len(args.signers) != len(args.l2Transmitters) { - panic("lengths of all the arrays must be equal") - } - - l1Rebalancer, err := liquiditymanager.NewLiquidityManager(args.l1LiquidityManagerAddress, e.Clients[args.l1ChainID]) - helpers.PanicErr(err) - l2Rebalancer, err := liquiditymanager.NewLiquidityManager(args.l2LiquidityManagerAddress, e.Clients[args.l2ChainID]) - helpers.PanicErr(err) - - // set config on L2 first then L1 - var ( - l1Oracles []confighelper2.OracleIdentityExtra - l2Oracles []confighelper2.OracleIdentityExtra - ) - for i := 0; i < len(args.signers); i++ { - l1Oracles = append(l1Oracles, confighelper2.OracleIdentityExtra{ - OracleIdentity: confighelper2.OracleIdentity{ - OffchainPublicKey: args.offchainPubKeys[i], - OnchainPublicKey: args.signers[i].Bytes(), - PeerID: args.peerIDs[i], - TransmitAccount: types.Account(args.l1Transmitters[i].Hex()), - }, - ConfigEncryptionPublicKey: args.configPubKeys[i], - }) - l2Oracles = append(l2Oracles, confighelper2.OracleIdentityExtra{ - OracleIdentity: confighelper2.OracleIdentity{ - OffchainPublicKey: args.offchainPubKeys[i], - OnchainPublicKey: args.signers[i].Bytes(), - PeerID: args.peerIDs[i], - TransmitAccount: types.Account(args.l2Transmitters[i].Hex()), - }, - ConfigEncryptionPublicKey: args.configPubKeys[i], - }) - } - var schedule []int - for range l1Oracles { - schedule = append(schedule, 1) - } - offchainConfig, onchainConfig := []byte{}, []byte{} - f := uint8(1) - _, _, f, onchainConfig, offchainConfigVersion, offchainConfig, err := ocr3confighelper.ContractSetConfigArgsForTests( - args.deltaProgress, - args.deltaResend, - args.deltaInitial, - args.deltaRound, - args.deltaGrace, - args.deltaCertifiedCommitRequest, - args.deltaStage, - args.rMax, - schedule, - l2Oracles, - offchainConfig, - args.maxDurationQuery, - args.maxDurationObservation, - args.maxDurationShouldAcceptAttestedReport, - args.maxDurationShouldTransmitAcceptedReport, - int(f), - onchainConfig) - helpers.PanicErr(err) - tx, err := l2Rebalancer.SetOCR3Config(l2Transactor, args.signers, args.l2Transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) - helpers.PanicErr(err) - helpers.ConfirmTXMined(context.Background(), e.Clients[args.l2ChainID], tx, int64(args.l2ChainID), "setting OCR3 config on L2 liquidityManager") - - fmt.Println("sleeping a bit before setting config on L1") - time.Sleep(1 * time.Minute) - - // set config on L1 - offchainConfig, onchainConfig = []byte{}, []byte{} - _, _, f, onchainConfig, offchainConfigVersion, offchainConfig, err = ocr3confighelper.ContractSetConfigArgsForTests( - args.deltaProgress, - args.deltaResend, - args.deltaInitial, - args.deltaRound, - args.deltaGrace, - args.deltaCertifiedCommitRequest, - args.deltaStage, - args.rMax, - schedule, - l1Oracles, - offchainConfig, - args.maxDurationQuery, - args.maxDurationObservation, - args.maxDurationShouldAcceptAttestedReport, - args.maxDurationShouldTransmitAcceptedReport, - int(f), - onchainConfig) - helpers.PanicErr(err) - tx, err = l1Rebalancer.SetOCR3Config(l1Transactor, args.signers, args.l1Transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) - helpers.PanicErr(err) - helpers.ConfirmTXMined(context.Background(), e.Clients[args.l1ChainID], tx, int64(args.l1ChainID), "setting OCR3 config on L1 liquidityManager") -} - -func validateEnv(env multienv.Env, l1ChainID, l2ChainID uint64, websocket bool) { - _, ok := env.Clients[l1ChainID] - if !ok { - panic("L1 client not found") - } - _, ok = env.Clients[l2ChainID] - if !ok { - panic("L2 client not found") - } - _, ok = env.Transactors[l1ChainID] - if !ok { - panic("L1 transactor not found") - } - _, ok = env.Transactors[l2ChainID] - if !ok { - panic("L2 transactor not found") - } - if websocket { - _, ok = env.WSURLs[l1ChainID] - if !ok { - panic("L1 websocket URL not found") - } - _, ok = env.WSURLs[l2ChainID] - if !ok { - panic("L2 websocket URL not found") - } - } -} diff --git a/core/services/ocr2/plugins/liquiditymanager/internal/integration_test.go b/core/services/ocr2/plugins/liquiditymanager/internal/integration_test.go deleted file mode 100644 index 765366a5c34..00000000000 --- a/core/services/ocr2/plugins/liquiditymanager/internal/integration_test.go +++ /dev/null @@ -1,843 +0,0 @@ -package internal_test - -import ( - "context" - "fmt" - "math/big" - "net/http" - "sync" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core" - gethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" - "github.com/hashicorp/consul/sdk/freeport" - chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/libocr/commontypes" - confighelper2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink-common/pkg/config" - - "github.com/smartcontractkit/chainlink-common/pkg/loop" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - v2toml "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" - evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" - "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/liquiditymanager/generated/liquiditymanager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/liquiditymanager/generated/mock_l1_bridge_adapter" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/logger/audit" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/liquiditymanager/bridge/testonlybridge" - integrationtesthelpers "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/liquiditymanager/testhelpers/integration" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" - "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" - "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" - - "github.com/smartcontractkit/chainlink/v2/core/utils" - "github.com/smartcontractkit/chainlink/v2/plugins" -) - -var ( - mainChainID = int64(chainsel.GETH_TESTNET.EvmChainID) -) - -func TestLiquidityManager_Integration(t *testing.T) { - t.Skip("flakey test") - newTestUniverse(t, 2, false) -} - -type ocr3Node struct { - app chainlink.Application - peerID string - transmitters map[int64]common.Address - keybundle ocr2key.KeyBundle -} - -type onchainUniverse struct { - backend *backends.SimulatedBackend - chainID uint64 - wethToken *weth9.WETH9 - lockReleasePool *lock_release_token_pool.LockReleaseTokenPool - liquidityManager *liquiditymanager.LiquidityManager - bridgeAdapter *mock_l1_bridge_adapter.MockL1BridgeAdapter -} - -func setupNodeOCR3( - t *testing.T, - owner *bind.TransactOpts, - port int, - chainIDToBackend map[int64]*backends.SimulatedBackend, - p2pV2Bootstrappers []commontypes.BootstrapperLocator, - useForwarders bool, -) *ocr3Node { - // Do not want to load fixtures as they contain a dummy chainID. - config, db := heavyweight.FullTestDBNoFixturesV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Insecure.OCRDevelopmentMode = ptr(true) // Disables ocr spec validation so we can have fast polling for the test. - - c.Feature.LogPoller = ptr(true) - - c.P2P.V2.Enabled = ptr(true) - c.P2P.V2.DeltaDial = config.MustNewDuration(500 * time.Millisecond) - c.P2P.V2.DeltaReconcile = config.MustNewDuration(5 * time.Second) - c.P2P.V2.ListenAddresses = &[]string{fmt.Sprintf("127.0.0.1:%d", port)} - if len(p2pV2Bootstrappers) > 0 { - c.P2P.V2.DefaultBootstrappers = &p2pV2Bootstrappers - } - - c.OCR.Enabled = ptr(false) - c.OCR.DefaultTransactionQueueDepth = ptr(uint32(200)) - c.OCR2.Enabled = ptr(true) - - c.EVM[0].LogPollInterval = config.MustNewDuration(500 * time.Millisecond) - c.EVM[0].GasEstimator.LimitDefault = ptr[uint64](3_500_000) - c.EVM[0].Transactions.ForwardersEnabled = &useForwarders - c.OCR2.ContractPollInterval = config.MustNewDuration(5 * time.Second) - - var chains v2toml.EVMConfigs - for chainID := range chainIDToBackend { - chains = append(chains, createConfigV2Chain(big.NewInt(chainID))) - } - c.EVM = chains - c.OCR2.ContractPollInterval = config.MustNewDuration(5 * time.Second) - }) - - lggr := logger.TestLogger(t) - lggr.SetLogLevel(zapcore.InfoLevel) - ctx := testutils.Context(t) - clients := make(map[int64]client.Client) - - for chainID, backend := range chainIDToBackend { - clients[chainID] = client.NewSimulatedBackendClient(t, backend, big.NewInt(chainID)) - } - - master := keystore.New(db, utils.FastScryptParams, lggr) - - keystore := KeystoreSim{ - eks: &EthKeystoreSim{ - Eth: master.Eth(), - t: t, - }, - csa: master.CSA(), - } - mailMon := mailbox.NewMonitor("LiquidityManager", lggr.Named("mailbox")) - evmOpts := chainlink.EVMFactoryConfig{ - ChainOpts: legacyevm.ChainOpts{ - AppConfig: config, - GenEthClient: func(i *big.Int) client.Client { - t.Log("genning eth client for chain id:", i.String()) - client, ok := clients[i.Int64()] - if !ok { - t.Fatal("no backend for chainID", i) - } - return client - }, - MailMon: mailMon, - DS: db, - }, - CSAETHKeystore: keystore, - } - relayerFactory := chainlink.RelayerFactory{ - Logger: lggr, - LoopRegistry: plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), config.Tracing()), - GRPCOpts: loop.GRPCOpts{}, - } - initOps := []chainlink.CoreRelayerChainInitFunc{chainlink.InitEVM(testutils.Context(t), relayerFactory, evmOpts)} - rci, err := chainlink.NewCoreRelayerChainInteroperators(initOps...) - require.NoError(t, err) - - app, err := chainlink.NewApplication(chainlink.ApplicationOpts{ - Config: config, - DS: db, - KeyStore: master, - RelayerChainInteroperators: rci, - Logger: lggr, - ExternalInitiatorManager: nil, - CloseLogger: lggr.Sync, - UnrestrictedHTTPClient: &http.Client{}, - RestrictedHTTPClient: &http.Client{}, - AuditLogger: audit.NoopLogger, - MailMon: mailMon, - LoopRegistry: plugins.NewLoopRegistry(lggr, config.Tracing()), - }) - require.NoError(t, err) - require.NoError(t, app.GetKeyStore().Unlock(ctx, "password")) - _, err = app.GetKeyStore().P2P().Create(ctx) - require.NoError(t, err) - - p2pIDs, err := app.GetKeyStore().P2P().GetAll() - require.NoError(t, err) - require.Len(t, p2pIDs, 1) - peerID := p2pIDs[0].PeerID() - - // create a transmitter for each chain - transmitters := make(map[int64]common.Address) - for chainID, backend := range chainIDToBackend { - addrs, err2 := app.GetKeyStore().Eth().EnabledAddressesForChain(testutils.Context(t), big.NewInt(chainID)) - require.NoError(t, err2) - if len(addrs) == 1 { - // just fund the address - fundAddress(t, owner, addrs[0], assets.Ether(10).ToInt(), backend) - transmitters[chainID] = addrs[0] - } else { - // create key and fund it - _, err3 := app.GetKeyStore().Eth().Create(testutils.Context(t), big.NewInt(chainID)) - require.NoError(t, err3, "failed to create key for chain", chainID) - sendingKeys, err3 := app.GetKeyStore().Eth().EnabledAddressesForChain(testutils.Context(t), big.NewInt(chainID)) - require.NoError(t, err3) - require.Len(t, sendingKeys, 1) - fundAddress(t, owner, sendingKeys[0], assets.Ether(10).ToInt(), backend) - transmitters[chainID] = sendingKeys[0] - } - } - require.Len(t, transmitters, len(chainIDToBackend)) - - keybundle, err := app.GetKeyStore().OCR2().Create(ctx, chaintype.EVM) - require.NoError(t, err) - - return &ocr3Node{ - app: app, - peerID: peerID.Raw(), - transmitters: transmitters, - keybundle: keybundle, - } -} - -func newTestUniverse(t *testing.T, numChains int, adapterHoldNative bool) { - // create chains and deploy contracts - owner, chains := createChains(t, numChains) - universes := deployContracts(t, owner, chains, adapterHoldNative) - createConnectedNetwork(t, owner, chains, universes) - transferBalances(t, owner, universes) - mainContract := universes[mainChainID].liquidityManager.Address() - - t.Log("Creating bootstrap node") - bootstrapNodePort := freeport.GetOne(t) - bootstrapNode := setupNodeOCR3(t, owner, bootstrapNodePort, chains, nil, false) - numNodes := 4 - - t.Log("creating ocr3 nodes") - var ( - oracles = make(map[int64][]confighelper2.OracleIdentityExtra) - transmitters = make(map[int64][]common.Address) - onchainPubKeys []common.Address - kbs []ocr2key.KeyBundle - apps []chainlink.Application - nodes []*ocr3Node - ) - ports := freeport.GetN(t, numNodes) - for i := 0; i < numNodes; i++ { - // Supply the bootstrap IP and port as a V2 peer address - bootstrappers := []commontypes.BootstrapperLocator{ - {PeerID: bootstrapNode.peerID, Addrs: []string{ - fmt.Sprintf("127.0.0.1:%d", bootstrapNodePort), - }}, - } - node := setupNodeOCR3(t, owner, ports[i], chains, bootstrappers, false) - - kbs = append(kbs, node.keybundle) - apps = append(apps, node.app) - for chainID, transmitter := range node.transmitters { - transmitters[chainID] = append(transmitters[chainID], transmitter) - } - onchainPubKeys = append(onchainPubKeys, common.BytesToAddress(node.keybundle.PublicKey())) - for chainID, transmitter := range node.transmitters { - identity := confighelper2.OracleIdentityExtra{ - OracleIdentity: confighelper2.OracleIdentity{ - OnchainPublicKey: node.keybundle.PublicKey(), - TransmitAccount: ocrtypes.Account(transmitter.Hex()), - OffchainPublicKey: node.keybundle.OffchainPublicKey(), - PeerID: node.peerID, - }, - ConfigEncryptionPublicKey: node.keybundle.ConfigEncryptionPublicKey(), - } - oracles[chainID] = append(oracles[chainID], identity) - } - nodes = append(nodes, node) - } - - t.Log("starting ticker to commit blocks") - tick := time.NewTicker(1 * time.Second) - defer tick.Stop() - tickCtx, tickCancel := context.WithCancel(testutils.Context(t)) - defer tickCancel() - var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() - for { - select { - case <-tick.C: - for _, backend := range chains { - backend.Commit() - } - case <-tickCtx.Done(): - return - } - } - }() - t.Cleanup(func() { - tickCancel() - wg.Wait() - }) - - t.Log("setting config") - blocksBeforeConfig := setLiquidityManagerConfigs( - t, - owner, - universes, - chains, - onchainPubKeys, - transmitters, - oracles) - mainFromBlock := blocksBeforeConfig[mainChainID] - - t.Log("adding bootstrap node job") - err := bootstrapNode.app.Start(testutils.Context(t)) - require.NoError(t, err, "failed to start bootstrap node") - t.Cleanup(func() { - require.NoError(t, bootstrapNode.app.Stop()) - }) - - evmChains := bootstrapNode.app.GetRelayers().LegacyEVMChains() - require.NotNil(t, evmChains) - require.Len(t, evmChains.Slice(), numChains) - bootstrapJobSpec, err := integrationtesthelpers.NewBootsrapJobSpec(&integrationtesthelpers.LMJobSpecParams{ - ChainID: 1337, - ContractID: mainContract.Hex(), - RelayFromBlock: mainFromBlock, - }) - require.NoError(t, err, "failed to create bootstrap job spec") - bootstrapJobSpecStr, err := bootstrapJobSpec.String() - require.NoError(t, err, "failed to convert bootstrap job spec to string") - t.Log("creating bootstrap job with spec:\n", bootstrapJobSpecStr) - ocrJob, err := ocrbootstrap.ValidatedBootstrapSpecToml(bootstrapJobSpecStr) - require.NoError(t, err, "failed to validate bootstrap job") - err = bootstrapNode.app.AddJobV2(testutils.Context(t), &ocrJob) - require.NoError(t, err, "failed to add bootstrap job") - - t.Log("creating ocr3 jobs") - for i := 0; i < numNodes; i++ { - err = apps[i].Start(testutils.Context(t)) - require.NoError(t, err) - tapp := apps[i] - t.Cleanup(func() { - require.NoError(t, tapp.Stop()) - }) - - mainChain := mustGetChainByEvmID(t, testutils.SimulatedChainID.Int64()) - jobSpec, err := integrationtesthelpers.NewJobSpec(&integrationtesthelpers.LMJobSpecParams{ - Name: "liquiditymanager-integration-test", - Type: "ping-pong", - ChainID: 1337, - ContractID: mainContract.Hex(), - OCRKeyBundleID: kbs[i].ID(), - TransmitterID: nodes[i].transmitters[1337].Hex(), - RelayFromBlock: mainFromBlock, - FollowerChains: buildFollowerChainsFromBlocksToml(blocksBeforeConfig), - LiquidityManagerAddress: mainContract, - NetworkSelector: mainChain.Selector, - }) - require.NoError(t, err, "failed to create job spec") - jobSpecStr, err := jobSpec.String() - require.NoError(t, err, "failed to convert job spec to string") - t.Log("Creating liquidityManager job with spec:\n", jobSpecStr) - ocrJob2, err2 := validate.ValidatedOracleSpecToml( - testutils.Context(t), - apps[i].GetConfig().OCR2(), - apps[i].GetConfig().Insecure(), - jobSpecStr, - nil, - ) - require.NoError(t, err2, "failed to validate liquidityManager job") - err2 = apps[i].AddJobV2(testutils.Context(t), &ocrJob2) - require.NoError(t, err2, "failed to add liquidityManager job") - } - - t.Log("waiting for a transmission") - waitForTransmissions(t, universes) -} - -func waitForTransmissions( - t *testing.T, - universes map[int64]onchainUniverse, -) { - start := uint64(1) - liquidityTransferredSink := make(chan *liquiditymanager.LiquidityManagerLiquidityTransferred) - finalizationStepSink := make(chan *liquiditymanager.LiquidityManagerFinalizationStepCompleted) - var subs []event.Subscription - for _, uni := range universes { - sub, err := uni.liquidityManager.WatchLiquidityTransferred(&bind.WatchOpts{ - Start: &start, - }, liquidityTransferredSink, nil, nil, nil) - require.NoError(t, err, "failed to create subscription") - subs = append(subs, sub) - - sub, err = uni.liquidityManager.WatchFinalizationStepCompleted(&bind.WatchOpts{ - Start: &start, - }, finalizationStepSink, nil, nil) - require.NoError(t, err, "failed to create subscription") - subs = append(subs, sub) - } - defer func() { - for _, sub := range subs { - sub.Unsubscribe() - } - }() - ticker := time.NewTicker(1 * time.Second) - defer ticker.Stop() - sentEvents := map[string]struct{}{} - for { - select { - case lt := <-liquidityTransferredSink: - // determine if it's a send or receive event based on the BridgeReturnData field - // if it's a send event, then the BridgeReturnData will not be empty - if len(lt.BridgeReturnData) > 0 { - // for the test bridges, bridge return data is just a nonce - nonce, err := testonlybridge.UnpackBridgeSendReturnData(lt.BridgeReturnData) - require.NoError(t, err) - t.Log("received send event with nonce:", nonce, "tx hash:", lt.Raw.TxHash.String()) - sentEvents[nonce.String()] = struct{}{} - } else { - // for the test bridges, the bridge specific data is an amount and a nonce - amount, nonce, err := testonlybridge.UnpackFinalizeBridgePayload(lt.BridgeSpecificData) - require.NoError(t, err) - t.Log("received receive event with amount:", amount, "nonce:", nonce, "tx hash:", lt.Raw.TxHash.String()) - _, ok := sentEvents[nonce.String()] - if ok { - t.Log("received corresponding receive event") - return - } - t.Fatal("received receive event without corresponding send event") - } - case fsc := <-finalizationStepSink: - nonce, err := testonlybridge.UnpackProveBridgePayload(fsc.BridgeSpecificData) - require.NoError(t, err) - t.Log("received finalization step completed event with seqNr:", fsc.OcrSeqNum, - ", nonce:", nonce.String(), ", tx hash:", fsc.Raw.TxHash.String()) - case <-ticker.C: - t.Log("waiting for transmission or liquidity transferred event") - } - } -} - -func setLiquidityManagerConfig( - t *testing.T, - owner *bind.TransactOpts, - wrapper *liquiditymanager.LiquidityManager, - chain *backends.SimulatedBackend, - onchainPubKeys []common.Address, - transmitters []common.Address, - oracles []confighelper2.OracleIdentityExtra, -) (blockBeforeConfig int64) { - beforeConfig, err := chain.BlockByNumber(testutils.Context(t), nil) - require.NoError(t, err) - - // most of the config on the follower chains does not matter - // except for signers + transmitters - var schedule []int - for range oracles { - schedule = append(schedule, 1) - } - offchainConfig, onchainConfig := []byte{}, []byte{} - f := uint8(1) - _, _, f, onchainConfig, offchainConfigVersion, offchainConfig, err := ocr3confighelper.ContractSetConfigArgsForTests( - 30*time.Second, // deltaProgress - 10*time.Second, // deltaResend - 20*time.Second, // deltaInitial - 2*time.Second, // deltaRound - 20*time.Second, // deltaGrace - 10*time.Second, // deltaCertifiedCommitRequest - 10*time.Second, // deltaStage - 3, // rmax - schedule, - oracles, - offchainConfig, - 50*time.Millisecond, // maxDurationQuery - 5*time.Second, // maxDurationObservation - 10*time.Second, // maxDurationShouldAcceptAttestedReport - 10*time.Second, // maxDurationShouldTransmitAcceptedReport - int(f), - onchainConfig) - require.NoError(t, err, "failed to create contract config") - _, err = wrapper.SetOCR3Config( - owner, - onchainPubKeys, - transmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig) - require.NoError(t, err, "failed to set config") - chain.Commit() - - iter, err := wrapper.FilterConfigSet(&bind.FilterOpts{ - Start: beforeConfig.Number().Uint64(), - }) - require.NoError(t, err, "failed to create ConfigSet filter") - require.True(t, iter.Next()) - e := iter.Event - require.Equal(t, onchainPubKeys, e.Signers, "signers do not match") - require.Equal(t, transmitters, e.Transmitters, "transmitters do not match") - t.Log("config digest for liquidityManager at address: ", wrapper.Address(), ", is:", hexutil.Encode(e.ConfigDigest[:])) - - return beforeConfig.Number().Int64() -} - -func setLiquidityManagerConfigs( - t *testing.T, - owner *bind.TransactOpts, - universes map[int64]onchainUniverse, - chains map[int64]*backends.SimulatedBackend, - onchainPubKeys []common.Address, - transmitters map[int64][]common.Address, - oracles map[int64][]confighelper2.OracleIdentityExtra) (blocksBeforeConfig map[int64]int64) { - blocksBeforeConfig = make(map[int64]int64) - for chainID, uni := range universes { - blocksBeforeConfig[chainID] = setLiquidityManagerConfig( - t, - owner, - uni.liquidityManager, - chains[chainID], - onchainPubKeys, - transmitters[chainID], - oracles[chainID], - ) - } - return -} - -func ptr[T any](v T) *T { return &v } - -func createConfigV2Chain(chainID *big.Int) *v2toml.EVMConfig { - chain := v2toml.Defaults((*evmutils.Big)(chainID)) - chain.GasEstimator.LimitDefault = ptr(uint64(4e6)) - chain.LogPollInterval = config.MustNewDuration(500 * time.Millisecond) - chain.Transactions.ForwardersEnabled = ptr(false) - chain.FinalityDepth = ptr(uint32(2)) - return &v2toml.EVMConfig{ - ChainID: (*evmutils.Big)(chainID), - Enabled: ptr(true), - Chain: chain, - Nodes: v2toml.EVMNodes{&v2toml.Node{}}, - } -} - -var _ keystore.Eth = &EthKeystoreSim{} - -type EthKeystoreSim struct { - keystore.Eth - t *testing.T -} - -// override -func (e *EthKeystoreSim) SignTx(ctx context.Context, address common.Address, tx *gethtypes.Transaction, chainID *big.Int) (*gethtypes.Transaction, error) { - // always sign with chain id 1337 for the simulated backend - e.t.Log("always signing tx for chain id:", chainID.String(), "with chain id 1337, tx hash:", tx.Hash()) - return e.Eth.SignTx(ctx, address, tx, big.NewInt(1337)) -} - -type KeystoreSim struct { - eks keystore.Eth - csa keystore.CSA -} - -func (e KeystoreSim) Eth() keystore.Eth { - return e.eks -} - -func (e KeystoreSim) CSA() keystore.CSA { - return e.csa -} - -func fundAddress(t *testing.T, from *bind.TransactOpts, to common.Address, amount *big.Int, backend *backends.SimulatedBackend) { - nonce, err := backend.PendingNonceAt(testutils.Context(t), from.From) - require.NoError(t, err) - gp, err := backend.SuggestGasPrice(testutils.Context(t)) - require.NoError(t, err) - rawTx := gethtypes.NewTx(&gethtypes.LegacyTx{ - Nonce: nonce, - GasPrice: gp, - Gas: 21000, - To: &to, - Value: amount, - }) - signedTx, err := from.Signer(from.From, rawTx) - require.NoError(t, err) - err = backend.SendTransaction(testutils.Context(t), signedTx) - require.NoError(t, err) - backend.Commit() -} - -func createChains(t *testing.T, numChains int) (owner *bind.TransactOpts, chains map[int64]*backends.SimulatedBackend) { - owner = testutils.MustNewSimTransactor(t) - chains = make(map[int64]*backends.SimulatedBackend) - - chains[mainChainID] = backends.NewSimulatedBackend(core.GenesisAlloc{ - owner.From: core.GenesisAccount{ - Balance: assets.Ether(10_000).ToInt(), - }, - }, 30e6) - - for chainID := int64(chainsel.TEST_90000001.EvmChainID); chainID < int64(chainsel.TEST_90000020.EvmChainID); chainID++ { - chains[chainID] = backends.NewSimulatedBackend(core.GenesisAlloc{ - owner.From: core.GenesisAccount{ - Balance: assets.Ether(10000).ToInt(), - }, - }, 30e6) - - if len(chains) == numChains { - break - } - } - return -} - -func deployContracts( - t *testing.T, - owner *bind.TransactOpts, - chains map[int64]*backends.SimulatedBackend, - adapterHoldNative bool, -) ( - universes map[int64]onchainUniverse, -) { - universes = make(map[int64]onchainUniverse) - for chainID, backend := range chains { - // Deploy wrapped ether contract - // will act as the ERC-20 being bridged - wethAddress, _, _, err := weth9.DeployWETH9(owner, backend) - require.NoError(t, err, "failed to deploy WETH9 contract") - backend.Commit() - wethToken, err := weth9.NewWETH9(wethAddress, backend) - require.NoError(t, err, "failed to create WETH9 wrapper") - - // deposit some eth into the weth contract - _, err = wethToken.Deposit(&bind.TransactOpts{ - From: owner.From, - Signer: owner.Signer, - Value: assets.Ether(100).ToInt(), - Context: testutils.Context(t), - }) - require.NoError(t, err, "failed to deposit eth into weth contract") - - // deploy arm and arm proxy. - // required by the token pool - // otherwise not used by this test. - armAddress, _, _, err := mock_rmn_contract.DeployMockRMNContract(owner, backend) - require.NoError(t, err, "failed to deploy MockRMNContract contract") - backend.Commit() - armProxyAddress, _, _, err := rmn_proxy_contract.DeployRMNProxyContract(owner, backend, armAddress) - require.NoError(t, err, "failed to deploy RMNProxyContract contract") - backend.Commit() - - routerAddress, _, _, err := router.DeployRouter(owner, backend, wethAddress, armProxyAddress) - require.NoError(t, err, "failed to deploy Router contract") - backend.Commit() - - // deploy lock/release pool targeting the weth9 contract - lockReleasePoolAddress, _, _, err := lock_release_token_pool.DeployLockReleaseTokenPool( - owner, backend, wethAddress, []common.Address{}, armProxyAddress, true, routerAddress) - require.NoError(t, err, "failed to deploy LockReleaseTokenPool contract") - backend.Commit() - lockReleasePool, err := lock_release_token_pool.NewLockReleaseTokenPool(lockReleasePoolAddress, backend) - require.NoError(t, err) - - // deploy the liquidityManager and set the liquidity container to be the lock release pool - ch := mustGetChainByEvmID(t, chainID) - liquidityManagerAddr, _, _, err := liquiditymanager.DeployLiquidityManager(owner, backend, wethAddress, ch.Selector, lockReleasePoolAddress, big.NewInt(0), common.Address{}) - require.NoError(t, err, "failed to deploy LiquidityManager contract") - liquidityManager, err := liquiditymanager.NewLiquidityManager(liquidityManagerAddr, backend) - require.NoError(t, err, "failed to create LiquidityManager wrapper") - - // set the liquidityManager of the lock release pool to be the just deployed liquidityManager - _, err = lockReleasePool.SetRebalancer(owner, liquidityManagerAddr) - require.NoError(t, err, "failed to set liquidityManager on lock/release pool") - backend.Commit() - actualLiquidityManager, err := lockReleasePool.GetRebalancer(&bind.CallOpts{Context: testutils.Context(t)}) - require.NoError(t, err) - require.Equal(t, liquidityManagerAddr, actualLiquidityManager) - - // deploy the bridge adapter to point to the weth contract address - bridgeAdapterAddress, _, _, err := mock_l1_bridge_adapter.DeployMockL1BridgeAdapter(owner, backend, wethAddress, adapterHoldNative) - require.NoError(t, err, "failed to deploy mock l1 bridge adapter") - backend.Commit() - bridgeAdapter, err := mock_l1_bridge_adapter.NewMockL1BridgeAdapter(bridgeAdapterAddress, backend) - require.NoError(t, err) - - universes[chainID] = onchainUniverse{ - backend: backend, - chainID: uint64(chainID), - wethToken: wethToken, - lockReleasePool: lockReleasePool, - liquidityManager: liquidityManager, - bridgeAdapter: bridgeAdapter, - } - - t.Log("deployed contracts for chain:", chainID, - "weth:", wethAddress.Hex(), - "lockReleasePool:", lockReleasePool.Address().Hex(), - "rebalancer:", liquidityManagerAddr.Hex(), - "bridgeAdapter:", bridgeAdapterAddress.Hex(), - ) - } - return -} - -func buildFollowerChainsFromBlocksToml(fromBlocks map[int64]int64) string { - var s string - for chainID, fromBlock := range fromBlocks { - if chainID == mainChainID { - continue - } - s += fmt.Sprintf("%d = %d\n", chainID, fromBlock) - } - return s -} - -func transferBalances( - t *testing.T, - owner *bind.TransactOpts, - universes map[int64]onchainUniverse, -) { - for _, uni := range universes { - // move some weth to the bridge adapters - // so that they can transfer it to the rebalancer - // when it calls finalizeWithdrawal - _, err := uni.wethToken.Transfer(owner, uni.bridgeAdapter.Address(), assets.Ether(5).ToInt()) - require.NoError(t, err, "failed to transfer weth to bridge adapter") - uni.backend.Commit() - // confirm balance - bal, err := uni.wethToken.BalanceOf(&bind.CallOpts{Context: testutils.Context(t)}, uni.bridgeAdapter.Address()) - require.NoError(t, err) - require.Equal(t, assets.Ether(5).ToInt(), bal) - - // move some weth to the lock/release pool - // the LM will pull from this pool in order to send cross-chain - _, err = uni.wethToken.Transfer(owner, uni.lockReleasePool.Address(), assets.Ether(5).ToInt()) - require.NoError(t, err, "failed to transfer weth to lock/release pool") - uni.backend.Commit() - // confirm balance - bal, err = uni.wethToken.BalanceOf(&bind.CallOpts{Context: testutils.Context(t)}, uni.lockReleasePool.Address()) - require.NoError(t, err) - require.Equal(t, assets.Ether(5).ToInt(), bal) - - // check the balance of the token pool through the rebalancer, - // should be the same as the balance of the lock/release pool - // retrieved above. - bal, err = uni.liquidityManager.GetLiquidity(&bind.CallOpts{Context: testutils.Context(t)}) - require.NoError(t, err) - require.Equal(t, assets.Ether(5).ToInt(), bal) - } -} - -// create a connection from the main chain to all follower chains -// and from all follower chains to the main chain -// this is analogous to the main chain being an L1 and all other -// chains being L2's. -func createConnectedNetwork( - t *testing.T, - owner *bind.TransactOpts, - chains map[int64]*backends.SimulatedBackend, - universes map[int64]onchainUniverse, -) { - for chainID, uni := range universes { - if chainID == mainChainID { - continue - } - // follower -> main connection - remoteChain := mustGetChainByEvmID(t, mainChainID) - - _, err := uni.liquidityManager.SetCrossChainRebalancer( - owner, - liquiditymanager.ILiquidityManagerCrossChainRebalancerArgs{ - RemoteRebalancer: universes[mainChainID].liquidityManager.Address(), - RemoteChainSelector: remoteChain.Selector, - Enabled: true, - LocalBridge: uni.bridgeAdapter.Address(), - RemoteToken: universes[mainChainID].wethToken.Address(), - }) - require.NoError(t, err, "failed to SetCrossChainRebalancer from follower to main chain") - chains[chainID].Commit() - - mgr, err := uni.liquidityManager.GetCrossChainRebalancer(&bind.CallOpts{Context: testutils.Context(t)}, remoteChain.Selector) - require.NoError(t, err) - require.Equal(t, universes[mainChainID].liquidityManager.Address(), mgr.RemoteRebalancer) - require.Equal(t, uni.bridgeAdapter.Address(), mgr.LocalBridge) - require.Equal(t, universes[mainChainID].wethToken.Address(), mgr.RemoteToken) - require.True(t, mgr.Enabled) - - // main -> follower connection - remoteChain = mustGetChainByEvmID(t, chainID) - - _, err = universes[mainChainID].liquidityManager.SetCrossChainRebalancer( - owner, - liquiditymanager.ILiquidityManagerCrossChainRebalancerArgs{ - RemoteRebalancer: uni.liquidityManager.Address(), - RemoteChainSelector: remoteChain.Selector, - Enabled: true, - LocalBridge: universes[mainChainID].bridgeAdapter.Address(), - RemoteToken: uni.wethToken.Address(), - }) - require.NoError(t, err, "failed to add neighbor from main to follower chain") - chains[mainChainID].Commit() - - mgr, err = universes[mainChainID].liquidityManager.GetCrossChainRebalancer( - &bind.CallOpts{Context: testutils.Context(t)}, remoteChain.Selector) - require.NoError(t, err) - require.Equal(t, uni.liquidityManager.Address(), mgr.RemoteRebalancer) - require.Equal(t, universes[mainChainID].bridgeAdapter.Address(), mgr.LocalBridge) - require.Equal(t, uni.wethToken.Address(), mgr.RemoteToken) - require.True(t, mgr.Enabled) - } - - // sanity check connections - for chainID, uni := range universes { - destChains, err := uni.liquidityManager.GetSupportedDestChains(&bind.CallOpts{Context: testutils.Context(t)}) - require.NoError(t, err, "couldn't get supported dest chains") - t.Log("num dest chains:", len(destChains), "dest chains:", destChains) - if chainID == mainChainID { - require.Len(t, destChains, len(universes)-1) - } else { - require.Len(t, destChains, 1) - } - mgrs, err := uni.liquidityManager.GetAllCrossChainRebalancers(&bind.CallOpts{ - Context: testutils.Context(t), - }) - require.NoError(t, err, "couldn't get all cross-chain liquidity managers") - t.Log("chainID:", chainID, "num neighbors:", len(mgrs)) - if chainID == mainChainID { - // should be connected to all follower chains - require.Len(t, mgrs, len(universes)-1, "unexpected number of neighbors on main chain") - } else { - // should be connected to just the main chain - require.Len(t, mgrs, 1, "unexpected number of neighbors on follower chain") - } - } -} - -func mustGetChainByEvmID(t *testing.T, chainID int64) chainsel.Chain { - ch, exists := chainsel.ChainByEvmChainID(uint64(chainID)) - require.True(t, exists) - return ch -}