Cách kiểm tra hợp đồng proxy và quyền nâng cấp

Khi phân tích một dự án blockchain, chỉ xem mã nguồn tại địa chỉ token hoặc giao thức chưa chắc đã đủ. Địa chỉ người dùng tương tác có thể là proxy contract, còn logic thực thi nằm trong một implementation contract khác. Nếu implementation có thể thay đổi, hành vi của hợp đồng cũng có thể được cập nhật mà không cần đổi địa chỉ proxy.

Quy trình dưới đây tập trung vào các mạng tương thích EVM như Ethereum, BNB Smart Chain, Polygon, Arbitrum và các mạng có blockchain explorer hỗ trợ đọc hợp đồng. Tên tab và mức độ nhận diện proxy có thể khác nhau giữa từng explorer.

Table of Contents

Hợp đồng proxy là gì?

Proxy contract là hợp đồng đóng vai trò điểm truy cập cố định. Proxy thường giữ trạng thái của ứng dụng và chuyển tiếp lời gọi đến implementation bằng cơ chế thực thi ủy quyền. Implementation chứa phần lớn logic nghiệp vụ như chuyển token, gửi tài sản, quản trị hoặc tạm dừng hoạt động.

Một upgradeable smart contract thường gồm các thành phần:

  • Proxy: địa chỉ người dùng và ứng dụng tương tác.
  • Implementation: hợp đồng chứa logic đang được sử dụng.
  • Admin, owner hoặc role quản trị: chủ thể có thể thay đổi implementation hoặc cấu hình hệ thống.
  • ProxyAdmin, beacon, multisig hoặc timelock: lớp quản trị trung gian, tùy kiến trúc.

Không phải proxy nào cũng có thể nâng cấp. Một số proxy được triển khai theo kiểu bất biến, đã từ bỏ quyền quản trị hoặc phụ thuộc vào beacon dùng chung. Vì vậy, nhìn thấy proxy chưa đủ để kết luận dự án có thể tùy ý sửa hợp đồng.

Cách kiểm tra hợp đồng proxy trên blockchain explorer

Ảnh minh hoạ: Cách kiểm tra hợp đồng proxy và quyền nâng cấp

1. Xác nhận đúng mạng và đúng địa chỉ

Cùng một chuỗi ký tự địa chỉ có thể xuất hiện trên nhiều mạng EVM nhưng đại diện cho các hợp đồng khác nhau. Trước khi phân tích, cần đối chiếu:

  • Tên blockchain và chain đang chọn trên ví.
  • Địa chỉ công bố trong tài liệu chính thức của dự án.
  • Loại địa chỉ: ví cá nhân, hợp đồng, proxy hay implementation.
  • Giao dịch triển khai và thời điểm hợp đồng bắt đầu hoạt động.

Nếu chưa chắc sản phẩm đã chạy trên mạng nào, nên thực hiện bước kiểm tra mainnet của dự án crypto trước khi đọc hợp đồng.

2. Mở khu vực mã nguồn và giao diện đọc hợp đồng

Tại trang địa chỉ hợp đồng, tìm các dấu hiệu như:

  • Nhãn cho biết địa chỉ là proxy.
  • Trường hiển thị implementation hoặc implementation address.
  • Tab có tên tương đương “Read as Proxy” hoặc “Write as Proxy”.
  • Thông báo mã nguồn đã xác minh và liên kết đến hợp đồng triển khai logic.
  • Các hàm hoặc trường liên quan đến implementation, admin, beacon, upgradeTo hay upgradeToAndCall.

Tên hiển thị không thống nhất giữa các blockchain explorer. Việc không có nhãn proxy không chứng minh hợp đồng không phải proxy.

Tham khảo thêm:  Mã độc thay địa chỉ ví: Cách kiểm tra trước khi gửi

3. Kiểm tra bytecode và lịch sử giao dịch

Nếu explorer chưa nhận diện kiến trúc, có thể tìm thêm các tín hiệu:

  • Mã nguồn proxy rất ngắn và chủ yếu chuyển tiếp lời gọi.
  • Bytecode chứa mẫu thực thi ủy quyền thường dùng trong proxy.
  • Giao dịch triển khai hoặc cấu hình ban đầu ghi địa chỉ implementation.
  • Lịch sử có sự kiện hay giao dịch mang ý nghĩa nâng cấp.
  • Địa chỉ hợp đồng có nhiều giao dịch gọi hàm nhưng logic hiển thị rất ít.

Đây chỉ là tín hiệu kỹ thuật. Một mẫu bytecode tương tự proxy có thể là clone, forwarder hoặc kiến trúc tùy biến, nên cần kiểm tra thêm storage, sự kiện và mã nguồn.

Cách xác định implementation contract

Cách 1: Dùng liên kết do explorer cung cấp

Nếu explorer nhận diện đúng proxy, implementation thường được hiển thị ngay trong trang hợp đồng. Hãy mở địa chỉ đó và xác minh:

  • Mã nguồn implementation có được xác minh hay không.
  • ABI có chứa các hàm ứng dụng mà proxy đang cung cấp hay không.
  • Địa chỉ implementation có trùng với dữ liệu đọc từ proxy hay không.
  • Có lịch sử thay đổi implementation hay không.

Khi đọc trạng thái, nên ưu tiên giao diện đọc qua proxy. Đọc trực tiếp tại implementation có thể trả về dữ liệu trong vùng lưu trữ riêng của implementation, không phải trạng thái đang nằm ở proxy. Đây là nguyên nhân phổ biến khiến owner(), paused() hoặc số dư hiển thị giá trị rỗng hay khác dự kiến.

Cách 2: Kiểm tra storage slot chuẩn

Nhiều proxy EVM sử dụng các storage slot chuẩn hóa theo EIP-1967 để lưu implementation, admin hoặc beacon. Explorer hoặc công cụ đọc blockchain có thể giải mã các slot này thành địa chỉ.

Quy trình đối chiếu gồm:

  1. Đọc slot implementation tại địa chỉ proxy.
  2. Tách địa chỉ hợp đồng từ giá trị trả về.
  3. Kiểm tra địa chỉ đó có bytecode hay không.
  4. So sánh với implementation mà explorer công bố.
  5. Nếu có beacon, mở beacon và đọc implementation hiện tại từ beacon.

Nếu dữ liệu trong storage khác nhãn của explorer, không nên mặc định một trong hai nguồn chắc chắn đúng. Có thể explorer chưa cập nhật, proxy dùng kiến trúc tùy biến hoặc dữ liệu đã được giải mã sai.

Cách 3: Nhận diện loại proxy

Loại proxy quyết định nơi cần tìm quyền nâng cấp:

Kiến trúc Nơi thường chứa cơ chế nâng cấp Điểm cần kiểm tra
Transparent proxy Proxy hoặc ProxyAdmin Admin của proxy và owner của ProxyAdmin
UUPS Logic nâng cấp trong implementation Hàm ủy quyền nâng cấp và cơ chế kiểm soát quyền
Beacon proxy Upgradeable beacon Owner hoặc role của beacon
Minimal proxy hoặc clone Địa chỉ logic thường được cố định trong bytecode Clone có thực sự nâng cấp được hay không
Proxy tùy biến Phụ thuộc mã nguồn và storage riêng Hàm quản trị, slot lưu trữ và lịch sử giao dịch

Trong UUPS, việc thấy hàm upgradeToAndCall trong ABI của implementation chưa đủ để kết luận bất kỳ ai cũng gọi được. Cần đọc phần kiểm tra quyền của hàm nâng cấp và xác định chủ thể vượt qua điều kiện đó.

Cách kiểm tra quyền nâng cấp smart contract

Mục tiêu là trả lời hai câu hỏi: ai có thể khởi tạo nâng cấp và điều kiện nào khiến giao dịch nâng cấp được chấp nhận.

Bước 1: Tìm các hàm và role liên quan

Tại giao diện đọc qua proxy hoặc tại hợp đồng quản trị, tìm các mục như:

  • owner()
  • admin()
  • getAdmin()
  • implementation()
  • UPGRADER_ROLE()
  • hasRole()
  • getRoleAdmin()
  • upgradeToAndCall()
  • Các hàm đổi admin, chuyển quyền sở hữu hoặc cập nhật beacon

Tên hàm có thể khác hoàn toàn nếu dự án dùng mã tùy biến. Vì vậy, cần đọc mã nguồn và không chỉ tìm theo tên phổ biến.

Bước 2: Truy ngược đến địa chỉ có quyền cuối cùng

Nếu owner() trả về một địa chỉ, hãy mở địa chỉ đó trên explorer:

  • Nếu là ví cá nhân, quyền có thể do một khóa riêng kiểm soát.
  • Nếu là multisig, cần kiểm tra chủ sở hữu và ngưỡng phê duyệt từ dữ liệu on-chain hoặc giao diện hợp đồng đã xác minh.
  • Nếu là timelock, cần xem vai trò đề xuất, thực thi, hủy và thời gian trì hoãn được cấu hình trên chuỗi.
  • Nếu là ProxyAdmin, tiếp tục đọc owner() của ProxyAdmin.
  • Nếu là hợp đồng quản trị khác, tiếp tục truy ngược cho đến khi hiểu được điều kiện thực thi cuối cùng.
Tham khảo thêm:  Meta hỗ trợ các công ty khởi nghiệp về Web3

Không nên dừng ở kết luận “quyền thuộc multisig” nếu chưa xác định được multisig đó có thể thay đổi thành viên hay ngưỡng ký bằng cơ chế nào.

Bước 3: Kiểm tra role-based access control

Với hợp đồng dùng cơ chế role, hãy xác định:

  1. Giá trị định danh của role nâng cấp.
  2. Hàm nâng cấp yêu cầu role nào.
  3. Địa chỉ nào đang có role đó.
  4. Role quản trị nào có thể cấp hoặc thu hồi quyền nâng cấp.
  5. Chủ thể nào đang nắm role quản trị cấp cao nhất.

Một số hợp đồng không hỗ trợ liệt kê toàn bộ thành viên role trực tiếp. Khi đó, có thể cần đối chiếu sự kiện cấp và thu hồi role từ thời điểm triển khai đến block hiện tại. Lịch sử sự kiện không đầy đủ hoặc việc index dữ liệu bị lỗi có thể làm kết quả thiếu địa chỉ.

Bước 4: Đọc lịch sử nâng cấp

Tìm các giao dịch và sự kiện liên quan đến thay đổi implementation, admin, owner hoặc role. Với mỗi lần nâng cấp, nên ghi nhận:

  • Địa chỉ gửi giao dịch.
  • Hợp đồng thực sự thực thi lệnh.
  • Implementation cũ và mới nếu dữ liệu cho phép xác định.
  • Giao dịch có đi qua multisig hoặc timelock không.
  • Sau nâng cấp có lời gọi khởi tạo hoặc thay đổi trạng thái đi kèm không.

Lịch sử này giúp phân biệt quyền tồn tại trên lý thuyết với quy trình quản trị đã được sử dụng trong thực tế. Khi cần đánh giá hoạt động phát triển đứng sau các lần thay đổi, có thể kết hợp với quy trình đánh giá GitHub dự án crypto, nhưng dữ liệu GitHub không thay thế bằng chứng on-chain.

Cách kiểm tra quyền tạm dừng hợp đồng

Ảnh minh hoạ: Cách kiểm tra hợp đồng proxy và quyền nâng cấp

Quyền tạm dừng thường độc lập với quyền nâng cấp. Một địa chỉ có thể được phép gọi chức năng dừng hoạt động nhưng không được thay implementation, hoặc ngược lại.

Xác định hợp đồng có cơ chế pause hay không

Tìm trong ABI và mã nguồn các thành phần như:

  • paused()
  • pause() và unpause()
  • PAUSER_ROLE()
  • Modifier hoặc điều kiện tương đương whenNotPaused
  • Cờ trạng thái tùy biến như isPaused, transfersEnabled hoặc emergencyMode

Sau đó kiểm tra các hàm nào thực sự chịu ảnh hưởng. Hợp đồng có biến paused không đồng nghĩa toàn bộ hệ thống sẽ dừng. Cơ chế pause có thể chỉ chặn chuyển token, gửi tiền, vay, rút tài sản hoặc một nhóm chức năng cụ thể.

Xác định địa chỉ có thể pause và unpause

Nếu hàm dùng onlyOwner, đọc owner qua proxy. Nếu dùng role, kiểm tra thành viên của role tạm dừng và role có quyền cấp role đó. Nếu lệnh được chuyển sang một hợp đồng quản trị khác, tiếp tục truy ngược như khi kiểm tra quyền nâng cấp.

Cần kiểm tra riêng quyền pause và unpause. Một thiết kế khẩn cấp có thể cho phép nhiều địa chỉ tạm dừng nhưng chỉ quản trị cấp cao mới được mở lại.

Kiểm tra trạng thái hiện tại

Đọc paused() hoặc biến trạng thái tương đương qua proxy. Sau đó kiểm tra giao dịch gần nhất làm thay đổi trạng thái. Nếu ứng dụng ngừng hoạt động nhưng hợp đồng không bị pause, nguyên nhân có thể nằm ở blockchain, oracle, frontend, bridge hoặc dịch vụ ngoài chuỗi. Khi đó, quy trình kiểm tra blockchain có ngừng hoạt động hay không sẽ giúp tách lỗi mạng khỏi quyền quản trị hợp đồng.

Đánh giá địa chỉ đang nắm quyền quản trị

Việc xác định được địa chỉ chỉ là bước đầu. Để đánh giá rủi ro quản trị, cần trả lời thêm:

  • Địa chỉ là ví cá nhân hay hợp đồng?
  • Nếu là multisig, quyền phê duyệt có tập trung vào ít chủ thể hay không?
  • Có timelock tạo khoảng chờ trước khi nâng cấp không?
  • Timelock có cơ chế bỏ qua hoặc vai trò khẩn cấp không?
  • Admin có thể tự thay đổi thành viên, ngưỡng ký hoặc thời gian chờ không?
  • Quyền nâng cấp và quyền tạm dừng có tách biệt không?
  • Có thể thay implementation và gọi hàm khởi tạo trong cùng một giao dịch không?
  • Quyền đã được từ bỏ thật sự hay chỉ chuyển sang một hợp đồng khác?
Tham khảo thêm:  FDV và vốn hóa lưu hành: Cách tính, tránh hiểu sai

Thông tin website, whitepaper hoặc tuyên bố “phi tập trung” không đủ để xác nhận quyền kiểm soát. Có thể dùng khung kiểm tra whitepaper dự án crypto để đối chiếu cam kết với cấu hình on-chain, đồng thời áp dụng quy trình xác minh đối tác và chủ thể liên quan nếu địa chỉ quản trị được gắn với một tổ chức cụ thể.

Giới hạn khi explorer hoặc mã nguồn không đầy đủ

Mã nguồn chưa xác minh

Khi proxy hoặc implementation chưa xác minh mã nguồn, explorer thường chỉ cung cấp bytecode và lịch sử giao dịch. Trong trường hợp này:

  • Không thể chắc chắn ABI tự nhập phản ánh đúng mọi hàm của hợp đồng.
  • Việc dịch ngược bytecode có thể giúp nhận diện mẫu nhưng không khôi phục đầy đủ tên biến, ý nghĩa nghiệp vụ hoặc mã nguồn ban đầu.
  • Có thể đọc storage và calldata, nhưng cách diễn giải phụ thuộc vào kiến trúc hợp đồng.
  • Không nên kết luận hợp đồng an toàn chỉ vì chưa nhìn thấy hàm nâng cấp hoặc tạm dừng.

Một ABI lấy từ hợp đồng tương tự chỉ nên được dùng để kiểm tra giả thuyết, không phải bằng chứng rằng hai hợp đồng có cùng logic.

Explorer nhận diện sai hoặc chưa cập nhật proxy

Explorer có thể không nhận diện proxy tùy biến, implementation mới hoặc proxy qua beacon. Ngược lại, nhãn tự động cũng có thể không phản ánh đầy đủ chuỗi quản trị.

Nên đối chiếu ít nhất các lớp dữ liệu sau:

  1. Nhãn và giao diện proxy của explorer.
  2. Storage tại proxy hoặc beacon.
  3. Bytecode và mã nguồn đã xác minh.
  4. Sự kiện cùng lịch sử giao dịch nâng cấp.
  5. Kết quả gọi hàm đọc trực tiếp trên chuỗi.

Nếu các nguồn mâu thuẫn, kết luận phù hợp là chưa đủ bằng chứng để xác định chắc chắn, thay vì chọn dữ liệu thuận tiện nhất.

Không thể suy ra người thật chỉ từ địa chỉ

Blockchain cho biết địa chỉ hoặc hợp đồng nào có quyền, nhưng không tự chứng minh cá nhân hay tổ chức ngoài đời đang kiểm soát khóa. Nhãn explorer, tên miền và thông tin dự án chỉ là dữ liệu bổ sung, trừ khi có bằng chứng xác thực phù hợp.

Checklist kiểm tra nhanh

Ảnh minh hoạ: Cách kiểm tra hợp đồng proxy và quyền nâng cấp
  • Xác nhận đúng blockchain và địa chỉ hợp đồng.
  • Kiểm tra explorer có gắn nhãn proxy không.
  • Tìm tab đọc qua proxy và địa chỉ implementation.
  • Đối chiếu implementation với storage hoặc beacon.
  • Xác định kiến trúc Transparent, UUPS, Beacon, clone hay tùy biến.
  • Đọc owner, admin, ProxyAdmin và các role quản trị.
  • Truy ngược qua multisig, timelock hoặc hợp đồng trung gian.
  • Tìm quyền nâng cấp và điều kiện kiểm soát quyền.
  • Tìm quyền pause, unpause và phạm vi chức năng bị chặn.
  • Kiểm tra sự kiện cùng giao dịch nâng cấp trước đây.
  • Không đọc trạng thái trực tiếp từ implementation rồi coi đó là trạng thái của proxy.
  • Ghi rõ giới hạn nếu mã nguồn chưa xác minh hoặc explorer không nhận diện được kiến trúc.

Câu hỏi thường gặp

Proxy contract có phải lúc nào cũng nâng cấp được không?

Không. Một số proxy có implementation cố định, một số đã chuyển hoặc từ bỏ quyền quản trị, còn clone tối giản thường trỏ đến logic được ghi trong bytecode. Cần kiểm tra kiến trúc và quyền on-chain thay vì chỉ dựa vào nhãn proxy.

Implementation contract có giữ tài sản không?

Trong mô hình proxy phổ biến, trạng thái và tài sản thường gắn với địa chỉ proxy, còn implementation cung cấp logic. Tuy nhiên, kiến trúc tùy biến có thể khác. Cần kiểm tra số dư, luồng gọi và mã nguồn của cả hai địa chỉ.

Vì sao đọc owner() tại implementation lại trả về địa chỉ rỗng?

Khi gọi trực tiếp implementation, hàm đọc vùng lưu trữ của chính implementation. Trong khi đó, owner của hệ thống thường được lưu tại proxy và chỉ được truy cập đúng khi gọi qua proxy bằng ABI của implementation.

Có hàm nâng cấp trong ABI nghĩa là hợp đồng còn quyền nâng cấp không?

Không nhất thiết. Hàm có thể bị giới hạn bởi owner, role, timelock hoặc điều kiện tùy biến. Quyền cũng có thể đã được chuyển sang địa chỉ không thể sử dụng. Phải kiểm tra điều kiện trong mã nguồn và trạng thái hiện tại trên chuỗi.

Không thấy pause() thì có thể kết luận hợp đồng không tạm dừng được không?

Chưa thể. Dự án có thể dùng tên hàm khác, chặn chức năng thông qua role, cấu hình module hoặc nâng cấp implementation để thay đổi hành vi. Khi mã nguồn chưa xác minh, mức độ chắc chắn càng thấp.