diff --git a/evm/generators.go b/evm/generators.go index e9ad003..ed1e792 100644 --- a/evm/generators.go +++ b/evm/generators.go @@ -1107,7 +1107,7 @@ type SafeTransactionData struct { GasPrice string ` + "`" + `json:"gasPrice"` + "`" + ` GasToken string ` + "`" + `json:"gasToken"` + "`" + ` RefundReceiver string ` + "`" + `json:"refundReceiver"` + "`" + ` - Nonce uint64 ` + "`" + `json:"nonce"` + "`" + ` + Nonce *big.Int ` + "`" + `json:"nonce"` + "`" + ` SafeTxHash string ` + "`" + `json:"safeTxHash"` + "`" + ` Sender string ` + "`" + `json:"sender"` + "`" + ` Signature string ` + "`" + `json:"signature"` + "`" + ` @@ -1119,7 +1119,7 @@ const ( ) -func DeployWithSafe(client *ethclient.Client, key *keystore.Key, safeAddress common.Address, factoryAddress common.Address, value *big.Int, safeApi string, deployBytecode []byte, safeOperationType SafeOperationType, salt [32]byte) error { +func DeployWithSafe(client *ethclient.Client, key *keystore.Key, safeAddress common.Address, factoryAddress common.Address, value *big.Int, safeApi string, deployBytecode []byte, safeOperationType SafeOperationType, salt [32]byte, safeNonce *big.Int) error { abi, err := CreateCall.CreateCallMetaData.GetAbi() if err != nil { return fmt.Errorf("failed to get ABI: %v", err) @@ -1130,7 +1130,7 @@ func DeployWithSafe(client *ethclient.Client, key *keystore.Key, safeAddress com return fmt.Errorf("failed to pack performCreate2 transaction: %v", err) } - return CreateSafeProposal(client, key, safeAddress, factoryAddress, safeCreateCallTxData, value, safeApi, SafeOperationType(safeOperationType)) + return CreateSafeProposal(client, key, safeAddress, factoryAddress, safeCreateCallTxData, value, safeApi, SafeOperationType(safeOperationType), safeNonce) } func PredictDeploymentAddressSafe(from common.Address, salt [32]byte, deployBytecode []byte) (common.Address, error) { @@ -1143,7 +1143,7 @@ func PredictDeploymentAddressSafe(from common.Address, salt [32]byte, deployByte return deployedAddress, nil } -func CreateSafeProposal(client *ethclient.Client, key *keystore.Key, safeAddress common.Address, to common.Address, data []byte, value *big.Int, safeApi string, safeOperationType SafeOperationType) error { +func CreateSafeProposal(client *ethclient.Client, key *keystore.Key, safeAddress common.Address, to common.Address, data []byte, value *big.Int, safeApi string, safeOperationType SafeOperationType, safeNonce *big.Int) error { chainID, err := client.ChainID(context.Background()) if err != nil { return fmt.Errorf("failed to get chain ID: %v", err) @@ -1155,10 +1155,16 @@ func CreateSafeProposal(client *ethclient.Client, key *keystore.Key, safeAddress return fmt.Errorf("failed to create GnosisSafe instance: %v", err) } - // Fetch the current nonce from the Safe contract - nonce, err := safeInstance.Nonce(&bind.CallOpts{}) - if err != nil { - return fmt.Errorf("failed to fetch nonce from Safe contract: %v", err) + nonce := safeNonce + if safeNonce == nil { + // Fetch the current nonce from the Safe contract + fetchedNonce, err := safeInstance.Nonce(&bind.CallOpts{}) + if err != nil { + return fmt.Errorf("failed to fetch nonce from Safe contract: %v", err) + } + nonce = fetchedNonce + } else { + nonce = safeNonce } safeTransactionData := SafeTransactionData{ @@ -1171,7 +1177,7 @@ func CreateSafeProposal(client *ethclient.Client, key *keystore.Key, safeAddress GasPrice: "0", GasToken: NativeTokenAddress, RefundReceiver: NativeTokenAddress, - Nonce: nonce.Uint64(), + Nonce: nonce, } // Calculate SafeTxHash @@ -1298,11 +1304,11 @@ func {{.DeployHandler.HandlerName}}() *cobra.Command { var gasLimit uint64 var simulate bool var timeout uint - var safeAddress, safeApi, safeCreateCall, safeSaltRaw string + var safeAddress, safeApi, safeCreateCall, safeSaltRaw, safeNonceRaw string var safeOperationType uint8 var salt [32]byte var predictAddress bool - + var safeNonce *big.Int {{range .DeployHandler.MethodArgs}} var {{.CLIVar}} {{.CLIType}} {{if (ne .CLIRawVar .CLIVar)}}var {{.CLIRawVar}} {{.CLIRawType}}{{end}} @@ -1368,6 +1374,17 @@ func {{.DeployHandler.HandlerName}}() *cobra.Command { } else { copy(salt[:], safeSaltRaw) } + + if safeNonceRaw == "" { + fmt.Println("--safe-nonce not specified, using default (0)") + safeNonce = big.NewInt(0) + } else { + safeNonce = new(big.Int) + _, ok := safeNonce.SetString(safeNonceRaw, 0) + if !ok { + return fmt.Errorf("--safe-nonce is not a valid big integer") + } + } } {{range .DeployHandler.MethodArgs}} @@ -1432,7 +1449,7 @@ func {{.DeployHandler.HandlerName}}() *cobra.Command { return nil } else { fmt.Println("Creating Safe proposal...") - err = DeployWithSafe(client, key, common.HexToAddress(safeAddress), common.HexToAddress(safeCreateCall), value, safeApi, deployBytecode, SafeOperationType(safeOperationType), salt) + err = DeployWithSafe(client, key, common.HexToAddress(safeAddress), common.HexToAddress(safeCreateCall), value, safeApi, deployBytecode, SafeOperationType(safeOperationType), salt, safeNonce) if err != nil { return fmt.Errorf("failed to create Safe proposal: %v", err) } @@ -1500,6 +1517,7 @@ func {{.DeployHandler.HandlerName}}() *cobra.Command { cmd.Flags().Uint8Var(&safeOperationType, "safe-operation", 1, "Safe operation type: 0 (Call) or 1 (DelegateCall) - default is 1") cmd.Flags().StringVar(&safeSaltRaw, "safe-salt", "", "Salt to use for the Safe transaction") cmd.Flags().BoolVar(&predictAddress, "safe-predict-address", false, "Predict the deployment address (only works for Safe transactions)") + cmd.Flags().StringVar(&safeNonceRaw, "safe-nonce", "", "Safe nonce overrider for the transaction (optional)") {{range .DeployHandler.MethodArgs}} cmd.Flags().{{.Flag}} @@ -1629,13 +1647,14 @@ func {{.HandlerName}}() *cobra.Command { var TransactMethodCommandsTemplate string = `{{$structName := .StructName}} {{range .TransactHandlers}} func {{.HandlerName}}() *cobra.Command { - var keyfile, nonce, password, value, gasPrice, maxFeePerGas, maxPriorityFeePerGas, rpc, contractAddressRaw, safeFunction string + var keyfile, nonce, password, value, gasPrice, maxFeePerGas, maxPriorityFeePerGas, rpc, contractAddressRaw, safeFunction, safeNonceRaw string var gasLimit uint64 var simulate bool var timeout uint var contractAddress common.Address var safeAddress, safeApi string var safeOperationType uint8 + var safeNonce *big.Int {{range .MethodArgs}} var {{.CLIVar}} {{.CLIType}} @@ -1683,6 +1702,17 @@ func {{.HandlerName}}() *cobra.Command { if SafeOperationType(safeOperationType).String() == "Unknown" { return fmt.Errorf("--safe-operation must be 0 (Call) or 1 (DelegateCall)") } + + if safeNonceRaw == "" { + fmt.Println("--safe-nonce not specified, using default (0)") + safeNonce = big.NewInt(0) + } else { + safeNonce = new(big.Int) + _, ok := safeNonce.SetString(safeNonceRaw, 0) + if !ok { + return fmt.Errorf("--safe-nonce is not a valid big integer") + } + } } {{range .MethodArgs}} @@ -1754,7 +1784,8 @@ func {{.HandlerName}}() *cobra.Command { if value == nil { value = big.NewInt(0) } - err = CreateSafeProposal(client, key, common.HexToAddress(safeAddress), contractAddress, transaction, value, safeApi, SafeOperationType(safeOperationType)) + + err = CreateSafeProposal(client, key, common.HexToAddress(safeAddress), contractAddress, transaction, value, safeApi, SafeOperationType(safeOperationType), safeNonce) if err != nil { return fmt.Errorf("failed to create Safe proposal: %v", err) } @@ -1818,6 +1849,7 @@ func {{.HandlerName}}() *cobra.Command { cmd.Flags().StringVar(&safeApi, "safe-api", "", "Safe API for the Safe Transaction Service (optional)") cmd.Flags().Uint8Var(&safeOperationType, "safe-operation", 0, "Safe operation type: 0 (Call) or 1 (DelegateCall)") cmd.Flags().StringVar(&safeFunction, "safe-function", "", "Safe function overrider to use for the transaction (optional)") + cmd.Flags().StringVar(&safeNonceRaw, "safe-nonce", "", "Safe nonce overrider for the transaction (optional)") {{range .MethodArgs}} cmd.Flags().{{.Flag}} diff --git a/examples/ownable-erc-721/OwnableERC721.go b/examples/ownable-erc-721/OwnableERC721.go index 393e367..36d8110 100644 --- a/examples/ownable-erc-721/OwnableERC721.go +++ b/examples/ownable-erc-721/OwnableERC721.go @@ -1,5 +1,5 @@ // This file was generated by seer: https://github.com/G7DAO/seer. -// seer version: 0.2.2 +// seer version: 0.3.1 // seer command: seer evm generate --package main --cli --includemain --abi fixtures/OwnableERC721.json --bytecode fixtures/OwnableERC721.bin --struct OwnableERC721 --output examples/ownable-erc-721/OwnableERC721.go // Code generated - DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. @@ -31,10 +31,10 @@ import ( "os" "time" - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/ethclient" "github.com/G7DAO/seer/bindings/CreateCall" "github.com/G7DAO/seer/bindings/GnosisSafe" + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/ethclient" "github.com/spf13/cobra" "golang.org/x/term" @@ -1310,10 +1310,11 @@ func CreateOwnableERC721DeploymentCommand() *cobra.Command { var gasLimit uint64 var simulate bool var timeout uint - var safeAddress, safeApi, safeCreateCall, safeSaltRaw string + var safeAddress, safeApi, safeCreateCall, safeSaltRaw, safeNonceRaw string var safeOperationType uint8 var salt [32]byte var predictAddress bool + var safeNonce *big.Int var name_0 string @@ -1382,6 +1383,17 @@ func CreateOwnableERC721DeploymentCommand() *cobra.Command { } else { copy(salt[:], safeSaltRaw) } + + if safeNonceRaw == "" { + fmt.Println("--safe-nonce not specified, using default (0)") + safeNonce = big.NewInt(0) + } else { + safeNonce = new(big.Int) + _, ok := safeNonce.SetString(safeNonceRaw, 0) + if !ok { + return fmt.Errorf("--safe-nonce is not a valid big integer") + } + } } if ownerRaw == "" { @@ -1449,7 +1461,7 @@ func CreateOwnableERC721DeploymentCommand() *cobra.Command { return nil } else { fmt.Println("Creating Safe proposal...") - err = DeployWithSafe(client, key, common.HexToAddress(safeAddress), common.HexToAddress(safeCreateCall), value, safeApi, deployBytecode, SafeOperationType(safeOperationType), salt) + err = DeployWithSafe(client, key, common.HexToAddress(safeAddress), common.HexToAddress(safeCreateCall), value, safeApi, deployBytecode, SafeOperationType(safeOperationType), salt, safeNonce) if err != nil { return fmt.Errorf("failed to create Safe proposal: %v", err) } @@ -1516,6 +1528,7 @@ func CreateOwnableERC721DeploymentCommand() *cobra.Command { cmd.Flags().Uint8Var(&safeOperationType, "safe-operation", 1, "Safe operation type: 0 (Call) or 1 (DelegateCall) - default is 1") cmd.Flags().StringVar(&safeSaltRaw, "safe-salt", "", "Salt to use for the Safe transaction") cmd.Flags().BoolVar(&predictAddress, "safe-predict-address", false, "Predict the deployment address (only works for Safe transactions)") + cmd.Flags().StringVar(&safeNonceRaw, "safe-nonce", "", "Safe nonce overrider for the transaction (optional)") cmd.Flags().StringVar(&name_0, "name-0", "", "name-0 argument") cmd.Flags().StringVar(&symbol, "symbol", "", "symbol argument") @@ -2211,13 +2224,14 @@ func CreateTokenUriCommand() *cobra.Command { } func CreateApproveCommand() *cobra.Command { - var keyfile, nonce, password, value, gasPrice, maxFeePerGas, maxPriorityFeePerGas, rpc, contractAddressRaw, safeFunction string + var keyfile, nonce, password, value, gasPrice, maxFeePerGas, maxPriorityFeePerGas, rpc, contractAddressRaw, safeFunction, safeNonceRaw string var gasLimit uint64 var simulate bool var timeout uint var contractAddress common.Address var safeAddress, safeApi string var safeOperationType uint8 + var safeNonce *big.Int var to0 common.Address var to0Raw string @@ -2265,6 +2279,17 @@ func CreateApproveCommand() *cobra.Command { if SafeOperationType(safeOperationType).String() == "Unknown" { return fmt.Errorf("--safe-operation must be 0 (Call) or 1 (DelegateCall)") } + + if safeNonceRaw == "" { + fmt.Println("--safe-nonce not specified, using default (0)") + safeNonce = big.NewInt(0) + } else { + safeNonce = new(big.Int) + _, ok := safeNonce.SetString(safeNonceRaw, 0) + if !ok { + return fmt.Errorf("--safe-nonce is not a valid big integer") + } + } } if to0Raw == "" { @@ -2344,7 +2369,8 @@ func CreateApproveCommand() *cobra.Command { if value == nil { value = big.NewInt(0) } - err = CreateSafeProposal(client, key, common.HexToAddress(safeAddress), contractAddress, transaction, value, safeApi, SafeOperationType(safeOperationType)) + + err = CreateSafeProposal(client, key, common.HexToAddress(safeAddress), contractAddress, transaction, value, safeApi, SafeOperationType(safeOperationType), safeNonce) if err != nil { return fmt.Errorf("failed to create Safe proposal: %v", err) } @@ -2408,6 +2434,7 @@ func CreateApproveCommand() *cobra.Command { cmd.Flags().StringVar(&safeApi, "safe-api", "", "Safe API for the Safe Transaction Service (optional)") cmd.Flags().Uint8Var(&safeOperationType, "safe-operation", 0, "Safe operation type: 0 (Call) or 1 (DelegateCall)") cmd.Flags().StringVar(&safeFunction, "safe-function", "", "Safe function overrider to use for the transaction (optional)") + cmd.Flags().StringVar(&safeNonceRaw, "safe-nonce", "", "Safe nonce overrider for the transaction (optional)") cmd.Flags().StringVar(&to0Raw, "to-0", "", "to-0 argument (common.Address)") cmd.Flags().StringVar(&tokenIdRaw, "token-id", "", "token-id argument") @@ -2415,13 +2442,14 @@ func CreateApproveCommand() *cobra.Command { return cmd } func CreateMintCommand() *cobra.Command { - var keyfile, nonce, password, value, gasPrice, maxFeePerGas, maxPriorityFeePerGas, rpc, contractAddressRaw, safeFunction string + var keyfile, nonce, password, value, gasPrice, maxFeePerGas, maxPriorityFeePerGas, rpc, contractAddressRaw, safeFunction, safeNonceRaw string var gasLimit uint64 var simulate bool var timeout uint var contractAddress common.Address var safeAddress, safeApi string var safeOperationType uint8 + var safeNonce *big.Int var to0 common.Address var to0Raw string @@ -2469,6 +2497,17 @@ func CreateMintCommand() *cobra.Command { if SafeOperationType(safeOperationType).String() == "Unknown" { return fmt.Errorf("--safe-operation must be 0 (Call) or 1 (DelegateCall)") } + + if safeNonceRaw == "" { + fmt.Println("--safe-nonce not specified, using default (0)") + safeNonce = big.NewInt(0) + } else { + safeNonce = new(big.Int) + _, ok := safeNonce.SetString(safeNonceRaw, 0) + if !ok { + return fmt.Errorf("--safe-nonce is not a valid big integer") + } + } } if to0Raw == "" { @@ -2548,7 +2587,8 @@ func CreateMintCommand() *cobra.Command { if value == nil { value = big.NewInt(0) } - err = CreateSafeProposal(client, key, common.HexToAddress(safeAddress), contractAddress, transaction, value, safeApi, SafeOperationType(safeOperationType)) + + err = CreateSafeProposal(client, key, common.HexToAddress(safeAddress), contractAddress, transaction, value, safeApi, SafeOperationType(safeOperationType), safeNonce) if err != nil { return fmt.Errorf("failed to create Safe proposal: %v", err) } @@ -2612,6 +2652,7 @@ func CreateMintCommand() *cobra.Command { cmd.Flags().StringVar(&safeApi, "safe-api", "", "Safe API for the Safe Transaction Service (optional)") cmd.Flags().Uint8Var(&safeOperationType, "safe-operation", 0, "Safe operation type: 0 (Call) or 1 (DelegateCall)") cmd.Flags().StringVar(&safeFunction, "safe-function", "", "Safe function overrider to use for the transaction (optional)") + cmd.Flags().StringVar(&safeNonceRaw, "safe-nonce", "", "Safe nonce overrider for the transaction (optional)") cmd.Flags().StringVar(&to0Raw, "to-0", "", "to-0 argument (common.Address)") cmd.Flags().StringVar(&tokenIdRaw, "token-id", "", "token-id argument") @@ -2619,13 +2660,14 @@ func CreateMintCommand() *cobra.Command { return cmd } func CreateRenounceOwnershipCommand() *cobra.Command { - var keyfile, nonce, password, value, gasPrice, maxFeePerGas, maxPriorityFeePerGas, rpc, contractAddressRaw, safeFunction string + var keyfile, nonce, password, value, gasPrice, maxFeePerGas, maxPriorityFeePerGas, rpc, contractAddressRaw, safeFunction, safeNonceRaw string var gasLimit uint64 var simulate bool var timeout uint var contractAddress common.Address var safeAddress, safeApi string var safeOperationType uint8 + var safeNonce *big.Int cmd := &cobra.Command{ Use: "renounce-ownership", @@ -2668,6 +2710,17 @@ func CreateRenounceOwnershipCommand() *cobra.Command { if SafeOperationType(safeOperationType).String() == "Unknown" { return fmt.Errorf("--safe-operation must be 0 (Call) or 1 (DelegateCall)") } + + if safeNonceRaw == "" { + fmt.Println("--safe-nonce not specified, using default (0)") + safeNonce = big.NewInt(0) + } else { + safeNonce = new(big.Int) + _, ok := safeNonce.SetString(safeNonceRaw, 0) + if !ok { + return fmt.Errorf("--safe-nonce is not a valid big integer") + } + } } return nil @@ -2732,7 +2785,8 @@ func CreateRenounceOwnershipCommand() *cobra.Command { if value == nil { value = big.NewInt(0) } - err = CreateSafeProposal(client, key, common.HexToAddress(safeAddress), contractAddress, transaction, value, safeApi, SafeOperationType(safeOperationType)) + + err = CreateSafeProposal(client, key, common.HexToAddress(safeAddress), contractAddress, transaction, value, safeApi, SafeOperationType(safeOperationType), safeNonce) if err != nil { return fmt.Errorf("failed to create Safe proposal: %v", err) } @@ -2792,17 +2846,19 @@ func CreateRenounceOwnershipCommand() *cobra.Command { cmd.Flags().StringVar(&safeApi, "safe-api", "", "Safe API for the Safe Transaction Service (optional)") cmd.Flags().Uint8Var(&safeOperationType, "safe-operation", 0, "Safe operation type: 0 (Call) or 1 (DelegateCall)") cmd.Flags().StringVar(&safeFunction, "safe-function", "", "Safe function overrider to use for the transaction (optional)") + cmd.Flags().StringVar(&safeNonceRaw, "safe-nonce", "", "Safe nonce overrider for the transaction (optional)") return cmd } func CreateSafeTransferFromCommand() *cobra.Command { - var keyfile, nonce, password, value, gasPrice, maxFeePerGas, maxPriorityFeePerGas, rpc, contractAddressRaw, safeFunction string + var keyfile, nonce, password, value, gasPrice, maxFeePerGas, maxPriorityFeePerGas, rpc, contractAddressRaw, safeFunction, safeNonceRaw string var gasLimit uint64 var simulate bool var timeout uint var contractAddress common.Address var safeAddress, safeApi string var safeOperationType uint8 + var safeNonce *big.Int var from0 common.Address var from0Raw string @@ -2852,6 +2908,17 @@ func CreateSafeTransferFromCommand() *cobra.Command { if SafeOperationType(safeOperationType).String() == "Unknown" { return fmt.Errorf("--safe-operation must be 0 (Call) or 1 (DelegateCall)") } + + if safeNonceRaw == "" { + fmt.Println("--safe-nonce not specified, using default (0)") + safeNonce = big.NewInt(0) + } else { + safeNonce = new(big.Int) + _, ok := safeNonce.SetString(safeNonceRaw, 0) + if !ok { + return fmt.Errorf("--safe-nonce is not a valid big integer") + } + } } if from0Raw == "" { @@ -2939,7 +3006,8 @@ func CreateSafeTransferFromCommand() *cobra.Command { if value == nil { value = big.NewInt(0) } - err = CreateSafeProposal(client, key, common.HexToAddress(safeAddress), contractAddress, transaction, value, safeApi, SafeOperationType(safeOperationType)) + + err = CreateSafeProposal(client, key, common.HexToAddress(safeAddress), contractAddress, transaction, value, safeApi, SafeOperationType(safeOperationType), safeNonce) if err != nil { return fmt.Errorf("failed to create Safe proposal: %v", err) } @@ -3004,6 +3072,7 @@ func CreateSafeTransferFromCommand() *cobra.Command { cmd.Flags().StringVar(&safeApi, "safe-api", "", "Safe API for the Safe Transaction Service (optional)") cmd.Flags().Uint8Var(&safeOperationType, "safe-operation", 0, "Safe operation type: 0 (Call) or 1 (DelegateCall)") cmd.Flags().StringVar(&safeFunction, "safe-function", "", "Safe function overrider to use for the transaction (optional)") + cmd.Flags().StringVar(&safeNonceRaw, "safe-nonce", "", "Safe nonce overrider for the transaction (optional)") cmd.Flags().StringVar(&from0Raw, "from-0", "", "from-0 argument (common.Address)") cmd.Flags().StringVar(&to0Raw, "to-0", "", "to-0 argument (common.Address)") @@ -3012,13 +3081,14 @@ func CreateSafeTransferFromCommand() *cobra.Command { return cmd } func CreateSafeTransferFrom0Command() *cobra.Command { - var keyfile, nonce, password, value, gasPrice, maxFeePerGas, maxPriorityFeePerGas, rpc, contractAddressRaw, safeFunction string + var keyfile, nonce, password, value, gasPrice, maxFeePerGas, maxPriorityFeePerGas, rpc, contractAddressRaw, safeFunction, safeNonceRaw string var gasLimit uint64 var simulate bool var timeout uint var contractAddress common.Address var safeAddress, safeApi string var safeOperationType uint8 + var safeNonce *big.Int var from0 common.Address var from0Raw string @@ -3070,6 +3140,17 @@ func CreateSafeTransferFrom0Command() *cobra.Command { if SafeOperationType(safeOperationType).String() == "Unknown" { return fmt.Errorf("--safe-operation must be 0 (Call) or 1 (DelegateCall)") } + + if safeNonceRaw == "" { + fmt.Println("--safe-nonce not specified, using default (0)") + safeNonce = big.NewInt(0) + } else { + safeNonce = new(big.Int) + _, ok := safeNonce.SetString(safeNonceRaw, 0) + if !ok { + return fmt.Errorf("--safe-nonce is not a valid big integer") + } + } } if from0Raw == "" { @@ -3168,7 +3249,8 @@ func CreateSafeTransferFrom0Command() *cobra.Command { if value == nil { value = big.NewInt(0) } - err = CreateSafeProposal(client, key, common.HexToAddress(safeAddress), contractAddress, transaction, value, safeApi, SafeOperationType(safeOperationType)) + + err = CreateSafeProposal(client, key, common.HexToAddress(safeAddress), contractAddress, transaction, value, safeApi, SafeOperationType(safeOperationType), safeNonce) if err != nil { return fmt.Errorf("failed to create Safe proposal: %v", err) } @@ -3234,6 +3316,7 @@ func CreateSafeTransferFrom0Command() *cobra.Command { cmd.Flags().StringVar(&safeApi, "safe-api", "", "Safe API for the Safe Transaction Service (optional)") cmd.Flags().Uint8Var(&safeOperationType, "safe-operation", 0, "Safe operation type: 0 (Call) or 1 (DelegateCall)") cmd.Flags().StringVar(&safeFunction, "safe-function", "", "Safe function overrider to use for the transaction (optional)") + cmd.Flags().StringVar(&safeNonceRaw, "safe-nonce", "", "Safe nonce overrider for the transaction (optional)") cmd.Flags().StringVar(&from0Raw, "from-0", "", "from-0 argument (common.Address)") cmd.Flags().StringVar(&to0Raw, "to-0", "", "to-0 argument (common.Address)") @@ -3243,13 +3326,14 @@ func CreateSafeTransferFrom0Command() *cobra.Command { return cmd } func CreateSetApprovalForAllCommand() *cobra.Command { - var keyfile, nonce, password, value, gasPrice, maxFeePerGas, maxPriorityFeePerGas, rpc, contractAddressRaw, safeFunction string + var keyfile, nonce, password, value, gasPrice, maxFeePerGas, maxPriorityFeePerGas, rpc, contractAddressRaw, safeFunction, safeNonceRaw string var gasLimit uint64 var simulate bool var timeout uint var contractAddress common.Address var safeAddress, safeApi string var safeOperationType uint8 + var safeNonce *big.Int var operator common.Address var operatorRaw string @@ -3297,6 +3381,17 @@ func CreateSetApprovalForAllCommand() *cobra.Command { if SafeOperationType(safeOperationType).String() == "Unknown" { return fmt.Errorf("--safe-operation must be 0 (Call) or 1 (DelegateCall)") } + + if safeNonceRaw == "" { + fmt.Println("--safe-nonce not specified, using default (0)") + safeNonce = big.NewInt(0) + } else { + safeNonce = new(big.Int) + _, ok := safeNonce.SetString(safeNonceRaw, 0) + if !ok { + return fmt.Errorf("--safe-nonce is not a valid big integer") + } + } } if operatorRaw == "" { @@ -3380,7 +3475,8 @@ func CreateSetApprovalForAllCommand() *cobra.Command { if value == nil { value = big.NewInt(0) } - err = CreateSafeProposal(client, key, common.HexToAddress(safeAddress), contractAddress, transaction, value, safeApi, SafeOperationType(safeOperationType)) + + err = CreateSafeProposal(client, key, common.HexToAddress(safeAddress), contractAddress, transaction, value, safeApi, SafeOperationType(safeOperationType), safeNonce) if err != nil { return fmt.Errorf("failed to create Safe proposal: %v", err) } @@ -3444,6 +3540,7 @@ func CreateSetApprovalForAllCommand() *cobra.Command { cmd.Flags().StringVar(&safeApi, "safe-api", "", "Safe API for the Safe Transaction Service (optional)") cmd.Flags().Uint8Var(&safeOperationType, "safe-operation", 0, "Safe operation type: 0 (Call) or 1 (DelegateCall)") cmd.Flags().StringVar(&safeFunction, "safe-function", "", "Safe function overrider to use for the transaction (optional)") + cmd.Flags().StringVar(&safeNonceRaw, "safe-nonce", "", "Safe nonce overrider for the transaction (optional)") cmd.Flags().StringVar(&operatorRaw, "operator", "", "operator argument (common.Address)") cmd.Flags().StringVar(&approvedRaw, "approved", "", "approved argument (true, t, y, yes, 1 OR false, f, n, no, 0)") @@ -3451,13 +3548,14 @@ func CreateSetApprovalForAllCommand() *cobra.Command { return cmd } func CreateTransferFromCommand() *cobra.Command { - var keyfile, nonce, password, value, gasPrice, maxFeePerGas, maxPriorityFeePerGas, rpc, contractAddressRaw, safeFunction string + var keyfile, nonce, password, value, gasPrice, maxFeePerGas, maxPriorityFeePerGas, rpc, contractAddressRaw, safeFunction, safeNonceRaw string var gasLimit uint64 var simulate bool var timeout uint var contractAddress common.Address var safeAddress, safeApi string var safeOperationType uint8 + var safeNonce *big.Int var from0 common.Address var from0Raw string @@ -3507,6 +3605,17 @@ func CreateTransferFromCommand() *cobra.Command { if SafeOperationType(safeOperationType).String() == "Unknown" { return fmt.Errorf("--safe-operation must be 0 (Call) or 1 (DelegateCall)") } + + if safeNonceRaw == "" { + fmt.Println("--safe-nonce not specified, using default (0)") + safeNonce = big.NewInt(0) + } else { + safeNonce = new(big.Int) + _, ok := safeNonce.SetString(safeNonceRaw, 0) + if !ok { + return fmt.Errorf("--safe-nonce is not a valid big integer") + } + } } if from0Raw == "" { @@ -3594,7 +3703,8 @@ func CreateTransferFromCommand() *cobra.Command { if value == nil { value = big.NewInt(0) } - err = CreateSafeProposal(client, key, common.HexToAddress(safeAddress), contractAddress, transaction, value, safeApi, SafeOperationType(safeOperationType)) + + err = CreateSafeProposal(client, key, common.HexToAddress(safeAddress), contractAddress, transaction, value, safeApi, SafeOperationType(safeOperationType), safeNonce) if err != nil { return fmt.Errorf("failed to create Safe proposal: %v", err) } @@ -3659,6 +3769,7 @@ func CreateTransferFromCommand() *cobra.Command { cmd.Flags().StringVar(&safeApi, "safe-api", "", "Safe API for the Safe Transaction Service (optional)") cmd.Flags().Uint8Var(&safeOperationType, "safe-operation", 0, "Safe operation type: 0 (Call) or 1 (DelegateCall)") cmd.Flags().StringVar(&safeFunction, "safe-function", "", "Safe function overrider to use for the transaction (optional)") + cmd.Flags().StringVar(&safeNonceRaw, "safe-nonce", "", "Safe nonce overrider for the transaction (optional)") cmd.Flags().StringVar(&from0Raw, "from-0", "", "from-0 argument (common.Address)") cmd.Flags().StringVar(&to0Raw, "to-0", "", "to-0 argument (common.Address)") @@ -3667,13 +3778,14 @@ func CreateTransferFromCommand() *cobra.Command { return cmd } func CreateTransferOwnershipCommand() *cobra.Command { - var keyfile, nonce, password, value, gasPrice, maxFeePerGas, maxPriorityFeePerGas, rpc, contractAddressRaw, safeFunction string + var keyfile, nonce, password, value, gasPrice, maxFeePerGas, maxPriorityFeePerGas, rpc, contractAddressRaw, safeFunction, safeNonceRaw string var gasLimit uint64 var simulate bool var timeout uint var contractAddress common.Address var safeAddress, safeApi string var safeOperationType uint8 + var safeNonce *big.Int var newOwner common.Address var newOwnerRaw string @@ -3719,6 +3831,17 @@ func CreateTransferOwnershipCommand() *cobra.Command { if SafeOperationType(safeOperationType).String() == "Unknown" { return fmt.Errorf("--safe-operation must be 0 (Call) or 1 (DelegateCall)") } + + if safeNonceRaw == "" { + fmt.Println("--safe-nonce not specified, using default (0)") + safeNonce = big.NewInt(0) + } else { + safeNonce = new(big.Int) + _, ok := safeNonce.SetString(safeNonceRaw, 0) + if !ok { + return fmt.Errorf("--safe-nonce is not a valid big integer") + } + } } if newOwnerRaw == "" { @@ -3791,7 +3914,8 @@ func CreateTransferOwnershipCommand() *cobra.Command { if value == nil { value = big.NewInt(0) } - err = CreateSafeProposal(client, key, common.HexToAddress(safeAddress), contractAddress, transaction, value, safeApi, SafeOperationType(safeOperationType)) + + err = CreateSafeProposal(client, key, common.HexToAddress(safeAddress), contractAddress, transaction, value, safeApi, SafeOperationType(safeOperationType), safeNonce) if err != nil { return fmt.Errorf("failed to create Safe proposal: %v", err) } @@ -3854,6 +3978,7 @@ func CreateTransferOwnershipCommand() *cobra.Command { cmd.Flags().StringVar(&safeApi, "safe-api", "", "Safe API for the Safe Transaction Service (optional)") cmd.Flags().Uint8Var(&safeOperationType, "safe-operation", 0, "Safe operation type: 0 (Call) or 1 (DelegateCall)") cmd.Flags().StringVar(&safeFunction, "safe-function", "", "Safe function overrider to use for the transaction (optional)") + cmd.Flags().StringVar(&safeNonceRaw, "safe-nonce", "", "Safe nonce overrider for the transaction (optional)") cmd.Flags().StringVar(&newOwnerRaw, "new-owner", "", "new-owner argument (common.Address)") @@ -4081,7 +4206,7 @@ type SafeTransactionData struct { GasPrice string `json:"gasPrice"` GasToken string `json:"gasToken"` RefundReceiver string `json:"refundReceiver"` - Nonce uint64 `json:"nonce"` + Nonce *big.Int `json:"nonce"` SafeTxHash string `json:"safeTxHash"` Sender string `json:"sender"` Signature string `json:"signature"` @@ -4092,7 +4217,7 @@ const ( NativeTokenAddress = "0x0000000000000000000000000000000000000000" ) -func DeployWithSafe(client *ethclient.Client, key *keystore.Key, safeAddress common.Address, factoryAddress common.Address, value *big.Int, safeApi string, deployBytecode []byte, safeOperationType SafeOperationType, salt [32]byte) error { +func DeployWithSafe(client *ethclient.Client, key *keystore.Key, safeAddress common.Address, factoryAddress common.Address, value *big.Int, safeApi string, deployBytecode []byte, safeOperationType SafeOperationType, salt [32]byte, safeNonce *big.Int) error { abi, err := CreateCall.CreateCallMetaData.GetAbi() if err != nil { return fmt.Errorf("failed to get ABI: %v", err) @@ -4103,7 +4228,7 @@ func DeployWithSafe(client *ethclient.Client, key *keystore.Key, safeAddress com return fmt.Errorf("failed to pack performCreate2 transaction: %v", err) } - return CreateSafeProposal(client, key, safeAddress, factoryAddress, safeCreateCallTxData, value, safeApi, SafeOperationType(safeOperationType)) + return CreateSafeProposal(client, key, safeAddress, factoryAddress, safeCreateCallTxData, value, safeApi, SafeOperationType(safeOperationType), safeNonce) } func PredictDeploymentAddressSafe(from common.Address, salt [32]byte, deployBytecode []byte) (common.Address, error) { @@ -4116,7 +4241,7 @@ func PredictDeploymentAddressSafe(from common.Address, salt [32]byte, deployByte return deployedAddress, nil } -func CreateSafeProposal(client *ethclient.Client, key *keystore.Key, safeAddress common.Address, to common.Address, data []byte, value *big.Int, safeApi string, safeOperationType SafeOperationType) error { +func CreateSafeProposal(client *ethclient.Client, key *keystore.Key, safeAddress common.Address, to common.Address, data []byte, value *big.Int, safeApi string, safeOperationType SafeOperationType, safeNonce *big.Int) error { chainID, err := client.ChainID(context.Background()) if err != nil { return fmt.Errorf("failed to get chain ID: %v", err) @@ -4128,10 +4253,16 @@ func CreateSafeProposal(client *ethclient.Client, key *keystore.Key, safeAddress return fmt.Errorf("failed to create GnosisSafe instance: %v", err) } - // Fetch the current nonce from the Safe contract - nonce, err := safeInstance.Nonce(&bind.CallOpts{}) - if err != nil { - return fmt.Errorf("failed to fetch nonce from Safe contract: %v", err) + nonce := safeNonce + if safeNonce == nil { + // Fetch the current nonce from the Safe contract + fetchedNonce, err := safeInstance.Nonce(&bind.CallOpts{}) + if err != nil { + return fmt.Errorf("failed to fetch nonce from Safe contract: %v", err) + } + nonce = fetchedNonce + } else { + nonce = safeNonce } safeTransactionData := SafeTransactionData{ @@ -4144,7 +4275,7 @@ func CreateSafeProposal(client *ethclient.Client, key *keystore.Key, safeAddress GasPrice: "0", GasToken: NativeTokenAddress, RefundReceiver: NativeTokenAddress, - Nonce: nonce.Uint64(), + Nonce: nonce, } // Calculate SafeTxHash diff --git a/version/version.go b/version/version.go index 06b4342..9c975c4 100644 --- a/version/version.go +++ b/version/version.go @@ -1,3 +1,3 @@ package version -var SeerVersion string = "0.3.0" +var SeerVersion string = "0.3.1"