Skip to content

Commit f48cced

Browse files
authored
Merge pull request #1 from fissionlabsio/x-distr-scrt-foundation-tax
Secret Foundation Tax
2 parents 325be5f + 3709237 commit f48cced

File tree

7 files changed

+135
-24
lines changed

7 files changed

+135
-24
lines changed

x/distribution/handler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func NewCommunityPoolSpendProposalHandler(k Keeper) govtypes.Handler {
107107
return keeper.HandleCommunityPoolSpendProposal(ctx, k, c)
108108

109109
default:
110-
return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized distr proposal content type: %T", c)
110+
return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s proposal content type: %T", types.ModuleName, c)
111111
}
112112
}
113113
}

x/distribution/keeper/allocation.go

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,24 +77,48 @@ func (k Keeper) AllocateTokens(
7777
previousProposer.String()))
7878
}
7979

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

84-
// allocate tokens proportionally to voting power
85-
// TODO consider parallelizing later, ref https://github.com/enigmampc/cosmos-sdk/pull/3099#discussion_r246276376
83+
foundationTax := k.GetSecretFoundationTax(ctx)
84+
foundationTaxAddr := k.GetSecretFoundationAddr(ctx)
85+
86+
// only apply the secret foundation tax when the tax and address is non-zero
87+
var foundationTaxSum sdk.DecCoins
88+
if !foundationTax.IsZero() && !foundationTaxAddr.Empty() {
89+
voteMultiplier = voteMultiplier.Sub(foundationTax)
90+
91+
foundationTaxSum = feesCollected.MulDecTruncate(foundationTax)
92+
remaining = remaining.Sub(foundationTaxSum)
93+
}
94+
95+
// allocate tokens proportionally to voting power minus any taxes
8696
for _, vote := range previousVotes {
8797
validator := k.stakingKeeper.ValidatorByConsAddr(ctx, vote.Validator.Address)
8898

89-
// TODO consider microslashing for missing votes.
90-
// ref https://github.com/enigmampc/cosmos-sdk/issues/2525#issuecomment-430838701
9199
powerFraction := sdk.NewDec(vote.Validator.Power).QuoTruncate(sdk.NewDec(totalPreviousPower))
92100
reward := feesCollected.MulDecTruncate(voteMultiplier).MulDecTruncate(powerFraction)
101+
102+
// allocate tokens to the validator
93103
k.AllocateTokensToValidator(ctx, validator, reward)
104+
105+
// update the remaining allocation for the community pool
94106
remaining = remaining.Sub(reward)
95107
}
96108

97-
// allocate community funding
109+
// Send the foundation tax sum to the foundation tax address. Note, the taxes
110+
// collected are decimals and when coverted to integer coins, we must truncate.
111+
// The remainder is given back to the community pool.
112+
if !foundationTaxSum.IsZero() {
113+
foundationTaxSumTrunc, rem := foundationTaxSum.TruncateDecimal()
114+
remaining = remaining.Add(rem...)
115+
116+
if err := k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, foundationTaxAddr, foundationTaxSumTrunc); err != nil {
117+
panic(err)
118+
}
119+
}
120+
121+
// allocate community funding minus the foundation tax
98122
feePool.CommunityPool = feePool.CommunityPool.Add(remaining...)
99123
k.SetFeePool(ctx, feePool)
100124
}

x/distribution/keeper/params.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,15 @@ func (k Keeper) GetWithdrawAddrEnabled(ctx sdk.Context) (enabled bool) {
4141
k.paramSpace.Get(ctx, types.ParamStoreKeyWithdrawAddrEnabled, &enabled)
4242
return enabled
4343
}
44+
45+
// GetSecretFoundationTax returns the current secret foundation tax.
46+
func (k Keeper) GetSecretFoundationTax(ctx sdk.Context) (tax sdk.Dec) {
47+
k.paramSpace.Get(ctx, types.ParamSecretFoundationTax, &tax)
48+
return tax
49+
}
50+
51+
// GetSecretFoundationAddr returns the current secret foundation address.
52+
func (k Keeper) GetSecretFoundationAddr(ctx sdk.Context) (addr sdk.AccAddress) {
53+
k.paramSpace.Get(ctx, types.ParamSecretFoundationAddress, &addr)
54+
return addr
55+
}

x/distribution/simulation/genesis.go

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
sdk "github.com/enigmampc/cosmos-sdk/types"
1212
"github.com/enigmampc/cosmos-sdk/types/module"
1313
"github.com/enigmampc/cosmos-sdk/x/distribution/types"
14+
"github.com/enigmampc/cosmos-sdk/x/simulation"
1415
)
1516

1617
// Simulation parameter constants
@@ -19,6 +20,7 @@ const (
1920
BaseProposerReward = "base_proposer_reward"
2021
BonusProposerReward = "bonus_proposer_reward"
2122
WithdrawEnabled = "withdraw_enabled"
23+
FoundationTax = "foundation_tax"
2224
)
2325

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

46+
// GenSecretFoundationTax returns a randomized secret foundation tax parameter.
47+
func GenSecretFoundationTax(r *rand.Rand) sdk.Dec {
48+
return sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(int64(r.Intn(30)), 2))
49+
}
50+
4451
// RandomizedGenState generates a random GenesisState for distribution
4552
func RandomizedGenState(simState *module.SimulationState) {
4653
var communityTax sdk.Dec
@@ -67,13 +74,23 @@ func RandomizedGenState(simState *module.SimulationState) {
6774
func(r *rand.Rand) { withdrawEnabled = GenWithdrawEnabled(r) },
6875
)
6976

77+
var foundationTax sdk.Dec
78+
simState.AppParams.GetOrGenerate(
79+
simState.Cdc, FoundationTax, &foundationTax, simState.Rand,
80+
func(r *rand.Rand) { foundationTax = GenSecretFoundationTax(r) },
81+
)
82+
83+
foundationTaxAcc, _ := simulation.RandomAcc(simState.Rand, simState.Accounts)
84+
7085
distrGenesis := types.GenesisState{
7186
FeePool: types.InitialFeePool(),
7287
Params: types.Params{
73-
CommunityTax: communityTax,
74-
BaseProposerReward: baseProposerReward,
75-
BonusProposerReward: bonusProposerReward,
76-
WithdrawAddrEnabled: withdrawEnabled,
88+
CommunityTax: communityTax,
89+
SecretFoundationTax: foundationTax,
90+
SecretFoundationAddress: foundationTaxAcc.Address,
91+
BaseProposerReward: baseProposerReward,
92+
BonusProposerReward: bonusProposerReward,
93+
WithdrawAddrEnabled: withdrawEnabled,
7794
},
7895
}
7996

x/distribution/simulation/params.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,23 @@ const (
1414
keyCommunityTax = "communitytax"
1515
keyBaseProposerReward = "baseproposerreward"
1616
keyBonusProposerReward = "bonusproposerreward"
17+
keySecretFoundationTax = "secretfoundationtax"
1718
)
1819

19-
// ParamChanges defines the parameters that can be modified by param change proposals
20-
// on the simulation
20+
// ParamChanges defines the parameters that can be modified by param change
21+
// proposals in simulations.
2122
func ParamChanges(r *rand.Rand) []simulation.ParamChange {
2223
return []simulation.ParamChange{
2324
simulation.NewSimParamChange(types.ModuleName, keyCommunityTax,
2425
func(r *rand.Rand) string {
2526
return fmt.Sprintf("\"%s\"", GenCommunityTax(r))
2627
},
2728
),
29+
simulation.NewSimParamChange(types.ModuleName, keySecretFoundationTax,
30+
func(r *rand.Rand) string {
31+
return fmt.Sprintf("\"%s\"", GenSecretFoundationTax(r))
32+
},
33+
),
2834
simulation.NewSimParamChange(types.ModuleName, keyBaseProposerReward,
2935
func(r *rand.Rand) string {
3036
return fmt.Sprintf("\"%s\"", GenBaseProposerReward(r))

x/distribution/types/genesis.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,16 @@ type GenesisState struct {
6666
}
6767

6868
func NewGenesisState(
69-
params Params, fp FeePool, dwis []DelegatorWithdrawInfo, pp sdk.ConsAddress, r []ValidatorOutstandingRewardsRecord,
70-
acc []ValidatorAccumulatedCommissionRecord, historical []ValidatorHistoricalRewardsRecord,
71-
cur []ValidatorCurrentRewardsRecord, dels []DelegatorStartingInfoRecord, slashes []ValidatorSlashEventRecord,
69+
params Params,
70+
fp FeePool,
71+
dwis []DelegatorWithdrawInfo,
72+
pp sdk.ConsAddress,
73+
r []ValidatorOutstandingRewardsRecord,
74+
acc []ValidatorAccumulatedCommissionRecord,
75+
historical []ValidatorHistoricalRewardsRecord,
76+
cur []ValidatorCurrentRewardsRecord,
77+
dels []DelegatorStartingInfoRecord,
78+
slashes []ValidatorSlashEventRecord,
7279
) GenesisState {
7380

7481
return GenesisState{

x/distribution/types/params.go

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,18 @@ var (
2020
ParamStoreKeyBaseProposerReward = []byte("baseproposerreward")
2121
ParamStoreKeyBonusProposerReward = []byte("bonusproposerreward")
2222
ParamStoreKeyWithdrawAddrEnabled = []byte("withdrawaddrenabled")
23+
ParamSecretFoundationTax = []byte("secretfoundationtax")
24+
ParamSecretFoundationAddress = []byte("secretfoundationaddress")
2325
)
2426

2527
// Params defines the set of distribution parameters.
2628
type Params struct {
27-
CommunityTax sdk.Dec `json:"community_tax" yaml:"community_tax"`
28-
BaseProposerReward sdk.Dec `json:"base_proposer_reward" yaml:"base_proposer_reward"`
29-
BonusProposerReward sdk.Dec `json:"bonus_proposer_reward" yaml:"bonus_proposer_reward"`
30-
WithdrawAddrEnabled bool `json:"withdraw_addr_enabled" yaml:"withdraw_addr_enabled"`
29+
CommunityTax sdk.Dec `json:"community_tax" yaml:"community_tax"`
30+
BaseProposerReward sdk.Dec `json:"base_proposer_reward" yaml:"base_proposer_reward"`
31+
BonusProposerReward sdk.Dec `json:"bonus_proposer_reward" yaml:"bonus_proposer_reward"`
32+
WithdrawAddrEnabled bool `json:"withdraw_addr_enabled" yaml:"withdraw_addr_enabled"`
33+
SecretFoundationTax sdk.Dec `json:"secret_foundation_tax" yaml:"secret_foundation_tax"`
34+
SecretFoundationAddress sdk.AccAddress `json:"secret_foundation_address" yaml:"secret_foundation_address"`
3135
}
3236

3337
// ParamKeyTable returns the parameter key table.
@@ -38,10 +42,12 @@ func ParamKeyTable() params.KeyTable {
3842
// DefaultParams returns default distribution parameters
3943
func DefaultParams() Params {
4044
return Params{
41-
CommunityTax: sdk.NewDecWithPrec(2, 2), // 2%
42-
BaseProposerReward: sdk.NewDecWithPrec(1, 2), // 1%
43-
BonusProposerReward: sdk.NewDecWithPrec(4, 2), // 4%
44-
WithdrawAddrEnabled: true,
45+
CommunityTax: sdk.NewDecWithPrec(2, 2), // 2%
46+
SecretFoundationTax: sdk.ZeroDec(), // 0%
47+
SecretFoundationAddress: sdk.AccAddress{},
48+
BaseProposerReward: sdk.NewDecWithPrec(1, 2), // 1%
49+
BonusProposerReward: sdk.NewDecWithPrec(4, 2), // 4%
50+
WithdrawAddrEnabled: true,
4551
}
4652
}
4753

@@ -57,6 +63,8 @@ func (p *Params) ParamSetPairs() params.ParamSetPairs {
5763
params.NewParamSetPair(ParamStoreKeyBaseProposerReward, &p.BaseProposerReward, validateBaseProposerReward),
5864
params.NewParamSetPair(ParamStoreKeyBonusProposerReward, &p.BonusProposerReward, validateBonusProposerReward),
5965
params.NewParamSetPair(ParamStoreKeyWithdrawAddrEnabled, &p.WithdrawAddrEnabled, validateWithdrawAddrEnabled),
66+
params.NewParamSetPair(ParamSecretFoundationTax, &p.SecretFoundationTax, validateSecretFoundationTax),
67+
params.NewParamSetPair(ParamSecretFoundationAddress, &p.SecretFoundationAddress, validateSecretFoundationAddress),
6068
}
6169
}
6270

@@ -67,6 +75,11 @@ func (p Params) ValidateBasic() error {
6775
"community tax should non-negative and less than one: %s", p.CommunityTax,
6876
)
6977
}
78+
if p.SecretFoundationTax.IsNegative() || p.SecretFoundationTax.GT(sdk.OneDec()) {
79+
return fmt.Errorf(
80+
"secret foundation tax should non-negative and less than one: %s", p.SecretFoundationTax,
81+
)
82+
}
7083
if p.BaseProposerReward.IsNegative() {
7184
return fmt.Errorf(
7285
"base proposer reward should be positive: %s", p.BaseProposerReward,
@@ -105,6 +118,38 @@ func validateCommunityTax(i interface{}) error {
105118
return nil
106119
}
107120

121+
func validateSecretFoundationTax(i interface{}) error {
122+
v, ok := i.(sdk.Dec)
123+
if !ok {
124+
return fmt.Errorf("invalid parameter type: %T", i)
125+
}
126+
127+
if v.IsNil() {
128+
return fmt.Errorf("secret foundation tax must be not nil")
129+
}
130+
if v.IsNegative() {
131+
return fmt.Errorf("secret foundation tax must be positive: %s", v)
132+
}
133+
if v.GT(sdk.OneDec()) {
134+
return fmt.Errorf("secret foundation tax too large: %s", v)
135+
}
136+
137+
return nil
138+
}
139+
140+
func validateSecretFoundationAddress(i interface{}) error {
141+
v, ok := i.(sdk.AccAddress)
142+
if !ok {
143+
return fmt.Errorf("invalid parameter type: %T", i)
144+
}
145+
146+
if !v.Empty() {
147+
return sdk.VerifyAddressFormat(v)
148+
}
149+
150+
return nil
151+
}
152+
108153
func validateBaseProposerReward(i interface{}) error {
109154
v, ok := i.(sdk.Dec)
110155
if !ok {

0 commit comments

Comments
 (0)