Hiện nay rất nhiều token có sử dụng thông qua 1 Proxy Contract, điều này có nghĩ là chủ sở hữu token Proxy Contract này có quyền thay thế token gốc bằng một token khác, do đó tiềm ẩn nhiều vấn đề về bảo mật. Thêm nữa, lượng Gas Used sử dụng qua token Proxy lớn hơn khá nhiều so với sử dụng trực tiếp.
Nhưng với những dự án mới, hoặc một số dự án uy tín họ vẫn sử dụng cách này để giúp có thể dễ dàng nâng cấp trong tương lai khi gặp vấn đề về lỗi hoặc bảo mật với contract cũ. Đặc biệt hữu ích khi cần triển khai các thuật toán mới, chưa được kiểm chứng.
Vậy có cách nào, chúng ta có thể kiểm tra TỰ ĐỘNG một token có sử dụng qua một Proxy Contract hay không?
Tìm hiểu về Token sử dụng qua Proxy Contract
Giờ chúng ta đi sâu tìm hiểu token điển hình sử dụng Proxy Contract, đó là token USD Base Coin (USDbC) trên Base Network. Nếu nhìn trên BaseScan, chúng ta sẽ dễ dàng biết được đó có phải Proxy Contract hay không dựa vào thông tin hiển thị trong phần Contract/Code
Xem trong code thì toàn là hàm Write, và có kiểm tra thì:
- Nếu gọi các hàm dành cho Admin thì chỉ Admin mới gọi được, người khác gọi sẽ bị Revert
- Nếu gọi các hàm của ERC20 thì sẽ tự động gọi tới contract của token ERC20
Chi tiết xem: The transparent proxy pattern
Giải pháp kiểm tra token có sử dụng Proxy Contract hay không?
Qua quá trình tìm hiểu và xem source code, tôi thấy rằng các Proxy Contract luôn có hàm implementation() trả về địa chỉ token liên quan. Tôi thử gọi hàm này bằng staticcall nhưng không thành công, hàm này luôn trả về lỗi REVERT.
Tôi thử tìm signature của hàm implementation() trên Openchain Signatures thì hàm không tham số có Signature là 0x5c60da1b, dùng web3.eth.getCode() để lấy code của contract xem trong code contract có mã 5c60da1b kết quả hơi buồn vì không có.
Tôi thử chuyển sang token ERC20 bình thường ví dụ Wrapped Ether (WETH), tôi lấy source của smart contract này về và kiểm tra xem nó có chứa Signature của một số hàm thông dụng của ERC20 không?
- transfer(address,uint256): Có Signature là a9059cbb => Có trong code của Smart Contract.
- balanceOf(address) => Có Signature là 70a08231 => Có trong code của Smart Contract.
- symbol() => Có Signature là 95d89b41 => Có trong code của Smart Contract.
Đến đây chúng ta đã tìm ra Giải Pháp để kiểm tra một token có sử dụng Proxy Contract hay không?
- B1: Dùng hàm web3.eth.getCode() để lấy code của Smart Contract.
- B2: Kiểm tra code của Smart Contract có chứa đồng thời ba xâu: “a9059cbb“, “70a08231“, và “95d89b41“
- B3: Phân loại:
- Nếu code chứa đồng thời cả 3 xâu trên => Là Token ERC20 bình thường
- Ngược lại là token có sử dụng Proxy Contract.
Cài đặt code để kiểm tra token có sử dụng Proxy Contract hay không?
Dựa theo giải pháp trên, giờ chúng ta sẽ viết check-proxy-token.js để kiểm tra một token có sử dụng Proxy Contract hay không? Mã nguồn như bên dưới:
const Web3 = require('web3');
// RPC on BASE Network
let rpcNode = "https://mainnet.base.org";
let web3 = new Web3(rpcNode);
// Check token has use proxy or not?
async function checkProxyToken(token) {
try {
let code = await web3.eth.getCode(token);
if (code) {
// transfer(address,uint256) => 0xa9059cbb
// balanceOf(address) => 0x70a08231
// symbol() => 0x95d89b41
if (code.indexOf("a9059cbb")>=0 && code.indexOf("70a08231") && code.indexOf("95d89b41")) return false;
return true;
}
} catch(ex) {
console.error("checkProxyToken EXCEPTION", token, ex);
}
return null;
}
async function main() {
let token = "0xd9aaec86b65d86f6a7b5b1b0c42ffa531710b6ca";
let hasProxy = await checkProxyToken(token);
console.log(`HasProxy(${token}) = ${hasProxy}`);
}
main();
Bạn chạy bằng lệnh sau:
# Cài đặt thư viện Web3 (Lần đầu)
npm install web3
# Chạy công cụ
node check-proxy-token.js
Trả lời