Calculation of fees in the RockPaperScissors
contract leaves dust when _handleTie()
is called. In fact, 10% is taken from the pot for the admin and the rest is split between the players. This is because the division of the pot by 10% for the admin and potentially splitting an odd prize do not take into account the decimal precision of ETH.
This can lead to a situation where the contract has a small amount of ETH left over after the fees are taken. This dust can accumulate over time and lead to a significant amount of ETH being left.
PlayerA create a game with a bet = 0.043784470443721407 ether
and playerB joins the game with the same bet: pot = 0.087568940887442814 ether
.
Both players play the game and the game ends with a tie.
The contract takes 10% of the pot for the admin: fees = 0.008756894088744281 ether
.
The rest of the pot is split between the players: refundPerPlayer = 0.039406023399349266 ether
.
The contract returns 0.039406023399349266 ether
to each player, so the total pot minus the fees is 0.078812046798698532 ether
.
0.078812046798698532 ether + 0.008756894088744281 ether = 0.087568940887442813 ether
, which is not equal to the original pot of 0.087568940887442814 ether
.
The difference is 0.000000000000000001 ether
, which is the dust.
Foundry test:
Take into account the decimal precision of ETH when calculating fees and splitting the pot.
Consider making a common internal function to handle the fees calculation and splitting the pot. This way, you can ensure that the same logic is used in all cases and avoid any discrepancies. Could be useful for _finishGame()
and maybe fixing the unit tests would be great:
The tie-handling logic loses one wei due to integer division
The tie-handling logic loses one wei due to integer division
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.