Sự ra đời của Ethereum đã thiết lập một mô hình tính toán mới dựa trên nguyên tắc bất biến, nơi mã nguồn sau khi được triển khai lên blockchain sẽ tồn tại vĩnh viễn và không thể thay đổi. Tuy nhiên, trong thực tế phát triển phần mềm, tính bất biến này tạo ra một rào cản lớn đối với việc sửa lỗi, cập nhật tính năng và tối ưu hóa hệ thống. Để giải quyết mâu thuẫn giữa tính bất biến của blockchain và nhu cầu linh hoạt của phần mềm, mô hình Proxy Contract đã được phát triển như một giải pháp tiêu chuẩn. Báo cáo này, được biên soạn bởi đội ngũ Tấn Phát Digital, phân tích sâu sắc về bản chất của Proxy Contract, các cơ chế kỹ thuật nền tảng, các tiêu chuẩn phổ biến và đặc biệt là những rủi ro bảo mật tinh vi khiến người dùng cuối dễ dàng bị đánh lừa trong các kịch bản thực tế.
1. Khái niệm cốt lõi và sự phân tách giữa Trạng thái và Logic
Hợp đồng thông minh truyền thống trên Ethereum là một thực thể đơn khối, nơi mã thực thi (logic) và không gian lưu trữ (storage) gắn liền với một địa chỉ duy nhất. Proxy Contract phá vỡ cấu trúc này bằng cách tách biệt hệ thống thành hai thành phần độc lập nhưng tương tác chặt chẽ: hợp đồng Proxy (giữ trạng thái) và hợp đồng Logic (giữ mã thực thi).
Mô hình này cho phép duy trì một địa chỉ cố định cho người dùng và các ứng dụng ngoại vi, trong khi logic nghiệp vụ đằng sau có thể được thay thế bằng cách thay đổi địa chỉ trỏ đến hợp đồng logic bên trong bộ nhớ của proxy. Điều này tạo ra một "ảo giác về sự biến đổi" trên một hạ tầng vốn dĩ bất biến.
1.1 Vai trò của các thành phần trong kiến trúc Proxy
Trong kiến trúc này, hợp đồng Proxy đóng vai trò là điểm tiếp xúc duy nhất. Mọi tài sản, số dư Ether và các biến trạng thái quan trọng như quyền sở hữu, số dư người dùng đều được lưu trữ vĩnh viễn tại địa chỉ của Proxy. Ngược lại, hợp đồng Logic (còn gọi là Implementation Contract) chỉ chứa các chỉ dẫn về cách xử lý dữ liệu.
Các thành phần chính bao gồm:
Proxy Contract: Lưu trữ dữ liệu, số dư token, địa chỉ của Implementation và quyền quản trị. Có tính chất bất biến về địa chỉ, nhưng có thể thay đổi dữ liệu bên trong.
Logic (Implementation): Chứa mã nguồn của các hàm nghiệp vụ (ví dụ: transfer, mint, swap). Có tính chất thay thế được bằng phiên bản mới.
ProxyAdmin: Hợp đồng hoặc ví quản trị có quyền thực hiện việc nâng cấp, giúp kiểm soát khả năng thay đổi của toàn bộ hệ thống.
Sự phân tách này mang lại lợi ích to lớn trong việc bảo trì hệ thống. Nếu một lỗ hổng bảo mật được phát hiện trong logic nghiệp vụ, nhà phát triển chỉ cần triển khai một hợp đồng logic mới đã được sửa lỗi và cập nhật địa chỉ trong proxy, thay vì phải yêu cầu hàng nghìn người dùng chuyển tài sản sang một địa chỉ mới hoàn toàn.
Xem thêm: Smart Contract là gì?
2. Cơ chế DELEGATECALL: Động cơ của sự nâng cấp
Cơ sở kỹ thuật cho phép Proxy Contract hoạt động là opcode delegatecall, được giới thiệu trong EIP-7 của mạng lưới Ethereum. Đây là một lệnh gọi đặc biệt cho phép một hợp đồng nạp mã thực thi từ một địa chỉ khác nhưng chạy trong "ngữ cảnh" (context) của chính nó.
2.1 Bảo toàn ngữ cảnh trong thực thi EVM
Khi hợp đồng Proxy thực hiện delegatecall tới hợp đồng Logic, các biến môi trường của giao dịch được bảo toàn nguyên vẹn. Điều này có nghĩa là bên trong hợp đồng Logic, các giá trị sau sẽ không thay đổi so với khi gọi trực tiếp vào Proxy:
msg.sender: Vẫn là địa chỉ của người dùng ban đầu, không phải địa chỉ của Proxy.msg.value: Lượng Ether gửi kèm trong giao dịch được giữ nguyên.storage: Mọi lệnh đọc (SLOAD) và ghi (SSTORE) đều tác động trực tiếp lên không gian lưu trữ của Proxy, không phải của hợp đồng Logic.
Sự khác biệt giữa lệnh gọi thông thường (CALL) và DELEGATECALL là vô cùng quan trọng đối với an ninh và chức năng của hệ thống. Trong một lệnh CALL, hợp đồng mục tiêu hoạt động trên bộ nhớ của chính nó và thấy msg.sender là hợp đồng gọi. Trong DELEGATECALL, hợp đồng mục tiêu hoạt động như một thư viện logic được nạp vào máy chủ Proxy.
2.2 Phân tích luồng thực thi thông qua Hàm Fallback
Vì Proxy Contract thường không định nghĩa các hàm nghiệp vụ để tránh xung đột, nó sử dụng hàm fallback để tiếp nhận mọi cuộc gọi không xác định. Khi người dùng gọi hàm transfer(address,uint256) trên Proxy, do Proxy không có hàm này, máy ảo Ethereum (EVM) sẽ kích hoạt hàm fallback. Tại đây, một đoạn mã assembly cấp thấp sẽ được thực thi để ủy quyền cuộc gọi.
Quy trình kỹ thuật diễn ra như sau:
Sử dụng
calldatacopyđể sao chép toàn bộ dữ liệu đầu vào của giao dịch vào bộ nhớ đệm (memory).Lấy địa chỉ của hợp đồng Logic hiện tại từ một vị trí lưu trữ xác định.
Thực hiện lệnh
delegatecallvới toàn bộ lượng gas khả dụng, truyền vào dữ liệu đã sao chép.Sau khi hợp đồng Logic hoàn thành thực thi, kết quả trả về và dữ liệu đầu ra được sao chép ngược lại bằng
returndatacopy.Proxy trả kết quả về cho người dùng ban đầu, hoàn thành chu kỳ ủy quyền một cách minh bạch.
3. Kiến trúc Bộ nhớ và Tiêu chuẩn EIP-1967
Một trong những thách thức lớn nhất của Proxy Pattern là quản lý xung đột bộ nhớ (Storage Collision). Vì cả Proxy và Implementation đều chia sẻ cùng một không gian lưu trữ của Proxy, nếu cả hai cùng cố gắng sử dụng một "slot" bộ nhớ cho các mục đích khác nhau, thảm họa sẽ xảy ra.
3.1 Nguy cơ Xung đột Bộ nhớ
Trong Solidity, các biến trạng thái được sắp xếp vào các slot 32-byte theo thứ tự khai báo. Giả sử Proxy khai báo biến address _implementation ở slot 0 để lưu địa chỉ logic. Nếu hợp đồng Logic khai báo biến uint256 _balance cũng ở slot 0, thì mỗi khi hàm logic cập nhật số dư, nó sẽ vô tình ghi đè lên địa chỉ của chính nó trong Proxy. Điều này dẫn đến việc hợp đồng bị chiếm quyền kiểm soát bởi kẻ tấn công nếu chúng có thể thao túng giá trị ghi vào slot đó.
3.2 Giải pháp Unstructured Storage và EIP-1967
Để ngăn chặn xung đột, tiêu chuẩn EIP-1967 đã được thiết lập, định nghĩa các vị trí lưu trữ đặc biệt cho các biến quản trị của Proxy bằng cách băm các chuỗi ký tự định danh:

Việc trừ đi 1 sau khi băm đảm bảo rằng slot này không thể được tạo ra bởi việc băm thông thường của các mảng động hoặc bản đồ (mappings) trong Solidity, giảm thiểu xác suất xung đột xuống mức gần như bằng không.
Xem thêm: Smart Contract Audit là gì?
4. Các mô hình Proxy phổ biến và Phân tích đánh đổi
4.1 Transparent Proxy Pattern (TPP)
Mô hình này nhằm giải quyết vấn đề "xung đột định danh hàm". Cơ chế của TPP dựa trên việc phân quyền người gọi: nếu người gọi là Admin, Proxy chỉ thực hiện các lệnh gọi đến các hàm quản trị của chính nó; nếu người gọi không phải Admin, Proxy luôn chuyển tiếp cuộc gọi đến Implementation.
4.2 Universal Upgradeable Proxy Standard (UUPS) - EIP-1822
UUPS tối ưu hơn TPP bằng cách di chuyển logic nâng cấp từ Proxy sang chính hợp đồng Implementation. Proxy lúc này cực kỳ tinh giản, giúp tiết kiệm gas vì không cần kiểm tra Admin tại Proxy. Tuy nhiên, nếu nâng cấp lên một phiên bản mới thiếu logic nâng cấp, hợp đồng sẽ bị khóa vĩnh viễn.
4.3 Beacon Proxy
Được thiết kế cho các dự án cần triển khai hàng loạt hợp đồng giống nhau. Các Proxy trỏ đến một hợp đồng trung gian gọi là "Beacon" giữ địa chỉ Implementation chung. Khi Beacon cập nhật, toàn bộ các Proxy phụ thuộc sẽ được nâng cấp đồng loạt.
4.4 Diamond Standard (EIP-2535)
Diamond Standard cho phép một hợp đồng Proxy kết nối với nhiều hợp đồng Implementation khác nhau (Facets). Điều này giải quyết giới hạn kích thước hợp đồng 24KB bằng cách chia nhỏ logic và cho phép nâng cấp từng phần độc lập.
5. Rủi ro Bảo mật và Cơ chế Đánh lừa Người dùng
Theo quan sát từ Tấn Phát Digital, người dùng thường bị đánh lừa bởi cảm giác an toàn giả tạo khi thấy một địa chỉ hợp đồng không đổi hoặc một mã nguồn đã được xác minh trên các trình khám phá khối.
5.1 Rủi ro về Quyền quản trị và Sự tập trung hóa
Rủi ro lớn nhất là quyền kiểm soát tuyệt đối của Admin. Nếu khóa quản trị bị xâm nhập, kẻ tấn công có thể thực hiện một vụ "Flash Upgrade" sang mã nguồn độc hại để rút tiền và sau đó nâng cấp ngược lại phiên bản cũ để xóa dấu vết.
5.2 Lỗi Khởi tạo (Uninitialized Proxy Vulnerability)
Vì Proxy không thể sử dụng constructor, nhà phát triển dùng hàm initialize. Nếu Admin quên gọi hàm này hoặc không bảo vệ nó, kẻ tấn công có thể tự gọi để chiếm quyền Admin. Vụ hack ví Parity năm 2017 đóng băng hơn 500.000 ETH là một ví dụ lịch sử đau đớn liên quan đến lỗi này.
5.3 Xung đột Bộ nhớ và Sự cố Audius
Vụ hack giao thức Audius năm 2022 là minh chứng điển hình cho sai lầm về sắp xếp slot bộ nhớ:
Trước nâng cấp: Slot 0 lưu trữ trạng thái khởi tạo (
initialized = true). Hợp đồng hoạt động bình thường.Sau nâng cấp: Nhà phát triển thêm biến
proxyAdminvào Proxy, vô tình trùng slot 0.Khai thác: Giá trị địa chỉ của Admin khiến hệ thống hiểu nhầm là chưa được khởi tạo. Hacker gọi hàm
initializelần nữa và chiếm quyền sở hữu.Thiệt hại: Hacker chuyển 6 triệu USD token ra khỏi quỹ cộng đồng.
5.4 Các kỹ thuật Che giấu và Ngụy trang
Kẻ lừa đảo thường đặt tên các hàm nguy hiểm như safeWithdraw() nhưng thực chất là hàm rút sạch tiền. Chúng cũng có thể chỉ xác minh mã nguồn của Proxy (vốn rất ngắn và vô hại) trong khi giấu kín mã nguồn của Implementation chứa các "cửa sau" độc hại.
6. Phân tích các vụ Rug Pull Proxy điển hình (2024 - 2025)
6.1 Trường hợp LIBRA và Sự tiến hóa của Rug Pull
Dự án LIBRA năm 2025 đã sử dụng chiến thuật "Fragmented Rug Pull" để tránh bị phát hiện. Thay vì một lệnh rút tiền lớn, kẻ lừa đảo sử dụng proxy để phân phối quyền rút tiền cho hàng loạt ví vệ tinh, thực hiện hàng nghìn giao dịch nhỏ dưới ngưỡng cảnh báo của hệ thống giám sát. Sau đó, chúng nâng cấp proxy lên một hợp đồng chứa lệnh selfdestruct để xóa sạch bằng chứng.
6.2 Kinto Finance và Lỗ hổng Proxy cấp thấp
Tháng 7 năm 2025, Kinto Finance bị tấn công thông qua một lỗi trong cơ chế quản trị proxy. Kẻ tấn công chiếm quyền nâng cấp và nhanh chóng mint thêm 110.000 token trái phép, rút 1,55 triệu USD từ các pool thanh khoản.
7. Quy trình Kiểm tra và Xác minh cho Người dùng
Để bảo vệ tài sản, Tấn Phát Digital khuyến nghị người dùng thực hiện các bước sau:
Kiểm tra tính năng Verify Proxy: Xem Etherscan có hiển thị tab "Read as Proxy" hay không.
Theo dõi lịch sử Upgraded: Nếu một hợp đồng nâng cấp quá thường xuyên mà không có thông báo, đó là dấu hiệu nguy hiểm.
Xác minh quyền quản trị: Địa chỉ Admin nên là ví đa chữ ký (Multisig) hoặc có cơ chế Timelock để trì hoãn các thay đổi quan trọng.
Sử dụng công cụ hỗ trợ: Tận dụng các nền tảng như GoPlus Security hay TokenSniffer để quét các dấu hiệu của Honeypot hoặc quyền Mint token bất thường.
8. Chiến lược Phòng thủ cho Nhà phát triển
Nhà phát triển nên sử dụng các thư viện chuẩn của OpenZeppelin và luôn áp dụng kỹ thuật "Storage Gap" (tạo mảng trống uint256 private __gap;) để dự phòng không gian bộ nhớ. Mọi thay đổi trong Implementation phải được kiểm tra tương thích layout bộ nhớ thông qua các công cụ tự động như Hardhat Upgrades Plugin trước khi triển khai.
9. Câu hỏi thường gặp (FAQs)
Tại sao cần sử dụng Proxy Contract thay vì triển khai hợp đồng mới? Sử dụng Proxy giúp duy trì một địa chỉ hợp đồng cố định duy nhất cho người dùng và các ứng dụng tích hợp, tránh việc phải di chuyển dữ liệu (migration) tốn kém và yêu cầu người dùng chuyển sang địa chỉ mới mỗi khi có bản cập nhật hoặc sửa lỗi.
Sự khác biệt cốt lõi giữa lệnh CALL và DELEGATECALL là gì? Trong lệnh
CALL, hợp đồng mục tiêu chạy trên bộ nhớ của chính nó. Ngược lại,DELEGATECALLnạp mã của hợp đồng mục tiêu nhưng thực thi trong "ngữ cảnh" của hợp đồng gọi, nghĩa là nó sử dụng bộ nhớ, số dư và giữ nguyênmsg.sendercủa hợp đồng gọi.Tại sao Transparent Proxy lại tốn gas hơn UUPS? Transparent Proxy yêu cầu kiểm tra xem người gọi có phải là Admin hay không ở mỗi giao dịch để quyết định hướng đi của cuộc gọi (đến admin hay đến logic). UUPS loại bỏ bước kiểm tra này tại Proxy vì logic nâng cấp nằm trực tiếp trong hợp đồng Implementation.
Làm thế nào để nhận biết một dự án đang sử dụng Proxy? Trên Etherscan, người dùng có thể tìm nút "Is this a proxy?" hoặc các tab "Read as Proxy"/"Write as Proxy". Nếu có, đó chắc chắn là một hợp đồng ủy quyền.
Storage Gap là gì? Đây là kỹ thuật đặt các mảng trống (ví dụ:
uint256 private __gap;) trong hợp đồng cơ sở để dự phòng không gian lưu trữ cho các biến mới trong tương lai, ngăn chặn việc xô lệch vị trí bộ nhớ của các hợp đồng kế thừa.Rủi ro của việc không khởi tạo (Initialize) Proxy là gì? Nếu hàm
initializekhông được gọi ngay sau khi triển khai, kẻ tấn công có thể tự gọi hàm này để trở thành chủ sở hữu (Owner) của hợp đồng và chiếm toàn quyền kiểm soát.Tại sao Proxy không thể sử dụng hàm constructor? Bởi vì mã trong
constructorchỉ chạy một lần duy nhất tại địa chỉ của hợp đồng Logic khi nó được triển khai, trong khi trạng thái thực tế của người dùng lại nằm ở địa chỉ của Proxy.Function Selector Clashing là gì? Đây là hiện tượng hai hàm khác tên nhau nhưng có cùng mã định danh 4-byte. Hacker có thể lợi dụng điều này để lừa người dùng gọi một hàm nghiệp vụ nhưng thực tế lại kích hoạt hàm quản trị nguy hiểm.
Làm thế nào để đảm bảo việc nâng cấp Proxy là an toàn? Dự án nên sử dụng ví đa chữ ký (Multisig) kết hợp với cơ chế Timelock (trì hoãn thời gian thực thi) để cộng đồng có thời gian kiểm tra mã nguồn mới trước khi nó có hiệu lực.
Có thể vô hiệu hóa khả năng nâng cấp của Proxy không? Có. Nhà phát triển có thể nâng cấp tới một bản Implementation không chứa logic nâng cấp hoặc sử dụng hàm từ bỏ quyền quản trị để biến Proxy thành một hợp đồng bất biến vĩnh viễn.
Beacon Proxy khác gì so với Proxy thông thường? Thay vì mỗi Proxy lưu địa chỉ Logic, chúng trỏ đến một hợp đồng trung gian (Beacon). Việc cập nhật Beacon sẽ nâng cấp đồng loạt hàng nghìn Proxy phụ thuộc chỉ trong một giao dịch.
Hợp đồng ProxyAdmin có vai trò gì? Trong mô hình Transparent Proxy của OpenZeppelin,
ProxyAdminlà hợp đồng trung gian nắm quyền sở hữu Proxy, giúp quản trị việc nâng cấp một cách an toàn và tách biệt khỏi các tương tác của người dùng thông thường.Làm thế nào để phát hiện cửa sau (backdoor) trong Proxy? Người dùng nên kiểm tra mã nguồn Implementation đã được xác minh chưa và sử dụng các công cụ như Slither để quét các hàm có quyền
onlyOwnercó khả năng rút tiền hoặc khóa giao dịch.Flash Upgrade Attack là gì? Đây là kỹ thuật tấn công khi hacker nâng cấp Proxy sang mã độc, thực hiện hành vi trộm tiền, sau đó lập tức nâng cấp ngược lại phiên bản cũ chỉ trong một giao dịch để xóa dấu vết on-chain.
Làm thế nào để khởi tạo Proxy một cách an toàn nhất? Nhà phát triển nên sử dụng quy trình khởi tạo nguyên tử (Atomic Initialization), nghĩa là việc triển khai Proxy và gọi hàm
initializediễn ra trong cùng một giao dịch để tránh bị hacker "hớt tay trên".
Proxy Contract là giải pháp kỹ thuật tất yếu cho sự phát triển của hệ sinh thái Blockchain. Tuy nhiên, sự linh hoạt này cũng mang lại rủi ro nếu không được quản trị minh bạch. Tấn Phát Digital tin rằng sự minh bạch trong quản trị và sự cẩn trọng của người dùng chính là "tính bất biến" thực sự mà cộng đồng cần hướng tới trong thế giới Web3 đầy biến động.









