New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Malicious user can steal all assets in BondNFT #170
Comments
GalloDaSballo marked the issue as duplicate of #68 |
GalloDaSballo marked the issue as not a duplicate |
GalloDaSballo marked the issue as primary issue |
TriHaz marked the issue as sponsor confirmed |
The warden has shown how, due to an inconsistent implementation of Bond State change, how they could repeatedly claim rewards for an expired bond, stealing value from all other depositors. Because the findings doesn't just deny yield to others, but allows a single attacker to seize the majority of the yield rewards, leveraging a broken invariant, I agree with High Severity |
GalloDaSballo marked the issue as selected for report |
Mitigation: code-423n4/2022-12-tigris#2 (comment) |
Lines of code
https://github.com/code-423n4/2022-12-tigris/blob/588c84b7bb354d20cbca6034544c4faa46e6a80e/contracts/BondNFT.sol#L168-L187
Vulnerability details
Impact
Malicious user can drain all assets in BondNFT, and other users will lose their rewards.
Proof of Concept
When calling BondNFT.claim() for an expired bond, it will recalculate
accRewardsPerShare
. This is because the reward after theexpireEpoch
does not belong to that expired bond and needs to be redistributed to all other bonds.In the current implementation of BondNFT.claim(), it can be called repeatedly as long as the expired bond is not released.
According to the formula in the above code, we can find that although each subsequent
claim()
of the expired bond will transfer 0 reward, theaccRewardsPerShare
will be updated cumulatively.Thus, the pending rewards of all other users will increase every time the expired bond is
claim()
ed.A malicious user can exploit this vulnerability to steal all assets in BondNFT contract:
expireEpoch
Lock.claim(B1)
to increase rewards of B2 continuously, until the pending rewards of B2 approaches the total amount of asset in the contract.Lock.claim(B2)
to claim all pending rewards of B2.An example of such an attack:
Output:
Tools Used
VS Code
Recommended Mitigation Steps
I recommend that an expired bond should be forced to
release()
,claim()
an expired bond should revert.Sample code:
The text was updated successfully, but these errors were encountered: