Skip to content

Compile failure across all prototypes: shielded types as mapping keys (Error 10109) with ssolc 0.8.31 #10

@memosr

Description

@memosr

Summary

All 5 prototypes in this repository fail to compile with the current public Seismic toolchain. The mapping(saddress => ...) pattern, which appears in 8 source files across the repo, triggers Error (10109): Shielded types are not allowed as mapping keys in ssolc 0.8.31 (commit cd9163d).

This appears to be a breaking change in the compiler that occurred after the prototypes were merged (~Feb 2025), with public ssolc updated in April 2026.

Environment

Component Version
OS macOS 14 (Apple Silicon, M2)
sforge 1.3.5-v0.2.0 (2026-04-16)
ssolc 0.8.31-develop.2026.4.29+commit.cd9163d8
sfoundryup latest (installed via official script)
Repo commit main HEAD as of 2026-05-16

Reproduction

git clone https://github.com/SeismicSystems/prototypes.git
cd prototypes/level
sforge build

Error output

Compiling 35 files with ssolc 0.8.31 (cd9163d)
Error: Compiler run failed:
Error (10109): Shielded types are not allowed as mapping keys.
  --> src/SRC20.sol:43:13:
   |
43 |     mapping(saddress account => suint256) private _balances;
   |             ^^^^^^^^

The same error occurs in every prototype subdirectory (level, dwell, folio, riff, nibble).

Scope — Affected Files

A repo-wide grep -rn "mapping(saddress" returned 17 occurrences across 8 files in 5 prototypes:

File Occurrences Prototype
folio/src/ChainTracker.sol 4 FOLIO
level/src/SRC20.sol 2 LEVEL
level/src/WDGSRC20.sol 2 LEVEL
level/src/Level.sol 2 LEVEL
riff/src/SRC20.sol 2 RIFF
nibble/src/Rewards20.sol 2 NIBBLE
dwell/src/SRC20.sol 2 DWELL
dwell/src/USDY.sol 1 DWELL
Total 17 5 prototypes

Confirmation: This is a compiler rule, not a typo

The official Seismic documentation explicitly states this constraint:

Mappings can have shielded values but keys cannot be shielded types.

Example: mapping(saddress => uint256) private lookup; // INVALID — shielded key

Source: docs.seismic.systems — Type System

So the rejection is intentional. The prototypes were written before the rule was enforced.

Impact

  • New developers who clone the repo cannot run sforge build or sforge test on any prototype.
  • CI in .github/workflows/ci.yml uses a self-hosted runner with a pinned private sforge build (SFOUNDRY_ROOT=/home/azureuser/...), which may explain why CI still passes for maintainers.
  • External contributions (PRs, test additions, bug fixes) cannot be validated locally with the public toolchain.

Possible Resolutions

I'm flagging this for discussion rather than prescribing a fix, since each option has tradeoffs that affect the privacy model of these prototypes:

Option A — Switch keys to address, keep values shielded

mapping(address account => suint256) private _balances;
  • Pro: Minimal change, compiles immediately.
  • Con: Account membership becomes public (only amounts stay private). This may conflict with the intended privacy model of LEVEL/DWELL/etc.

Option B — Redesign with commitment-based accounts

Use commitment hashes as keys (Tornado-style), with off-chain account discovery.

  • Pro: Preserves full privacy.
  • Con: Significant refactor, changes prototype semantics.

Option C — Pin a compatible ssolc version

Publish the older ssolc (or document how to pin) so the existing code compiles.

  • Pro: Zero code changes.
  • Con: Pinning to old compiler defers the migration indefinitely.

Option D — Update the public toolchain to match maintainer CI

If the private build behaves differently, the public release could be updated to match.

Offer to help

If the maintainer team decides on a direction (especially Option A), I'm happy to open a PR implementing the changes across all affected files. I'm also working on adding test coverage for level (specifically removeLiquidity, calcSwapInput correctness, and epoch-reset behavior for operatorWithdraw) — those are blocked on this issue.

Thanks for the great work on these prototypes — happy to contribute once the compile path is clear.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions