Skip to content

Commit e1a60bb

Browse files
authored
fix: use opscontract.WriteOutput in set-config (#107)
We can get rid of some types in `set-config` operations and instead use the types provided by CLDF. This way we avoid having redundant types in the codebase and centralize evm common types with the types provided by opsgen pkgs.
1 parent 2da6931 commit e1a60bb

6 files changed

Lines changed: 95 additions & 123 deletions

File tree

mcms/evm/internal/gasboost/gas_boost.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,32 @@
11
package gasboost
22

33
import (
4+
"math/big"
5+
6+
"github.com/ethereum/go-ethereum/accounts/abi/bind"
47
cldfevm "github.com/smartcontractkit/chainlink-deployments-framework/chain/evm"
58
opscontract "github.com/smartcontractkit/chainlink-deployments-framework/chain/evm/operations2/contract"
69
cldfproposalutils "github.com/smartcontractkit/chainlink-deployments-framework/engine/cld/mcms/proposalutils"
710
"github.com/smartcontractkit/chainlink-deployments-framework/operations"
811
)
912

13+
// CloneTransactOptsWithGas returns a copy of opts with optional gas limit and price overrides.
14+
func CloneTransactOptsWithGas(opts *bind.TransactOpts, gasLimit, gasPrice uint64) *bind.TransactOpts {
15+
if opts == nil {
16+
return nil
17+
}
18+
19+
newOpts := *opts
20+
if gasLimit > 0 {
21+
newOpts.GasLimit = gasLimit
22+
}
23+
if gasPrice > 0 {
24+
newOpts.GasPrice = new(big.Int).SetUint64(gasPrice)
25+
}
26+
27+
return &newOpts
28+
}
29+
1030
// ToContractConfig converts proposal gas-boost settings to framework contract gas-boost config.
1131
func ToContractConfig(cfg *cldfproposalutils.GasBoostConfig) *opscontract.GasBoostConfig {
1232
if cfg == nil {

mcms/evm/internal/gasboost/gas_boost_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,30 @@
11
package gasboost
22

33
import (
4+
"math/big"
45
"testing"
56

7+
"github.com/ethereum/go-ethereum/accounts/abi/bind"
68
cldfproposalutils "github.com/smartcontractkit/chainlink-deployments-framework/engine/cld/mcms/proposalutils"
79
"github.com/stretchr/testify/require"
810
)
911

12+
func TestCloneTransactOptsWithGas(t *testing.T) {
13+
t.Parallel()
14+
15+
require.Nil(t, CloneTransactOptsWithGas(nil, 100, 200))
16+
17+
opts := &bind.TransactOpts{GasLimit: 1, GasPrice: big.NewInt(1)}
18+
got := CloneTransactOptsWithGas(opts, 0, 0)
19+
require.Equal(t, uint64(1), got.GasLimit)
20+
require.Equal(t, int64(1), got.GasPrice.Int64())
21+
require.NotSame(t, opts, got)
22+
23+
got = CloneTransactOptsWithGas(opts, 500_000, 30_000_000_000)
24+
require.Equal(t, uint64(500_000), got.GasLimit)
25+
require.Equal(t, uint64(30_000_000_000), got.GasPrice.Uint64())
26+
}
27+
1028
func TestToContractConfig(t *testing.T) {
1129
t.Parallel()
1230

mcms/evm/set-config/evm_call.go

Lines changed: 0 additions & 33 deletions
This file was deleted.

mcms/evm/set-config/operation.go

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,20 @@ package evmsetconfig
22

33
import (
44
"fmt"
5+
"math/big"
56

67
"github.com/Masterminds/semver/v3"
78
"github.com/ethereum/go-ethereum/accounts/abi/bind"
89
"github.com/ethereum/go-ethereum/common"
910
"github.com/ethereum/go-ethereum/core/types"
10-
mcmsevm "github.com/smartcontractkit/mcms/sdk/evm"
11-
mcmsbindings "github.com/smartcontractkit/mcms/sdk/evm/bindings"
12-
mcmstypes "github.com/smartcontractkit/mcms/types"
13-
1411
cldf_evm "github.com/smartcontractkit/chainlink-deployments-framework/chain/evm"
12+
opscontract "github.com/smartcontractkit/chainlink-deployments-framework/chain/evm/operations2/contract"
1513
cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment"
1614
cldfproposalutils "github.com/smartcontractkit/chainlink-deployments-framework/engine/cld/mcms/proposalutils"
1715
"github.com/smartcontractkit/chainlink-deployments-framework/operations"
16+
mcmsevm "github.com/smartcontractkit/mcms/sdk/evm"
17+
mcmsbindings "github.com/smartcontractkit/mcms/sdk/evm/bindings"
18+
mcmstypes "github.com/smartcontractkit/mcms/types"
1819

1920
"github.com/smartcontractkit/cld-changesets/mcms/evm/internal/gasboost"
2021
)
@@ -50,50 +51,62 @@ var OpEVMSetConfigMCM = operations.NewOperation(
5051
"evm-mcm-set-config",
5152
semver.MustParse("1.0.0"),
5253
"Sets MCMS config on an EVM MCM contract",
53-
func(b operations.Bundle, deps cldf_evm.Chain, in OpEVMSetConfigInput) (EVMCallOutput, error) {
54+
func(b operations.Bundle, deps cldf_evm.Chain, in OpEVMSetConfigInput) (opscontract.WriteOutput, error) {
5455
if !in.NoSend && deps.DeployerKey == nil {
55-
return EVMCallOutput{}, fmt.Errorf("missing deployer key for chain %d", deps.Selector)
56+
return opscontract.WriteOutput{}, fmt.Errorf("missing deployer key for chain %d", deps.Selector)
5657
}
5758

5859
var opts *bind.TransactOpts
5960
if in.NoSend {
6061
opts = cldf.SimTransactOpts()
6162
} else {
62-
opts = cloneTransactOptsWithGas(deps.DeployerKey, in.GasLimit, in.GasPrice)
63+
opts = gasboost.CloneTransactOptsWithGas(deps.DeployerKey, in.GasLimit, in.GasPrice)
6364
}
6465
if opts == nil {
65-
return EVMCallOutput{}, fmt.Errorf("failed to build transact opts for chain %d", deps.Selector)
66+
return opscontract.WriteOutput{}, fmt.Errorf("failed to build transact opts for chain %d", deps.Selector)
6667
}
6768
opts.Context = b.GetContext()
69+
6870
configurer := mcmsevm.NewConfigurer(deps.Client, opts)
6971
res, err := configurer.SetConfig(b.GetContext(), in.Target.Address.Hex(), &in.Target.Config, false)
7072
if err != nil {
71-
return EVMCallOutput{}, fmt.Errorf("failed to set config on %s: %w", in.Target.Address, err)
73+
return opscontract.WriteOutput{}, fmt.Errorf("failed to set config on %s: %w", in.Target.Address, err)
7274
}
7375

7476
tx, ok := res.RawData.(*types.Transaction)
7577
if !ok {
76-
return EVMCallOutput{}, fmt.Errorf("unexpected raw data type %T from SetConfig", res.RawData)
78+
return opscontract.WriteOutput{}, fmt.Errorf("unexpected raw data type %T from SetConfig", res.RawData)
7779
}
7880

79-
confirmed := false
80-
if !in.NoSend {
81-
if _, err = cldf.ConfirmIfNoErrorWithABI(deps, tx, mcmsbindings.ManyChainMultiSigABI, err); err != nil {
82-
return EVMCallOutput{}, fmt.Errorf("failed to confirm set config tx against %s: %w", in.Target.Address, err)
83-
}
84-
b.Logger.Infow("SetConfig tx confirmed", "txHash", res.Hash, "address", in.Target.Address.Hex())
85-
confirmed = true
81+
out := writeOutputFromSetConfig(deps.Selector, in.Target, tx)
82+
if in.NoSend {
83+
return out, nil
84+
}
85+
86+
if _, err = cldf.ConfirmIfNoErrorWithABI(deps, tx, mcmsbindings.ManyChainMultiSigABI, err); err != nil {
87+
return opscontract.WriteOutput{}, fmt.Errorf("failed to confirm set config tx against %s: %w", in.Target.Address, err)
8688
}
89+
b.Logger.Infow("SetConfig tx confirmed", "txHash", res.Hash, "address", in.Target.Address.Hex())
90+
91+
out.ExecInfo = &opscontract.ExecInfo{Hash: res.Hash}
8792

88-
return EVMCallOutput{
89-
To: in.Target.Address,
90-
Data: tx.Data(),
91-
ContractType: in.Target.ContractType,
92-
Confirmed: confirmed,
93-
}, nil
93+
return out, nil
9494
},
9595
)
9696

97+
func writeOutputFromSetConfig(chainSelector uint64, target MCMSetConfigTarget, tx *types.Transaction) opscontract.WriteOutput {
98+
return opscontract.WriteOutput{
99+
ChainSelector: chainSelector,
100+
Tx: mcmsevm.NewTransaction(
101+
target.Address,
102+
tx.Data(),
103+
big.NewInt(0),
104+
string(target.ContractType),
105+
[]string{},
106+
),
107+
}
108+
}
109+
97110
func retrySetConfigWithGasBoost(cfg *cldfproposalutils.GasBoostConfig) operations.ExecuteOption[OpEVMSetConfigInput, cldf_evm.Chain] {
98111
if cfg == nil {
99112
return operations.WithRetry[OpEVMSetConfigInput, cldf_evm.Chain]()

mcms/evm/set-config/operation_test.go

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@ package evmsetconfig
22

33
import (
44
"crypto/ecdsa"
5-
"math/big"
65
"testing"
76

8-
"github.com/ethereum/go-ethereum/accounts/abi/bind"
97
"github.com/ethereum/go-ethereum/common"
108
"github.com/stretchr/testify/require"
119

1210
chainselectors "github.com/smartcontractkit/chain-selectors"
1311
cldf_evm "github.com/smartcontractkit/chainlink-deployments-framework/chain/evm"
12+
opscontract "github.com/smartcontractkit/chainlink-deployments-framework/chain/evm/operations2/contract"
1413
mcmscontracts "github.com/smartcontractkit/chainlink-deployments-framework/engine/cld/contracts/mcms"
1514
cldftesthelpers "github.com/smartcontractkit/chainlink-deployments-framework/engine/cld/mcms/proposalutils/testhelpers"
1615
"github.com/smartcontractkit/chainlink-deployments-framework/engine/test/runtime"
@@ -37,22 +36,6 @@ func TestOpEVMSetConfigMCM_missingDeployerKey(t *testing.T) {
3736
require.ErrorContains(t, err, "missing deployer key")
3837
}
3938

40-
func TestCloneTransactOptsWithGas(t *testing.T) {
41-
t.Parallel()
42-
43-
require.Nil(t, cloneTransactOptsWithGas(nil, 100, 200))
44-
45-
opts := &bind.TransactOpts{GasLimit: 1, GasPrice: big.NewInt(1)}
46-
got := cloneTransactOptsWithGas(opts, 0, 0)
47-
require.Equal(t, uint64(1), got.GasLimit)
48-
require.Equal(t, int64(1), got.GasPrice.Int64())
49-
require.NotSame(t, opts, got)
50-
51-
got = cloneTransactOptsWithGas(opts, 500_000, 30_000_000_000)
52-
require.Equal(t, uint64(500_000), got.GasLimit)
53-
require.Equal(t, uint64(30_000_000_000), got.GasPrice.Uint64())
54-
}
55-
5639
func TestOpEVMSetConfigInputGasOverridable(t *testing.T) {
5740
t.Parallel()
5841

@@ -108,12 +91,12 @@ func TestOpEVMSetConfigMCM(t *testing.T) {
10891
},
10992
)
11093
require.NoError(t, err)
111-
require.Equal(t, refs.Canceller, report.Output.To)
112-
require.NotEmpty(t, report.Output.Data)
113-
require.Equal(t, !tt.noSend, report.Output.Confirmed)
94+
require.Equal(t, refs.Canceller.Hex(), report.Output.Tx.To)
95+
require.NotEmpty(t, report.Output.Tx.Data)
96+
require.Equal(t, !tt.noSend, report.Output.Executed())
11497

11598
if tt.noSend {
116-
batch, err := evmCallOutputsToBatch(selector, []EVMCallOutput{report.Output})
99+
batch, err := opscontract.NewBatchOperationFromWrites([]opscontract.WriteOutput{report.Output})
117100
require.NoError(t, err)
118101
require.Len(t, batch.Transactions, 1)
119102
require.NoError(t, rt.Exec(

mcms/evm/set-config/sequence.go

Lines changed: 16 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@ package evmsetconfig
22

33
import (
44
"fmt"
5-
"math/big"
65
"strconv"
76

87
"github.com/Masterminds/semver/v3"
98
"github.com/ethereum/go-ethereum/common"
109
cldf_evm "github.com/smartcontractkit/chainlink-deployments-framework/chain/evm"
10+
opscontract "github.com/smartcontractkit/chainlink-deployments-framework/chain/evm/operations2/contract"
1111
"github.com/smartcontractkit/chainlink-deployments-framework/changeset/sequenceutils"
1212
cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment"
13-
cldfproposalutils "github.com/smartcontractkit/chainlink-deployments-framework/engine/cld/mcms/proposalutils"
1413
"github.com/smartcontractkit/chainlink-deployments-framework/operations"
1514
mcmstypes "github.com/smartcontractkit/mcms/types"
1615

@@ -40,11 +39,7 @@ func runEVMSetConfig(
4039
}
4140

4241
useMCMS := in.MCMS != nil
43-
44-
var outs []EVMCallOutput
45-
if useMCMS {
46-
outs = make([]EVMCallOutput, 0, len(targets))
47-
}
42+
var writes []opscontract.WriteOutput
4843

4944
for _, target := range targets {
5045
opReport, execErr := operations.ExecuteOperation(
@@ -62,29 +57,33 @@ func runEVMSetConfig(
6257
return sequenceutils.OnChainOutput{}, execErr
6358
}
6459

65-
if !useMCMS {
60+
if useMCMS {
61+
writes = append(writes, opReport.Output)
6662
continue
6763
}
6864

69-
out := opReport.Output
70-
out.ContractType = target.ContractType
71-
outs = append(outs, out)
65+
if opReport.Output.Executed() {
66+
b.Logger.Infow("SetConfig tx confirmed",
67+
"chainSelector", chain.Selector,
68+
"address", target.Address.Hex(),
69+
"txHash", opReport.Output.ExecInfo.Hash,
70+
)
71+
}
7272
}
7373

74-
out := sequenceutils.OnChainOutput{}
7574
if !useMCMS {
76-
return out, nil
75+
return sequenceutils.OnChainOutput{}, nil
7776
}
7877

79-
batch, err := evmCallOutputsToBatch(in.ChainSelector, outs)
78+
batch, err := opscontract.NewBatchOperationFromWrites(writes)
8079
if err != nil {
8180
return sequenceutils.OnChainOutput{}, err
8281
}
83-
if len(batch.Transactions) > 0 {
84-
out.BatchOps = []mcmstypes.BatchOperation{batch}
82+
if len(batch.Transactions) == 0 {
83+
return sequenceutils.OnChainOutput{}, nil
8584
}
8685

87-
return out, nil
86+
return sequenceutils.OnChainOutput{BatchOps: []mcmstypes.BatchOperation{batch}}, nil
8887
}
8988

9089
func setConfigTargets(e cldf.Environment, configs []setconfig.ContractSetConfig) ([]MCMSetConfigTarget, error) {
@@ -108,31 +107,3 @@ func setConfigTargets(e cldf.Environment, configs []setconfig.ContractSetConfig)
108107

109108
return targets, nil
110109
}
111-
112-
func evmCallOutputsToBatch(chainSelector uint64, outs []EVMCallOutput) (mcmstypes.BatchOperation, error) {
113-
result := mcmstypes.BatchOperation{
114-
ChainSelector: mcmstypes.ChainSelector(chainSelector),
115-
Transactions: []mcmstypes.Transaction{},
116-
}
117-
118-
for _, out := range outs {
119-
if out.Confirmed {
120-
continue
121-
}
122-
123-
batchOperation, err := cldfproposalutils.BatchOperationForChain(
124-
chainSelector,
125-
out.To.Hex(),
126-
out.Data,
127-
big.NewInt(0),
128-
string(out.ContractType),
129-
[]string{},
130-
)
131-
if err != nil {
132-
return mcmstypes.BatchOperation{}, fmt.Errorf("failed to create batch operation for chain %d: %w", chainSelector, err)
133-
}
134-
result.Transactions = append(result.Transactions, batchOperation.Transactions...)
135-
}
136-
137-
return result, nil
138-
}

0 commit comments

Comments
 (0)