본문으로 건너뛰기

Gas Cost Comparison: Stylus Rust vs Solidity

Aug 22, 2024
Yoonsoo Jang
Software Engineer, DSRV

Introduction

When developing smart contracts, gas costs are a critical consideration. This article compares the gas costs of smart contracts written in Solidity and Stylus to determine which is more efficient.
You can download the sample code from the GitHub repository.

Overview

  • Solidity: The most widely used programming language for writing smart contracts on the Ethereum blockchain.
  • Stylus: Stylus allows you to write smart contracts in languages that compile to WASM, like Rust and C++, offering high efficiency, lower gas fees, and interoperability with Solidity on the Arbitrum network.

Testing with Computationally Intensive Functions

One common example of high computational cost in smart contracts is cryptographic operations. For this comparison, we used the keccak256 hashing function, which is known for its significant computation requirements.
This test was conducted on the Arbitrum Sepolia testnet. ( RPC: https://sepolia-rollup.arbitrum.io/rpc Chain ID: 421614 )

Solidity Smart Contract

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

contract HashStorage {
bytes32 public storedHash;

function storeHash(string memory _input) public {
storedHash = keccak256(abi.encodePacked(_input));
}

}

Stylus Rust

#![cfg_attr(not(feature = "export-abi"), no_main)]
extern crate alloc;

use stylus_sdk::{crypto::keccak, prelude::*, storage::StorageFixedBytes};

#[global_allocator]
static ALLOC: mini_alloc::MiniAlloc = mini_alloc::MiniAlloc::INIT;

sol_storage! {
#[entrypoint]
pub struct HashStorage {
StorageFixedBytes<32> h;
}
}

#[external]
impl HashStorage {
pub fn store_hash(&mut self, input: String) {
let hash = keccak(input.as_bytes());
self.h.set(hash.into());
}

pub fn get_hash(&self) -> String {
let h = self.h.get();
hex::encode(h)
}
}

 You can build and deploy Stylus-Rust using Remix IDE with the CODE BY WELLDONE STUDIO plugin,
and it also supports method calls.
Please refer to this document for instructions on how to use it.

remix-arbitrum-deploy remix-arbitrum-method-call

Gas Consumption Results

2024-09-05 Test Result
Stylus contracts showed an average gas cost that was -49.50% lower compared to Solidity contracts.
Solidity Contract
Stylus Contract

NoSolidityStylus
1423,734205,441
2403,834204,047
3403,834205,441
4396,946204,047
5405,556201,956
6403,834204,744
7403,834205,441
8402,112205,441
9403,834205,441
10403,834204,047
Avg405,135204,605 ( -49.50 % )

2024-08-22 Test Result
Unexpectedly, Stylus contracts showed an average gas cost that was +25.26% higher compared to Solidity contracts.
Solidity Contract
Stylus Contract

NoSolidityStylus
145,01837,111
227,91837,111
327,91837,111
427,91837,111
527,91837,111
627,91837,111
727,91837,111
827,91837,111
927,91837,111
1027,91837,111
Avg29,62837,111 ( +25.26% )

But the next day, I tested it again and found that the gas costs between the two were similar, or there were cases where Stylus had lower gas costs. Therefore, it was difficult to draw a clear conclusion.

2nd Test - Performing 1,000 keccak256 hash operations in a single call.

Assuming that the true potential of Stylus is revealed when the computational intensity reaches a certain level, I modified the code to perform keccak256 1,000 times and then tested it as follows.

Solidity Smart Contract

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

contract HashStorage1000 {
bytes32 public storedHash;

function storeHash(string memory _input) public {
bytes32 hash = keccak256(abi.encodePacked(_input));

for (uint i = 0; i < 999; i++) {
hash = keccak256(abi.encodePacked(hash));
}

storedHash = hash;
}
}

Stylus Rust

#![cfg_attr(not(feature = "export-abi"), no_main)]
extern crate alloc;

use stylus_sdk::{crypto::keccak, prelude::*, storage::StorageFixedBytes};

#[global_allocator]
static ALLOC: mini_alloc::MiniAlloc = mini_alloc::MiniAlloc::INIT;

sol_storage! {
#[entrypoint]
pub struct HashStorage1000 {
StorageFixedBytes<32> h;
}
}

#[external]
impl HashStorage1000 {
pub fn store_hash(&mut self, input: String) {
let mut hash = keccak(input.as_bytes());

for _ in 1..1000 {
hash = keccak(&hash);
}

self.h.set(hash.into());
}

pub fn get_hash(&self) -> String {
let h = self.h.get();
hex::encode(h)
}
}

Gas Consumption Results

2024-09-05 Test Result That's impressive! The gas costs of Stylus have been reduced by -9.53% compared to Solidity.
Solidity Contract
Stylus Contract

NoSolidityStylus
1786,394675,577
2764,802695,535
3763,110695,535
4764,802695,535
5763,110695,535
6764,802695,535
7764,802695,535
8764,802695,535
9764,802695,535
10764,802695,535
Avg766,623693,539 ( -9.53% )

2024-08-22 Test Result
That's impressive! The gas costs of Stylus have been reduced by -86.3% compared to Solidity.
Solidity Contract
Stylus Contract

NoSolidityStylus
1412,55753,311
2396,54054,397
3396,52654,403
4396,55454,385
5396,53054,381
6396,53154,379
7396,55154,402
8396,56954,440
9396,60854,450
10396,59854,458
Avg398,15654,301 ( -86.4% )

3rd Test - Local Test Node

2024-08-22 Test Result
This test was conducted in a local node using Nitro Testnode. This was done to test in a more controlled environment and minimize the impact of external factors, which we might have encountered during testing on Arbitrum Sepolia. The test results showed that the gas savings rate was 86.6%, which was nearly identical to the results from the local test node.

NoSolidityStylus
1412,55753,343
2395,45753,343
3395,45753,343
4395,45753,343
5395,45753,343
6395,45753,343
7395,45753,343
8395,45753,343
9395,45753,343
10395,45753,343
Avg397,16753,343 ( -86.6% )

Conclusion

The results of these tests clearly demonstrate the significant efficiency gains that can be achieved by using Stylus for smart contract development, particularly in computationally intensive scenarios. While initial tests showed that Stylus contracts might incur higher gas costs for a single keccak operation, the true potential of Stylus becomes evident when dealing with more intensive computations, such as executing multiple keccak operations. In this test, the fact that gas costs were reduced by up to 86.6% compared to Solidity highlights Stylus's ability to effectively optimize performance and resource utilization. This makes Stylus an attractive option for developers looking to build high-performance, cost-effective smart contracts on the Arbitrum network. As Stylus continues to evolve, it will likely become a key tool in the blockchain developer's toolkit, offering both flexibility and efficiency in contract development.

Reference

https://github.com/LimeChain/stylus-benchmark
https://github.com/OffchainLabs/stylus-hello-world
https://github.com/OffchainLabs/nitro-testnode