Skip to content
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

add a new command to withdraw banned funds #80

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,14 @@ Additionally, you can update the commission if you need to.
hydra hydragon commission --data-dir ./node-secrets --commission 10 --jsonrpc http://localhost:8545
```

### Claiming the generated rewards from validating

Once a validator starts validating blocks, rewards are generated at the end of each epoch based on the validator’s activity level. Validators can claim rewards at any time, provided rewards have been generated. If no rewards are available, the transaction will fail. Use the following command:

```
hydra hydragon claim-rewards --data-dir ./node-secrets --jsonrpc http://localhost:8545
```

### Ban Validator
To reduce the risk of stalling caused by validators experiencing temporary issues or acting maliciously, we’ve implemented an ejection and ban mechanism. Anyone who recongizes a suspicious activity, and the rules are met, can execute the ban process. Below is an outline of how the system works (specific conditions are detailed in our [genesis contracts](https://github.com/Hydra-Chain/hydragon-core-contracts)):
1. **Initial Ejection**: If your validator stops proposing or participating in consensus whether due to hardware failure, software issues, or malicious intent—the ban procedure will be initiated. The validator will be ejected, allowing time for recovery. If no action is taken, a ban may follow. The threshold to trigger this process is initially set at 18,000 blocks (~2 hours), depending on block creation speed.
Expand All @@ -207,6 +215,15 @@ To reduce the risk of stalling caused by validators experiencing temporary issue

***Note:** Please keep in mind that if malicious behavior is detected, a manual ban can be initiated by the Hydragon DAO. Furthermore, if the conditions for initiating a ban and enforcing the ban are met, a user can execute the relevant functions by interacting with the contract via the explorer or programmatically.*

#### Withdrawing funds after ban

If your validator has been banned, you can still withdraw the remaining funds after the penalty and burned rewards have been deducted. Use the following command:

```
hydra hydragon withdraw --banned --data-dir ./node-secrets --jsonrpc http://localhost:8545
```

***Note:*** If your machine is no longer running, you can use [our RPC](#adding-hydragon-network-to-metamask) as the value for the jsonrpc flag.

### Command Line Interface

Expand Down
23 changes: 12 additions & 11 deletions command/sidechain/commission/commission.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ import (
)

var (
params setCommissionParams

delegationManager = contracts.HydraDelegationContract
setCommissionFn = contractsapi.HydraDelegation.Abi.Methods["setCommission"]
commissionUpdatedEventABI = contractsapi.HydraDelegation.Abi.Events["CommissionUpdated"]
)

var params setCommissionParams

func GetCommand() *cobra.Command {
setCommissionCmd := &cobra.Command{
Use: "commission",
Expand Down Expand Up @@ -141,19 +142,19 @@ func runCommand(cmd *cobra.Command, _ []string) error {
}

func setCommission(sender txrelayer.TxRelayer, account *wallet.Account) (*ethgo.Receipt, error) {
setCommissionFn := &contractsapi.SetCommissionHydraDelegationFn{
NewCommission: new(big.Int).SetUint64(params.commission),
}

input, err := setCommissionFn.EncodeAbi()
encoded, err := setCommissionFn.Encode([]interface{}{
new(big.Int).SetUint64(params.commission),
})
if err != nil {
return nil, fmt.Errorf("encoding set commission function failed: %w", err)
}

txn := &ethgo.Transaction{
Input: input,
To: (*ethgo.Address)(&delegationManager),
}
txn := sidechain.CreateTransaction(
account.Ecdsa.Address(),
(*ethgo.Address)(&delegationManager),
encoded,
nil,
)

receipt, err := sender.SendTransaction(txn, account.Ecdsa)
if err != nil {
Expand Down
14 changes: 14 additions & 0 deletions command/sidechain/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package sidechain
import (
"errors"
"fmt"
"math/big"
"os"

"github.com/0xPolygon/polygon-edge/command/polybftsecrets"
"github.com/0xPolygon/polygon-edge/consensus/polybft/wallet"
"github.com/umbracle/ethgo"
)

const (
Expand Down Expand Up @@ -60,3 +62,15 @@ func GetAccount(
func GetAccountFromDir(accountDir string, insecureLocalStore bool) (*wallet.Account, error) {
return GetAccount(accountDir, "", insecureLocalStore)
}

// CreateTransaction is a helper function that creates a standard transaction based on the input parameters
func CreateTransaction(sender ethgo.Address, to *ethgo.Address, input []byte, value *big.Int) *ethgo.Transaction {
txn := &ethgo.Transaction{
From: sender,
To: to,
Input: input,
Value: value,
}

return txn
}
25 changes: 13 additions & 12 deletions command/sidechain/registration/register_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,16 @@ import (
)

var (
params registerParams

hydraChain = contracts.HydraChainContract
stakeManager = contracts.HydraStakingContract
registerFn = contractsapi.HydraChain.Abi.Methods["register"]
stakeFn = contractsapi.HydraStaking.Abi.Methods["stake"]
newValidatorEventABI = contractsapi.HydraChain.Abi.Events["NewValidator"]
stakeEventABI = contractsapi.HydraStaking.Abi.Events["Staked"]
)

var params registerParams

func GetCommand() *cobra.Command {
registerCmd := &cobra.Command{
Use: "register-validator",
Expand Down Expand Up @@ -240,20 +241,20 @@ func registerValidator(
return nil, fmt.Errorf("register validator failed: %w", err)
}

registerFn := &contractsapi.RegisterHydraChainFn{
Signature: sigMarshal,
Pubkey: account.Bls.PublicKey().ToBigInt(),
}

input, err := registerFn.EncodeAbi()
encoded, err := registerFn.Encode([]interface{}{
sigMarshal,
account.Bls.PublicKey().ToBigInt(),
})
if err != nil {
return nil, fmt.Errorf("register validator failed: %w", err)
}

txn := &ethgo.Transaction{
Input: input,
To: (*ethgo.Address)(&hydraChain),
}
txn := sidechain.CreateTransaction(
account.Ecdsa.Address(),
(*ethgo.Address)(&hydraChain),
encoded,
nil,
)

return sender.SendTransaction(txn, account.Ecdsa)
}
21 changes: 12 additions & 9 deletions command/sidechain/rewards/rewards.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ import (
"github.com/0xPolygon/polygon-edge/types"
)

var params withdrawRewardsParams
var (
params withdrawRewardsParams

claimRewardsFn = contractsapi.HydraStaking.Abi.Methods["claimStakingRewards"]
)

func GetCommand() *cobra.Command {
unstakeCmd := &cobra.Command{
Expand Down Expand Up @@ -81,18 +85,17 @@ func runCommand(cmd *cobra.Command, _ []string) error {
return err
}

claimRewardsFn := contractsapi.ClaimStakingRewardsHydraStakingFn{}

encoded, err := claimRewardsFn.EncodeAbi()
encoded, err := claimRewardsFn.Encode([]interface{}{})
if err != nil {
return err
}

txn := &ethgo.Transaction{
From: validatorAddr,
Input: encoded,
To: (*ethgo.Address)(&contracts.HydraStakingContract),
}
txn := sidechain.CreateTransaction(
validatorAddr,
(*ethgo.Address)(&contracts.HydraStakingContract),
encoded,
nil,
)

receipt, err := txRelayer.SendTransaction(txn, validatorAccount.Ecdsa)
if err != nil {
Expand Down
36 changes: 18 additions & 18 deletions command/sidechain/staking/stake.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ import (
)

var (
params stakeParams
params stakeParams

stakeFn = contractsapi.HydraStaking.Abi.Methods["stake"]
delegateFn = contractsapi.HydraDelegation.Abi.Methods["delegate"]
stakeEventABI = contractsapi.HydraStaking.Abi.Events["Staked"]
delegateEventABI = contractsapi.HydraDelegation.Abi.Events["Delegated"]
)
Expand Down Expand Up @@ -115,35 +118,32 @@ func runCommand(cmd *cobra.Command, _ []string) error {
var contractAddr *ethgo.Address

if params.self {
encoded, err = contractsapi.HydraStaking.Abi.Methods["stake"].Encode([]interface{}{})
if err != nil {
return err
}

encoded, err = stakeFn.Encode([]interface{}{})
contractAddr = (*ethgo.Address)(&contracts.HydraStakingContract)
} else {
delegateToAddress := types.StringToAddress(params.delegateAddress)

encoded, err = contractsapi.HydraDelegation.Abi.Methods["delegate"].Encode(
[]interface{}{ethgo.Address(delegateToAddress), false})
if err != nil {
return err
}

encoded, err = delegateFn.Encode([]interface{}{
ethgo.Address(delegateToAddress),
})
contractAddr = (*ethgo.Address)(&contracts.HydraDelegationContract)
}

if err != nil {
return err
}

parsedValue, err := common.ParseUint256orHex(&params.amount)
if err != nil {
return fmt.Errorf("cannot parse \"amount\" value %s", params.amount)
}

txn := &ethgo.Transaction{
From: validatorAccount.Ecdsa.Address(),
Input: encoded,
To: contractAddr,
Value: parsedValue,
}
txn := sidechain.CreateTransaction(
validatorAccount.Ecdsa.Address(),
contractAddr,
encoded,
parsedValue,
)

receipt, err := txRelayer.SendTransaction(txn, validatorAccount.Ecdsa)
if err != nil {
Expand Down
17 changes: 9 additions & 8 deletions command/sidechain/terminate-ban/terminate_ban.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (

var (
params terminateBanParams

terminateBanFn = contractsapi.HydraChain.Abi.Methods["terminateBanProcedure"]
)

func GetCommand() *cobra.Command {
Expand Down Expand Up @@ -84,18 +86,17 @@ func runCommand(cmd *cobra.Command, _ []string) error {
return err
}

encoded, err := contractsapi.HydraChain.Abi.Methods["terminateBanProcedure"].Encode(
[]interface{}{},
)
encoded, err := terminateBanFn.Encode([]interface{}{})
if err != nil {
return err
}

txn := &ethgo.Transaction{
From: validatorAccount.Ecdsa.Address(),
Input: encoded,
To: (*ethgo.Address)(&contracts.HydraChainContract),
}
txn := sidechain.CreateTransaction(
validatorAccount.Ecdsa.Address(),
(*ethgo.Address)(&contracts.HydraChainContract),
encoded,
nil,
)

receipt, err := txRelayer.SendTransaction(txn, validatorAccount.Ecdsa)
if err != nil {
Expand Down
25 changes: 14 additions & 11 deletions command/sidechain/unstaking/unstake.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ import (
"github.com/umbracle/ethgo"
)

var params unstakeParams
var (
params unstakeParams

unstakeFn = contractsapi.HydraStaking.Abi.Methods["unstake"]
)

func GetCommand() *cobra.Command {
unstakeCmd := &cobra.Command{
Expand Down Expand Up @@ -85,20 +89,19 @@ func runCommand(cmd *cobra.Command, _ []string) error {
return err
}

unstakeFn := &contractsapi.UnstakeHydraStakingFn{
Amount: params.amountValue,
}

encoded, err := unstakeFn.EncodeAbi()
encoded, err := unstakeFn.Encode([]interface{}{
params.amountValue,
})
if err != nil {
return err
}

txn := &ethgo.Transaction{
From: validatorAccount.Ecdsa.Address(),
Input: encoded,
To: (*ethgo.Address)(&contracts.HydraStakingContract),
}
txn := sidechain.CreateTransaction(
validatorAccount.Ecdsa.Address(),
(*ethgo.Address)(&contracts.HydraStakingContract),
encoded,
nil,
)

receipt, err := txRelayer.SendTransaction(txn, validatorAccount.Ecdsa)
if err != nil {
Expand Down
15 changes: 8 additions & 7 deletions command/sidechain/whitelist/whitelist_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ import (
)

var (
params whitelistParams

whitelistFn = contractsapi.HydraChain.Abi.Methods["addToWhitelist"]
whitelistEventABI = contractsapi.HydraChain.Abi.Events["AddedToWhitelist"]
)

var params whitelistParams

func GetCommand() *cobra.Command {
registerCmd := &cobra.Command{
Use: "whitelist-validator",
Expand Down Expand Up @@ -101,11 +101,12 @@ func runCommand(cmd *cobra.Command, _ []string) error {
return fmt.Errorf("enlist validator failed: %w", err)
}

txn := &ethgo.Transaction{
From: governanceAccount.Ecdsa.Address(),
Input: encoded,
To: (*ethgo.Address)(&contracts.HydraChainContract),
}
txn := sidechain.CreateTransaction(
governanceAccount.Ecdsa.Address(),
(*ethgo.Address)(&contracts.HydraChainContract),
encoded,
nil,
)

receipt, err := txRelayer.SendTransaction(txn, governanceAccount.Ecdsa)
if err != nil {
Expand Down
5 changes: 5 additions & 0 deletions command/sidechain/withdraw/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@ import (
sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain"
)

var (
bannedFundsFlag = "banned"
)

type withdrawParams struct {
accountDir string
accountConfig string
jsonRPC string
bannedFunds bool
insecureLocalStore bool
}

Expand Down
Loading