-
Notifications
You must be signed in to change notification settings - Fork 0
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
Port CLI to mcms for non CLD integrations #182
base: main
Are you sure you want to change the base?
Changes from all commits
26dba82
ee9f2a3
8b00837
06c27c7
da2e759
acb5a35
a1d167b
bceea90
cc55ad1
31b403f
4416003
e567353
4001cb7
b67a298
faf7f3a
5b81a56
4abd108
0c0814c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
PRIVATE_KEY=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef | ||
RPC_URL=https://mainnet.infura.io/v3/0123456789abcdef0123456789abcdef |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. most of the code under |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/smartcontractkit/mcms/cmd/mcms" | ||
) | ||
|
||
func main() { | ||
rootCmd := mcms.BuildMCMSCmd() | ||
|
||
if err := rootCmd.Execute(); err != nil { | ||
fmt.Println(err) | ||
os.Exit(1) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package mcms | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
|
||
chainsel "github.com/smartcontractkit/chain-selectors" | ||
"github.com/smartcontractkit/mcms/sdk" | ||
"github.com/smartcontractkit/mcms/sdk/evm" | ||
"github.com/smartcontractkit/mcms/types" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func buildMCMSCheckQuorumCmd(proposalPath string, chainSelector uint64) *cobra.Command { | ||
return &cobra.Command{ | ||
Use: "check-quorum", | ||
Short: "Determines whether the provided signatures meet the quorum to set the root", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
fmt.Printf("Checking quorum for proposal %s\n", proposalPath) | ||
proposal, err := loadProposal(proposalPath) | ||
if err != nil { | ||
fmt.Printf("Error loading proposal: %s\n", err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is probably bringing up a linting error, but you can you the print function on the |
||
return err | ||
} | ||
|
||
// Get EVM chain ID | ||
chain, exists := chainsel.ChainBySelector(chainSelector) | ||
if !exists { | ||
return errors.New("chain not found") | ||
} | ||
|
||
// Load RPCs | ||
backends, err := loadRPCs([]types.ChainSelector{types.ChainSelector(chain.Selector)}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Create Inspector | ||
chainInspector := evm.NewInspector(backends[types.ChainSelector(chain.Selector)]) | ||
|
||
// Convert proposal to signable | ||
s, err := proposal.Signable(map[types.ChainSelector]sdk.Inspector{ | ||
types.ChainSelector(chain.Selector): chainInspector, | ||
}) | ||
if err != nil { | ||
fmt.Printf("Error converting proposal to signable: %s\n", err) | ||
return err | ||
} | ||
quorumMet, err := s.CheckQuorum(types.ChainSelector(chainSelector)) | ||
if err != nil { | ||
fmt.Printf("Error checking quorum: %s\n", err) | ||
return err | ||
} | ||
if quorumMet { | ||
fmt.Printf("Signature Quorum met!") | ||
} else { | ||
fmt.Printf("Signature Quorum not met!") | ||
return errors.New("signature Quorum not met") | ||
} | ||
return nil | ||
}, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package mcms | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"math/big" | ||
|
||
"github.com/ethereum/go-ethereum/accounts/abi/bind" | ||
chainsel "github.com/smartcontractkit/chain-selectors" | ||
"github.com/smartcontractkit/mcms/sdk/evm/bindings" | ||
"github.com/smartcontractkit/mcms/types" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func buildDeployCmd(chainSelector uint64) *cobra.Command { | ||
return &cobra.Command{ | ||
Use: "deploy", | ||
Short: "Deploys the MCMS contract on the specified chain", | ||
Long: ``, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
// Get EVM chain ID | ||
chain, exists := chainsel.ChainBySelector(chainSelector) | ||
if !exists { | ||
return errors.New("chain not found") | ||
} | ||
|
||
// Load Private Key | ||
pk, err := loadPrivateKey() | ||
if err != nil { | ||
fmt.Printf("Error loading private key: %s\n", err) | ||
return err | ||
} | ||
|
||
auth, err := bind.NewKeyedTransactorWithChainID(pk, big.NewInt(int64(chain.EvmChainID))) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Load RPCs | ||
backends, err := loadRPCs([]types.ChainSelector{types.ChainSelector(chain.Selector)}) | ||
if err != nil { | ||
return err | ||
} | ||
backend := backends[types.ChainSelector(chain.Selector)] | ||
|
||
// Deploy MCM contract | ||
_, tx, instance, err := bindings.DeployManyChainMultiSig(auth, backend) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
_, err = EVMConfirm(context.Background(), backend, tx.Hash().Hex()) | ||
if err != nil { | ||
return err | ||
} | ||
fmt.Printf("Transaction %s confirmed\n", tx.Hash().Hex()) | ||
fmt.Printf("MCMS Contract deployed at %s\n", instance.Address().Hex()) | ||
return nil | ||
}, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package mcms | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"math/big" | ||
|
||
"github.com/ethereum/go-ethereum/accounts/abi/bind" | ||
chainsel "github.com/smartcontractkit/chain-selectors" | ||
"github.com/smartcontractkit/mcms/sdk" | ||
"github.com/smartcontractkit/mcms/sdk/evm" | ||
"github.com/smartcontractkit/mcms/types" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func buildExecuteChainCmd(proposalPath string, chainSelector uint64) *cobra.Command { | ||
return &cobra.Command{ | ||
Use: "execute-chain", | ||
Short: "Executes all operations for a given chain in an MCMS Proposal. Root must be set first.", | ||
Long: ``, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
proposal, err := loadProposal(proposalPath) | ||
if err != nil { | ||
fmt.Printf("Error loading proposal: %s\n", err) | ||
return err | ||
} | ||
|
||
// Get EVM chain ID | ||
chain, exists := chainsel.ChainBySelector(chainSelector) | ||
if !exists { | ||
return errors.New("chain not found") | ||
} | ||
|
||
encoders, err := proposal.GetEncoders() | ||
if err != nil { | ||
fmt.Printf("Error getting encoders: %s\n", err) | ||
return err | ||
} | ||
|
||
// Load Private Key | ||
pk, err := loadPrivateKey() | ||
if err != nil { | ||
fmt.Printf("Error loading private key: %s\n", err) | ||
return err | ||
} | ||
|
||
auth, err := bind.NewKeyedTransactorWithChainID(pk, big.NewInt(int64(chain.EvmChainID))) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Load RPCs | ||
backends, err := loadRPCs([]types.ChainSelector{types.ChainSelector(chain.Selector)}) | ||
if err != nil { | ||
return err | ||
} | ||
backend := backends[types.ChainSelector(chain.Selector)] | ||
|
||
// Create Executor | ||
chainExecutor := evm.NewExecutor( | ||
encoders[types.ChainSelector(chain.Selector)].(*evm.Encoder), | ||
backend, | ||
auth, | ||
) | ||
|
||
// Convert proposal to executor | ||
e, err := proposal.Executable(map[types.ChainSelector]sdk.Executor{ | ||
types.ChainSelector(chain.Selector): chainExecutor, | ||
}) | ||
if err != nil { | ||
fmt.Printf("Error converting proposal to executor: %s\n", err) | ||
return err | ||
} | ||
|
||
for i, op := range e.Proposal.Operations { | ||
if op.ChainSelector == types.ChainSelector(chainSelector) { | ||
txHash, err := e.Execute(i) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
fmt.Printf("Transaction sent: %s", txHash) | ||
_, err = EVMConfirm(context.Background(), backend, txHash) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
} | ||
} | ||
return nil | ||
}, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package mcms | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"math/big" | ||
|
||
"github.com/ethereum/go-ethereum/accounts/abi/bind" | ||
chainsel "github.com/smartcontractkit/chain-selectors" | ||
"github.com/smartcontractkit/mcms/sdk" | ||
"github.com/smartcontractkit/mcms/sdk/evm" | ||
"github.com/smartcontractkit/mcms/types" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func buildExecuteOperationCmd(proposalPath string, chainSelector uint64) *cobra.Command { | ||
var index uint64 | ||
|
||
cmd := cobra.Command{ | ||
Use: "execute-operation", | ||
Short: "Executes a single operation on a given chain in an MCMS Proposal. Root must be set first.", | ||
Long: ``, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
proposal, err := loadProposal(proposalPath) | ||
if err != nil { | ||
fmt.Printf("Error loading proposal: %s\n", err) | ||
return err | ||
} | ||
|
||
// Get EVM chain ID | ||
chain, exists := chainsel.ChainBySelector(chainSelector) | ||
if !exists { | ||
return errors.New("chain not found") | ||
} | ||
|
||
encoders, err := proposal.GetEncoders() | ||
if err != nil { | ||
fmt.Printf("Error getting encoders: %s\n", err) | ||
return err | ||
} | ||
|
||
// Load Private Key | ||
pk, err := loadPrivateKey() | ||
if err != nil { | ||
fmt.Printf("Error loading private key: %s\n", err) | ||
return err | ||
} | ||
|
||
auth, err := bind.NewKeyedTransactorWithChainID(pk, big.NewInt(int64(chain.EvmChainID))) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Load RPCs | ||
backends, err := loadRPCs([]types.ChainSelector{types.ChainSelector(chain.Selector)}) | ||
if err != nil { | ||
return err | ||
} | ||
backend := backends[types.ChainSelector(chain.Selector)] | ||
|
||
// Create Executor | ||
chainExecutor := evm.NewExecutor( | ||
encoders[types.ChainSelector(chain.Selector)].(*evm.Encoder), | ||
backend, | ||
auth, | ||
) | ||
|
||
// Convert proposal to executor | ||
e, err := proposal.Executable(map[types.ChainSelector]sdk.Executor{ | ||
types.ChainSelector(chain.Selector): chainExecutor, | ||
}) | ||
if err != nil { | ||
fmt.Printf("Error converting proposal to executor: %s\n", err) | ||
return err | ||
} | ||
|
||
txHash, err := e.Execute(int(index)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
fmt.Printf("Transaction sent: %s", txHash) | ||
_, err = EVMConfirm(context.Background(), backend, txHash) | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
}, | ||
} | ||
|
||
cmd.Flags().Uint64Var(&index, "index", 0, "Index of the operation to execute") | ||
|
||
return &cmd | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package mcms | ||
|
||
import ( | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func BuildMCMSCmd() *cobra.Command { | ||
var ( | ||
proposalPath string | ||
chainSelector uint64 | ||
) | ||
|
||
cmd := cobra.Command{ | ||
Use: "mcms", | ||
Short: "Manage MCMS proposals", | ||
Long: ``, | ||
} | ||
|
||
cmd.PersistentFlags().StringVar(&proposalPath, "proposal", "", "Absolute file path containing the proposal to be submitted") | ||
cmd.MarkFlagRequired("proposal") | ||
cmd.PersistentFlags().Uint64Var(&chainSelector, "selector", 0, "Chain selector for the command to connect to") | ||
|
||
cmd.AddCommand(buildDeployCmd(chainSelector)) | ||
cmd.AddCommand(buildSetConfigCmd(chainSelector)) | ||
cmd.AddCommand(buildMCMSCheckQuorumCmd(proposalPath, chainSelector)) | ||
cmd.AddCommand(buildExecuteChainCmd(proposalPath, chainSelector)) | ||
cmd.AddCommand(buildExecuteOperationCmd(proposalPath, chainSelector)) | ||
cmd.AddCommand(buildSetRootCmd(proposalPath, chainSelector)) | ||
cmd.AddCommand(newSignPrivateKeyCmd(proposalPath)) | ||
cmd.AddCommand(newSignLedgerCmd(proposalPath)) | ||
|
||
return &cmd | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should lint this code, or if there is a linter that is specifically not needed, we can exclude it explicitly.
I am very wary of blanket exclusions