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: 68/111
Findings: 2
Award: $78.95
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: __141345__
Also found by: 0xbepresent, Deivitto, HollaDieWaldfee, Nyx, PaludoX0, RaymondFam, ak1, cccz, ck, cryptostellar5, csanuragjain, ladboy233, rvierdiiev
68.0946 USDC - $68.09
Staking is not allowed when contracts are paused, but with restake() function it can be bypassed.
restakeGGP() doesn't have whenNotPaused modifier.
function restakeGGP(address stakerAddr, uint256 amount) public onlySpecificRegisteredContract("ClaimNodeOp", msg.sender) { // Transfer GGP tokens from the ClaimNodeOp contract to this contract ggp.safeTransferFrom(msg.sender, address(this), amount); _stakeGGP(stakerAddr, amount); }
Manuel Review
restakeGGP() or _stakeGGP() should have whenNotPaused modifier.
#0 - c4-judge
2023-01-08T13:28:14Z
GalloDaSballo marked the issue as duplicate of #351
#1 - c4-judge
2023-01-29T18:15:30Z
GalloDaSballo marked the issue as duplicate of #673
#2 - c4-judge
2023-02-08T08:56:54Z
GalloDaSballo marked the issue as satisfactory
🌟 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
10.8565 USDC - $10.86
minipool can be created without staking AVAX with recreateMinipool(). recreateMinipool() function doesn't check if the owner withdrew or not.
I just added withdrawMinipoolFunds() to the original test.
function testRecreateMinipool() public { uint256 duration = 4 weeks; uint256 depositAmt = 1000 ether; uint256 avaxAssignmentRequest = 1000 ether; uint256 validationAmt = depositAmt + avaxAssignmentRequest; // Enough to start but not to re-stake, we will add more later uint128 ggpStakeAmt = 100 ether; vm.startPrank(nodeOp); ggp.approve(address(staking), MAX_AMT); staking.stakeGGP(ggpStakeAmt); MinipoolManager.Minipool memory mp = createMinipool(depositAmt, avaxAssignmentRequest, duration); console.log("balance1", nodeOpBalance); vm.stopPrank(); address liqStaker1 = getActorWithTokens("liqStaker1", MAX_AMT, MAX_AMT); vm.prank(liqStaker1); ggAVAX.depositAVAX{value: MAX_AMT}(); vm.prank(address(rialto)); minipoolMgr.claimAndInitiateStaking(mp.nodeID); bytes32 txID = keccak256("txid"); vm.prank(address(rialto)); minipoolMgr.recordStakingStart(mp.nodeID, txID, block.timestamp); skip(duration / 2); // Give rialto the rewards it needs uint256 rewards = 10 ether; deal(address(rialto), address(rialto).balance + rewards); // Pay out the rewards vm.prank(address(rialto)); minipoolMgr.recordStakingEnd{value: validationAmt + rewards}(mp.nodeID, block.timestamp, rewards); // Now try to restake vm.expectRevert(MinipoolManager.InvalidMultisigAddress.selector); minipoolMgr.recreateMinipool(mp.nodeID); vm.prank(address(rialto)); vm.expectRevert(MinipoolManager.InsufficientGGPCollateralization.selector); minipoolMgr.recreateMinipool(mp.nodeID); // Add a bit more collateral to cover the compounding rewards vm.startPrank(nodeOp); staking.stakeGGP(1 ether); minipoolMgr.withdrawMinipoolFunds(mp.nodeID); vm.stopPrank(); vm.prank(address(rialto)); minipoolMgr.recreateMinipool(mp.nodeID); console.log("staking.getAVAXStake(mp.owner) :", staking.getAVAXStake(mp.owner) / 1e18); //MinipoolManager.Minipool memory mpCompounded = minipoolMgr.getMinipoolByNodeID(mp.nodeID); //assertEq(mpCompounded.status, uint256(MinipoolStatus.Prelaunch)); //assertGt(mpCompounded.avaxNodeOpAmt, mp.avaxNodeOpAmt); //assertGt(mpCompounded.avaxNodeOpAmt, mp.avaxNodeOpInitialAmt); //assertGt(mpCompounded.avaxLiquidStakerAmt, mp.avaxLiquidStakerAmt); //assertEq(staking.getAVAXStake(mp.owner), mpCompounded.avaxNodeOpAmt); //assertEq(staking.getAVAXAssigned(mp.owner), mpCompounded.avaxLiquidStakerAmt); //assertEq(staking.getMinipoolCount(mp.owner), 1); //assertEq(mpCompounded.startTime, 0); //assertGt(mpCompounded.initialStartTime, 0); }
Foundry
recreateMinipool() needs check staking balance before increaseAVAXStake().
#0 - GalloDaSballo
2023-01-10T20:55:18Z
Dup of #484 but without Front-run aspect, awarding half
#1 - c4-judge
2023-01-10T20:55:26Z
GalloDaSballo marked the issue as duplicate of #484
#2 - c4-judge
2023-01-10T20:55:34Z
GalloDaSballo marked the issue as partial-50
#3 - c4-judge
2023-02-03T12:41:09Z
GalloDaSballo marked the issue as duplicate of #569
#4 - c4-judge
2023-02-08T08:27:15Z
GalloDaSballo changed the severity to 2 (Med Risk)
#5 - c4-judge
2023-02-09T08:45:54Z
GalloDaSballo changed the severity to QA (Quality Assurance)
#6 - Simon-Busch
2023-02-09T12:34:52Z
Changed the severity back to M as requested by @GalloDaSballo