diff --git a/.all-contributorsrc b/.all-contributorsrc
index 85561970be5..f210c1310a7 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -12697,6 +12697,24 @@
"contributions": [
"content"
]
+ },
+ {
+ "login": "jenish-thapa",
+ "name": "Jenish Thapa",
+ "avatar_url": "https://avatars.githubusercontent.com/u/141203631?v=4",
+ "profile": "https://github.com/jenish-thapa",
+ "contributions": [
+ "ideas"
+ ]
+ },
+ {
+ "login": "iusx",
+ "name": "iusx",
+ "avatar_url": "https://avatars.githubusercontent.com/u/57232813?v=4",
+ "profile": "https://jiangxue.org/~ritsu",
+ "contributions": [
+ "code"
+ ]
}
],
"contributorsPerLine": 7,
diff --git a/.env.example b/.env.example
index 08e8ef5b97d..b16d4a8b822 100644
--- a/.env.example
+++ b/.env.example
@@ -29,7 +29,7 @@ IS_PREVIEW_DEPLOY=false
# Build pages only for the specified langs. Leave it empty to build all the langs
# e.g. `en,fr` will only build English and French pages
# Note: always include `en` as it is the default lang of the site
-BUILD_LOCALES=
+NEXT_PUBLIC_BUILD_LOCALES=
# If resource constraints are being hit during builds, change LIMIT_CPUS to a
# fixed number of CPUs (e.g. 2) to limit the demand during build time
diff --git a/.eslintrc.json b/.eslintrc.json
index c8813d5bbf6..02e6c67aab5 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -23,8 +23,6 @@
// Packages. `react` related packages come first.
// Also, put `react-icons` in sorting order not with `react`
["^react(?!-.)$", "^\\w", "^@\\w"],
- // The Chakra theme directory if imported to story file or other places
- ["^@/@chakra-ui"],
// From the `types` directory.
["^@/lib/types", "^@/lib/interfaces"],
// From the `components` directory.
@@ -65,17 +63,6 @@
"varsIgnorePattern": "^_$"
}
],
- "unused-imports/no-unused-imports-ts": "warn",
- "no-restricted-imports": [
- "warn",
- {
- "paths": [
- {
- "name": "react-i18next",
- "message": "Please use next-i18next instead of react-i18next."
- }
- ]
- }
- ]
+ "unused-imports/no-unused-imports-ts": "warn"
}
}
diff --git a/.github/ISSUE_TEMPLATE/suggest_quiz.yaml b/.github/ISSUE_TEMPLATE/suggest_quiz.yaml
index 7ca8c1d7b93..af037b47770 100644
--- a/.github/ISSUE_TEMPLATE/suggest_quiz.yaml
+++ b/.github/ISSUE_TEMPLATE/suggest_quiz.yaml
@@ -1,5 +1,5 @@
name: Suggest quiz
-description: Add, update, delete questions for a quiz on ethereum.osg
+description: Add, update, delete questions for a quiz on ethereum.org
title: Add/Update/Delete quiz question
labels: ["feature ✨", "quiz 📚"]
body:
diff --git a/.github/labeler.yml b/.github/labeler.yml
index e6d58364be9..db08d5281e7 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -16,7 +16,6 @@
"config ⚙️":
- i18n.config.json
- next.config.js
- - next-i18next.config,js
- next-sitemap.config.js
- tsconfig.json
- .nvmrc
diff --git a/.github/workflows/chromatic.yml b/.github/workflows/chromatic.yml
index 3054c265b98..7422a81a40f 100644
--- a/.github/workflows/chromatic.yml
+++ b/.github/workflows/chromatic.yml
@@ -15,7 +15,6 @@ on:
- "src/components/**/*"
- "src/pages/**/*"
- "src/layouts/**/*"
- - "src/@chakra-ui/**/*"
- ".storybook/**/*"
- "tailwind.config.ts"
- "src/styles/**/*"
diff --git a/.storybook/ChakraDecorator.tsx b/.storybook/ChakraDecorator.tsx
deleted file mode 100644
index dbde5985d55..00000000000
--- a/.storybook/ChakraDecorator.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-import { useEffect, useMemo, useState } from "react"
-import {
- ChakraBaseProvider,
- extendBaseTheme,
- useColorMode,
-} from "@chakra-ui/react"
-import type { Decorator } from "@storybook/react"
-
-import theme from "../src/@chakra-ui/theme"
-
-import i18n from "./i18next"
-
-type DecoratorProps = Parameters
-
-const ColorModeSync = ({ context }: { context: DecoratorProps[1] }) => {
- const { setColorMode } = useColorMode()
-
- useEffect(() => {
- const isDarkMode = localStorage.getItem("chakra-ui-color-mode") === "dark"
-
- context.globals.colorMode = isDarkMode ? "dark" : "light"
- }, [])
-
- useEffect(() => {
- setColorMode(context.globals.colorMode)
- }, [setColorMode, context])
-
- return null
-}
-
-/**
- * This is a custom local setup of the official Chakra UI Storybook addon.
- *
- * A local version was created in response to provide a better sync between
- * updated local direction to the Chakra theme.
- *
- * (This would most likely not be updated in the addon due to ongoing creation of Chakra v3 at the time this
- * setup was created.)
- *
- * Will be deprecated and removed when Chakra v3 is available for migration.
- *
- */
-export const ChakraDecorator: Decorator = (getStory, context) => {
- const [dir, updateDir] = useState<"ltr" | "rtl">()
-
- i18n.on("languageChanged", (locale) => {
- const direction = i18n.dir(locale)
- document.documentElement.dir = direction
- updateDir(direction)
- })
-
- const themeWithDirectionOverride = useMemo(() => {
- return extendBaseTheme({ direction: dir }, theme)
- }, [dir])
-
- return (
-
- <>
-
- {getStory(context)}
- >
-
- )
-}
diff --git a/.storybook/main.ts b/.storybook/main.ts
index 02d785aefdc..e0f73e81f1c 100644
--- a/.storybook/main.ts
+++ b/.storybook/main.ts
@@ -1,5 +1,4 @@
import TsconfigPathsPlugin from "tsconfig-paths-webpack-plugin"
-import { propNames } from "@chakra-ui/react"
import type { StorybookConfig } from "@storybook/nextjs"
/**
@@ -17,8 +16,8 @@ import type { StorybookConfig } from "@storybook/nextjs"
const config: StorybookConfig = {
stories: [
"../src/components/**/*.stories.{ts,tsx}",
- "../src/@chakra-ui/stories/*.stories.tsx",
"../src/layouts/stories/*.stories.tsx",
+ "../src/styles/*.stories.tsx",
],
addons: [
"@storybook/addon-links",
@@ -29,9 +28,9 @@ const config: StorybookConfig = {
},
},
"@storybook/addon-interactions",
- "storybook-react-i18next",
"@storybook/addon-themes",
"@chromatic-com/storybook",
+ "storybook-next-intl",
],
staticDirs: ["../public"],
framework: {
@@ -41,11 +40,6 @@ const config: StorybookConfig = {
docs: {
autodocs: "tag",
},
- refs: {
- "@chakra-ui/react": {
- disable: true,
- },
- },
webpackFinal: async (config) => {
config.module = config.module || {}
config.module.rules = config.module.rules || []
@@ -79,23 +73,6 @@ const config: StorybookConfig = {
typescript: {
reactDocgenTypescriptOptions: {
shouldExtractLiteralValuesFromEnum: true,
- /**
- * For handling bloated controls table of Chakra Props
- *
- * https://github.com/chakra-ui/chakra-ui/issues/2009#issuecomment-852793946
- */
- propFilter: (prop) => {
- const excludedPropNames = propNames.concat([
- "as",
- "apply",
- "sx",
- "__css",
- ])
- const isStyledSystemProp = excludedPropNames.includes(prop.name)
- const isHTMLElementProp =
- prop.parent?.fileName.includes("node_modules") ?? false
- return !(isStyledSystemProp || isHTMLElementProp)
- },
},
reactDocgen: "react-docgen-typescript",
diff --git a/.storybook/modes.ts b/.storybook/modes.ts
index 086d07ab0d1..ed683104212 100644
--- a/.storybook/modes.ts
+++ b/.storybook/modes.ts
@@ -1,6 +1,6 @@
import pickBy from "lodash/pickBy"
-import { baseLocales } from "./i18next"
+import { baseLocales } from "./next-intl"
import { breakpointSet } from "./preview"
export const viewportModes = breakpointSet.reduce<{
diff --git a/.storybook/i18next.ts b/.storybook/next-intl.ts
similarity index 71%
rename from .storybook/i18next.ts
rename to .storybook/next-intl.ts
index a2fbde38908..4d2a7844b37 100644
--- a/.storybook/i18next.ts
+++ b/.storybook/next-intl.ts
@@ -1,7 +1,3 @@
-import i18n, { Resource } from "i18next"
-// eslint-disable-next-line no-restricted-imports
-import { initReactI18next } from "react-i18next"
-
export const baseLocales = {
en: { title: "English", left: "En" },
zh: { title: "中国人", left: "Zh" },
@@ -32,7 +28,7 @@ const supportedLngs = Object.keys(baseLocales)
/**
* Taking the ns array and generating those files for each language available.
*/
-const resources: Resource = ns.reduce((acc, n) => {
+const messagesByLocale = ns.reduce((acc, n) => {
supportedLngs.forEach((lng) => {
if (!acc[lng]) acc[lng] = {}
@@ -57,16 +53,18 @@ const resources: Resource = ns.reduce((acc, n) => {
return acc
}, {})
-console.log("🚀 ~ constresources:Resource=ns.reduce ~ resources:", resources)
+console.log(
+ "🚀 ~ constresources:Resource=ns.reduce ~ resources:",
+ messagesByLocale
+)
-i18n.use(initReactI18next).init({
- debug: true,
- fallbackLng: "en",
- interpolation: { escapeValue: false },
- react: { useSuspense: false },
- supportedLngs,
- resources,
- defaultNS: "common",
-})
+const nextIntl = {
+ defaultLocale: "en",
+ messagesByLocale,
+ getMessageFallback: ({ key }: { key: string }) => {
+ const keyOnly = key.split(".").pop()
+ return keyOnly || key
+ },
+}
-export default i18n
+export default nextIntl
diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx
index 191fa7888d7..1095a3011c2 100644
--- a/.storybook/preview.tsx
+++ b/.storybook/preview.tsx
@@ -5,7 +5,7 @@ import type { Preview } from "@storybook/react"
import ThemeProvider from "@/components/ThemeProvider"
import { TooltipProvider } from "@/components/ui/tooltip"
-import i18n, { baseLocales } from "./i18next"
+import nextIntl, { baseLocales } from "./next-intl"
import { withNextThemes } from "./withNextThemes"
import "../src/styles/global.css"
@@ -47,7 +47,7 @@ const preview: Preview = {
),
],
parameters: {
- i18n,
+ nextIntl,
controls: {
matchers: {
color: /(background|color)$/i,
diff --git a/.storybook/types.ts b/.storybook/types.ts
deleted file mode 100644
index 1b8116ee78a..00000000000
--- a/.storybook/types.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import type { StyleConfig, ThemingProps } from "@chakra-ui/react"
-import type { ArgTypes } from "@storybook/react"
-
-// Type declarations below pulled directly from `@chakra-ui/storybook-addon`
-// with some alteration
-// (Subject to deprecation and removal upon release of Chakra v3)
-
-/**
- * `keyof` alternative which omits non-string keys
- */
-type KeyOf = [T] extends [never]
- ? never
- : T extends object
- ? Extract
- : never
-
-export type ThemingArgTypeKey = "variant" | "size"
-
-/**
- * Create Storybook controls based on a Chakra UI theme component.
- *
- * @example
- * export default {
- * title: "Components / Forms / Button",
- * argTypes: getThemingArgTypes(theme, "Button"),
- * }
- *
- * @example full example
- * import { Meta, StoryFn } from "@storybook/react"
- * import { getThemingArgTypes } from "@chakra-ui/storybook-addon"
- * import { theme } from ""
- *
- * export default {
- * title: "Components / Forms / Button",
- * argTypes: {
- * ...getThemingArgTypes(theme, "Button"),
- * children: "string"
- * },
- * args: { children: "Button" },
- * } as Meta
- *
- * interface StoryProps extends ThemingProps<"Button"> {
- * children?: React.ReactNode
- * }
- *
- * export const Basic: StoryFn = (props) =>
- *
- * @param theme same Chakra UI theme used in .storybook/preview.tsx
- * @param componentName component name to create the ArgTypes for
- */
-export function getThemingArgTypes<
- Theme extends Record & {
- components?: Record
- },
- ComponentName extends KeyOf,
->(theme: Theme, componentName: ComponentName) {
- const component = theme.components?.[componentName]
- if (!component) {
- return undefined
- }
-
- const argTypes: ArgTypes<
- Partial, ThemingArgTypeKey>>
- > = {}
-
- const variantOptions = Object.keys(component.variants || {})
- if (variantOptions.length) {
- argTypes.variant = {
- type: { name: "enum", value: variantOptions },
- defaultValue: component.defaultProps?.variant,
- }
- }
-
- const sizeOptions = Object.keys(component.sizes || {})
- if (sizeOptions.length) {
- argTypes.size = {
- type: { name: "enum", value: sizeOptions },
- defaultValue: component.defaultProps?.size,
- }
- }
-
- return argTypes
-}
diff --git a/.storybook/utils.ts b/.storybook/utils.ts
deleted file mode 100644
index 9b523865e1a..00000000000
--- a/.storybook/utils.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-// eslint-disable-next-line no-restricted-imports
-import { getI18n } from "react-i18next"
-
-import { ns as exposedNs } from "./i18next"
-
-/**
- * Get translations using the `getI18n` method.
- *
- * Only requires the key and optionally the namespace.
- *
- * Used for Stories where it is invalid to use the `useTranslation` hook in
- * the `render` function.
- *
- * The `ns` param is also typed with the namespaces that are exposed in
- * storybook.
- *
- * @param key - The key to translate.
- * @param ns - The exposed namespace.
- * @returns The translated string.
- */
-export const getTranslation = (
- key: string,
- ns?: (typeof exposedNs)[number]
-) => {
- const { t } = getI18n()
- return t(key, { ns })
-}
diff --git a/README.md b/README.md
index 54e49e44432..30cea9830a2 100644
--- a/README.md
+++ b/README.md
@@ -95,9 +95,9 @@ yarn dev
- Open this directory in your favorite text editor / IDE, and see your changes live by visiting `localhost:3000` from your browser
- Pro Tip:
- Explore scripts within `package.json` for more build options
- - Get **faster** production builds by building only one language. E.g. in your `.env` file, set `BUILD_LOCALES=en` to build the content only in English
- - To build the site in other selected languages too, you need to set them in `BUILD_LOCALES`, eg: `BUILD_LOCALES=en,es` if you also want to build only English (required) and Spanish.
- - To build all languages, simply comment this line out with a hash mark, eg: `# BUILD_LOCALES=`
+ - Get **faster** production builds by building only one language. E.g. in your `.env` file, set `NEXT_PUBLIC_BUILD_LOCALES=en` to build the content only in English
+ - To build the site in other selected languages too, you need to set them in `NEXT_PUBLIC_BUILD_LOCALES`, eg: `NEXT_PUBLIC_BUILD_LOCALES=en,es` if you also want to build only English (required) and Spanish.
+ - To build all languages, simply comment this line out with a hash mark, eg: `# NEXT_PUBLIC_BUILD_LOCALES=`
By default the script will build all the languages (complete list in `i18n.config.json`).
@@ -168,7 +168,7 @@ Learn more about how we review pull requests [here](docs/review-process.md).
- To help with verification we request GitHub contributors connect their GitHub account with their Discord account (Discord > Settings > Connections > GitHub). Crowdin contributors will be verified directly through Crowdin by our team.
-If you haven't contributed yet and would like to earn a POAP/OATs to show your loyalty to the Ethereum space, head over to the [issues](https://github.com/ethereum/ethereum-org-website/issues/) tab to get started! If you would like to contribute to translations check out our [Translation Program](https://ethereum.org/en/contributing/translation-program/).
+If you haven't contributed yet and would like to earn a POAP/OATs to show your loyalty to the Ethereum space, head over to the [issues](https://github.com/ethereum/ethereum-org-website/issues/) tab to get started! If you would like to contribute to translations check out our [Translation Program](https://ethereum.org/en/contributing/translation-program/).
@@ -1942,6 +1942,8 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
diff --git a/docs/best-practices.md b/docs/best-practices.md
index db9281a1a39..b8d73a4be81 100644
--- a/docs/best-practices.md
+++ b/docs/best-practices.md
@@ -52,7 +52,7 @@ Markdown will be translated as whole pages of content, so no specific action is
- _tl;dr Each individual JSON entry should be a complete phrase by itself_
-- This is done using the `Translation` component. However there is an alternative method for regular JS: using the `t` function from `next-i18next`
+- This is done using the `Translation` component. However there is an alternative method for regular JS: using the `t` function from `@/hooks/useTranslation`
- **Method one: `` component (preferred if only needed in JSX)**
@@ -66,7 +66,7 @@ Markdown will be translated as whole pages of content, so no specific action is
- **Method two: `t()`**
```tsx
- import { useTranslation } from "next-i18next"
+ import { useTranslation } from "@/hooks/useTranslation"
// Utilize anywhere in JS using
const { t } = useTranslation()
diff --git a/next-i18next.config.js b/next-i18next.config.js
deleted file mode 100644
index cb62211c599..00000000000
--- a/next-i18next.config.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/* eslint-disable @typescript-eslint/no-var-requires */
-const path = require("path")
-const i18nConfig = require("./i18n.config.json")
-
-const BUILD_LOCALES = process.env.BUILD_LOCALES
-// Supported locales defined in `i18n.config.json`
-const locales = BUILD_LOCALES
- ? BUILD_LOCALES.split(",")
- : i18nConfig.map(({ code }) => code)
-
-/** @type {import('next-i18next').UserConfig} */
-module.exports = {
- i18n: {
- // "default" locale is a hack to always display the locale prefix in the
- // url. Ref: https://nextjs.org/docs/pages/building-your-application/routing/internationalization#prefixing-the-default-locale
- defaultLocale: "default",
- // supported locales defined in `i18n.config.json`
- locales: ["default", ...locales],
- localeDetection: false,
- },
- // define custom location for intl files, otherwise default to public/locales (https://github.com/i18next/next-i18next#2-translation-content)
- // use path.resolve to work with Netlify (https://github.com/i18next/next-i18next/issues/1552#issuecomment-1538452722)
- localePath: path.resolve("./src/intl"),
- // see updates to your translation JSON files without having to restart your development server each time
- reloadOnPrerender: true,
- // Language codes to lookup, given set language is 'en-US': 'all' --> ['en-US', 'en', 'dev'], 'currentOnly' --> 'en-US', 'languageOnly' --> 'en'
- load: "currentOnly",
- // Language will be lowercased EN --> en while leaving full locales like en-US
- cleanCode: true,
- // Language will be lowercased eg. en-US --> en-us
- lowerCaseLng: true,
-}
diff --git a/next.config.js b/next.config.js
index cd81f57e2db..6a9a16a212e 100644
--- a/next.config.js
+++ b/next.config.js
@@ -5,7 +5,9 @@ const withBundleAnalyzer = require("@next/bundle-analyzer")({
enabled: process.env.ANALYZE === "true",
})
-const { i18n } = require("./next-i18next.config")
+const createNextIntlPlugin = require("next-intl/plugin")
+
+const withNextIntl = createNextIntlPlugin()
const LIMIT_CPUS = Number(process.env.LIMIT_CPUS ?? 2)
@@ -59,7 +61,6 @@ module.exports = (phase, { defaultConfig }) => {
return config
},
- i18n,
trailingSlash: true,
images: {
deviceSizes: [640, 750, 828, 1080, 1200, 1504, 1920],
@@ -111,5 +112,5 @@ module.exports = (phase, { defaultConfig }) => {
}
}
- return withBundleAnalyzer(nextConfig)
+ return withBundleAnalyzer(withNextIntl(nextConfig))
}
diff --git a/package.json b/package.json
index 09a4f054153..8427d8927cd 100644
--- a/package.json
+++ b/package.json
@@ -1,11 +1,10 @@
{
"name": "ethereum-org-website",
- "version": "9.5.0",
+ "version": "9.6.0",
"license": "MIT",
"private": true,
"scripts": {
"dev": "next dev",
- "postinstall": "yarn theme",
"build": "next build",
"postbuild": "next-sitemap",
"start": "next start",
@@ -23,16 +22,11 @@
"markdown-checker": "ts-node -O '{ \"module\": \"commonjs\" }' src/scripts/markdownChecker.ts",
"events-import": "ts-node -O '{ \"module\": \"commonjs\" }' src/scripts/events-import.ts",
"crowdin-needs-review": "ts-node -O '{ \"module\": \"commonjs\" }' src/scripts/crowdin/reports/generateReviewReport.ts",
- "theme": "chakra-cli tokens ./src/@chakra-ui/theme.ts",
- "theme:watch": "chakra-cli tokens ./src/@chakra-ui/theme.ts --watch",
"prepare": "husky"
},
"dependencies": {
- "@chakra-ui/react": "^2.8.0",
"@crowdin/crowdin-api-client": "^1.25.0",
"@docsearch/react": "^3.5.2",
- "@emotion/react": "^11.11.1",
- "@emotion/styled": "^11.11.0",
"@hookform/resolvers": "^3.8.0",
"@next/bundle-analyzer": "^14.2.5",
"@radix-ui/react-accordion": "^1.2.0",
@@ -64,12 +58,11 @@
"framer-motion": "^10.13.0",
"gray-matter": "^4.0.3",
"htmr": "^1.0.2",
- "i18next": "^23.6.0",
"lodash.merge": "^4.6.2",
"lodash.shuffle": "^4.2.0",
"lodash.union": "^4.6.0",
"next": "^14.2.21",
- "next-i18next": "^14.0.3",
+ "next-intl": "^3.26.3",
"next-mdx-remote": "^3.0.8",
"next-sitemap": "^4.2.3",
"next-themes": "^0.3.0",
@@ -80,7 +73,6 @@
"react-dom": "^18.2.0",
"react-emoji-render": "^2.0.1",
"react-hook-form": "^7.52.1",
- "react-i18next": "^13.3.1",
"react-icons": "^4.10.1",
"react-lite-youtube-embed": "^2.4.0",
"react-select": "5.8.0",
@@ -96,7 +88,6 @@
"yaml-loader": "^0.8.0"
},
"devDependencies": {
- "@chakra-ui/cli": "^2.4.1",
"@chromatic-com/storybook": "1.5.0",
"@netlify/plugin-nextjs": "^5.8.0",
"@storybook/addon-essentials": "8.1.10",
@@ -137,7 +128,7 @@
"prettier-plugin-tailwindcss": "^0.6.5",
"raw-loader": "^4.0.2",
"storybook": "8.1.10",
- "storybook-react-i18next": "3.1.1",
+ "storybook-next-intl": "^1.2.5",
"tailwindcss": "^3.4.4",
"ts-node": "^10.9.1",
"tsconfig-paths-webpack-plugin": "4.1.0",
diff --git a/public/content/community/research/index.md b/public/content/community/research/index.md
index 3b238fb9658..9fea58e0243 100644
--- a/public/content/community/research/index.md
+++ b/public/content/community/research/index.md
@@ -358,7 +358,7 @@ Tools for Ethereum developers are rapidly improving. There is lots of active res
### Oracles {#oracles}
-Oracles import off-chain data onto the blockchain in a permissionless and decentralized way. Getting this data on-chain enables dapps to be reactive to real-world phenomena such as price fluctuations in real-world assets, events in off-chain apps, or even changes in the weather.
+Oracles import offchain data onto the blockchain in a permissionless and decentralized way. Getting this data onchain enables dapps to be reactive to real-world phenomena such as price fluctuations in real-world assets, events in offchain apps, or even changes in the weather.
#### Background reading {#background-reading-18}
diff --git a/public/content/contributing/style-guide/content-standardization/index.md b/public/content/contributing/style-guide/content-standardization/index.md
index 8fbf287c31a..de3a5c329c6 100644
--- a/public/content/contributing/style-guide/content-standardization/index.md
+++ b/public/content/contributing/style-guide/content-standardization/index.md
@@ -270,3 +270,15 @@ When citing articles from a specific author or organization, use the article's n
- [A rollup-centric ethereum roadmap by Vitalik Buterin](https://ethereum-magicians.org/t/a-rollup-centric-ethereum-roadmap/4698)
- [ConsenSys on The History of Ethereum Testnets](https://consensys.net/blog/news/the-history-of-ethereum-testnets/) – _ConsenSys_
```
+
+### Onchain and offchain {#onchain-offchain}
+
+Similar to "online" or "offline", the terms "onchain" and "offchain" should be written as one word, without a space or hyphenation.
+
+```md
+<--- Good --->
+Discussion was held in an offchain forum, and the vote was performed onchain.
+
+<--- Bad--->
+Discussion was held in an off-chain forum, and the vote was performed on-chain.
+```
diff --git a/public/content/dao/index.md b/public/content/dao/index.md
index 5287be1e8fa..0c1249cbc13 100644
--- a/public/content/dao/index.md
+++ b/public/content/dao/index.md
@@ -19,7 +19,7 @@ A DAO is a collectively-owned organization working towards a shared mission.
DAOs allow us to work with like-minded folks around the globe without trusting a benevolent leader to manage the funds or operations. There is no CEO who can spend funds on a whim or CFO who can manipulate the books. Instead, blockchain-based rules baked into the code define how the organization works and how funds are spent.
-They have built-in treasuries that no one has the authority to access without the approval of the group. Decisions are governed by proposals and voting to ensure everyone in the organization has a voice, and everything happens transparently [on-chain](/glossary/#on-chain).
+They have built-in treasuries that no one has the authority to access without the approval of the group. Decisions are governed by proposals and voting to ensure everyone in the organization has a voice, and everything happens transparently [onchain](/glossary/#onchain).
## Why do we need DAOs? {#why-dao}
@@ -120,7 +120,7 @@ _Typically used for more closer-knit, human-centric organizations like charities
### Reputation-based membership {#reputation-based-membership}
-Reputation represents proof of participation and grants voting power in the DAO. Unlike token or share-based membership, reputation-based DAOs don't transfer ownership to contributors. Reputation cannot be bought, transferred or delegated; DAO members must earn reputation through participation. On-chain voting is permissionless and prospective members can freely submit proposals to join the DAO and request to receive reputation and tokens as a reward in exchange for their contributions.
+Reputation represents proof of participation and grants voting power in the DAO. Unlike token or share-based membership, reputation-based DAOs don't transfer ownership to contributors. Reputation cannot be bought, transferred or delegated; DAO members must earn reputation through participation. Onchain voting is permissionless and prospective members can freely submit proposals to join the DAO and request to receive reputation and tokens as a reward in exchange for their contributions.
_Typically used for decentralized development and governance of protocols and [dapps](/glossary/#dapp), but also well suited to a diverse set of organizations like charities, worker collectives, investment clubs, etc._
diff --git a/public/content/decentralized-identity/index.md b/public/content/decentralized-identity/index.md
index 634fbd86b4b..db25688e9aa 100644
--- a/public/content/decentralized-identity/index.md
+++ b/public/content/decentralized-identity/index.md
@@ -67,9 +67,9 @@ Decentralized identity allows companies to skip on conventional [Know-Your-Custo
### 3. Voting and online communities {#voting-and-online-communities}
-Online voting and social media are two novel applications for decentralized identity. Online voting schemes are susceptible to manipulation, especially if malicious actors create false identities to vote. Asking individuals to present on-chain attestations can improve the integrity of online voting processes.
+Online voting and social media are two novel applications for decentralized identity. Online voting schemes are susceptible to manipulation, especially if malicious actors create false identities to vote. Asking individuals to present onchain attestations can improve the integrity of online voting processes.
-Decentralized identity can help create online communities that are free of fake accounts. For example, each user might have to authenticate their identity using an on-chain identity system, like the Ethereum Name Service, reducing the possibility of bots.
+Decentralized identity can help create online communities that are free of fake accounts. For example, each user might have to authenticate their identity using an onchain identity system, like the Ethereum Name Service, reducing the possibility of bots.
### 4. Anti-Sybil protection {#sybil-protection}
@@ -119,47 +119,47 @@ Decentralized identifiers are also crucial to protecting the privacy of personal
How attestation information is stored and retrieved in an Ethereum-based identity ecosystem is different from traditional identity management. Here is an overview of the various approaches to issuing, storing, and verifying attestations in decentralized identity systems:
-### Off-chain attestations {#off-chain-attestations}
+### Offchain attestations {#offchain-attestations}
-One concern with storing attestations on-chain is that they might contain information individuals want to keep private. The public nature of the Ethereum blockchain makes it unattractive to store such attestations.
+One concern with storing attestations onchain is that they might contain information individuals want to keep private. The public nature of the Ethereum blockchain makes it unattractive to store such attestations.
-The solution is to issue attestations, held by users off-chain in digital wallets, but signed with the issuer's DID stored on-chain. These attestations are encoded as [JSON Web Tokens](https://en.wikipedia.org/wiki/JSON_Web_Token) and contain the issuer's digital signature—which allows for easy verification of off-chain claims.
+The solution is to issue attestations, held by users offchain in digital wallets, but signed with the issuer's DID stored onchain. These attestations are encoded as [JSON Web Tokens](https://en.wikipedia.org/wiki/JSON_Web_Token) and contain the issuer's digital signature—which allows for easy verification of offchain claims.
-Here's an hypothetical scenario to explain off-chain attestations:
+Here's an hypothetical scenario to explain offchain attestations:
1. A university (the issuer) generates an attestation (a digital academic certificate), signs with its keys, and issues it to Bob (the identity owner).
2. Bob applies for a job and wants to prove his academic qualifications to an employer, so he shares the attestation from his mobile wallet. The company (the verifier) can then confirm the validity of the attestation by checking the issuer's DID (i.e., its public key on Ethereum).
-### Off-chain attestations with persistent access {#offchain-attestations-with-persistent-access}
+### Offchain attestations with persistent access {#offchain-attestations-with-persistent-access}
-Under this arrangement attestations are transformed into JSON files and stored off-chain (ideally on a [decentralized cloud storage](/developers/docs/storage/) platform, such as IPFS or Swarm). However, a [hash](/glossary/#hash) of the JSON file is stored on-chain and linked to a DID via an on-chain registry. The associated DID could either be that of the issuer of the attestation or the recipient.
+Under this arrangement attestations are transformed into JSON files and stored offchain (ideally on a [decentralized cloud storage](/developers/docs/storage/) platform, such as IPFS or Swarm). However, a [hash](/glossary/#hash) of the JSON file is stored onchain and linked to a DID via an onchain registry. The associated DID could either be that of the issuer of the attestation or the recipient.
This approach enables attestations to gain blockchain-based persistence, while keeping claims information encrypted and verifiable. It also allows for selective disclosure since the holder of the private key can decrypt the information.
-### On-chain attestations {#onchain-attestations}
+### Onchain attestations {#onchain-attestations}
-On-chain attestations are held in [smart contracts](/glossary/#smart-contract) on the Ethereum blockchain. The smart contract (acting as a registry) will map an attestation to a corresponding on-chain decentralized identifier (a public key).
+Onchain attestations are held in [smart contracts](/glossary/#smart-contract) on the Ethereum blockchain. The smart contract (acting as a registry) will map an attestation to a corresponding onchain decentralized identifier (a public key).
-Here's an example to show how on-chain attestations might work in practice:
+Here's an example to show how onchain attestations might work in practice:
1. A company (XYZ Corp) plans to sell ownership shares using a smart contract but only wants buyers that have completed a background check.
-2. XYZ Corp can have the company performing background checks to issue on-chain attestations on Ethereum. This attestation certifies that an individual has passed the background check without exposing any personal information.
+2. XYZ Corp can have the company performing background checks to issue onchain attestations on Ethereum. This attestation certifies that an individual has passed the background check without exposing any personal information.
3. The smart contract selling shares can check the registry contract for the identities of screened buyers, making it possible for the smart contract to determine who is permitted to buy shares or not.
### Soulbound tokens and identity {#soulbound}
-[Soulbound tokens](https://vitalik.eth.limo/general/2022/01/26/soulbound.html) ([non-transferable NFTs](/glossary/#nft)) could be used to collect information unique to a specific wallet. This effectively creates a unique on-chain identity bound to a particular Ethereum address that could include tokens representing achievements (e.g. finishing some specific online course or passing a threshold score in a game) or community participation.
+[Soulbound tokens](https://vitalik.eth.limo/general/2022/01/26/soulbound.html) ([non-transferable NFTs](/glossary/#nft)) could be used to collect information unique to a specific wallet. This effectively creates a unique onchain identity bound to a particular Ethereum address that could include tokens representing achievements (e.g. finishing some specific online course or passing a threshold score in a game) or community participation.
## Use decentralized identity {#use-decentralized-identity}
There are many ambitious projects using Ethereum as a foundation for decentralized identity solutions:
-- **[Ethereum Name Service (ENS)](https://ens.domains/)** - _A decentralized naming system for on-chain, machine-readable identifiers, like, Ethereum wallet addresses, content hashes, and metadata._
+- **[Ethereum Name Service (ENS)](https://ens.domains/)** - _A decentralized naming system for onchain, machine-readable identifiers, like, Ethereum wallet addresses, content hashes, and metadata._
- **[SpruceID](https://www.spruceid.com/)** - _A decentralized identity project which allows users to control digital identity with Ethereum accounts and ENS profiles instead of relying on third-party services._
-- **[Ethereum Attestation Service (EAS)](https://attest.sh/)** - _A decentralized ledger/protocol for making on-chain or off-chain attestations about anything._
+- **[Ethereum Attestation Service (EAS)](https://attest.sh/)** - _A decentralized ledger/protocol for making onchain or offchain attestations about anything._
- **[Proof of Humanity](https://www.proofofhumanity.id)** - _Proof of Humanity (or PoH) is a social identity verification system built on Ethereum._
- **[BrightID](https://www.brightid.org/)** - _A decentralized, open-source social identity network seeking to reform identity verification through the creation and analysis of a social graph._
- **[walt.id](https://walt.id)** — _Open source decentralized identity and wallet infrastructure that enables developers and organizations to leverage self-sovereign identity and NFTs/SBTs._
@@ -180,7 +180,7 @@ There are many ambitious projects using Ethereum as a foundation for decentraliz
- [Decentralized Identity (Bonus Livestream Session)](https://www.youtube.com/watch?v=ySHNB1za_SE&t=539s) — _A great explainer video on decentralized identity by Andreas Antonopolous_
- [Sign In with Ethereum and Decentralized Identity with Ceramic, IDX, React, and 3ID Connect](https://www.youtube.com/watch?v=t9gWZYJxk7c) — _YouTube tutorial on building out an identity management system for creating, reading, and updating a user's profile using their Ethereum wallet by Nader Dabit_
- [BrightID - Decentralized Identity on Ethereum](https://www.youtube.com/watch?v=D3DbMFYGRoM) — _Bankless podcast episode discussing BrightID, a decentralized identity solution for Ethereum_
-- [The Off Chain Internet: Decentralized Identity & Verifiable Credentials](https://www.youtube.com/watch?v=EZ_Bb6j87mg) — EthDenver 2022 presentation by Evin McMullen
+- [The Offchain Internet: Decentralized Identity & Verifiable Credentials](https://www.youtube.com/watch?v=EZ_Bb6j87mg) — EthDenver 2022 presentation by Evin McMullen
- [Verifiable Credentials Explained](https://www.youtube.com/watch?v=ce1IdSr-Kig) - YouTube explainer video with demo by Tamino Baumann
### Communities {#communities}
diff --git a/public/content/desci/index.md b/public/content/desci/index.md
index 1abd03ddb7b..ebac2262588 100644
--- a/public/content/desci/index.md
+++ b/public/content/desci/index.md
@@ -37,7 +37,7 @@ An incomplete list of key problems in science and how decentralized science can
| **New models for publishing** can be developed that use Web3 primitives for trust, transparency and universal access. | You publish through established pathways frequently acknowledged as **inefficient, biased and exploitative**. |
| You can **earn tokens and reputation for peer-reviewing** work. | Your **peer-review work is unpaid**, benefiting for-profit publishers. |
| **You own the intellectual property (IP)** you generate and distribute it according to transparent terms. | **Your home institution owns the IP** you generate. Access to the IP is not transparent. |
-| **Sharing all of the research**, including the data from unsuccessful efforts, by having all steps on-chain. | **Publication bias** means that researchers are more likely to share experiments that had successful results. |
+| **Sharing all of the research**, including the data from unsuccessful efforts, by having all steps onchain. | **Publication bias** means that researchers are more likely to share experiments that had successful results. |
## Ethereum and DeSci {#ethereum-and-desci}
@@ -76,7 +76,7 @@ Intellectual property (IP) is a big problem in traditional science: from being s
In the same way that NFTs can pass revenue for future transactions back to the original creator, you can establish transparent value attribution chains to reward researchers, governing bodies (like DAOs), or even the subjects whose data is collected.
-[IP-NFTs](https://medium.com/molecule-blog/ip-nfts-for-researchers-a-new-biomedical-funding-paradigm-91312d8d92e6) can also function as a key to a decentralized data repository of the research experiments being undertaken, and plug into NFT and [DeFi](/glossary/#defi) financialization (from fractionalization to lending pools and value appraisal). It also allows natively on-chain entities such as DAOs like [VitaDAO](https://www.vitadao.com/) to conduct research directly on-chain.
+[IP-NFTs](https://medium.com/molecule-blog/ip-nfts-for-researchers-a-new-biomedical-funding-paradigm-91312d8d92e6) can also function as a key to a decentralized data repository of the research experiments being undertaken, and plug into NFT and [DeFi](/glossary/#defi) financialization (from fractionalization to lending pools and value appraisal). It also allows natively onchain entities such as DAOs like [VitaDAO](https://www.vitadao.com/) to conduct research directly onchain.
The advent of non-transferable ["soulbound" tokens](https://vitalik.eth.limo/general/2022/01/26/soulbound.html) may also play an important role in DeSci by allowing individuals to prove their experience and credentials linked to their Ethereum address.
### Data storage, access and architecture {#data-storage}
diff --git a/public/content/developers/docs/consensus-mechanisms/pos/attack-and-defense/index.md b/public/content/developers/docs/consensus-mechanisms/pos/attack-and-defense/index.md
index 048cf885b47..d51c63752c4 100644
--- a/public/content/developers/docs/consensus-mechanisms/pos/attack-and-defense/index.md
+++ b/public/content/developers/docs/consensus-mechanisms/pos/attack-and-defense/index.md
@@ -16,7 +16,7 @@ A common misconception is that a successful attacker can generate new ether, or
A **“reorg”** is a reshuffling of blocks into a new order, perhaps with some addition or subtraction of blocks in the canonical chain. A malicious reorg might ensure specific blocks are included or excluded, allowing double-spending or value extraction by front-running and back-running transactions (MEV). Re-orgs could also be used to prevent certain transactions from being included in the canonical chain - a form of censorship. The most extreme form of reorg is “finality reversion” which removes or replaces blocks that have previously been finalized. This is only possible if more than ⅓ of the total staked ether is destroyed by the attacker - this guarantee is known as “economic finality” - more on this later.
-**Double finality** is the unlikely but severe condition where two forks are able to finalize simultaneously, creating a permanent schism in the chain. This is theoretically possible for an attacker willing to risk 34% of the total staked ether. The community would be forced to coordinate off-chain and come to an agreement about which chain to follow, which would require strength in the social layer.
+**Double finality** is the unlikely but severe condition where two forks are able to finalize simultaneously, creating a permanent schism in the chain. This is theoretically possible for an attacker willing to risk 34% of the total staked ether. The community would be forced to coordinate offchain and come to an agreement about which chain to follow, which would require strength in the social layer.
A **finality delay** attack prevents the network from reaching the necessary conditions finalizing sections of the chain. Without finality, it is hard to trust financial applications built on top of Ethereum. The aim of a finality delay attack is likely simply to disrupt Ethereum rather than to directly profit, unless the attacker has some strategic short position(s).
@@ -127,7 +127,7 @@ One of the strengths of Ethereum’s PoS consensus is that there are a [range of
Whatever the penalty imposed on the attacker, the community also has to decide together whether the dishonest chain, despite being the one favored by the fork choice algorithm coded into the Ethereum clients, is in fact invalid and that the community should build on top of the honest chain instead. Honest validators could collectively agree to build on top of a community-accepted fork of the Ethereum blockchain that might, for example, have forked off the canonical chain before the attack started or have the attackers’ validators forcibly removed. Honest validators would be incentivized to build on this chain because they would avoid the penalties applied to them for failing (rightly) to attest to the attacker’s chain. Exchanges, on-ramps and applications built on Ethereum would presumably prefer to be on the honest chain and would follow the honest validators to the honest blockchain.
-However, this would be a substantial governance challenge. Some users and validators would undoubtedly lose out as a result of the switch back to the honest chain, transactions in blocks validated after the attack could potentially be rolled back, disrupting the application layer, and it quite simply undermines the ethics of some users who tend to believe “code is law”. Exchanges and applications will most likely have linked off-chain actions to on-chain transactions that may now be rolled back, starting a cascade of retractions and revisions that would be hard to unpick fairly, especially if ill-gotten gains have been mixed, deposited into DeFi or other derivatives with secondary effects for honest users. Undoubtedly some users, perhaps even institutional ones, would have already benefited from the dishonest chain either by being shrewd or by serendipity, and might oppose a fork to protect their gains. There have been calls to rehearse the community response to >51% attacks so that a sensible coordinated mitigation could be executed quickly. There is some useful discussion by Vitalik on ethresear.ch [here](https://ethresear.ch/t/timeliness-detectors-and-51-attack-recovery-in-blockchains/6925) and [here](https://ethresear.ch/t/responding-to-51-attacks-in-casper-ffg/6363) and on Twitter [here](https://twitter.com/skylar_eth/status/1551798684727508992?s=20&t=oHZ1xv8QZdOgAXhxZKtHEw). The aim of a coordinated social response should be to be very targeted and specific about punishing the attacker and minimizing effects for other users.
+However, this would be a substantial governance challenge. Some users and validators would undoubtedly lose out as a result of the switch back to the honest chain, transactions in blocks validated after the attack could potentially be rolled back, disrupting the application layer, and it quite simply undermines the ethics of some users who tend to believe “code is law”. Exchanges and applications will most likely have linked offchain actions to onchain transactions that may now be rolled back, starting a cascade of retractions and revisions that would be hard to unpick fairly, especially if ill-gotten gains have been mixed, deposited into DeFi or other derivatives with secondary effects for honest users. Undoubtedly some users, perhaps even institutional ones, would have already benefited from the dishonest chain either by being shrewd or by serendipity, and might oppose a fork to protect their gains. There have been calls to rehearse the community response to >51% attacks so that a sensible coordinated mitigation could be executed quickly. There is some useful discussion by Vitalik on ethresear.ch [here](https://ethresear.ch/t/timeliness-detectors-and-51-attack-recovery-in-blockchains/6925) and [here](https://ethresear.ch/t/responding-to-51-attacks-in-casper-ffg/6363) and on Twitter [here](https://twitter.com/skylar_eth/status/1551798684727508992?s=20&t=oHZ1xv8QZdOgAXhxZKtHEw). The aim of a coordinated social response should be to be very targeted and specific about punishing the attacker and minimizing effects for other users.
Governance is already a complicated topic. Managing a Layer-0 emergency response to a dishonest finalizing chain would undoubtedly be challenging for the Ethereum community, but it [has happened](/history/#dao-fork-summary) - [twice](/history/#tangerine-whistle) - in Ethereum’s history).
diff --git a/public/content/developers/docs/consensus-mechanisms/pos/keys/index.md b/public/content/developers/docs/consensus-mechanisms/pos/keys/index.md
index 8778b06972f..fbbbe284493 100644
--- a/public/content/developers/docs/consensus-mechanisms/pos/keys/index.md
+++ b/public/content/developers/docs/consensus-mechanisms/pos/keys/index.md
@@ -23,7 +23,7 @@ The validator signing key consists of two elements:
- Validator **private** key
- Validator **public** key
-The purpose of the validator private key is to sign on-chain operations such as block proposals and attestations. Because of this, these keys must be held in a hot wallet.
+The purpose of the validator private key is to sign onchain operations such as block proposals and attestations. Because of this, these keys must be held in a hot wallet.
This flexibility has the advantage of moving validator signing keys very quickly from one device to another, however, if they have gotten lost or stolen, a thief may be able to **act maliciously** in a few ways:
@@ -56,6 +56,8 @@ Separating the validator keys from the Ethereum account keys enables multiple va

+**Note**: Exiting from staking duties and withdrawing a validator's balance currently requires signing a [voluntary exit message (VEM)](https://mirror.xyz/ladislaus.eth/wmoBbUBes2Wp1_6DvP6slPabkyujSU7MZOFOC3QpErs&1) with the validator key. However, [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002) is a proposal that will allow a user to trigger a validator's exit and withdrawals its balance by signing exit messages with the withdrawal key in the future. This will reduce trust assumptions by enabling stakers who delegate ETH to [staking-as-a-service providers](https://ethereum.org/en/staking/saas/#what-is-staking-as-a-service) to remain in control of their funds.
+
## Deriving keys from a seed phrase {#deriving-keys-from-seed}
If every 32 ETH staked required a new set of 2 completely independent keys, key management would quickly become unwieldy, especially for users running multiple validators. Instead, multiple validator keys can be derived from a single common secret and storing that single secret allows access to multiple validator keys.
@@ -94,3 +96,5 @@ Each branch is separated by a `/` so `m/2` means start with the master key and f
- [Ethereum Foundation blog post by Carl Beekhuizen](https://blog.ethereum.org/2020/05/21/keys/)
- [EIP-2333 BLS12-381 key generation](https://eips.ethereum.org/EIPS/eip-2333)
+- [EIP-7002: Execution Layer Triggered Exits](https://research.2077.xyz/eip-7002-unpacking-improvements-to-staking-ux-post-merge)
+- [Key management at scale](https://docs.ethstaker.cc/ethstaker-knowledge-base/scaled-node-operators/key-management-at-scale)
diff --git a/public/content/developers/docs/consensus-mechanisms/pos/rewards-and-penalties/index.md b/public/content/developers/docs/consensus-mechanisms/pos/rewards-and-penalties/index.md
index 696a4a285ec..f71cf730371 100644
--- a/public/content/developers/docs/consensus-mechanisms/pos/rewards-and-penalties/index.md
+++ b/public/content/developers/docs/consensus-mechanisms/pos/rewards-and-penalties/index.md
@@ -84,6 +84,8 @@ The reward, penalty and slashing design of the consensus mechanism encourages in
- [Incentives in Ethereum's hybrid Casper protocol](https://arxiv.org/pdf/1903.04205.pdf)
- [Vitalik's annotated spec](https://github.com/ethereum/annotated-spec/blob/master/phase0/beacon-chain.md#rewards-and-penalties-1)
- [Eth2 Slashing Prevention Tips](https://medium.com/prysmatic-labs/eth2-slashing-prevention-tips-f6faa5025f50)
+- [EIP-7251 Explained: Increasing Maximum Effective Balance For Validators](https://research.2077.xyz/eip-7251_Increase_MAX_EFFECTIVE_BALANCE)
+- [Analysis of slashing penalties under EIP-7251](https://ethresear.ch/t/slashing-penalty-analysis-eip-7251/16509)
_Sources_
diff --git a/public/content/developers/docs/data-and-analytics/block-explorers/index.md b/public/content/developers/docs/data-and-analytics/block-explorers/index.md
index 463812d447d..0617a850b0d 100644
--- a/public/content/developers/docs/data-and-analytics/block-explorers/index.md
+++ b/public/content/developers/docs/data-and-analytics/block-explorers/index.md
@@ -5,7 +5,7 @@ lang: en
sidebarDepth: 3
---
-Block explorers are your portal to Ethereum's data. You can use them to see real-time data on blocks, transactions, validators, accounts, and other on-chain activity.
+Block explorers are your portal to Ethereum's data. You can use them to see real-time data on blocks, transactions, validators, accounts, and other onchain activity.
## Prerequisites {#prerequisites}
diff --git a/public/content/developers/docs/data-and-analytics/index.md b/public/content/developers/docs/data-and-analytics/index.md
index c2de60c04df..3953cb1fbdb 100644
--- a/public/content/developers/docs/data-and-analytics/index.md
+++ b/public/content/developers/docs/data-and-analytics/index.md
@@ -1,12 +1,12 @@
---
title: Data and analytics
-description: How to get on-chain analytics and data for use in your dapps
+description: How to get onchain analytics and data for use in your dapps
lang: en
---
## Introduction {#Introduction}
-As utilization of the network continues to grow, an increasing amount of valuable information will exist in the on-chain data. As the volume of data rapidly increases, calculating and aggregating this information to report upon or drive a dapp can become a time and process heavy endeavor.
+As utilization of the network continues to grow, an increasing amount of valuable information will exist in the onchain data. As the volume of data rapidly increases, calculating and aggregating this information to report upon or drive a dapp can become a time and process heavy endeavor.
Leveraging existing data providers can expedite development, produce more accurate results, and reduce ongoing maintenance efforts. This will enable a team to concentrate on the core functionality their project is trying to provide.
@@ -18,13 +18,13 @@ In terms of architectural fundamentals, understanding what an [API](https://www.
## Block explorers {#block-explorers}
-Many [Block Explorers](/developers/docs/data-and-analytics/block-explorers/) offer [RESTful](https://www.wikipedia.org/wiki/Representational_state_transfer) [API](https://www.wikipedia.org/wiki/API) gateways that will provide developers visibility into real-time data on blocks, transactions, validators, accounts, and other on-chain activity.
+Many [Block Explorers](/developers/docs/data-and-analytics/block-explorers/) offer [RESTful](https://www.wikipedia.org/wiki/Representational_state_transfer) [API](https://www.wikipedia.org/wiki/API) gateways that will provide developers visibility into real-time data on blocks, transactions, validators, accounts, and other onchain activity.
Developers can then process and transform this data to give their users unique insights and interactions with the [blockchain](/glossary/#blockchain). For example, [Etherscan](https://etherscan.io) provides execution and consensus data for every 12s slot.
## The Graph {#the-graph}
-The [Graph Network](https://thegraph.com/) is a decentralized indexing protocol for organizing blockchain data. Instead of building and managing off-chain and centralized data stores to aggregate on-chain data, with The Graph, developers can build serverless applications that run entirely on public infrastructure.
+The [Graph Network](https://thegraph.com/) is a decentralized indexing protocol for organizing blockchain data. Instead of building and managing offchain and centralized data stores to aggregate onchain data, with The Graph, developers can build serverless applications that run entirely on public infrastructure.
Using [GraphQL](https://graphql.org/), developers can query any of the curated open APIs, known as sub-graphs, to acquire the necessary information they need to drive their dapp. By querying these indexed sub-graphs, Reports and dapps not only get performance and scalability benefits but also the built in accuracy provided by network consensus. As new improvements and/or sub-graphs are added to the network, your projects can rapidly iterate to take advantage of these enhancements.
@@ -34,7 +34,7 @@ Using [GraphQL](https://graphql.org/), developers can query any of the curated o
## Dune Analytics {#dune-analytics}
-[Dune Analytics](https://dune.com/) pre-processes blockchain data into relational database (DuneSQL) tables, allows users to query blockchain data using SQL and build dashboards based on query results. On-chain data are organized into 4 raw tables: `blocks`, `transactions`, (event) `logs` and (call) `traces`. Popular contracts and protocols have been decoded, and each has its own set of event and call tables. Those event and call tables are processed further and organized into abstraction tables by the type of protocols, for example, dex, lending, stablecoins, etc.
+[Dune Analytics](https://dune.com/) pre-processes blockchain data into relational database (DuneSQL) tables, allows users to query blockchain data using SQL and build dashboards based on query results. Onchain data are organized into 4 raw tables: `blocks`, `transactions`, (event) `logs` and (call) `traces`. Popular contracts and protocols have been decoded, and each has its own set of event and call tables. Those event and call tables are processed further and organized into abstraction tables by the type of protocols, for example, dex, lending, stablecoins, etc.
## SubQuery Network {#subquery-network}
@@ -45,11 +45,15 @@ To start, visit the [Ethereum quick start guide](https://academy.subquery.networ
## Ethernow - Mempool Data Program {#ethernow}
[Blocknative](https://www.blocknative.com/) provides open access to its Ethereum historical [mempool data archive](https://www.ethernow.xyz/mempool-data-archive). This enables researchers and community good projects to explore the pre-chain layer of Ethereum Mainnet. The data set is actively maintained and represents the most comprehensive historical record of mempool transaction events within the Ethereum ecosystem. Learn more at [Ethernow](https://www.ethernow.xyz/).
-## Further Reading {#further-reading}
+## EVM Query Language
+
+EVM Query Language (EQL) is an SQL-like language designed to query EVM (Ethereum Virtual Machine) chains. EQL's ultimate goal is to support complex relational queries on EVM chain first-class citizens (blocks, accounts, and transactions) while providing developers and researchers with an ergonomic syntax for everyday use. With EQL, developers can fetch blockchain data using familiar SQL-like syntax and eliminate the need for complex boilerplate code. EQL supports standard blockchain data requests (e.g., retrieving an account's nonce and balance on Ethereum or fetching the current block size and timestamp) and is continually adding support for more complex requests and featuresets.
+## Further Reading {#further-reading}
+- [Exploring Crypto Data I: Data Flow Architectures](https://research.2077.xyz/exploring-crypto-data-1-data-flow-architectures)
- [Graph Network Overview](https://thegraph.com/docs/en/about/network/)
- [Graph Query Playground](https://thegraph.com/explorer/subgraph/graphprotocol/graph-network-mainnet?version=current)
- [API code examples on EtherScan](https://etherscan.io/apis#contracts)
- [Beaconcha.in Beacon Chain explorer](https://beaconcha.in)
- [Dune Basics](https://docs.dune.com/#dune-basics)
-- [SubQuery Ethereum Quick Start Guide](https://academy.subquery.network/indexer/quickstart/quickstart_chains/ethereum-gravatar.html)
+- [EVM Query Language](https://eql.sh/blog/alpha-release-notes)
diff --git a/public/content/developers/docs/data-availability/index.md b/public/content/developers/docs/data-availability/index.md
index 6900b9527b7..f56bf33373b 100644
--- a/public/content/developers/docs/data-availability/index.md
+++ b/public/content/developers/docs/data-availability/index.md
@@ -6,7 +6,7 @@ lang: en
"Don't trust, verify" is a common maxim in Ethereum. The idea is that your node can independently verify that the information it receives is correct by executing all the transactions in the blocks they receive from peers to ensure that the changes proposed precisely match those computed independently by the node. This means nodes do not have to trust that the senders of the block are honest. This is not possible if data is missing.
-**Data availability** refers to the confidence a user can have that the data required to verify a block is really available to all network participants. For full nodes on Ethereum layer 1 this is relatively simple; the full node downloads a copy of all the data in each block - the data _has_ to be available for the downloading to be possible. A block with missing data would be discarded rather than being added to the blockchain. This is "on chain data availability" and it is a feature of monolithic blockchains. Full nodes cannot be tricked into accepting invalid transactions because they download and execute every transaction for themselves. However, for modular blockchains, layer 2 rollups and light clients, the data availability landscape is more complex, requiring some more sophisticated verification procedures.
+**Data availability** refers to the confidence a user can have that the data required to verify a block is really available to all network participants. For full nodes on Ethereum layer 1 this is relatively simple; the full node downloads a copy of all the data in each block - the data _has_ to be available for the downloading to be possible. A block with missing data would be discarded rather than being added to the blockchain. This is "onchain data availability" and it is a feature of monolithic blockchains. Full nodes cannot be tricked into accepting invalid transactions because they download and execute every transaction for themselves. However, for modular blockchains, layer 2 rollups and light clients, the data availability landscape is more complex, requiring some more sophisticated verification procedures.
## Prerequisites {#prerequisites}
@@ -32,7 +32,7 @@ DAS will be used to ensure rollup operators make their transaction data availabl
Data Availability Committees (DACs) are trusted parties that provide, or attest to, data availability. DACs can be used instead of, [or in combination with](https://hackmd.io/@vbuterin/sharding_proposal#Why-not-use-just-committees-and-not-DAS) DAS. The security guarantees that come with committees depends on the specific set up. Ethereum uses randomly sampled subsets of validators to attest to data availability for light nodes, for example.
-DACs are also used by some validiums. The DAC is a trusted set of nodes that stores copies of data offline. The DAC is required to make the data available in the event of a dispute. Members of the DAC also publish on-chain attestations to prove that the said data is indeed available. Some validiums replace DACs with a proof-of-stake (PoS) validator system. Here, anyone can become a validator and store data off-chain. However, they must provide a “bond”, which is deposited in a smart contract. In the event of malicious behavior, such as the validator withholding data, the bond can be slashed. Proof-of-stake data availability committees are considerably more secure than regular DACs because they directly incentivize honest behavior.
+DACs are also used by some validiums. The DAC is a trusted set of nodes that stores copies of data offline. The DAC is required to make the data available in the event of a dispute. Members of the DAC also publish onchain attestations to prove that the said data is indeed available. Some validiums replace DACs with a proof-of-stake (PoS) validator system. Here, anyone can become a validator and store data offchain. However, they must provide a “bond”, which is deposited in a smart contract. In the event of malicious behavior, such as the validator withholding data, the bond can be slashed. Proof-of-stake data availability committees are considerably more secure than regular DACs because they directly incentivize honest behavior.
## Data availability and light nodes {#data-availability-and-light-nodes}
@@ -54,11 +54,11 @@ Even in this scenario, attacks that withhold just a few bytes could feasibly go
## Data availability and layer 2 rollups {#data-availability-and-layer-2-rollups}
-[Layer 2 scaling solutions](/layer-2/), such as [rollups](/glossary/#rollups), reduce transaction costs and increase Ethereum's throughput by processing transactions off-chain. Rollup transactions are compressed and posted on Ethereum in batches. Batches represent thousands of individual off-chain transactions in a single transaction on Ethereum. This reduces congestion on the base layer and reduces fees for users.
+[Layer 2 scaling solutions](/layer-2/), such as [rollups](/glossary/#rollups), reduce transaction costs and increase Ethereum's throughput by processing transactions offchain. Rollup transactions are compressed and posted on Ethereum in batches. Batches represent thousands of individual offchain transactions in a single transaction on Ethereum. This reduces congestion on the base layer and reduces fees for users.
-However, it is only possible to trust the 'summary' transactions posted to Ethereum if the state change proposed can be independently verified and confirmed to be the result of applying all the individual off-chain transactions. If rollup operators do not make the transaction data available for this verification, then they could send incorrect data to Ethereum.
+However, it is only possible to trust the 'summary' transactions posted to Ethereum if the state change proposed can be independently verified and confirmed to be the result of applying all the individual offchain transactions. If rollup operators do not make the transaction data available for this verification, then they could send incorrect data to Ethereum.
-[Optimistic rollups](/developers/docs/scaling/optimistic-rollups/) post compressed transaction data to Ethereum and wait for some amount of time (typically 7 days) to allow independent verifiers to check the data. If anyone identifies a problem, they can generate a fraud-proof and use it to challenge the rollup. This would cause the chain to roll back and omit the invalid block. This is only possible if data is available. Currently, there are two ways that optimistic rollups post transaction data to L1. Some rollups make data permanently available as `CALLDATA` which lives permanently on-chain. With the implementation of EIP-4844, some rollups post their transaction data to cheaper blob storage instead. This is not permanent storage. Independent verifiers have to query the blobs and raise their challenges within ~18 days before the data is deleted from Ethereum layer-1. Data availability is only guaranteed by the Ethereum protocol for that short fixed window. After that, it becomes the responsibility of other entities in the Ethereum ecosystem. Any node can verify data availability using DAS, i.e. by downloading small, random samples of the blob data.
+[Optimistic rollups](/developers/docs/scaling/optimistic-rollups/) post compressed transaction data to Ethereum and wait for some amount of time (typically 7 days) to allow independent verifiers to check the data. If anyone identifies a problem, they can generate a fraud-proof and use it to challenge the rollup. This would cause the chain to roll back and omit the invalid block. This is only possible if data is available. Currently, there are two ways that optimistic rollups post transaction data to L1. Some rollups make data permanently available as `CALLDATA` which lives permanently onchain. With the implementation of EIP-4844, some rollups post their transaction data to cheaper blob storage instead. This is not permanent storage. Independent verifiers have to query the blobs and raise their challenges within ~18 days before the data is deleted from Ethereum layer-1. Data availability is only guaranteed by the Ethereum protocol for that short fixed window. After that, it becomes the responsibility of other entities in the Ethereum ecosystem. Any node can verify data availability using DAS, i.e. by downloading small, random samples of the blob data.
[Zero-knowledge (ZK) rollups](/developers/docs/scaling/zk-rollups) don't need to post transaction data since [zero-knowledge validity proofs](/glossary/#zk-proof) guarantee the correctness of state transitions. However, data availability is still an issue because we can't guarantee the functionality of the ZK-rollup (or interact with it) without access to its state data. For example, users cannot know their balances if an operator withholds details about the rollup’s state. Also, they cannot perform state updates using information contained in a newly added block.
@@ -74,7 +74,7 @@ The core Ethereum protocol is primarily concerned with data availability, not da
- [WTF is Data Availability?](https://medium.com/blockchain-capital-blog/wtf-is-data-availability-80c2c95ded0f)
- [What Is Data Availability?](https://coinmarketcap.com/alexandria/article/what-is-data-availability)
-- [The Ethereum Off-Chain Data Availability Landscape](https://blog.celestia.org/ethereum-off-chain-data-availability-landscape/)
+- [The Ethereum Offchain Data Availability Landscape](https://blog.celestia.org/ethereum-offchain-data-availability-landscape/)
- [A primer on data availability checks](https://dankradfeist.de/ethereum/2019/12/20/data-availability-checks.html)
- [An explanation of the sharding + DAS proposal](https://hackmd.io/@vbuterin/sharding_proposal#ELI5-data-availability-sampling)
- [A note on data availability and erasure coding](https://github.com/ethereum/research/wiki/A-note-on-data-availability-and-erasure-coding#can-an-attacker-not-circumvent-this-scheme-by-releasing-a-full-unavailable-block-but-then-only-releasing-individual-bits-of-data-as-clients-query-for-them)
diff --git a/public/content/developers/docs/design-and-ux/index.md b/public/content/developers/docs/design-and-ux/index.md
index 43749e9012b..c9d9a8eddbe 100644
--- a/public/content/developers/docs/design-and-ux/index.md
+++ b/public/content/developers/docs/design-and-ux/index.md
@@ -23,7 +23,7 @@ This is a curated list of user research done in web3 that may help with design a
| Area of focus | Name |
| :------------------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Crypto onboarding | [The WalletConnect Pulse 2024: Crypto Consumer Sentiment & Usage](https://walletconnect.com/pulse-2024-crypto-consumer-report) |
+| Crypto onboarding | [The Reown Pulse 2024: Crypto Consumer Sentiment & Usage](https://reown.com/blog/unveiling-walletconnects-consumer-crypto-report) |
| Crypto onboarding | [CRADL: UX in Cryptocurrency](https://docs.google.com/presentation/d/1s2OPSH5sMJzxRYaJSSRTe8W2iIoZx0PseIV-WeZWD1s/edit?usp=sharing) |
| Crypto onboarding | [CRADL: Onboarding to Cryptocurrency](https://docs.google.com/presentation/d/1R9nFuzA-R6SxaGCKhoMbE4Vxe0JxQSTiHXind3LVq_w/edit?usp=sharing) |
| Crypto onboarding | [Bitcoin UX report](https://github.com/patestevao/BitcoinUX-report/blob/master/report.md) |
@@ -45,7 +45,6 @@ This is a curated list of user research done in web3 that may help with design a
- [Web3 UX Design Handbook](https://web3ux.design/) - Practical guide to designing Web3 apps
- [Web3 Design Principles](https://medium.com/@lyricalpolymath/web3-design-principles-f21db2f240c1) - A framework of UX rules for blockchain based dapps
- [Blockchain Design Principles](https://medium.com/design-ibm/blockchain-design-principles-599c5c067b6e) - Lessons learned by the blockchain design team at IBM
-- [Web3 Design Patterns](https://www.web3designpatterns.io/)- A curated library of design patterns from real Web3 products
- [W3design.io](https://w3design.io/) - A curated library of UI flows of different projects in the ecosystem
- [Neueux.com](https://neueux.com/apps) - UI library of user flows with diverse filtering options
- [Web3's Usability Crisis: What You NEED to Know!](https://www.youtube.com/watch?v=oBSXT_6YDzg) - A panel discussion on pitfalls of developer focused project building (video, 34 min)
@@ -58,7 +57,6 @@ This is a curated list of user research done in web3 that may help with design a
## Web3 Design Case Studies {#design-case-studies}
- [Deep Work Studio](https://deepwork.studio/case-studies/)
-- [Crypto UX Handbook](https://www.cryptouxhandbook.com/)
- [Selling an NFT on OpenSea](https://builtformars.com/case-studies/opensea)
- [Wallet UX teardown how wallets need to change](https://www.youtube.com/watch?v=oTpuxYj8JWI&ab_channel=ETHDenver) (video, 20 min)
@@ -79,7 +77,7 @@ Get involved in professional community-driven organizations or join design group
- [Openux.xyz](https://openux.xyz/)
- [Open Source Web3Design](https://www.web3designers.org/)
-## Design Systems {#design-systems}
+## Design Systems and other design resources {#design-systems-and-resources}
- [Optimism Design](https://www.figma.com/@optimism) (Figma)
- [Ethereum.org Design system](https://www.figma.com/@ethdotorg) (Figma)
diff --git a/public/content/developers/docs/gas/index.md b/public/content/developers/docs/gas/index.md
index e6feee8496a..ac91fbaaaca 100644
--- a/public/content/developers/docs/gas/index.md
+++ b/public/content/developers/docs/gas/index.md
@@ -140,4 +140,5 @@ If you want to monitor gas prices, so you can send your ETH for less, you can us
- [Proof of Stake versus Proof of Work](https://blockgeeks.com/guides/proof-of-work-vs-proof-of-stake/)
- [Gas Optimization Strategies for Developers](https://www.alchemy.com/overviews/solidity-gas-optimization)
- [EIP-1559 docs](https://eips.ethereum.org/EIPS/eip-1559).
-- [Tim Beiko's EIP-1559 Resources](https://hackmd.io/@timbeiko/1559-resources).
+- [Tim Beiko's EIP-1559 Resources](https://hackmd.io/@timbeiko/1559-resources)
+- [EIP-1559: Separating Mechanisms From Memes](https://research.2077.xyz/eip-1559-separating-mechanisms-from-memes)
diff --git a/public/content/developers/docs/intro-to-ether/index.md b/public/content/developers/docs/intro-to-ether/index.md
index b794ee17afe..38ea4508fbe 100644
--- a/public/content/developers/docs/intro-to-ether/index.md
+++ b/public/content/developers/docs/intro-to-ether/index.md
@@ -40,7 +40,7 @@ As well as creating ether through block rewards, ether can be destroyed through
Ether burn occurs in every transaction on Ethereum. When users pay for their transactions, a base gas fee, set by the network according to transactional demand, gets destroyed. This, coupled with variable block sizes and a maximum gas fee, simplifies transaction fee estimation on Ethereum. When network demand is high, [blocks](https://etherscan.io/block/12965263) can burn more ether than they mint, effectively offsetting ether issuance.
-Burning the base fee hinders a block producer's ability to manipulate transactions. For example, if block producers received the base fee, they could include their own transactions for free and raise the base fee for everyone else. Alternatively, they could refund the base fee to some users off-chain, leading to a more opaque and complex transaction fee market.
+Burning the base fee hinders a block producer's ability to manipulate transactions. For example, if block producers received the base fee, they could include their own transactions for free and raise the base fee for everyone else. Alternatively, they could refund the base fee to some users offchain, leading to a more opaque and complex transaction fee market.
## Denominations of ether {#denominations}
diff --git a/public/content/developers/docs/mev/index.md b/public/content/developers/docs/mev/index.md
index 68483f19370..f259f7fc55d 100644
--- a/public/content/developers/docs/mev/index.md
+++ b/public/content/developers/docs/mev/index.md
@@ -108,7 +108,7 @@ This possibility of blockchain re-organization has been [previously explored on
## State of MEV {#state-of-mev}
-MEV extraction ballooned in early 2021, resulting in extremely high gas prices in the first few months of the year. The emergence of Flashbots's MEV relay has reduced the effectiveness of generalized frontrunners and has taken gas price auctions off-chain, lowering gas prices for ordinary users.
+MEV extraction ballooned in early 2021, resulting in extremely high gas prices in the first few months of the year. The emergence of Flashbots's MEV relay has reduced the effectiveness of generalized frontrunners and has taken gas price auctions offchain, lowering gas prices for ordinary users.
While many searchers are still making good money from MEV, as opportunities become more well-known and more and more searchers compete for the same opportunity, validators will capture more and more total MEV revenue (because the same sort of gas auctions as originally described above also occur in Flashbots, albeit privately, and validators will capture the resulting gas revenue). MEV is also not unique to Ethereum, and as opportunities become more competitive on Ethereum, searchers are moving to alternate blockchains like Binance Smart Chain, where similar MEV opportunities as those on Ethereum exist with less competition.
@@ -130,7 +130,7 @@ With fewer resources at their disposal, solo stakers may be unable to profit fro
### Permissioned mempools {#permissioned-mempools}
-In response to sandwiching and frontrunning attacks, traders may start conducting off-chain deals with validators for transaction privacy. Instead of sending a potential MEV transaction to the public mempool, the trader sends it directly to the validator, who includes it in a block and splits profits with the trader.
+In response to sandwiching and frontrunning attacks, traders may start conducting offchain deals with validators for transaction privacy. Instead of sending a potential MEV transaction to the public mempool, the trader sends it directly to the validator, who includes it in a block and splits profits with the trader.
“Dark pools” are a larger version of this arrangement and function as permissioned, access-only mempools open to users willing to pay certain fees. This trend would diminish Ethereum’s permissionlessness and trustlessness and potentially transform the blockchain into a “pay-to-play” mechanism that favors the highest bidder.
@@ -156,7 +156,7 @@ In-protocol proposer-builder separation reduces MEV’s effect on consensus by r
This doesn’t exclude validators totally from MEV-related income, though, as builders must bid high to get their blocks accepted by validators. Nevertheless, with validators no longer directly focused on optimizing MEV income, the threat of time-bandit attacks reduces.
-Proposer-builder separation also reduces MEV’s centralization risks. For instance, the use of a commit-reveal scheme removes the need for builders to trust validators not to steal the MEV opportunity or expose it to other builders. This lowers the barrier for solo stakers to benefit from MEV, otherwise, builders would trend towards favoring large pools with off-chain reputation and conducting off-chain deals with them.
+Proposer-builder separation also reduces MEV’s centralization risks. For instance, the use of a commit-reveal scheme removes the need for builders to trust validators not to steal the MEV opportunity or expose it to other builders. This lowers the barrier for solo stakers to benefit from MEV, otherwise, builders would trend towards favoring large pools with offchain reputation and conducting offchain deals with them.
Similarly, validators don’t have to trust builders not to withhold block bodies or publish invalid blocks because payment is unconditional. The validator’s fee still processes even if the proposed block is unavailable or declared invalid by other validators. In the latter case, the block is simply discarded, forcing the block builder to lose all transaction fees and MEV revenue.
diff --git a/public/content/developers/docs/nodes-and-clients/index.md b/public/content/developers/docs/nodes-and-clients/index.md
index 5da1a93f3a9..a74fec8a1bf 100644
--- a/public/content/developers/docs/nodes-and-clients/index.md
+++ b/public/content/developers/docs/nodes-and-clients/index.md
@@ -194,14 +194,14 @@ Learn more about it by reading its [documentation](https://github.com/ethereumjs
There are multiple consensus clients (previously known as 'Eth2' clients) to support the [consensus upgrades](/roadmap/beacon-chain/). They are responsible for all consensus-related logic including the fork-choice algorithm, processing attestations and managing [proof-of-stake](/developers/docs/consensus-mechanisms/pos) rewards and penalties.
-| Client | Language | Operating systems | Networks |
-| ------------------------------------------------------------- | ---------- | --------------------- | ----------------------------------------------------------------- |
-| [Lighthouse](https://lighthouse.sigmaprime.io/) | Rust | Linux, Windows, macOS | Beacon Chain, Goerli, Pyrmont, Sepolia, Ropsten, and more |
-| [Lodestar](https://lodestar.chainsafe.io/) | TypeScript | Linux, Windows, macOS | Beacon Chain, Goerli, Sepolia, Ropsten, and more |
-| [Nimbus](https://nimbus.team/) | Nim | Linux, Windows, macOS | Beacon Chain, Goerli, Sepolia, Ropsten, and more |
-| [Prysm](https://docs.prylabs.network/docs/getting-started/) | Go | Linux, Windows, macOS | Beacon Chain, Gnosis, Goerli, Pyrmont, Sepolia, Ropsten, and more |
-| [Teku](https://consensys.net/knowledge-base/ethereum-2/teku/) | Java | Linux, Windows, macOS | Beacon Chain, Gnosis, Goerli, Sepolia, Ropsten, and more |
-| [Grandine](https://docs.grandine.io/) (beta) | Rust | Linux, Windows, macOS | Beacon Chain, Goerli, Sepolia, and more |
+| Client | Language | Operating systems | Networks |
+| ------------------------------------------------------------- | ---------- | --------------------- | --------------------------------------------------------- |
+| [Lighthouse](https://lighthouse.sigmaprime.io/) | Rust | Linux, Windows, macOS | Beacon Chain, Holesky, Pyrmont, Sepolia, and more |
+| [Lodestar](https://lodestar.chainsafe.io/) | TypeScript | Linux, Windows, macOS | Beacon Chain, Holesky, Sepolia, and more |
+| [Nimbus](https://nimbus.team/) | Nim | Linux, Windows, macOS | Beacon Chain, Holesky, Sepolia, and more |
+| [Prysm](https://docs.prylabs.network/docs/getting-started/) | Go | Linux, Windows, macOS | Beacon Chain, Gnosis, Holesky, Pyrmont, Sepolia, and more |
+| [Teku](https://consensys.net/knowledge-base/ethereum-2/teku/) | Java | Linux, Windows, macOS | Beacon Chain, Gnosis, Holesky, Sepolia, and more |
+| [Grandine](https://docs.grandine.io/) | Rust | Linux, Windows, macOS | Beacon Chain, Holesky, Sepolia, and more |
### Lighthouse {#lighthouse}
diff --git a/public/content/developers/docs/nodes-and-clients/nodes-as-a-service/index.md b/public/content/developers/docs/nodes-and-clients/nodes-as-a-service/index.md
index 4ab1b1247c6..cdc47d6a482 100644
--- a/public/content/developers/docs/nodes-and-clients/nodes-as-a-service/index.md
+++ b/public/content/developers/docs/nodes-and-clients/nodes-as-a-service/index.md
@@ -226,7 +226,7 @@ Here is a list of some of the most popular Ethereum node providers, feel free to
- 500+ administrative and service APIs
- RESTful interface for Ethereum transaction submission (Apache Kafka backed)
- Outbound streams for event delivery (Apache Kafka backed)
- - Deep collection of "off-chain" and ancillary services (e.g. bilateral encrypted messaging transport)
+ - Deep collection of "offchain" and ancillary services (e.g. bilateral encrypted messaging transport)
- Straightforward network onboarding with governance and role-based access control
- Sophisticated user management for both administrators and end users
- Highly scalable, resilient, enterprise-grade infrastructure
diff --git a/public/content/developers/docs/oracles/index.md b/public/content/developers/docs/oracles/index.md
index b119328b1cb..97b3c100e81 100644
--- a/public/content/developers/docs/oracles/index.md
+++ b/public/content/developers/docs/oracles/index.md
@@ -4,9 +4,9 @@ description: Oracles provide Ethereum smart contracts with access to real-world
lang: en
---
-Oracles are applications that produce data feeds that make off-chain data sources available to the blockchain for smart contracts. This is necessary because Ethereum-based smart contracts cannot, by default, access information stored outside the blockchain network.
+Oracles are applications that produce data feeds that make offchain data sources available to the blockchain for smart contracts. This is necessary because Ethereum-based smart contracts cannot, by default, access information stored outside the blockchain network.
-Giving smart contracts the ability to execute using off-chain data extends the utility and value of decentralized applications. For instance, on-chain prediction markets rely on oracles to provide information about outcomes that they use to validate user predictions. Suppose Alice bets 20 ETH on who will become the next U.S. President. In that case, the prediction-market dapp needs an oracle to confirm election results and determine if Alice is eligible for a payout.
+Giving smart contracts the ability to execute using offchain data extends the utility and value of decentralized applications. For instance, onchain prediction markets rely on oracles to provide information about outcomes that they use to validate user predictions. Suppose Alice bets 20 ETH on who will become the next U.S. President. In that case, the prediction-market dapp needs an oracle to confirm election results and determine if Alice is eligible for a payout.
## Prerequisites {#prerequisites}
@@ -14,11 +14,11 @@ This page assumes the reader is familiar with Ethereum fundamentals, including [
## What is a blockchain oracle? {#what-is-a-blockchain-oracle}
-Oracles are applications that source, verify, and transmit external information (i.e. information stored off-chain) to smart contracts running on the blockchain. Besides “pulling” off-chain data and broadcasting it on Ethereum, oracles can also “push” information from the blockchain to external systems, e.g., unlocking a smart lock once the user sends a fee via an Ethereum transaction.
+Oracles are applications that source, verify, and transmit external information (i.e. information stored offchain) to smart contracts running on the blockchain. Besides “pulling” offchain data and broadcasting it on Ethereum, oracles can also “push” information from the blockchain to external systems, e.g., unlocking a smart lock once the user sends a fee via an Ethereum transaction.
-Without an oracle, a smart contract would be limited entirely to on-chain data.
+Without an oracle, a smart contract would be limited entirely to onchain data.
-Oracles differ based on the source of data (one or multiple sources), trust models (centralized or decentralized), and system architecture (immediate-read, publish-subscribe, and request-response). We can also distinguish between oracles based on whether they retrieve external data for use by on-chain contracts (input oracles), send information from the blockchain to the off-chain applications (output oracles), or perform computational tasks off-chain (computational oracles).
+Oracles differ based on the source of data (one or multiple sources), trust models (centralized or decentralized), and system architecture (immediate-read, publish-subscribe, and request-response). We can also distinguish between oracles based on whether they retrieve external data for use by onchain contracts (input oracles), send information from the blockchain to the offchain applications (output oracles), or perform computational tasks offchain (computational oracles).
## Why do smart contracts need oracles? {#why-do-smart-contracts-need-oracles}
@@ -36,11 +36,11 @@ If blockchains received information from external sources (i.e. from the real wo
For a public blockchain like Ethereum, with thousands of nodes around the world processing transactions, determinism is critical. With no central authority serving as a source of truth, nodes need mechanisms for arriving at the same state after applying the same transactions. A case whereby node A executes a smart contract’s code and gets "3" as a result, while node B gets "7" after running the same transaction would cause consensus to break down and eliminate Ethereum’s value as a decentralized computing platform.
-This scenario also highlights the problem with designing blockchains to pull information from external sources. Oracles, however, solve this problem by taking information from off-chain sources and storing it on the blockchain for smart contracts to consume. Since information stored on-chain is unalterable and publicly available, Ethereum nodes can safely use the oracle imported off-chain data to compute state changes without breaking consensus.
+This scenario also highlights the problem with designing blockchains to pull information from external sources. Oracles, however, solve this problem by taking information from offchain sources and storing it on the blockchain for smart contracts to consume. Since information stored onchain is unalterable and publicly available, Ethereum nodes can safely use the oracle imported offchain data to compute state changes without breaking consensus.
-To do this, an oracle is typically made up of a smart contract running on-chain and some off-chain components. The on-chain contract receives requests for data from other smart contracts, which it passes to the off-chain component (called an oracle node). This oracle node can query data sources—using application programming interfaces (APIs), for example—and send transactions to store the requested data in the smart contract's storage.
+To do this, an oracle is typically made up of a smart contract running onchain and some offchain components. The onchain contract receives requests for data from other smart contracts, which it passes to the offchain component (called an oracle node). This oracle node can query data sources—using application programming interfaces (APIs), for example—and send transactions to store the requested data in the smart contract's storage.
-Essentially, a blockchain oracle bridges the information gap between the blockchain and the external environment, creating “hybrid smart contracts”. A hybrid smart contract is one that functions based on a combination of on-chain contract code and off-chain infrastructure. Decentralized prediction markets are an excellent example of hybrid smart contracts. Other examples might include crop insurance smart contracts that pay out when a set of oracles determine that certain weather phenomena have taken place.
+Essentially, a blockchain oracle bridges the information gap between the blockchain and the external environment, creating “hybrid smart contracts”. A hybrid smart contract is one that functions based on a combination of onchain contract code and offchain infrastructure. Decentralized prediction markets are an excellent example of hybrid smart contracts. Other examples might include crop insurance smart contracts that pay out when a set of oracles determine that certain weather phenomena have taken place.
## What is the oracle problem? {#the-oracle-problem}
@@ -54,11 +54,11 @@ The so-called “oracle problem” demonstrates the issues that come with using
Different oracles offer different solutions to the oracle problem, which we explore later. Oracles are typically evaluated on how well they can handle the following challenges:
-1. **Correctness**: An oracle should not cause smart contracts to trigger state changes based on invalid off-chain data. An oracle must guarantee _authenticity_ and _integrity_ of data. Authenticity means the data was gotten from the correct source, while integrity means the data remained intact (i.e. wasn’t altered) before being sent on-chain.
+1. **Correctness**: An oracle should not cause smart contracts to trigger state changes based on invalid offchain data. An oracle must guarantee _authenticity_ and _integrity_ of data. Authenticity means the data was gotten from the correct source, while integrity means the data remained intact (i.e. wasn’t altered) before being sent onchain.
2. **Availability**: An oracle should not delay or prevent smart contracts from executing actions and triggering state changes. This means that data from an oracle must be _available on request_ without interruption.
-3. **Incentive compatibility**: An oracle should incentivize off-chain data providers to submit correct information to smart contracts. Incentive compatibility involves _attributability_ and _accountability_. Attributability allows for linking a piece of external information to its provider, while accountability bonds data providers to the information they give, so they can be rewarded or penalized based on the quality of information provided.
+3. **Incentive compatibility**: An oracle should incentivize offchain data providers to submit correct information to smart contracts. Incentive compatibility involves _attributability_ and _accountability_. Attributability allows for linking a piece of external information to its provider, while accountability bonds data providers to the information they give, so they can be rewarded or penalized based on the quality of information provided.
## How does a blockchain oracle service work? {#how-does-a-blockchain-oracle-service-work}
@@ -66,7 +66,7 @@ Different oracles offer different solutions to the oracle problem, which we expl
Users are entities (i.e., smart contracts) that need information external to the blockchain to complete specific actions. The basic workflow of an oracle service starts with the user sending a data request to the oracle contract. Data requests will usually answer some or all of the following questions:
-1. What sources can off-chain nodes consult for the requested information?
+1. What sources can offchain nodes consult for the requested information?
2. How do reporters process information from data sources and extract useful data points?
@@ -78,11 +78,11 @@ Users are entities (i.e., smart contracts) that need information external to the
### Oracle contract {#oracle-contract}
-The oracle contract is the on-chain component for the oracle service. It listens for data requests from other contracts, relays data queries to oracle nodes, and broadcasts returned data to client contracts. This contract may also perform some computation on the returned data points to produce an aggregate value to send to the requesting contract.
+The oracle contract is the onchain component for the oracle service. It listens for data requests from other contracts, relays data queries to oracle nodes, and broadcasts returned data to client contracts. This contract may also perform some computation on the returned data points to produce an aggregate value to send to the requesting contract.
-The oracle contract exposes some functions which client contracts call when making a data request. Upon receiving a new query, the smart contract will emit a [log event](/developers/docs/smart-contracts/anatomy/#events-and-logs) with details of the data request. This notifies off-chain nodes subscribed to the log (usually using something like the JSON-RPC `eth_subscribe` command), who proceed to retrieve data defined in the log event.
+The oracle contract exposes some functions which client contracts call when making a data request. Upon receiving a new query, the smart contract will emit a [log event](/developers/docs/smart-contracts/anatomy/#events-and-logs) with details of the data request. This notifies offchain nodes subscribed to the log (usually using something like the JSON-RPC `eth_subscribe` command), who proceed to retrieve data defined in the log event.
-Below is an [example oracle contract](https://medium.com/@pedrodc/implementing-a-blockchain-oracle-on-ethereum-cedc7e26b49e) by Pedro Costa. This is a simple oracle service that can query off-chain APIs upon request by other smart contracts and store the requested information on the blockchain:
+Below is an [example oracle contract](https://medium.com/@pedrodc/implementing-a-blockchain-oracle-on-ethereum-cedc7e26b49e) by Pedro Costa. This is a simple oracle service that can query offchain APIs upon request by other smart contracts and store the requested information on the blockchain:
```solidity
pragma solidity >=0.4.21 <0.6.0;
@@ -198,11 +198,11 @@ contract Oracle {
### Oracle nodes {#oracle-nodes}
-The oracle node is the off-chain component of the oracle service. It extracts information from external sources, such as APIs hosted on third-party servers, and puts it on-chain for consumption by smart contracts. Oracle nodes listen for events from the on-chain oracle contract and proceed to complete the task described in the log.
+The oracle node is the offchain component of the oracle service. It extracts information from external sources, such as APIs hosted on third-party servers, and puts it onchain for consumption by smart contracts. Oracle nodes listen for events from the onchain oracle contract and proceed to complete the task described in the log.
-A common task for oracle nodes is sending a [HTTP GET](https://www.w3schools.com/tags/ref_httpmethods.asp) request to an API service, parsing the response to extract relevant data, formatting into a blockchain-readable output, and sending it on-chain by including it in a transaction to the oracle contract. The oracle node may also be required to attest to the validity and integrity of submitted information using “authenticity proofs”, which we explore later.
+A common task for oracle nodes is sending a [HTTP GET](https://www.w3schools.com/tags/ref_httpmethods.asp) request to an API service, parsing the response to extract relevant data, formatting into a blockchain-readable output, and sending it onchain by including it in a transaction to the oracle contract. The oracle node may also be required to attest to the validity and integrity of submitted information using “authenticity proofs”, which we explore later.
-Computational oracles also rely on off-chain nodes to perform computational tasks that would be impractical to execute on-chain, given gas costs and block size limits. For example, the oracle node may be tasked with generating a verifiably random figure (e.g., for blockchain-based games).
+Computational oracles also rely on offchain nodes to perform computational tasks that would be impractical to execute onchain, given gas costs and block size limits. For example, the oracle node may be tasked with generating a verifiably random figure (e.g., for blockchain-based games).
## Oracle design patterns {#oracle-design-patterns}
@@ -216,15 +216,15 @@ This type of oracle exposes a “data feed” which other contracts can regularl
A request-response setup allows the client contract to request arbitrary data other than that provided by a publish-subscribe oracle. Request-response oracles are ideal when the dataset is too large to be stored in a smart contract’s storage, and/or users will only need a small part of the data at any point in time.
-Although more complex than publish-subscribe models, request-response oracles are basically what we described in the previous section. The oracle will have an on-chain component that receives a data request and passes it to an off-chain node for processing.
+Although more complex than publish-subscribe models, request-response oracles are basically what we described in the previous section. The oracle will have an onchain component that receives a data request and passes it to an offchain node for processing.
-Users initiating data queries must cover the cost of retrieving information from the off-chain source. The client contract must also provide funds to cover gas costs incurred by the oracle contract in returning the response via the callback function specified in the request.
+Users initiating data queries must cover the cost of retrieving information from the offchain source. The client contract must also provide funds to cover gas costs incurred by the oracle contract in returning the response via the callback function specified in the request.
## Centralized vs. decentralized oracles {#types-of-oracles}
### Centralized oracles {#centralized-oracles}
-A centralized oracle is controlled by a single entity responsible for aggregating off-chain information and updating the oracle contract's data as requested. Centralized oracles are efficient since they rely on a single source of truth. They may function better in cases where proprietary datasets are published directly by the owner with a widely accepted signature. However, they bring downsides as well:
+A centralized oracle is controlled by a single entity responsible for aggregating offchain information and updating the oracle contract's data as requested. Centralized oracles are efficient since they rely on a single source of truth. They may function better in cases where proprietary datasets are published directly by the owner with a widely accepted signature. However, they bring downsides as well:
#### Low correctness guarantees {#low-correctness-guarantees}
@@ -232,7 +232,7 @@ With centralized oracles, there's no way to confirm if the information provided
#### Poor availability {#poor-availability}
-Centralized oracles aren't guaranteed to always make off-chain data available to other smart contracts. If the provider decides to turn off the service or a hacker hijacks the oracle's off-chain component, your smart contract is at risk of a denial of service (DoS) attack.
+Centralized oracles aren't guaranteed to always make offchain data available to other smart contracts. If the provider decides to turn off the service or a hacker hijacks the oracle's offchain component, your smart contract is at risk of a denial of service (DoS) attack.
#### Poor incentive compatibility {#poor-incentive-compatibility}
@@ -240,7 +240,7 @@ Centralized oracles often have poorly designed or non-existent incentives for th
### Decentralized oracles {#decentralized-oracles}
-Decentralized oracles are designed to overcome the limitations of centralized oracles by eliminating single points of failure. A decentralized oracle service comprises multiple participants in a peer-to-peer network that form consensus on off-chain data before sending it to a smart contract.
+Decentralized oracles are designed to overcome the limitations of centralized oracles by eliminating single points of failure. A decentralized oracle service comprises multiple participants in a peer-to-peer network that form consensus on offchain data before sending it to a smart contract.
A decentralized oracle should (ideally) be permissionless, trustless, and free from administration by a central party; in reality, decentralization among oracles is on a spectrum. There are semi-decentralized oracle networks where anyone can participate, but with an “owner” that approves and removes nodes based on historical performance. Fully decentralized oracle networks also exist: these usually run as standalone blockchains and have defined consensus mechanisms for coordinating nodes and punishing misbehavior.
@@ -248,7 +248,7 @@ Using decentralized oracles comes with the following benefits:
### High correctness guarantees {#high-correctness-guarantees}
-Decentralized oracles attempt to achieve correctness of data using different approaches. This includes using proofs attesting to the authenticity and integrity of the returned information and requiring multiple entities to collectively agree on the validity of off-chain data.
+Decentralized oracles attempt to achieve correctness of data using different approaches. This includes using proofs attesting to the authenticity and integrity of the returned information and requiring multiple entities to collectively agree on the validity of offchain data.
#### Authenticity proofs {#authenticity-proofs}
@@ -264,9 +264,9 @@ Certain classes of decentralized oracles require oracle node operators to provid
#### Consensus-based validation of information {#consensus-based-validation-of-information}
-Centralized oracles rely on a single source of truth when providing data to smart contracts, which introduces the possibility of publishing inaccurate information. Decentralized oracles solve this problem by relying on multiple oracle nodes to query off-chain information. By comparing data from multiple sources, decentralized oracles reduce the risk of passing invalid information to on-chain contracts.
+Centralized oracles rely on a single source of truth when providing data to smart contracts, which introduces the possibility of publishing inaccurate information. Decentralized oracles solve this problem by relying on multiple oracle nodes to query offchain information. By comparing data from multiple sources, decentralized oracles reduce the risk of passing invalid information to onchain contracts.
-Decentralized oracles, however, must deal with discrepancies in information retrieved from multiple off-chain sources. To minimize differences in information and ensure the data passed to the oracle contract reflects the collective opinion of oracle nodes, decentralized oracles use the following mechanisms:
+Decentralized oracles, however, must deal with discrepancies in information retrieved from multiple offchain sources. To minimize differences in information and ensure the data passed to the oracle contract reflects the collective opinion of oracle nodes, decentralized oracles use the following mechanisms:
##### Voting/staking on accuracy of data
@@ -282,15 +282,15 @@ Staking/voting also protects decentralized oracles from [Sybil attacks](/glossar
An early idea for this was [SchellingCoin](https://blog.ethereum.org/2014/03/28/schellingcoin-a-minimal-trust-universal-data-feed/), a proposed data feed where participants submit responses to "scalar" questions (questions whose answers are described by magnitude, e.g., "what is the price of ETH?"), along with a deposit. Users who provide values between the 25th and 75th [percentile](https://en.wikipedia.org/wiki/Percentile) are rewarded, while those whose values deviate largely from the median value are penalized.
-While SchellingCoin doesn’t exist today, a number of decentralized oracles—notably [Maker Protocol’s Oracles](https://docs.makerdao.com/smart-contract-modules/oracle-module)—use the schelling-point mechanism to improve accuracy of oracle data. Each Maker Oracle consists of an off-chain P2P network of nodes ("relayers" and "feeds") who submit market prices for collateral assets and an on-chain “Medianizer” contract that calculates the median of all provided values. Once the specified delay period is over, this median value becomes the new reference price for the associated asset.
+While SchellingCoin doesn’t exist today, a number of decentralized oracles—notably [Maker Protocol’s Oracles](https://docs.makerdao.com/smart-contract-modules/oracle-module)—use the schelling-point mechanism to improve accuracy of oracle data. Each Maker Oracle consists of an offchain P2P network of nodes ("relayers" and "feeds") who submit market prices for collateral assets and an onchain “Medianizer” contract that calculates the median of all provided values. Once the specified delay period is over, this median value becomes the new reference price for the associated asset.
-Other examples of oracles that use Schelling point mechanisms include [Chainlink Off-Chain Reporting](https://docs.chain.link/docs/off-chain-reporting/) and [Witnet](https://witnet.io/). In both systems, responses from oracle nodes in the peer-to-peer network are aggregated into a single aggregate value, such as a mean or median. Nodes are rewarded or punished according to the extent to which their responses align with or deviate from the aggregate value.
+Other examples of oracles that use Schelling point mechanisms include [Chainlink Offchain Reporting](https://docs.chain.link/docs/offchain-reporting/) and [Witnet](https://witnet.io/). In both systems, responses from oracle nodes in the peer-to-peer network are aggregated into a single aggregate value, such as a mean or median. Nodes are rewarded or punished according to the extent to which their responses align with or deviate from the aggregate value.
-Schelling point mechanisms are attractive because they minimize on-chain footprint (only one transaction needs to be sent) while guaranteeing decentralization. The latter is possible because nodes must sign off on the list of submitted responses before it is fed into the algorithm that produces the mean/median value.
+Schelling point mechanisms are attractive because they minimize onchain footprint (only one transaction needs to be sent) while guaranteeing decentralization. The latter is possible because nodes must sign off on the list of submitted responses before it is fed into the algorithm that produces the mean/median value.
### Availability {#availability}
-Decentralized oracle services ensure high availability of off-chain data to smart contracts. This is achieved by decentralizing both the source of off-chain information and nodes responsible for transferring the information on-chain.
+Decentralized oracle services ensure high availability of offchain data to smart contracts. This is achieved by decentralizing both the source of offchain information and nodes responsible for transferring the information onchain.
This ensures fault-tolerance since the oracle contract can rely on multiple nodes (who also rely on multiple data sources) to execute queries from other contracts. Decentralization at the source _and_ node-operator level is crucial—a network of oracle nodes serving information retrieved from the same source will run into the same problem as a centralized oracle.
@@ -358,15 +358,15 @@ contract PriceConsumerV3 {
Certain blockchain applications, such as blockchain-based games or lottery schemes, require a high level of unpredictability and randomness to work effectively. However, the deterministic execution of blockchains eliminates randomness.
-The original approach was to use pseudorandom cryptographic functions, such as `blockhash`, but these could be [manipulated by miners](https://ethereum.stackexchange.com/questions/3140/risk-of-using-blockhash-other-miners-preventing-attack#:~:text=So%20while%20the%20miners%20can,to%20one%20of%20the%20players.) solving the proof-of-work algorithm. Also, Ethereum’s [switch to proof-of-stake](/roadmap/merge/) means developers can no longer rely on `blockhash` for on-chain randomness. The Beacon Chain’s [RANDAO mechanism](https://eth2book.info/altair/part2/building_blocks/randomness) provides an alternative source of randomness instead.
+The original approach was to use pseudorandom cryptographic functions, such as `blockhash`, but these could be [manipulated by miners](https://ethereum.stackexchange.com/questions/3140/risk-of-using-blockhash-other-miners-preventing-attack#:~:text=So%20while%20the%20miners%20can,to%20one%20of%20the%20players.) solving the proof-of-work algorithm. Also, Ethereum’s [switch to proof-of-stake](/roadmap/merge/) means developers can no longer rely on `blockhash` for onchain randomness. The Beacon Chain’s [RANDAO mechanism](https://eth2book.info/altair/part2/building_blocks/randomness) provides an alternative source of randomness instead.
-It is possible to generate the random value off-chain and send it on-chain, but doing so imposes high trust requirements on users. They must believe the value was truly generated via unpredictable mechanisms and wasn’t altered in transit.
+It is possible to generate the random value offchain and send it onchain, but doing so imposes high trust requirements on users. They must believe the value was truly generated via unpredictable mechanisms and wasn’t altered in transit.
-Oracles designed for off-chain computation solve this problem by securely generating random outcomes off-chain that they broadcast on-chain along with cryptographic proofs attesting to the unpredictability of the process. An example is [Chainlink VRF](https://docs.chain.link/docs/chainlink-vrf/) (Verifiable Random Function), which is a provably fair and tamper-proof random number generator (RNG) useful for building reliable smart contracts for applications that rely on unpredictable outcomes. Another example is [API3 QRNG](https://docs.api3.org/explore/qrng/) that serves Quantum random number generation (QRNG) is a public method of Web3 RNG based on quantum phenomena, served with the courtesy of the Australian National University (ANU).
+Oracles designed for offchain computation solve this problem by securely generating random outcomes offchain that they broadcast onchain along with cryptographic proofs attesting to the unpredictability of the process. An example is [Chainlink VRF](https://docs.chain.link/docs/chainlink-vrf/) (Verifiable Random Function), which is a provably fair and tamper-proof random number generator (RNG) useful for building reliable smart contracts for applications that rely on unpredictable outcomes. Another example is [API3 QRNG](https://docs.api3.org/explore/qrng/) that serves Quantum random number generation (QRNG) is a public method of Web3 RNG based on quantum phenomena, served with the courtesy of the Australian National University (ANU).
### Getting outcomes for events {#getting-outcomes-for-events}
-With oracles, creating smart contracts that respond to real-world events is easy. Oracle services make this possible by allowing contracts to connect to external APIs through off-chain components and consume information from those data sources. For example, the prediction dapp mentioned earlier may request an oracle to return election results from a trusted off-chain source (e.g., the Associated Press).
+With oracles, creating smart contracts that respond to real-world events is easy. Oracle services make this possible by allowing contracts to connect to external APIs through offchain components and consume information from those data sources. For example, the prediction dapp mentioned earlier may request an oracle to return election results from a trusted offchain source (e.g., the Associated Press).
Using oracles to retrieve data based on real-world outcomes enables other novel use cases; for example, a decentralized insurance product needs accurate information about weather, disasters, etc. to work effectively.
@@ -378,7 +378,7 @@ But there are also _private functions_ within a contract that are inaccessible t
Developers will need to trigger such functions at intervals to keep the application running smoothly. However, this might lead to more hours lost on mundane tasks for developers, which is why automating execution of smart contracts is attractive.
-Some decentralized oracle networks offer automation services, which allow off-chain oracle nodes to trigger smart contract functions according to parameters defined by the user. Typically, this requires “registering” the target contract with the oracle service, providing funds to pay the oracle operator, and specifying the conditions or times to trigger the contract.
+Some decentralized oracle networks offer automation services, which allow offchain oracle nodes to trigger smart contract functions according to parameters defined by the user. Typically, this requires “registering” the target contract with the oracle service, providing funds to pay the oracle operator, and specifying the conditions or times to trigger the contract.
Chainlink’s [Keeper Network](https://chain.link/keepers) provides options for smart contracts to outsource regular maintenance tasks in a trust minimized and decentralized manner. Read the official [Keeper's documentation](https://docs.chain.link/docs/chainlink-keepers/introduction/) for information on making your contract Keeper-compatible and using the Upkeep service.
@@ -390,7 +390,7 @@ There are multiple oracle applications you can integrate into your Ethereum dapp
**[RedStone Oracles](https://redstone.finance/)** - _RedStone is a decentralized modular oracle that provides gas-optimized data feeds. It specializes in offering price feeds for emerging assets, such as liquid staking tokens (LSTs), liquid restaking tokens (LRTs), and Bitcoin staking derivatives._
-**[Chronicle](https://chroniclelabs.org/)** - _Chronicle overcomes the current limitations of transferring data on-chain by developing truly scalable, cost-efficient, decentralized, and verifiable oracles._
+**[Chronicle](https://chroniclelabs.org/)** - _Chronicle overcomes the current limitations of transferring data onchain by developing truly scalable, cost-efficient, decentralized, and verifiable oracles._
**[Witnet](https://witnet.io/)** - _Witnet is a permissionless, decentralized, and censorship-resistant oracle helping smart contracts to react to real world events with strong crypto-economic guarantees._
@@ -402,11 +402,11 @@ There are multiple oracle applications you can integrate into your Ethereum dapp
**[Paralink](https://paralink.network/)** - _Paralink provides an open source and decentralized oracle platform for smart contracts running on Ethereum and other popular blockchains._
-**[Pyth Network](https://pyth.network/)** - _The Pyth network is a first-party financial oracle network designed to publish continuous real-world data on-chain in a tamper-resistant, decentralized, and self-sustainable environment._
+**[Pyth Network](https://pyth.network/)** - _The Pyth network is a first-party financial oracle network designed to publish continuous real-world data onchain in a tamper-resistant, decentralized, and self-sustainable environment._
**[API3 DAO](https://www.api3.org/)** - _API3 DAO is delivering first-party oracle solutions that deliver greater source transparency, security and scalability in a decentralized solution for smart contracts_
-**[Supra](https://supra.com/)** - A vertically integrated toolkit of cross-chain solutions that interlink all blockchains, public (L1s and L2s) or private (enterprises), providing decentralized oracle price feeds that can be used for on-chain and off-chain use-cases.
+**[Supra](https://supra.com/)** - A vertically integrated toolkit of cross-chain solutions that interlink all blockchains, public (L1s and L2s) or private (enterprises), providing decentralized oracle price feeds that can be used for onchain and offchain use-cases.
## Further reading {#further-reading}
diff --git a/public/content/developers/docs/scaling/index.md b/public/content/developers/docs/scaling/index.md
index cdfd4b69197..98c0ce37f77 100644
--- a/public/content/developers/docs/scaling/index.md
+++ b/public/content/developers/docs/scaling/index.md
@@ -13,27 +13,27 @@ The main goal of scalability is to increase transaction speed (faster finality)
While speed and throughput are important, it is essential that scaling solutions enabling these goals remain decentralized and secure. Keeping the barrier to entry low for node operators is critical in preventing a progression towards centralized and insecure computing power.
-Conceptually we first categorize scaling as either on-chain scaling or off-chain scaling.
+Conceptually we first categorize scaling as either onchain scaling or offchain scaling.
## Prerequisites {#prerequisites}
You should have a good understanding of all the foundational topics. Implementing scaling solutions is advanced as the technology is less battle-tested, and continues to be researched and developed.
-## On-Chain scaling {#on-chain-scaling}
+## Onchain scaling {#onchain-scaling}
-On-chain scaling requires changes to the Ethereum protocol (layer 1 [Mainnet](/glossary/#mainnet)). For a long time, sharding the blockchain was expected to scale Ethereum. This was going to involve splitting the blockchain into discrete pieces (shards) to be verified by subsets of validators. However, scaling by layer-2 rollups has taken over as the primary scaling technique. This is supported by the addition of a new cheaper form of data attached to Ethereum blocks that is specially designed to make rollups cheap for users.
+Onchain scaling requires changes to the Ethereum protocol (layer 1 [Mainnet](/glossary/#mainnet)). For a long time, sharding the blockchain was expected to scale Ethereum. This was going to involve splitting the blockchain into discrete pieces (shards) to be verified by subsets of validators. However, scaling by layer-2 rollups has taken over as the primary scaling technique. This is supported by the addition of a new cheaper form of data attached to Ethereum blocks that is specially designed to make rollups cheap for users.
### Sharding {#sharding}
Sharding is the process of splitting a database. Subsets of validators would be responsible for individual shards rather than keeping track of all of Ethereum. Sharding was on the Ethereum [roadmap](/roadmap/) for a long time, and was once intended to be shipped before The Merge to proof-of-stake. However, the rapid development of [layer 2 rollups](#layer-2-scaling) and the invention of [Danksharding](/roadmap/danksharding) (adding blobs of rollup data to Ethereum blocks that can be very efficiently verified by validators) has led the Ethereum community to favour rollup-centric scaling instead of scaling by sharding. This will also help to keep Ethereum's consensus logic simpler.
-## Off-chain scaling {#off-chain-scaling}
+## Offchain scaling {#offchain-scaling}
-Off-chain solutions are implemented separately from layer 1 Mainnet - they require no changes to the existing Ethereum protocol. Some solutions, known as "layer 2" solutions, derive their security directly from layer 1 Ethereum consensus, such as [optimistic rollups](/developers/docs/scaling/optimistic-rollups/), [zero-knowledge rollups](/developers/docs/scaling/zk-rollups/) or [state channels](/developers/docs/scaling/state-channels/). Other solutions involve the creation of new chains in various forms that derive their security separately from Mainnet, such as [sidechains](#sidechains), [validiums](#validium), or [plasma chains](#plasma). These solutions communicate with Mainnet but derive their security differently to obtain a variety of goals.
+Offchain solutions are implemented separately from layer 1 Mainnet - they require no changes to the existing Ethereum protocol. Some solutions, known as "layer 2" solutions, derive their security directly from layer 1 Ethereum consensus, such as [optimistic rollups](/developers/docs/scaling/optimistic-rollups/), [zero-knowledge rollups](/developers/docs/scaling/zk-rollups/) or [state channels](/developers/docs/scaling/state-channels/). Other solutions involve the creation of new chains in various forms that derive their security separately from Mainnet, such as [sidechains](#sidechains), [validiums](#validium), or [plasma chains](#plasma). These solutions communicate with Mainnet but derive their security differently to obtain a variety of goals.
### Layer 2 scaling {#layer-2-scaling}
-This category of off-chain solutions derives its security from Mainnet Ethereum.
+This category of offchain solutions derives its security from Mainnet Ethereum.
Layer 2 is a collective term for solutions designed to help scale your application by handling transactions off the Ethereum Mainnet (layer 1) while taking advantage of the robust decentralized security model of Mainnet. Transaction speed suffers when the network is busy, making the user experience poor for certain types of dapps. And as the network gets busier, gas prices increase as transaction senders aim to outbid each other. This can make using Ethereum very expensive.
@@ -57,11 +57,11 @@ Rollups perform transaction execution outside layer 1 and then the data is poste
There are two types of rollups with different security models:
- **Optimistic rollups**: assumes transactions are valid by default and only runs computation, via a [**fraud proof**](/glossary/#fraud-proof), in the event of a challenge. [More on Optimistic rollups](/developers/docs/scaling/optimistic-rollups/).
-- **Zero-knowledge rollups**: runs computation off-chain and submits a [**validity proof**](/glossary/#validity-proof) to the chain. [More on zero-knowledge rollups](/developers/docs/scaling/zk-rollups/).
+- **Zero-knowledge rollups**: runs computation offchain and submits a [**validity proof**](/glossary/#validity-proof) to the chain. [More on zero-knowledge rollups](/developers/docs/scaling/zk-rollups/).
#### State channels {#channels}
-State channels utilize multisig contracts to enable participants to transact quickly and freely off-chain, then settle finality with Mainnet. This minimizes network congestion, fees, and delays. The two types of channels are currently state channels and payment channels.
+State channels utilize multisig contracts to enable participants to transact quickly and freely offchain, then settle finality with Mainnet. This minimizes network congestion, fees, and delays. The two types of channels are currently state channels and payment channels.
Learn more about [state channels](/developers/docs/scaling/state-channels/).
@@ -94,7 +94,7 @@ Learn more about [Validium](/developers/docs/scaling/validium/).
-_Note the explanation in the video uses the term "Layer 2" to refer to all off-chain scaling solutions, while we differentiate "Layer 2" as an off-chain solution that derives its security through layer 1 Mainnet consensus._
+_Note the explanation in the video uses the term "Layer 2" to refer to all offchain scaling solutions, while we differentiate "Layer 2" as an offchain solution that derives its security through layer 1 Mainnet consensus._
diff --git a/public/content/developers/docs/scaling/optimistic-rollups/index.md b/public/content/developers/docs/scaling/optimistic-rollups/index.md
index 21bee49f97c..427afa388e4 100644
--- a/public/content/developers/docs/scaling/optimistic-rollups/index.md
+++ b/public/content/developers/docs/scaling/optimistic-rollups/index.md
@@ -4,7 +4,7 @@ description: An introduction to optimistic rollups—a scaling solution used by
lang: en
---
-Optimistic rollups are layer 2 (L2) protocols designed to extend the throughput of Ethereum's base layer. They reduce computation on the main Ethereum chain by processing transactions off-chain, offering significant improvements in processing speeds. Unlike other scaling solutions, such as [sidechains](/developers/docs/scaling/sidechains/), optimistic rollups derive security from Mainnet by publishing transaction results on-chain, or [plasma chains](/developers/docs/scaling/plasma/), which also verify transactions on Ethereum with fraud proofs, but store transaction data elsewhere.
+Optimistic rollups are layer 2 (L2) protocols designed to extend the throughput of Ethereum's base layer. They reduce computation on the main Ethereum chain by processing transactions offchain, offering significant improvements in processing speeds. Unlike other scaling solutions, such as [sidechains](/developers/docs/scaling/sidechains/), optimistic rollups derive security from Mainnet by publishing transaction results onchain, or [plasma chains](/developers/docs/scaling/plasma/), which also verify transactions on Ethereum with fraud proofs, but store transaction data elsewhere.
As computation is the slow, expensive part of using Ethereum, optimistic rollups can offer up to 10-100x improvements in scalability. Optimistic rollups also write transactions to Ethereum as `calldata` or in [blobs](/roadmap/danksharding/), reducing gas costs for users.
@@ -14,11 +14,11 @@ You should have read and understood our pages on [Ethereum scaling](/developers/
## What is an optimistic rollup? {#what-is-an-optimistic-rollup}
-An optimistic rollup is an approach to scaling Ethereum that involves moving computation and state storage off-chain. Optimistic rollups execute transactions outside of Ethereum, but post transaction data to Mainnet as `calldata` or in [blobs](/roadmap/danksharding/).
+An optimistic rollup is an approach to scaling Ethereum that involves moving computation and state storage offchain. Optimistic rollups execute transactions outside of Ethereum, but post transaction data to Mainnet as `calldata` or in [blobs](/roadmap/danksharding/).
-Optimistic rollup operators bundle multiple off-chain transactions together in large batches before submitting to Ethereum. This approach enables spreading fixed costs across multiple transactions in each batch, reducing fees for end-users. Optimistic rollups also use compression techniques to reduce the amount of data posted on Ethereum.
+Optimistic rollup operators bundle multiple offchain transactions together in large batches before submitting to Ethereum. This approach enables spreading fixed costs across multiple transactions in each batch, reducing fees for end-users. Optimistic rollups also use compression techniques to reduce the amount of data posted on Ethereum.
-Optimistic rollups are considered “optimistic” because they assume off-chain transactions are valid and don't publish proofs of validity for transaction batches posted on-chain. This separates optimistic rollups from [zero-knowledge rollups](/developers/docs/scaling/zk-rollups) that publish cryptographic [proofs of validity](/glossary/#validity-proof) for off-chain transactions.
+Optimistic rollups are considered “optimistic” because they assume offchain transactions are valid and don't publish proofs of validity for transaction batches posted onchain. This separates optimistic rollups from [zero-knowledge rollups](/developers/docs/scaling/zk-rollups) that publish cryptographic [proofs of validity](/glossary/#validity-proof) for offchain transactions.
Optimistic rollups instead rely on a fraud-proving scheme to detect cases where transactions are not calculated correctly. After a rollup batch is submitted on Ethereum, there's a time window (called a challenge period) during which anyone can challenge the results of a rollup transaction by computing a [fraud proof](/glossary/#fraud-proof).
@@ -28,17 +28,17 @@ If the rollup batch remains unchallenged (i.e., all transactions are correctly e
## How do optimistic rollups interact with Ethereum? {#optimistic-rollups-and-Ethereum}
-Optimistic rollups are [off-chain scaling solutions](/developers/docs/scaling/#off-chain-scaling) built to operate on top of Ethereum. Each optimistic rollup is managed by a set of smart contracts deployed on the Ethereum network. Optimistic rollups process transactions off the main Ethereum chain, but post off-chain transactions (in batches) to an on-chain rollup contract. Like the Ethereum blockchain, this transaction record is immutable and forms the "optimistic rollup chain."
+Optimistic rollups are [offchain scaling solutions](/developers/docs/scaling/#offchain-scaling) built to operate on top of Ethereum. Each optimistic rollup is managed by a set of smart contracts deployed on the Ethereum network. Optimistic rollups process transactions off the main Ethereum chain, but post offchain transactions (in batches) to an onchain rollup contract. Like the Ethereum blockchain, this transaction record is immutable and forms the "optimistic rollup chain."
The architecture of an optimistic rollup comprises the following parts:
-**On-chain contracts**: The optimistic rollups's operation is controlled by smart contracts running on Ethereum. This includes contracts that store rollup blocks, monitor state updates on the rollup, and track user deposits. In this sense, Ethereum serves as the base layer or "layer 1" for optimistic rollups.
+**Onchain contracts**: The optimistic rollups's operation is controlled by smart contracts running on Ethereum. This includes contracts that store rollup blocks, monitor state updates on the rollup, and track user deposits. In this sense, Ethereum serves as the base layer or "layer 1" for optimistic rollups.
-**Off-chain virtual machine (VM)**: Although contracts managing the optimistic rollup protocol run on Ethereum, the rollup protocol performs computation and state storage on another virtual machine separate from the [Ethereum Virtual Machine](/developers/docs/evm/). The off-chain VM is where applications live and state changes are executed; it serves as the upper layer or "layer 2" for an optimistic rollup.
+**Offchain virtual machine (VM)**: Although contracts managing the optimistic rollup protocol run on Ethereum, the rollup protocol performs computation and state storage on another virtual machine separate from the [Ethereum Virtual Machine](/developers/docs/evm/). The offchain VM is where applications live and state changes are executed; it serves as the upper layer or "layer 2" for an optimistic rollup.
-As optimistic rollups are designed to run programs either written or compiled for the EVM, the off-chain VM incorporates many EVM design specs. Additionally, fraud proofs computed on-chain allows the Ethereum network to enforce the validity of state changes computed in the off-chain VM.
+As optimistic rollups are designed to run programs either written or compiled for the EVM, the offchain VM incorporates many EVM design specs. Additionally, fraud proofs computed onchain allows the Ethereum network to enforce the validity of state changes computed in the offchain VM.
-Optimistic rollups are described as 'hybrid scaling solutions' because, while they exist as separate protocols, their security properties are derived from Ethereum. Among other things, Ethereum guarantees the correctness of a rollup’s off-chain computation and the availability of data behind the computation. This makes optimistic rollups more secure than pure off-chain scaling protocols (e.g., [sidechains](/developers/docs/scaling/sidechains/)) that do not rely on Ethereum for security.
+Optimistic rollups are described as 'hybrid scaling solutions' because, while they exist as separate protocols, their security properties are derived from Ethereum. Among other things, Ethereum guarantees the correctness of a rollup’s offchain computation and the availability of data behind the computation. This makes optimistic rollups more secure than pure offchain scaling protocols (e.g., [sidechains](/developers/docs/scaling/sidechains/)) that do not rely on Ethereum for security.
Optimistic rollups rely on the main Ethereum protocol for the following:
@@ -56,7 +56,7 @@ Optimistic rollups also rely on Ethereum for censorship resistance. In an optimi
- Rollup operators can prevent users from withdrawing funds deposited in the rollup contract by withholding state data necessary to Merkle proofs of ownership. Withholding state data can also conceal the rollup’s state from users and prevent them from interacting with the rollup.
-Optimistic rollups solve this problem by forcing operators to publish data associated with state updates on Ethereum. Publishing rollup data on-chain has the following benefits:
+Optimistic rollups solve this problem by forcing operators to publish data associated with state updates on Ethereum. Publishing rollup data onchain has the following benefits:
- If an optimistic rollup operator goes offline or stops producing transaction batches, another node can use available data to reproduce the rollup’s last state and continue block production.
@@ -82,17 +82,17 @@ Other validators on the optimistic rollup chain are expected to execute the subm
Some optimistic rollups may forgo a permissionless validator system and use a single “sequencer” to execute the chain. Like a validator, the sequencer processes transactions, produces rollup blocks, and submits rollup transactions to the L1 chain (Ethereum).
-The sequencer is different from a regular rollup operator because they have greater control over the ordering of transactions. Also, the sequencer has priority access to the rollup chain and is the only entity authorized to submit transactions to the on-chain contract. Transactions from non-sequencer nodes or regular users are simply queued up in a separate inbox until the sequencer includes them in a new batch.
+The sequencer is different from a regular rollup operator because they have greater control over the ordering of transactions. Also, the sequencer has priority access to the rollup chain and is the only entity authorized to submit transactions to the onchain contract. Transactions from non-sequencer nodes or regular users are simply queued up in a separate inbox until the sequencer includes them in a new batch.
#### Submitting rollup blocks to Ethereum {#submitting-blocks-to-ethereum}
-As mentioned, the operator of an optimistic rollup bundles off-chain transactions into a batch and sends it to Ethereum for notarization. This process involves compressing transaction-related data and publishing it on Ethereum as `calldata` or in blobs.
+As mentioned, the operator of an optimistic rollup bundles offchain transactions into a batch and sends it to Ethereum for notarization. This process involves compressing transaction-related data and publishing it on Ethereum as `calldata` or in blobs.
-`calldata` is a non-modifiable, non-persistent area in a smart contract that behaves mostly like [memory](/developers/docs/smart-contracts/anatomy/#memory). While `calldata` persists on-chain as part of the blockchain's [history logs](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html?highlight=memory#logs), it is not stored as a part of Ethereum's state. Because `calldata` does not touch any part of Ethereum's state, it is cheaper than state for storing data on-chain.
+`calldata` is a non-modifiable, non-persistent area in a smart contract that behaves mostly like [memory](/developers/docs/smart-contracts/anatomy/#memory). While `calldata` persists onchain as part of the blockchain's [history logs](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html?highlight=memory#logs), it is not stored as a part of Ethereum's state. Because `calldata` does not touch any part of Ethereum's state, it is cheaper than state for storing data onchain.
The `calldata` keyword is also used in Solidity to pass arguments to a smart contract function at execution time. `calldata` identifies the function being called during a transaction and holds inputs to the function in the form of an arbitrary sequence of bytes.
-In the context of optimistic rollups, `calldata` is used to send compressed transaction data to the on-chain contract. The rollup operator adds a new batch by calling the required function in the rollup contract and passing the compressed data as function arguments. Using `calldata` reduces user fees since most costs that rollups incur come from storing data on-chain.
+In the context of optimistic rollups, `calldata` is used to send compressed transaction data to the onchain contract. The rollup operator adds a new batch by calling the required function in the rollup contract and passing the compressed data as function arguments. Using `calldata` reduces user fees since most costs that rollups incur come from storing data onchain.
Here is [an example](https://etherscan.io/tx/0x9102bfce17c58b5fc1c974c24b6bb7a924fb5fbd7c4cd2f675911c27422a5591) of a rollup batch submission to show how this concept works. The sequencer invoked the `appendSequencerBatch()` method and passed the compressed transaction data as inputs using `calldata`.
@@ -104,7 +104,7 @@ Blobs are non-modifiable and non-persistent (just like `calldata`) but are prune
At any point in time, the optimistic rollup’s state (accounts, balances, contract code, etc.) is organized as a [Merkle tree](/whitepaper/#merkle-trees) called a “state tree”. The root of this Merkle tree (state root), which references the rollup’s latest state, is hashed and stored in the rollup contract. Every state transition on the chain produces a new rollup state, which an operator commits to by computing a new state root.
-The operator is required to submit both old state roots and new state roots when posting batches. If the old state root matches the existing state root in the on-chain contract, the latter is discarded and replaced with the new state root.
+The operator is required to submit both old state roots and new state roots when posting batches. If the old state root matches the existing state root in the onchain contract, the latter is discarded and replaced with the new state root.
The rollup operator is also required to commit a Merkle root for the transaction batch itself. This allows anyone to prove the inclusion of a transaction in the batch (on L1) by presenting a [Merkle proof](/developers/tutorials/merkle-proofs-for-offline-data-integrity/).
@@ -118,7 +118,7 @@ If someone disputes an assertion, then the rollup protocol will initiate the fra
Single-round interactive proving schemes replay disputed transactions on L1 to detect invalid assertions. The rollup protocol emulates the re-execution of the disputed transaction on L1 (Ethereum) using a verifier contract, with the computed state root determining who wins the challenge. If the challenger's claim about the rollup’s correct state is correct, the operator is penalized by having their bond slashed.
-However, re-executing transactions on L1 to detect fraud requires publishing state commitments for individual transactions and increases the data rollups must publish on-chain. Replaying transactions also incurs significant gas costs. For these reasons, optimistic rollups are switching to multi-round interactive proving, which achieves the same objective (i.e., detecting invalid rollup operations) with more efficiency.
+However, re-executing transactions on L1 to detect fraud requires publishing state commitments for individual transactions and increases the data rollups must publish onchain. Replaying transactions also incurs significant gas costs. For these reasons, optimistic rollups are switching to multi-round interactive proving, which achieves the same objective (i.e., detecting invalid rollup operations) with more efficiency.
#### Multi-round interactive proving {#multi-round-interactive-proving}
@@ -132,7 +132,7 @@ Some notes about this type of fraud proof:
1. Multi-round interactive fraud proving is considered efficient because it minimizes the work the L1 chain must do in dispute arbitration. Instead of replaying the entire transaction, the L1 chain only needs to re-execute one step in the rollup's execution.
-2. Bisection protocols reduce the amount of data posted on-chain (no need to publish state commits for every transaction). Also, optimistic rollup transactions are not constrained by Ethereum's gas limit. Conversely, optimistic rollups re-executing transactions must make sure an L2 transaction has a lower gas limit to emulate its execution within a single Ethereum transaction.
+2. Bisection protocols reduce the amount of data posted onchain (no need to publish state commits for every transaction). Also, optimistic rollup transactions are not constrained by Ethereum's gas limit. Conversely, optimistic rollups re-executing transactions must make sure an L2 transaction has a lower gas limit to emulate its execution within a single Ethereum transaction.
3. Part of the malicious asserter's bond is awarded to the challenger, while the other part is burned. The burning prevents collusion among validators; if two validators collude to initiate bogus challenges, they will still forfeit a considerable chunk of the entire stake.
@@ -156,7 +156,7 @@ Optimistic rollups are designed for interoperability with Ethereum Mainnet and a
To use an optimistic rollup, users deposit ETH, ERC-20 tokens, and other accepted assets in the rollup’s [bridge](/developers/docs/bridges/) contract on L1. The bridge contract will relay the transaction to L2, where an equivalent amount of assets is minted and sent to the user’s chosen address on the optimistic rollup.
-User-generated transactions (like an L1 > L2 deposit) are usually queued until the sequencer re-submits them to the rollup contract. However, to preserve censorship resistance, optimistic rollups allow users to submit a transaction directly to the on-chain rollup contract if it has been delayed past the maximum time allowed.
+User-generated transactions (like an L1 > L2 deposit) are usually queued until the sequencer re-submits them to the rollup contract. However, to preserve censorship resistance, optimistic rollups allow users to submit a transaction directly to the onchain rollup contract if it has been delayed past the maximum time allowed.
Some optimistic rollups adopt a more straightforward approach to prevent sequencers from censoring users. Here, a block is defined by all transactions submitted to the L1 contract since the previous block (e.g., deposits) in addition to the transactions processed on the rollup chain. If a sequencer ignores an L1 transaction, it will publish the (provably) wrong state root; therefore, sequencers cannot delay user-generated messages once posted on L1.
@@ -198,7 +198,7 @@ Finally, we should note that L2 > L1 message calls between contracts need to acc
Optimistic rollups use a gas fee scheme, much like Ethereum, to denote how much users pay per transaction. Fees charged on optimistic rollups depends on the following components:
-1. **State write**: Optimistic rollups publish transaction data and block headers (consisting of the previous block header hash, state root, batch root) to Ethereum as a `blob`, or "binary large object". [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) introduced a cost-effective solution for including data on-chain. A `blob` is a new transaction field that allows rollups to post compressed state transition data to Ethereum L1. Unlike `calldata`, which remains permanently on-chain, blobs are short-lived and can be pruned from clients after [4096 epochs](https://github.com/ethereum/consensus-specs/blob/81f3ea8322aff6b9fb15132d050f8f98b16bdba4/configs/mainnet.yaml#L147) (approximately 18 days). By using blobs to post batches of compressed transactions, optimistic rollups can significantly reduce the cost of writing transactions to L1.
+1. **State write**: Optimistic rollups publish transaction data and block headers (consisting of the previous block header hash, state root, batch root) to Ethereum as a `blob`, or "binary large object". [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) introduced a cost-effective solution for including data onchain. A `blob` is a new transaction field that allows rollups to post compressed state transition data to Ethereum L1. Unlike `calldata`, which remains permanently onchain, blobs are short-lived and can be pruned from clients after [4096 epochs](https://github.com/ethereum/consensus-specs/blob/81f3ea8322aff6b9fb15132d050f8f98b16bdba4/configs/mainnet.yaml#L147) (approximately 18 days). By using blobs to post batches of compressed transactions, optimistic rollups can significantly reduce the cost of writing transactions to L1.
2. **Blob gas used**: Blob-carrying transactions employ a dynamic fee mechanism similar to the one introduced by [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559). The gas fee for type-3 transactions takes into account the base fee for blobs, which is determined by the network based on blob-space demand and the blob-space usage of the transaction being sent.
@@ -208,7 +208,7 @@ Optimistic rollups apply several mechanisms to reducing fees for users, includin
## How do optimistic rollups scale Ethereum? {#scaling-ethereum-with-optimistic-rollups}
-As explained, optimistic rollups publish compressed transaction data on Ethereum to guarantee data availability. The ability to compress data published on-chain is crucial to scaling throughput on Ethereum with optimistic rollups.
+As explained, optimistic rollups publish compressed transaction data on Ethereum to guarantee data availability. The ability to compress data published onchain is crucial to scaling throughput on Ethereum with optimistic rollups.
The main Ethereum chain places limits on how much data blocks can hold, denominated in gas units (the [average block size](/developers/docs/blocks/#block-size) is 15 million gas). While this restricts how much gas each transaction can use, it also means we can increase transactions processed per block by reducing transaction-related data—directly improving scalability.
@@ -244,7 +244,7 @@ The introduction of [data sharding](/roadmap/danksharding/) on Ethereum is expec
| Fraud proving guarantees trustless finality and allows honest minorities to secure the chain. | If there are no honest nodes a malicious operator can steal funds by posting invalid blocks and state commitments. |
| Computing fraud proofs is open to regular L2 node, unlike validity proofs (used in ZK-rollups) that require special hardware. | Security model relies on at least one honest node executing rollup transactions and submitting fraud proofs to challenge invalid state transitions. |
| Rollups benefit from "trustless liveness" (anyone can force the chain to advance by executing transactions and posting assertions) | Users must wait for the one-week challenge period to expire before withdrawing funds back to Ethereum. |
-| Optimistic rollups rely on well-designed cryptoeconomic incentives to increase security on the chain. | Rollups must post all transaction data on-chain, which can increase costs. |
+| Optimistic rollups rely on well-designed cryptoeconomic incentives to increase security on the chain. | Rollups must post all transaction data onchain, which can increase costs. |
| Compatibility with EVM and Solidity allows developers to port Ethereum-native smart contracts to rollups or use existing tooling to create new dapps. |
### A visual explanation of optimistic rollups {#optimistic-video}
diff --git a/public/content/developers/docs/scaling/plasma/index.md b/public/content/developers/docs/scaling/plasma/index.md
index efac61b8b9e..a743e45ce89 100644
--- a/public/content/developers/docs/scaling/plasma/index.md
+++ b/public/content/developers/docs/scaling/plasma/index.md
@@ -6,7 +6,7 @@ incomplete: true
sidebarDepth: 3
---
-A Plasma chain is a separate blockchain anchored to Ethereum Mainnet but executing transactions off-chain with its own mechanism for block validation. Plasma chains are sometimes referred to as "child" chains, essentially smaller copies of the Ethereum Mainnet. Plasma chains use [fraud proofs](/glossary/#fraud-proof) (like [optimistic rollups](/developers/docs/scaling/optimistic-rollups/)) to arbitrate disputes.
+A Plasma chain is a separate blockchain anchored to Ethereum Mainnet but executing transactions offchain with its own mechanism for block validation. Plasma chains are sometimes referred to as "child" chains, essentially smaller copies of the Ethereum Mainnet. Plasma chains use [fraud proofs](/glossary/#fraud-proof) (like [optimistic rollups](/developers/docs/scaling/optimistic-rollups/)) to arbitrate disputes.
Merkle trees enable the creation of an endless stack of these chains that can work to offload bandwidth from parent chains (including Ethereum Mainnet). However, while these chains derive some security from Ethereum (via fraud proofs), their security and efficiency are affected by several design limitations.
@@ -24,7 +24,7 @@ The Plasma contract functions, among other things, as a [bridge](/developers/doc
The basic components of the Plasma framework are:
-### Off-chain computation {#off-chain-computation}
+### Offchain computation {#offchain-computation}
Ethereum's current processing speed is limited to ~ 15-20 transactions per second, reducing the short-term possibility of scaling to handle more users. This problem exists mainly because Ethereum's [consensus mechanism](/developers/docs/consensus-mechanisms/) requires many peer-to-peer nodes to verify every update to the blockchain's state.
@@ -32,17 +32,17 @@ Although Ethereum's consensus mechanism is necessary for security, it may not ap
Plasma supposes that Ethereum Mainnet doesn't need to verify all transactions. Instead, we can process transactions off Mainnet, freeing nodes from having to validate every transaction.
-Off-chain computation is necessary since Plasma chains can optimize for speed and cost. For example, a Plasma chain may—and most often does—use a single "operator" to manage the ordering and execution of transactions. With just one entity verifying transactions, processing times on a plasma chain are faster than Ethereum Mainnet.
+Offchain computation is necessary since Plasma chains can optimize for speed and cost. For example, a Plasma chain may—and most often does—use a single "operator" to manage the ordering and execution of transactions. With just one entity verifying transactions, processing times on a plasma chain are faster than Ethereum Mainnet.
### State commitments {#state-commitments}
-While Plasma executes transactions off-chain, they are settled on the main Ethereum execution layer—otherwise, Plasma chains cannot benefit from Ethereum's security guarantees. But finalizing off-chain transactions without knowing the state of the plasma chain would break the security model and allow the proliferation of invalid transactions. This is why the operator, the entity responsible for producing blocks on the plasma chain, is required to publish "state commitments" on Ethereum periodically.
+While Plasma executes transactions offchain, they are settled on the main Ethereum execution layer—otherwise, Plasma chains cannot benefit from Ethereum's security guarantees. But finalizing offchain transactions without knowing the state of the plasma chain would break the security model and allow the proliferation of invalid transactions. This is why the operator, the entity responsible for producing blocks on the plasma chain, is required to publish "state commitments" on Ethereum periodically.
A [commitment scheme](https://en.wikipedia.org/wiki/Commitment_scheme) is a cryptographic technique for committing to a value or statement without revealing it to another party. Commitments are "binding" in the sense that you cannot change the value or statement once you've committed to it. State commitments in Plasma take the form of "Merkle roots" (derived from a [Merkle tree](/whitepaper/#merkle-trees)) which the operator sends at intervals to the Plasma contract on the Ethereum chain.
Merkle roots are cryptographic primitives that enable compressing of large amounts of information. A Merkle root (also called a "block root" in this case) could represent all the transactions in a block. Merkle roots also make it easier to verify that a small piece of data is part of the larger dataset. For instance, a user can produce a [Merkle proof](/developers/tutorials/merkle-proofs-for-offline-data-integrity/#main-content) to prove the inclusion of a transaction in a specific block.
-Merkle roots are important for providing information about the off-chain's state to Ethereum. You can think of Merkle roots as "save points": the operator is saying, "This is the state of the Plasma chain at x point in time, and this is the Merkle root as proof." The operator is committing to the _current state_ of the plasma chain with a Merkle root, which is why it is called a "state commitment".
+Merkle roots are important for providing information about the offchain's state to Ethereum. You can think of Merkle roots as "save points": the operator is saying, "This is the state of the Plasma chain at x point in time, and this is the Merkle root as proof." The operator is committing to the _current state_ of the plasma chain with a Merkle root, which is why it is called a "state commitment".
### Entries and exits {#entries-and-exits}
@@ -86,9 +86,9 @@ The mass exit problem occurs when a large number of users try to withdraw from a
Data availability is the ability to verify that the information for a proposed block was actually published on the blockchain network. A block is "unavailable" if the producer publishes the block itself but withholds data used to create the block.
-Blocks must be available if nodes are to be able to download the block and verify the validity of transactions. Blockchains ensure data availability by forcing block producers to post all transaction data on-chain.
+Blocks must be available if nodes are to be able to download the block and verify the validity of transactions. Blockchains ensure data availability by forcing block producers to post all transaction data onchain.
-Data availability also helps with securing off-chain scaling protocols that build on Ethereum's base layer. By forcing operators on these chains to publish transaction data on Ethereum, anyone can challenge invalid blocks by constructing fraud proofs referencing the correct state of the chain.
+Data availability also helps with securing offchain scaling protocols that build on Ethereum's base layer. By forcing operators on these chains to publish transaction data on Ethereum, anyone can challenge invalid blocks by constructing fraud proofs referencing the correct state of the chain.
Plasma chains primarily store transaction data with the operator and **do not publish any data on Mainnet** (i.e., besides periodic state commitments). This means users must rely on the operator to provide block data if they need to create fraud proofs challenging invalid transactions. If this system works, then users can always use fraud proofs to secure funds.
@@ -111,7 +111,7 @@ Although exit games sound nice in theory, real-life mass exits will likely trigg
| Offers high throughput and low cost per transaction. | Does not support general computation (cannot run smart contracts). Only basic token transfers, swaps, and a few other transaction types are supported via predicate logic. |
| Good for transactions between arbitrary users (no overhead per user pair if both are established on the plasma chain) | Need to periodically watch the network (liveness requirement) or delegate this responsibility to someone else to ensure the security of your funds. |
| Plasma chains can be adapted to specific use-cases that are unrelated to the main chain. Anyone, including businesses, can customize Plasma smart contracts to provide scalable infrastructure that works in different contexts. | Relies on one or more operators to store data and serve it upon request. |
-| Reduces load on Ethereum Mainnet by moving computation and storage off-chain. | Withdrawals are delayed by several days to allow for challenges. For fungible assets, this can be mitigated by liquidity providers, but there is an associated capital cost. |
+| Reduces load on Ethereum Mainnet by moving computation and storage offchain. | Withdrawals are delayed by several days to allow for challenges. For fungible assets, this can be mitigated by liquidity providers, but there is an associated capital cost. |
| | If too many users try to exit simultaneously, Ethereum Mainnet could get congested. |
## Plasma vs layer 2 scaling protocols {#plasma-vs-layer-2}
@@ -120,7 +120,7 @@ While Plasma was once considered a useful scaling solution for Ethereum, it has
### Efficiency {#efficiency}
-[Zero-Knowledge rollups](/developers/docs/scaling/zk-rollups) generate cryptographic proofs of the validity of each batch of transactions processed off-chain. This prevents the users (and operators) from advancing invalid state transitions, eliminating the need for challenge periods and exit games. It also means users don't have to watch the chain periodically to secure their funds.
+[Zero-Knowledge rollups](/developers/docs/scaling/zk-rollups) generate cryptographic proofs of the validity of each batch of transactions processed offchain. This prevents the users (and operators) from advancing invalid state transitions, eliminating the need for challenge periods and exit games. It also means users don't have to watch the chain periodically to secure their funds.
### Support for smart contracts {#support-for-smart-contracts}
diff --git a/public/content/developers/docs/scaling/state-channels/index.md b/public/content/developers/docs/scaling/state-channels/index.md
index a4cfdefe0e2..bb395088d8e 100644
--- a/public/content/developers/docs/scaling/state-channels/index.md
+++ b/public/content/developers/docs/scaling/state-channels/index.md
@@ -5,7 +5,7 @@ lang: en
sidebarDepth: 3
---
-State channels allow participants to securely transact off-chain while keeping interaction with Ethereum Mainnet at a minimum. Channel peers can conduct an arbitrary number of off-chain transactions while only submitting two on-chain transactions to open and close the channel. This allows for extremely high transaction throughput and results in lower costs for users.
+State channels allow participants to securely transact offchain while keeping interaction with Ethereum Mainnet at a minimum. Channel peers can conduct an arbitrary number of offchain transactions while only submitting two onchain transactions to open and close the channel. This allows for extremely high transaction throughput and results in lower costs for users.
## Prerequisites {#prerequisites}
@@ -13,35 +13,35 @@ You should have read and understood our pages on [Ethereum scaling](/developers/
## What are channels? {#what-are-channels}
-Public blockchains, such as Ethereum, face scalability challenges due to their distributed architecture: on-chain transactions must be executed by all nodes. Nodes have to be able to handle the volume of transactions in a block using modest hardware, imposing a limit on the transaction throughput to keep the network decentralized. Blockchain channels solve this problem by allowing users to interact off-chain while still relying on the security of the main chain for final settlement.
+Public blockchains, such as Ethereum, face scalability challenges due to their distributed architecture: onchain transactions must be executed by all nodes. Nodes have to be able to handle the volume of transactions in a block using modest hardware, imposing a limit on the transaction throughput to keep the network decentralized. Blockchain channels solve this problem by allowing users to interact offchain while still relying on the security of the main chain for final settlement.
Channels are simple peer-to-peer protocols that allow two parties to make many transactions between themselves and then only post the final results to the blockchain. The channel uses cryptography to demonstrate that the summary data they generate is truly the result of a valid set of intermediate transactions. A ["multisig"](/developers/docs/smart-contracts/#multisig) smart contract ensures the transactions are signed by the correct parties.
With channels, state changes are executed and validated by interested parties, minimizing computation on Ethereum's execution layer. This decreases congestion on Ethereum and also increases transaction processing speeds for users.
-Each channel is managed by a [multisig smart contract](/developers/docs/smart-contracts/#multisig) running on Ethereum. To open a channel, participants deploy the channel contract on-chain and deposit funds into it. Both parties collectively sign a state update to initialize the channel's state, after which they can transact quickly and freely off-chain.
+Each channel is managed by a [multisig smart contract](/developers/docs/smart-contracts/#multisig) running on Ethereum. To open a channel, participants deploy the channel contract onchain and deposit funds into it. Both parties collectively sign a state update to initialize the channel's state, after which they can transact quickly and freely offchain.
-To close the channel, participants submit the last agreed-upon state of the channel on-chain. Afterward, the smart contract distributes the locked funds according to each participant's balance in the channel's final state.
+To close the channel, participants submit the last agreed-upon state of the channel onchain. Afterward, the smart contract distributes the locked funds according to each participant's balance in the channel's final state.
Peer-to-peer channels are particularly useful for situations where some predefined participants wish to transact with high frequency without incurring visible overhead. Blockchain channels fall under two categories: **payment channels** and **state channels**.
## Payment channels {#payment-channels}
-A payment channel is best described as a "two-way ledger" collectively maintained by two users. The ledger's initial balance is the sum of deposits locked into the on-chain contract during the channel opening phase. Payment channel transfers can be performed instantaneously and without the involvement of the actual blockchain itself, except for an initial one-time on-chain creation and an eventual closing of the channel.
+A payment channel is best described as a "two-way ledger" collectively maintained by two users. The ledger's initial balance is the sum of deposits locked into the onchain contract during the channel opening phase. Payment channel transfers can be performed instantaneously and without the involvement of the actual blockchain itself, except for an initial one-time onchain creation and an eventual closing of the channel.
Updates to the ledger's balance (i.e., the payment channel's state) require the approval of all parties in the channel. A channel update, signed by all channel participants, is considered finalized, much like a transaction on Ethereum.
-Payment channels were among the earliest scaling solutions designed to minimize expensive on-chain activity of simple user interactions (e.g. ETH transfers, atomic swaps, micropayments). Channel participants can conduct an unlimited amount of instant, feeless transactions between each other as long as the net sum of their transfers does not exceed the deposited tokens.
+Payment channels were among the earliest scaling solutions designed to minimize expensive onchain activity of simple user interactions (e.g. ETH transfers, atomic swaps, micropayments). Channel participants can conduct an unlimited amount of instant, feeless transactions between each other as long as the net sum of their transfers does not exceed the deposited tokens.
## State channels {#state-channels}
-Apart from supporting off-chain payments, payment channels have not proven useful for handling general state transition logic. State channels were created to solve this problem and make channels useful for scaling general-purpose computation.
+Apart from supporting offchain payments, payment channels have not proven useful for handling general state transition logic. State channels were created to solve this problem and make channels useful for scaling general-purpose computation.
State channels still have a lot in common with payment channels. For example, users interact by exchanging cryptographically signed messages (transactions), which the other channel participants must also sign. If a proposed state update isn't signed by all participants, it is considered invalid.
However, in addition to holding the user's balances, the channel also tracks the current state of the contract's storage (i.e., values of contract variables).
-This makes it possible to execute a smart contract off-chain between two users. In this scenario, updates to the smart contract's internal state require only the approval of the peers who created the channel.
+This makes it possible to execute a smart contract offchain between two users. In this scenario, updates to the smart contract's internal state require only the approval of the peers who created the channel.
While this solves the scalability problem described earlier, it has implications for security. On Ethereum, the validity of state transitions is enforced by the network's consensus protocol. This makes it impossible to propose an invalid update to a smart contract's state or alter smart contract execution.
@@ -49,13 +49,13 @@ State channels don't have the same security guarantees. To some extent, a state
## How state channels work {#how-state-channels-work}
-Basically, the activity in a state channel is a session of interactions involving users and a blockchain system. Users mostly communicate with each other off-chain and only interact with the underlying blockchain to open the channel, close the channel, or settle potential disputes between participants.
+Basically, the activity in a state channel is a session of interactions involving users and a blockchain system. Users mostly communicate with each other offchain and only interact with the underlying blockchain to open the channel, close the channel, or settle potential disputes between participants.
The following section outlines the basic workflow of a state channel:
### Opening the channel {#opening-the-channel}
-Opening a channel requires participants to commit funds to a smart contract on Mainnet. The deposit also functions as a virtual tab, so participating actors can transact freely without needing to settle payments immediately. Only when the channel is finalized on-chain do parties settle each other and withdraw what's left of their tab.
+Opening a channel requires participants to commit funds to a smart contract on Mainnet. The deposit also functions as a virtual tab, so participating actors can transact freely without needing to settle payments immediately. Only when the channel is finalized onchain do parties settle each other and withdraw what's left of their tab.
This deposit also serves as a bond to guarantee honest behavior from each participant. If depositors are found guilty of malicious actions during the dispute resolution phase, the contract slashes their deposit.
@@ -73,13 +73,13 @@ After initializing the channel's state, peers interact by signing transactions a
- The transaction which triggers the state transition (e.g., Alice sends 5 ETH to Bob)
-State updates in the channel are not broadcasted on-chain as is normally the case when users interact on Mainnet, which aligns with state channels' goal to minimize on-chain footprint. As long as participants agree on state updates, they are as final as an Ethereum transaction. Participants only need to depend on Mainnet's consensus if a dispute arises.
+State updates in the channel are not broadcasted onchain as is normally the case when users interact on Mainnet, which aligns with state channels' goal to minimize onchain footprint. As long as participants agree on state updates, they are as final as an Ethereum transaction. Participants only need to depend on Mainnet's consensus if a dispute arises.
### Closing the channel {#closing-the-channel}
-Closing a state channel requires submitting the channel's final, agreed-upon state to the on-chain smart contract. Details referenced in the state update include the number of each participant's moves and a list of approved transactions.
+Closing a state channel requires submitting the channel's final, agreed-upon state to the onchain smart contract. Details referenced in the state update include the number of each participant's moves and a list of approved transactions.
-After verifying that the state update is valid (i.e., it is signed by all parties) the smart contract finalizes the channel and distributes the locked funds according to the channel's outcome. Payments made off-chain are applied to Ethereum's state and each participant receives their remaining portion of the locked funds.
+After verifying that the state update is valid (i.e., it is signed by all parties) the smart contract finalizes the channel and distributes the locked funds according to the channel's outcome. Payments made offchain are applied to Ethereum's state and each participant receives their remaining portion of the locked funds.
The scenario described above represents what happens in the happy case. Sometimes, users may be unable to reach an agreement and finalize the channel (the sad case). Any of the following could be true of the situation:
@@ -87,33 +87,33 @@ The scenario described above represents what happens in the happy case. Sometime
- Participants refuse to co-sign valid state updates
-- Participants try to finalize the channel by proposing an old state update to the on-chain contract
+- Participants try to finalize the channel by proposing an old state update to the onchain contract
- Participants propose invalid state transitions for others to sign
-Whenever consensus breaks down between participating actors in a channel, the last option is to rely on Mainnet's consensus to enforce the channel's final, valid state. In this case, closing the state channel requires settling disputes on-chain.
+Whenever consensus breaks down between participating actors in a channel, the last option is to rely on Mainnet's consensus to enforce the channel's final, valid state. In this case, closing the state channel requires settling disputes onchain.
### Settling disputes {#settling-disputes}
-Typically, parties in a channel agree on closing the channel beforehand and co-sign the last state transition, which they submit to the smart contract. Once the update is approved on-chain, execution of the off-chain smart contract ends and participants exit the channel with their money.
+Typically, parties in a channel agree on closing the channel beforehand and co-sign the last state transition, which they submit to the smart contract. Once the update is approved onchain, execution of the offchain smart contract ends and participants exit the channel with their money.
-However, one party can submit an on-chain request to end the smart contract's execution and finalize the channel—without waiting for their counterpart's approval. If any of the consensus-breaking situations described earlier occur, either party can trigger the on-chain contract to close the channel and distribute funds. This provides **trustlessness**, ensuring that honest parties can exit their deposits at any point, regardless of the other party's actions.
+However, one party can submit an onchain request to end the smart contract's execution and finalize the channel—without waiting for their counterpart's approval. If any of the consensus-breaking situations described earlier occur, either party can trigger the onchain contract to close the channel and distribute funds. This provides **trustlessness**, ensuring that honest parties can exit their deposits at any point, regardless of the other party's actions.
-To process the channel exit, the user must submit the application's last valid state update to the on-chain contract. If this checks out (i.e., it bears the signature of all parties), then funds are redistributed in their favor.
+To process the channel exit, the user must submit the application's last valid state update to the onchain contract. If this checks out (i.e., it bears the signature of all parties), then funds are redistributed in their favor.
-There is, however, a delay in executing single-user exit requests. If the request to conclude the channel was unanimously approved, then the on-chain exit transaction is executed immediately.
+There is, however, a delay in executing single-user exit requests. If the request to conclude the channel was unanimously approved, then the onchain exit transaction is executed immediately.
-The delay comes into play in single-user exits due to the possibility of fraudulent actions. For example, a channel participant may try to finalize the channel on Ethereum by submitting an older state update on-chain.
+The delay comes into play in single-user exits due to the possibility of fraudulent actions. For example, a channel participant may try to finalize the channel on Ethereum by submitting an older state update onchain.
-As a countermeasure, state channels allow honest users to challenge invalid state updates by submitting the latest, valid state of the channel on-chain. State channels are designed such that newer, agreed-upon state updates trump older state updates.
+As a countermeasure, state channels allow honest users to challenge invalid state updates by submitting the latest, valid state of the channel onchain. State channels are designed such that newer, agreed-upon state updates trump older state updates.
-Once a peer triggers the on-chain dispute-resolution system, the other party is required to respond within a time limit (called the challenge window). This allows users to challenge the exit transaction, especially if the other party is applying a stale update.
+Once a peer triggers the onchain dispute-resolution system, the other party is required to respond within a time limit (called the challenge window). This allows users to challenge the exit transaction, especially if the other party is applying a stale update.
-Whatever the case may be, channel users always have strong finality guarantees: if the state transition in their possession was signed by all members and is the most recent update, then it is of equal finality with a regular on-chain transaction. They still have to challenge the other party on-chain, but the only possible outcome is finalizing the last valid state, which they hold.
+Whatever the case may be, channel users always have strong finality guarantees: if the state transition in their possession was signed by all members and is the most recent update, then it is of equal finality with a regular onchain transaction. They still have to challenge the other party onchain, but the only possible outcome is finalizing the last valid state, which they hold.
### How do state channels interact with Ethereum? {#how-do-state-channels-interact-with-ethereum}
-Although they exist as off-chain protocols, state channels have an on-chain component: the smart contract deployed on Ethereum when opening the channel. This contract controls the assets deposited into the channel, verifies state updates, and arbitrates disputes between participants.
+Although they exist as offchain protocols, state channels have an onchain component: the smart contract deployed on Ethereum when opening the channel. This contract controls the assets deposited into the channel, verifies state updates, and arbitrates disputes between participants.
State channels don't publish transaction data or state commitments to Mainnet, unlike [layer 2](/layer-2/) scaling solutions. However, they are more connected to Mainnet than, say, [sidechains](/developers/docs/scaling/sidechains/), making them somewhat safer.
@@ -121,53 +121,53 @@ State channels rely on the main Ethereum protocol for the following:
#### 1. Liveness {#liveness}
-The on-chain contract deployed when opening the channel is responsible for the channel's functionality. If the contract is running on Ethereum, then the channel is always available for usage. Conversely, a sidechain can always fail, even if Mainnet is operational, putting user funds at risk.
+The onchain contract deployed when opening the channel is responsible for the channel's functionality. If the contract is running on Ethereum, then the channel is always available for usage. Conversely, a sidechain can always fail, even if Mainnet is operational, putting user funds at risk.
#### 2. Security {#security}
To some extent, state channels rely on Ethereum to provide security and protect users from malicious peers. As discussed in later sections, channels use a fraud proof mechanism that lets users challenge attempts to finalize the channel with an invalid or stale update.
-In this case, the honest party provides the latest valid state of the channel as a fraud proof to the on-chain contract for verification. Fraud proofs enable mutually distrustful parties to conduct off-chain transactions without risking their funds in the process.
+In this case, the honest party provides the latest valid state of the channel as a fraud proof to the onchain contract for verification. Fraud proofs enable mutually distrustful parties to conduct offchain transactions without risking their funds in the process.
#### 3. Finality {#finality}
-State updates collectively signed by channel users are considered as good as on-chain transactions. Still, all in-channel activity only achieves true finality when the channel is closed on Ethereum.
+State updates collectively signed by channel users are considered as good as onchain transactions. Still, all in-channel activity only achieves true finality when the channel is closed on Ethereum.
-In the optimistic case, both parties can cooperate and sign the final state update and submit on-chain to close the channel, after which the funds are distributed according to the channel's final state. In the pessimistic case, where someone tries to cheat by posting an incorrect state update on-chain, their transaction isn't finalized until the challenge window elapses.
+In the optimistic case, both parties can cooperate and sign the final state update and submit onchain to close the channel, after which the funds are distributed according to the channel's final state. In the pessimistic case, where someone tries to cheat by posting an incorrect state update onchain, their transaction isn't finalized until the challenge window elapses.
## Virtual state channels {#virtual-state-channels}
-The naive implementation of a state channel would be to deploy a new contract when two users wish to execute an application off-chain. This is not only infeasible, but it also negates the cost-effectiveness of state channels (on-chain transaction costs can quickly add up).
+The naive implementation of a state channel would be to deploy a new contract when two users wish to execute an application offchain. This is not only infeasible, but it also negates the cost-effectiveness of state channels (onchain transaction costs can quickly add up).
-To solve this problem, "virtual channels" were created. Unlike regular channels that require on-chain transactions to open and terminate, a virtual channel can be opened, executed, and finalized without interacting with the main chain. It is even possible to settle disputes off-chain using this method.
+To solve this problem, "virtual channels" were created. Unlike regular channels that require onchain transactions to open and terminate, a virtual channel can be opened, executed, and finalized without interacting with the main chain. It is even possible to settle disputes offchain using this method.
-This system relies on the existence of so-called "ledger channels", which have been funded on-chain. Virtual channels between two parties can be built on top of an existing ledger channel, with the owner(s) of the ledger channel serving as an intermediary.
+This system relies on the existence of so-called "ledger channels", which have been funded onchain. Virtual channels between two parties can be built on top of an existing ledger channel, with the owner(s) of the ledger channel serving as an intermediary.
-Users in each virtual channel interact via a new contract instance, with the ledger channel able to support multiple contract instances. The ledger channel's state also contains more than one contract storage state, allowing for parallel execution of applications off-chain between different users.
+Users in each virtual channel interact via a new contract instance, with the ledger channel able to support multiple contract instances. The ledger channel's state also contains more than one contract storage state, allowing for parallel execution of applications offchain between different users.
Just like regular channels, users exchange state updates to progress the state machine. Unless a dispute arises, the intermediary only has to be contacted when opening or terminating the channel.
### Virtual payment channels {#virtual-payment-channels}
-Virtual payment channels work off the same idea as virtual state channels: participants connected to the same network can pass messages without needing to open a new channel on-chain. In virtual payment channels, value transfers are routed through one or more intermediaries, with guarantees that only the intended recipient can receive transferred funds.
+Virtual payment channels work off the same idea as virtual state channels: participants connected to the same network can pass messages without needing to open a new channel onchain. In virtual payment channels, value transfers are routed through one or more intermediaries, with guarantees that only the intended recipient can receive transferred funds.
## Applications of state channels {#applications-of-state-channels}
### Payments {#payments}
-Early blockchain channels were simple protocols that allowed two participants to conduct rapid, low-fee transfers off-chain without having to pay high transaction fees on Mainnet. Today, payment channels are still useful for applications designed for the exchange and deposits of ether and tokens.
+Early blockchain channels were simple protocols that allowed two participants to conduct rapid, low-fee transfers offchain without having to pay high transaction fees on Mainnet. Today, payment channels are still useful for applications designed for the exchange and deposits of ether and tokens.
Channel-based payments have the following advantages:
-1. **Throughput**: The amount of off-chain transactions per channel is unconnected to Ethereum's throughput, which is influenced by various factors, especially block size and block time. By executing transactions off-chain, blockchain channels can achieve higher throughput.
+1. **Throughput**: The amount of offchain transactions per channel is unconnected to Ethereum's throughput, which is influenced by various factors, especially block size and block time. By executing transactions offchain, blockchain channels can achieve higher throughput.
-2. **Privacy**: Because channels exist off-chain, details of interactions between participants are not recorded on Ethereum's public blockchain. Channel users only have to interact on-chain when funding and closing channels or settling disputes. Thus, channels are useful for individuals who desire more private transactions.
+2. **Privacy**: Because channels exist offchain, details of interactions between participants are not recorded on Ethereum's public blockchain. Channel users only have to interact onchain when funding and closing channels or settling disputes. Thus, channels are useful for individuals who desire more private transactions.
-3. **Latency**: Off-chain transactions conducted between channel participants can be settled instantly, if both parties cooperate, reducing delays. In contrast, sending a transaction on Mainnet requires waiting for nodes to process the transaction, produce a new block with the transaction, and reach consensus. Users may also need to wait for more block confirmations before considering a transaction finalized.
+3. **Latency**: Offchain transactions conducted between channel participants can be settled instantly, if both parties cooperate, reducing delays. In contrast, sending a transaction on Mainnet requires waiting for nodes to process the transaction, produce a new block with the transaction, and reach consensus. Users may also need to wait for more block confirmations before considering a transaction finalized.
4. **Cost**: State channels are particularly useful in situations where a set of participants will exchange many state updates over a long period. The only costs incurred are the opening and closing of the state channel smart contract; every state change between opening and closing the channel will be cheaper than the last as the settlement cost is distributed accordingly.
-Implementing state channels on layer 2 solutions, such as [rollups](/developers/docs/scaling/#rollups), could make them even more attractive for payments. While channels offer cheap payments, the costs of setting up the on-chain contract on Mainnet during the opening phase can be get expensive—especially when gas fees spike. Ethereum-based rollups offer [lower transaction fees](https://l2fees.info/) and can reduce overhead for channel participants by bringing down setup fees.
+Implementing state channels on layer 2 solutions, such as [rollups](/developers/docs/scaling/#rollups), could make them even more attractive for payments. While channels offer cheap payments, the costs of setting up the onchain contract on Mainnet during the opening phase can be get expensive—especially when gas fees spike. Ethereum-based rollups offer [lower transaction fees](https://l2fees.info/) and can reduce overhead for channel participants by bringing down setup fees.
### Microtransactions {#microtransactions}
@@ -179,19 +179,19 @@ Beyond the cost of opening and closing the channel, participants don't incur fur
### Decentralized applications {#decentralized-applications}
-Like payment channels, state channels can make conditional payments according to the state machine's final states. State channels can also support arbitrary state transition logic, making them useful for executing generic apps off-chain.
+Like payment channels, state channels can make conditional payments according to the state machine's final states. State channels can also support arbitrary state transition logic, making them useful for executing generic apps offchain.
-State channels are often limited to simple turn-based applications, as this makes it easier to manage funds committed to the on-chain contract. Also, with a limited number of parties updating the off-chain application's state at intervals, punishing dishonest behavior is relatively straightforward.
+State channels are often limited to simple turn-based applications, as this makes it easier to manage funds committed to the onchain contract. Also, with a limited number of parties updating the offchain application's state at intervals, punishing dishonest behavior is relatively straightforward.
-The efficiency of a state channel application also depends on its design. For example, a developer might deploy the app channel contract on-chain once and allow other players to re-use the app without having to go on-chain. In this case, the initial app channel serves as a ledger channel supporting multiple virtual channels, each running a new instance of the app's smart contract off-chain.
+The efficiency of a state channel application also depends on its design. For example, a developer might deploy the app channel contract onchain once and allow other players to re-use the app without having to go onchain. In this case, the initial app channel serves as a ledger channel supporting multiple virtual channels, each running a new instance of the app's smart contract offchain.
-A potential use-case for state channel applications is simple two-player games, where funds are distributed based on the game's outcome. The benefit here is that players don't have to trust each other (trustlessness) and the on-chain contract, not players, controls the allocation of funds and settlement of disputes (decentralization).
+A potential use-case for state channel applications is simple two-player games, where funds are distributed based on the game's outcome. The benefit here is that players don't have to trust each other (trustlessness) and the onchain contract, not players, controls the allocation of funds and settlement of disputes (decentralization).
Other possible use-cases for state channel apps include ENS name ownership, NFT ledgers, and many more.
### Atomic transfers {#atomic-transfers}
-Early payment channels were restricted to transfers between two parties, limiting their usability. However, the introduction of virtual channels allowed individuals to route transfers through intermediaries (i.e., multiple p2p channels) without having to open a new channel on-chain.
+Early payment channels were restricted to transfers between two parties, limiting their usability. However, the introduction of virtual channels allowed individuals to route transfers through intermediaries (i.e., multiple p2p channels) without having to open a new channel onchain.
Commonly described as "multi-hop transfers", routed payments are atomic (i.e., either all parts of the transaction succeed or it fails altogether). Atomic transfers use [Hashed Timelock Contracts (HTLCs)](https://en.bitcoin.it/wiki/Hash_Time_Locked_Contracts) to ensure the payment is released only if certain conditions are met, thereby reducing counterparty risk.
@@ -203,41 +203,41 @@ To ensure efficiency, state channels place time limits on the ability of channel
In reality, users can go offline for reasons out of their control (e.g., poor internet connection, mechanical failure, etc.). If an honest user goes offline, a malicious peer can exploit the situation by presenting old intermediate states to the adjudicator contract and stealing the committed funds.
-Some channels use "watchtowers"—entities responsible for watching on-chain dispute events on behalf of others and taking necessary actions, like alerting concerned parties. However, this can add to the costs of using a state channel.
+Some channels use "watchtowers"—entities responsible for watching onchain dispute events on behalf of others and taking necessary actions, like alerting concerned parties. However, this can add to the costs of using a state channel.
### Data unavailability {#data-unavailability}
As explained earlier, challenging an invalid dispute requires presenting the latest, valid state of the state channel. This is another rule based on an assumption—that users have access to the channel's latest state.
-Although expecting channel users to store copies of off-chain application state is reasonable, this data may be lost due to error or mechanical failure. If the user doesn't have the data backed up, they can only hope that the other party doesn't finalize an invalid exit request using old state transitions in their possession.
+Although expecting channel users to store copies of offchain application state is reasonable, this data may be lost due to error or mechanical failure. If the user doesn't have the data backed up, they can only hope that the other party doesn't finalize an invalid exit request using old state transitions in their possession.
Ethereum users don't have to deal with this problem since the network enforces rules on data availability. Transaction data is stored and propagated by all nodes and available for users to download if and when necessary.
### Liquidity issues {#liquidity-issues}
-To establish a blockchain channel, participants need to lock funds in an on-chain smart contract for the channel's lifecycle. This reduces the liquidity of channel users and also limits channels to those who can afford to keep funds locked on Mainnet.
+To establish a blockchain channel, participants need to lock funds in an onchain smart contract for the channel's lifecycle. This reduces the liquidity of channel users and also limits channels to those who can afford to keep funds locked on Mainnet.
-However, ledger channels—operated by an off-chain service provider (OSP)—can reduce liquidity issues for users. Two peers connected to a ledger channel can create a virtual channel, which they can open and finalize completely off-chain, anytime they want.
+However, ledger channels—operated by an offchain service provider (OSP)—can reduce liquidity issues for users. Two peers connected to a ledger channel can create a virtual channel, which they can open and finalize completely offchain, anytime they want.
-Off-chain service providers could also open channels with multiple peers, making them useful for routing payments. Of course, users must pay fees to OSPs for their services, which may be undesirable for some.
+Offchain service providers could also open channels with multiple peers, making them useful for routing payments. Of course, users must pay fees to OSPs for their services, which may be undesirable for some.
### Griefing attacks {#griefing-attacks}
Griefing attacks are a common feature of fraud proof-based systems. A griefing attack does not directly benefit the attacker but causes grief (i.e., harm) to the victim, hence the name.
-Fraud proving is susceptible to griefing attacks because the honest party must respond to every dispute, even invalid ones, or risk losing their funds. A malicious participant can decide to repeatedly post stale state transitions on-chain, forcing the honest party to respond with the valid state. The cost of those on-chain transactions can quickly add up, causing honest parties to lose out in the process.
+Fraud proving is susceptible to griefing attacks because the honest party must respond to every dispute, even invalid ones, or risk losing their funds. A malicious participant can decide to repeatedly post stale state transitions onchain, forcing the honest party to respond with the valid state. The cost of those onchain transactions can quickly add up, causing honest parties to lose out in the process.
### Predefined participant sets {#predefined-participant-sets}
-By design, the number of participants that comprise a state channel remains fixed throughout its lifetime. This is because updating the participant set would complicate the channel's operation, especially when funding the channel, or settling disputes. Adding or removing participants would also require additional on-chain activity, which increases overhead for users.
+By design, the number of participants that comprise a state channel remains fixed throughout its lifetime. This is because updating the participant set would complicate the channel's operation, especially when funding the channel, or settling disputes. Adding or removing participants would also require additional onchain activity, which increases overhead for users.
While this makes state channels easier to reason about, it limits the usefulness of channel designs to application developers. This partly explains why state channels have been dropped in favor of other scaling solutions, such as rollups.
### Parallel transaction processing {#parallel-transaction-processing}
-Participants in the state channel send state updates in turns, which is why they work best for "turn-based applications" (e.g., a two-player chess game). This eliminates the need to handle simultaneous state updates and reduces the work the on-chain contract must do to punish stale update posters. However, a side-effect of this design is that transactions are dependent on each other, increasing latency and diminishing the overall user experience.
+Participants in the state channel send state updates in turns, which is why they work best for "turn-based applications" (e.g., a two-player chess game). This eliminates the need to handle simultaneous state updates and reduces the work the onchain contract must do to punish stale update posters. However, a side-effect of this design is that transactions are dependent on each other, increasing latency and diminishing the overall user experience.
-Some state channels solve this problem by using a "full-duplex" design that separates the off-chain state into two unidirectional "simplex" states, allowing for concurrent state updates. Such designs improve off-chain throughput and decrease transaction delays.
+Some state channels solve this problem by using a "full-duplex" design that separates the offchain state into two unidirectional "simplex" states, allowing for concurrent state updates. Such designs improve offchain throughput and decrease transaction delays.
## Use state channels {#use-state-channels}
diff --git a/public/content/developers/docs/scaling/validium/index.md b/public/content/developers/docs/scaling/validium/index.md
index 11d2ec76569..895332b57c6 100644
--- a/public/content/developers/docs/scaling/validium/index.md
+++ b/public/content/developers/docs/scaling/validium/index.md
@@ -5,7 +5,7 @@ lang: en
sidebarDepth: 3
---
-Validium is a [scaling solution](/developers/docs/scaling/) that enforces integrity of transactions using validity proofs like [ZK-rollups](/developers/docs/scaling/zk-rollups/), but doesn’t store transaction data on the Ethereum Mainnet. While off-chain data availability introduces trade-offs, it can lead to massive improvements in scalability (validiums can process [~9,000 transactions, or more, per second](https://blog.matter-labs.io/zkrollup-vs-validium-starkex-5614e38bc263)).
+Validium is a [scaling solution](/developers/docs/scaling/) that enforces integrity of transactions using validity proofs like [ZK-rollups](/developers/docs/scaling/zk-rollups/), but doesn’t store transaction data on the Ethereum Mainnet. While offchain data availability introduces trade-offs, it can lead to massive improvements in scalability (validiums can process [~9,000 transactions, or more, per second](https://blog.matter-labs.io/zkrollup-vs-validium-starkex-5614e38bc263)).
## Prerequisites {#prerequisites}
@@ -13,35 +13,35 @@ You should have read and understood our page on [Ethereum scaling](/developers/d
## What is validium? {#what-is-validium}
-Validiums are scaling solutions that use off-chain data availability and computation designed to improve throughput by processing transactions off the Ethereum Mainnet. Like zero-knowledge rollups (ZK-rollups), validiums publish [zero-knowledge proofs](/glossary/#zk-proof) to verify off-chain transactions on Ethereum. This prevents invalid state transitions and enhances the security guarantees of a validium chain.
+Validiums are scaling solutions that use offchain data availability and computation designed to improve throughput by processing transactions off the Ethereum Mainnet. Like zero-knowledge rollups (ZK-rollups), validiums publish [zero-knowledge proofs](/glossary/#zk-proof) to verify offchain transactions on Ethereum. This prevents invalid state transitions and enhances the security guarantees of a validium chain.
These "validity proofs" can come in the form of ZK-SNARKs (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge) or ZK-STARKs (Zero-Knowledge Scalable Transparent ARgument of Knowledge). More on [zero-knowledge proofs](https://consensys.net/blog/blockchain-explained/zero-knowledge-proofs-starks-vs-snarks/).
-Funds belonging to validium users are controlled by a smart contract on Ethereum. Validiums offer near-instant withdrawals, much like ZK-rollups do; once the validity proof for a withdrawal request has been verified on Mainnet, users can withdraw funds by providing [Merkle proofs](/developers/tutorials/merkle-proofs-for-offline-data-integrity/). The Merkle proof validates the inclusion of the user’s withdrawal transaction in a verified transaction batch, allowing the on-chain contract to process the withdrawal.
+Funds belonging to validium users are controlled by a smart contract on Ethereum. Validiums offer near-instant withdrawals, much like ZK-rollups do; once the validity proof for a withdrawal request has been verified on Mainnet, users can withdraw funds by providing [Merkle proofs](/developers/tutorials/merkle-proofs-for-offline-data-integrity/). The Merkle proof validates the inclusion of the user’s withdrawal transaction in a verified transaction batch, allowing the onchain contract to process the withdrawal.
-However, validium users can have their funds frozen and withdrawals restricted. This can happen if data availability managers on the validium chain withhold off-chain state data from users. Without access to transaction data, users cannot compute the Merkle proof required to prove ownership of funds and execute withdrawals.
+However, validium users can have their funds frozen and withdrawals restricted. This can happen if data availability managers on the validium chain withhold offchain state data from users. Without access to transaction data, users cannot compute the Merkle proof required to prove ownership of funds and execute withdrawals.
This is the major difference between validiums and ZK-rollups—their positions on the data availability spectrum. Both solutions approach data storage differently, which has implications for security and trustlessness.
## How do validiums interact with Ethereum? {#how-do-validiums-interact-with-ethereum}
-Validiums are scaling protocols built on top of the existing Ethereum chain. Although it executes transactions off-chain, a validium chain is administered by a collection of smart contracts deployed on Mainnet including:
+Validiums are scaling protocols built on top of the existing Ethereum chain. Although it executes transactions offchain, a validium chain is administered by a collection of smart contracts deployed on Mainnet including:
-1. **Verifier contract**: The verifier contract verifies the validity of proofs submitted by the validium operator when making state updates. This includes validity proofs attesting to the correctness of off-chain transactions and data availability proofs verifying the existence of off-chain transaction data.
+1. **Verifier contract**: The verifier contract verifies the validity of proofs submitted by the validium operator when making state updates. This includes validity proofs attesting to the correctness of offchain transactions and data availability proofs verifying the existence of offchain transaction data.
-2. **Main contract**: The main contract stores state commitments (Merkle roots) submitted by block producers and updates the validium's state once a validity proof is verified on-chain. This contract also processes deposits to and withdrawals from the validium chain.
+2. **Main contract**: The main contract stores state commitments (Merkle roots) submitted by block producers and updates the validium's state once a validity proof is verified onchain. This contract also processes deposits to and withdrawals from the validium chain.
Validiums also rely on the main Ethereum chain for the following:
### Settlement {#settlement}
-Transactions executed on a validium cannot be fully confirmed until the parent chain verifies their validity. All business conducted on a validium must eventually be settled on Mainnet. The Ethereum blockchain also provides "settlement guarantees" for validium users, meaning off-chain transactions cannot be reversed or altered once committed to on-chain.
+Transactions executed on a validium cannot be fully confirmed until the parent chain verifies their validity. All business conducted on a validium must eventually be settled on Mainnet. The Ethereum blockchain also provides "settlement guarantees" for validium users, meaning offchain transactions cannot be reversed or altered once committed to onchain.
### Security {#security}
-Ethereum, acting as a settlement layer, also guarantees the validity of state transitions on validium. Off-chain transactions executed on the validium chain are verified via a smart contract on the base Ethereum layer.
+Ethereum, acting as a settlement layer, also guarantees the validity of state transitions on validium. Offchain transactions executed on the validium chain are verified via a smart contract on the base Ethereum layer.
-If the on-chain verifier contract deems the proof invalid, the transactions are rejected. This means operators must satisfy validity conditions enforced by the Ethereum protocol before updating the validium's state.
+If the onchain verifier contract deems the proof invalid, the transactions are rejected. This means operators must satisfy validity conditions enforced by the Ethereum protocol before updating the validium's state.
## How does validium work? {#how-does-validium-work}
@@ -55,11 +55,11 @@ The operator aggregates transactions into a batch and sends it to a proving circ
The state of the validium is hashed as a Merkle tree with the root stored in the main contract on Ethereum. The Merkle root, also known as the state root, acts as a cryptographic commitment to the current state of accounts and balances on the validium.
-To perform a state update, the operator must compute a new state root (after executing transactions) and submit it to the on-chain contract. If the validity proof checks out, the proposed state is accepted and the validium switches to the new state root.
+To perform a state update, the operator must compute a new state root (after executing transactions) and submit it to the onchain contract. If the validity proof checks out, the proposed state is accepted and the validium switches to the new state root.
### Deposits and withdrawals {#deposits-and-withdrawals}
-Users move funds from Ethereum to a validium by depositing ETH (or any ERC-compatible token) in the on-chain contract. The contract relays the deposit event to the validium off-chain, where the user's address is credited with an amount equal to their deposit. The operator also includes this deposit transaction in a new batch.
+Users move funds from Ethereum to a validium by depositing ETH (or any ERC-compatible token) in the onchain contract. The contract relays the deposit event to the validium offchain, where the user's address is credited with an amount equal to their deposit. The operator also includes this deposit transaction in a new batch.
To move funds back to Mainnet, a validium user initiates a withdrawal transaction and submits it to the operator who validates the withdrawal request and includes it in a batch. The user's assets on the validium chain are also destroyed before they can exit the system. Once the validity proof associated with the batch is verified, the user can call the main contract to withdraw the remainder of their initial deposit.
@@ -69,25 +69,25 @@ As an anti-censorship mechanism, the validium protocol allows users to withdraw
After executing a batch of transactions, the operator submits the associated validity proof to the verifier contract and proposes a new state root to the main contract. If the proof is valid, the main contract updates the validium's state and finalizes the results of transactions in the batch.
-Unlike a ZK-rollup, block producers on a validium are not required to publish transaction data for transaction batches (only block headers). This makes validium a purely off-chain scaling protocol, as opposed to "hybrid" scaling protocols (i.e., [layer 2](/layer-2/)) that publish state data on the main Ethereum chain as `calldata`.
+Unlike a ZK-rollup, block producers on a validium are not required to publish transaction data for transaction batches (only block headers). This makes validium a purely offchain scaling protocol, as opposed to "hybrid" scaling protocols (i.e., [layer 2](/layer-2/)) that publish state data on the main Ethereum chain as `calldata`.
### Data availability {#data-availability}
-As mentioned, validiums utilize an off-chain data availability model, where operators store all transaction data off Ethereum Mainnet. Validium's low on-chain data footprint improves scalability (throughput isn't limited by Ethereum's data processing capacity) and reduces user fees (the cost of publishing `calldata` is lower).
+As mentioned, validiums utilize an offchain data availability model, where operators store all transaction data off Ethereum Mainnet. Validium's low onchain data footprint improves scalability (throughput isn't limited by Ethereum's data processing capacity) and reduces user fees (the cost of publishing `calldata` is lower).
-Off-chain data availability, however, presents a problem: data necessary for creating or verifying Merkle proofs may be unavailable. This means users may be unable to withdraw funds from the on-chain contract if operators should act maliciously.
+Offchain data availability, however, presents a problem: data necessary for creating or verifying Merkle proofs may be unavailable. This means users may be unable to withdraw funds from the onchain contract if operators should act maliciously.
-Various validium solutions attempt to solve this problem by decentralizing the storage of state data. This involves forcing block producers to send the underlying data to "data availability managers" responsible for storing off-chain data and making it available to users on request.
+Various validium solutions attempt to solve this problem by decentralizing the storage of state data. This involves forcing block producers to send the underlying data to "data availability managers" responsible for storing offchain data and making it available to users on request.
-Data availability managers in validium attest to the availability of data for off-chain transactions by signing every validium batch. These signatures constitute a form of "availability proof" which the on-chain verifier contract checks before approving state updates.
+Data availability managers in validium attest to the availability of data for offchain transactions by signing every validium batch. These signatures constitute a form of "availability proof" which the onchain verifier contract checks before approving state updates.
Validiums differ in their approach to data availability management. Some rely on trusted parties to store state data, while others use randomly assigned validators for the task.
#### Data availability committee (DAC) {#data-availability-committee}
-To guarantee the availability of off-chain data, some validium solutions appoint a group of trusted entities, collectively known as a data availability committee (DAC), to store copies of the state and provide proof of data availability. DACs are easier to implement and require less coordination since membership is low.
+To guarantee the availability of offchain data, some validium solutions appoint a group of trusted entities, collectively known as a data availability committee (DAC), to store copies of the state and provide proof of data availability. DACs are easier to implement and require less coordination since membership is low.
-However, users must trust the DAC to make the data available when needed (e.g., for generating Merkle proofs). There's the possibility of members of data availability committees [getting compromised by a malicious actor](https://notes.ethereum.org/DD7GyItYQ02d0ax_X-UbWg?view) who can then withhold off-chain data.
+However, users must trust the DAC to make the data available when needed (e.g., for generating Merkle proofs). There's the possibility of members of data availability committees [getting compromised by a malicious actor](https://notes.ethereum.org/DD7GyItYQ02d0ax_X-UbWg?view) who can then withhold offchain data.
[More on data availability committees in validiums](https://medium.com/starkware/data-availability-e5564c416424).
@@ -95,7 +95,7 @@ However, users must trust the DAC to make the data available when needed (e.g.,
Other validiums require participants charged with storing offline data to stake (i.e., lock up) tokens in a smart contract before assuming their roles. This stake serves as a “bond” to guarantee honest behavior among data availability managers and reduces trust assumptions. If these participants fail to prove data availability, the bond is slashed.
-In a bonded data availability scheme, anyone can be assigned to hold off-chain data once they provide the required stake. This expands the pool of eligible data availability managers, reducing the centralization that affects data availability committees (DACs). More importantly, this approach relies on cryptoeconomic incentives to prevent malicious activity, which is considerably more secure than appointing trusted parties to secure offline data in the validium.
+In a bonded data availability scheme, anyone can be assigned to hold offchain data once they provide the required stake. This expands the pool of eligible data availability managers, reducing the centralization that affects data availability committees (DACs). More importantly, this approach relies on cryptoeconomic incentives to prevent malicious activity, which is considerably more secure than appointing trusted parties to secure offline data in the validium.
[More on bonded data availability in validiums](https://blog.matter-labs.io/zkporter-a-breakthrough-in-l2-scaling-ed5e48842fbf).
@@ -103,7 +103,7 @@ In a bonded data availability scheme, anyone can be assigned to hold off-chain d
Validiums offer many benefits but come with trade-offs (most notably, data availability). But, as with many scaling solutions, validiums are suited to specific use-cases—which is why volitions were created.
-Volitions combine a ZK-rollup and validium chain and allow users to switch between the two scaling solutions. With volitions, users can take advantage of validium's off-chain data availability for certain transactions, while retaining the freedom to switch to an on-chain data availability solution (ZK-rollup) if needed. This essentially gives users the freedom to choose trade-offs as dictated by their unique circumstances.
+Volitions combine a ZK-rollup and validium chain and allow users to switch between the two scaling solutions. With volitions, users can take advantage of validium's offchain data availability for certain transactions, while retaining the freedom to switch to an onchain data availability solution (ZK-rollup) if needed. This essentially gives users the freedom to choose trade-offs as dictated by their unique circumstances.
A decentralized exchange (DEX) may prefer using a validium’s scalable and private infrastructure for high-value trades. It can also use a ZK-rollup for users who want a ZK-rollup's higher security guarantees and trustlessness.
@@ -113,34 +113,34 @@ Like ZK-rollups, validiums are mostly suited to simple applications, such as tok
Some validium projects attempt to sidestep this problem by compiling EVM-compatible languages (e.g., Solidity, Vyper) into creating custom bytecode optimized for efficient proving. A drawback of this approach is that new zero-knowledge proof-friendly VMs may not support important EVM opcodes, and developers have to write directly in the high-level language for an optimal experience. This creates even more problems: it forces developers to build dapps with an entirely new development stack and breaks compatibility with current Ethereum infrastructure.
-Some teams, however, are attempting to optimize existing EVM opcodes for ZK-proving circuits. This will result in the development of a zero-knowledge Ethereum Virtual Machine (zkEVM), an EVM-compatible VM that produces proofs to verify the correctness of program execution. With a zkEVM, validium chains can execute smart contracts off-chain and submit validity proofs to verify an off-chain computation (without having to re-execute it) on Ethereum.
+Some teams, however, are attempting to optimize existing EVM opcodes for ZK-proving circuits. This will result in the development of a zero-knowledge Ethereum Virtual Machine (zkEVM), an EVM-compatible VM that produces proofs to verify the correctness of program execution. With a zkEVM, validium chains can execute smart contracts offchain and submit validity proofs to verify an offchain computation (without having to re-execute it) on Ethereum.
[More on zkEVMs](https://www.alchemy.com/overviews/zkevm).
## How do validiums scale Ethereum? {#scaling-ethereum-with-validiums}
-### 1. Off-chain data storage {#off-chain-data-storage}
+### 1. Offchain data storage {#offchain-data-storage}
-Layer 2 scaling projects, such as optimistic rollups and ZK-rollups, trade the infinite scalability of pure off-chain scaling protocols (e.g., [Plasma](/developers/docs/scaling/plasma/)) for security by publishing some transaction data on L1. But this means the scalability properties of rollups is limited by data bandwidth on Ethereum Mainnet ([data sharding](/roadmap/danksharding/) proposes to improve Ethereum's data storage capacity for this reason).
+Layer 2 scaling projects, such as optimistic rollups and ZK-rollups, trade the infinite scalability of pure offchain scaling protocols (e.g., [Plasma](/developers/docs/scaling/plasma/)) for security by publishing some transaction data on L1. But this means the scalability properties of rollups is limited by data bandwidth on Ethereum Mainnet ([data sharding](/roadmap/danksharding/) proposes to improve Ethereum's data storage capacity for this reason).
-Validiums achieve scalability by keeping all transaction data off-chain and only post state commitments (and validity proofs) when relaying state updates to the main Ethereum chain. The existence of validity proofs, however, gives validiums higher security guarantees than other pure off-chain scaling solutions, including Plasma and [sidechains](/developers/docs/scaling/sidechains/). By reducing the amount of data Ethereum has to process before validating off-chain transactions, validium designs greatly extend throughput on Mainnet.
+Validiums achieve scalability by keeping all transaction data offchain and only post state commitments (and validity proofs) when relaying state updates to the main Ethereum chain. The existence of validity proofs, however, gives validiums higher security guarantees than other pure offchain scaling solutions, including Plasma and [sidechains](/developers/docs/scaling/sidechains/). By reducing the amount of data Ethereum has to process before validating offchain transactions, validium designs greatly extend throughput on Mainnet.
### 2. Recursive proofs {#recursive-proofs}
A recursive proof is a validity proof that verifies the validity of other proofs. These "proof of proofs" are generated by recursively aggregating multiple proofs until one final proof verifying all previous proofs is created. Recursive proofs scale blockchain processing speeds by increasing the number of transactions that can be verified per validity proof.
-Typically, each validity proof the validium operator submits to Ethereum for verification validates the integrity of a single block. Whereas a single recursive proof can be used to confirm the validity of several validium blocks at the same time—this is possible since the proving circuit can recursively aggregate several block proofs into one final proof. If the on-chain verifier contract accepts the recursive proof, all the underlying blocks are finalized immediately.
+Typically, each validity proof the validium operator submits to Ethereum for verification validates the integrity of a single block. Whereas a single recursive proof can be used to confirm the validity of several validium blocks at the same time—this is possible since the proving circuit can recursively aggregate several block proofs into one final proof. If the onchain verifier contract accepts the recursive proof, all the underlying blocks are finalized immediately.
## Pros and cons of validium {#pros-and-cons-of-validium}
| Pros | Cons |
| ------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Validity proofs enforce integrity of off-chain transactions and prevent operators from finalizing invalid state updates. | Producing validity proofs requires special hardware, which poses a centralization risk. |
+| Validity proofs enforce integrity of offchain transactions and prevent operators from finalizing invalid state updates. | Producing validity proofs requires special hardware, which poses a centralization risk. |
| Increases capital efficiency for users (no delays in withdrawing funds back to Ethereum) | Limited support for general computation/smart contracts; specialized languages required for development. |
| Not vulnerable to certain economic attacks faced by fraud-proof based systems in high-value applications. | High computational power required to generate ZK proofs; not cost-effective for low throughput applications. |
| Reduces gas fees for users by not posting calldata to Ethereum Mainnet. | Slower subjective finality time (10-30 min to generate a ZK proof) but faster to full finality because there is no dispute time delay. |
-| Suitable for specific use-cases, like trading or blockchain gaming that prioritize transaction privacy and scalability. | Users can be prevented from withdrawing funds since generating Merkle proofs of ownership requires off-chain data to be available at all times. |
-| Off-chain data availability provides higher levels of throughput and increases scalability. | Security model relies on trust assumptions and cryptoeconomic incentives, unlike ZK-rollups, which purely rely on cryptographic security mechanisms. |
+| Suitable for specific use-cases, like trading or blockchain gaming that prioritize transaction privacy and scalability. | Users can be prevented from withdrawing funds since generating Merkle proofs of ownership requires offchain data to be available at all times. |
+| Offchain data availability provides higher levels of throughput and increases scalability. | Security model relies on trust assumptions and cryptoeconomic incentives, unlike ZK-rollups, which purely rely on cryptographic security mechanisms. |
### Use Validium/Volitions {#use-validium-and-volitions}
@@ -163,3 +163,4 @@ Multiple projects provide implementations of Validium and volitions that you can
- [ZK-rollups vs Validium](https://blog.matter-labs.io/zkrollup-vs-validium-starkex-5614e38bc263)
- [Volition and the Emerging Data Availability spectrum](https://medium.com/starkware/volition-and-the-emerging-data-availability-spectrum-87e8bfa09bb)
- [Rollups, Validiums, and Volitions: Learn About the Hottest Ethereum Scaling Solutions](https://www.defipulse.com/blog/rollups-validiums-and-volitions-learn-about-the-hottest-ethereum-scaling-solutions)
+- [The Practical Guide to Ethereum Rollups](https://research.2077.xyz/the-practical-guide-to-ethereum-rollups)
diff --git a/public/content/developers/docs/scaling/zk-rollups/index.md b/public/content/developers/docs/scaling/zk-rollups/index.md
index 0e0332e408c..cdfe7289155 100644
--- a/public/content/developers/docs/scaling/zk-rollups/index.md
+++ b/public/content/developers/docs/scaling/zk-rollups/index.md
@@ -4,7 +4,7 @@ description: An introduction to zero-knowledge rollups—a scaling solution used
lang: en
---
-Zero-knowledge rollups (ZK-rollups) are layer 2 [scaling solutions](/developers/docs/scaling/) that increase throughput on Ethereum Mainnet by moving computation and state-storage off-chain. ZK-rollups can process thousands of transactions in a batch and then only post some minimal summary data to Mainnet. This summary data defines the changes that should be made to the Ethereum state and some cryptographic proof that those changes are correct.
+Zero-knowledge rollups (ZK-rollups) are layer 2 [scaling solutions](/developers/docs/scaling/) that increase throughput on Ethereum Mainnet by moving computation and state-storage offchain. ZK-rollups can process thousands of transactions in a batch and then only post some minimal summary data to Mainnet. This summary data defines the changes that should be made to the Ethereum state and some cryptographic proof that those changes are correct.
## Prerequisites {#prerequisites}
@@ -12,35 +12,35 @@ You should have read and understood our page on [Ethereum scaling](/developers/d
## What are zero-knowledge rollups? {#what-are-zk-rollups}
-**Zero-knowledge rollups (ZK-rollups)** bundle (or 'roll up') transactions into batches that are executed off-chain. Off-chain computation reduces the amount of data that has to be posted to the blockchain. ZK-rollup operators submit a summary of the changes required to represent all the transactions in a batch rather than sending each transaction individually. They also produce [validity proofs](/glossary/#validity-proof) to prove the correctness of their changes.
+**Zero-knowledge rollups (ZK-rollups)** bundle (or 'roll up') transactions into batches that are executed offchain. Offchain computation reduces the amount of data that has to be posted to the blockchain. ZK-rollup operators submit a summary of the changes required to represent all the transactions in a batch rather than sending each transaction individually. They also produce [validity proofs](/glossary/#validity-proof) to prove the correctness of their changes.
-The ZK-rollup's state is maintained by a smart contract deployed on the Ethereum network. To update this state, ZK-rollup nodes must submit a validity proof for verification. As mentioned, the validity proof is a cryptographic assurance that the state-change proposed by the rollup is really the result of executing the given batch of transactions. This means that ZK-rollups only need to provide validity proofs to finalize transactions on Ethereum instead of posting all transaction data on-chain like [optimistic rollups](/developers/docs/scaling/optimistic-rollups/).
+The ZK-rollup's state is maintained by a smart contract deployed on the Ethereum network. To update this state, ZK-rollup nodes must submit a validity proof for verification. As mentioned, the validity proof is a cryptographic assurance that the state-change proposed by the rollup is really the result of executing the given batch of transactions. This means that ZK-rollups only need to provide validity proofs to finalize transactions on Ethereum instead of posting all transaction data onchain like [optimistic rollups](/developers/docs/scaling/optimistic-rollups/).
There are no delays when moving funds from a ZK-rollup to Ethereum because exit transactions are executed once the ZK-rollup contract verifies the validity proof. Conversely, withdrawing funds from optimistic rollups is subject to a delay to allow anyone to challenge the exit transaction with a [fraud proof](/glossary/#fraud-proof).
-ZK-rollups write transactions to Ethereum as `calldata`. `calldata` is where data that is included in external calls to smart contract functions gets stored. Information in `calldata` is published on the blockchain, allowing anyone to reconstruct the rollup’s state independently. ZK-rollups use compression techniques to reduce transaction data—for example, accounts are represented by an index rather than an address, which saves 28 bytes of data. On-chain data publication is a significant cost for rollups, so data compression can reduce fees for users.
+ZK-rollups write transactions to Ethereum as `calldata`. `calldata` is where data that is included in external calls to smart contract functions gets stored. Information in `calldata` is published on the blockchain, allowing anyone to reconstruct the rollup’s state independently. ZK-rollups use compression techniques to reduce transaction data—for example, accounts are represented by an index rather than an address, which saves 28 bytes of data. Onchain data publication is a significant cost for rollups, so data compression can reduce fees for users.
## How do ZK-rollups interact with Ethereum? {#zk-rollups-and-ethereum}
-A ZK-rollup chain is an off-chain protocol that operates on top of the Ethereum blockchain and is managed by on-chain Ethereum smart contracts. ZK-rollups execute transactions outside of Mainnet, but periodically commit off-chain transaction batches to an on-chain rollup contract. This transaction record is immutable, much like the Ethereum blockchain, and forms the ZK-rollup chain.
+A ZK-rollup chain is an offchain protocol that operates on top of the Ethereum blockchain and is managed by onchain Ethereum smart contracts. ZK-rollups execute transactions outside of Mainnet, but periodically commit offchain transaction batches to an onchain rollup contract. This transaction record is immutable, much like the Ethereum blockchain, and forms the ZK-rollup chain.
The ZK-rollup's core architecture is made up of the following components:
-1. **On-chain contracts**: As mentioned, the ZK-rollup protocol is controlled by smart contracts running on Ethereum. This includes the main contract which stores rollup blocks, tracks deposits, and monitors state updates. Another on-chain contract (the verifier contract) verifies zero-knowledge proofs submitted by block producers. Thus, Ethereum serves as the base layer or "layer 1" for the ZK-rollup.
+1. **Onchain contracts**: As mentioned, the ZK-rollup protocol is controlled by smart contracts running on Ethereum. This includes the main contract which stores rollup blocks, tracks deposits, and monitors state updates. Another onchain contract (the verifier contract) verifies zero-knowledge proofs submitted by block producers. Thus, Ethereum serves as the base layer or "layer 1" for the ZK-rollup.
-2. **Off-chain virtual machine (VM)**: While the ZK-rollup protocol lives on Ethereum, transaction execution and state storage happen on a separate virtual machine independent of the [EVM](/developers/docs/evm/). This off-chain VM is the execution environment for transactions on the ZK-rollup and serves as the secondary layer or "layer 2" for the ZK-rollup protocol. Validity proofs verified on Ethereum Mainnet guarantee the correctness of state transitions in the off-chain VM.
+2. **Offchain virtual machine (VM)**: While the ZK-rollup protocol lives on Ethereum, transaction execution and state storage happen on a separate virtual machine independent of the [EVM](/developers/docs/evm/). This offchain VM is the execution environment for transactions on the ZK-rollup and serves as the secondary layer or "layer 2" for the ZK-rollup protocol. Validity proofs verified on Ethereum Mainnet guarantee the correctness of state transitions in the offchain VM.
-ZK-rollups are "hybrid scaling solutions"—off-chain protocols that operate independently but derive security from Ethereum. Specifically, the Ethereum network enforces the validity of state updates on the ZK-rollup and guarantees the availability of data behind every update to the rollup's state. As a result, ZK-rollups are considerably safer than pure off-chain scaling solutions, such as [sidechains](/developers/docs/scaling/sidechains/), which are responsible for their security properties, or [validiums](/developers/docs/scaling/validium/), which also verify transactions on Ethereum with validity proofs, but store transaction data elsewhere.
+ZK-rollups are "hybrid scaling solutions"—offchain protocols that operate independently but derive security from Ethereum. Specifically, the Ethereum network enforces the validity of state updates on the ZK-rollup and guarantees the availability of data behind every update to the rollup's state. As a result, ZK-rollups are considerably safer than pure offchain scaling solutions, such as [sidechains](/developers/docs/scaling/sidechains/), which are responsible for their security properties, or [validiums](/developers/docs/scaling/validium/), which also verify transactions on Ethereum with validity proofs, but store transaction data elsewhere.
ZK-rollups rely on the main Ethereum protocol for the following:
### Data availability {#data-availability}
-ZK-rollups publish state data for every transaction processed off-chain to Ethereum. With this data, it is possible for individuals or businesses to reproduce the rollup’s state and validate the chain themselves. Ethereum makes this data available to all participants of the network as `calldata`.
+ZK-rollups publish state data for every transaction processed offchain to Ethereum. With this data, it is possible for individuals or businesses to reproduce the rollup’s state and validate the chain themselves. Ethereum makes this data available to all participants of the network as `calldata`.
-ZK-rollups don’t need to publish much transaction data on-chain because validity proofs already verify the authenticity of state transitions. Nevertheless, storing data on-chain is still important because it allows permissionless, independent verification of the L2 chain's state which in turn allows anyone to submit batches of transactions, preventing malicious operators from censoring or freezing the chain.
+ZK-rollups don’t need to publish much transaction data onchain because validity proofs already verify the authenticity of state transitions. Nevertheless, storing data onchain is still important because it allows permissionless, independent verification of the L2 chain's state which in turn allows anyone to submit batches of transactions, preventing malicious operators from censoring or freezing the chain.
-On-chain is required for users to interact with the rollup. Without access to state data users cannot query their account balance or initiate transactions (e.g., withdrawals) that rely on state information.
+Onchain is required for users to interact with the rollup. Without access to state data users cannot query their account balance or initiate transactions (e.g., withdrawals) that rely on state information.
### Transaction finality {#transaction-finality}
@@ -62,27 +62,27 @@ Other ZK-rollups may rotate the operator role by using a [proof-of-stake](/devel
#### How ZK-rollups publish transaction data on Ethereum {#how-zk-rollups-publish-transaction-data-on-ethereum}
-As explained, transaction data is published on Ethereum as `calldata`. `calldata` is a data area in a smart contract used to pass arguments to a function and behaves similarly to [memory](/developers/docs/smart-contracts/anatomy/#memory). While `calldata` isn’t stored as part of Ethereum’s state, it persists on-chain as part of the Ethereum chain's [history logs](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html?highlight=memory#logs). `calldata` does not affect Ethereum's state, making it a cheap way to store data on-chain.
+As explained, transaction data is published on Ethereum as `calldata`. `calldata` is a data area in a smart contract used to pass arguments to a function and behaves similarly to [memory](/developers/docs/smart-contracts/anatomy/#memory). While `calldata` isn’t stored as part of Ethereum’s state, it persists onchain as part of the Ethereum chain's [history logs](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html?highlight=memory#logs). `calldata` does not affect Ethereum's state, making it a cheap way to store data onchain.
-The `calldata` keyword often identifies the smart contract method being called by a transaction and holds inputs to the method in the form of an arbitrary sequence of bytes. ZK-rollups use `calldata` to publish compressed transaction data on-chain; the rollup operator simply adds a new batch by calling the required function in the rollup contract and passes the compressed data as function arguments. This helps reduce costs for users since a large part of rollup fees go toward storing transaction data on-chain.
+The `calldata` keyword often identifies the smart contract method being called by a transaction and holds inputs to the method in the form of an arbitrary sequence of bytes. ZK-rollups use `calldata` to publish compressed transaction data onchain; the rollup operator simply adds a new batch by calling the required function in the rollup contract and passes the compressed data as function arguments. This helps reduce costs for users since a large part of rollup fees go toward storing transaction data onchain.
### State commitments {#state-commitments}
-The ZK-rollup’s state, which includes L2 accounts and balances, is represented as a [Merkle tree](/whitepaper/#merkle-trees). A cryptographic hash of the Merkle tree’s root (Merkle root) is stored in the on-chain contract, allowing the rollup protocol to track changes in the state of the ZK-rollup.
+The ZK-rollup’s state, which includes L2 accounts and balances, is represented as a [Merkle tree](/whitepaper/#merkle-trees). A cryptographic hash of the Merkle tree’s root (Merkle root) is stored in the onchain contract, allowing the rollup protocol to track changes in the state of the ZK-rollup.
-The rollup transitions to a new state after the execution of a new set of transactions. The operator who initiated the state transition is required to compute a new state root and submit to the on-chain contract. If the validity proof associated with the batch is authenticated by the verifier contract, the new Merkle root becomes the ZK-rollup’s canonical state root.
+The rollup transitions to a new state after the execution of a new set of transactions. The operator who initiated the state transition is required to compute a new state root and submit to the onchain contract. If the validity proof associated with the batch is authenticated by the verifier contract, the new Merkle root becomes the ZK-rollup’s canonical state root.
Besides computing state roots, the ZK-rollup operator also creates a batch root—the root of a Merkle tree comprising all transactions in a batch. When a new batch is submitted, the rollup contract stores the batch root, allowing users to prove a transaction (e.g., a withdrawal request) was included in the batch. Users will have to provide transaction details, the batch root, and a [Merkle proof](/developers/tutorials/merkle-proofs-for-offline-data-integrity/) showing the inclusion path.
### Validity proofs {#validity-proofs}
-The new state root that the ZK-rollup operator submits to the L1 contract is the result of updates to the rollup’s state. Say Alice sends 10 tokens to Bob, the operator simply decreases Alice’s balance by 10 and increments Bob’s balance by 10. The operator then hashes the updated account data, rebuilds the rollup's Merkle tree, and submits the new Merkle root to the on-chain contract.
+The new state root that the ZK-rollup operator submits to the L1 contract is the result of updates to the rollup’s state. Say Alice sends 10 tokens to Bob, the operator simply decreases Alice’s balance by 10 and increments Bob’s balance by 10. The operator then hashes the updated account data, rebuilds the rollup's Merkle tree, and submits the new Merkle root to the onchain contract.
But the rollup contract won’t automatically accept the proposed state commitment until the operator proves the new Merkle root resulted from correct updates to the rollup’s state. The ZK-rollup operator does this by producing a validity proof, a succinct cryptographic commitment verifying the correctness of batched transactions.
-Validity proofs allow parties to prove the correctness of a statement without revealing the statement itself—hence, they are also called zero-knowledge proofs. ZK-rollups use validity proofs to confirm the correctness of off-chain state transitions without having to re-execute transactions on Ethereum. These proofs can come in the form of a [ZK-SNARK](https://arxiv.org/abs/2202.06877) (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge) or [ZK-STARK](https://eprint.iacr.org/2018/046) (Zero-Knowledge Scalable Transparent Argument of Knowledge).
+Validity proofs allow parties to prove the correctness of a statement without revealing the statement itself—hence, they are also called zero-knowledge proofs. ZK-rollups use validity proofs to confirm the correctness of offchain state transitions without having to re-execute transactions on Ethereum. These proofs can come in the form of a [ZK-SNARK](https://arxiv.org/abs/2202.06877) (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge) or [ZK-STARK](https://eprint.iacr.org/2018/046) (Zero-Knowledge Scalable Transparent Argument of Knowledge).
-Both SNARKs and STARKs help attest to the integrity of off-chain computation in ZK-rollups, although each proof type has distinctive features.
+Both SNARKs and STARKs help attest to the integrity of offchain computation in ZK-rollups, although each proof type has distinctive features.
**ZK-SNARKs**
@@ -96,7 +96,7 @@ Trust assumptions aside, ZK-SNARKs are popular for their small proof sizes and c
**ZK-STARKs**
-Like ZK-SNARKs, ZK-STARKs prove the validity of off-chain computation without revealing the inputs. However, ZK-STARKs are considered an improvement on ZK-SNARKs because of their scalability and transparency.
+Like ZK-SNARKs, ZK-STARKs prove the validity of offchain computation without revealing the inputs. However, ZK-STARKs are considered an improvement on ZK-SNARKs because of their scalability and transparency.
ZK-STARKs are 'transparent', as they can work without the trusted setup of a Common Reference String (CRS). Instead, ZK-STARKs rely on publicly verifiable randomness to set up parameters for generating and verifying proofs.
@@ -152,7 +152,7 @@ Users enter the ZK-rollup by depositing tokens in the rollup's contract deployed
If the pending deposit queue starts filling up, the ZK-rollup operator will take the deposit transactions and submit them to the rollup contract. Once the user's funds are in the rollup, they can start transacting by sending transactions to the operator for processing. Users can verify balances on the rollup by hashing their account data, sending the hash to the rollup contract, and providing a Merkle proof to verify against the current state root.
-Withdrawing from a ZK-rollup to L1 is straightforward. The user initiates the exit transaction by sending their assets on the rollup to a specified account for burning. If the operator includes the transaction in the next batch, the user can submit a withdrawal request to the on-chain contract. This withdrawal request will include the following:
+Withdrawing from a ZK-rollup to L1 is straightforward. The user initiates the exit transaction by sending their assets on the rollup to a specified account for burning. If the operator includes the transaction in the next batch, the user can submit a withdrawal request to the onchain contract. This withdrawal request will include the following:
- Merkle proof proving the inclusion of the user's transaction to the burn account in a transaction batch
@@ -180,7 +180,7 @@ How much users pay for transactions on ZK-rollups is dependent on the gas fee, j
1. **State write**: There is a fixed cost for writing to Ethereum’s state (i.e., submitting a transaction on the Ethereum blockchain). ZK-rollups reduce this cost by batching transactions and spreading fixed costs across multiple users.
-2. **Data publication**: ZK-rollups publish state data for every transaction to Ethereum as `calldata`. `calldata` costs are currently governed by [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559), which stipulates a cost of 16 gas for non-zero bytes and 4 gas for zero bytes of `calldata`, respectively. The cost paid on each transaction is influenced by how much `calldata` needs to be posted on-chain for it.
+2. **Data publication**: ZK-rollups publish state data for every transaction to Ethereum as `calldata`. `calldata` costs are currently governed by [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559), which stipulates a cost of 16 gas for non-zero bytes and 4 gas for zero bytes of `calldata`, respectively. The cost paid on each transaction is influenced by how much `calldata` needs to be posted onchain for it.
3. **L2 operator fees**: This is the amount paid to the rollup operator as compensation for computational costs incurred in processing transactions, much like [transaction "priority fees (tips)"](/developers/docs/gas/#how-are-gas-fees-calculated) on Ethereum Mainnet.
@@ -192,7 +192,7 @@ Apart from batching transactions, ZK-rollups reduce fees for users by compressin
### Transaction data compression {#transaction-data-compression}
-ZK-rollups extend the throughput on Ethereum’s base layer by taking computation off-chain, but the real boost for scaling comes from compressing transaction data. Ethereum’s [block size](/developers/docs/blocks/#block-size) limits the data each block can hold and, by extension, the number of transactions processed per block. By compressing transaction-related data, ZK-rollups significantly increase the number of transactions processed per block.
+ZK-rollups extend the throughput on Ethereum’s base layer by taking computation offchain, but the real boost for scaling comes from compressing transaction data. Ethereum’s [block size](/developers/docs/blocks/#block-size) limits the data each block can hold and, by extension, the number of transactions processed per block. By compressing transaction-related data, ZK-rollups significantly increase the number of transactions processed per block.
ZK-rollups can compress transaction data better than optimistic rollups since they don't have to post all the data required to validate each transaction. They only have to post the minimal data required to rebuild the latest state of accounts and balances on the rollup.
@@ -208,10 +208,10 @@ Recursive proofs, however, make it possible to finalize several blocks with one
| Pros | Cons |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Validity proofs ensure correctness of off-chain transactions and prevent operators from executing invalid state transitions. | The cost associated with computing and verifying validity proofs is substantial and can increase fees for rollup users. |
+| Validity proofs ensure correctness of offchain transactions and prevent operators from executing invalid state transitions. | The cost associated with computing and verifying validity proofs is substantial and can increase fees for rollup users. |
| Offers faster transaction finality as state updates are approved once validity proofs are verified on L1. | Building EVM-compatible ZK-rollups is difficult due to complexity of zero-knowledge technology. |
| Relies on trustless cryptographic mechanisms for security, not the honesty of incentivized actors as with [optimistic rollups](/developers/docs/scaling/optimistic-rollups/#optimistic-pros-and-cons). | Producing validity proofs requires specialized hardware, which may encourage centralized control of the chain by a few parties. |
-| Stores data needed to recover the off-chain state on L1, which guarantees security, censorship-resistance, and decentralization. | Centralized operators (sequencers) can influence the ordering of transactions. |
+| Stores data needed to recover the offchain state on L1, which guarantees security, censorship-resistance, and decentralization. | Centralized operators (sequencers) can influence the ordering of transactions. |
| Users benefit from greater capital efficiency and can withdraw funds from L2 without delays. | Hardware requirements may reduce the number of participants that can force the chain to make progress, increasing the risk of malicious operators freezing the rollup's state and censoring users. |
| Doesn't depend on liveness assumptions and users don't have to validate the chain to protect their funds. | Some proving systems (e.g., ZK-SNARK) require a trusted setup which, if mishandled, could potentially compromise a ZK-rollup's security model. |
| Better data compression can help reduce the costs of publishing `calldata` on Ethereum and minimize rollup fees for users. | |
@@ -245,10 +245,12 @@ Projects working on zkEVMs include:
- [What Are Zero-Knowledge Rollups?](https://coinmarketcap.com/alexandria/glossary/zero-knowledge-rollups)
- [What are zero-knowledge rollups?](https://alchemy.com/blog/zero-knowledge-rollups)
+- [The Practical Guide To Ethereum Rollups](https://research.2077.xyz/the-practical-guide-to-ethereum-rollups)
- [STARKs vs SNARKs](https://consensys.net/blog/blockchain-explained/zero-knowledge-proofs-starks-vs-snarks/)
- [What is a zkEVM?](https://www.alchemy.com/overviews/zkevm)
- [ZK-EVM types: Ethereum-equivalent, EVM-equivalent, Type 1, Type 4, and other cryptic buzzwords](https://taiko.mirror.xyz/j6KgY8zbGTlTnHRFGW6ZLVPuT0IV0_KmgowgStpA0K4)
- [Intro to zkEVM](https://hackmd.io/@yezhang/S1_KMMbGt)
+- [What are ZK-EVM L2s?](https://linea.mirror.xyz/qD18IaQ4BROn_Y40EBMTUTdJHYghUtdECscSWyMvm8M)
- [Awesome-zkEVM resources](https://github.com/LuozhuZhang/awesome-zkevm)
- [ZK-SNARKS under the hood](https://vitalik.eth.limo/general/2017/02/01/zk_snarks.html)
- [How are SNARKs possible?](https://vitalik.eth.limo/general/2021/01/26/snarks.html)
diff --git a/public/content/developers/docs/smart-contracts/index.md b/public/content/developers/docs/smart-contracts/index.md
index 4be9a10e4c6..d28f22c6402 100644
--- a/public/content/developers/docs/smart-contracts/index.md
+++ b/public/content/developers/docs/smart-contracts/index.md
@@ -86,9 +86,9 @@ Learn more about [smart contract composability](/developers/docs/smart-contracts
## Limitations {#limitations}
-Smart contracts alone cannot get information about "real-world" events because they can't retrieve data from off-chain sources. This means they can't respond to events in the real world. This is by design. Relying on external information could jeopardise consensus, which is important for security and decentralization.
+Smart contracts alone cannot get information about "real-world" events because they can't retrieve data from offchain sources. This means they can't respond to events in the real world. This is by design. Relying on external information could jeopardise consensus, which is important for security and decentralization.
-However, it is important for blockchain applications to be able to use off-chain data. The solution is [oracles](/developers/docs/oracles/) which are tools that ingest off-chain data and make it available to smart contracts.
+However, it is important for blockchain applications to be able to use offchain data. The solution is [oracles](/developers/docs/oracles/) which are tools that ingest offchain data and make it available to smart contracts.
Another limitation of smart contracts is the maximum contract size. A smart contract can be a maximum of 24KB or it will run out of gas. This can be circumnavigated by using [The Diamond Pattern](https://eips.ethereum.org/EIPS/eip-2535).
diff --git a/public/content/developers/docs/smart-contracts/security/index.md b/public/content/developers/docs/smart-contracts/security/index.md
index 17a70417390..1199e9d5cd7 100644
--- a/public/content/developers/docs/smart-contracts/security/index.md
+++ b/public/content/developers/docs/smart-contracts/security/index.md
@@ -199,23 +199,23 @@ This example shows the basic features of emergency stops:
`onlyWhenStopped` is used for functions that should be callable during an emergency (e.g., `emergencyWithdraw()`). Such functions can help resolve the situation, hence their exclusion from the “restricted functions” list.
-Using an emergency stop functionality provides an effective stopgap for dealing with serious vulnerabilities in your smart contract. However, it increases the need for users to trust developers not to activate it for self-serving reasons. To this end, decentralizing control of the emergency stop either by subjecting it to an on-chain voting mechanism, timelock, or approval from a multisig wallet are possible solutions.
+Using an emergency stop functionality provides an effective stopgap for dealing with serious vulnerabilities in your smart contract. However, it increases the need for users to trust developers not to activate it for self-serving reasons. To this end, decentralizing control of the emergency stop either by subjecting it to an onchain voting mechanism, timelock, or approval from a multisig wallet are possible solutions.
#### Event monitoring {#event-monitoring}
[Events](https://docs.soliditylang.org/en/v0.8.15/contracts.html#events) allow you to track calls to smart contract functions and monitor changes to state variables. It is ideal to program your smart contract to emit an event whenever some party takes a safety-critical action (e.g., withdrawing funds).
-Logging events and monitoring them off-chain provides insights on contract operations and aids faster discovery of malicious actions. This means your team can respond faster to hacks and take action to mitigate impact on users, such as pausing functions or performing an upgrade.
+Logging events and monitoring them offchain provides insights on contract operations and aids faster discovery of malicious actions. This means your team can respond faster to hacks and take action to mitigate impact on users, such as pausing functions or performing an upgrade.
You can also opt for an off-the-shelf monitoring tool that automatically forwards alerts whenever someone interacts with your contracts. These tools will allow you to create custom alerts based on different triggers, such as transaction volume, frequency of function calls, or the specific functions involved. For example, you could program an alert that comes in when the amount withdrawn in a single transaction crosses a particular threshold.
### 7. Design secure governance systems {#design-secure-governance-systems}
-You may want to decentralize your application by turning over control of core smart contracts to community members. In this case, the smart contract system will include a governance module—a mechanism that allows community members to approve administrative actions via an on-chain governance system. For example, a proposal to upgrade a proxy contract to a new implementation may be voted upon by token-holders.
+You may want to decentralize your application by turning over control of core smart contracts to community members. In this case, the smart contract system will include a governance module—a mechanism that allows community members to approve administrative actions via an onchain governance system. For example, a proposal to upgrade a proxy contract to a new implementation may be voted upon by token-holders.
Decentralized governance can be beneficial, especially because it aligns the interests of developers and end-users. Nevertheless, smart contract governance mechanisms may introduce new risks if implemented incorrectly. A plausible scenario is if an attacker acquires enormous voting power (measured in number of tokens held) by taking out a [flash loan](/defi/#flash-loans) and pushes through a malicious proposal.
-One way of preventing problems related to on-chain governance is to [use a timelock](https://blog.openzeppelin.com/protect-your-users-with-smart-contract-timelocks/). A timelock prevents a smart contract from executing certain actions until a specific amount of time passes. Other strategies include assigning a “voting weight” to each token based on how long it has been locked up for, or measuring the voting power of an address at a historical period (for example, 2-3 blocks in the past) instead of the current block. Both methods reduce the possibility of quickly amassing voting power to swing on-chain votes.
+One way of preventing problems related to onchain governance is to [use a timelock](https://blog.openzeppelin.com/protect-your-users-with-smart-contract-timelocks/). A timelock prevents a smart contract from executing certain actions until a specific amount of time passes. Other strategies include assigning a “voting weight” to each token based on how long it has been locked up for, or measuring the voting power of an address at a historical period (for example, 2-3 blocks in the past) instead of the current block. Both methods reduce the possibility of quickly amassing voting power to swing onchain votes.
More on [designing secure governance systems](https://blog.openzeppelin.com/smart-contract-security-guidelines-4-strategies-for-safer-governance-systems/), [different voting mechanisms in DAOs](https://hackernoon.com/governance-is-the-holy-grail-for-daos), and [the common DAO attack vectors leveraging DeFi](https://dacian.me/dao-governance-defi-attacks) in the shared links.
@@ -439,13 +439,13 @@ As of version 0.8.0, the Solidity compiler rejects code that results in integer
#### Oracle manipulation {#oracle-manipulation}
-[Oracles](/developers/docs/oracles/) source off-chain information and send it on-chain for smart contracts to use. With oracles, you can design smart contracts that interoperate with off-chain systems, such as capital markets, greatly expanding their application.
+[Oracles](/developers/docs/oracles/) source offchain information and send it onchain for smart contracts to use. With oracles, you can design smart contracts that interoperate with offchain systems, such as capital markets, greatly expanding their application.
-But if the oracle is corrupted and sends incorrect information on-chain, smart contracts will execute based on erroneous inputs, which can cause problems. This is the basis of the “oracle problem”, which concerns the task of making sure information from a blockchain oracle is accurate, up-to-date, and timely.
+But if the oracle is corrupted and sends incorrect information onchain, smart contracts will execute based on erroneous inputs, which can cause problems. This is the basis of the “oracle problem”, which concerns the task of making sure information from a blockchain oracle is accurate, up-to-date, and timely.
-A related security concern is using an on-chain oracle, such as a decentralized exchange, to get the spot price for an asset. Lending platforms in the [decentralized finance (DeFi)](/defi/) industry often do this to determine the value of a user’s collateral to determine how much they can borrow.
+A related security concern is using an onchain oracle, such as a decentralized exchange, to get the spot price for an asset. Lending platforms in the [decentralized finance (DeFi)](/defi/) industry often do this to determine the value of a user’s collateral to determine how much they can borrow.
-DEX prices are often accurate, largely due to arbitrageurs restoring parity in markets. However, they are open to manipulation, particularly if the on-chain oracle calculates asset prices based on historical trading patterns (as is usually the case).
+DEX prices are often accurate, largely due to arbitrageurs restoring parity in markets. However, they are open to manipulation, particularly if the onchain oracle calculates asset prices based on historical trading patterns (as is usually the case).
For instance, an attacker could artificially pump the spot price of an asset by taking out a flash loan right before interacting with your lending contract. Querying the DEX for the asset’s price would return a higher-than-normal value (due to the attacker’s large “buy order” skewing demand for the asset), allowing them to borrow more than they should. Such "flash loan attacks" have been used to exploit reliance on price oracles among DeFi applications, costing protocols millions in lost funds.
@@ -453,7 +453,7 @@ For instance, an attacker could artificially pump the spot price of an asset by
The minimum requirement to [avoid oracle manipulation](https://www.cyfrin.io/blog/price-oracle-manipultion-attacks-with-examples) is to use a decentralized oracle network that queries information from multiple sources to avoid single points of failure. In most cases, decentralized oracles have built-in cryptoeconomic incentives to encourage oracle nodes to report correct information, making them more secure than centralized oracles.
-If you plan on querying an on-chain oracle for asset prices, consider using one that implements a time-weighted average price (TWAP) mechanism. A [TWAP oracle](https://docs.uniswap.org/contracts/v2/concepts/core-concepts/oracles) queries the price of an asset at two different points in time (which you can modify) and calculates the spot price based on the average obtained. Choosing longer time periods protects your protocol against price manipulation since large orders executed recently cannot impact asset prices.
+If you plan on querying an onchain oracle for asset prices, consider using one that implements a time-weighted average price (TWAP) mechanism. A [TWAP oracle](https://docs.uniswap.org/contracts/v2/concepts/core-concepts/oracles) queries the price of an asset at two different points in time (which you can modify) and calculates the spot price based on the average obtained. Choosing longer time periods protects your protocol against price manipulation since large orders executed recently cannot impact asset prices.
## Smart contract security resources for developers {#smart-contract-security-resources-for-developers}
diff --git a/public/content/developers/docs/smart-contracts/testing/index.md b/public/content/developers/docs/smart-contracts/testing/index.md
index 7062738aade..ae848a97df6 100644
--- a/public/content/developers/docs/smart-contracts/testing/index.md
+++ b/public/content/developers/docs/smart-contracts/testing/index.md
@@ -150,7 +150,7 @@ Unit testing frameworks for Solidity smart contracts come in different languages
While unit testing debugs contract functions in isolation, integration tests evaluate the components of a smart contract as a whole. Integration testing can detect issues arising from cross-contract calls or interactions between different functions in the same smart contract. For example, integration tests can help check if things like [inheritance](https://docs.soliditylang.org/en/v0.8.12/contracts.html#inheritance) and dependency injection work properly.
-Integration testing is useful if your contract adopts a modular architecture or interfaces with other on-chain contracts during execution. One way of running integration tests is to [fork the blockchain](/glossary/#fork) at a specific height (using a tool like [Forge](https://book.getfoundry.sh/forge/fork-testing) or [Hardhat](https://hardhat.org/hardhat-network/docs/guides/forking-other-networks) and simulate interactions between your contract and deployed contracts.
+Integration testing is useful if your contract adopts a modular architecture or interfaces with other onchain contracts during execution. One way of running integration tests is to [fork the blockchain](/glossary/#fork) at a specific height (using a tool like [Forge](https://book.getfoundry.sh/forge/fork-testing) or [Hardhat](https://hardhat.org/hardhat-network/docs/guides/forking-other-networks) and simulate interactions between your contract and deployed contracts.
The forked blockchain will behave similarly to Mainnet and have accounts with associated states and balances. But it only acts as a sandboxed local development environment, meaning you won't need real ETH for transactions, for example, nor will your changes affect the real Ethereum protocol.
@@ -207,7 +207,7 @@ While automated testing performed in a local development environment can provide
Testing your contract on a local blockchain (also known as a [development network](/developers/docs/development-networks/)) is a recommended alternative to testing on Mainnet. A local blockchain is a copy of the Ethereum blockchain running locally on your computer which simulates the behavior of Ethereum's execution layer. As such, you can program transactions to interact with a contract without incurring significant overhead.
-Running contracts on a local blockchain could be useful as a form of manual integration testing. [Smart contracts are highly composable](/developers/docs/smart-contracts/composability/), allowing you to integrate with existing protocols—but you'll still need to ensure that such complex on-chain interactions produce the correct results.
+Running contracts on a local blockchain could be useful as a form of manual integration testing. [Smart contracts are highly composable](/developers/docs/smart-contracts/composability/), allowing you to integrate with existing protocols—but you'll still need to ensure that such complex onchain interactions produce the correct results.
[More on development networks.](/developers/docs/development-networks/)
diff --git a/public/content/developers/docs/smart-contracts/verifying/index.md b/public/content/developers/docs/smart-contracts/verifying/index.md
index 740977e763a..e698940c881 100644
--- a/public/content/developers/docs/smart-contracts/verifying/index.md
+++ b/public/content/developers/docs/smart-contracts/verifying/index.md
@@ -72,11 +72,11 @@ The traditional process of verifying contracts can be complex. This is why we ha
Although mostly known as an [Ethereum blockchain explorer](/developers/docs/data-and-analytics/block-explorers/), Etherscan also offers a [source code verification service](https://etherscan.io/verifyContract) for smart contract developers and users.
-Etherscan allows you to recompile contract bytecode from the original data payload (source code, library address, compiler settings, contract address, etc.) If the recompiled bytecode is associated with the bytecode (and constructor parameters) of the on-chain contract, then [the contract is verified](https://info.etherscan.com/types-of-contract-verification/).
+Etherscan allows you to recompile contract bytecode from the original data payload (source code, library address, compiler settings, contract address, etc.) If the recompiled bytecode is associated with the bytecode (and constructor parameters) of the onchain contract, then [the contract is verified](https://info.etherscan.com/types-of-contract-verification/).
Once verified, your contract’s source code receives a "Verified" label and is published on Etherscan for others to audit. It also gets added to the [Verified Contracts](https://etherscan.io/contractsVerified/) section—a repository of smart contracts with verified source codes.
-Etherscan is the most used tool for verifying contracts. However, Etherscan's contract verification has a drawback: it fails to compare the **metadata hash** of the on-chain bytecode and recompiled bytecode. Therefore the matches in Etherscan are partial matches.
+Etherscan is the most used tool for verifying contracts. However, Etherscan's contract verification has a drawback: it fails to compare the **metadata hash** of the onchain bytecode and recompiled bytecode. Therefore the matches in Etherscan are partial matches.
[More on verifying contracts on Etherscan](https://medium.com/etherscan-blog/verifying-contracts-on-etherscan-f995ab772327).
diff --git a/public/content/developers/docs/storage/index.md b/public/content/developers/docs/storage/index.md
index ce2913058bf..4e57b3f297e 100644
--- a/public/content/developers/docs/storage/index.md
+++ b/public/content/developers/docs/storage/index.md
@@ -38,7 +38,7 @@ Platforms with blockchain-based persistence:
**Contract-based** persistence has the intuition that data cannot be replicated by every node and stored forever, and instead must be upkept with contract agreements. These are agreements made with multiple nodes that have promised to hold a piece of data for a period of time. They must be refunded or renewed whenever they run out to keep the data persisted.
-In most cases, instead of storing all data on-chain, the hash of where the data is located on a chain gets stored. This way, the entire chain doesn't need to scale to keep all of the data.
+In most cases, instead of storing all data onchain, the hash of where the data is located on a chain gets stored. This way, the entire chain doesn't need to scale to keep all of the data.
Platforms with contract-based persistence:
diff --git a/public/content/developers/tutorials/all-you-can-cache/index.md b/public/content/developers/tutorials/all-you-can-cache/index.md
index 7e56310b9c2..58ca65f6144 100644
--- a/public/content/developers/tutorials/all-you-can-cache/index.md
+++ b/public/content/developers/tutorials/all-you-can-cache/index.md
@@ -8,9 +8,9 @@ published: 2022-09-15
lang: en
---
-When using rollups the cost of a byte in the transaction is a lot more expensive than the cost of a storage slot. Therefore, it makes sense to cache as much information as possible on chain.
+When using rollups the cost of a byte in the transaction is a lot more expensive than the cost of a storage slot. Therefore, it makes sense to cache as much information as possible onchain.
-In this article you learn how to create and use a caching contract in such a way that any parameter value that is likely to be used multiple times will be cached and available for use (after the first time) with a much smaller number of bytes, and how to write off chain code that uses this cache.
+In this article you learn how to create and use a caching contract in such a way that any parameter value that is likely to be used multiple times will be cached and available for use (after the first time) with a much smaller number of bytes, and how to write offchain code that uses this cache.
If you want to skip the article and just see the source code, [it is here](https://github.com/qbzzt/20220915-all-you-can-cache). The development stack is [Foundry](https://book.getfoundry.sh/getting-started/installation).
@@ -242,7 +242,7 @@ One big advantage of Foundry is that it allows tests to be written in Solidity (
function encodeVal(uint _val) public view returns(bytes memory) {
```
-`encodeVal` is a function that off-chain code calls to help create calldata that uses the cache. It receives a single value and returns the bytes that encode it. This function is a `view`, so it does not require a transaction and when called externally does not cost any gas.
+`encodeVal` is a function that offchain code calls to help create calldata that uses the cache. It receives a single value and returns the bytes that encode it. This function is a `view`, so it does not require a transaction and when called externally does not cost any gas.
```solidity
uint _key = val2key[_val];
@@ -724,7 +724,7 @@ The read function is a `view`, so it does not require a transaction and does not
uint cacheGoat = worm.cacheWrite(0x60A7);
```
-Here we use the fact that `cacheWrite` returns the cache key. This is not something we'd expect to use in production, because `cacheWrite` changes the state, and therefore can only be called during a transaction. Transactions don't have return values, if they have results those results are supposed to be emitted as events. So the `cacheWrite` return value is only accessible from on-chain code, and on-chain code does not need parameter caching.
+Here we use the fact that `cacheWrite` returns the cache key. This is not something we'd expect to use in production, because `cacheWrite` changes the state, and therefore can only be called during a transaction. Transactions don't have return values, if they have results those results are supposed to be emitted as events. So the `cacheWrite` return value is only accessible from onchain code, and onchain code does not need parameter caching.
```solidity
(_success,) = address(worm).call(_callInput);
diff --git a/public/content/developers/tutorials/eip-1271-smart-contract-signatures/index.md b/public/content/developers/tutorials/eip-1271-smart-contract-signatures/index.md
index b3abd974208..5c60937ad63 100644
--- a/public/content/developers/tutorials/eip-1271-smart-contract-signatures/index.md
+++ b/public/content/developers/tutorials/eip-1271-smart-contract-signatures/index.md
@@ -36,7 +36,7 @@ Your Ethereum account (i.e. your externally-owned account/EOA) has a private key
An app can [verify a signature](https://docs.alchemy.com/docs/how-to-verify-a-message-signature-on-ethereum) you create using a third-party library like ethers.js [without knowing your private key](https://en.wikipedia.org/wiki/Public-key_cryptography) and be confident that _you_ were the one that created the signature.
-> In fact, because EOA digital signatures use public-key cryptography, they can be generated and verified **off-chain**! This is how gasless DAO voting works — instead of submitting votes on-chain, digital signatures can be created and verified off-chain using cryptographic libraries.
+> In fact, because EOA digital signatures use public-key cryptography, they can be generated and verified **offchain**! This is how gasless DAO voting works — instead of submitting votes onchain, digital signatures can be created and verified offchain using cryptographic libraries.
While EOA accounts have a private key, smart contract accounts do not have any sort of private or secret key (so "Log in with Ethereum", etc. cannot natively work with smart contract accounts).
@@ -92,11 +92,11 @@ One notable contract which implements EIP-1271 is Safe (previously Gnosis Safe).
In Safe’s code, `isValidSignature` [is implemented](https://github.com/safe-global/safe-contracts/blob/main/contracts/handler/CompatibilityFallbackHandler.sol) so that signatures can be created and verified in [two ways](https://ethereum.stackexchange.com/questions/122635/signing-messages-as-a-gnosis-safe-eip1271-support):
-1. On-chain messages
+1. Onchain messages
1. Creation: a safe owner creates a new safe transaction to “sign” a message, passing the message as data into the transaction. Once enough owners sign the transaction to reach the multisig threshold, the transaction is broadcast and run. In the transaction, there is a safe function called which adds the message to a list of “approved” messages.
2. Verification: call `isValidSignature` on the Safe contract, and pass in the message to verify as the message parameter and [an empty value for the signature parameter](https://github.com/safe-global/safe-contracts/blob/main/contracts/handler/CompatibilityFallbackHandler.sol#L32) (i.e. `0x`). The Safe will see that the signature parameter is empty and instead of cryptographically verifying the signature, it will know to just go ahead and check whether the message is on the list of “approved” messages.
-2. Off-chain messages:
- 1. Creation: a safe owner creates a message off-chain, then gets other safe owners to sign the message each individually until there are enough signatures to overcome the multisig approval threshold.
+2. Offchain messages:
+ 1. Creation: a safe owner creates a message offchain, then gets other safe owners to sign the message each individually until there are enough signatures to overcome the multisig approval threshold.
2. Verification: call `isValidSignature`. In the message parameter, pass in the message to be verified. In the signature parameter, pass in each safe owner’s individual signatures all concatenated together, back-to-back. The Safe will check that there are enough signatures to meet the threshold **and** that each signature is valid. If so, it will return a value indicating successful signature verification.
## What exactly is the `_hash` parameter? Why not pass the whole message?
diff --git a/public/content/developers/tutorials/erc20-with-safety-rails/index.md b/public/content/developers/tutorials/erc20-with-safety-rails/index.md
index 0d23224e3a8..4df78aaee9f 100644
--- a/public/content/developers/tutorials/erc20-with-safety-rails/index.md
+++ b/public/content/developers/tutorials/erc20-with-safety-rails/index.md
@@ -146,7 +146,7 @@ Freezing and thawing contracts requires several changes:
mapping(address => bool) public frozenAccounts;
```
-- [Events](https://www.tutorialspoint.com/solidity/solidity_events.htm) to inform anybody interested when an account is frozen or thawed. Technically speaking events are not required for these actions, but it helps off chain code to be able to listen to these events and know what is happening. It's considered good manners for a smart contract to emit them when something that miught be relevant to somebody else happens.
+- [Events](https://www.tutorialspoint.com/solidity/solidity_events.htm) to inform anybody interested when an account is frozen or thawed. Technically speaking events are not required for these actions, but it helps offchain code to be able to listen to these events and know what is happening. It's considered good manners for a smart contract to emit them when something that miught be relevant to somebody else happens.
The events are indexed so will be possible to search for all the times an account has been frozen or thawed.
diff --git a/public/content/developers/tutorials/hello-world-smart-contract-fullstack/index.md b/public/content/developers/tutorials/hello-world-smart-contract-fullstack/index.md
index e8b357c9faf..2ad730eda4e 100644
--- a/public/content/developers/tutorials/hello-world-smart-contract-fullstack/index.md
+++ b/public/content/developers/tutorials/hello-world-smart-contract-fullstack/index.md
@@ -435,7 +435,7 @@ To interact with our contract, we need to create a contract instance in our code
1. Provider - a node provider that gives you read and write access to the blockchain
2. Signer - represents an Ethereum account that can sign transactions
-3. Contract - an Ethers.js object representing a specific contract deployed on-chain
+3. Contract - an Ethers.js object representing a specific contract deployed onchain
We'll use the contract ABI from the previous step to create our instance of the contract:
diff --git a/public/content/developers/tutorials/how-to-use-tellor-as-your-oracle/index.md b/public/content/developers/tutorials/how-to-use-tellor-as-your-oracle/index.md
index e91c3a2c572..d425324a6e3 100644
--- a/public/content/developers/tutorials/how-to-use-tellor-as-your-oracle/index.md
+++ b/public/content/developers/tutorials/how-to-use-tellor-as-your-oracle/index.md
@@ -10,7 +10,7 @@ source: Tellor Docs
sourceUrl: https://docs.tellor.io/tellor/
---
-Pop Quiz: Your protocol is just about finished, but it needs an oracle to get access to off chain data...What do you do?
+Pop Quiz: Your protocol is just about finished, but it needs an oracle to get access to offchain data...What do you do?
## (Soft) Prerequisites {#soft-prerequisites}
diff --git a/public/content/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md b/public/content/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md
index 40bdfcbcdd6..e024ef53dbb 100644
--- a/public/content/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md
+++ b/public/content/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md
@@ -1,6 +1,6 @@
---
title: Learn Foundational Ethereum Topics with SQL
-description: This tutorial helps readers understand fundamental Ethereum concepts including transactions, blocks and gas by querying on-chain data with Structured Query Language (SQL).
+description: This tutorial helps readers understand fundamental Ethereum concepts including transactions, blocks and gas by querying onchain data with Structured Query Language (SQL).
author: "Paul Apivat"
tags: ["SQL", "Querying", "Transactions"]
skill: beginner
@@ -10,17 +10,17 @@ source: paulapivat.com
sourceUrl: https://paulapivat.com/post/query_ethereum/
---
-Many Ethereum tutorials target developers, but there’s a lack of educational resources for data analysts or for people who wish to see on-chain data without running a client or node.
+Many Ethereum tutorials target developers, but there’s a lack of educational resources for data analysts or for people who wish to see onchain data without running a client or node.
-This tutorial helps readers understand fundamental Ethereum concepts including transactions, blocks and gas by querying on-chain data with structured query language (SQL) through an interface provided by [Dune Analytics](https://dune.xyz/home).
+This tutorial helps readers understand fundamental Ethereum concepts including transactions, blocks and gas by querying onchain data with structured query language (SQL) through an interface provided by [Dune Analytics](https://dune.xyz/home).
-On-chain data can help us understand Ethereum, the network, and as an economy for computing power and should serve as a base for understanding challenges facing Ethereum today (i.e., rising gas prices) and, more importantly, discussions around scaling solutions.
+Onchain data can help us understand Ethereum, the network, and as an economy for computing power and should serve as a base for understanding challenges facing Ethereum today (i.e., rising gas prices) and, more importantly, discussions around scaling solutions.
### Transactions {#transactions}
A user’s journey on Ethereum starts with initializing a user-controlled account or an entity with an ETH balance. There are two account types - user-controlled or a smart contract (see [ethereum.org](/developers/docs/accounts/)).
-Any account can be viewed on a block explorer like [Etherscan](https://etherscan.io/). Block explorers are a portal to Ethereum’s data. They display, in real-time, data on blocks, transactions, miners, accounts and other on-chain activity (see [here](/developers/docs/data-and-analytics/block-explorers/)).
+Any account can be viewed on a block explorer like [Etherscan](https://etherscan.io/). Block explorers are a portal to Ethereum’s data. They display, in real-time, data on blocks, transactions, miners, accounts and other onchain activity (see [here](/developers/docs/data-and-analytics/block-explorers/)).
However, a user may wish to query the data directly to reconcile the information provided by external block explorers. [Dune Analytics](https://duneanalytics.com/) provides this capability to anyone with some knowledge of SQL.
@@ -132,9 +132,9 @@ The only thing this query does not cover is _list of transaction_ which requires
- Chain data (list of blocks, transactions)
- State data (result of each transaction’s state transition)
-State root falls in the latter and is _implicit_ data (not stored on-chain), while chain data is explicit and stored on the chain itself ([source](https://ethereum.stackexchange.com/questions/359/where-is-the-state-data-stored)).
+State root falls in the latter and is _implicit_ data (not stored onchain), while chain data is explicit and stored on the chain itself ([source](https://ethereum.stackexchange.com/questions/359/where-is-the-state-data-stored)).
-For this tutorial, we'll be focusing on on-chain data that _can_ be queried with SQL via Dune Analytics.
+For this tutorial, we'll be focusing on onchain data that _can_ be queried with SQL via Dune Analytics.
As stated above, each block contains a list of transactions, we can query this by filtering for a specific block. We'll try the most recent block, 12396854:
@@ -262,7 +262,7 @@ ORDER BY block_time DESC
### Summary {#summary}
-With this tutorial, we understand foundational Ethereum concepts and how the Ethereum blockchain works by querying and getting a feel for on-chain data.
+With this tutorial, we understand foundational Ethereum concepts and how the Ethereum blockchain works by querying and getting a feel for onchain data.
The dashboard that holds all code used in this tutorial can be found [here](https://duneanalytics.com/paulapivat/Learn-Ethereum).
diff --git a/public/content/developers/tutorials/logging-events-smart-contracts/index.md b/public/content/developers/tutorials/logging-events-smart-contracts/index.md
index ecd0fd7b483..6ddf21dc45e 100644
--- a/public/content/developers/tutorials/logging-events-smart-contracts/index.md
+++ b/public/content/developers/tutorials/logging-events-smart-contracts/index.md
@@ -59,4 +59,4 @@ If we now deploy the contract and call the increment function, we’ll see that

-Logs are really useful for debugging your smart contracts but they are also important if you build applications used by different people and make it easier to make analytics to track and understand how your smart contract is used. The logs generated by transactions are displayed in popular block explorers and you can also for example use them to create off chain scripts for listening to specific events and taking action when they occur.
+Logs are really useful for debugging your smart contracts but they are also important if you build applications used by different people and make it easier to make analytics to track and understand how your smart contract is used. The logs generated by transactions are displayed in popular block explorers and you can also for example use them to create offchain scripts for listening to specific events and taking action when they occur.
diff --git a/public/content/developers/tutorials/merkle-proofs-for-offline-data-integrity/index.md b/public/content/developers/tutorials/merkle-proofs-for-offline-data-integrity/index.md
index fd1de41b86d..743ee598e22 100644
--- a/public/content/developers/tutorials/merkle-proofs-for-offline-data-integrity/index.md
+++ b/public/content/developers/tutorials/merkle-proofs-for-offline-data-integrity/index.md
@@ -1,6 +1,6 @@
---
title: Merkle proofs for offline data integrity
-description: Ensuring data integrity on chain for data that is stored, mostly, off chain
+description: Ensuring data integrity onchain for data that is stored, mostly, offchain
author: Ori Pomerantz
tags: ["storage"]
skill: advanced
@@ -24,13 +24,13 @@ In this article you learn **how** to ensure data integrity without storing the d
## How does it work? {#how-does-it-work}
-In theory we could just store the hash of the data on chain, and send all the data in transactions that require it. However, this is still too expensive. A byte of data to a transaction costs about 16 gas, currently about half a cent, or about $5 per kilobyte. At $5000 per megabyte, this is still too expensive for many uses, even without the added cost of hashing the data.
+In theory we could just store the hash of the data onchain, and send all the data in transactions that require it. However, this is still too expensive. A byte of data to a transaction costs about 16 gas, currently about half a cent, or about $5 per kilobyte. At $5000 per megabyte, this is still too expensive for many uses, even without the added cost of hashing the data.
The solution is to repeatedly hash different subsets of the data, so for the data that you don't need to send you can just send a hash. You do this using a Merkle tree, a tree data structure where each node is a hash of the nodes below it:

-The root hash is the only part that needs to be stored on chain. To prove a certain value, you provide all the hashes that need to be combined with it to obtain the root. For example, to prove `C` you provide `D`, `H(A-B)`, and `H(E-H)`.
+The root hash is the only part that needs to be stored onchain. To prove a certain value, you provide all the hashes that need to be combined with it to obtain the root. For example, to prove `C` you provide `D`, `H(A-B)`, and `H(E-H)`.

@@ -38,9 +38,9 @@ The root hash is the only part that needs to be stored on chain. To prove a cert
[The sample code is provided here](https://github.com/qbzzt/merkle-proofs-for-offline-data-integrity).
-### Off-chain code {#off-chain-code}
+### Offchain code {#offchain-code}
-In this article we use JavaScript for the off-chain computations. Most decentralized applications have their off-chain component in JavaScript.
+In this article we use JavaScript for the offchain computations. Most decentralized applications have their offchain component in JavaScript.
#### Creating the Merkle root {#creating-the-merkle-root}
@@ -62,7 +62,7 @@ const dataArray = [
]
```
-Encoding each entry into a single 256-bit integer results in less readable code than using JSON, for example. However, this means significantly less processing to retrieve the data in the contract, so much lower gas costs. [You can read JSON on chain](https://github.com/chrisdotn/jsmnSol), it's just a bad idea if avoidable.
+Encoding each entry into a single 256-bit integer results in less readable code than using JSON, for example. However, this means significantly less processing to retrieve the data in the contract, so much lower gas costs. [You can read JSON onchain](https://github.com/chrisdotn/jsmnSol), it's just a bad idea if avoidable.
```javascript
// The array of hash values, as BigInts
@@ -85,7 +85,7 @@ The ethers hash function expects to get a JavaScript string with a hexadecimal n
const pairHash = (a, b) => hash(hash(a) ^ hash(b))
```
-This function is symmetrical (hash of a [xor](https://en.wikipedia.org/wiki/Exclusive_or) b). This means that when we check the Merkle proof we don't need to worry about whether to put the value from the proof before or after the calculated value. Merkle proof checking is done on chain, so the less we need to do there the better.
+This function is symmetrical (hash of a [xor](https://en.wikipedia.org/wiki/Exclusive_or) b). This means that when we check the Merkle proof we don't need to worry about whether to put the value from the proof before or after the calculated value. Merkle proof checking is done onchain, so the less we need to do there the better.
Warning:
Cryptography is harder than it looks.
@@ -172,9 +172,9 @@ We hash `(v[0],v[1])`, `(v[2],v[3])`, etc. So for even values we need the next o
} // getMerkleProof
```
-### On-chain code {#on-chain-code}
+### Onchain code {#onchain-code}
-Finally we have the code that checks the proof. The on-chain code is written in [Solidity](https://docs.soliditylang.org/en/v0.8.11/). Optimization is a lot more important here because gas is relatively expensive.
+Finally we have the code that checks the proof. The onchain code is written in [Solidity](https://docs.soliditylang.org/en/v0.8.11/). Optimization is a lot more important here because gas is relatively expensive.
```solidity
//SPDX-License-Identifier: Public Domain
@@ -241,7 +241,7 @@ In mathematical notation Merkle proof verification looks like this: `H(proof_n,
Merkle proofs don't work well with [rollups](/developers/docs/scaling/#rollups). The reason is that rollups write all the transaction data on L1, but process on L2. The cost to send a Merkle proof with a transaction averages to 638 gas per layer (currently a byte in call data costs 16 gas if it isn't zero, and 4 if it is zero). If we have 1024 words of data, a Merkle proof requires ten layers, or a total of 6380 gas.
-Looking for example at [Optimism](https://public-grafana.optimism.io/d/9hkhMxn7z/public-dashboard?orgId=1&refresh=5m), writing L1 gas costs about 100 gwei and L2 gas costs 0.001 gwei (that is the normal price, it can rise with congestion). So for the cost of one L1 gas we can spend a hundred thousand gas on L2 processing. Assuming we don't overwrite storage, this means that we can write about five words to storage on L2 for the price of one L1 gas. For a single Merkle proof we can write the entire 1024 words to storage (assuming they can be calculated on chain to begin with, rather than provided in a transaction) and still have most of the gas left over.
+Looking for example at [Optimism](https://public-grafana.optimism.io/d/9hkhMxn7z/public-dashboard?orgId=1&refresh=5m), writing L1 gas costs about 100 gwei and L2 gas costs 0.001 gwei (that is the normal price, it can rise with congestion). So for the cost of one L1 gas we can spend a hundred thousand gas on L2 processing. Assuming we don't overwrite storage, this means that we can write about five words to storage on L2 for the price of one L1 gas. For a single Merkle proof we can write the entire 1024 words to storage (assuming they can be calculated onchain to begin with, rather than provided in a transaction) and still have most of the gas left over.
## Conclusion {#conclusion}
diff --git a/public/content/developers/tutorials/secret-state/index.md b/public/content/developers/tutorials/secret-state/index.md
new file mode 100644
index 00000000000..00eaec9f41c
--- /dev/null
+++ b/public/content/developers/tutorials/secret-state/index.md
@@ -0,0 +1,730 @@
+---
+title: Using zero-knowledge for a secret state
+description: onchain games are limited because they cannot keep any hidden information. After reading this tutorial, a reader will be able to combine zero-knowledge proofs and server components to create verifiable games with a secret state, offchain, component. The technique to do this will be demonstrated by creating a minesweeper game.
+author: Ori Pomerantz
+tags: ["server", "offchain", "centralized", "zero-knowledge", "zokrates", "mud"]
+skill: advanced
+lang: en
+published: 2025-03-15
+---
+
+_There are no secrets on the blockchain_. Everything that is posted on the blockchain is open to everybody to read. This is necessary, because the blockchain is based on anybody being able to verify it. However, games often rely on secret state. For example, the game of [minesweeper]() makes absolutely no sense if you can just go on a blockchain explorer and see the map.
+
+The simplest solution is to use a [server component](/developers/tutorials/server-components/) to hold the secret state. However, the reason we use blockchain is to prevent cheating by the game developer. We need to ensure the server component's honesty. The server can provide a hash of the state, and use [zero-knowledge proofs](/zero-knowledge-proofs/#why-zero-knowledge-proofs-are-important) to prove that the state used to calculate the result of a move is the correct one.
+
+After reading this article you will know how to create this kind of secret state holding server, a client for showing the state, and an onchain component for communication between the two. The main tools we use will be:
+
+| Tool | Purpose | Verified on version |
+| --------------------------------------------- | ------------------------------------------------------- | ------------------: |
+| [Zokrates](https://zokrates.github.io/) | Zero-knowledge proofs and their verification | 1.1.9 |
+| [Typescript](https://www.typescriptlang.org/) | Programming language for both the server and the client | 5.4.2 |
+| [Node](https://nodejs.org/en) | Running the server | 20.18.2 |
+| [Viem](https://viem.sh/) | Communication with the Blockchain | 2.9.20 |
+| [MUD](https://mud.dev/) | Onchain data management | 2.0.12 |
+| [React](https://react.dev/) | Client user interface | 18.2.0 |
+| [Vite](https://vitejs.dev/) | Serving the client code | 4.2.1 |
+
+## Minesweeper example {#minesweeper}
+
+[Minesweeper]() is a game that includes a secret map with a minefield. The player chooses to dig in a specific location. If that location has a mine, it's game over. Otherwise, the player gets the number of mines in the eight squares surrounding that location.
+
+This application is written using [MUD](https://mud.dev/), a framework that lets us store data onchain using a [key-value database](https://aws.amazon.com/nosql/key-value/) and synchronize that data automatically with offchain components. In addition to synchronization, MUD makes it easy to provide access control, and for other users to [extend](https://mud.dev/guides/extending-a-world) our application permissionlessly.
+
+### Running the minesweeper example {#running-minesweeper-example}
+
+To run the minesweeper example:
+
+1. Make sure you [have the prerequisites installed](https://mud.dev/quickstart#prerequisites): [Node](https://mud.dev/quickstart#prerequisites), [Foundry](https://book.getfoundry.sh/getting-started/installation), [`git`](https://git-scm.com/downloads), [`pnpm`](https://git-scm.com/downloads), and [`mprocs`](https://github.com/pvolok/mprocs).
+
+2. Clone the repository.
+
+ ```sh copy
+ git clone https://github.com/qbzzt/20240901-secret-state.git
+ ```
+
+3. Install the packages.
+
+ ```sh copy
+ cd 20240901-secret-state/
+ pnpm install
+ npm install -g mprocs
+ ```
+
+ If Foundry was installed as part of `pnpm install`, you need to restart the command-line shell.
+
+4. Compile the contracts
+
+ ```sh copy
+ cd packages/contracts
+ forge build
+ cd ../..
+ ```
+
+
+5. Start the program (including an [anvil](https://book.getfoundry.sh/anvil/) blockchain) and wait.
+
+ ```sh copy
+ mprocs
+ ```
+
+ Note that the startup takes a long time. To see the progress, first use the down arrow to scroll to the _contracts_ tab to see the MUD contracts being deployed. When you get the message _Waiting for file changes…_, the contracts are deployed and further progress will happen in the _server_ tab. There, you wait until you get the message _Verifier address: 0x...._.
+
+ If this step is successful, you will see the `mprocs` screen, with the different processes on the left and the console output for the currently selected process on the right.
+
+ 
+
+ If there is a problem with `mprocs`, you can run the four processes manually, each in its own command line window:
+
+ - **Anvil**
+
+ ```sh
+ cd packages/contracts
+ anvil --base-fee 0 --block-time 2
+ ```
+
+ - **Contracts**
+
+ ```sh
+ cd packages/contracts
+ pnpm mud dev-contracts --rpc http://127.0.0.1:8545
+ ```
+
+ - **Server**
+
+ ```sh
+ cd packages/server
+ pnpm start
+ ```
+
+ - **Client**
+
+ ```sh
+ cd packages/client
+ pnpm run dev
+ ```
+
+6. Now you can browse to [the client](http://localhost:3000), click **New Game**, and start playing.
+
+### Tables {#tables}
+
+We need [several tables](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/mud.config.ts) onchain.
+
+- `Configuration`: This table is a singleton, it has no key and single record. It is used to hold game configuration information:
+ - `height`: The height of a minefield
+ - `width`: The width of a minefield
+ - `numberOfBombs`: The number of bombs in each minefield
+- `VerifierAddress`: This table is also a singleton. It is used to hold one part of the configuration, the address of the verifier contract (`verifier`). We could have put this information in the `Configuration` table, but it is set by a different component, the server, so it's easier to put it in a separate table.
+
+- `PlayerGame`: The key is the player's address. The data is:
+
+ - `gameId`: 32-byte value that is the hash of the map the player is playing on (the game identifier).
+ - `win`: a boolean that is whether the player won the game.
+ - `lose`: a boolean that is whether the player lost the game.
+ - `digNumber`: the number of successful digs in the game.
+
+- `GamePlayer`: This table holds the reverse mapping, from `gameId` to player address.
+
+- `Map`: The key is a tuple of three values:
+
+ - `gameId`: 32-byte value that is the hash of the map the player is playing on (the game identifier).
+ - `x` coordinate
+ - `y` coordinate
+
+ The value is a single number. It's 255 if a bomb was detected. Otherwise, it is the number of bombs around that location plus one. We cannot just use the number of bombs, because by default all storage in the EVM and all row values in MUD are zero. We need to distinguish between "the player haven't dug here yet" and "the player dug here, and found there are zero bombs around".
+
+In addition, communication between the client and server happens through the onchain component. This is also implemented using tables.
+
+- `PendingGame`: Unserviced requests to start a new game.
+- `PendingDig`: Unserviced requests to dig in a specific place in a specific game. This is an [offchain table](https://mud.dev/store/tables#types-of-tables), meaning that it does not get written to EVM storage, it's only readable offchain using events.
+
+### Execution and data flows {#execution-data-flows}
+
+These flows coordinate execution between the client, the onchain component, and the server.
+
+#### Initialization {#initialization-flow}
+
+When you run `mprocs`, these steps happen:
+
+1. [`mprocs`](https://github.com/pvolok/mprocs) runs four components:
+
+ - [Anvil](https://book.getfoundry.sh/anvil/), which runs a local blockchain
+ - [Contracts](https://github.com/qbzzt/20240901-secret-state/tree/main/packages/contracts), which compiles (if needed) and deploys the contracts for MUD
+ - [Client](https://github.com/qbzzt/20240901-secret-state/tree/main/packages/client), which runs [Vite](https://vitejs.dev/) to serve the UI and client code to web browsers.
+ - [Server](https://github.com/qbzzt/20240901-secret-state/tree/main/packages/server), which performs the server actions
+
+2. The `contracts` package deploys the MUD contracts and then runs [the `PostDeploy.s.sol` script](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/script/PostDeploy.s.sol). This script sets the configuration. The code from github specifies [a 10x5 minefield with eight mines in it](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/script/PostDeploy.s.sol#L23).
+
+3. [The server](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts) starts by [setting up MUD](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L6). Among other things, this activates data synchronization, so that a copy of the relevant tables exists in the server's memory.
+
+4. The server subscribes a function to be executed [when the `Configuration` table changes](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L23). [This function](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L24-L168) is called after `PostDeploy.s.sol` executes and modifies the table.
+
+5. When the server initialization function has the configuration, [it calls `zkFunctions`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L34-L35) to initialize [the zero-knowledge part of the server](#using-zokrates-from-typescript). This cannot happen until we get the configuration because the zero-knowledge functions have to have the width and height of the minefield as constants.
+
+6. After the zero-knowledge part of the server is initialized, the next step is to [deploy the zero-knowledge verification contract to the blockchain](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L42-L53) and set the verifiee address in MUD.
+
+7. Finally, we subscribe to updates so we'll see when a player requests either [to start a new game](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L55-L71) or to [dig in an existing game](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L73-L108).
+
+#### New game {#new-game-flow}
+
+This is what happens when the player requests a new game.
+
+1. If there is no game in progress for this player, or there is one but with a gameId of zero, the client displays a [new game button](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L175). When the user presses this button, [React runs the `newGame` function](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L96).
+
+2. [`newGame`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/mud/createSystemCalls.ts#L43-L46) is a `System` call. In MUD all calls are routed through the `World` contract, and in most cases you call `__`. In this case, the call is to `app__newGame`, which MUD then routes to [`newGame` in `GameSystem`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L16-L22).
+
+3. The onchain function checks that the player does not have a game in progress, and if there isn't one [adds the request to the `PendingGame` table](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L21).
+
+4. The server detects the change in `PendingGame` and [runs the subscribed function](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L55-L71). This function calls [`newGame`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L110-L114), which in turn calls [`createGame`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L116-L144).
+
+5. The first thing `createGame` does is [create a random map with the appropriate number of mines](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L120-L135). Then, it calls [`makeMapBorders`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L147-L166) to create a map with blank borders, which is necessary for Zokrates. Finally, `createGame` calls [`calculateMapHash`](#calculateMapHash), to get the hash of the map, which is used as the game ID.
+
+6. The `newGame` function adds the new game to `gamesInProgress`.
+
+7. The last thing the server does is call [`app__newGameResponse`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L38-L43), which is onchain. This function is in a different `System`, [`ServerSystem`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol), to enable access control. Access control is defined in the [MUD configuration file](https://mud.dev/config), [`mud.config.ts`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/mud.config.ts#L67-L72).
+
+ The access list only allows a single address to call the `System`. This restricts access to the server functions to a single address, so nobody can impersonate the server.
+
+8. The onchain component updates the relevant tables:
+
+ - Create the game in `PlayerGame`.
+ - Set the reverse mapping in `GamePlayer`.
+ - Remove the request from `PendingGame`.
+
+9. The server identifies the change in `PendingGame`, but does not do anything because [`wantsGame`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L58-L60) is false.
+
+10. On the client [`gameRecord`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L143-L148) is set to the `PlayerGame` entry for the player's address. When `PlayerGame` changes, `gameRecord` changes too.
+
+11. If there is a value in `gameRecord`, and the game hasn't been won or lost, the client [displays the map](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L175-L190).
+
+#### Dig {#dig-flow}
+
+1. The player [clicks the map cell's button](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L188), which calls [the `dig` function](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/mud/createSystemCalls.ts#L33-L36). This function calls [`dig` onchain](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L24-L32).
+
+2. The onchain component [performs a number of sanity checks](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L25-L30), and if successful adds the dig request to [`PendingDig`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L31).
+
+3. The server [detects the change in `PendingDig`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L73). [If it is valid](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L75-L84), it [calls the zero-knowledge code](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L86-L95) (explained below) to generate both the result and a proof that it is valid.
+
+4. [The server](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L97-L107) calls [`digResponse`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L45-L64) onchain.
+
+5. `digResponse` does two things. First, it checks [the zero knowledge proof](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L47-L61). Then, if the proof checks out, it calls [`processDigResult`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L67-L86) to actually process the result.
+
+6. `processDigResult` checks if the game has been [lost](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L76-L78) or [won](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L83-L86), and [updates `Map`, the onchain map](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L80).
+
+7. The client picks up the updates automatically and [updates the map displayed to the player](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L175-L190), and if applicable tells the player if it's a win or a lose.
+
+## Using Zokrates {#using-zokrates}
+
+In the flows explained above we skipped over the zero-knowledge parts, treating them as a black box. Now let's crank it open and see how that code is written.
+
+### Hashing the map {#hashing-map}
+
+We can use [this JavaScript code](https://github.com/ZK-Plus/ICBC24_Tutorial_Compute-Offchain-Verify-onchain/tree/solutions/exercise) to implement [Poseidon](https://www.poseidon-hash.info), the Zokrates hash function we use. However, while this would be faster, it would also be more complicated than just using the Zokrates hash function to do it. This is a tutorial, and so the code is optimized for simplicity, not for performance. Therefore, we need two different Zokrates programs, one to just calculate the hash of a map (`hash`) and one to actually create a zero-knowledge proof of the result of the dig in a location on the map (`dig`).
+
+### The hash function {#hash-function}
+
+This is the function that calculates the hash of a map. We'll go over this code line by line.
+
+```
+import "hashes/poseidon/poseidon.zok" as poseidon;
+import "utils/pack/bool/pack128.zok" as pack128;
+```
+
+These two lines import two functions from the [Zokrates standard library](https://zokrates.github.io/toolbox/stdlib.html). [The first function](https://github.com/Zokrates/ZoKrates/blob/latest/zokrates_stdlib/stdlib/hashes/poseidon/poseidon.zok) is a [Poseidon hash](https://www.poseidon-hash.info/). It takes an array of [`field` elements](https://zokrates.github.io/language/types.html#field) and returns a `field`.
+
+The field element in Zokrates is typically less than 256 bits long, but not by much. To simplify the code, we restrict the map to be up to 512 bits, and hash an array of four fields, and in each field we use only 128 bits. [The `pack128` function](https://github.com/Zokrates/ZoKrates/blob/latest/zokrates_stdlib/stdlib/utils/pack/bool/pack128.zok) changes an array of 128 bits into a `field` for this purpose.
+
+```
+ def hashMap(bool[${width+2}][${height+2}] map) -> field {
+```
+
+This line starts a function definition. `hashMap` gets a single parameter called `map`, a two dimensional `bool`(ean) array. The size of the map is `width+2` by `height+2` for reasons that are [explained below](#why-map-border).
+
+We can use `${width+2}` and `${height+2}` because the Zokrates programs are stored in this application as [template strings](https://www.w3schools.com/js/js_string_templates.asp). Code between `${` and `}` is evaluated by JavaScript, and this way the program can be used for different map sizes. The map parameter has a one location wide border all around it without any bombs, which is the reason we need to add two to the width and height.
+
+The return value is a `field` that contains the hash.
+
+```
+ bool[512] mut map1d = [false; 512];
+```
+
+The map is two-dimensional. However, the `pack128` function does not work with two-dimensional arrays. So we first flatten the map into a 512-byte array, using `map1d`. By default Zokrates variables are constants, but we need to assign values to this array in a loop, so we define it as [`mut`](https://zokrates.github.io/language/variables.html#mutability).
+
+We need to initialize the array because Zokrates doesn't have `undefined`. The `[false; 512]` expression means [an array of 512 `false` values](https://zokrates.github.io/language/types.html#declaration-and-initialization).
+
+```
+ u32 mut counter = 0;
+```
+
+We also need a counter to distinguish between the bits we already filled in `map1d` and those we haven't.
+
+```
+ for u32 x in 0..${width+2} {
+```
+
+This is how you declare a [`for` loop](https://zokrates.github.io/language/control_flow.html#for-loops) in Zokrates. A Zokrates `for` loop has to have fixed bounds, because while it appears to be a loop, the compiler actually "unrolls" it. The expression `${width+2}` is a compile time constant because `width` is set by the TypeScript code before it calls the compiler.
+
+```
+ for u32 y in 0..${height+2} {
+ map1d[counter] = map[x][y];
+ counter = counter+1;
+ }
+ }
+```
+
+For every location in the map, put that value in the `map1d` array and increment the counter.
+
+```
+ field[4] hashMe = [
+ pack128(map1d[0..128]),
+ pack128(map1d[128..256]),
+ pack128(map1d[256..384]),
+ pack128(map1d[384..512])
+ ];
+```
+
+The `pack128` to create an array of four `field` values from `map1d`. In Zokrates `array[a..b]` means the slice of the array that starts at `a` and ends at `b-1`.
+
+```
+ return poseidon(hashMe);
+}
+```
+
+Use `poseidon` to convert this array to a hash.
+
+### The hash program {#hash-program}
+
+The server needs to call `hashMap` directly to create game identifiers. However, Zokrates can only call the `main` function on a program to start, so we create a program with a `main` that calls the hash function.
+
+```
+${hashFragment}
+
+def main(bool[${width+2}][${height+2}] map) -> field {
+ return hashMap(map);
+}
+```
+
+### The dig program {#dig-program}
+
+This is the heart of the zero-knowledge part of the application, where we produce the proofs that are used to verify dig results.
+
+```
+${hashFragment}
+
+// The number of mines in location (x,y)
+def map2mineCount(bool[${width+2}][${height+2}] map, u32 x, u32 y) -> u8 {
+ return if map[x+1][y+1] { 1 } else { 0 };
+}
+```
+
+#### Why map border {#why-map-border}
+
+Zero-knowledge proofs use [arithmetic circuits](https://medium.com/web3studio/simple-explanations-of-arithmetic-circuits-and-zero-knowledge-proofs-806e59a79785), which don't have an easy equivalent to an `if` statement. Instead, they use the equivalent of the [conditional operator](https://en.wikipedia.org/wiki/Ternary_conditional_operator). If `a` can be either zero or one, you can calculate `if a { b } else { c }` as `ab+(1-a)c`.
+
+Because of this, a Zokrates `if` statement always evaluates both branches. For example, if you have this code:
+
+```
+bool[5] arr = [false; 5];
+u32 index=10;
+return if index>4 { 0 } else { arr[index] }
+```
+
+It will error out, because it needs to calculate `arr[10]`, even though that value will be later multiplied by zero.
+
+This is the reason we need a one location wide border all around the map. We need to calculate the total number of mines around a location, and that means we need to see the location one row above and below, to the left and to the right, of the location where we're digging. Which means those location have to exist in the map array that Zokrates is provided.
+
+```
+def main(private bool[${width+2}][${height+2}] map, u32 x, u32 y) -> (field, u8) {
+```
+
+By default Zokrates proofs include their inputs. It does no good to know there are five mines around a spot unless you actually know which spot it is (and you can't just match it to your request, because then the prover could use different values and not tell you about it). However, we need to keep the map a secret, while providing it to Zokrates. The solution is to use a `private` parameter, one that is _not_ revealed by the proof.
+
+This opens another venue for abuse. The prover could use the correct coordinates, but create a map with any number of mines around the location, and possibly at the location itself. To prevent this abuse, we make the zero knowledge proof include the hash of the map, which is the game identifier.
+
+```
+ return (hashMap(map),
+```
+
+The return value here is a tuple that includes the map hash array as well as the dig result.
+
+```
+ if map2mineCount(map, x, y) > 0 { 0xFF } else {
+```
+
+We use 255 as a special value in case the location itself has a bomb.
+
+```
+ map2mineCount(map, x-1, y-1) + map2mineCount(map, x, y-1) + map2mineCount(map, x+1, y-1) +
+ map2mineCount(map, x-1, y) + map2mineCount(map, x+1, y) +
+ map2mineCount(map, x-1, y+1) + map2mineCount(map, x, y+1) + map2mineCount(map, x+1, y+1)
+ }
+ );
+}
+```
+
+If the player hasn't hit a mine, add the mine counts for the area around the location and return that.
+
+### Using Zokrates from TypeScript {#using-zokrates-from-typescript}
+
+Zokrates has a command line interface, but in this program we use it in the [TypeScript code](https://zokrates.github.io/toolbox/zokrates_js.html).
+
+The library that contains the Zokrates definitions is called [`zero-knowledge.ts`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts).
+
+```typescript
+import { initialize as zokratesInitialize } from "zokrates-js"
+```
+
+Import the [Zokrates JavaScript bindings](https://zokrates.github.io/toolbox/zokrates_js.html). We only need the [`initialize`](https://zokrates.github.io/toolbox/zokrates_js.html#initialize) function because it returns a promise that resolves to all the Zokrates definitions.
+
+```typescript
+export const zkFunctions = async (width: number, height: number) : Promise => {
+```
+
+Similar to Zokrates itself, we also export only one function, which is also [asynchronous](https://www.w3schools.com/js/js_async.asp). When it eventually returns, it provides several functions as we'll see below.
+
+```typescript
+const zokrates = await zokratesInitialize()
+```
+
+Initialize Zokrates, get everything we need from the library.
+
+```typescript
+const hashFragment = `
+ import "utils/pack/bool/pack128.zok" as pack128;
+ import "hashes/poseidon/poseidon.zok" as poseidon;
+ .
+ .
+ .
+ }
+ `
+
+const hashProgram = `
+ ${hashFragment}
+ .
+ .
+ .
+ `
+
+const digProgram = `
+ ${hashFragment}
+ .
+ .
+ .
+ `
+```
+
+Next we have the hash function and two Zokrates programs we saw above.
+
+```typescript
+const digCompiled = zokrates.compile(digProgram)
+const hashCompiled = zokrates.compile(hashProgram)
+```
+
+Here we compile those programs.
+
+```typescript
+// Create the keys for zero knowledge verification.
+// On a production system you'd want to use a setup ceremony.
+// (https://zokrates.github.io/toolbox/trusted_setup.html#initializing-a-phase-2-ceremony).
+const keySetupResults = zokrates.setup(digCompiled.program, "")
+const verifierKey = keySetupResults.vk
+const proverKey = keySetupResults.pk
+```
+
+On a production system we might use a more complicated [setup ceremony](https://zokrates.github.io/toolbox/trusted_setup.html#initializing-a-phase-2-ceremony), but this is good enough for a demonstration. It's not a problem that the users can know the prover key - they still cannot use it to prove things unless they are true. Because we specify the entropy (the second parameter, `""`), the results are always going to be the same.
+
+**Note:** Compilation of Zokrates programs and key creation are slow processes. There is no need to repeat them every time, just when map size changes. On a production system you'd do them once, and then store the output. The only reason I am not doing it here is for the sake of simplicity.
+
+#### `calculateMapHash` {#calculateMapHash}
+
+```typescript
+const calculateMapHash = function (hashMe: boolean[][]): string {
+ return (
+ "0x" +
+ BigInt(zokrates.computeWitness(hashCompiled, [hashMe]).output.slice(1, -1))
+ .toString(16)
+ .padStart(64, "0")
+ )
+}
+```
+
+The [`computeWitness`](https://zokrates.github.io/toolbox/zokrates_js.html#computewitnessartifacts-args-options) function actually runs the Zokrates program. It returns a structure with two fields: `output`, which is the output of the program as a JSON string, and `witness`, which is the information needed to create the a zero knowledge proof of the result. Here we just need the output.
+
+The output is a string of the form `"31337"`, a decimal number enclosed in quotation marks. But the output we need for `viem` is a hexadecimal number of the form `0x60A7`. So we use `.slice(1,-1)` to remove the quotation marks and then `BigInt` to run the remaining string, which is a decimal number, to a [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt). `.toString(16)` converts this `BigInt` into a hexadecimal string, and `"0x"+` adds the marker for hexadecimal numbers.
+
+```typescript
+// Dig and return a zero knowledge proof of the result
+// (server-side code)
+```
+
+The zero knowledge proof includes the public inputs (`x` and `y`) and results (hash of the map and number of bombs).
+
+```typescript
+ const zkDig = function(map: boolean[][], x: number, y: number) : any {
+ if (x<0 || x>=width || y<0 || y>=height)
+ throw new Error("Trying to dig outside the map")
+```
+
+It's a problem to check if an index is out of bounds in Zokrates, so we do it here.
+
+```typescript
+const runResults = zokrates.computeWitness(digCompiled, [map, `${x}`, `${y}`])
+```
+
+Execute the dig program.
+
+```typescript
+ const proof = zokrates.generateProof(
+ digCompiled.program,
+ runResults.witness,
+ proverKey)
+
+ return proof
+ }
+```
+
+Use [`generateProof`](https://zokrates.github.io/toolbox/zokrates_js.html#generateproofprogram-witness-provingkey-entropy) and return the proof.
+
+```typescript
+const solidityVerifier = `
+ // Map size: ${width} x ${height}
+ \n${zokrates.exportSolidityVerifier(verifierKey)}
+ `
+```
+
+A Solidity verifier, a smart contract we can deploy to the blockchain and use to verify proofs generated by `digCompiled.program`.
+
+```typescript
+ return {
+ zkDig,
+ calculateMapHash,
+ solidityVerifier,
+ }
+}
+```
+
+Finally, return everything that other code might need.
+
+## Security tests {#security-tests}
+
+Security tests are important because a functionality bug will eventually reveal itself. But if the application is insecure, that is likely to remain hidden for a long time before it is revealed by somebody cheating and getting away with resources that belong to others.
+
+### Permissions {#permissions}
+
+There is one privileged entity in this game, the server. It is the only user allowed to call the functions in [`ServerSystem`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol). We can use [`cast`](https://book.getfoundry.sh/cast/) to verify calls to permissioned functions are only allowed as the server account.
+
+[The server's private key is in `setupNetwork.ts`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/mud/setupNetwork.ts#L52).
+
+1. On the computer that runs `anvil` (the blockchain), set these environment variables.
+
+ ```sh copy
+ WORLD_ADDRESS=0x8d8b6b8414e1e3dcfd4168561b9be6bd3bf6ec4b
+ UNAUTHORIZED_KEY=0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a
+ AUTHORIZED_KEY=0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d
+ ```
+
+2. Use `cast` to attempt to set the verifier address as an unauthorized address.
+
+ ```sh copy
+ cast send $WORLD_ADDRESS 'app__setVerifier(address)' `cast address-zero` --private-key $UNAUTHORIZED_KEY
+ ```
+
+ Not only does `cast` report a failure, but you can open **MUD Dev Tools** in the game on the browser, click **Tables**, and select **app\_\_VerifierAddress**. See that the address is not zero.
+
+3. Set the verifier address as the server's address.
+
+ ```sh copy
+ cast send $WORLD_ADDRESS 'app__setVerifier(address)' `cast address-zero` --private-key $AUTHORIZED_KEY
+ ```
+
+ The address in **app\_\_VerifiedAddress** should now be zero.
+
+All MUD functions in the same `System` go through the same access control, so I consider this test sufficient. If you don't, you can check the other functions in [`ServerSystem`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol).
+
+### Zero-knowledge abuses {#zero-knowledge-abuses}
+
+The math to verify Zokrates is beyond the scope of this tutorial (and my abilities). However, we can run various checks on the zero-knowledge code to verify that if it is not done correctly it fails. All of these tests are going to require us to change [`zero-knowledge.ts`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts) and restart the entire application. It is not sufficient to restart the server process, because it puts the application in an impossible state (the player has a game in progress, but the game is no longer available to the server).
+
+#### Wrong answer {#wrong-answer}
+
+The simplest possibility is to provide the wrong answer in the zero-knowledge proof. To do that, we go inside `zkDig` and [modify line 91](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L91):
+
+```ts
+proof.inputs[3] = "0x" + "1".padStart(64, "0")
+```
+
+This means we'll always claim there is one bomb, regardless of the correct answer. Try to play with this version, and you'll see in the **server** tab of the `pnpm dev` screen this error:
+
+```
+ cause: {
+ code: 3,
+ message: 'execution reverted: revert: Zero knowledge verification fail',
+ data: '0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000
+000000000000000000000000000000000000000000000000205a65726f206b6e6f776c6564676520766572696669636174696f6
+e206661696c'
+ },
+```
+
+So this kind of cheat fails.
+
+#### Wrong proof {#wrong-proof}
+
+What happens if we provide the correct information, but just have the wrong proof data? Now, replace line 91 with:
+
+```ts
+proof.proof = {
+ a: ["0x" + "1".padStart(64, "0"), "0x" + "2".padStart(64, "0")],
+ b: [
+ ["0x" + "1".padStart(64, "0"), "0x" + "2".padStart(64, "0")],
+ ["0x" + "1".padStart(64, "0"), "0x" + "2".padStart(64, "0")],
+ ],
+ c: ["0x" + "1".padStart(64, "0"), "0x" + "2".padStart(64, "0")],
+}
+```
+
+It still fails, but now it fails without a reason because it happens during the verifier call.
+
+### How can a user verify the zero trust code? {#user-verify-zero-trust}
+
+Smart contracts are relatively easy to verify. Typically, the developer publishes the source code to a block explorer, and the block explorer verifies that the source code does compile to the code in the [contract deployment transaction](https://ethereum.org/en/developers/docs/smart-contracts/deploying/). In the case of MUD `System`s this is [slightly more complicated](https://mud.dev/cli/verify), but not by much.
+
+This is harder with zero-knowledge. The verifier includes some constants and runs some calculations on them. This doesn't tell you what is being proved.
+
+```solidity
+ function verifyingKey() pure internal returns (VerifyingKey memory vk) {
+ vk.alpha = Pairing.G1Point(uint256(0x0f43f4fe7b5c2326fed4ac6ed2f4003ab9ab4ea6f667c2bdd77afb068617ee16), uint256(0x25a77832283f9726935219b5f4678842cda465631e72dbb24708a97ba5d0ce6f));
+ vk.beta = Pairing.G2Point([uint256(0x2cebd0fbd21aca01910581537b21ae4fed46bc0e524c055059aa164ba0a6b62b), uint256(0x18fd4a7bc386cf03a95af7163d5359165acc4e7961cb46519e6d9ee4a1e2b7e9)], [uint256(0x11449dee0199ef6d8eebfe43b548e875c69e7ce37705ee9a00c81fe52f11a009), uint256(0x066d0c83b32800d3f335bb9e8ed5e2924cf00e77e6ec28178592eac9898e1a00)]);
+```
+
+The solution, at least until block explorers get around to adding Zokrates verification to their user interfaces, is for the application developers to make available the Zokrates programs, and for at least some users to compile them themselves with the appropriate verification key.
+
+To do so:
+
+1. [Install Zokrates](https://zokrates.github.io/gettingstarted.html).
+2. Create a file, `dig.zok`, with the Zokrates program. The code below assumes you kept the original map size, 10x5.
+
+ ```zokrates
+ import "utils/pack/bool/pack128.zok" as pack128;
+ import "hashes/poseidon/poseidon.zok" as poseidon;
+
+ def hashMap(bool[12][7] map) -> field {
+ bool[512] mut map1d = [false; 512];
+ u32 mut counter = 0;
+
+ for u32 x in 0..12 {
+ for u32 y in 0..7 {
+ map1d[counter] = map[x][y];
+ counter = counter+1;
+ }
+ }
+
+ field[4] hashMe = [
+ pack128(map1d[0..128]),
+ pack128(map1d[128..256]),
+ pack128(map1d[256..384]),
+ pack128(map1d[384..512])
+ ];
+
+ return poseidon(hashMe);
+ }
+
+
+ // The number of mines in location (x,y)
+ def map2mineCount(bool[12][7] map, u32 x, u32 y) -> u8 {
+ return if map[x+1][y+1] { 1 } else { 0 };
+ }
+
+ def main(private bool[12][7] map, u32 x, u32 y) -> (field, u8) {
+ return (hashMap(map) ,
+ if map2mineCount(map, x, y) > 0 { 0xFF } else {
+ map2mineCount(map, x-1, y-1) + map2mineCount(map, x, y-1) + map2mineCount(map, x+1, y-1) +
+ map2mineCount(map, x-1, y) + map2mineCount(map, x+1, y) +
+ map2mineCount(map, x-1, y+1) + map2mineCount(map, x, y+1) + map2mineCount(map, x+1, y+1)
+ }
+ );
+ }
+ ```
+
+3. Compile the Zokrates code and create the verification key. The verification key has to be created with the same entropy used in the original server, [in this case an empty string](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L67).
+
+ ```sh copy
+ zokrates compile --input dig.zok
+ zokrates setup -e ""
+ ```
+
+4. Create the Solidity verifier on your own, and verify it is functionally identical to the one on the blockchain (the server adds a comment, but that's not important).
+
+ ```sh copy
+ zokrates export-verifier
+ diff verifier.sol ~/20240901-secret-state/packages/contracts/src/verifier.sol
+ ```
+
+## Design decisions {#design}
+
+In any sufficiently complex application there are competing design goals that require trade-offs. Let's look at some of the tradeoffs and why the current solution is preferable to other options.
+
+### Why zero-knowledge {#why-zero-knowledge}
+
+For minesweeper you don't really need zero-knowledge. The server can always hold the map, and then just reveal all of it when the game is over. Then, at the end of the game, the smart contract can calculate the map hash, verify that it matches, and if it doesn't penalize the server or disregard the game completely.
+
+I didn't use this simpler solution because it only works for short games with a well defined end state. When a game is potentially infinite (such as the case with [autonomous worlds](https://0xparc.org/blog/autonomous-worlds)), you need a solution that proves the state _without_ revealing it.
+
+As a tutorial this article needed a short game that is easy to understand, but this technique is most useful for longer games.
+
+### Why Zokrates? {#why-zokrates}
+
+[Zokrates](https://zokrates.github.io/) isn't the only zero-knowledge library available, but it is similar to a normal, [imperative](https://en.wikipedia.org/wiki/Imperative_programming) programming language and supports boolean variables.
+
+For your application, with different requirements, you might prefer to use [Circum](https://docs.circom.io/getting-started/installation/) or [Cairo](https://www.cairo-lang.org/tutorials/getting-started-with-cairo/).
+
+### When to compile Zokrates {#when-compile-zokrates}
+
+In this program we compile the Zokrates programs [every time the server starts](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L60-L61). This is clearly a waste of resources, but this is a tutorial, optimized for simplicity.
+
+If I were writing a production-level application, I'd check if I have a file with the compiled Zokrates programs at this minefield size, and if so use that. The same is true for deploying a verifier contract onchain.
+
+### Creating the verifier and prover keys {#key-creation}
+
+[Key creation](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L63-L69) is another pure calculation that needn't be done more than once for a given minefield size. Again, it is done only once for the sake of simplicity.
+
+Additionally, we could use [a setup ceremony](https://zokrates.github.io/toolbox/trusted_setup.html#initializing-a-phase-2-ceremony). The advantage of a setup ceremony is that you need either the entropy or some intermediate result from each participant to cheat on the zero-knowledge proof. If at least one ceremony participant is honest and deletes that information, the zero-knowledge proofs are safe from certain attacks. However, there is _no mechanism_ to verify that information has been deleted from everywhere. If zero-knowledge proofs are critically important, you want to participate in the setup ceremony.
+
+Here we rely on [perpetual powers of tau](https://github.com/privacy-scaling-explorations/perpetualpowersoftau), which had dozens of participants. It is probably safe enough, and much simpler. We also don't add entropy to the during key creation, which makes it easier for users to [verify the zero-knowledge configuration](#user-verify-zero-trust).
+
+### Where to verify {#where-verification}
+
+We can verify the zero-knowledge proofs either onchain (which costs gas) or in the client (using [`verify`](https://zokrates.github.io/toolbox/zokrates_js.html#verifyverificationkey-proof)). I chose the first, because this lets you [verify the verifier](#user-verify-zero-trust) once and then trust that if doesn't change as long as the contract address for it stays the same. If verification was done on the client, you'd have to verify the code you receive each time you download the client.
+
+Also, while this game is single player, a lot of blockchain games are multi-player. onchain verification means you only verify the zero-knowledge proof once. Doing it in the client would require each client to verify independently.
+
+### Flatten the map in TypeScript or Zokrates? {#where-flatten}
+
+In general, when processing can be done either in TypeScript or Zokrates, it is better to do it TypeScript, which is a lot faster, and does not require zero-knowledge proofs. This is the reason, for example, that we don't provide Zokrates with the hash and make it verify that it is correct. Hashing has to be done inside Zokrates, but the match between the returned hash and the hash onchain can happen outside it.
+
+However, we still [flatten the map in Zokrates](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L15-L20), whereas we could have done it in TypeScript. The reason is that the other options are, in my opinion, worse.
+
+- Provide a one dimensional array of boolean to the Zokrates code, and use an expression such as `x*(height+2)
++y` to get the two dimensional map. This would make [the code](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L44-L47) somewhat more complicated, so I decided the performance gain isn't worth it for a tutorial.
+
+- Send Zokrates both the one dimensional array and the two dimensional array. However, this solution doesn't gain us anything. The Zokrates code would have to verify that the one dimensional array it is provided really is the correct representation of the two dimensional array. So there wouldn't be any performance gain.
+
+- Flatten the two dimensional array in Zokrates. This is the simplest option, so I chose it.
+
+### Where to store maps {#where-store-maps}
+
+In this application [`gamesInProgress`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L20) is simply a variable in memory. This means that if you server dies and needs to be restarted, all the information it stored is lost. Not only are players unable to continue their game, they cannot even start a new game because the onchain component thinks they still have a game in progress.
+
+This is clearly bad design for a production system, in which you'd store this information in a database. The only reason I used a variable here is because this is a tutorial and simplicity is the main consideration.
+
+## Conclusion: Under what conditions is this the appropriate technique? {#conclusion}
+
+So, now you know how to write a game with a server that stores secret state that doesn't belong onchain. But in what cases should you do it? There are two main considerations.
+
+- _Long running game_: [As mentioned above](#why-zero-knowledge), in a short game you can just publish the state once the game is over and have everything verified then. But that is not an option when the game takes a long or indefinite time, and the state needs to stay secret.
+
+- _Some centralization acceptable_: Zero-knowledge proofs can verify integrity, that an entity is not faking the results. What they can't do is ensure that the entity will still be available and answer messages. In situations where availability also needs to be decentralized, zero-knowledge proofs are not a sufficient solution, and you need [multi-party computation](https://en.wikipedia.org/wiki/Secure_multi-party_computation).
+
+### Acknowledgements {#acknowledgements}
+
+- Alvaro Alonso read a draft of this article and cleared up some of my misunderstandings about Zokrates.
+
+Any remaining errors are my responsibility.
diff --git a/public/content/developers/tutorials/secret-state/mprocs.png b/public/content/developers/tutorials/secret-state/mprocs.png
new file mode 100644
index 00000000000..3364e25a6e2
Binary files /dev/null and b/public/content/developers/tutorials/secret-state/mprocs.png differ
diff --git a/public/content/developers/tutorials/server-components/index.md b/public/content/developers/tutorials/server-components/index.md
index 14fae60d5ab..4c924c69ca9 100644
--- a/public/content/developers/tutorials/server-components/index.md
+++ b/public/content/developers/tutorials/server-components/index.md
@@ -1,6 +1,6 @@
---
title: "Server components and agents for web3 apps"
-description: After reading this tutorial, you will be able to write TypeScript servers that listen to events on a blockchain and respond accordingly with their own transactions. This will enable you to write centralized applications (because the server is a point of failure), but can interact with web3 entities. The same techniques can also be used to write an agent that responds to on-chain events without a human in the loop.
+description: After reading this tutorial, you will be able to write TypeScript servers that listen to events on a blockchain and respond accordingly with their own transactions. This will enable you to write centralized applications (because the server is a point of failure), but can interact with web3 entities. The same techniques can also be used to write an agent that responds to onchain events without a human in the loop.
author: Ori Pomerantz
lang: en
@@ -169,7 +169,7 @@ const greeter = getContract({
})
```
-Now that we have all the prerequisites, we can finally create a [contract instance](https://viem.sh/docs/contract/getContract). We will use this contract instance to communicate with the on-chain contract.
+Now that we have all the prerequisites, we can finally create a [contract instance](https://viem.sh/docs/contract/getContract). We will use this contract instance to communicate with the onchain contract.
##### Reading from the blockchain
diff --git a/public/content/developers/tutorials/short-abi/index.md b/public/content/developers/tutorials/short-abi/index.md
index ff6cfd424b1..65e7879dd28 100644
--- a/public/content/developers/tutorials/short-abi/index.md
+++ b/public/content/developers/tutorials/short-abi/index.md
@@ -21,7 +21,7 @@ However, the technique explained here should work just as well for other rollups
### Terminology {#terminology}
When discussing rollups, the term 'layer 1' (L1) is used for Mainnet, the production Ethereum network.
-The term 'layer 2' (L2) is used for the rollup or any other system that relies on L1 for security but does most of its processing off-chain.
+The term 'layer 2' (L2) is used for the rollup or any other system that relies on L1 for security but does most of its processing offchain.
## How can we further reduce the cost of L2 transactions? {#how-can-we-further-reduce-the-cost-of-L2-transactions}
@@ -196,7 +196,7 @@ In the case of `CalldataInterpreter`, _any_ call gets here because there are no
Read the first byte of the calldata, which tells us the function.
There are two reasons why a function would not be available here:
-1. Functions that are `pure` or `view` don't change the state and don't cost gas (when called off-chain).
+1. Functions that are `pure` or `view` don't change the state and don't cost gas (when called offchain).
It makes no sense to try to reduce their gas cost.
2. Functions that rely on [`msg.sender`](https://docs.soliditylang.org/en/v0.8.12/units-and-global-variables.html#block-and-transaction-properties).
The value of `msg.sender` is going to be `CalldataInterpreter`'s address, not the caller.
diff --git a/public/content/developers/tutorials/smart-contract-security-guidelines/index.md b/public/content/developers/tutorials/smart-contract-security-guidelines/index.md
index e38a40829a3..234ad0541cd 100644
--- a/public/content/developers/tutorials/smart-contract-security-guidelines/index.md
+++ b/public/content/developers/tutorials/smart-contract-security-guidelines/index.md
@@ -24,9 +24,9 @@ Documentation can be written at different levels, and should be updated while im
- **Schema and architectural diagrams**, including the contract interactions and the state machine of the system. [Slither printers](https://github.com/crytic/slither/wiki/Printer-documentation) can help to generate these schemas.
- **Thorough code documentation**, the [Natspec format](https://solidity.readthedocs.io/en/develop/natspec-format.html) can be used for Solidity.
-### On-chain vs off-chain computation {#on-chain-vs-off-chain-computation}
+### Onchain vs offchain computation {#onchain-vs-offchain-computation}
-- **Keep as much code as you can off-chain.** Keep the on-chain layer small. Pre-process data with code off-chain in such a way that verification on-chain is simple. Do you need an ordered list? Sort the list offchain, then only check its order onchain.
+- **Keep as much code as you can offchain.** Keep the onchain layer small. Pre-process data with code offchain in such a way that verification onchain is simple. Do you need an ordered list? Sort the list offchain, then only check its order onchain.
### Upgradeability {#upgradeability}
diff --git a/public/content/developers/tutorials/uniswap-v2-annotated-code/index.md b/public/content/developers/tutorials/uniswap-v2-annotated-code/index.md
index 17568f9a979..b727ed831e5 100644
--- a/public/content/developers/tutorials/uniswap-v2-annotated-code/index.md
+++ b/public/content/developers/tutorials/uniswap-v2-annotated-code/index.md
@@ -755,7 +755,7 @@ This is the main function of the factory, to create a pair exchange between two
(address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
```
-We want the address of the new exchange to be deterministic, so it can be calculated in advance off chain (this can be useful for [layer 2 transactions](/developers/docs/scaling/)).
+We want the address of the new exchange to be deterministic, so it can be calculated in advance offchain (this can be useful for [layer 2 transactions](/developers/docs/scaling/)).
To do this we need to have a consistent order of the token addresses, regardless of the order in which we have received them, so we sort them here.
```solidity
@@ -817,7 +817,7 @@ These two functions allow `feeSetter` to control the fee recipient (if any), and
[This contract](https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) implements the ERC-20 liquidity token. It is similar to the [OpenZeppelin ERC-20 contract](/developers/tutorials/erc20-annotated-code), so I will only explain the part that is different, the `permit` functionality.
Transactions on Ethereum cost ether (ETH), which is equivalent to real money. If you have ERC-20 tokens but not ETH, you can't send transactions, so you can't do anything with them. One solution to avoid this problem is [meta-transactions](https://docs.uniswap.org/contracts/v2/guides/smart-contract-integration/supporting-meta-transactions).
-The owner of the tokens signs a transaction that allows somebody else to withdraw tokens off chain and sends it using the Internet to the recipient. The recipient, which does have ETH, then submits the permit on behalf of the owner.
+The owner of the tokens signs a transaction that allows somebody else to withdraw tokens offchain and sends it using the Internet to the recipient. The recipient, which does have ETH, then submits the permit on behalf of the owner.
```solidity
bytes32 public DOMAIN_SEPARATOR;
diff --git a/public/content/enterprise/index.md b/public/content/enterprise/index.md
index 0725819503b..5203cfecb8b 100644
--- a/public/content/enterprise/index.md
+++ b/public/content/enterprise/index.md
@@ -89,7 +89,7 @@ Here are some of the enterprise applications that have been built on top of the
- [ABN AMRO](https://tokeny.com/tokeny-fuels-abn-amro-bank-in-tokenizing-green-bonds-on-polygon/) - _with Tokeny, tokenized green bonds_
- [Crowdz](https://crowdz.io/) - _invoice/receivables financing and factoring platform_
- [Mata Capital](https://consensys.io/blockchain-use-cases/finance/mata-capital) - _real estate investment tokenization_
-- [Obligate](https://www.obligate.com/) - _regulated and KYC'd on-chain bonds and commercial paper_
+- [Obligate](https://www.obligate.com/) - _regulated and KYC'd onchain bonds and commercial paper_
- [Siemens](https://press.siemens.com/global/en/pressrelease/siemens-issues-first-digital-bond-blockchain ) - _bond issuance_
- [Sila](https://silamoney.com/) - _banking and ACH payments infrastructure-as-a-service, using a stablecoin_
- [Societe Generale FORGE](https://www.sgforge.com/product/bonds/) - _bond issuance_
diff --git a/public/content/glossary/index.md b/public/content/glossary/index.md
index 64026adc232..5a97cf5151c 100644
--- a/public/content/glossary/index.md
+++ b/public/content/glossary/index.md
@@ -320,11 +320,11 @@ lang: en
## O {#section-o}
-
+
-
+
diff --git a/public/content/governance/index.md b/public/content/governance/index.md
index e3ff43c529c..658c7785d9d 100644
--- a/public/content/governance/index.md
+++ b/public/content/governance/index.md
@@ -20,17 +20,17 @@ No one person owns or controls the Ethereum protocol, but decisions still need t
## Ethereum Governance {#ethereum-governance}
-Ethereum governance is the process by which protocol changes are made. It's important to point out that this process isn't related to how people and applications use the protocol - Ethereum is permissionless. Anyone from anywhere in the world can participate in on-chain activities. There are no rules set for who can or cannot build an application or send a transaction. However, there is a process to propose changes to the core protocol, which decentralized applications run on top of. Since so many people depend on Ethereum's stability, there is a very high coordination threshold for core changes, including social and technical processes, to ensure any changes to Ethereum are secure and widely supported by the community.
+Ethereum governance is the process by which protocol changes are made. It's important to point out that this process isn't related to how people and applications use the protocol - Ethereum is permissionless. Anyone from anywhere in the world can participate in onchain activities. There are no rules set for who can or cannot build an application or send a transaction. However, there is a process to propose changes to the core protocol, which decentralized applications run on top of. Since so many people depend on Ethereum's stability, there is a very high coordination threshold for core changes, including social and technical processes, to ensure any changes to Ethereum are secure and widely supported by the community.
-### On-chain vs off-chain governance {#on-chain-vs-off-chain}
+### Onchain vs offchain governance {#onchain-vs-offchain}
-Blockchain technology allows for new governance capabilities, known as on-chain governance. On-chain governance is when proposed protocol changes are decided by a stakeholder vote, usually by holders of a governance token, and voting happens on the blockchain. With some forms of on-chain governance, the proposed protocol changes are already written in code and implemented automatically if the stakeholders approve the changes via signing a transaction.
+Blockchain technology allows for new governance capabilities, known as onchain governance. Onchain governance is when proposed protocol changes are decided by a stakeholder vote, usually by holders of a governance token, and voting happens on the blockchain. With some forms of onchain governance, the proposed protocol changes are already written in code and implemented automatically if the stakeholders approve the changes via signing a transaction.
-The opposite approach, off-chain governance, is where any protocol change decisions happen through an informal process of social discussion, which, if approved, would be implemented in code.
+The opposite approach, offchain governance, is where any protocol change decisions happen through an informal process of social discussion, which, if approved, would be implemented in code.
-**Ethereum governance happens off-chain** with a wide variety of stakeholders involved in the process.
+**Ethereum governance happens offchain** with a wide variety of stakeholders involved in the process.
-_Whilst at the protocol level Ethereum governance is off-chain, many use cases built on top of Ethereum, such as DAOs, use on-chain governance._
+_Whilst at the protocol level Ethereum governance is offchain, many use cases built on top of Ethereum, such as DAOs, use onchain governance._
More on DAOs
diff --git a/public/content/history/index.md b/public/content/history/index.md
index 761c2d28d44..53d951389f2 100644
--- a/public/content/history/index.md
+++ b/public/content/history/index.md
@@ -32,8 +32,8 @@ Since 2021, upgrades to the **execution layer** are named according to the city
| Berlin | 2014 | 0 | Apr 15, 2021 |
| London | 2015 | I | Aug 5, 2021 |
| Shanghai | 2016 | II | Apr 12, 2023 |
-| **Cancun** | 2017 | III | Mar 13, 2024 |
-| _Prague_ | 2018 | IV | TBD |
+| Cancun | 2017 | III | Mar 13, 2024 |
+| **Prague** | 2018 | IV | TBD - Next |
| _Osaka_ | 2019 | V | TBD |
| _Bogota_ | 2022 | VI | TBD |
| _Bangkok_ | 2024 | VII | TBD |
@@ -42,23 +42,26 @@ Since 2021, upgrades to the **execution layer** are named according to the city
Since the launch of the [Beacon Chain](/glossary/#beacon-chain), upgrades to the **consensus layer** are named after celestial stars beginning with letters that proceed in alphabetical order:
-| Upgrade Name | Upgrade Date |
-| ----------------------------------------------------------- | ------------ |
-| Beacon Chain genesis | Dec 1, 2020 |
-| [Altair](https://en.wikipedia.org/wiki/Altair) | Oct 27, 2021 |
-| [Bellatrix](https://en.wikipedia.org/wiki/Bellatrix) | Sep 6, 2022 |
-| [Capella](https://en.wikipedia.org/wiki/Capella) | Apr 12, 2023 |
-| [**Deneb**](https://en.wikipedia.org/wiki/Deneb) | Mar 13, 2024 |
-| [_Electra_]() | TBD |
+| Upgrade Name | Upgrade Date |
+| ------------------------------------------------------------- | ------------ |
+| Beacon Chain genesis | Dec 1, 2020 |
+| [Altair](https://en.wikipedia.org/wiki/Altair) | Oct 27, 2021 |
+| [Bellatrix](https://en.wikipedia.org/wiki/Bellatrix) | Sep 6, 2022 |
+| [Capella](https://en.wikipedia.org/wiki/Capella) | Apr 12, 2023 |
+| [Deneb](https://en.wikipedia.org/wiki/Deneb) | Mar 13, 2024 |
+| [**Electra**]() | TBD - Next |
+| [_Fulu_]() | TBD |
**Combined naming**
-The execution and consensus upgrades were initially rolled out at different times, but after [The Merge](/roadmap/merge/) in 2022 these have been deployed simultaneously. As-such, colloquial terms have emerged to simplify references to these upgrades using a single conjoined term. This began with the _Shanghai-Capella_ upgrade, commonly referred to as "**Shapella**", and is continued with the _Cancun-Deneb_ upgrade, which may be referred to as "**Dencun**."
+The execution and consensus upgrades were initially rolled out at different times, but after [The Merge](/roadmap/merge/) in 2022 these have been deployed simultaneously. As-such, colloquial terms have emerged to simplify references to these upgrades using a single conjoined term. This began with the _Shanghai-Capella_ upgrade, commonly referred to as "**Shapella**", and is continued with the _Cancun-Deneb_ (**Dencun**), and the _Prague-Electra_ (**Pectra**) upgrades.
| Execution Upgrade | Consensus Upgrade | Short Name |
| ----------------- | ----------------- | ---------- |
| Shanghai | Capella | "Shapella" |
| Cancun | Deneb | "Dencun" |
+| Prague | Electra | "Pectra" |
+| Osaka | Fulu | "Fusaka" |
@@ -68,6 +71,55 @@ Looking for future protocol upgrades? [Learn about upcoming upgrades on the Ethe
+## 2025 {#2025}
+
+### Prague-Electra ("Pectra", _in progress_) {#pectra}
+
+
+
+The Prague-Electra ("Pectra") upgrade includes several improvements to the Ethereum protocol aimed at enhancing the experience for all users, layer 2 networks, stakers and node operators.
+
+Staking gets an upgrade with compounding validator accounts, and improved control over staked funds using the execution withdrawal address. EIP-7251 increases the max effective balance for a single validator to 2048, improving capital efficiency for stakers. EIP-7002 allows an execution account to securely trigger validator actions, including exiting, or withdrawing portions of the funds, improving the experience for ETH stakers, while helping strengthen accountability for node operators.
+
+Other parts of the upgrade focus on improving the experience for regular users. EIP-7702 brings the ability for a regular non-smart-contract account ([EOA](/glossary/#eoa)) to execute code similar to a smart contract. This unlocks unbounded new functionality for traditional Ethereum accounts, such as transaction batching, gas sponsorship, alternative authentication, programmable spending controls, account recovery mechanisms and more.
+
+
+
+Better user experience:
+
+
EIP-7549 - Move committee index outside Attestation
+
+
+
+
+- [Pectra.wtf](https//pectra.wtf)
+- [How Pectra will enhance the staking experience](https://www.kiln.fi/post/next-ethereum-upgrade-how-pectra-will-enhance-the-staking-experience)
+- [Read the Electra upgrade specifications](https://github.com/ethereum/consensus-specs/blob/dev/specs/electra/)
+- [Prague-Electra ("Pectra") FAQ](/roadmap/pectra/)
+
+
+
## 2024 {#2024}
### Cancun-Deneb ("Dencun") {#dencun}
@@ -426,7 +478,7 @@ The Constantinople fork:
-
EIP-145 – optimises cost of certain on-chain actions.
+
EIP-145 – optimises cost of certain onchain actions.
EIP-1014 – allows you to interact with addresses that have yet to be created.
EIP-1052 – introduces the EXTCODEHASH instruction to retrieve the hash of another contract's code.
EIP-1234 – makes sure the blockchain doesn't freeze before proof-of-stake and reduces block reward from 3 to 2 ETH.
diff --git a/public/content/roadmap/account-abstraction/index.md b/public/content/roadmap/account-abstraction/index.md
index cbb761126d3..6927aade99f 100644
--- a/public/content/roadmap/account-abstraction/index.md
+++ b/public/content/roadmap/account-abstraction/index.md
@@ -72,11 +72,11 @@ These are just a few examples of how user experiences could be leveled up by acc
## How will account abstraction be implemented? {#how-will-aa-be-implemented}
-Smart contract wallets exist today but are challenging to implement because the EVM does not support them. Instead, they rely on wrapping relatively complex code around standard Ethereum transactions. Ethereum can change this by allowing smart contracts to initiate transactions, handling the necessary logic in Ethereum smart contracts instead of off-chain. Putting logic into smart contracts also increases Ethereum's decentralization since it removes the need for "relayers" run by wallet developers to translate messages signed by the user to regular Ethereum transactions.
+Smart contract wallets exist today but are challenging to implement because the EVM does not support them. Instead, they rely on wrapping relatively complex code around standard Ethereum transactions. Ethereum can change this by allowing smart contracts to initiate transactions, handling the necessary logic in Ethereum smart contracts instead of offchain. Putting logic into smart contracts also increases Ethereum's decentralization since it removes the need for "relayers" run by wallet developers to translate messages signed by the user to regular Ethereum transactions.
-EIP-2771 introduces the concept of meta-transactions that allow third parties to pay for a user's gas costs without making changes to the Ethereum protocol. The idea is that transactions signed by a user get sent to a `Forwarder` contract. The forwarder is a trusted entity that verifies that transactions are valid before sending them on to a gas relay. This is done off-chain, avoiding the need to pay gas. The gas relay passes the transaction on to a `Recipient` contract, paying the necessary gas to make the transaction executable on Ethereum. The transaction is executed if the `Forwarder` is known and trusted by the `Recipient`. This model makes it easy for developers to implement gasless transactions for users.
+EIP-2771 introduces the concept of meta-transactions that allow third parties to pay for a user's gas costs without making changes to the Ethereum protocol. The idea is that transactions signed by a user get sent to a `Forwarder` contract. The forwarder is a trusted entity that verifies that transactions are valid before sending them on to a gas relay. This is done offchain, avoiding the need to pay gas. The gas relay passes the transaction on to a `Recipient` contract, paying the necessary gas to make the transaction executable on Ethereum. The transaction is executed if the `Forwarder` is known and trusted by the `Recipient`. This model makes it easy for developers to implement gasless transactions for users.
diff --git a/public/content/roadmap/danksharding/index.md b/public/content/roadmap/danksharding/index.md
index 534f95c8665..e22d76b31e3 100644
--- a/public/content/roadmap/danksharding/index.md
+++ b/public/content/roadmap/danksharding/index.md
@@ -17,17 +17,17 @@ summaryPoints:
Proto-Danksharding, also known as [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844), is a way for [rollups](/layer-2/#rollups) to add cheaper data to blocks. The name comes from the two researchers who proposed the idea: Protolambda and Dankrad Feist. Historically, rollups had been limited in how cheap they can make user transactions by the fact that they post their transactions in `CALLDATA`.
-This is expensive because it is processed by all Ethereum nodes and lives on-chain forever, even though rollups only need the data for a short time. Proto-Danksharding introduces data blobs that can be sent and attached to blocks. The data in these blobs is not accessible to the EVM and is automatically deleted after a fixed time period (set to 4096 epochs at time of writing, or about 18 days). This means rollups can send their data much more cheaply and pass the savings on to end users in the form of cheaper transactions.
+This is expensive because it is processed by all Ethereum nodes and lives onchain forever, even though rollups only need the data for a short time. Proto-Danksharding introduces data blobs that can be sent and attached to blocks. The data in these blobs is not accessible to the EVM and is automatically deleted after a fixed time period (set to 4096 epochs at time of writing, or about 18 days). This means rollups can send their data much more cheaply and pass the savings on to end users in the form of cheaper transactions.
-Rollups are a way to scale Ethereum by batching transactions off-chain and then posting the results to Ethereum. A rollup is essentially composed of two parts: data and execution check. The data is the full sequence of transactions that is being processed by a rollup to produce the state change being posted to Ethereum. The execution check is the re-execution of those transactions by some honest actor (a "prover") to ensure that the proposed state change is correct. To perform the execution check, the transaction data has to be available for long enough for anyone to download and check. This means any dishonest behavior by the rollup sequencer can be identified and challenged by the prover. However, it does not need to be available forever.
+Rollups are a way to scale Ethereum by batching transactions offchain and then posting the results to Ethereum. A rollup is essentially composed of two parts: data and execution check. The data is the full sequence of transactions that is being processed by a rollup to produce the state change being posted to Ethereum. The execution check is the re-execution of those transactions by some honest actor (a "prover") to ensure that the proposed state change is correct. To perform the execution check, the transaction data has to be available for long enough for anyone to download and check. This means any dishonest behavior by the rollup sequencer can be identified and challenged by the prover. However, it does not need to be available forever.
-Rollups post commitments to their transaction data on-chain and also make the actual data available in data blobs. This means provers can check the commitments are valid or challenge data they think is wrong. At the node-level, the blobs of data are held in the consensus client. The consensus clients attest that they have seen the data and that it has been propagated around the network. If the data was kept forever, these clients would bloat and lead to large hardware requirements for running nodes. Instead, the data is automatically pruned from the node every 18 days. The consensus client attestations demonstrate that there was a sufficient opportunity for provers to verify the data. The actual data can be stored off-chain by rollup operators, users or others.
+Rollups post commitments to their transaction data onchain and also make the actual data available in data blobs. This means provers can check the commitments are valid or challenge data they think is wrong. At the node-level, the blobs of data are held in the consensus client. The consensus clients attest that they have seen the data and that it has been propagated around the network. If the data was kept forever, these clients would bloat and lead to large hardware requirements for running nodes. Instead, the data is automatically pruned from the node every 18 days. The consensus client attestations demonstrate that there was a sufficient opportunity for provers to verify the data. The actual data can be stored offchain by rollup operators, users or others.
@@ -47,7 +47,7 @@ The EIP-4844 KZG ceremony was open to the public and tens of thousands of people
-When a rollup posts data in a blob, they provide a "commitment" that they post on-chain. This commitment is the result of evaluating a polynomial fit to the data at certain points. These points are defined by the random numbers generated in the KZG ceremony. Provers can then evaluate the polynomial at the same points in order to verify the data - if they arrive at the same values then the data is correct.
+When a rollup posts data in a blob, they provide a "commitment" that they post onchain. This commitment is the result of evaluating a polynomial fit to the data at certain points. These points are defined by the random numbers generated in the KZG ceremony. Provers can then evaluate the polynomial at the same points in order to verify the data - if they arrive at the same values then the data is correct.
diff --git a/public/content/roadmap/merge/index.md b/public/content/roadmap/merge/index.md
index aff0da7d792..ada43184597 100644
--- a/public/content/roadmap/merge/index.md
+++ b/public/content/roadmap/merge/index.md
@@ -98,7 +98,7 @@ The Merge came with changes to consensus, which also includes changes related to
block structure
slot/block timing
opcode changes
-
sources of on-chain randomness
+
sources of onchain randomness
concept of safe head and finalized blocks
diff --git a/public/content/roadmap/scaling/index.md b/public/content/roadmap/scaling/index.md
index ee0a7dcc31e..cbebcabdc98 100644
--- a/public/content/roadmap/scaling/index.md
+++ b/public/content/roadmap/scaling/index.md
@@ -1,6 +1,6 @@
---
title: Scaling Ethereum
-description: Rollups batch transactions together off-chain, reducing costs for the user. However, the way rollups currently use data is too expensive, limiting how cheap transactions can be. Proto-Danksharding fixes this.
+description: Rollups batch transactions together offchain, reducing costs for the user. However, the way rollups currently use data is too expensive, limiting how cheap transactions can be. Proto-Danksharding fixes this.
lang: en
image: /images/roadmap/roadmap-transactions.png
alt: "Ethereum roadmap"
diff --git a/public/content/roadmap/verkle-trees/index.md b/public/content/roadmap/verkle-trees/index.md
index a5a466f03a8..a2d355534de 100644
--- a/public/content/roadmap/verkle-trees/index.md
+++ b/public/content/roadmap/verkle-trees/index.md
@@ -57,6 +57,8 @@ Verkle tree testnets are already up and running, but there are still substantial
- [Verkle Trees for Statelessness](https://verkle.info/)
- [Dankrad Feist explain Verkle trees on PEEPanEIP](https://www.youtube.com/watch?v=RGJOQHzg3UQ)
+- [Verkle Trees For The Rest Of Us](https://research.2077.xyz/verkle-trees)
+- [Anatomy of A Verkle Proof](https://ihagopian.com/posts/anatomy-of-a-verkle-proof)
- [Guillaume Ballet explain Verkle trees at ETHGlobal](https://www.youtube.com/watch?v=f7bEtX3Z57o)
- ["How Verkle trees make Ethereum lean and mean" by Guillaume Ballet at Devcon 6](https://www.youtube.com/watch?v=Q7rStTKwuYs)
- [Piper Merriam on stateless clients from ETHDenver 2020](https://www.youtube.com/watch?v=0yiZJNciIJ4)
diff --git a/public/content/staking/pools/index.md b/public/content/staking/pools/index.md
index aa2611d076d..e7cdc71ea71 100644
--- a/public/content/staking/pools/index.md
+++ b/public/content/staking/pools/index.md
@@ -17,7 +17,7 @@ summaryPoints:
Staking pools are a collaborative approach to allow many with smaller amounts of ETH to obtain the 32 ETH required to activate a set of validator keys. Pooling functionality is not natively supported within the protocol, so solutions were built out separately to address this need.
-Some pools operate using smart contracts, where funds can be deposited to a contract, which trustlessly manages and tracks your stake, and issues you a token that represents this value. Other pools may not involve smart contracts and are instead mediated off-chain.
+Some pools operate using smart contracts, where funds can be deposited to a contract, which trustlessly manages and tracks your stake, and issues you a token that represents this value. Other pools may not involve smart contracts and are instead mediated offchain.
## Why stake with a pool? {#why-stake-with-a-pool}
diff --git a/public/content/whitepaper/index.md b/public/content/whitepaper/index.md
index 190dff5fc4e..287edab98bb 100644
--- a/public/content/whitepaper/index.md
+++ b/public/content/whitepaper/index.md
@@ -268,7 +268,7 @@ def send(to, value):
self.storage[to] = self.storage[to] + value
```
-This is essentially a literal implementation of the "banking system" state transition function described further above in this document. A few extra lines of code need to be added to provide for the initial step of distributing the currency units in the first place and a few other edge cases, and ideally a function would be added to let other contracts query for the balance of an address. But that's all there is to it. Theoretically, Ethereum-based token systems acting as sub-currencies can potentially include another important feature that on-chain Bitcoin-based meta-currencies lack: the ability to pay transaction fees directly in that currency. The way this would be implemented is that the contract would maintain an ether balance with which it would refund ether used to pay fees to the sender, and it would refill this balance by collecting the internal currency units that it takes in fees and reselling them in a constant running auction. Users would thus need to "activate" their accounts with ether, but once the ether is there it would be reusable because the contract would refund it each time.
+This is essentially a literal implementation of the "banking system" state transition function described further above in this document. A few extra lines of code need to be added to provide for the initial step of distributing the currency units in the first place and a few other edge cases, and ideally a function would be added to let other contracts query for the balance of an address. But that's all there is to it. Theoretically, Ethereum-based token systems acting as sub-currencies can potentially include another important feature that onchain Bitcoin-based meta-currencies lack: the ability to pay transaction fees directly in that currency. The way this would be implemented is that the contract would maintain an ether balance with which it would refund ether used to pay fees to the sender, and it would refill this balance by collecting the internal currency units that it takes in fees and reselling them in a constant running auction. Users would thus need to "activate" their accounts with ether, but once the ether is there it would be reusable because the contract would refund it each time.
### Financial derivatives and Stable-Value Currencies {#financial-derivatives-and-stable-value-currencies}
@@ -341,7 +341,7 @@ Normally, 1% per day is enough for Alice, and if Alice wants to withdraw more sh
**7. Prediction markets**. Provided an oracle or SchellingCoin, prediction markets are also easy to implement, and prediction markets together with SchellingCoin may prove to be the first mainstream application of [futarchy](http://hanson.gmu.edu/futarchy.html) as a governance protocol for decentralized organizations.
-**8. On-chain decentralized marketplaces**, using the identity and reputation system as a base.
+**8. Onchain decentralized marketplaces**, using the identity and reputation system as a base.
## Miscellanea And Concerns {#miscellanea-and-concerns}
diff --git a/public/content/zero-knowledge-proofs/index.md b/public/content/zero-knowledge-proofs/index.md
index 5d1bd2a6a1a..b39b8b8e3fb 100644
--- a/public/content/zero-knowledge-proofs/index.md
+++ b/public/content/zero-knowledge-proofs/index.md
@@ -32,7 +32,7 @@ Going back to our earlier example, the only evidence you need to prove your citi
Credit card payments are often visible to multiple parties, including the payments provider, banks, and other interested parties (e.g., government authorities). While financial surveillance has benefits for identifying illegal activity, it also undermines the privacy of ordinary citizens.
-Cryptocurrencies were intended to provide a means for users to conduct private, peer-to-peer transactions. But most cryptocurrency transactions are openly visible on public blockchains. User identities are often pseudonymous and either wilfully linked to real-world identities (e.g. by including ETH addresses on Twitter or GitHub profiles) or can be associated with real-world identities using basic on and off-chain data analysis.
+Cryptocurrencies were intended to provide a means for users to conduct private, peer-to-peer transactions. But most cryptocurrency transactions are openly visible on public blockchains. User identities are often pseudonymous and either wilfully linked to real-world identities (e.g. by including ETH addresses on Twitter or GitHub profiles) or can be associated with real-world identities using basic on and offchain data analysis.
There are specific “privacy coins” designed for completely anonymous transactions. Privacy-focused blockchains, such as Zcash and Monero, shield transaction details, including sender/receiver addresses, asset type, quantity, and the transaction timeline.
@@ -58,9 +58,9 @@ Verifiable computation is another application of zero-knowledge technology for i
Verifiable computation is **critical to improving processing speeds on blockchains** without reducing security. Understanding this requires knowing the differences in proposed solutions for scaling Ethereum.
-[On-chain scaling solutions](/developers/docs/scaling/#on-chain-scaling), such as sharding, require extensive modification of the blockchain’s base layer. However, this approach is highly complex and errors in implementation can undermine Ethereum’s security model.
+[Onchain scaling solutions](/developers/docs/scaling/#onchain-scaling), such as sharding, require extensive modification of the blockchain’s base layer. However, this approach is highly complex and errors in implementation can undermine Ethereum’s security model.
-[Off-chain scaling solutions](/developers/docs/scaling/#off-chain-scaling) don’t require redesigning the core Ethereum protocol. Instead they rely on an outsourced computation model to improve throughput on Ethereum’s base layer.
+[Offchain scaling solutions](/developers/docs/scaling/#offchain-scaling) don’t require redesigning the core Ethereum protocol. Instead they rely on an outsourced computation model to improve throughput on Ethereum’s base layer.
Here’s how that works in practice:
@@ -68,17 +68,17 @@ Here’s how that works in practice:
- After processing transactions, the other chain returns the results to be applied to Ethereum’s state.
-The benefit here is that Ethereum doesn’t have to do any execution and only needs to apply results from outsourced computation to its state. This reduces network congestion and also improves transaction speeds (off-chain protocols optimize for faster execution).
+The benefit here is that Ethereum doesn’t have to do any execution and only needs to apply results from outsourced computation to its state. This reduces network congestion and also improves transaction speeds (offchain protocols optimize for faster execution).
-The chain needs a way to validate off-chain transactions without re-executing them, or else the value of off-chain execution is lost.
+The chain needs a way to validate offchain transactions without re-executing them, or else the value of offchain execution is lost.
-This is where verifiable computation comes into play. When a node executes a transaction outside of Ethereum, it submits a zero-knowledge proof to prove the correctness of off-chain execution. This proof (called a [validity proof](/glossary/#validity-proof)) guarantees that a transaction is valid, allowing Ethereum to apply the result to its state—without waiting for anyone to dispute it.
+This is where verifiable computation comes into play. When a node executes a transaction outside of Ethereum, it submits a zero-knowledge proof to prove the correctness of offchain execution. This proof (called a [validity proof](/glossary/#validity-proof)) guarantees that a transaction is valid, allowing Ethereum to apply the result to its state—without waiting for anyone to dispute it.
-[Zero-knowledge rollups](/developers/docs/scaling/zk-rollups) and [validiums](/developers/docs/scaling/validium/) are two off-chain scaling solutions that use validity proofs to provide secure scalability. These protocols execute thousands of transactions off-chain and submit proofs for verification on Ethereum. Those results can be applied immediately once the proof is verified, allowing Ethereum to process more transactions without increasing computation on the base layer.
+[Zero-knowledge rollups](/developers/docs/scaling/zk-rollups) and [validiums](/developers/docs/scaling/validium/) are two offchain scaling solutions that use validity proofs to provide secure scalability. These protocols execute thousands of transactions offchain and submit proofs for verification on Ethereum. Those results can be applied immediately once the proof is verified, allowing Ethereum to process more transactions without increasing computation on the base layer.
-### Reducing bribery and collusion in on-chain voting {#secure-blockchain-voting}
+### Reducing bribery and collusion in onchain voting {#secure-blockchain-voting}
-Blockchain voting schemes have many favorable characteristics: they are fully auditable, secure against attacks, resistant to censorship, and free of geographical constraints. But even on-chain voting schemes aren't immune to the problem of **collusion**.
+Blockchain voting schemes have many favorable characteristics: they are fully auditable, secure against attacks, resistant to censorship, and free of geographical constraints. But even onchain voting schemes aren't immune to the problem of **collusion**.
Defined as “coordinating to limit open competition by deceiving, defrauding, and misleading others,” collusion may take the form of a malicious actor influencing voting by offering bribes. For example, Alice might receive a bribe from Bob to vote for `option B` on a ballot even if she prefers `option A`.
@@ -86,13 +86,13 @@ Bribery and collusion limit the effectiveness of any process that uses voting as
For example, [quadratic funding mechanisms](https://www.radicalxchange.org/concepts/plural-funding/) rely on donations to measure preference for certain options among different public good projects. Each donation counts as a "vote" for a specific project, with projects that receive more votes getting more funds from the matching pool.
-Using on-chain voting makes quadratic funding susceptible to collusion: blockchain transactions are public, so bribers can inspect a bribee’s on-chain activity to see how they “voted”. This way quadratic funding ceases to be an effective means for allocating funds based on the aggregated preferences of the community.
+Using onchain voting makes quadratic funding susceptible to collusion: blockchain transactions are public, so bribers can inspect a bribee’s onchain activity to see how they “voted”. This way quadratic funding ceases to be an effective means for allocating funds based on the aggregated preferences of the community.
-Fortunately, newer solutions such as MACI (Minimum Anti-Collusion Infrastructure) are using zero-knowledge proofs to make on-chain voting (eg., quadratic funding mechanisms) resistant to bribery and collusion. MACI is a set of smart contracts and scripts that allow a central administrator (called a "coordinator") to aggregate votes and tally results _without_ revealing specifics on how each individual voted. Even so, it is still possible to verify that the votes were counted properly, or confirm that a particular individual participated in the voting round.
+Fortunately, newer solutions such as MACI (Minimum Anti-Collusion Infrastructure) are using zero-knowledge proofs to make onchain voting (eg., quadratic funding mechanisms) resistant to bribery and collusion. MACI is a set of smart contracts and scripts that allow a central administrator (called a "coordinator") to aggregate votes and tally results _without_ revealing specifics on how each individual voted. Even so, it is still possible to verify that the votes were counted properly, or confirm that a particular individual participated in the voting round.
#### How does MACI work with zero-knowledge proofs? {#how-maci-works-with-zk-proofs}
-At the start, the coordinator deploys the MACI contract on Ethereum, after which users can sign up for voting (by registering their public key in the smart contract). Users cast votes by sending messages encrypted with their public key to the smart contract (a valid vote must be signed with the most recent public key associated with the user's identity, among other criteria). Afterward, the coordinator processes all messages once the voting period ends, tallies the votes, and verifies the results on-chain.
+At the start, the coordinator deploys the MACI contract on Ethereum, after which users can sign up for voting (by registering their public key in the smart contract). Users cast votes by sending messages encrypted with their public key to the smart contract (a valid vote must be signed with the most recent public key associated with the user's identity, among other criteria). Afterward, the coordinator processes all messages once the voting period ends, tallies the votes, and verifies the results onchain.
In MACI, zero-knowledge proofs are used to ensure correctness of computation by making it impossible for the coordinator to incorrectly process votes and tally results. This is achieved by requiring the coordinator to generate ZK-SNARK proofs verifying that a) all messages were processed correctly b) the final result corresponds to the sum of all _valid_ votes.
@@ -104,11 +104,11 @@ Thus, even without sharing a breakdown of votes per user (as is usually the case
- Alice secretly sends an encrypted transaction to change the public key associated with her identity.
- Alice sends another (encrypted) message to the smart contract voting for `option A` using the new public key.
- Alice shows Bob a transaction which shows she voted for `option B` (which is invalid since the public key is no longer associated with Alice's identity in the system)
-- While processing messages, the coordinator skips Alice's vote for `option B` and counts only the vote for `option A`. Hence, Bob's attempt to collude with Alice and manipulate the on-chain vote fails.
+- While processing messages, the coordinator skips Alice's vote for `option B` and counts only the vote for `option A`. Hence, Bob's attempt to collude with Alice and manipulate the onchain vote fails.
Using MACI _does_ require trusting the coordinator not to collude with bribers or attempt to bribe voters themselves. The coordinator can decrypt user messages (necessary for creating the proof), so they can accurately verify how each person voted.
-But in cases where the coordinator remains honest, MACI represents a powerful tool for guaranteeing the sanctity of on-chain voting. This explains its popularity among quadratic funding applications (e.g., [clr.fund](https://clr.fund/#/about/maci)) that rely heavily on the integrity of each individual's voting choices.
+But in cases where the coordinator remains honest, MACI represents a powerful tool for guaranteeing the sanctity of onchain voting. This explains its popularity among quadratic funding applications (e.g., [clr.fund](https://clr.fund/#/about/maci)) that rely heavily on the integrity of each individual's voting choices.
[Learn more about MACI](https://privacy-scaling-explorations.github.io/maci/).
diff --git a/public/images/network-maturity/developing.svg b/public/images/network-maturity/developing.svg
new file mode 100644
index 00000000000..1085ae950e6
--- /dev/null
+++ b/public/images/network-maturity/developing.svg
@@ -0,0 +1,12 @@
+
diff --git a/public/images/network-maturity/emerging.svg b/public/images/network-maturity/emerging.svg
new file mode 100644
index 00000000000..fa3554c02bc
--- /dev/null
+++ b/public/images/network-maturity/emerging.svg
@@ -0,0 +1,15 @@
+
diff --git a/public/images/network-maturity/maturing.svg b/public/images/network-maturity/maturing.svg
new file mode 100644
index 00000000000..0a140c29b03
--- /dev/null
+++ b/public/images/network-maturity/maturing.svg
@@ -0,0 +1,20 @@
+
diff --git a/public/images/network-maturity/robust.svg b/public/images/network-maturity/robust.svg
new file mode 100644
index 00000000000..68e0e989d3d
--- /dev/null
+++ b/public/images/network-maturity/robust.svg
@@ -0,0 +1,28 @@
+
diff --git a/src/@chakra-ui/components/Accordion.ts b/src/@chakra-ui/components/Accordion.ts
deleted file mode 100644
index f69674790a8..00000000000
--- a/src/@chakra-ui/components/Accordion.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import { accordionAnatomy } from "@chakra-ui/anatomy"
-import { createMultiStyleConfigHelpers } from "@chakra-ui/react"
-
-const { defineMultiStyleConfig, definePartsStyle } =
- createMultiStyleConfigHelpers(accordionAnatomy.keys)
-
-const baseStyle = definePartsStyle({
- container: {
- "& > :is(h2, h3)": {
- fontSize: "initial",
- fontWeight: "initial",
- },
- },
- button: {
- py: "2",
- px: { base: "2", md: "4" },
- gap: "2",
- _hover: { bg: "background.highlight", color: "primary.hover" },
- _focusVisible: {
- outline: "4px solid",
- outlineColor: "primary.hover",
- outlineOffset: -1,
- bg: "background.highlight",
- color: "primary.hover",
- borderRadius: "base",
- },
- _expanded: {
- bg: "background.highlight",
- color: "primary.highContrast",
- svg: { transform: "rotate(180deg)" },
- },
- },
- panel: {
- mt: "2",
- p: { base: 2, md: 4 },
- fontSize: "sm",
- },
- icon: {
- fontSize: "2xl",
- transform: "rotate(270deg)",
- },
-})
-
-export const Accordion = defineMultiStyleConfig({
- baseStyle,
-})
diff --git a/src/@chakra-ui/components/Avatar.ts b/src/@chakra-ui/components/Avatar.ts
deleted file mode 100644
index a38b1fed150..00000000000
--- a/src/@chakra-ui/components/Avatar.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-import pick from "lodash/pick"
-import { avatarAnatomy } from "@chakra-ui/anatomy"
-import {
- createMultiStyleConfigHelpers,
- cssVar,
- defineStyle,
- getToken,
-} from "@chakra-ui/react"
-
-import { avatarDefaultTheme, defineMergeStyles } from "./components.utils"
-
-const { defineMultiStyleConfig, definePartsStyle } =
- createMultiStyleConfigHelpers(avatarAnatomy.keys)
-
-const { baseStyle: defaultBaseStyle, sizes: defaultSizes } = avatarDefaultTheme
-
-const $border = cssVar("avatar-border-color", "transparent")
-const $mlBySize = cssVar("ml-by-size")
-
-const baseStyleContainer = defineStyle((props) => {
- const primaryLowContrast = getToken(
- "colors",
- "primary.lowContrast"
- )(props.theme)
-
- return defineMergeStyles(defaultBaseStyle?.(props).container, {
- [$border.variable]: "transparent",
- borderWidth: "1px",
- "&:hover, [data-peer]:hover ~ &": {
- boxShadow: `0.15em 0.15em 0 ${primaryLowContrast}`,
- },
- _focus: {
- outline: "4px solid",
- outlineColor: "primary.hover",
- outlineOffset: "-1px",
- },
- _active: {
- [$border.variable]: "colors.primary.hover",
- boxShadow: "none",
- "& img": {
- opacity: 0.7,
- },
- },
- "[role='group'] &": {
- [$border.variable]: "colors.background.base",
- _notLast: {
- ms: $mlBySize.reference,
- },
- },
- })
-})
-
-const baseStyleExessLabel = defineStyle((props) =>
- defineMergeStyles(defaultBaseStyle?.(props).excessLabel, {
- bg: "body.base",
- color: "background.base",
- ms: $mlBySize.reference,
- })
-)
-
-const baseStyle = definePartsStyle((props) => ({
- container: baseStyleContainer(props),
- excessLabel: baseStyleExessLabel(props),
-}))
-
-const USED_SIZES = ["xs", "sm", "md", "lg"] as const
-
-const pickedDefaultSizes: { [k in (typeof USED_SIZES)[number]]?: object } =
- pick(defaultSizes, ...USED_SIZES)
-
-const sizes = defineMergeStyles(pickedDefaultSizes, {
- xs: {
- group: {
- [$mlBySize.variable]: "space.-1",
- },
- excessLabel: {
- fontSize: "0.563rem",
- },
- },
- sm: {
- group: {
- [$mlBySize.variable]: "space.-2",
- },
- excessLabel: {
- fontSize: "sm",
- },
- },
-})
-
-export const Avatar = defineMultiStyleConfig({
- baseStyle,
- // @ts-expect-error incompatible type shapes
- sizes,
-})
diff --git a/src/@chakra-ui/components/Badge.ts b/src/@chakra-ui/components/Badge.ts
deleted file mode 100644
index 7d181350e19..00000000000
--- a/src/@chakra-ui/components/Badge.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import { defineStyle, defineStyleConfig } from "@chakra-ui/react"
-
-import { badgeDefaultTheme, defineMergeStyles } from "./components.utils"
-
-const { baseStyle: defaultBaseStyle } = badgeDefaultTheme
-
-const baseStyle = defineMergeStyles(defaultBaseStyle, {
- borderRadius: "base",
- border: "1px solid",
- borderColor: "transparent",
- fontWeight: "initial",
- py: 1,
- px: 2,
- lineHeight: "1.6rem",
- textTransform: "uppercase",
-})
-
-const COLOR_SCHEME_MAP = {
- purple: {
- color: "black300",
- background: "primary100",
- borderColor: "primary100",
- },
- orange: {
- color: "text",
- background: "orange.100",
- borderColor: "orange.100",
- },
- green: {
- color: "white",
- background: "green.500",
- borderColor: "green.500",
- },
- blue: {
- color: "black",
- background: "blue.300",
- borderColor: "blue.300",
- },
- red: {
- color: "white",
- background: "red.500",
- borderColor: "red.500",
- },
- pink: {
- color: "black",
- background: "red.100",
- borderColor: "red.100",
- },
- gray: {
- color: "black",
- background: "gray.300",
- borderColor: "gray.300",
- },
-}
-
-const variantSecondary = defineStyle(({ colorScheme: c = "orange" }) => ({
- ...COLOR_SCHEME_MAP[c],
- background: "transparent",
-}))
-
-const variantSolid = defineStyle(({ colorScheme: c = "purple" }) => ({
- ...COLOR_SCHEME_MAP[c],
- borderColor: "transparent",
-}))
-
-export const Badge = defineStyleConfig({
- baseStyle,
- variants: {
- solid: variantSolid,
- secondary: variantSecondary,
- },
- sizes: {
- sm: {
- py: 0,
- },
- lg: {
- px: 3,
- },
- },
- defaultProps: {
- variant: "solid",
- },
-})
diff --git a/src/@chakra-ui/components/Breadcrumb.ts b/src/@chakra-ui/components/Breadcrumb.ts
deleted file mode 100644
index cf190a23312..00000000000
--- a/src/@chakra-ui/components/Breadcrumb.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import { breadcrumbAnatomy } from "@chakra-ui/anatomy"
-import { createMultiStyleConfigHelpers } from "@chakra-ui/react"
-
-import { breadcrumbDefaultTheme, defineMergeStyles } from "./components.utils"
-
-const { defineMultiStyleConfig } = createMultiStyleConfigHelpers(
- breadcrumbAnatomy.keys
-)
-
-const baseStyle = defineMergeStyles(breadcrumbDefaultTheme.baseStyle, {
- list: {
- m: 0,
- lineHeight: "base",
- flexWrap: "wrap",
- },
- item: {
- color: "body.medium",
- letterSpacing: "wider",
- m: 0,
- },
- link: {
- fontWeight: "normal",
- _hover: {
- color: "primary.base",
- textDecor: "none",
- },
- _active: {
- color: "primary.base",
- },
- /*
- * `&[aria-current="page"]`
- * Redundancy to ensure styling on the active
- * link is applied.
- */
- _activeLink: {
- color: "primary.base",
- },
- },
- separator: {
- mx: "2.5",
- },
-})
-
-export const Breadcrumb = defineMultiStyleConfig({
- baseStyle,
-})
diff --git a/src/@chakra-ui/components/Button.ts b/src/@chakra-ui/components/Button.ts
deleted file mode 100644
index 5d46960d242..00000000000
--- a/src/@chakra-ui/components/Button.ts
+++ /dev/null
@@ -1,131 +0,0 @@
-import { defineStyle, defineStyleConfig } from "@chakra-ui/react"
-
-/**
- * This selector over the more specific `& .chakra-button__icon` accounts
- * for icons used both as a singleton (in IconButton) and as aside element
- * with text. The mention classname is not used for the singleton.
- *
- * And because the icons `fontSize` is different than the text, the icon size
- * needs to stay the same when a singleton.
- */
-const ICON_SELECTOR = "& svg"
-
-const baseStyle = defineStyle({
- // Sizing and positioning classes:
- borderRadius: "base",
- border: "1px",
- fontWeight: "normal",
- lineHeight: "1.6",
- transitionProperty: "common",
- transitionDuration: "normal",
- whiteSpace: "normal",
- p: "unset",
- // Base default styling is "outline" pattern, primary color for text, border matches, no bg
- borderColor: "currentColor",
- color: "primary.base",
- // Hover: Default hover adds box-shadow, text (border) to --primary-hover
- _hover: {
- color: "primary.hover",
- boxShadow: "buttonHover",
- },
- // Focus: Add 4px outline to all buttons, --primary-hover
- _focusVisible: {
- outline: "4px solid",
- outlineColor: "primary.hover",
- outlineOffset: -1,
- },
- // Active: text (border) to --primary-hover instead of primary, hide shadow
- _active: {
- color: "primary.hover",
- boxShadow: "none",
- },
- // Disabled: Pointer events none, text (border) to --disabled
- _disabled: {
- color: "disabled",
- pointerEvents: "none",
- },
- // isSecondary: Switch text (border) to --body instead of --primary
- "&[data-secondary='true']": {
- color: "body.base",
- },
- "&.chakra-link": {
- textDecoration: "none",
- _hover: {
- textDecoration: "none",
- },
- },
- [ICON_SELECTOR]: {
- flexShrink: 0,
- },
-})
-
-const variantSolid = defineStyle({
- color: "white",
- bg: "primary.action",
- borderColor: "transparent !important",
- _hover: {
- color: "white !important",
- bg: "primary.actionHover",
- },
- _active: {
- bg: "primary.actionHover",
- },
- _disabled: {
- bg: "disabled",
- color: "background.base",
- },
-})
-
-const variantOutline = defineStyle({}) // "outline" is base styling above
-
-const variantGhost = {
- borderColor: "transparent",
- _hover: { shadow: "none" },
-}
-
-const variantLink = defineStyle({
- borderColor: "transparent",
- // fontWeight: 700, // TODO: Not in DS; confirm then remove
- _hover: { shadow: "none" },
- textDecor: "underline",
- py: 0,
- px: 1,
- _active: {
- color: "primary.base",
- },
-})
-
-const sizes = {
- md: defineStyle({
- py: "2",
- px: "4",
- [ICON_SELECTOR]: {
- fontSize: "2xl",
- },
- }),
- sm: defineStyle({
- fontSize: "xs",
- py: "1.5",
- px: "2",
- [ICON_SELECTOR]: {
- fontSize: "md",
- },
- }),
-}
-
-const variants = {
- solid: variantSolid,
- outline: variantOutline,
- ghost: variantGhost,
- link: variantLink,
-}
-
-export const Button = defineStyleConfig({
- baseStyle,
- sizes,
- variants,
- defaultProps: {
- size: "md",
- variant: "solid",
- },
-})
diff --git a/src/@chakra-ui/components/Checkbox.ts b/src/@chakra-ui/components/Checkbox.ts
deleted file mode 100644
index 5ea15c84ec2..00000000000
--- a/src/@chakra-ui/components/Checkbox.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import { checkboxAnatomy } from "@chakra-ui/anatomy"
-import { createMultiStyleConfigHelpers, defineStyle } from "@chakra-ui/react"
-
-import {
- checkboxDefaultTheme,
- commonInputTriggerStyles,
- defineMergeStyles,
-} from "./components.utils"
-
-const { sizes: defaultSizes } = checkboxDefaultTheme
-
-const { definePartsStyle, defineMultiStyleConfig } =
- createMultiStyleConfigHelpers(checkboxAnatomy.keys)
-
-const { commonContainerProps, commonControlProps, commonLabelProps } =
- commonInputTriggerStyles
-
-const checkboxMdSize = defaultSizes?.md
-
-const baseStyleControl = defineMergeStyles(
- checkboxMdSize?.control,
- commonControlProps,
- {
- boxSize: "var(--checkbox-size)", // Comes from default theme
- borderRadius: "sm",
- }
-)
-
-const baseStyleLabel = defineStyle({ ...commonLabelProps })
-
-const baseStyleContainer = defineStyle({ ...commonContainerProps })
-
-const baseStyleIcon = defineStyle({
- boxSize: 2,
-})
-
-const baseStyle = definePartsStyle({
- container: baseStyleContainer,
- control: baseStyleControl,
- label: baseStyleLabel,
- icon: baseStyleIcon,
-})
-
-export const Checkbox = defineMultiStyleConfig({
- baseStyle,
-})
diff --git a/src/@chakra-ui/components/Heading.ts b/src/@chakra-ui/components/Heading.ts
deleted file mode 100644
index 475d3190003..00000000000
--- a/src/@chakra-ui/components/Heading.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import { defineStyleConfig } from "@chakra-ui/react"
-
-import { headingDefaultTheme } from "./components.utils"
-
-const HEADING_SIZES = ["2xl", "xl", "lg", "md", "sm", "xs"] as const
-
-type SCALE_VALUE = string | [string, null, null, string]
-
-type SIZE_SCALE = { [key in (typeof HEADING_SIZES)[number]]: SCALE_VALUE }
-
-const lineHeightScale: SIZE_SCALE = {
- "2xl": "4xs",
- xl: ["2xs", null, null, "4xs"],
- lg: "2xs",
- md: ["xs", null, null, "2xs"],
- sm: ["base", null, null, "xs"],
- xs: "base",
-}
-
-const fontSizeScale: SIZE_SCALE = {
- "2xl": ["4xl", null, null, "5xl"],
- xl: ["3xl", null, null, "4xl"],
- lg: ["2xl", null, null, "3xl"],
- md: ["xl", null, null, "2xl"],
- sm: ["md", null, null, "xl"],
- xs: ["sm", null, null, "md"],
-}
-
-const sizes = HEADING_SIZES.reduce<{
- [key: string]: { fontSize: SCALE_VALUE; lineHeight: SCALE_VALUE }
-}>((obj, key) => {
- return {
- ...obj,
- [key]: {
- fontSize: fontSizeScale[key],
- lineHeight: lineHeightScale[key],
- },
- }
-}, {})
-
-export const Heading = defineStyleConfig({
- ...headingDefaultTheme,
- sizes,
-})
diff --git a/src/@chakra-ui/components/Input.ts b/src/@chakra-ui/components/Input.ts
deleted file mode 100644
index af894eb6701..00000000000
--- a/src/@chakra-ui/components/Input.ts
+++ /dev/null
@@ -1,121 +0,0 @@
-import { inputAnatomy } from "@chakra-ui/anatomy"
-import { cssVar } from "@chakra-ui/react"
-import {
- createMultiStyleConfigHelpers,
- defineStyle,
-} from "@chakra-ui/styled-system"
-
-import { defineMergeStyles, inputDefaultTheme } from "./components.utils"
-
-const { defineMultiStyleConfig, definePartsStyle } =
- createMultiStyleConfigHelpers(inputAnatomy.keys)
-
-// From the default theme
-const $height = cssVar("input-height")
-
-const baseStyle = definePartsStyle((props) => {
- const {
- focusBorderColor: fc = "primaryHover",
- errorBorderColor: ec = "errorOutline",
- } = props
-
- return defineMergeStyles(
- inputDefaultTheme.baseStyle,
- inputDefaultTheme.variants?.outline(props),
- {
- field: {
- borderRadius: "base",
- outline: "3px solid transparent",
- lineHeight: 1,
- px: "2",
- _placeholder: {
- color: "disabled",
- opacity: 1,
- },
- _focusVisible: {
- outlineColor: fc,
- outlineOffset: "-1px",
- borderColor: "transparent",
- boxShadow: "none",
- },
- _hover: null, // override default
- _invalid: {
- borderColor: ec,
- boxShadow: "none",
- },
- _disabled: {
- borderColor: "disabled",
- opacity: 1,
- },
- "&:not(:disabled)": {
- borderColor: "body.base",
- _active: {
- bg: "background.highlight",
- borderColor: "primary.highContrast",
- },
- "[data-group] &:hover, &:hover": {
- borderColor: "primary.hover",
- },
- },
- },
- element: {
- fontSize: "2xl",
- transitionProperty: "common",
- transitionDuration: "normal",
- _groupHover: {
- color: "primary.hover",
- },
- _peerFocusVisible: {
- color: fc,
- _peerInvalid: {
- color: ec,
- },
- _peerDisabled: {
- color: "disabled",
- },
- },
- _peerDisabled: {
- color: "disabled",
- },
- "[data-peer]:not(:disabled):active ~ &": {
- color: "primary.dark",
- _dark: {
- color: "primary.highContrast",
- },
- },
- },
- }
- )
-})
-
-const size = {
- md: defineStyle({
- [$height.variable]: "sizes.10.5",
- }),
- sm: defineStyle({
- [$height.variable]: "sizes.8",
- }),
-}
-
-const sizes = {
- md: definePartsStyle({
- field: size.md,
- element: size.md,
- }),
- sm: definePartsStyle({
- field: { ...size.sm, fontSize: "sm" },
- element: {
- ...size.sm,
- fontSize: "xl",
- },
- }),
-}
-
-export const Input = defineMultiStyleConfig({
- baseStyle,
- sizes,
- defaultProps: {
- variant: "outline",
- size: "md",
- },
-})
diff --git a/src/@chakra-ui/components/Link.ts b/src/@chakra-ui/components/Link.ts
deleted file mode 100644
index fd626ffa08f..00000000000
--- a/src/@chakra-ui/components/Link.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { defineStyleConfig } from "@chakra-ui/react"
-
-import { defineMergeStyles, linkDefaultTheme } from "./components.utils"
-import { Text } from "./Text"
-
-export const Link = defineStyleConfig({
- baseStyle: defineMergeStyles(linkDefaultTheme.baseStyle, {
- color: "primary.base",
- textDecor: "underline",
- textUnderlineOffset: "3px",
- _focusVisible: {
- boxShadow: "none",
- outline: "2px solid",
- outlineColor: "primary.hover",
- outlineOffset: "2px",
- borderRadius: "sm",
- },
- _hover: {
- color: "primary.hover",
- },
- "&[data-inline-link]": {
- _visited: {
- color: "primary.visited",
- },
- },
- }),
- sizes: Text.sizes,
-})
diff --git a/src/@chakra-ui/components/Modal.ts b/src/@chakra-ui/components/Modal.ts
deleted file mode 100644
index 6575ff295f3..00000000000
--- a/src/@chakra-ui/components/Modal.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-import { modalAnatomy } from "@chakra-ui/anatomy"
-import { createMultiStyleConfigHelpers } from "@chakra-ui/react"
-
-import { defineMergeStyles, modalDefaultTheme } from "./components.utils"
-
-const { defineMultiStyleConfig, definePartsStyle } =
- createMultiStyleConfigHelpers(modalAnatomy.keys)
-
-const {
- baseStyle: defaultBaseStyle,
- sizes: defaultSizes,
- defaultProps,
-} = modalDefaultTheme
-
-export const Modal = defineMultiStyleConfig({
- baseStyle: definePartsStyle((props) =>
- defineMergeStyles(defaultBaseStyle?.(props), {
- dialog: {
- bg: "background.base",
- gap: "4",
- padding: { base: "4", sm: "8" },
- borderRadius: "base",
- boxShadow: "none",
- },
- header: {
- flex: "1",
- padding: "0",
- fontWeight: "bold",
- fontSize: "2xl",
- me: "8",
- },
- closeButton: {
- position: "static",
- color: "body.base",
- bg: "background.base",
- },
- body: {
- padding: "0",
- fontWeight: "normal",
- fontSize: "md",
- },
- footer: {
- gap: "2",
- px: "0",
- pt: "8",
- pb: "0",
- },
- })
- ),
- sizes: {
- ...defaultSizes,
- full: definePartsStyle((props) => ({
- dialogContainer: {
- alignItems: { base: "flex-start", md: "center" },
- },
- dialog: {
- padding: { base: "4", sm: "8", md: "16" },
- my: { base: "4", md: props.isCentered ? "auto" : "4" },
- mx: "4",
- minH: {
- base: "calc(100vh - 2rem)",
- md: "min(100vh, 792px)",
- },
- maxW: {
- base: "calc(100vw - 2rem)",
- md: "min(100vw, 1000px)",
- },
- },
- })),
- },
-
- defaultProps: {
- ...defaultProps,
- variant: undefined,
- },
-})
diff --git a/src/@chakra-ui/components/Popover.ts b/src/@chakra-ui/components/Popover.ts
deleted file mode 100644
index d5113100f27..00000000000
--- a/src/@chakra-ui/components/Popover.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { popoverAnatomy as parts } from "@chakra-ui/anatomy"
-import { cssVar } from "@chakra-ui/react"
-import { createMultiStyleConfigHelpers } from "@chakra-ui/styled-system"
-
-import { defineMergeStyles, popoverDefaultTheme } from "./components.utils"
-
-const { definePartsStyle, defineMultiStyleConfig } =
- createMultiStyleConfigHelpers(parts.keys)
-
-const {
- baseStyle: defaultBaseStyle,
- sizes: defaultSizes,
- defaultProps,
-} = popoverDefaultTheme
-
-const $arrowBg = cssVar("popper-arrow-bg")
-const $arrowSize = cssVar("popper-arrow-size")
-const $arrowShadowColor = cssVar("popper-arrow-shadow-color")
-
-const baseStyle = definePartsStyle(
- defineMergeStyles(defaultBaseStyle, {
- popper: {
- borderRadius: "base",
- zIndex: "popover",
- },
- content: {
- [$arrowSize.variable]: "8px",
- p: 2,
- bg: "background.highlight",
- borderRadius: "base",
- boxShadow: `0px 0px 16px 0px #00000040`,
- fontSize: "sm",
- border: "none",
- minWidth: "48", // 12rem
- maxWidth: "xs", // 20rem
- lineHeight: "base",
- w: "auto",
- _focusVisible: {
- boxShadow: "none",
- },
- },
- body: {
- color: "body.base",
- fontWeight: "normal",
- textTransform: "none",
- },
- header: {
- border: "none",
- },
- arrow: {
- [$arrowBg.variable]: "colors.background.highlight",
- [$arrowShadowColor.variable]: "colors.background.highlight",
- border: "none",
- },
- })
-)
-
-export const Popover = defineMultiStyleConfig({
- baseStyle,
- sizes: defaultSizes,
- defaultProps: {
- ...defaultProps,
- variant: undefined,
- },
-})
diff --git a/src/@chakra-ui/components/Progress.ts b/src/@chakra-ui/components/Progress.ts
deleted file mode 100644
index fca025bf4a2..00000000000
--- a/src/@chakra-ui/components/Progress.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import { progressAnatomy as parts } from "@chakra-ui/anatomy"
-import { defineStyleConfig } from "@chakra-ui/react"
-import { createMultiStyleConfigHelpers } from "@chakra-ui/styled-system"
-
-const { definePartsStyle } = createMultiStyleConfigHelpers(parts.keys)
-
-const baseStyle = definePartsStyle(() => ({
- track: {
- bg: "primary.light",
- // `borderRadius` applies to both track and `filledTrack` (https://github.com/chakra-ui/chakra-ui/pull/2946)
- borderRadius: "full",
- },
- filledTrack: {
- bgColor: "primary.base",
- },
-}))
-
-// see https://github.com/chakra-ui/chakra-ui/blob/38acfe89c5d1f1edc67bbc44e2edd38980ca3e08/packages/components/theme/src/components/progress.ts#L63
-const sizes = {
- xs: definePartsStyle({
- track: { h: "1" },
- }),
- sm: definePartsStyle({
- track: { h: "2" },
- }),
- md: definePartsStyle({
- track: { h: "2.5" },
- }),
- lg: definePartsStyle({
- track: { h: "3" },
- }),
-}
-
-export const Progress = defineStyleConfig({
- sizes,
- baseStyle,
- defaultProps: {
- size: "md",
- },
-})
diff --git a/src/@chakra-ui/components/Radio.ts b/src/@chakra-ui/components/Radio.ts
deleted file mode 100644
index de6ac57cf09..00000000000
--- a/src/@chakra-ui/components/Radio.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-import { radioAnatomy } from "@chakra-ui/anatomy"
-import {
- createMultiStyleConfigHelpers,
- cssVar,
- defineStyle,
-} from "@chakra-ui/react"
-
-import {
- commonInputTriggerStyles,
- defineMergeStyles,
- radioDefaultTheme,
-} from "./components.utils"
-
-const { defineMultiStyleConfig, definePartsStyle } =
- createMultiStyleConfigHelpers(radioAnatomy.keys)
-
-export const $radioDisableColor = cssVar("radio-disable-color")
-
-const { commonContainerProps, commonControlProps, commonLabelProps } =
- commonInputTriggerStyles
-
-const baseStyleContainer = defineStyle({ ...commonContainerProps })
-
-const baseStyleControl = defineMergeStyles(
- radioDefaultTheme.baseStyle?.({} as never).control,
- commonControlProps,
- {
- boxSize: 4,
- fontSize: "md",
- "*:hover > &": {
- outlineOffset: "-1px",
- },
- _checked: {
- _before: {
- // Force half the size, as '50%' value not reliable.
- boxSize: 2,
- },
- },
- }
-)
-
-const baseStyleLabel = defineStyle({ ...commonLabelProps })
-
-const baseStyle = definePartsStyle({
- container: baseStyleContainer,
- control: baseStyleControl,
- label: baseStyleLabel,
-})
-
-export const Radio = defineMultiStyleConfig({
- baseStyle,
-})
diff --git a/src/@chakra-ui/components/Switch.ts b/src/@chakra-ui/components/Switch.ts
deleted file mode 100644
index 69a487d178f..00000000000
--- a/src/@chakra-ui/components/Switch.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-import { switchAnatomy } from "@chakra-ui/anatomy"
-import { createMultiStyleConfigHelpers } from "@chakra-ui/react"
-
-import {
- _notDisabledReadOnly,
- commonInputTriggerStyles,
- defineMergeStyles,
- switchDefaultTheme,
-} from "./components.utils"
-
-const { defineMultiStyleConfig, definePartsStyle } =
- createMultiStyleConfigHelpers(switchAnatomy.keys)
-
-const { baseStyle: defaultBaseStyle, sizes: defaultSizes } = switchDefaultTheme
-
-const switchSmSize = defaultSizes?.sm
-
-const { commonControlProps, commonContainerProps } = commonInputTriggerStyles
-
-const baseStyleContainer = defineMergeStyles(
- defaultBaseStyle?.({} as never).container,
- switchSmSize?.container,
- commonContainerProps
-)
-
-const baseStyleThumb = defineMergeStyles(
- defaultBaseStyle?.({} as never).thumb,
- {
- bg: "background.base",
- [".chakra-switch__track:not([data-checked])[data-disabled] > &"]: {
- border: "1px",
- borderColor: "disabled",
- },
- }
-)
-
-const baseStyleTrack = defineMergeStyles(
- defaultBaseStyle?.({} as never).track,
- commonControlProps,
- {
- bg: "body.medium",
- borderColor: "transparent",
- _invalid: { borderColor: "error.outline" },
- _focusVisible: { bg: "gray.500", borderColor: "transparent" },
- ["&:not([data-checked])[data-disabled]"]: {
- bg: "transparent",
- borderColor: "disabled",
- },
- [_notDisabledReadOnly]: {
- "*[data-checked]:hover > &, *:not([data-checked]):hover > &": {
- bg: "primary.hover",
- borderColor: "transparent",
- },
- },
- }
-)
-
-const baseStyle = definePartsStyle({
- container: baseStyleContainer,
- thumb: baseStyleThumb,
- track: baseStyleTrack,
-})
-
-export const Switch = defineMultiStyleConfig({
- baseStyle,
-})
diff --git a/src/@chakra-ui/components/Table.ts b/src/@chakra-ui/components/Table.ts
deleted file mode 100644
index 4c100361ada..00000000000
--- a/src/@chakra-ui/components/Table.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import { tableAnatomy } from "@chakra-ui/anatomy"
-import {
- createMultiStyleConfigHelpers,
- cssVar,
- defineStyle,
-} from "@chakra-ui/react"
-
-import { defineMergeStyles, tableDefaultTheme } from "./components.utils"
-
-const { defineMultiStyleConfig, definePartsStyle } =
- createMultiStyleConfigHelpers(tableAnatomy.keys)
-
-const $bgColor = cssVar("bg-color")
-
-const cellPadding = defineStyle({
- p: 4,
-})
-
-const baseStyle = defineMergeStyles(
- tableDefaultTheme.baseStyle,
- definePartsStyle({
- table: {
- [$bgColor.variable]: "colors.background.highlight",
- },
- th: {
- borderBottom: "1px",
- borderColor: "body.base",
- color: "body.base",
- textTransform: "none",
- verticalAlign: "bottom",
- ...cellPadding,
- },
- tr: {
- "th, td": {
- _notLast: {
- borderInlineEnd: "2px",
- borderInlineEndColor: "background.base",
- },
- },
- },
- td: {
- ...cellPadding,
- },
- tbody: {
- tr: {
- verticalAlign: "top",
- _hover: {
- /**
- * Override specificity when hovering
- * over even rows in 'striped' variant.
- */
- bg: $bgColor.reference,
- },
- },
- },
- })
-)
-
-const variantMinimalStriped = definePartsStyle({
- tbody: {
- tr: {
- _even: {
- bg: $bgColor.reference,
- },
- },
- },
-})
-
-const variantSimpleStriped = definePartsStyle({
- ...variantMinimalStriped,
- thead: {
- bg: $bgColor.reference,
- },
-})
-
-const variantSimple = definePartsStyle({
- thead: {
- bg: $bgColor.reference,
- },
-})
-
-export const Table = defineMultiStyleConfig({
- baseStyle,
- variants: {
- minimal: {},
- "minimal-striped": variantMinimalStriped,
- simple: variantSimple,
- "simple-striped": variantSimpleStriped,
- },
- defaultProps: {
- variant: "simple",
- },
-})
diff --git a/src/@chakra-ui/components/Tabs.ts b/src/@chakra-ui/components/Tabs.ts
deleted file mode 100644
index d8fce5f22be..00000000000
--- a/src/@chakra-ui/components/Tabs.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import { tabsAnatomy } from "@chakra-ui/anatomy"
-import { createMultiStyleConfigHelpers } from "@chakra-ui/react"
-
-import { tabsDefaultTheme } from "./components.utils"
-
-const { baseStyle, sizes, defaultProps } = tabsDefaultTheme
-
-const { definePartsStyle, defineMultiStyleConfig } =
- createMultiStyleConfigHelpers(tabsAnatomy.keys)
-
-const variantPrimary = definePartsStyle({
- tab: {
- borderTopRadius: "0.3rem",
- borderBottom: "1px solid",
- borderBottomColor: "primary.base",
- px: 4,
- py: "0.3rem",
- _selected: {
- color: "background.base",
- bg: "primary.base",
- },
- },
- tabpanels: {
- mt: 4,
- },
- tabpanel: {
- p: 6,
- bg: "ednBackground",
- border: "1px solid",
- borderColor: "lightBorder",
- borderRadius: "lg",
- },
-})
-
-export const Tabs = defineMultiStyleConfig({
- baseStyle,
- sizes,
- variants: {
- primary: variantPrimary,
- },
- defaultProps: {
- ...defaultProps,
- variant: "primary",
- },
-})
diff --git a/src/@chakra-ui/components/Tag/index.ts b/src/@chakra-ui/components/Tag/index.ts
deleted file mode 100644
index 6fba1cf53a1..00000000000
--- a/src/@chakra-ui/components/Tag/index.ts
+++ /dev/null
@@ -1,155 +0,0 @@
-import { tagAnatomy } from "@chakra-ui/anatomy"
-import {
- createMultiStyleConfigHelpers,
- defineStyle,
- theme,
-} from "@chakra-ui/react"
-
-import { defineMergeStyles } from "../components.utils"
-
-import { $badgeBg, $badgeColor, STATUS_COLORS } from "./utils"
-
-const { definePartsStyle, defineMultiStyleConfig } =
- createMultiStyleConfigHelpers(tagAnatomy.keys)
-
-const { Tag: tagTheme } = theme.components
-
-const baseStyleContainer = defineMergeStyles(tagTheme.baseStyle?.container, {
- border: "1px",
- borderColor: "transparent",
- boxSizing: "border-box",
- gap: 1,
- borderRadius: "full",
- px: 2,
- py: 0.5,
- minH: 8,
- fontWeight: 300,
- "&:any-link": {
- textDecor: "none",
- _focusWithin: {
- outline: "4px solid",
- outlineColor: "transparent",
- outlineOffset: 0,
- },
- },
-})
-
-const baseStyleLabel = defineStyle({
- ...tagTheme.baseStyle?.label,
- fontSize: "xs",
- textTransform: "uppercase",
- textAlign: "center",
- lineHeight: 1.6,
-})
-
-const baseStyleCloseButton = defineStyle({
- ...tagTheme.baseStyle?.closeButton,
- opacity: 1,
- m: 0,
- // Clear default
- _focusVisible: null,
-})
-
-const baseStyle = definePartsStyle({
- container: baseStyleContainer,
- label: baseStyleLabel,
- closeButton: baseStyleCloseButton,
-})
-
-const getStatusStyles = (status: string, variant: string) => {
- const statusStyles = STATUS_COLORS[status][variant]
-
- return {
- container: statusStyles,
- }
-}
-
-const variantSubtle = definePartsStyle((props) => {
- const { status = "normal" } = props
- const defaultStyles = tagTheme.variants?.subtle(props)
- const statusStyles = getStatusStyles(status, "subtle")
- return {
- container: {
- ...defaultStyles?.container,
- // Remove default dark mode styles
- _dark: {},
- ...statusStyles.container,
- },
- closeButton: {
- "&:focus-visible, &:hover": {
- bg: "white",
- },
- },
- }
-})
-
-const variantSolid = definePartsStyle((props) => {
- const { status = "normal" } = props
- const defaultStyles = tagTheme.variants?.solid(props)
- const statusStyles = getStatusStyles(status, "solid")
- return {
- container: {
- ...defaultStyles?.container,
- // Remove default dark mode styles
- _dark: {},
- ...statusStyles.container,
- },
- closeButton: {
- "&:focus-visible, &:hover": {
- bg: "white",
- color: $badgeBg.reference,
- },
- },
- }
-})
-
-const variantOutline = definePartsStyle((props) => {
- const { status = "normal" } = props
- const defaultStyles = tagTheme.variants?.outline(props)
- const statusStyles = getStatusStyles(status, "outline")
- return {
- container: {
- ...defaultStyles?.container,
- boxShadow: "none",
- borderColor: $badgeColor.reference,
- // Remove default dark mode styles
- _dark: {},
- ...statusStyles.container,
- },
- closeButton: {
- "&:focus-visible, &:hover": {
- bg: "body.light",
- },
- },
- }
-})
-
-const variantHighContrast = definePartsStyle((props) => {
- const { status = "normal" } = props
- const defaultStyles = tagTheme.variants?.outline(props)
- const statusStyles = getStatusStyles(status, "highContrast")
- return {
- container: {
- ...defaultStyles?.container,
- boxShadow: "none",
-
- // Remove default dark mode styles
- _dark: {},
- ...statusStyles.container,
- },
- }
-})
-const variants = {
- subtle: variantSubtle,
- solid: variantSolid,
- outline: variantOutline,
- highContrast: variantHighContrast,
-}
-
-export const Tag = defineMultiStyleConfig({
- baseStyle,
- variants,
- defaultProps: {
- variant: "subtle",
- },
-})
diff --git a/src/@chakra-ui/components/Tag/utils.ts b/src/@chakra-ui/components/Tag/utils.ts
deleted file mode 100644
index d938f7bfdec..00000000000
--- a/src/@chakra-ui/components/Tag/utils.ts
+++ /dev/null
@@ -1,415 +0,0 @@
-import { cssVar } from "@chakra-ui/react"
-
-// Because the color scheme from the default theme
-// Goes through the `Badge` config, used the variables
-// created from that config.
-export const $badgeBg = cssVar("badge-bg")
-export const $badgeColor = cssVar("badge-color")
-
-export const $tagBoxshadowColor = cssVar("tag-boxshadow-color")
-
-// TODO: Can this get consolidated?
-export const STATUS_COLORS = {
- normal: {
- subtle: {
- [$badgeBg.variable]: "colors.background.highlight",
- [$badgeColor.variable]: "colors.body.medium",
- "&:any-link": {
- _hover: {
- [$badgeBg.variable]: "colors.primary.hover",
- [$badgeColor.variable]: "colors.background.base",
- [$tagBoxshadowColor.variable]: "colors.background.highlight",
- boxShadow: `2px 2px 0 ${$tagBoxshadowColor.reference}`,
- },
- _focusWithin: {
- [$badgeBg.variable]: "colors.primary.light",
- [$badgeColor.variable]: "colors.body.medium",
- outlineColor: "primary.hover",
- },
- _active: {
- [$badgeBg.variable]: "colors.primary.hover",
- [$badgeColor.variable]: "colors.primary.light",
- },
- },
- },
- solid: {
- [$badgeBg.variable]: "colors.body.medium",
- [$badgeColor.variable]: "colors.background.highlight",
- "&:any-link": {
- _hover: {
- [$badgeBg.variable]: "colors.primary.hover",
- [$badgeColor.variable]: "colors.background.base",
- [$tagBoxshadowColor.variable]: "colors.background.highlight",
- boxShadow: `2px 2px 0 ${$tagBoxshadowColor.reference}`,
- },
- _focusWithin: {
- [$badgeBg.variable]: "colors.primary.light",
- [$badgeColor.variable]: "colors.body.medium",
- outlineColor: "primary.hover",
- },
- _active: {
- [$badgeBg.variable]: "colors.primary.hover",
- [$badgeColor.variable]: "colors.primary.light",
- },
- },
- },
- outline: {
- [$badgeColor.variable]: "colors.body.medium",
- "&:any-link": {
- _hover: {
- [$badgeBg.variable]: "colors.primary.hover",
- [$badgeColor.variable]: "colors.background.base",
- bg: $badgeBg.reference,
- [$tagBoxshadowColor.variable]: "colors.background.highlight",
- boxShadow: `2px 2px 0 ${$tagBoxshadowColor.reference}`,
- borderColor: "transparent",
- },
- _focusWithin: {
- [$badgeBg.variable]: "colors.primary.light",
- [$badgeColor.variable]: "colors.body.medium",
- bg: $badgeBg.reference,
- outlineColor: "primary.hover",
- borderColor: "transparent",
- },
- _active: {
- [$badgeBg.variable]: "colors.primary.hover",
- [$badgeColor.variable]: "colors.primary.light",
- },
- },
- },
- highContrast: {
- [$badgeBg.variable]: "colors.body.light",
- [$badgeColor.variable]: "colors.body.base",
- "&:any-link": {
- _hover: {
- [$badgeBg.variable]: "colors.body.light",
- [$badgeColor.variable]: "colors.body.medium",
- [$tagBoxshadowColor.variable]: "colors.background.highlight",
- boxShadow: `2px 2px 0 ${$tagBoxshadowColor.reference}`,
- },
- _focusWithin: {
- [$badgeBg.variable]: "colors.body.light",
- [$badgeColor.variable]: "colors.body.medium",
- outlineColor: "primary.hover",
- },
- _active: {
- [$badgeBg.variable]: "colors.body.light",
- [$badgeColor.variable]: "colors.body.medium",
- },
- },
- },
- },
- tag: {
- subtle: {
- [$badgeBg.variable]: "colors.primary.light",
- [$badgeColor.variable]: "colors.primary.dark",
- "&:any-link": {
- _hover: {
- [$badgeBg.variable]: "colors.primary.hover",
- [$badgeColor.variable]: "colors.background.base",
- [$tagBoxshadowColor.variable]: "colors.primary.light",
- boxShadow: `2px 2px 0 ${$tagBoxshadowColor.reference}`,
- },
- _focusWithin: {
- [$badgeBg.variable]: "colors.primary.hover",
- [$badgeColor.variable]: "colors.background.base",
- outlineColor: "primary.base",
- },
- _active: {
- boxShadow: "none",
- },
- },
- },
- solid: {
- [$badgeBg.variable]: "colors.primary.dark",
- [$badgeColor.variable]: "colors.primary.light",
- "&:any-link": {
- _hover: {
- [$badgeBg.variable]: "colors.primary.hover",
- [$badgeColor.variable]: "colors.background.base",
- [$tagBoxshadowColor.variable]: "colors.primary.light",
- boxShadow: `2px 2px 0 ${$tagBoxshadowColor.reference}`,
- },
- _focusWithin: {
- [$badgeBg.variable]: "colors.primary.hover",
- [$badgeColor.variable]: "colors.background.base",
- outlineColor: "primary.base",
- },
- _active: {
- boxShadow: "none",
- },
- },
- },
- outline: {
- [$badgeColor.variable]: "colors.primary.highContrast",
- "&:any-link": {
- _hover: {
- [$badgeBg.variable]: "colors.primary.light",
- [$badgeColor.variable]: "colors.primary.dark",
- bg: $badgeBg.reference,
- [$tagBoxshadowColor.variable]: "colors.primary.light",
- boxShadow: `2px 2px 0 ${$tagBoxshadowColor.reference}`,
- },
- _focusWithin: {
- [$badgeBg.variable]: "colors.primary.light",
- [$badgeColor.variable]: "colors.primary.dark",
- bg: $badgeBg.reference,
- outlineColor: $badgeColor.reference,
- },
- _active: {
- boxShadow: "none",
- },
- },
- },
- highContrast: {
- [$badgeBg.variable]: "colors.background.highlight",
- [$badgeColor.variable]: "colors.primary.highContrast",
- "&:any-link": {
- _hover: {
- [$badgeBg.variable]: "colors.primary.lowContrast",
- [$badgeColor.variable]: "colors.primary.highContrast",
- [$tagBoxshadowColor.variable]: "colors.background.highlight",
- boxShadow: `2px 2px 0 ${$tagBoxshadowColor.reference}`,
- },
- _focusWithin: {
- [$badgeBg.variable]: "colors.primary.lowContrast",
- [$badgeColor.variable]: "colors.primary.highContrast",
- outlineColor: "colors.primary.highContrast",
- },
- _active: {
- [$badgeBg.variable]: "colors.primary.lowContrast",
- [$badgeColor.variable]: "colors.primary.highContrast",
- },
- },
- },
- },
- success: {
- subtle: {
- [$badgeBg.variable]: "colors.success.light",
- [$badgeColor.variable]: "colors.success.base",
- "&:any-link": {
- _hover: {
- boxShadow: `2px 2px 0 ${$badgeColor.reference}`,
- },
- _focusWithin: {
- outlineColor: $badgeColor.reference,
- },
- _active: {
- boxShadow: "none",
- },
- },
- },
- solid: {
- [$badgeBg.variable]: "colors.success.base",
- [$badgeColor.variable]: "colors.success.light",
- "&:any-link": {
- _hover: {
- [$badgeBg.variable]: "colors.success.light",
- [$badgeColor.variable]: "colors.success.base",
- boxShadow: `2px 2px 0 ${$badgeColor.reference}`,
- },
- _focusWithin: {
- [$badgeBg.variable]: "colors.success.light",
- [$badgeColor.variable]: "colors.success.base",
- outlineColor: $badgeColor.reference,
- },
- _active: {
- [$badgeBg.variable]: "colors.success.light",
- [$badgeColor.variable]: "colors.success.base",
- boxShadow: "none",
- },
- },
- },
- outline: {
- [$badgeColor.variable]: "colors.success.outline",
- "&:any-link": {
- _hover: {
- [$badgeBg.variable]: "colors.success.light",
- [$badgeColor.variable]: "colors.success.base",
- boxShadow: `2px 2px 0 ${$badgeColor.reference}`,
- bg: $badgeBg.reference,
- },
- _focusWithin: {
- [$badgeBg.variable]: "colors.success.light",
- [$badgeColor.variable]: "colors.success.base",
- bg: $badgeBg.reference,
- outlineColor: $badgeColor.reference,
- },
- _active: {
- [$badgeBg.variable]: "colors.success.light",
- [$badgeColor.variable]: "colors.success.base",
- bg: $badgeBg.reference,
- boxShadow: "none",
- },
- },
- },
- highContrast: {
- [$badgeBg.variable]: "colors.success.light",
- [$badgeColor.variable]: "colors.success.base",
- "&:any-link": {
- _hover: {
- [$badgeBg.variable]: "colors.success.light",
- [$badgeColor.variable]: "colors.success.base",
- boxShadow: `2px 2px 0 ${$badgeColor.reference}`,
- },
- _focusWithin: {
- [$badgeBg.variable]: "colors.success.light",
- [$badgeColor.variable]: "colors.success.base",
- outlineColor: $badgeColor.reference,
- },
- _active: {
- [$badgeBg.variable]: "colors.success.light",
- [$badgeColor.variable]: "colors.success.base",
- boxShadow: "none",
- },
- },
- },
- },
- error: {
- subtle: {
- [$badgeBg.variable]: "colors.error.light",
- [$badgeColor.variable]: "colors.error.base",
- "&:any-link": {
- _hover: {
- boxShadow: `2px 2px 0 ${$badgeColor.reference}`,
- },
- _focusWithin: {
- outlineColor: $badgeColor.reference,
- },
- _active: {
- boxShadow: "none",
- },
- },
- },
- solid: {
- [$badgeBg.variable]: "colors.error.base",
- [$badgeColor.variable]: "colors.error.light",
- "&:any-link": {
- _hover: {
- [$badgeBg.variable]: "colors.error.light",
- [$badgeColor.variable]: "colors.error.base",
- boxShadow: `2px 2px 0 ${$badgeColor.reference}`,
- },
- _focusWithin: {
- [$badgeBg.variable]: "colors.error.light",
- [$badgeColor.variable]: "colors.error.base",
- outlineColor: $badgeColor.reference,
- },
- _active: {
- boxShadow: "none",
- },
- },
- },
- outline: {
- [$badgeColor.variable]: "colors.error.outline",
- "&:any-link": {
- _hover: {
- [$badgeBg.variable]: "colors.error.light",
- [$badgeColor.variable]: "colors.error.base",
- bg: $badgeBg.reference,
- boxShadow: `2px 2px 0 ${$badgeColor.reference}`,
- },
- _focusWithin: {
- [$badgeBg.variable]: "colors.error.light",
- [$badgeColor.variable]: "colors.error.base",
- bg: $badgeBg.reference,
- outlineColor: $badgeColor.reference,
- },
- _active: {
- boxShadow: "none",
- },
- },
- },
-
- highContrast: {
- [$badgeBg.variable]: "colors.error.light",
- [$badgeColor.variable]: "colors.error.base",
- "&:any-link": {
- _hover: {
- boxShadow: `2px 2px 0 ${$badgeColor.reference}`,
- },
- _focusWithin: {
- outlineColor: $badgeColor.reference,
- },
- _active: {
- boxShadow: "none",
- },
- },
- },
- },
- warning: {
- subtle: {
- [$badgeBg.variable]: "colors.attention.light",
- [$badgeColor.variable]: "colors.attention.base",
- "&:any-link": {
- _hover: {
- [$tagBoxshadowColor.variable]: "colors.attention.base",
- boxShadow: `2px 2px 0 ${$tagBoxshadowColor.reference}`,
- },
- _focusWithin: {
- outlineColor: $badgeColor.reference,
- },
- _active: {
- boxShadow: "none",
- },
- },
- },
- solid: {
- [$badgeBg.variable]: "colors.attention.base",
- [$badgeColor.variable]: "white",
- "&:any-link": {
- _hover: {
- [$badgeBg.variable]: "colors.attention.light",
- [$badgeColor.variable]: "colors.attention.base",
- [$tagBoxshadowColor.variable]: "colors.attention.base",
- boxShadow: `2px 2px 0 ${$tagBoxshadowColor.reference}`,
- },
- _focusWithin: {
- [$badgeBg.variable]: "colors.attention.light",
- [$badgeColor.variable]: "colors.attention.base",
- outlineColor: $badgeColor.reference,
- },
- _active: {
- boxShadow: "none",
- },
- },
- },
- outline: {
- [$badgeColor.variable]: "colors.attention.outline",
- "&:any-link": {
- _hover: {
- [$badgeBg.variable]: "colors.attention.light",
- [$badgeColor.variable]: "colors.attention.base",
- [$tagBoxshadowColor.variable]: "colors.attention.base",
- bg: $badgeBg.reference,
- boxShadow: `2px 2px 0 ${$tagBoxshadowColor.reference}`,
- },
- _focusWithin: {
- [$badgeBg.variable]: "colors.attention.light",
- [$badgeColor.variable]: "colors.attention.base",
- bg: $badgeBg.reference,
- outlineColor: $badgeColor.reference,
- },
- _active: {
- boxShadow: "none",
- },
- },
- },
- highContrast: {
- [$badgeBg.variable]: "colors.attention.light",
- [$badgeColor.variable]: "colors.attention.base",
- "&:any-link": {
- _hover: {
- [$tagBoxshadowColor.variable]: "colors.attention.base",
- boxShadow: `2px 2px 0 ${$tagBoxshadowColor.reference}`,
- },
- _focusWithin: {
- outlineColor: $badgeColor.reference,
- },
- _active: {
- boxShadow: "none",
- },
- },
- },
- },
-}
diff --git a/src/@chakra-ui/components/Text.ts b/src/@chakra-ui/components/Text.ts
deleted file mode 100644
index c9f5a025086..00000000000
--- a/src/@chakra-ui/components/Text.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import { defineStyle, defineStyleConfig } from "@chakra-ui/react"
-
-const sizes = {
- "6xl": defineStyle({
- fontSize: "6xl",
- lineHeight: "4xs",
- }),
- "5xl": defineStyle({
- fontSize: "5xl",
- lineHeight: "4xs",
- }),
- "4xl": defineStyle({
- fontSize: "4xl",
- lineHeight: "4xs",
- }),
- "3xl": defineStyle({
- fontSize: "3xl",
- lineHeight: "2xs",
- }),
- "2xl": defineStyle({
- fontSize: "2xl",
- lineHeight: "2xs",
- }),
- xl: defineStyle({
- fontSize: "xl",
- lineHeight: "xs",
- }),
- lg: defineStyle({
- fontSize: "lg",
- lineHeight: "base",
- }),
- md: defineStyle({
- fontSize: "md",
- lineHeight: "base",
- }),
- sm: defineStyle({
- fontSize: "sm",
- lineHeight: "base",
- }),
- xs: defineStyle({
- fontSize: "xs",
- lineHeight: "base",
- }),
-}
-
-export const Text = defineStyleConfig({
- sizes,
-})
diff --git a/src/@chakra-ui/components/components.utils.ts b/src/@chakra-ui/components/components.utils.ts
deleted file mode 100644
index 444c0a24bfd..00000000000
--- a/src/@chakra-ui/components/components.utils.ts
+++ /dev/null
@@ -1,135 +0,0 @@
-import merge from "lodash/merge"
-import { cssVar, SystemStyleObject, theme } from "@chakra-ui/react"
-
-const {
- Alert: alertDefaultTheme,
- Avatar: avatarDefaultTheme,
- Badge: badgeDefaultTheme,
- Breadcrumb: breadcrumbDefaultTheme,
- Checkbox: checkboxDefaultTheme,
- CloseButton: closeButtonDefaultTheme,
- Code: codeDefaultTheme,
- Drawer: drawerDefaultTheme,
- Form: formDefaultTheme,
- FormLabel: formLabelDefaultTheme,
- Heading: headingDefaultTheme,
- Input: inputDefaultTheme,
- Link: linkDefaultTheme,
- List: listDefaultTheme,
- Menu: menuDefaultTheme,
- Modal: modalDefaultTheme,
- Popover: popoverDefaultTheme,
- Radio: radioDefaultTheme,
- Select: selectDefaultTheme,
- Spinner: spinnerDefaultTheme,
- Switch: switchDefaultTheme,
- Table: tableDefaultTheme,
- Tabs: tabsDefaultTheme,
- Tag: tagDefaultTheme,
-} = theme.components
-
-export {
- alertDefaultTheme,
- avatarDefaultTheme,
- badgeDefaultTheme,
- breadcrumbDefaultTheme,
- checkboxDefaultTheme,
- closeButtonDefaultTheme,
- codeDefaultTheme,
- drawerDefaultTheme,
- formDefaultTheme,
- formLabelDefaultTheme,
- headingDefaultTheme,
- inputDefaultTheme,
- linkDefaultTheme,
- listDefaultTheme,
- menuDefaultTheme,
- modalDefaultTheme,
- popoverDefaultTheme,
- radioDefaultTheme,
- selectDefaultTheme,
- spinnerDefaultTheme,
- switchDefaultTheme,
- tableDefaultTheme,
- tabsDefaultTheme,
- tagDefaultTheme,
-}
-
-/**
- * Allows for type safety groups of styles that will be merged.
- *
- * This is for merging default imported theming with custom styles.
- *
- * @param defaultTheming - The related object that comes from the Charka default themes
- *
- * @param styleObjs - The following style objects to be merged
- */
-export function defineMergeStyles(
- defaultTheming?: SystemStyleObject | unknown,
- ...styleObjs: SystemStyleObject[] | unknown[]
-): Record {
- return merge(defaultTheming, ...styleObjs)
-}
-
-export const _notDisabledReadOnly =
- "&:not([data-disabled], [disabled], [data-readonly])"
-
-const $inputTriggerDisableColor = cssVar("input-trigger-disable-color")
-
-export const commonInputTriggerStyles = {
- commonControlProps: {
- border: "1px",
- borderColor: "body.medium",
- outline: "3px solid",
- outlineColor: "transparent",
- _checked: {
- color: "background.base",
- bg: "primary.base",
- borderColor: "primary.base",
- },
- _focusVisible: {
- borderColor: "primary.highContrast",
- outlineColor: "primary.hover",
- outlineOffset: "2px",
- boxShadow: "none",
- },
- _disabled: {
- bg: $inputTriggerDisableColor.reference,
- borderColor: $inputTriggerDisableColor.reference,
- opacity: 1,
- _checked: {
- bg: $inputTriggerDisableColor.reference,
- borderColor: $inputTriggerDisableColor.reference,
- },
- },
- [_notDisabledReadOnly]: {
- // Hovering over the label triggers the style for the control
- "*[data-checked]:hover > &": {
- bg: "primary.hover",
- borderColor: "primary.highContrast",
- },
- "*:not([data-checked]):hover > &": {
- bg: "body.light",
- borderColor: "primary.highContrast",
- },
- },
- _invalid: {
- // TODO: Investigate inconsistency in prop rendering order (possible Chakra bug)
- // border: "2px",
- borderColor: "error.base",
- bg: "error.light",
- },
- },
- commonContainerProps: {
- [$inputTriggerDisableColor.variable]: "colors.disabled",
- ["[data-disabled], [disabled], [data-readonly]"]: {
- cursor: "not-allowed",
- },
- },
- commonLabelProps: {
- _disabled: {
- color: $inputTriggerDisableColor.reference,
- opacity: 1,
- },
- },
-}
diff --git a/src/@chakra-ui/components/index.ts b/src/@chakra-ui/components/index.ts
deleted file mode 100644
index cd1914ca7e7..00000000000
--- a/src/@chakra-ui/components/index.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import { Accordion } from "./Accordion"
-import { Avatar } from "./Avatar"
-import { Badge } from "./Badge"
-import { Breadcrumb } from "./Breadcrumb"
-import { Button } from "./Button"
-import { Checkbox } from "./Checkbox"
-import {
- closeButtonDefaultTheme,
- codeDefaultTheme,
- drawerDefaultTheme,
- formDefaultTheme,
- formLabelDefaultTheme,
- menuDefaultTheme,
- spinnerDefaultTheme,
-} from "./components.utils"
-import { Heading } from "./Heading"
-import { Input } from "./Input"
-import { Link } from "./Link"
-import { Modal } from "./Modal"
-import { Popover } from "./Popover"
-import { Progress } from "./Progress"
-import { Radio } from "./Radio"
-import { Switch } from "./Switch"
-import { Table } from "./Table"
-import { Tabs } from "./Tabs"
-import { Tag } from "./Tag"
-import { Text } from "./Text"
-
-// eslint-disable-next-line import/no-anonymous-default-export
-export default {
- Accordion,
- Avatar,
- Badge,
- Breadcrumb,
- Button,
- Checkbox,
- CloseButton: closeButtonDefaultTheme,
- Code: codeDefaultTheme,
- Drawer: drawerDefaultTheme,
- Form: formDefaultTheme,
- FormLabel: formLabelDefaultTheme,
- Heading,
- Input,
- Link,
- Menu: menuDefaultTheme,
- Modal,
- Popover,
- Progress,
- Radio,
- Spinner: spinnerDefaultTheme,
- Switch,
- Table,
- Tabs,
- Tag,
- Text,
-}
diff --git a/src/@chakra-ui/foundations/colors.ts b/src/@chakra-ui/foundations/colors.ts
deleted file mode 100644
index 58f443a9282..00000000000
--- a/src/@chakra-ui/foundations/colors.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-export type Colors = typeof colors
-
-const colors = {
- gray: {
- 50: "#f7f7f7",
- 100: "#eeeeee",
- 150: "#ececec",
- 200: "#cecece",
- 300: "#acacac",
- 400: "#8C8C8C",
- 500: "#616161",
- 600: "#333333",
- 700: "#222222",
- 800: "#1b1b1b",
- 900: "#121212",
- 950: "#0a0a0a",
- },
- blue: {
- 50: "#F8FBFF",
- 100: "#E8F1FF",
- 200: "#CADFFB",
- 300: "#88AAF1",
- 400: "#6995F7",
- 500: "#4473EF",
- 600: "#3C4CEB",
- 700: "#2B36A8",
- 800: "#232F71",
- 900: "#1B273A",
- },
- orange: {
- 50: "#FFF3ED",
- 100: "#FFF0DB",
- 200: "#FFD7A7",
- 300: "#FEB077",
- 400: "#FD8640",
- 500: "#FB610E",
- 600: "#EC4A0A",
- 700: "#C4350A",
- 800: "#7D2711",
- 900: "#3A291D",
- },
- purple: {
- 50: "#F3ECFF",
- 100: "#EDE2FF",
- 200: "#DAC5FC",
- 300: "#CCAFFC",
- 400: "#B38DF0",
- 500: "#945AF4",
- 600: "#6C24DF",
- 700: "#561BB5",
- 800: "#41128B",
- 900: "#1E0546",
- },
- red: {
- 100: "#f7c8c8",
- 500: "#b80000",
- // ! Deprecating 900
- 900: "#1B0C0C",
- },
- green: {
- 100: "#ddf4e4",
- // ! Deprecating 400
- 400: "#48BB78",
- 500: "#0a7146",
- // ! Deprecating 900
- 900: "#0A160E",
- },
- yellow: {
- 200: "#fff8df",
- 500: "#bd8400",
- },
-}
-
-export default colors
diff --git a/src/@chakra-ui/foundations/index.ts b/src/@chakra-ui/foundations/index.ts
deleted file mode 100644
index b06bb6b1b83..00000000000
--- a/src/@chakra-ui/foundations/index.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import colors from "./colors"
-import shadows from "./shadows"
-import sizes from "./sizes"
-import spacing from "./spacing"
-import typography from "./typography"
-
-// Check the following link to see all the possible options:
-// https://github.com/chakra-ui/chakra-ui/blob/main/packages/theme/src/foundations/index.ts
-const foundations = {
- colors,
- shadows,
- space: spacing,
- sizes: {
- ...spacing,
- ...sizes,
- },
- ...typography,
-}
-
-export default foundations
diff --git a/src/@chakra-ui/foundations/shadows.ts b/src/@chakra-ui/foundations/shadows.ts
deleted file mode 100644
index 15190c39b41..00000000000
--- a/src/@chakra-ui/foundations/shadows.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-const shadows = {
- // using css variables bc shadows do not support color tokens yet
-
- outline: "0 0 0 4px var(--eth-colors-primary-hover)",
- table:
- "0 14px 66px rgba(0,0,0,.07), 0 10px 17px rgba(0,0,0,.03), 0 4px 7px rgba(0,0,0,.05)",
- drop: "0 4px 17px 0 var(--eth-colors-blackAlpha-200)",
- tableBox: {
- light:
- "0 14px 66px rgba(0,0,0,.07), 0 10px 17px rgba(0,0,0,.03), 0 4px 7px rgba(0,0,0,.05)",
- dark: "0 14px 66px hsla(0,0%,96.1%,.07), 0 10px 17px hsla(0,0%,96.1%,.03), 0 4px 7px hsla(0,0%,96.1%,.05)",
- },
- tableBoxHover: "0px 8px 17px rgba(0, 0, 0, 0.15)",
- tableItemBox: {
- light: "0 1px 1px rgba(0, 0, 0, 0.1)",
- dark: "0 1px 1px hsla(0,0%,100%,.1)",
- },
- tableItemBoxHover: "0 0 1px var(--eth-colors-primary-base)",
- gridYellowBoxShadow: "8px 8px 0px 0px var(--eth-colors-gridYellow)",
- gridBlueBowShadow: "8px 8px 0px 0px var(--eth-colors-gridBlue)",
-
- // * Part of new DS
- // TODO: Deprecate buttonHover when all buttons migrated to tailwind
- buttonHover: "4px 4px 0 0 var(--eth-colors-primary-lowContrast)",
- tooltip: "0 0 16px var(--eth-colors-tooltipShadow)",
-}
-
-export default shadows
diff --git a/src/@chakra-ui/foundations/sizes.ts b/src/@chakra-ui/foundations/sizes.ts
deleted file mode 100644
index dd55c276fb2..00000000000
--- a/src/@chakra-ui/foundations/sizes.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-const container = {
- "2xl": "1536px",
-}
-
-const sizes = {
- container,
-}
-
-export default sizes
diff --git a/src/@chakra-ui/foundations/spacing.ts b/src/@chakra-ui/foundations/spacing.ts
deleted file mode 100644
index 6f5271b1c7a..00000000000
--- a/src/@chakra-ui/foundations/spacing.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-const spacing = {
- 7.5: "1.875rem",
- 10.5: "2.625rem",
- 19: "4.75rem", // Nav height
-}
-
-export default spacing
diff --git a/src/@chakra-ui/foundations/typography.ts b/src/@chakra-ui/foundations/typography.ts
deleted file mode 100644
index fe26cb0ab75..00000000000
--- a/src/@chakra-ui/foundations/typography.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-const typography = {
- fonts: {
- heading: "var(--font-inter)",
- body: "var(--font-inter)",
- monospace: "var(--font-mono)",
- },
-
- lineHeights: {
- "6xs": 1.1,
- "5xs": 1.15,
- "4xs": 1.2,
- "3xs": 1.25,
- "2xs": 1.3,
- xs: 1.4,
- sm: 1.5,
- base: 1.6,
- },
-}
-
-export default typography
diff --git a/src/@chakra-ui/semanticTokens.ts b/src/@chakra-ui/semanticTokens.ts
deleted file mode 100644
index b1d447bd07b..00000000000
--- a/src/@chakra-ui/semanticTokens.ts
+++ /dev/null
@@ -1,115 +0,0 @@
-import {
- darkTheme as oldDarkTheme,
- lightTheme as oldLightTheme,
-} from "../theme"
-
-/** @deprecated */
-const oldLightThemeColors = oldLightTheme.colors
-const oldDarkThemeColors = oldDarkTheme.colors
-/**
- * @deprecated
- *
- * define each of the old colors as a `semanticToken`:
- * `name: { _light: lightColor, _dark: darkColor }`
- */
-const oldColors = Object.keys(oldLightThemeColors).reduce((colors, color) => {
- const lightColor = oldLightThemeColors[color]
- const darkColor = oldDarkThemeColors[color]
-
- if (typeof lightColor !== "string" || typeof darkColor !== "string") {
- return colors
- }
-
- return {
- ...colors,
- [color]: { _light: lightColor, _dark: darkColor },
- }
-}, {})
-
-const semanticTokens = {
- colors: {
- // define old colors from the old theme as semanticTokens to transition
- // from emotion components to chakra
- // TODO: remove these colors as we migrate away from them
- ...oldColors,
-
- // Design System colors
-
- // Main Set
- primary: {
- base: { _light: "purple.600", _dark: "purple.400" },
- highContrast: { _light: "purple.800", _dark: "purple.200" },
- lowContrast: { _light: "purple.100", _dark: "purple.900" },
- hover: { _light: "purple.500", _dark: "purple.300" },
- visited: { _light: "purple.700", _dark: "purple.300" },
- action: { _light: "purple.600", _dark: "purple.600" },
- actionHover: { _light: "purple.500", _dark: "purple.500" },
- // ! Deprecating primary.light
- light: { _light: "blue.100", _dark: "orange.100" },
- // ! Deprecating primary.dark
- dark: { _light: "blue.700", _dark: "orange.800" },
- // ! Deprecating primary.pressed
- pressed: { _light: "blue.400", _dark: "orange.800" },
- },
- body: {
- base: { _light: "gray.800", _dark: "gray.100" },
- medium: { _light: "gray.500", _dark: "gray.400" },
- light: { _light: "gray.200", _dark: "gray.600" },
- },
- background: {
- base: { _light: "white", _dark: "black" },
- highlight: { _light: "gray.100", _dark: "gray.900" },
- },
- disabled: { _light: "gray.400", _dark: "gray.500" },
- // ! Deprecating neutral
- neutral: { _light: "white", _dark: "gray.900" },
-
- // Complementary Set
- attention: {
- base: "yellow.500",
- light: "yellow.200",
- outline: { _light: "attention.base", _dark: "attention.light" },
- },
- // ? Keep "error" or rename to "fail" ?
- error: {
- base: "red.500",
- light: "red.100",
- outline: { _light: "error.base", _dark: "error.light" },
- // ! Deprecating error.neutral
- neutral: { _light: "red.100", _dark: "red.900" },
- },
- success: {
- base: "green.500",
- light: "green.100",
- outline: { _light: "success.base", _dark: "success.light" },
- // ! Deprecating success.neutral
- neutral: { _light: "green.100", _dark: "green.900" },
- },
-
- // Misc
- tooltipShadow: {
- _light: "blackAlpha.400",
- _dark: "whiteAlpha.400",
- },
- hubHeroContentBg: {
- _light: "rgba(255, 255, 255, 0.80)",
- _dark: "rgba(34, 34, 34, 0.80)",
- },
- },
- gradients: {
- bgMainGradient: {
- _light:
- "linear-gradient(102.7deg, rgba(185, 185, 241, 0.2) 0%, rgba(84, 132, 234, 0.2) 51.56%, rgba(58, 142, 137, 0.2) 100%)",
- _dark:
- "linear-gradient(102.7deg, rgba(185, 185, 241, 0.2) 0%, rgba(84, 132, 234, 0.2) 51.56%, rgba(58, 142, 137, 0.2) 100%)",
- },
- },
- shadows: {
- menu: {
- accordion:
- "0px 2px 2px 0px rgba(0, 0, 0, 0.12) inset, 0px -3px 2px 0px rgba(0, 0, 0, 0.14) inset",
- },
- },
-}
-
-export default semanticTokens
diff --git a/src/@chakra-ui/stories/Colors.stories.tsx b/src/@chakra-ui/stories/Colors.stories.tsx
deleted file mode 100644
index ddaf32ef76d..00000000000
--- a/src/@chakra-ui/stories/Colors.stories.tsx
+++ /dev/null
@@ -1,187 +0,0 @@
-import { type ReactNode } from "react"
-import capitalize from "lodash/capitalize"
-import { Box, Flex, HStack, Square, Stack, Text } from "@chakra-ui/react"
-import type { Meta, StoryObj } from "@storybook/react"
-
-import colors from "@/@chakra-ui/foundations/colors"
-import semanticTokens from "@/@chakra-ui/semanticTokens"
-
-const semanticTokenColors = semanticTokens["colors"]
-
-import Heading from "@/components/Heading"
-
-const meta = {
- title: "Design System/Colors",
- parameters: {
- // Do not create snapshots for any stories in the file.
- chromatic: { disableSnapshot: true },
- },
-} satisfies Meta
-
-export default meta
-
-const primitiveColorKeys = ["gray", "blue", "orange"]
-export const Primitives: StoryObj = {
- render: () => {
- const primitiveColorsMap = Object.entries(colors)
- .filter((obj) => primitiveColorKeys.includes(obj[0]))
- .reduce<{ [tokenKey: string]: [string, string][] }>(
- (acc, [key, value]) => {
- const tokenMap = Object.entries(value)
- return {
- ...acc,
- [key]: tokenMap,
- }
- },
- {}
- )
-
- return (
-
- {primitiveColorKeys.map((color) => (
-
-
- {primitiveColorsMap[color].map(([tokenKey, value]) => (
-
-
-
-
-
- {value}
-
- {color}.{tokenKey}
-
-
-
- ))}
-
-
- ))}
-
- )
- },
-}
-
-const ColorGroupWrapper = ({
- color,
- children,
-}: {
- color: string
- children: ReactNode
-}) => {
- return (
-
- {children}
-
- )
-}
-
-export const SemanticScheme: StoryObj = {
- parameters: {
- chromatic: {
- modes: {
- darkMode: {
- colorMode: "dark",
- },
- lightMode: {
- colorMode: "light",
- },
- },
- },
- },
- render: () => {
- const tokenNames = [
- "primary",
- "body",
- "background",
- "disabled",
- "success",
- "attention",
- "error",
- ] as const
- const deprecatedTokens: Record<(typeof tokenNames)[number], string[]> = {
- primary: ["light", "dark", "pressed"],
- body: [],
- background: [],
- disabled: [],
- success: ["neutral", "outline"],
- attention: ["neutral", "outline"],
- error: ["neutral", "outline"],
- }
-
- return (
-
- {tokenNames.map((tokenName) => {
- const currentDeprecatedTokens = deprecatedTokens[
- tokenName
- ] as string[]
-
- const tokenObj = semanticTokenColors[tokenName]
-
- const filteredTokenObj =
- "base" in tokenObj
- ? Object.keys(semanticTokens["colors"][tokenName]).filter(
- (key) => !currentDeprecatedTokens.includes(key)
- )
- : undefined
-
- return (
-
- {capitalize(tokenName)}
-
- {!filteredTokenObj ? (
-
- ) : (
- <>
- {filteredTokenObj.map((nestedKey) => (
-
- ))}
- >
- )}
-
-
- )
- })}
-
- )
- },
-}
-
-const SemanticColorBlock = ({
- nestedKey,
- tokenName,
-}: Record<"nestedKey" | "tokenName", string>) => (
-
-
-
- {tokenName}.{nestedKey}
-
-
-)
diff --git a/src/@chakra-ui/theme.ts b/src/@chakra-ui/theme.ts
deleted file mode 100644
index 00e4fd2ce6e..00000000000
--- a/src/@chakra-ui/theme.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { extendBaseTheme, type ThemeConfig } from "@chakra-ui/react"
-
-import components from "./components"
-import foundations from "./foundations"
-import semanticTokens from "./semanticTokens"
-
-const config: ThemeConfig = {
- cssVarPrefix: "eth",
- initialColorMode: "light",
- /**
- * Disable Chakra's system color subscription, as it works differently from
- * `next-themes` and causes a desync with it.
- *
- * Chakra will always change the color mode based on the system preference.
- * While `next-themes` will only change to the system preference if the user
- * has `system` as their active theme.
- */
- useSystemColorMode: false,
-}
-
-/**
- * Override default styles with our custom theme.
- *
- * The complete list of default Chakra styles can be found here:
- * https://github.com/chakra-ui/chakra-ui/tree/main/packages/theme/src
- */
-const theme = {
- config,
- ...foundations,
- semanticTokens,
- components,
-}
-
-export default extendBaseTheme(theme)
diff --git a/src/components/ActionCard.tsx b/src/components/ActionCard.tsx
index be0b38cd5de..b54d79aa26a 100644
--- a/src/components/ActionCard.tsx
+++ b/src/components/ActionCard.tsx
@@ -1,7 +1,7 @@
import { StaticImageData } from "next/image"
import type { BaseHTMLAttributes, ElementType, ReactNode } from "react"
-import { TwImage } from "@/components/Image"
+import { Image } from "@/components/Image"
import InlineLink from "@/components/ui/Link"
import { LinkBox, LinkOverlay } from "@/components/ui/link-box"
@@ -53,7 +53,7 @@ const ActionCard = ({
isRight ? "justify-end" : "justify-center"
)}
>
- (
diff --git a/src/components/Link.tsx b/src/components/Link.tsx
deleted file mode 100644
index d694af331d8..00000000000
--- a/src/components/Link.tsx
+++ /dev/null
@@ -1,191 +0,0 @@
-import NextLink, { type LinkProps as NextLinkProps } from "next/link"
-import { useRouter } from "next/router"
-import { RxExternalLink } from "react-icons/rx"
-import {
- forwardRef,
- Icon,
- Link as ChakraLink,
- type LinkProps as ChakraLinkProps,
- type StyleProps,
- VisuallyHidden,
-} from "@chakra-ui/react"
-
-import { type MatomoEventOptions, trackCustomEvent } from "@/lib/utils/matomo"
-import { getRelativePath } from "@/lib/utils/relativePath"
-import * as url from "@/lib/utils/url"
-
-import { DISCORD_PATH, SITE_URL } from "@/lib/constants"
-
-import { useRtlFlip } from "@/hooks/useRtlFlip"
-
-type BaseProps = {
- hideArrow?: boolean
- isPartiallyActive?: boolean
- activeStyle?: StyleProps
- customEventOptions?: MatomoEventOptions
-}
-
-export type LinkProps = BaseProps &
- ChakraLinkProps &
- Omit
-
-/**
- * Link wrapper which handles:
- *
- * - Hashed links
- * e.g.
- *
- * - External links
- * e.g.
- *
- * - PDFs & static files (which open in a new tab)
- * e.g.
- */
-export const BaseLink = forwardRef(function Link(
- {
- href,
- children,
- hideArrow,
- isPartiallyActive = true,
- activeStyle = { color: "primary.base" },
- customEventOptions,
- ...props
- }: LinkProps,
- ref
-) {
- const { locale, asPath } = useRouter()
- const { flipForRtl } = useRtlFlip()
-
- if (!href) {
- console.warn("Link component is missing href prop:", asPath, locale)
- return
- }
-
- const isActive = url.isHrefActive(href, asPath, isPartiallyActive)
- const isDiscordInvite = url.isDiscordInvite(href)
- const isPdf = url.isPdf(href)
- const isExternal = url.isExternal(href)
- const isInternalPdf = isPdf && !isExternal
- const isHash = url.isHash(href)
-
- // Get proper download link for internally hosted PDF's & static files (ex: whitepaper)
- // Opens in separate window.
- if (isInternalPdf) {
- href = getRelativePath(asPath, href)
- }
-
- if (isDiscordInvite) {
- href = new URL(DISCORD_PATH, SITE_URL).href
- }
-
- const commonProps = {
- ref,
- ...props,
- ...(isActive && activeStyle),
- href,
- }
-
- if (isExternal) {
- return (
-
- trackCustomEvent(
- customEventOptions ?? {
- eventCategory: `Link`,
- eventAction: `Clicked`,
- eventName: "Clicked on external link",
- eventValue: href,
- }
- )
- }
- {...commonProps}
- >
- {children}
- (opens in a new tab)
- {!hideArrow && (
-
- )}
-
- )
- }
-
- if (isInternalPdf) {
- return (
-
- trackCustomEvent(
- customEventOptions ?? {
- eventCategory: `Link`,
- eventAction: `Clicked`,
- eventName: "Clicked on internal PDF",
- eventValue: href,
- }
- )
- }
- {...commonProps}
- as={NextLink}
- >
- {children}
-
- )
- }
-
- if (isHash) {
- return (
- {
- e.stopPropagation()
- trackCustomEvent(
- customEventOptions ?? {
- eventCategory: "Link",
- eventAction: "Clicked",
- eventName: "Clicked on hash link",
- eventValue: href,
- }
- )
- }}
- {...commonProps}
- >
- {children}
-
- )
- }
-
- return (
-
- trackCustomEvent(
- customEventOptions ?? {
- eventCategory: `Link`,
- eventAction: `Clicked`,
- eventName: `Clicked on internal link`,
- eventValue: href,
- }
- )
- }
- {...commonProps}
- as={NextLink}
- >
- {children}
-
- )
-})
-
-const InlineLink = forwardRef((props: LinkProps, ref) => {
- return
-})
-
-export default InlineLink
diff --git a/src/components/LocaleDateTime.tsx b/src/components/LocaleDateTime.tsx
index ea21c327a6a..2ab4c7e50b7 100644
--- a/src/components/LocaleDateTime.tsx
+++ b/src/components/LocaleDateTime.tsx
@@ -1,4 +1,4 @@
-import { useRouter } from "next/router"
+import { useLocale } from "next-intl"
type LocaleDateTimeProps = {
utcDateTime: string
@@ -26,7 +26,7 @@ const LocaleDateTime = ({
"LocaleDateTime hideDate and hideTime props cannot both be true"
)
- const { locale } = useRouter()
+ const locale = useLocale()
const date = new Date(utcDateTime)
const defaultDateOptions: Intl.DateTimeFormatOptions = {
month: "long",
diff --git a/src/components/Logo/index.tsx b/src/components/Logo/index.tsx
index 9c32a6d7544..73516511844 100644
--- a/src/components/Logo/index.tsx
+++ b/src/components/Logo/index.tsx
@@ -1,8 +1,7 @@
-import { useTranslation } from "next-i18next"
-
-import { TwImage as Image } from "@/components/Image"
+import { Image } from "@/components/Image"
import useColorModeValue from "@/hooks/useColorModeValue"
+import { useTranslation } from "@/hooks/useTranslation"
import darkImage from "@/public/images/ef-logo.png"
import lightImage from "@/public/images/ef-logo-white.png"
diff --git a/src/components/MarkdownImage.tsx b/src/components/MarkdownImage.tsx
index 28eb16ac05b..6d44ae121cb 100644
--- a/src/components/MarkdownImage.tsx
+++ b/src/components/MarkdownImage.tsx
@@ -1,13 +1,13 @@
import { extname } from "path"
-import { type ImageProps, TwImage } from "@/components/Image"
+import NextLink from "next/link"
+
+import { Image, type ImageProps } from "@/components/Image"
import { toPosixPath } from "@/lib/utils/relativePath"
import { CONTENT_IMAGES_MAX_WIDTH } from "@/lib/constants"
-import InlineLink from "./ui/Link"
-
interface MarkdownImageProps extends Omit {
width: string
height: string
@@ -42,13 +42,8 @@ const MarkdownImage = ({
// display the wrapper as a `span` to avoid dom nesting warnings as mdx
// sometimes wraps images in `p` tags
-
-
+
-
+
)
}
diff --git a/src/components/MergeArticleList.tsx b/src/components/MergeArticleList.tsx
index 307394df22d..1763cfa61b3 100644
--- a/src/components/MergeArticleList.tsx
+++ b/src/components/MergeArticleList.tsx
@@ -1,7 +1,7 @@
-import { useTranslation } from "next-i18next"
-
import CardList, { type CardProps } from "@/components/CardList"
+import { useTranslation } from "@/hooks/useTranslation"
+
const MergeArticleList = () => {
const { t } = useTranslation(["page-upgrades", "page-upgrades-index"])
diff --git a/src/components/MergeInfographic/MergeInfographic.stories.tsx b/src/components/MergeInfographic/MergeInfographic.stories.tsx
index 073e4272fe9..6b486f5e1ec 100644
--- a/src/components/MergeInfographic/MergeInfographic.stories.tsx
+++ b/src/components/MergeInfographic/MergeInfographic.stories.tsx
@@ -1,4 +1,3 @@
-import { Box } from "@chakra-ui/react"
import { Meta, StoryObj } from "@storybook/react"
import { langViewportModes } from "../../../.storybook/modes"
@@ -18,9 +17,9 @@ const meta = {
},
decorators: [
(Story) => (
-
+
-
+
),
],
} satisfies Meta
diff --git a/src/components/MergeInfographic/index.tsx b/src/components/MergeInfographic/index.tsx
index 2dc30128ea1..163af7e8225 100644
--- a/src/components/MergeInfographic/index.tsx
+++ b/src/components/MergeInfographic/index.tsx
@@ -1,4 +1,3 @@
-import { useTranslation } from "next-i18next"
import type { SVGTextElementAttributes } from "react"
import Translation from "@/components/Translation"
@@ -10,6 +9,8 @@ import { HStack } from "../ui/flex"
import { Background } from "./Background"
+import { useTranslation } from "@/hooks/useTranslation"
+
const Text = ({
className,
...rest
@@ -63,9 +64,7 @@ const MergeInfographic = () => {
void
@@ -19,7 +19,7 @@ type DesktopNavMenuProps = {
const DesktopNavMenu = ({ toggleColorMode }: DesktopNavMenuProps) => {
const { t } = useTranslation("common")
- const { locale } = useRouter()
+ const locale = useLocale()
const languagePickerRef = useRef(null)
const ThemeIcon = useColorModeValue(MdBrightness2, MdWbSunny)
diff --git a/src/components/Nav/Menu/useSubMenu.ts b/src/components/Nav/Menu/useSubMenu.ts
index b44b39e7999..6d51aca23bc 100644
--- a/src/components/Nav/Menu/useSubMenu.ts
+++ b/src/components/Nav/Menu/useSubMenu.ts
@@ -1,10 +1,12 @@
import type { MotionProps } from "framer-motion"
-import { useRouter } from "next/router"
+import { useLocale } from "next-intl"
import { useRtlFlip } from "@/hooks/useRtlFlip"
+import { usePathname } from "@/i18n/routing"
export const useSubMenu = () => {
- const { asPath, locale } = useRouter()
+ const pathname = usePathname()
+ const locale = useLocale()
const { isRtl } = useRtlFlip()
const menuVariants: MotionProps["variants"] = {
@@ -13,7 +15,7 @@ export const useSubMenu = () => {
}
return {
- asPath,
+ asPath: pathname,
locale,
menuVariants,
}
diff --git a/src/components/Nav/Mobile/HamburgerButton.tsx b/src/components/Nav/Mobile/HamburgerButton.tsx
index 1bb8c2c484d..15fa6f967a7 100644
--- a/src/components/Nav/Mobile/HamburgerButton.tsx
+++ b/src/components/Nav/Mobile/HamburgerButton.tsx
@@ -1,6 +1,5 @@
import { forwardRef } from "react"
import { motion } from "framer-motion"
-import { useTranslation } from "next-i18next"
import { cn } from "@/lib/utils/cn"
@@ -8,6 +7,8 @@ import { HAMBURGER_BUTTON_ID } from "@/lib/constants"
import { Button, type ButtonProps } from "../../ui/buttons/Button"
+import { useTranslation } from "@/hooks/useTranslation"
+
const hamburgerSvg =
"M 2 13 l 10 0 l 0 0 l 10 0 M 4 19 l 8 0 M 12 19 l 8 0 M 2 25 l 10 0 l 0 0 l 10 0"
const glyphSvg =
diff --git a/src/components/Nav/Mobile/LvlAccordion.tsx b/src/components/Nav/Mobile/LvlAccordion.tsx
index e3596464ab5..c213eca9ce4 100644
--- a/src/components/Nav/Mobile/LvlAccordion.tsx
+++ b/src/components/Nav/Mobile/LvlAccordion.tsx
@@ -1,5 +1,5 @@
import { useState } from "react"
-import { useRouter } from "next/router"
+import { useLocale } from "next-intl"
import * as AccordionPrimitive from "@radix-ui/react-accordion"
import { cn } from "@/lib/utils/cn"
@@ -18,6 +18,8 @@ import {
AccordionTrigger,
} from "./MenuAccordion"
+import { usePathname } from "@/i18n/routing"
+
type LvlAccordionProps = {
lvl: Level
items: NavItem[]
@@ -45,14 +47,15 @@ const LvlAccordion = ({
activeSection,
onToggle,
}: LvlAccordionProps) => {
- const { asPath, locale } = useRouter()
+ const pathname = usePathname()
+ const locale = useLocale()
const [value, setValue] = useState("")
return (
{items.map(({ label, description, ...action }) => {
const isLink = "href" in action
- const isActivePage = isLink && cleanPath(asPath) === action.href
+ const isActivePage = isLink && cleanPath(pathname) === action.href
const isExpanded = value === label
const nestedAccordionSpacingMap = {
diff --git a/src/components/Nav/Mobile/MenuBody.tsx b/src/components/Nav/Mobile/MenuBody.tsx
index 70e7e2435b2..19dc48b7414 100644
--- a/src/components/Nav/Mobile/MenuBody.tsx
+++ b/src/components/Nav/Mobile/MenuBody.tsx
@@ -1,5 +1,5 @@
import { useState } from "react"
-import { useRouter } from "next/router"
+import { useLocale } from "next-intl"
import { cn } from "@/lib/utils/cn"
import { trackCustomEvent } from "@/lib/utils/matomo"
@@ -23,7 +23,7 @@ type MenuBodyProps = {
}
const MenuBody = ({ linkSections, onToggle }: MenuBodyProps) => {
- const { locale } = useRouter()
+ const locale = useLocale()
const [value, setValue] = useState("")
return (
diff --git a/src/components/Nav/Mobile/MenuFooter.tsx b/src/components/Nav/Mobile/MenuFooter.tsx
index db48b3a132c..0fb8c5672fb 100644
--- a/src/components/Nav/Mobile/MenuFooter.tsx
+++ b/src/components/Nav/Mobile/MenuFooter.tsx
@@ -1,4 +1,3 @@
-import { useTranslation } from "next-i18next"
import { BsTranslate } from "react-icons/bs"
import { MdBrightness2, MdSearch, MdWbSunny } from "react-icons/md"
@@ -10,6 +9,7 @@ import FooterButton from "./FooterButton"
import FooterItemText from "./FooterItemText"
import useColorModeValue from "@/hooks/useColorModeValue"
+import { useTranslation } from "@/hooks/useTranslation"
type MenuFooterProps = {
onToggle: () => void
diff --git a/src/components/Nav/Mobile/MenuHeader.tsx b/src/components/Nav/Mobile/MenuHeader.tsx
index 6d26290c881..b7c43fce378 100644
--- a/src/components/Nav/Mobile/MenuHeader.tsx
+++ b/src/components/Nav/Mobile/MenuHeader.tsx
@@ -1,7 +1,7 @@
-import { useTranslation } from "next-i18next"
-
import { SheetClose, SheetTitle } from "@/components/ui/sheet"
+import { useTranslation } from "@/hooks/useTranslation"
+
const MenuHeader = () => {
const { t } = useTranslation("common")
diff --git a/src/components/Nav/index.tsx b/src/components/Nav/index.tsx
index 66833cf7f4c..83f7547145d 100644
--- a/src/components/Nav/index.tsx
+++ b/src/components/Nav/index.tsx
@@ -1,6 +1,5 @@
import { useRef } from "react"
import dynamic from "next/dynamic"
-import { useTranslation } from "next-i18next"
import { EthHomeIcon } from "@/components/icons"
import Search from "@/components/Search"
@@ -14,6 +13,7 @@ import { useNav } from "./useNav"
import { useBreakpointValue } from "@/hooks/useBreakpointValue"
import { useIsClient } from "@/hooks/useIsClient"
+import { useTranslation } from "@/hooks/useTranslation"
const Menu = dynamic(() => import("./Menu"), {
ssr: false,
diff --git a/src/components/Nav/useNav.ts b/src/components/Nav/useNav.ts
index 95ab3496483..48f77916df0 100644
--- a/src/components/Nav/useNav.ts
+++ b/src/components/Nav/useNav.ts
@@ -1,4 +1,3 @@
-import { useTranslation } from "next-i18next"
import { useTheme } from "next-themes"
import {
BsBook,
@@ -18,7 +17,6 @@ import {
BsUiChecksGrid,
} from "react-icons/bs"
import { PiFlask, PiUsersFourLight } from "react-icons/pi"
-import { useColorMode } from "@chakra-ui/react"
import EthereumIcon from "@/components/icons/ethereum-icon.svg"
@@ -26,10 +24,11 @@ import { trackCustomEvent } from "@/lib/utils/matomo"
import type { NavSections } from "./types"
+import useTranslation from "@/hooks/useTranslation"
+
export const useNav = () => {
const { t } = useTranslation("common")
const { setTheme, resolvedTheme } = useTheme()
- const { setColorMode } = useColorMode()
const linkSections: NavSections = {
learn: {
@@ -475,7 +474,6 @@ export const useNav = () => {
const targetTheme = resolvedTheme === "dark" ? "light" : "dark"
setTheme(targetTheme)
- setColorMode(targetTheme)
trackCustomEvent({
eventCategory: "nav bar",
diff --git a/src/components/NetworkMaturity.tsx b/src/components/NetworkMaturity.tsx
new file mode 100644
index 00000000000..41fa17872e9
--- /dev/null
+++ b/src/components/NetworkMaturity.tsx
@@ -0,0 +1,109 @@
+import InlineLink from "./ui/Link"
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "./ui/table"
+import ExpandableCard from "./ExpandableCard"
+
+import DevelopingImage from "@/public/images/network-maturity/developing.svg"
+import EmergingImage from "@/public/images/network-maturity/emerging.svg"
+import MaturingImage from "@/public/images/network-maturity/maturing.svg"
+import RobustImage from "@/public/images/network-maturity/robust.svg"
+
+const NetworkMaturity = () => {
+ return (
+
+
+
+
+
+ We review the network’s progress towards{" "}
+
+ Ethereum alignment
+ {" "}
+ (rollup stages 0-2),{" "}
+ total value locked (TVL),
+ time live in production, and{" "}
+ risk considerations. These levels help track
+ network development and provide a standardized way for the
+ community to evaluate progress.
+
+
+ Technical progress alone is not enough, user adoption and age are
+ essential part of the overall strength and maturity on any
+ network.
+
+
+
+
+
+
+ Maturity
+ Requirements
+
+
+
+
+
+
+
+ Robust
+
+
+
+ • Stage 2 • At least $1B TVL
+
+
+
+
+
+
+
+ Maturing
+
+
+
+ • Stage 1 • At least $150M TVL
+ • 6+ months live in production
+
+
+
+
+
+
+
+ Developing
+
+
+
+ • Stage 0 • Risk assessment: 3/5 (L2beat)
+ • At least $150M TVL
+ • 6+ months live in production
+
+
+
+
+
+
+
+ Emerging
+
+
+
+ • Stage 0 • Risk assessment: 2/5 (L2beat)
+ • At least $150M TVL or 6+ months live in production
+
+
+
+
+
+
+
+ )
+}
+
+export default NetworkMaturity
diff --git a/src/components/OldHeading.tsx b/src/components/OldHeading.tsx
deleted file mode 100644
index e8f3a400ed4..00000000000
--- a/src/components/OldHeading.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { Heading, type HeadingProps } from "@chakra-ui/react"
-
-/**
- * @deprecated To be removed in favor of new Chakra Heading theme
- *
- * Renders a heading with the styles from the old theme.
- */
-const OldHeading = (props: HeadingProps) => {
- let mt = 8
-
- if (typeof props.as === "undefined" || props.as === "h2") {
- mt = 12
- }
-
- if (props.as === "h3") {
- mt = 10
- }
-
- return
-}
-
-export default OldHeading
diff --git a/src/components/OldText.tsx b/src/components/OldText.tsx
deleted file mode 100644
index 38cc17ee9de..00000000000
--- a/src/components/OldText.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import { Text, type TextProps } from "@chakra-ui/react"
-
-/**
- * @deprecated To be removed in favor of new Chakra Text theme
- *
- * Renders body copy with a defined margin bottom for spacing (old theme)
- */
-const OldText = (props: TextProps) => {
- const mb = props.as && props.as !== "p" ? 0 : "1.45rem"
- return
-}
-
-export default OldText
diff --git a/src/components/OrderedList.tsx b/src/components/OrderedList.tsx
deleted file mode 100644
index a418f05670b..00000000000
--- a/src/components/OrderedList.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-// Libraries
-import React from "react"
-import {
- Box,
- ListItem,
- OrderedList as ChakraOrderedList,
- SystemStyleObject,
-} from "@chakra-ui/react"
-
-export type OrderedListProps = {
- listData: Array
-}
-
-/**
- * The custom ordered list numbers in a solid circular background
- */
-const liCustomType: SystemStyleObject = {
- content: `counter(li-counter)`,
- position: "absolute",
- top: "-3px", // adjusts circle + number up and down
- insetInlineStart: "-3rem",
- width: "34px",
- height: "1.6rem",
- pt: "9px", // adjusts number up and down,
- lineHeight: "100%",
- borderRadius: "50%",
- background: "grayBackground",
- textAlign: "center",
-}
-
-// `listData` should be a list of strings, or HTML components
-// ex: [
string
] or ['string']
-const OrderedList = ({ listData }: OrderedListProps) => {
- return (
-
-
- {listData.map((data, idx) => {
- return (
-
- {data}
-
- )
- })}
-
-
- )
-}
-
-export default OrderedList
diff --git a/src/components/PageHero.tsx b/src/components/PageHero.tsx
index 15029253ad5..89062e01219 100644
--- a/src/components/PageHero.tsx
+++ b/src/components/PageHero.tsx
@@ -1,6 +1,6 @@
import type { ReactNode } from "react"
-import { type ImageProps, TwImage } from "@/components/Image"
+import { Image, type ImageProps } from "@/components/Image"
import { cn } from "@/lib/utils/cn"
import { type MatomoEventOptions } from "@/lib/utils/matomo"
@@ -131,7 +131,7 @@ const PageHero = ({
"w-full self-center"
)}
>
- {
- const { locale, locales: rawLocales, asPath } = useRouter()
+ const locale = useLocale()
+ const pathname = usePathname()
const { t } = useTranslation()
- const locales = filterRealLocales(rawLocales)
+ const locales = filterRealLocales(LOCALES_CODES)
const desc = description || t("site-description")
const siteTitle = t("site-title")
// Remove any query params (?) or hash links (#)
- const path = asPath.replace(/[?#].*/, "")
+ const path = pathname.replace(/[?#].*/, "")
const slug = path.split("/")
// Set canonical URL w/ language path to avoid duplicate content
diff --git a/src/components/ProductCard.tsx b/src/components/ProductCard.tsx
index 6d335c8f649..5efd34d4b56 100644
--- a/src/components/ProductCard.tsx
+++ b/src/components/ProductCard.tsx
@@ -1,5 +1,4 @@
import type { ImageProps } from "next/image"
-import { useTranslation } from "next-i18next"
import type { ReactNode } from "react"
import { cn } from "@/lib/utils/cn"
@@ -8,7 +7,9 @@ import { ButtonLink } from "./ui/buttons/Button"
import { Center, Flex, HStack } from "./ui/flex"
import { Tag } from "./ui/tag"
import GitStars from "./GitStars"
-import { TwImage } from "./Image"
+import { Image } from "./Image"
+
+import { useTranslation } from "@/hooks/useTranslation"
type SubjectBadgeProps = {
subject: string
@@ -87,7 +88,7 @@ const ProductCard = ({
)}
>
-
+
{githubRepoStars > 0 && (
diff --git a/src/components/ProductList.tsx b/src/components/ProductList.tsx
index c3a6efaab4d..4a745682993 100644
--- a/src/components/ProductList.tsx
+++ b/src/components/ProductList.tsx
@@ -4,7 +4,7 @@ import { VisuallyHidden } from "@radix-ui/react-visually-hidden"
import { ButtonLink } from "./ui/buttons/Button"
import { Flex } from "./ui/flex"
import { List, ListItem } from "./ui/list"
-import { TwImage } from "./Image"
+import { Image } from "./Image"
type Content = {
title: string
@@ -37,7 +37,7 @@ const ProductList = ({ actionLabel, content, category }: ProductListProps) => {