@@ -60,6 +60,11 @@ var ibcUpdateChannelChainChainId *string
60
60
var recoverChainIdEvmChainId * string
61
61
var recoverChainIdNewChainId * string
62
62
63
+ var governanceContractAddress * string
64
+ var governanceTargetAddress * string
65
+ var governanceTargetChain * string
66
+ var governanceCallData * string
67
+
63
68
func init () {
64
69
governanceFlagSet := pflag .NewFlagSet ("governance" , pflag .ExitOnError )
65
70
chainID = governanceFlagSet .String ("chain-id" , "" , "Chain ID" )
@@ -171,6 +176,19 @@ func init() {
171
176
AdminClientRecoverChainIdCmd .Flags ().AddFlagSet (recoverChainIdFlagSet )
172
177
AdminClientRecoverChainIdCmd .Flags ().AddFlagSet (moduleFlagSet )
173
178
TemplateCmd .AddCommand (AdminClientRecoverChainIdCmd )
179
+
180
+ // flags for general-purpose governance call command
181
+ generalPurposeGovernanceFlagSet := pflag .NewFlagSet ("general-purpose-governance" , pflag .ExitOnError )
182
+ governanceContractAddress = generalPurposeGovernanceFlagSet .String ("governance-contract" , "" , "Governance contract address" )
183
+ governanceTargetAddress = generalPurposeGovernanceFlagSet .String ("target-address" , "" , "Address of the governed contract" )
184
+ governanceCallData = generalPurposeGovernanceFlagSet .String ("call-data" , "" , "calldata" )
185
+ governanceTargetChain = generalPurposeGovernanceFlagSet .String ("chain-id" , "" , "Chain ID" )
186
+ // evm call command
187
+ AdminClientGeneralPurposeGovernanceEvmCallCmd .Flags ().AddFlagSet (generalPurposeGovernanceFlagSet )
188
+ TemplateCmd .AddCommand (AdminClientGeneralPurposeGovernanceEvmCallCmd )
189
+ // solana call command
190
+ AdminClientGeneralPurposeGovernanceSolanaCallCmd .Flags ().AddFlagSet (generalPurposeGovernanceFlagSet )
191
+ TemplateCmd .AddCommand (AdminClientGeneralPurposeGovernanceSolanaCallCmd )
174
192
}
175
193
176
194
var TemplateCmd = & cobra.Command {
@@ -292,6 +310,18 @@ var AdminClientWormholeRelayerSetDefaultDeliveryProviderCmd = &cobra.Command{
292
310
Run : runWormholeRelayerSetDefaultDeliveryProviderTemplate ,
293
311
}
294
312
313
+ var AdminClientGeneralPurposeGovernanceEvmCallCmd = & cobra.Command {
314
+ Use : "governance-evm-call" ,
315
+ Short : "Generate a 'general purpose evm governance call' template for specified chain and address" ,
316
+ Run : runGeneralPurposeGovernanceEvmCallTemplate ,
317
+ }
318
+
319
+ var AdminClientGeneralPurposeGovernanceSolanaCallCmd = & cobra.Command {
320
+ Use : "governance-solana-call" ,
321
+ Short : "Generate a 'general purpose solana governance call' template for specified chain and address" ,
322
+ Run : runGeneralPurposeGovernanceSolanaCallTemplate ,
323
+ }
324
+
295
325
func runGuardianSetTemplate (cmd * cobra.Command , args []string ) {
296
326
// Use deterministic devnet addresses as examples in the template, such that this doubles as a test fixture.
297
327
guardians := make ([]* nodev1.GuardianSetUpdate_Guardian , * setUpdateNumGuardians )
@@ -932,6 +962,100 @@ func runWormholeRelayerSetDefaultDeliveryProviderTemplate(cmd *cobra.Command, ar
932
962
fmt .Print (string (b ))
933
963
}
934
964
965
+ func runGeneralPurposeGovernanceEvmCallTemplate (cmd * cobra.Command , args []string ) {
966
+ if * governanceTargetAddress == "" {
967
+ log .Fatal ("--target-address must be specified" )
968
+ }
969
+ if ! common .IsHexAddress (* governanceTargetAddress ) {
970
+ log .Fatal ("invalid target address" )
971
+ }
972
+ governanceTargetAddress := common .HexToAddress (* governanceTargetAddress ).Hex ()
973
+ if * governanceCallData == "" {
974
+ log .Fatal ("--call-data must be specified" )
975
+ }
976
+ if * governanceContractAddress == "" {
977
+ log .Fatal ("--governance-contract must be specified" )
978
+ }
979
+ if ! common .IsHexAddress (* governanceContractAddress ) {
980
+ log .Fatal ("invalid governance contract address" )
981
+ }
982
+ governanceContractAddress := common .HexToAddress (* governanceContractAddress ).Hex ()
983
+ if * governanceTargetChain == "" {
984
+ log .Fatal ("--chain-id must be specified" )
985
+ }
986
+ chainID , err := parseChainID (* governanceTargetChain )
987
+ if err != nil {
988
+ log .Fatal ("failed to parse chain id: " , err )
989
+ }
990
+
991
+ m := & nodev1.InjectGovernanceVAARequest {
992
+ CurrentSetIndex : uint32 (* templateGuardianIndex ),
993
+ Messages : []* nodev1.GovernanceMessage {
994
+ {
995
+ Sequence : rand .Uint64 (),
996
+ Nonce : rand .Uint32 (),
997
+ Payload : & nodev1.GovernanceMessage_EvmCall {
998
+ EvmCall : & nodev1.EvmCall {
999
+ ChainId : uint32 (chainID ),
1000
+ GovernanceContract : governanceContractAddress ,
1001
+ TargetContract : governanceTargetAddress ,
1002
+ AbiEncodedCall : * governanceCallData ,
1003
+ },
1004
+ },
1005
+ },
1006
+ },
1007
+ }
1008
+
1009
+ b , err := prototext.MarshalOptions {Multiline : true }.Marshal (m )
1010
+ if err != nil {
1011
+ panic (err )
1012
+ }
1013
+ fmt .Print (string (b ))
1014
+ }
1015
+
1016
+ func runGeneralPurposeGovernanceSolanaCallTemplate (cmd * cobra.Command , args []string ) {
1017
+ if * governanceCallData == "" {
1018
+ log .Fatal ("--call-data must be specified" )
1019
+ }
1020
+ if * governanceContractAddress == "" {
1021
+ log .Fatal ("--governance-contract must be specified" )
1022
+ }
1023
+ _ , err := base58 .Decode (* governanceContractAddress )
1024
+ if err != nil {
1025
+ log .Fatal ("invalid base58 governance contract address" )
1026
+ }
1027
+ if * governanceTargetChain == "" {
1028
+ log .Fatal ("--chain-id must be specified" )
1029
+ }
1030
+ chainID , err := parseChainID (* governanceTargetChain )
1031
+ if err != nil {
1032
+ log .Fatal ("failed to parse chain id: " , err )
1033
+ }
1034
+
1035
+ m := & nodev1.InjectGovernanceVAARequest {
1036
+ CurrentSetIndex : uint32 (* templateGuardianIndex ),
1037
+ Messages : []* nodev1.GovernanceMessage {
1038
+ {
1039
+ Sequence : rand .Uint64 (),
1040
+ Nonce : rand .Uint32 (),
1041
+ Payload : & nodev1.GovernanceMessage_SolanaCall {
1042
+ SolanaCall : & nodev1.SolanaCall {
1043
+ ChainId : uint32 (chainID ),
1044
+ GovernanceContract : * governanceContractAddress ,
1045
+ EncodedInstruction : * governanceCallData ,
1046
+ },
1047
+ },
1048
+ },
1049
+ },
1050
+ }
1051
+
1052
+ b , err := prototext.MarshalOptions {Multiline : true }.Marshal (m )
1053
+ if err != nil {
1054
+ panic (err )
1055
+ }
1056
+ fmt .Print (string (b ))
1057
+ }
1058
+
935
1059
// parseAddress parses either a hex-encoded address and returns
936
1060
// a left-padded 32 byte hex string.
937
1061
func parseAddress (s string ) (string , error ) {
0 commit comments