Closed code423n4 closed 2 years ago
Will have to review this and see if I can reproduce this issue.
While the variable is named _maxSendAmount
, in wfCashLogic.mintViaAsset
or wfCashLogic.mintViaUnderlying
the entire amount is transferred. It doesn't seems to be an instance where there is dust in allowance.
https://github.com/code-423n4/2022-06-notional-coop-findings/issues/89#issuecomment-1155977567
Downgrading to Low / QA.
Consider with #228
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
mintFCashPosition -> _mintFCashPosition -> _approve call sequence tend to leave positive unspent allowance, which can make new fCash positions opening unavailable for an underlying that forbid approval of a positive value if allowance is positive (most known example is USDT).
Setting severity to be medium as this is system unavailability case and USDT is supported by both Aave and Compound and, being widely used, can be reasonably expected to added to Notional.
Proof of Concept
mintFCashPosition uses arbitrary underlying _sendToken:
https://github.com/code-423n4/2022-06-notional-coop/blob/6f8c325f604e2576e2fe257b6b57892ca181509a/index-coop-notional-trade-module/contracts/protocol/modules/v1/NotionalTradeModule.sol#L147-L167
Underlying _sendToken there can be an ERC20 that do not allow an approval of a positive value if allowance is positive already (for example, USDT):
https://github.com/d-xo/weird-erc20#approval-race-protections
mintFCashPosition -> _mintFCashPosition calls _approve() for _sendToken ERC20 with _maxSendAmount, which is the maximum allowed _sendToken to be spent:
https://github.com/code-423n4/2022-06-notional-coop/blob/6f8c325f604e2576e2fe257b6b57892ca181509a/index-coop-notional-trade-module/contracts/protocol/modules/v1/NotionalTradeModule.sol#L433-L449
https://github.com/code-423n4/2022-06-notional-coop/blob/6f8c325f604e2576e2fe257b6b57892ca181509a/index-coop-notional-trade-module/contracts/protocol/modules/v1/NotionalTradeModule.sol#L490-L505
As _maxSendAmount is a limit, in most cases the actual _sendToken amount spent is less and the allowance will remain partially unspent. Then, if _sendToken is as described each next mintFCashPosition will be reverted, the function become unavailable.
Recommended Mitigation Steps
Consider adding zero amount approval in _approve() before actual amount approval to force zero allowance: