Solidity port of the Etornie Solana programs, deployed on Moca Chain (EVMOS-based L1) for the Animoca grant track.
Three contracts mirror the original etornie-solana Anchor programs:
| Solana program (Anchor) | EVM contract (Solidity) | Purpose |
|---|---|---|
etornie-attestation |
EtornieAttestation.sol |
Per-case on-chain attestation + lifecycle event log |
etornie-ip-token |
EtornieIpToken.sol |
Soul-bound ERC-721 case NFT (mint/burn only) |
etornie-zk-verifier |
EtornieZkVerifier.sol |
Groth16 verifier with three circuits: HelloWorld, FileOwnership, Compliance (x402) |
Built by Wiener Labs for Etornie AG (Ruessenstrasse 5, 6340 Baar, Switzerland).
- Foundry (forge, cast, anvil) — Solidity 0.8.24, evm-version
shanghai - OpenZeppelin Contracts v5.0.2 —
ERC721,AccessControl - No external runtime deps — all OZ utilities + forge-std vendored under
lib/
Moca Chain is an EVMOS-based L1 with London opcodes and partial Shanghai support. Native token $MOCA, ~1 s block time, 60 M gas limit.
| Network | Chain ID | RPC | Explorer |
|---|---|---|---|
| Testnet | 222888 |
https://rpc.testnet.mocachain.dev |
https://testnet-scan.mocachain.org |
| Mainnet | 2288 |
https://rpc.mocachain.org (API key) |
https://scan.mocachain.org |
Testnet faucet: https://faucet.mocachain.org.
git clone https://github.com/wienerlabs/etornie-moca-contracts.git
cd etornie-moca-contracts
forge install # pulls forge-std + openzeppelin-contracts
forge build
forge test -vvv-
Get test MOCA from the faucet for the deployer address.
-
Configure env — copy
.env.exampleto.env, fillPRIVATE_KEY+MOCA_TESTNET_RPC. -
Dry-run (no broadcast):
source .env forge script script/Deploy.s.sol --rpc-url moca_testnet -
Broadcast:
forge script script/Deploy.s.sol --rpc-url moca_testnet --broadcast --private-key $PRIVATE_KEY -
Verify on explorer:
https://testnet-scan.mocachain.org/address/<DEPLOYED_ADDRESS>
- One record per
case_id(16-byte UUID). Subsequentcreatereverts. updateemitsCaseAttestationUpdatedwitholdMetadataHash+newMetadataHashso the tx log alone is a full timeline.- Writes gated by
OPERATOR_ROLE. Admin can rotate operators viagrantRole/revokeRole.
- ERC-721 with
_updateoverride that reverts on transfer (allows only mint and burn) — matches the SolanaDefaultAccountState=Frozendesign. tokenIdis deterministic:uint256(uint128(caseId)). Top 128 bits reserved.- Mint + burn gated by
OPERATOR_ROLE. Burn precondition (case in terminal state) is enforced off-chain by the backend.
- Wraps three Groth16 verifier sub-contracts (one per circuit). Sub-verifier addresses are admin-settable so each circuit's verifying key can be rotated.
- Records are keyed by
keccak256(user, digest)so the same proof cannot be replayed against the same user. verifyFileOwnership/verifyCompliancemirror the Solana canonical encoding of(hi, lo)halves to close the grief vector where unused high bits could map distinct hashes to the same slot.- Auto-generated snarkjs Groth16 verifier contracts (one per circuit) are deployed separately and registered via
setHelloWorldVerifier/setFileOwnershipVerifier/setComplianceVerifier. Circom source lives in theetornie-solanarepo undercircuits/.
forge test -vvv
Current suite:
| Suite | Tests | Coverage focus |
|---|---|---|
EtornieAttestation.t.sol |
7 | create, update, role gating, duplicate revert, fuzz on case IDs |
EtornieIpToken.t.sol |
9 | mint, burn, soul-bound revert (transfer + safeTransfer), interface ids |
EtornieZkVerifier.t.sol |
9 | verify success (×3 circuits), mismatched digest, replay, invalid proof, malformed input |
All 25 tests pass locally (forge test).
.
├── src/
│ ├── EtornieAttestation.sol
│ ├── EtornieIpToken.sol
│ └── EtornieZkVerifier.sol
├── test/
│ ├── EtornieAttestation.t.sol
│ ├── EtornieIpToken.t.sol
│ └── EtornieZkVerifier.t.sol
├── script/
│ └── Deploy.s.sol
├── lib/
│ ├── forge-std/
│ └── openzeppelin-contracts/
├── foundry.toml
├── remappings.txt
├── .env.example
├── LICENSE
└── README.md
| Contract | Address | Tx |
|---|---|---|
EtornieAttestation |
0x79987a54DB54680bd4c3Ac3AbF1E34D723180e56 |
0xd7f218f6…02c3db |
EtornieIpToken |
0x81222d1f6FcA1b47F87F2ffDbBE77259Ce85ee2F |
0x9cc2a7fc…62dbb |
EtornieZkVerifier |
0xeeb6d9973437C54d000BF2388147ae179723DCfC |
0xf4bdaa41…bb9c70c |
Admin + operator on every contract: 0x6345eE23c81132A3b3245E2fcB55374205A2C8c4 (initial deployer; rotate via grantRole / revokeRole before mainnet).
Deploy gas: ~0.0031 MOCA total (~3.1 M gas at ~1 Gwei) across the three contracts.
Not deployed yet.
etornie-solana— original Anchor programs + Circom circuitsetornie.xyz— marketing site- Etornie product — production app at
app.etornie.com
MIT — see LICENSE.