
Thiết kế hợp đồng tinh vi, stETH làm thế nào để tự động phân phối lợi nhuận theo ngày?
Tuyển chọn TechFlowTuyển chọn TechFlow

Thiết kế hợp đồng tinh vi, stETH làm thế nào để tự động phân phối lợi nhuận theo ngày?
Tài khoản không thực hiện bất kỳ giao dịch nào, nhưng số lượng stETH lại đang tăng lên.
Tác giả: ZAN Team
Sau khi đổi một lượng nhỏ ETH của mình sang stETH, tôi nhận thấy stETH tăng trưởng tự nhiên mỗi ngày, liên tục tạo ra lợi nhuận. Tuy nhiên, tôi lại không thấy bất kỳ giao dịch nào xuất hiện trong tài khoản. Vì sao vậy? Bài viết này sẽ cùng bạn tìm hiểu thiết kế tinh tế đằng sau hiện tượng này và làm rõ bí mật về việc phân phối lợi nhuận.

1 stETH sau vài ngày đã tạo ra một khoản lợi nhuận nhất định
Trước tiên, hãy cùng tìm hiểu cơ chế kiếm lợi nhuận từ stETH – chính là hoạt động đặt cược (staking) trên Ethereum. Độc giả nào đã nắm rõ khái niệm này có thể chuyển xuống phần tiếp theo.

Ban đầu, Ethereum giống như Bitcoin, sử dụng cơ chế đồng thuận Proof of Work (PoW). Tuy nhiên, do PoW tiêu tốn nhiều điện năng cũng như các lo ngại về bảo mật và hiệu suất, nên vào tháng 9 năm 2022, Ethereum đã nâng cấp lên cơ chế Proof of Stake (PoS).
Thay vì dùng sức mạnh tính toán để đào coin và đạt được sự đồng thuận như trước, Ethereum giờ đây yêu cầu người dùng đặt cược ETH để giành quyền bỏ phiếu, từ đó nhận thưởng và thúc đẩy sự đồng thuận theo cơ chế PoS.
Khi tham gia mạng lưới Ethereum với 32 ETH, bạn có thể trở thành một trình xác thực (validator), chịu trách nhiệm lưu trữ dữ liệu, xử lý giao dịch và thêm các khối mới vào chuỗi khối. Miễn là bạn đóng gói giao dịch đúng cách thành khối mới và kiểm tra công việc của các validator khác, bạn sẽ nhận được phần thưởng bằng ETH. Như vậy, ETH của bạn có thể sinh lời ổn định thông qua hình thức đặt cược này.
Tuy nhiên, hình thức staking này vẫn còn khá phức tạp đối với người dùng phổ thông, bởi không chỉ cần tới 32 ETH mà còn phải sở hữu một máy tính chuyên dụng hoạt động liên tục, kết nối mạng Ethereum. Ngoài ra, việc đặt cược ETH khiến tài sản này mất đi tính thanh khoản. Vì thế, các sản phẩm phái sinh đặt cược linh hoạt (Liquid Staking Derivatives - LSD) đã ra đời nhằm giải quyết hai vấn đề: ngưỡng tham gia cao và thiếu tính thanh khoản. LSD cho phép người dùng đặt cược số lượng ETH dưới 32, không cần vận hành nút riêng, mà ủy thác ETH cho bên thứ ba để staking, đồng thời nhận lại token tương ứng (như stETH của Lido hay rETH của Rocket Pool). Những token thanh khoản này có thể được giao dịch, vay mượn hoặc sử dụng trong các hoạt động tài chính khác, giúp người dùng dễ dàng tham gia staking để kiếm lợi nhuận mà vẫn giữ được tính linh hoạt về vốn.

Vì vậy, bản chất của stETH là: bạn gửi ETH cho Lido, Lido sử dụng số ETH này để tham gia PoS trên Ethereum và tạo lợi nhuận; bạn nhận lại stETH như một bằng chứng sở hữu. Tiếp theo, Lido cần phân phối lợi nhuận cho các địa chỉ đang nắm giữ stETH.
Chúng ta có thể thấy lợi nhuận từ stETH được cập nhật tự động mỗi ngày. Hình dưới đây là minh họa kết quả thử nghiệm của chúng tôi, bạn có thể kiểm tra hàng ngày trong ví mã hóa để xác minh.

Tới đây, những ai quen thuộc với phát triển hợp đồng thông minh có lẽ sẽ thắc mắc: Nếu mỗi ngày đều phải phân phối một lượng lợi nhuận rất nhỏ, thì phí gas có thể còn cao hơn cả khoản lợi nhuận đó.
Đúng vậy, nếu Lido áp dụng cách đơn giản nhất – trực tiếp gửi lợi nhuận vào từng địa chỉ – thì chi phí gas thực sự không thể chấp nhận được. Theo trực giác, việc gửi token đến hàng ngàn địa chỉ sẽ tiêu tốn một lượng gas khổng lồ.
Tuy nhiên, Lido thật sự đã làm cho stETH trong ví của người dùng tăng lên tự động mỗi ngày, mà chúng ta lại không thấy bất kỳ giao dịch nào xảy ra ở địa chỉ đó. Làm cách nào để đạt được điều này?
Chúng tôi đã tìm đến hợp đồng của Lido tại https://etherscan.io/token/0xae7ab96520de3a18e5e111b5eaab095312d7fe84 và truy cập phương thức balanceOf:

balanceOf là phương thức tuân thủ chuẩn ERC20, ví tiền mã hóa sử dụng phương thức này để xác định số dư token của người dùng.
Ta thấy rằng trong hợp đồng stETH, phương thức này gọi đến getPooledEthByShares. Phương thức này nhận tham số là mapping (address => uint256) private shares; – tức là số cổ phần mà mỗi người dùng sở hữu. Nhưng liệu đây có phải là số lượng stETH? Rõ ràng là không, bởi nếu vậy thì mỗi ngày đều phải cập nhật dữ liệu cho mọi địa chỉ. Dù có thể thực hiện bằng cách gọi một phương thức trong hợp đồng để cập nhật toàn bộ shares qua một giao dịch duy nhất, nhưng chi phí gas vẫn sẽ cực kỳ lớn.
Có lẽ lúc này bạn đã đoán được cách hợp đồng hoạt động rồi. Hãy cùng xem kỹ hơn phương thức getPooledEthByShares.

Ta thấy giá trị trả về cuối cùng là: sharesAmount của địa chỉ nhân với _getTotalPooledEther(), rồi chia cho _getTotalShares.
_getTotalPooledEther biểu thị tổng lượng stETH (nếu quy đổi stETH sang ETH theo tỷ lệ 1:1 thì cũng là tổng lượng ETH), _getTotalShares biểu thị tổng số cổ phần. Như vậy, số lượng stETH của mỗi địa chỉ được tính toán động dựa trên công thức này.
Ví dụ: hiện tại có tổng cộng 1000 cổ phần (_getTotalShares), trong đó địa chỉ A sở hữu 100 cổ phần (tương ứng sharesAmount ở trên). 1000 cổ phần này tương ứng với 1000 stETH (giá trị trả về của _getTotalPooledEther). Vậy theo công thức, địa chỉ A sở hữu 100 stETH. Khi Lido sử dụng tổng số 1000 ETH này để staking và thu được thêm 1 ETH lợi nhuận, hệ thống cập nhật _getTotalPooledEther lên 1001 – tức là tổng stETH ban đầu 1000 đã tăng lên thành 1001. Khi đó, số stETH mới của địa chỉ A được tính là: 100 * 1001 / 1000 = 100,1 stETH.
Nói đơn giản: số cổ phần của mỗi địa chỉ không đổi, nhưng lượng stETH tương ứng với mỗi cổ phần tăng lên, nên khi tính toán thì số stETH hiển thị tự động tăng theo.
Tiếp tục xem mã nguồn, logic trong _getTotalPooledEther bị ảnh hưởng bởi phương thức handleOracleReport, phương thức này sẽ cập nhật dữ liệu liên quan trong hợp đồng. Cụ thể, việc gọi phương thức này được thực hiện định kỳ thông qua hợp đồng https://etherscan.io/address/0x852deD011285fe67063a08005c71a85690503Cee, nơi gọi submitReportData để cập nhật dữ liệu (trong submitReportData có gọi handleOracleReport của hợp đồng Lido):

Ta thấy rằng mỗi ngày đều có giao dịch cập nhật dữ liệu. Đây chính là lý do vì sao dù không thấy giao dịch nào trong địa chỉ của chúng ta, nhưng số dư vẫn thay đổi mỗi ngày.
Phía sau hiện tượng này phản ánh một đặc điểm của hợp đồng thông minh ERC20 trên Ethereum: số lượng token mà một địa chỉ sở hữu không được "đóng cứng" trên địa chỉ đó, mà được trả về bởi phương thức trong hợp đồng. Do đó, có thể xảy ra trường hợp một tài khoản không có giao dịch nào nhưng số lượng token vẫn thay đổi. Điều này vừa mang lại tính linh hoạt cho hợp đồng ERC20, vừa gây nhầm lẫn cho nhiều người chưa quen thuộc với hợp đồng thông minh. Mong rằng bài viết này giúp bạn hiểu rõ hơn về hợp đồng thông minh và tương tác an toàn hơn với chúng.
Ngoài ra, mặc dù việc đặt cược ETH để nhận stETH có vẻ mang lại lợi nhuận ổn định, nhưng vẫn tiềm ẩn những rủi ro nhất định. Bài viết này chỉ mang tính tham khảo nghiên cứu kỹ thuật về hợp đồng staking, không cấu thành bất kỳ lời khuyên đầu tư nào.
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














