
Xác định cơ hội chênh lệch giá trong DeFi thông qua mã code
Tuyển chọn TechFlowTuyển chọn TechFlow

Xác định cơ hội chênh lệch giá trong DeFi thông qua mã code
Bài viết này sẽ phân tích một số cơ hội chênh lệch giá có thể tồn tại trong mã hợp đồng của các sàn giao dịch phi tập trung và công cụ tổng hợp.
Tổng quan
Tài chính phi tập trung (tiếng Anh: Decentralized finance, thường gọi là DeFi) là hình thức tài chính được xây dựng trên nền tảng blockchain, không phụ thuộc vào các tổ chức tài chính như công ty môi giới, sàn giao dịch hay ngân hàng để cung cấp các công cụ tài chính, mà thay vào đó sử dụng các hợp đồng thông minh trên blockchain để thực hiện các hoạt động tài chính. Trong hệ sinh thái DeFi tồn tại rất nhiều cơ hội chênh lệch giá, bao gồm nhưng không giới hạn ở thanh lý tài sản và arbitrage chênh lệch giá. Bài viết này sẽ phân tích một số cơ hội arbitrage tiềm năng trong mã hợp đồng của các sàn giao dịch phi tập trung (DEX) và các bộ tổng hợp (Aggregator).
Phân tích
Uniswap
Uniswap là một nền tảng giao dịch tiền mã hóa phi tập trung sử dụng mô hình nhà tạo lập thị trường tự động (AMM), hiện nay có hai phiên bản phổ biến là Uniswap V2 và Uniswap V3. Chúng ta sẽ lần lượt phân tích những cơ hội arbitrage tiềm ẩn trong từng phiên bản.
Uniswap V2 Router
Trong Uniswap V2, người dùng thường tương tác với các hợp đồng Pair và Factory thông qua hợp đồng Router. Thông thường, Router chỉ đóng vai trò trung chuyển token trong giao dịch chứ không lưu trữ token. Tuy nhiên, do các nguyên nhân như airdrop hoặc nhầm lẫn khi chuyển khoản, một số token vẫn có thể bị gửi vào hợp đồng Router. Vậy làm thế nào để rút những token này ra?
Qua việc phân tích mã nguồn của hợp đồng Uniswap V2 Router 02, phát hiện hàm removeLiquidityETHSupportingFeeOnTransferTokens:

Hàm này dùng để rút thanh khoản trong cặp có chứa WETH. Khi gọi hàm removeLiquidity bên trong, tham số địa chỉ "to" được truyền vào là address(this), nghĩa là cả hai loại token trước tiên sẽ được chuyển về hợp đồng Router, sau đó Router mới chuyển tiếp đến địa chỉ đích. Mặc dù lượng WETH được chuyển về là cố định (trả về từ removeLiquidity và không thể thay đổi), lượng token còn lại được chuyển đi lại bằng balanceOf(address(this)) — tức là toàn bộ số dư hiện có của token đó trong hợp đồng Router.
Do đó, dựa trên phân tích trên, chúng ta có thể đưa ra quy trình arbitrage như sau:
-
Theo dõi và phát hiện ERC-20 token tồn tại trong hợp đồng Router 02;
-
Gọi hàm addLiquidityETH để thêm thanh khoản cho cặp token ERC-20 này và WETH;
-
Gọi hàm removeLiquidityETHSupportingFeeOnTransferTokens để rút thanh khoản.
Hạn chế:
-
Nếu cặp token này chưa từng tạo thanh khoản với WETH trước đó, việc thêm thanh khoản lần đầu sẽ mất một phần nhỏ thanh khoản (MINIMUM_LIQUIDITY);
-
Hiện tại chưa tìm thấy cách rút WETH và ETH khỏi hợp đồng Router 02.
Uniswap V2 Pair
Hợp đồng Uniswap V2 Pair, còn gọi là pool thanh khoản, lưu trữ hai loại token cung cấp thanh khoản. Do hợp đồng Pair sử dụng biến reserve để ghi nhận số dư thay vì balanceOf(address(this)), nên khi có ai đó vô tình gửi trực tiếp token thanh khoản vào hợp đồng, sẽ xuất hiện chênh lệch giữa balance và reserve. Hợp đồng Pair có hàm cân bằng tên là skim, chúng ta có thể gọi hàm này để rút lượng token chênh lệch đó ra:

Có thể thấy hàm này sẽ chuyển lượng token chênh lệch giữa balance và reserve của hai token trong pool đến địa chỉ "to".
Ngoài hai loại token này, đôi khi trong pool cũng có các token ERC-20 khác do gửi nhầm hoặc airdrop. Làm thế nào để rút những token này?
Sau khi phân tích mã nguồn, phát hiện không có cách nào trực tiếp rút các token này, ngoại trừ một trường hợp đặc biệt: khi trong pool tồn tại LP token của chính pool đó.
Trong trường hợp này, chúng ta có thể gọi hàm burn của hợp đồng Pair để rút thanh khoản và nhận lại hai loại token gốc:

Uniswap V3 SwapRouter
Hợp đồng SwapRouter của Uniswap V3 cũng gặp tình trạng tương tự như Router của Uniswap V2, tức là có thể tồn tại ERC-20 token và ETH. May mắn thay, SwapRouter cung cấp một vài hàm giúp dễ dàng rút các token này.
Để rút ERC-20 token, ta có thể dùng hàm sweepToken:

Để rút ETH, ta dùng hàm refundETH:

Hoặc có thể gọi trực tiếp hàm unwrapWETH9 để chuyển WETH thành ETH rồi rút ra:

Trên đây là phân tích arbitrage đối với hợp đồng SwapRouter của Uniswap V3.
Sau khi phân tích mã nguồn hợp đồng Pool của Uniswap V3, phát hiện không có cách nào để rút các token khác khỏi hợp đồng, cũng không tồn tại tình huống chênh lệch giữa balance và reserve như trong hợp đồng Pair của Uniswap V2.
SushiSwap
SushiSwap ban đầu là một dự án fork từ Uniswap, sau đó phát triển thành một hệ sinh thái độc lập, cung cấp nhiều sản phẩm và dịch vụ tài chính khác nhau.
Vì SushiSwap tương tự Uniswap V2, nên các phương pháp arbitrage đã nêu trên dành cho Uniswap V2 cũng áp dụng được cho SushiSwap.
SushiXSwap
SushiXSwap là giao thức giao dịch đa chuỗi do SushiSwap phát triển, dựa trên LayerZero, hỗ trợ các mạng lưới như Optimism, Arbitrum, Fantom, BNB Chain, Polygon và Avalanche. Người dùng có thể thực hiện giao dịch xuyên chuỗi giữa các mạng lưới và tài sản được hỗ trợ.
Làm thế nào để rút token khỏi hợp đồng SushiXSwap?
Các chức năng chính của SushiXSwap đều được thực hiện thông qua hàm cook, cung cấp một loạt thao tác với danh sách hỗ trợ như sau:

Trong đó có thao tác ACTION_DST_WITHDRAW_TOKEN, đoạn mã triển khai như sau:

Trước tiên giải mã dữ liệu "data" truyền vào hàm cook, kiểm tra xem amount có bằng 0 hay không, nếu bằng 0 thì đặt amount bằng số dư ERC-20 token hoặc ETH hiện có trong hợp đồng. Cuối cùng gọi _transferTokens để chuyển token đến địa chỉ chỉ định:

Do đó, chúng ta chỉ cần xây dựng đúng tham số "actions" và "datas" truyền vào hàm cook: đặt actions là ACTION_DST_WITHDRAW_TOKEN, trong data cấu hình token muốn chuyển, địa chỉ nhận và số lượng, là có thể rút token khỏi hợp đồng SushiXSwap.
Sushi BentoBox
Sushi BentoBox là một thành phần trong hệ sinh thái SushiSwap. BentoBox là một sản phẩm tối ưu lãi suất trong lĩnh vực tài chính phi tập trung (DeFi) với độ linh hoạt cao. Nói đơn giản, nó là một nền tảng hợp đồng thông minh cho phép người dùng lưu trữ, vay mượn và kiếm lãi. Mục tiêu chính của BentoBox là tối ưu hóa lợi nhuận cho người dùng trong lĩnh vực DeFi.
Hợp đồng BentoBox trên Ethereum đang lưu trữ một lượng lớn token. Liệu hợp đồng này có tiềm năng arbitrage hay không?
Người dùng có thể gửi tiền vào BentoBox thông qua hàm deposit, triển khai như sau:

Có thể thấy người dùng truyền vào địa chỉ token, địa chỉ khấu trừ, địa chỉ nhận, số lượng, cổ phần. Hàm thực hiện một loạt kiểm tra, sau đó chuyển đổi giữa amount và share. Điểm then chốt nằm ở dòng 195–198, nơi kiểm tra điều kiện: amount <= _tokenBalanceOf(token).sub(total.elastic).
Trong hợp đồng BentoBox, số dư token được ghi nhận bằng total.elastic, tương tự reserve trong hợp đồng Pair của Uniswap. Trong một số trường hợp, nó có thể chênh lệch với _tokenBalanceOf(token). Ta có thể tận dụng đặc điểm này của hàm deposit để chuyển phần chênh lệch thành số dư thật sự trong BentoBox.
Do đó, khi truyền tham số, ta đặt token là địa chỉ token có chênh lệch, amount bằng đúng phần chênh lệch, from là địa chỉ hợp đồng BentoBox, to là địa chỉ ví của mình. Đến dòng 207, do from là chính hợp đồng BentoBox, nên sẽ không thực hiện chuyển khoản, mà chỉ cập nhật lại giá trị total.elastic và _tokenBalanceOf(token), đồng thời chuyển phần chênh lệch thành số dư nội bộ cho địa chỉ "to".
DODO
DODO là một sàn giao dịch phi tập trung, sử dụng thuật toán tạo lập thị trường chủ động (PMM) độc quyền để cung cấp thanh khoản hiệu quả trên chuỗi cho các tài sản Web3. DODO vừa tự cung cấp thanh khoản, vừa tổng hợp thanh khoản từ các sàn giao dịch khác.
DODO có một loạt hợp đồng, trong đó người dùng thường dùng DODO V2 Proxy 02 để đổi token. Tương tự như Router của Uniswap, hợp đồng này cũng có thể lưu giữ một số token do nhiều nguyên nhân. Làm thế nào để rút những token này?
DODO V2 Proxy 02
Hợp đồng DODO V2 Proxy 02 có hàm externalSwap, dùng để gọi các nền tảng bên ngoài mà DODO tổng hợp (như 0x, 1inch) để thực hiện hoán đổi, đoạn mã triển khai như sau:

Dòng 1719–1721 thực hiện kiểm tra tham số đầu vào, sau đó dòng 1724 kiểm tra xem fromToken có phải là ETH hay không. Nếu không, sẽ chuyển token của người gọi vào hợp đồng và thực hiện ủy quyền. Sau khi phân tích mã DODOAPPROVE, phát hiện chỉ cần đặt fromTokenAmount = 0 là có thể bỏ qua bước kiểm tra này:

Tiếp theo là kiểm tra hợp đồng bên ngoài được gọi phải nằm trong danh sách trắng. Tuy nhiên, swapTarget và calldataConcat đều do người dùng kiểm soát, do đó ta có thể đặt swapTarget là địa chỉ hợp đồng 0x hoặc 1inch, và calldataConcat là dữ liệu mã hóa của một hàm view (luôn trả true), từ đó vượt qua require kiểm tra phía sau:

Tiếp theo, toàn bộ số dư toToken trong hợp đồng sẽ được chuyển cho người gọi. toToken có thể là ERC-20 hoặc ETH. Sau khi gửi, hệ thống kiểm tra số lượng tối thiểu mong đợi (minReturnAmount). Chỉ cần đặt minReturnAmount rất nhỏ là có thể vượt qua. Hai lời gọi hàm cuối không quan trọng.

Thông qua các bước trên, ta có thể rút được cả ERC-20 token và ETH khỏi hợp đồng DODO V2 Proxy 02.
1inch
1inch là một bộ tổng hợp sàn giao dịch phi tập trung (DEX Aggregator), tập hợp thanh khoản từ nhiều DEX khác nhau nhằm cung cấp mức giá tốt nhất cho người dùng khi đổi token. Bằng cách tích hợp thanh khoản từ nhiều nguồn, 1inch giúp người dùng tối ưu giao dịch và tìm được mức giá ưu đãi nhất trên các nền tảng. Các hợp đồng thông minh của 1inch tự động thực hiện giao dịch giữa các DEX, cho phép người dùng dễ dàng đạt được mức giá tốt nhất và trượt giá thấp nhất. Ngoài ra, 1inch còn cung cấp các tính năng khác như khai thác thanh khoản và token quản trị.
Hợp đồng chính của 1inch là AggregationRouter, hiện nay phổ biến nhất là phiên bản V4 và V5. Các hợp đồng này cũng có thể lưu giữ một số token do nhiều nguyên nhân. Chúng ta có thể rút token bằng cách xây dựng đúng tham số truyền vào hàm.
AggregationRouterV5
Hợp đồng AggregationRouterV5 có hàm swap, triển khai như sau:

Sau khi kiểm tra minReturnAmount trong desc, lấy srcToken và dstToken từ desc. Tiếp theo, các dòng 986–997 có thể được bỏ qua bằng cách cấu hình đúng flags và srcToken trong cấu trúc desc:

Sau đó thực thi hàm _execute, thực hiện lệnh call và kiểm tra trạng thái. Vì executor do người dùng truyền vào, ta có thể dùng địa chỉ 0 để bỏ qua:

Tiếp theo lấy số dư dstToken trong hợp đồng. Các dòng 1007–1018 có thể bỏ qua bằng cách cấu hình flags và minReturnAmount trong desc:

Cuối cùng, toàn bộ số dư dstToken trong hợp đồng sẽ được chuyển đến địa chỉ dstReceiver, địa chỉ này do người dùng kiểm soát:

Thông qua các bước trên, ta có thể cấu hình tham số truyền vào hàm swap để rút toàn bộ token khỏi hợp đồng AggregationRouterV5.
AggregationRouterV4
AggregationRouterV4 không khác nhiều so với AggregationRouterV5, cũng có hàm swap với triển khai như sau:

Có thể thấy việc triển khai hàm swap giống hệt AggregationRouterV5, chỉ khác là V5 đã tối ưu lệnh call. Do đó, có thể dùng phương pháp tương tự để rút token khỏi hợp đồng AggregationRouterV4.
Tổng kết
Bài viết đã giới thiệu sơ lược một số sàn giao dịch phi tập trung và bộ tổng hợp, đồng thời thảo luận các cơ hội arbitrage tiềm năng, phân tích nguyên lý từ góc độ mã hợp đồng. Tuy nhiên, khả năng thành công trong thực tế còn phụ thuộc vào nhiều yếu tố như phí GAS, tốc độ nút mạng, v.v.
Chào mừng tham gia cộng đồng chính thức TechFlow
Nhóm Telegram:https://t.me/TechFlowDaily
Tài khoản Twitter chính thức:https://x.com/TechFlowPost
Tài khoản Twitter tiếng Anh:https://x.com/BlockFlow_News














