Closed code423n4 closed 2 years ago
I think there should never be an instance where there is dust in allowance.
When NotionalTradeModule._approve()
is called, setToken
(owner) gives _maxAssetAmount
of allowance to the fCashPosition
(spender) for _sendToken
.
When NotionalTradeModule._mint()
is called, either wfCashLogic.mintViaAsset
or wfCashLogic.mintViaUnderlying
functions is executed. These functions will do safeTransferFrom
(located here a, b) where owner is the setToken
, spender is the fCashPosition
and amount is _maxAssetAmount
I think this is a duplicate of: https://github.com/code-423n4/2022-06-notional-coop-findings/issues/221
Consider with #80
Lines of code
https://github.com/code-423n4/2022-06-notional-coop/blob/6f8c325f604e2576e2fe257b6b57892ca181509a/index-coop-notional-trade-module/contracts/protocol/modules/v1/NotionalTradeModule.sol#L490-L505
Vulnerability details
Impact
most of the
token
s won't allow to callapprove()
function when the current allowance is not0
. for exampleopenzeppelin
is like this which is mostly used by protocols. in_approve()
ofNotionalTradeModule
, contract don't first set approve value to0
and tries to set it to_maxAssetAmount
in one call. so if there were some dust left in that allowance that call will revert and whole transaction will fail. because_mintFCashPosition()
uses_approve()
somintFCashPosition()
functionality of contract won't work. There is high chance that could make dust in allowance. because in mintingwfcash
the exact amount ofunderlying
token is clear andwfcash
returns extra amount ofunderlying
orasset
token. so if inwfcash
logic, code don't transfer the extra amount in the first place so that would make some dust to stay in allowance.Proof of Concept
This is
_approve()
code inNotionalTradeModule
:As you can see the codes checks the current allowance of
_setToken
for_fCashPosition
in_sendToken
and if it was less than_maxAssetAmount
, it make_setToken
to callsapprove()
in_sendtoken
and set the allowance to_maxAssetAmount
. but if there were some dust left in allowance then this call will revert becasue in most of token implementations, the logic won't allow setting approval amount when it's not0
and this will cause the whole transaction to revert. Because_mintFCashPosition()
uses the_approve()
function somintFCashPosition()
will be fail for thatfcash
andsetToken
and manager can't add thatfcash
tosetToken
portfolio.The exact amount of
underlying
orasset
token to mint_mintFCashPosition
is determined byNotionalV2
and there are always some extra amount ofunderlying
orasset
remain inwfCash
which send them back to the minter. so ifwfCash
don't transfer all the tokens in the first place and only transfer the quired ones then for sure some dust will remain in allowance. In general for many reason dust can remain inallowance
, so it's safer if the contract don't take any chance and set the approval to0x0
first then set it to_maxAssetAmount
.Tools Used
VIM
Recommended Mitigation Steps
set the approval to
0x0
first then set it to_maxAssetAmount
.