Skip to content

Commit

Permalink
CCIP-3591 USDC Integration Tests (#15279)
Browse files Browse the repository at this point in the history
* Stub

* Adding missing deployments parts

* Adding missing deployments parts

* Failing but trying to process, missing attestation

* Bump

* Green run

* Refactor

* Minor refactor

* Minor refactor

* Minor refactor

* Minor refactor

* Final refactor

* Post merge fixes

* Post review fixes

* Post review fixes

* Post review fixes

* Post review fixes

* Post review fixes

* Post review fixes

* Post review fixes

* Post review fixes

* Post review fixes

* Post review fixes

* Post review fixes
  • Loading branch information
mateusz-sekara authored Nov 18, 2024
1 parent 1f9c07d commit 276d1f3
Show file tree
Hide file tree
Showing 24 changed files with 1,305 additions and 49 deletions.
5 changes: 5 additions & 0 deletions .changeset/seven-schools-invent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": patch
---

Integration tests for USDC token transfer #internal
14 changes: 14 additions & 0 deletions .github/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,20 @@ runner-test-matrix:
E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2
E2E_JD_VERSION: 0.4.0

- id: smoke/ccip_usdc_test.go:*
path: integration-tests/smoke/ccip_usdc_test.go
test_env_type: docker
runs_on: ubuntu-latest
triggers:
- PR E2E Core Tests
- Merge Queue E2E Core Tests
- Nightly E2E Tests
test_cmd: cd integration-tests/ && go test smoke/ccip_usdc_test.go -timeout 12m -test.parallel=1 -count=1 -json
pyroscope_env: ci-smoke-ccipv1_6-evm-simulated
test_env_vars:
E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2
E2E_JD_VERSION: 0.4.0

- id: smoke/fee_boosting_test.go:*
path: integration-tests/smoke/fee_boosting_test.go
test_env_type: docker
Expand Down
142 changes: 141 additions & 1 deletion core/scripts/go.mod

Large diffs are not rendered by default.

461 changes: 454 additions & 7 deletions core/scripts/go.sum

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions deployment/ccip/changeset/active_candidate.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ func SetCandidatePluginChangeset(
tokenConfig.GetTokenInfo(e.Logger, state.Chains[newChainSel].LinkToken, state.Chains[newChainSel].Weth9),
nodes.NonBootstraps(),
state.Chains[homeChainSel].RMNHome.Address(),
nil,
)
if err != nil {
return deployment.ChangesetOutput{}, err
Expand Down
1 change: 1 addition & 0 deletions deployment/ccip/changeset/active_candidate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ func TestActiveCandidate(t *testing.T) {
tokenConfig.GetTokenInfo(e.Logger, state.Chains[destCS].LinkToken, state.Chains[destCS].Weth9),
nodes.NonBootstraps(),
rmnHomeAddress,
nil,
)
require.NoError(t, err)

Expand Down
1 change: 1 addition & 0 deletions deployment/ccip/changeset/add_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ func AddDonAndSetCandidateChangeset(
tokenConfig.GetTokenInfo(e.Logger, state.Chains[newChainSel].LinkToken, state.Chains[newChainSel].Weth9),
nodes.NonBootstraps(),
state.Chains[homeChainSel].RMNHome.Address(),
nil,
)
if err != nil {
return deployment.ChangesetOutput{}, err
Expand Down
1 change: 1 addition & 0 deletions deployment/ccip/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ type TokenSymbol string
const (
LinkSymbol TokenSymbol = "LINK"
WethSymbol TokenSymbol = "WETH"
USDCSymbol TokenSymbol = "USDC"
LinkDecimals = 18
WethDecimals = 18
)
67 changes: 62 additions & 5 deletions deployment/ccip/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import (
"github.com/pkg/errors"
"github.com/smartcontractkit/ccip-owner-contracts/pkg/config"
owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers"

cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3"
"github.com/smartcontractkit/chainlink-ccip/pluginconfig"
commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config"
"github.com/smartcontractkit/chainlink-common/pkg/logger"

"github.com/smartcontractkit/chainlink/deployment"
Expand Down Expand Up @@ -56,10 +58,14 @@ var (
CapabilitiesRegistry deployment.ContractType = "CapabilitiesRegistry"
PriceFeed deployment.ContractType = "PriceFeed"
// Note test router maps to a regular router contract.
TestRouter deployment.ContractType = "TestRouter"
CCIPReceiver deployment.ContractType = "CCIPReceiver"
BurnMintToken deployment.ContractType = "BurnMintToken"
BurnMintTokenPool deployment.ContractType = "BurnMintTokenPool"
TestRouter deployment.ContractType = "TestRouter"
CCIPReceiver deployment.ContractType = "CCIPReceiver"
BurnMintToken deployment.ContractType = "BurnMintToken"
BurnMintTokenPool deployment.ContractType = "BurnMintTokenPool"
USDCToken deployment.ContractType = "USDCToken"
USDCMockTransmitter deployment.ContractType = "USDCMockTransmitter"
USDCTokenMessenger deployment.ContractType = "USDCTokenMessenger"
USDCTokenPool deployment.ContractType = "USDCTokenPool"
)

func DeployPrerequisiteChainContracts(e deployment.Environment, ab deployment.AddressBook, selectors []uint64) error {
Expand Down Expand Up @@ -263,6 +269,17 @@ func DeployPrerequisiteContracts(e deployment.Environment, ab deployment.Address
return nil
}

type USDCConfig struct {
Enabled bool
USDCAttestationConfig
}

type USDCAttestationConfig struct {
API string
APITimeout *commonconfig.Duration
APIInterval *commonconfig.Duration
}

type DeployCCIPContractConfig struct {
HomeChainSel uint64
FeedChainSel uint64
Expand All @@ -271,6 +288,7 @@ type DeployCCIPContractConfig struct {
// I believe it makes sense to have the same signers across all chains
// since that's the point MCMS.
MCMSConfig MCMSConfig
USDCConfig USDCConfig
// For setting OCR configuration
OCRSecrets deployment.OCRSecrets
}
Expand Down Expand Up @@ -332,6 +350,7 @@ func DeployCCIPContracts(e deployment.Environment, ab deployment.AddressBook, c
return fmt.Errorf("rmn home not found")
}

usdcConfiguration := make(map[cciptypes.ChainSelector]pluginconfig.USDCCCTPTokenConfig)
for _, chainSel := range c.ChainsToDeploy {
chain, ok := e.Chains[chainSel]
if !ok {
Expand All @@ -344,6 +363,30 @@ func DeployCCIPContracts(e deployment.Environment, ab deployment.AddressBook, c
if err != nil {
return err
}

if c.USDCConfig.Enabled {
token, pool, messenger, transmitter, err1 := DeployUSDC(e.Logger, chain, ab, existingState.Chains[chainSel])
if err1 != nil {
return err1
}
e.Logger.Infow("Deployed USDC contracts",
"chainSelector", chainSel,
"token", token.Address(),
"pool", pool.Address(),
"transmitter", transmitter.Address(),
"messenger", messenger.Address(),
)

usdcConfiguration[cciptypes.ChainSelector(chainSel)] = pluginconfig.USDCCCTPTokenConfig{
SourcePoolAddress: pool.Address().Hex(),
SourceMessageTransmitterAddr: transmitter.Address().Hex(),
}
}
}

for _, chainSel := range c.ChainsToDeploy {
chain, _ := e.Chains[chainSel]

chainAddresses, err := ab.AddressesForChain(chain.Selector)
if err != nil {
e.Logger.Errorw("Failed to get chain addresses", "err", err)
Expand All @@ -367,6 +410,19 @@ func DeployCCIPContracts(e deployment.Environment, ab deployment.AddressBook, c
if err != nil {
return err
}
var tokenDataObserversConf []pluginconfig.TokenDataObserverConfig
if c.USDCConfig.Enabled {
tokenDataObserversConf = []pluginconfig.TokenDataObserverConfig{{
Type: pluginconfig.USDCCCTPHandlerType,
Version: "1.0",
USDCCCTPObserverConfig: &pluginconfig.USDCCCTPObserverConfig{
Tokens: usdcConfiguration,
AttestationAPI: c.USDCConfig.API,
AttestationAPITimeout: c.USDCConfig.APITimeout,
AttestationAPIInterval: c.USDCConfig.APIInterval,
},
}}
}
// For each chain, we create a DON on the home chain (2 OCR instances)
if err := AddDON(
e.Logger,
Expand All @@ -380,6 +436,7 @@ func DeployCCIPContracts(e deployment.Environment, ab deployment.AddressBook, c
chain,
e.Chains[c.HomeChainSel],
nodes.NonBootstraps(),
tokenDataObserversConf,
); err != nil {
e.Logger.Errorw("Failed to add DON", "err", err)
return err
Expand Down
7 changes: 5 additions & 2 deletions deployment/ccip/deploy_home_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ func BuildOCR3ConfigForCCIPHome(
tokenInfo map[ccipocr3.UnknownEncodedAddress]pluginconfig.TokenInfo,
nodes deployment.Nodes,
rmnHomeAddress common.Address,
configs []pluginconfig.TokenDataObserverConfig,
) (map[cctypes.PluginType]ccip_home.CCIPHomeOCR3Config, error) {
p2pIDs := nodes.PeerIDs()
// Get OCR3 Config from helper
Expand Down Expand Up @@ -438,7 +439,7 @@ func BuildOCR3ConfigForCCIPHome(
InflightCacheExpiry: *commonconfig.MustNewDuration(InflightCacheExpiry),
RootSnoozeTime: *commonconfig.MustNewDuration(RootSnoozeTime),
BatchingStrategyID: BatchingStrategyID,
TokenDataObservers: []pluginconfig.TokenDataObserverConfig{},
TokenDataObservers: configs,
})
}
if err2 != nil {
Expand Down Expand Up @@ -969,8 +970,10 @@ func AddDON(
dest deployment.Chain,
home deployment.Chain,
nodes deployment.Nodes,
tokenConfigs []pluginconfig.TokenDataObserverConfig,
) error {
ocrConfigs, err := BuildOCR3ConfigForCCIPHome(ocrSecrets, offRamp, dest, feedChainSel, tokenInfo, nodes, rmnHomeAddress)
ocrConfigs, err := BuildOCR3ConfigForCCIPHome(
ocrSecrets, offRamp, dest, feedChainSel, tokenInfo, nodes, rmnHomeAddress, tokenConfigs)
if err != nil {
return err
}
Expand Down
36 changes: 34 additions & 2 deletions deployment/ccip/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package ccipdeployment

import (
"fmt"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_messenger"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_transmitter"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_token_pool"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -80,8 +83,11 @@ type CCIPChainState struct {
CCIPConfig *ccip_config.CCIPConfig

// Test contracts
Receiver *maybe_revert_message_receiver.MaybeRevertMessageReceiver
TestRouter *router.Router
Receiver *maybe_revert_message_receiver.MaybeRevertMessageReceiver
TestRouter *router.Router
USDCTokenPool *usdc_token_pool.USDCTokenPool
MockUSDCTransmitter *mock_usdc_token_transmitter.MockE2EUSDCTransmitter
MockUSDCTokenMessenger *mock_usdc_token_messenger.MockE2EUSDCTokenMessenger
}

func (c CCIPChainState) GenerateView() (view.ChainView, error) {
Expand Down Expand Up @@ -372,6 +378,32 @@ func LoadChainState(chain deployment.Chain, addresses map[string]deployment.Type
return state, err
}
state.LinkToken = lt
case deployment.NewTypeAndVersion(USDCToken, deployment.Version1_0_0).String():
ut, err := burn_mint_erc677.NewBurnMintERC677(common.HexToAddress(address), chain.Client)
if err != nil {
return state, err
}
state.BurnMintTokens677 = map[TokenSymbol]*burn_mint_erc677.BurnMintERC677{
USDCSymbol: ut,
}
case deployment.NewTypeAndVersion(USDCTokenPool, deployment.Version1_0_0).String():
utp, err := usdc_token_pool.NewUSDCTokenPool(common.HexToAddress(address), chain.Client)
if err != nil {
return state, err
}
state.USDCTokenPool = utp
case deployment.NewTypeAndVersion(USDCMockTransmitter, deployment.Version1_0_0).String():
umt, err := mock_usdc_token_transmitter.NewMockE2EUSDCTransmitter(common.HexToAddress(address), chain.Client)
if err != nil {
return state, err
}
state.MockUSDCTransmitter = umt
case deployment.NewTypeAndVersion(USDCTokenMessenger, deployment.Version1_0_0).String():
utm, err := mock_usdc_token_messenger.NewMockE2EUSDCTokenMessenger(common.HexToAddress(address), chain.Client)
if err != nil {
return state, err
}
state.MockUSDCTokenMessenger = utm
case deployment.NewTypeAndVersion(CCIPHome, deployment.Version1_6_0_dev).String():
ccipHome, err := ccip_home.NewCCIPHome(common.HexToAddress(address), chain.Client)
if err != nil {
Expand Down
74 changes: 54 additions & 20 deletions deployment/ccip/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,43 +9,36 @@ import (
"time"

mapset "github.com/deckarep/golang-set/v2"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"

"github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"

cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3"
commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils"
"github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext"

"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677"

"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"

"go.uber.org/multierr"
"go.uber.org/zap/zapcore"

chainsel "github.com/smartcontractkit/chain-selectors"

"github.com/smartcontractkit/chainlink-ccip/pkg/reader"
cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3"
"github.com/smartcontractkit/chainlink-common/pkg/logger"
commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils"
jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job"
"github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext"

"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_ethusd_aggregator_wrapper"

"github.com/smartcontractkit/chainlink/deployment/environment/memory"

"github.com/smartcontractkit/chainlink-common/pkg/logger"

"github.com/smartcontractkit/chainlink/deployment/environment/devenv"
"github.com/smartcontractkit/chainlink/deployment/environment/memory"

"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/burn_mint_token_pool"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_v3_aggregator_contract"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_token_pool"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_ethusd_aggregator_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677"
)

const (
Expand Down Expand Up @@ -574,18 +567,19 @@ func DeployTransferableToken(
}

// Add burn/mint permissions
if err := grantMintBurnPermissions(chains[src], srcToken, srcPool.Address()); err != nil {
if err := grantMintBurnPermissions(lggr, chains[src], srcToken, srcPool.Address()); err != nil {
return nil, nil, nil, nil, err
}

if err := grantMintBurnPermissions(chains[dst], dstToken, dstPool.Address()); err != nil {
if err := grantMintBurnPermissions(lggr, chains[dst], dstToken, dstPool.Address()); err != nil {
return nil, nil, nil, nil, err
}

return srcToken, srcPool, dstToken, dstPool, nil
}

func grantMintBurnPermissions(chain deployment.Chain, token *burn_mint_erc677.BurnMintERC677, address common.Address) error {
func grantMintBurnPermissions(lggr logger.Logger, chain deployment.Chain, token *burn_mint_erc677.BurnMintERC677, address common.Address) error {
lggr.Infow("Granting burn permissions", "token", token.Address(), "burner", address)
tx, err := token.GrantBurnRole(chain.DeployerKey, address)
if err != nil {
return err
Expand All @@ -595,6 +589,7 @@ func grantMintBurnPermissions(chain deployment.Chain, token *burn_mint_erc677.Bu
return err
}

lggr.Infow("Granting mint permissions", "token", token.Address(), "minter", address)
tx, err = token.GrantMintRole(chain.DeployerKey, address)
if err != nil {
return err
Expand All @@ -603,6 +598,45 @@ func grantMintBurnPermissions(chain deployment.Chain, token *burn_mint_erc677.Bu
return err
}

func setUSDCTokenPoolCounterPart(
chain deployment.Chain,
tokenPool *usdc_token_pool.USDCTokenPool,
destChainSelector uint64,
destTokenAddress common.Address,
destTokenPoolAddress common.Address,
) error {
allowedCaller := common.LeftPadBytes(destTokenPoolAddress.Bytes(), 32)
var fixedAddr [32]byte
copy(fixedAddr[:], allowedCaller[:32])

domain, _ := reader.AllAvailableDomains()[destChainSelector]

domains := []usdc_token_pool.USDCTokenPoolDomainUpdate{
{
AllowedCaller: fixedAddr,
DomainIdentifier: domain,
DestChainSelector: destChainSelector,
Enabled: true,
},
}
tx, err := tokenPool.SetDomains(chain.DeployerKey, domains)
if err != nil {
return err
}

_, err = chain.Confirm(tx)
if err != nil {
return err
}

pool, err := burn_mint_token_pool.NewBurnMintTokenPool(tokenPool.Address(), chain.Client)
if err != nil {
return err
}

return setTokenPoolCounterPart(chain, pool, destChainSelector, destTokenAddress, destTokenPoolAddress)
}

func setTokenPoolCounterPart(
chain deployment.Chain,
tokenPool *burn_mint_token_pool.BurnMintTokenPool,
Expand Down
Loading

0 comments on commit 276d1f3

Please sign in to comment.