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 12 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
2 changes: 1 addition & 1 deletion core/scripts/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ require (
github.com/shirou/gopsutil/v3 v3.24.3 // indirect
github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 // indirect
github.com/smartcontractkit/chain-selectors v1.0.27 // indirect
github.com/smartcontractkit/chainlink-ccip v0.0.0-20241111114733-aa3b2f8e9f94 // indirect
github.com/smartcontractkit/chainlink-ccip v0.0.0-20241115135201-8abdc446670e // indirect
github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect
github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e // indirect
github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect
Expand Down
4 changes: 2 additions & 2 deletions core/scripts/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1090,8 +1090,8 @@ github.com/smartcontractkit/chain-selectors v1.0.27 h1:VE/ftX9Aae4gnw67yR1raKi+3
github.com/smartcontractkit/chain-selectors v1.0.27/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE=
github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU=
github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08=
github.com/smartcontractkit/chainlink-ccip v0.0.0-20241111114733-aa3b2f8e9f94 h1:BeLnOf2KKQpJj9nzfnE7QEg9ZqJ2jy/sbpNYVixVM2Y=
github.com/smartcontractkit/chainlink-ccip v0.0.0-20241111114733-aa3b2f8e9f94/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis=
github.com/smartcontractkit/chainlink-ccip v0.0.0-20241115135201-8abdc446670e h1:UqpMF/C/RLIdyLvPPBbkvSyqMlhnHTJPdVNjtjvAyeA=
github.com/smartcontractkit/chainlink-ccip v0.0.0-20241115135201-8abdc446670e/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis=
github.com/smartcontractkit/chainlink-common v0.3.1-0.20241111184621-c61aebee0af9 h1:xjrbuLW28nJ661Hu9dodcCQm7ElB5AWnZjmqGiGLNZg=
github.com/smartcontractkit/chainlink-common v0.3.1-0.20241111184621-c61aebee0af9/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco=
github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw=
Expand Down
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
10 changes: 1 addition & 9 deletions deployment/ccip/changeset/active_candidate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,7 @@ func TestActiveCandidate(t *testing.T) {
// this will construct ocr3 configurations for the
// commit and exec plugin we will be using
rmnHomeAddress := state.Chains[homeCS].RMNHome.Address()
ocr3ConfigMap, err := ccdeploy.BuildOCR3ConfigForCCIPHome(
deployment.XXXGenerateTestOCRSecrets(),
state.Chains[destCS].OffRamp,
e.Chains[destCS],
destCS,
tokenConfig.GetTokenInfo(e.Logger, state.Chains[destCS].LinkToken, state.Chains[destCS].Weth9),
nodes.NonBootstraps(),
rmnHomeAddress,
)
ocr3ConfigMap, err := ccdeploy.BuildOCR3ConfigForCCIPHome(deployment.XXXGenerateTestOCRSecrets(), state.Chains[destCS].OffRamp, e.Chains[destCS], destCS, tokenConfig.GetTokenInfo(e.Logger, state.Chains[destCS].LinkToken, state.Chains[destCS].Weth9), nodes.NonBootstraps(), rmnHomeAddress, nil)
mateusz-sekara marked this conversation as resolved.
Show resolved Hide resolved
require.NoError(t, err)

setCommitCandidateOp, err := ccdeploy.SetCandidateOnExistingDon(
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
)
77 changes: 70 additions & 7 deletions deployment/ccip/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@ package ccipdeployment

import (
"fmt"
"math/big"

"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/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/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"
"math/big"

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

Expand Down Expand Up @@ -60,10 +65,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"
)

type Contracts interface {
Expand All @@ -86,7 +95,10 @@ type Contracts interface {
*burn_mint_token_pool.BurnMintTokenPool |
*maybe_revert_message_receiver.MaybeRevertMessageReceiver |
*aggregator_v3_interface.AggregatorV3Interface |
*erc20.ERC20
*erc20.ERC20 |
*mock_usdc_token_transmitter.MockE2EUSDCTransmitter |
*mock_usdc_token_messenger.MockE2EUSDCTokenMessenger |
*usdc_token_pool.USDCTokenPool
}

type ContractDeploy[C Contracts] struct {
Expand Down Expand Up @@ -125,6 +137,17 @@ func deployContract[C Contracts](
return &contractDeploy, 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 @@ -133,6 +156,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 @@ -194,6 +218,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 @@ -209,6 +234,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)
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 @@ -232,6 +281,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 @@ -245,6 +307,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 @@ -77,8 +80,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 @@ -351,6 +357,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
52 changes: 47 additions & 5 deletions deployment/ccip/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package ccipdeployment
import (
"context"
"fmt"
mapset "github.com/deckarep/golang-set/v2"
"github.com/smartcontractkit/chainlink-ccip/pkg/reader"
mateusz-sekara marked this conversation as resolved.
Show resolved Hide resolved
"math/big"
"sort"
"testing"
"time"

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

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

Expand All @@ -18,6 +18,7 @@ import (
cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3"
"github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext"

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

"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -525,18 +526,19 @@ func DeployTransferableToken(
}

// Add burn/mint permissions
if err := grantMintBurnPermissions(chains[src], srcToken, srcPool.Address()); err != nil {
if err := grantMintBurnPermissions(nil, chains[src], srcToken, srcPool.Address()); err != nil {
mateusz-sekara marked this conversation as resolved.
Show resolved Hide resolved
return nil, nil, nil, nil, err
}

if err := grantMintBurnPermissions(chains[dst], dstToken, dstPool.Address()); err != nil {
if err := grantMintBurnPermissions(nil, 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 @@ -546,6 +548,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 @@ -554,6 +557,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