ElasticSwap contest - danb's results

The first AMM for Elastic Supply Tokens.

General Information

Platform: Code4rena

Start Date: 20/01/2022

Pot Size: $50,000 USDC

Total HM: 3

Participants: 35

Period: 7 days

Judge: GalloDaSballo

Total Solo HM: 2

Id: 77

League: ETH

ElasticSwap

Findings Distribution

Researcher Performance

Rank: 5/35

Findings: 2

Award: $1,250.60

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: WatchPug

Also found by: camden, danb, hyh

Labels

bug
duplicate
2 (Med Risk)
sponsor acknowledged

Awards

845.0019 USDC - $845.00

External Links

Handle

danb

Vulnerability details

https://github.com/code-423n4/2022-01-elasticswap/blob/main/elasticswap/src/libraries/MathLib.sol#L493

Impact

first liquidity provider can drain others

Proof of Concept

consider the following scenario: a malicious user creates the usdc-usdt pool, they provided 1 basic unit of usdt and 1 basic unit of usdc (1/10**6 each)

the amount of liquidity token that will be minted is sqrt(1*1) = 1.

next, they will transfer 1M usdc and 1M usdt, this won't change the amount of liquidity tokens

now the value of 1 liquidity tokens (the total supply) is equal to the entire pool reserves.

this means that providing liquidity which is less than the pool reserves will cause minting 0 liquidity token, because of rounding down to zero

the next liquidity provider provides 500K USDT and 500K USDC.

the amount of liquidity token that will be minted for them will round down to zero, and they will end up paying 500k usdc and 500k usdt and get nothing.

this money will go to the pool reserves so the attacker can just withdraw their liquidity and get all of the money from the new liquidity provider because they own the entire liquidity tokens supply.

the attacker can also wait for more liquidity providers to provide liquidity so they can take their money.

Tools Used

manual review

I suggest using the same mechanism in uniswap v2 to prevent such attack, locking the first 1000 liquidity tokens of the first liquidity provider, this makes the attack not practical.

https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2Pair.sol#L120 https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2Pair.sol#L121

#0 - 0xean

2022-01-31T15:05:31Z

Yup, we are going to implement that. Thank you for the report.

#1 - 0xean

2022-01-31T15:50:31Z

dupe of #145

Findings Information

🌟 Selected for report: pauliax

Also found by: 0x1f8b, Jujic, danb, harleythedog

Labels

bug
duplicate
1 (Low Risk)

Awards

202.8004 USDC - $202.80

External Links

Handle

danb

Vulnerability details

https://github.com/code-423n4/2022-01-elasticswap/blob/main/elasticswap/src/libraries/MathLib.sol#L640 https://github.com/code-423n4/2022-01-elasticswap/blob/main/elasticswap/src/libraries/MathLib.sol#L676

> instead if >=

Impact

the function might fail unexpectedly.

Proof of Concept

a user wants to swap with zero slippage.

they check the amount they would get from the swap before they call the function, and set the minimum amount to this.

there is no slippage, but the transaction still fails, because it requires the amount to be greater than the minimum but it's equal.

Tools Used

manual review

change > to >=

#0 - 0xean

2022-01-31T15:01:09Z

dupe of #175

Findings Information

🌟 Selected for report: harleythedog

Also found by: 0x1f8b, cmichel, danb, pauliax

Labels

bug
duplicate
1 (Low Risk)

Awards

202.8004 USDC - $202.80

External Links

Handle

danb

Vulnerability details

https://github.com/code-423n4/2022-01-elasticswap/blob/main/elasticswap/src/contracts/Exchange.sol#L135

Impact

tokens with fee on transfer can still be added. if the balance is not zero their is no check for fee on transfer.

Proof of Concept

alice create a pair with a token with fee on transfer, she transfer a tiny amount to the pool and then provides liquidity. the check

if (isExchangeEmpty) { require( IERC20(baseToken).balanceOf(address(this)) == tokenQtys.baseTokenQty, "Exchange: FEE_ON_TRANSFER_NOT_SUPPORTED" ); }

is not reached because the pool is not empty.

check if the pool is empty by totalSupply instead of the balance, and compare the balance before the transfer to the balance after the transfer.

#0 - 0xean

2022-01-31T14:41:12Z

dupe of #119

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