Architecture
Gas

Gas

Gas is a way to measure computational expense of a smart contract execution, including CPU time and storage cost. Its unit is 1, i.e. you can think of it as countable points. Gas consumption is deterministic, so executing the same thing costs the same amount of gas across all hardware and operating systems.

CosmWasm gas vs. Cosmos SDK gas

CosmWasm charges gas for Wasm operations, calls to host functions and calls to the Cosmos SDK. CosmWasm gas is different from Cosmos SDK gas as the numbers here are much larger. Since we charge gas for arbitrary user defined operations, we need to charge each Wasm operation individually and cannot group larger tasks together. As a result, the gas values become much larger than in Cosmos SDK even for very fast executions. There is a multiplier (opens in a new tab) to translate between CosmWasm gas and Cosmos SDK. It was measured and set to 100 a while ago and can be adjusted when necessary.

CosmWasm gas pricing

For CosmWasm gas, the target gas consumption is 1 Teragas (10^12 gas) per second. This idea is inspired by NEAR (opens in a new tab) and we encourage you to read their excellent docs on that topic.

In order to meet this target, we execute Argon2 in a test contract (#1120 (opens in a new tab)). This is a CPU and memory intense job that does not call out into the host. At a constant gas cost per operation of 1 (pre CosmWasm 1.0), this consumed 96837752 gas and took 15ms on our CI system. The ideal cost per operation for this system is 10^12 / (96837752 / (15 / 1000)): 154. This is rounded to 150 for simplicity.

CosmWasm 2.1 update: All gas values were re-evaluated and adjusted to meet the 1 Teragas/second target mentioned above. A rerun of the Argon2 test contract consumed 5270718300 gas with the previous cost of 150, so the operation count was 5270718300 / 150 = 35138122. This took 6ms on our benchmark server, so the new cost per operation is 10^12 / (35138122 / (6 / 1000)): 171. This is rounded to 170 for simplicity.

Benchmarking system:

  • CPU: Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz (4 cores, 8 threads)
  • RAM: 32GB DDR4 2133 MHz

Each machine is different, we know that. But the above target helps us in multiple ways:

  1. Develop an intuition what it means to burn X gas or how much gas can be used if a block should be executable in e.g. 1 second
  2. Have a target for adjustments, e.g. when the Wasm runtime becomes faster or slower
  3. Allow pricing of calls that are not executed in Wasm, such as crypto APIs
  4. Find significant over or underpricing

Gas overflow potential

CosmWasm gas aims for 1 Teragas/second, i.e. the uint64 range exceeds after 18 million seconds (5000 hours)1. Assuming a max supported block execution time of 30 seconds, the gas price has to be over-priced by a factor of 614891 (614891 Teragas/second) in order to exceed the uint64 range2. Since serious over or underpricing is considered a bug, using uint64 for gas measurements is considered safe.

Cosmos SDK gas uses values that are smaller by a factor of 150, so those don't overflow as well. Since no Cosmos SDK gas values are processed inside of this repository, this is not our main concern. However, it's good to know that we can safely pass them in uint64 fields, as long as the full range is supported. This is the case for the C API as well as JSON numbers (opens in a new tab) as long as both sides support integers in their JSON implementation. Go and Rust do that while many other implementations don't support integers, and convert them to IEEE-754 doubles, which has a safe integer range up to about 53 bit (e.g. JavaScript and jq).

1 (2^64-1) / 10^12

2 ((2^64-1)/30) / 10^12

CosmWasm 1.x -> 2.0 changes

In all versions before 2.0, the gas values were bigger by a factor of 1000. There is no need to have them this big and in order to reduce the risk of overflow, the gas values were lowered in #1599 (opens in a new tab). Here is a breakdown of what this change entails:

CosmWasm 1.xCosmWasm 2.x
Cost target1 Teragas/millisecond1 Teragas/second
Exceeds uint64 range after5 hours5124 hours (213 days)
Cost per Wasm op150_000150
Multiplier140_000_000140_000