Calldata là gì? Trong thế giới blockchain Ethereum, đây là một trong những khái niệm kỹ thuật nền tảng nhưng thường bị hiểu lầm hoặc bỏ qua. Calldata (dữ liệu gọi) là vùng dữ liệu chỉ đọc chứa các byte được gửi kèm theo một giao dịch hoặc một lời gọi hàm đến hợp đồng thông minh.

- 1. Calldata là gì? Định nghĩa chi tiết
- 2. Cấu trúc của Calldata
- 2.1. Function Selector (4 byte đầu tiên)
- 2.2. Các tham số (Arguments)
- 3. Calldata hoạt động như thế nào trên Blockchain?
- 3.1. Quy trình gửi giao dịch với calldata
- 3.2. Calldata trong quá trình thực thi hợp đồng
- 4. Chi phí Gas của Calldata
- 4.1. Công thức tính phí calldata
- 4.2. So sánh với storage và memory
- 4.3. EIP-7623: Tăng chi phí calldata
- 5. Calldata và các Data Location khác trong Solidity
- 6. Calldata và ABI Encoding
- 7. Calldata và Layer-2 Rollup
- 8. Ưu điểm và nhược điểm của Calldata
- 9. Câu hỏi thường gặp về Calldata
- 10. Kết luận
Nếu giao dịch Ethereum là một phong bì thư, thì calldata chính là nội dung lá thư – phần dữ liệu thực sự mà người gửi muốn truyền đạt đến hợp đồng. Mỗi khi bạn gọi hàm transfer của token ERC-20, mint NFT, hay swap token trên Uniswap, calldata chính là phần dữ liệu chứa tên hàm và các tham số mà ví của bạn gửi đến hợp đồng thông minh.
Điều đặc biệt quan trọng là calldata được lưu trữ vĩnh viễn trên blockchain như một phần của bản ghi giao dịch, nhưng nó không thể bị thay đổi bởi hợp đồng trong quá trình thực thi. Đây là lý do tại sao calldata được sử dụng rộng rãi bởi các Rollup Layer-2 như Arbitrum và Optimism để đăng dữ liệu giao dịch của họ lên Ethereum Layer-1 với chi phí thấp hơn so với lưu trữ trong contract storage.
Trong bài viết này, chúng ta sẽ cùng tìm hiểu Calldata là gì, cấu trúc của nó, cách mã hóa ABI, chi phí gas, sự khác biệt với memory và storage, và tác động của các nâng cấp gần đây như EIP-4844 đến vai trò của calldata. Nếu bạn chưa nắm nền tảng, hãy đọc bài Transaction là gì? và Smart Contract là gì? trước.
1. Calldata là gì? Định nghĩa chi tiết
Calldata là vùng dữ liệu chỉ đọc được gửi kèm theo một giao dịch Ethereum hoặc một lời gọi hàm giữa các hợp đồng. Về mặt kỹ thuật, calldata là một mảng byte (byte array) chứa toàn bộ dữ liệu đầu vào của một giao dịch, bao gồm:
-
Function selector: 4 byte đầu tiên xác định hàm nào sẽ được gọi.
-
Các tham số: Dữ liệu được mã hóa theo chuẩn ABI.
Khi một người dùng gửi ETH cho một địa chỉ ví thông thường, calldata thường trống rỗng (0 byte). Nhưng khi gửi giao dịch đến một hợp đồng thông minh, calldata chứa dữ liệu chỉ dẫn cho hợp đồng biết cần thực hiện hành động gì.
Ví dụ đơn giản: Khi bạn gọi hàm transfer(address,uint256) của một token ERC-20 để chuyển 100 token đến địa chỉ 0xRecipient, calldata sẽ trông như sau:
0xa9059cbb000000000000000000000000RecipientAddress0000000000000000000000000000000000000000000000000000000005f5e100
Trong đó:
-
0xa9059cbb: 4 byte đầu tiên (function selector) xác định hàmtransfer. -
Phần còn lại: Địa chỉ người nhận (32 byte) và số lượng token (32 byte), được mã hóa theo chuẩn ABI.
Đặc điểm quan trọng của calldata:
-
Chỉ đọc (Read-only): Hợp đồng không thể sửa đổi calldata. Nó chỉ có thể đọc dữ liệu từ đó.
-
Không thể truy cập từ bên ngoài: Calldata chỉ có thể được truy cập bởi hàm đang thực thi. Các hàm khác trong cùng hợp đồng không thể đọc calldata của hàm trước đó.
-
Lưu trữ vĩnh viễn: Calldata được lưu trữ trên blockchain như một phần của giao dịch, nhưng có chi phí gas thấp hơn so với contract storage.
-
Không giới hạn kích thước: Calldata không có giới hạn kích thước cứng, nhưng kích thước càng lớn thì phí gas càng cao.
Bạn có thể tìm hiểu thêm về giao dịch trong bài Transaction là gì?.
2. Cấu trúc của Calldata
Calldata không phải là một khối dữ liệu ngẫu nhiên. Nó tuân theo một cấu trúc chặt chẽ được định nghĩa bởi chuẩn ABI (Application Binary Interface) của Ethereum.

2.1. Function Selector (4 byte đầu tiên)
4 byte đầu tiên của calldata là function selector – một mã định danh xác định hàm nào của hợp đồng sẽ được gọi. Selector được tính bằng cách lấy 4 byte đầu tiên của hash Keccak-256 của chuỗi chữ ký hàm (ví dụ: transfer(address,uint256)).
Ví dụ:
-
Hàm
transfer(address,uint256): selector =0xa9059cbb -
Hàm
approve(address,uint256): selector =0x095ea7b3 -
Hàm
swapExactTokensForTokens(uint256,uint256,address[],address,uint256): selector =0x38ed1739
Khi hợp đồng nhận được calldata, nó so sánh 4 byte đầu tiên với bảng selector để xác định hàm cần thực thi.
2.2. Các tham số (Arguments)
Sau 4 byte selector, calldata chứa các tham số của hàm. Mỗi tham số được mã hóa thành 32 byte (256 bit) theo chuẩn ABI. Điều này có nghĩa là ngay cả một tham số nhỏ như uint8 cũng chiếm 32 byte trong calldata.
Ví dụ mã hóa ABI:
-
Tham số
address: 32 byte, với 20 byte địa chỉ được căn phải và 12 byte padding 0 ở bên trái. -
Tham số
uint256: 32 byte, biểu diễn số nguyên. -
Tham số
bool: 32 byte, với 0 hoặc 1. -
Tham số
stringhoặcbytes: Độ dài động, được mã hóa với offset và length.
Cấu trúc calldata cho hàm transfer:
[0-3] Function selector: 0xa9059cbb [4-35] Tham số 1: address (32 byte) [36-67] Tham số 2: uint256 (32 byte)
Tổng kích thước calldata cho hàm transfer là 68 byte (4 + 32 + 32). Đối với các hàm phức tạp hơn như swap trên Uniswap, calldata có thể lên đến hàng trăm byte.
Ví dụ minh họa chi tiết
Giả sử bạn muốn gọi hàm transfer trên một hợp đồng token với:
-
Người nhận:
0x742d35Cc6634C0532925a3b844Bc454e4438f44e -
Số lượng: 100 token (với 18 chữ số thập phân, tức là
100000000000000000000)
Calldata sẽ được mã hóa như sau:
0xa9059cbb 000000000000000000000000742d35Cc6634C0532925a3b844Bc454e4438f44e 0000000000000000000000000000000000000000000000000000000000000064
Tổng cộng 68 byte, trong đó:
-
4 byte selector.
-
32 byte địa chỉ người nhận.
-
32 byte số lượng token.
Bạn có thể tìm hiểu thêm về ABI encoding trong bài Smart Contract là gì?.
3. Calldata hoạt động như thế nào trên Blockchain?
3.1. Quy trình gửi giao dịch với calldata
Khi người dùng gửi một giao dịch đến hợp đồng thông minh, ví sẽ thực hiện các bước sau:

-
Xây dựng calldata: Ví mã hóa function selector và các tham số theo chuẩn ABI.
-
Đính kèm calldata vào giao dịch: Calldata được đặt trong trường
datacủa giao dịch. -
Ký giao dịch: Ví ký giao dịch bằng khóa riêng tư.
-
Phát sóng giao dịch: Giao dịch được gửi đến mạng lưới Ethereum.
-
Thực thi hợp đồng: Khi giao dịch được xác nhận, EVM nạp calldata và thực thi hàm tương ứng.
-
Lưu trữ calldata: Calldata được lưu trữ vĩnh viễn trên blockchain như một phần của giao dịch.
3.2. Calldata trong quá trình thực thi hợp đồng
Khi hợp đồng nhận được calldata, nó có thể truy cập dữ liệu này thông qua data location calldata. Trong Solidity, calldata là một vùng dữ liệu chỉ đọc dành riêng cho các tham số của hàm external. Ví dụ:
function transfer(address to, uint256 amount) external { // 'to' và 'amount' nằm trong calldata // Không thể sửa đổi 'to' hoặc 'amount' }
Nếu bạn cần sửa đổi dữ liệu, bạn phải sao chép nó vào memory:
function process(uint256[] calldata data) external { uint256[] memory mutableData = data; // Sao chép từ calldata vào memory mutableData[0] = 100; // Có thể sửa đổi }
Điểm quan trọng: Calldata không thể bị sửa đổi bởi hợp đồng. Điều này đảm bảo tính toàn vẹn của dữ liệu đầu vào và ngăn chặn các cuộc tấn công thay đổi tham số trong quá trình thực thi.
Bạn có thể tìm hiểu thêm về EVM trong bài EVM là gì?.
4. Chi phí Gas của Calldata
Một trong những yếu tố quan trọng nhất khi nói về calldata là chi phí gas. Calldata có chi phí gas thấp hơn đáng kể so với việc lưu trữ dữ liệu trong contract storage, nhưng vẫn tốn kém hơn so với việc sử dụng memory.
4.1. Công thức tính phí calldata
Theo đặc tả của Ethereum, chi phí gas cho calldata được tính như sau:
-
4 gas cho mỗi byte có giá trị 0.
-
16 gas cho mỗi byte có giá trị khác 0.
Điều này có nghĩa là calldata chứa nhiều byte 0 sẽ rẻ hơn so với calldata chứa nhiều byte khác 0.
Ví dụ: Một giao dịch transfer ERC-20 có calldata 68 byte:
-
4 byte selector: có thể chứa byte 0 và byte khác 0.
-
32 byte địa chỉ: thường chứa nhiều byte 0 (địa chỉ được căn phải).
-
32 byte số lượng: thường chứa nhiều byte 0 (nếu số lượng nhỏ).
Giả sử calldata có 20 byte 0 và 48 byte khác 0:
-
Phí = (20 × 4) + (48 × 16) = 80 + 768 = 848 gas.
4.2. So sánh với storage và memory
| Data Location | Chi phí gas | Lưu trữ | Có thể sửa đổi |
|---|---|---|---|
| Calldata | 4-16 gas/byte | Vĩnh viễn (trên blockchain) | Không |
| Memory | 3-10 gas/byte | Tạm thời (trong RAM) | Có |
| Storage | 20,000 gas/word (ghi mới) | Vĩnh viễn (trên blockchain) | Có |
Nhận xét: Calldata rẻ hơn storage rất nhiều (khoảng 1,250 lần cho mỗi byte), nhưng đắt hơn memory. Đây là lý do tại sao calldata được sử dụng rộng rãi cho dữ liệu không cần sửa đổi, trong khi memory được dùng cho dữ liệu tạm thời cần xử lý.
4.3. EIP-7623: Tăng chi phí calldata
Vào tháng 2 năm 2024, EIP-7623 được đề xuất nhằm tăng chi phí calldata cho các giao dịch có tỷ lệ calldata cao so với execution gas. Đề xuất này nhằm hạn chế kích thước block tối đa và khuyến khích sử dụng blob space cho dữ liệu Rollup.
5. Calldata và các Data Location khác trong Solidity
Trong Solidity, có ba data location chính: storage, memory, và calldata. Mỗi loại có vai trò và đặc điểm riêng.

Storage
Storage là nơi lưu trữ vĩnh viễn dữ liệu của hợp đồng trên blockchain. Biến trạng thái (state variables) được lưu trong storage. Ghi dữ liệu vào storage rất tốn gas (20,000 gas cho mỗi word 32 byte). Storage có thể được sửa đổi bởi hợp đồng.
Memory
Memory là vùng dữ liệu tạm thời được sử dụng trong quá trình thực thi hàm. Dữ liệu trong memory bị xóa sau khi hàm kết thúc. Memory có thể được sửa đổi và có chi phí gas trung bình.
Calldata
Calldata là vùng dữ liệu chỉ đọc chứa các tham số của hàm external. Calldata không thể bị sửa đổi và có chi phí gas thấp nhất trong ba loại. Calldata chỉ có thể được truy cập bởi hàm đang thực thi.
Khi nào sử dụng calldata:
-
Khi hàm chỉ cần đọc tham số mà không sửa đổi.
-
Khi muốn tiết kiệm gas so với memory.
-
Khi tham số là mảng hoặc struct lớn.
Khi nào sử dụng memory:
-
Khi cần sửa đổi dữ liệu trong hàm.
-
Khi cần tạo dữ liệu mới trong quá trình thực thi.
-
Khi làm việc với dữ liệu trả về từ lời gọi hàm khác.
Bạn có thể tìm hiểu thêm về Solidity trong bài Smart Contract là gì?.
6. Calldata và ABI Encoding
ABI (Application Binary Interface) là chuẩn mã hóa dữ liệu để tương tác với hợp đồng thông minh Ethereum. Calldata được mã hóa theo chuẩn ABI, cho phép hợp đồng giải mã và hiểu các tham số được truyền vào.

Function Selector
4 byte đầu tiên của calldata là function selector – hash Keccak-256 của chữ ký hàm, lấy 4 byte đầu tiên. Selector cho phép hợp đồng xác định hàm nào cần thực thi.
Mã hóa tham số
Các tham số được mã hóa thành các khối 32 byte. Đối với kiểu dữ liệu động (như string, bytes, array), ABI sử dụng offset và length để mã hóa.
Ví dụ: Hàm transfer(address,uint256) với:
-
to=0x742d35Cc6634C0532925a3b844Bc454e4438f44e -
amount=100000000000000000000
Calldata:
0xa9059cbb 000000000000000000000000742d35Cc6634C0532925a3b844Bc454e4438f44e 0000000000000000000000000000000000000000000000000000000000000064
EIP-7706: Tách biệt phí calldata
Vào tháng 5 năm 2024, EIP-7706 được đề xuất nhằm tách biệt thị trường phí cho calldata khỏi execution gas và blob gas. Đề xuất này giới thiệu một loại giao dịch mới với max_basefee và priority_fee riêng cho calldata, giúp kiểm soát tốt hơn chi phí calldata trong các block.
7. Calldata và Layer-2 Rollup
Một trong những ứng dụng quan trọng nhất của calldata là trong các Rollup Layer-2 như Arbitrum, Optimism, và Base. Các Rollup này xử lý giao dịch off-chain nhưng đăng dữ liệu giao dịch lên Ethereum Layer-1 dưới dạng calldata để đảm bảo tính khả dụng dữ liệu.

Tại sao Rollup sử dụng calldata?
Rollup cần đăng dữ liệu giao dịch lên Layer-1 để:
-
Đảm bảo tính khả dụng dữ liệu: Bất kỳ ai cũng có thể tải dữ liệu và xác minh trạng thái của Rollup.
-
Kế thừa bảo mật: Dữ liệu trên Layer-1 được bảo vệ bởi cơ chế đồng thuận của Ethereum.
-
Giảm chi phí: Calldata rẻ hơn storage, giúp giảm phí giao dịch cho người dùng.
Ví dụ: Một Rollup có thể gộp hàng nghìn giao dịch thành một batch duy nhất và đăng batch đó lên Ethereum dưới dạng calldata. Chi phí calldata được chia đều cho tất cả người dùng trong batch, giúp phí giao dịch cá nhân giảm xuống chỉ còn vài cent.
Hạn chế của calldata cho Rollup
Mặc dù calldata rẻ hơn storage, nó vẫn tốn kém so với nhu cầu của Rollup. Calldata được lưu trữ vĩnh viễn trên blockchain, trong khi Rollup chỉ cần dữ liệu trong một khoảng thời gian ngắn để xác minh. Điều này dẫn đến lãng phí không gian lưu trữ và chi phí cao hơn cần thiết.
EIP-4844: Blob thay thế calldata
Proto-Danksharding (EIP-4844) ra đời để giải quyết vấn đề này. Thay vì đăng dữ liệu dưới dạng calldata, Rollup có thể sử dụng blob – một loại dữ liệu tạm thời được xóa sau khoảng 18 ngày. Blob có chi phí thấp hơn calldata và tách biệt khỏi không gian khối thông thường.
Tác động: Sau khi EIP-4844 được kích hoạt vào tháng 3 năm 2024, phí giao dịch trên các Rollup đã giảm hơn 90%. Một số Rollup đã chuyển hoàn toàn từ calldata sang blob để tiết kiệm chi phí.
Bạn có thể tìm hiểu thêm về EIP-4844 trong bài Proto-Danksharding (EIP-4844) là gì?.
8. Ưu điểm và nhược điểm của Calldata
Ưu điểm
-
Chi phí thấp: Calldata rẻ hơn storage rất nhiều, giúp tiết kiệm gas.
-
Lưu trữ vĩnh viễn: Dữ liệu calldata được lưu trên blockchain mãi mãi.
-
Không thể sửa đổi: Đảm bảo tính toàn vẹn của dữ liệu đầu vào.
-
Hỗ trợ ABI chuẩn: Dễ dàng tương tác với hợp đồng thông minh.
-
Nền tảng cho Layer-2: Calldata là cơ chế chính để Rollup đăng dữ liệu lên Layer-1.
Nhược điểm
-
Không thể sửa đổi: Hợp đồng không thể thay đổi calldata, đôi khi gây bất tiện.
-
Chi phí cao hơn memory: Mặc dù rẻ hơn storage, calldata vẫn đắt hơn memory.
-
Giới hạn kích thước block: Calldata chiếm không gian block, có thể gây tắc nghẽn.
-
Lưu trữ vĩnh viễn lãng phí: Đối với Rollup, việc lưu trữ calldata vĩnh viễn là không cần thiết.
-
Phụ thuộc vào ABI: Calldata phải được mã hóa đúng chuẩn ABI, nếu không sẽ thất bại.
9. Câu hỏi thường gặp về Calldata
Calldata có phải là memory không?
Không. Calldata và memory là hai vùng dữ liệu khác nhau. Calldata chỉ đọc và chứa tham số của hàm external, trong khi memory có thể sửa đổi và được sử dụng cho dữ liệu tạm thời trong quá trình thực thi. Calldata rẻ hơn memory nhưng không linh hoạt bằng.
Calldata có bị xóa không?
Không. Calldata được lưu trữ vĩnh viễn trên blockchain như một phần của giao dịch. Nó không bao giờ bị xóa. Điều này khác với blob (EIP-4844), vốn bị xóa sau khoảng 18 ngày.
Tại sao calldata rẻ hơn storage?
Calldata rẻ hơn storage vì nó không cần được xác minh bởi tất cả các node trong quá trình thực thi. Calldata chỉ cần được lưu trữ và đọc, trong khi storage cần được cập nhật và duy trì như một phần của trạng thái toàn cục.
Calldata có giới hạn kích thước không?
Calldata không có giới hạn kích thước cứng, nhưng kích thước càng lớn thì phí gas càng cao. Ngoài ra, kích thước block có giới hạn, nên calldata quá lớn có thể khiến giao dịch không được đưa vào block.
Làm thế nào để giảm chi phí calldata?
Bạn có thể giảm chi phí calldata bằng cách:
-
Giảm kích thước calldata: Sử dụng ít tham số hơn hoặc mã hóa dữ liệu hiệu quả hơn.
-
Sử dụng byte 0: Calldata chứa nhiều byte 0 sẽ rẻ hơn.
-
Sử dụng blob (EIP-4844): Đối với Rollup, blob rẻ hơn calldata.
-
Sử dụng Layer-2: Giao dịch trên Layer-2 có phí calldata thấp hơn nhiều.
Calldata có thể bị tấn công không?
Calldata không thể bị tấn công trực tiếp vì nó là dữ liệu chỉ đọc. Tuy nhiên, nếu calldata được mã hóa sai hoặc chứa dữ liệu độc hại, nó có thể gây ra lỗi trong hợp đồng. Do đó, việc xác thực calldata trong hợp đồng là rất quan trọng.
Calldata có được sử dụng trong zk-Rollup không?
Có. Các zk-Rollup như zkSync và StarkNet cũng sử dụng calldata để đăng dữ liệu lên Layer-1, mặc dù họ cũng đang chuyển sang sử dụng blob sau EIP-4844.
10. Kết luận
Calldata là gì? Đó là vùng dữ liệu chỉ đọc chứa các byte được gửi kèm theo giao dịch Ethereum, bao gồm function selector và các tham số được mã hóa theo chuẩn ABI. Calldata được lưu trữ vĩnh viễn trên blockchain, có chi phí gas thấp hơn storage, và là nền tảng cho các Rollup Layer-2 đăng dữ liệu lên Layer-1.
Mặc dù calldata đóng vai trò quan trọng trong việc giảm chi phí giao dịch, sự ra đời của EIP-4844 (Proto-Danksharding) với blob đã mở ra một kỷ nguyên mới, nơi dữ liệu Rollup có thể được lưu trữ tạm thời với chi phí thấp hơn nhiều. Tuy nhiên, calldata vẫn là một phần không thể thiếu của Ethereum, đặc biệt là cho các giao dịch hợp đồng thông minh thông thường.
Hiểu rõ calldata giúp bạn nắm bắt được cách Ethereum xử lý dữ liệu đầu vào, cách tối ưu hóa chi phí gas, và cách các Layer-2 tương tác với Layer-1. Đây là kiến thức nền tảng cho bất kỳ ai muốn phát triển hoặc sử dụng hợp đồng thông minh trên Ethereum.
Nếu bạn muốn tìm hiểu sâu hơn về các khái niệm liên quan, hãy đọc bài Transaction là gì?, Gas Fee là gì? và Proto-Danksharding (EIP-4844) là gì?.
Nguồn tham khảo:
Ethereum.org – Data Storage Strategies | EIP-4844 Specification









