Nhảy đến nội dung chính

Giới thiệu

Khi bạn thực hiện các call đến NEAR blockchain để cập nhật hoặc thay đổi dữ liệu trên đó, những người điều hành cơ sở hạ tầng của blockchain này sẽ phải chịu một số chi phí. Vào cuối ngày, những máy tính ở đâu đó trong network sẽ xử lý yêu cầu của bạn, các validator chạy trên những máy tính này phải trả một chi phí đáng kể để giữ chúng chạy.

Giống như những programmable blockchain khác, NEAR thưởng cho những người này bằng cách tính transaction fees, hay còn gọi là gas fees với những tác động làm thay đổi dữ liệu trên blockchain.

Nếu bạn đã quen thuộc với các nhà cung cấp web2 cloud service (Amazon Web Services, Google Cloud, v. v.), thì có sự khác biệt lớn với các blockchain là những user bị tính phí ngay lập tức khi họ thực hiện call một ứng dụng, thay vì các developer phải trả tất cả các chi phí sử dụng đó. Điều này sẽ tạo ra các tiềm năng mới, chẳng hạn như những ứng dụng sẽ tránh được việc bị dừng sau một thời gian dài hoạt động do developer/company hết tiền. Tuy nhiên, nó cũng đi kèm với hạn chế về việc sử dụng tăng đột biến. Để giải quyết vấn đề này, NEAR cho phép các developer có thể trang trải phí gas cho các user, việc này sẽ mang lại trải nghiệm tốt hơn cho những người dùng đến từ web2.

Khi nghĩ về gas, hãy ghi nhớ hai khái niệm sau:

  • Gas units: trong nội bộ, transaction fees không được tính trực tiếp vào NEAR tokens, mà sẽ được tính qua giai đoạn giữa "gas units". Lợi ích của gas units là chúng có tính xác định - cùng một giao dịch sẽ luôn có cùng chi phí gas units.
  • Gas price: được tính bằng cách nhân số lượng gas units với một gas price, để xác định chi phí mà người dùng cần thanh toán. Giá này sẽ được tự động tính lại cho mỗi block dựa trên nhu cầu của network (nếu block trước đó nhiều hơn một nữa thì giá sẽ tăng, nếu không giá sẽ giảm, và giá sẽ không thay đổi quá 1% với mỗi block). Giá thấp nhất là do network quy định, hiện tại là 100 triệu yoctoNEAR.

Lưu ý là gas price có thể khác nhau giữa mainnet & testnet của NEAR. Kiểm tra gas price trước khi xem những con số dưới đây.

Suy nghĩ một chút về khái niệm gas

NEAR có block time nhiều hơn hoặc ít hơn một giây, được thực hiện bằng giới hạn lượng gas trên mỗi block. Bạn có thể truy vấn lượng gas giới hạn này bằng cách sử dụng protocol_config RPC endpoint, và tìm max_gas_burnt bên dưới limit_config. Giá trị gas unit đã được tính toán cẩn thận để đưa ra những con số dưới đây:

  • 10¹² gas unit, hoặc 1 TGas (TeraGas)...
  • 1 millisecond của "compute" time
  • ... mức tối thiểu của gas price là 100 triệu yoctoNEAR, tương đương với khoản phí 0.1 milliNEAR

Giá trị 1ms là một số gần đúng nhưng khá có ích, và nó là mục tiêu hiện tại của việc thiết lập gas unit trong NEAR. Gas units không chỉ gói gọn compute/CPU time mà còn bandwidth/network, time và cả storage/IO time. Thông qua một governance mechanism, các tham số của hệ thống có thể được tinh chỉnh, hay cập nhật được tỷ lệ quy đổi giữa TGas và milliseconds trong tương lai, nhưng hiện tại tỷ lệ ở trên vẫn đang là một giá trị phù hợp để bắt đầu suy nghĩ về gas unit là gì và chúng đến từ đâu.

Chi phí cho các thao tác thường gặp

Để cho bạn cái nhìn đầu tiên về chi phí sử dụng trên NEAR, bảng dưới đây sẽ liệt kê những thao tác thường gặp, cùng với mức TGas cần thiết là bao nhiêu, chi phí thực hiện là bao nhiêu milliNEAR, với gas price thấp nhất là 100 triệu yN.

OperationTGasfee (mN)fee (Ⓝ)
Create Account0.420.0424.2⨉10⁻⁵
Send Funds0.450.0454.5⨉10⁻⁵
Stake0.500.0505.0⨉10⁻⁵
Add Full Access Key0.420.0424.2⨉10⁻⁵
Delete Key0.410.0414.1⨉10⁻⁵
Đào sâu hơn

Những con số này đến từ đâu?

NEAR đã configured với chi phí cơ bản. Ví dụ:

create_account_cost: {
send_sir: 99607375000,
send_not_sir: 99607375000,
execution: 99607375000
}

Từ "sir" là viết tắt của "sender is receiver". Tất cả giá trị đều giống hệt nhau, nhưng chúng có thể thay đổi trong tương lai.

Khi bạn gửi yêu cầu tạo một tài khoản mới, NEAR ngay lập tức khấu trừ số tiền send thích hợp từ tài khoản của bạn. Sau đó, nó tạo một receipt, một cơ chế lưu giữ sổ sách nội bộ để tạo điều kiện thuận lợi cho asynchronous, sharded design của NEAR (nếu bạn đã biết Ethereum, hãy quên những gì bạn đã biết về Ethereum's receipt, chúng hoàn toàn khác nhau). Việc tạo một receipt có các chi phí liên quan:

action_receipt_creation_config: {
send_sir: 108059500000,
send_not_sir: 108059500000,
execution: 108059500000
}

Bạn có thể truy vấn giá trị này bằng cách sử dụng protocol_config RPC endpoint và tìm kiếm action_receipt_creation_config.

Số tiền send thích hợp để tạo receipt này cũng được khấu trừ ngay lập tức vào tài khoản của bạn.

Hành động "create account" sẽ không được hoàn tất cho tới khi block tiếp theo được tạo ra. Tại thời điểm này, số tiền execution cho mỗi hành động sẽ được trừ vào tài khoản của bạn (một điều cần lưu ý: vì gas price được tính toán lại trên mỗi block, cho nên chi phí của block tiếp theo sẽ là: gas unit trên block tiếp theo nhân với gas price ở block đó, nó có thể chênh lệch tới 1% với gas price ở block hiện tại). Cộng tất cả lại để tính tổng transaction fee:

(create_account_cost.send_sir  + action_receipt_creation_config.send_sir ) * gas_price_at_block_1 +
(create_account_cost.execution + action_receipt_creation_config.execution) * gas_price_at_block_2

Chi phí của những thao tác phức tạp

Những con số chúng ta vừa đề cập ở trên sẽ cho bạn cảm giác giao dịch trên NEAR rất rẻ! Nhưng bạn sẽ không hình dung được về việc sẽ tốn bao nhiêu chi phí để sử dụng một ứng dụng phức tạp hơn, hoặc xa hơn là vận hành một doanh nghiệp dựa trên NEAR. Chúng ta hãy nói về việc tính toán một số phí gas phức tạp hơn như: deploying contract và function call.

Deploying Contract

Về cơ bản, chi phí deploying contract sẽ bao gồm hai phần khác nhau. Đơn giản, đó là:

deploy_contract_cost: 184765750000,
deploy_contract_cost_per_byte: 6812999,

Một lần nữa, những giá trị này có thể truy vấn bằng cách sử dụng protocol_config RPC endpoint.

Đầu tiên là chi phí cơ bản, nó không phụ thuộc vào kích thước của contract. Hãy nhớ rằng mỗi chi phí cần phải nhân đôi, cho cả hai việc sendexecute, và cũng sẽ áp dụng send & execute cho receipt (chi phí chính xác xem ở trên), các gas unit đi kèm:

2 * 184765750000 +
2 * contract_size_in_bytes * 6812999 +
2 * 108059500000

(Chia kết quả cho 10¹² để đổi ra TGas!)

Lưu ý rằng điều này bao gồm chi phí tải lên và ghi các byte vào bộ nhớ, nhưng không bao gồm chi phí lưu giữ các byte này trong bộ nhớ. Chi phí lưu trữ dài hạn được tính thông qua storage staking, chi phí có thể thu hồi theo mỗi byte cũng sẽ được khấu trừ vào tài khoản của bạn trong quá trình deploy contract.

Với AssemplyScript contract trong ví dụ về Fungible Token thì biên dịch chỉ hơn 16kb (Rust contract thì lớn hơn, nhưng điều này sẽ được tối ưu hóa). Sử dụng cách tính ở trên, chúng ta thấy rằng cần 0.81 TGas (và do đó 0.081mN gas price tối thiểu) cho transaction fee để deploy contract, trong khi 1.5N sẽ bị khóa để storage staking.

Function call

Với bản chất mục đích chung của NEAR, các function call dành được phần thắng cho các tính toán gas phức tạp nhất. Một function call nhất định sẽ sử dụng một lượng CPU, network và IO rất khó để dự đoán. Số lượng của mỗi loại thậm chí có thể thay đổi dựa trên lượng dữ liệu đã được lưu trữ trong contract!

Với mức độ phức tạp này, sẽ không có nhiều lợi ích khi xem qua một ví dụ, liệt kê (hãy nhìn ext_costs bên dưới wasm_config bằng cách sử dụng protocol_config RPC endpoint) các phép tính gas (bạn có thể tự nghiên cứu điều này nếu bạn muốn). Thay vào đó, hãy tiếp cận từ hai góc độ khác nhau: so sánh ballpark comparison với Ethereum và nhận các ước tính chính xác với các bài automated test.

Ballpark Comparison với Ethereum

Giống như NEAR, Ethereum sử dụng các gas unit để mô hình hóa độ phức tính toán của một hoạt động. Nhưng khác ở chỗ, thay vì sử dụng gas price có thể dự đoán được, Ethereum sử dụng một marketplace động, dựa trên việc đấu giá. Điều này làm cho việc so sánh với gas price của Ethereum và NEAR hơi phức tạp, nhưng chúng ta sẽ cố gắng hết sức.

Etherscan cung cấp biểu đồ lịch sử gas price của Ethereum. Các mức giá này được tính bằng "Gwei" hoặc Gigawei, trong đó wei là số lượng ETH nhỏ nhất có thể, giá trị của nó là 10⁻¹⁸ ETH. Từ tháng 11/2017 đến tháng 07/2020, trung bình gas price là 21Gwei. Hãy gọi đây là chi phí "average" gas price. Vào tháng 07/2020, chi phí average gas price đã tăng lên 57Gwei. Lấy con số này làm "high" gas fee của Ethereum.

Bằng cách nhân gas unit của Ethereum với gas price để tính được chi phí được tính bằng milliETH (mE), giống như cách chúng ta đã chuyển đổi TGas thành milliNEAR với NEAR. Hãy xem một số hành động phổ biến, và so sánh gas units của Ethereum với NEAR, cũng như các giá trị "average" & "high" mà chúng ta đã đề cập ở trên.

OperationETH gas unitsavg mEhigh mENEAR TGasmN
Transfer native token (ETH or NEAR)21k0.4411.1970.450.045
Deploy & initialize a fungible token contract1.1M23.363.190.9 (plus 1.5Ⓝ in storage staking)
Transfer a fungible token~45k0.9452.565141.4
Setting an escrow for a fungible token44k0.9262.5180.8
Checking a balance for a fungible token00000
Những function call yêu cầu khởi động một VM và tải tất cả các byte mà Wasm đã biên dịch vào bộ nhớ, do đó chi phí tăng lên so với các thao tác cơ bản, có thể xem thêm về chủ đề [tối ưu hóa chi phí cho function call](https://github.com/near/nearcore/issues/3094).

Trong các hoạt động, nếu nhìn qua chúng ta chỉ thấy NEAR được cải thiện khoảng 10 lần so với Ethereum, nhưng thêm một điều cần lưu ý là tổng nguồn cung của NEAR là hơn 1 tỷ, trong khi đó tổng cung của Ethereum là hơn 100 triệu. Vì vậy, tương ứng với tổng nguồn cung, gas fee của NEAR cũng thấp hơn khoảng 10 lần so với Ethereum. Ngoài ra, nếu giá NEAR tăng lên một cách đáng kể, thì phí gas tối thiểu do NEAR network đặt ra có thể được hạ xuống.

Bạn có thể mong đợi network luôn ở mức gas price tối thiểu, tìm hiểu thêm ở Economics whitepaper.

Ước tính độ chính xác với Automated Test

Chúng tôi sẽ sớm có phần nói về cách ước tính chi phí gas chuyên sâu; theo dõi issue này để cập nhật thông tin. Thay vì chờ đến lúc đó, bạn có thể xem ví dụ làm thế nào thực hiện simulation testing, một cách hiệu quả để kiểm tra các contract của bạn cũng hiểu rõ hơn các khía cạnh mà nó thực hiện.

Nếu bạn đang sử dụng AssemblyScript SDK của NEAR, bạn có thể dùng 2 method, context.prepaidGas and context.usedGas. Chúng có thể được sử dụng mà có hoặc không có các bài test để báo cáo cho virtual machine biết về phí gas được đính kèm và mức tiêu thụ của nó tại thời điểm contract của bạn đang được thực thi:

/**
* Lấy tổng số lượng gas unit đính kèm với call.
*/
get prepaidGas(): u64 {
return env.prepaid_gas();
}

/**
* Lấy số gas unit đã đốt trong quá trình thực hiện contract và
* đính kèm vào promises (không được vượt quá prepaid gas).
*/
get usedGas(): u64 {
return env.used_gas();
}

Làm thế nào để mua gas?

You don't directly buy gas; you attach tokens to transactions.

Calls to NEAR to read data are always free. But when you make a call to add or update data, you have to do so from an account that has some amount of NEAR tokens available in its balance, and these tokens will be attached to pay the gas fee.

If you're coming from Ethereum, you may be used to the idea of paying a higher gas price to get your transaction processed faster. In NEAR, gas costs are deterministic, and you can't pay extra.

For basic operations like "transfer funds," you can't specify an amount to attach. The gas needed is easy to calculate ahead of time, so it's automatically attached for you. (Check it: near-cli has a send command, which accepts no gas parameter; near-api-js has a sendTokens function which accepts no gas argument.) As shown in the tables above, these operations are cheap, so you probably won't even notice the slight reduction in your account's balance.

Function calls are more complex and you can attach an explicit amount of gas to these transactions, up to a maximum value of 3⨉10¹⁴ gas units. This maximum value of prepaid gas is subject to change but you can query this value by using the protocol_config RPC endpoint and search for max_total_prepaid_gas.

You can also override the default value of attached gas. Here is an example using near-cli:

near call myContract.testnet myFunction "{ \"arg1\": \"val1\" }" --gas=300000000000000

And in near-api-js, you can also specify an explicit amount of gas units to attach when calling a change method; see example here.

The telltale error that calls for this solution looks like this:

Error:
Transaction A9BzFKmgNNUmEx9Ue9ARC2rbWeiMnq6LpcXh53xPhSN6 failed.
Exceeded the prepaid gas
How many tokens will these units cost?

Note that you are greenlighting a maximum number of gas units, not a number of NEAR tokens or yoctoNEAR.

These units will be multiplied by the gas price at the block in which they're processed. If the function call makes cross-contract calls, then separate parts of the function will be processed in different blocks, and could use different gas prices. At a minimum, the function will take two blocks to complete, as explained in the blue box above.

Assuming the system rests at minimum gas price of 100 million yoctoNEAR during the total operation, a maximum attached gas of 3⨉10¹⁴ would seem to allow a maximum expenditure of 3⨉10²² yN. However, there's also a pessimistic multiplier of about 6.4 to prevent shard congestion.

Multiplying all three of these numbers, we find that maximum attached gas units allow about 0.2Ⓝ to be spent on the operation if gas prices stay at their minimum. If gas prices are above the minimum, this charge could be higher.

What if the gas price is at the minimum during the starting block, but the operation takes several blocks to complete, and subsequent blocks have higher gas prices? Could the charge be more than ~0.2Ⓝ? No. The pessimistic multiplier accounts for this possibility.

Attach extra gas; get refunded!

How can you know the exact right amount to attach when you call a function? You can't!

Gas units are based on computational complexity for a given operation, which can be affected by a smart contract's state. This is hard to predict ahead of time. And gas price is adjusted each block based on how busy the network was during the previous block, which is also hard to predict ahead of time.

But good news!

  • Gas doesn't cost much on NEAR
  • If you attach more gas than needed, you'll get refunded

This is also true for basic operations. In the previous section we mentioned that these are automatically calculated and attached. In fact, given that the gas price could be adjusted slightly while these operations are being applied (see blue box above), a slight amount extra is attached, and any beyond what's necessary gets refunded.

What about Prepaid Gas?

The NEAR Team understands that developers want to provide their users with the best possible onboarding experience. To realize this vision, developers can design their applications in a way that first-time users can draw funds for purchasing gas directly from an account maintained by the developer. Once onboarded, users can then transition to paying for their own platform use.

In this sense, prepaid gas can be realized using a funded account and related contract(s) for onboarding new users.

So how can a developer pay the gas fee for their users on NEAR?

  • A user can use the funds directly from the developer's account suitable only for the gas fees on this dApp. Then the developer has to distinguish users based on the signers' keys instead of the account names.

  • Using function calls, you can allow a new user without an account to use your dApp and your contract on-chain. The back-end creates a new access key for the user on the contract's account and points it towards the contract itself. Now the user can immediately use the web app without going through any wallet.

NEAR Protocol does not provide any limiting feature on the usage of developer funds. Developers can set allowances on access keys that correspond to specific users -- one FunctionCall access key per new user with a specific allowance.

What's the price of gas right now?

You can directly query the NEAR platform for the price of gas on a specific block using the RPC method gas_price. This price may change depending on network load. The price is denominated in yoctoNEAR (10^-24 NEAR)

  1. Take any recent block hash from the blockchain using NEAR Explorer

    At time of writing, SqNPYxdgspCT3dXK93uVvYZh18yPmekirUaXpoXshHv was the latest block hash

  2. Issue an RPC request for the price of gas on this block using the method gas_price documented here

    http post https://rpc.testnet.near.org jsonrpc=2.0 method=gas_price params:='["SqNPYxdgspCT3dXK93uVvYZh18yPmekirUaXpoXshHv"]' id=dontcare
  3. Observe the results

    {
    "id": "dontcare",
    "jsonrpc": "2.0",
    "result": {
    "gas_price": "5000"
    }
    }

The price of 1 unit of gas at this block was 5000 yoctoNEAR (10^-24 NEAR).

Some closing thoughts from the whitepaper

Fundamentally, the NEAR platform is a marketplace between willing participants. On the supply side, operators of the validator nodes and other fundamental infrastructure need to be incentivized to provide these services which make up the “community cloud.” On the demand side, the developers and end-users of the platform who are paying for its use need to be able to do so in a way which is simple, clear and consistent so it helps them.

A blockchain-based cloud provides several specific resources to the applications which run atop it:

  • Compute (CPU): This is the actual computer processing (and immediately available RAM) which run the code in a contract.
  • Bandwidth ("Network"): This is the network traffic between participants and users, including messages which submit transactions and those which propagate blocks.
  • Storage: Permanent data storage on the chain, typically expressed as a function of both storage space and time.

Existing blockchains like Ethereum account for all of these in a single up front transaction fee which represents a separate accounting for each of them but ultimately charges developers or users for them only once in a single fee. This is a high volatility fee commonly denominated in “gas”.

Developers prefer predictable pricing so they can budget and provide prices for their end users. The pricing for the above-mentioned resources on NEAR is an amount which is slowly adjusted based on system usage (and subject to the smoothing effect of resharding for extreme usage) rather than being fully auction-based. This means that a developer can more predictably know that the cost of running transactions or maintaining their storage.

To dig deeper into how and why gas works the way it does on NEAR, check out the Economics section of the main whitepaper and the Transaction and Storage Fees section of the economics whitepaper.

Got a question?

Ask it on StackOverflow!