Skip to content
Available on private testnetTestnet: yesMainnet: Not availableSoftware: solc 0.8.26 --strict-assemblyUpdated

Yul

Compiler solc 0.8.26 --strict-assembly
EVM target --evm-version cancun
ABI None generated — you write the dispatcher and declare the ABI yourself
Status ✅ Tested: compile, deploy, call

Example

The // @abi comments are the convention the Wallet Studio reads to build a call interface for Yul and Huff.

Counter.yul
// Starter counter (Yul, compiled by solc 0.8.26). Unaudited example.
// The ABI is declared here because Yul has none:
// @abi function increment() nonpayable returns ()
// @abi function get() view returns (uint256)
// @abi event Incremented(uint256 value)
object "Counter" {
  code {
    datacopy(0, dataoffset("runtime"), datasize("runtime"))
    return(0, datasize("runtime"))
  }
  object "runtime" {
    code {
      if callvalue() { revert(0, 0) }
      switch shr(224, calldataload(0))
      case 0xd09de08a /* increment() */ {
        let v := add(sload(0), 1)
        sstore(0, v)
        mstore(0, v)
        // keccak256("Incremented(uint256)")
        log1(0, 32, 0x20d8a6f5a693f9d1d627a598e8820f7a55ee74c183aa8f1a30e8d4e8dd9a8d84)
        return(0, 0)
      }
      case 0x6d4ce63c /* get() */ {
        mstore(0, sload(0))
        return(0, 32)
      }
      default { revert(0, 0) }
    }
  }
}

Compile and deploy

solc --strict-assembly --evm-version cancun --optimize --bin Counter.yul \
  | sed -n '/Binary representation:/{n;p;}' > Counter.bin
TX=$(cast send --async --keystore "$KEYSTORE" --password-file "$PASSWORD_FILE" --rpc-url "$RPC" --create "0x$(cat Counter.bin)")
ADDR=$(cast receipt "$TX" contractAddress --rpc-url "$RPC")
cast send "$ADDR" "increment()" --keystore "$KEYSTORE" --password-file "$PASSWORD_FILE" --rpc-url "$RPC"
cast call "$ADDR" "get()(uint256)" --rpc-url "$RPC"

Manual ABI for tools (Counter.abi.json):

[{"type":"function","name":"increment","inputs":[],"outputs":[],"stateMutability":"nonpayable"},
 {"type":"function","name":"get","inputs":[],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
 {"type":"event","name":"Incremented","inputs":[{"name":"value","type":"uint256","indexed":false}],"anonymous":false}]

Measured: 93 runtime bytes, 73,278 deployment gas, 44,248 gas for increment().

Caveats

  • No overflow checks, no ABI decoding, no reentrancy protection unless you write them.
  • Selectors and event topics are hard-coded; a typo silently breaks the interface — test every function.
  • Prefer Yul inside Solidity (assembly { … }) for a few hot paths over whole-contract Yul.

Found a problem? Report a documentation issue · Build testnet-rc1+72057fe3ec