| name | defi-amm-security |
| description | Solidity AMM 컨트랙트, 유동성 풀, 스왑 플로를 위한 보안 체크리스트입니다. 재진입, CEI 순서, donation/inflation 공격, 오라클 조작, 슬리피지, 관리자 제어, 정수 연산을 다룹니다. |
| origin | ECC direct-port adaptation |
| version | 1.0.0 |
DeFi AMM Security
Solidity AMM 컨트랙트, LP vault, 스왑 함수에 대한 치명적 취약점 패턴과 강화 구현 패턴입니다.
사용 시점
- Solidity AMM 또는 유동성 풀 컨트랙트를 작성하거나 감사할 때
- 토큰 잔고를 보유하는 swap, deposit, withdraw, mint, burn 플로를 구현할 때
- share/reserve 계산에
token.balanceOf(address(this))를 사용하는 컨트랙트를 리뷰할 때
- DeFi 프로토콜에 fee setter, pauser, oracle update 같은 admin 기능을 추가할 때
동작 방식
체크리스트 + 패턴 라이브러리로 사용합니다. 모든 사용자 진입점을 아래 범주로 점검하고 손수 만든 변형보다 강화된 예시를 우선합니다.
예시
재진입: CEI 순서 강제
취약한 예:
function withdraw(uint256 amount) external {
require(balances[msg.sender] >= amount);
token.transfer(msg.sender, amount);
balances[msg.sender] -= amount;
}
안전한 예:
function withdraw(uint256 amount) external nonReentrant {
require(balances[msg.sender] >= amount, "Insufficient");
balances[msg.sender] -= amount;
token.safeTransfer(msg.sender, amount);
}
강화된 라이브러리가 있는데 재진입 방어를 직접 구현하지 않습니다.
Donation / inflation 공격
token.balanceOf(address(this))를 share 계산에 직접 쓰면 공격자가 의도된 경로 밖에서 토큰을 보내 분모를 조작할 수 있습니다.
// Vulnerable
function deposit(uint256 assets) external returns (uint256 shares) {
shares = (assets * totalShares) / token.balanceOf(address(this));
}
// Safe
uint256 private _totalAssets;
핵심은 내부 accounting을 별도로 추적하고 실제 수령 토큰 수를 계산하는 것입니다.
오라클 조작
spot price는 flash loan으로 조작 가능합니다. TWAP를 우선합니다.
슬리피지 보호
모든 swap 경로는 caller가 제공한 slippage와 deadline을 받아야 합니다.
function swap(
uint256 amountIn,
uint256 amountOutMin,
uint256 deadline
) external returns (uint256 amountOut) {
require(block.timestamp <= deadline, "Expired");
amountOut = _calculateOut(amountIn);
require(amountOut >= amountOutMin, "Slippage exceeded");
}
안전한 reserve 수학
큰 reserve 계산에는 naive a * b / c보다 mulDiv류의 안전한 primitive를 사용합니다.
관리자 제어
소유권 이전은 명시적 수락이 있는 패턴을 선호하고, privileged path는 전부 gate 처리합니다.
보안 체크리스트
- 재진입 노출 진입점에
nonReentrant
- CEI 순서 준수
- share 계산이 raw
balanceOf(address(this))에 의존하지 않음
- ERC-20 전송에
SafeERC20
- deposit 시 실제 수령량 측정
- 오라클은 TWAP 또는 조작 저항 소스 사용
- swap에
amountOutMin과 deadline 필수
- 오버플로 민감 reserve 수학에
mulDiv 같은 안전 primitive 사용
- admin 함수 접근 제어
- emergency pause 존재 및 테스트
- production 전 static analysis와 fuzzing 수행