Platform: Code4rena
Start Date: 03/05/2023
Pot Size: $60,500 USDC
Total HM: 25
Participants: 114
Period: 8 days
Judge: Picodes
Total Solo HM: 6
Id: 234
League: ETH
Rank: 28/114
Findings: 4
Award: $327.76
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: aviggiano
Also found by: 0xSmartContract, 0xTheC0der, 0xcm, ABAIKUNANBAEV, Audinarey, Audit_Avengers, BGSecurity, Bauchibred, Dug, Evo, Haipls, Jerry0x, TS, bytes032, devscrooge, kenta, ladboy233, mrvincere, patitonar, sakshamguruji, tsvetanovv
15.5756 USDC - $15.58
In RewardsManager.sol the method _transferAjnaRewards(uint256 rewardsEarned_)
validates the balance of the contract and updates the rewards to transfer in if (rewardsEarned_ > ajnaBalance) rewardsEarned_ = ajnaBalance;
.
This can cause the user to lose all their rewards, the contract registers the accumulated and distributed amount (preventing re-claiming it again in the future) but at the moment of transferring can actually transfer 0 if there are no funds. Even if the user calls it via a UI expecting to receive rewards, the transaction could be frontrunned. It should revert if there are no funds to distribute, especially when calling claimRewards()
.
Token-Transfer
#0 - c4-judge
2023-05-18T09:29:51Z
Picodes marked the issue as duplicate of #361
#1 - c4-judge
2023-05-29T20:59:01Z
Picodes marked the issue as satisfactory
253.665 USDC - $253.66
In RewardsManager.sol
the method updateBucketExchangeRatesAndClaim()
distributes rewards to the caller for updating the bucket exchange rate. However, this transaction can be frontrunned by an attacker allowing them to get the rewards.
MEV
#0 - c4-judge
2023-05-18T15:35:40Z
Picodes marked the issue as duplicate of #373
#1 - c4-judge
2023-05-30T21:24:56Z
Picodes marked the issue as satisfactory
🌟 Selected for report: rbserver
Also found by: 0xnev, ABAIKUNANBAEV, Audit_Avengers, Aymen0909, BGSecurity, BRONZEDISC, Bason, DadeKuma, GG_Security, Jerry0x, Jorgect, MohammedRizwan, REACH, Sathish9098, Shogoki, T1MOH, UniversalCrypto, aviggiano, ayden, berlin-101, bytes032, codeslide, descharre, fatherOfBlocks, hals, kaveyjoe, kodyvim, lfzkoala, lukris02, nadin, naman1778, patitonar, pontifex, sakshamguruji, squeaky_cactus, teawaterwire, wonjun, yjrwkk
36.2377 USDC - $36.24
https://github.com/code-423n4/2023-05-ajna/blob/276942bc2f97488d07b887c8edceaaab7a5c3964/ajna-core/src/PositionManager.sol#L42 The PositionManager ERC721 contract supports PermitERC721. This functionality can be leveraged to introduce a method stakeWithPermit() to improve the user experience.
ajnaTokenAddress
in Funding.sol should be a constanthttps://github.com/code-423n4/2023-05-ajna/blob/276942bc2f97488d07b887c8edceaaab7a5c3964/ajna-grants/src/grants/base/Funding.sol#L21
Constants should be used for literal values written into the code, and immutable variables should be used for expressions, or values calculated in, or passed into the constructor. In this case, it makes sense for ajnaTokenAddress
to be a constant.
#0 - c4-judge
2023-05-18T18:42:41Z
Picodes marked the issue as grade-b
🌟 Selected for report: JCN
Also found by: 0x73696d616f, 0xSmartContract, 0xnev, Audit_Avengers, Aymen0909, Blckhv, Eurovickk, K42, Kenshin, Rageur, Raihan, ReyAdmirado, SAAJ, SAQ, Shubham, Tomio, Walter, ayden, codeslide, descharre, dicethedev, hunter_w3b, j4ld1na, kaveyjoe, okolicodes, patitonar, petrichor, pontifex, yongskiws
22.2767 USDC - $22.28
https://github.com/code-423n4/2023-05-ajna/blob/276942bc2f97488d07b887c8edceaaab7a5c3964/ajna-core/src/PositionManager.sol#L101-L104
In PositionManager.sol the modifier mayInteract(address pool_, uint256 tokenId_)
validates that token id exists in _requireMinted(tokenId_);
but this validations is already included as part of _isApprovedOrOwner(msg.sender, tokenId_)
that is called later.
https://github.com/code-423n4/2023-05-ajna/blob/276942bc2f97488d07b887c8edceaaab7a5c3964/ajna-core/src/PositionManager.sol#L229 The method is using _mint() instead of safeMint(), so there is no external call nor risks of reentrant.
https://github.com/code-423n4/2023-05-ajna/blob/276942bc2f97488d07b887c8edceaaab7a5c3964/ajna-core/src/RewardsManager.sol#L122
In RewardsManager.sol the method claimRewards() performs the following validation if (isEpochClaimed[tokenId_][epochToClaim_]) revert AlreadyClaimed();
. This is done after reading a storage state and performing another validation. This one should be moved to the start of the method in order be cheaper to revert in that case.
validateEpoch_
in _claimRewards()
methodhttps://github.com/code-423n4/2023-05-ajna/blob/276942bc2f97488d07b887c8edceaaab7a5c3964/ajna-core/src/RewardsManager.sol#L565
https://github.com/code-423n4/2023-05-ajna/blob/276942bc2f97488d07b887c8edceaaab7a5c3964/ajna-core/src/RewardsManager.sol#L124
This flag is used to perform the following validation if (validateEpoch_ && epochToClaim_ > IPool(ajnaPool_).currentBurnEpoch()) revert EpochNotAvailable();
but this is only done in the case the method is called from the external claimRewards()
method where the flag is true. This flag should be removed and the validation should be perform direclty in the external claimRewards()
https://github.com/code-423n4/2023-05-ajna/blob/276942bc2f97488d07b887c8edceaaab7a5c3964/ajna-core/src/RewardsManager.sol#L819 https://github.com/code-423n4/2023-05-ajna/blob/276942bc2f97488d07b887c8edceaaab7a5c3964/ajna-grants/src/grants/GrantFund.sol#L67 https://github.com/code-423n4/2023-05-ajna/blob/276942bc2f97488d07b887c8edceaaab7a5c3964/ajna-grants/src/grants/base/StandardFunding.sol#L264 While safeERC20 methods are useful to interact with several ERC20 tokens that have different behaviors. The ajna token reverts when a call to transfer() or transferFrom() are performed. As these contract are intended to use ajna token as rewards, then it can be safe and save gas using directly transfer() and transferFrom(). This affect the following calls:
IERC20(ajnaToken).safeTransfer(msg.sender, rewardsEarned_);
token.safeTransferFrom(msg.sender, address(this), fundingAmount_);
IERC20(ajnaTokenAddress).safeTransfer(msg.sender, rewardClaimed_);
#0 - c4-judge
2023-05-17T10:55:12Z
Picodes marked the issue as grade-b