From 908ec33485ff681fc34e5986e8e5fcd0f7aa70cf Mon Sep 17 00:00:00 2001 From: Balamurali Gopalswami Date: Wed, 4 Dec 2024 19:08:26 -0500 Subject: [PATCH] Remvoing ctf v2 dep and deploying token and pool using Burn and Mint --- .../ccip/testhelpers/integration/jobspec.go | 2 +- .../ccip-tests/actions/ccip_helpers.go | 97 +++++++++++-------- .../ccip-tests/contracts/contract_deployer.go | 97 +++++++++++++++++++ .../ccip-tests/contracts/contract_models.go | 8 +- .../testconfig/tomls/ccip-default.toml | 8 +- 5 files changed, 161 insertions(+), 51 deletions(-) diff --git a/core/services/ocr2/plugins/ccip/testhelpers/integration/jobspec.go b/core/services/ocr2/plugins/ccip/testhelpers/integration/jobspec.go index dd6b667ed1..6452f2db82 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/integration/jobspec.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/integration/jobspec.go @@ -298,7 +298,7 @@ func (params CCIPJobSpecParams) ExecutionJobSpec() (*OCR2TaskJobSpec, error) { } if params.LBTCConfig != nil { ocrSpec.PluginConfig["LBTCConfig.AttestationAPI"] = fmt.Sprintf(`"%s"`, params.LBTCConfig.AttestationAPI) - ocrSpec.PluginConfig["LBTCConfig.SourceTokenAddress"] = fmt.Sprintf(`"%s"`, params.LBTCConfig.SourceTokenAddress) + ocrSpec.PluginConfig["LBTCConfig.SourceTokenAddress"] = fmt.Sprintf("\"%s\"", params.LBTCConfig.SourceTokenAddress) ocrSpec.PluginConfig["LBTCConfig.AttestationAPITimeoutSeconds"] = params.LBTCConfig.AttestationAPITimeoutSeconds } return &OCR2TaskJobSpec{ diff --git a/integration-tests/ccip-tests/actions/ccip_helpers.go b/integration-tests/ccip-tests/actions/ccip_helpers.go index 445d9d5ca4..35adcf8082 100644 --- a/integration-tests/ccip-tests/actions/ccip_helpers.go +++ b/integration-tests/ccip-tests/actions/ccip_helpers.go @@ -32,13 +32,11 @@ import ( "golang.org/x/exp/rand" "golang.org/x/sync/errgroup" - "github.com/smartcontractkit/chainlink-testing-framework/framework" - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" - chainselectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-testing-framework/framework/components/fake" "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" ctfClient "github.com/smartcontractkit/chainlink-testing-framework/lib/client" ctftestenv "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" @@ -935,8 +933,8 @@ func (ccipModule *CCIPCommon) DeployContracts( return fmt.Errorf("granting minter role to token transmitter shouldn't fail %w", err) } } else if ccipModule.IsLBTCDeployment() && i == 0 { - // if it's USDC deployment, we deploy the burn mint token 677 with decimal 6 and cast it to ERC20Token - lbtcToken, err := ccipModule.tokenDeployer.DeployBurnMintERC677(new(big.Int).Mul(big.NewInt(1e6), big.NewInt(1e18))) + // if it's LBTC deployment, we deploy the burn mint token 677 with decimal 8 and cast it to ERC20Token + lbtcToken, err := ccipModule.tokenDeployer.DeployCustomBurnMintERC677Token("Lombard LBTC", "LBTC", uint8(18), new(big.Int).Mul(big.NewInt(1e6), big.NewInt(1e18))) if err != nil { return fmt.Errorf("deploying bridge lbtc token contract shouldn't fail %w", err) } @@ -1008,6 +1006,13 @@ func (ccipModule *CCIPCommon) DeployContracts( } ccipModule.BridgeTokenPools = append(ccipModule.BridgeTokenPools, usdcPool) + } else if ccipModule.IsLBTCDeployment() && i == 0 { + lbtcPool, err := ccipModule.tokenDeployer.DeployBurnAndMintTokenPoolContract(token.Address(), *ccipModule.RMNContract, ccipModule.Router.Instance.Address()) + if err != nil { + return fmt.Errorf("deploying burn and mint bridge Token pool(lbtc) shouldn't fail %w", err) + } + + ccipModule.BridgeTokenPools = append(ccipModule.BridgeTokenPools, lbtcPool) } else { // deploy lock release token pool in case of non-usdc deployment btp, err := ccipModule.tokenDeployer.DeployLockReleaseTokenPoolContract(token.Address(), *ccipModule.RMNContract, ccipModule.Router.Instance.Address()) @@ -1306,6 +1311,7 @@ func DefaultCCIPModule( ExistingDeployment: pointer.GetBool(testGroupConf.ExistingDeployment), MulticallEnabled: pointer.GetBool(testGroupConf.MulticallInOneTx), USDCMockDeployment: testGroupConf.USDCMockDeployment, + LBTCMockDeployment: testGroupConf.LBTCMockDeployment, NoOfTokensNeedingDynamicPrice: pointer.GetInt(testGroupConf.TokenConfig.NoOfTokensWithDynamicPrice), poolFunds: testhelpers.Link(5), gasUpdateWatcherMu: &sync.Mutex{}, @@ -3755,7 +3761,7 @@ func (lane *CCIPLane) DeployNewCCIPLane( } if !lane.Source.Common.ExistingDeployment && lane.Source.Common.IsLBTCDeployment() { api := "/bridge/v1/deposits/getByHash" - url := framework.HostDockerInternal() + api + url := "http://localhost:8080" + api //framework.HostDockerInternal() + // Only one LBTC allowed per chain jobParams.LBTCConfig = &config.LBTCConfig{ SourceTokenAddress: common.HexToAddress(lane.Source.Common.BridgeTokens[0].Address()), @@ -4455,48 +4461,53 @@ func SetMockServerWithUSDCAttestation( // The path is set with regex to match any path that starts with /v1/attestations func SetMockServerWithLBTCAttestation() error { apiPath := "/bridge/v1/deposits/getByHash" - cfg := &fake.Input{ - Port: 9111, - } - out, err := fake.NewFakeDataProvider(cfg) - if err != nil { - return fmt.Errorf("failed to create fake data provider: %w", err) - } - path := out.BaseURLDocker + apiPath + service := gin.Default() + //Service.Use(recordMiddleware()) + go func() { + _ = service.Run("http://localhost:8080") + }() + //out := &Output{ + // BaseURLHost: fmt.Sprintf("http://localhost:%d", in.Port), + // BaseURLDocker: fmt.Sprintf("%s:%d", framework.HostDockerInternal(), in.Port), + //} + //in.Out = out + //return out, nil + //out, err := fake.NewFakeDataProvider(cfg) + //if err != nil { + // return fmt.Errorf("failed to create fake data provider: %w", err) + //} + path := "" + apiPath //out.BaseURLDocker + apiPath method := "POST" - err = fake.Func( - method, - apiPath, - func(c *gin.Context) { - var requestBody struct { - MessageHashes []string `json:"messageHash"` - } - if err := c.ShouldBindJSON(&requestBody); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid JSON"}) - return - } + service.Handle(method, path, func(c *gin.Context) { + var requestBody struct { + MessageHashes []string `json:"messageHash"` + } + if err := c.ShouldBindJSON(&requestBody); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid JSON"}) + return + } - // You can log the request body or process it if needed - fmt.Println("Received messageHash:", requestBody.MessageHashes[0]) + // You can log the request body or process it if needed + fmt.Println("Received messageHash:", requestBody.MessageHashes[0]) - // Mock response body based on the request - mockResponse := gin.H{ - "attestations": []map[string]any{ - { - "message_hash": requestBody.MessageHashes[0], - "status": "NOTARIZATION_STATUS_SESSION_APPROVED", - "attestation": "0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000e45c70a5050000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000845f8e3c214d8d0e4d83fc094f302aa26a12a0bc0000000000000000000000000000000000000000000000000000000000014a34000000000000000000000000845f8e3c214d8d0e4d83fc094f302aa26a12a0bc00000000000000000000000062f10ce5b727edf787ea45776bd050308a61150800000000000000000000000000000000000000000000000000000000000003e60000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000040277eeafba008d767c2636d9428f2ebb13ab29ac70337f4fc34b0f5606767cae546f9be3f12160de6d142e5b3c1c3ebd0bf4298662b32b597d0cc5970c7742fc10000000000000000000000000000000000000000000000000000000000000040bbcd60ecc9e06f2effe7c94161219498a1eb435b419387adadb86ec9a52dfb066ce027532517df7216404049d193a25b85c35edfa3e7c5aa4757bfe84887a3980000000000000000000000000000000000000000000000000000000000000040da4a6dc619b5ca2349783cabecc4efdbc910090d3e234d7b8d0430165f8fae532f9a965ceb85c18bb92e059adefa7ce5835850a705761ab9e026d2db4a13ef9a", - }, + // Mock response body based on the request + mockResponse := gin.H{ + "attestations": []map[string]any{ + { + "message_hash": requestBody.MessageHashes[0], + "status": "NOTARIZATION_STATUS_SESSION_APPROVED", + "attestation": "0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000e45c70a5050000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000845f8e3c214d8d0e4d83fc094f302aa26a12a0bc0000000000000000000000000000000000000000000000000000000000014a34000000000000000000000000845f8e3c214d8d0e4d83fc094f302aa26a12a0bc00000000000000000000000062f10ce5b727edf787ea45776bd050308a61150800000000000000000000000000000000000000000000000000000000000003e60000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000040277eeafba008d767c2636d9428f2ebb13ab29ac70337f4fc34b0f5606767cae546f9be3f12160de6d142e5b3c1c3ebd0bf4298662b32b597d0cc5970c7742fc10000000000000000000000000000000000000000000000000000000000000040bbcd60ecc9e06f2effe7c94161219498a1eb435b419387adadb86ec9a52dfb066ce027532517df7216404049d193a25b85c35edfa3e7c5aa4757bfe84887a3980000000000000000000000000000000000000000000000000000000000000040da4a6dc619b5ca2349783cabecc4efdbc910090d3e234d7b8d0430165f8fae532f9a965ceb85c18bb92e059adefa7ce5835850a705761ab9e026d2db4a13ef9a", }, - } + }, + } - // Return the mocked response - c.JSON(http.StatusOK, mockResponse) - }, + // Return the mocked response + c.JSON(http.StatusOK, mockResponse) + }, ) - if err != nil { - return fmt.Errorf("failed to create mock response: %w", err) - } + //if err != nil { + // return fmt.Errorf("failed to create mock response: %w", err) + //} log.Info().Str("path", path).Msg("setting attestation-api response for any msgHash") return nil } diff --git a/integration-tests/ccip-tests/contracts/contract_deployer.go b/integration-tests/ccip-tests/contracts/contract_deployer.go index 979b9a8bdd..0686246fb1 100644 --- a/integration-tests/ccip-tests/contracts/contract_deployer.go +++ b/integration-tests/ccip-tests/contracts/contract_deployer.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + burn_mint_token_pool "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/burn_mint_token_pool_1_4_0" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" @@ -241,6 +242,43 @@ func (e *CCIPContractsDeployer) DeployBurnMintERC677(ownerMintingAmount *big.Int return token, err } +func (e *CCIPContractsDeployer) DeployCustomBurnMintERC677Token(name, symbol string, decimals uint8, ownerMintingAmount *big.Int) (*ERC677Token, error) { + address, _, instance, err := e.evmClient.DeployContract("Burn Mint ERC 677", func( + auth *bind.TransactOpts, + _ bind.ContractBackend, + ) (common.Address, *types.Transaction, interface{}, error) { + return burn_mint_erc677.DeployBurnMintERC677(auth, wrappers.MustNewWrappedContractBackend(e.evmClient, nil), name, symbol, decimals, new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e9))) + }) + if err != nil { + return nil, err + } + + token := &ERC677Token{ + client: e.evmClient, + logger: e.logger, + ContractAddress: *address, + instance: instance.(*burn_mint_erc677.BurnMintERC677), + OwnerAddress: common.HexToAddress(e.evmClient.GetDefaultWallet().Address()), + OwnerWallet: e.evmClient.GetDefaultWallet(), + } + if ownerMintingAmount != nil { + // grant minter role to owner and mint tokens + err = token.GrantMintRole(common.HexToAddress(e.evmClient.GetDefaultWallet().Address())) + if err != nil { + return token, fmt.Errorf("granting minter role to owner shouldn't fail %w", err) + } + err = e.evmClient.WaitForEvents() + if err != nil { + return token, fmt.Errorf("error in waiting for granting mint role %w", err) + } + err = token.Mint(common.HexToAddress(e.evmClient.GetDefaultWallet().Address()), ownerMintingAmount) + if err != nil { + return token, fmt.Errorf("minting tokens shouldn't fail %w", err) + } + } + return token, err +} + func (e *CCIPContractsDeployer) DeployERC20TokenContract(deployerFn blockchain.ContractDeployer) (*ERC20Token, error) { address, _, _, err := e.evmClient.DeployContract("Custom ERC20 Token", deployerFn) if err != nil { @@ -488,6 +526,65 @@ func (e *CCIPContractsDeployer) DeployUSDCTokenPoolContract(tokenAddr string, to } } +func (e *CCIPContractsDeployer) DeployBurnAndMintTokenPoolContract(tokenAddr string, rmnProxy common.Address, router common.Address) ( + *TokenPool, + error, +) { + version := VersionMap[TokenPoolContract] + e.logger.Debug().Str("Token", tokenAddr).Msg("Deploying Burn and Mint token pool") + token := common.HexToAddress(tokenAddr) + switch version { + case Latest: + address, _, _, err := e.evmClient.DeployContract("Burn and Mint Token Pool", func( + auth *bind.TransactOpts, + _ bind.ContractBackend, + ) (common.Address, *types.Transaction, interface{}, error) { + return burn_mint_token_pool.DeployBurnMintTokenPool( + auth, + wrappers.MustNewWrappedContractBackend(e.evmClient, nil), + token, + []common.Address{}, + rmnProxy, + router, + ) + }) + + if err != nil { + return nil, err + } + pool, err := burn_mint_token_pool.NewBurnMintTokenPool(*address, wrappers.MustNewWrappedContractBackend(e.evmClient, nil)) + + if err != nil { + return nil, err + } + e.logger.Info(). + Str("Contract Address", address.Hex()). + Str("Contract Name", "USDC Token Pool"). + Str("From", e.evmClient.GetDefaultWallet().Address()). + Str("Network Name", e.evmClient.GetNetworkConfig().Name). + Msg("New contract") + poolInterface, err := token_pool.NewTokenPool(*address, wrappers.MustNewWrappedContractBackend(e.evmClient, nil)) + if err != nil { + return nil, err + } + return &TokenPool{ + client: e.evmClient, + logger: e.logger, + Instance: &TokenPoolWrapper{ + Latest: &LatestPool{ + PoolInterface: poolInterface, + BurnAndMintTokenPool: pool, + }, + }, + EthAddress: *address, + OwnerAddress: common.HexToAddress(e.evmClient.GetDefaultWallet().Address()), + OwnerWallet: e.evmClient.GetDefaultWallet(), + }, err + default: + return nil, fmt.Errorf("version not supported: %s", version) + } +} + func (e *CCIPContractsDeployer) DeployLockReleaseTokenPoolContract(tokenAddr string, rmnProxy common.Address, router common.Address) ( *TokenPool, error, diff --git a/integration-tests/ccip-tests/contracts/contract_models.go b/integration-tests/ccip-tests/contracts/contract_models.go index 9b339560d6..caeaca1956 100644 --- a/integration-tests/ccip-tests/contracts/contract_models.go +++ b/integration-tests/ccip-tests/contracts/contract_models.go @@ -18,6 +18,7 @@ import ( "golang.org/x/exp/rand" "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + burn_mint_token_pool "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/burn_mint_token_pool_1_4_0" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" @@ -401,9 +402,10 @@ func (l *LinkToken) Transfer(to string, amount *big.Int) error { } type LatestPool struct { - PoolInterface *token_pool.TokenPool - LockReleasePool *lock_release_token_pool.LockReleaseTokenPool - USDCPool *usdc_token_pool.USDCTokenPool + PoolInterface *token_pool.TokenPool + BurnAndMintTokenPool *burn_mint_token_pool.BurnMintTokenPool + LockReleasePool *lock_release_token_pool.LockReleaseTokenPool + USDCPool *usdc_token_pool.USDCTokenPool } type V1_4_0Pool struct { diff --git a/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml b/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml index 8baeea2417..feee2c266b 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml @@ -231,7 +231,7 @@ EIP1559FeeCapBufferBlocks = 0 # Run by default using latest version from `ccip-develop` branch, override this value to use a specific version [CCIP.Env.NewCLCluster.Common.ChainlinkImage] -version = "ccip-develop" +version = "latest" # the following configs are specific to each test type, smoke, load , chaos, etc... [CCIP.Groups] @@ -268,7 +268,7 @@ LBTCMockDeployment = true MsgType = 'DataWithToken' # type of message to be sent, either 'Token' or 'DataWithToken' Or 'Data' DestGasLimit = 100000 # change this to 0 gas limit if you are doing ccip-send to an EOA DataLength = 1000 # length of the data to be sent in ccip message if MsgType = 'Data'/'DataWithToken' -NoOfTokens = 2 # number of bridge tokens to be sent in ccip message if MsgType = 'Token'/'DataWithToken' +NoOfTokens = 1 # number of bridge tokens to be sent in ccip message if MsgType = 'Token'/'DataWithToken' AmountPerToken = 1 # amount to be sent for each bridge token in ccip message if MsgType = 'Token'/'DataWithToken' [CCIP.Groups.smoke.TokenConfig] @@ -276,8 +276,8 @@ TimeoutForPriceUpdate = '15m' # Duration to wait for the price update to time-ou # Now testing only with dynamic price getter (no pipeline). # Could be removed once the pipeline is completely removed. WithPipeline = false -NoOfTokensPerChain = 2 # number of bridge tokens to be deployed per network; if MsgType = 'Token'/'DataWithToken' -CCIPOwnerTokens = false # if true, the test will use deploy the tokens by the CCIPOwner, otherwise the tokens will be deployed by a non-owner account, only applicable for 1.5 pools and onwards +NoOfTokensPerChain = 1 # number of bridge tokens to be deployed per network; if MsgType = 'Token'/'DataWithToken' +CCIPOwnerTokens = true # if true, the test will use deploy the tokens by the CCIPOwner, otherwise the tokens will be deployed by a non-owner account, only applicable for 1.5 pools and onwards #NoOfTokensWithDynamicPrice = 15 # number of tokens with dynamic price to be deployed #DynamicPriceUpdateInterval ='15s' # Periodic interval to update the price of tokens, if there are tokens with dynamic price