diff --git a/Makefile b/Makefile index 3cc1ce48..3b47d59f 100644 --- a/Makefile +++ b/Makefile @@ -124,6 +124,9 @@ endif dev: @ignite chain serve --reset-once --skip-proto --verbose +dev-continue: + @ignite chain serve --skip-proto --verbose + ############################################################################### ### Formatting & Linting ### ############################################################################### diff --git a/app/upgrades/v1_5/upgrade.go b/app/upgrades/v1_5/upgrade.go index 7408dffc..45aa5111 100644 --- a/app/upgrades/v1_5/upgrade.go +++ b/app/upgrades/v1_5/upgrade.go @@ -84,8 +84,8 @@ func MigrateFundersModule(sdkCtx sdk.Context, cdc codec.Codec, fundersStoreKey s CoinWhitelist: []*fundersTypes.WhitelistCoinEntry{ { CoinDenom: globalTypes.Denom, - MinFundingAmount: oldParams.MinFundingAmount, - MinFundingAmountPerBundle: oldParams.MinFundingAmountPerBundle, + MinFundingAmount: math.NewIntFromUint64(oldParams.MinFundingAmount), + MinFundingAmountPerBundle: math.NewIntFromUint64(oldParams.MinFundingAmountPerBundle), CoinWeight: math.LegacyMustNewDecFromStr("0.06"), }, }, diff --git a/config.yml b/config.yml index ce56361e..c715770e 100644 --- a/config.yml +++ b/config.yml @@ -7,42 +7,49 @@ build: - third_party/proto - proto_vendor accounts: - - name: dummy + - name: dummy # kyve137v27tfyegc083w5kj9zhhrfk34n8vhjma73gq + coins: + - 1000000tkyve # 1 tkyve -> 6 decimals mnemonic: expect crisp umbrella hospital firm exhibit future size slot update blood deliver fat happy ghost visa recall usual path purity junior ring ordinary stove - - name: alice + - name: alice # kyve1jq304cthpx0lwhpqzrdjrcza559ukyy3zsl2vd coins: - - 2000000000000000tkyve + - 1000000000acoin # 1000 acoins -> 6 decimals + - 1000000000000bcoin # 1000 bcoins -> 9 decimals + - 1000000000ccoin # 1000 ccoins -> 6 decimals + - 2000000000000tkyve # 2M tkyve -> 6 decimals mnemonic: worry grief loyal smoke pencil arrow trap focus high pioneer tomato hedgehog essence purchase dove pond knee custom phone gentle sunset addict mother fabric - - name: bob + - name: bob # kyve1hvg7zsnrj6h29q9ss577mhrxa04rn94h7zjugq coins: - - 1000000000000000tkyve + - 1000000000acoin # 1000 acoins -> 6 decimals + - 1000000000000bcoin # 1000 bcoins -> 9 decimals + - 1000000000ccoin # 1000 ccoins -> 6 decimals + - 1000000000000tkyve # 1M tkyve -> 6 decimals mnemonic: crash sick toilet stumble join cash erode glory door weird diagram away lizard solid segment apple urge joy annual able tank define candy demise - - name: charlie + - name: charlie #kyve1ay22rr3kz659fupu0tcswlagq4ql6rwm4nuv0s coins: - - 1000000000000000tkyve + - 1000000000acoin # 1000 acoins -> 6 decimals + - 1000000000000bcoin # 1000 bcoins -> 9 decimals + - 1000000000ccoin # 1000 ccoins -> 6 decimals + - 1000000000000tkyve # 1M tkyve -> 6 decimals mnemonic: shoot inject fragile width trend satisfy army enact volcano crowd message strike true divorce search rich office shoulder sport relax rhythm symbol gadget size - - name: faucet + - name: faucet # kyve1kahmjds2rxj2qzamdvy5m8ljnkqrf5xhetes7q coins: - - 1000000000000000tkyve + - 1000000000000tkyve # 1M tkyve -> 6 decimals mnemonic: open home share route party lake room solution quantum pact model avocado humor dilemma review desert turtle total humor produce rate keen eagle fee - - name: foundation + - name: foundation # kyve1fd4qu868n7arav8vteghcppxxa0p2vna5f5ep8 coins: - # for fees - - 1000000tkyve - # address: kyve1fd4qu868n7arav8vteghcppxxa0p2vna5f5ep8 + - 1000000tkyve # 1 tkyve -> 6 decimals mnemonic: evidence taxi material cabin annual phrase practice unhappy safe jealous section drink illness panther bread aim mouse dolphin deliver ready doll finger search cheap - - name: foundation_inflation + - name: foundation_inflation # kyve1tuxsc7ez79aydyee86qxm05zyx0l7d78c2zzsn coins: - # for fees - - 1000000tkyve - # address: kyve1tuxsc7ez79aydyee86qxm05zyx0l7d78c2zzsn + - 1000000tkyve # 1 tkyve -> 6 decimals mnemonic: hold urge sustain chef furnace foam oven fall harsh core anchor during crew secret craft rhythm choose gold soft aisle sort phrase enter orphan faucet: @@ -61,20 +68,16 @@ genesis: coins: - denom: "tkyve" amount: "165000000000000000" - - address: "kyve1vg5325u5mat0y44g73n8t8z2le26fsa4n947f5" # funders module - coins: - - denom: "tkyve" - amount: "5300000000000000" supply: - denom: "tkyve" - amount: "170300000000000000" # all balances together + amount: "165000000000000000" delegation: params: unbonding_delegation_time: 10 global: params: burn_ratio: "0.5" - min_gas_price: "1" + min_gas_price: "0.02" gov: params: voting_period: 120s @@ -134,55 +137,30 @@ genesis: commencement: "1647212400" pool: params: - protocol_inflation_share: "0.04" - pool_count: "2" + protocol_inflation_share: "0.1" + max_voting_power_per_pool: "1" + pool_count: "1" pool_list: - - config: "{\"network\":\"kyve-1\",\"rpc\":\"https://rpc-eu-1.kyve.network\"}" + - config: "{\"network\":\"kyve-1\",\"rpc\":\"https://rpc.kyve.network\"}" current_compression_id: "1" current_index: "0" current_key: "" - current_storage_provider_id: "1" + current_storage_provider_id: "3" current_summary: "" id: "0" - logo: "" + logo: "ar://WOiYR7qF7G_dp6eO0bFC7AorS7601qgek3X_IeAZook" max_bundle_size: "100" - min_delegation: "100000000000" - name: "KYVE // Mainnet" - inflation_share_weight: "2500000000" + min_delegation: "100000000" + name: "KYVE" + inflation_share_weight: "1" disabled: false - runtime: '@kyvejs/tendermint-bsync' + runtime: '@kyvejs/tendermint' start_key: "1" total_bundles: "0" upload_interval: "60" protocol: - version: "1.0.0" - binaries: "{\"kyve-linux-arm64\":\"https://github.com/KYVENetwork/kyvejs/releases/download/%40kyvejs%2Ftendermint-bsync%401.0.0/kyve-linux-arm64.zip\",\"kyve-linux-x64\":\"https://github.com/KYVENetwork/kyvejs/releases/download/%40kyvejs%2Ftendermint-bsync%401.0.0/kyve-linux-x64.zip\",\"kyve-macos-x64\":\"https://github.com/KYVENetwork/kyvejs/releases/download/%40kyvejs%2Ftendermint-bsync%401.0.0/kyve-macos-x64.zip\"}" - last_upgrade: "0" - upgrade_plan: - version: "" - binaries: "" - scheduled_at: "0" - duration: "0" - - config: "{\"network\":\"kyve-1\",\"rpc\":\"https://rpc-eu-1.kyve.network\"}" - current_compression_id: "1" - current_index: "0" - current_key: "" - current_storage_provider_id: "1" - current_summary: "" - id: "1" - logo: "" - max_bundle_size: "100" - min_delegation: "100000000000" - name: "KYVE // Blub" - inflation_share_weight: "2500000000" - disabled: false - runtime: '@kyvejs/tendermint-bsync' - start_key: "1" - total_bundles: "0" - upload_interval: "60" - protocol: - version: "1.0.0" - binaries: "{\"kyve-linux-arm64\":\"https://github.com/KYVENetwork/kyvejs/releases/download/%40kyvejs%2Ftendermint-bsync%401.0.0/kyve-linux-arm64.zip\",\"kyve-linux-x64\":\"https://github.com/KYVENetwork/kyvejs/releases/download/%40kyvejs%2Ftendermint-bsync%401.0.0/kyve-linux-x64.zip\",\"kyve-macos-x64\":\"https://github.com/KYVENetwork/kyvejs/releases/download/%40kyvejs%2Ftendermint-bsync%401.0.0/kyve-macos-x64.zip\"}" + version: "1.1.6" + binaries: "{\"kyve-linux-arm64\":\"https://github.com/KYVENetwork/kyvejs/releases/download/%40kyvejs%2Ftendermint%401.1.6/kyve-linux-arm64.zip\",\"kyve-linux-x64\":\"https://github.com/KYVENetwork/kyvejs/releases/download/%40kyvejs%2Ftendermint%401.1.6/kyve-linux-x64.zip\",\"kyve-macos-x64\":\"https://github.com/KYVENetwork/kyvejs/releases/download/%40kyvejs%2Ftendermint%401.1.6/kyve-macos-x64.zip\"}" last_upgrade: "0" upgrade_plan: version: "" @@ -195,7 +173,31 @@ genesis: staking: params: bond_denom: tkyve + bundles: + params: + storage_costs: + - storage_provider_id: "3" + cost: "0.000000006288" funders: + params: + min_funding_multiple: 10 + coin_whitelist: + - coin_denom: "tkyve" + min_funding_amount: "10000000" + min_funding_amount_per_bundle: "1000000" + coin_weight: "0.055" + - coin_denom: "acoin" + min_funding_amount: "10000000" + min_funding_amount_per_bundle: "1000000" + coin_weight: "10.3" + - coin_denom: "bcoin" + min_funding_amount: "10000000000" + min_funding_amount_per_bundle: "1000000000" + coin_weight: "0.095" + - coin_denom: "ccoin" + min_funding_amount: "10000000" + min_funding_amount_per_bundle: "1000000" + coin_weight: "0.86" funder_list: - address: "kyve1jq304cthpx0lwhpqzrdjrcza559ukyy3zsl2vd" contact: "https://twitter.com/kyvenetwork" @@ -203,55 +205,22 @@ genesis: description: "Alice is the first funder of the KYVE network." website: "https://kyve.network" identity: "0657A086E5201562" - - address: "kyve1ze3ncmkvat3t2mcj9e3uy8uktat4fq2vltcnat" + - address: "kyve1hvg7zsnrj6h29q9ss577mhrxa04rn94h7zjugq" contact: "https://twitter.com/kyvenetwork" - moniker: "Otto" - description: "Another funder of the KYVE network." - website: "https://ot.to" + moniker: "Bob" + description: "Bob is the second funder of the KYVE network." + website: "https://kyve.network" identity: "0657A086E5201562" - funding_list: - - pool_id: 0 - funder_address: "kyve1jq304cthpx0lwhpqzrdjrcza559ukyy3zsl2vd" - amounts: - - denom: tkyve - amount: "5000000000000" - amounts_per_bundle: - - denom: tkyve - amount: "230000000" - total_funded: - - denom: tkyve - amount: "2200400000000" - - pool_id: 0 - funder_address: "kyve1ze3ncmkvat3t2mcj9e3uy8uktat4fq2vltcnat" - amounts: - - denom: tkyve - amount: "200000000000" - amounts_per_bundle: - - denom: tkyve - amount: "20000000" - total_funded: - - denom: tkyve - amount: "64500000000" - - pool_id: 1 - funder_address: "kyve1ze3ncmkvat3t2mcj9e3uy8uktat4fq2vltcnat" - amounts: - - denom: tkyve - amount: "100000000000" - amounts_per_bundle: - - denom: tkyve - amount: "10000000" - total_funded: - - denom: tkyve - amount: "23000000000" + funding_list: [] funding_state_list: - pool_id: 0 - active_funder_addresses: [ "kyve1jq304cthpx0lwhpqzrdjrcza559ukyy3zsl2vd", "kyve1ze3ncmkvat3t2mcj9e3uy8uktat4fq2vltcnat" ] - - pool_id: 1 - active_funder_addresses: [ "kyve1ze3ncmkvat3t2mcj9e3uy8uktat4fq2vltcnat" ] + active_funder_addresses: [] chain_id: kyve-local validators: - name: alice bonded: 1000000000000tkyve + app: + minimum-gas-prices: "0.02tkyve" config: consensus: timeout_commit: "2s" diff --git a/docs/static/openapi.yml b/docs/static/openapi.yml index 28e6a2ca..d53f3311 100644 --- a/docs/static/openapi.yml +++ b/docs/static/openapi.yml @@ -4747,22 +4747,30 @@ paths: to be funded, this value needs to be unique + coin_decimals: + type: integer + format: int64 + title: coin_decimals are the decimals of the coin min_funding_amount: type: string - format: uint64 title: >- min_funding_amount is the minimum required amount of this denom that needs - to be funded + to be funded. It is of type math.Int since a uint64 + is not sufficient for a + + coin with 18 decimals min_funding_amount_per_bundle: type: string - format: uint64 title: >- min_funding_amount_per_bundle is the minimum required amount of this denom - that needs to be funded per bundle + that needs to be funded per bundle. It is of type + math.Int since a uint64 + + is not sufficient for a coin with 18 decimals coin_weight: type: string description: >- diff --git a/proto/kyve/funders/v1beta1/params.proto b/proto/kyve/funders/v1beta1/params.proto index 2c114036..0191fae2 100644 --- a/proto/kyve/funders/v1beta1/params.proto +++ b/proto/kyve/funders/v1beta1/params.proto @@ -12,15 +12,25 @@ message WhitelistCoinEntry { // coin_denom is the denom of a coin which is allowed to be funded, this value // needs to be unique string coin_denom = 1; + // coin_decimals are the decimals of the coin + uint32 coin_decimals = 2; // min_funding_amount is the minimum required amount of this denom that needs - // to be funded - uint64 min_funding_amount = 2; + // to be funded. It is of type math.Int since a uint64 is not sufficient for a + // coin with 18 decimals + string min_funding_amount = 3 [ + (gogoproto.customtype) = "cosmossdk.io/math.Int", + (gogoproto.nullable) = false + ]; // min_funding_amount_per_bundle is the minimum required amount of this denom - // that needs to be funded per bundle - uint64 min_funding_amount_per_bundle = 3; + // that needs to be funded per bundle. It is of type math.Int since a uint64 + // is not sufficient for a coin with 18 decimals + string min_funding_amount_per_bundle = 4 [ + (gogoproto.customtype) = "cosmossdk.io/math.Int", + (gogoproto.nullable) = false + ]; // coin_weight is a factor used to sort funders after their funding amounts. // This should be the market price of the coin in USD/coin. This value should be kept up-to-date. - string coin_weight = 4 [ + string coin_weight = 5 [ (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", (gogoproto.nullable) = false ]; diff --git a/testutil/integration/helpers.go b/testutil/integration/helpers.go index a1ffc938..40db2fdb 100644 --- a/testutil/integration/helpers.go +++ b/testutil/integration/helpers.go @@ -1,10 +1,22 @@ package integration import ( + "fmt" + + "cosmossdk.io/math" + globalTypes "github.com/KYVENetwork/chain/x/global/types" sdk "github.com/cosmos/cosmos-sdk/types" ) +func (suite *KeeperTestSuite) MustNewIntFromStr(amount string) math.Int { + result, ok := math.NewIntFromString(amount) + if !ok { + panic(fmt.Sprintf("error parsing \"%s\" to math.Int", amount)) + } + return result +} + func (suite *KeeperTestSuite) GetCoinsFromCommunityPool() sdk.Coins { pool, err := suite.App().DistributionKeeper.FeePool.Get(suite.Ctx()) if err != nil { diff --git a/testutil/integration/integration.go b/testutil/integration/integration.go index fff8a116..25462cc2 100644 --- a/testutil/integration/integration.go +++ b/testutil/integration/integration.go @@ -196,6 +196,29 @@ func (suite *KeeperTestSuite) MintCoins(address string, amount uint64) error { return nil } +func (suite *KeeperTestSuite) MintCoin(address string, coin sdk.Coin) error { + // mint coins ukyve, A, B, C + coins := sdk.NewCoins(coin) + err := suite.app.BankKeeper.MintCoins(suite.ctx, mintTypes.ModuleName, coins) + if err != nil { + return err + } + + suite.Commit() + + receiver, err := sdk.AccAddressFromBech32(address) + if err != nil { + return err + } + + err = suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, mintTypes.ModuleName, receiver, coins) + if err != nil { + return err + } + + return nil +} + func (suite *KeeperTestSuite) MintDenomToModule(moduleAddress string, amount uint64, denom string) error { coins := sdk.NewCoins(sdk.NewInt64Coin(denom, int64(amount))) err := suite.app.BankKeeper.MintCoins(suite.ctx, mintTypes.ModuleName, coins) diff --git a/util/validate.go b/util/validate.go index bccd7ecc..7288a70b 100644 --- a/util/validate.go +++ b/util/validate.go @@ -9,7 +9,7 @@ import ( func ValidateDecimal(i interface{}) error { v, ok := i.(math.LegacyDec) if !ok { - return fmt.Errorf("invalid type: %T", i) + return fmt.Errorf("invalid math.LegacyDec type: %T", i) } if v.IsNil() || v.IsNegative() { @@ -19,10 +19,23 @@ func ValidateDecimal(i interface{}) error { return nil } +func ValidateInt(i interface{}) error { + v, ok := i.(math.Int) + if !ok { + return fmt.Errorf("invalid math.Int type: %T", i) + } + + if v.IsNil() || v.IsNegative() { + return fmt.Errorf("invalid int: %s", v) + } + + return nil +} + func ValidateNumber(i interface{}) error { v, ok := i.(uint64) if !ok { - return fmt.Errorf("invalid type: %T", i) + return fmt.Errorf("invalid uint64 type: %T", i) } if math.NewIntFromUint64(v).IsNil() || math.NewIntFromUint64(v).IsNegative() { @@ -35,7 +48,7 @@ func ValidateNumber(i interface{}) error { func ValidatePositiveNumber(i interface{}) error { v, ok := i.(uint64) if !ok { - return fmt.Errorf("invalid type: %T", i) + return fmt.Errorf("invalid uint64 type: %T", i) } if math.NewIntFromUint64(v).IsNil() || @@ -50,7 +63,7 @@ func ValidatePositiveNumber(i interface{}) error { func ValidatePercentage(i interface{}) error { v, ok := i.(math.LegacyDec) if !ok { - return fmt.Errorf("invalid type: %T", i) + return fmt.Errorf("invalid math.LegacyDec type: %T", i) } if v.IsNil() || v.IsNegative() || v.GT(math.LegacyOneDec()) { diff --git a/x/bundles/keeper/keeper_suite_funding_bundles_test.go b/x/bundles/keeper/keeper_suite_funding_bundles_test.go index 446c1032..04546dee 100644 --- a/x/bundles/keeper/keeper_suite_funding_bundles_test.go +++ b/x/bundles/keeper/keeper_suite_funding_bundles_test.go @@ -70,26 +70,26 @@ var _ = Describe("funding bundles", Ordered, func() { s.App().FundersKeeper.SetParams(s.Ctx(), funderstypes.NewParams([]*funderstypes.WhitelistCoinEntry{ { CoinDenom: globaltypes.Denom, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.A_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.B_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(2), }, { CoinDenom: i.C_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(3), }, }, 0)) diff --git a/x/bundles/keeper/keeper_suite_inflation_splitting_test.go b/x/bundles/keeper/keeper_suite_inflation_splitting_test.go index 27d17a42..b46457fc 100644 --- a/x/bundles/keeper/keeper_suite_inflation_splitting_test.go +++ b/x/bundles/keeper/keeper_suite_inflation_splitting_test.go @@ -82,26 +82,26 @@ var _ = Describe("inflation splitting", Ordered, func() { s.App().FundersKeeper.SetParams(s.Ctx(), funderstypes.NewParams([]*funderstypes.WhitelistCoinEntry{ { CoinDenom: globalTypes.Denom, - MinFundingAmount: 100, - MinFundingAmountPerBundle: uint64(amountPerBundle), + MinFundingAmount: math.NewInt(100), + MinFundingAmountPerBundle: math.NewInt(amountPerBundle), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.A_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: uint64(amountPerBundle), + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewInt(amountPerBundle), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.B_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: uint64(amountPerBundle), + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewInt(amountPerBundle), CoinWeight: math.LegacyNewDec(2), }, { CoinDenom: i.C_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: uint64(amountPerBundle), + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewInt(amountPerBundle), CoinWeight: math.LegacyNewDec(3), }, }, 0)) @@ -1532,7 +1532,8 @@ var _ = Describe("inflation splitting", Ordered, func() { Expect(c2.Sub(c1...).AmountOf(i.C_DENOM).Uint64()).To(BeZero()) // assert total pool funds - Expect(s.App().FundersKeeper.GetTotalActiveFunding(s.Ctx(), fundingState.PoolId)[0].Amount.Uint64()).To(Equal(200*i.KYVE - 10_000)) + Expect(s.App().FundersKeeper.GetTotalActiveFunding(s.Ctx(), fundingState.PoolId).AmountOf(i.A_DENOM).Int64()).To(Equal(200*i.T_KYVE - 2*amountPerBundle)) + Expect(s.App().FundersKeeper.GetTotalActiveFunding(s.Ctx(), fundingState.PoolId).AmountOf(i.B_DENOM).Int64()).To(Equal(200*i.T_KYVE - 4*amountPerBundle)) Expect(fundingState.ActiveFunderAddresses).To(HaveLen(2)) }) @@ -1642,7 +1643,8 @@ var _ = Describe("inflation splitting", Ordered, func() { Expect(c2.Sub(c1...).AmountOf(i.C_DENOM).Uint64()).To(BeZero()) // assert total pool funds - Expect(s.App().FundersKeeper.GetTotalActiveFunding(s.Ctx(), fundingState.PoolId)[0].Amount.Uint64()).To(Equal(200*i.KYVE - 10_000)) + Expect(s.App().FundersKeeper.GetTotalActiveFunding(s.Ctx(), fundingState.PoolId).AmountOf(i.A_DENOM).Int64()).To(Equal(200*i.T_KYVE - 2*amountPerBundle)) + Expect(s.App().FundersKeeper.GetTotalActiveFunding(s.Ctx(), fundingState.PoolId).AmountOf(i.B_DENOM).Int64()).To(Equal(200*i.T_KYVE - 4*amountPerBundle)) Expect(fundingState.ActiveFunderAddresses).To(HaveLen(2)) }) diff --git a/x/bundles/keeper/keeper_suite_stakers_leave_test.go b/x/bundles/keeper/keeper_suite_stakers_leave_test.go index 0633b5a5..3d64b87f 100644 --- a/x/bundles/keeper/keeper_suite_stakers_leave_test.go +++ b/x/bundles/keeper/keeper_suite_stakers_leave_test.go @@ -62,7 +62,7 @@ var _ = Describe("stakers leave", Ordered, func() { }) params := funderstypes.DefaultParams() - params.CoinWhitelist[0].MinFundingAmountPerBundle = 10_000 + params.CoinWhitelist[0].MinFundingAmountPerBundle = math.NewInt(10_000) s.App().FundersKeeper.SetParams(s.Ctx(), params) s.RunTxFundersSuccess(&funderstypes.MsgFundPool{ diff --git a/x/bundles/keeper/keeper_suite_valid_bundles_test.go b/x/bundles/keeper/keeper_suite_valid_bundles_test.go index edc63a3b..8d6b1f57 100644 --- a/x/bundles/keeper/keeper_suite_valid_bundles_test.go +++ b/x/bundles/keeper/keeper_suite_valid_bundles_test.go @@ -28,6 +28,7 @@ TEST CASES - valid bundles * Produce a valid bundle with multiple validators, multiple coins and no foreign delegations * Produce a valid bundle with multiple validators, multiple coins which are not enough for the storage reward and no foreign delegations * Produce a valid bundle with multiple validator, multiple coins and no foreign delegations where one coin is removed from the whitelist +* Produce a valid bundle with multiple validators, multiple coins and real world values */ @@ -36,7 +37,6 @@ var _ = Describe("valid bundles", Ordered, func() { var initialBalanceStaker0, initialBalanceValaddress0, initialBalanceStaker1, initialBalanceValaddress1, initialBalanceStaker2, initialBalanceValaddress2 sdk.Coins amountPerBundle := int64(10_000) - BeforeEach(func() { // init new clean chain s = i.NewCleanChain() @@ -85,26 +85,26 @@ var _ = Describe("valid bundles", Ordered, func() { s.App().FundersKeeper.SetParams(s.Ctx(), fundersTypes.NewParams([]*fundersTypes.WhitelistCoinEntry{ { CoinDenom: globalTypes.Denom, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: uint64(amountPerBundle), + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewInt(amountPerBundle), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.A_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: uint64(amountPerBundle), + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewInt(amountPerBundle), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.B_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: uint64(amountPerBundle), + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewInt(amountPerBundle), CoinWeight: math.LegacyNewDec(2), }, { CoinDenom: i.C_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: uint64(amountPerBundle), + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewInt(amountPerBundle), CoinWeight: math.LegacyNewDec(3), }, }, 0)) @@ -1115,7 +1115,7 @@ var _ = Describe("valid bundles", Ordered, func() { Expect(fundingState.ActiveFunderAddresses).To(HaveLen(1)) }) - It("Produce a valid bundle with multiple validators, multiple coins which are not enough for the storage reward and no foreign delegations", func() { + It("Produce a valid bundle with multiple validators, multiple coins and no foreign delegations", func() { // ARRANGE // fund additionally to the already funded 100acoins s.RunTxPoolSuccess(&fundersTypes.MsgFundPool{ @@ -1263,26 +1263,26 @@ var _ = Describe("valid bundles", Ordered, func() { s.App().FundersKeeper.SetParams(s.Ctx(), fundersTypes.NewParams([]*fundersTypes.WhitelistCoinEntry{ { CoinDenom: globalTypes.Denom, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: uint64(amountPerBundle), + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewInt(amountPerBundle), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.A_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: uint64(amountPerBundle), + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewInt(amountPerBundle), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.B_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: uint64(amountPerBundle), + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewInt(amountPerBundle), CoinWeight: math.LegacyNewDec(2), }, { CoinDenom: i.C_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: uint64(amountPerBundle), + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewInt(amountPerBundle), CoinWeight: math.LegacyMustNewDecFromStr("0.0000001"), }, }, 0)) @@ -1440,20 +1440,20 @@ var _ = Describe("valid bundles", Ordered, func() { s.App().FundersKeeper.SetParams(s.Ctx(), fundersTypes.NewParams([]*fundersTypes.WhitelistCoinEntry{ { CoinDenom: globalTypes.Denom, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: uint64(amountPerBundle), + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewInt(amountPerBundle), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.A_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: uint64(amountPerBundle), + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewInt(amountPerBundle), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.B_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: uint64(amountPerBundle), + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewInt(amountPerBundle), CoinWeight: math.LegacyNewDec(2), }, }, 0)) @@ -1590,4 +1590,202 @@ var _ = Describe("valid bundles", Ordered, func() { Expect(s.App().FundersKeeper.GetTotalActiveFunding(s.Ctx(), fundingState.PoolId).String()).To(Equal(sdk.NewCoins(i.ACoin(100*i.T_KYVE-amountPerBundle), i.BCoin(100*i.T_KYVE-amountPerBundle), i.CCoin(100*i.T_KYVE)).String())) Expect(fundingState.ActiveFunderAddresses).To(HaveLen(1)) }) + + It("Produce a valid bundle with multiple validators, multiple coins and real world values", func() { + // ARRANGE + // prices are from the 06/06/24 + + // Irys: https://node1.bundlr.network/price/1048576 -> 1048 winston/byte * 40 USD/AR * 1.5 / 10**12 + bundleParams := s.App().BundlesKeeper.GetParams(s.Ctx()) + bundleParams.StorageCosts = []bundletypes.StorageCost{ + {StorageProviderId: 1, Cost: math.LegacyMustNewDecFromStr("0.000000006288")}, + } + s.App().BundlesKeeper.SetParams(s.Ctx(), bundleParams) + + // tkyve -> $KYVE + // acoin -> $TIA + // bcoin -> $ARCH + // ccoin -> $OSMO + s.App().FundersKeeper.SetParams(s.Ctx(), fundersTypes.NewParams([]*fundersTypes.WhitelistCoinEntry{ + { + CoinDenom: globalTypes.Denom, + CoinDecimals: 9, + MinFundingAmount: math.NewIntFromUint64(100_000_000_000), // 100 $KYVE + MinFundingAmountPerBundle: math.NewInt(100_000_000), // 0.1 $KYVE + CoinWeight: math.LegacyMustNewDecFromStr("0.055"), // 0.055 $USD + }, + { + CoinDenom: i.A_DENOM, + CoinDecimals: 6, + MinFundingAmount: math.NewIntFromUint64(100_000_000), // 100 $TIA + MinFundingAmountPerBundle: math.NewInt(100_000), // 0.1 $TIA + CoinWeight: math.LegacyMustNewDecFromStr("10.33"), // 10.33 $USD + }, + { + CoinDenom: i.B_DENOM, + CoinDecimals: 18, + MinFundingAmount: s.MustNewIntFromStr("100000000000000000000"), // 100 $ARCH + MinFundingAmountPerBundle: s.MustNewIntFromStr("100000000000000000"), // 0.1 $ARCH + CoinWeight: math.LegacyMustNewDecFromStr("0.084"), // 0.084 $USD + }, + { + CoinDenom: i.C_DENOM, + CoinDecimals: 6, + MinFundingAmount: math.NewIntFromUint64(100_000_000), // 100 $OSMO + MinFundingAmountPerBundle: math.NewInt(100_000), // 0.1 $OSMO + CoinWeight: math.LegacyMustNewDecFromStr("0.84"), // 0.84 $USD + }, + }, 0)) + + // mint another 1,000 $ARCH to Alice + err := s.MintCoin(i.ALICE, sdk.NewCoin(i.B_DENOM, s.MustNewIntFromStr("1000000000000000000000"))) + _ = err + + // defund everything so we have a clean state + s.RunTxPoolSuccess(&fundersTypes.MsgDefundPool{ + Creator: i.ALICE, + Amounts: i.ACoins(100 * i.T_KYVE), + }) + + // fund with every coin 100 units for amount and 1 for amount per bundle + s.RunTxPoolSuccess(&fundersTypes.MsgFundPool{ + Creator: i.ALICE, + Amounts: sdk.NewCoins(i.KYVECoin(100_000_000_000), i.ACoin(100_000_000), sdk.NewCoin(i.B_DENOM, s.MustNewIntFromStr("100000000000000000000")), i.CCoin(100_000_000)), + AmountsPerBundle: sdk.NewCoins(i.KYVECoin(1_000_000_000), i.ACoin(1_000_000), sdk.NewCoin(i.B_DENOM, s.MustNewIntFromStr("1000000000000000000")), i.CCoin(1_000_000)), + }) + + s.RunTxBundlesSuccess(&bundletypes.MsgSubmitBundleProposal{ + Creator: i.VALADDRESS_0_A, + Staker: i.STAKER_0, + PoolId: 0, + StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI", + DataSize: 1048576, // 1MB + DataHash: "test_hash", + FromIndex: 0, + BundleSize: 100, + FromKey: "0", + ToKey: "99", + BundleSummary: "test_value", + }) + + s.RunTxBundlesSuccess(&bundletypes.MsgVoteBundleProposal{ + Creator: i.VALADDRESS_1_A, + Staker: i.STAKER_1, + PoolId: 0, + StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI", + Vote: bundletypes.VOTE_TYPE_VALID, + }) + + initialBalanceStaker1 = s.GetCoinsFromAddress(i.STAKER_1) + initialBalanceValaddress1 = s.GetCoinsFromAddress(i.VALADDRESS_1_A) + + c1 := s.GetCoinsFromCommunityPool() + + s.CommitAfterSeconds(60) + + // ACT + s.RunTxBundlesSuccess(&bundletypes.MsgSubmitBundleProposal{ + Creator: i.VALADDRESS_1_A, + Staker: i.STAKER_1, + PoolId: 0, + StorageId: "P9edn0bjEfMU_lecFDIPLvGO2v2ltpFNUMWp5kgPddg", + DataSize: 100, + DataHash: "test_hash2", + FromIndex: 100, + BundleSize: 100, + FromKey: "100", + ToKey: "199", + BundleSummary: "test_value2", + }) + + // ASSERT + // check if bundle got finalized on pool + pool, poolFound := s.App().PoolKeeper.GetPool(s.Ctx(), 0) + Expect(poolFound).To(BeTrue()) + + Expect(pool.CurrentKey).To(Equal("99")) + Expect(pool.CurrentSummary).To(Equal("test_value")) + Expect(pool.CurrentIndex).To(Equal(uint64(100))) + Expect(pool.TotalBundles).To(Equal(uint64(1))) + + // check if finalized bundle got saved + finalizedBundle, finalizedBundleFound := s.App().BundlesKeeper.GetFinalizedBundle(s.Ctx(), 0, 0) + Expect(finalizedBundleFound).To(BeTrue()) + + Expect(finalizedBundle.PoolId).To(Equal(uint64(0))) + Expect(finalizedBundle.StorageId).To(Equal("y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI")) + Expect(finalizedBundle.Uploader).To(Equal(i.STAKER_0)) + Expect(finalizedBundle.FromIndex).To(Equal(uint64(0))) + Expect(finalizedBundle.ToIndex).To(Equal(uint64(100))) + Expect(finalizedBundle.FromKey).To(Equal("0")) + Expect(finalizedBundle.ToKey).To(Equal("99")) + Expect(finalizedBundle.BundleSummary).To(Equal("test_value")) + Expect(finalizedBundle.DataHash).To(Equal("test_hash")) + Expect(finalizedBundle.FinalizedAt).NotTo(BeZero()) + Expect(finalizedBundle.StakeSecurity.ValidVotePower).To(Equal(200 * i.KYVE)) + Expect(finalizedBundle.StakeSecurity.TotalVotePower).To(Equal(200 * i.KYVE)) + + // check if next bundle proposal got registered + bundleProposal, bundleProposalFound := s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0) + Expect(bundleProposalFound).To(BeTrue()) + + Expect(bundleProposal.PoolId).To(Equal(uint64(0))) + Expect(bundleProposal.StorageId).To(Equal("P9edn0bjEfMU_lecFDIPLvGO2v2ltpFNUMWp5kgPddg")) + Expect(bundleProposal.Uploader).To(Equal(i.STAKER_1)) + Expect(bundleProposal.NextUploader).NotTo(BeEmpty()) + Expect(bundleProposal.DataSize).To(Equal(uint64(100))) + Expect(bundleProposal.DataHash).To(Equal("test_hash2")) + Expect(bundleProposal.BundleSize).To(Equal(uint64(100))) + Expect(bundleProposal.FromKey).To(Equal("100")) + Expect(bundleProposal.ToKey).To(Equal("199")) + Expect(bundleProposal.BundleSummary).To(Equal("test_value2")) + Expect(bundleProposal.UpdatedAt).NotTo(BeZero()) + Expect(bundleProposal.VotersValid).To(ContainElement(i.STAKER_1)) + Expect(bundleProposal.VotersInvalid).To(BeEmpty()) + Expect(bundleProposal.VotersAbstain).To(BeEmpty()) + + // check uploader status + valaccountUploader, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccountUploader.Points).To(BeZero()) + + balanceUploaderValaddress := s.GetCoinsFromAddress(valaccountUploader.Valaddress) + Expect(balanceUploaderValaddress).To(Equal(initialBalanceValaddress0)) + + // check voter status + valaccountVoter, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_1) + Expect(valaccountVoter.Points).To(BeZero()) + + balanceVoterValaddress := s.GetCoinsFromAddress(valaccountVoter.Valaddress) + Expect(balanceVoterValaddress).To(Equal(initialBalanceValaddress1)) + + balanceVoter := s.GetCoinsFromAddress(valaccountVoter.Staker) + Expect(balanceVoter).To(Equal(initialBalanceStaker1)) + + // check uploader rewards + uploader, _ := s.App().StakersKeeper.GetStaker(s.Ctx(), valaccountUploader.Staker) + balanceUploader := s.GetCoinsFromAddress(valaccountUploader.Staker) + + // assert payout transfer + Expect(balanceUploader.String()).To(Equal(initialBalanceStaker0.String())) + // assert commission rewards (here we round down since the result of commission rewards gets truncated) + // (amount_per_bundle - treasury_reward - storage_cost) * uploader_commission + storage_cost + // storage_cost = 1MB * storage_price / coin_length * coin_price + // (amount_per_bundle - (amount_per_bundle * 0.01) - _((1048576 * 0.000000006288 * 10**coin_decimals) / (4 * coin_weight))_) * 0.1 + _((1048576 * 0.000000006288) / (4 * coin_weight))_ + Expect(uploader.CommissionRewards.String()).To(Equal(sdk.NewCoins(i.KYVECoin(125_973_187), i.ACoin(99_143), i.BCoin(116_661_015_771_428_571), i.CCoin(100_765)).String())) + // assert uploader self delegation rewards (here we round up since the result of delegation rewards is the remainder minus the truncated commission rewards) + // (amount_per_bundle - (amount_per_bundle * 0.01) - _((29970208 * 0.000000006288 * 1**coin_decimals) / (4 * coin_weight))_) * (1 - 0.1) + Expect(s.App().DelegationKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(sdk.NewCoins(i.KYVECoin(864_026_813), i.ACoin(890_857), i.BCoin(873_338_984_228_571_429), i.CCoin(889_235)).String())) + + fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) + + // assert treasury payout + c2 := s.GetCoinsFromCommunityPool() + Expect(c2.Sub(c1...).AmountOf(i.A_DENOM)).To(Equal(math.NewInt(10000))) + Expect(c2.Sub(c1...).AmountOf(i.B_DENOM)).To(Equal(math.NewInt(10000000000000000))) + Expect(c2.Sub(c1...).AmountOf(i.C_DENOM)).To(Equal(math.NewInt(10000))) + + // assert total pool funds + Expect(s.App().FundersKeeper.GetTotalActiveFunding(s.Ctx(), fundingState.PoolId).String()).To(Equal(sdk.NewCoins(i.KYVECoin(99_000_000_000), i.ACoin(99_000_000), sdk.NewCoin(i.B_DENOM, s.MustNewIntFromStr("99000000000000000000")), i.CCoin(99_000_000)).String())) + Expect(fundingState.ActiveFunderAddresses).To(HaveLen(1)) + }) }) diff --git a/x/bundles/keeper/keeper_suite_zero_delegation_test.go b/x/bundles/keeper/keeper_suite_zero_delegation_test.go index 73dd0939..7fea5206 100644 --- a/x/bundles/keeper/keeper_suite_zero_delegation_test.go +++ b/x/bundles/keeper/keeper_suite_zero_delegation_test.go @@ -62,7 +62,7 @@ var _ = Describe("zero delegation", Ordered, func() { s.RunTxPoolSuccess(msg) params := funderstypes.DefaultParams() - params.CoinWhitelist[0].MinFundingAmountPerBundle = amountPerBundle + params.CoinWhitelist[0].MinFundingAmountPerBundle = math.NewIntFromUint64(amountPerBundle) s.App().FundersKeeper.SetParams(s.Ctx(), params) // create funders diff --git a/x/bundles/keeper/logic_bundles.go b/x/bundles/keeper/logic_bundles.go index d8a5e25c..11a4e06e 100644 --- a/x/bundles/keeper/logic_bundles.go +++ b/x/bundles/keeper/logic_bundles.go @@ -2,6 +2,7 @@ package keeper import ( "cosmossdk.io/errors" + "cosmossdk.io/math" globalTypes "github.com/KYVENetwork/chain/x/global/types" poolTypes "github.com/KYVENetwork/chain/x/pool/types" @@ -274,17 +275,25 @@ func (k Keeper) calculatePayouts(ctx sdk.Context, poolId uint64, totalPayout sdk // funds left of each coin, and in the case there are not enough the coins are removed and therefore for the // next bundle we split between the other remaining coins. whitelist := k.fundersKeeper.GetCoinWhitelistMap(ctx) + // wantedStorageRewards are the amounts based on the current storage cost we want to pay out, this can be more + // than we have available in totalPayout wantedStorageRewards := sdk.NewCoins() + // storageCostPerCoin is the storage cost in $USD for each coin. This implies that each coin contributes the same + // amount of value to the storage rewards storageCostPerCoin := k.GetStorageCost(ctx, bundleProposal.StorageProviderId).MulInt64(int64(bundleProposal.DataSize)).QuoInt64(int64(totalPayout.Len())) - for _, coin := range totalPayout { weight := whitelist[coin.Denom].CoinWeight if weight.IsZero() { continue } - amount := storageCostPerCoin.Quo(weight) - wantedStorageRewards = wantedStorageRewards.Add(sdk.NewCoin(coin.Denom, amount.TruncateInt())) + // currencyUnit is the amount of base denoms of the currency + currencyUnit := math.LegacyNewDec(10).Power(uint64(whitelist[coin.Denom].CoinDecimals)) + // amount is the value of storageCostPerCoin in the base denomination of the currency. We calculate this + // by multiplying first with the amount of base denoms of the currency and then divide this by the $USD + // value per currency unit which is the weight. + amount := storageCostPerCoin.Mul(currencyUnit).Quo(weight).TruncateInt() + wantedStorageRewards = wantedStorageRewards.Add(sdk.NewCoin(coin.Denom, amount)) } // we take the min here since there can be the case where we want to charge more coins for the storage diff --git a/x/bundles/keeper/logic_bundles_test.go b/x/bundles/keeper/logic_bundles_test.go index d6a1fd23..a9d54e04 100644 --- a/x/bundles/keeper/logic_bundles_test.go +++ b/x/bundles/keeper/logic_bundles_test.go @@ -22,6 +22,7 @@ TEST CASES - logic_bundles.go * Assert pool can run while voting power of one node is too high * Assert pool can run while voting power of one node is 40% * Assert pool can run while voting power of one node exceeds 40% +* Assert pool can run with a single staker while voting power is 100% * Assert pool can run * Assert pool can run while pool has no funds * Assert pool can run when endKey is reached @@ -382,6 +383,49 @@ var _ = Describe("logic_bundles.go", Ordered, func() { Expect(err).To(Equal(bundlesTypes.ErrVotingPowerTooHigh)) }) + It("Assert pool can run with a single staker while voting power is 100%", func() { + // ARRANGE + params := s.App().PoolKeeper.GetParams(s.Ctx()) + params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("1") + s.App().PoolKeeper.SetParams(s.Ctx(), params) + + msg := &pooltypes.MsgCreatePool{ + Authority: gov, + Name: "PoolTest", + Runtime: "@kyve/test", + Logo: "ar://Tewyv2P5VEG8EJ6AUQORdqNTectY9hlOrWPK8wwo-aU", + Config: "ar://DgdB-2hLrxjhyEEbCML__dgZN5_uS7T6Z5XDkaFh3P0", + StartKey: "0", + UploadInterval: 60, + InflationShareWeight: math.LegacyMustNewDecFromStr("1"), + MinDelegation: 100 * i.KYVE, + MaxBundleSize: 100, + Version: "0.0.0", + Binaries: "{}", + StorageProviderId: 2, + CompressionId: 1, + } + s.RunTxPoolSuccess(msg) + + s.RunTxStakersSuccess(&stakertypes.MsgCreateStaker{ + Creator: i.STAKER_0, + Amount: 300 * i.KYVE, + }) + + s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + }) + + // ACT + err := s.App().BundlesKeeper.AssertPoolCanRun(s.Ctx(), 0) + + // ASSERT + Expect(err).NotTo(HaveOccurred()) + }) + It("Assert pool can run", func() { // ARRANGE s.RunTxStakersSuccess(&stakertypes.MsgCreateStaker{ diff --git a/x/funders/keeper/logic_funders.go b/x/funders/keeper/logic_funders.go index 9f023f5b..81278854 100644 --- a/x/funders/keeper/logic_funders.go +++ b/x/funders/keeper/logic_funders.go @@ -140,8 +140,8 @@ func (k Keeper) ensureParamsCompatibility(ctx sdk.Context, funding *types.Fundin minFundingAmountsPerBundle := sdk.NewCoins() for _, entry := range params.CoinWhitelist { - minFundingAmounts = minFundingAmounts.Add(sdk.NewInt64Coin(entry.CoinDenom, int64(entry.MinFundingAmount))) - minFundingAmountsPerBundle = minFundingAmountsPerBundle.Add(sdk.NewInt64Coin(entry.CoinDenom, int64(entry.MinFundingAmountPerBundle))) + minFundingAmounts = minFundingAmounts.Add(sdk.NewCoin(entry.CoinDenom, entry.MinFundingAmount)) + minFundingAmountsPerBundle = minFundingAmountsPerBundle.Add(sdk.NewCoin(entry.CoinDenom, entry.MinFundingAmountPerBundle)) } // before we perform compatibility checks we clean the funding state diff --git a/x/funders/keeper/logic_funders_test.go b/x/funders/keeper/logic_funders_test.go index e79528b1..9aa7bf3a 100644 --- a/x/funders/keeper/logic_funders_test.go +++ b/x/funders/keeper/logic_funders_test.go @@ -61,26 +61,26 @@ var _ = Describe("logic_funders.go", Ordered, func() { whitelist = []*funderstypes.WhitelistCoinEntry{ { CoinDenom: globaltypes.Denom, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.A_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.B_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(2), }, { CoinDenom: i.C_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(3), }, } @@ -371,20 +371,20 @@ var _ = Describe("logic_funders.go", Ordered, func() { s.App().FundersKeeper.SetParams(s.Ctx(), funderstypes.NewParams([]*funderstypes.WhitelistCoinEntry{ { CoinDenom: globaltypes.Denom, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.B_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(2), }, { CoinDenom: i.C_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(3), }, }, 20)) @@ -460,8 +460,8 @@ var _ = Describe("logic_funders.go", Ordered, func() { s.App().FundersKeeper.SetParams(s.Ctx(), funderstypes.NewParams([]*funderstypes.WhitelistCoinEntry{ { CoinDenom: globaltypes.Denom, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { @@ -508,8 +508,8 @@ var _ = Describe("logic_funders.go", Ordered, func() { s.App().FundersKeeper.SetParams(s.Ctx(), funderstypes.NewParams([]*funderstypes.WhitelistCoinEntry{ { CoinDenom: globaltypes.Denom, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { @@ -556,8 +556,8 @@ var _ = Describe("logic_funders.go", Ordered, func() { s.App().FundersKeeper.SetParams(s.Ctx(), funderstypes.NewParams([]*funderstypes.WhitelistCoinEntry{ { CoinDenom: globaltypes.Denom, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { diff --git a/x/funders/keeper/msg_server_defund_pool_test.go b/x/funders/keeper/msg_server_defund_pool_test.go index f1876173..7bc4f5f0 100644 --- a/x/funders/keeper/msg_server_defund_pool_test.go +++ b/x/funders/keeper/msg_server_defund_pool_test.go @@ -66,26 +66,26 @@ var _ = Describe("msg_server_defund_pool.go", Ordered, func() { whitelist = []*types.WhitelistCoinEntry{ { CoinDenom: globaltypes.Denom, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.A_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.B_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(2), }, { CoinDenom: i.C_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(3), }, } @@ -307,20 +307,20 @@ var _ = Describe("msg_server_defund_pool.go", Ordered, func() { s.App().FundersKeeper.SetParams(s.Ctx(), types.NewParams([]*types.WhitelistCoinEntry{ { CoinDenom: globaltypes.Denom, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.B_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(2), }, { CoinDenom: i.C_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(3), }, }, 20)) @@ -342,20 +342,20 @@ var _ = Describe("msg_server_defund_pool.go", Ordered, func() { s.App().FundersKeeper.SetParams(s.Ctx(), types.NewParams([]*types.WhitelistCoinEntry{ { CoinDenom: globaltypes.Denom, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.B_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(2), }, { CoinDenom: i.C_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(3), }, }, 20)) diff --git a/x/funders/keeper/msg_server_fund_pool_test.go b/x/funders/keeper/msg_server_fund_pool_test.go index 58a21d64..09b6307c 100644 --- a/x/funders/keeper/msg_server_fund_pool_test.go +++ b/x/funders/keeper/msg_server_fund_pool_test.go @@ -80,26 +80,26 @@ var _ = Describe("msg_server_fund_pool.go", Ordered, func() { whitelist = []*funderstypes.WhitelistCoinEntry{ { CoinDenom: globaltypes.Denom, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.A_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.B_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(2), }, { CoinDenom: i.C_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(3), }, } @@ -440,20 +440,20 @@ var _ = Describe("msg_server_fund_pool.go", Ordered, func() { whitelist = []*funderstypes.WhitelistCoinEntry{ { CoinDenom: globaltypes.Denom, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.A_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.B_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(2), }, } @@ -484,20 +484,20 @@ var _ = Describe("msg_server_fund_pool.go", Ordered, func() { whitelist = []*funderstypes.WhitelistCoinEntry{ { CoinDenom: globaltypes.Denom, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.A_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.B_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(2), }, } @@ -521,20 +521,20 @@ var _ = Describe("msg_server_fund_pool.go", Ordered, func() { whitelist = []*funderstypes.WhitelistCoinEntry{ { CoinDenom: globaltypes.Denom, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.A_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.B_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(2), }, } diff --git a/x/funders/keeper/msg_server_update_params_test.go b/x/funders/keeper/msg_server_update_params_test.go index 6d170d1f..90ec9ed6 100644 --- a/x/funders/keeper/msg_server_update_params_test.go +++ b/x/funders/keeper/msg_server_update_params_test.go @@ -3,6 +3,8 @@ package keeper_test import ( "time" + "cosmossdk.io/math" + i "github.com/KYVENetwork/chain/testutil/integration" sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -31,6 +33,7 @@ TEST CASES - msg_server_update_params.go * Update existing coin whitelist entry with invalid value * Update multiple coin whitelist entries * Update coin whitelist entry without the native kyve coin +* Update coin whitelist entry with 18 decimal values * Update min-funding-multiple * Update min-funding-multiple with invalid value @@ -111,7 +114,7 @@ var _ = Describe("msg_server_update_params.go", Ordered, func() { It("Update every param at once", func() { // ARRANGE payload := `{ - "coin_whitelist": [{"coin_denom":"tkyve","min_funding_amount":20000000000,"min_funding_amount_per_bundle":2000000000,"coin_weight":"5"}], + "coin_whitelist": [{"coin_denom":"tkyve","coin_decimals":6,"min_funding_amount":"20000000000","min_funding_amount_per_bundle":"2000000000","coin_weight":"5"}], "min_funding_multiple": 25 }` @@ -143,8 +146,9 @@ var _ = Describe("msg_server_update_params.go", Ordered, func() { Expect(updatedParams.CoinWhitelist).To(HaveLen(1)) Expect(updatedParams.CoinWhitelist[0].CoinDenom).To(Equal("tkyve")) - Expect(updatedParams.CoinWhitelist[0].MinFundingAmount).To(Equal(uint64(20000000000))) - Expect(updatedParams.CoinWhitelist[0].MinFundingAmountPerBundle).To(Equal(uint64(2000000000))) + Expect(updatedParams.CoinWhitelist[0].CoinDecimals).To(Equal(uint32(6))) + Expect(updatedParams.CoinWhitelist[0].MinFundingAmount).To(Equal(math.NewInt(20000000000))) + Expect(updatedParams.CoinWhitelist[0].MinFundingAmountPerBundle).To(Equal(math.NewInt(2000000000))) Expect(updatedParams.CoinWhitelist[0].CoinWeight.TruncateInt64()).To(Equal(int64(5))) Expect(updatedParams.MinFundingMultiple).To(Equal(uint64(25))) @@ -217,7 +221,7 @@ var _ = Describe("msg_server_update_params.go", Ordered, func() { It("Update existing coin whitelist entry", func() { // ARRANGE payload := `{ - "coin_whitelist": [{"coin_denom":"tkyve","min_funding_amount":20000000000,"min_funding_amount_per_bundle":200000,"coin_weight":"7"}] + "coin_whitelist": [{"coin_denom":"tkyve","coin_decimals":9,"min_funding_amount":"20000000000","min_funding_amount_per_bundle":"200000","coin_weight":"7"}] }` msg := &types.MsgUpdateParams{ @@ -248,8 +252,9 @@ var _ = Describe("msg_server_update_params.go", Ordered, func() { Expect(updatedParams.CoinWhitelist).To(HaveLen(1)) Expect(updatedParams.CoinWhitelist[0].CoinDenom).To(Equal("tkyve")) - Expect(updatedParams.CoinWhitelist[0].MinFundingAmount).To(Equal(uint64(20000000000))) - Expect(updatedParams.CoinWhitelist[0].MinFundingAmountPerBundle).To(Equal(uint64(200000))) + Expect(updatedParams.CoinWhitelist[0].CoinDecimals).To(Equal(uint32(9))) + Expect(updatedParams.CoinWhitelist[0].MinFundingAmount).To(Equal(math.NewInt(20000000000))) + Expect(updatedParams.CoinWhitelist[0].MinFundingAmountPerBundle).To(Equal(math.NewInt(200000))) Expect(updatedParams.CoinWhitelist[0].CoinWeight.TruncateInt64()).To(Equal(int64(7))) Expect(updatedParams.MinFundingMultiple).To(Equal(types.DefaultMinFundingMultiple)) @@ -258,7 +263,7 @@ var _ = Describe("msg_server_update_params.go", Ordered, func() { It("Update existing coin whitelist entry with invalid value", func() { // ARRANGE payload := `{ - "coin_whitelist": [{"coin_denom":"tkyve","min_funding_amount":invalid,"min_funding_amount_per_bundle":100000,"coin_weight":"1"}] + "coin_whitelist": [{"coin_denom":"tkyve","coin_decimals":6,"min_funding_amount":invalid,"min_funding_amount_per_bundle":"100000","coin_weight":"1"}] }` msg := &types.MsgUpdateParams{ @@ -288,7 +293,7 @@ var _ = Describe("msg_server_update_params.go", Ordered, func() { It("Update multiple coin whitelist entries", func() { // ARRANGE payload := `{ - "coin_whitelist": [{"coin_denom":"tkyve","min_funding_amount":20000000000,"min_funding_amount_per_bundle":200000,"coin_weight":"5"},{"coin_denom":"acoin","min_funding_amount":10000000000,"min_funding_amount_per_bundle":100000,"coin_weight":"2"}] + "coin_whitelist": [{"coin_denom":"tkyve","coin_decimals":9,"min_funding_amount":"20000000000","min_funding_amount_per_bundle":"200000","coin_weight":"5"},{"coin_denom":"acoin","coin_decimals":12,"min_funding_amount":"10000000000","min_funding_amount_per_bundle":"100000","coin_weight":"2"}] }` msg := &types.MsgUpdateParams{ @@ -320,13 +325,15 @@ var _ = Describe("msg_server_update_params.go", Ordered, func() { Expect(updatedParams.CoinWhitelist).To(HaveLen(2)) Expect(updatedParams.CoinWhitelist[0].CoinDenom).To(Equal("tkyve")) - Expect(updatedParams.CoinWhitelist[0].MinFundingAmount).To(Equal(uint64(20000000000))) - Expect(updatedParams.CoinWhitelist[0].MinFundingAmountPerBundle).To(Equal(uint64(200000))) + Expect(updatedParams.CoinWhitelist[0].CoinDecimals).To(Equal(uint32(9))) + Expect(updatedParams.CoinWhitelist[0].MinFundingAmount).To(Equal(math.NewInt(20000000000))) + Expect(updatedParams.CoinWhitelist[0].MinFundingAmountPerBundle).To(Equal(math.NewInt(200000))) Expect(updatedParams.CoinWhitelist[0].CoinWeight.TruncateInt64()).To(Equal(int64(5))) Expect(updatedParams.CoinWhitelist[1].CoinDenom).To(Equal("acoin")) - Expect(updatedParams.CoinWhitelist[1].MinFundingAmount).To(Equal(uint64(10000000000))) - Expect(updatedParams.CoinWhitelist[1].MinFundingAmountPerBundle).To(Equal(uint64(100000))) + Expect(updatedParams.CoinWhitelist[1].CoinDecimals).To(Equal(uint32(12))) + Expect(updatedParams.CoinWhitelist[1].MinFundingAmount).To(Equal(math.NewInt(10000000000))) + Expect(updatedParams.CoinWhitelist[1].MinFundingAmountPerBundle).To(Equal(math.NewInt(100000))) Expect(updatedParams.CoinWhitelist[1].CoinWeight.TruncateInt64()).To(Equal(int64(2))) Expect(updatedParams.MinFundingMultiple).To(Equal(types.DefaultMinFundingMultiple)) @@ -335,7 +342,7 @@ var _ = Describe("msg_server_update_params.go", Ordered, func() { It("Update coin whitelist entry without the native kyve coin", func() { // ARRANGE payload := `{ - "coin_whitelist": [{"coin_denom":"acoin","min_funding_amount":10000000000,"min_funding_amount_per_bundle":100000,"coin_weight":"2"}] + "coin_whitelist": [{"coin_denom":"acoin","coin_decimals":6,"min_funding_amount":10000000000,"min_funding_amount_per_bundle":100000,"coin_weight":"2"}] }` msg := &types.MsgUpdateParams{ @@ -361,6 +368,51 @@ var _ = Describe("msg_server_update_params.go", Ordered, func() { Expect(updatedParams.MinFundingMultiple).To(Equal(types.DefaultMinFundingMultiple)) }) + It("Update coin whitelist entry with 18 decimal values", func() { + // ARRANGE + // we update here with 1000 * 10**18 as min_funding_amount and 100 * 10**18 as min_funding_amount_per_bundle + // which are both bigger than the max uint of 2**64 + payload := `{ + "coin_whitelist": [{"coin_denom":"tkyve","coin_decimals":18,"min_funding_amount":"1000000000000000000000","min_funding_amount_per_bundle":"100000000000000000000","coin_weight":"2"}] + }` + + msg := &types.MsgUpdateParams{ + Authority: gov, + Payload: payload, + } + + proposal, _ := govV1Types.NewMsgSubmitProposal( + []sdk.Msg{msg}, minDeposit, i.DUMMY[0], "", "title", "summary", false, + ) + + vote := govV1Types.NewMsgVote( + voter, 1, govV1Types.VoteOption_VOTE_OPTION_YES, "", + ) + + // ACT + _, submitErr := s.RunTx(proposal) + _, voteErr := s.RunTx(vote) + + s.CommitAfter(*votingPeriod) + s.Commit() + + // ASSERT + updatedParams := s.App().FundersKeeper.GetParams(s.Ctx()) + Expect(submitErr).NotTo(HaveOccurred()) + Expect(voteErr).NotTo(HaveOccurred()) + + Expect(updatedParams.CoinWhitelist).To(HaveLen(1)) + + minFundingAmount, _ := math.NewIntFromString("1000000000000000000000") + minFundingAmountPerBundle, _ := math.NewIntFromString("100000000000000000000") + + Expect(updatedParams.CoinWhitelist[0].CoinDenom).To(Equal("tkyve")) + Expect(updatedParams.CoinWhitelist[0].CoinDecimals).To(Equal(uint32(18))) + Expect(updatedParams.CoinWhitelist[0].MinFundingAmount).To(Equal(minFundingAmount)) + Expect(updatedParams.CoinWhitelist[0].MinFundingAmountPerBundle).To(Equal(minFundingAmountPerBundle)) + Expect(updatedParams.CoinWhitelist[0].CoinWeight.TruncateInt64()).To(Equal(int64(2))) + }) + It("Update min-funding-multiple", func() { // ARRANGE payload := `{ diff --git a/x/funders/types/funders.go b/x/funders/types/funders.go index f8df0a21..83172637 100644 --- a/x/funders/types/funders.go +++ b/x/funders/types/funders.go @@ -1,11 +1,17 @@ package types -import sdk "github.com/cosmos/cosmos-sdk/types" +import ( + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" +) func (f *Funding) GetScore(whitelist map[string]WhitelistCoinEntry) (score uint64) { for _, coin := range f.Amounts { if entry, found := whitelist[coin.Denom]; found { - score += uint64(entry.CoinWeight.MulInt64(coin.Amount.Int64()).TruncateInt64()) + // we first multiply the coin weight which is the USD value per currency unit and then times the amount, + // because dividing with the amount of base denoms (10^coin_decimals) first could exceed the decimal + // precision of 18 + score += uint64(entry.CoinWeight.MulInt(coin.Amount).Quo(math.LegacyNewDec(10).Power(uint64(entry.CoinDecimals))).TruncateInt64()) } } diff --git a/x/funders/types/funders_test.go b/x/funders/types/funders_test.go index e79e4668..e4cf3fbf 100644 --- a/x/funders/types/funders_test.go +++ b/x/funders/types/funders_test.go @@ -40,26 +40,26 @@ var _ = Describe("logic_funders.go", Ordered, func() { s.App().FundersKeeper.SetParams(s.Ctx(), types.NewParams([]*types.WhitelistCoinEntry{ { CoinDenom: globaltypes.Denom, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.A_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.B_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(2), }, { CoinDenom: i.C_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(3), }, }, 20)) @@ -139,14 +139,14 @@ var _ = Describe("logic_funders.go", Ordered, func() { s.App().FundersKeeper.SetParams(s.Ctx(), types.NewParams([]*types.WhitelistCoinEntry{ { CoinDenom: globaltypes.Denom, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.A_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: 1 * i.KYVE, + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewIntFromUint64(1 * i.KYVE), CoinWeight: math.LegacyNewDec(1), }, }, 20)) diff --git a/x/funders/types/params.go b/x/funders/types/params.go index f6fb7e0d..3ad4b4e6 100644 --- a/x/funders/types/params.go +++ b/x/funders/types/params.go @@ -31,8 +31,9 @@ func DefaultParams() Params { []*WhitelistCoinEntry{ { CoinDenom: globalTypes.Denom, - MinFundingAmount: uint64(1_000_000_000), // 1,000 $KYVE - MinFundingAmountPerBundle: uint64(100_000), // 0.1 $KYVE + CoinDecimals: uint32(6), + MinFundingAmount: math.NewInt(1_000_000_000), // 1,000 $KYVE + MinFundingAmountPerBundle: math.NewInt(100_000), // 0.1 $KYVE CoinWeight: math.LegacyNewDec(1), }, }, @@ -54,11 +55,11 @@ func (p *Params) Validate() error { return errors.New("coin denom is empty") } - if err := util.ValidateNumber(entry.MinFundingAmount); err != nil { + if err := util.ValidateInt(entry.MinFundingAmount); err != nil { return err } - if err := util.ValidateNumber(entry.MinFundingAmountPerBundle); err != nil { + if err := util.ValidateInt(entry.MinFundingAmountPerBundle); err != nil { return err } diff --git a/x/funders/types/params.pb.go b/x/funders/types/params.pb.go index 4493ce71..ef3c4460 100644 --- a/x/funders/types/params.pb.go +++ b/x/funders/types/params.pb.go @@ -30,15 +30,19 @@ type WhitelistCoinEntry struct { // coin_denom is the denom of a coin which is allowed to be funded, this value // needs to be unique CoinDenom string `protobuf:"bytes,1,opt,name=coin_denom,json=coinDenom,proto3" json:"coin_denom,omitempty"` + // coin_decimals are the decimals of the coin + CoinDecimals uint32 `protobuf:"varint,2,opt,name=coin_decimals,json=coinDecimals,proto3" json:"coin_decimals,omitempty"` // min_funding_amount is the minimum required amount of this denom that needs - // to be funded - MinFundingAmount uint64 `protobuf:"varint,2,opt,name=min_funding_amount,json=minFundingAmount,proto3" json:"min_funding_amount,omitempty"` + // to be funded. It is of type math.Int since a uint64 is not sufficient for a + // coin with 18 decimals + MinFundingAmount cosmossdk_io_math.Int `protobuf:"bytes,3,opt,name=min_funding_amount,json=minFundingAmount,proto3,customtype=cosmossdk.io/math.Int" json:"min_funding_amount"` // min_funding_amount_per_bundle is the minimum required amount of this denom - // that needs to be funded per bundle - MinFundingAmountPerBundle uint64 `protobuf:"varint,3,opt,name=min_funding_amount_per_bundle,json=minFundingAmountPerBundle,proto3" json:"min_funding_amount_per_bundle,omitempty"` + // that needs to be funded per bundle. It is of type math.Int since a uint64 + // is not sufficient for a coin with 18 decimals + MinFundingAmountPerBundle cosmossdk_io_math.Int `protobuf:"bytes,4,opt,name=min_funding_amount_per_bundle,json=minFundingAmountPerBundle,proto3,customtype=cosmossdk.io/math.Int" json:"min_funding_amount_per_bundle"` // coin_weight is a factor used to sort funders after their funding amounts. // This should be the market price of the coin in USD/coin. This value should be kept up-to-date. - CoinWeight cosmossdk_io_math.LegacyDec `protobuf:"bytes,4,opt,name=coin_weight,json=coinWeight,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"coin_weight"` + CoinWeight cosmossdk_io_math.LegacyDec `protobuf:"bytes,5,opt,name=coin_weight,json=coinWeight,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"coin_weight"` } func (m *WhitelistCoinEntry) Reset() { *m = WhitelistCoinEntry{} } @@ -81,16 +85,9 @@ func (m *WhitelistCoinEntry) GetCoinDenom() string { return "" } -func (m *WhitelistCoinEntry) GetMinFundingAmount() uint64 { +func (m *WhitelistCoinEntry) GetCoinDecimals() uint32 { if m != nil { - return m.MinFundingAmount - } - return 0 -} - -func (m *WhitelistCoinEntry) GetMinFundingAmountPerBundle() uint64 { - if m != nil { - return m.MinFundingAmountPerBundle + return m.CoinDecimals } return 0 } @@ -160,31 +157,33 @@ func init() { func init() { proto.RegisterFile("kyve/funders/v1beta1/params.proto", fileDescriptor_906a9a55094dc984) } var fileDescriptor_906a9a55094dc984 = []byte{ - // 381 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0xcd, 0x8e, 0xda, 0x30, - 0x14, 0x85, 0xe3, 0x82, 0x90, 0x30, 0x6a, 0x55, 0x59, 0x2c, 0xd2, 0x56, 0x04, 0x4a, 0x37, 0x59, - 0x20, 0xbb, 0xb4, 0x2f, 0xd0, 0x52, 0x60, 0xd3, 0x3f, 0x94, 0x45, 0x51, 0xbb, 0x89, 0xf2, 0xe3, - 0x26, 0x16, 0xb1, 0x1d, 0x25, 0x0e, 0x34, 0xcf, 0xd0, 0x4d, 0x1f, 0x8b, 0x25, 0xcb, 0xaa, 0x0b, - 0x54, 0xc1, 0x6a, 0xde, 0x62, 0x14, 0x13, 0x66, 0x46, 0xc3, 0xec, 0xac, 0x73, 0xbf, 0x7b, 0x7d, - 0xcf, 0xb9, 0xf0, 0xe5, 0xaa, 0x5c, 0x53, 0xf2, 0xb3, 0x10, 0x21, 0xcd, 0x72, 0xb2, 0x1e, 0xfb, - 0x54, 0x79, 0x63, 0x92, 0x7a, 0x99, 0xc7, 0x73, 0x9c, 0x66, 0x52, 0x49, 0xd4, 0xad, 0x10, 0x5c, - 0x23, 0xb8, 0x46, 0x9e, 0x77, 0x23, 0x19, 0x49, 0x0d, 0x90, 0xea, 0x75, 0x62, 0x87, 0x57, 0x00, - 0xa2, 0x65, 0xcc, 0x14, 0x4d, 0x58, 0xae, 0x3e, 0x48, 0x26, 0x66, 0x42, 0x65, 0x25, 0xea, 0x41, - 0x18, 0x48, 0x26, 0xdc, 0x90, 0x0a, 0xc9, 0x4d, 0x30, 0x00, 0x76, 0xdb, 0x69, 0x57, 0xca, 0xb4, - 0x12, 0xd0, 0x08, 0x22, 0xce, 0x84, 0x5b, 0x7d, 0xc1, 0x44, 0xe4, 0x7a, 0x5c, 0x16, 0x42, 0x99, - 0x8f, 0x06, 0xc0, 0x6e, 0x3a, 0x4f, 0x39, 0x13, 0xf3, 0x53, 0xe1, 0xbd, 0xd6, 0xd1, 0x3b, 0xd8, - 0xbb, 0xa4, 0xdd, 0x94, 0x66, 0xae, 0x5f, 0x88, 0x30, 0xa1, 0x66, 0x43, 0x37, 0x3e, 0xbb, 0xdf, - 0xb8, 0xa0, 0xd9, 0x44, 0x03, 0x68, 0x0a, 0x3b, 0x7a, 0x9d, 0x0d, 0x65, 0x51, 0xac, 0xcc, 0x66, - 0xb5, 0xcf, 0xe4, 0xd5, 0x76, 0xdf, 0x37, 0xfe, 0xed, 0xfb, 0x2f, 0x02, 0x99, 0x73, 0x99, 0xe7, - 0xe1, 0x0a, 0x33, 0x49, 0xb8, 0xa7, 0x62, 0xfc, 0x89, 0x46, 0x5e, 0x50, 0x4e, 0x69, 0xe0, 0x68, - 0x1b, 0x4b, 0xdd, 0x36, 0xfc, 0x0d, 0x60, 0x6b, 0xa1, 0x83, 0x42, 0x5f, 0xe1, 0x93, 0xd3, 0xc0, - 0xb3, 0x75, 0x13, 0x0c, 0x1a, 0x76, 0xe7, 0x8d, 0x8d, 0x1f, 0xca, 0x0e, 0x5f, 0x26, 0xe4, 0x3c, - 0xd6, 0x83, 0xcf, 0x3a, 0x7a, 0x0d, 0xbb, 0x77, 0x3d, 0xf2, 0x22, 0x51, 0x2c, 0x4d, 0x68, 0x9d, - 0x09, 0xba, 0xb5, 0xf6, 0xb9, 0xae, 0x4c, 0xe6, 0xdb, 0x83, 0x05, 0x76, 0x07, 0x0b, 0xfc, 0x3f, - 0x58, 0xe0, 0xcf, 0xd1, 0x32, 0x76, 0x47, 0xcb, 0xf8, 0x7b, 0xb4, 0x8c, 0x1f, 0xa3, 0x88, 0xa9, - 0xb8, 0xf0, 0x71, 0x20, 0x39, 0xf9, 0xf8, 0xfd, 0xdb, 0xec, 0x0b, 0x55, 0x1b, 0x99, 0xad, 0x48, - 0x10, 0x7b, 0x4c, 0x90, 0x5f, 0x37, 0xc7, 0x57, 0x65, 0x4a, 0x73, 0xbf, 0xa5, 0x0f, 0xf9, 0xf6, - 0x3a, 0x00, 0x00, 0xff, 0xff, 0x73, 0xb9, 0xd1, 0x11, 0x19, 0x02, 0x00, 0x00, + // 413 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x4f, 0x6f, 0xd3, 0x30, + 0x18, 0xc6, 0xe3, 0x6d, 0x4c, 0x9a, 0xc7, 0x10, 0xb2, 0x8a, 0x14, 0x40, 0xcd, 0xca, 0x76, 0xc9, + 0x01, 0xd9, 0x0c, 0x3e, 0x01, 0xa5, 0x9b, 0x84, 0xca, 0x9f, 0x2a, 0x07, 0x2a, 0xb8, 0x44, 0x4e, + 0x62, 0x12, 0xab, 0xb1, 0x1d, 0xc5, 0x4e, 0x4b, 0x3e, 0x03, 0x17, 0x3e, 0x56, 0x0f, 0x1c, 0x7a, + 0x44, 0x1c, 0x2a, 0xd4, 0x7e, 0x11, 0x14, 0x27, 0x14, 0x44, 0x39, 0x70, 0x8b, 0x1e, 0x3f, 0xcf, + 0x4f, 0x79, 0x9f, 0xf7, 0x85, 0x8f, 0x66, 0xf5, 0x9c, 0x91, 0x8f, 0x95, 0x4c, 0x58, 0xa9, 0xc9, + 0xfc, 0x2a, 0x62, 0x86, 0x5e, 0x91, 0x82, 0x96, 0x54, 0x68, 0x5c, 0x94, 0xca, 0x28, 0xd4, 0x6b, + 0x2c, 0xb8, 0xb3, 0xe0, 0xce, 0xf2, 0xa0, 0x97, 0xaa, 0x54, 0x59, 0x03, 0x69, 0xbe, 0x5a, 0xef, + 0xc5, 0xd7, 0x03, 0x88, 0xa6, 0x19, 0x37, 0x2c, 0xe7, 0xda, 0xbc, 0x50, 0x5c, 0x5e, 0x4b, 0x53, + 0xd6, 0xa8, 0x0f, 0x61, 0xac, 0xb8, 0x0c, 0x13, 0x26, 0x95, 0x70, 0xc1, 0x00, 0xf8, 0x27, 0xc1, + 0x49, 0xa3, 0x8c, 0x1a, 0x01, 0x5d, 0xc2, 0xb3, 0xee, 0x39, 0xe6, 0x82, 0xe6, 0xda, 0x3d, 0x18, + 0x00, 0xff, 0x2c, 0xb8, 0xdd, 0x3a, 0x5a, 0x0d, 0x8d, 0x21, 0x12, 0x5c, 0x86, 0xcd, 0x7f, 0x70, + 0x99, 0x86, 0x54, 0xa8, 0x4a, 0x1a, 0xf7, 0xb0, 0x61, 0x0d, 0xfb, 0xcb, 0xf5, 0xb9, 0xf3, 0x7d, + 0x7d, 0x7e, 0x2f, 0x56, 0x5a, 0x28, 0xad, 0x93, 0x19, 0xe6, 0x8a, 0x08, 0x6a, 0x32, 0xfc, 0x52, + 0x9a, 0xe0, 0xae, 0xe0, 0xf2, 0xa6, 0xcd, 0x3d, 0xb7, 0x31, 0x14, 0xc2, 0xfe, 0x3e, 0x2c, 0x2c, + 0x58, 0x19, 0x46, 0x95, 0x4c, 0x72, 0xe6, 0x1e, 0xfd, 0x0f, 0xf7, 0xfe, 0xdf, 0xdc, 0x09, 0x2b, + 0x87, 0x36, 0x8f, 0x46, 0xf0, 0xd4, 0x8e, 0xb4, 0x60, 0x3c, 0xcd, 0x8c, 0x7b, 0xcb, 0xe2, 0x2e, + 0x3b, 0xdc, 0xc3, 0x7d, 0xdc, 0x2b, 0x96, 0xd2, 0xb8, 0x1e, 0xb1, 0x38, 0xb0, 0x4d, 0x4d, 0x6d, + 0xec, 0xe2, 0x33, 0x80, 0xc7, 0x13, 0xbb, 0x0b, 0xf4, 0x16, 0xde, 0x69, 0x81, 0xbf, 0xda, 0x75, + 0xc1, 0xe0, 0xd0, 0x3f, 0x7d, 0xea, 0xe3, 0x7f, 0xad, 0x07, 0xef, 0x2f, 0x21, 0xb0, 0x1d, 0xef, + 0x74, 0xf4, 0x04, 0xf6, 0xfe, 0xac, 0x40, 0x54, 0xb9, 0xe1, 0x45, 0xce, 0x6c, 0xf7, 0x47, 0x01, + 0xfa, 0x3d, 0xda, 0xeb, 0xee, 0x65, 0x78, 0xb3, 0xdc, 0x78, 0x60, 0xb5, 0xf1, 0xc0, 0x8f, 0x8d, + 0x07, 0xbe, 0x6c, 0x3d, 0x67, 0xb5, 0xf5, 0x9c, 0x6f, 0x5b, 0xcf, 0xf9, 0xf0, 0x38, 0xe5, 0x26, + 0xab, 0x22, 0x1c, 0x2b, 0x41, 0xc6, 0xef, 0xdf, 0x5d, 0xbf, 0x61, 0x66, 0xa1, 0xca, 0x19, 0x89, + 0x33, 0xca, 0x25, 0xf9, 0xb4, 0xbb, 0x2f, 0x53, 0x17, 0x4c, 0x47, 0xc7, 0xf6, 0x56, 0x9e, 0xfd, + 0x0c, 0x00, 0x00, 0xff, 0xff, 0xf8, 0xea, 0x4b, 0x0e, 0x7c, 0x02, 0x00, 0x00, } func (m *WhitelistCoinEntry) Marshal() (dAtA []byte, err error) { @@ -216,14 +215,29 @@ func (m *WhitelistCoinEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintParams(dAtA, i, uint64(size)) } i-- + dAtA[i] = 0x2a + { + size := m.MinFundingAmountPerBundle.Size() + i -= size + if _, err := m.MinFundingAmountPerBundle.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- dAtA[i] = 0x22 - if m.MinFundingAmountPerBundle != 0 { - i = encodeVarintParams(dAtA, i, uint64(m.MinFundingAmountPerBundle)) - i-- - dAtA[i] = 0x18 + { + size := m.MinFundingAmount.Size() + i -= size + if _, err := m.MinFundingAmount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintParams(dAtA, i, uint64(size)) } - if m.MinFundingAmount != 0 { - i = encodeVarintParams(dAtA, i, uint64(m.MinFundingAmount)) + i-- + dAtA[i] = 0x1a + if m.CoinDecimals != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.CoinDecimals)) i-- dAtA[i] = 0x10 } @@ -300,12 +314,13 @@ func (m *WhitelistCoinEntry) Size() (n int) { if l > 0 { n += 1 + l + sovParams(uint64(l)) } - if m.MinFundingAmount != 0 { - n += 1 + sovParams(uint64(m.MinFundingAmount)) - } - if m.MinFundingAmountPerBundle != 0 { - n += 1 + sovParams(uint64(m.MinFundingAmountPerBundle)) + if m.CoinDecimals != 0 { + n += 1 + sovParams(uint64(m.CoinDecimals)) } + l = m.MinFundingAmount.Size() + n += 1 + l + sovParams(uint64(l)) + l = m.MinFundingAmountPerBundle.Size() + n += 1 + l + sovParams(uint64(l)) l = m.CoinWeight.Size() n += 1 + l + sovParams(uint64(l)) return n @@ -398,9 +413,9 @@ func (m *WhitelistCoinEntry) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field MinFundingAmount", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field CoinDecimals", wireType) } - m.MinFundingAmount = 0 + m.CoinDecimals = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowParams @@ -410,16 +425,16 @@ func (m *WhitelistCoinEntry) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.MinFundingAmount |= uint64(b&0x7F) << shift + m.CoinDecimals |= uint32(b&0x7F) << shift if b < 0x80 { break } } case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field MinFundingAmountPerBundle", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MinFundingAmount", wireType) } - m.MinFundingAmountPerBundle = 0 + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowParams @@ -429,12 +444,61 @@ func (m *WhitelistCoinEntry) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.MinFundingAmountPerBundle |= uint64(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MinFundingAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MinFundingAmountPerBundle", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MinFundingAmountPerBundle.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field CoinWeight", wireType) } diff --git a/x/query/keeper/helper.go b/x/query/keeper/helper.go index 6703c771..a7c101ea 100644 --- a/x/query/keeper/helper.go +++ b/x/query/keeper/helper.go @@ -84,6 +84,8 @@ func (k Keeper) GetFullStaker(ctx sdk.Context, stakerAddress string) *types.Full func (k Keeper) GetPoolStatus(ctx sdk.Context, pool *pooltypes.Pool) pooltypes.PoolStatus { // Get the total and the highest delegation of a single validator in the pool totalDelegation, highestDelegation := k.delegationKeeper.GetTotalAndHighestDelegationOfPool(ctx, pool.Id) + maxVotingPower := k.poolKeeper.GetMaxVotingPowerPerPool(ctx) + maxDelegation := uint64(maxVotingPower.MulInt64(int64(totalDelegation)).TruncateInt64()) var poolStatus pooltypes.PoolStatus @@ -96,7 +98,7 @@ func (k Keeper) GetPoolStatus(ctx sdk.Context, pool *pooltypes.Pool) pooltypes.P poolStatus = pooltypes.POOL_STATUS_END_KEY_REACHED } else if totalDelegation < pool.MinDelegation { poolStatus = pooltypes.POOL_STATUS_NOT_ENOUGH_DELEGATION - } else if highestDelegation*2 > totalDelegation { + } else if highestDelegation > maxDelegation { poolStatus = pooltypes.POOL_STATUS_VOTING_POWER_TOO_HIGH } else if k.fundersKeeper.GetTotalActiveFunding(ctx, pool.Id).IsZero() { poolStatus = pooltypes.POOL_STATUS_NO_FUNDS diff --git a/x/stakers/keeper/msg_server_claim_commission_rewards_test.go b/x/stakers/keeper/msg_server_claim_commission_rewards_test.go index 227f9e65..67fed59d 100644 --- a/x/stakers/keeper/msg_server_claim_commission_rewards_test.go +++ b/x/stakers/keeper/msg_server_claim_commission_rewards_test.go @@ -52,26 +52,26 @@ var _ = Describe("msg_server_claim_commission_rewards.go", Ordered, func() { s.App().FundersKeeper.SetParams(s.Ctx(), funderstypes.NewParams([]*funderstypes.WhitelistCoinEntry{ { CoinDenom: globaltypes.Denom, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: uint64(amountPerBundle), + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewInt(amountPerBundle), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.A_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: uint64(amountPerBundle), + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewInt(amountPerBundle), CoinWeight: math.LegacyNewDec(1), }, { CoinDenom: i.B_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: uint64(amountPerBundle), + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewInt(amountPerBundle), CoinWeight: math.LegacyNewDec(2), }, { CoinDenom: i.C_DENOM, - MinFundingAmount: 10 * i.KYVE, - MinFundingAmountPerBundle: uint64(amountPerBundle), + MinFundingAmount: math.NewIntFromUint64(10 * i.KYVE), + MinFundingAmountPerBundle: math.NewInt(amountPerBundle), CoinWeight: math.LegacyNewDec(3), }, }, 20))