From 5e82c7a058485b8e5fba356f7e31f1b9881b6d04 Mon Sep 17 00:00:00 2001 From: dragonheaven Date: Sat, 15 May 2021 11:05:48 +0200 Subject: [PATCH 1/9] Add PIP18 Activation height --- config/activations.go | 7 +++++++ node/spr.go | 15 +++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/config/activations.go b/config/activations.go index 73cd837..d23f725 100644 --- a/config/activations.go +++ b/config/activations.go @@ -77,6 +77,12 @@ var ( // // Activation of 2.0.5 PIP10AverageActivation uint32 = 295190 + + // PIP18DelegateStakingActivation implements delegate staking by using PEG addresses. + // 1. Balances of PEG for each address is more complicated. It is the balance of PEG for the address (assuming it has not be delegated) + // 2. We quit looking at the rich list, and just consider the top 100 submissions with the highest stake + // 3. We pay out with the ratio of the total PEG staked. (Removes old top 100 PEG addresses staking reward and give staking opportunity to all PEG holders) + PIP18DelegateStakingActivation uint32 = 999999 ) func SetAllActivations(act uint32) { @@ -97,4 +103,5 @@ func SetAllActivations(act uint32) { V204EnhanceActivation = act V204BurnMintedTokenActivation = act PIP10AverageActivation = act + PIP18DelegateStakingActivation = act } diff --git a/node/spr.go b/node/spr.go index 5c11c49..106771e 100644 --- a/node/spr.go +++ b/node/spr.go @@ -31,6 +31,9 @@ func (d *Pegnetd) GradeS(ctx context.Context, block *factom.EBlock) (graderStake if block.Height >= config.V202EnhanceActivation { ver = 7 } + if block.Height >= config.PIP18DelegateStakingActivation { + ver = 8 + } g, err := graderStake.NewGrader(ver, int32(block.Height)) if err != nil { @@ -43,8 +46,16 @@ func (d *Pegnetd) GradeS(ctx context.Context, block *factom.EBlock) (graderStake } // allow only top 100 stake holders submit prices stakerRCD := extids[1] - if d.Pegnet.IsIncludedTopPEGAddress(stakerRCD) { - // ignore bad opr errors + if block.Height < config.PIP18DelegateStakingActivation { + if d.Pegnet.IsIncludedTopPEGAddress(stakerRCD) { + // ignore bad opr errors + err = g.AddSPR(entry.Hash[:], extids, entry.Content) + if err != nil { + // This is a noisy debug print + //logrus.WithError(err).WithFields(logrus.Fields{"hash": entry.Hash.String()}).Debug("failed to add spr") + } + } + } else { err = g.AddSPR(entry.Hash[:], extids, entry.Content) if err != nil { // This is a noisy debug print From 4b244da97b084804ffb762cda94d03db26bcb73e Mon Sep 17 00:00:00 2001 From: dragonheaven Date: Sat, 22 May 2021 23:48:49 +0200 Subject: [PATCH 2/9] Allow PEG address using IsNonZeroPEGAddress() --- node/pegnet/addresses.go | 17 +++++++++++++++++ node/spr.go | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/node/pegnet/addresses.go b/node/pegnet/addresses.go index 16ca618..bcb879a 100644 --- a/node/pegnet/addresses.go +++ b/node/pegnet/addresses.go @@ -462,6 +462,23 @@ func (p *Pegnet) IsIncludedTopPEGAddress(address []byte) bool { return false } +func (p *Pegnet) IsNonZeroPEGAddress(address []byte) bool { + stmt2 := `SELECT COUNT(*) FROM pn_addresses WHERE peg_balance > 0 AND address = ?;` + rows, err2 := p.DB.Query(stmt2, address[:]) + if err2 != nil { + fmt.Println("DB query is failed") + return false + } + defer rows.Close() + + for rows.Next() { + var count int + rows.Scan(&count) + return count > 0 + } + return false +} + // SelectRichList returns the balance of all addresses for a given ticker func (p *Pegnet) SelectRichList(ticker fat2.PTicker, count int) ([]BalancePair, error) { if ticker <= fat2.PTickerInvalid || fat2.PTickerMax <= ticker { diff --git a/node/spr.go b/node/spr.go index 106771e..11f14d8 100644 --- a/node/spr.go +++ b/node/spr.go @@ -55,7 +55,7 @@ func (d *Pegnetd) GradeS(ctx context.Context, block *factom.EBlock) (graderStake //logrus.WithError(err).WithFields(logrus.Fields{"hash": entry.Hash.String()}).Debug("failed to add spr") } } - } else { + } else if d.Pegnet.IsNonZeroPEGAddress(stakerRCD) { err = g.AddSPR(entry.Hash[:], extids, entry.Content) if err != nil { // This is a noisy debug print From 811d980131a88f25ce04fc063f1c3637f9339502 Mon Sep 17 00:00:00 2001 From: dragonheaven Date: Wed, 26 May 2021 23:23:36 +0200 Subject: [PATCH 3/9] IsNonZeroPEGAddress --- node/pegnet/addresses.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/pegnet/addresses.go b/node/pegnet/addresses.go index bcb879a..b1c4ece 100644 --- a/node/pegnet/addresses.go +++ b/node/pegnet/addresses.go @@ -464,7 +464,7 @@ func (p *Pegnet) IsIncludedTopPEGAddress(address []byte) bool { func (p *Pegnet) IsNonZeroPEGAddress(address []byte) bool { stmt2 := `SELECT COUNT(*) FROM pn_addresses WHERE peg_balance > 0 AND address = ?;` - rows, err2 := p.DB.Query(stmt2, address[:]) + rows, err2 := p.DB.Query(stmt2, address) if err2 != nil { fmt.Println("DB query is failed") return false From c3a182e16b457134b030beaf7a9307459aeeb96a Mon Sep 17 00:00:00 2001 From: dragonheaven Date: Thu, 27 May 2021 01:43:39 +0200 Subject: [PATCH 4/9] NewGraderV4 --- node/pegnet/addresses.go | 16 +++++++++------- node/spr.go | 10 +++++++--- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/node/pegnet/addresses.go b/node/pegnet/addresses.go index b1c4ece..7af0e8a 100644 --- a/node/pegnet/addresses.go +++ b/node/pegnet/addresses.go @@ -462,21 +462,23 @@ func (p *Pegnet) IsIncludedTopPEGAddress(address []byte) bool { return false } -func (p *Pegnet) IsNonZeroPEGAddress(address []byte) bool { - stmt2 := `SELECT COUNT(*) FROM pn_addresses WHERE peg_balance > 0 AND address = ?;` +func (p *Pegnet) GetPEGAddress(address []byte) (uint64, error) { + stmt2 := `SELECT peg_balance FROM pn_addresses WHERE address = ?;` rows, err2 := p.DB.Query(stmt2, address) if err2 != nil { fmt.Println("DB query is failed") - return false + return 0, err2 } defer rows.Close() for rows.Next() { - var count int - rows.Scan(&count) - return count > 0 + var pegBalance uint64 + if err := rows.Scan(&pegBalance); err != nil { + return 0, err + } + return pegBalance, nil } - return false + return 0, nil } // SelectRichList returns the balance of all addresses for a given ticker diff --git a/node/spr.go b/node/spr.go index 11f14d8..30d850c 100644 --- a/node/spr.go +++ b/node/spr.go @@ -36,9 +36,13 @@ func (d *Pegnetd) GradeS(ctx context.Context, block *factom.EBlock) (graderStake } g, err := graderStake.NewGrader(ver, int32(block.Height)) - if err != nil { + gv2, err2 := graderStake.NewGraderV4(ver, int32(block.Height)) + if err != nil && ver < 8 { return nil, err } + if err2 != nil && ver >= 8 { + return nil, err2 + } for _, entry := range block.Entries { extids := make([][]byte, len(entry.ExtIDs)) for i := range entry.ExtIDs { @@ -55,8 +59,8 @@ func (d *Pegnetd) GradeS(ctx context.Context, block *factom.EBlock) (graderStake //logrus.WithError(err).WithFields(logrus.Fields{"hash": entry.Hash.String()}).Debug("failed to add spr") } } - } else if d.Pegnet.IsNonZeroPEGAddress(stakerRCD) { - err = g.AddSPR(entry.Hash[:], extids, entry.Content) + } else if pegBalance, _ := d.Pegnet.GetPEGAddress(stakerRCD); pegBalance > 0 { + err = gv2.AddSPRV4(entry.Hash[:], extids, entry.Content, pegBalance) if err != nil { // This is a noisy debug print //logrus.WithError(err).WithFields(logrus.Fields{"hash": entry.Hash.String()}).Debug("failed to add spr") From 71282e89b9657cff501dde50b332b197a7c41721 Mon Sep 17 00:00:00 2001 From: dragonheaven Date: Thu, 19 Aug 2021 00:42:08 +0200 Subject: [PATCH 5/9] GradeDelegatedS --- node/pegnet/txhistory.go | 42 +++++++++++++++++++- node/spr.go | 83 +++++++++++++++++++++++++++++++--------- node/sync.go | 72 ++++++++++++++++++++++++++++++---- 3 files changed, 169 insertions(+), 28 deletions(-) diff --git a/node/pegnet/txhistory.go b/node/pegnet/txhistory.go index 82074ed..4f76685 100644 --- a/node/pegnet/txhistory.go +++ b/node/pegnet/txhistory.go @@ -5,6 +5,7 @@ import ( "encoding/hex" "encoding/json" "fmt" + "github.com/pegnet/pegnet/modules/graderDelegateStake" "strings" "time" @@ -426,6 +427,45 @@ func (p *Pegnet) InsertStaking100Coinbase(tx *sql.Tx, winner *graderStake.Gradin return nil } +// InsertCoinbase inserts the payouts from staking into the history system. +// There is one transaction per winning SPR, with the entry hash pointing to that specific spr +func (p *Pegnet) InsertStaking100CoinbaseDelegate(tx *sql.Tx, winner *graderDelegateStake.GradingDelegatedSPR, addr []byte, timestamp time.Time) error { + stmt, err := tx.Prepare(`INSERT INTO "pn_history_txbatch" + (entry_hash, height, blockorder, timestamp, executed) VALUES + (?, ?, ?, ?, ?)`) + if err != nil { + return err + } + + lookup, err := tx.Prepare(insertLookupQuery) + if err != nil { + return err + } + + _, err = stmt.Exec(winner.EntryHash, winner.SPR.GetHeight(), 0, timestamp.Unix(), winner.SPR.GetHeight()) + if err != nil { + return err + } + + coinbaseStatement, err := tx.Prepare(`INSERT INTO "pn_history_transaction" + (entry_hash, tx_index, action_type, from_address, from_asset, from_amount, to_asset, to_amount, outputs) VALUES + (?, ?, ?, ?, ?, ?, ?, ?, ?)`) + if err != nil { + return err + } + + _, err = coinbaseStatement.Exec(winner.EntryHash, 0, Coinbase, addr, "", 0, "PEG", winner.Payout(), "") + if err != nil { + return err + } + + if _, err = lookup.Exec(winner.EntryHash, 0, addr); err != nil { + return err + } + + return nil +} + // InsertStakingCoinbase inserts the payouts from mining into the history system. // There is one transaction per winning OPR, with the entry hash pointing to that specific opr func (p *Pegnet) InsertStakingCoinbase(tx *sql.Tx, txid string, height uint32, heightTimestamp time.Time, payouts map[string]uint64, addressMap map[string]factom.FAAddress) error { @@ -614,4 +654,4 @@ func (p *Pegnet) InsertZeroingCoinbase(tx *sql.Tx, txid string, addTxid string, } return nil -} \ No newline at end of file +} diff --git a/node/spr.go b/node/spr.go index 30d850c..7fd7b7d 100644 --- a/node/spr.go +++ b/node/spr.go @@ -3,8 +3,10 @@ package node import ( "context" "fmt" + "github.com/pegnet/pegnet/modules/spr" "github.com/Factom-Asset-Tokens/factom" + "github.com/pegnet/pegnet/modules/graderDelegateStake" "github.com/pegnet/pegnet/modules/graderStake" "github.com/pegnet/pegnetd/config" ) @@ -35,22 +37,18 @@ func (d *Pegnetd) GradeS(ctx context.Context, block *factom.EBlock) (graderStake ver = 8 } - g, err := graderStake.NewGrader(ver, int32(block.Height)) - gv2, err2 := graderStake.NewGraderV4(ver, int32(block.Height)) - if err != nil && ver < 8 { - return nil, err - } - if err2 != nil && ver >= 8 { - return nil, err2 - } - for _, entry := range block.Entries { - extids := make([][]byte, len(entry.ExtIDs)) - for i := range entry.ExtIDs { - extids[i] = entry.ExtIDs[i] + if ver < 8 { + g, err := graderStake.NewGrader(ver, int32(block.Height)) + if err != nil { + return nil, err } - // allow only top 100 stake holders submit prices - stakerRCD := extids[1] - if block.Height < config.PIP18DelegateStakingActivation { + for _, entry := range block.Entries { + extids := make([][]byte, len(entry.ExtIDs)) + for i := range entry.ExtIDs { + extids[i] = entry.ExtIDs[i] + } + // allow only top 100 stake holders submit prices + stakerRCD := extids[1] if d.Pegnet.IsIncludedTopPEGAddress(stakerRCD) { // ignore bad opr errors err = g.AddSPR(entry.Hash[:], extids, entry.Content) @@ -59,14 +57,61 @@ func (d *Pegnetd) GradeS(ctx context.Context, block *factom.EBlock) (graderStake //logrus.WithError(err).WithFields(logrus.Fields{"hash": entry.Hash.String()}).Debug("failed to add spr") } } - } else if pegBalance, _ := d.Pegnet.GetPEGAddress(stakerRCD); pegBalance > 0 { - err = gv2.AddSPRV4(entry.Hash[:], extids, entry.Content, pegBalance) + } + return g.Grade(), nil + } + return nil, nil +} + +// Grade Staking Price Records +func (d *Pegnetd) GradeDelegatedS(ctx context.Context, block *factom.EBlock) (graderDelegateStake.DelegatedGradedBlock, error) { + if block == nil { + // TODO: Handle the case where there is no opr block. + // Must delay conversions if this- happens + return nil, nil + } + + if *block.ChainID != config.SPRChain { + return nil, fmt.Errorf("trying to grade a non-spr chain") + } + + ver := uint8(8) + if block.Height >= config.PIP18DelegateStakingActivation { + ver = 8 + } + + if ver == 8 { + g, err := graderDelegateStake.NewDelegatedGrader(ver, int32(block.Height)) + if err != nil { + return nil, err + } + for _, entry := range block.Entries { + extids := make([][]byte, len(entry.ExtIDs)) + for i := range entry.ExtIDs { + extids[i] = entry.ExtIDs[i] + } + o2, errP := spr.ParseS1Content(entry.Content) + var balanceOfPEG uint64 = 0 + if errP == nil { + balanceOfPEG, _ = d.Pegnet.GetPEGAddress([]byte(o2.Address)) + } + if errP == nil && len(extids) == 5 && len(extids[0]) == 1 && extids[0][0] == 8 { + listOfDelegatorsAddress, err := g.GetDelegatorsAddress(extids[3], extids[4], o2.Address) + if err != nil { + continue + } + for i := 0; i < len(listOfDelegatorsAddress); i++ { + individualBalance, _ := d.Pegnet.GetPEGAddress([]byte(listOfDelegatorsAddress[i])) + balanceOfPEG += individualBalance + } + } + err = g.AddSPRV4(entry.Hash[:], extids, entry.Content, balanceOfPEG) if err != nil { // This is a noisy debug print //logrus.WithError(err).WithFields(logrus.Fields{"hash": entry.Hash.String()}).Debug("failed to add spr") } } + return g.Grade(), nil } - - return g.Grade(), nil + return nil, nil } diff --git a/node/sync.go b/node/sync.go index dcac58a..9a4e25a 100644 --- a/node/sync.go +++ b/node/sync.go @@ -4,6 +4,7 @@ import ( "context" "database/sql" "fmt" + "github.com/pegnet/pegnet/modules/graderDelegateStake" "math/big" "sort" "time" @@ -380,7 +381,17 @@ func (d *Pegnetd) SyncBlock(ctx context.Context, tx *sql.Tx, height uint32) erro // Then, grade the new OPR Block. The results of this will be used // to execute conversions that are in holding. gradedBlock, err := d.Grade(ctx, oprEBlock) - gradedSPRBlock, err_s := d.GradeS(ctx, sprEBlock) + + var gradedSPRBlock graderStake.GradedBlock + var gradedDelegatedSPRBlock graderDelegateStake.DelegatedGradedBlock + var err_s error + if sprEBlock != nil { + if height < config.PIP18DelegateStakingActivation { + gradedSPRBlock, err_s = d.GradeS(ctx, sprEBlock) + } else { + gradedDelegatedSPRBlock, err_s = d.GradeDelegatedS(ctx, sprEBlock) + } + } isRatesAvailable := false if height < config.V20HeightActivation { if err != nil { @@ -441,10 +452,19 @@ func (d *Pegnetd) SyncBlock(ctx context.Context, tx *sql.Tx, height uint32) erro oprWinners = winnersOpr[0].OPR.GetOrderedAssetsUint() } } - if gradedSPRBlock != nil { - winnersSpr := gradedSPRBlock.Winners() - if 0 < len(winnersSpr) { - sprWinners = winnersSpr[0].SPR.GetOrderedAssetsUint() + if height < config.PIP18DelegateStakingActivation { + if gradedSPRBlock != nil { + winnersSpr := gradedSPRBlock.Winners() + if 0 < len(winnersSpr) { + sprWinners = winnersSpr[0].SPR.GetOrderedAssetsUint() + } + } + } else { + if gradedDelegatedSPRBlock != nil { + winnersSpr := gradedDelegatedSPRBlock.Winners() + if 0 < len(winnersSpr) { + sprWinners = winnersSpr[0].SPR.GetOrderedAssetsUint() + } } } if 0 < len(oprWinners) || 0 < len(sprWinners) { @@ -555,9 +575,17 @@ func (d *Pegnetd) SyncBlock(ctx context.Context, tx *sql.Tx, height uint32) erro if height >= config.V20HeightActivation { // 5) Apply effects of graded SPR Block (PEG rewards, if any) // These funds will be available for transactions and conversions executed in the next block - if gradedSPRBlock != nil { - if err := d.ApplyGradedSPRBlock(tx, gradedSPRBlock, dblock.Timestamp); err != nil { - return err + if height < config.PIP18DelegateStakingActivation { + if gradedSPRBlock != nil { + if err := d.ApplyGradedSPRBlock(tx, gradedSPRBlock, dblock.Timestamp); err != nil { + return err + } + } + } else { + if gradedDelegatedSPRBlock != nil { + if err := d.ApplyGradedDelegatedSPRBlock(tx, gradedDelegatedSPRBlock, dblock.Timestamp); err != nil { + return err + } } } } @@ -1421,6 +1449,34 @@ func (d *Pegnetd) ApplyGradedSPRBlock(tx *sql.Tx, gradedSPRBlock graderStake.Gra return nil } +// ApplyGradedDelegatedSPRBlock pays out PEG to the winners of the given GradedBlock. +// If an error is returned, the sql.Tx should be rolled back by the caller. +func (d *Pegnetd) ApplyGradedDelegatedSPRBlock(tx *sql.Tx, gradedSPRBlock graderDelegateStake.DelegatedGradedBlock, timestamp time.Time) error { + winners := gradedSPRBlock.Winners() + for i := range winners { + addr, err := factom.NewFAAddress(winners[i].SPR.GetAddress()) + if err != nil { + // TODO: This is kinda an odd case. I think we should just drop the rewards + // for an invalid address. We can always add back the rewards and they will have + // a higher balance after a change. + log.WithError(err).WithFields(log.Fields{ + "height": winners[i].SPR.GetHeight(), + "ehash": fmt.Sprintf("%x", winners[i].EntryHash), + }).Warnf("failed to reward") + continue + } + + if _, err := d.Pegnet.AddToBalance(tx, &addr, fat2.PTickerPEG, uint64(winners[i].Payout())); err != nil { + return err + } + + if err := d.Pegnet.InsertStaking100CoinbaseDelegate(tx, winners[i], addr[:], timestamp); err != nil { + return err + } + } + return nil +} + func isDone(ctx context.Context) bool { select { case <-ctx.Done(): From dc879b1b4e3201e59dbeac2336aa9abb3b8eadaa Mon Sep 17 00:00:00 2001 From: dragonheaven Date: Thu, 19 Aug 2021 21:02:18 +0200 Subject: [PATCH 6/9] Check if element is exist in GradeDelegatedS --- node/spr.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/node/spr.go b/node/spr.go index 7fd7b7d..1df3bf1 100644 --- a/node/spr.go +++ b/node/spr.go @@ -63,6 +63,16 @@ func (d *Pegnetd) GradeS(ctx context.Context, block *factom.EBlock) (graderStake return nil, nil } +func isElementExist(element string, list []string) bool { + isExist := false + for j := 0; j < len(list); j++ { + if list[j] == element { + isExist = true + } + } + return isExist +} + // Grade Staking Price Records func (d *Pegnetd) GradeDelegatedS(ctx context.Context, block *factom.EBlock) (graderDelegateStake.DelegatedGradedBlock, error) { if block == nil { @@ -85,6 +95,7 @@ func (d *Pegnetd) GradeDelegatedS(ctx context.Context, block *factom.EBlock) (gr if err != nil { return nil, err } + var groupOfDelegatorsAddress []string for _, entry := range block.Entries { extids := make([][]byte, len(entry.ExtIDs)) for i := range entry.ExtIDs { @@ -101,8 +112,13 @@ func (d *Pegnetd) GradeDelegatedS(ctx context.Context, block *factom.EBlock) (gr continue } for i := 0; i < len(listOfDelegatorsAddress); i++ { + isDuplicatedAddress := isElementExist(listOfDelegatorsAddress[i], groupOfDelegatorsAddress) + if isDuplicatedAddress { + continue + } individualBalance, _ := d.Pegnet.GetPEGAddress([]byte(listOfDelegatorsAddress[i])) balanceOfPEG += individualBalance + groupOfDelegatorsAddress = append(groupOfDelegatorsAddress, listOfDelegatorsAddress[i]) } } err = g.AddSPRV4(entry.Hash[:], extids, entry.Content, balanceOfPEG) From 74bfd5606f244060db4fdd9b9d261a84032a3707 Mon Sep 17 00:00:00 2001 From: dragonheaven Date: Mon, 30 Aug 2021 21:11:01 +0200 Subject: [PATCH 7/9] PIP18DelegateStakingActivation --- config/activations.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/activations.go b/config/activations.go index d23f725..985da8b 100644 --- a/config/activations.go +++ b/config/activations.go @@ -82,7 +82,7 @@ var ( // 1. Balances of PEG for each address is more complicated. It is the balance of PEG for the address (assuming it has not be delegated) // 2. We quit looking at the rich list, and just consider the top 100 submissions with the highest stake // 3. We pay out with the ratio of the total PEG staked. (Removes old top 100 PEG addresses staking reward and give staking opportunity to all PEG holders) - PIP18DelegateStakingActivation uint32 = 999999 + PIP18DelegateStakingActivation uint32 = 313042 ) func SetAllActivations(act uint32) { From bcb2433b64069be5d8f22cf4868839c9a7e5d230 Mon Sep 17 00:00:00 2001 From: dragonheaven Date: Tue, 31 Aug 2021 00:05:11 +0200 Subject: [PATCH 8/9] PIP18DelegateStakingActivation --- config/activations.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/activations.go b/config/activations.go index 985da8b..9bde47e 100644 --- a/config/activations.go +++ b/config/activations.go @@ -82,7 +82,7 @@ var ( // 1. Balances of PEG for each address is more complicated. It is the balance of PEG for the address (assuming it has not be delegated) // 2. We quit looking at the rich list, and just consider the top 100 submissions with the highest stake // 3. We pay out with the ratio of the total PEG staked. (Removes old top 100 PEG addresses staking reward and give staking opportunity to all PEG holders) - PIP18DelegateStakingActivation uint32 = 313042 + PIP18DelegateStakingActivation uint32 = 313906 ) func SetAllActivations(act uint32) { From 11f2b2a1a28fd39d05337c2262d0e99bd4df7148 Mon Sep 17 00:00:00 2001 From: dragonheaven Date: Mon, 6 Sep 2021 15:46:42 +0200 Subject: [PATCH 9/9] PIP18DelegateStakingActivation --- config/activations.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/activations.go b/config/activations.go index 9bde47e..6ed917c 100644 --- a/config/activations.go +++ b/config/activations.go @@ -82,7 +82,7 @@ var ( // 1. Balances of PEG for each address is more complicated. It is the balance of PEG for the address (assuming it has not be delegated) // 2. We quit looking at the rich list, and just consider the top 100 submissions with the highest stake // 3. We pay out with the ratio of the total PEG staked. (Removes old top 100 PEG addresses staking reward and give staking opportunity to all PEG holders) - PIP18DelegateStakingActivation uint32 = 313906 + PIP18DelegateStakingActivation uint32 = 314482 ) func SetAllActivations(act uint32) {