A permissionless protocol to leverage trade any ERC20 tokens.
Platform: Code4rena
Start Date: 11/12/2023
End Date: 21/12/2023
Period: 10 days
Status: Completed
Pot Size: $24,150 USDC
Participants: 5
Reporter: PaperParachute
Judge: 0xLeastwood
Id: 312
League: ETH
Total Prize Pool: $24,150 USDC
Join C4 Discord to register
Submit findings using the C4 form
Starts December 11, 2023 20:00 UTC
Ends December 21, 2023 20:00 UTC
The 4naly3er report can be found here.
Slither results can be found in here. We’ve reviewed all findings that relate to Particle’s code (excluding imported libraries), and found no concerning issues.
Note for C4 wardens: Anything included in this Automated Findings / Publicly Known Issues
section is considered a publicly known issue and is ineligible for awards.
Particle LAMM protocol enables permissionless leverage trading for any ERC20 tokens. The key idea is to borrow concentrated liquidity from AMMs (Uniswap v3 as a start). For a concentrated liquidity position, its price boundaries mathematically define the amount of tokens to convert at all price points. When borrowing from a concentrated liquidity position, the protocol calculates the exact amount required to top up upfront, such that the contract always locks enough tokens in case the price moves adversely to a price boundary. This design eliminates the need for a price oracle.
libraries/FullMath.sol
, libraries/TickMath.sol
, libraries/LiquidityAmounts.sol
, libraries/PoolAddress.sol
and interfaces/INonfungiblePositionManager.sol
are adopted from Uniswap production code to support solidity 0.8.23. The diff can be examined via the following commands.
diff -u ./lib/v3-core/contracts/libraries/FullMath.sol ./contracts/libraries/FullMath.sol --ignore-space-change diff -u ./lib/v3-core/contracts/libraries/TickMath.sol ./contracts/libraries/TickMath.sol --ignore-space-change diff -u ./lib/v3-periphery/contracts/libraries/LiquidityAmounts.sol ./contracts/libraries/LiquidityAmounts.sol --ignore-space-change diff -u ./lib/v3-periphery/contracts/libraries/PoolAddress.sol ./contracts/libraries/PoolAddress.sol --ignore-space-change diff -u ./lib/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol ./contracts/interfaces/INonfungiblePositionManager.sol --ignore-space-change
9
1299
15
1 interface, 9 structs
Inheritance
95%
False
AMM, ERC-20 Token
True
Uniswap v3 basic math, Uniswap liquidity logic
False
Uniswap basic math, most importantly conversion of liquidity into different token amounts under different price points
False
False
About the design: (1) is the collateral guarantee safe in all conditions, meaning, the LPs suffers no higher impermanent loss than Uniswap itself (except for Uniswap's own rounding error) (2) borrowed liquidity should earn no less fees compared to the same liquidity would have otherwise earned in the pool (3) do we use uniswap critical variables correctly, such as the feeGrowth parameters and how we handle the premiumPortion (4) are the liquidation conditions safe or exploitable. In addition, about the implementation details: access control, token edge-case handling, reentrancy risks, and proper integration with external contracts.
Cloning with submodules
git clone --recurse-submodules
Updating with submodule if the repo was cloned without --recurse-submodules
git submodule update --init --recursive
Add the following to .env
PRIVATE_KEY=[WALLET_PRIVATE_KEY] MAINNET_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/[ALCHEMY_API_KEY] GOERLI_RPC_URL=https://eth-goerli.g.alchemy.com/v2/[ALCHEMY_API_KEY] ETHERSCAN_API_KEY=[ETHERSCAN_API_KEY]
Run
foundryup source .env
Unit tests
forge test -vv --fork-url $MAINNET_RPC_URL --fork-block-number [BLOCK_NUMBER]
Gas report
forge test --gas-report --fork-url $MAINNET_RPC_URL --fork-block-number [BLOCK_NUMBER]
Coverage
forge coverage --ir-minimum --fork-url $MAINNET_RPC_URL --fork-block-number [BLOCK_NUMBER]
Deploy
forge script script/DeployPositionManager.s.sol:DeployParticlePositionManager --rpc-url $GOERLI_RPC_URL/$MAINNET_RPC_URL --private-key $PRIVATE_KEY --broadcast --verify -vv
Verify
forge verify-contract [CONTRACT_ADDRESS] contracts/protocol/ParticlePositionManager.sol:ParticlePositionManager --chain goerli/mainnet --watch
Dependencies
yarn install source .env
Deploy
yarn deploy script/deployPositionManager.ts --network goerli/mainnet --show-stack-traces
Verfiy
yarn verify --network goerli/mainnet [IMPLMENTATION_ADDRESS] yarn verify --network goerli/mainnet [PROXY_ADDRESS] [IMPLMENTATION_ADDRESS] 0x