threshold-network / merkle-distribution

Threshold Network rewards generation and distribution
https://threshold.network
1 stars 6 forks source link

tBTC rewards miscalculation for stakes that starts a authorization decrease #108

Closed manumonti closed 7 months ago

manumonti commented 7 months ago

I have detected a bug when the tBTC rewards script is calculating the rewards for a specific period:

Context

To get the authorization history of each stake, the script fetches the authorization-related events from the tokenStaking contract:

https://github.com/threshold-network/merkle-distribution/blob/e3c621ccd05eacd7826dfac461198dbbf75abb43/src/scripts/tbtcv2-rewards/rewards.ts#L148-L178

The type of events that the script fetches are: AuthorizationIncreased and AuthorizationDecreaseApproved.

Additionally, if a stake starts the deauthorization process, an event of type AuthorizationDecreaseRequested is emitted. But these kinds of events are not considered by the script because if I understood correctly, the stake is eligible for rewards until the deauthorization is finished with an AuthorizationDecreaseApproved event.

The problem

If a stake started the deauthorization process during or after the distribution period, only AuthorizationDecreaseRequested event is emitted. So, for the script, authorization has remained the same since the start of the rewards period until now: the authorization will be retrieved by calling to tokenStaking.eligibleStake() function:

https://github.com/threshold-network/merkle-distribution/blob/e3c621ccd05eacd7826dfac461198dbbf75abb43/src/scripts/tbtcv2-rewards/rewards.ts#L571

The problem is that, apparently, during the deauthorization process (i.e. after AuthorizationDecreaseRequested and before AuthorizationDecreaseApproved events), this function returns the amount already.

Example

For the period Nov 1st to Nov 22nd, the stake 0x17eDe21b60c44A0139968E0d1D9a001D2bdC8f85 returns an authorization of 0, so it isn't eligible for rewards.

But the authorization at the start of the period and at the end of the period is the same and greater than 0:

at start: https://www.tdly.co/shared/simulation/f531cffc-a7af-4950-afa1-c91cf839198c at end: https://www.tdly.co/shared/simulation/51e6760c-fd3b-40fd-bdb1-22e0c371172d

These are the transactions in which an authorization decrease is requested, and executed after the rewards period:

https://etherscan.io/tx/0x355c9a3969526a7a4f68159de09abfde08064148bb281996353f6caf656d9c74 https://etherscan.io/tx/0xdecdd8723c4d7c94ccecd409038e6a17d346af4511774c21b450a001fbee8396

So, the script should return some rewards for this stake.