Closed code423n4 closed 1 year ago
0xA5DF marked the issue as primary issue
I see this as an edge case of #976 . It could be solved by adding slippage protection.
Will add slippage protection to future versions.
luziusmeisser marked the issue as sponsor confirmed
hansfriese marked the issue as duplicate of #396
hansfriese marked the issue as duplicate of #396
hansfriese marked the issue as satisfactory
Lines of code
https://github.com/code-423n4/2023-04-frankencoin/blob/1022cb106919fba963a89205d3b90bf62543f68f/contracts/Equity.sol#L244-L247
Vulnerability details
minting in
onTokenTransfer
handles the caseequity <= amount
as the first deposit, minting it1000
shares no matter the amount ofZCHF
transferredThe issue is that there is another case scenario in which
equity <= amount
: if a loss happens and equity stands at a negative value (see the example given here).In such case, if
amount
is large enough to bring back equity above water here, it will result inequity <= amount
beingtrue
, minting the user only1000
shares.Impact
An innocent user calling
Equity.onTokenTransfer()
just after a huge equity loss - which triggeredFrankencoin.notifyLoss
, will get fewer shares than expected.Note that as the transactions can happen in the same block, there is nothing protecting users from this happening.
The big difference with this scenario is that the victim did not intend to do this - also, they will not be able to bootstrap the system after this because of the check line 311.
Proof Of Concept
Run the test
test_Audit_Equity_UnfairLoss
in the following gist: https://gist.github.com/joestakey/fbc954de53b7e018f5121212488e847crun it once as it is, this should result in:
Then toggle the block marked with
TOGGLE
on - which simulates a loss.This should result in:
The equity loss resulted in Charlie receiving less shares than expected
Tools Used
Manual Analysis
Mitigation
onTokenTransfer
should introduce aminSharesOut
parameter to protect users from this scenario.Users will be able to estimate the number of shares they would receive using
calculateShares()
, and use this as a basis for how many shares they allow to receive.