Incorrect calculation of rewards in the _farmPlots function results in users getting wrong/huge rewards or causing munchables to always get stuck with overflow errors #218
The original design intent was to adjust the schnibblesTotal reward by 5% or 10% based on the realm compatibility rules, thus preventing users from placing munchables onto realms different from the munchables' properties. However, incorrect math can cause schnibblesTotal to be inconsistent with this rule, or even become negative. This can cause users to receive incorrect rewards, even break the game ecosystem due to type conversion resulting in huge rewards, or munchables always get stuck due to overflow errors.
Proof of Concept
The reward calculation in the _farmPlot function code snippet:
It got its arithmetic priorities in the wrong order, and for positive finalBonus it miscalculated the rewards.
For a negative finalBonus, there are two scenarios:
Landlord Locked Up Funds Before LandManager Contract Deployment
There are many landlords have already locked funds because the LockManager contract is deployed on the mainnet and can be found in deployment.json
Upon deploying the LandManager contract, these landlords will have a zero tax rate if they choose not to call triggerPlotMetadata to update plot metadata.
A malicious user could pre-lock funds and, after deploying the LandManager contract, have another account holding the NFT. They could then place a munchableNFT with different realm attributes to occupy the zero-tax plot.
Now give a example: If schnibblesTotal is 1000 and finalBonus is -10, the calculation results in -90. Casting -90 to uint256 yields a large number.
and next calculation:
Since _toiler.latestTaxRate is 0, it does not overflow, allowing the user to get a huge reward.
Landlord Locked Up Funds After LandManager Contract Deployment
After the LandManager contract is deployed, any newly locked funds may result in users not being able to farm due to overflow errors in the reward calculation, and causing munchables to always be stuck.
Poc Test
To facilitate the testing of the first scenario, you need to comment out this line of the AccountManager contract (this line of code is an update to adapt to the landmanager contract, which will not exist in the onchain contract), or make a mock function. I chose the former.
Lines of code
https://github.com/code-423n4/2024-07-munchables/blob/main/src/managers/LandManager.sol#L270-L289 https://github.com/code-423n4/2024-07-munchables/blob/main/deployments/cache/mainnet/deployment-2024-06-01T21-33-57.416Z.json#L72-L77 https://github.com/code-423n4/2024-07-munchables/blob/main/deployments/utils/consts.ts#L129-L131
Vulnerability details
Impact
The original design intent was to adjust the schnibblesTotal reward by 5% or 10% based on the realm compatibility rules, thus preventing users from placing munchables onto realms different from the munchables' properties. However, incorrect math can cause schnibblesTotal to be inconsistent with this rule, or even become negative. This can cause users to receive incorrect rewards, even break the game ecosystem due to type conversion resulting in huge rewards, or munchables always get stuck due to overflow errors.
Proof of Concept
The reward calculation in the
_farmPlot
function code snippet:the schnibblesTotal will be affected by the finalbonus calculated by REALM_BONUSES and RARITY_BONUSES.
For specific rules, see the configuration parameters of the deployment script and the documentation. https://munchables.gitbook.io/munchables/explorers-guide/glossary/schnibble-multipliers
the key point is REALM_BONUSES:
when the user putting munchables onto realms that are not the same as the munchables' property, the finalBonus will be negtive, for example -10.
now check this code snippet:
It got its arithmetic priorities in the wrong order, and for positive finalBonus it miscalculated the rewards.
For a negative finalBonus, there are two scenarios:
LockManager
contract is deployed on the mainnet and can be found in deployment.jsonSince
_toiler.latestTaxRate
is 0, it does not overflow, allowing the user to get a huge reward.Poc Test
To facilitate the testing of the first scenario, you need to comment out this line of the AccountManager contract (this line of code is an update to adapt to the landmanager contract, which will not exist in the onchain contract), or make a mock function. I chose the former.
the poc file:
and get the output:
For the second test, the commented code is reverted back and run the poc file and will get an overflow error.
Tools Used
Manual
Recommended Mitigation Steps
Assessed type
Math