Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CCIP-3591 USDC Integration Tests #15279

Merged
merged 25 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading