GoGoPool contest - enckrish's results

Liquid staking for Avalanche.

General Information

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

GoGoPool

Findings Distribution

Researcher Performance

Rank: 40/111

Findings: 2

Award: $408.47

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: HollaDieWaldfee

Also found by: 0xdeadbeef0x, bin2chen, cozzetti, danyams, enckrish, imare, ladboy233

Labels

bug
3 (High Risk)
partial-50
sponsor confirmed
upgraded by judge
duplicate-136
fix security (sponsor)

Awards

373.7183 USDC - $373.72

External Links

Lines of code

https://github.com/code-423n4/2022-12-gogopool/blob/main/contracts/contract/MinipoolManager.sol#L670

Vulnerability details

Impact

Multisigs can update the expected AVAX reward rate to adjust for the staking reward rate provided by AVAX staking. If the expected rate is increased, then a larger amount of GGP of validators will be slashed if they don't provide any reward. But, if validators don't have enough GGP staked (GGP staked is fixed at 10% of AVAX assigned), to account for the expected reward rate, multiplied with the duration, then slash will revert. This will result in the particular pool not being able to be withdrawable, and the liquid staker and node operator funds will be stuck.

		uint256 expectedAVAXRewardsAmt = getExpectedAVAXRewardsAmt(duration, avaxLiquidStakerAmt);
		uint256 slashGGPAmt = calculateGGPSlashAmt(expectedAVAXRewardsAmt);
		setUint(keccak256(abi.encodePacked("minipool.item", index, ".ggpSlashAmt")), slashGGPAmt);

		emit GGPSlashed(nodeID, slashGGPAmt);

		Staking staking = Staking(getContractAddress("Staking"));
		staking.slashGGP(owner, slashGGPAmt);

While it is possible to call recordStakingEnd at an earlier time than the expected duration, it will still result in slashing for the entire duration, so it is not a valid path.

Proof of Concept

Bob creates a minipool with 1000 AVAX and 100 AVAX worth of GGP staked. Sometime later, in responding to higher AVAX staking rates, a multisig increases the expected AVAX rewards rate. Since, Bob has high downtime, he doesn't get any reward, and the multisig calls MinipoolManager.recordStakingEnd with 0 avaxTotalRewardAmt. When slash is called, it reverts expectedAVAXRewardsAmt > X. This also causes recordStakingEnd to revert, and the funds are not able to be returned.

Tools Used

Manual inspection

slash should slash based on the current time and the start time of the pool. Alternatively, the multisig can send an end time, which will be used to calculate the amount to be slashed.

Also, if the amount to be slashed is greater than the staked amount, it should slash the staked amount only, to prevent panic due to underflow.

#0 - GalloDaSballo

2023-01-10T19:24:36Z

Arguably dup of big duration to skip slashing, but keeping separate for now

#1 - c4-sponsor

2023-01-11T19:08:43Z

emersoncloud marked the issue as sponsor confirmed

#2 - emersoncloud

2023-01-11T19:14:49Z

Only the Rialto multisig can set the expectedAVAXRewardsAmt, so we can be sure to take precautions while setting. But slashing should not revert for underflow, we should handle that case.

#3 - 0xju1ie

2023-01-20T11:44:55Z

would agree its mostly a dupe of #694 but with the added revert for underflow

#4 - emersoncloud

2023-01-24T13:07:53Z

Duplicate of #136

#5 - GalloDaSballo

2023-02-01T19:32:24Z

In contrast to #136 this report focuses mostly on admin privilege, while still hitting at the core issue of reverting

I'm awarding 50% for this reason

#6 - c4-judge

2023-02-01T19:32:33Z

GalloDaSballo marked the issue as duplicate of #136

#7 - c4-judge

2023-02-01T19:32:38Z

GalloDaSballo marked the issue as partial-50

#8 - c4-judge

2023-02-03T19:40:44Z

GalloDaSballo changed the severity to 3 (High Risk)

Awards

34.7487 USDC - $34.75

Labels

bug
2 (Med Risk)
satisfactory
duplicate-702

External Links

Lines of code

https://github.com/code-423n4/2022-12-gogopool/blob/main/contracts/contract/MinipoolManager.sol#L236 https://github.com/code-423n4/2022-12-gogopool/blob/main/contracts/contract/MultisigManager.sol#L67

Vulnerability details

Impact

All pools get assigned to the same multisig, assuming the protocol runs at least 1 active pool every time. Every minipool created is assigned a multisig, which cannot be changed later. The protocol selects a multisig for this using MinipoolManager.requireNextActiveMultisig, which returns the first enabled multisig.

Filename: contracts/contract/MinipoolManager.sol
236:    		address multisig = multisigManager.requireNextActiveMultisig();

To configure, such that any new pool gets assigned a new multisig, the previous has to be disabled. But comments indicate that disabling a multisig, will also disable validations by any pools that have that multisig.

Filename: contracts/contract/MultisigManager.sol
67:    	/// @dev this will prevent the multisig from completing validations. The minipool will need to be manually reassigned to a new multisig
68:   	function disableMultisig(address addr) external guardianOrSpecificRegisteredContract("Ocyticus", msg.sender) {

The code doesn't contain any function to reassign a pool to a new multisig. So, if the protocol always has at least 1 minipool running, it becomes impossible to change the multisig.

Proof of Concept

Creating a new pool will assign to it the first enables multisig. Any new pool created from when this pool started to when this pool ends, will have the same multisig, since disabling that multisig to change to another, will disable validation by the earlier pool. So, assuming the protocol always has 1 pool active, that multisig could never be changed.

Tools Used

Manual inspection

Add a function to reassign all pools of a to-be-disabled multisig to a different multisig. This may include logic to transfer the staking funds plus any rewards, from the old multisig to the new multisig, through the reassigning function.

#0 - c4-judge

2023-01-08T13:26:12Z

GalloDaSballo marked the issue as duplicate of #702

#1 - c4-judge

2023-02-08T19:58:15Z

GalloDaSballo marked the issue as satisfactory

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter