Platform: Code4rena
Start Date: 11/11/2021
Pot Size: $50,000 USDC
Total HM: 9
Participants: 27
Period: 7 days
Judge: alcueca
Total Solo HM: 5
Id: 53
League: ETH
Rank: 5/27
Findings: 2
Award: $3,322.98
π Selected for report: 5
π Solo Findings: 0
cmichel
Some tokens (like USDT) don't correctly implement the EIP20 standard and their transfer
/transferFrom
function return void
instead of a success boolean. Calling these functions with the correct EIP20 function signatures will always revert.
Non-safe transfers are used in:
NestedFactory.unlockTokens
Tokens that don't correctly implement the latest EIP20 spec, like USDT, will be unusable in the protocol as they revert the transaction because of the missing return value.
We recommend using OpenZeppelinβs SafeERC20
versions with the safeTransfer
and safeTransferFrom
functions that handle the return value check as well as non-standard-compliant tokens.
#0 - maximebrugel
2021-11-17T17:05:01Z
Duplicated : #78
389.9738 USDC - $389.97
cmichel
Some parameters of functions are not checked for non-zero values:
NestedFactory.constructor
: address parameters could be zero or not a contractNestedReserve.constructor
: address parameters could be zero or not a contractNestedBuybacker.constructor
: address parameters could be zero or not a contractWrong user input or wallets defaulting to the zero addresses for a missing input can lead to the contract needing to redeploy or wasted gas.
Validate the parameters.
π Selected for report: cmichel
866.6085 USDC - $866.61
cmichel
The NestedAsset.backfillTokenURI
function can only be called by the factory but the factory never calls it.
Unused code can hint at programming or architectural errors.
When minting tokens (using mint
) it sets no tokenURI
and there's currently no way to set it anymore.
Add a way to use backfillTokenURI
.
#0 - alcueca
2021-12-03T15:18:24Z
Disputed on which grounds, @adrien-supizet?
#1 - adrien-supizet
2021-12-03T15:42:49Z
@alcueca Sorry for the missing details. Here it is:
The NestedAsset
contract is not upgradeable, the NFT collection is here to stay.
Even though today we do not need to store any metadata in the NFTs, we know it's very likely to be the case in the future.
Indeed, the current NestedFactory
does not use this function, but we assume that the next factory might. Therefore we want to keep this unused function.
π Selected for report: cmichel
866.6085 USDC - $866.61
cmichel
The _transferInputTokens
function accesses msg.value
if the input token is ETH, and this function is called in a loop in _submitOutOrders
.
Therefore, in theory, one can specify two ETH orders but only pay once as the msg.value
will be processed in each order iteration.
The severity is low as
_transferInputTokens
in a loop always have _fromReserve == true
which does not access msg.value
I'd advocate against using msg.value
in a loop.
Imo, the best way to circumvent this is to not deal with ETH in the contract at all and just use WETH directly, as that's what the contract wants anyway for the orders.
Maybe just adding a depositAllETH
function that deposits msg.value
to WETH once at the beginning of the swap functions makes sense.
#0 - maximebrugel
2021-11-23T16:12:28Z
We do not access msg.value
in a loop expect multicall
that we will remove (#226)
233.9843 USDC - $233.98
cmichel
The NestedFactory.addOperator
function pushes the operator
even if it already exists in operators
.
When this duplicated operator is removed through a removeOperator
call, only the first instance is removed.
The operator can now still be called which can lead to unexpected behavior.
Check if the operator already exists before adding it.
π Selected for report: cmichel
866.6085 USDC - $866.61
cmichel
The NestedFactory._handleUnderSpending
function implements a condition as _amountToSpent - _amountSpent > 0
instead of _amountToSpent > _amountSpent
.
The former reverts if _amountSpent > _amountToSpent
while the latter doesn't.
It's unclear which behavior is preferred.
Think about if _amountSpent > _amountToSpent
should revert or not. If not, the if
condition can be rewritten as _amountSpent > _amountToSpent
which would also save gas.
π Selected for report: pmerkleplant
13.9113 USDC - $13.91
cmichel
The NestedBuybacker.triggerForToken
gets the _sellToken
balance but does never use this result.
// this balance is never used uint256 balance = _sellToken.balanceOf(address(this));
A good compiler should eliminate dead code but it's better to remove unused code in the first place.
#0 - maximebrugel
2021-11-17T17:00:16Z
Duplicated : #65