diff --git a/docs/docs.json b/docs/docs.json index dccc09947..a1c3ae7bf 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -1298,6 +1298,7 @@ "group": "Development with Foundry", "pages": [ "learn/foundry/deploy-with-foundry", + "learn/foundry/deploy-smart-contracts-set-basenames", "learn/foundry/setup-with-base", "learn/foundry/testing-smart-contracts", "learn/foundry/verify-contract-with-basescan", @@ -1342,6 +1343,12 @@ "learn/hardhat/hardhat-deploy/hardhat-deploy-sbs" ] }, + { + "group": "Naming Smart Contracts", + "pages": [ + "learn/hardhat/hardhat-naming/set-basenames-with-hardhat" + ] + }, { "group": "Verifying Smart Contracts", "pages": [ @@ -1364,7 +1371,8 @@ "learn/hardhat/hardhat-tools-and-testing/analyzing-test-coverage", "learn/hardhat/hardhat-tools-and-testing/optimizing-gas-usage", "learn/hardhat/hardhat-tools-and-testing/reducing-contract-size", - "learn/hardhat/hardhat-tools-and-testing/deploy-with-hardhat" + "learn/hardhat/hardhat-tools-and-testing/deploy-with-hardhat", + "learn/hardhat/hardhat-tools-and-testing/set-basenames-with-hardhat" ] } ] diff --git a/docs/get-started/build-app.mdx b/docs/get-started/build-app.mdx index 449477e29..5a8023abf 100644 --- a/docs/get-started/build-app.mdx +++ b/docs/get-started/build-app.mdx @@ -245,6 +245,7 @@ We now have a working onchain tally app! While the example is simple, it illustr This is just the beginning. There are many ways we can improve upon this app. For example, we could: +- Set a Basename for your contract using [Foundry and the Enscribe library](/learn/foundry/deploy-smart-contracts-set-basenames). - Make the `increment` transaction gasless by integrating with [Paymaster](/onchainkit/transaction/transaction#sponsor-with-paymaster-capabilities) - Improve the wallet connection and sign up flow with the [WalletModal](/onchainkit/wallet/wallet-modal) component - Add onchain [Identity](/onchainkit/identity/identity) so we know who added the most recent tally diff --git a/docs/get-started/deploy-smart-contracts.mdx b/docs/get-started/deploy-smart-contracts.mdx index 7554b28ad..6df2bb7cf 100644 --- a/docs/get-started/deploy-smart-contracts.mdx +++ b/docs/get-started/deploy-smart-contracts.mdx @@ -141,3 +141,4 @@ This will return the initial value of the Counter contract's `number` storage va - Use [Onchainkit](https://onchainkit.com) to connect your frontend to your contracts! Onchainkit is a library of ready-to-use React components and Typescript utilities. - Learn more about interacting with your contracts in the command line using Foundry from our [Foundry tutorial](/learn/foundry/deploy-with-foundry). +- Set a Basename for your contract using [Foundry and the Enscribe library](/learn/foundry/deploy-smart-contracts-set-basenames). diff --git a/docs/get-started/launch-token.mdx b/docs/get-started/launch-token.mdx index 103ee0fae..1de759f5d 100644 --- a/docs/get-started/launch-token.mdx +++ b/docs/get-started/launch-token.mdx @@ -147,6 +147,13 @@ Install OpenZeppelin contracts for secure, audited ERC-20 implementation: forge install OpenZeppelin/openzeppelin-contracts ``` +Install Enscribe contracts naming library for setting a Basename for your contracts: + +```bash Terminal +# Install Enscribe contracts naming library +forge install enscribexyz/enscribe +``` + ### Smart Contract Development Create your token contract using OpenZeppelin's ERC-20 implementation: @@ -157,6 +164,7 @@ pragma solidity ^0.8.19; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; +import "enscribe/Ens.sol"; /** * @title MyToken @@ -229,6 +237,9 @@ contract DeployToken is Script { initialSupply, deployerAddress ); + + // Set a Basename for the token contract assuming you have the mydomain.base.eth Basename registered on Base + Ens.setName(block.chainid, address(token), "myawesometoken.mydomain.base.eth"); // Stop broadcasting transactions vm.stopBroadcast(); @@ -261,7 +272,7 @@ Update `foundry.toml` for Base network configuration: src = "src" out = "out" libs = ["lib"] -remappings = ["@openzeppelin/=lib/openzeppelin-contracts/"] +remappings = ["@openzeppelin/=lib/openzeppelin-contracts/", "enscribe/=lib/enscribe/src/"] [rpc_endpoints] base_sepolia = "${BASE_SEPOLIA_RPC_URL}" @@ -364,6 +375,10 @@ forge script script/DeployToken.s.sol:DeployToken \ --verify ``` + +You can see your contract's Basename by visiting [Enscribe Explorer](https://app.enscribe.xyz/explore/84532/myawesometoken.mydomain.base.eth). + + The `--verify` flag automatically verifies your contract on BaseScan, making it easier for users to interact with your token. diff --git a/docs/learn/foundry/deploy-smart-contracts-set-basenames.mdx b/docs/learn/foundry/deploy-smart-contracts-set-basenames.mdx new file mode 100644 index 000000000..476ac6341 --- /dev/null +++ b/docs/learn/foundry/deploy-smart-contracts-set-basenames.mdx @@ -0,0 +1,190 @@ +--- +title: 'Foundry: Naming a smart contract' +description: A guide to help you get started with deploying your smart contracts on Base and setting Basenames for them using Foundry. +--- + +Welcome to the Base deployment quickstart guide! This comprehensive walkthrough will help you set up your environment and deploy smart contracts on Base. Whether you're a seasoned developer or just starting out, this guide has got you covered. + +## What You'll Achieve + +By the end of this quickstart, you'll be able to: + +- Set up your development environment to deploy on Base +- Deploy your smart contracts to Base and set Basenames for them + + +**Why Base?** + +Base is a fast, low-cost, builder-friendly Ethereum L2 built to bring the next billion users onchain. By following this guide, you'll join a vibrant ecosystem of developers, creators, and innovators who are building a global onchain economy. + + + +## Set Up Your Development Environment + +1. Create a new project directory + +```bash +mkdir my-base-project && cd my-base-project +``` + +2. Install Foundry, a powerful framework for smart contract development + +```bash +curl -L https://foundry.paradigm.xyz | bash +foundryup +``` + +This installs Foundry and updates it to the latest version. + +3. Initialize a new Solidity project + +```bash +forge init +``` + +Your Foundry project is now ready. You'll find an example contract in the `src` directory, which you can replace with your own contracts. For the purposes of this guide, we'll use the Counter contract provided in `/src/Counter.sol` + + +Foundry provides a suite of tools for Ethereum application development, including Forge (for testing), Cast (for interacting with the chain), and Anvil (for setting up a local node). You can learn more about Foundry [here](https://book.getfoundry.sh/). + + + +## Configure Foundry with Base + +To deploy your smart contracts to Base, you need two key components: + +1. A node connection to interact with the Base network +2. A funded private key to deploy the contract + +Let's set up both of these: + +### 1. Set up your node connection + +1. Create a `.env` file in your project's root directory +2. Add the Base network RPC URL to your `.env` file + +```bash +BASE_RPC_URL="https://mainnet.base.org" +BASE_SEPOLIA_RPC_URL="https://sepolia.base.org" +``` + +3. Load your environment variables + +```bash +source .env +``` + + +Base Sepolia is the test network for Base, which we will use for the rest of this guide. You can obtain free Base Sepolia ETH from one of the [faucets listed here](/base-chain/tools/network-faucets). + + + +### 2. Secure your private key + +1. Store your private key in Foundry's secure keystore + +```bash +cast wallet import deployer --interactive +``` + +2. When prompted enter your private key and a password. + +Your private key is stored in `~/.foundry/keystores` which is not tracked by git. + + +Never share or commit your private key. Always keep it secure and handle with care. + + + +## Setup Your Contract for Naming using Foundry Script + +We'll deploy the Counter contract using a Foundry script that will also set a Basename for the contract. First, ensure you have a Basename available to use. You can purchase a Basename from [base.org/names](https://base.org/names) or use a free Basename from the [faucets listed here](/base-chain/tools/network-faucets). + +1. Install enscribesol + +```bash +forge install enscribexyz/enscribe +``` + +2. Install openzeppelin + +```bash +forge install OpenZeppelin/openzeppelin-contracts +``` + +3. Create `remapping.txt` and add the following remappings: + +``` +enscribe/=lib/enscribe/src/ +@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/ +``` + +4. Make Counter implement Ownable + +Update your `Counter.sol` contract to inherit from `Ownable`: + +```solidity +import "@openzeppelin/contracts/access/Ownable.sol"; + +contract Counter is Ownable { + uint256 public number; + + constructor(uint256 initialCount) Ownable(msg.sender) { + number = initialCount; + } + + function setNumber(uint256 newNumber) public { + number = newNumber; + } + + function increment() public { + number++; + } +} +``` + +5. Set a primary name for the contract address in `Counter.s.sol`. We'll use `enscribesol124.abhi.basetest.eth` for this example but you should use your own basename. + +Update your deployment script to set a name for the contract: + +```solidity +import {Script} from "forge-std/Script.sol"; +import {Counter} from "../src/Counter.sol"; +import {Ens} from "enscribe/NameSetter.sol"; + +contract CounterScript is Script { + Counter public counter; + + function setUp() public {} + + function run() public { + vm.startBroadcast(); + + counter = new Counter(0); + Ens.setName(block.chainid, address(counter), "enscribesol124.abhi.basetest.eth"); + + vm.stopBroadcast(); + } +} +``` + +## Deploy Your Contracts + +Now that your environment is set up, let's deploy your contracts to Base Sepolia. + +1. Use the following command to compile and deploy your contract + +```bash +forge script ./src/Counter.s.sol:CounterScript --rpc-url $BASE_SEPOLIA_RPC_URL --account deployer +``` + +2. After successful deployment, the transaction hash will be printed to the console output + +### Verify Basename Assignment + +To ensure your Basename was assigned to the contract successfully: + +1. Copy the contract address from the output +2. Navigate to https://app.enscribe.xyz/explore/84532/enscribesol124.abhi.basetest.eth to see the details of the contract we deployed and named. + +** You've deployed your smart contracts to Base Sepolia and set Basenames for them!** \ No newline at end of file diff --git a/docs/learn/hardhat/hardhat-naming/set-basenames-with-hardhat.mdx b/docs/learn/hardhat/hardhat-naming/set-basenames-with-hardhat.mdx new file mode 100644 index 000000000..e17cae9af --- /dev/null +++ b/docs/learn/hardhat/hardhat-naming/set-basenames-with-hardhat.mdx @@ -0,0 +1,270 @@ +--- +title: Setting a Basename +slug: /set-basename-with-hardhat +description: "A tutorial that teaches how to set a Basename for a smart contract on the Base test network using Hardhat." +author: abhi +--- + +This section will guide you through setting a Basename for an Ownable smart contract on the Base test network using [Hardhat](https://hardhat.org/) and the [hardhat-enscribe](https://github.com/enscribexyz/enscribe-hardhat) plugin. + +Hardhat is a developer tool that provides a simple way to deploy, test, and debug smart contracts. The hardhat-enscribe plugin allows you to set a Basename for your smart contract. + + + +## Objectives + +By the end of this tutorial, you should be able to do the following: + +- Setup Hardhat for Base +- Create an Ownable smart contract for Base +- Compile a smart contract for Base +- Set a Basename for a smart contract on Base + + + +## Prerequisites + +### Node v18+ + +This tutorial requires you have Node version 18+ installed. + +- Download [Node v18+](https://nodejs.org/en/download/) + +If you are using `nvm` to manage your node versions, you can just run `nvm install 18`. + +### Coinbase Wallet + +In order to deploy a smart contract, you will first need a web3 wallet. You can create a wallet by downloading the Coinbase Wallet browser extension. + +- Download [Coinbase Wallet](https://chrome.google.com/webstore/detail/coinbase-wallet-extension/hnfanknocfeofbddgcijnmhnfnkdnaad?hl=en) + +### Wallet funds + +Deploying contracts to the blockchain requires a gas fee. Therefore, you will need to fund your wallet with ETH to cover those gas fees. + +For this tutorial, you will be deploying a contract to the Base Sepolia test network. You can fund your wallet with Base Sepolia ETH using one of the faucets listed on the Base [Network Faucets](https://docs.base.org/base-chain/tools/network-faucets) page. + + + +## Creating a project + +Before you can begin deploying smart contracts to Base, you need to set up your development environment by creating a Node.js project. + +To create a new Node.js project, run: + +```bash +npm init --y +``` + +Next, you will need to install Hardhat and create a new Hardhat project + +To install Hardhat, run: + +```bash +npm install --save-dev hardhat +``` + +To create a new Hardhat project, run: + +```bash +npx hardhat init +``` + +Select `Create a TypeScript project` then press _enter_ to confirm the project root. + +Select `y` for both adding a `.gitignore` and loading the sample project. It will take a moment for the project setup process to complete. + + + +## Configuring Hardhat with Base + +In order to deploy smart contracts to the Base network, you will need to configure your Hardhat project and add the Base network. + +To configure Hardhat to use Base, add Base as a network to your project's `hardhat.config.ts` file: + +```tsx +import { HardhatUserConfig } from 'hardhat/config'; +import '@nomicfoundation/hardhat-toolbox'; + +require('dotenv').config(); + +const config: HardhatUserConfig = { + solidity: { + version: '0.8.23', + }, + networks: { + // for mainnet + 'base-mainnet': { + url: 'https://mainnet.base.org', + accounts: [process.env.WALLET_KEY as string], + gasPrice: 1000000000, + }, + // for testnet + 'base-sepolia': { + url: 'https://sepolia.base.org', + accounts: [process.env.WALLET_KEY as string], + gasPrice: 1000000000, + }, + // for local dev environment + 'base-local': { + url: 'http://localhost:8545', + accounts: [process.env.WALLET_KEY as string], + gasPrice: 1000000000, + }, + }, + defaultNetwork: 'hardhat', +}; + +export default config; +``` + +### Install Hardhat toolbox + +The above configuration uses the `@nomicfoundation/hardhat-toolbox` plugin to bundle all the commonly used packages and Hardhat plugins recommended to start developing with Hardhat. + +To install `@nomicfoundation/hardhat-toolbox`, run: + +```bash +npm install --save-dev @nomicfoundation/hardhat-toolbox +``` + +### Install hardhat-enscribe + +To install `hardhat-enscribe`, run: + +```bash +npm install --save-dev @enscribe/hardhat-enscribe +``` + +### Loading environment variables + +The above configuration also uses [dotenv](https://www.npmjs.com/package/dotenv) to load the `WALLET_KEY` environment variable from a `.env` file to `process.env.WALLET_KEY`. You should use a similar method to avoid hardcoding your private keys within your source code. + +To install `dotenv`, run: + +```bash +npm install --save-dev dotenv +``` + +Once you have `dotenv` installed, you can create a `.env` file with the following content: + +``` +WALLET_KEY="" +``` + +Substituting `` with the private key for your wallet. + + + +`WALLET_KEY` is the private key of the wallet to use when deploying a contract. For instructions on how to get your private key from Coinbase Wallet, visit the [Coinbase Wallet documentation](https://docs.cloud.coinbase.com/wallet-sdk/docs/developer-settings#show-private-key). **It is critical that you do NOT commit this to a public repo** + + + +### Local Networks + +You can run the Base network locally, and deploy using it. If this is what you are looking to do, see the [repo containing the relevant Docker builds](https://github.com/base-org/node). + +It will take a **very** long time for your node to sync with the network. If you get errors that the `nonce has already been used` when trying to deploy, you aren't synced yet. + +For quick testing, such as if you want to add unit tests to the below HelloWorld contract, you may wish to leave the `defaultNetwork` as `'hardhat'`. + + + +## Compiling the smart contract + +Below is a simple Ownable smart contract written in the Solidity programming language: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import "@openzeppelin/contracts/access/Ownable.sol"; + +contract HelloWorld is Ownable { + string public helloWorld; + + constructor() Ownable(msg.sender) { + helloWorld = "Hello World!"; + } + + function setHelloWorld(string memory _helloWorld) public onlyOwner { + helloWorld = _helloWorld; + } +} +``` + +The Solidity code above defines a smart contract named `HelloWorld`. The code uses the `Ownable` interface provided by the [OpenZeppelin Contracts library](https://docs.openzeppelin.com/contracts/5.x/) to create an Ownable smart contract. + +To add the OpenZeppelin Contracts library to your project, run: + +```bash +npm install --save @openzeppelin/contracts +``` + +In your project, delete the `contracts/Lock.sol` contract that was generated with the project and add the above code in a new file called `contracts/HelloWorld.sol`. (You can also delete the `test/Lock.ts` test file, but you should add your own tests ASAP!). + +To compile the contract using Hardhat, run: + +```bash +npx hardhat compile +``` + + + +## Deploying the smart contract + +Once your contract has been successfully compiled, you can deploy the contract to the Base Sepolia test network. + +To deploy the contract to the Base Sepolia test network, you'll need to modify the `scripts/deploy.ts` in your project: + +```tsx +import { ethers } from 'hardhat'; + +async function main() { + const helloWorld = await ethers.deployContract('HelloWorld'); + + await helloWorld.waitForDeployment(); + + console.log('HelloWorld Contract Deployed at ' + helloWorld.target); +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +You'll also need testnet ETH in your wallet. See the [prerequisites](#prerequisites) if you haven't done that yet. Otherwise, the deployment attempt will fail. + +Finally, run: + +```bash +npx hardhat run scripts/deploy.ts --network base-sepolia +``` + +The contract will be deployed on the Base Sepolia test network. You can view the deployment status and contract by using a [block explorer](/base-chain/tools/block-explorers) and searching for the address returned by your deploy script. If you've deployed an exact copy of the HelloWorld contract above, it will already be verified and you'll be able to read and write to the contract using the web interface. + + + + +If you'd like to deploy to mainnet, you'll modify the command like so: + +```bash +npx hardhat run scripts/deploy.ts --network base-mainnet +``` + + + +## Setting a Basename for the smart contract + +Once the contract is deployed, you can set the Basename for the contract using the `hardhat-enscribe` plugin. + +To set the Basename for the contract, grab the deployed address and run: + +```bash +npx hardhat enscribe name --contract --network base-sepolia +``` + +You can now view the Basename set at `https://www.enscribe.xyz/explore/84532/`. \ No newline at end of file diff --git a/docs/learn/hardhat/hardhat-tools-and-testing/overview.mdx b/docs/learn/hardhat/hardhat-tools-and-testing/overview.mdx index 3c649f947..f4edfb860 100644 --- a/docs/learn/hardhat/hardhat-tools-and-testing/overview.mdx +++ b/docs/learn/hardhat/hardhat-tools-and-testing/overview.mdx @@ -57,6 +57,9 @@ By the end of these guides, you should be able to: - Use the Solidity Coverage plugin to analyze the coverage of your test suite - Increase the coverage of your test suite +### Contract Naming +- Use Hardhat Enscribe plugin to set a Basename for your contract + --- ## Prerequisites