PoolTogether V5: Part Deux - nadin's results

A protocol for no-loss prize savings.

General Information

Platform: Code4rena

Start Date: 02/08/2023

Pot Size: $42,000 USDC

Total HM: 13

Participants: 45

Period: 5 days

Judge: hickuphh3

Total Solo HM: 5

Id: 271

League: ETH

PoolTogether

Findings Distribution

Researcher Performance

Rank: 3/45

Findings: 2

Award: $2,768.02

🌟 Selected for report: 1

🚀 Solo Findings: 1

Findings Information

🌟 Selected for report: nadin

Labels

bug
2 (Med Risk)
high quality report
primary issue
selected for report
sponsor confirmed
M-02

Awards

2291.9874 USDC - $2,291.99

External Links

Lines of code

https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/libraries/ContinuousGDA.sol#L34-L36 https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/libraries/ContinuousGDA.sol#L64 https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/libraries/ContinuousGDA.sol#L85-L87 https://github.com/PaulRBerg/prb-math/blob/5959ef59f906d689c2472ed08797872a1cc00644/src/sd59x18/Math.sol#L168-L181

Vulnerability details

Impact

ContinuousGDA.sol inherits a version of PRB Math that contains a vulnerability in the SD59x18.exp() function, which can be reverted on hugely negative numbers. SD59x18.exp() is used for calculations in ContinuousGDA.sol#purchasePrice() , ContinuousGDA.sol#purchaseAmount() and ContinuousGDA.sol#computeK(). Recently, the creators of the PRBMath have acknowledged this situation. Here is the corresponding link. This issue should be proactively corrected by PoolTogether to avoid unexpected results that corrupt the protocol's computation flow.

Proof of Concept

There are 05 instances of this issue: see here

File: ContinuousGDA.sol 34: topE = topE.exp().sub(ONE); 36: bottomE = bottomE.exp(); 64: SD59x18 exp = _decayConstant.mul(_timeSinceLastAuctionStart).exp(); 85: SD59x18 eValue = exponent.exp(); 87: SD59x18 denominator = (_decayConstant.mul(_purchaseAmount).div(_emissionRate)).exp().sub(ONE);

Proof of the bug acknowledgment by the creator of the PRBMath SD59x18.exp() correctly returns 0 for inputs less than (roughly) -41.45e18, however it starts to throw PRBMath_SD59x18_Exp2_InputTooBig when the input gets hugely negative. This is because of the unchecked multiplication in exp() overflowing into positive values: see here

function exp(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); // This check prevents values greater than 192e18 from being passed to {exp2}. if (xInt > uEXP_MAX_INPUT) { revert Errors.PRBMath_SD59x18_Exp_InputTooBig(x); } unchecked { // Inline the fixed-point multiplication to save gas. int256 doubleUnitProduct = xInt * uLOG2_E; // <== overflow result = exp2(wrap(doubleUnitProduct / uUNIT)); } }

Tools Used

Manual Review and Proof of the bug acknowledgment by the creator of the PRBMath

A potential fix would be to compare the input with the smallest (most negative) number that can be safely multiplied by uLOG2_E, and return 0 if it's smaller. Alternatively, exp() could return 0 for inputs smaller than -41.45e18, which are expected to be truncated to zero by exp2() anyway.

Assessed type

Math

#0 - c4-pre-sort

2023-08-08T03:17:18Z

raymondfam marked the issue as primary issue

#1 - c4-pre-sort

2023-08-08T05:26:21Z

raymondfam marked the issue as high quality report

#2 - c4-sponsor

2023-08-10T19:50:31Z

asselstine marked the issue as sponsor confirmed

#3 - c4-judge

2023-08-14T09:47:52Z

HickupHH3 marked the issue as selected for report

#4 - HickupHH3

2023-08-14T09:51:10Z

Would have been nice to see a concrete example where the input < -41.45e18.

Given that the pricing formula parameters are determined by the liquidation pair creator, it is a possibility to achieve this condition and have this bug invoked.

Findings Information

🌟 Selected for report: MohammedRizwan

Also found by: MohammedRizwan, nadin, ptsanev

Labels

bug
2 (Med Risk)
satisfactory
sponsor confirmed
duplicate-31

Awards

476.0281 USDC - $476.03

External Links

Lines of code

https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationPairFactory.sol#L65-L108

Vulnerability details

Impact

Allowing creation of new LiquidationPairs by Re-org attack may adversely affect pricing in LiquidationPair.sol contracts.

Proof of Concept

The LiquidationPairFactory.sol#createPair() function deploys a new LiquidationPair using the create, where the address derivation depends only on the arguments passed. At the same time, some of the chains like Arbitrum and Polygon are suspicious of the reorg attack. LiquidationPairFactory.sol#createPair()

File: LiquidationPairFactory.sol function createPair( ILiquidationSource _source, address _tokenIn, address _tokenOut, uint32 _periodLength, uint32 _periodOffset, uint32 _targetFirstSaleTime, SD59x18 _decayConstant, uint112 _initialAmountIn, uint112 _initialAmountOut, uint256 _minimumAuctionAmount ) external returns (LiquidationPair) { LiquidationPair _liquidationPair = new LiquidationPair( // @audit-issue Reorg Attack _source, _tokenIn, _tokenOut, _periodLength, _periodOffset, _targetFirstSaleTime, _decayConstant, _initialAmountIn, _initialAmountOut, _minimumAuctionAmount ); allPairs.push(_liquidationPair); deployedPairs[_liquidationPair] = true; emit PairCreated( _liquidationPair, _source, _tokenIn, _tokenOut, _periodLength, _periodOffset, _targetFirstSaleTime, _decayConstant, _initialAmountIn, _initialAmountOut, _minimumAuctionAmount ); return _liquidationPair; }

Optimistic rollups (Optimism/Arbitrum) are also suspect to reorgs since if someone finds a fraud the blocks will be reverted, even though the user receives a confirmation. Can refer this an issue previously report here to have more understanding about it.

Tools Used

Manual review and previously report here

Deploy createPair() via create2 with salt.

Assessed type

Other

#0 - c4-pre-sort

2023-08-07T23:46:51Z

raymondfam marked the issue as primary issue

#1 - c4-sponsor

2023-08-10T19:58:08Z

asselstine marked the issue as sponsor confirmed

#2 - HickupHH3

2023-08-12T08:39:54Z

Allowing this to remain as medium because it "adversely affect pricing". Would be nice to see more concrete proof though:

where the address derivation depends only on the arguments passed.

true for create2, not for create, so I suppose one could pass in less favourable arguments.

#3 - c4-judge

2023-08-12T08:39:58Z

HickupHH3 marked the issue as selected for report

#4 - stalinMacias

2023-08-14T19:24:29Z

Hey @HickupHH3 Can I ask how is the reorg-attack causing any harm to the protocol? The warden's statement " may adversely affect pricing in LiquidationPair.sol contracts." is very vague and there is not proof of how the pricing is impacted.

As for the previous report that the warden used as a reference for his finding, I think the reorg attack is valid in that protocol because the deployed contracts have a payable constructor that is expecting to receive ETH, and if the reorg attack happens then the ETH sent by the deployer is lost, but in this case, for this protocol, the deployed contracts are not payable, so what's the incentive to cause a "reorg-attack", and more important, what are the consequences?

IMHO, if there is no proof about how the pricing may be affected, this should be assessed as a Q/A

#5 - HickupHH3

2023-08-15T03:02:05Z

@stalinMacias It's not so much causing a re-org attack, but taking advantage of it.

Because create is used, you could theoretically deploy with different params but have the same contract address in this scenario, then re-send (replay) the liquidator's tx to auction for more / less POOL tokens.

I shouldn't be doing the work to reason it out though, burden of proof lies with the wardens. None have sufficient justification to warrant the medium severity.

Downgrading to QA.

#6 - c4-judge

2023-08-15T03:02:15Z

HickupHH3 changed the severity to QA (Quality Assurance)

#7 - c4-judge

2023-08-15T03:02:34Z

HickupHH3 marked the issue as not selected for report

#8 - c4-judge

2023-08-15T03:02:39Z

HickupHH3 marked the issue as grade-c

#9 - Nadinnnn

2023-08-15T07:06:18Z

I agree with this issue being downgraded to QA, but still having an attack like you helped us understand more about how this issue can be exploited. The sponsor has also confirmed this issue and I think they will fix it. So I think this case can get grade A.

#10 - c4-judge

2023-08-17T14:50:07Z

This previously downgraded issue has been upgraded by HickupHH3

#11 - c4-judge

2023-08-17T14:50:17Z

HickupHH3 marked issue #31 as primary and marked this issue as a duplicate of 31

#12 - c4-judge

2023-08-17T15:02:20Z

HickupHH3 marked the issue as satisfactory

#13 - c4-judge

2023-08-17T15:04:12Z

HickupHH3 marked the issue as not a duplicate

#14 - c4-judge

2023-08-17T15:04:28Z

HickupHH3 changed the severity to QA (Quality Assurance)

#15 - c4-judge

2023-08-17T15:04:40Z

This previously downgraded issue has been upgraded by HickupHH3

#16 - c4-judge

2023-08-17T15:04:40Z

This previously downgraded issue has been upgraded by HickupHH3

#17 - c4-judge

2023-08-17T15:04:50Z

HickupHH3 marked the issue as duplicate of #31

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