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: 26/101
Findings: 5
Award: $368.68
🌟 Selected for report: 1
🚀 Solo Findings: 0
🌟 Selected for report: xiaoming90
Also found by: 0xSmartContract, 8olidity, PaludoX0, Ruhum, adriro, bin2chen, cccz, koxuan, ladboy233, pashov, poirots, rvierdiiev, unforgiven
41.6303 USDC - $41.63
When calling AutoPx*.previewWithdraw in AutoPx*.withdraw, the comment says "No need to check for rounding error, previewWithdraw rounds up".
function withdraw( uint256 assets, address receiver, address owner ) public override returns (uint256 shares) { // Compound rewards and ensure they are properly accounted for prior to withdrawal calculation compound(poolFee, 1, 0, true); shares = previewWithdraw(assets); // No need to check for rounding error, previewWithdraw rounds up.
But only PirexERC4626.previewWithdraw rounds up. AutoPx*.previewWithdraw overrides PirexERC4626.previewWithdraw, but does not round up.
function previewWithdraw(uint256 assets) public view override returns (uint256) { // Calculate shares based on the specified assets' proportion of the pool uint256 shares = convertToShares(assets); // Save 1 SLOAD uint256 _totalSupply = totalSupply; // Factor in additional shares to fulfill withdrawal if user is not the last to withdraw return (_totalSupply == 0 || _totalSupply - shares == 0) ? shares : (shares * FEE_DENOMINATOR) / (FEE_DENOMINATOR - withdrawalPenalty); } ... function convertToShares(uint256 assets) public view virtual returns (uint256) { uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero. return supply == 0 ? assets : assets.mulDivDown(supply, totalAssets()); }
This breaks the developer's intention and does not comply with the EIP-4626 specification
https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/AutoPxGmx.sol#L199-L217 https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/AutoPxGlp.sol#L177-L195 https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/PirexERC4626.sol#L99-L105 https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/AutoPxGmx.sol#L315-L323
None
Call PirexERC4626.previewWithdraw instead of convertToShares in AutoPx*.previewWithdraw
function previewWithdraw(uint256 assets) public view override returns (uint256) { // Calculate shares based on the specified assets' proportion of the pool - uint256 shares = convertToShares(assets); + uint256 shares = PirexERC4626.previewWithdraw(assets);
#0 - c4-judge
2022-12-04T13:01:37Z
Picodes marked the issue as duplicate of #264
#1 - c4-judge
2022-12-04T13:02:12Z
Picodes marked the issue as partial-25
#2 - Picodes
2022-12-04T13:02:25Z
No impact described aside from the non compliance with the EIP
#3 - c4-judge
2023-01-01T11:34:42Z
Picodes changed the severity to 3 (High Risk)
#4 - C4-Staff
2023-01-10T21:57:30Z
JeeberC4 marked the issue as duplicate of #264
#5 - liveactionllama
2023-01-11T18:44:06Z
Duplicate of #178
🌟 Selected for report: Jeiwan
Also found by: 0xLad, 0xSmartContract, 8olidity, HE1M, JohnSmith, KingNFT, Koolex, Lambda, R2, __141345__, carrotsmuggler, cccz, gogo, hl_, joestakey, koxuan, ladboy233, pashov, peanuts, rbserver, rvierdiiev, seyni, unforgiven, xiaoming90, yongskiws
25.3241 USDC - $25.32
A well known attack vector for almost all shares based liquidity pool contracts, where an early user can manipulate the price per share and profit from late users' deposits because of the precision loss caused by the rather large value of price per share.
A malicious early user can deposit() with 1 wei of pxGMX as the first depositor of the apxGMX, and get 1 wei of shares.
Then the attacker can send 10000e18 - 1 of pxGMX and inflate the price per share from 1.0000 to an extreme value of 1.0000e22 ( from (1 + 10000e18 - 1) / 1) .
As a result, the future user who deposits 19999e18 will only receive 1 wei (from 19999e18 * 1 / 10000e18) of shares token.
They will immediately lose 9999e18 or half of their deposits if they redeem() right after the deposit().
https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/PirexERC4626.sol#L60-L78 https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/AutoPxGmx.sol#L164-L166 https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/AutoPxGmx.sol#L339-L362 https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/PirexERC4626.sol#L167-L176
None
Consider requiring a minimal amount of share tokens to be minted for the first minter, and send a part of the initial mints as a reserve to the DAO so that the pricePerShare can be more resistant to manipulation.
#0 - c4-judge
2022-12-04T13:18:19Z
Picodes marked the issue as duplicate of #407
#1 - c4-judge
2023-01-01T11:10:04Z
Picodes marked the issue as satisfactory
#2 - c4-judge
2023-01-01T11:36:31Z
Picodes changed the severity to 3 (High Risk)
#3 - C4-Staff
2023-01-10T21:54:30Z
JeeberC4 marked the issue as duplicate of #275
🌟 Selected for report: cccz
Also found by: Englave, Jeiwan, aphak5010, hansfriese, immeas, rbserver, xiaoming90
213.8538 USDC - $213.85
AutoPxGmx.compound allows anyone to call to compound the reward and get the incentive. However, AutoPxGmx.compound calls SWAP_ROUTER.exactInputSingle with some of the parameters provided by the caller, which allows the user to perform a sandwich attack for profit. For example, a malicious user could provide the fee parameter to make the token swap occur in a small liquid pool, and could make the amountOutMinimum parameter 1 to make the token swap accept a large slippage, thus making it easier to perform a sandwich attack.
None
Consider using poolFee as the fee and using an onchain price oracle to calculate the amountOutMinimum
#0 - c4-judge
2022-12-04T12:56:41Z
Picodes marked the issue as duplicate of #391
#1 - c4-judge
2022-12-05T10:31:09Z
Picodes marked the issue as not a duplicate
#2 - c4-judge
2022-12-05T10:31:42Z
Picodes marked the issue as primary issue
#3 - c4-judge
2022-12-05T10:33:23Z
Picodes marked the issue as selected for report
#4 - Picodes
2022-12-05T10:34:14Z
Flagging as best as the warden identifies that the main risk is not the possibility to increase fees but the fact that some of the pools will be highly illiquid
#5 - c4-sponsor
2022-12-08T05:09:31Z
drahrealm marked the issue as disagree with severity
#6 - drahrealm
2022-12-08T05:10:02Z
#7 - Picodes
2022-12-30T21:01:52Z
It's very likely that this attack is profitable as most of the time only 1 or 2 pools have decent liquidity, so medium severity is appropriate
#8 - c4-judge
2022-12-30T21:04:44Z
Picodes marked the issue as satisfactory
🌟 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
amountOutMinimum is 1 when compound() is called in some functions of the AutoPxGmx contract, and will be used as the amountOutMinimum parameter when calling SWAP_ROUTER.exactInputSingle
compound(poolFee, 1, 0, true);
According to the https://docs.uniswap.org/contracts/v3/guides/swaps/single-swaps description, the amountOutMinimum should be calculated using the Uniswap SDK or the onchain price oracle. Simply setting it to 1 may result in losses due to improper slippage control.
https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/AutoPxGmx.sol#L242-L278 https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/AutoPxGmx.sol#L321-L322 https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/AutoPxGmx.sol#L345-L346 https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/AutoPxGmx.sol#L227-L228
None
Consider using the Uniswap SDK or the onchain price oracle to calculate the amountOutMinimum
#0 - c4-judge
2022-12-04T00:22:33Z
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:10:23Z
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: xiaoming90
Also found by: 0x52, 8olidity, aphak5010, bin2chen, cccz, hansfriese, hihen, joestakey, ladboy233, rvierdiiev, unforgiven
71.9536 USDC - $71.95
In the constructor of AutoPx*, when setting the platform, the platform is approved to use the contract's gmx or gmxBaseReward tokens in order to perform the token swap in the compound function.
platform = _platform; rewardsModule = _rewardsModule; // Approve the Uniswap V3 router to manage our base reward (inbound swap token) gmxBaseReward.safeApprove(address(SWAP_ROUTER), type(uint256).max); gmx.safeApprove(_platform, type(uint256).max);
However, when the platform is updated in the setPlatform function, the new platform is not approved to use the tokens in the contract. This causes the compound function to fail when the platform is updated because the platform is not approved to use the tokens.
function setPlatform(address _platform) external onlyOwner { if (_platform == address(0)) revert ZeroAddress(); platform = _platform; emit PlatformUpdated(_platform); }
https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/AutoPxGmx.sol#L152-L158 https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/AutoPxGmx.sol#L92-L97 https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/AutoPxGlp.sol#L130-L136 https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/AutoPxGlp.sol#L83-L87
None
Change to
function setPlatform(address _platform) external onlyOwner { if (_platform == address(0)) revert ZeroAddress(); + gmx.safeApprove(platform, 0); platform = _platform; + gmx.safeApprove(_platform, type(uint256).max); emit PlatformUpdated(_platform); } ... function setPlatform(address _platform) external onlyOwner { if (_platform == address(0)) revert ZeroAddress(); + gmxBaseReward.safeApprove(platform, 0); platform = _platform; + gmxBaseReward.safeApprove(_platform, type(uint256).max); emit PlatformUpdated(_platform); }
#0 - c4-judge
2022-12-04T13:18:37Z
Picodes marked the issue as duplicate of #182
#1 - c4-judge
2023-01-01T11:09:23Z
Picodes marked the issue as satisfactory
#2 - c4-judge
2023-01-01T11:29:18Z
Picodes changed the severity to 3 (High Risk)
#3 - c4-judge
2023-01-01T11:32:53Z
Picodes changed the severity to 2 (Med Risk)