Skip to content

Commit

Permalink
feature: add oracle split param and logic
Browse files Browse the repository at this point in the history
  • Loading branch information
fragwuerdig committed Jun 27, 2024
1 parent 9fffed2 commit 6dcb232
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 61 deletions.
1 change: 1 addition & 0 deletions custom/auth/ante/expected_keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type TreasuryKeeper interface {
HasBurnTaxExemptionAddress(ctx sdk.Context, addresses ...string) bool
HasBurnTaxExemptionContract(ctx sdk.Context, address string) bool
GetMinInitialDepositRatio(ctx sdk.Context) sdk.Dec
GetOracleSplit(ctx sdk.Context) sdk.Dec
}

// OracleKeeper for feeder validation
Expand Down
24 changes: 23 additions & 1 deletion custom/auth/ante/fee_burntax.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@ import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth/types"

oracle "github.com/classic-terra/core/v3/x/oracle/types"
treasury "github.com/classic-terra/core/v3/x/treasury/types"
)

// BurnTaxSplit splits
func (fd FeeDecorator) BurnTaxSplit(ctx sdk.Context, taxes sdk.Coins) (err error) {
burnSplitRate := fd.treasuryKeeper.GetBurnSplitRate(ctx)
oracleSplitRate := fd.treasuryKeeper.GetOracleSplit(ctx)
distributionDeltaCoins := sdk.NewCoins()
oracleSplitCoins := sdk.NewCoins()

if burnSplitRate.IsPositive() {
distributionDeltaCoins := sdk.NewCoins()

for _, taxCoin := range taxes {
splitcoinAmount := burnSplitRate.MulInt(taxCoin.Amount).RoundInt()
Expand All @@ -24,6 +27,25 @@ func (fd FeeDecorator) BurnTaxSplit(ctx sdk.Context, taxes sdk.Coins) (err error
taxes = taxes.Sub(distributionDeltaCoins...)
}

if oracleSplitRate.IsPositive() {

for _, distrCoin := range distributionDeltaCoins {
oracleCoinAmnt := oracleSplitRate.MulInt(distrCoin.Amount).RoundInt()
oracleSplitCoins = oracleSplitCoins.Add(sdk.NewCoin(distrCoin.Denom, oracleCoinAmnt))
}
}

if !oracleSplitCoins.IsZero() {
if err = fd.bankKeeper.SendCoinsFromModuleToModule(
ctx,
types.FeeCollectorName,
oracle.ModuleName,
oracleSplitCoins,
); err != nil {
return errorsmod.Wrapf(sdkerrors.ErrInsufficientFunds, err.Error())
}
}

if !taxes.IsZero() {
if err = fd.bankKeeper.SendCoinsFromModuleToModule(
ctx,
Expand Down
41 changes: 33 additions & 8 deletions custom/auth/ante/fee_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -732,14 +732,26 @@ func (s *AnteTestSuite) TestTaxExemption() {

// go test -v -run ^TestAnteTestSuite/TestBurnSplitTax$ github.com/classic-terra/core/v3/custom/auth/ante
func (s *AnteTestSuite) TestBurnSplitTax() {
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(1, 0)) // 100%
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(1, 1)) // 10%
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(1, 2)) // 0.1%
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(0, 0)) // 0% burn all taxes (old burn tax behavior)
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(-1, 1)) // -10% invalid rate
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(1, 0), sdk.ZeroDec()) // 100% distribute, 0% to oracle
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(1, 1), sdk.ZeroDec()) // 10% distribute, 0% to oracle
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(1, 2), sdk.ZeroDec()) // 0.1% distribute, 0% to oracle
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(0, 0), sdk.ZeroDec()) // 0% distribute, 0% to oracle
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(1, 0), sdk.NewDecWithPrec(5, 1)) // 100% distribute, 50% to oracle
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(5, 1)) // 10% distribute, 50% to oracle
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(1, 2), sdk.NewDecWithPrec(5, 1)) // 0.1% distribute, 50% to oracle
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(0, 0), sdk.NewDecWithPrec(5, 1)) // 0% distribute, 50% to oracle
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(1, 0), sdk.ZeroDec()) // 100% distribute, 0% to oracle
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(1, 1), sdk.ZeroDec()) // 10% distribute, 0% to oracle
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(1, 2), sdk.ZeroDec()) // 0.1% distribute, 0% to oracle
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(0, 0), sdk.ZeroDec()) // 0% distribute, 0% to oracle
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(1, 0), sdk.OneDec()) // 100% distribute, 100% to oracle
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(1, 1), sdk.OneDec()) // 10% distribute, 100% to oracle
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(1, 2), sdk.OneDec()) // 0.1% distribute, 100% to oracle
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(0, 0), sdk.OneDec()) // 0% distribute, 100% to oracle
s.runBurnSplitTaxTest(sdk.NewDecWithPrec(-1, 1), sdk.ZeroDec()) // -10% distribute - invalid rate
}

func (s *AnteTestSuite) runBurnSplitTaxTest(burnSplitRate sdk.Dec) {
func (s *AnteTestSuite) runBurnSplitTaxTest(burnSplitRate sdk.Dec, oracleSplitRate sdk.Dec) {
s.SetupTest(true) // setup
require := s.Require()
s.txBuilder = s.clientCtx.TxConfig.NewTxBuilder()
Expand All @@ -752,6 +764,7 @@ func (s *AnteTestSuite) runBurnSplitTaxTest(burnSplitRate sdk.Dec) {

// Set burn split tax
tk.SetBurnSplitRate(s.ctx, burnSplitRate)
tk.SetOracleSplit(s.ctx, oracleSplitRate)

// keys and addresses
priv1, _, addr1 := testdata.KeyTestPubAddr()
Expand Down Expand Up @@ -804,15 +817,27 @@ func (s *AnteTestSuite) runBurnSplitTaxTest(burnSplitRate sdk.Dec) {
tk.BurnCoinsFromBurnAccount(s.ctx)

feeCollectorAfter := sdk.NewDecCoinsFromCoins(bk.GetAllBalances(s.ctx, ak.GetModuleAddress(authtypes.FeeCollectorName))...)
oracleAfter := sdk.NewDecCoinsFromCoins(bk.GetAllBalances(s.ctx, ak.GetModuleAddress(oracletypes.ModuleName))...)
taxes := ante.FilterMsgAndComputeTax(s.ctx, tk, msg)
burnTax := sdk.NewDecCoinsFromCoins(taxes...)

if burnSplitRate.IsPositive() {
distributionDeltaCoins := burnTax.MulDec(burnSplitRate)
expectedOracleCoins := distributionDeltaCoins.MulDec(oracleSplitRate)
expectedDistrCoins := distributionDeltaCoins.Sub(expectedOracleCoins)

if expectedOracleCoins == nil {
expectedOracleCoins = sdk.NewDecCoins()
}

if expectedDistrCoins == nil {
expectedDistrCoins = sdk.NewDecCoins()
}

// expected: community pool 50%
fmt.Printf("BurnSplitRate %v, DistributionDeltaCoins %v\n", burnSplitRate, distributionDeltaCoins)
require.Equal(feeCollectorAfter, distributionDeltaCoins)
fmt.Printf("-- BurnSplitRate %+v, OracleSplitRate %+v, OracleCoins %+v, DistrCoins %+v\n", burnSplitRate, oracleSplitRate, expectedOracleCoins, expectedDistrCoins)
require.Equal(feeCollectorAfter, expectedDistrCoins)
require.Equal(oracleAfter, expectedOracleCoins)
burnTax = burnTax.Sub(distributionDeltaCoins)
}

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ require (
github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect
github.com/opencontainers/image-spec v1.1.0-rc2 // indirect
github.com/opencontainers/runc v1.1.12 // indirect
github.com/regen-network/cosmos-proto v0.3.1 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1079,6 +1079,8 @@ github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Ung
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzywPxOvwMdxcg=
github.com/regen-network/cosmos-proto v0.3.1/go.mod h1:jO0sVX6a1B36nmE8C9xBFXpNwWejXC7QqCOnH3O0+YM=
github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4=
github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI=
github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc=
Expand Down
6 changes: 6 additions & 0 deletions proto/terra/treasury/v1beta1/treasury.proto
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ message Params {
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
string oracle_split = 10 [
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.moretags) = "yaml:\"oracle_split\"",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
}

// PolicyConstraints - defines policy constraints can be applied in tax & reward policies
Expand Down
9 changes: 9 additions & 0 deletions x/treasury/keeper/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ func (k Keeper) SetMinInitialDepositRatio(ctx sdk.Context, minInitialDepositRati
k.paramSpace.Set(ctx, types.KeyMinInitialDepositRatio, minInitialDepositRatio)
}

func (k Keeper) GetOracleSplit(ctx sdk.Context) (res sdk.Dec) {
k.paramSpace.Get(ctx, types.KeyOracleSplit, &res)
return
}

func (k Keeper) SetOracleSplit(ctx sdk.Context, oracleSplit sdk.Dec) {
k.paramSpace.Set(ctx, types.KeyOracleSplit, oracleSplit)
}

// GetParams returns the total set of treasury parameters.
func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
k.paramSpace.GetParamSetIfExists(ctx, &params)
Expand Down
29 changes: 29 additions & 0 deletions x/treasury/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ var (
KeyWindowProbation = []byte("WindowProbation")
KeyBurnTaxSplit = []byte("BurnTaxSplit")
KeyMinInitialDepositRatio = []byte("MinInitialDepositRatio")
KeyOracleSplit = []byte("OracleSplit")
)

// Default parameter values
Expand All @@ -47,6 +48,7 @@ var (
DefaultRewardWeight = sdk.NewDecWithPrec(5, 2) // 5%
DefaultBurnTaxSplit = sdk.NewDecWithPrec(1, 1) // 10% goes to community pool, 90% burn
DefaultMinInitialDepositRatio = sdk.ZeroDec() // 0% min initial deposit
DefaultOracleSplit = sdk.NewDecWithPrec(5, 1) // 50% oracle, 50% community pool
)

var _ paramstypes.ParamSet = &Params{}
Expand All @@ -63,6 +65,7 @@ func DefaultParams() Params {
WindowProbation: DefaultWindowProbation,
BurnTaxSplit: DefaultBurnTaxSplit,
MinInitialDepositRatio: DefaultMinInitialDepositRatio,
OracleSplit: DefaultOracleSplit,
}
}

Expand Down Expand Up @@ -90,6 +93,7 @@ func (p *Params) ParamSetPairs() paramstypes.ParamSetPairs {
paramstypes.NewParamSetPair(KeyWindowProbation, &p.WindowProbation, validateWindowProbation),
paramstypes.NewParamSetPair(KeyBurnTaxSplit, &p.BurnTaxSplit, validateBurnTaxSplit),
paramstypes.NewParamSetPair(KeyMinInitialDepositRatio, &p.MinInitialDepositRatio, validateMinInitialDepositRatio),
paramstypes.NewParamSetPair(KeyOracleSplit, &p.OracleSplit, validateOraceSplit),
}
}

Expand Down Expand Up @@ -137,6 +141,14 @@ func (p Params) Validate() error {
return fmt.Errorf("treasury parameter WindowLong must be bigger than WindowShort: (%d, %d)", p.WindowLong, p.WindowShort)
}

if p.OracleSplit.IsNegative() {
return fmt.Errorf("treasury parameter OracleSplit must be positive: %s", p.OracleSplit)
}

if p.OracleSplit.GT(sdk.OneDec()) {
return fmt.Errorf("treasury parameter OracleSplit must be less than or equal to 1.0: %s", p.OracleSplit)
}

return nil
}

Expand Down Expand Up @@ -268,3 +280,20 @@ func validateMinInitialDepositRatio(i interface{}) error {

return nil
}

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

if v.IsNegative() {
return fmt.Errorf("oracle split must be positive: %s", v)
}

if v.GT(sdk.OneDec()) {
return fmt.Errorf("oracle split must be less than or equal to 1.0: %s", v)
}

return nil
}
Loading

0 comments on commit 6dcb232

Please sign in to comment.