Platform: Code4rena
Start Date: 21/11/2022
Pot Size: $90,500 USDC
Total HM: 18
Participants: 101
Period: 7 days
Judge: Picodes
Total Solo HM: 4
Id: 183
League: ETH
Rank: 40/101
Findings: 3
Award: $109.07
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: deliriusz
Also found by: 0x52, 0xLad, 0xbepresent, Englave, R2, Ruhum, cccz, gzeon, hihen, keccak123, ladboy233, pashov, pedroais, perseverancesuccess, rbserver, rvierdiiev, simon135, unforgiven, wagmi, xiaoming90
15.9293 USDC - $15.93
Judge has assessed an item in Issue #316 as M risk. The relevant finding follows:
compound in AutoPxGmx can be called by anyone and can be sandwiched if a poorly chosen amountOutMinimum is used. The idea is to call the function often by adding an incentive to the caller. There is a problematic hidden incentive - the amountOutMinimum value is controlled by the caller. This means that MEV bots have incentive to call this function and take a cut of the rewards by setting amountOutMinimum to a lower value than could be received by the vault.
The function argument amountOutMinimum is on line 244. It is used in the Uniswap swap on line 275. It can be set to any value except zero, enabling the majority of the value from the swap to be lost.
Recommendation Disincentive sandwiching of this swap. There should be additional checks that the amountOutMinimum function argument is a reasonable value. One way to do this is using a TWAP or oracle to get the exchange rate and use gmxBaseRewardAmountIn to calculate what the minimum allowable amountOutMinimum is.
#0 - c4-judge
2022-12-05T08:50:49Z
Picodes marked the issue as duplicate of #183
#1 - c4-judge
2022-12-30T20:53:41Z
Picodes marked the issue as duplicate of #185
#2 - c4-judge
2023-01-01T11:01:02Z
Picodes marked the issue as satisfactory
#3 - C4-Staff
2023-01-10T22:10:37Z
JeeberC4 marked the issue as duplicate of #137
🌟 Selected for report: 0xSmartContract
Also found by: 0xAgro, 0xNazgul, 0xPanda, 0xbepresent, 0xfuje, Awesome, B2, Bnke0x0, Deivitto, Diana, Funen, Jeiwan, JohnSmith, Josiah, R2, RaymondFam, Rolezn, Sathish9098, Waze, adriro, aphak5010, brgltd, btk, carrotsmuggler, ch0bu, chaduke, codeislight, codexploder, cryptostellar5, csanuragjain, danyams, datapunk, delfin454000, deliriusz, eierina, erictee, fatherOfBlocks, gz627, gzeon, hansfriese, hihen, jadezti, joestakey, keccak123, martin, nameruse, oyc_109, pedr02b2, perseverancesuccess, rbserver, rotcivegaf, rvierdiiev, sakshamguruji, shark, simon135, subtle77, unforgiven, xiaoming90, yixxas
53.4851 USDC - $53.49
compound
in AutoPxGmx can be called by anyone and can be sandwiched if a poorly chosen amountOutMinimum
is used. The idea is to call the function often by adding an incentive to the caller. There is a problematic hidden incentive - the amountOutMinimum
value is controlled by the caller. This means that MEV bots have incentive to call this function and take a cut of the rewards by setting amountOutMinimum
to a lower value than could be received by the vault.
The function argument amountOutMinimum
is on line 244. It is used in the Uniswap swap on line 275. It can be set to any value except zero, enabling the majority of the value from the swap to be lost.
Disincentive sandwiching of this swap. There should be additional checks that the amountOutMinimum
function argument is a reasonable value. One way to do this is using a TWAP or oracle to get the exchange rate and use gmxBaseRewardAmountIn
to calculate what the minimum allowable amountOutMinimum
is.
_setupRole
is deprecated. Instead use _grantRole
. This also removes a function call because _setupRole
calls _grantRole
. _setupRole
is found in PxERC20
OpenZeppelin clearly indicates this function is deprecated
Use _grantRole
not _setupRole
This comment about approving the Uniswap router is wrong. It was accidentally copied from another file.
// Approve the Uniswap V3 router to manage our base reward (inbound swap token)
Change the comment to Approve platform address to manage our base reward
_platform
is already of type address in this line. It does not need to be cast to address
gmxBaseReward.safeApprove(address(_platform), type(uint256).max);
- gmxBaseReward.safeApprove(address(_platform), type(uint256).max); + gmxBaseReward.safeApprove(_platform, type(uint256).max);
Identical functions in AutoPxGlp and AutoPxGmx have slightly different comments.
https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/AutoPxGmx.sol#L170-L171 https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/AutoPxGlp.sol#L148-L149
https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/AutoPxGmx.sol#L196-L197 https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/AutoPxGlp.sol#L174-L175
- @param assets uint256 Assets - @return uint256 Shares + @param assets uint256 Assets amount + @return uint256 Shares amount
Use the same comments in different contracts of a project when the code is the same.
#0 - c4-judge
2022-12-05T08:51:27Z
Picodes marked the issue as grade-b
🌟 Selected for report: gzeon
Also found by: 0xPanda, 0xSmartContract, B2, Deivitto, Diana, JohnSmith, PaludoX0, Rahoz, RaymondFam, ReyAdmirado, Rolezn, Schlagatron, Secureverse, Tomio, __141345__, adriro, ajtra, aphak5010, c3phas, chaduke, codeislight, cryptonue, datapunk, dharma09, halden, karanctf, keccak123, oyc_109, pavankv, sakshamguruji, saneryee, unforgiven
39.6537 USDC - $39.65
Solidity errors save gas compared to require
Three lines use require:
Use solidity errors to replace require for gas savings
Variables that are private or internal use less gas than public or external variables
Many variables can make use of this change if the contract does not need to make these variables public.
Make variables private or internal if they do not need to be public or external
A payable function saves gas compared to one that is not payable. If a function has an onlyOwner modifier or has similar access controls to prevent the function from receiving ETH, the function can be payable to save gas.
Many functions have the onlyOwner modifier and can be more efficient
Make all functions with onlyOwner payable
Use unchecked when possible for gas savings. Line 403: https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/PirexRewards.sol#L403
- uint256 amount = (rewardState * userRewards) / globalRewards; + unchecked { uint256 amount = (rewardState * userRewards) / globalRewards; }
Use unchecked for gas savings when there is no overflow or underflow risk
#0 - c4-judge
2022-12-05T14:04:11Z
Picodes marked the issue as grade-b
#1 - drahrealm
2022-12-09T06:45:37Z
G-01 is taken into consideration
#2 - c4-sponsor
2022-12-09T06:45:44Z
drahrealm marked the issue as sponsor confirmed