Open c4-bot-8 opened 6 months ago
jhsagd76 marked the issue as satisfactory
jhsagd76 marked the issue as duplicate of #68
jhsagd76 marked the issue as not a duplicate
jhsagd76 marked the issue as primary issue
jhsagd76 marked the issue as selected for report
Per request from the judge @jhsagd76 here, updating the labels on this issue accordingly.
Lines of code
https://github.com/ArenaX-Labs/2024-02-ai-arena-mitigation/blob/setUpAirdrop-mitigation/src/FighterFarm.sol#L412-L436
Vulnerability details
Impact
Each
fighter
has a specific number of max reRolls, according tofighterType
. This means that the owner of thefighter
can callFighterFarm.reRoll()
at mostmaxRerollsAllowed
times, in order to obtain better fighter's attributes.We want to underline three aspects:
FighterFarm.reRoll()
operation has a cost in NRNnumRerolls
of a specificfighter
is not reset when it is transfereddna
is the only value used to computefighter
's traits. After mitigation,dna
depends just ontokenId
andnumRerolls[tokenId]
Because the reasons above, the owner of a
fighter
can always forecast what is the best number ofreRolls
. So, a cunning player should always improve itsfighter
's traits using the right number ofreRolls
. For this reason, we could expect that allfighters
will be reRolled until they reach the best number ofreRolls
. Furthermore, a malicious player can wait for the righttokenId
which can be used inreRoll
operation to obtain a very rare fighter.Remaining reRolls of a fighter don't increase its value
We asked in a private thread a clarification on the
FighterFarm.reRoll()
mechanism. This was the answer:While this was true before the mitigation, now the
dna
doesn't depend onmsg.sender
anymore. This means that the outcomes ofreRoll
operations made by the seller is the same of the outcomes obtained by the buyer. If they are both cunning players, they know before the transfer if thatfighter
would improve usingFighterFarm.reRoll()
operation or not. We want to underline that this mechanism strongly changes after the mitigation. As long as the outcome ofreRoll
operation depended onmsg.sender
, buying afighter
with remainingreRoll
operations made sense, because buyerreRoll
operations would have different outcome then the seller ones.After mitigation, seller and buyer can reach the same rare attributes. They both should be aware on the best outcome of
reRoll
operation. If not, it could happen because one or both of them are not cunning: the transfer could be not fair, impacting the game and the market.So, after mitigation, the
reRoll
operation appears as a pretense to pay NRNs. Its initial aim is lost.The only right thing to do is to reach the best
numRerolls
for eachfighter
As we said above, remaining reRolls of a fighter don't increase its market value. So, why a player should decide to not perform
reRoll
operations until reaching the best attributes combination? In this way, each player is forced to use NRNs to reach the best combination, because it doens't make sense to have a non-optimalfighter
: it hasn't more market value and it can become a betterfighter
for sure.A malicious player could wait the right
tokenId
to mint itsfighter
andreRoll
itA malicious player could wait to redeem his/her mint pass until he can obtain the wanted
tokenId
. This can be done because that player has foreseen that the wantedtokenId
combined with a specificnumRerolls
permit obtaining a very rarefighter
.Conclusion
Now, the
reRoll
operation seems useless. It can be used only to have different battle traits (weight and element). So we proposereRoll
modifies just the battle attributes.If somebody would sell his/her
fighter
, remainingnumRerolls
doesn't influence thefighter
value. Before mitigation, there was the possibility that a new player with the rightmsg.sender
would obtain better attrbutes for afighter
. Now, all players can obtain the same and foreseenable outcome fromreRoll
operations. Furthermore, now malicious players have the possibility to precomputedna
despite theirmsg.sender
and thus they can createfighter
with wanted rare attributes.Proof of concept
This is the mitigated FighterFarm.reRoll() operation:
The
dna
is computed at line FighterFarm.sol#L424:It depends just on
tokenId
, which never change, andnumRerolls[tokenId]
, which can change only usingFighterFarm.reRoll()
operation.Let's
maxRerollsAllowed[fighterType] = 10
. This means this fighter can be rerolled 10 times. We can forecast thedna
results for each of 10 reroll operations. For example, we forecast that the 5threRolled
operation will reach the best attributes combination. So, we know before the firstreRoll
operation that it not makes sense to perform more than 5reRolls
.If this
fighter
can not reach a good attributes combination, we could try to sell it, hoping we find a naive buyer, with allnumRerolls
available. On the other hand, if thisfighter
can reach a good attributes combination, we could make 5reRolls
, obtain the optimal attributes combination and use it in battles; or we could sell it, even before use 5reRolls
, because the reachable optimal attributes combination can be forecast by everyone, and it becomes an intrinsic value of thefighter
Tools Used
Visual inspection
Recommended Mitigation Steps
The issue relies on the pseudorandom mechanism. It is impossible to build a pseudorandom public mechanism that can't be forecasted. Before the mitigation, an external source could be exploited to obtain the wanted
reRoll
outcomes. Now, the best outcome is intrinsic infighter
. Furthermore, a malicious player could still exploit thetokenId
to obtain the wantedreRoll
. We strongly suggest to use an external oracle or to addblock.timestamp
to the computation ofdna
, to make a bit harder to forecast outcome attributes.Assessed type
Other