Conversation
Mirror the regular contract-storage design (the parameterised pointer type storage(a) and its classes) for EVM transient storage, using the tload/tstore opcodes instead of sload/sstore. The pointer type is named tstorage(a) so that `transient` stays free to become a storage-location keyword. Layout metadata is location-independent, so StorageSize and the generic CanStore/Assign/LVA/RVA/IdxAccess/mapping machinery are reused from std rather than duplicated. New pieces are the parts that actually touch the opcodes: the TransientType class and its value-type instances, CanStore instances for tstorage value types, mappings, and strings/bytes, the byte-array helpers, and the readTransient / ltidx / rtidx accessors. Add a transient counter dispatch example and register it in the suite. Assisted-By: Claude Opus 4.8 <noreply@anthropic.com>
Introduce a `transient` keyword and the contract-field syntax `name : transient T`, which marks a field as living in EVM transient storage. A StorageLocation marker (Storage | Transient) is threaded from the surface AST through name resolution into the resolved AST and on to the field-access desugarer. Lowering is not yet implemented: the field-access desugarer rejects transient fields with a clear "not implemented yet" message. So the syntax parses and type-resolves but fails at desugaring, which is the seam where transient lowering (tstorage-based CStructField instances) will later plug in. Because `transient` is now reserved, the standard-library module can no longer be imported as `std.transient`; rename it to `std.tstorage` (the type it provides is already `tstorage`) and update the counter example. Parser tests cover both plain and initialized transient fields; test/examples/dispatch/transient_field.solc demonstrates the end-to-end syntax (intentionally unregistered, as it fails at desugaring). Assisted-By: Claude Opus 4.8 <noreply@anthropic.com>
FieldAccess now translates a `transient` field of type t to tstorage(t) in its generated CStructField instance (a regular field still maps to storage(t)), replacing the previous "not implemented" desugaring error. The storage-kind distinction is an output of the CStructField context, not the MemberAccessProxy main type, so a second location-specific LVA/RVA instance would overlap the storage one. Instead, generalize the std LVA/RVA instances to abstract over the reference constructor: a `refType` bound by CStructField(refType, off), refType:Typedef(word) and refType:CanStore(loadType), built from the slot offset via Typedef.abs. FieldAccess selects the location purely by the refType it emits. test/examples/dispatch/transient_field.solc now compiles and is a registered dispatch test; set/get on the transient field lower to tstore/tload (verified: a write+read in one call round-trips). Assisted-By: Claude Opus 4.8 <noreply@anthropic.com>
The dispatch test only compiles the contract; this adds an executing
end-to-end test via the testrunner/contest path that asserts EVM
behaviour.
Add a `roundtrip` method (write then read the transient field in one
call) and transient_field.json with three assertions:
- roundtrip(77) returns 77 (tstore then tload within one tx);
- set(99) succeeds;
- a later get() returns 0, because transient storage is cleared at the
end of each transaction (EIP-1153).
The last assertion is what distinguishes transient from persistent
storage: if the field were lowered to sstore/sload, get() would return
99 and the test would fail. Wired into run_contests.sh (run by
`nix flake check`).
Assisted-By: Claude Opus 4.8 <noreply@anthropic.com>
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds support for EVM transient storage, mirroring the existing persistent-storage design.
What's included:
tstorage(a)type andTransientTypeclass (backed bytload/tstore), withCanStoreinstances for scalars, mappings, strings, and bytes. Layout metadata (StorageSize) is reused from std, since transient and persistent storage share the same slot layout.transientkeyword - contract fields can now be declared name : transient T to place them in transient storage. AStorageLocationmarker (Storage | Transient) threads through the AST from parser to desugarer.FieldAccesslowers a transient field totstorage(t)instead ofstorage(t). The std LVA/RVA contract-field instances were generalized over the reference type so a single instance serves both locations (a second instance would overlap onMemberAccessProxy).transient_field.{solc,json}verifies the semantics via thetestrunner: a write+read within one call returns the value, while a value written in one transaction reads back as 0 in a later one, confirming per-transaction clearing.Fields default to persistent storage, so existing contracts are unaffected.