Skip to content

Instantly share code, notes, and snippets.

@hrkrshnn
hrkrshnn / generic.org
Last active April 21, 2024 01:51
Some generic writeup about common gas optimizations, etc.

Upgrade to at least 0.8.4

Using newer compiler versions and the optimizer gives gas optimizations and additional safety checks for free!

The advantages of versions 0.8.* over <0.8.0 are:

  • Safemath by default from 0.8.0 (can be more gas efficient than some library based safemath).
  • Low level inliner from 0.8.2, leads to cheaper runtime gas. Especially relevant when the contract has small functions. For
@hrkrshnn
hrkrshnn / Readme.md
Last active April 4, 2023 08:11
Instructions to see raw SMTLib queries generated by SMTChecker from solc

Compile solc locally after applying the below patch (solc.patch).Build instructions.

./solc example.sol --model-checker-engine bmc
Call to check. Solver state:
(declare-datatypes ((bytes_tuple 0)) (((bytes_tuple (bytes_tuple_accessor_array (Array Int Int)) (bytes_tuple_accessor_length Int)))))
(declare-datatypes ((tx_type 0)) (((tx_type (block.basefee Int) (block.chainid Int) (block.coinbase Int) (block.difficulty Int) (block.gaslimit Int) (block.number Int) (block.timestamp Int) (blockhash (Array Int Int)) (msg.data bytes_tuple) (msg.sender Int) (msg.sig Int) (msg.value Int) (tx.gasprice Int) (tx.origin Int)))))
@hrkrshnn
hrkrshnn / BribeContract.yul
Last active October 10, 2022 14:42
Run by `solc --strict-assembly --optimize --ir-optimized`. Context: https://twitter.com/NoahZinsmeister/status/1499845282598731782 Need to use Yul, since there is no `verbatim` in Solidity's inline assembly.
// UNTESTED!
object "BribeContract" {
code {
let size := datasize("BribeRuntime")
codecopy(0, dataoffset("BribeRuntime"), size)
return(0, size)
}
object "BribeRuntime" {
code {
// Bribe by sending ETH. To try and claim, send a tx without ETH. Assumes that a tx with
"""
An approach for
https://github.com/ethereum/solidity/pull/11493/files#r651807831
"""
# stack is modelled by an array of characters
stackAfter = ['a', 'x', 'b', 'e', 'x', 'b', 'd', 'a', 'z', 'c']
# operation
# (a, b, c, d) -> (x, y, z)
#include <iostream>
#include <vector>
#include <set>
/// `_sigma` denotes a vector of size say `n`.
/// Corresponds to a permutation of {0, 1, 2, ..., n - 1}
/// The value `_sigma[i]` means `i` is mapped to `_sigma[i]`.
///
/// A cycle is a set {a_1, a_2, ..., a_N} such that
/// a_1 -> a_2; a_2 -> a_3, ..., a_{N-1} -> a_N; a_N -> a_1
pragma solidity ^0.8.5;
contract C {
function convert(bytes memory m) external pure returns (bytes4) {
return bytes4(m);
}
}

When you're looping over an array from front to back, does it make sense to cache arr.length in a stack variable, or will it SLOAD/MLOAD that only once if it sees it won't change in the loop body

In the Yul optimizer (for the new code generator), there is an optimization step LoopInvariantCodeMotion designed to detect expressions that remain invariant in the loop and move them outside the loop. Take the following solidity example that finds the sum of a dynamic integer array in storage.

        uint sum = 0;
        for (uint i = 0; i < arr.length; ++i)
        {
            sum += arr[i];
 }
@hrkrshnn
hrkrshnn / changesFunctionSpecializer.diff
Created February 3, 2021 18:48
isoltest --optimize
Staged changes (154)
modified test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_storage.sol
@@ -25,6 +25,6 @@ contract C {
// ----
// f() -> 0x20, 0x8, 0x40, 0x3, 0x9, 0xa, 0xb
// gas ir: 199675
-// gas irOptimized: 194189
+// gas irOptimized: 193702
// gas legacy: 196426
-// gas legacyOptimized: 193470
@hrkrshnn
hrkrshnn / calldata_example.sol
Created September 30, 2021 09:41
An example of using calldata parameter in internal functions.
contract C {
function f(uint[] calldata arr) external returns(uint) {
return sum(arr);
}
function sum(uint[] calldata arr) internal returns(uint _sum) {
for(uint i = 0; i < arr.length; i++) {
_sum += arr[i];
}
}
}