Skip to content

Commit 97ce85d

Browse files
committed
add setWatchList changeset
1 parent b5fa134 commit 97ce85d

3 files changed

Lines changed: 248 additions & 4 deletions

File tree

deployment/vault/changeset/ethbalmon_setKeeperRegistryAddress.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,10 @@ type SetKeeperRegistryOperationInput struct {
151151
}
152152

153153
type SetKeeperRegistryOperationOutput struct {
154-
ChainSelector uint64
155-
BatchOperation mcmstypes.BatchOperation
156-
TimelockAddress string
157-
MCMSAddress string
154+
ChainSelector uint64 `json:"chain_selector"`
155+
BatchOperation mcmstypes.BatchOperation `json:"batch_operation"`
156+
TimelockAddress string `json:"timelock_address"`
157+
MCMSAddress string `json:"mcms_address"`
158158
}
159159

160160
var SetKeeperRegistryOperation = operations.NewOperation(
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
package changeset
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"math/big"
7+
8+
"github.com/Masterminds/semver/v3"
9+
"github.com/ethereum/go-ethereum/common"
10+
"github.com/smartco ntractkit/mcms"
11+
cldf_evm "github.com/smartcontractkit/chainlink-deployments-framework/chain/evm"
12+
cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment"
13+
"github.com/smartcontractkit/chainlink-deployments-framework/operations"
14+
"github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/eth_balance_monitor_wrapper"
15+
"github.com/smartcontractkit/chainlink/deployment/common/proposalutils"
16+
commontypes "github.com/smartcontractkit/chainlink/deployment/common/types"
17+
vaulttypes "github.com/smartcontractkit/chainlink/deployment/vault/changeset/types"
18+
mcmssdk "github.com/smartcontractkit/mcms/sdk"
19+
mcmsevmsdk "github.com/smartcontractkit/mcms/sdk/evm"
20+
mcmstypes "github.com/smartcontractkit/mcms/types"
21+
)
22+
23+
type ethBalMonSetWatchList struct{}
24+
25+
var EthBalMonSetWatchList cldf.ChangeSetV2[vaulttypes.EthBalMonSetWatchListInput] = ethBalMonSetWatchList{}
26+
27+
func (sw ethBalMonSetWatchList) VerifyPreconditions(env cldf.Environment, config vaulttypes.EthBalMonSetWatchListInput) error {
28+
return nil
29+
30+
}
31+
32+
func (sw ethBalMonSetWatchList) Apply(e cldf.Environment, config vaulttypes.EthBalMonSetWatchListInput) (cldf.ChangesetOutput, error) {
33+
logger := e.Logger
34+
logger.Infow("Generating EthBalMon setWatchList proposal", "numChains", len(config.Chains))
35+
36+
evmChains := e.BlockChains.EVMChains()
37+
38+
var primaryChain cldf_evm.Chain
39+
for chainSelector := range config.Chains {
40+
primaryChain = evmChains[chainSelector]
41+
break
42+
}
43+
44+
deps := VaultDeps{
45+
Auth: primaryChain.DeployerKey,
46+
Chain: primaryChain,
47+
Environment: e,
48+
DataStore: e.DataStore,
49+
}
50+
51+
seqInput := EthBalMonSetWatchListSeqInput{
52+
Chains: config.Chains,
53+
}
54+
55+
seqReport, err := operations.ExecuteSequence(e.OperationsBundle, EthBalMonSetWatchListSequence, deps, seqInput)
56+
if err != nil {
57+
return cldf.ChangesetOutput{}, fmt.Errorf("failed on EthBalMonSetWatchListSequence sequence: %w", err)
58+
}
59+
60+
return cldf.ChangesetOutput{
61+
MCMSTimelockProposals: seqReport.Output.MCMSTimelockProposals,
62+
}, nil
63+
}
64+
65+
type EthBalMonSetWatchListSeqInput struct {
66+
Chains map[uint64]vaulttypes.EthBalMonSetWatchListChainConfig `json:"chains"`
67+
}
68+
69+
type EthBalMonSetWatchListSeqOutput struct {
70+
MCMSTimelockProposals []mcms.TimelockProposal `json:"mcms_timelock_proposals"`
71+
}
72+
73+
var EthBalMonSetWatchListSequence = operations.NewSequence(
74+
"ethbalmon-setWathcList-sequence",
75+
semver.MustParse("1.0.0"),
76+
"Sequence to create operations for EthBalMon setWatchList",
77+
func(b operations.Bundle, deps VaultDeps, input EthBalMonSetWatchListSeqInput) (EthBalMonSetWatchListSeqOutput, error) {
78+
b.Logger.Infow("Starting EthBalMon setWatchList sequence",
79+
"chains", len(input.Chains),
80+
)
81+
var batches []mcmstypes.BatchOperation
82+
timelockAddresses := make(map[uint64]string)
83+
mcmAddressByChain := make(map[uint64]string)
84+
inspectorPerChain := make(map[uint64]mcmssdk.Inspector)
85+
86+
for chainSelector, chainConfig := range input.Chains {
87+
opReport, err := operations.ExecuteOperation(b, EthBalMonSetWatchListOperation, deps, EthBalMonSetWatchListOpInput{
88+
ChainSelector: chainSelector,
89+
Addresses: chainConfig.Addresses,
90+
MinBalancesWei: chainConfig.MinBalancesWei,
91+
TopUpAmountsWei: chainConfig.TopUpAmountsWei,
92+
})
93+
opOutput := opReport.Output
94+
if err != nil {
95+
return EthBalMonSetWatchListSeqOutput{}, fmt.Errorf("chain %d: failed to generate setWatchList batch: %w", chainSelector, err)
96+
}
97+
batches = append(batches, opOutput.BatchOperation)
98+
timelockAddresses[chainSelector] = opOutput.TimelockAddress
99+
mcmAddressByChain[chainSelector] = opOutput.MCMSAddress
100+
inspectorPerChain[chainSelector] = opOutput.Inspector
101+
}
102+
103+
proposal, err := proposalutils.BuildProposalFromBatchesV2(deps.Environment, timelockAddresses, mcmAddressByChain, inspectorPerChain, batches, "EthBalMon SetWatchList", proposalutils.TimelockConfig{
104+
MinDelay: 0,
105+
})
106+
107+
if err != nil {
108+
return EthBalMonSetWatchListSeqOutput{}, fmt.Errorf("failed to build timelock proposal: %w", err)
109+
}
110+
b.Logger.Infow("Generated EthBalMon setWatchList proposal",
111+
"chains", len(input.Chains), "operations", len(batches))
112+
113+
return EthBalMonSetWatchListSeqOutput{
114+
MCMSTimelockProposals: []mcms.TimelockProposal{*proposal},
115+
}, nil
116+
},
117+
)
118+
119+
type EthBalMonSetWatchListOpInput struct {
120+
ChainSelector uint64 `json:"chain_selector"`
121+
Addresses []common.Address `json:"addresses"`
122+
MinBalancesWei []big.Int `json:"min_balance_wei"`
123+
TopUpAmountsWei []big.Int `json:"topup_amounts_wei"`
124+
}
125+
126+
type EthBalMonSetWatchListOpOutput struct {
127+
ChainSelector uint64 `json:"chain_selector"`
128+
BatchOperation mcmstypes.BatchOperation `json:"batch_operation"`
129+
TimelockAddress string `json:"timelock_address"`
130+
MCMSAddress string `json:"mcms_address"`
131+
Inspector *mcmsevmsdk.Inspector `json:"inspector"`
132+
}
133+
134+
var EthBalMonSetWatchListOperation = operations.NewOperation(
135+
"ethbalmon-setWathcList-operation",
136+
semver.MustParse("1.0.0"),
137+
"Operation to create transaction batch for EthBalMon setWatchList",
138+
func(b operations.Bundle, deps VaultDeps, input EthBalMonSetWatchListOpInput) (EthBalMonSetWatchListOpOutput, error) {
139+
b.Logger.Infow("Starting EthBalMon setWatchList operation",
140+
"chainsel", input.ChainSelector,
141+
"addresses", len(input.Addresses),
142+
)
143+
chain, ok := deps.Environment.BlockChains.EVMChains()[input.ChainSelector]
144+
145+
if !ok {
146+
return EthBalMonSetWatchListOpOutput{}, fmt.Errorf("chain not found in environment: %d", input.ChainSelector)
147+
}
148+
149+
ethBalMonAddr, err := mustGetContractAddress(
150+
deps.DataStore,
151+
input.ChainSelector,
152+
cldf.ContractType(vaulttypes.ETHBALMON_CONTRACT_TYPE),
153+
)
154+
if err != nil {
155+
return EthBalMonSetWatchListOpOutput{},
156+
fmt.Errorf("failed to get EthBalMon address: %w", err)
157+
}
158+
159+
timelockAddr, err := mustGetContractAddress(
160+
deps.DataStore,
161+
input.ChainSelector,
162+
commontypes.RBACTimelock,
163+
)
164+
if err != nil {
165+
return EthBalMonSetWatchListOpOutput{},
166+
fmt.Errorf("failed to get timelock address: %w", err)
167+
}
168+
mcmsAddr, err := mustGetContractAddress(
169+
deps.DataStore,
170+
input.ChainSelector,
171+
commontypes.ManyChainMultisig,
172+
)
173+
if err != nil {
174+
return EthBalMonSetWatchListOpOutput{},
175+
fmt.Errorf("failed to get MCMS address: %w", err)
176+
}
177+
178+
ethBalMon, err := eth_balance_monitor_wrapper.NewEthBalanceMonitor(
179+
common.HexToAddress(ethBalMonAddr),
180+
chain.Client,
181+
)
182+
if err != nil {
183+
return EthBalMonSetWatchListOpOutput{},
184+
fmt.Errorf("failed to instantiate EthBalanceMonitor at %s: %w", ethBalMonAddr, err)
185+
}
186+
187+
minBalancesWei := make([]*big.Int, len(input.MinBalancesWei))
188+
for i := range input.MinBalancesWei {
189+
minBalancesWei[i] = &input.MinBalancesWei[i]
190+
}
191+
192+
topAmountsWei := make([]*big.Int, len(input.TopUpAmountsWei))
193+
for i := range input.TopUpAmountsWei {
194+
topAmountsWei[i] = &input.TopUpAmountsWei[i]
195+
}
196+
setWatchListTx, err := ethBalMon.SetWatchList(cldf.SimTransactOpts(), input.Addresses, minBalancesWei, topAmountsWei)
197+
if err != nil {
198+
return EthBalMonSetWatchListOpOutput{}, fmt.Errorf("failed to generate setWatchList calldata on chain %d: %w ", input.ChainSelector, err)
199+
}
200+
201+
batch := mcmstypes.BatchOperation{
202+
ChainSelector: mcmstypes.ChainSelector(input.ChainSelector),
203+
Transactions: []mcmstypes.Transaction{
204+
{
205+
OperationMetadata: mcmstypes.OperationMetadata{
206+
ContractType: vaulttypes.ETHBALMON_CONTRACT_TYPE,
207+
Tags: []string{
208+
"setWatchList",
209+
},
210+
},
211+
To: ethBalMonAddr,
212+
Data: setWatchListTx.Data(),
213+
AdditionalFields: json.RawMessage(`{"value": 0}`),
214+
},
215+
},
216+
}
217+
218+
chainInspector := mcmsevmsdk.NewInspector(chain.Client)
219+
220+
b.Logger.Infow("Generated EthBalMon setWatchlist batch",
221+
"chainSelector", input.ChainSelector,
222+
"ethBalMon", ethBalMonAddr,
223+
"newWatchList", input.Addresses,
224+
)
225+
226+
return EthBalMonSetWatchListOpOutput{
227+
ChainSelector: input.ChainSelector,
228+
BatchOperation: batch,
229+
TimelockAddress: timelockAddr,
230+
MCMSAddress: mcmsAddr,
231+
Inspector: chainInspector,
232+
}, nil
233+
},
234+
)

deployment/vault/changeset/types/types.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package types
44
import (
55
"math/big"
66

7+
"github.com/ethereum/go-ethereum/common"
78
"github.com/smartcontractkit/chainlink/deployment/common/proposalutils"
89
)
910

@@ -101,3 +102,12 @@ type SetKeeperRegistryChainConfig struct {
101102
type EthBalMonSetKeeperRegistryAddressInput struct {
102103
Chains map[uint64]SetKeeperRegistryChainConfig `json:"chains"`
103104
}
105+
106+
type EthBalMonSetWatchListChainConfig struct {
107+
Addresses []common.Address `json:"addresses"`
108+
MinBalancesWei []big.Int `json:"min_balance_wei"`
109+
TopUpAmountsWei []big.Int `json:"topup_amounts_wei"`
110+
}
111+
type EthBalMonSetWatchListInput struct {
112+
Chains map[uint64]EthBalMonSetWatchListChainConfig `json:"chains"`
113+
}

0 commit comments

Comments
 (0)