HIP-30: Emission split (#4497)

* HIP-30: sharding configuration boilerplate

* update comments

* goimports

* HIP-30: minimum validator commission of 7%

Based on #4495, which must be merged before this PR. This PR should be
rebased with dev after #4495 is merged to retain atomicity of changes by
pull request.

* goimports

* HIP-30: Emission split implementation

Note that the allocated split of the emission goes directly to the
recipient (and not via the Reward). This is because rewards are indexed
by validator and not by delegator, and the recipient may/may not have
any delegations which we can reward. Even if one was guaranteed to
exist, it would mess up the math of the validator.

* set up mainnet recipient of emission split

* HIP-30: Emission split addresses for non mainnet

* update test

* update test

* Update mainnet.go

---------

Co-authored-by: Casey Gardiner <117784577+ONECasey@users.noreply.github.com>
pull/4491/merge
Max 1 year ago committed by GitHub
parent 62feec962b
commit 0c981ff0d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 20
      internal/chain/engine.go
  2. 79
      internal/chain/reward.go
  3. 14
      internal/configs/sharding/instance.go
  4. 12
      internal/configs/sharding/localnet.go
  5. 4
      internal/configs/sharding/mainnet.go
  6. 10
      internal/configs/sharding/partner.go
  7. 13
      internal/configs/sharding/testnet.go

@ -6,6 +6,7 @@ import (
"sort" "sort"
"time" "time"
"github.com/harmony-one/harmony/common/denominations"
"github.com/harmony-one/harmony/internal/params" "github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/numeric" "github.com/harmony-one/harmony/numeric"
@ -312,7 +313,7 @@ func (e *engineImpl) Finalize(
// Accumulate block rewards and commit the final state root // Accumulate block rewards and commit the final state root
// Header seems complete, assemble into a block and return // Header seems complete, assemble into a block and return
payout, err := AccumulateRewardsAndCountSigs( remainder, payout, err := AccumulateRewardsAndCountSigs(
chain, state, header, beacon, sigsReady, chain, state, header, beacon, sigsReady,
) )
if err != nil { if err != nil {
@ -332,6 +333,23 @@ func (e *engineImpl) Finalize(
// TODO: make the viewID fetch from caller of the block proposal. // TODO: make the viewID fetch from caller of the block proposal.
header.SetViewID(new(big.Int).SetUint64(viewID())) header.SetViewID(new(big.Int).SetUint64(viewID()))
// Add the emission recovery split to the balance
if chain.Config().IsHIP30(header.Epoch()) {
// convert to ONE - note that numeric.Dec
// is designed for staking decimals and not
// ONE balances so we use big.Int for this math
remainderOne := new(big.Int).Div(
remainder.Int, big.NewInt(denominations.One),
)
// this goes directly to the balance (on shard 0, of course)
// because the reward mechanism isn't built to handle
// rewards not obtained from any delegations
state.AddBalance(
shard.Schedule.InstanceForEpoch(header.Epoch()).
HIP30RecoveryAddress(),
remainderOne,
)
}
// Finalize the state root // Finalize the state root
header.SetRoot(state.IntermediateRoot(chain.Config().IsS3(header.Epoch()))) header.SetRoot(state.IntermediateRoot(chain.Config().IsS3(header.Epoch())))
return types.NewBlock(header, txs, receipts, outcxs, incxs, stks), payout, nil return types.NewBlock(header, txs, receipts, outcxs, incxs, stks), payout, nil

@ -139,11 +139,11 @@ func lookupDelegatorShares(
func accumulateRewardsAndCountSigsBeforeStaking( func accumulateRewardsAndCountSigsBeforeStaking(
bc engine.ChainReader, state *state.DB, bc engine.ChainReader, state *state.DB,
header *block.Header, sigsReady chan bool, header *block.Header, sigsReady chan bool,
) (reward.Reader, error) { ) (numeric.Dec, reward.Reader, error) {
parentHeader := bc.GetHeaderByHash(header.ParentHash()) parentHeader := bc.GetHeaderByHash(header.ParentHash())
if parentHeader == nil { if parentHeader == nil {
return network.EmptyPayout, errors.Errorf( return numeric.ZeroDec(), network.EmptyPayout, errors.Errorf(
"cannot find parent block header in DB at parent hash %s", "cannot find parent block header in DB at parent hash %s",
header.ParentHash().Hex(), header.ParentHash().Hex(),
) )
@ -151,11 +151,11 @@ func accumulateRewardsAndCountSigsBeforeStaking(
if parentHeader.Number().Cmp(common.Big0) == 0 { if parentHeader.Number().Cmp(common.Big0) == 0 {
// Parent is an epoch block, // Parent is an epoch block,
// which is not signed in the usual manner therefore rewards nothing. // which is not signed in the usual manner therefore rewards nothing.
return network.EmptyPayout, nil return numeric.ZeroDec(), network.EmptyPayout, nil
} }
parentShardState, err := bc.ReadShardState(parentHeader.Epoch()) parentShardState, err := bc.ReadShardState(parentHeader.Epoch())
if err != nil { if err != nil {
return nil, errors.Wrapf( return numeric.ZeroDec(), nil, errors.Wrapf(
err, "cannot read shard state at epoch %v", parentHeader.Epoch(), err, "cannot read shard state at epoch %v", parentHeader.Epoch(),
) )
} }
@ -163,7 +163,7 @@ func accumulateRewardsAndCountSigsBeforeStaking(
// Block here until the commit sigs are ready or timeout. // Block here until the commit sigs are ready or timeout.
// sigsReady signal indicates that the commit sigs are already populated in the header object. // sigsReady signal indicates that the commit sigs are already populated in the header object.
if err := waitForCommitSigs(sigsReady); err != nil { if err := waitForCommitSigs(sigsReady); err != nil {
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
_, signers, _, err := availability.BallotResult( _, signers, _, err := availability.BallotResult(
@ -171,7 +171,7 @@ func accumulateRewardsAndCountSigsBeforeStaking(
) )
if err != nil { if err != nil {
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
totalAmount := big.NewInt(0) totalAmount := big.NewInt(0)
@ -194,12 +194,12 @@ func accumulateRewardsAndCountSigsBeforeStaking(
Int64("block-reward", stakingReward.PreStakedBlocks.Int64()). Int64("block-reward", stakingReward.PreStakedBlocks.Int64()).
Int64("total-amount-paid-out", totalAmount.Int64()). Int64("total-amount-paid-out", totalAmount.Int64()).
Msg("Total paid out was not equal to block-reward") Msg("Total paid out was not equal to block-reward")
return nil, errors.Wrapf( return numeric.ZeroDec(), nil, errors.Wrapf(
network.ErrPayoutNotEqualBlockReward, "payout "+totalAmount.String(), network.ErrPayoutNotEqualBlockReward, "payout "+totalAmount.String(),
) )
} }
return network.NewPreStakingEraRewarded(totalAmount), nil return numeric.ZeroDec(), network.NewPreStakingEraRewarded(totalAmount), nil
} }
// getDefaultStakingReward returns the static default reward based on the the block production interval and the chain. // getDefaultStakingReward returns the static default reward based on the the block production interval and the chain.
@ -240,14 +240,14 @@ func getDefaultStakingReward(bc engine.ChainReader, epoch *big.Int, blockNum uin
func AccumulateRewardsAndCountSigs( func AccumulateRewardsAndCountSigs(
bc engine.ChainReader, state *state.DB, bc engine.ChainReader, state *state.DB,
header *block.Header, beaconChain engine.ChainReader, sigsReady chan bool, header *block.Header, beaconChain engine.ChainReader, sigsReady chan bool,
) (reward.Reader, error) { ) (numeric.Dec, reward.Reader, error) {
blockNum := header.Number().Uint64() blockNum := header.Number().Uint64()
epoch := header.Epoch() epoch := header.Epoch()
isBeaconChain := bc.CurrentHeader().ShardID() == shard.BeaconChainShardID isBeaconChain := bc.CurrentHeader().ShardID() == shard.BeaconChainShardID
if blockNum == 0 { if blockNum == 0 {
err := waitForCommitSigs(sigsReady) // wait for commit signatures, or timeout and return err. err := waitForCommitSigs(sigsReady) // wait for commit signatures, or timeout and return err.
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
// Pre-staking era // Pre-staking era
@ -258,12 +258,12 @@ func AccumulateRewardsAndCountSigs(
// Rewards are accumulated only in the beaconchain, so just wait for commit sigs and return. // Rewards are accumulated only in the beaconchain, so just wait for commit sigs and return.
if !isBeaconChain { if !isBeaconChain {
err := waitForCommitSigs(sigsReady) err := waitForCommitSigs(sigsReady)
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
defaultReward := getDefaultStakingReward(bc, epoch, blockNum) defaultReward := getDefaultStakingReward(bc, epoch, blockNum)
if defaultReward.IsNegative() { // TODO: Figure out whether that's possible. if defaultReward.IsNegative() { // TODO: Figure out whether that's possible.
return network.EmptyPayout, nil return numeric.ZeroDec(), network.EmptyPayout, nil
} }
// Handle rewards on pre-aggregated rewards era. // Handle rewards on pre-aggregated rewards era.
@ -275,12 +275,12 @@ func AccumulateRewardsAndCountSigs(
// Wait for commit signatures, or timeout and return err. // Wait for commit signatures, or timeout and return err.
if err := waitForCommitSigs(sigsReady); err != nil { if err := waitForCommitSigs(sigsReady); err != nil {
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
// Only do reward distribution at the 63th block in the modulus. // Only do reward distribution at the 63th block in the modulus.
if blockNum%RewardFrequency != RewardFrequency-1 { if blockNum%RewardFrequency != RewardFrequency-1 {
return network.EmptyPayout, nil return numeric.ZeroDec(), network.EmptyPayout, nil
} }
return distributeRewardAfterAggregateEpoch(bc, state, header, beaconChain, defaultReward) return distributeRewardAfterAggregateEpoch(bc, state, header, beaconChain, defaultReward)
@ -300,7 +300,16 @@ func waitForCommitSigs(sigsReady chan bool) error {
} }
func distributeRewardAfterAggregateEpoch(bc engine.ChainReader, state *state.DB, header *block.Header, beaconChain engine.ChainReader, func distributeRewardAfterAggregateEpoch(bc engine.ChainReader, state *state.DB, header *block.Header, beaconChain engine.ChainReader,
defaultReward numeric.Dec) (reward.Reader, error) { rewardToDistribute numeric.Dec) (numeric.Dec, reward.Reader, error) {
epoch := header.Epoch()
defaultReward := rewardToDistribute
remainingReward := numeric.ZeroDec()
if bc.Config().IsHIP30(epoch) {
fractionToRecovery := shard.Schedule.InstanceForEpoch(epoch).HIP30EmissionFraction()
fractionToValidators := numeric.OneDec().Sub(fractionToRecovery)
defaultReward = rewardToDistribute.Mul(fractionToValidators)
remainingReward = rewardToDistribute.Mul(fractionToRecovery)
}
newRewards, payouts := newRewards, payouts :=
big.NewInt(0), []reward.Payout{} big.NewInt(0), []reward.Payout{}
@ -331,7 +340,7 @@ func distributeRewardAfterAggregateEpoch(bc engine.ChainReader, state *state.DB,
if cxLinks := curHeader.CrossLinks(); len(cxLinks) > 0 { if cxLinks := curHeader.CrossLinks(); len(cxLinks) > 0 {
crossLinks := types.CrossLinks{} crossLinks := types.CrossLinks{}
if err := rlp.DecodeBytes(cxLinks, &crossLinks); err != nil { if err := rlp.DecodeBytes(cxLinks, &crossLinks); err != nil {
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
allCrossLinks = append(allCrossLinks, crossLinks...) allCrossLinks = append(allCrossLinks, crossLinks...)
} }
@ -346,7 +355,7 @@ func distributeRewardAfterAggregateEpoch(bc engine.ChainReader, state *state.DB,
payables, _, err := processOneCrossLink(bc, state, cxLink, defaultReward, i) payables, _, err := processOneCrossLink(bc, state, cxLink, defaultReward, i)
if err != nil { if err != nil {
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
allPayables = append(allPayables, payables...) allPayables = append(allPayables, payables...)
@ -385,29 +394,29 @@ func distributeRewardAfterAggregateEpoch(bc engine.ChainReader, state *state.DB,
for _, addr := range allAddresses { for _, addr := range allAddresses {
snapshot, err := bc.ReadValidatorSnapshot(addr) snapshot, err := bc.ReadValidatorSnapshot(addr)
if err != nil { if err != nil {
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
due := allValidatorPayable[addr] due := allValidatorPayable[addr]
newRewards.Add(newRewards, due) newRewards.Add(newRewards, due)
shares, err := lookupDelegatorShares(snapshot) shares, err := lookupDelegatorShares(snapshot)
if err != nil { if err != nil {
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
if err := state.AddReward(snapshot.Validator, due, shares); err != nil { if err := state.AddReward(snapshot.Validator, due, shares); err != nil {
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
} }
utils.Logger().Debug().Int64("elapsed time", time.Now().Sub(startTimeLocal).Milliseconds()).Msg("After Chain Reward (AddReward)") utils.Logger().Debug().Int64("elapsed time", time.Now().Sub(startTimeLocal).Milliseconds()).Msg("After Chain Reward (AddReward)")
utils.Logger().Debug().Int64("elapsed time", time.Now().Sub(startTime).Milliseconds()).Msg("After Chain Reward") utils.Logger().Debug().Int64("elapsed time", time.Now().Sub(startTime).Milliseconds()).Msg("After Chain Reward")
return network.NewStakingEraRewardForRound( return remainingReward, network.NewStakingEraRewardForRound(
newRewards, payouts, newRewards, payouts,
), nil ), nil
} }
func distributeRewardBeforeAggregateEpoch(bc engine.ChainReader, state *state.DB, header *block.Header, beaconChain engine.ChainReader, func distributeRewardBeforeAggregateEpoch(bc engine.ChainReader, state *state.DB, header *block.Header, beaconChain engine.ChainReader,
defaultReward numeric.Dec, sigsReady chan bool) (reward.Reader, error) { defaultReward numeric.Dec, sigsReady chan bool) (numeric.Dec, reward.Reader, error) {
newRewards, payouts := newRewards, payouts :=
big.NewInt(0), []reward.Payout{} big.NewInt(0), []reward.Payout{}
@ -417,7 +426,7 @@ func distributeRewardBeforeAggregateEpoch(bc engine.ChainReader, state *state.DB
startTime := time.Now() startTime := time.Now()
crossLinks := types.CrossLinks{} crossLinks := types.CrossLinks{}
if err := rlp.DecodeBytes(cxLinks, &crossLinks); err != nil { if err := rlp.DecodeBytes(cxLinks, &crossLinks); err != nil {
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
utils.Logger().Debug().Int64("elapsed time", time.Now().Sub(startTime).Milliseconds()).Msg("Decode Cross Links") utils.Logger().Debug().Int64("elapsed time", time.Now().Sub(startTime).Milliseconds()).Msg("Decode Cross Links")
@ -427,7 +436,7 @@ func distributeRewardBeforeAggregateEpoch(bc engine.ChainReader, state *state.DB
payables, _, err := processOneCrossLink(bc, state, cxLink, defaultReward, i) payables, _, err := processOneCrossLink(bc, state, cxLink, defaultReward, i)
if err != nil { if err != nil {
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
allPayables = append(allPayables, payables...) allPayables = append(allPayables, payables...)
@ -461,17 +470,17 @@ func distributeRewardBeforeAggregateEpoch(bc engine.ChainReader, state *state.DB
payable.EcdsaAddress, payable.EcdsaAddress,
) )
if err != nil { if err != nil {
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
due := resultsHandle[bucket][payThem].payout due := resultsHandle[bucket][payThem].payout
newRewards.Add(newRewards, due) newRewards.Add(newRewards, due)
shares, err := lookupDelegatorShares(snapshot) shares, err := lookupDelegatorShares(snapshot)
if err != nil { if err != nil {
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
if err := state.AddReward(snapshot.Validator, due, shares); err != nil { if err := state.AddReward(snapshot.Validator, due, shares); err != nil {
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
payouts = append(payouts, reward.Payout{ payouts = append(payouts, reward.Payout{
Addr: payable.EcdsaAddress, Addr: payable.EcdsaAddress,
@ -487,14 +496,14 @@ func distributeRewardBeforeAggregateEpoch(bc engine.ChainReader, state *state.DB
// Block here until the commit sigs are ready or timeout. // Block here until the commit sigs are ready or timeout.
// sigsReady signal indicates that the commit sigs are already populated in the header object. // sigsReady signal indicates that the commit sigs are already populated in the header object.
if err := waitForCommitSigs(sigsReady); err != nil { if err := waitForCommitSigs(sigsReady); err != nil {
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
startTime := time.Now() startTime := time.Now()
// Take care of my own beacon chain committee, _ is missing, for slashing // Take care of my own beacon chain committee, _ is missing, for slashing
parentE, members, payable, missing, err := ballotResultBeaconchain(beaconChain, header) parentE, members, payable, missing, err := ballotResultBeaconchain(beaconChain, header)
if err != nil { if err != nil {
return network.EmptyPayout, errors.Wrapf(err, "shard 0 block %d reward error with bitmap %x", header.Number(), header.LastCommitBitmap()) return numeric.ZeroDec(), network.EmptyPayout, errors.Wrapf(err, "shard 0 block %d reward error with bitmap %x", header.Number(), header.LastCommitBitmap())
} }
subComm := shard.Committee{ShardID: shard.BeaconChainShardID, Slots: members} subComm := shard.Committee{ShardID: shard.BeaconChainShardID, Slots: members}
@ -505,13 +514,13 @@ func distributeRewardBeforeAggregateEpoch(bc engine.ChainReader, state *state.DB
payable, payable,
missing, missing,
); err != nil { ); err != nil {
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
votingPower, err := lookupVotingPower( votingPower, err := lookupVotingPower(
parentE, &subComm, parentE, &subComm,
) )
if err != nil { if err != nil {
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
allSignersShare := numeric.ZeroDec() allSignersShare := numeric.ZeroDec()
@ -528,7 +537,7 @@ func distributeRewardBeforeAggregateEpoch(bc engine.ChainReader, state *state.DB
if !voter.IsHarmonyNode { if !voter.IsHarmonyNode {
snapshot, err := bc.ReadValidatorSnapshot(voter.EarningAccount) snapshot, err := bc.ReadValidatorSnapshot(voter.EarningAccount)
if err != nil { if err != nil {
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
due := defaultReward.Mul( due := defaultReward.Mul(
voter.OverallPercent.Quo(allSignersShare), voter.OverallPercent.Quo(allSignersShare),
@ -537,10 +546,10 @@ func distributeRewardBeforeAggregateEpoch(bc engine.ChainReader, state *state.DB
shares, err := lookupDelegatorShares(snapshot) shares, err := lookupDelegatorShares(snapshot)
if err != nil { if err != nil {
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
if err := state.AddReward(snapshot.Validator, due, shares); err != nil { if err := state.AddReward(snapshot.Validator, due, shares); err != nil {
return network.EmptyPayout, err return numeric.ZeroDec(), network.EmptyPayout, err
} }
payouts = append(payouts, reward.Payout{ payouts = append(payouts, reward.Payout{
Addr: voter.EarningAccount, Addr: voter.EarningAccount,
@ -551,7 +560,7 @@ func distributeRewardBeforeAggregateEpoch(bc engine.ChainReader, state *state.DB
} }
utils.Logger().Debug().Int64("elapsed time", time.Now().Sub(startTime).Milliseconds()).Msg("Beacon Chain Reward") utils.Logger().Debug().Int64("elapsed time", time.Now().Sub(startTime).Milliseconds()).Msg("Beacon Chain Reward")
return network.NewStakingEraRewardForRound( return numeric.ZeroDec(), network.NewStakingEraRewardForRound(
newRewards, payouts, newRewards, payouts,
), nil ), nil
} }

@ -108,6 +108,20 @@ func NewInstance(
"emission split must be within [0, 1]", "emission split must be within [0, 1]",
) )
} }
if !emissionFractionToRecovery.Equal(numeric.ZeroDec()) {
if recoveryAddress == (ethCommon.Address{}) {
return nil, errors.Errorf(
"have non-zero emission split but no target address",
)
}
}
if recoveryAddress != (ethCommon.Address{}) {
if emissionFractionToRecovery.Equal(numeric.ZeroDec()) {
return nil, errors.Errorf(
"have target address but no emission split",
)
}
}
return instance{ return instance{
numShards: numShards, numShards: numShards,

@ -22,6 +22,9 @@ var feeCollectorsLocalnet = FeeCollectors{
mustAddress("0x1563915e194D8CfBA1943570603F7606A3115508"): numeric.MustNewDecFromStr("0.5"), mustAddress("0x1563915e194D8CfBA1943570603F7606A3115508"): numeric.MustNewDecFromStr("0.5"),
} }
// pk: 0x3333333333333333333333333333333333333333333333333333333333333333
var hip30CollectionAddressLocalnet = mustAddress("0x5CbDd86a2FA8Dc4bDdd8a8f69dBa48572EeC07FB")
type localnetSchedule struct{} type localnetSchedule struct{}
const ( const (
@ -36,6 +39,8 @@ const (
func (ls localnetSchedule) InstanceForEpoch(epoch *big.Int) Instance { func (ls localnetSchedule) InstanceForEpoch(epoch *big.Int) Instance {
switch { switch {
case params.LocalnetChainConfig.IsHIP30(epoch):
return localnetV4
case params.LocalnetChainConfig.IsFeeCollectEpoch(epoch): case params.LocalnetChainConfig.IsFeeCollectEpoch(epoch):
return localnetV3_2 return localnetV3_2
case params.LocalnetChainConfig.IsSixtyPercent(epoch): case params.LocalnetChainConfig.IsSixtyPercent(epoch):
@ -203,4 +208,11 @@ var (
numeric.ZeroDec(), ethCommon.Address{}, numeric.ZeroDec(), ethCommon.Address{},
localnetReshardingEpoch, LocalnetSchedule.BlocksPerEpoch(), localnetReshardingEpoch, LocalnetSchedule.BlocksPerEpoch(),
) )
localnetV4 = MustNewInstance(
2, 9, 6, 0, numeric.MustNewDecFromStr("0.68"),
genesis.LocalHarmonyAccountsV2, genesis.LocalFnAccountsV2,
emptyAllowlist, feeCollectorsLocalnet,
numeric.MustNewDecFromStr("0.25"), hip30CollectionAddressLocalnet,
localnetReshardingEpoch, LocalnetSchedule.BlocksPerEpoch(),
)
) )

@ -54,8 +54,8 @@ var (
mustAddress("0xbdFeE8587d347Cd8df002E6154763325265Fa84c"): numeric.MustNewDecFromStr("0.5"), mustAddress("0xbdFeE8587d347Cd8df002E6154763325265Fa84c"): numeric.MustNewDecFromStr("0.5"),
} }
hip30CollectionAddress = ethCommon.Address{} // Emission DAO
// hip30CollectionAddress = mustAddress("0xMustAddress") hip30CollectionAddress = mustAddress("0xD8194284df879f465ed61DBA6fa8300940cacEA3")
) )
func mustAddress(addrStr string) ethCommon.Address { func mustAddress(addrStr string) ethCommon.Address {

@ -42,6 +42,8 @@ const (
func (ps partnerSchedule) InstanceForEpoch(epoch *big.Int) Instance { func (ps partnerSchedule) InstanceForEpoch(epoch *big.Int) Instance {
switch { switch {
case params.PartnerChainConfig.IsHIP30(epoch):
return partnerV4
case params.PartnerChainConfig.IsFeeCollectEpoch(epoch): case params.PartnerChainConfig.IsFeeCollectEpoch(epoch):
return partnerV3 return partnerV3
case epoch.Cmp(feeCollectEpochV1) >= 0: case epoch.Cmp(feeCollectEpochV1) >= 0:
@ -121,3 +123,11 @@ var partnerV3 = MustNewInstance(
feeCollectorsDevnet[1], numeric.ZeroDec(), ethCommon.Address{}, feeCollectorsDevnet[1], numeric.ZeroDec(), ethCommon.Address{},
partnerReshardingEpoch, PartnerSchedule.BlocksPerEpoch(), partnerReshardingEpoch, PartnerSchedule.BlocksPerEpoch(),
) )
var partnerV4 = MustNewInstance(
2, 5, 4, 0,
numeric.MustNewDecFromStr("0.9"), genesis.TNHarmonyAccounts,
genesis.TNFoundationalAccounts, emptyAllowlist,
feeCollectorsDevnet[1], numeric.MustNewDecFromStr("0.25"),
hip30CollectionAddressTestnet, partnerReshardingEpoch,
PartnerSchedule.BlocksPerEpoch(),
)

@ -21,6 +21,8 @@ var feeCollectorsTestnet = FeeCollectors{
mustAddress("0xb41B6B8d9e68fD44caC8342BC2EEf4D59531d7d7"): numeric.MustNewDecFromStr("0.5"), mustAddress("0xb41B6B8d9e68fD44caC8342BC2EEf4D59531d7d7"): numeric.MustNewDecFromStr("0.5"),
} }
var hip30CollectionAddressTestnet = mustAddress("0x58dB8BeCe892F343350D125ff22B242784a8BA38")
type testnetSchedule struct{} type testnetSchedule struct{}
const ( const (
@ -40,6 +42,8 @@ const (
func (ts testnetSchedule) InstanceForEpoch(epoch *big.Int) Instance { func (ts testnetSchedule) InstanceForEpoch(epoch *big.Int) Instance {
switch { switch {
case params.TestnetChainConfig.IsHIP30(epoch):
return testnetV5
case params.TestnetChainConfig.IsFeeCollectEpoch(epoch): case params.TestnetChainConfig.IsFeeCollectEpoch(epoch):
return testnetV4 return testnetV4
case epoch.Cmp(shardReductionEpoch) >= 0: case epoch.Cmp(shardReductionEpoch) >= 0:
@ -157,4 +161,13 @@ var (
feeCollectorsTestnet, numeric.ZeroDec(), ethCommon.Address{}, feeCollectorsTestnet, numeric.ZeroDec(), ethCommon.Address{},
testnetReshardingEpoch, TestnetSchedule.BlocksPerEpoch(), testnetReshardingEpoch, TestnetSchedule.BlocksPerEpoch(),
) )
testnetV5 = MustNewInstance(
2, 30, 8, 0.15,
numeric.MustNewDecFromStr("0.90"), genesis.TNHarmonyAccountsV1,
genesis.TNFoundationalAccounts, emptyAllowlist,
feeCollectorsTestnet, numeric.MustNewDecFromStr("0.25"),
hip30CollectionAddressTestnet, testnetReshardingEpoch,
TestnetSchedule.BlocksPerEpoch(),
)
) )

Loading…
Cancel
Save