
코드를 통해 DeFi의 차익거래 기회 식별
개요
탈중앙화 금융(DeFi)은 증권사, 거래소, 은행과 같은 중앙화된 기관 없이 블록체인 상의 스마트 계약을 통해 금융 서비스를 제공하는 시스템입니다. DeFi에서는 정산, 차익거래 등 다양한 차익 실현 기회가 존재합니다. 본 문서는 주요 탈중앙화 거래소(DEX) 및 에이그리게이터(Aggregator)의 스마트 계약 코드에서 발견할 수 있는 잠재적 차익 실현 기회를 분석합니다.
분석
Uniswap
Uniswap은 자동 시장 제조자(AMM) 모델을 채택한 탈중앙화 암호화폐 거래 플랫폼로, 현재 Uniswap V2와 V3 두 가지 주요 버전이 사용되고 있습니다. 각각의 버전에서 발생 가능한 차익 실현 기회를 개별적으로 분석합니다.
Uniswap V2 Router
Uniswap V2에서 사용자는 일반적으로 Router 계약을 통해 Pair 및 Factory 계약과 상호작용합니다. 보통 Router 계약은 중계 역할만 수행하며 토큰을 보유하지 않지만, 에어드랍이나 전송 오류 등으로 인해 Router 계약 내에 ERC-20 토큰이 남아 있을 수 있습니다. 이러한 토큰을 어떻게 회수할 수 있을까요?
Uniswap V2 Router 02 계약 코드를 분석하면, removeLiquidityETHSupportingFeeOnTransferTokens 함수가 존재함을 확인할 수 있습니다.

이 함수는 WETH가 포함된 유동성 풀에서 유동성을 제거할 때 사용되며, 내부적으로 removeLiquidity를 호출할 때 to 주소로 address(this)(즉 Router 계약 자체)를 사용하여 두 종류의 토큰을 먼저 Router 계약으로 이체한 후, 다시 사용자가 지정한 주소로 전송합니다. 이 과정에서 WETH의 수량은 removeLiquidity의 반환값에 의해 결정되어 수정 불가능하지만, 다른 토큰의 수량은 balanceOf(address(this)) 즉, Router 계약 내 잔고 기준으로 전송됩니다.
따라서 위 분석을 바탕으로 다음과 같은 차익 실현 프로세스를 도출할 수 있습니다:
- Router 02 계약 내에 ERC-20 토큰이 존재하는지 모니터링
- addLiquidityETH 함수를 호출하여 해당 ERC-20 토큰과 WETH로 유동성 추가
- removeLiquidityETHSupportingFeeOnTransferTokens 함수를 호출하여 유동성 제거
제한 사항:
- 해당 토큰이 처음으로 WETH와 페어를 구성하는 경우, 초기 유동성 공급 시 MINIMUM_LIQUIDITY만큼 소량 손실 발생
- Router 02 계약 내의 WETH 또는 ETH를 추출하는 방법은 현재로서는 발견되지 않음
Uniswap V2 Pair
Uniswap V2의 Pair 계약(유동성 풀)은 두 종류의 토큰을 보유하고 있으며, 잔고를 reserve 변수로 관리합니다. 실제 balanceOf(address(this))와 reserve 값 사이에 차이가 발생할 수 있는데, 예를 들어 사용자가 실수로 토큰을 직접 전송했을 경우입니다. 이 차이를 해소하기 위해 skim 함수를 제공하며, 이를 호출하면 차액만큼의 토큰을 지정된 주소로 전송할 수 있습니다.

skim 함수는 유동성 풀 내 두 토큰의 실제 잔고와 reserve 간의 차이를 to 주소로 전송합니다.
또한 유동성 풀에는 실수 전송, 에어드랍 등의 이유로 페어를 구성하는 두 토큰 외의 다른 ERC-20 토큰도 존재할 수 있습니다. 이러한 토큰은 어떻게 회수할 수 있을까요?
코드 분석 결과, 일반적인 경우에는 다른 토큰을 회수할 수 없습니다. 단 하나의 예외는 유동성 풀 내에 그 자체의 LP 토큰이 존재하는 경우입니다.
이러한 상황에서는 burn 함수를 호출하여 유동성을 제거하고, 대응하는 두 토큰을 회수할 수 있습니다.

Uniswap V3 SwapRouter
Uniswap V3의 SwapRouter 계약 역시 V2 Router와 마찬가지로 ERC-20 토큰 및 ETH가 누적될 수 있습니다. 다행히도 SwapRouter는 이러한 토큰을 쉽게 회수할 수 있도록 설계되어 있습니다.
ERC-20 토큰 회수에는 sweepToken 함수를 사용할 수 있습니다.

ETH 회수는 refundETH 함수를 통해 가능합니다.

또한 unwrapWETH9 함수를 직접 호출하여 WETH를 ETH로 변환하고 회수할 수 있습니다.

이상은 Uniswap V3 SwapRouter 계약에 대한 차익 실현 분석입니다. 한편, Uniswap V3 Pool 계약은 다른 토큰을 회수할 수 있는 메커니즘이 없으며, V2의 reserve와 balance 간 차이 문제도 존재하지 않습니다.
SushiSwap
SushiSwap은 원래 Uniswap의 포크 프로젝트였으나, 이후 독립된 생태계로 성장하여 다양한 금융 서비스를 제공하고 있습니다.
SushiSwap은 Uniswap V2와 구조가 유사하므로, 앞서 언급한 Uniswap V2의 차익 실현 기법들은 SushiSwap에도 동일하게 적용 가능합니다.
SushiXSwap
SushiXSwap은 LayerZero 기반의 멀티체인 거래 프로토콜로, Optimism, Arbitrum, Fantom, BNB Chain, Polygon, Avalanche 등에서 크로스체인 거래를 지원합니다.
SushiXSwap 계약 내 토큰은 어떻게 회수할 수 있을까요?
SushiXSwap의 핵심 기능은 cook 함수를 통해 구현되며, 다음 작업들이 지원됩니다.

ACTION_DST_WITHDRAW_TOKEN 작업은 다음과 같이 구현되어 있습니다.

cook 함수에 전달된 data를 디코딩한 후, amount 값이 0인지 확인하고, 0일 경우 해당 토큰 또는 ETH의 계약 내 전체 잔고로 설정합니다. 이후 _transferTokens를 호출하여 지정된 주소로 전송합니다.

따라서 actions 배열에 ACTION_DST_WITHDRAW_TOKEN을 포함시키고, data 내에 전송할 토큰, 수신 주소, 수량을 적절히 설정하면 SushiXSwap 계약 내 토큰을 회수할 수 있습니다.
Sushi BentoBox
BentoBox는 SushiSwap 생태계 내 고도로 최적화된 금융 플랫폼으로, 사용자가 토큰을 예치하고, 차용하며, 이자를 벌 수 있는 스마트 계약입니다. 주요 목적은 DeFi에서의 수익 극대화입니다.
이더리움 상의 BentoBox 계약에는 다수의 토큰이 저장되어 있으며, 차익 실현 기회가 존재할 수 있습니다.
BentoBox의 deposit 함수는 다음과 같습니다.

토큰 주소, 출금 주소(from), 수신 주소(to), 수량(amount), 지분(share) 등을 입력받으며, total.elastic이라는 값을 통해 계약 내 잔고를 관리합니다. 이 값은 Uniswap의 reserve와 유사합니다. 그러나 실제 _tokenBalanceOf(token)과 차이가 발생할 수 있습니다.
deposit 함수의 195~198행에서 amount <= _tokenBalanceOf(token).sub(total.elastic) 조건을 검사합니다. 이 조건을 활용하면, 실제 잔고와 elastic 값의 차이만큼을 자신의 계좌 잔고로 전환할 수 있습니다.
구체적으로, token에는 차이가 발생한 토큰 주소를, amount에는 그 차이값을, from에는 BentoBox 계약 주소를, to에는 자신의 주소를 설정합니다. 207행에서는 from이 계약 주소이므로 실제 전송 없이 내부 잔고만 조정되며, 결과적으로 차이분이 사용자의 BentoBox 내 잔고로 반영됩니다.
DODO
DODO는 독자적인 PMM(Proactive Market Making) 알고리즘을 사용하는 탈중앙화 거래 플랫폼로, 자체 유동성과 외부 거래소의 유동성을 결합하여 효율적인 거래를 제공합니다.
사용자는 DODO V2 Proxy 02 계약을 통해 토큰 교환을 수행합니다. 이 계약도 여러 이유로 토큰이 누적될 수 있으며, 이를 어떻게 회수할 수 있을까요?
DODO V2 Proxy 02
DODO V2 Proxy 02 계약에는 externalSwap 함수가 존재하며, 0x, 1inch 등의 외부 거래소를 통해 교환을 수행합니다.

1719~1721행에서 파라미터 유효성 검사를 수행하며, 1724행에서 fromToken이 ETH가 아닐 경우 사용자로부터 토큰을 계약으로 이체합니다. 이후 DODOApprove 계약을 분석하면, fromTokenAmount를 0으로 설정하면 인증 절차를 우회할 수 있음을 알 수 있습니다.

다음으로 swapTarget과 calldataConcat이 사용자에 의해 제어되며, 화이트리스트에 등록된 외부 계약(ex. 0x, 1inch)을 호출하도록 설정할 수 있습니다. 또한 calldataConcat을 해당 계약의 view 함수로 인코딩하여 require 조건을 통과시킬 수 있습니다.

이후 계약 내 toToken(ERC-20 또는 ETH)이 모두 호출자에게 전송되며, minReturnAmount를 매우 작은 값으로 설정하면 최소 수령량 검사를 통과할 수 있습니다. 이후 두 함수 호출은 무의미합니다.

위 과정을 통해 DODO V2 Proxy 02 계약 내 ERC-20 토큰과 ETH를 성공적으로 회수할 수 있습니다.
1inch
1inch는 여러 DEX의 유동성을 통합하여 최적의 거래 가격을 제공하는 탈중앙화 거래소 에이그리게이터입니다. 스마트 계약을 통해 여러 거래소에서 최저 슬리피지를 제공하며, 유동성 마이닝 및 거버넌스 토큰 기능도 제공합니다.
1inch의 주요 계약은 AggregationRouter이며, 현재 V4와 V5 버전이 널리 사용되고 있습니다. 이 계약들 역시 다양한 이유로 토큰을 보유할 수 있으며, 특정 파라미터를 조작하여 토큰을 회수할 수 있습니다.
AggregationRouterV5
AggregationRouterV5는 swap 함수를 제공하며, 그 구현은 다음과 같습니다.

desc 구조체 내 minReturnAmount를 검사한 후, srcToken과 dstToken을 추출합니다. 986~997행에서는 desc의 flags와 srcToken을 조작하여 전송 로직을 우회할 수 있습니다.

_execute 함수 실행 시 executor가 사용자에 의해 제어되므로, 0 주소를 사용하여 call 실패를 방지할 수 있습니다.

다음으로 계약 내 dstToken 잔고를 조회하며, 1007~1018행에서는 desc의 flags 및 minReturnAmount를 조작하여 검사를 통과할 수 있습니다.

마지막으로 계약 내 모든 dstToken 잔고가 dstReceiver 주소(사용자 제어)로 전송됩니다.

이러한 절차를 통해 AggregationRouterV5 계약 내 토큰을 성공적으로 회수할 수 있습니다.
AggregationRouterV4
AggregationRouterV4는 V5와 유사하며, swap 함수의 구현도 거의 동일합니다.

V5가 call 처리를 최적화했을 뿐이며, 기본적인 로직은 동일하므로, V5에서 사용한 방법을 그대로 적용하여 AggregationRouterV4 계약 내 토큰도 회수할 수 있습니다.
결론
본 문서는 주요 탈중앙화 거래소 및 에이그리게이터의 일부를 소개하고, 스마트 계약 수준에서 발생 가능한 차익 실현 기회를 분석했습니다. 실제 적용 시에는 GAS 비용, 노드 반응 속도 등 다양한 외부 요인이 성패를 좌우할 수 있음을 유념해야 합니다.
TechFlow 공식 커뮤니티에 오신 것을 환영합니다
Telegram 구독 그룹:https://t.me/TechFlowDaily
트위터 공식 계정:https://x.com/TechFlowPost
트위터 영어 계정:https://x.com/BlockFlow_News














