Platform: Code4rena
Start Date: 18/05/2023
Pot Size: $24,500 USDC
Total HM: 3
Participants: 72
Period: 4 days
Judge: LSDan
Id: 237
League: ETH
Rank: 12/72
Findings: 1
Award: $341.12
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: ABA
Also found by: 0x4non, 0xHati, 0xMosh, 0xSmartContract, 0xWaitress, 0xhacksmithh, 0xnev, 0xprinc, Arabadzhiev, BLACK-PANDA-REACH, Deekshith99, Dimagu, KKat7531, Kose, LosPollosHermanos, MohammedRizwan, QiuhaoLi, RaymondFam, Rickard, Rolezn, SAAJ, Sathish9098, Shubham, SmartGooofy, Tripathi, Udsen, V1235816, adriro, arpit, ayden, bigtone, codeVolcan, d3e4, dwward3n, fatherOfBlocks, favelanky, jovemjeune, kutugu, lfzkoala, lukris02, matrix_0wl, minhquanym, ni8mare, parsely, pxng0lin, radev_sw, ravikiranweb3, rbserver, sces60107, souilos, tnevler, turvy_fuzz, yellowBirdy
341.1226 USDC - $341.12
Issue | Contexts | |
---|---|---|
LOW‑1 | Contracts are not using their OZ Upgradeable counterparts | 2 |
LOW‑2 | Upgrade OpenZeppelin Contract Dependency | 1 |
LOW‑3 | Consider case where _reservedRate will exceed JBConstants.MAX_RESERVED_RATE which will revert | 1 |
LOW‑4 | uniswapV3SwapCallback will revert even though _amountReceived == _minimumAmountReceived | 1 |
Total: 5 contexts over 4 issues
Issue | Contexts | |
---|---|---|
NC‑1 | Use Underscores for Number Literals | 1 |
NC‑2 | Use a more recent version of Solidity | 1 |
NC‑3 | Empty blocks should be removed or emit something | 1 |
NC‑4 | Large multiples of ten should use scientific notation | 1 |
NC‑5 | Keep using JBConstants convention for constants | 1 |
Total: 5 contexts over 5 issues
The non-upgradeable standard version of OpenZeppelin’s library are inherited / used by the contracts. It would be safer to use the upgradeable versions of the library contracts to avoid unexpected behaviour.
15: import "@openzeppelin/contracts/access/Ownable.sol"; 16: import "@openzeppelin/contracts/interfaces/IERC20.sol";
Where applicable, use the contracts from @openzeppelin/contracts-upgradeable
instead of @openzeppelin/contracts
.
See https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/tree/master/contracts for list of available upgradeable contracts
An outdated OZ version is used (which has known vulnerabilities, see: https://github.com/OpenZeppelin/openzeppelin-contracts/security/advisories).
Require dependencies to be at least version of 4.8.3 to include critical vulnerability patches.
"@openzeppelin/contracts": "^4.7.3"
https://github.com/code-423n4/2023-05-juicebox/tree/main/juice-buyback/contracts/../package.json#L25
Update OpenZeppelin Contracts Usage in package.json and require at least version of 4.8.3 via >=4.8.3
_reservedRate
will exceed JBConstants.MAX_RESERVED_RATE
which will revertConsider the case where _reservedRate
> JBConstants.MAX_RESERVED_RATE
which will cause JBConstants.MAX_RESERVED_RATE - _reservedRate
to underflow and thus revert the mulDiv
call
As per below code snippets it is clear that a ticketId claimableAmount can be zero if the time has elapsed for the reward claim. In such case for other valid ticketIds sent in by the user the rewards claim will also fail since the transaction will revert since claimedAmount == 0.
uint256 _nonReservedToken = PRBMath.mulDiv( _amountReceived, JBConstants.MAX_RESERVED_RATE - _reservedRate, JBConstants.MAX_RESERVED_RATE );
uniswapV3SwapCallback
will revert even though _amountReceived == _minimumAmountReceived
Consider the case where _reservedRate
> JBConstants.MAX_RESERVED_RATE
which will cause JBConstants.MAX_RESERVED_RATE - _reservedRate
to underflow and thus revert the mulDiv
call
The function does not validate when _amountReceived
is equal to _minimumAmountReceived
which is the minimum amount to receive. In this case, it will revert.
if (_amountReceived < _minimumAmountReceived) revert JuiceBuyback_MaximumSlippage();
68: uint256 private constant SLIPPAGE_DENOMINATOR = 10000;
<a href="https://blog.soliditylang.org/2022/09/08/solidity-0.8.17-release-announcement/">0.8.17</a>:
Yul Optimizer: Prevent the incorrect removal of storage writes before calls to Yul functions that conditionally terminate the external EVM call.
<a href="https://blog.soliditylang.org/2023/02/22/solidity-0.8.19-release-announcement/">0.8.19</a>: SMTChecker: New trusted mode that assumes that any compile-time available code is the actual used code, even in external calls. Bug Fixes:
<a href="https://blog.soliditylang.org/2023/05/10/solidity-0.8.20-release-announcement/">0.8.20</a>:
pragma solidity ^0.8.16;
Consider updating to a more recent solidity version.
239: {}
Use (e.g. 1e6) rather than decimal literals (e.g. 100000), for better code readability.
68: uint256 private constant SLIPPAGE_DENOMINATOR = 10000;
JBConstants
convention for constantsIt is seen that the protocol uses JBConstants.sol
to store constants. The contract should keep using the same convention and apply the constant value in JBConstants.sol
You can see the use of JBConstants
foe example in:
279: _amountReceived, JBConstants.MAX_RESERVED_RATE - _reservedRate, JBConstants.MAX_RESERVED_RATE
This convention should also apply to:
68: uint256 private constant SLIPPAGE_DENOMINATOR = 10000;
#0 - c4-judge
2023-06-02T12:11:53Z
dmvt marked the issue as grade-a