Skip to content

Commit

Permalink
Merge pull request #632 from rocket-pool/v1-stake-deposit-warning
Browse files Browse the repository at this point in the history
V1 stake/deposit warning
  • Loading branch information
0xfornax authored Sep 4, 2024
2 parents 34c5ed2 + f9b59ec commit ed5292a
Show file tree
Hide file tree
Showing 15 changed files with 205 additions and 11 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ require (
github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7
github.com/prysmaticlabs/prysm/v5 v5.0.3
github.com/rivo/tview v0.0.0-20230208211350-7dfff1ce7854
github.com/rocket-pool/rocketpool-go v1.8.4-0.20240704232530-a1f7c637454f
github.com/rocket-pool/rocketpool-go v1.8.4-0.20240903025128-025f78ebda85
github.com/sethvargo/go-password v0.2.0
github.com/shirou/gopsutil/v3 v3.23.1
github.com/tyler-smith/go-bip39 v1.1.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -633,8 +633,8 @@ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rocket-pool/go-merkletree v1.0.1-0.20220406020931-c262d9b976dd h1:p9KuetSKB9nte9I/MkkiM3pwKFVQgqxxPTQ0y56Ff6s=
github.com/rocket-pool/go-merkletree v1.0.1-0.20220406020931-c262d9b976dd/go.mod h1:UE9fof8P7iESVtLn1K9CTSkNRYVFHZHlf96RKbU33kA=
github.com/rocket-pool/rocketpool-go v1.8.4-0.20240704232530-a1f7c637454f h1:m+hdM1sfgQ++0cifmP7bz/vyjft50lBxrfUjNzBXWgY=
github.com/rocket-pool/rocketpool-go v1.8.4-0.20240704232530-a1f7c637454f/go.mod h1:f2TVsMOYmCwaJOhshG2zRoX89PZmvCkCD7UYJ9waRkI=
github.com/rocket-pool/rocketpool-go v1.8.4-0.20240903025128-025f78ebda85 h1:sCeOQE95E9KATbaz9rnHezLvZnJa0FdNp+kE7cwogSI=
github.com/rocket-pool/rocketpool-go v1.8.4-0.20240903025128-025f78ebda85/go.mod h1:f2TVsMOYmCwaJOhshG2zRoX89PZmvCkCD7UYJ9waRkI=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
Expand Down
2 changes: 1 addition & 1 deletion rocketpool-cli/node/create-vacant-minipool.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func createVacantMinipool(c *cli.Context, pubkey types.ValidatorPubkey) error {
if c.String("max-slippage") == "auto" {

// Use default max slippage
minNodeFee = nodeFees.NodeFee - DefaultMaxNodeFeeSlippage
minNodeFee = nodeFees.NodeFee - defaultMaxNodeFeeSlippage
if minNodeFee < nodeFees.MinNodeFee {
minNodeFee = nodeFees.MinNodeFee
}
Expand Down
13 changes: 11 additions & 2 deletions rocketpool-cli/node/deposit.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import (
)

// Config
const DefaultMaxNodeFeeSlippage = 0.01 // 1% below current network fee
const (
defaultMaxNodeFeeSlippage = 0.01 // 1% below current network fee
depositWarningMessage = "NOTE: by creating a new minipool, your node will automatically initialize voting power to itself. If you would like to delegate your on-chain voting power, you should run the command `rocketpool pdao initialize-voting` before creating a new minipool."
)

func nodeDeposit(c *cli.Context) error {

Expand Down Expand Up @@ -45,6 +48,12 @@ func nodeDeposit(c *cli.Context) error {
fmt.Println("Your eth2 client is on the correct network.")
fmt.Println()

// If hotfix is live and voting isn't initialized, display a warning
err = warnIfVotingUninitialized(rp, c, depositWarningMessage)
if err != nil {
return nil
}

// Check if the fee distributor has been initialized
isInitializedResponse, err := rp.IsFeeDistributorInitialized()
if err != nil {
Expand Down Expand Up @@ -100,7 +109,7 @@ func nodeDeposit(c *cli.Context) error {
if c.String("max-slippage") == "auto" {

// Use default max slippage
minNodeFee = nodeFees.NodeFee - DefaultMaxNodeFeeSlippage
minNodeFee = nodeFees.NodeFee - defaultMaxNodeFeeSlippage
if minNodeFee < nodeFees.MinNodeFee {
minNodeFee = nodeFees.MinNodeFee
}
Expand Down
11 changes: 11 additions & 0 deletions rocketpool-cli/node/stake-rpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ import (
"github.com/rocket-pool/smartnode/shared/utils/math"
)

// Config
const (
stakeRPLWarningMessage = "NOTE: by staking RPL, your node will automatically initialize voting power to itself. If you would like to delegate your on-chain voting power, you should run the command `rocketpool pdao initialize-voting` before staking RPL."
)

func nodeStakeRpl(c *cli.Context) error {

// Get RP client
Expand All @@ -29,6 +34,12 @@ func nodeStakeRpl(c *cli.Context) error {
return err
}

// If hotfix is live and voting isn't initialized, display a warning
err = warnIfVotingUninitialized(rp, c, stakeRPLWarningMessage)
if err != nil {
return nil
}

// If a custom nonce is set, print the multi-transaction warning
if c.GlobalUint64("nonce") != 0 {
cliutils.PrintMultiTransactionNonceWarning()
Expand Down
32 changes: 30 additions & 2 deletions rocketpool-cli/node/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

"github.com/goccy/go-json"
"github.com/mitchellh/go-homedir"
"github.com/urfave/cli"
"gopkg.in/yaml.v2"

"github.com/rocket-pool/rocketpool-go/types"
Expand Down Expand Up @@ -277,14 +278,14 @@ func promptTimezone() string {
func promptMinNodeFee(networkCurrentNodeFee, networkMinNodeFee float64) float64 {

// Get suggested min node fee
suggestedMinNodeFee := networkCurrentNodeFee - DefaultMaxNodeFeeSlippage
suggestedMinNodeFee := networkCurrentNodeFee - defaultMaxNodeFeeSlippage
if suggestedMinNodeFee < networkMinNodeFee {
suggestedMinNodeFee = networkMinNodeFee
}

// Prompt for suggested max slippage
fmt.Printf("The current network node commission rate that your minipool should receive is %f%%.\n", networkCurrentNodeFee*100)
fmt.Printf("The suggested maximum commission rate slippage for your deposit transaction is %f%%.\n", DefaultMaxNodeFeeSlippage*100)
fmt.Printf("The suggested maximum commission rate slippage for your deposit transaction is %f%%.\n", defaultMaxNodeFeeSlippage*100)
fmt.Printf("This will result in your minipool receiving a minimum possible commission rate of %f%%.\n", suggestedMinNodeFee*100)
if cliutils.Confirm("Do you want to use the suggested maximum commission rate slippage?") {
return suggestedMinNodeFee
Expand Down Expand Up @@ -389,3 +390,30 @@ func promptForSoloKeyPassword(rp *rocketpool.Client, cfg *config.RocketPoolConfi
return passwordFile, nil

}

// Display a warning if hotfix is live and voting is uninitialized
func warnIfVotingUninitialized(rp *rocketpool.Client, c *cli.Context, warningMessage string) error {
// Check for Houston 1.3.1 Hotfix
hotfix, err := rp.IsHoustonHotfixDeployed()
if err != nil {
return fmt.Errorf("error checking if Houston Hotfix has been deployed: %w", err)
}

if !hotfix.IsHoustonHotfixDeployed {
// Check if voting power is initialized
isVotingInitializedResponse, err := rp.IsVotingInitialized()
if err != nil {
return fmt.Errorf("error checking if voting is initialized: %w", err)
}
if !isVotingInitializedResponse.VotingInitialized {
fmt.Println("Your voting power hasn't been initialized yet. Please visit https://docs.rocketpool.net/guides/houston/participate#initializing-voting to learn more.")
// Post a warning about initializing voting
if !(c.Bool("yes") || cliutils.Confirm(fmt.Sprintf("%s%s%s\nWould you like to continue?", colorYellow, warningMessage, colorReset))) {
fmt.Println("Cancelled.")
return fmt.Errorf("operation cancelled by user")
}
}
}

return nil
}
18 changes: 18 additions & 0 deletions rocketpool/api/network/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,24 @@ func RegisterSubcommands(command *cli.Command, name string, aliases []string) {

},
},
{
Name: "is-houston-hotfix-deployed",
Aliases: []string{"ihhd"},
Usage: "Checks if Houston Hotfix 1.3.1 has been deployed yet.",
UsageText: "rocketpool api network is-houston-deployed",
Action: func(c *cli.Context) error {

// Validate args
if err := cliutils.ValidateArgCount(c, 0); err != nil {
return err
}

// Run
api.PrintResponse(isHoustonHotfixDeployed(c))
return nil

},
},

{
Name: "latest-delegate",
Expand Down
33 changes: 33 additions & 0 deletions rocketpool/api/network/upgrades.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package network

import (
"github.com/rocket-pool/smartnode/shared/services"
"github.com/rocket-pool/smartnode/shared/services/state"
"github.com/rocket-pool/smartnode/shared/types/api"
"github.com/urfave/cli"
)

func isHoustonHotfixDeployed(c *cli.Context) (*api.IsHoustonHotfixDeployedResponse, error) {

// Get services
if err := services.RequireRocketStorage(c); err != nil {
return nil, err
}
rp, err := services.GetRocketPool(c)
if err != nil {
return nil, err
}

// Response
response := api.IsHoustonHotfixDeployedResponse{}

isHoustonHotfixDeployed, err := state.IsHoustonHotfixDeployed(rp, nil)
if err != nil {
return nil, err
}
response.IsHoustonHotfixDeployed = isHoustonHotfixDeployed

// Return response
return &response, nil

}
22 changes: 20 additions & 2 deletions rocketpool/api/pdao/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -968,11 +968,29 @@ func RegisterSubcommands(command *cli.Command, name string, aliases []string) {

},
},
{
Name: "is-voting-initialized",
Aliases: []string{"ivi"},
Usage: "Checks if voting is initialized.",
UsageText: "rocketpool api pdao is-voting-initialized",
Action: func(c *cli.Context) error {

// Validate args
if err := cliutils.ValidateArgCount(c, 0); err != nil {
return err
}

// Run
api.PrintResponse(isVotingInitialized(c))
return nil

},
},
{
Name: "can-initialize-voting",
Aliases: []string{"civ"},
Usage: "Checks if voting can be initialized.",
UsageText: "rocketpool api pdao can-initialize-voting delegate-address",
UsageText: "rocketpool api pdao can-initialize-voting",
Action: func(c *cli.Context) error {

// Validate args
Expand All @@ -990,7 +1008,7 @@ func RegisterSubcommands(command *cli.Command, name string, aliases []string) {
Name: "initialize-voting",
Aliases: []string{"iv"},
Usage: "Initialize voting.",
UsageText: "rocketpool api pdao initialize-voting delegate-address",
UsageText: "rocketpool api pdao initialize-voting",
Action: func(c *cli.Context) error {

// Validate args
Expand Down
22 changes: 22 additions & 0 deletions rocketpool/api/pdao/initialize-voting.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,28 @@ import (
"github.com/rocket-pool/smartnode/shared/utils/eth1"
)

func isVotingInitialized(c *cli.Context) (*api.PDAOIsVotingInitializedResponse, error) {

w, err := services.GetWallet(c)
if err != nil {
return nil, err
}
rp, err := services.GetRocketPool(c)
if err != nil {
return nil, err
}
nodeAccount, err := w.GetNodeAccount()
if err != nil {
return nil, err
}

response := api.PDAOIsVotingInitializedResponse{}
response.VotingInitialized, err = network.GetVotingInitialized(rp, nodeAccount.Address, nil)

return &response, nil

}

func canNodeInitializeVoting(c *cli.Context) (*api.PDAOCanInitializeVotingResponse, error) {

// Get services
Expand Down
16 changes: 16 additions & 0 deletions shared/services/rocketpool/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,22 @@ func (c *Client) DownloadRewardsFile(interval uint64) (api.DownloadRewardsFileRe
return response, nil
}

// Check if Houston Hotfix 1.3.1 has been deployed yet
func (c *Client) IsHoustonHotfixDeployed() (api.IsHoustonHotfixDeployedResponse, error) {
responseBytes, err := c.callAPI("network is-houston-hotfix-deployed")
if err != nil {
return api.IsHoustonHotfixDeployedResponse{}, fmt.Errorf("could not check if Houston Hotfix is deployed: %w", err)
}
var response api.IsHoustonHotfixDeployedResponse
if err := json.Unmarshal(responseBytes, &response); err != nil {
return api.IsHoustonHotfixDeployedResponse{}, fmt.Errorf("could not decode is-houston-hotfix-deployed response: %w", err)
}
if response.Error != "" {
return api.IsHoustonHotfixDeployedResponse{}, fmt.Errorf("could not check if Houston Hotfix is deployed: %s", response.Error)
}
return response, nil
}

// Get the address of the latest minipool delegate contract
func (c *Client) GetLatestDelegate() (api.GetLatestDelegateResponse, error) {
responseBytes, err := c.callAPI("network latest-delegate")
Expand Down
18 changes: 17 additions & 1 deletion shared/services/rocketpool/pdao.go
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,23 @@ func (c *Client) GetCurrentVotingDelegate() (api.PDAOCurrentVotingDelegateRespon
return response, nil
}

// CanInitializeVoting fetches whether the node's is initialized for on-chain voting
// IsVotingInitialized checks if a node has initialized voting power
func (c *Client) IsVotingInitialized() (api.PDAOIsVotingInitializedResponse, error) {
responseBytes, err := c.callAPI("pdao is-voting-initialized")
if err != nil {
return api.PDAOIsVotingInitializedResponse{}, fmt.Errorf("could not call is-voting-initialized: %w", err)
}
var response api.PDAOIsVotingInitializedResponse
if err := json.Unmarshal(responseBytes, &response); err != nil {
return api.PDAOIsVotingInitializedResponse{}, fmt.Errorf("could not decode is-voting-initialized response: %w", err)
}
if response.Error != "" {
return api.PDAOIsVotingInitializedResponse{}, fmt.Errorf("error after requesting is-voting-initialized: %s", response.Error)
}
return response, nil
}

// CanInitializeVoting fetches the gas estimate and returns and error if voting is already initialized
func (c *Client) CanInitializeVoting() (api.PDAOCanInitializeVotingResponse, error) {
responseBytes, err := c.callAPI("pdao can-initialize-voting")
if err != nil {
Expand Down
11 changes: 11 additions & 0 deletions shared/services/state/update-checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,14 @@ func IsHoustonDeployed(rp *rocketpool.RocketPool, opts *bind.CallOpts) (bool, er
constraint, _ := version.NewConstraint(">= 1.3.0")
return constraint.Check(currentVersion), nil
}

// Check if Houston Hotfix has been deployed
func IsHoustonHotfixDeployed(rp *rocketpool.RocketPool, opts *bind.CallOpts) (bool, error) {
currentVersion, err := utils.GetCurrentVersion(rp, opts)
if err != nil {
return false, err
}

constraint, _ := version.NewConstraint(">= 1.3.1")
return constraint.Check(currentVersion), nil
}
6 changes: 6 additions & 0 deletions shared/types/api/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,9 @@ type GetLatestDelegateResponse struct {
Error string `json:"error"`
Address common.Address `json:"address"`
}

type IsHoustonHotfixDeployedResponse struct {
Status string `json:"status"`
Error string `json:"error"`
IsHoustonHotfixDeployed bool `json:"isHoustonHotfixDeployed"`
}
6 changes: 6 additions & 0 deletions shared/types/api/pdao.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,12 @@ type PDAOInitializeVotingResponse struct {
TxHash common.Hash `json:"txHash"`
}

type PDAOIsVotingInitializedResponse struct {
Status string `json:"status"`
Error string `json:"error"`
VotingInitialized bool `json:"votingInitialized"`
}

type PDAOStatusResponse struct {
Status string `json:"status"`
Error string `json:"error"`
Expand Down

0 comments on commit ed5292a

Please sign in to comment.