Đầu năm nay, chúng tôi đã đạt mốc $1 tỷ về tổng khối lượng thanh toán bằng stablecoin. Để tham khảo, chúng tôi đã xử lý giao dịch stablecoin đầu tiên cách đây chưa đầy 12 tháng. Mọi thứ bắt đầu với một số ít khách hàng yêu cầu một điều đơn giản: khả năng nhận thanh toán bằng stablecoin từ khách hàng của họ trên toàn thế giới và có thể sử dụng số tiền đó. Thanh toán bằng đô la Mỹ- Nhanh chóng và đáng tin cậy, mà không phải chịu phí cao. Các giải pháp off-ramp hiện có đòi hỏi phí từ 1-3%, thời gian thanh toán kéo dài nhiều ngày và quy trình tuân thủ phức tạp, tốn thời gian. Chúng tôi nhận ra cơ hội và đã phát triển một phiên bản MVP trong hai tuần. Chỉ trong một tháng, chúng tôi đã đạt được khối lượng giao dịch thực tế và đáng kể.
Thách thức nằm ở việc mở rộng quy mô.
Stablecoin được thanh toán trong vài giây, ở bất kỳ đâu, vào bất kỳ thời điểm nào. Hệ thống ngân hàng truyền thống không được thiết kế cho điều đó - chúng hoạt động dựa trên xử lý theo lô, thời hạn giao dịch theo ngày làm việc và khung thời gian thanh toán kéo dài nhiều ngày. Một khách hàng ở Singapore gửi cho bạn $50,000 bằng USDC vào lúc 2 giờ sáng thứ Bảy. Trên chuỗi khối, giao dịch được thanh toán trong vài giây. Tuy nhiên, giao dịch ACH vào tài khoản ngân hàng của bạn sẽ không được khởi tạo cho đến thứ Hai, không đến được cho đến thứ Tư và có thể bị giữ lại trong quá trình kiểm duyệt ở đâu đó giữa hai thời điểm đó. Kết nối hai thế giới này đòi hỏi phải phối hợp giữa các hệ thống chưa bao giờ được thiết kế để giao tiếp với nhau, mỗi hệ thống có trạng thái riêng của mình.
Bài viết này đề cập đến hai thành phần cơ sở hạ tầng mà chúng tôi đã xây dựng để đảm bảo việc chuyển động của stablecoin hoạt động giống như việc chuyển động tiền tệ đạt tiêu chuẩn ngân hàng:
1. Lưu chuyển vốnMột công cụ điều phối dạng khai báo cho các quy trình tài chính kéo dài và liên quan đến nhiều hệ thống.
2. Của chúng tôi Khung thực thi trên chuỗiMô hình vòng đời cho các hoạt động trên chuỗi đáng tin cậy
Tất cả các thành phần khác—lối ra, lối vào và các tài khoản USD toàn cầu không lưu ký của chúng tôi—được xây dựng bằng cách kết hợp các thành phần cơ bản này. Nếu bạn chỉ nhớ một điều từ bài viết này: stablecoin rất đơn giản; stablecoin ngân hàng Không phải.
Dòng tiền
Khi chuyển tiền qua nhiều hệ thống bên ngoài, bạn cần hơn cả sự phối hợp tạm thời. Bạn cần một cách để mô tả toàn bộ luồng giao dịch một cách rõ ràng: những gì cần xảy ra, phản ứng với những sự kiện nào, và với những đảm bảo nào. Và luồng giao dịch đó cần phải có thể kiểm tra, tiếp tục được và chính xác ngay cả khi các bước gặp sự cố giữa chừng. Đó chính là những gì Flow of Funds mang lại cho chúng ta.
Vấn đề về việc di chuyển tiền tệ
Hầu hết các thách thức trong việc phối hợp phần mềm đều liên quan đến việc xử lý sự cố một cách linh hoạt. Phối hợp tài chính có một yêu cầu khắt khe hơn: Tiền đã bắt đầu lưu thông..
Xem xét một giao dịch chuyển khoản tức thì. Khách hàng nhận được $10,000 USDC. Chúng tôi ghi có vào tài khoản của họ ngay lập tức (trước khi giao dịch ACH cơ bản được thanh toán) để họ có thể sử dụng số vốn đó ngay lập tức. Đằng sau hậu trường, chúng tôi đã cấp một khoản vay. Khi giao dịch ACH đến sau vài ngày, chúng tôi thu hồi khoản vay và phí.
Đó là bốn quy trình trên hai hệ thống bên ngoài: thanh lý tài sản kỹ thuật số, giải ngân khoản vay, thanh toán ACH và thu phí. Mỗi bước phụ thuộc vào bước trước đó, và bất kỳ bước nào cũng có thể gặp sự cố. Bạn không thể quản lý điều này bằng cách sử dụng trạng thái phân tán và các trình xử lý tạm thời.
Trừu tượng lõi
Hệ thống điều phối dựa trên quy tắc và khai báo Flow of Funds. Trừu tượng hóa cốt lõi bao gồm ba phần:
Sự kiện là các tín hiệu cho biết đã xảy ra một sự kiện nào đó—giao dịch ACH đã được thanh toán, tiền đã được nhận, yêu cầu ủy quyền thẻ đã được xử lý, v.v. Các sự kiện có thể đến từ các hệ thống bên ngoài hoặc được phát ra từ bên trong.
Quy tắc Xác định các hành động cần thực hiện khi xảy ra các sự kiện. Mỗi quy tắc xác định danh sách các sự kiện kích hoạt và chuỗi các tác động phụ cần thực thi.
Tác dụng phụ Các hành động chúng ta thực hiện để phản hồi sự kiện: khởi tạo chuyển khoản, tạo lệnh giữ, giải ngân khoản vay, thu phí. Một quy tắc chỉ được kích hoạt một lần. Lần đầu tiên sự kiện khớp xuất hiện, các tác vụ phụ sẽ được thực thi theo thứ tự, và quy tắc sẽ được tiêu thụ. Điều này đảm bảo tính idempotent trong bối cảnh luồng.
Tại sao lại là Declarative?
Giải pháp thay thế là kiến trúc điều phối bắt buộc: các trình xử lý gọi các trình xử lý khác, trạng thái được phân tán trên các bảng, và "dòng chảy" chỉ tồn tại trong sự phối hợp ngầm giữa các đoạn mã.
Điều đó hoạt động tốt cho các quy trình đơn giản. Đối với các hoạt động tài chính kéo dài nhiều ngày, liên quan đến nhiều hệ thống, có các yêu cầu tuân thủ và sự cố một phần, hệ thống trở nên không thể duy trì. Xử lý lỗi được thực hiện một cách tùy tiện. Các đường dẫn phục hồi là ngầm định. Sau sáu tháng, không ai có thể tự tin trả lời câu hỏi "Nếu bước 3 thất bại sau khi bước 2 thành công, thì điều gì sẽ xảy ra?"
Các quy tắc khai báo đảo ngược mô hình. Bạn định nghĩa máy trạng thái một cách rõ ràng: những Sự kiện kích hoạt những Các hành động. Hệ thống điều phối xử lý việc thực thi, lưu trữ và khôi phục. Quy trình là tài liệu.
Bảo đảm
FoF cung cấp cho chúng ta bốn hằng số mà chúng ta có thể tin cậy:
1. Tính idempotent - Một quy tắc được kích hoạt chính xác một lần cho mỗi bối cảnh luồng, bất kể có sự kiện trùng lặp hay các lần thử lại.
2. Đối chiếu xác định - Trong cùng một tình huống, luồng sẽ dẫn đến cùng một trạng thái.
3. Khả năng kiểm toán đầy đủ - Mọi tác dụng phụ đều được theo dõi với nguồn gốc truy vết trở lại sự kiện kích hoạt.
4. Khả năng kết hợp - Các luồng phức tạp được xây dựng từ các quy tắc đơn giản, kết hợp với nhau mà không trở nên cồng kềnh.
Theo dõi quá trình thực thi
Chúng tôi theo dõi mọi tác dụng phụ thông qua các bản ghi Node—mỗi bản ghi được liên kết với bản ghi cha của nó, tạo thành một cây thực thi hoàn chỉnh. Khi cần kiểm tra tuân thủ, chúng tôi có thể theo dõi chính xác đường dẫn qua hệ thống.
Khả năng kết hợp: Quy tắc lồng nhau
Quy tắc có thể tạo ra các quy tắc con. Đây là cách các luồng phức tạp, nhiều bước được tổ chức mà không trở nên cồng kềnh. Khi một giao dịch nhánh được tạo ra, quy tắc ban đầu không cố gắng xử lý mọi thứ. Nó thiết lập tương lai Quy tắc — người nghe đang chờ đợi các sự kiện sẽ xảy ra sau này:
Logic thanh toán không tồn tại dưới dạng mã chết chờ được gọi. Nó tồn tại dưới dạng một quy tắc, chờ đợi sự kiện của nó. Khi webhook từ nhà cung cấp dịch vụ ngân hàng đến sau vài ngày, quy tắc được kích hoạt và luồng tiếp tục. Quy tắc cha được thực thi và quy tắc con tiếp tục truyền tải ngữ cảnh.
Điều này cũng có nghĩa là các luồng có thể được kết hợp một cách tùy ý. Muốn triển khai tính năng nạp tiền ngay lập tức? Rất đơn giản. Thêm một quy tắc để giải ngân khoản vay và thiết lập các quy tắc trả nợ. Mỗi thành phần được tách biệt, nhưng tất cả đều kết hợp thành một luồng hoạt động thống nhất.
Bối cảnh thực thi tác dụng phụ
Không phải tất cả các tác dụng phụ đều như nhau. Một số cần được thực hiện đồng bộ với giao dịch cơ sở dữ liệu. Một số gọi các API bên ngoài. Một số là loại "gửi và quên".
Lợi ích
Lợi ích lớn nhất là cách FoF thay đổi cách các kỹ sư viết mã điều phối tại Slash. Nếu không có nó, mỗi kỹ sư sẽ giải quyết cùng một vấn đề theo cách khác nhau. Mọi người đều tái phát minh lại bánh xe, và các bánh xe đó đều có hình dạng hơi khác nhau.
FoF nâng mức sàn. Bạn xác định. gì nên xảy ra, không Làm thế nào Để xử lý mọi trường hợp lỗi. Khung làm việc này quản lý quá trình thực thi, lưu trữ và khả năng quan sát. Các kỹ sư mới có thể đọc định nghĩa luồng và hiểu nó mà không cần phải theo dõi qua các lớp mã lệnh. Và việc viết mã điều phối kém chất lượng trở nên khó khăn hơn khi mức trừu tượng buộc bạn phải rõ ràng về các sự kiện, tác dụng phụ và chuyển đổi trạng thái.
Ramps: FoF trong thực tiễn
Với FoF làm nền tảng cho việc xây dựng các luồng tài chính, việc phát triển các sản phẩm cốt lõi của chúng tôi trở thành vấn đề xác định các quy tắc phù hợp cho từng luồng. Khái niệm trừu tượng này không quan tâm đến các hệ thống ở đầu kia, nó chỉ đơn giản là điều phối.
Các điểm ra và điểm vào là "dòng chảy" được điều phối bởi động cơ này, giới thiệu một hệ thống bên ngoài mới: nhà cung cấp tiền điện tử (hoặc bàn giao dịch OTC) xử lý việc chuyển đổi giữa stablecoin và tiền pháp định. Giống như bất kỳ hệ thống bên ngoài nào, chúng cung cấp các bản cập nhật trạng thái theo điều kiện của riêng mình - điều này có thể được sử dụng để kích hoạt các sự kiện FoF. Từ đó, chỉ cần kết hợp các dòng chảy.
Lối ra
Các cổng thanh toán cho phép khách hàng nhận thanh toán bằng stablecoin và chuyển đổi chúng thành USD trong tài khoản Slash của họ. Quy trình rất đơn giản:
- Khách hàng nhận USDC hoặc USDT tại địa chỉ nạp tiền mà chúng tôi tạo ra thông qua nhà cung cấp tiền điện tử của mình.
- Nhà cung cấp phát hiện khoản tiền gửi, chuyển đổi sang USD và khởi tạo giao dịch ACH hoặc chuyển khoản.
- Nhà cung cấp dịch vụ ngân hàng của chúng tôi nhận chuyển khoản đến.
- Chúng tôi đối chiếu giao dịch chuyển khoản với giao dịch gốc và ghi có vào tài khoản.
Đối với các khoản gửi tiền ngay lập tức—nơi chúng tôi ghi có cho khách hàng ngay lập tức và thu hồi khoản vay khi giao dịch ACH được thanh toán—quy trình bao gồm việc giải ngân khoản vay, thu hồi khoản vay và thu phí. Mỗi quy trình là một quy tắc riêng biệt, theo dõi sự kiện của nó và kết hợp thành một quy trình thống nhất. Định nghĩa FoF trông giống như sau:
Đường dẫn vào
Các điểm vào (On-ramps) hoạt động ngược lại: khách hàng chuyển USD từ tài khoản Slash của họ và nhận stablecoin vào ví bên ngoài. Quy trình:
- Khách hàng thực hiện chuyển khoản đến địa chỉ ví đích.
- Chúng tôi tạo các khoản giữ trên tài khoản của họ cho số tiền cộng với phí.
- Chúng tôi thực hiện chuyển khoản ACH hoặc chuyển khoản điện tử theo hướng dẫn nạp tiền tại nhà cung cấp dịch vụ tiền điện tử của chúng tôi.
- Nhà cung cấp nhận được khoản tiền và chuyển stablecoin đến địa chỉ đích.
Điều đáng chú ý là việc triển khai này yêu cầu rất ít hạ tầng mới. Khung FoF và logic đối chiếu mà chúng tôi xây dựng cho các điểm thoát (off-ramps) đã được áp dụng trực tiếp. Các điểm vào (on-ramps) có quy tắc khác nhau để theo dõi các sự kiện khác nhau — nhưng cơ chế nền tảng vẫn giống nhau.
Vòng đời trên chuỗi
FoF đã giải quyết vấn đề phối hợp ở phía tiền pháp định — hệ thống ngân hàng, nhà cung cấp dịch vụ, tuân thủ quy định. Tuy nhiên, khi chúng tôi bắt đầu phát triển Global USD, chúng tôi gặp phải một lĩnh vực mới: chính chuỗi khối. Đưa giao dịch lên chuỗi, xác nhận giao dịch đã được thực hiện, xử lý sự cố và tái tổ chức chuỗi, cũng như suy ra trạng thái chính xác từ kết quả — đó là một vấn đề phối hợp khác. Chúng tôi cần những đảm bảo tương tự như với FoF, nhưng cho việc thực thi trên chuỗi.
Quy trình: Ý định → Thực thi → Đối chiếu
Chúng tôi áp dụng một mô hình nhất quán cho tất cả các hoạt động blockchain:
1. Ý định: Xác định mục tiêu mà chúng ta đang hướng tới.
2. Thực thiGửi giao dịch và theo dõi quá trình đưa giao dịch vào khối.
3 Đối chiếuXử lý các khối đã được xác nhận, cập nhật trạng thái nội bộ, kích hoạt các luồng xử lý tiếp theo.
Nếu bạn đến từ lĩnh vực tài chính truyền thống, so sánh này rất đơn giản:
- Ý định ≈ lệnh thanh toán
- Thực thi ≈ đang chờ xử lý
- Đối chiếu ≈ đã đăng
Mỗi giai đoạn có các trách nhiệm và chế độ hỏng hóc riêng biệt. Phần còn lại của phần này sẽ hướng dẫn cách chúng tôi xây dựng từng lớp.
Trước khi có thể thực thi bất kỳ điều gì, chúng ta cần phải định nghĩa gì Chúng tôi đang thực thi. Một giao dịch blockchain về cơ bản là một lệnh (một hàm được gọi với các tham số), nhưng chuỗi không hiểu các lệnh có thể đọc được bởi con người. Mọi thứ đều được mã hóa thành Dữ liệu cuộc gọi - Một khối byte hexadecimal xác định hàm cần gọi và các tham số cần truyền.
Ví dụ, một giao dịch chuyển USDC đơn giản—"chuyển 500 USDC đến địa chỉ X"—sẽ trở thành:
0xa9059cbb0000000000000000000000007e2f5e1fd4d79ed41118fc6f59b53b575c51f182000000000000000000000000000000000000000000000000000000001dcd6500
Dữ liệu cuộc gọi thô như thế này là không rõ ràng và không cung cấp thông tin gì về Tại sao Tiền đã được chuyển. Và khi bạn đang xây dựng các hệ thống cần theo dõi bối cảnh kinh doanh—không chỉ việc tài sản được chuyển giao, mà còn việc đây là việc thu phí cho hóa đơn số 1234—bạn cần phải giữ nguyên bối cảnh đó.
Chúng tôi giải quyết vấn đề này bằng cách sử dụng một danh sách các định nghĩa hàm có kiểu:
Các kỹ sư làm việc với các thuật ngữ chuyên môn—hợp đồng, người nhận, số tiền—thay vì chuỗi hex. Hệ thống đăng ký xác thực đầu vào, xử lý mã hóa và lưu trữ metadata mà chúng ta sẽ cần sau này: danh mục, thẻ và bối cảnh kinh doanh.
Tạo cuộc gọi trở nên đơn giản:
Mỗi cuộc gọi sẽ được ghi lại dưới dạng một bản ghi BlockchainCall:
Chúng tôi coi BlockchainCall là đơn vị công việc cơ bản. Một giao dịch có thể gộp nhiều cuộc gọi, nhưng mỗi cuộc gọi đại diện cho một hoạt động có thể truy vết riêng biệt. Trường yêu cầu lưu trữ toàn bộ dữ liệu đầu vào có kiểu dữ liệu, bao gồm cả các byte đã mã hóa - bao gồm cả metadata và bối cảnh tùy ý. Metadata này chính là yếu tố giúp chúng tôi trả lời câu hỏi "Giao dịch chuyển $500 này dùng để làm gì?" khi đối chiếu trạng thái chuỗi với các hoạt động kinh doanh.
Thực thi: Hướng dẫn các giao dịch đến trạng thái hoàn tất
Gửi một giao dịch nghe có vẻ đơn giản. Trên thực tế, có rất nhiều rủi ro giữa "gửi đi" và "giao dịch thành công."
Khi bạn gửi một giao dịch, nó không được đưa trực tiếp vào một khối. Nó được đưa vào mempool- Khu vực chờ nơi các giao dịch được lưu trữ cho đến khi nhà sản xuất khối (block producer) chọn chúng. Trong thời gian chờ đợi, các giao dịch có thể bị loại bỏ (mempool đã đầy), bị vượt qua (ai đó trả phí cao hơn) hoặc bị kẹt (giá gas quá thấp so với điều kiện mạng hiện tại).
Khí Đây là cách các mạng lưới dựa trên Ethereum định giá các hoạt động tính toán. Mỗi hoạt động đều tiêu tốn gas, và bạn thanh toán gas bằng token gốc của mạng lưới. Khi gửi giao dịch, bạn chỉ định mức giá gas tối đa mà bạn sẵn sàng trả. Nếu tắc nghẽn mạng tăng đột biến sau khi bạn gửi giao dịch, mức giá gas của bạn có thể không còn cạnh tranh - giao dịch của bạn sẽ nằm trong mempool, chờ đợi, có thể mãi mãi.
Ngay cả sau khi một giao dịch được ghi vào một khối, nó vẫn chưa thực sự hoàn tất. Các blockchain có thể gặp phải Các cuộc tái cơ cấu (reorgs)- Các tình huống mà mạng lưới loại bỏ các khối gần đây và thay thế chúng bằng một chuỗi khối khác. Một giao dịch mà bạn cho là đã được xác nhận có thể biến mất. Điều này hiếm khi xảy ra trên các mạng lưới đã phát triển, nhưng "hiếm" không có nghĩa là "không bao giờ" khi bạn đang chuyển tiền thật.
Mỗi sự cố này xảy ra ở một lớp khác nhau: ước tính gas, ký tên, gửi giao dịch, xác nhận. Và việc khắc phục mỗi sự cố yêu cầu các biện pháp khắc phục khác nhau - giao dịch bị kẹt cần gửi lại với mức gas cao hơn, chữ ký không hợp lệ cần ký lại, và việc tái tổ chức (reorg) yêu cầu toàn bộ quy trình phải thử lại.
Chúng tôi xử lý điều này bằng cách mô hình hóa chu kỳ thực thi dưới dạng một cấu trúc phân cấp gồm 4 thực thể. Ở cấp cao nhất là kết quả kinh doanh mà chúng tôi đang cố gắng đạt được. Dưới nó, các lớp ngày càng cụ thể hơn chịu trách nhiệm về chuẩn bị, ký kết và nộp hồ sơ. Mỗi lớp chịu trách nhiệm về vùng lỗi của mình và có thể tự động thử lại trước khi chuyển lên lớp trên:
Ý định Blockchain Đại diện cho kết quả kinh doanh: "Chuyển 500 USDC đến địa chỉ này làm thanh toán cho hóa đơn số 1234." Đây là trình điều phối cấp cao nhất theo dõi toàn bộ vòng đời và có thể khởi tạo lại nếu cần thiết.
Cuộc gọi đã chuẩn bị là một giao dịch không thể thay đổi, không có dấu, với ước tính gas được khóa cố định. Nếu ước tính gas hết hạn (điều kiện mạng thay đổi), chúng tôi tạo một PreparedCall mới.
Thực thi cuộc gọi đã chuẩn bị Đại diện cho một nỗ lực ký kết. Đối với các thao tác phía máy chủ, chúng tôi tự động ký kết. Đối với các thao tác hướng đến người dùng (như Global USD), người dùng xác nhận thông qua mã OTP. Dù bằng cách nào, sau khi ký kết, chúng tôi sẵn sàng gửi yêu cầu.
Nút thực thi cuộc gọi đã chuẩn bị Đây là một lần gửi giao dịch duy nhất. Chúng tôi gửi giao dịch đến mạng và kiểm tra xem nó có được chấp nhận hay không. Nếu giao dịch thất bại vì các lý do có thể thử lại (thời gian chờ mạng hết hạn, bị loại khỏi mempool), chúng tôi tạo một nút mới và thử lại.
Mỗi lớp chịu trách nhiệm xử lý vùng lỗi của riêng mình:
Điểm mấu chốt là khi một lớp hết các tùy chọn khắc phục, sự cố sẽ được nâng cấp lên lớp cha. Hãy xem xét trường hợp đánh giá thấp liên tục về gas. Tình trạng tắc nghẽn mạng tăng đột biến, và các thông số gas được khóa trong PreparedCall của chúng ta không còn cạnh tranh được. Nút thực thi thử lại một vài lần, và có thể tắc nghẽn sẽ giảm bớt. Sau N lần thất bại, nó không thể làm gì thêm. Lỗi được nâng cấp lên Execution, đạt đến trạng thái cuối cùng và nâng cấp lên Intent. Intent tạo ra một Intent con với hệ số gas cao hơn, xây dựng một PreparedCall mới, và chu kỳ bắt đầu lại.
Mỗi lớp xử lý vùng lỗi của riêng mình, nhưng việc nâng cấp là rõ ràng. Ý định cha giữ nguyên lịch sử đầy đủ; ý định con nhận được một lần thử mới với các thông số được điều chỉnh. Chúng ta không bao giờ mất bối cảnh về Tại sao Chúng tôi đang thử lại.
Hòa giải: Từ các sự kiện chuỗi đến trạng thái sản phẩm
Một giao dịch được bao gồm trong một khối. Bây giờ thì sao?
Blockchain không trực tiếp cho chúng ta biết rằng một giao dịch chuyển 1000 USDC đã diễn ra. Nó chỉ cho chúng ta biết rằng một giao dịch đã được thực hiện và phát ra một số... Nhật ký sự kiệnChúng ta cần phân tích các bản ghi đó, xác định ý nghĩa của chúng và cập nhật trạng thái nội bộ cho phù hợp.
Nhật ký sự kiện là cách hợp đồng thông minh ghi lại những gì đã xảy ra trong quá trình thực thi. Khi bạn gọi hàm chuyển Chức năng trên hợp đồng USDC, hợp đồng phát ra một Chuyển nhượng Sự kiện bao gồm ba thông tin: người gửi, người nhận và số lượng. Sự kiện này được ghi lại trong biên lai giao dịch dưới dạng một mục nhật ký.
Nhưng các bản ghi được mã hóa dưới dạng các trường chủ đề và dữ liệu chứa các giá trị được mã hóa hex. Việc phân tích chúng yêu cầu phải biết chữ ký sự kiện và giải mã các tham số. Một bản ghi Transfer thô trông giống như sau:
Làm thế nào để chúng ta biết đây là một giao dịch chuyển nhượng? Mỗi bản ghi's chủ đề[0] là hàm băm Keccak256 của chữ ký sự kiện - trong trường hợp này, 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef là hàm băm của Chuyển khoản (địa chỉ nguồn, địa chỉ đích, giá trị uint256)- Sự kiện chuyển nhượng tiêu chuẩn ERC-20. Các tham số được đánh dấu là được lập chỉ mục được lưu trữ trong mảng chủ đề theo thứ tự khai báo, sau hàm băm chữ ký. Đối với sự kiện Chuyển giao này, từ nằm trong chủ đề[1] và để trong chủ đề[2]Các tham số không được lập chỉ mục như giá trị được mã hóa bằng ABI trong dữ liệu.
Trích xuất chi tiết giao dịch từ nhật ký này:
- từ:
chủ đề[1](32 byte, có thêm 0 ở đầu) →0x7e2f5e1fd4d79ed41118fc6f59b53b575c51f182 - để:
chủ đề[2](32 byte, có thêm 0 ở đầu) →0xa6dbc393e2b1c30cff2fbc3930c3e4ddfc9d1373 - giá trị:
dữ liệuĐược giải mã thành uint256 →0x4c4b40= 5.000.000 (5 USDC, vì USDC có 6 chữ số thập phân).
Việc phải nắm rõ cách phân tích mọi loại nhật ký dường như là một cơn ác mộng - đó là lý do tại sao chúng tôi đã phát triển các bộ xử lý nhật ký có khả năng phân tích các loại sự kiện cụ thể và chuyển đổi chúng thành trạng thái của hệ thống:
Bộ xử lý nhập dữ liệu nhật ký thô, phân tích nó thành các trường có kiểu dữ liệu (thay vì chuỗi hex), và tạo ra các thực thể miền.
Sự bao gồm so với sự xác nhận
Chúng tôi quản lý hai giai đoạn vòng đời riêng biệt:
- Sự bao gồm - Giao dịch lần đầu tiên xuất hiện trong một khối. Trạng thái hiện tại là tạm thời - khối này vẫn có thể bị tái tổ chức.
- Xác nhận - Khối đã đạt độ sâu đủ (có đủ số khối tiếp theo để loại trừ khả năng tái tổ chức). Trạng thái đã được xác định cuối cùng.
Sự phân biệt này rất quan trọng. Chúng ta có thể cập nhật giao diện người dùng (UI) để hiển thị trạng thái đang chờ xử lý khi thêm vào, nhưng sẽ không kích hoạt các luồng FoF tiếp theo cho đến khi có xác nhận. Chi phí của việc hành động dựa trên trạng thái tạm thời là không giới hạn.
Các bộ xử lý nhật ký xử lý các sự kiện riêng lẻ, nhưng chúng ta thường cần phối hợp giữa chúng hoặc thêm trạng thái cấp giao dịch. Các bộ xử lý giao dịch gói gọn điều này: chúng nhận đầu ra đã hợp nhất từ tất cả các bộ xử lý nhật ký và có thể biến đổi nó, thêm vào nó hoặc kích hoạt các tác động tiếp theo. Đây cũng là nơi chu kỳ hai giai đoạn xuất hiện. Xử lý giao dịch Chạy ở chế độ bao gồm - chúng tôi tạo ra trạng thái tạm thời. Xác nhận quy trình Chạy sau khi khối được xác nhận - đây thường là nơi chúng ta hoàn tất chu kỳ hoạt động cho các giao dịch tài chính.
Kết nối nhật ký với các cuộc gọi
Khi bộ xử lý nhật ký của chúng tôi tạo ra một bản ghi chuyển giao, nó cần liên kết trở lại với BlockchainCall gốc. Nhật ký cho chúng ta biết gì Đã xảy ra — tài sản được chuyển từ A sang B. BlockchainCall cho chúng ta biết Tại sao—đây là việc thu phí, thanh toán cho nhà cung cấp hoặc hoàn tiền. Đối với các giao dịch đơn giản chỉ cần một lần gọi, điều này khá đơn giản. Đối với các giao dịch gộp—nơi chúng ta gộp nhiều thao tác vào một giao dịch trên chuỗi để tiết kiệm gas—việc này trở nên phức tạp hơn. Biên lai cung cấp cho chúng ta danh sách phẳng của tất cả các nhật ký được phát ra trong quá trình thực thi, mà không có thông tin nào cho biết lần gọi nào đã tạo ra nhật ký nào. Chúng ta giải quyết vấn đề này bằng cách theo dõi khung gọi (call-frame tracing), điều mà chúng ta sẽ đề cập chi tiết trong phần nâng cao bên dưới.
Nâng cao: Gán nhật ký theo lô cho các cuộc gọi riêng lẻ
Phần này đề cập đến một thách thức kỹ thuật cụ thể liên quan đến giao dịch theo lô. Nếu bạn không làm việc với ERC-4337 hoặc thực thi theo lô, bạn có thể bỏ qua và chuyển sang Global USD. Trước đó, chúng tôi đã đề cập rằng việc kết nối các bản ghi trở lại BlockchainCall gốc của chúng là đơn giản đối với các giao dịch đơn lẻ. Đối với các giao dịch theo lô, điều này không đơn giản.
Vấn đề
Khi chúng ta gộp nhiều thao tác vào một giao dịch duy nhất—ví dụ: một khoản thanh toán $500 cộng với phí $1—cả hai đều được thực thi một cách nguyên tử. Biên lai giao dịch cung cấp cho chúng ta một danh sách phẳng của mọi nhật ký được phát ra trong quá trình thực thi:
Chúng tôi nhận được một mảng phẳng chứa tất cả các bản ghi được ghi lại trong quá trình thực thi. Khi xem xét bản ghi này, chúng tôi có thể xác định hai sự kiện Chuyển giao tại các chỉ số bản ghi 1 và 2 (cả hai đều chia sẻ...) 0xddf252ad... Chuyển giao chữ ký sự kiện mà chúng ta đã thảo luận trước đó).
Nhưng khoản nào là thanh toán và khoản nào là phí? Hóa đơn không cho chúng ta biết—các bản ghi được gán cho giao dịch cấp cao nhất, không phải cho các cuộc gọi riêng lẻ trong một lô. Bạn có thể nghĩ: chỉ cần khớp các bản ghi với các cuộc gọi theo thứ tự. Nhưng điều đó chỉ hoạt động nếu mỗi cuộc gọi phát ra chính xác một bản ghi. Một giao dịch chuyển khoản đơn giản phát ra một bản ghi; một giao dịch hoán đổi có thể phát ra năm bản ghi. Nếu không biết giới hạn, bạn không thể ánh xạ chúng một cách đáng tin cậy.
Theo dõi khung gọi
Giải pháp hóa ra là Ghi nhật ký giao dịch gỡ lỗi- Phương thức RPC của nút lưu trữ Geth mà hầu hết mọi người sử dụng để gỡ lỗi các giao dịch thất bại. Nhưng nó còn làm một việc khác: nó tái phát giao dịch và trả về cây khung gọi hoàn chỉnh, kèm theo nhật ký được gắn ở độ sâu chính xác trong cấu trúc gọi.
Kết quả là một cấu trúc lồng nhau theo cách đệ quy của các khung gọi (được đơn giản hóa để dễ đọc).
Chúng tôi chuyển đổi cấu trúc đệ quy này thành một sơ đồ giữ nguyên các mối quan hệ cây:
Xem xét một giao dịch UserOp theo lô với hai giao dịch chuyển USDC: một khoản thanh toán $500 và một khoản phí $1.10, được thể hiện bởi bản ghi thực thi ở trên. Bản ghi này cung cấp cho chúng ta:

Toàn bộ giao dịch hiện có thể được biểu diễn dưới dạng một cây. Điều này định hình lại toàn bộ vấn đề: thay vì suy luận cấu trúc từ một mảng nhật ký phẳng, chúng ta tái tạo cây thực thi - nơi cấu trúc gọi hàm được thể hiện rõ ràng và các nhật ký được gắn vào các khung đã phát ra chúng.
Từ đó, việc xác định nguồn gốc trở nên đơn giản. Tìm nút tương ứng với Thực thi lô Gọi, lặp qua các phần tử con tại các chỉ số 0..N-1và thu thập nhật ký một cách đệ quy từ mỗi cây con. Mỗi chỉ mục con 0..N-1 được ánh xạ trực tiếp đến hàm BlockchainCall tương ứng của nó. Chỉ mục trong lôChúng ta hiện đã biết chính xác cuộc gọi nào đã tạo ra các bản ghi nào.

Vì hầu hết mọi giao dịch đều cần thông tin này, chúng tôi đã tích hợp trực tiếp tính năng này vào bộ xử lý nhật ký của mình. Nó tái tạo cây gọi đầy đủ, khớp nhật ký với khung gốc của chúng và giải quyết tất cả các BlockchainCalls trong lô. Mỗi bộ xử lý nhật ký sau đó nhận được ngữ cảnh gọi và khung cụ thể cho nhật ký mà nó đang xử lý:
Danh sách đầy đủ các nguồn gốc:
USD Toàn cầu: Dự án Tốt nghiệp
Các cổng ra và cổng vào đã giải quyết một vấn đề cho khách hàng hiện tại của chúng tôi—các doanh nghiệp có tài khoản ngân hàng tại Mỹ muốn chuyển đổi giữa tiền fiat và tiền điện tử. Tuy nhiên, chúng tôi liên tục nhận được phản hồi từ một phân khúc khác: các doanh nghiệp quốc tế cần truy cập vào hệ thống thanh toán bằng đô la Mỹ nhưng không thể dễ dàng tiếp cận chúng.
Nếu bạn là một nhà thầu phần mềm tại Argentina, một nhà bán lẻ thương mại điện tử tại Nigeria hoặc một công ty SaaS tại Đông Nam Á, việc mở tài khoản ngân hàng tại Mỹ thường đòi hỏi phải thành lập một thực thể pháp nhân tại Mỹ – bao gồm luật sư, đại diện đăng ký và hàng tháng chi phí phát sinh. Nhiều doanh nghiệp hợp pháp thực tế bị loại trừ khỏi nền kinh tế đô la, không phải vì họ đã làm gì sai, mà vì nơi họ được thành lập.
Stablecoin thay đổi điều này. Số dư USDC tương đương với số dư USD. Global USD là nỗ lực của chúng tôi trong việc xây dựng hạ tầng ngân hàng dựa trên nguyên tắc đó.
Không lưu trữ theo thiết kế
Chúng tôi đã xây dựng Global USD như một hệ thống không lưu ký. Quyết định này được đưa ra dựa trên hai yếu tố: phức tạp về mặt pháp lý và niềm tin.
Việc giữ tiền của khách hàng đòi hỏi các yêu cầu cấp phép khác nhau tùy theo từng khu vực pháp lý. Kiến trúc không lưu ký giúp đơn giản hóa tình trạng cấp phép của chúng tôi ở nhiều thị trường này. Về mặt tin cậy, khách hàng tự quản lý khóa riêng của mình — theo thiết kế, Slash không thể khởi tạo giao dịch mà không có sự ủy quyền mật mã từ người ký tài khoản.
Thuật toán cơ bản là ví thông minhMột hợp đồng thông minh hoạt động như một ví điện tử nhưng có khả năng kiểm soát truy cập có thể lập trình.
Mỗi tài khoản Global USD là một ví thông minh được quản lý bởi một hệ thống đa chữ ký (multi-sig). Mỗi thành viên được ủy quyền của doanh nghiệp đều nắm giữ một khóa. Các giao dịch chuyển khoản yêu cầu sự phê duyệt của họ trước khi thực hiện. Slash có thể chuẩn bị một giao dịch, nhưng chúng tôi không thể thực hiện Không cần sự ủy quyền của người ký.
Ký kết mà không có quyền giám hộ
Điều này đặt ra một câu hỏi về trải nghiệm người dùng (UX): Nếu người dùng kiểm soát các khóa, liệu họ có cần phải quản lý các cụm từ hạt giống và ký giao dịch thủ công không?
Chúng tôi sử dụng cơ sở hạ tầng ví tích hợp từ Privy và Alchemy. Khi người dùng tạo tài khoản, một khóa riêng tư được tạo ra trong bộ nhớ cách ly phần cứng (môi trường thực thi đáng tin cậy, hay TEE). Khóa này tồn tại, nhưng được thiết kế để không thể truy cập trực tiếp bởi Slash hoặc bất kỳ ai khác. Khi người dùng khởi tạo một giao dịch, họ xác nhận thông qua OTP, điều này cho phép TEE ký thay mặt họ. Giao dịch đã ký sau đó được gửi lên mạng.
Từ góc độ người dùng, việc này giống như việc xác nhận một giao dịch chuyển khoản ngân hàng. Từ góc độ quản lý tài sản, chúng tôi không bao giờ tiếp xúc với các khóa riêng tư.
Điều này mang lại những gì
Một doanh nghiệp tại Lagos nay có thể giữ đô la Mỹ, nhận thanh toán từ khách hàng Mỹ và thanh toán cho nhà cung cấp quốc tế — tất cả mà không cần tài khoản ngân hàng Mỹ, không có rủi ro lưu ký và với cùng quy trình kiểm toán và tuân thủ mà chúng tôi áp dụng cho bất kỳ khách hàng Slash nào.
Đó chính là những gì stablecoin thực sự có thể trở thành: không chỉ là một phương thức thanh toán, mà còn là cơ sở hạ tầng nền tảng cho một hệ thống tài chính dễ tiếp cận hơn.
Tiếp theo là gì?
Các công cụ cơ bản mà chúng tôi đã xây dựng không chỉ dùng để chuyển tiền giữa tiền fiat và tiền điện tử. Chúng là nền tảng cho mọi thứ chúng tôi đang phát triển tại Slash. Chúng tôi đang mở rộng các dịch vụ tài khoản toàn cầu của mình – mang đến cho nhiều doanh nghiệp hơn khả năng truy cập vào hệ thống thanh toán USD, bất kể họ được thành lập ở đâu. Và chúng tôi đang phát triển thẻ thanh toán toàn cầu: một thẻ có tỷ lệ hoàn tiền cao, được bảo đảm bằng stablecoin, cho phép khách hàng chi tiêu số dư của mình ở bất kỳ đâu. Cả hai đều phụ thuộc mạnh mẽ vào các khung làm việc điều phối và thực thi mà chúng tôi đã mô tả ở đây. Nếu bạn đã đọc đến đây và là một kỹ sư muốn giải quyết các vấn đề hạ tầng phức tạp cho khách hàng thực tế tại một công ty đang phát triển nhanh chóng, chúng tôi đang tuyển dụng.