Skip to content

Commit

Permalink
Transfer to timelock (#15507)
Browse files Browse the repository at this point in the history
* Transfer to timelock

* Side quest support link view

* Adjust keystone

* KS test working

* Comments and fix test

* Comments and fix another test
  • Loading branch information
connorwstein authored Dec 4, 2024
1 parent 103dba2 commit 1bfd6e4
Show file tree
Hide file tree
Showing 29 changed files with 514 additions and 716 deletions.
15 changes: 15 additions & 0 deletions deployment/address_book.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,3 +256,18 @@ func SearchAddressBook(ab AddressBook, chain uint64, typ ContractType) (string,

return "", fmt.Errorf("not found")
}

func AddressBookContains(ab AddressBook, chain uint64, addrToFind string) (bool, error) {
addrs, err := ab.AddressesForChain(chain)
if err != nil {
return false, err
}

for addr := range addrs {
if addr == addrToFind {
return true, nil
}
}

return false, nil
}
108 changes: 26 additions & 82 deletions deployment/ccip/changeset/accept_ownership_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,10 @@ package changeset

import (
"testing"
"time"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers"

"github.com/smartcontractkit/chainlink-common/pkg/utils/tests"

commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset"
"github.com/smartcontractkit/chainlink/deployment/environment/memory"

Expand Down Expand Up @@ -47,15 +43,9 @@ func Test_NewAcceptOwnershipChangeset(t *testing.T) {
_, err = commonchangeset.ApplyChangesets(t, e.Env, timelocks, []commonchangeset.ChangesetApplication{
// note this doesn't have proposals.
{
Changeset: commonchangeset.WrapChangeSet(commonchangeset.NewTransferOwnershipChangeset),
Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock),
Config: genTestTransferOwnershipConfig(e, allChains, state),
},
// this has proposals, ApplyChangesets will sign & execute them.
// in practice, signing and executing are separated processes.
{
Changeset: commonchangeset.WrapChangeSet(commonchangeset.NewAcceptOwnershipChangeset),
Config: genTestAcceptOwnershipConfig(e, allChains, state),
},
})
require.NoError(t, err)

Expand All @@ -66,76 +56,35 @@ func genTestTransferOwnershipConfig(
e DeployedEnv,
chains []uint64,
state CCIPOnChainState,
) commonchangeset.TransferOwnershipConfig {
) commonchangeset.TransferToMCMSWithTimelockConfig {
var (
timelocksPerChain = make(map[uint64]common.Address)
contracts = make(map[uint64][]commonchangeset.OwnershipTransferrer)
contracts = make(map[uint64][]common.Address)
)

// chain contracts
for _, chain := range chains {
timelocksPerChain[chain] = state.Chains[chain].Timelock.Address()
contracts[chain] = []commonchangeset.OwnershipTransferrer{
state.Chains[chain].OnRamp,
state.Chains[chain].OffRamp,
state.Chains[chain].FeeQuoter,
state.Chains[chain].NonceManager,
state.Chains[chain].RMNRemote,
contracts[chain] = []common.Address{
state.Chains[chain].OnRamp.Address(),
state.Chains[chain].OffRamp.Address(),
state.Chains[chain].FeeQuoter.Address(),
state.Chains[chain].NonceManager.Address(),
state.Chains[chain].RMNRemote.Address(),
}
}

// home chain
homeChainTimelockAddress := state.Chains[e.HomeChainSel].Timelock.Address()
timelocksPerChain[e.HomeChainSel] = homeChainTimelockAddress
contracts[e.HomeChainSel] = append(contracts[e.HomeChainSel],
state.Chains[e.HomeChainSel].CapabilityRegistry,
state.Chains[e.HomeChainSel].CCIPHome,
state.Chains[e.HomeChainSel].RMNHome,
)

return commonchangeset.TransferOwnershipConfig{
OwnersPerChain: timelocksPerChain,
Contracts: contracts,
}
}

func genTestAcceptOwnershipConfig(
e DeployedEnv,
chains []uint64,
state CCIPOnChainState,
) commonchangeset.AcceptOwnershipConfig {
var (
timelocksPerChain = make(map[uint64]common.Address)
proposerMCMses = make(map[uint64]*gethwrappers.ManyChainMultiSig)
contracts = make(map[uint64][]commonchangeset.OwnershipAcceptor)
)
for _, chain := range chains {
timelocksPerChain[chain] = state.Chains[chain].Timelock.Address()
proposerMCMses[chain] = state.Chains[chain].ProposerMcm
contracts[chain] = []commonchangeset.OwnershipAcceptor{
state.Chains[chain].OnRamp,
state.Chains[chain].OffRamp,
state.Chains[chain].FeeQuoter,
state.Chains[chain].NonceManager,
state.Chains[chain].RMNRemote,
}
}

// add home chain contracts.
// this overwrite should be fine.
timelocksPerChain[e.HomeChainSel] = state.Chains[e.HomeChainSel].Timelock.Address()
proposerMCMses[e.HomeChainSel] = state.Chains[e.HomeChainSel].ProposerMcm
contracts[e.HomeChainSel] = append(contracts[e.HomeChainSel],
state.Chains[e.HomeChainSel].CapabilityRegistry,
state.Chains[e.HomeChainSel].CCIPHome,
state.Chains[e.HomeChainSel].RMNHome,
state.Chains[e.HomeChainSel].CapabilityRegistry.Address(),
state.Chains[e.HomeChainSel].CCIPHome.Address(),
state.Chains[e.HomeChainSel].RMNHome.Address(),
)

return commonchangeset.AcceptOwnershipConfig{
OwnersPerChain: timelocksPerChain,
ProposerMCMSes: proposerMCMses,
Contracts: contracts,
MinDelay: time.Duration(0),
return commonchangeset.TransferToMCMSWithTimelockConfig{
ContractsByChain: contracts,
}
}

Expand All @@ -147,34 +96,29 @@ func assertTimelockOwnership(
chains []uint64,
state CCIPOnChainState,
) {
ctx := tests.Context(t)
// check that the ownership has been transferred correctly
for _, chain := range chains {
for _, contract := range []commonchangeset.OwnershipTransferrer{
state.Chains[chain].OnRamp,
state.Chains[chain].OffRamp,
state.Chains[chain].FeeQuoter,
state.Chains[chain].NonceManager,
state.Chains[chain].RMNRemote,
for _, contract := range []common.Address{
state.Chains[chain].OnRamp.Address(),
state.Chains[chain].OffRamp.Address(),
state.Chains[chain].FeeQuoter.Address(),
state.Chains[chain].NonceManager.Address(),
state.Chains[chain].RMNRemote.Address(),
} {
owner, err := contract.Owner(&bind.CallOpts{
Context: ctx,
})
owner, _, err := commonchangeset.LoadOwnableContract(contract, e.Env.Chains[chain].Client)
require.NoError(t, err)
require.Equal(t, state.Chains[chain].Timelock.Address(), owner)
}
}

// check home chain contracts ownership
homeChainTimelockAddress := state.Chains[e.HomeChainSel].Timelock.Address()
for _, contract := range []commonchangeset.OwnershipTransferrer{
state.Chains[e.HomeChainSel].CapabilityRegistry,
state.Chains[e.HomeChainSel].CCIPHome,
state.Chains[e.HomeChainSel].RMNHome,
for _, contract := range []common.Address{
state.Chains[e.HomeChainSel].CapabilityRegistry.Address(),
state.Chains[e.HomeChainSel].CCIPHome.Address(),
state.Chains[e.HomeChainSel].RMNHome.Address(),
} {
owner, err := contract.Owner(&bind.CallOpts{
Context: ctx,
})
owner, _, err := commonchangeset.LoadOwnableContract(contract, e.Env.Chains[e.HomeChainSel].Client)
require.NoError(t, err)
require.Equal(t, homeChainTimelockAddress, owner)
}
Expand Down
8 changes: 1 addition & 7 deletions deployment/ccip/changeset/cs_active_candidate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,9 @@ func TestActiveCandidate(t *testing.T) {
_, err = commonchangeset.ApplyChangesets(t, e, timelocks, []commonchangeset.ChangesetApplication{
// note this doesn't have proposals.
{
Changeset: commonchangeset.WrapChangeSet(commonchangeset.NewTransferOwnershipChangeset),
Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock),
Config: genTestTransferOwnershipConfig(tenv, allChains, state),
},
// this has proposals, ApplyChangesets will sign & execute them.
// in practice, signing and executing are separated processes.
{
Changeset: commonchangeset.WrapChangeSet(commonchangeset.NewAcceptOwnershipChangeset),
Config: genTestAcceptOwnershipConfig(tenv, allChains, state),
},
})
require.NoError(t, err)
// Apply the accept ownership proposal to all the chains.
Expand Down
41 changes: 25 additions & 16 deletions deployment/ccip/changeset/cs_add_chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,21 @@ func TestAddChainInbound(t *testing.T) {
TimelockExecutors: e.Env.AllDeployerKeys(),
TimelockMinDelay: big.NewInt(0),
}
out, err := commonchangeset.DeployMCMSWithTimelock(e.Env, map[uint64]commontypes.MCMSWithTimelockConfig{
initialDeploy[0]: cfg,
initialDeploy[1]: cfg,
initialDeploy[2]: cfg,
e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{
{
Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken),
Config: initialDeploy,
},
{
Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock),
Config: map[uint64]commontypes.MCMSWithTimelockConfig{
initialDeploy[0]: cfg,
initialDeploy[1]: cfg,
initialDeploy[2]: cfg,
},
},
})
require.NoError(t, err)
require.NoError(t, e.Env.ExistingAddresses.Merge(out.AddressBook))
newAddresses = deployment.NewMemoryAddressBook()
tokenConfig := NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds)

Expand Down Expand Up @@ -99,12 +107,19 @@ func TestAddChainInbound(t *testing.T) {
require.NoError(t, err)

// Deploy contracts to new chain
out, err = commonchangeset.DeployMCMSWithTimelock(e.Env, map[uint64]commontypes.MCMSWithTimelockConfig{
newChain: cfg,
e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{
{
Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken),
Config: []uint64{newChain},
},
{
Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock),
Config: map[uint64]commontypes.MCMSWithTimelockConfig{
newChain: cfg,
},
},
})
require.NoError(t, err)
require.NoError(t, e.Env.ExistingAddresses.Merge(out.AddressBook))

newAddresses = deployment.NewMemoryAddressBook()

err = deployPrerequisiteChainContracts(e.Env, newAddresses, []uint64{newChain}, nil)
Expand Down Expand Up @@ -138,15 +153,9 @@ func TestAddChainInbound(t *testing.T) {
}, []commonchangeset.ChangesetApplication{
// note this doesn't have proposals.
{
Changeset: commonchangeset.WrapChangeSet(commonchangeset.NewTransferOwnershipChangeset),
Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock),
Config: genTestTransferOwnershipConfig(e, initialDeploy, state),
},
// this has proposals, ApplyChangesets will sign & execute them.
// in practice, signing and executing are separated processes.
{
Changeset: commonchangeset.WrapChangeSet(commonchangeset.NewAcceptOwnershipChangeset),
Config: genTestAcceptOwnershipConfig(e, initialDeploy, state),
},
})
require.NoError(t, err)

Expand Down
64 changes: 34 additions & 30 deletions deployment/ccip/changeset/cs_deploy_chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,6 @@ func TestDeployChainContractsChangeset(t *testing.T) {
nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain)
require.NoError(t, err)
p2pIds := nodes.NonBootstraps().PeerIDs()
// deploy home chain
homeChainCfg := DeployHomeChainConfig{
HomeChainSel: homeChainSel,
RMNStaticConfig: NewTestRMNStaticConfig(),
RMNDynamicConfig: NewTestRMNDynamicConfig(),
NodeOperators: NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From),
NodeP2PIDsPerNodeOpAdmin: map[string][][32]byte{
"NodeOperator": p2pIds,
},
}
output, err := DeployHomeChain(e, homeChainCfg)
require.NoError(t, err)
require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook))

// deploy pre-requisites
prerequisites, err := DeployPrerequisites(e, DeployPrerequisiteConfig{
ChainSelectors: selectors,
})
require.NoError(t, err)
require.NoError(t, e.ExistingAddresses.Merge(prerequisites.AddressBook))

cfg := make(map[uint64]commontypes.MCMSWithTimelockConfig)
for _, chain := range e.AllChainSelectors() {
cfg[chain] = commontypes.MCMSWithTimelockConfig{
Expand All @@ -59,17 +38,42 @@ func TestDeployChainContractsChangeset(t *testing.T) {
TimelockMinDelay: big.NewInt(0),
}
}
output, err = commonchangeset.DeployMCMSWithTimelock(e, cfg)
require.NoError(t, err)
require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook))

// deploy ccip chain contracts
output, err = DeployChainContracts(e, DeployChainContractsConfig{
ChainSelectors: selectors,
HomeChainSelector: homeChainSel,
e, err = commonchangeset.ApplyChangesets(t, e, nil, []commonchangeset.ChangesetApplication{
{
Changeset: commonchangeset.WrapChangeSet(DeployHomeChain),
Config: DeployHomeChainConfig{
HomeChainSel: homeChainSel,
RMNStaticConfig: NewTestRMNStaticConfig(),
RMNDynamicConfig: NewTestRMNDynamicConfig(),
NodeOperators: NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From),
NodeP2PIDsPerNodeOpAdmin: map[string][][32]byte{
"NodeOperator": p2pIds,
},
},
},
{
Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken),
Config: selectors,
},
{
Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock),
Config: cfg,
},
{
Changeset: commonchangeset.WrapChangeSet(DeployPrerequisites),
Config: DeployPrerequisiteConfig{
ChainSelectors: selectors,
},
},
{
Changeset: commonchangeset.WrapChangeSet(DeployChainContracts),
Config: DeployChainContractsConfig{
ChainSelectors: selectors,
HomeChainSelector: homeChainSel,
},
},
})
require.NoError(t, err)
require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook))

// load onchain state
state, err := LoadOnchainState(e)
Expand Down
Loading

0 comments on commit 1bfd6e4

Please sign in to comment.