Skip to content

Commit 33c4113

Browse files
akremstudydanflo27claude
authored
Fix dispute fee distribution for multi rounds (#1030)
* fix: refund dispute fees from round 1 amount, burn later round fees * Fix/dispute multiround review findings (#1032) * test: clean up multi-round dispute integration tests Dedupe the multi-round dispute test scaffolding ahead of the multi-round fee fixes: fold the from-bond round-1 starter into a payFromBond param, route round-1 setup through markRoundUnresolved, add proposeRound/fundedDisputer/seedTipper helpers for the repeated proposal and account blocks, and make setupDisputedReporter delegate to the multi-reporter variant. Replace the tipper validator account with a plain funded account (only its tips carry vote power), make vote execution deterministic instead of conditional, and drop debug prints and review-process commentary from test comments. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: do not track later-round dispute fees as refundable first-round stake AddDisputeRound paid escalation-round fees with isFirstRound=true, so a later round paid from bond appended its stake origins to the FeePaidFromStake tracker under the dispute's shared hash id. FeeRefund distributes the refundable round-1 fee pro-rata over that tracker, so a later-round bond payer could siphon part of the round-1 payer's refund (or leave a stale tracker when round 1 was account-funded). Later-round fees are fully consumed and never refunded, so pass isFirstRound=false. Adds regression tests covering account-funded and bond-funded round 1, the refund split after an INVALID resolution, and max-round escalation where every later round pays from bond. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: burn later-round fee pool when no claim-eligible voters exist ExecuteVote reserved half of BurnAmount as a voter reward whenever any vote group participated, including the team. CalculateReward only pays user and reporter voters, so a dispute resolved by team vote alone reserved an unclaimable balance in the dispute module forever; with later-round fees now accumulating into BurnAmount, that stranded amount grows with every escalation round. Gate the voter reward on claim-eligible participation instead: rename GetSumOfAllGroupVotesAllRounds to GetSumOfUserAndReporterVotesAllRounds and drop team votes from the sum, so team-only resolutions burn the entire consumed fee pool. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: resolve first-round fee payer in ClaimableDisputeRewards DisputeFeePayer records are only ever written under the round-1 dispute id, and WithdrawFeeRefund resolves PrevDisputeIds[0] before loading them. The ClaimableDisputeRewards query looked the payer up under the requested dispute id instead, so querying the final resolved round of a multi-round dispute reported a zero fee refund that the transaction path would actually pay. Resolve the first-round id in the query the same way the transaction does. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: report previous-round voter rewards in ClaimableDisputeRewards The query only called CalculateReward when the address had a Voter record under the requested dispute id, but ClaimReward has no such gate: CalculateReward scans every round via PrevDisputeIds, so an address that voted only in an earlier round of a multi-round dispute has a real claim that the query reported as zero. Use the final-round Voter record solely for the RewardClaimed flag (matching where ClaimReward stores it) and compute the reward regardless; CalculateReward already yields zero for non-participants. Includes a combined regression test where one address holds both a round-1 fee refund and a previous-round-only voter reward, queried by the final dispute id and then withdrawn through both transaction paths. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: correct round-1 fee split in ADR1011 and trim blank line at EOF Round 1's 5% does not all go to the burn pool: execution burns half and reserves half as the voter reward, and burns all of it when no users or reporters voted. Also remove the trailing blank line flagged by git diff --check. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: preserve previous-round voter rewards --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Dan F <florentinodc@outlook.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 660fa54 commit 33c4113

12 files changed

Lines changed: 782 additions & 104 deletions
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# ADR 1011: Dispute round fees
2+
3+
## Authors
4+
5+
@akrem
6+
7+
## Changelog
8+
9+
- 2026-06-10: initial version
10+
11+
## Context
12+
13+
A dispute can go through more than one round. Round 1 is the main dispute. If a round does not reach quorum someone can push it to another round by paying a fee, and that fee doubles every round. The chain caps this at 5 rounds.
14+
15+
This ADR is about what the fee is for each round and what happens to it.
16+
17+
Round 1's fee is refundable. You pay the dispute fee, which is the same as the slash amount. If the dispute resolves support you get your fee back minus a small burn and you also get the reporter's slashed tokens. If it resolves invalid you just get your fee back minus the burn. If it resolves against you the reporter gets your fee. So the round 1 fee comes back to you unless you lose the dispute.
18+
19+
Rounds 2 and up are different. The fee you pay to start another round is not refundable to anyone. It is a burn. The whole fee gets consumed, half of it is actually burned and half goes to the voters of the dispute (if no users or reporters voted in any round, the voter half is burned as well). The only thing that is ever refundable is the round 1 fee.
20+
21+
The fee for each extra round starts at 5% of the slash amount and doubles each round. So round 2 is 10% of the slash, round 3 is 20%, round 4 is 40%, round 5 is 80%, capped at 100%. It gets expensive fast on purpose.
22+
23+
Why it works this way:
24+
25+
If a dispute is extended to multiple rounds, the escalating fee does two things:
26+
27+
1. The doubling fee keeps anyone from dragging a dispute out forever. Every extra round costs a lot more than the last one.
28+
2. Half of the round fee goes to the voters to incentivize them to vote on the extra rounds. The fee grows as the rounds go up, so the reward for voting grows with it. Burning all of it instead would just destroy the tokens.
29+
30+
The round 1 fee stays separate from all of this. It is the part that is actually at risk between the disputer and the reporter, and the final round decides what happens to it. The extra round fees are just the cost of asking for another vote.
31+
32+
33+
## Issues / Notes on Implementation
34+
35+
The fee schedule for reference, with s as the slash amount (5% is s/20):
36+
37+
- Round 1: pay s. This is the refundable fee. 5% is consumed (half burned, half reserved as the voter reward; all of it burned if no users or reporters voted), 95% is refundable.
38+
- Round 2: pay s/10 (10% of s). Fully consumed.
39+
- Round 3: pay s/5 (20%). Fully consumed.
40+
- Round 4: pay 2s/5 (40%). Fully consumed.
41+
- Round 5: pay 4s/5 (80%). Fully consumed.
42+
43+
Disputes are capped at 5 rounds.

tests/integration/dispute_keeper_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,7 +1154,7 @@ func (s *IntegrationTestSuite) TestDisputeFiveRounds5thRdNewPayer() {
11541154
s.NoError(err)
11551155
s.Equal(types.Resolved, dispute.DisputeStatus)
11561156
fmt.Println("DISPUTE FEE TOTAL", dispute.FeeTotal.String())
1157-
expectedClaimAmount := dispute.FeeTotal.MulRaw(95).QuoRaw(100)
1157+
expectedClaimAmount := dispute.DisputeFee.MulRaw(95).QuoRaw(100)
11581158
fmt.Println("EXPECTED CLAIM AMOUNT", expectedClaimAmount)
11591159

11601160
_, err = s.Setup.App.BeginBlocker(s.Setup.Ctx)
@@ -1535,7 +1535,7 @@ func (s *IntegrationTestSuite) TestDisputeFiveRounds1Payer() {
15351535
s.NoError(err)
15361536
s.Equal(types.Resolved, dispute.DisputeStatus)
15371537
fmt.Println("DISPUTE FEE TOTAL", dispute.FeeTotal.String())
1538-
expectedClaimAmount := dispute.FeeTotal.MulRaw(95).QuoRaw(100)
1538+
expectedClaimAmount := dispute.SlashAmount.MulRaw(95).QuoRaw(100)
15391539
fmt.Println("EXPECTED CLAIM AMOUNT", expectedClaimAmount)
15401540

15411541
_, err = s.Setup.App.BeginBlocker(s.Setup.Ctx)
@@ -1945,7 +1945,7 @@ func (s *IntegrationTestSuite) TestDisputeFiveRoundsTwoFeePayers() {
19451945
s.NoError(err)
19461946
s.Equal(types.Resolved, dispute.DisputeStatus)
19471947
fmt.Println("DISPUTE FEE TOTAL", dispute.FeeTotal.String())
1948-
expectedClaimAmountTotal := dispute.FeeTotal.MulRaw(95).QuoRaw(100)
1948+
expectedClaimAmountTotal := dispute.DisputeFee.MulRaw(95).QuoRaw(100)
19491949
fmt.Println("EXPECTED CLAIM AMOUNT TOTAL", expectedClaimAmountTotal)
19501950

19511951
_, err = s.Setup.App.BeginBlocker(s.Setup.Ctx)

tests/integration/dispute_multiround_support_test.go

Lines changed: 625 additions & 0 deletions
Large diffs are not rendered by default.

x/dispute/keeper/claim_reward.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,16 @@ func (k Keeper) CalculateReward(ctx sdk.Context, addr sdk.AccAddress, id uint64)
7979
globalUserPower := math.ZeroInt()
8080

8181
for _, pastId := range dispute.PrevDisputeIds {
82+
// Get global vote counts for the past dispute. A missing row means that
83+
// round had no user/reporter votes to reward.
84+
pastVoteCounts, err := k.VoteCountsByGroup.Get(ctx, pastId)
85+
if err != nil {
86+
if errors.Is(err, collections.ErrNotFound) {
87+
continue
88+
}
89+
return math.Int{}, err
90+
}
91+
8292
pastVoterInfo, err := k.Voter.Get(ctx, collections.Join(pastId, addr.Bytes()))
8393
if err == nil {
8494
// Voter info exists for this past dispute
@@ -88,13 +98,10 @@ func (k Keeper) CalculateReward(ctx sdk.Context, addr sdk.AccAddress, id uint64)
8898
return math.Int{}, err
8999
}
90100
addrUserPower = addrUserPower.Add(userTips)
91-
}
92-
93-
// Get global vote counts for the past dispute
94-
pastVoteCounts, err := k.VoteCountsByGroup.Get(ctx, pastId)
95-
if err != nil {
101+
} else if !errors.Is(err, collections.ErrNotFound) {
96102
return math.Int{}, err
97103
}
104+
98105
// Add up the global power for each group
99106
globalReporterPower = globalReporterPower.Add(math.NewIntFromUint64(pastVoteCounts.Reporters.Support)).
100107
Add(math.NewIntFromUint64(pastVoteCounts.Reporters.Against)).Add(math.NewIntFromUint64(pastVoteCounts.Reporters.Invalid))

x/dispute/keeper/dispute.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,9 @@ func (k Keeper) AddDisputeRound(ctx sdk.Context, sender sdk.AccAddress, dispute
258258
msg.Fee.Amount = roundFee
259259
}
260260

261-
// Pay the dispute fee
262-
if err := k.PayDisputeFee(ctx, sender, msg.Fee, msg.PayFromBond, dispute.HashId, true); err != nil {
261+
// Pay the dispute fee. Later-round fees are fully consumed (never refunded), so they
262+
// must not be tracked as refundable first-round stake.
263+
if err := k.PayDisputeFee(ctx, sender, msg.Fee, msg.PayFromBond, dispute.HashId, false); err != nil {
263264
return err
264265
}
265266

@@ -268,7 +269,8 @@ func (k Keeper) AddDisputeRound(ctx sdk.Context, sender sdk.AccAddress, dispute
268269
}
269270

270271
prevDisputeId := dispute.DisputeId
271-
dispute.BurnAmount = dispute.BurnAmount.Add(fivePercent) // burnAmt = 5 % of fee total
272+
dispute.BurnAmount = dispute.BurnAmount.Add(roundFee)
273+
// FeeTotal is informationl only, tracks total fees paid across rounds.
272274
dispute.FeeTotal = dispute.FeeTotal.Add(msg.Fee.Amount)
273275
disputeId := k.NextDisputeId(ctx)
274276
dispute.DisputeId = disputeId

x/dispute/keeper/execute.go

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
layertypes "github.com/tellor-io/layer/types"
99
"github.com/tellor-io/layer/x/dispute/types"
1010

11+
"cosmossdk.io/collections"
1112
"cosmossdk.io/math"
1213

1314
sdk "github.com/cosmos/cosmos-sdk/types"
@@ -48,17 +49,20 @@ func (k Keeper) ExecuteVote(ctx context.Context, id uint64) error {
4849
return errors.New("vote already executed")
4950
}
5051

51-
// the burnAmount starts at %5 of disputeFee, half of which is burned and the other half is distributed to the voters
52+
// the burnAmount is round 1's 5% of the dispute fee plus all later-round fees, half
53+
// of which is burned and the other half is distributed to the voters
5254
disputeBurnAmountDec := math.LegacyNewDecFromInt(dispute.BurnAmount)
5355
halfBurnAmountDec := disputeBurnAmountDec.Quo(math.LegacyNewDec(2))
5456
halfBurnAmount := halfBurnAmountDec.TruncateInt()
5557
voterReward := halfBurnAmount
56-
totalVoterPower, err := k.GetSumOfAllGroupVotesAllRounds(ctx, id)
58+
// only user and reporter votes can claim through CalculateReward; team votes decide
59+
// outcomes but earn nothing, so they must not cause a voter reward to be reserved
60+
totalVoterPower, err := k.GetSumOfUserAndReporterVotesAllRounds(ctx, id)
5761
if err != nil {
5862
return err
5963
}
6064
if totalVoterPower.IsZero() {
61-
// if no voters, burn the entire burnAmount
65+
// if no claim-eligible voters, burn the entire burnAmount
6266
halfBurnAmount = dispute.BurnAmount
6367
// non voters get nothing
6468
voterReward = math.ZeroInt()
@@ -153,8 +157,8 @@ func (k Keeper) RefundFailedDisputeFee(ctx context.Context, feePayer sdk.AccAddr
153157
return k.ReturnFeetoStake(ctx, hashId, fee)
154158
}
155159

156-
func (k Keeper) RefundDisputeFee(ctx context.Context, feePayer sdk.AccAddress, payerInfo types.PayerInfo, disputeFeeTotal math.Int, hashId []byte, slashAmt math.Int) (math.Int, error) {
157-
amtFixed6, remainder := CalculateRefundAmount(payerInfo.Amount, slashAmt, disputeFeeTotal)
160+
func (k Keeper) RefundDisputeFee(ctx context.Context, feePayer sdk.AccAddress, payerInfo types.PayerInfo, totalFeeRd1 math.Int, hashId []byte) (math.Int, error) {
161+
amtFixed6, remainder := CalculateRefundAmount(payerInfo.Amount, totalFeeRd1)
158162

159163
coins := sdk.NewCoins(sdk.NewCoin(layertypes.BondDenom, amtFixed6))
160164
if !payerInfo.FromBond {
@@ -173,46 +177,48 @@ func (k Keeper) RewardReporterBondToFeePayers(ctx context.Context, feePayer sdk.
173177
return remainder, k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, stakingtypes.BondedPoolName, sdk.NewCoins(sdk.NewCoin(layertypes.BondDenom, amtFixed6)))
174178
}
175179

176-
func (k Keeper) GetSumOfAllGroupVotesAllRounds(ctx context.Context, id uint64) (math.Int, error) {
180+
// GetSumOfUserAndReporterVotesAllRounds sums claim-eligible (user and reporter) vote
181+
// power across all rounds of a dispute. Team votes are excluded because they cannot
182+
// claim voter rewards.
183+
func (k Keeper) GetSumOfUserAndReporterVotesAllRounds(ctx context.Context, id uint64) (math.Int, error) {
177184
dispute, err := k.Disputes.Get(ctx, id)
178185
if err != nil {
179186
return math.Int{}, err
180187
}
181188

182189
sumUsers := uint64(0)
183190
sumReporters := uint64(0)
184-
sumTeam := uint64(0)
185191

186192
// process vote counts function
187193
processVoteCounts := func(voteCounts types.StakeholderVoteCounts) {
188194
sumUsers += voteCounts.Users.Support + voteCounts.Users.Against + voteCounts.Users.Invalid
189195
sumReporters += voteCounts.Reporters.Support + voteCounts.Reporters.Against + voteCounts.Reporters.Invalid
190-
sumTeam += voteCounts.Team.Support + voteCounts.Team.Against + voteCounts.Team.Invalid
191196
}
192197

193198
// process current dispute
194199
voteCounts, err := k.VoteCountsByGroup.Get(ctx, id)
195200
if err != nil {
196-
return math.ZeroInt(), nil
201+
if !errors.Is(err, collections.ErrNotFound) {
202+
return math.Int{}, err
203+
}
204+
voteCounts = types.StakeholderVoteCounts{}
197205
}
198206
processVoteCounts(voteCounts)
199207

200208
// process previous disputes
201209
for _, roundId := range dispute.PrevDisputeIds {
202210
voteCounts, err := k.VoteCountsByGroup.Get(ctx, roundId)
203211
if err != nil {
204-
voteCounts = types.StakeholderVoteCounts{
205-
Users: types.VoteCounts{Support: 0, Against: 0, Invalid: 0},
206-
Reporters: types.VoteCounts{Support: 0, Against: 0, Invalid: 0},
207-
Team: types.VoteCounts{Support: 0, Against: 0, Invalid: 0},
212+
if !errors.Is(err, collections.ErrNotFound) {
213+
return math.Int{}, err
208214
}
215+
voteCounts = types.StakeholderVoteCounts{}
209216
}
210217
processVoteCounts(voteCounts)
211218
}
212219

213220
totalSum := math.NewInt(int64(sumUsers)).
214-
Add(math.NewInt(int64(sumReporters))).
215-
Add(math.NewInt(int64(sumTeam)))
221+
Add(math.NewInt(int64(sumReporters)))
216222

217223
return totalSum, nil
218224
}

x/dispute/keeper/execute_test.go

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,12 @@ func (k *KeeperTestSuite) TestRefundDisputeFee() {
9393

9494
k.reporterKeeper.On("FeeRefund", k.ctx, []byte("hash"), math.NewInt(760)).Return(nil)
9595
k.bankKeeper.On("SendCoinsFromModuleToModule", k.ctx, types.ModuleName, "bonded_tokens_pool", sdk.NewCoins(sdk.NewCoin("loya", math.NewInt(760)))).Return(nil)
96-
dust, err := k.disputeKeeper.RefundDisputeFee(k.ctx, feepayer1, feePayers[0], math.NewInt(1000), []byte("hash"), math.NewInt(1000))
96+
dust, err := k.disputeKeeper.RefundDisputeFee(k.ctx, feepayer1, feePayers[0], math.NewInt(1000), []byte("hash"))
9797
k.NoError(err)
9898
k.True(math.ZeroInt().Equal(dust))
9999

100100
k.bankKeeper.On("SendCoinsFromModuleToAccount", k.ctx, types.ModuleName, feepayer2, sdk.NewCoins(sdk.NewCoin("loya", math.NewInt(190)))).Return(nil)
101-
dust, err = k.disputeKeeper.RefundDisputeFee(k.ctx, feepayer2, feePayers[1], math.NewInt(1000), []byte("hash"), math.NewInt(1000))
101+
dust, err = k.disputeKeeper.RefundDisputeFee(k.ctx, feepayer2, feePayers[1], math.NewInt(1000), []byte("hash"))
102102
k.NoError(err)
103103
k.True(math.ZeroInt().Equal(dust))
104104
}
@@ -155,23 +155,22 @@ func (k *KeeperTestSuite) TestRewardReporterBondToFeePayers() {
155155
k.Equal(shareFixed12.Mod(layertypes.PowerReduction), dust)
156156
}
157157

158-
func (k *KeeperTestSuite) TestGetSumOfAllGroupVotesAllRounds() {
158+
func (k *KeeperTestSuite) TestGetSumOfUserAndReporterVotesAllRounds() {
159159
k.ctx = k.ctx.WithBlockTime(time.Now())
160160
dispute := k.dispute(k.ctx)
161161
k.NoError(k.disputeKeeper.Disputes.Set(k.ctx, dispute.DisputeId, dispute))
162162

163-
// set vote counts for current dispute
163+
// set vote counts for current dispute; team votes are set but must not be counted
164164
currentVoteCounts := types.StakeholderVoteCounts{
165165
Users: types.VoteCounts{Support: 10, Against: 5, Invalid: 2}, // 17
166166
Reporters: types.VoteCounts{Support: 8, Against: 3, Invalid: 1}, // 12
167-
// Tokenholders: types.VoteCounts{Support: 15, Against: 7, Invalid: 3}, // 25
168-
Team: types.VoteCounts{Support: 5, Against: 2, Invalid: 1}, // 8 total=37
167+
Team: types.VoteCounts{Support: 5, Against: 2, Invalid: 1}, // excluded, total=29
169168
}
170169
k.NoError(k.disputeKeeper.VoteCountsByGroup.Set(k.ctx, dispute.DisputeId, currentVoteCounts))
171170

172171
// test no previous disputes
173-
expectedTotalSum := math.NewInt(37)
174-
totalSum, err := k.disputeKeeper.GetSumOfAllGroupVotesAllRounds(k.ctx, dispute.DisputeId)
172+
expectedTotalSum := math.NewInt(29)
173+
totalSum, err := k.disputeKeeper.GetSumOfUserAndReporterVotesAllRounds(k.ctx, dispute.DisputeId)
175174
k.NoError(err)
176175
k.True(expectedTotalSum.Equal(totalSum))
177176

@@ -181,20 +180,17 @@ func (k *KeeperTestSuite) TestGetSumOfAllGroupVotesAllRounds() {
181180
{
182181
Users: types.VoteCounts{Support: 5, Against: 3, Invalid: 1}, // 9
183182
Reporters: types.VoteCounts{Support: 4, Against: 2, Invalid: 0}, // 6
184-
// Tokenholders: types.VoteCounts{Support: 8, Against: 4, Invalid: 2}, // 14
185-
Team: types.VoteCounts{Support: 3, Against: 1, Invalid: 0}, // 4 total=19
183+
Team: types.VoteCounts{Support: 3, Against: 1, Invalid: 0}, // excluded, total=15
186184
},
187185
{
188186
Users: types.VoteCounts{Support: 7, Against: 4, Invalid: 2}, // 13
189187
Reporters: types.VoteCounts{Support: 6, Against: 3, Invalid: 1}, // 10
190-
// Tokenholders: types.VoteCounts{Support: 10, Against: 5, Invalid: 2}, // 17
191-
Team: types.VoteCounts{Support: 4, Against: 2, Invalid: 1}, // 7 total=30
188+
Team: types.VoteCounts{Support: 4, Against: 2, Invalid: 1}, // excluded, total=23
192189
},
193190
{
194191
Users: types.VoteCounts{Support: 3, Against: 2, Invalid: 0}, // 5
195192
Reporters: types.VoteCounts{Support: 2, Against: 1, Invalid: 0}, // 3
196-
// Tokenholders: types.VoteCounts{Support: 5, Against: 3, Invalid: 1}, // 9
197-
Team: types.VoteCounts{Support: 2, Against: 1, Invalid: 0}, // 3 total=11
193+
Team: types.VoteCounts{Support: 2, Against: 1, Invalid: 0}, // excluded, total=8
198194
},
199195
}
200196

@@ -205,15 +201,15 @@ func (k *KeeperTestSuite) TestGetSumOfAllGroupVotesAllRounds() {
205201

206202
k.NoError(k.disputeKeeper.Disputes.Set(k.ctx, dispute.DisputeId, dispute))
207203

208-
// Calculate the expected total sum
204+
// Calculate the expected total sum (team votes excluded)
209205
expectedTotalSum = math.NewInt(0).
210-
Add(math.NewInt(int64(17 + 12 + 8))). // Current dispute
211-
Add(math.NewInt(int64(9 + 6 + 4))). // Previous dispute 1
212-
Add(math.NewInt(int64(13 + 10 + 7))). // Previous dispute 2
213-
Add(math.NewInt(int64(5 + 3 + 3))) // Previous dispute 3
206+
Add(math.NewInt(int64(17 + 12))). // Current dispute
207+
Add(math.NewInt(int64(9 + 6))). // Previous dispute 1
208+
Add(math.NewInt(int64(13 + 10))). // Previous dispute 2
209+
Add(math.NewInt(int64(5 + 3))) // Previous dispute 3
214210

215211
// Call the function and check the result
216-
totalSum, err = k.disputeKeeper.GetSumOfAllGroupVotesAllRounds(k.ctx, dispute.DisputeId)
212+
totalSum, err = k.disputeKeeper.GetSumOfUserAndReporterVotesAllRounds(k.ctx, dispute.DisputeId)
217213
k.NoError(err)
218214
k.True(expectedTotalSum.Equal(totalSum))
219215
}

x/dispute/keeper/math_utils.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,20 @@ import (
88

99
// CalculateRefundAmount calculates the amount of the fee to be refunded to the payer
1010
// returns the amount to be refunded (amtFixed6) and the remainder (dust)
11-
func CalculateRefundAmount(payerFee, totalFeeRd1, disputeFeeTotal math.Int) (math.Int, math.Int) {
11+
func CalculateRefundAmount(payerFee, totalFeeRd1 math.Int) (math.Int, math.Int) {
1212
payerFeeDec := payerFee.ToLegacyDec()
1313
totalFeeRd1Dec := math.LegacyNewDecFromInt(totalFeeRd1)
1414

15-
// fivePercent = disputeFeeTotal / 20
16-
fivePercentDec := disputeFeeTotal.ToLegacyDec().Quo(math.LegacyNewDec(20))
15+
// fivePercent = totalFeeRd1 / 20
16+
fivePercentDec := totalFeeRd1.ToLegacyDec().Quo(math.LegacyNewDec(20))
1717
fivePercent := fivePercentDec.TruncateInt()
1818

19-
// totalFeeMinusBurn = disputeFeeTotal - fivePercent
20-
totalFeeMinusBurnDec := disputeFeeTotal.Sub(fivePercent).ToLegacyDec()
19+
// totalFeeMinusBurn = totalFeeRd1 - fivePercent
20+
totalFeeMinusBurnDec := totalFeeRd1.Sub(fivePercent).ToLegacyDec()
2121

2222
powerReductionDec := math.LegacyNewDecFromInt(layertypes.PowerReduction)
2323

24-
// (fee paid in rd1 / total fee rd 1) * (total fee all rounds - burn)
24+
// (payerFee / totalFeeRd1) * (totalFeeRd1 - burn)
2525
// result scaled by PowerReduction
2626
amtFixed12Dec := payerFeeDec.Mul(totalFeeMinusBurnDec).Mul(powerReductionDec).Quo(totalFeeRd1Dec)
2727

0 commit comments

Comments
 (0)