# Table of Contents - [Welcome | Seismic Docs](#welcome-seismic-docs) - [Quickstart | Seismic Docs](#quickstart-seismic-docs) - [Tutorial | Seismic Docs](#tutorial-seismic-docs) - [Setting Up Your Walnut App Project | Seismic Docs](#setting-up-your-walnut-app-project-seismic-docs) - [Verify devtool installation | Seismic Docs](#verify-devtool-installation-seismic-docs) - [Installation | Seismic Docs](#installation-seismic-docs) - [Create project structure and monorepo workspace | Seismic Docs](#create-project-structure-and-monorepo-workspace-seismic-docs) - [Writing, testing and deploying the contract | Seismic Docs](#writing-testing-and-deploying-the-contract-seismic-docs) - [Initialize the contracts subdirectory | Seismic Docs](#initialize-the-contracts-subdirectory-seismic-docs) - [Initialize the CLI subdirectory | Seismic Docs](#initialize-the-cli-subdirectory-seismic-docs) - [Chapter 1: Making the Kernel | Seismic Docs](#chapter-1-making-the-kernel-seismic-docs) - [Chapter 2: Making the Shell and revealing the Kernel | Seismic Docs](#chapter-2-making-the-shell-and-revealing-the-kernel-seismic-docs) - [Chapter 3: Reset Mechanism, Rounds, and a more conditional Kernel Reveal | Seismic Docs](#chapter-3-reset-mechanism-rounds-and-a-more-conditional-kernel-reveal-seismic-docs) - [Deploying your contract | Seismic Docs](#deploying-your-contract-seismic-docs) - [Interacting with the contract via a CLI | Seismic Docs](#interacting-with-the-contract-via-a-cli-seismic-docs) - [suint / sint | Seismic Docs](#suint-sint-seismic-docs) - [Quick primer: seismic-viem | Seismic Docs](#quick-primer-seismic-viem-seismic-docs) - [Understanding the Walnut contract | Seismic Docs](#understanding-the-walnut-contract-seismic-docs) - [Clients | Seismic Docs](#clients-seismic-docs) - [Chapter 1: Defining the constants and utilities | Seismic Docs](#chapter-1-defining-the-constants-and-utilities-seismic-docs) - [Basics | Seismic Docs](#basics-seismic-docs) - [saddress | Seismic Docs](#saddress-seismic-docs) - [Chapter 4: Testing your Walnut contract | Seismic Docs](#chapter-4-testing-your-walnut-contract-seismic-docs) - [sbool | Seismic Docs](#sbool-seismic-docs) - [The Seismic Transaction | Seismic Docs](#the-seismic-transaction-seismic-docs) - [Collections | Seismic Docs](#collections-seismic-docs) - [Differences from Ethereum | Seismic Docs](#differences-from-ethereum-seismic-docs) - [Signed reads | Seismic Docs](#signed-reads-seismic-docs) - [Chapter 2: Writing the core app | Seismic Docs](#chapter-2-writing-the-core-app-seismic-docs) - [Chapter 3: Bringing it all together | Seismic Docs](#chapter-3-bringing-it-all-together-seismic-docs) - [Deploy tools | Seismic Docs](#deploy-tools-seismic-docs) - [Tx Lifecycle | Seismic Docs](#tx-lifecycle-seismic-docs) - [Links & Contact | Seismic Docs](#links-contact-seismic-docs) - [Testnet | Seismic Docs](#testnet-seismic-docs) - [Mainnet | Seismic Docs](#mainnet-seismic-docs) - [Node Operator FAQ | Seismic Docs](#node-operator-faq-seismic-docs) - [Codebases | Seismic Docs](#codebases-seismic-docs) - [Devnet | Seismic Docs](#devnet-seismic-docs) - [Email Protection | Cloudflare](#email-protection-cloudflare) - [Gotchas | Seismic Docs](#gotchas-seismic-docs) - [Basics | Seismic Docs](#basics-seismic-docs) - [Links & Contact | Seismic Docs](#links-contact-seismic-docs) --- # Welcome | Seismic Docs ![Page cover](https://docs.seismic.systems/~gitbook/image?url=https%3A%2F%2F1987385627-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FhkB2uNxma1rxIgBfHgAT%252Fuploads%252FFedL3xZFwTlW11mcYznm%252Flight.png%3Falt%3Dmedia%26token%3D76f25354-93a8-4714-ae69-a54da01c6f4a&width=1248&dpr=3&quality=100&sign=dc3ff31c&sv=2)![Page cover](https://docs.seismic.systems/~gitbook/image?url=https%3A%2F%2F1987385627-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FhkB2uNxma1rxIgBfHgAT%252Fuploads%252FuKULThI7BUOy1wizI6BM%252Fdark.png%3Falt%3Dmedia%26token%3D229ff21b-a593-4660-b22e-a3a2c731e1c5&width=1248&dpr=3&quality=100&sign=40c08709&sv=2) * * * ### [hashtag](https://docs.seismic.systems/#what-is-seismic) What is Seismic? Seismic is a privacy enabled blockchain for fintechs. The blockchain is EVM, so developer experience is approximately the same as Ethereum, with a bit of extra syntax to control privacy settings. It also comes with additional modules commonly needed by fintechs, such as compliance tooling and on-/off-ramps. Whether you're an individual developer or part of a larger team, Seismic can help you build crypto powered products while protecting the privacy of your users. * * * ### [hashtag](https://docs.seismic.systems/#how-to-use-the-docs) How to use the docs The docs are organized into 4 sections: * [Getting Started](https://docs.seismic.systems/) : You are here. * [Onboarding](https://docs.seismic.systems/onboarding/quickstart) : Shortcut to getting your hands dirty. * [Core](https://docs.seismic.systems/core/basics) : Walkthrough of core concepts for developing on Seismic. * [Appendix](https://docs.seismic.systems/appendix/links-and-contact) : Detailed technical references. Use the sidebar to navigate through the sections, or search (`Cmd+K`) to quickly find a page. * * * ### [hashtag](https://docs.seismic.systems/#pre-requisite-knowledge) Pre-requisite knowledge Our documentation assumes some familiarity with blockchain app development. Before getting started, it'll help if you're comfortable with: * [Solidityarrow-up-right](https://www.soliditylang.org/) * [Foundryarrow-up-right](https://getfoundry.sh/) * [Viemarrow-up-right](https://viem.sh/) If you're new to blockchain app development or need a refresher, we recommend starting out with the [CryptoZombiesarrow-up-right](https://cryptozombies.io/en/course) tutorial. * * * ### [hashtag](https://docs.seismic.systems/#work-with-us) Work with us If you might benefit from direct support from the team, please don't hesitate to reach out to `dev@seismic.systems`. We pride ourselves in fast response time. You can also check out our [X accountarrow-up-right](https://x.com/SeismicSys) for the latest updates. [NextInstallationchevron-right](https://docs.seismic.systems/getting-started/installation) Last updated 5 days ago --- # Quickstart | Seismic Docs You can play around with `stype` using our [starter repositoryarrow-up-right](https://github.com/SeismicSystems/seismic-starter) . This assumes you went through everything in [Installation](https://docs.seismic.systems/getting-started/installation) . Copy git clone "https://git@github.com/SeismicSystems/seismic-starter.git" cd seismic-starter/packages/contracts sforge test -vv [PreviousInstallationchevron-left](https://docs.seismic.systems/getting-started/installation) [NextTutorialchevron-right](https://docs.seismic.systems/onboarding/tutorial) Last updated 12 months ago --- # Tutorial | Seismic Docs [rectangle-terminalSetting Up Your Walnut App Projectchevron-right](https://docs.seismic.systems/onboarding/tutorial/setting-up-your-walnut-app-project) [file-signatureWriting, testing and deploying the contractchevron-right](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract) [user-alienInteracting with the contract via a CLIchevron-right](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli) [acornUnderstanding the Walnut contractchevron-right](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract) [PreviousQuickstartchevron-left](https://docs.seismic.systems/onboarding/quickstart) [NextSetting Up Your Walnut App Projectchevron-right](https://docs.seismic.systems/onboarding/tutorial/setting-up-your-walnut-app-project) Last updated 1 year ago --- # Setting Up Your Walnut App Project | Seismic Docs In this chapter, you’ll set up the foundation for the Walnut App using a clean and modular monorepo-style workspace. This structure separates concerns into distinct areas, making your project easier to navigate and maintain. You’ll create a `contracts` directory to house your Seismic smart contracts and tests, and a `cli` directory to serve as the command-line interface for interacting with those contracts. By the end of this chapter, you’ll have a fully initialized project, complete with dependencies, formatting tools, and a seamless environment for both contract development and interaction. [PreviousTutorialchevron-left](https://docs.seismic.systems/onboarding/tutorial) [NextVerify devtool installationchevron-right](https://docs.seismic.systems/onboarding/tutorial/setting-up-your-walnut-app-project/verify-devtool-installation) Last updated 1 year ago --- # Verify devtool installation | Seismic Docs Before continuing, ensure that you have completed the steps in the [Installation](https://docs.seismic.systems/getting-started/installation) section to install all necessary Seismic developer tools: • `sforge`: Framework for testing and deploying smart contracts. • `sanvil` : Local Seismic node. • `ssolc`: The Seismic Solidity compiler. Run each of the above commands in your terminal with a `--version` flag to ensure that they're installed correctly. Also ensure that you have [bunarrow-up-right](https://bun.sh/) installed on your machine. If you do not have `bun` installed, follow the instructions [herearrow-up-right](https://bun.sh/docs/installation) to install it on your machine. [PreviousSetting Up Your Walnut App Projectchevron-left](https://docs.seismic.systems/onboarding/tutorial/setting-up-your-walnut-app-project) [NextCreate project structure and monorepo workspacechevron-right](https://docs.seismic.systems/onboarding/tutorial/setting-up-your-walnut-app-project/create-project-structure-and-monorepo-workspace) Last updated 1 year ago --- # Installation | Seismic Docs * * * ### [hashtag](https://docs.seismic.systems/getting-started/installation#system-requirements) System requirements Before you begin, make sure your machine meets the following requirements: * x84\_64 or arm64 architecture * MacOS, Ubuntu, or Windows * * * ### [hashtag](https://docs.seismic.systems/getting-started/installation#install-the-local-development-suite) Install the local development suite The local development suite uses `sforge` as the testing framework, `sanvil` as the local node, and `ssolc` as the compiler. 1. Install [rustarrow-up-right](https://www.rust-lang.org/tools/install) and [cargoarrow-up-right](https://doc.rust-lang.org/cargo/getting-started/installation.html) on your machine if you don't already have them. Default installation works well. Copy curl https://sh.rustup.rs -sSf | sh 1. Download and execute the sfoundryup installation script. Copy curl -L \ -H "Accept: application/vnd.github.v3.raw" \ "https://api.github.com/repos/SeismicSystems/seismic-foundry/contents/sfoundryup/install?ref=seismic" | bash source ~/.zshenv # or ~/.bashrc or ~/.zshrc 1. Install `sforge`, `sanvil`, `ssolc`. Expect this to take between 5-20 minutes depending on your machine. Copy sfoundryup source ~/.zshenv # or ~/.bashrc or ~/.zshrc 1. (Optional) Remove old build artifacts in existing projects. You can ignore this step if you aren't working with existing foundry projects. Copy sforge clean # run in your project's contract directory * * * ### [hashtag](https://docs.seismic.systems/getting-started/installation#set-up-the-vscode-extension) Set up the VSCode extension We recommend adding syntax highlighting via the [`seismic`arrow-up-right](https://marketplace.visualstudio.com/items?itemName=SeismicSys.seismic) (or [`seismic`arrow-up-right](https://open-vsx.org/extension/SeismicSys/seismic) for Open VSX) extension from the VSCode marketplace. If you already have the `solidity` extension, you'll have to disable it while writing Seismic code. [PreviousWelcomechevron-left](https://docs.seismic.systems/) [NextQuickstartchevron-right](https://docs.seismic.systems/onboarding/quickstart) Last updated 4 days ago --- # Create project structure and monorepo workspace | Seismic Docs 1. **Create the project folder and navigate into it:** Copy mkdir walnut-app cd walnut-app 1. **Create the** `**packages**` **directory with subdirectories for** `**contracts**` **and** `**cli**` Copy mkdir -p packages/contracts packages/cli The `contracts` subdirectory will house the Seismic smart contract(s) and test(s) for the project, while the `cli` will house the interface to interact with the contracts. 1. **Initialize a bun project in the root directory:** Copy bun init -y && rm index.ts && rm tsconfig.json && touch .prettierrc && touch .gitmodules We remove the default `index.ts` and `tsconfig.json` files created by `bun init -y` to keep the root directory clean and focused on managing the monorepo structure rather than containing code. We also create a `.prettierrc` file for consistent code formatting and a `.gitmodules` file to manage contract submodules. 1. **Replace the default** `**package.json**` **with the following content for a monorepo setup:** Copy { "workspaces": [\ "packages/**"\ ], "dependencies": {}, "devDependencies": { "@trivago/prettier-plugin-sort-imports": "^5.2.1", "prettier": "^3.4.2" } } 1. **Add the following to the** `**.prettierrc**` **file for consistent code formatting:** Copy { "semi": false, "tabWidth": 2, "singleQuote": true, "printWidth": 80, "trailingComma": "es5", "plugins": ["@trivago/prettier-plugin-sort-imports"], "importOrder": [\ "^(?!@)([^.].*$)",\ "^@(.*)$",\ "^[./]",\ "^(?!@)([^.].*$)",\ "^@(.*)$",\ "^[./]"\ ], "importOrderParserPlugins": ["typescript", "jsx", "decorators-legacy"], "importOrderSeparation": true, "importOrderSortSpecifiers": true } 1. **Replace the**`**.gitignore**` **file with:** Copy # Compiler files cache/ out/ # Ignores development broadcast logs !/broadcast /broadcast/*/31337/ /broadcast/**/dry-run/ # Docs docs/ # Dotenv file .env node_modules/ 1. **Add the following to the** `**.gitmodules**` **file to track git submodules (in our case, only the Forge standard library,** `**forge-std**`**):** Copy [submodule "packages/contracts/lib/forge-std"] path = packages/contracts/lib/forge-std url = https://github.com/foundry-rs/forge-std [PreviousVerify devtool installationchevron-left](https://docs.seismic.systems/onboarding/tutorial/setting-up-your-walnut-app-project/verify-devtool-installation) [NextInitialize the contracts subdirectorychevron-right](https://docs.seismic.systems/onboarding/tutorial/setting-up-your-walnut-app-project/initialize-the-contracts-subdirectory) Last updated 1 year ago --- # Writing, testing and deploying the contract | Seismic Docs This section dives into the heart of the Walnut App—the **shielded smart contract** that powers its functionality. You’ll start by building the foundational pieces of the Walnut, including the kernel and the protective shell, before implementing more advanced features like rounds, reset mechanisms, and contributor-based access control. By the end of this section, you’ll have a fully functional, round-based Walnut contract that is secure, fair, and replayable. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract#what-youll-learn) What You'll Learn In this section, you’ll: • Define and initialize the kernel, the hidden value inside the Walnut. • Build the **shell**, the protective layer that hides the kernel, and implement a `hit()` function to help crack it, and a `shake` function to increment the kernel value by an encrypted amount. • Add a `look()` function to conditionally reveal the kernel. • Implement a reset mechanism to restart the Walnut for multiple rounds. • Track player contributions in each round, ensuring that only contributors can access the kernel. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract#overview-of-chapters) Overview of Chapters * [**Chapter 1: Making the Kernel**](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-1-making-the-kernel) You’ll define the kernel using a shielded state variable (suint256) and implement a shake() function to increment its value. This chapter introduces **shielded writes.** * [**Chapter 2: Making the Shell and Revealing the Kernel**](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-2-making-the-shell-and-revealing-the-kernel) Learn how to build the shell, which protects the kernel from being accessed prematurely. You’ll implement the `hit()`function to crack the shell and the `look()` function to reveal the kernel once conditions are met. * [**Chapter 3: Reset Mechanism, Rounds, and a more conditional Kernel Reveal**](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-3-reset-mechanism-rounds-and-a-more-conditional-kernel-reveal) This chapter introduces a reset mechanism to enable multiple rounds of gameplay. You’ll track contributions per round and ensure that only players who helped crack the Walnut in a specific round can reveal the kernel. This chapter introduces **shielded reads.** [PreviousInitialize the CLI subdirectorychevron-left](https://docs.seismic.systems/onboarding/tutorial/setting-up-your-walnut-app-project/initialize-the-cli-subdirectory) [NextChapter 1: Making the Kernelchevron-right](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-1-making-the-kernel) Last updated 1 year ago --- # Initialize the contracts subdirectory | Seismic Docs 1. **Navigate to the contracts subdirectory:** Copy cd packages/contracts 1. **Initialize a project with** `**sforge**` **:** Copy sforge init --no-commit && rm -rf .github This command will: * Create the contract project structure (e.g., `src/` , `test/`, `foundry.toml`). * Automatically install the Forge standard library (`forge-std` ) as a submodule. * Remove the `.github` workflow folder (not required) 1. Edit the `.gitignore` file to be the following: Copy .env broadcast/ cache/ 1. Delete the default contract, test and script files (`Counter.sol` and `Counter.t.sol` and `Counter.s.sol` ) and replace them with their `Walnut` counterparts (`Walnut.sol` , `Walnut.t.sol and Walnut.s.sol ):` Copy # Remove the Counter files rm -f src/Counter.sol test/Counter.t.sol script/Counter.s.sol # Create empty Walnut files in the same locations touch src/Walnut.sol test/Walnut.t.sol script/Walnut.s.sol These files are empty for now, but we will add to them as we go along. [PreviousCreate project structure and monorepo workspacechevron-left](https://docs.seismic.systems/onboarding/tutorial/setting-up-your-walnut-app-project/create-project-structure-and-monorepo-workspace) [NextInitialize the CLI subdirectorychevron-right](https://docs.seismic.systems/onboarding/tutorial/setting-up-your-walnut-app-project/initialize-the-cli-subdirectory) Last updated 10 months ago --- # Initialize the CLI subdirectory | Seismic Docs Now that the `contracts` subdirectory has been initialized, you should now initialize the `cli` subdirectory that will be used to interact with the deployed contracts. 1. **Navigate to the contracts subdirectory:** Copy # Assuming you are currently in the contracts directory cd ../cli 1. **Initialize a new bun project** Copy bun init -y 1. Now, create an `src/` folder and move `index.ts` there. Copy mkdir -p src && mv -t src index.ts 1. Now, edit `package.json` to be the following: Copy { "name": "walnut-cli", "license": "MIT License", "type": "module", "scripts": { "dev": "bun run src/index.ts" }, "dependencies": { "dotenv": "^16.4.7", "seismic-viem": "1.0.9", "viem": "^2.22.3" }, "devDependencies": { "@types/node": "^22.7.6", "typescript": "^5.6.3" } } 1. Edit `.gitignore` to be: Copy node_modules Your environment is now set! [PreviousInitialize the contracts subdirectorychevron-left](https://docs.seismic.systems/onboarding/tutorial/setting-up-your-walnut-app-project/initialize-the-contracts-subdirectory) [NextWriting, testing and deploying the contractchevron-right](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract) Last updated 1 year ago --- # Chapter 1: Making the Kernel | Seismic Docs In this chapter, you’ll learn to create and initialize the kernel, a hidden value inside the Walnut, and increment it by implementing a shake function. _Estimated time: ~10 minutes._ ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-1-making-the-kernel#defining-the-kernel) Defining the kernel The **kernel** is the hidden number inside the Walnut. Using Seismic’s `**suint256**` type, the kernel is shielded on-chain. Open up `packages/contracts/Walnut.sol` and define the kernel as a state variable and initialize it in the constructor: Copy // SPDX-License-Identifier: MIT License pragma solidity ^0.8.13; contract Walnut { suint256 kernel; // The shielded kernel (number inside the Walnut) // Constructor to initialize the kernel constructor(suint256 _kernel) { kernel = _kernel; } } **Add a shake function** Next, let’s implement a function to increment the kernel. The shake function takes an **suint256** parameter, `_numShakes` which specifies the amount to increment the kernel by. Copy function shake(suint256 _numShakes) public { kernel += _numShakes; // Increment the kernel value using the shielded parameter. emit Shake(msg.sender); // Log the shake event. } **What's happening here?** Since `shake` takes in an `stype` as one of its parameters, it is key that no information about this parameter (in this case, the number of shakes) is leaked at any time during the function call. This means that the value of `_numShakes` is known only to the function caller and is encrypted on-chain. The function also updates a state variable (`kernel` ) and hence constitutes a state transition, which makes a call to this function a **shielded write.** [PreviousWriting, testing and deploying the contractchevron-left](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract) [NextChapter 2: Making the Shell and revealing the Kernelchevron-right](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-2-making-the-shell-and-revealing-the-kernel) Last updated 1 year ago --- # Chapter 2: Making the Shell and revealing the Kernel | Seismic Docs In this chapter, you’ll build the **shell**, the protective layer that hides the kernel. You’ll initialize the shell’s strength and implement a `hit` function to decrement it. Additionally, you’ll add a `look()` function with a `requiredCracked` modifier to ensure the kernel can only be viewed once the shell is fully broken. _Estimated Time: ~10 minutes._ ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-2-making-the-shell-and-revealing-the-kernel#defining-the-shell) Defining the shell The shell determines the Walnut’s resilience. It has an integer strength (`shellStrength`), which represents how many hits it can withstand before cracking. Let’s define the shell and initialize it in the constructor: Copy uint256 shellStrength; // The strength of the Walnut's shell. constructor(uint256 _shellStrength, suint256 _kernel) { shellStrength = _shellStrength; // Set the initial shell strength. kernel = _kernel; // Initialize the kernel. } ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-2-making-the-shell-and-revealing-the-kernel#adding-the-hit-function) Adding the hit function Each time the Walnut is hit, the shell strength decreases, simulating damage to the protective shell. This is crucial for revealing the kernel, **as the shell must be fully broken for the kernel to be accessed:** Copy // Event to log hits event Hit(address indexed hitter, uint256 remainingShellStrength); // Function to hit the walnut shell function hit() public { shellStrength--; // Decrease the shell strength. emit Hit(msg.sender, shellStrength); // Log the hit event. } // Modifier to ensure the shell is not cracked. modifier requireIntact() { require(shellStrength > 0, "SHELL_ALREADY_CRACKED"); _; } ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-2-making-the-shell-and-revealing-the-kernel#whats-happening-here) What's happening here? * **The** `**requireIntact**` modifier: Ensures that the function cannot be called if the Walnut’s shell is already broken (`shellStrength == 0`). This prevents unnecessary calls after the shell is fully cracked. We can now also add this modifier to the shake function in order to restrict `shake` being called even after the shell is broken: * **Decrementing the shell**: Each call to `hit`decreases the shell’s strength (`shellStrength`) by one. * **Logging the action**: The `Hit` event records the hitter’s address `(msg.sender)` and the remaining shell strength. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-2-making-the-shell-and-revealing-the-kernel#example-call) Example call: Here’s how calling the hit function works in practice: • **Initial State**: The shell strength is set to 5. • **First Hit**: A player calls hit(). The shell strength decreases to 4. • **Subsequent Hits**: Each additional hit reduces the shell strength by 1 until it reaches 0 ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-2-making-the-shell-and-revealing-the-kernel#revealing-the-kernel) Revealing the Kernel Now that we have implemented the shell’s durability and the ability to break it using the hit function, we can introduce a new condition: the kernel should only be revealed once the shell is fully cracked. Currently, there is no way to access the kernel’s value. However, now that we have a shell with a decreasing strength, we can apply a condition that restricts when the kernel can be seen. Specifically: • The kernel **should remain hidden** while the **shell is intact**. • The kernel **can only be revealed** once the shell’s strength reaches **zero, i.e. when it is cracked**. To enforce this, we will create a function called `look()` , which will return the kernel’s value, but only if the Walnut has been fully cracked. Here’s how we define `look()` with a `requireCracked` modifier: **What's happening here?** * **Restricting Access with a Condition**: The `requireCracked` modifier ensures that look() can only be called if `shellStrength == 0`, meaning the Walnut has been fully cracked. * **Revealing the Kernel**: Once the condition is met, `look()` returns the unshielded value of the kernel. * **Preventing Premature Access**: If look() is called before the shell is broken, the function will revert with the error `"SHELL_INTACT"`. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-2-making-the-shell-and-revealing-the-kernel#updated-contract-with-hit-shake-and-look) Updated contract with hit, shake and look [PreviousChapter 1: Making the Kernelchevron-left](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-1-making-the-kernel) [NextChapter 3: Reset Mechanism, Rounds, and a more conditional Kernel Revealchevron-right](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-3-reset-mechanism-rounds-and-a-more-conditional-kernel-reveal) Last updated 11 months ago * [Defining the shell](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-2-making-the-shell-and-revealing-the-kernel#defining-the-shell) * [Adding the hit function](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-2-making-the-shell-and-revealing-the-kernel#adding-the-hit-function) * [What's happening here?](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-2-making-the-shell-and-revealing-the-kernel#whats-happening-here) * [Example call:](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-2-making-the-shell-and-revealing-the-kernel#example-call) * [Revealing the Kernel](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-2-making-the-shell-and-revealing-the-kernel#revealing-the-kernel) * [Updated contract with hit, shake and look](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-2-making-the-shell-and-revealing-the-kernel#updated-contract-with-hit-shake-and-look) sun-brightdesktopmoon Copy function shake(suint256 _numShakes) public requireIntact { kernel += _numShakes; // Increment the kernel value using the shielded parameter. emit Shake(msg.sender); // Log the shake event. } Copy // Function to reveal the kernel if the shell is fully cracked. function look() public view requireCracked returns (uint256) { return uint256(kernel); // Reveal the kernel as a standard uint256. } // Modifier to ensure the shell is fully cracked before revealing the kernel. modifier requireCracked() { require(shellStrength == 0, "SHELL_INTACT"); // Ensure the shell is broken before revealing the kernel. _; } Copy // SPDX-License-Identifier: MIT License pragma solidity ^0.8.13; contract Walnut { uint256 shellStrength; // The strength of the Walnut's shell. suint256 kernel; // The hidden kernel (number inside the Walnut). // Events event Hit(address indexed hitter, uint256 remainingShellStrength); // Logs when the Walnut is hit. event Shake(address indexed shaker); // Logs when the Walnut is shaken. // Constructor to initialize the shell and kernel. constructor(uint256 _shellStrength, suint256 _kernel) { shellStrength = _shellStrength; // Set the initial shell strength. kernel = _kernel; // Initialize the kernel. } // Function to hit the Walnut and reduce its shell strength. function hit() public requireIntact { shellStrength--; // Decrease the shell strength. emit Hit(msg.sender, shellStrength); // Log the hit action. } // Function to shake the Walnut and increment the kernel. function shake(suint256 _numShakes) public requireIntact { kernel += _numShakes; // Increment the kernel by the given number of shakes. emit Shake(msg.sender); // Log the shake action. } // Function to reveal the kernel if the shell is fully cracked. function look() public view requireCracked returns (uint256) { return uint256(kernel); // Reveal the kernel as a standard uint256. } // Modifier to ensure the shell is fully cracked before revealing the kernel. modifier requireCracked() { require(shellStrength == 0, "SHELL_INTACT"); // Ensure the shell is broken before revealing the kernel. _; } // Modifier to ensure the shell is not cracked. modifier requireIntact() { require(shellStrength > 0, "SHELL_ALREADY_CRACKED"); _; } } sun-brightdesktopmoon --- # Chapter 3: Reset Mechanism, Rounds, and a more conditional Kernel Reveal | Seismic Docs In this chapter, we’ll implement a reset mechanism that allows the Walnut to be reused in multiple rounds, ensuring each game session starts fresh. We’ll also track contributors per round so that only players who participated in cracking the Walnut can call `look()`. By the end, we’ll have a fully functional round-based walnut game where the kernel remains shielded until conditions are met! _Estimated time: ~15 minutes._ ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-3-reset-mechanism-rounds-and-a-more-conditional-kernel-reveal#the-need-for-a-reset-mechanism) The need for a Reset mechanism Right now, once the Walnut is cracked, there’s no way to reset it. If a game session were to continue, we’d have no way to start fresh—the shell would remain at 0, and the kernel would be permanently revealed. To solve this, we need to introduce: ✅ A `reset` function that restores the Walnut to its original state. ✅ Round tracking, so each reset creates a new round. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-3-reset-mechanism-rounds-and-a-more-conditional-kernel-reveal#the-need-for-a-contributor-check) The need for a contributor check While the reset mechanism and round tracking allow us to restart the Walnut for continuous gameplay, they still don’t address **who** should be allowed to call the `look()` function. Right now, any player can call `look()` once the shell is cracked, even if they didn’t participate in hitting it during the current round. This creates the following issues: * **Fairness**: Players who didn’t contribute should not be able to reap the benefits of seeing the kernel. * **Incentivizing Contribution**: The game needs to encourage active participation by ensuring that only those who helped crack the Walnut in a specific round are rewarded with access to the kernel. The solution to this is implementing a conditional check on `look()` which allows only those players who **contributed in hitting the shell for a particular round (i.e., players whose hit count is >0 for that round)** to view the kernel after the walnut is cracked. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-3-reset-mechanism-rounds-and-a-more-conditional-kernel-reveal#implementing-the-reset-mechanism) Implementing the Reset Mechanism The reset mechanism allows the Walnut to be reused for multiple rounds, with each round starting fresh. It restores the Walnut’s shell and kernel to their original states and increments the round counter to mark the beginning of a new round. Here’s how we can implement the reset function: **What’s Happening Here?** * **Condition for Reset (**`**requireCracked**`**):** The reset function can only be called once the Walnut’s shell is cracked, enforced by the `requireCracked` modifier. * **Restoring Initial State**: The shell strength and kernel are reset to their original values (`initialShellStrength` and `initialKernel`), ensuring the Walnut starts afresh for the next round. * **Round Tracking**: The `round` counter increments each time the Walnut is reset, allowing us to distinguish between rounds. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-3-reset-mechanism-rounds-and-a-more-conditional-kernel-reveal#modifying-hit-to-track-contributions) Modifying hit() to track contributions To enforce fair access to the kernel, we’ll track the number of hits each player contributes in a given round. This is achieved using the `hitsPerRound` mapping: Every time a player calls the `hit()` function, we update their contribution in the current round: **What’s Happening Here?** * **Tracking Contributions**: The `hitsPerRound` mapping records each player’s hits in the current round. This ensures we can verify who participated when the Walnut was cracked. * **Replayable Rounds**: Because contributions are tracked by round, the game can fairly reset and start fresh without losing player data from previous rounds. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-3-reset-mechanism-rounds-and-a-more-conditional-kernel-reveal#restricting-look-with-a-contributor-check) Restricting look() with a contributor check To ensure only contributors can reveal the kernel, we’ll use a modifier called `onlyContributor`: We’ll then apply this modifier to the `look()` function: **Congratulations!** You made it through to writing the entire shielded smart contract for a multiplayer, multi-round, walnut app! **Final Walnut contract** Now, onto testing the contract! [PreviousChapter 2: Making the Shell and revealing the Kernelchevron-left](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-2-making-the-shell-and-revealing-the-kernel) [NextChapter 4: Testing your Walnut contractchevron-right](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-4-testing-your-walnut-contract) Last updated 1 year ago * [The need for a Reset mechanism](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-3-reset-mechanism-rounds-and-a-more-conditional-kernel-reveal#the-need-for-a-reset-mechanism) * [The need for a contributor check](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-3-reset-mechanism-rounds-and-a-more-conditional-kernel-reveal#the-need-for-a-contributor-check) * [Implementing the Reset Mechanism](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-3-reset-mechanism-rounds-and-a-more-conditional-kernel-reveal#implementing-the-reset-mechanism) * [Modifying hit() to track contributions](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-3-reset-mechanism-rounds-and-a-more-conditional-kernel-reveal#modifying-hit-to-track-contributions) * [Restricting look() with a contributor check](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-3-reset-mechanism-rounds-and-a-more-conditional-kernel-reveal#restricting-look-with-a-contributor-check) sun-brightdesktopmoon Copy // The current round number. uint256 round; // Event to log resets. event Reset(uint256 indexed newRound, uint256 shellStrength); function reset() public requireCracked { shellStrength = initialShellStrength; // Restore the shell strength. kernel = initialKernel; // Reset the kernel to its original value. round++; // Increment the round counter. emit Reset(round, shellStrength); // Log the reset action. } Copy // Mapping to track contributions: hitsPerRound[round][player] → number of hits. mapping(uint256 => mapping(address => uint256)) hitsPerRound; Copy function hit() public requireIntact { shellStrength--; // Decrease the shell strength. hitsPerRound[round][msg.sender]++; // Record the player's contribution for the current round. emit Hit(round, msg.sender, shellStrength); // Log the hit event. } Copy modifier onlyContributor() { require(hitsPerRound[round][msg.sender] > 0, "NOT_A_CONTRIBUTOR"); // Check if the caller contributed in the current round. _; } Copy // Look at the kernel if the shell is cracked and the caller contributed. function look() public view requireCracked onlyContributor returns (uint256) { return uint256(kernel); // Return the kernel value. } Copy // SPDX-License-Identifier: MIT License pragma solidity ^0.8.13; contract Walnut { uint256 initialShellStrength; // The initial shell strength for resets. uint256 shellStrength; // The current shell strength. uint256 round; // The current round number. suint256 initialKernel; // The initial hidden kernel value for resets. suint256 kernel; // The current hidden kernel value. // Tracks the number of hits per player per round. mapping(uint256 => mapping(address => uint256)) hitsPerRound; // Events to log hits, shakes, and resets. // Event to log hits. event Hit(uint256 indexed round, address indexed hitter, uint256 remaining); // Event to log shakes. event Shake(uint256 indexed round, address indexed shaker); // Event to log resets. event Reset(uint256 indexed newRound, uint256 shellStrength); constructor(uint256 _shellStrength, suint256 _kernel) { initialShellStrength = _shellStrength; // Set the initial shell strength. shellStrength = _shellStrength; // Initialize the shell strength. initialKernel = _kernel; // Set the initial kernel value. kernel = _kernel; // Initialize the kernel value. round = 1; // Start with the first round. } // Get the current shell strength. function getShellStrength() public view returns (uint256) { return shellStrength; } // Hit the Walnut to reduce its shell strength. function hit() public requireIntact { shellStrength--; // Decrease the shell strength. hitsPerRound[round][msg.sender]++; // Record the player's hit for the current round. emit Hit(round, msg.sender, shellStrength); // Log the hit. } // Shake the Walnut to increase the kernel value. function shake(suint256 _numShakes) public requireIntact { kernel += _numShakes; // Increment the kernel value. emit Shake(round, msg.sender); // Log the shake. } // Reset the Walnut for a new round. function reset() public requireCracked { shellStrength = initialShellStrength; // Reset the shell strength. kernel = initialKernel; // Reset the kernel value. round++; // Move to the next round. emit Reset(round, shellStrength); // Log the reset. } // Look at the kernel if the shell is cracked and the caller contributed. function look() public view requireCracked onlyContributor returns (uint256) { return uint256(kernel); // Return the kernel value. } // Set the kernel to a specific value. function set_number(suint _kernel) public { kernel = _kernel; } // Modifier to ensure the shell is fully cracked. modifier requireCracked() { require(shellStrength == 0, "SHELL_INTACT"); _; } // Modifier to ensure the shell is not cracked. modifier requireIntact() { require(shellStrength > 0, "SHELL_ALREADY_CRACKED"); _; } // Modifier to ensure the caller has contributed in the current round. modifier onlyContributor() { require(hitsPerRound[round][msg.sender] > 0, "NOT_A_CONTRIBUTOR"); _; } } sun-brightdesktopmoon --- # Deploying your contract | Seismic Docs In this chapter, you’ll deploy your Walnut contract to a local Seismic node for testing. By the end of this guide, you’ll have a fully deployed contract that you can interact with using your CLI or scripts. _Estimated Time: ~15 minutes._ ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/deploying-your-contract#writing-the-deploy-script) Writing the deploy script Navigate to the script folder in your Walnut App and open the `Walnut.s.sol` file located at: Copy packages/contracts/script and add the following to it: Copy // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; import {Script, console} from "forge-std/Script.sol"; import {Walnut} from "../src/Walnut.sol"; contract WalnutScript is Script { Walnut public walnut; function run() public { uint256 deployerPrivateKey = vm.envUint("PRIVKEY"); vm.startBroadcast(deployerPrivateKey); walnut = new Walnut(3, suint256(0)); vm.stopBroadcast(); } } This script will deploy a new instance of the Walnut contract with an initial shell strength of 3 and an initial kernel value of 0. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/deploying-your-contract#deploying-the-contract) Deploying the contract 1. In a separate terminal window, run in order to spin up a local Seismic node. 1. In `packages/contracts` , create a `.env` file and add the following to it: The `RPC_URL` denotes the port on which `sanvil` is running and the `PRIVKEY` is one of the nine standard `sanvil` testing private keys. 1. Now, from `packages/contracts`, run Your contract should be up and deployed to your local Seismic node! [PreviousChapter 4: Testing your Walnut contractchevron-left](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-4-testing-your-walnut-contract) [NextInteracting with the contract via a CLIchevron-right](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli) Last updated 11 months ago * [Writing the deploy script](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/deploying-your-contract#writing-the-deploy-script) * [Deploying the contract](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/deploying-your-contract#deploying-the-contract) sun-brightdesktopmoon Copy sanvil Copy RPC_URL=http://127.0.0.1:8545 PRIVKEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 Copy source .env sforge script script/Walnut.s.sol:WalnutScript \ --rpc-url $RPC_URL \ --broadcast sun-brightdesktopmoon --- # Interacting with the contract via a CLI | Seismic Docs In this section, you will write a CLI to interact with the deployed Walnut smart contract from scratch, simulating a multiplayer, multi-round game consisting of two players, Alice and Bob. At the end of this section, you will be able to see a full game play out on your local Seismic node! _Estimated time: ~30 minutes_ [PreviousDeploying your contractchevron-left](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/deploying-your-contract) [NextQuick primer: seismic-viemchevron-right](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/quick-primer-seismic-viem) Last updated 1 year ago sun-brightdesktopmoon sun-brightdesktopmoon --- # suint / sint | Seismic Docs All comparisons and operators for `suint` / `sint` are functionally identical to `uint` / `int`. The universal casting rules and restrictions described in [Basics](https://docs.seismic.systems/core/basics) apply. Copy suint256 a = suint256(10) suint256 b = suint256(3) // == EXAMPLES a > b // true a | b // 11 a << 2 // 40 a % b // 1 [PreviousBasicschevron-left](https://docs.seismic.systems/core/basics) [Nextsaddresschevron-right](https://docs.seismic.systems/core/basics/saddress) Last updated 1 year ago sun-brightdesktopmoon sun-brightdesktopmoon --- # Quick primer: seismic-viem | Seismic Docs Before proceeding to write the CLI, you need to be acquainted with some of the functions and utilities used to enable Seismic primitives (e.g. shielded reads, shielded writes etc.) through our client library, `seismic-viem` , which we will be using heavily to write the CLI. The detailed docs for `seismic-viem` can be found [herearrow-up-right](https://seismic-docs.netlify.app/) . _Estimated time: ~15 minutes_ ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/quick-primer-seismic-viem#shielded-wallet-client) Shielded wallet client The **shielded wallet client** is the shielded/Seismic counterpart of the **wallet client** in `viem` . It is used to enable extended functionality for interacting with shielded blockchain features, wallet operations, and encryption. It can be initialized using the `createShieldedWalletClient` function as follows: Copy const walletClient = await createShieldedWalletClient({ chain: seismicChain, transport: httpTransport, privateKey: '0xabcdef...', }) `createShieldedWalletClient` takes in the following parameters: 1. `chain` : a well-defined [Chainarrow-up-right](https://github.com/wevm/viem/blob/main/src/types/chain.ts) object 2. `transport` : the method of transport of interacting with the chain (`http` /`ws` along with the corresponding RPC URL) 3. `privateKey`: the private key to create the client for Once initialized, it can then be used to perform wallet operations or shielded-specific [actions.arrow-up-right](https://seismic-docs.netlify.app/seismic-viem/functions/createShieldedWalletClient) ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/quick-primer-seismic-viem#shielded-contract) Shielded contract A shielded contract instance provides an interface to interact with a shielded contract onchain. It has extended functionality for performing shielded write operations, signed reads, and contract interaction for a **specific contract** performed by a **specific wallet client** that it is initialized with. It can be initialized with the `getShieldedContract` as follows: Copy const contract = getShieldedContract({ abi: myContractAbi, address: '0x1234...', client: shieldedWalletClient, }) It takes in the following parameters: 1. `abi` : the ABI of the contract it is interacting with. 2. `address` : the address of the deployed contract it is interacting with. 3. `client` : the shielded wallet client that the interactions are to be performed by. This function extends the base `getContract` functionality by adding: * **Shielded write actions** for `nonpayable` and `payable` functions. * **Signed read actions** for `pure` and `view` functions. * Proxy-based access to dynamically invoke contract methods. We will extensively use **shielded writes (for** `**shake**` **) and shielded reads (for** `**look()**`**) in our CLI.** [PreviousInteracting with the contract via a CLIchevron-left](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli) [NextChapter 1: Defining the constants and utilitieschevron-right](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-1-defining-the-constants-and-utilities) Last updated 1 year ago * [Shielded wallet client](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/quick-primer-seismic-viem#shielded-wallet-client) * [Shielded contract](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/quick-primer-seismic-viem#shielded-contract) sun-brightdesktopmoon Copy // Perform a shielded write await contract.write.myFunction([arg1, arg2], { gas: 50000n }) // Perform a signed read const value = await contract.read.getValue() console.log('Value:', value) sun-brightdesktopmoon --- # Understanding the Walnut contract | Seismic Docs Imagine you’re holding a walnut, an unassuming object. Inside it lies a number, a secret **only revealed when you crack the shell**. There are primarily two actions you can take on this walnut: either **shaking** it or **hitting** it. **Shaking** the walnut some `n` number of times increments the number inside by `n`, while **hitting** the walnut brings it one step closer to the shell cracking. **You can only see the number inside if you have contributed to the cracking the shell, i.e., you have hit the walnut at least once.** This collaborative challenge is the heart of the Walnut App, and it’s all powered by the Walnut smart contract. Let’s dive into the inner workings of the contract and uncover how each part fuels this game. The contract can be found in the `packages/contracts/Walnut.sol` file of the starter repo. [hashtag](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#state-variables) State variables ---------------------------------------------------------------------------------------------------------------------------------- ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#startshell-and-shell) startShell and shell Think of the shell as the Walnut’s durability. `startShell` is the Walnut’s starting strength, and `shell` tracks how much of it remains as players hit it. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#startnumber-and-number) startNumber and number These are the secret numbers at the heart of the Walnut. `startNumber` initializes the hidden `number`, while `number` evolves as players shake the Walnut. Being `suint256` (shielded integers), these numbers remain encrypted on-chain—visible only to authorized participants. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#round) round A counter that increments with each new round/reset, ensuring every round has a fresh Walnut to crack. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#hitsperround) hitsPerRound A mapping that records every player’s contribution to the current round, ensuring only participants can peek at the Walnut’s secret. [hashtag](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#functions) Functions ---------------------------------------------------------------------------------------------------------------------- ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#hit) hit ( ) This function allows a player to hit the Walnut, reducing its durability and bringing it one step closer to cracking: **What happens:** * Checks if the shell is intact (`shell>0` ) * If it is, decrements `shell` by 1 * Increases the player who called `hit()` 's contribution in the current round (`hitsPerRound[round][playerAddress])` by 1 * Emits the `Hit` event to update all participants. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#shake-suint256-_numshakes) shake (suint256 \_numShakes) This function allows a player to shake the walnut `_numShakes` number of times. Since this is a **write** function that takes in an `stype` as one of its parameters, calling this function would constitute a **Seismic write.** **What happens:** * Adds `_numShakes` to `number` * Emits the `Shake` event. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#look) look ( ) This function allows contributors to the current round to view the `number` inside the walnut. Since this is a **view** function that **reveals an** `**stype**`**,** calling this function would constitute a **Seismic read.** **What happens:** * Requires the shell to be cracked (`requireCracked` modifier) * Ensures the function caller contributed to the cracking the walnut for this round (`onlyContributor` modifier) * Returns ("reveals") the `number` inside the walnut. [hashtag](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#modifiers) Modifiers ---------------------------------------------------------------------------------------------------------------------- Modifiers enforce the rules of the game: ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#requirecracked) requireCracked Ensures that `look()` can only be called if the Walnut’s shell is completely cracked. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#requireintact) requireIntact Ensures that `shake()` and `hit()` can only be called if the Walnut’s shell is intact. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#onlycontributor) onlyContributor Restricts access to `look()` , and hence the `number` being revealed, only to players who contributed **at least one hit in the current round.** [PreviousChapter 3: Bringing it all togetherchevron-left](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-3-bringing-it-all-together) [NextBasicschevron-right](https://docs.seismic.systems/core/basics) Last updated 11 months ago * [State variables](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#state-variables) * [startShell and shell](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#startshell-and-shell) * [startNumber and number](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#startnumber-and-number) * [round](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#round) * [hitsPerRound](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#hitsperround) * [Functions](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#functions) * [hit ( )](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#hit) * [shake (suint256 \_numShakes)](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#shake-suint256-_numshakes) * [look ( )](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#look) * [Modifiers](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#modifiers) * [requireCracked](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#requirecracked) * [requireIntact](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#requireintact) * [onlyContributor](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract#onlycontributor) sun-brightdesktopmoon sun-brightdesktopmoon --- # Clients | Seismic Docs ### [hashtag](https://docs.seismic.systems/core/clients#typescript) Typescript Seismic maintains [seismic-viemarrow-up-right](https://www.npmjs.com/package/seismic-viem) , which composes with [viemarrow-up-right](https://viem.sh/) to make calls to an RPC provider The documentation for seismic-viem can be found [herearrow-up-right](https://seismic-docs.netlify.app/seismic-react/globals) ### [hashtag](https://docs.seismic.systems/core/clients#rust) Rust Seismic maintains [seismic-alloyarrow-up-right](https://github.com/SeismicSystems/seismic-alloy) , which contains a crate called `seismic-alloy-provider` * Use `SeismicSignedProvider` to instantiate a client that can sign transactions (e.g. wallet client) * Use `SeismicUnsignedProvider` for a read-only client (e.g. public) [PreviousCollectionschevron-left](https://docs.seismic.systems/core/collections) [NextDifferences from Ethereumchevron-right](https://docs.seismic.systems/core/differences-from-ethereum) Last updated 3 months ago * [Typescript](https://docs.seismic.systems/core/clients#typescript) * [Rust](https://docs.seismic.systems/core/clients#rust) sun-brightdesktopmoon sun-brightdesktopmoon --- # Chapter 1: Defining the constants and utilities | Seismic Docs In this chapter, you will learn about defining and constants and utility functions which we will frequently use throughout the project. _Estimated time: ~10 minutes_ First, navigate to the root of the directory/monorepo and run `bun install` to install all the dependencies. Now, navigate to make a `lib` folder inside `packages/cli`with the files `constants.ts` and `utils.ts` and navigate to it: Copy mkdir -p packages/cli/lib touch packages/cli/lib/constants.ts packages/cli/lib/utils.ts cd packages/cli/lib `constants.ts` will contain the constants we use throughout the project with `utils.ts` will contain the necessary utility functions. Add the following to `constants.ts` : Copy import { join } from 'path' const CONTRACT_NAME = 'Walnut' const CONTRACT_DIR = join(__dirname, '../../contracts') export { CONTRACT_NAME, CONTRACT_DIR } This file centralizes key project constants: • `CONTRACT_NAME`: The Walnut contract name. • `CONTRACT_DIR`: Path to the contracts directory. Now, add the following to `utils.ts` : Copy import fs from 'fs' import { type ShieldedWalletClient, getShieldedContract } from 'seismic-viem' import { Abi, Address } from 'viem' async function getShieldedContractWithCheck( walletClient: ShieldedWalletClient, abi: Abi, address: Address ) { const contract = getShieldedContract({ abi: abi, address: address, client: walletClient, }) const code = await walletClient.getCode({ address: address, }) if (!code) { throw new Error('Please deploy contract before running this script.') } return contract } function readContractAddress(broadcastFile: string): `0x${string}` { const broadcast = JSON.parse(fs.readFileSync(broadcastFile, 'utf8')) if (!broadcast.transactions?.[0]?.contractAddress) { throw new Error('Invalid broadcast file format') } return broadcast.transactions[0].contractAddress } function readContractABI(abiFile: string): Abi { const abi = JSON.parse(fs.readFileSync(abiFile, 'utf8')) if (!abi.abi) { throw new Error('Invalid ABI file format') } return abi.abi } export { getShieldedContractWithCheck, readContractAddress, readContractABI } This file contains utility functions to interact with your Walnut contract: • `getShieldedContractWithCheck`: Ensures the contract is deployed and returns a shielded contract instance. • `readContractAddress`: Reads the deployed contract’s address from a broadcast file. • `readContractABI`: Parses the contract’s ABI from an ABI file for use in interactions. [PreviousQuick primer: seismic-viemchevron-left](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/quick-primer-seismic-viem) [NextChapter 2: Writing the core appchevron-right](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-2-writing-the-core-app) Last updated 1 year ago sun-brightdesktopmoon sun-brightdesktopmoon --- # Basics | Seismic Docs [hashtag](https://docs.seismic.systems/core/basics#mental-model) Mental model ---------------------------------------------------------------------------------- circle-info We assume familiarity with [Solidityarrow-up-right](https://soliditylang.org/) . Developers communicate to Seismic through the `stype`. A thorough understanding of this one concept unlocks all shielded computation and storage. The `stype` consists of three elementary types: * `**suint**` / `**sint**`: shielded integer * `**sbool**`: shielded boolean * `**saddress**`: shielded address The primary difference between them and their vanilla counterparts is that they're shielded. Any operations you apply to them are carried out as expected, but the values won't be visible to external observers. There are special considerations unique to each individual type. These are covered in the next three sections. For now, we'll develop a general understanding of `stype` that applies to all its component types. Here's the mental model you should have for shielded contracts. Whenever a tx is broadcasted by a user, it goes through the same submission, execution, and storage phases as a tx in a regular blockchain. The only difference is that when you look at the tx at these different stages- whether it's as a calldata payload during submission, a trace during execution, or as leaves in the MPT tree during storage- any bytes that represent `stype` variables are replaced with `0x000`. Let's step through a concrete example. We'll follow the lifecycle of a `transfer()` tx for an [`ERC20`arrow-up-right](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/) variant. This variant shields user balances and transfer amounts: Copy mapping(address => suint256) public balanceOf; // shielded balance function transfer(address to, suint256 amount) public { // shielded transfer amount balanceOf[msg.sender] -= amount; balanceOf[to] += amount; } ![](https://docs.seismic.systems/~gitbook/image?url=https%3A%2F%2F1987385627-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FhkB2uNxma1rxIgBfHgAT%252Fuploads%252Fhhi4uRKRMgunm8dh5Rkf%252F1.png%3Falt%3Dmedia%26token%3Df8402387-cf93-41cf-a186-5b5b6246a9da&width=768&dpr=3&quality=100&sign=1eaf721c&sv=2) Observers see 0x000 in place of stype variables during transaction submission, execution, and storage. Shielding user balances is done by changing the values of the `balanceOf` array to `suint256`. Shielding transfer amounts is done by changing the `amount` parameter in `transfer()` to `suint256`. Now we can see what happens at every stage of the tx lifecycle: 1. Submit. The tx is sitting in the mempool. You know that you're sending 12 tokens to your friend. Observers can look at the calldata and figure out that your friend is the recipient, but will see `0x000` instead of the number 12. 2. Execute. The tx is processed by a full node, and its trace is open. You know that 12 tokens were removed from your balance and 12 were added to your friend's. Observers know that the same number that was deducted from your balance was added to your friend's, but they see `0x000` instead of the number 12. 3. Store. The effects of the tx are applied to the state tree of all full nodes. You know that your new balance goes down by 12, to 200. You know that your friend's balance went up by 12, but you only see `0x000` for what its final state is. Observers know that your new balance is down the same amount that your friend's new balance is up, but they see `0x000` for both balances. circle-info Seismic currently shields a lot more than just the bytes representing `stype` variables, so the above model is more granular than you technically need to be. However, this will soon stop being the case. You should not fit your contracts to this temporary discrepancy. [hashtag](https://docs.seismic.systems/core/basics#casting) Casting ------------------------------------------------------------------------ You can cast `stype` variables to their unshielded counterparts, and vice-versa. Only explicit casting is allowed- no implicit. Note that whenever you do this, observers can look at the trace to figure out either the initial (if going from not `stype` to `stype`) or final (if going from `stype` to not `stype`) value. [hashtag](https://docs.seismic.systems/core/basics#restrictions) Restrictions ---------------------------------------------------------------------------------- There are two restrictions in how you can use `stype` variables: 1. You can't return them in `public` or `external` functions. This also means `stype` contract variables can't be `public`, since this automatically generates a getter. If you want to return one, you'll have to cast it into its unshielded counterpart. 1. You can't use them as constants. [PreviousUnderstanding the Walnut contractchevron-left](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract) [Nextsuint / sintchevron-right](https://docs.seismic.systems/core/basics/suint-sint) Last updated 27 days ago * [Mental model](https://docs.seismic.systems/core/basics#mental-model) * [Casting](https://docs.seismic.systems/core/basics#casting) * [Restrictions](https://docs.seismic.systems/core/basics#restrictions) sun-brightdesktopmoon Copy uint256 number = 100; suint256 sNumber = suint256(number); Copy /* * Throws a compiler error */ suint256 public v; // ========== /* * Throws a compiler error */ function f() external view returns (suint256) {} Copy /* * Throws a compiler error */ suint256 constant MY_CONSTANT = 42; sun-brightdesktopmoon --- # saddress | Seismic Docs An `saddress` variable has all `address` operations supported. As for members, it supports `call`, `delegatecall`, `staticcall`, `code`, and `codehash` _only_. You cannot have `saddress payable` or have `saddress` as a transaction signer. The universal casting rules and restrictions described in [Basics](https://docs.seismic.systems/core/basics) apply. Copy saddress a = saddress(0x123); saddress b = saddress(0x456); // == VALID EXAMPLES a == b // false b.call() // == INVALID EXAMPLES a.balance payable(a) [Previoussuint / sintchevron-left](https://docs.seismic.systems/core/basics/suint-sint) [Nextsboolchevron-right](https://docs.seismic.systems/core/basics/sbool) Last updated 10 months ago sun-brightdesktopmoon sun-brightdesktopmoon --- # Chapter 4: Testing your Walnut contract | Seismic Docs In this chapter, you’ll write tests to verify that the Walnut contract behaves as expected under various scenarios. Testing ensures the functionality, fairness, and access control mechanisms of your contract work seamlessly, particularly in multi-round gameplay. _Estimated Time: ~15 minutes._ ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-4-testing-your-walnut-contract#getting-started) Getting Started Navigate to the test folder in your Walnut App and open the `Walnut.t.sol` file located at: Copy packages/contracts/test/Walnut.t.sol This file is where you’ll write all the test cases for the Walnut contract. Start with the following base code: Copy // SPDX-License-Identifier: MIT License pragma solidity ^0.8.13; import {Test, console} from "forge-std/Test.sol"; import {Walnut} from "../src/Walnut.sol"; contract WalnutTest is Test { Walnut public walnut; function setUp() public { // Initialize a Walnut with shell strength = 2 and kernel = 0 walnut = new Walnut(2, suint256(0)); } } The `setUp()` function initializes the Walnut contract for use in all test cases. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-4-testing-your-walnut-contract#writing-test-cases) Writing Test Cases Start off with testing the basic functionalities, `hit` , `shake` , `look` and `reset` #### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-4-testing-your-walnut-contract#core-functionalities) Core functionalities 1. **Basic hit functionality** Ensures the Walnut’s shell can be cracked by `shellStrength` number of hits. 1. **Basic shake functionality** Validates that shaking the Walnut increments the kernel value. 1. **Reset functionality** Now, test for the restrictive/conditional nature of these basic functionalities. #### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-4-testing-your-walnut-contract#restricting-actions) Restricting Actions 1. **Preventing** `**hit**` **when shell is cracked** Ensures that hitting a cracked shell is not allowed. 1. **Preventing** `**shake**` **when shell is cracked** Ensures that shaking the Walnut after the shell is cracked is not allowed. 1. **Preventing** `**look**` **when shell is intact** Ensures that the kernel cannot be revealed unless the shell is fully cracked. 1. **Preventing** `**reset**` **when shell is intact** Validates that the Walnut cannot be reset unless the shell is fully cracked. Now, test for more complex scenarios. #### [hashtag](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-4-testing-your-walnut-contract#complex-scenarios) Complex scenarios 1. **Sequence of Multiple Actions** Ensures that the Walnut behaves correctly under a sequence of hits and shakes. 1. **Prevent Non-Contributors From Using** `**look()**` Ensures that only contributors in the current round can call `look()` . 1. **Contributor Tracking Across Rounds** Validates that contributions are tracked independently for each round. The test has one contributor hit both times and crack the shell in the first round, and a different contributor hit and crack the shell in the second round. We check for the fact the second round contributor cannot see the kernel after the first round and the first round contributor cannot see the kernel after the second. You can find the entire test file [herearrow-up-right](https://github.com/SeismicSystems/seismic-starter/blob/6251e663814ad9018441b15edc6a3a83fd9d38ce/packages/contracts/test/Walnut.t.sol#L1) . Test out the file by running the following inside the `packages/contracts` directory: The contract has been tested, time to deploy it! [PreviousChapter 3: Reset Mechanism, Rounds, and a more conditional Kernel Revealchevron-left](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-3-reset-mechanism-rounds-and-a-more-conditional-kernel-reveal) [NextDeploying your contractchevron-right](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/deploying-your-contract) Last updated 1 year ago * [Getting Started](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-4-testing-your-walnut-contract#getting-started) * [Writing Test Cases](https://docs.seismic.systems/onboarding/tutorial/writing-testing-and-deploying-the-contract/chapter-4-testing-your-walnut-contract#writing-test-cases) sun-brightdesktopmoon Copy function test_Hit() public { walnut.hit(); // Decrease shell strength by 1 walnut.hit(); // Fully crack the shell assertEq(walnut.look(), 0); // Kernel should still be 0 since no shakes } Copy function test_Shake() public { walnut.shake(suint256(10)); // Shake the Walnut, increasing the kernel walnut.hit(); // Decrease shell strength by 1 walnut.hit(); // Fully crack the shell assertEq(walnut.look(), 10); // Kernel should be 10 after 10 shakes } Copy function test_Reset() public { walnut.hit(); // Decrease shell strength by 1 walnut.shake(suint256(2)); // Shake the Walnut walnut.hit(); // Fully crack the shell walnut.reset(); // Reset the Walnut assertEq(walnut.getShellStrength(), 2); // Shell strength should reset to initial value walnut.hit(); // Start hitting again walnut.shake(suint256(5)); // Shake the Walnut again walnut.hit(); // Fully crack the shell again assertEq(walnut.look(), 5); // Kernel should reflect the shakes in the new round } Copy function test_CannotHitWhenCracked() public { walnut.hit(); // Decrease shell strength by 1 walnut.hit(); // Fully crack the shell vm.expectRevert("SHELL_ALREADY_CRACKED"); // Expect revert when hitting an already cracked shell walnut.hit(); } Copy function test_CannotShakeWhenCracked() public { walnut.hit(); // Decrease shell strength by 1 walnut.shake(suint256(1)); // Shake the Walnut walnut.hit(); // Fully crack the shell vm.expectRevert("SHELL_ALREADY_CRACKED"); // Expect revert when shaking an already cracked shell walnut.shake(suint256(1)); } Copy function test_CannotLookWhenIntact() public { walnut.hit(); // Partially crack the shell walnut.shake(suint256(1)); // Shake the Walnut vm.expectRevert("SHELL_INTACT"); // Expect revert when trying to look at the kernel with the shell intact walnut.look(); } Copy function test_CannotResetWhenIntact() public { walnut.hit(); // Partially crack the shell walnut.shake(suint256(1)); // Shake the Walnut vm.expectRevert("SHELL_INTACT"); // Expect revert when trying to reset without cracking the shell walnut.reset(); } Copy function test_ManyActions() public { uint256 shakes = 0; for (uint256 i = 0; i < 50; i++) { if (walnut.getShellStrength() > 0) { if (i % 25 == 0) { walnut.hit(); // Hit the shell every 25 iterations } else { uint256 numShakes = (i % 3) + 1; // Random shakes between 1 and 3 walnut.shake(suint256(numShakes)); shakes += numShakes; } } } assertEq(walnut.look(), shakes); // Kernel should match the total number of shakes } Copy function test_RevertWhen_NonContributorTriesToLook() public { address nonContributor = address(0xabcd); walnut.hit(); // Decrease shell strength by 1 walnut.shake(suint256(3)); // Shake the Walnut walnut.hit(); // Fully crack the shell vm.prank(nonContributor); // Impersonate a non-contributor vm.expectRevert("NOT_A_CONTRIBUTOR"); // Expect revert when non-contributor calls `look()` walnut.look(); } Copy function test_ContributorInRound2() public { address contributorRound2 = address(0xabcd); // Contributor for round 2 // Round 1: Cracked by address(this) walnut.hit(); // Hit 1 walnut.hit(); // Hit 2 assertEq(walnut.look(), 0); // Confirm kernel value walnut.reset(); // Start Round 2 // Round 2: ContributorRound2 cracks the Walnut vm.prank(contributorRound2); walnut.hit(); vm.prank(contributorRound2); walnut.shake(suint256(5)); // Shake kernel 5 times vm.prank(contributorRound2); walnut.hit(); vm.prank(contributorRound2); assertEq(walnut.look(), 5); // Kernel value is 5 for contributorRound2 vm.expectRevert("NOT_A_CONTRIBUTOR"); // address(this) cannot look in round 2 walnut.look(); } Copy sforge build sforge test sun-brightdesktopmoon --- # sbool | Seismic Docs All comparisons and operators for `sbool` function identically to `bool`. The universal casting rules and restrictions described in [Basics](https://docs.seismic.systems/core/basics) apply. We recommend reading the point on conditional execution in [Common mistakes](https://docs.seismic.systems/appendix/gotchas) prior to using `sbool` since it's easy to accidentally leak information with this type. Copy sbool a = sbool(true) sbool b = sbool(false) // == EXAMPLES a && b // false !b // true [Previoussaddresschevron-left](https://docs.seismic.systems/core/basics/saddress) [NextCollectionschevron-right](https://docs.seismic.systems/core/collections) Last updated 1 year ago sun-brightdesktopmoon sun-brightdesktopmoon --- # The Seismic Transaction | Seismic Docs [Tx Lifecyclechevron-right](https://docs.seismic.systems/core/seismic-transaction/tx-lifecycle) [Signed readschevron-right](https://docs.seismic.systems/core/seismic-transaction/signed-reads) [PreviousDifferences from Ethereumchevron-left](https://docs.seismic.systems/core/differences-from-ethereum) [NextTx Lifecyclechevron-right](https://docs.seismic.systems/core/seismic-transaction/tx-lifecycle) sun-brightdesktopmoon sun-brightdesktopmoon --- # Collections | Seismic Docs All `stype` variables can be stored in Solidity collections, much like their unshielded counterparts. They behave normally (as outlined in [Basics](https://docs.seismic.systems/core/basics) ) when used as values in these collections. It's when they're used as _both_ the keys and values where it gets interesting. This applies to arrays and maps in particular: Copy suint256[] a; // stype as value function f(suint256 idx) { a[idx] // stype as key // ... } // ========== mapping(saddress => suint256) m; // stype as key and value function d(suint256 k) { m[k] } What's special here is that you can hold on to `a[idx]` and `m[k]` without observers knowing which values in the collection they refer to. You can read from these references: Copy sbool b = a[idx] < 10; suint256 s = m[k] + 10; You can write to these references: Copy a[idx] *= 3; m[k] += a[idx]; Observers for any of these operations will not know which elements were read from / written to. ![](https://docs.seismic.systems/~gitbook/image?url=https%3A%2F%2F1987385627-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FhkB2uNxma1rxIgBfHgAT%252Fuploads%252F5OpcqyFqUvBLIIGsyhQj%252Ffigures.png%3Falt%3Dmedia%26token%3D947901e1-b763-49d4-b464-16379e328f24&width=768&dpr=3&quality=100&sign=8f2eaf03&sv=2) Using an `stype` as the key and value to a collection shields which element you're using. In the previous section, we only knew how to shield what was happening for certain elements. Now, we know how to shield which elements are being modified in the first place. We can take the ERC20 variant discussed in the [Basics](https://docs.seismic.systems/core/basics) section and extend it further to shielded balances, transfer amounts, _and now_ _recipients_. [Previoussboolchevron-left](https://docs.seismic.systems/core/basics/sbool) [NextClientschevron-right](https://docs.seismic.systems/core/clients) Last updated 1 year ago sun-brightdesktopmoon Copy mapping(saddress => suint256) public balanceOf; // key is now saddress function transfer(saddress to, suint256 amount) public { // recipient now saddress balanceOf[msg.sender] -= amount; balanceOf[to] += amount; } sun-brightdesktopmoon --- # Differences from Ethereum | Seismic Docs [hashtag](https://docs.seismic.systems/core/differences-from-ethereum#overview) Overview --------------------------------------------------------------------------------------------- The [Seismic EVMarrow-up-right](https://github.com/SeismicSystems/seismic-revm/blob/c29f4ea0681f09fb1e9998fa16568d4979c47ee3/README.md) is approximately a **superset of the EVM** ### [hashtag](https://docs.seismic.systems/core/differences-from-ethereum#whats-the-same) What's the same * Transaction construction and serialization identical to Ethereum (with one new transaction type) * Address generation, gas estimation, and signing work the same as Ethereum * [Almost all](https://docs.seismic.systems/core/differences-from-ethereum#rpc-compatibility) RPC methods are identical to reth * Standard Solidity bytecode will behave identically on Seismic * Seismic supports all of Ethereum's opcodes & precompiles * Transaction priority & fees follow EIP-1559 rules * Seismic will produce empty blocks when there are no pending transactions ### [hashtag](https://docs.seismic.systems/core/differences-from-ethereum#key-differences) Key differences * **Shielded storage**: Solidity contracts can store private data on-chain * **Runs in a TEE**: Seismic nodes must run in Trusted Execution Environments * **Seismic transaction:** We added a new transaction type that allows you to encrypt your calldata [hashtag](https://docs.seismic.systems/core/differences-from-ethereum#evm-compatibility) EVM Compatibility --------------------------------------------------------------------------------------------------------------- ### [hashtag](https://docs.seismic.systems/core/differences-from-ethereum#opcodes) Opcodes * `CLOAD` – load shielded data from storage * `CSTORE` – write shielded data to storage * `TIMESTAMP_MS` – get the block timestamp in milliseconds ### [hashtag](https://docs.seismic.systems/core/differences-from-ethereum#seismic-transaction) Seismic transaction The transaction with type `0x4a` allows users to encrypt their calldata. These otherwise work just like legacy transactions. We also support the other standard Ethereum transaction types (Legacy, EIP-1559, EIP-2930, EIP-4844, EIP-7702) ### [hashtag](https://docs.seismic.systems/core/differences-from-ethereum#precompiles) Precompiles All standard Ethereum precompiles are still available. Seismic added 6 new precompiles to our EVM: * **RNG:** `**0x64**` securely generate a random number * **ECDH** `**0x65**`: Elliptic Curve Diffie-Hellman, for generating a shared secret given a public key and secret key * **AES-GCM cryptography** * Encryption `**0x66**` * Decryption `**0x67**` * **HKDF** `**0x68**`: generate a cryptographic keys from a parent key * **Secp256k1** `**0x69**`: Sign a message given a secret key ### [hashtag](https://docs.seismic.systems/core/differences-from-ethereum#staking) Staking Seismic uses the same staking contract as Ethereum, which is hardcoded into our Genesis block at address `0x00000000219ab540356cbb839cbe05303d7705fa` ### [hashtag](https://docs.seismic.systems/core/differences-from-ethereum#block-times) Block times We will often produce multiple blocks in the same second, yet Ethereum's block timestamps are expressed in terms of unix seconds. Our solution to this: * Block headers and the EVM see timestamps in milliseconds * All RPC endpoints will format block timestamps in seconds for Ethereum compatibility (not ms) * In Seismic Solidity, `block.timestamp` returns unix seconds, just like in standard solidity. We added `block.timestamp_ms` which returns unix milliseconds ### [hashtag](https://docs.seismic.systems/core/differences-from-ethereum#rpc-compatibility) RPC compatibility We support almost every RPC endpoint in Reth, and have added a few more of our own These methods are in Reth, but will behave differently on Seismic: * Calls to tracing endpoints will remove shielded data from the trace * Calls to `getStorageAt` will fail if the requested storage slot holds shielded data [PreviousClientschevron-left](https://docs.seismic.systems/core/clients) [NextThe Seismic Transactionchevron-right](https://docs.seismic.systems/core/seismic-transaction) Last updated 3 months ago * [Overview](https://docs.seismic.systems/core/differences-from-ethereum#overview) * [What's the same](https://docs.seismic.systems/core/differences-from-ethereum#whats-the-same) * [Key differences](https://docs.seismic.systems/core/differences-from-ethereum#key-differences) * [EVM Compatibility](https://docs.seismic.systems/core/differences-from-ethereum#evm-compatibility) * [Opcodes](https://docs.seismic.systems/core/differences-from-ethereum#opcodes) * [Seismic transaction](https://docs.seismic.systems/core/differences-from-ethereum#seismic-transaction) * [Precompiles](https://docs.seismic.systems/core/differences-from-ethereum#precompiles) * [Staking](https://docs.seismic.systems/core/differences-from-ethereum#staking) * [Block times](https://docs.seismic.systems/core/differences-from-ethereum#block-times) * [RPC compatibility](https://docs.seismic.systems/core/differences-from-ethereum#rpc-compatibility) sun-brightdesktopmoon sun-brightdesktopmoon --- # Signed reads | Seismic Docs * The Seismic transaction has a counterpart, which we call “signed reads” * The motivation for a signed read is: in the EVM, users can make an `eth_call` and set the “from” field to any address they’d like to spoof * We want to give contract developers the ability to validate contract reads against msg.sender. For example, a user could implement an ERC20 token where only the owner can view their balance * To solve this, we do two things: (1) we zero out the “from” field when users make a vanilla `eth_call` and (2) we created the “signed read” to allow users to make a call with a specific `from` address * Signed reads are sent to Seismic's `eth_call` endpoint in the same way we would send a signed Seismic transaction to `eth_sendRawTransaction`. This can be either with a normal raw transaction, or an EIP-712 transaction * Signed reads must be a valid Seismic transaction (type `0x4a`). They cannot be made with any other transaction type * The response to a signed read will be encrypted to the encryption public key included in the transaction's Seismic elements. Therefore anyone who manages to intercept the response still cannot decrypt the response to the signed read. * Users can set the `signed_read` field in SeismicElements to `true`. We encourage this, and it is the default behaviour in our client implementations. The purpose of this is to prevent anyone who has managed to intercept this `eth_call` from sending that same payload to `eth_sendRawTransaction`, which would otherwise trigger a write transaction. When validating a transaction before it hits the pool, we check if the `signed_read` field is set to true; if it is, the transaction is rejected * This does not apply the other way around. Meaning, if `signed_read` is `false` (and the user wants to create a transaction), it can still be passed to `eth_call`. We think this validation is unnecessary because: * For an attacked to decrypt the response to a signed read, they’d need the user’s secret encryption key * The account's transaction nonce will increment right after their Seismic transaction is included in a block, after which the read will fail * This also allows `eth_estimateGas` to function properly; otherwise it would not pass validation on the `signed_read` field [PreviousTx Lifecyclechevron-left](https://docs.seismic.systems/core/seismic-transaction/tx-lifecycle) [NextLinks & Contactchevron-right](https://docs.seismic.systems/appendix/links-and-contact) Last updated 27 days ago sun-brightdesktopmoon sun-brightdesktopmoon --- # Chapter 2: Writing the core app | Seismic Docs In this chapter, you’ll write the core logic to interact with the Walnut contract by creating an App class. This class will initialize player-specific wallet clients and contracts, and provide easy-to-use functions like hit, shake, reset, and look. _Estimated time: ~20 minutes_ Now, navigate to `packages/cli/src/` and create a file called `app.ts` which will contain the core logic for the CLI: Copy # Assuming you are in packages/cli/lib cd ../src touch app.ts ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-2-writing-the-core-app#import-required-dependencies) Import required dependencies Start by importing all the necessary modules and functions at the top of `app.ts`: Copy import { type ShieldedContract, type ShieldedWalletClient, createShieldedWalletClient, getShieldedContract, } from 'seismic-viem' import { Abi, Address, Chain, http } from 'viem' import { privateKeyToAccount } from 'viem/accounts' import { getShieldedContractWithCheck } from '../lib/utils' ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-2-writing-the-core-app#define-the-app-configuration) Define the app configuration The `AppConfig` interface organizes all settings for the Walnut App, including player info, wallet setup, and contract details. It supports a multiplayer environment, with multiple players having distinct private keys and contract interactions. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-2-writing-the-core-app#create-the-app-class) Create the App class The `App` class manages player-specific wallet clients and contract instances, providing an easy-to-use interface for multiplayer gameplay. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-2-writing-the-core-app#add-initialization-logic-to-app) Add initialization logic to App The `init()`method sets up individual wallet clients and contract instances for each player, enabling multiplayer interactions. Each player gets their own wallet client and a direct connection to the contract. ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-2-writing-the-core-app#add-helper-methods-to-app) Add helper methods to App These helper methods ensure that the app fetches the correct wallet client or contract instance for a specific player, supporting multiplayer scenarios. `getWalletClient` : `getPlayerContract` : ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-2-writing-the-core-app#implement-contract-interaction-methods) Implement Contract Interaction Methods `reset` Resets the Walnut for the next round. The reset is player-specific and resets the shell and kernel values. `shake` Allows a player to shake the Walnut, incrementing the kernel. This supports multiplayer scenarios where each player’s shakes impact the Walnut. **Uses signed writes.** `hit` : A player can hit the Walnut to reduce the shell’s strength. Each hit is logged for the respective player. `look` : Reveals the kernel for a specific player if they contributed to cracking the shell. This ensures fairness in multiplayer gameplay. Uses **signed reads.** [PreviousChapter 1: Defining the constants and utilitieschevron-left](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-1-defining-the-constants-and-utilities) [NextChapter 3: Bringing it all togetherchevron-right](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-3-bringing-it-all-together) Last updated 1 year ago * [Import required dependencies](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-2-writing-the-core-app#import-required-dependencies) * [Define the app configuration](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-2-writing-the-core-app#define-the-app-configuration) * [Create the App class](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-2-writing-the-core-app#create-the-app-class) * [Add initialization logic to App](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-2-writing-the-core-app#add-initialization-logic-to-app) * [Add helper methods to App](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-2-writing-the-core-app#add-helper-methods-to-app) * [Implement Contract Interaction Methods](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-2-writing-the-core-app#implement-contract-interaction-methods) sun-brightdesktopmoon Copy interface AppConfig { players: Array<{ name: string // Name of the player privateKey: string // Private key for the player’s wallet }> wallet: { chain: Chain // Blockchain network (e.g., Seismic Devnet or Anvil) rpcUrl: string // RPC URL for blockchain communication } contract: { abi: Abi // The contract's ABI for interaction address: Address // The contract's deployed address } } Copy export class App { private config: AppConfig // Holds all app configuration private playerClients: Map = new Map() // Maps player names to their wallet clients private playerContracts: Map = new Map() // Maps player names to their contract instances constructor(config: AppConfig) { this.config = config } } Copy async init() { for (const player of this.config.players) { // Create a wallet client for the player const walletClient = await createShieldedWalletClient({ chain: this.config.wallet.chain, transport: http(this.config.wallet.rpcUrl), account: privateKeyToAccount(player.privateKey as `0x${string}`), }) this.playerClients.set(player.name, walletClient) // Map the client to the player // Initialize the player's contract instance and ensure the contract is deployed const contract = await getShieldedContractWithCheck( walletClient, this.config.contract.abi, this.config.contract.address ) this.playerContracts.set(player.name, contract) // Map the contract to the player } } Copy private getWalletClient(playerName: string): ShieldedWalletClient { const client = this.playerClients.get(playerName) if (!client) { throw new Error(`Wallet client for player ${playerName} not found`) } return client } Copy private getPlayerContract(playerName: string): ShieldedContract { const contract = this.playerContracts.get(playerName) if (!contract) { throw new Error(`Shielded contract for player ${playerName} not found`) } return contract } Copy async reset(playerName: string) { console.log(`- Player ${playerName} writing reset()`) const contract = this.getPlayerContract(playerName) const walletClient = this.getWalletClient(playerName) await walletClient.waitForTransactionReceipt({ hash: await contract.write.reset([], { gas: 100000n }) }) } Copy async shake(playerName: string, numShakes: number) { console.log(`- Player ${playerName} writing shake()`) const contract = this.getPlayerContract(playerName) const walletClient = this.getWalletClient(playerName) await contract.write.shake([numShakes], { gas: 50000n }) // signed write }) } Copy async hit(playerName: string) { console.log(`- Player ${playerName} writing hit()`) const contract = this.getPlayerContract(playerName) const walletClient = this.getWalletClient(playerName) await contract.write.hit([], { gas: 100000n }) } Copy async look(playerName: string) { console.log(`- Player ${playerName} reading look()`) const contract = this.getPlayerContract(playerName) const result = await contract.read.look() // signed read console.log(`- Player ${playerName} sees number:`, result) } sun-brightdesktopmoon --- # Chapter 3: Bringing it all together | Seismic Docs Now that we’ve built the core logic for interacting with the Walnut contract, it’s time to tie everything together into a CLI that runs a multiplayer game session with two players - **Alice and Bob.** In this chapter, you’ll set up the environment variables for multiple players and write `index.ts` to simulate gameplay. _Estimated time: ~20 minutes_ ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-3-bringing-it-all-together#set-up-environment-variables) Set Up Environment Variables Before running the Walnut game, we need to define environment variables that store important configurations such as the RPC URL, chain ID, and player private keys. Create a `.env` in `packages/cli` : Copy touch .env Open `.env` and paste the following: Copy CHAIN_ID=31337 RPC_URL=http://127.0.0.1:8545 ALICE_PRIVKEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 BOB_PRIVKEY=0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d **What’s Happening Here?** • `CHAIN_ID=31337` : `31337`is the default chain ID for `sanvil`(your local Seismic node). • `RPC_URL=http://127.0.0.1:8545` : This is the RPC URL for interacting with the local Seismic node. • `ALICE_PRIVKEY`and `BOB_PRIVKEY` : These are Alice and Bob’s private keys, allowing them to play the game. (These again are standard test keys provided by `sanvil`) ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-3-bringing-it-all-together#write-index.ts) Write index.ts Now, we’ll create the main entry point for our game session. This file will simulate gameplay, initializing players and having them interact with the Walnut contract. Open `packages/cli/src/index.ts`and follow these steps: #### [hashtag](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-3-bringing-it-all-together#import-dependencies) Import Dependencies Import the required libraries to read environment variables, define network configurations, and interact with the Walnut contract. #### [hashtag](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-3-bringing-it-all-together#define-the-main-function) Define the main() function This function initializes the contract and player wallets, then runs the game session. #### [hashtag](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-3-bringing-it-all-together#read-contract-details) Read Contract Details The contract’s ABI and deployed address are read from files generated during deployment. #### [hashtag](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-3-bringing-it-all-together#select-the-blockchain-network) Select the blockchain network Determine whether to use the local `sanvil`node (31337) or the Seismic devnet. #### [hashtag](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-3-bringing-it-all-together#define-players) Define players Assign Alice and Bob as players with private keys stored in `.env` . #### [hashtag](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-3-bringing-it-all-together#initialize-the-game-app) Initialize the Game App Create an `App` instance to interact with the Walnut contract. #### [hashtag](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-3-bringing-it-all-together#simulate-the-game-round-by-round) Simulate the game round by round The following logic executes two rounds of gameplay between Alice and Bob. **Round 1 - Alice Plays** **Round 2 - Bob Plays** **Alice Tries to Look in Round 2 (we expect this to fail since she has contributed in round 1 but not round 2)** ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-3-bringing-it-all-together#execute-the-main-function) Execute the main() function This ensures that the script runs when executed. The entire `index.ts` file can be found [herearrow-up-right](https://github.com/SeismicSystems/seismic-starter/blob/ameya/baby-walnut/packages/cli/src/index.ts) ### [hashtag](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-3-bringing-it-all-together#running-the-cli) Running the CLI Now, run the CLI from `packages/cli` by running: You should see something like this as the output: This output logs the events during two rounds of gameplay in the Walnut contract, showing interactions by Alice and Bob, along with a revert error when Alice attempts to call `look()`in Round 2. Congratulations! You've reached the end of the tutorial. You can find the code for the entire project [herearrow-up-right](https://github.com/SeismicSystems/seismic-starter/tree/ameya/baby-walnut) . [PreviousChapter 2: Writing the core appchevron-left](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-2-writing-the-core-app) [NextUnderstanding the Walnut contractchevron-right](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract) Last updated 11 months ago * [Set Up Environment Variables](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-3-bringing-it-all-together#set-up-environment-variables) * [Write index.ts](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-3-bringing-it-all-together#write-index.ts) * [Execute the main() function](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-3-bringing-it-all-together#execute-the-main-function) * [Running the CLI](https://docs.seismic.systems/onboarding/tutorial/interacting-with-the-contract-via-a-cli/chapter-3-bringing-it-all-together#running-the-cli) sun-brightdesktopmoon Copy import dotenv from 'dotenv' import { join } from 'path' import { seismicDevnet } from 'seismic-viem' import { anvil } from 'viem/chains' import { CONTRACT_DIR, CONTRACT_NAME } from '../lib/constants' import { readContractABI, readContractAddress } from '../lib/utils' import { App } from './app' // Load environment variables from .env file dotenv.config() Copy async function main() { if (!process.env.CHAIN_ID || !process.env.RPC_URL) { console.error('Please set your environment variables.') process.exit(1) } Copy const broadcastFile = join( CONTRACT_DIR, 'broadcast', `${CONTRACT_NAME}.s.sol`, process.env.CHAIN_ID, 'run-latest.json' ) const abiFile = join( CONTRACT_DIR, 'out', `${CONTRACT_NAME}.sol`, `${CONTRACT_NAME}.json` ) Copy const chain = process.env.CHAIN_ID === anvil.id.toString() ? anvil : seismicDevnet Copy const players = [\ { name: 'Alice', privateKey: process.env.ALICE_PRIVKEY! },\ { name: 'Bob', privateKey: process.env.BOB_PRIVKEY! },\ ] Copy const app = new App({ players, wallet: { chain, rpcUrl: process.env.RPC_URL!, }, contract: { abi: readContractABI(abiFile), address: readContractAddress(broadcastFile), }, }) await app.init() Copy console.log('=== Round 1 ===') await app.reset('Alice') await app.shake('Alice', 2) await app.hit('Alice') await app.shake('Alice', 4) await app.hit('Alice') await app.shake('Alice', 1) await app.hit('Alice') await app.look('Alice') Copy console.log('=== Round 2 ===') await app.reset('Bob') await app.hit('Bob') await app.shake('Bob', 1) await app.hit('Bob') await app.shake('Bob', 1) await app.hit('Bob') // Bob looks at the number in round 2 await app.look('Bob') Copy // Alice tries to look in round 2, should fail by reverting console.log('=== Testing Access Control ===') console.log("Attempting Alice's look() in Bob's round (should revert)") try { await app.look('Alice') console.error('❌ Expected look() to revert but it succeeded') process.exit(1) } catch (error) { console.log('✅ Received expected revert') } } Copy main() Copy bun dev Copy === Round 1 === - Player Alice writing shake() - Player Alice writing hit() - Player Alice writing shake() - Player Alice writing hit() - Player Alice writing shake() - Player Alice writing hit() - Player Alice reading look() - Player Alice sees number: 7n === Round 2 === - Player Bob writing reset() - Player Bob writing hit() - Player Bob writing shake() - Player Bob writing hit() - Player Bob writing shake() - Player Bob writing hit() - Player Bob reading look() - Player Bob sees number: 3n === Testing Access Control === - Attempting Alice's look() in Bob's round (should revert) ✅ Received expected revert sun-brightdesktopmoon --- # Deploy tools | Seismic Docs You can find our deploy tools [herearrow-up-right](https://github.com/SeismicSystems/deploy) Documentation for these tools will be published here soon [PreviousNode Operator FAQchevron-left](https://docs.seismic.systems/appendix/node-operator-faq) Last updated 3 months ago sun-brightdesktopmoon sun-brightdesktopmoon --- # Tx Lifecycle | Seismic Docs ![](https://docs.seismic.systems/~gitbook/image?url=https%3A%2F%2F1987385627-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FhkB2uNxma1rxIgBfHgAT%252Fuploads%252FFGDQ9UsibF3Xa14ZM8D4%252Fimage.png%3Falt%3Dmedia%26token%3D2e79f18c-f5c2-4b7d-9eba-1adcac0f2d67&width=768&dpr=3&quality=100&sign=5658aa04&sv=2) ### [hashtag](https://docs.seismic.systems/core/seismic-transaction/tx-lifecycle#key-management) Key management * The network manages its keys through the [`seismic-enclave-server`arrow-up-right](https://github.com/SeismicSystems/enclave/tree/seismic/crates/enclave-server) crate. Reth (and Summit) can make RPC calls to this server. One such call is to get the network keys * Enclave can boot in either `--genesis-node` or `--peers ` mode. The former generates its own root key and shares it with peers after they pass validation. The latter loops through its peer IPs until it receives the root key from one of them * Enclave then derives a few different keys from that root key. Most importantly, it derives the encryption secret key. This is the key used to decrypt Seismic transaction calldata * When [`seismic-reth`arrow-up-right](https://github.com/SeismicSystems/seismic-reth/tree/seismic/bin/seismic-reth) boots, it requests the derived keys from the enclave and keeps them in memory * We exposed a new RPC method, `seismic_getTeePublicKey`. Its response is the public key of the aforementioned secret key that decrypts Seismic transactions. Calling this endpoint is the first step that a client takes to build a Seismic transaction * Clients also generate their own secret key, which can be either ephemeral (default) or long-lived, if they prefer to manage this themselves * Their secret key and the network public key combine to create an AES key, which is used to encrypt calldata ### [hashtag](https://docs.seismic.systems/core/seismic-transaction/tx-lifecycle#encryption-and-metadata) Encryption & Metadata * The client will include their encryption public key in the transaction, along with four other parameters to tighten the security of encryption. These are: * a 12-byte `encryptionNonce` * `recentBlockHash`, which must be within 100 blocks of the latest block * an `expiresAtBlock` number, after which this transaction is invalid * optionally, a boolean `signedRead`. If set, it only allows the transaction to be used for signed reads. Otherwise, it will be rejected by transaction pool validation * There is one other field in Seismic transaction metadata: an integer called `messageVersion`. This field is a hack to allow browser extension wallets (e.g. MetaMask) to support the Seismic transaction type. Message version 0, the default, means a standard Seismic transaction as described above. Message version 2 corresponds to a transaction sent as EIP-712 typed data, which browser extension wallets can sign. There is no message version 1, but we reserved this for implementing Seismic transactions via `eth_personalSign` * These six Seismic-specific fields are called `SeismicElements`: the client encryption public key, the four security fields above, and the message version. They are combined with the EOA address (`sender`), `chainId`, `nonce`, `to` address, and `value`. The full set of 11 fields is referred to as the Seismic transaction metadata (`TxSeismicMetadata`) in [`seismic-alloy-consensus`arrow-up-right](https://github.com/SeismicSystems/seismic-alloy/tree/seismic/crates/consensus) * To encrypt calldata, we use AES with AEAD. The AEAD is an RLP encoding of the `TxSeismicMetadata`. The nonce for this encryption is the same 12-byte encryption nonce as we included in the metadata * The encrypted calldata is then passed to a Seismic transaction in the data/input field. Seismic transactions work just like Legacy Ethereum transactions, except: * they have a tx type of `74` or `0x4a` * they have these `SeismicElements` attached as well ### [hashtag](https://docs.seismic.systems/core/seismic-transaction/tx-lifecycle#decryption) Decryption * Transactions sent with type `0x4a` but incomplete Seismic elements are rejected from the tx pool, as are transactions not marked as `0x4a` but do contain Seismic elements * Nodes will decrypt Seismic transactions by: * decoding the transaction * recovering the signer * assembling the metadata * encoding it as AEAD via RLP * generating the AES key by combining the network's secret key with the transaction's encryption public key * If transaction decryption fails, the transaction is removed from the transaction pool * If it succeeds, it passes to the revm transaction environment _as plaintext_ * Calls to get transaction information after they have landed on chain should return input as the encrypted calldata, and not the plaintext * A note on calldata encoding: s-types are encoded the same way as their public analogues. The consequence is an interesting artifact of the Seismic protocol (and maybe a security concern): Solidity has no clue whether functions are called with Seismic transactions or not. As a result, it's totally allowed to alter shielded state with vanilla Ethereum transactions. It's also allowed to do the reverse, by altering public state with Seismic transactions ### [hashtag](https://docs.seismic.systems/core/seismic-transaction/tx-lifecycle#shielded-storage) Shielded storage * Inside Solidity, we've defined two new opcodes: `CLOAD` and `CSTORE`. These are the shielded analogues to `SLOAD` and `SSTORE`. We use `CLOAD`/`CSTORE` when the underlying type is an s-type. * Importantly, we maintain only one state tree, as you can see in [`seismic-trie`arrow-up-right](https://github.com/SeismicSystems/seismic-trie/) (a fork of alloy-trie). We modified the state tree by adding an extra boolean flag, `is_private`, to leaves. This is wrapped inside the struct called `FlaggedStorage`, which replaces `StorageValue` (a plain `U256`). We use this flag to validate `CLOAD`/`CSTORE` calls, and to know whether we can expose this piece of storage, via e.g. `eth_getStorageAt` * When we see a `CLOAD` opcode inside [`seismic-revm`arrow-up-right](https://github.com/SeismicSystems/seismic-revm) , we load the storage slot and validate that it either has `is_private` set to `true` or is an uninitialized slot. For `CSTORE`, we write the storage value with `is_private = true`. We throw errors when trying to `CLOAD`/`CSTORE` a `FlaggedStorage` that has `is_private = false` (“Invalid public storage access”). Similarly, we throw errors when trying to `SLOAD`/`SSTORE` on `FlaggedStorage` that has `is_private = true` (“Invalid private storage access”). These errors are thrown inside `seismic-revm`. * Unlike SSTORE/SLOAD, the gas cost of CLOAD/CSTORE does not change based on the length of the word stored. This is to prevent attackers from deducing information about shielded storage values ### [hashtag](https://docs.seismic.systems/core/seismic-transaction/tx-lifecycle#notes) Notes * Outside of `SeismicElements` and the encrypted calldata, Seismic transactions have the same fields as legacy transactions. In particular, it uses the same gas parameters: `gasPrice` and `gasLimit` * Seismic transactions cannot be used to deploy bytecode via `Create` calls. Instead, we only allow Seismic transactions to be sent to a specific address. We did this to make metadata validation easier, and we can’t see a good reason to deploy encrypted bytecode [PreviousThe Seismic Transactionchevron-left](https://docs.seismic.systems/core/seismic-transaction) [NextSigned readschevron-right](https://docs.seismic.systems/core/seismic-transaction/signed-reads) Last updated 11 days ago * [Key management](https://docs.seismic.systems/core/seismic-transaction/tx-lifecycle#key-management) * [Encryption & Metadata](https://docs.seismic.systems/core/seismic-transaction/tx-lifecycle#encryption-and-metadata) * [Decryption](https://docs.seismic.systems/core/seismic-transaction/tx-lifecycle#decryption) * [Shielded storage](https://docs.seismic.systems/core/seismic-transaction/tx-lifecycle#shielded-storage) * [Notes](https://docs.seismic.systems/core/seismic-transaction/tx-lifecycle#notes) sun-brightdesktopmoon sun-brightdesktopmoon --- # Links & Contact | Seismic Docs ### [hashtag](https://docs.seismic.systems/appendix/links-and-contact#official-channels) Official channels * [X.com/SeismicSysarrow-up-right](https://x.com/SeismicSys) * Join our [Discordarrow-up-right](https://discord.gg/XSPNseXCvW) * [Websitearrow-up-right](https://seismic.systems/) * [GitHub Organizationarrow-up-right](https://github.com/SeismicSystems) ### [hashtag](https://docs.seismic.systems/appendix/links-and-contact#links) Links * Seismic [Status hubarrow-up-right](https://status.seismicdev.net/) * [seismic clientarrow-up-right](https://client.seismic.systems/) documentation * Seismic solidity extensions * [in the VSCode Marketplacearrow-up-right](https://marketplace.visualstudio.com/items?itemName=SeismicSys.seismic) * [in Open VSXarrow-up-right](https://open-vsx.org/extension/SeismicSys/seismic) ### [hashtag](https://docs.seismic.systems/appendix/links-and-contact#contact) Contact For partnerships, contact L@, T@ or M@ seismic (dot) systems If you would like to work at Seismic, email your resume to M@ [PreviousSigned readschevron-left](https://docs.seismic.systems/core/seismic-transaction/signed-reads) [NextCodebaseschevron-right](https://docs.seismic.systems/appendix/codebases) Last updated 3 months ago * [Official channels](https://docs.seismic.systems/appendix/links-and-contact#official-channels) * [Links](https://docs.seismic.systems/appendix/links-and-contact#links) * [Contact](https://docs.seismic.systems/appendix/links-and-contact#contact) sun-brightdesktopmoon sun-brightdesktopmoon --- # Testnet | Seismic Docs Property Value Name Seismic Testnet Chain ID 5124 (0x1404) Chain type EVM L1 RPC (HTTP) `https://gcp-2.seismictest.net/rpc` RPC (WS) `wss://gcp-2.seismictest.net/ws` Block time ~600ms Finality 1 block Explorer [https://seismic-testnet.socialscan.io/arrow-up-right](https://seismic-testnet.socialscan.io/) Faucet [https://faucet.seismictest.net/arrow-up-right](https://faucet.seismictest.net/) Please don't hesitate to reach out to `[[email protected]](https://docs.seismic.systems/cdn-cgi/l/email-protection) ` for direct support from the team. [PreviousDevnetchevron-left](https://docs.seismic.systems/appendix/devnet) [NextMainnetchevron-right](https://docs.seismic.systems/appendix/mainnet) Last updated 5 days ago sun-brightdesktopmoon sun-brightdesktopmoon --- # Mainnet | Seismic Docs ### [hashtag](https://docs.seismic.systems/appendix/mainnet#network-configuration) Network Configuration Property Value Name Seismic Chain ID 5123 (0x1403) Chain type EVM L1 RPC (HTTP) TBA RPC (WS) TBA Block time 1 block per ~600ms Finality 1 block (may become 2 blocks) ### [hashtag](https://docs.seismic.systems/appendix/mainnet#genesis-date) Genesis date The mainnet genesis date will be announced publicly. Follow official channels for updates: ### [hashtag](https://docs.seismic.systems/appendix/mainnet#explorer) Explorer Currently in development #### [hashtag](https://docs.seismic.systems/appendix/mainnet#contract-verification) Contract verification The explorer will support the ability to verify contracts written in Seismic Solidity [PreviousTestnetchevron-left](https://docs.seismic.systems/appendix/testnet) [NextNode Operator FAQchevron-right](https://docs.seismic.systems/appendix/node-operator-faq) Last updated 3 months ago * [Network Configuration](https://docs.seismic.systems/appendix/mainnet#network-configuration) * [Genesis date](https://docs.seismic.systems/appendix/mainnet#genesis-date) * [Explorer](https://docs.seismic.systems/appendix/mainnet#explorer) sun-brightdesktopmoon sun-brightdesktopmoon --- # Node Operator FAQ | Seismic Docs ### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#general) General #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#seismic-nodes-have-to-run-inside-a-tee.-why-and-what-does-that-mean-for-node-operators) Seismic nodes have to run inside a TEE. Why? and what does that mean for node operators? Seismic nodes run inside TEEs so we can verify that they are running the correct software via remote attestation. If someone were to deploy a node that allowed them to view network secrets, it would be rejected by other nodes, and therefore never receive any sensitive data. As a result, all node operators have to be running the exact same versions of the code, including reth parameters. If you are an RPC provider partnering with us, and need nodes to run with specific settings, please contact our team – we'll see how we can help. While we have nothing in place to support this now, we can prioritize features to make it easier for you to run your business #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#is-seismic-a-zk-chain) Is Seismic a ZK Chain? No. Seismic uses trusted execution environments (TEE) via Intel TDX for privacy, not zero-knowledge proofs. #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#does-seismic-support-light-nodes-full-nodes-or-archival-nodes) Does Seismic support light nodes, full nodes or archival nodes? Seismic currently supports archival nodes only #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#how-fast-does-storage-grow) How fast does storage grow? * **Current size**: TBD (network has not yet launched) * **Archive node**: 1TB+ storage recommended initially * **Growth rate**: Will depend on network activity; approximately 12 hours of sync time expected for first year of operation Detailed storage projections will be published after mainnet launch #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#how-do-i-run-a-node) How do I run a node? There are instructions to deploy a node in our [deployarrow-up-right](https://github.com/SeismicSystems/deploy) repo. There are two steps: 1. Build (optional): you can build the image yourself using our Python scripts in the deploy repo. Alternatively we will be hosting images that we've built, along with the measurements generated. When we do this, you can download the image from the releases page of that repo. The basic command is: `python3 -m yocto.cli --build --logs` 2. Deploy: once you have an image, you can deploy it to Azure using our Python tooling. The basic command is: `python3 -m yocto.genesis_deploy -a 20251017221200 -n 1` Soon we will publish more detailed documentation on our Python tooling, which will allow you to customize the deploy ### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#hardware-requirements) Hardware requirements #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#cloud-hosting) Cloud hosting Seismic uses Azure's Confidential Computing with Intel TDX to run our nodes. We are also planning to support bare metal TDX as well #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#recommended-specs) Recommended specs * CPU: 4+ vCPUs * Memory: 16+GB RAM * Storage: 1TB * Azure Confidential virtual machines (TDX) with secure boot & TPM enabled * Example instance: EC4es v5 * Security: Confidential VM with secure boot and vTPM (NonPersistedTPM) * SKU: `standard_lrs` with `ConfidentialVM_NonPersistedTPM` security type ### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#rpc) RPC #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#are-there-rate-limits-on-rpc-calls) Are there rate limits on RPC calls? No rate limits are currently imposed by the protocol itself, though node operators may implement their own. #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#is-there-an-rpc-parameter-to-set-the-maximum-fee-cap) Is there an RPC parameter to set the maximum fee cap? Yes, `--rpc.txfeecap`. We use reth's default, which is 1.0 units of the native token (e.g. 1.0 ETH on testnet) #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#is-there-a-maximum-payload-size-for-rpc-requests) Is there a maximum payload size for RPC requests? Yes, this is controlled through the arg `--rpc.max-response-size`. We use reth's default, which is 160MB #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#is-there-a-limit-on-the-batch-count-for-rpc-requests) Is there a limit on the batch count for RPC requests? No. Just like in reth, there's no limit on batch count. The only limit comes from total payload size (above) #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#what-is-the-maximum-size-for-eth_getlogs-responses) What is the maximum size for `eth_getLogs` responses? This is the same as reth's maximum payload size for general RPC requests: 160MB #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#does-seismic-support-log-look-back) Does Seismic support log look back? Yes, archival nodes support complete log look back and retrieval of contract events from the beginning of the chain #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#what-sync-mode-should-i-use-for-fetching-logs) What sync mode should I use for fetching logs? We only support archival nodes. Make RPC calls to them with block filters #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#what-are-the-heaviest-rpc-methods) What are the heaviest RPC methods? The most resource-intensive RPC methods are: * `**eth_getLogs**` with large block ranges or many matching events * **Tracing calls** (e.g., `debug_traceTransaction`, `trace_*` methods) with complex geth tracers #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#are-block-height-indicators-available) Are block height indicators available? Yes, use `eth_blockNumber` to check current block height and sync progress #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#are-there-recommended-caching-rules-for-rpc-methods) Are there recommended caching rules for RPC methods? We haven't thought about this yet ### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#operations) Operations #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#how-often-are-hard-forks-expected) How often are hard forks expected? No hard forks have occurred yet (network is pre-mainnet). The frequency of future hard forks is TBD, but all upgrades will be communicated via Twitter, Discord, and direct partner outreach All changes will be deployed to testnet before mainnet #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#does-the-node-handle-sigterm-gracefully) Does the node handle SIGTERM gracefully? Individual processes do support this. However because the node has to run inside a TEE, the correct way to restart a node is to reboot the machine. Relevant processes will automatically spawn on boot **Expected restart time**: About 1 minute from machine reboot #### [hashtag](https://docs.seismic.systems/appendix/node-operator-faq#have-there-been-any-major-outages) Have there been any major outages? Mainnet has not launched yet, so no. In testnet, various incidents have occurred, but these have been resolved prior to public release [PreviousMainnetchevron-left](https://docs.seismic.systems/appendix/mainnet) [NextDeploy toolschevron-right](https://docs.seismic.systems/appendix/deploy-tools) Last updated 3 months ago * [General](https://docs.seismic.systems/appendix/node-operator-faq#general) * [Hardware requirements](https://docs.seismic.systems/appendix/node-operator-faq#hardware-requirements) * [RPC](https://docs.seismic.systems/appendix/node-operator-faq#rpc) * [Operations](https://docs.seismic.systems/appendix/node-operator-faq#operations) sun-brightdesktopmoon sun-brightdesktopmoon --- # Codebases | Seismic Docs [hashtag](https://docs.seismic.systems/appendix/codebases#summit) [Summitarrow-up-right](https://github.com/SeismicSystems/summit) ---------------------------------------------------------------------------------------------------------------------------------------- Our consensus client. Built on top of [Commonware'sarrow-up-right](https://commonware.xyz/) [primitivesarrow-up-right](https://github.com/commonwarexyz/monorepo) [hashtag](https://docs.seismic.systems/appendix/codebases#seismic-solidity) [Seismic Solidityarrow-up-right](https://github.com/SeismicSystems/seismic-solidity) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- Our fork of [Solidityarrow-up-right](https://soliditylang.org/) . We added a set of types & opcodes for shielded computation [hashtag](https://docs.seismic.systems/appendix/codebases#enclave) [Enclavearrow-up-right](https://github.com/SeismicSystems/enclave) ------------------------------------------------------------------------------------------------------------------------------------------- Codebase for encryption, TEE & on-chain verification [hashtag](https://docs.seismic.systems/appendix/codebases#execution-layer) Execution layer ----------------------------------------------------------------------------------------------- Most of the repositories here are forks of the reth stack ### [hashtag](https://docs.seismic.systems/appendix/codebases#alloy) **Alloy** #### [hashtag](https://docs.seismic.systems/appendix/codebases#seismic-alloy-core) [Seismic Alloy Corearrow-up-right](https://github.com/SeismicSystems/seismic-alloy-core) fork of [alloy-rs/corearrow-up-right](https://github.com/alloy-rs/core) * This is the repo that depends on nothing else * Upstream: version 1.1.2, commit [`e55993f`arrow-up-right](https://github.com/alloy-rs/core/tree/e55993f69d91f36fdb501d54e11a8265f90e42c1) #### [hashtag](https://docs.seismic.systems/appendix/codebases#seismic-alloy) [Seismic Alloyarrow-up-right](https://github.com/SeismicSystems/seismic-alloy) Analogous to [alloy-rs/op-alloyarrow-up-right](https://github.com/alloy-rs/op-alloy) , but not a fork of it * Depends on: * seismic-alloy-core * alloy-rs/alloy #### [hashtag](https://docs.seismic.systems/appendix/codebases#seismic-trie) [Seismic Triearrow-up-right](https://github.com/SeismicSystems/seismic-trie) fork of [alloy-rs/triearrow-up-right](https://github.com/alloy-rs/trie) * Depends on seismic-alloy-core * Upstream: version 0.8.1, commit [`a098d3f`arrow-up-right](https://github.com/alloy-rs/trie/commit/a098d3f6b212dc8e44a2d4886be9c0f6b2ec63e9) ### [hashtag](https://docs.seismic.systems/appendix/codebases#revm) **REVM** #### [hashtag](https://docs.seismic.systems/appendix/codebases#seismic-revm) [Seismic REVMarrow-up-right](https://github.com/SeismicSystem/seismic-revm) fork of [bluealloy/revmarrow-up-right](https://github.com/bluealloy/revm) * Depends on: * seismic-alloy-core * seismic-enclave * Upstream: version 23.1.0, commit [`b287ce02`arrow-up-right](https://github.com/bluealloy/revm/commit/b287ce025565c6f9206d5959c08acc401c8be5d4) #### [hashtag](https://docs.seismic.systems/appendix/codebases#seismic-evm) [Seismic EVMarrow-up-right](https://github.com/SeismicSystems/seismic-evm) fork of [alloy-rs/evmarrow-up-right](https://github.com/alloy-rs/evm) * Depends on: * alloy-rs/alloy * seismic-alloy * seismic-alloy-core * seismic-revm * Upstream: version 0.9.1, commit [`1c4f35c`arrow-up-right](https://github.com/alloy-rs/evm/commit/1c4f35ca45a4d32ec6929be0943ff59618fe8088) #### [hashtag](https://docs.seismic.systems/appendix/codebases#seismic-revm-inspectors) [Seismic REVM Inspectorsarrow-up-right](https://github.com/SeismicSystems/seismic-revm-inspectors) fork of [paradigmxyz/revm-inspectorsarrow-up-right](https://github.com/paradigmxyz/revm-inspectors) * Depends on: * seismic-alloy-core * alloy-rs/alloy * seismic-revm * Upstream: version 0.22.3, commit [`dd283db`arrow-up-right](https://github.com/paradigmxyz/revm-inspectors/commit/dd283dbeb19fd94a8e6de60ef9acfaad042f4b94) ### [hashtag](https://docs.seismic.systems/appendix/codebases#reth) [Retharrow-up-right](https://github.com/SeismicSystems/seismic-reth) fork of [paradigmxyz/retharrow-up-right](https://github.com/paradigmxyz/reth) * Depends on: * seismic-alloy-core * seismic-alloy * alloy-rs/alloy * alloy-trie * seismic-revm * seismic-evm * seismic-revm-inspectors * Upstream: version 1.2.1, commit [`3c0b3df8`arrow-up-right](https://github.com/foundry-rs/foundry/commit/3c0b3df8f8ef8800a10912ce5a9dcd9eb7e971ff) ### [hashtag](https://docs.seismic.systems/appendix/codebases#foundry) **Foundry** #### [hashtag](https://docs.seismic.systems/appendix/codebases#seismic-compilers) [Seismic Compilersarrow-up-right](https://github.com/SeismicSystems/seismic-compilers) fork of [foundry-rs/compilersarrow-up-right](https://github.com/foundry-rs/compilers) * Depends on: * seismic-alloy-core * Upstream: version 0.16.1, commit [`ec745cec`arrow-up-right](https://github.com/foundry-rs/compilers/commit/ec745cecb9c19e67140704bcb359928851ca48c5) #### [hashtag](https://docs.seismic.systems/appendix/codebases#seismic-foundry-fork-db) [Seismic Foundry Fork DBarrow-up-right](https://github.com/SeismicSystems/seismic-foundry-fork-db) fork of [foundry-rs/foundry-fork-dbarrow-up-right](https://github.com/foundry-rs/foundry-fork-db) * Depends on: * seismic-alloy-core * alloy-rs/alloy * seismic-revm * seismic-alloy (only for seismic-prelude) * Upstream: version 0.14.0, commit [`0fe2b2a`arrow-up-right](https://github.com/foundry-rs/foundry-fork-db/commit/0fe2b2a0bb7059ed44d8401ed3c9d0b9891a87c2) #### [hashtag](https://docs.seismic.systems/appendix/codebases#seismic-foundry) [Seismic Foundryarrow-up-right](https://github.com/SeismicSystems/seismic-foundry) fork of [foundry-rs/foundryarrow-up-right](https://github.com/foundry-rs/foundry) * Depends on: * seismic-alloy-core * seismic-alloy * alloy-rs/alloy * alloy-trie * seismic-revm * seismic-evm * seismic-revm-inspectors * seismic-foundry-fork-db * Upstream: version 1.2.1, commit [`b76d4f66`arrow-up-right](https://github.com/SeismicSystems/seismic-reth/commit/b76d4f66179243f6108ee9b1eed231cc854ad924) [hashtag](https://docs.seismic.systems/appendix/codebases#seismic-client) [Seismic Clientarrow-up-right](https://github.com/SeismicSystems/seismic-client) ---------------------------------------------------------------------------------------------------------------------------------------------------------------- A library for building web applications on Seismic. This repo provides two packages that compose with the viem/wagmi stack to interact with the Seismic network: * seismic-viem: composes with [viemarrow-up-right](https://viem.sh/) * seismic-react: composes with [wagmiarrow-up-right](https://wagmi.sh/) [hashtag](https://docs.seismic.systems/appendix/codebases#deployment) Deployment ------------------------------------------------------------------------------------- ### [hashtag](https://docs.seismic.systems/appendix/codebases#deploy) [Deployarrow-up-right](https://github.com/SeismicSystems/deploy) A repository containing tools to deploy infrastructure ### [hashtag](https://docs.seismic.systems/appendix/codebases#yocto-build-system) Yocto build system Seismic forked Flashbots' stack for reproducible TEE builds. This includes these repos: #### [hashtag](https://docs.seismic.systems/appendix/codebases#meta-seismic) [Meta Seismicarrow-up-right](https://github.com/SeismicSystems/meta-seismic) A Yocto layer that configures how the image runs Summit, Reth & the enclave server #### [hashtag](https://docs.seismic.systems/appendix/codebases#yocto-manifests) [Yocto Manifestsarrow-up-right](https://github.com/SeismicSystems/yocto-manifests) #### [hashtag](https://docs.seismic.systems/appendix/codebases#yocto-scripts) [Yocto Scriptsarrow-up-right](https://github.com/SeismicSystems/yocto-scripts) [PreviousLinks & Contactchevron-left](https://docs.seismic.systems/appendix/links-and-contact) [NextDevnetchevron-right](https://docs.seismic.systems/appendix/devnet) Last updated 3 months ago * [Summit](https://docs.seismic.systems/appendix/codebases#summit) * [Seismic Solidity](https://docs.seismic.systems/appendix/codebases#seismic-solidity) * [Enclave](https://docs.seismic.systems/appendix/codebases#enclave) * [Execution layer](https://docs.seismic.systems/appendix/codebases#execution-layer) * [Alloy](https://docs.seismic.systems/appendix/codebases#alloy) * [REVM](https://docs.seismic.systems/appendix/codebases#revm) * [Reth](https://docs.seismic.systems/appendix/codebases#reth) * [Foundry](https://docs.seismic.systems/appendix/codebases#foundry) * [Seismic Client](https://docs.seismic.systems/appendix/codebases#seismic-client) * [Deployment](https://docs.seismic.systems/appendix/codebases#deployment) * [Deploy](https://docs.seismic.systems/appendix/codebases#deploy) * [Yocto build system](https://docs.seismic.systems/appendix/codebases#yocto-build-system) sun-brightdesktopmoon sun-brightdesktopmoon --- # Devnet | Seismic Docs ![](https://docs.seismic.systems/~gitbook/image?url=https%3A%2F%2F1987385627-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FhkB2uNxma1rxIgBfHgAT%252Fuploads%252FTZfp8XHFNZcagX1LvH2M%252FScreenshot%25202025-03-25%2520at%25203.27.58%25E2%2580%25AFPM.png%3Falt%3Dmedia%26token%3Dd3875bd6-6b1c-422f-80d4-0c59cbbf6144&width=768&dpr=3&quality=100&sign=a4c3a599&sv=2) Welcome! This walkthrough is quick. It only requires a minute of actual attention, while the rest is waiting. **If you run into any issues, please check if it's one of the 10 common errors resolved in the** [**FAQ**](https://docs.seismic.systems/appendix/devnet#faq) **section.** You can also hop in [our discordarrow-up-right](https://discord.com/invite/seismic) and ask questions in the `#devnet` channel. If you end up deploying your own custom contract, please send the github link to [@lyroncarrow-up-right](https://t.me/lyronc) on TG! Also note, this **is not an incentivized testnet**. Works on Mac, Linux, and Windows via WSL (see [FAQ](https://docs.seismic.systems/appendix/devnet#faq) ). [hashtag](https://docs.seismic.systems/appendix/devnet#deploy-an-encrypted-contract) Deploy an encrypted contract ---------------------------------------------------------------------------------------------------------------------- #### [hashtag](https://docs.seismic.systems/appendix/devnet#id-1.-install-rust) 1\. Install Rust #### [hashtag](https://docs.seismic.systems/appendix/devnet#id-2.-install-jq) 2\. Install jq For Mac. See instructions for your machine [herearrow-up-right](https://jqlang.org/download/) . Only step that isn't OS agnostic. #### [hashtag](https://docs.seismic.systems/appendix/devnet#id-3.-install-sfoundryup) 3\. Install sfoundryup #### [hashtag](https://docs.seismic.systems/appendix/devnet#id-4.-run-sfoundryup) 4\. Run sfoundryup #### [hashtag](https://docs.seismic.systems/appendix/devnet#id-5.-clone-repository) 5\. Clone repository #### [hashtag](https://docs.seismic.systems/appendix/devnet#id-6.-deploy-contract) 6\. Deploy contract [hashtag](https://docs.seismic.systems/appendix/devnet#interact-with-an-encrypted-contract) Interact with an encrypted contract ------------------------------------------------------------------------------------------------------------------------------------ #### [hashtag](https://docs.seismic.systems/appendix/devnet#id-1.-install-bun) 1\. Install Bun #### [hashtag](https://docs.seismic.systems/appendix/devnet#id-2.-install-node-dependencies) 2\. Install node dependencies #### [hashtag](https://docs.seismic.systems/appendix/devnet#id-3.-send-transactions) 3\. Send transactions [hashtag](https://docs.seismic.systems/appendix/devnet#faq) FAQ -------------------------------------------------------------------- chevron-rightWhat if I'm on Windows?[hashtag](https://docs.seismic.systems/appendix/devnet#what-if-im-on-windows) We recommend using [WSLarrow-up-right](https://learn.microsoft.com/en-us/windows/wsl/install) to run commands as if you were on a Linux machine. Run Now restart your computer. After booting back up, you should be able to run the below command and follow the rest of the steps like normal chevron-rightI'm stuck at `1108/1112` when running `sfoundryup` .[hashtag](https://docs.seismic.systems/appendix/devnet#im-stuck-at-1108-1112-when-running-sfoundryup) Some machines take up to an hour to do this step. If it takes longer, ask a question in [our discord'sarrow-up-right](https://discord.com/invite/seismic) `#devnet` channel. chevron-rightI'm getting `Command failed: cargo build --bins --release`.[hashtag](https://docs.seismic.systems/appendix/devnet#im-getting-command-failed-cargo-build-bins-release) Means your machine doesn't have cargo. If you're on Linux, run chevron-rightI'm getting `jq (command not found)`.[hashtag](https://docs.seismic.systems/appendix/devnet#im-getting-jq-command-not-found) Means [step #2](https://docs.seismic.systems/appendix/devnet#id-2.-install-jq) didn't work. If you're on Linux, run chevron-rightI'm getting `Address not funded. Please check if your faucet transaction went...`[hashtag](https://docs.seismic.systems/appendix/devnet#im-getting-address-not-funded.-please-check-if-your-faucet-transaction-went) Means your wallet has no testnet ETH. Please go to the [faucetarrow-up-right](https://faucet-2.seismicdev.net/) , enter the address the script gave you, and wait for the green confirmation. ![](https://docs.seismic.systems/~gitbook/image?url=https%3A%2F%2F1987385627-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FhkB2uNxma1rxIgBfHgAT%252Fuploads%252FmaIy6mPyVAjgiKaI1pBt%252FScreenshot%25202025-03-25%2520at%25204.01.46%25E2%2580%25AFPM.png%3Falt%3Dmedia%26token%3D5077d6a7-21c7-4559-92e9-4f44ba498b4c&width=300&dpr=3&quality=100&sign=e5f52990&sv=2) chevron-rightI'm getting `Command 'brew' not found`.[hashtag](https://docs.seismic.systems/appendix/devnet#im-getting-command-brew-not-found) Means your machine doesn't have the [Homebrewarrow-up-right](https://brew.sh/) package manager. Run chevron-rightI'm getting `linker 'cc' not found`.[hashtag](https://docs.seismic.systems/appendix/devnet#im-getting-linker-cc-not-found) You can resolve by running chevron-rightI'm getting `command not found: sfoundryup` .[hashtag](https://docs.seismic.systems/appendix/devnet#im-getting-command-not-found-sfoundryup) If this comes up even after you complete [step #3](https://docs.seismic.systems/appendix/devnet#id-3.-install-sfoundryup) successfully, restart your terminal. Should be able to run it after. chevron-rightI'm getting `info: aborting installation` .[hashtag](https://docs.seismic.systems/appendix/devnet#im-getting-info-aborting-installation) Means you aren't selecting an option for your Rust installation. Run the `curl` command again, and press Enter. ![](https://docs.seismic.systems/~gitbook/image?url=https%3A%2F%2F1987385627-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FhkB2uNxma1rxIgBfHgAT%252Fuploads%252FgfeTVrFr3c3xqvbpIsmH%252FScreenshot%25202025-03-25%2520at%25204.55.36%25E2%2580%25AFPM.png%3Falt%3Dmedia%26token%3D112f9dee-0ccb-4e87-8f04-0d1a60316285&width=300&dpr=3&quality=100&sign=9b24f263&sv=2) chevron-rightI'm getting `Command: 'bun' not found`.[hashtag](https://docs.seismic.systems/appendix/devnet#im-getting-command-bun-not-found) You need to add bun to your PATH. You can either do this temporarily in your current terminal via the below command (you'll have to do it for every new window): Or set it properly, by opening up your `~/.bashrc` and adding [hashtag](https://docs.seismic.systems/appendix/devnet#view-official-links) View official links ---------------------------------------------------------------------------------------------------- Item Value Network Name Seismic devnet Currency Symbol ETH Chain ID 5124 RPC URL (HTTP) [https://node-2.seismicdev.net/rpcarrow-up-right](https://node-2.seismicdev.net/rpc) RPC URL (WS) [wss://node-2.seismicdev.net/wsarrow-up-right](wss://node-2.seismicdev.net/ws) Explorer [https://explorer-2.seismicdev.net/arrow-up-right](https://explorer-2.seismicdev.net/) Faucet [https://faucet-2.seismicdev.net/arrow-up-right](https://faucet-2.seismicdev.net/) Starter Repo [https://github.com/SeismicSystems/seismic-starterarrow-up-right](https://github.com/SeismicSystems/seismic-starter/tree/main) NOTE: This is a testnet with known decryption keys. Please don't put real information on it! [PreviousCodebaseschevron-left](https://docs.seismic.systems/appendix/codebases) [NextTestnetchevron-right](https://docs.seismic.systems/appendix/testnet) Last updated 5 days ago * [Deploy an encrypted contract](https://docs.seismic.systems/appendix/devnet#deploy-an-encrypted-contract) * [Interact with an encrypted contract](https://docs.seismic.systems/appendix/devnet#interact-with-an-encrypted-contract) * [FAQ](https://docs.seismic.systems/appendix/devnet#faq) * [View official links](https://docs.seismic.systems/appendix/devnet#view-official-links) sun-brightdesktopmoon Copy curl https://sh.rustup.rs -sSf | sh # choose default, just press enter . "$HOME/.cargo/env" Copy brew install jq Copy curl -L \ -H "Accept: application/vnd.github.v3.raw" \ "https://api.github.com/repos/SeismicSystems/seismic-foundry/contents/sfoundryup/install?ref=seismic" | bash source ~/.bashrc Copy sfoundryup # takes between 5m to 60m, and stalling for a while at 98% normal Copy git clone --recurse-submodules https://github.com/SeismicSystems/try-devnet.git cd try-devnet/packages/contract/ Copy bash script/deploy.sh Copy curl -fsSL https://bun.sh/install | bash Copy cd try-devnet/packages/cli/ bun install Copy bash script/transact.sh Copy wsl --install Copy wsl Copy sudo apt update && sudo apt install -y build-essential sudo apt install cargo -y Copy sudo apt-get install jq Copy /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" Copy sudo apt update && sudo apt install -y build-essential sudo apt install cargo -y Copy export PATH="/home/$(whoami)/.bun/bin:$PATH" Copy PATH="/home/$(whoami)/.bun/bin:$PATH" sun-brightdesktopmoon --- # Email Protection | Cloudflare Please enable cookies. Email Protection ================ You are unable to access this email address docs.seismic.systems ---------------------------------------------------------------- The website from which you got to this page is protected by Cloudflare. Email addresses on that page have been hidden in order to keep them from being accessed by malicious bots. **You must enable Javascript in your browser in order to decode the e-mail address**. If you have a website and are interested in protecting it in a similar way, you can [sign up for Cloudflare](https://www.cloudflare.com/sign-up?utm_source=email_protection) . * [How does Cloudflare protect email addresses on website from spammers?](https://developers.cloudflare.com/waf/tools/scrape-shield/email-address-obfuscation/) * [Can I sign up for Cloudflare?](https://developers.cloudflare.com/fundamentals/setup/account/create-account/) Cloudflare Ray ID: **9cc18e081f2ac947** • Your IP: Click to reveal 54.237.218.47 • Performance & security by [Cloudflare](https://www.cloudflare.com/5xx-error-landing) --- # Gotchas | Seismic Docs * conditional execution * dynamic loops #### [hashtag](https://docs.seismic.systems/appendix/gotchas#id-3.3-literals-and-enums) 3.3 Literals and Enums * Be cautious when using literals and enums with shielded types. They can inadvertently leak information if not handled properly. #### [hashtag](https://docs.seismic.systems/appendix/gotchas#id-3.4-exponentiation-and-gas-costs) 3.4 Exponentiation and Gas Costs * Using shielded integers as exponents in exponentiation operations can leak information through gas usage, as gas cost scales with the exponent value. #### [hashtag](https://docs.seismic.systems/appendix/gotchas#id-3.5-.min-and-.max-functions) 3.5 `.min()` and `.max()` Functions * Calling `.min()` and `.max()` on shielded integers can reveal information about their values. #### [hashtag](https://docs.seismic.systems/appendix/gotchas#id-3.6-immutable-variables) 3.6 `immutable` Variables * Shielded `immutable` variables are only truly confidential if the transaction calldata used during their instantiation is encrypted. * **Avoid Public Exposure**: Never expose shielded variables through public getters or events. * **Careful with Gas Usage**: Be mindful of operations where gas cost can vary based on shielded values (e.g., loops, exponentiation). * **Encrypt Calldata**: Ensure that any calldata used for initializing shielded `immutable` variables is encrypted. * **Manual Slot Packing**: If slot packing is necessary, use inline assembly carefully to avoid introducing vulnerabilities. * **Review Compiler Warnings**: Pay attention to compiler warnings related to shielded types to prevent accidental leaks. Last updated 1 year ago --- # Basics | Seismic Docs [hashtag](https://docs.seismic.systems/core#mental-model) Mental model --------------------------------------------------------------------------- circle-info We assume familiarity with [Solidityarrow-up-right](https://soliditylang.org/) . Developers communicate to Seismic through the `stype`. A thorough understanding of this one concept unlocks all shielded computation and storage. The `stype` consists of three elementary types: * `**suint**` / `**sint**`: shielded integer * `**sbool**`: shielded boolean * `**saddress**`: shielded address The primary difference between them and their vanilla counterparts is that they're shielded. Any operations you apply to them are carried out as expected, but the values won't be visible to external observers. There are special considerations unique to each individual type. These are covered in the next three sections. For now, we'll develop a general understanding of `stype` that applies to all its component types. Here's the mental model you should have for shielded contracts. Whenever a tx is broadcasted by a user, it goes through the same submission, execution, and storage phases as a tx in a regular blockchain. The only difference is that when you look at the tx at these different stages- whether it's as a calldata payload during submission, a trace during execution, or as leaves in the MPT tree during storage- any bytes that represent `stype` variables are replaced with `0x000`. Let's step through a concrete example. We'll follow the lifecycle of a `transfer()` tx for an [`ERC20`arrow-up-right](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/) variant. This variant shields user balances and transfer amounts: Copy mapping(address => suint256) public balanceOf; // shielded balance function transfer(address to, suint256 amount) public { // shielded transfer amount balanceOf[msg.sender] -= amount; balanceOf[to] += amount; } ![](https://docs.seismic.systems/~gitbook/image?url=https%3A%2F%2F1987385627-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FhkB2uNxma1rxIgBfHgAT%252Fuploads%252Fhhi4uRKRMgunm8dh5Rkf%252F1.png%3Falt%3Dmedia%26token%3Df8402387-cf93-41cf-a186-5b5b6246a9da&width=768&dpr=3&quality=100&sign=1eaf721c&sv=2) Observers see 0x000 in place of stype variables during transaction submission, execution, and storage. Shielding user balances is done by changing the values of the `balanceOf` array to `suint256`. Shielding transfer amounts is done by changing the `amount` parameter in `transfer()` to `suint256`. Now we can see what happens at every stage of the tx lifecycle: 1. Submit. The tx is sitting in the mempool. You know that you're sending 12 tokens to your friend. Observers can look at the calldata and figure out that your friend is the recipient, but will see `0x000` instead of the number 12. 2. Execute. The tx is processed by a full node, and its trace is open. You know that 12 tokens were removed from your balance and 12 were added to your friend's. Observers know that the same number that was deducted from your balance was added to your friend's, but they see `0x000` instead of the number 12. 3. Store. The effects of the tx are applied to the state tree of all full nodes. You know that your new balance goes down by 12, to 200. You know that your friend's balance went up by 12, but you only see `0x000` for what its final state is. Observers know that your new balance is down the same amount that your friend's new balance is up, but they see `0x000` for both balances. circle-info Seismic currently shields a lot more than just the bytes representing `stype` variables, so the above model is more granular than you technically need to be. However, this will soon stop being the case. You should not fit your contracts to this temporary discrepancy. [hashtag](https://docs.seismic.systems/core#casting) Casting ----------------------------------------------------------------- You can cast `stype` variables to their unshielded counterparts, and vice-versa. Only explicit casting is allowed- no implicit. Note that whenever you do this, observers can look at the trace to figure out either the initial (if going from not `stype` to `stype`) or final (if going from `stype` to not `stype`) value. Copy uint256 number = 100; suint256 sNumber = suint256(number); [hashtag](https://docs.seismic.systems/core#restrictions) Restrictions --------------------------------------------------------------------------- There are two restrictions in how you can use `stype` variables: 1. You can't return them in `public` or `external` functions. This also means `stype` contract variables can't be `public`, since this automatically generates a getter. If you want to return one, you'll have to cast it into its unshielded counterpart. Copy /* * Throws a compiler error */ suint256 public v; // ========== /* * Throws a compiler error */ function f() external view returns (suint256) {} 1. You can't use them as constants. Copy /* * Throws a compiler error */ suint256 constant MY_CONSTANT = 42; [PreviousUnderstanding the Walnut contractchevron-left](https://docs.seismic.systems/onboarding/tutorial/understanding-the-walnut-contract) [Nextsuint / sintchevron-right](https://docs.seismic.systems/core/basics/suint-sint) Last updated 27 days ago --- # Links & Contact | Seismic Docs ### [hashtag](https://docs.seismic.systems/appendix#official-channels) Official channels * [X.com/SeismicSysarrow-up-right](https://x.com/SeismicSys) * Join our [Discordarrow-up-right](https://discord.gg/XSPNseXCvW) * [Websitearrow-up-right](https://seismic.systems/) * [GitHub Organizationarrow-up-right](https://github.com/SeismicSystems) ### [hashtag](https://docs.seismic.systems/appendix#links) Links * Seismic [Status hubarrow-up-right](https://status.seismicdev.net/) * [seismic clientarrow-up-right](https://client.seismic.systems/) documentation * Seismic solidity extensions * [in the VSCode Marketplacearrow-up-right](https://marketplace.visualstudio.com/items?itemName=SeismicSys.seismic) * [in Open VSXarrow-up-right](https://open-vsx.org/extension/SeismicSys/seismic) ### [hashtag](https://docs.seismic.systems/appendix#contact) Contact For partnerships, contact L@, T@ or M@ seismic (dot) systems If you would like to work at Seismic, email your resume to M@ [PreviousSigned readschevron-left](https://docs.seismic.systems/core/seismic-transaction/signed-reads) [NextCodebaseschevron-right](https://docs.seismic.systems/appendix/codebases) Last updated 3 months ago ---