# Scaffold-ETH 2
Everything you need to build dApps on Ethereum. A modern, clean version of Scaffold-ETH with NextJS, RainbowKit, Wagmi and Typescript. Supports Hardhat and Foundry.
## High level overview
### Smart Contract Read and Write Operations Patterns
- Read: useScaffoldReadContract (packages/nextjs/hooks/scaffold-eth/useScaffoldReadContract.ts)
- Write: useScaffoldWriteContract (packages/nextjs/hooks/scaffold-eth/useScaffoldWriteContract.ts)
- Event Listening: useScaffoldEventHistory for historical data (packages/nextjs/hooks/scaffold-eth/useScaffoldEventHistory.ts)
You have all the details of our custom hooks in `## Hooks` section from this file.
### Best Practice Guidance for Components usage
Use Scaffold-ETH 2 components whenever it makes sense, they are located in `packages/nextjs/components/scaffold-eth`. You have all the details about components in `## components` section from this file.
### UI/Design System
Styling Framework:
- Base: Tailwind CSS v3
- Components: daisyUI v4
- DaisyUI Documentation: https://daisyui.com/llms.txt
- Implementation:
* Core theme configuration: packages/nextjs/tailwind.config.js
* Base styling: packages/nextjs/styles/globals.css
* Component-specific styling in individual component files
### Wallet Connection
- Supported: RainbowKit (packages/nextjs/providers/RainbowKitProvider.tsx)
### Deployment Configuration and Network Setup
- Default chains: check if `viem/chains` already has the chain present if not, follow the below steps.
- Chains: Can be defined directly in scaffold.config.ts or in a separate file (e.g., packages/nextjs/utils/customChains.ts)
- Targets: Configured in packages/nextjs/scaffold.config.ts via the targetNetworks array
- RPC: Can be hardcoded in chain definitions or configured via .env.local
Example Chain Config:
// In scaffold.config.ts or a separate file
export const lineaSepolia = defineChain({
id: 59_141,
name: "Linea Sepolia Testnet",
nativeCurrency: { name: "Linea Ether", symbol: "ETH", decimals: 18 },
rpcUrls: {
default: {
http: ["https://rpc.sepolia.linea.build"],
webSocket: ["wss://rpc.sepolia.linea.build"], // WebSocket is optional but recommended
},
},
blockExplorers: {
default: {
name: "Etherscan",
url: "https://sepolia.lineascan.build",
apiUrl: "https://api-sepolia.lineascan.build/api",
},
},
contracts: {
multicall3: {
address: "0xca11bde05977b3631167028862be2a173976ca11",
blockCreated: 227427,
},
},
testnet: true,
});
### disable-type-linting-error-checks
Source: https://docs.scaffoldeth.io/disable-type-linting-error-checks
#### β Disabling Type and Linting Error Checks
:::tip Hint
TypeScript helps you catch errors at compile time, which can save time and improve code quality, but can be challenging for those who are new to the language or who are used to the more dynamic nature of JavaScript. These sections show the steps required to disable type & lint checks on different levels.
:::tip Hint
#### Disabling Commit Checks
We run the `pre-commit` [git hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) which lints the staged files and doesn't let you commit if there is an linting error.
To disable this, go to the `.husky/pre-commit` file and comment out `yarn lint-staged --verbose`
```diff
- yarn lint-staged --verbose
+ # yarn lint-staged --verbose
```
#### Deploying to Vercel Without Any Checks
By default, Vercel runs type and lint checks before building your app. The deployment will fail if there are any type or lint errors.
To ignore these checks while deploying from the CLI, use:
```shell
yarn vercel:yolo
```
If your repo is connected to Vercel, you can set `NEXT_PUBLIC_IGNORE_BUILD_ERROR` to `true` in an [environment variable](https://vercel.com/docs/concepts/projects/environment-variables).
#### Disabling GitHub Workflow
We have a GitHub workflow setup checkout `.github/workflows/lint.yaml` which runs type and lint error checks every time code is **pushed** to `main` branch or **pull request** is made to `main` branch.
To disable it, **delete `.github` directory**.
## Components
Scaffold-ETH 2 provides a set of pre-built components for common web3 use cases. You can make use of them to accelerate and simplify your dapp development.
### Address
Source: https://docs.scaffoldeth.io/components/Address
Display an address (or ENS) along with a utility icon to copy the address. If the address is associated with an ENS that has an avatar, this avatar will be displayed. If not, a blockie image representation of the address will be shown.
By default, the component will show the ENS name (if available) and the address.

You can also choose to display only the ENS name (if available) or the address, by setting the `onlyEnsOrAddress` prop to `true`.

Clicking on the address redirects to the connected wallet's network block explorer. If the wallet is not connected, it redirects to the block explorer of [`targetNetworks[0]`](/deploying/deploy-nextjs-app#--targetnetworks). You can disable this behaviour with the `disableAddressLink` prop.
#### Import
```tsx
import { Address } from "~~/components/scaffold-eth";
```
#### Usage
```tsx
```
#### Props
| Prop | Type | Default Value | Description |
| --------------------------------- | --------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| **address** | `string` | `undefined` | Address in `0x___` format, it will resolve its ENS if it has one associated. |
| **disableAddressLink** (optional) | `boolean` | `false` | Set it to `true` to disable the blockexplorer link behaviour when clicking on the address. |
| **format** (optional) | `string` | `"short"` | By default, only the first five characters of the address are displayed. Set this to `"long"` to display the entire address. |
| **size** (optional) | `string` | `"base"` | Size for the displayed Address component. `base` by default but you can pass in `xs`, `sm`, `base`, `lg`, `xl`, `2xl`, `3xl`. |
| **onlyEnsOrAddress** (optional) | `boolean` | `false` | When `true`, displays only the ENS name (if available) or the address, not both. |
### AddressInput
Source: https://docs.scaffoldeth.io/components/AddressInput
Display an Ethereum address input that validates the address format, resolves ENS domains, and shows their avatars.
Also shows a blockie image for each address.

#### Import
```tsx
import { AddressInput } from "~~/components/scaffold-eth";
```
#### Usage
```tsx
const [address, setAddress] = useState("");
```
```tsx
```
#### Props
| Prop | Type | Default Value | Description |
| -------------------------- | ---------- | ------------- | ---------------------------------------------------------------------------- |
| **value** | `string` | `undefined` | An Ethereum address in (`0x___` format) or an ENS domain. |
| **onChange** | `function` | `undefined` | A callback invoked when the data in the address input changes. |
| **placeholder** (optional) | `string` | `undefined` | The string that will be rendered before address input has been entered. |
| **name** (optional) | `string` | `undefined` | Helps identify the data being sent if AddressInput is submitted into a form. |
| **disabled** (optional) | `boolean` | `false` | If `true`, sets the address input un-clickable and unusable. |
### Balance
Source: https://docs.scaffoldeth.io/components/Balance
Displays the balance of a given address in both ether (ETH) and US dollars (USD).

#### Import
```tsx
import { Balance } from "~~/components/scaffold-eth";
```
#### Usage
```tsx
```
#### Props
| Prop | Type | Default Value | Description |
| ------------------------ | -------- | ------------- | ------------------------------------------------------------------------------------------------------------------------- |
| **address** | `string` | `undefined` | Address in `0x___` format, it will resolve its ENS if it has one associated. |
| **className** (optional) | `string` | `""` | Prop to pass additional CSS styling to the component. You can use Tailwind / daisyUI classes like `text-3xl` for styling. |
### BlockieAvatar
Source: https://docs.scaffoldeth.io/components/BlockieAvatar
Show a blockie (bar code profile icon) component for a given public address.
The autogenerated blockie can be manually replaced by another image that we pass through the `ensImage` prop.

If you want more control over styling the blockie, you can directly use [blo](https://github.com/bpierre/blo) (pre-installed in Scaffold-ETH 2) and internally used by `BlockieAvatar` component to get the image URL.
#### Import
```tsx
import { BlockieAvatar } from "~~/components/scaffold-eth";
```
#### Usage
```tsx
```
#### Props
| Prop | Type | Default Value | Description |
| --------------------- | -------- | ------------- | ----------------------------------------------------------------------------------------- |
| `address` | `string` | `undefined` | The address for which you want to display its blockie. Ensure it's in the `0x___` format. |
| `size` | `number` | `undefined` | Width and Height in pixels (square). |
| `ensImage` (optional) | `string` | `undefined` | An arbitrary image url to render instead of the blockie. |
### EtherInput
Source: https://docs.scaffoldeth.io/components/EtherInput
Displays an input field for ETH/USD amount, with an option to convert between ETH and USD.

#### Import
```tsx
import { EtherInput } from "~~/components/scaffold-eth";
```
#### Usage
```tsx
const [ethAmount, setEthAmount] = useState("");
```
```tsx
setEthAmount(amount)} />
```
#### Props
| Prop | Type | Default Value | Description |
| -------------------------- | ---------- | ------------- | --------------------------------------------------------------------------------------- |
| **value** | `string` | `undefined` | You can enter ether quantity or USD quantity, but value will always be stored in ETH. |
| **onChange** | `function` | `undefined` | A callback invoked when the amount in the EtherInput changes. |
| **placeholder** (optional) | `string` | `undefined` | The string that will be rendered when there is no input value. |
| **name** (optional) | `string` | `undefined` | Helps identify the data being sent if EtherInput is submitted into a form. |
| **disabled** (optional) | `boolean` | `false` | When set to `true`, changes input background color and border to have disabled styling. |
### InputBase
Source: https://docs.scaffoldeth.io/components/InputBase
Simple building block for creating an input which comes with basic default styles (colors, rounded borders).

#### Import
```tsx
import { InputBase } from "~~/components/scaffold-eth";
```
#### Usage
```tsx
const [url, setUrl] = useState();
```
```tsx
```
#### Props
| Prop | Type | Default Value | Description |
| -------------------------- | ---------- | ------------- | --------------------------------------------------------------------------------------- |
| **value** | `string` | `undefined` | The data that your input will show. |
| **onChange** | `function` | `undefined` | A callback invoked when the data in the input changes. |
| **placeholder** (optional) | `string` | `undefined` | The string that will be rendered before input data has been entered. |
| **name** (optional) | `string` | `undefined` | Helps identify the data being sent if InputBase is submitted into a form. |
| **error** (optional) | `boolean` | `false` | When set to `true`, changes input border to have error styling. |
| **disabled** (optional) | `boolean` | `false` | When set to `true`, changes input background color and border to have disabled styling. |
### IntergerInput
Source: https://docs.scaffoldeth.io/components/IntergerInput
#### IntegerInput
Provides an input field for integer values, validating that user input is a valid integer, and showing error if not.
Shows by default a small button to multiply input's value \* 10^18 to transform to wei.

#### Import
```tsx
import { IntegerInput } from "~~/components/scaffold-eth";
```
#### Usage
```tsx
const [txValue, setTxValue] = useState("");
```
```tsx
{
setTxValue(updatedTxValue);
}}
placeholder="value (wei)"
/>
```
#### Props
| Prop | Type | Default Value | Description |
| -------------------------- | ---------- | ------------- | --------------------------------------------------------------------------------------- |
| **value** | `string` | `undefined` | The data that your input will show. |
| **onChange** | `function` | `undefined` | A callback invoked when the amount in the input changes. |
| **placeholder** (optional) | `string` | `undefined` | The string that will be rendered before input data has been entered. |
| **name** (optional) | `string` | `undefined` | Helps identify the data being sent if InputBase is submitted into a form. |
| **error** (optional) | `boolean` | `false` | When set to `true`, changes input border to have error styling. |
| **disabled** (optional) | `boolean` | `false` | When set to `true`, changes input background color and border to have disabled styling. |
### RainbowKitCustomConnectButton
Source: https://docs.scaffoldeth.io/components/RainbowKitCustomConnectButton
Scaffold-ETH 2 uses a custom _"Connect Button"_, based on RainbowKit, that is enhanced with several useful features:
- **Balance Display**: Shows the balance of the native token from the connected address.
- **Chain Name and Color**: Displays the name of the connected blockchain and uses a distinct color for each chain.
- **Custom Modal**: Includes copy address feature, view its QR code, access address details in blockexplorer, and disconnect.
You can extend this component to suit your app's needs.

#### Import
```tsx
import { RainbowKitCustomConnectButton } from "~~/components/scaffold-eth";
```
#### Usage
```tsx
```
## Contributing
### π Contributing to Scaffold-ETH 2
We welcome contributions to Scaffold-ETH 2!
This section aims to provide an overview of the contribution workflow to help us make the contribution process effective for everyone involved.
:::caution
The project is under active development. You can view the open Issues, follow the development process, and contribute to the project.
:::caution
### Getting Started
You can contribute to this repo in many ways:
- Solve open issues
- Report bugs or feature requests
- Improve the documentation
Contributions are made via Issues and Pull Requests (PRs). A few general guidelines for contributions:
- Search for existing Issues and PRs before creating your own.
- Contributions should only fix/add the functionality in the issue OR address style issues, _not both_.
- If you're running into an error, please give context. Explain what you're trying to do and how to reproduce the error.
- Please use the same formatting in the code repository. You can configure your IDE to do this by using the prettier / linting config files included in each package.
- If applicable, please edit the README.md file to reflect changes.
### Issues
Source: https://docs.scaffoldeth.io/contributing/Issues
Issues should be used to report problems, request a new feature, or discuss potential changes before a PR is created.
#### Solve an Issue
Scan through our [existing issues](https://github.com/scaffold-eth/scaffold-eth-2/issues) to find one that interests you.
If a contributor is working on the issue, they will be assigned to that individual. If you find an issue to work on, you are welcome to assign it to yourself and open a PR with a fix for it.
#### Create a New Issue
If a related issue doesn't exist, you can open a new issue.
Some tips to follow when you are creating an issue:
- Provide as much context as possible. Over-communicate to give the most detail to the reader.
- Include the steps to reproduce the issue or the reason for adding the feature.
- Screenshots, videos, etc., are highly appreciated.
### pullRequests
Source: https://docs.scaffoldeth.io/contributing/pullRequests
#### Pull Requests
#### Pull Request Process
We follow the ["fork-and-pull" Git workflow](https://github.com/susam/gitpr)
1. Fork the repo
2. Clone the project
3. Create a new branch with a descriptive name
4. Commit your changes to the new branch
5. Push changes to your fork
6. Open a PR in our repository and tag one of the maintainers to review your PR
Here are some tips for a high-quality pull request:
- Create a title for the PR that accurately defines the work done.
- Structure the description neatly to make it easy to consume by the readers. For example, you can include bullet points and screenshots instead of having one large paragraph.
- Add the link to the issue if applicable.
- Have a good commit message that summarises the work done.
Once you submit your PR:
- We may ask questions, request additional information, or ask for changes to be made before a PR can be merged. Please note that these are to make the PR clear for everyone involved and aims to create a frictionless interaction process.
- As you update your PR and apply changes, mark each conversation resolved.
Once the PR is approved, we'll "squash-and-merge" to keep the git commit history clean.
## Deploying
Learn how to deploy your Smart Contracts to a Live Network and how to deploy your NextJS App.
### deploy-nextjs-app
Source: https://docs.scaffoldeth.io/deploying/deploy-nextjs-app
#### Deploy Your NextJS App
:::tip Hint
We recommend connecting your GitHub repo to Vercel (through the Vercel UI) so it gets automatically deployed when pushing to `main`.
:::tip Hint
If you want to deploy directly from the CLI, run this and follow the steps to deploy to Vercel:
```
yarn vercel
```
You might need to log in to Vercel first by running:
```
yarn vercel:login
```
Once you log in (email, GitHub, etc), the default options should work. It'll give you a public URL.
If you want to redeploy to the same production URL you can run:
```
yarn vercel --prod
```
If you omit the `--prod` flag it will deploy it to a preview/test URL.
**Make sure to check the values of your Scaffold Configuration before deploying your NextJS App.**
#### Scaffold App Configuration
You can configure different settings for your dapp at `packages/nextjs/scaffold.config.ts`.
```ts
export type ScaffoldConfig = {
targetNetworks: Chain[];
pollingInterval: number;
alchemyApiKey: string;
walletConnectProjectId: string;
onlyLocalBurnerWallet: boolean;
walletAutoConnect: boolean;
// your dapp custom config, eg:
// tokenIcon : string;
};
```
The configuration parameters are described below. Make sure to update the values according to your needs:
##### - targetNetworks
Array of blockchain networks where your dapp is deployed. Use values that are present on chains object from [viem/chains](https://viem.sh/docs/chains/introduction) eg: `targetNetworks: [chains.optimism]`
To add a custom chain that's not in viem/chains, see the recipe, [Add a custom chain](/recipes/add-custom-chain).
##### - pollingInterval
The interval in milliseconds at which your front-end application polls the RPC servers for fresh data. _Note that this setting does not affect the local network._
##### - alchemyApiKey
Default Alchemy API key from Scaffold-ETH 2 for local testing purposes.
It's recommended to obtain your own API key from the [Alchemy Dashboard](https://dashboard.alchemyapi.io/) and store it in this environment variable: `NEXT_PUBLIC_ALCHEMY_API_KEY` in the `\packages\nextjs\.env.local` file.
##### - walletConnectProjectId
WalletConnect's default project ID from Scaffold-ETH 2 for local testing purposes.
It's recommended to obtain your own project ID from the [WalletConnect website](https://cloud.walletconnect.com) and store it in this environment variable: `NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID` in the `\packages\nextjs\.env.local` file.
##### - onlyLocalBurnerWallet
Controls the networks where the Burner Wallet feature is available. This feature provides a lightweight wallet for users.
- `true` => Use Burner Wallet only on Hardhat network.
- `false` => Use Burner Wallet on all networks.
##### - walletAutoConnect
Set it to `true` to activate automatic wallet connection behavior:
- If the user was connected into a wallet before, on page reload it reconnects automatically.
- If the user is not connected to any wallet, on reload, it connects to the burner wallet _if it is enabled for the current network_. See `onlyLocalBurnerWallet`
You can extend this configuration file, adding new parameters that you need to use across your dapp **(make sure you update the above type `ScaffoldConfig`)**:
```ts
tokenIcon: "π",
```
To use the values from the `ScaffoldConfig` in any other file of your application, you first need to import it in those files:
```ts
import scaffoldConfig from "~~/scaffold.config";
```
### deploy-smart-contracts
Source: https://docs.scaffoldeth.io/deploying/deploy-smart-contracts
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
#### Deploy Your Smart Contracts
To deploy your smart contracts to a live network, there are a few things you need to adjust.
#### 1. Configure your network
Scaffold-ETH 2 comes with a selection of predefined networks. To add your custom network:
```mdx-code-block
```
Go to `packages/hardhat/hardhat.config.ts` and add your network to the `networks` object.
```typescript title="packages/hardhat/hardhat.config.ts"
networks: {
// ... other networks
base: {
url: "https://mainnet.base.org",
accounts: [deployerPrivateKey]
},
}
```
```mdx-code-block
```
Go to `packages/foundry/foundry.toml` and add your network to the `rpc_endpoints` object.
```toml title="packages/foundry/foundry.toml"
[rpc_endpoints]
...other chains
base = "https://mainnet.base.org"
```
Here are the [Alchemy docs](https://docs.alchemy.com/docs/how-to-add-alchemy-rpc-endpoints-to-metamask) for information on specific networks.
You can also add your custom network by following the recipe [here](/recipes/add-custom-chain).
#### 2. Generate a new account or add one to deploy the contract(s) from.
The deployer account is the account that will deploy your contracts. Additionally, the deployer account will be used to execute any function calls that are part of your deployment script.
You can generate a random account / private key by running:
```
yarn generate
```
```mdx-code-block
```
It will automatically add the encrypted private key (`DEPLOYER_PRIVATE_KEY_ENCRYPTED`) in your `.env` file.
You will be prompted to enter a password which will be used to encrypt your private key. **Make sure to remember this password as you'll need it for future deployments and account queries.**
:::info Info
We are only storing the plain private key in memory, it's never stored in disk files for security reasons. Checkout the code [here](https://github.com/scaffold-eth/create-eth/blob/main/templates/solidity-frameworks/hardhat/packages/hardhat/scripts/generateAccount.ts).
:::info
If you prefer to import your private key, run:
```
yarn account:import
```
You will get prompted to paste your private key and set the encryption password. It will store your encrypted private key in your `.env` file.
```mdx-code-block
```
It will automatically generate a new [keystore](https://book.getfoundry.sh/reference/cli/cast/wallet#cast-wallet) with the name `scaffold-eth-custom`.
You will be prompted to enter a password which will be used to encrypt your keystore. **Make sure to remember this password as you'll need it for future deployments and account queries.**
Now you'll need to open your `packages/foundry/.env` file, and update `ETH_KEYSTORE_ACCOUNT=scaffold-eth-custom` to start using the new keystore.
If you prefer to import your private key (you need to delete your `scaffold-eth-custom` keystore first, if exists), run:
```
yarn account:import
```
You will get prompted to paste your private key and set the encryption password. It will store your encrypted private key in the `scaffold-eth-custom` keystore file.
Also if you want to use your existing keystore account you can just update the `ETH_KEYSTORE_ACCOUNT` in your `.env` file, setting the name of your existing keystore.
You can check the configured (generated or imported) account and balances with:
```
yarn account
```
You will need to enter your password to decrypt the private key and view the account information and balances.
#### 3. Deploy your smart contract(s)
```mdx-code-block
```
By default `yarn deploy` will deploy all the contracts from your `packages/hardhat/contracts` folder to the local network. You can change `defaultNetwork` in:
```sh
packages/hardhat/hardhat.config.ts
```
```mdx-code-block
```
By default `yarn deploy` will deploy all the contracts from your `packages/foundry/contracts` folder to the local network. You can change `defaultNetwork` in:
```sh
packages/foundry/foundry.toml
```
#### 3.1 Deploy specific contracts
To deploy specific contracts instead of all of them, you can follow these steps:
```mdx-code-block
```
1. Add tags to the deploy scripts located in `packages/hardhat/deploy`. For example `01_deploy_my_contract.ts`:
```ts
deployMyContract.tags = ["tagExample"];
```
2. Run `yarn deploy --tags tagExample` to run all the scripts with the "tagExample" tag.
`````mdx-code-block
1. Each contract that you wish to deploy individually should have its own deployment script in `packages/foundry/script`. For example: `DeployMyContract.s.sol`
2. Run the specific deployment script using:
```sh
yarn deploy --file DeployMyContract.s.sol
```
If you don't specify the `--file` parameter, the deployment will use the default `Deploy.s.sol` file. This default file can be configured to deploy multiple contracts in a specific order when you run the `yarn deploy` command.
#### 3.2 Deploy to specific networks
Run the command below to deploy the smart contracts to the target network. Make sure to have your encryption password and some funds in your deployer account to pay for the transaction.
```
yarn deploy --network network_name
```
```mdx-code-block
```
You can also specify a tag:
```sh
yarn deploy --network sepolia --tags tagExample
```
````mdx-code-block
Requires custom keystore setup, see [generate accounts](#2-generate-a-new-account-or-add-one-to-deploy-the-contracts-from)
You can also specify a file:
```sh
yarn deploy --network sepolia --file DeployMyContract.s.sol
```
#### 4. Verify your smart contract
You can verify your smart contract on Etherscan by running:
```
yarn verify --network network_name
```
eg: `yarn verify --network sepolia`
This command **works in both Hardhat and Foundry**, verifying all the deployed contracts. However, the verification method differs depending on the Solidity framework you're using...
Hardhat uses [etherscan-verify from hardhat-deploy](https://www.npmjs.com/package/hardhat-deploy#4-hardhat-etherscan-verify).
Additionally, **in Hardhat**, there's an alternative method for contract verification. You can use [hardhat-verify](https://hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-verify) to verify your contracts, passing in the network name, contract address and constructor arguments (if any):
```sh
yarn hardhat-verify --network network_name contract_address "Constructor arg 1"`
```
If the chain you're using is not supported by any of the verifying methods, you can add new supported chains to your chosen method, either [etherscan-verify](https://www.npmjs.com/package/hardhat-deploy#options-2) or [hardhat-verify](https://hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-verify#adding-support-for-other-networks).
Foundry uses `VerifyAll.s.sol` script located in `packages/foundry/script`.
#### Configuration of Third-Party Services for Production-Grade Apps.
By default, Scaffold-ETH 2 provides predefined API keys for popular services such as Alchemy and Etherscan. This allows you to begin developing and testing your applications more easily, avoiding the need to register for these services.
For production-grade applications, it's recommended to obtain your own API keys (to prevent rate limiting issues). You can configure these at:
```mdx-code-block
```
- `ALCHEMY_API_KEY` variable in `packages/hardhat/.env` and `packages/nextjs/.env.local`. You can create API keys from the [Alchemy dashboard](https://dashboard.alchemy.com/).
- `ETHERSCAN_API_KEY` variable in `packages/hardhat/.env` using your generated API key. You can get your key [here](https://etherscan.io/myapikey).
```mdx-code-block
```
- `ALCHEMY_API_KEY` variable in `packages/nextjs/.env.local`. You can create API keys from the [Alchemy dashboard](https://dashboard.alchemy.com/).
- `ETHERSCAN_API_KEY` variable in `packages/foundry/.env` using your generated API key. You can get your key [here](https://etherscan.io/myapikey).
```mdx-code-block
```
:::tip Hint
It's recommended to store envs for nextjs in Vercel/system env config for live apps and use .env.local for local testing.
:::tip Hint
```
`````
## Extensions
Extensions are modular add-ons for Scaffold-ETH 2 that provide additional functionality or serve as examples for specific features. They allow you to quickly add new features, pages, contracts, or components during project creation, ensuring seamless integration with Scaffold-ETH 2 core functionality.
### createExtensions
Source: https://docs.scaffoldeth.io/extensions/createExtensions
#### Creating Your Own Extension
This section will help you develop custom extensions for Scaffold-ETH 2, from simple additions to more complex modifications.
> Video Guide: For a visual walkthrough of the extension development process, check out our [YouTube tutorial](https://youtu.be/XQCv533XGZk?si=dlJH4zd4b99_6soW).
#### Extension Structure
Before diving into the development process, let's understand the structure an extension should follow:
```
your-extension/
βββ extension/
β βββ packages/
β β βββ hardhat/ # (optional) For Hardhat-specific additions
β β βββ foundry/ # (optional) For Foundry-specific additions
β β βββ nextjs/
β β βββ app/ # Any new pages/files
β β β βββ my-page
β β β βββ page.tsx
β β β
β β βββ ... # Any extra files/directories
β β βββ package.json # Only include additional dependencies/scripts
β βββ package.json # Monorepo root package.json file
β βββ README.md # Instance README
βββ README.md # Documentation for your extension
```
#### Developing a Simple Extension
For simple extensions, such as adding a new page or component, you can directly create the extension structure without going through the full development workflow. Here's how:
1. Create the directory structure as shown above.
2. Add your new page or component in the appropriate directory.
3. If needed, create a `package.json` with any additional dependencies.
4. Push your extension to GitHub.
That's it! Your simple extension is ready to be used by others via:
```shell
npx create-eth@latest -e {github-username}/{extension-repo-name}:{branch-name} # branch-name is optional
```
#### Developing an Advanced Extension
#### Template Files and Args
`create-eth` uses a templating system for advanced extensions that need to modify existing files. This system allows you to inject content into specific files in the base project using the `*.args.mjs` files.
Key points:
- They allow you to add specific content to files in the base project.
- Not all files can be modified this way. See [TEMPLATE-FILES.md](https://github.com/scaffold-eth/create-eth/blob/main/contributors/TEMPLATE-FILES.md) for a list of supported template files.
- To use a template file, create an `*.args.mjs` file in your extension having the same path structure as `*.template.mjs`. For example, to add extra tab in the header, you'd create `extension/packages/nextjs/components/Header.tsx.args.mjs`.
#### Advanced Development Workflow
When creating complex extensions, Scaffold-ETH 2 provides a set of tools to make the process easier. This workflow allows you to develop your extension in a full Scaffold-ETH 2 environment, test it locally, and then package it for distribution.
The workflow consists of two main parts:
1. Extension Development: This process helps you create your extension by modifying a base Scaffold-ETH 2 project.
2. Local Testing: This allows you to test your extension in a full Scaffold-ETH 2 environment before publishing.
#### Extension Development Utility
1. **Clone the `create-eth` Repository:**
```bash
git clone https://github.com/scaffold-eth/create-eth.git
cd create-eth
yarn install
```
2. **Run the Build Script:**
```bash
yarn build:dev
```
This creates `cli.js` and `create-extension.js` in the `dist` directory.
3. **Run the CLI to Create a New Instance:**
```bash
yarn cli
```
This command will create a **new base instance**, similar to running `npx create-eth@latest`.
The name mentioned for the "Your project name" question will be used as the **extension name**. For example, if you provide `eip` as the value to the question, then the final extension name will be `eip`.
4. **Develop the Extension:**
- cd into the instance directory.
- Make necessary changes to the instance project.
- Commit the changes in the instance repository.
5. **Create the Extension:**
Return to the `create-eth` folder.
```bash
yarn create-extension {projectName}
```
Example: `yarn create-extension eip`
This command gathers all changes from the instance and creates an extension in the `create-eth/externalExtensions/${extensionName}` directory. This directory is the actual extension directory (notice it contains only extra files related to your extension changes), which can be published to GitHub and used by others.
6. **Publish the Extension:**
- Go inside the extension directory.
- Push the extension to GitHub.
```bash
cd create-eth/externalExtensions/${extensionName}
git init
git add .
git commit -m "Initial commit of my extension"
git remote add origin
git push -u origin main
```
Now other developers can use your published extension by using:
```bash
npx create-eth@latest -e {github-username}/{extension-repo-name}:{branch-name} # extension-branch-name is optional
```
#### Local Testing:
This phase allows you to test your extension locally and see how it works when used by other developers.
> NOTE: If you've already published your extension to GitHub using the "Developing a Simple Extension" approach, make sure to clone that extension repository into the `create-eth/externalExtensions/` directory before proceeding with local testing.
1. **Run the CLI in dev mode:**
```bash
yarn cli -e {extensionName} --dev
```
Example: `yarn cli -e eip --dev`
The `extensionName` should be present in `create-eth/externalExtensions/${extensionName}`.
Let's suppose you named your project "my-dev-instance". Then this `my-dev-instance` should contain all your extension changes. `--dev` will symlink the extension to the instance project.
2. **Test and Tweak the Extension:**
Since the instance is symlinked with the extension, make necessary changes directly in the symlinked files within `my-dev-instance`, and changes should be automatically reflected in the `create-eth/externalExtensions/${extensionName}` directory.
3. **Push the tweaked changes**
- Go inside the extension directory.
- Push the changes to GitHub.
```bash
cd create-eth/externalExtensions/${extensionName}
git add .
git commit -m "some changes"
git push
```
Next time users call your extension via `npx create-eth@latest -e`, they will get the updated version.
### howToInstall
Source: https://docs.scaffoldeth.io/extensions/howToInstall
#### How to Install Extensions
This guide explains what are extensions and how to use them in your Scaffold-ETH 2 project.
#### What are Extensions?
Extensions are modular add-ons for Scaffold-ETH 2 that provide additional functionality or serve as examples for specific features.
:::info Info
Extensions can only be installed during the initial setup of a new Scaffold-ETH 2 project.
:::info Info
They offer several benefits:
- Seamless integration with the base Scaffold-ETH 2 project
- Quick addition of new features, pages, contracts, or components at project creation
- Compatibility with Scaffold-ETH 2 core updates and improvements
Extensions are compact packages containing specific code (such as a smart contract or UI component) that automatically integrate with the latest version of Scaffold-ETH 2 when initializing a new project via npx. They are starting points for your project, not finished products.
#### Installing Extensions
To install an extension when creating a new Scaffold-ETH 2 project, run:
```bash
npx create-eth@latest -e {github-username}/{extension-repo-name}:{branch-name}
```
The `{branch-name}` is optional. If not specified, it uses the default branch.
E.g.: `npx create-eth@latest -e ChangoMan/charts-extension`
#### Available Extensions
You can find a complete list of available extensions, including both curated (by BuidlGuidl) and community extensions, on [scaffold-eth website](https://scaffoldeth.io/extensions).
## External-contracts
### π‘ Interacting with External Contracts
If you need to interact with external contracts (i.e. not deployed with your SE-2 instance, e.g [`DAI`](https://etherscan.io/token/0x6b175474e89094c44da98b954eedeac495271d0f#code) contract) you can add external contract data to your `packages/nextjs/contracts/externalContracts.ts` file, which would let you use Scaffold-ETH 2 [custom hooks](/hooks).
To achieve this, include the contract name, its `address`, and `abi` in `externalContracts.ts` for each chain ID. Ensure to update the [`targetNetworks`](/deploying/deploy-nextjs-app#--targetnetworks) in `scaffold.config.ts` to your preferred chains to enable hooks typescript autocompletion.
This is the structure of `externalContracts` object:
```ts
const externalContracts = {
1: {
DAI: {
address: "0x...",
abi: [...],
},
WETH: {
address: "0x...",
abi: [...],
},
},
5: {
DAI: {
address: "0x...",
abi: [...],
},
WETH: {
address: "0x...",
abi: [...],
},
},
} as const;
```
## Hooks
### π Interacting with Your Smart Contracts
Scaffold-ETH 2 provides a collection of custom React hooks designed to simplify interactions with your deployed smart contracts. These hooks are wrappers around Wagmi, an easy-to-use interface with typescript autocompletions for reading from, writing to, and monitoring events emitted by your smart contracts.
To ensure autocompletions function correctly, always update the [`targetNetworks` ](/deploying/deploy-nextjs-app#--targetnetworks) in `scaffold.config.ts` to include the relevant network/chain whenever you deploy your contract using [`yarn deploy --network`](/deploying/deploy-smart-contracts#3-deploy-your-smart-contracts).
:::info
The custom hooks rely on three main files for their functionality and TypeScript autocompletion:
- `packages/nextjs/contracts/deployedContracts.ts`
- [`packages/nextjs/contracts/externalContracts.ts`](/external-contracts)
- `scaffold.config.ts`
The `deployedContracts.ts` file is auto-generated/updated whenever you run `yarn deploy --network`. It organizes contract addresses and abi's based on chainId.
:::
:::note
When having multiple chains configured in [`targetNetworks`](/deploying/deploy-nextjs-app#--targetnetworks), make sure to have same contractName's on other chains as `targetNetworks[0].id`.This ensures proper functionality and autocompletion of custom hooks, as the current setup and types assumes that same contract's are present on other chains as `targetNetworks[0]`.
:::
### useDeployedContractInfo
Source: https://docs.scaffoldeth.io/hooks/useDeployedContractInfo
Use this hook to fetch details about a deployed smart contract, including the ABI and address.
```ts
const { data: deployedContractData } = useDeployedContractInfo({ contractName: "YourContract" });
```
This example retrieves the details of the deployed contract with the specified name and stores the details in the `deployedContractData` object.
#### Configuration
| Parameter | Type | Description |
| :--------------------- | :------- | :------------------------------------------------------------------------------------------------------------------------- |
| **contractName** | `string` | Name of the contract. |
| **chainId** (optional) | `string` | Id of the chain the contract lives on. Defaults to [`targetNetworks[0].id`](/deploying/deploy-nextjs-app#--targetnetworks) |
#### Return Value
- `data`: Object containing `address` and `abi` of contract.
### useScaffoldContract
Source: https://docs.scaffoldeth.io/hooks/useScaffoldContract
Use this hook to get your contract instance by providing the contract name. It enables you to interact with your contract methods.
For reading data or sending transactions, it's recommended to use `useScaffoldReadContract` and `useScaffoldWriteContract`.
```ts
const { data: yourContract } = useScaffoldContract({
contractName: "YourContract",
});
// Returns the greeting and can be called in any function, unlike useScaffoldReadContract
await yourContract?.read.greeting();
// Used to write to a contract and can be called in any function
import { useWalletClient } from "wagmi";
const { data: walletClient } = useWalletClient();
const { data: yourContract } = useScaffoldContract({
contractName: "YourContract",
chainId: 31337,
walletClient,
});
const setGreeting = async () => {
// Call the method in any function
await yourContract?.write.setGreeting(["the greeting here"]);
};
```
This example uses the `useScaffoldContract` hook to obtain a contract instance for the `YourContract` smart contract.
#### Configuration
| Parameter | Type | Description |
| :-------------------------- | :----------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------- |
| **contractName** | `string` | Name of the contract. |
| **walletClient** (optional) | [`WalletClient`](https://wagmi.sh/react/api/hooks/useWalletClient) | Wallet client must be passed in order to call `write` methods of the contract |
| **chainId** (optional) | `string` | Id of the chain the contract lives on. Defaults to [`targetNetworks[0].id`](/deploying/deploy-nextjs-app#--targetnetworks) |
#### Return Value
- `data` : Object representing viem's [contract instance](https://viem.sh/docs/contract/getContract.html#return-value). Which can be used to call `read` and `write` of the contract.
- `isLoading` : Boolean indicating if the contract is being loaded.
### useScaffoldEventHistory
Source: https://docs.scaffoldeth.io/hooks/useScaffoldEventHistory
Use this hook to retrieve historical event logs for your smart contract, providing past activity data, with the option to watch for new events.
```ts
const {
data: events,
isLoading: isLoadingEvents,
error: errorReadingEvents,
} = useScaffoldEventHistory({
contractName: "YourContract",
eventName: "GreetingChange",
fromBlock: 31231n,
watch: true,
filters: { greetingSetter: "0x9eB2C4866aAe575bC88d00DE5061d5063a1bb3aF" },
blockData: true,
transactionData: true,
receiptData: true,
});
```
This example retrieves the historical event logs for the `GreetingChange` event of the `YourContract` smart contract, starting from block number 31231 and filtering events where the `greetingSetter` parameter is `0x9eB2C4866aAe575bC88d00DE5061d5063a1bb3aF`.
#### Configuration
| Parameter | Type | Description |
| :----------------------------- | :-------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **contractName** | `string` | Name of the contract to read from. |
| **eventName** | `string` | Name of the event to read. |
| **fromBlock** | `bigint` | Block number from which to start reading events. |
| **filters** (optional) | `object` | Apply filters to the event based on **indexed** parameter names and values `{ [parameterName]: value }`. |
| **blockData** (optional) | `boolean` | If set to true it will return the block data for each event (default: false). |
| **transactionData** (optional) | `boolean` | If set to true it will return the transaction data for each event (default: false). |
| **receiptData** (optional) | `boolean` | If set to true it will return the receipt data for each event (default: false). |
| **watch** (optional) | `boolean` | If set to true, the events will be refetched every [`pollingInterval`](/deploying/deploy-nextjs-app#--pollinginterval) set at `scaffold.config.ts`. (default: false). |
| **enabled** (optional) | `boolean` | If set to false, the hook will not fetch any data (default: true). |
| **chainId** (optional) | `string` | Id of the chain the contract lives on. Defaults to [`targetNetworks[0].id`](/deploying/deploy-nextjs-app#--targetnetworks) |
#### Return Values
- `data` property of the returned object contains an array of event objects, each containing the event parameters and (optionally) the block, transaction, and receipt data.
- `isLoading` property indicates whether the event logs are currently being fetched.
- `error` property contains any error that occurred during the fetching process (if applicable).
### useScaffoldReadContract
Source: https://docs.scaffoldeth.io/hooks/useScaffoldReadContract
Use this hook to read public variables and get data from read-only functions of your smart contract.
```ts
const { data: totalCounter } = useScaffoldReadContract({
contractName: "YourContract",
functionName: "userGreetingCounter",
args: ["0xd8da6bf26964af9d7eed9e03e53415d37aa96045"],
});
```
This example retrieves the data returned by the `userGreetingCounter` function of the `YourContract` smart contract.
#### Configuration
| Parameter | Type | Description |
| :--------------------- | :---------- | :------------------------------------------------------------------------------------------------------------------------- |
| **contractName** | `string` | Name of the contract to read from. |
| **functionName** | `string` | Name of the function to call. |
| **args** (optional) | `unknown[]` | Array of arguments to pass to the function (if accepts any). Types are inferred from contract's function parameters |
| **watch** (optional) | `boolean` | Watches and refreshes data on new blocks. (default : `true`) |
| **chainId** (optional) | `string` | Id of the chain the contract lives on. Defaults to [`targetNetworks[0].id`](/deploying/deploy-nextjs-app#--targetnetworks) |
You can also pass other arguments accepted by [useReadContract wagmi hook](https://wagmi.sh/react/api/hooks/useReadContract#parameters).
#### Return Values
- The retrieved data is stored in the `data` property of the returned object.
- You can refetch the data by calling the `refetch` function.
- The extended object includes properties inherited from wagmi useReadContract. You can check the [useReadContract return values](https://wagmi.sh/react/api/hooks/useReadContract#return-type) documentation to check the types.
### useScaffoldWatchContractEvent
Source: https://docs.scaffoldeth.io/hooks/useScaffoldWatchContractEvent
Use this hook to subscribe to events emitted by your smart contract, and receive real-time updates when these events are emitted.
```ts
useScaffoldWatchContractEvent({
contractName: "YourContract",
eventName: "GreetingChange",
// The onLogs function is called whenever a GreetingChange event is emitted by the contract.
// Parameters emitted by the event can be destructed using the below example
// for this example: event GreetingChange(address greetingSetter, string newGreeting, bool premium, uint256 value);
onLogs: logs => {
logs.map(log => {
const { greetingSetter, value, premium, newGreeting } = log.args;
console.log("π‘ GreetingChange event", greetingSetter, value, premium, newGreeting);
});
},
});
```
This example subscribes to the `GreetingChange` event emitted by the `YourContract` smart contract and logs the parameters from the event to the console when it's emitted.
This hook is a wrapper around wagmi's [useWatchContractEvent](https://wagmi.sh/react/api/hooks/useWatchContractEvent).
:::note
Due to shortcomings of some RPC providers, this hook may or may not fire events always [checkout this discussion](https://github.com/wevm/wagmi/issues/3883) for more details. To update the RPC link checkout [this section](/deploying/deploy-nextjs-app#--alchemyapikey)
:::
#### Configuration
| Parameter | Type | Description |
| :--------------------- | :--------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **contractName** | `string` | Name of the contract to read from. |
| **eventName** | `string` | Name of the event to read. |
| **onLogs** | `function` | Callback function to execute when the event is emitted. Accepts an array of `logs` that occurred during the [`pollingInterval`](/deploying/deploy-nextjs-app#--pollinginterval) set at `scaffold.config.ts`. Each array item contains an `args` property, which can be destructured to get the parameters emitted by the event. This function can customized according to your needs. |
| **chainId** (optional) | `string` | Id of the chain the contract lives on. Defaults to [`targetNetworks[0].id`](/deploying/deploy-nextjs-app#--targetnetworks) |
:::note
It is recommended to `setState` using [updater function](https://react.dev/reference/react/useState#updating-state-based-on-the-previous-state) in the `onLogs` function to avoid problems due to caching.
:::
### useScaffoldWriteContract
Source: https://docs.scaffoldeth.io/hooks/useScaffoldWriteContract
Use this hook to send a transaction to your smart contract to write data or perform an action.
```ts
const { writeContractAsync: writeYourContractAsync } = useScaffoldWriteContract({ contractName: "YourContract" });
```
The following configuration options can be passed to the hook:
#### Configuration
| Parameter | Type | Description |
| :--------------------------------- | :------- | :------------------------------------------------------------------------------------------------------------------------- |
| **contractName** | `string` | Name of the contract to write to. |
| **chainId** (optional) | `string` | Id of the chain the contract lives on. Defaults to [`targetNetworks[0].id`](/deploying/deploy-nextjs-app#--targetnetworks) |
| **writeContractParams** (optional) | `object` | wagmi's `useWriteContract` hook [parameters object](https://wagmi.sh/react/api/hooks/useWriteContract#parameters) |
To send the transaction, you can call the `writeContractAsync` function returned by the hook (which we instance as `writeYourContractAsync`). Here's an example usage:
```tsx
```
This example sends a transaction to the `YourContract` smart contract to call the `setGreeting` function with the arguments passed in `args`. The `writeContractAsync` function (`writeYourContractAsync` instance) sends the transaction to the smart contract.
Below is the configuration for `writeContractAsync` function:
#### Configuration
| Parameter | Type | Description |
| :--------------------------------- | :---------- | :------------------------------------------------------------------------------------------------------------------- |
| **functionName** | `string` | Name of the function to call. |
| **args** (optional) | `unknown[]` | Array of arguments to pass to the function (if accepts any). Types are inferred from contract's function parameters. |
| **value** (optional) | `bigint` | Amount of ETH to send with the transaction (for payable functions only). |
| **onBlockConfirmation** (optional) | `function` | Callback function to execute when the transaction is confirmed. |
| **blockConfirmations** (optional) | `number` | Number of block confirmations to wait for before considering transaction to be confirmed (default : 1). |
You can also pass other arguments accepted by [writeContractAsync from wagmi](https://wagmi.sh/react/api/hooks/useWriteContract#mutate-async).
#### Return Values
- `writeContractAsync` function sends the transaction to the smart contract.
- `isMining` property indicates whether the transaction is currently being mined.
- The extended object includes properties inherited from wagmi useWriteContract. You can check the [useWriteContract return values](https://wagmi.sh/react/api/hooks/useWriteContract#return-type) documentation to check the types.
### useTransactor
Source: https://docs.scaffoldeth.io/hooks/useTransactor
Use this hook to interact with the chain and give UI feedback on the transaction status.

Any error will instead show a popup with nice error message.

```ts
const transactor = useTransactor();
const writeTx = transactor({
to: "0x97843608a00e2bbc75ab0C1911387E002565DEDE", // address of buidlguidl.eth
value: 1000000000000000000n,
});
await writeTx();
```
This example tries to send 1 ETH to the address `buidlguidl.eth`, prompting the connected [`WalletClient`](https://wagmi.sh/react/api/hooks/useWalletClient#usewalletclient) for a signature. And in the case of a successful transaction, it will show a popup in the UI with the message: "π Transaction completed successfully!".
You can pass in anything that is a valid parameter to [Viem's `sendTransaction` function](https://viem.sh/docs/actions/wallet/sendTransaction#parameters) to callback function. It also possible to pass it an promise that resolves in with a transaction hash for example promise from [Wagmi's `writeContractAsync` function](https://wagmi.sh/react/api/hooks/useWriteContract#mutate-async).
[Refer to this recipe](/recipes/WriteToContractWriteAsyncButton) for a more detailed example.
#### Configuration
#### useTransactor
| Parameter | Type | Description |
| :---------------------------- | :--------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **\_walletClient** (optional) | [`WalletClient`](https://viem.sh/docs/clients/wallet.html) | The wallet client that should sign the transaction. Defaults to the connected wallet client, and is only needed if the transaction is not already sent using `writeContractAsync` |
#### callback function
| Parameter | Type | Description |
| :------------------------------------------- | :---------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **tx** | [`sendTransaction`-parameters](https://viem.sh/docs/actions/wallet/sendTransaction#parameters) or `Promise` | Either valid parameters for [`sendTransaction`-parameters](https://viem.sh/docs/actions/wallet/sendTransaction#parameters) or a promise that resolves with the transaction hash, e.g. [Wagmi's `writeContractAsync` function](https://wagmi.sh/react/api/hooks/useWriteContract#mutate-async). |
| **options** (optional) | `object` | Additional options for the confirmation. |
| **ββoptions.blockConfirmations** (optional) | `number` | The number of block confirmations to wait for before resolving. Defaults to 1. |
| **ββoptions.onBlockConfirmation** (optional) | `function` | A callback function that is called once all `blockConfirmations` is reached. |
#### Return Values
#### useTransactor
- The callback function that is used to initialize the UI feedback flow.
#### callback function
- A promise that resolves with the transaction hash once the transaction is mined.
## Quick-start
### environment
Source: https://docs.scaffoldeth.io/quick-start/environment
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
Now that our installation is complete, let's configure the development environment for Scaffold ETH-2.
#### 1. **Initialize a Local Blockchain**:
In the first terminal, run a local network:
```
yarn chain
```
This command starts a local Ethereum network using Hardhat or Foundry, depending on which one you selected in the CLI. The network runs on your local machine and can be used for testing and development. You can customize the network configuration in:
```mdx-code-block
```
```sh
packages/hardhat/hardhat.config.ts
```
```mdx-code-block
```
```sh
packages/foundry/foundry.toml
```
#### 2. **Deploy Your Smart Contract**:
In the second terminal, deploy the test contract:
```
yarn deploy
```
This command deploys a test smart contract to the local network. The contract can be modified to suit your needs and can be found in:
```mdx-code-block
```
```sh
packages/hardhat/contracts
```
```mdx-code-block
```
```sh
packages/foundry/contracts
```
The `yarn deploy` command uses a deploy script to deploy the contract to the network. You can customize the deployment script located in:
```mdx-code-block
```
```sh
packages/hardhat/deploy
```
```mdx-code-block
```
```sh
packages/foundry/script
```
#### 3. **Launch your NextJS Application**:
In the third terminal, start your NextJS app:
```
yarn start
```
Visit your app on `http://localhost:3000`. You can interact with your smart contract using the contract component or the example ui in the frontend.
#### What's Next:
```mdx-code-block
```
- Edit your smart contract:
- `YourContract.sol` in `packages/hardhat/contracts`
- Edit your deployment scripts:
- `packages/hardhat/deploy`
- Edit your frontend homepage at `packages/nextjs/app/page.tsx`. For guidance on [routing](https://nextjs.org/docs/app/building-your-application/routing/defining-routes) and configuring [pages/layouts](https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts) checkout the Next.js documentation.
- Edit the app config in `packages/nextjs/scaffold.config.ts`
- Edit your smart contract test in:
- `packages/hardhat/test` to run test use `yarn hardhat:test`
```mdx-code-block
```
- Edit your smart contract:
- `YourContract.sol` in `packages/foundry/contracts`
- Edit your deployment scripts:
- `packages/foundry/script`
- Edit your frontend homepage at `packages/nextjs/app/page.tsx`. For guidance on [routing](https://nextjs.org/docs/app/building-your-application/routing/defining-routes) and configuring [pages/layouts](https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts) checkout the Next.js documentation.
- Edit the app config in `packages/nextjs/scaffold.config.ts`
- Edit your smart contract test in:
- `packages/foundry/test` to run test use `yarn foundry:test`
### installation
Source: https://docs.scaffoldeth.io/quick-start/installation
#### Requirements
Before you begin, you need to install the following tools:
- [Node (>= v20.18.3)](https://nodejs.org/en/download/)
- Yarn ([v1](https://classic.yarnpkg.com/en/docs/install/) or [v2+](https://yarnpkg.com/getting-started/install))
- [Git](https://git-scm.com/downloads)
#### Setup
For a simplified setup, Scaffold-ETH 2 offers a npx tool that guides you interactively through the setup:
```
npx create-eth@latest
```
You will be presented with a series of prompts:
- **Project Name:** Enter a name for your project, e.g., my-dapp-example.
- **Solidity Framework** Choose your preferred solidity framework (Hardhat, Foundry)
Once the setup is complete, navigate to the project directory:
```
cd project-name
```
:::info Hint
If you choose Foundry as solidity framework in the CLI, you'll also need Foundryup installed on your machine.
Checkout: [getfoundry.sh](https://getfoundry.sh/)
:::info Hint
If you want to use extensions, you can add the -e flag followed by the extension name:
```
npx create-eth@latest -e extension-name
```
For more information about available extensions and how to use them, check out the [Extensions section](/extensions)
## Recipes
Explore a collection of practical recipes to implement common web3 use-cases with Scaffold-ETH 2. Learn how to interact with smart contracts, read and display data, manage account balances, and more. Each recipe offers step-by-step guidance, making it easy to implement different blockchain features into your dApps.
### add-custom-chain
Source: https://docs.scaffoldeth.io/recipes/add-custom-chain
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
#### Add a custom chain
This recipe demonstrates how to add a custom chain to your project. We'll use Base as an example, but you can apply this process to any other chain you want to add.
Scaffold-ETH 2 uses [viem/chains](https://viem.sh/docs/chains/introduction) as a list of chains.
Normally, Base already exists in viem/chains and [you can import it and use it](/deploying/deploy-nextjs-app#--targetnetworks), but we're going to add it manually to show you how to do it.
:::info
Scaffold-ETH 2 consists of two parts:
- `packages/nextjs`: nextjs frontend
- `packages/hardhat` or `packages/foundry`: hardhat or foundry to deploy smart contracts
The frontend and the hardhat/foundry project use a different set of chains.
You should add the chain to both the frontend and your hardhat/foundry config. Checkout [deploying your smart contract](/deploying/deploy-smart-contracts) section on how to deploy different chains.
By doing this, you will be able to deploy the contracts to the chain you added and interact with them from the frontend.
:::
#### Step 1: Define the chain
First, create a new file called `customChains.ts` in your `packages/nextjs/utils/` directory.
Open the file with your favorite editor and add the following code to define the chain.
```typescript title="packages/nextjs/utils/customChains.ts"
import { defineChain } from "viem";
// Base chain
export const base = defineChain({
id: 8453,
name: "Base",
nativeCurrency: { name: "Base", symbol: "ETH", decimals: 18 },
rpcUrls: {
default: {
http: ["https://mainnet.base.org"],
},
},
blockExplorers: {
default: {
name: "Basescan",
url: "https://basescan.org",
},
},
});
```
In this file, we're defining the Base chain. We're using the `defineChain` function from viem to define the chain. You can add as many chains as you want to the `customChains.ts` file.
#### Step 2: Update `scaffold.config.ts`
Next, update your `scaffold.config.ts` file to include the new chain:
```typescript title="packages/nextjs/scaffold.config.ts"
import { base } from "./utils/customChains";
// ... other imports and type definitions
const scaffoldConfig = {
targetNetworks: [base],
// ... other configuration options
} as const satisfies ScaffoldConfig;
export default scaffoldConfig;
```
If you'd like to add multiple chains, you can do so by adding them to the `targetNetworks` array. Below is a simple example of how to add multiple chains.
```typescript title="packages/nextjs/scaffold.config.ts"
import { base, baseSepolia } from "./utils/customChains";
const scaffoldConfig = {
targetNetworks: [base, baseSepolia],
// ... other configuration options
} as const satisfies ScaffoldConfig;
```
### GetCurrentBalanceFromAccount
Source: https://docs.scaffoldeth.io/recipes/GetCurrentBalanceFromAccount
#### Get the Current Balance of the Connected Account
This recipe shows how to fetch and display the ETH balance of the currently connected account.
Here is the full code, which we will be implementing in the guide below:
```tsx title="components/ConnectedAddressBalance.tsx"
import { useAccount } from "wagmi";
import { Address, Balance } from "~~/components/scaffold-eth";
export const ConnectedAddressBalance = () => {
const { address: connectedAddress } = useAccount();
return (
Your Ethereum Balance
Address:
Balance:
);
};
```
#### Implementation guide
#### Step 1: Create a new Component
Begin by creating a new component in the "components" folder of your application.
```tsx title="components/ConnectedAddressBalance.tsx"
export const ConnectedAddressBalance = () => {
return (
Your Ethereum Balance
);
};
```
#### Step 2: Retrieve the Connected Account
Fetch the Ethereum address of the currently connected account using the [useAccount wagmi hook](https://wagmi.sh/react/api/hooks/useAccount) and easily display them using Scaffold ETH-2 [Address](/components/Address) and [Balance](/components/Balance) components.
```tsx title="components/ConnectedAddressBalance.tsx"
// highlight-start
import { useAccount } from "wagmi";
import { Address, Balance } from "~~/components/scaffold-eth";
// highlight-end
export const ConnectedAddressBalance = () => {
// highlight-start
const { address: connectedAddress } = useAccount();
// highlight-end
return (
);
};
```
### ReadUintFromContract
Source: https://docs.scaffoldeth.io/recipes/ReadUintFromContract
#### Read a `uint` from a contract
This recipe demonstrates how to read data from contract functions and display it on the UI. We'll showcase an example that accepts some arguments (parameters), and another with no arguments at all.
Here is the full code, which we will be implementing in the guide below:
```tsx title="components/GreetingsCount.tsx"
import { useAccount } from "wagmi";
import { useScaffoldReadContract } from "~~/hooks/scaffold-eth";
export const GreetingsCount = () => {
const { address: connectedAddress } = useAccount();
const { data: totalCounter, isLoading: isTotalCounterLoading } = useScaffoldReadContract({
contractName: "YourContract",
functionName: "totalCounter",
});
const { data: connectedAddressCounter, isLoading: isConnectedAddressCounterLoading } = useScaffoldReadContract({
contractName: "YourContract",
functionName: "userGreetingCounter",
args: [connectedAddress], // passing args to function
});
return (
);
};
```
#### Implementation guide
#### Step 1: Create a new Component
Begin by creating a new component in the "components" folder of your application.
```tsx title="components/GreetingsCount.tsx"
export const GreetingsCount = () => {
return (
Total Greetings count:
Your Greetings count:
);
};
```
#### Step 2: Retrieve total greetings count
Initialize the [useScaffoldReadContract](/hooks/useScaffoldReadContract) hook to read from the contract. This hook provides the `data` which contains the return value of the function.
```tsx title="components/GreetingsCount.tsx"
//highlight-start
import { useScaffoldReadContract } from "~~/hooks/scaffold-eth";
// highlight-end
export const GreetingsCount = () => {
// highlight-start
const { data: totalCounter } = useScaffoldReadContract({
contractName: "YourContract",
functionName: "totalCounter",
});
// highlight-end
return (
Total Greetings count:
//highlight-start
{totalCounter ? totalCounter.toString() : 0}
//highlight-end
Your Greetings count:
);
};
```
In the line `const {data: totalCounter} = useScaffoldReadContract({...})` we are using [destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) to assign `data` to a new name `totalCounter`.
In the contract, `totalCounter` returns an `uint` value, which is represented as a [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) in javascript and can be converted to a readable string using `.toString()`.
#### Step 3: Retrieve connected address greetings count
We can get the connected address using the [useAccount](https://wagmi.sh/react/api/hooks/useAccount) hook and pass it to `args` key in the `useScaffoldReadContract` hook configuration. This will be used as an argument to read the contract function.
```tsx title="components/GreetingsCount.tsx"
import { useScaffoldReadContract } from "~~/hooks/scaffold-eth";
//highlight-start
import { useAccount } from "wagmi";
//highlight-end
export const GreetingsCount = () => {
//highlight-start
const { address: connectedAddress } = useAccount();
//highlight-end
const { data: totalCounter } = useScaffoldReadContract({
contractName: "YourContract",
functionName: "totalCounter",
});
//highlight-start
const { data: connectedAddressCounter } = useScaffoldReadContract({
contractName: "YourContract",
functionName: "userGreetingCounter",
args: [connectedAddress], // passing args to function
});
//highlight-end
return (