This document describes how to verify the contract, generate/compile, and deploy the MessageVault subgraph in The Graph Studio, and how to consume it from the frontend. It includes references to the project’s backend and frontend.
See also: Frontend README · Backend README
A live demo is available at https://messagevault.casaislabs.com.
Contract on Etherscan (Sepolia): https://sepolia.etherscan.io/address/0xDB069580321E87f30eA171bf20a45BB18A3E5B09
Important: This repository does not include or version a local subgraph/ folder. Manage your Subgraph in The Graph Studio and do not commit subgraph/.
- Live Demo
- Project Composition & Standards
- TL;DR — Create and Deploy Quickly
- Requirements
- Subgraph — Create, Build & Deploy
- Common Problems
- Maintenance
- Related docs: Frontend README · Backend README
Overview
- Monorepo:
backend(Hardhat/Ignition + Solidity),frontend(Vite/React + Wagmi), and no-versionedsubgraph/(Studio-first). - Contract:
MessageVault.solimplements an ERC-4337 smart account to store and emit messages. - Tooling: Hardhat v3,
ethers v6, OpenZeppelin utils, Ignition for deployments, The Graph Studio for indexing.
EVM Standards & Why
ERC‑4337 (IAccount, EntryPoint v0.7): enables account abstraction so non‑owners can invoke wallet actions viaUserOperationif they pass signature validation. This allows sponsored gas (Paymaster), session capabilities, and richer UX.EIP‑191 (personal_sign): signatures overuserOpHashused invalidateUserOpfor off‑chain signing and replay‑protected verification.EIP‑1271: explicitly not implemented in this wallet to keep validation surface small; only EIP‑191 is accepted.- OpenZeppelin
ECDSAandMessageHashUtils: robust signature handling and message prefixing;ReentrancyGuardprevents reentrancy in state‑changing paths.
How the DApp & Contract Work
- Ownership and permissions:
ownercan call wallet functions directly.EntryPointmay call on behalf of a validated signer throughvalidateUserOp(AA flow).
- Core actions:
sendMessageToWallet(string content): emitsMessageStored(recipient=this, sender=actor, id, content)and incrementsnextMessageId(no on-chain persistence ofcontent; rely on events).setEntryPoint(address): wires the wallet to a canonical EntryPoint (v0.7 on Sepolia).addDeposit()andwithdrawDepositTo(address,uint256): manage EntryPoint deposits for AA operations.
- Indexing:
MessageStored,OwnerChanged, andEntryPointSetare indexed by The Graph. The Subgraph is created and managed in Studio (nosubgraph/in repo).
sequenceDiagram
autonumber
title Owner (EOA) Flow
participant FE as Frontend (Client)
participant MV as MessageVault
FE->>MV: sendMessageToWallet("hello")
MV-->>MV: Validate owner
MV-->>MV: Store message + increment id
MV-->>FE: Emit MessageStored
sequenceDiagram
autonumber
title ERC‑4337 (AA) Flow — EntryPoint v0.7
participant FE as Frontend (Client)
participant EP as EntryPoint v0.7
participant MV as MessageVault
FE->>EP: eth_sendUserOperation
EP->>MV: validateUserOp
MV-->>EP: Signature valid
EP->>MV: Execute callData
MV-->>EP: Emit MessageStored
EP-->>FE: Operation result
Collects UserOperations from clients, simulates validation against EntryPoint (simulateValidation), and submits batches via handleOps. It ensures operations are valid and pays the L1 transaction gas, recovering fees from accounts or paymasters.
Optionally sponsors gas for UserOperations by providing paymasterAndData. A managed Paymaster (e.g., Alchemy Gas Manager) can cover gas so end users don’t need ETH. If not sponsoring, the account’s EntryPoint deposit must cover prefund.
In this project, the smart account is MessageVault; the Paymaster is external (not part of the contract). The backend README documents using a managed Paymaster and shows how to deposit/withdraw to EntryPoint when needed.
sequenceDiagram
autonumber
title Project specifics — MessageVault with EntryPoint v0.7 and Bundler
participant FE as Frontend (Client)
participant B as Bundler
participant EP as EntryPoint v0.7
participant PM as Paymaster (external)
participant MV as MessageVault
FE->>B: eth_sendUserOperation(userOp)
B->>EP: simulateValidation(userOp)
EP->>MV: validateUserOp(userOp)
MV-->>EP: Signature valid and selector allowed
EP->>PM: validatePaymasterUserOp (if sponsored)
Note over B,EP: If validation passes
B->>EP: handleOps([userOp])
EP->>MV: execute callData
MV-->>EP: MessageStored
EP-->>B: receipt
B-->>FE: Operation result
sequenceDiagram
participant FE as Frontend (Client)
participant B as Bundler
participant PM as Paymaster
participant EP as EntryPoint v0.7
participant MV as MessageVault
FE->>B: eth_sendUserOperation(userOp)
B->>EP: simulateValidation(userOp)
EP->>MV: validateUserOp(userOp, userOpHash)
EP->>PM: validatePaymasterUserOp(userOp)
Note over B,EP: If validation passes
B->>EP: handleOps([userOp])
EP->>MV: execute callData (sendMessageToWallet)
MV-->>EP: emit MessageStored
EP-->>B: receipt
B-->>FE: operation result
Benefits & Utilities
- Better UX with Account Abstraction: users can interact without owning the wallet or directly spending gas (with a Paymaster).
- Fine‑grained permissioning: only the
sendMessageToWalletselector is allowed for non‑owner AA calls, reducing attack surface. - Event‑driven architecture: clean integration with The Graph for analytics, feeds, and app state.
- Efficiency: messages are not stored in contract storage; only events are emitted. Clients read via The Graph for pagination, ordering, and low gas overhead.
- Operational resilience: deposit management via EntryPoint and robust balance reads across variants.
- Simpler client logic: single
sendMessageToWalletentry captures both owner and AA flows.
Notes
- The Subgraph is managed in Studio; endpoints must be configured via environment variables (e.g.,
VITE_SUBGRAPH_URL). - See
backend/README.mdfor deployment details, Etherscan verification, and EntryPoint parameters.
- Create in Subgraph Studio
- Go to
https://thegraph.com/studio/and create a subgraph (slugmessage-vault). - Network:
sepolia. Contract address:0xDB069580321E87f30eA171bf20a45BB18A3E5B09. startBlock:9554995. Copy yourDeploy Key.
- Go to
- Authenticate CLI
- Install Graph CLI:
npm install -g @graphprotocol/graph-cli@latest - Run:
graph auth <DEPLOY_KEY>
- Install Graph CLI:
- Deploy
- Studio-first: deploy a new version in Studio.
- CLI (optional): in a temporary folder run
graph init, updatesubgraph.yaml/schema.graphql, thengraph codegen && graph build, andgraph deploy <SUBGRAPH_SLUG> --version-label v0.0.X. Do not commit these files.
- Endpoints
- Find endpoints in Studio. Configure your frontend via
VITE_SUBGRAPH_URL. Do not hardcode URLs.
- Node.js 18+
- NPM or Yarn
- The Graph Studio account and your
Deploy Key graph-cliavailable (global or vianpx)- Contract verification details are documented in Backend README
Important: This project does not include or version a local subgraph/ folder. Do not add/commit subgraph/ to this repository.
What this means:
- Manage your Subgraph in The Graph Studio (create, deploy versions, review status and endpoints).
- If you need to edit schema or mappings locally, generate a temporary project with Graph CLI in a throwaway folder: run
graph init, thengraph codegen && graph build, andgraph deploy <SUBGRAPH_SLUG> --version-label v0.0.X. Do not commit these files. - Configure clients via environment variables (e.g.,
VITE_SUBGRAPH_URL); never hardcode endpoint URLs. - Keep only minimal details here to re-create when needed: contract address,
startBlock, and ABI source (Etherscan orbackend/artifacts).
- Create in Subgraph Studio
- Go to
https://thegraph.com/studio/and click “Create Subgraph”. - Choose a slug (e.g.,
message-vault), network (sepolia), contract address, andstartBlock(9554995). - Copy your
Deploy Key.
- Authenticate
- Install Graph CLI globally:
npm install -g @graphprotocol/graph-cli@latest(oryarn global add @graphprotocol/graph-cli). - Run:
graph auth <DEPLOY_KEY>
- Deploy
graph deploy <SUBGRAPH_SLUG> --version-label v0.0.X- Confirm in Studio that status becomes “Synced”.
Endpoints
- Find endpoints in Studio on your subgraph page.
- Do not hardcode URLs; use environment variables (e.g.,
VITE_SUBGRAPH_URL).
Optional local edits
- Only if you need to change schema/mappings: scaffold in a temporary folder with
graph init, thengraph codegen && graph build, and redeploy with the command above.
Docs
- Quick Start: https://thegraph.com/docs/en/subgraphs/quick-start/
- “Invalid input” on deploy: provide
--version-label(v0.0.1,v0.0.2, etc.). - “Unknown subgraph”: confirm the slug in Studio (
message-vaultvsmessagevault). - Changes in
schemaorsrc: re-runnpm run codegenandnpm run buildbefore redeploy. - No results: check
startBlock, contract address, and that there are subsequentMessageStoredevents.
- For new versions:
graph deploy message-vault --version-label v0.0.X - Keep versioning consistent and document relevant changes in mappings or schema.
