Skip to content

Commit

Permalink
Merge pull request #1 from fissionlabsio/x-distr-scrt-foundation-tax
Browse files Browse the repository at this point in the history
Secret Foundation Tax
  • Loading branch information
assafmo authored Sep 2, 2020
2 parents 325be5f + 3709237 commit f48cced
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 24 deletions.
2 changes: 1 addition & 1 deletion x/distribution/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func NewCommunityPoolSpendProposalHandler(k Keeper) govtypes.Handler {
return keeper.HandleCommunityPoolSpendProposal(ctx, k, c)

default:
return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized distr proposal content type: %T", c)
return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s proposal content type: %T", types.ModuleName, c)
}
}
}
36 changes: 30 additions & 6 deletions x/distribution/keeper/allocation.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,24 +77,48 @@ func (k Keeper) AllocateTokens(
previousProposer.String()))
}

// calculate fraction allocated to validators
communityTax := k.GetCommunityTax(ctx)
voteMultiplier := sdk.OneDec().Sub(proposerMultiplier).Sub(communityTax)

// allocate tokens proportionally to voting power
// TODO consider parallelizing later, ref https://github.com/enigmampc/cosmos-sdk/pull/3099#discussion_r246276376
foundationTax := k.GetSecretFoundationTax(ctx)
foundationTaxAddr := k.GetSecretFoundationAddr(ctx)

// only apply the secret foundation tax when the tax and address is non-zero
var foundationTaxSum sdk.DecCoins
if !foundationTax.IsZero() && !foundationTaxAddr.Empty() {
voteMultiplier = voteMultiplier.Sub(foundationTax)

foundationTaxSum = feesCollected.MulDecTruncate(foundationTax)
remaining = remaining.Sub(foundationTaxSum)
}

// allocate tokens proportionally to voting power minus any taxes
for _, vote := range previousVotes {
validator := k.stakingKeeper.ValidatorByConsAddr(ctx, vote.Validator.Address)

// TODO consider microslashing for missing votes.
// ref https://github.com/enigmampc/cosmos-sdk/issues/2525#issuecomment-430838701
powerFraction := sdk.NewDec(vote.Validator.Power).QuoTruncate(sdk.NewDec(totalPreviousPower))
reward := feesCollected.MulDecTruncate(voteMultiplier).MulDecTruncate(powerFraction)

// allocate tokens to the validator
k.AllocateTokensToValidator(ctx, validator, reward)

// update the remaining allocation for the community pool
remaining = remaining.Sub(reward)
}

// allocate community funding
// Send the foundation tax sum to the foundation tax address. Note, the taxes
// collected are decimals and when coverted to integer coins, we must truncate.
// The remainder is given back to the community pool.
if !foundationTaxSum.IsZero() {
foundationTaxSumTrunc, rem := foundationTaxSum.TruncateDecimal()
remaining = remaining.Add(rem...)

if err := k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, foundationTaxAddr, foundationTaxSumTrunc); err != nil {
panic(err)
}
}

// allocate community funding minus the foundation tax
feePool.CommunityPool = feePool.CommunityPool.Add(remaining...)
k.SetFeePool(ctx, feePool)
}
Expand Down
12 changes: 12 additions & 0 deletions x/distribution/keeper/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,15 @@ func (k Keeper) GetWithdrawAddrEnabled(ctx sdk.Context) (enabled bool) {
k.paramSpace.Get(ctx, types.ParamStoreKeyWithdrawAddrEnabled, &enabled)
return enabled
}

// GetSecretFoundationTax returns the current secret foundation tax.
func (k Keeper) GetSecretFoundationTax(ctx sdk.Context) (tax sdk.Dec) {
k.paramSpace.Get(ctx, types.ParamSecretFoundationTax, &tax)
return tax
}

// GetSecretFoundationAddr returns the current secret foundation address.
func (k Keeper) GetSecretFoundationAddr(ctx sdk.Context) (addr sdk.AccAddress) {
k.paramSpace.Get(ctx, types.ParamSecretFoundationAddress, &addr)
return addr
}
25 changes: 21 additions & 4 deletions x/distribution/simulation/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
sdk "github.com/enigmampc/cosmos-sdk/types"
"github.com/enigmampc/cosmos-sdk/types/module"
"github.com/enigmampc/cosmos-sdk/x/distribution/types"
"github.com/enigmampc/cosmos-sdk/x/simulation"
)

// Simulation parameter constants
Expand All @@ -19,6 +20,7 @@ const (
BaseProposerReward = "base_proposer_reward"
BonusProposerReward = "bonus_proposer_reward"
WithdrawEnabled = "withdraw_enabled"
FoundationTax = "foundation_tax"
)

// GenCommunityTax randomized CommunityTax
Expand All @@ -41,6 +43,11 @@ func GenWithdrawEnabled(r *rand.Rand) bool {
return r.Int63n(101) <= 95 // 95% chance of withdraws being enabled
}

// GenSecretFoundationTax returns a randomized secret foundation tax parameter.
func GenSecretFoundationTax(r *rand.Rand) sdk.Dec {
return sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(int64(r.Intn(30)), 2))
}

// RandomizedGenState generates a random GenesisState for distribution
func RandomizedGenState(simState *module.SimulationState) {
var communityTax sdk.Dec
Expand All @@ -67,13 +74,23 @@ func RandomizedGenState(simState *module.SimulationState) {
func(r *rand.Rand) { withdrawEnabled = GenWithdrawEnabled(r) },
)

var foundationTax sdk.Dec
simState.AppParams.GetOrGenerate(
simState.Cdc, FoundationTax, &foundationTax, simState.Rand,
func(r *rand.Rand) { foundationTax = GenSecretFoundationTax(r) },
)

foundationTaxAcc, _ := simulation.RandomAcc(simState.Rand, simState.Accounts)

distrGenesis := types.GenesisState{
FeePool: types.InitialFeePool(),
Params: types.Params{
CommunityTax: communityTax,
BaseProposerReward: baseProposerReward,
BonusProposerReward: bonusProposerReward,
WithdrawAddrEnabled: withdrawEnabled,
CommunityTax: communityTax,
SecretFoundationTax: foundationTax,
SecretFoundationAddress: foundationTaxAcc.Address,
BaseProposerReward: baseProposerReward,
BonusProposerReward: bonusProposerReward,
WithdrawAddrEnabled: withdrawEnabled,
},
}

Expand Down
10 changes: 8 additions & 2 deletions x/distribution/simulation/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,23 @@ const (
keyCommunityTax = "communitytax"
keyBaseProposerReward = "baseproposerreward"
keyBonusProposerReward = "bonusproposerreward"
keySecretFoundationTax = "secretfoundationtax"
)

// ParamChanges defines the parameters that can be modified by param change proposals
// on the simulation
// ParamChanges defines the parameters that can be modified by param change
// proposals in simulations.
func ParamChanges(r *rand.Rand) []simulation.ParamChange {
return []simulation.ParamChange{
simulation.NewSimParamChange(types.ModuleName, keyCommunityTax,
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", GenCommunityTax(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keySecretFoundationTax,
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", GenSecretFoundationTax(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyBaseProposerReward,
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", GenBaseProposerReward(r))
Expand Down
13 changes: 10 additions & 3 deletions x/distribution/types/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,16 @@ type GenesisState struct {
}

func NewGenesisState(
params Params, fp FeePool, dwis []DelegatorWithdrawInfo, pp sdk.ConsAddress, r []ValidatorOutstandingRewardsRecord,
acc []ValidatorAccumulatedCommissionRecord, historical []ValidatorHistoricalRewardsRecord,
cur []ValidatorCurrentRewardsRecord, dels []DelegatorStartingInfoRecord, slashes []ValidatorSlashEventRecord,
params Params,
fp FeePool,
dwis []DelegatorWithdrawInfo,
pp sdk.ConsAddress,
r []ValidatorOutstandingRewardsRecord,
acc []ValidatorAccumulatedCommissionRecord,
historical []ValidatorHistoricalRewardsRecord,
cur []ValidatorCurrentRewardsRecord,
dels []DelegatorStartingInfoRecord,
slashes []ValidatorSlashEventRecord,
) GenesisState {

return GenesisState{
Expand Down
61 changes: 53 additions & 8 deletions x/distribution/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,18 @@ var (
ParamStoreKeyBaseProposerReward = []byte("baseproposerreward")
ParamStoreKeyBonusProposerReward = []byte("bonusproposerreward")
ParamStoreKeyWithdrawAddrEnabled = []byte("withdrawaddrenabled")
ParamSecretFoundationTax = []byte("secretfoundationtax")
ParamSecretFoundationAddress = []byte("secretfoundationaddress")
)

// Params defines the set of distribution parameters.
type Params struct {
CommunityTax sdk.Dec `json:"community_tax" yaml:"community_tax"`
BaseProposerReward sdk.Dec `json:"base_proposer_reward" yaml:"base_proposer_reward"`
BonusProposerReward sdk.Dec `json:"bonus_proposer_reward" yaml:"bonus_proposer_reward"`
WithdrawAddrEnabled bool `json:"withdraw_addr_enabled" yaml:"withdraw_addr_enabled"`
CommunityTax sdk.Dec `json:"community_tax" yaml:"community_tax"`
BaseProposerReward sdk.Dec `json:"base_proposer_reward" yaml:"base_proposer_reward"`
BonusProposerReward sdk.Dec `json:"bonus_proposer_reward" yaml:"bonus_proposer_reward"`
WithdrawAddrEnabled bool `json:"withdraw_addr_enabled" yaml:"withdraw_addr_enabled"`
SecretFoundationTax sdk.Dec `json:"secret_foundation_tax" yaml:"secret_foundation_tax"`
SecretFoundationAddress sdk.AccAddress `json:"secret_foundation_address" yaml:"secret_foundation_address"`
}

// ParamKeyTable returns the parameter key table.
Expand All @@ -38,10 +42,12 @@ func ParamKeyTable() params.KeyTable {
// DefaultParams returns default distribution parameters
func DefaultParams() Params {
return Params{
CommunityTax: sdk.NewDecWithPrec(2, 2), // 2%
BaseProposerReward: sdk.NewDecWithPrec(1, 2), // 1%
BonusProposerReward: sdk.NewDecWithPrec(4, 2), // 4%
WithdrawAddrEnabled: true,
CommunityTax: sdk.NewDecWithPrec(2, 2), // 2%
SecretFoundationTax: sdk.ZeroDec(), // 0%
SecretFoundationAddress: sdk.AccAddress{},
BaseProposerReward: sdk.NewDecWithPrec(1, 2), // 1%
BonusProposerReward: sdk.NewDecWithPrec(4, 2), // 4%
WithdrawAddrEnabled: true,
}
}

Expand All @@ -57,6 +63,8 @@ func (p *Params) ParamSetPairs() params.ParamSetPairs {
params.NewParamSetPair(ParamStoreKeyBaseProposerReward, &p.BaseProposerReward, validateBaseProposerReward),
params.NewParamSetPair(ParamStoreKeyBonusProposerReward, &p.BonusProposerReward, validateBonusProposerReward),
params.NewParamSetPair(ParamStoreKeyWithdrawAddrEnabled, &p.WithdrawAddrEnabled, validateWithdrawAddrEnabled),
params.NewParamSetPair(ParamSecretFoundationTax, &p.SecretFoundationTax, validateSecretFoundationTax),
params.NewParamSetPair(ParamSecretFoundationAddress, &p.SecretFoundationAddress, validateSecretFoundationAddress),
}
}

Expand All @@ -67,6 +75,11 @@ func (p Params) ValidateBasic() error {
"community tax should non-negative and less than one: %s", p.CommunityTax,
)
}
if p.SecretFoundationTax.IsNegative() || p.SecretFoundationTax.GT(sdk.OneDec()) {
return fmt.Errorf(
"secret foundation tax should non-negative and less than one: %s", p.SecretFoundationTax,
)
}
if p.BaseProposerReward.IsNegative() {
return fmt.Errorf(
"base proposer reward should be positive: %s", p.BaseProposerReward,
Expand Down Expand Up @@ -105,6 +118,38 @@ func validateCommunityTax(i interface{}) error {
return nil
}

func validateSecretFoundationTax(i interface{}) error {
v, ok := i.(sdk.Dec)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}

if v.IsNil() {
return fmt.Errorf("secret foundation tax must be not nil")
}
if v.IsNegative() {
return fmt.Errorf("secret foundation tax must be positive: %s", v)
}
if v.GT(sdk.OneDec()) {
return fmt.Errorf("secret foundation tax too large: %s", v)
}

return nil
}

func validateSecretFoundationAddress(i interface{}) error {
v, ok := i.(sdk.AccAddress)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}

if !v.Empty() {
return sdk.VerifyAddressFormat(v)
}

return nil
}

func validateBaseProposerReward(i interface{}) error {
v, ok := i.(sdk.Dec)
if !ok {
Expand Down

0 comments on commit f48cced

Please sign in to comment.