argotorg / argotorg/solidity

Warning 2394 is emitted for inline assembly tstore but not for high-level transient state variable writes

Open
#16,691 0 comments 0 reactions 1 assignee Claimed by @nikola-matic View on GitHub
bug :bug:
Dominant language
C++
Stars
25.7k
Forks
6.2k
Avg merge
2d 19h
Merged PRs (30d)
29

Description

## Description

The transient storage composability warning (`Warning 2394`) is emitted for inline assembly `tstore(...)`, but not for high-level transient state-variable writes, even though both forms compile to the same `TSTORE` opcode and carry the same composability risk.

Expected behavior: using a high-level transient state variable write such as `counter = v;` should emit the same transient storage composability warning as `assembly { tstore(...) }`, or the warning policy should otherwise be applied consistently to all source-level uses that write transient storage.

Actual behavior: only the inline assembly form warns. The high-level `transient` state-variable assignment compiles silently.

This creates an auditor/user blind spot: contracts using high-level transient storage may miss the warning that transient storage is cleared only at the end of the transaction, not at the end of each call frame, and therefore can break composability if not cleared appropriately.

## Environment

- Compiler version: `0.8.35-develop.2026.5.5+commit.47b9dedd.Linux.g++`
- Compilation pipeline (legacy, IR, EOF): IR / via-IR code generation for high-level transient variables; inline assembly warning observed through normal Solidity compilation
- Target EVM version (as per compiler settings): Cancun or later
- Framework/IDE (e.g. Foundry, Hardhat, Remix): solc command line
- EVM execution environment / backend / blockchain client: N/A
- Operating system: `Linux ubuntu-jammy`

## Steps to Reproduce

Compile the following minimal contract with a Cancun-or-later EVM target:

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.35;

contract C {
uint256 transient counter;

function setHighLevel(uint256 v) external {
counter = v; // No Warning 2394
}

function setAssembly(uint256 v) external {
assembly {
tstore(0, v) // Emits Warning 2394
}
}
}
```

Example command:

```bash
./build/solc/solc --evm-version cancun C.sol
```

Observed result: the compiler emits the transient storage composability warning only for the inline assembly `tstore`:

```text
Warning 2394: Transient storage as defined by EIP-1153 can break the composability of smart contracts: Since transient storage is cleared only at the end of the transaction and not at the end of the outermost call frame to the contract within a transaction, your contract may unintentionally misbehave when invoked multiple times in a complex transaction. To avoid this, be sure to clear all transient storage at the end of any call to your contract. The use of transient storage for reentrancy guards that are cleared at the end of the call is safe.
```

There is no corresponding warning for:

```solidity
counter = v;
```

However, the high-level assignment lowers to a transient storage write (`TSTORE`) as well. Both forms therefore have the same relevant composability hazard, but only one receives the warning.

The asymmetry appears to come from the warning being emitted in Yul/inline-assembly analysis for the `tstore` builtin, while high-level transient state-variable lowering emits generated IR/Yul that is not checked by the same warning path.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.