Skip to Content
Advanced Mini CoursesAI Builder: Create Smart Contracts using Aider and Gemini-2.5-pro

From Zero to dApp Hero: Building a Full-Stack Web3 Project with AI (Aider + Gemini)

Video

Loading video player...

Can AI Really Build a Web3 App from Scratch?

Ever felt overwhelmed by the sheer complexity of building a full-stack decentralized application? Smart contracts, frontend frameworks, wallet integration, deployment scripts… it’s a lot! You’ve probably heard the hype about AI coding assistants like GitHub Copilot, but what about tools specifically designed for iterative development across your entire codebase?

What if you could have an AI pair programmer, powered by a cutting-edge model like Google’s Gemini 2.5 Pro, sitting right in your terminal, ready to refactor your Solidity, build your Next.js frontend, write tests, and even manage your Git commits? Sounds like science fiction?

It’s not. Meet Aider.

Aider is an AI coding assistant that works directly with your local Git repository. Unlike simple autocompletion tools, Aider understands your entire project context, allowing you to prompt complex changes across multiple files. Combined with a powerful LLM like Gemini 2.5 Pro, it becomes a formidable tool for accelerating Web3 development.

But is it all hype? Can you really trust AI to build secure smart contracts and functional frontends? Does it eliminate the need for developer expertise, or just change the workflow?

In this tutorial, we’re putting it to the test.

We’ll embark on a journey, mirroring a real development session, to build a complete ERC20 token sale dApp from the ground up, relying heavily on Aider and Gemini 2.5 Pro. We’ll start with an empty directory and prompt our way through:

  • Setting up a Foundry project for our smart contracts.
  • Developing an ERC20 token (AIDER/AID) using OpenZeppelin v5.
  • Implementing a token sale mechanism (buy 1 AID for 0.1 ETH).
  • Writing tests and deployment scripts.
  • Debugging AI-generated code (because yes, AI makes mistakes!).
  • Building a sleek Next.js 15 frontend with Tailwind CSS and Shadcn UI.
  • Integrating RainbowKit for wallet connections.
  • Deploying locally to Anvil and interacting with the dApp.

This isn’t just about the final code; it’s about the process. You’ll witness the prompts, the AI’s responses, the inevitable errors, and the debugging steps required. We’ll explore the strengths and weaknesses of using AI for Web3 development, giving you a realistic perspective on how these tools can augment, but not entirely replace, your skills.

What You’ll Learn:

  • How to set up and use Aider with Gemini 2.5 Pro in a Docker environment.
  • Structuring a full-stack Web3 project (Next.js + Foundry).
  • Prompting Aider for smart contract development (ERC20, token sale logic).
  • Debugging Solidity code generated by AI.
  • Using Foundry for testing, building, and local deployment (Anvil).
  • Prompting Aider for Next.js frontend development with RainbowKit integration.
  • Connecting a frontend to a locally deployed smart contract.
  • The practical workflow, benefits, and pitfalls of AI-assisted Web3 development.

Ready to see if AI can live up to the promise and build a working dApp? Let’s fire up Aider and start coding!

1. Setting the Stage: Project Setup and Tools

Before we unleash the AI, we need to prepare our development environment. We’ll structure our project with the smart contracts nested inside the main Next.js application directory. This allows us to easily share ABIs and deployment information later.

Prerequisites:

Step 1: Project Structure & Git Initialization

First, create your main project directory and initialize Git:

mkdir aider-gemini-dapp cd aider-gemini-dapp git init

Step 2: Foundry Setup for Contracts

Now, create a subdirectory for the smart contracts and initialize a Foundry project within it.

mkdir contracts cd contracts forge init --no-commit cd ..
  • forge init creates the basic Foundry structure (src, test, script, lib, foundry.toml).
  • --no-commit prevents forge init from creating its own Git commit, as we want the main project directory to be the single Git repository. Foundry will automatically add forge-std as a Git submodule.

Your structure should look like this:

aider-gemini-dapp/ ā”œā”€ā”€ .git/ ā”œā”€ā”€ contracts/ │ ā”œā”€ā”€ lib/ │ │ └── forge-std/ │ ā”œā”€ā”€ script/ │ │ └── Counter.s.sol │ ā”œā”€ā”€ src/ │ │ └── Counter.sol │ ā”œā”€ā”€ test/ │ │ └── Counter.t.sol │ ā”œā”€ā”€ .gitignore │ └── foundry.toml └── .gitmodules
Git Submodules

Foundry uses Git submodules to manage dependencies like forge-std and, later, OpenZeppelin. The .gitmodules file in your root directory tracks these submodules.

Step 3: Setting up Aider with Docker and Gemini

We’ll run Aider inside a Docker container to keep things clean. Aider’s documentation provides the necessary Docker commands.

  1. Pull the Aider Docker Image:

    docker pull paulgauthier/aider-full
  2. Prepare API Key: Create a file named .env in your project’s root directory (aider-gemini-dapp) and add your Google AI API key:

    # .env GEMINI_API_KEY=YOUR_GOOGLE_AI_API_KEY_HERE

    Important: Add .env to your root .gitignore file to avoid committing your API key!

    echo ".env" >> .gitignore git add .gitignore git commit -m "Add .env to gitignore"
  3. Run Aider: Execute the following command from your project’s root directory (aider-gemini-dapp). This mounts your current directory into the container’s /app directory and configures Aider to use Gemini 2.5 Pro.

    docker run --rm -it \ -v $(pwd):/app \ -e GEMINI_API_KEY \ --env-file .env \ paulgauthier/aider-full \ --model gemini/gemini-2.5-pro
    • --rm: Removes the container when it exits.
    • -it: Runs in interactive mode.
    • -v $(pwd):/app: Mounts your project directory.
    • --env-file .env: Loads the API key from the .env file.
    • --model gemini/gemini-2.5-pro-latest: Specifies the Gemini model (ensure you have access). Here you would put sonnet or other models if you have access ()

    Aider should start, potentially asking to add its cache files to .gitignore. Type y and press Enter.

    Added .aider* to .gitignore. Added the change to git. Continue? [y/N/a] y

You are now inside the Aider chat interface, ready to give instructions!

2. Prompting the Smart Contract: From Counter to Token Sale

Our Foundry project starts with a default Counter contract. We need to tell Aider to replace this with our desired AiderToken ERC20 contract and its sale logic.

Step 1: Adding Initial Files to Aider Chat

First, we need to make Aider aware of the existing contract files. Use the /add command within the Aider chat:

/add contracts/src/Counter.sol contracts/script/Counter.s.sol contracts/test/Counter.t.sol contracts/README.md

Aider will confirm the files have been added to the chat context.

Step 2: The Core Smart Contract Prompt

Now, let’s give Aider the main instruction. We want it to:

  • Replace the Counter contract with an ERC20 token named ā€œAIDERā€ (symbol ā€œAIDā€).
  • Use OpenZeppelin Contracts v5.
  • Implement a buyTokens function where 1 AID costs 0.1 ETH.
  • Make the contract Ownable.
  • Update the deployment script (Counter.s.sol -> AiderToken.s.sol).
  • Update the tests (Counter.t.sol -> AiderToken.t.sol).
  • Update the contracts/README.md to describe the new token.

Here’s the prompt (similar to the one used in the video):

I'm working on this new token project and I just set up an empty foundry project using `forge init`. The goal is to change this default Counter contract to an OpenZeppelin Contracts v5 ERC20 token. The token should be named "AIDER" with the symbol "AID" and use the standard 18 decimals. It should be Ownable. We also want to sell the token directly from the contract. Add a payable function `buyTokens` where users can send ETH to buy tokens at a fixed price of 0.1 ETH per 1 AID token. Your task is to: 1. Replace the contents of `contracts/src/Counter.sol` with the new `AiderToken.sol` contract implementing the ERC20 token and the `buyTokens` functionality. 2. Rename `contracts/src/Counter.sol` to `contracts/src/AiderToken.sol`. 3. Update the deployment script `contracts/script/Counter.s.sol` to deploy the `AiderToken` instead. Rename it to `contracts/script/AiderToken.s.sol`. 4. Update the tests in `contracts/test/Counter.t.sol` to properly test the `AiderToken` (name, symbol, decimals, ownership, and the `buyTokens` function). Rename it to `contracts/test/AiderToken.t.sol`. 5. Update the `contracts/README.md` file to describe this new AiderToken project and its features, removing the Counter information. 6. Make sure to include OpenZeppelin v5 contracts as a dependency.

Aider will analyze the request, plan the changes, and likely ask for confirmation before proceeding. It might also ask to run commands, like installing OpenZeppelin.

Step 3: Handling Dependencies (OpenZeppelin)

Aider might suggest running forge install @openzeppelin/contracts. However, running commands directly inside the Aider Docker container might fail if Foundry isn’t installed within the container image.

It’s often better to run Foundry commands in a separate terminal on your host machine (where Foundry is installed).

  • Aider: When Aider asks to run forge install, tell it no.

  • Your Terminal (Host): Navigate to the contracts directory and run the install command yourself:

    cd contracts forge install OpenZeppelin/openzeppelin-contracts@v5.0.2 --no-commit # Add forge-std if it wasn't added automatically or you need a specific version # forge install foundry-rs/forge-std --no-commit cd ..
    • --no-commit prevents Forge from creating a commit for the dependency installation.
    • Specify the version (@v5.0.2) for consistency.
  • Aider: After installing manually, tell Aider you’ve handled the dependency. You might need to re-add the foundry.toml file or tell Aider to /update-repo-map if it seems unaware of the new library files in contracts/lib.

Aider will then proceed to generate the code changes based on your prompt. Review the proposed changes carefully.

3. Debugging the AI: Refining the Smart Contract

AI code generation is rarely perfect on the first try, especially with the nuances of Solidity. Expect to iterate and debug.

Common Issues & Refinements (Based on Video):

  1. Initial buyTokens Logic: Aider’s first version might have flaws:

    • Incorrect Payment Handling: It might initially require the exact payment amount instead of accepting more and refunding.
    • Dependency Issues: It might try to use external libraries unnecessarily (like foundry-devops-tools mentioned in the video) for deployment scripts.
    • Visibility: It might mark buyTokens as external when it needs to be public to be called by the receive function later.
  2. Adding receive(): The initial prompt didn’t explicitly ask for a receive function to allow direct ETH transfers. We need to add this.

  3. Decimal Calculation Bug: A critical error often made by AI is forgetting to handle token decimals correctly when calculating how many tokens to mint based on ETH received. msg.value / TOKEN_PRICE gives the number of tokens, but _mint expects the amount in the base unit (amount * 10^decimals).

  4. Test Failures: Tests written by AI might fail due to:

    • Incorrect setup (using sender instead of vm.prank).
    • Incorrect assertions (especially around balances after refunds, due to gas costs).
    • Not covering edge cases introduced by refinements.

The Debugging Loop with Aider:

This is where Aider shines. Instead of manually fixing everything, you can feed the compiler errors or test failures back to Aider.

  • Compiler Errors: If forge build fails in your terminal, copy the error message and paste it into the Aider chat.

    I ran `forge build` in the contracts directory and got this error: <paste compiler error here> Can you fix this?
  • Refining Logic: Ask Aider to modify the contract based on your requirements.

    Please change the `buyTokens` function in `AiderToken.sol`: 1. It should accept any `msg.value` as long as it's greater than or equal to `TOKEN_PRICE`. 2. Calculate the number of tokens to mint based on `msg.value / TOKEN_PRICE`. 3. Calculate any `refundAmount = msg.value % TOKEN_PRICE`. 4. Mint the correct amount of tokens in base units (considering 18 decimals). 5. If `refundAmount` is greater than 0, send it back to `msg.sender`. 6. Add necessary error handling (e.g., for insufficient payment or failed refund). Also, add a `receive() external payable` function that simply calls `buyTokens()`. Update the tests accordingly.
  • Test Failures: If forge test fails, provide the failure output.

    The tests are failing with this message: <paste test failure output here> It seems like the token amount calculation or assertion is wrong. Can you fix the `AiderToken.sol` contract and the `AiderToken.t.sol` test?

    Aider might identify the decimal issue or problems with assertions. For gas-related assertion failures (like checking exact ETH balance after refund), you might need to adjust tests to check for ranges (>= or <=) instead of exact equality.

Key Fixes Applied (Based on Video Outcome):

  • Visibility: buyTokens changed from external to public.
  • Refund Logic: Implemented correct calculation and refund transfer.
  • Decimal Calculation: Correctly multiplied tokensToMint by 10**decimals() before calling _mint.
  • receive() Added: Included the receive function.
  • Tests Updated: Adjusted tests to use vm.prank and handle refund assertions more robustly.

Final AiderToken.sol (Example):

// SPDX-License-Identifier: MIT // Compatible with OpenZeppelin Contracts v5.0.2 pragma solidity ^0.8.20; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; contract AiderToken is ERC20, Ownable { uint256 public constant TOKEN_PRICE = 0.1 ether; // Price per token in ETH (wei) error AiderToken__InsufficientPayment(); error AiderToken__TransferFailed(); constructor(address initialOwner) ERC20("AIDER", "AID") Ownable(initialOwner) { // No initial supply is minted upon deployment in this version. // Tokens are only created when purchased via buyTokens. } /** * @notice Allows users to buy tokens by sending ETH. * @dev Mints new tokens to the sender based on the ETH sent and the TOKEN_PRICE. * Requires msg.value to be at least TOKEN_PRICE. * Refunds any ETH sent in excess of the cost of whole tokens. */ function buyTokens() public payable { // Changed from external to public if (msg.value < TOKEN_PRICE) { revert AiderToken__InsufficientPayment(); } uint256 tokensToMint = msg.value / TOKEN_PRICE; // Number of tokens (e.g., 5) // *** Critical Fix: Calculate amount in base units *** uint256 amountToMint = tokensToMint * (10**decimals()); // Amount in base units (e.g., 5 * 10**18) uint256 refundAmount = msg.value % TOKEN_PRICE; _mint(msg.sender, amountToMint); // Mint the correct amount in base units // Refund excess ETH if any if (refundAmount > 0) { (bool success, ) = msg.sender.call{value: refundAmount}(""); if (!success) { revert AiderToken__TransferFailed(); // Note: In a real-world scenario, consider the implications // if the refund fails (e.g., user contract cannot receive ETH). // The tokens are already minted at this point. } } } /** * @notice Allows direct ETH transfers to the contract to buy tokens. * @dev Calls the buyTokens function internally. */ receive() external payable { buyTokens(); } /** * @notice Allows the owner to withdraw the accumulated ETH balance from the contract. */ function withdraw() external onlyOwner { (bool success, ) = owner().call{value: address(this).balance}(""); if (!success) { revert AiderToken__TransferFailed(); } } // The decimals function is inherited from ERC20 and defaults to 18. }

Keep iterating with forge build and forge test in your terminal and feeding results back to Aider until the contract compiles cleanly and all tests pass. Remember to commit the changes using Aider (y when prompted) or manually.

4. Building the Frontend with AI

With the smart contract ready, let’s build the user interface using Next.js, Tailwind, Shadcn UI, and RainbowKit.

Step 1: Initialize Next.js Project

In your root project directory (aider-gemini-dapp), run the Next.js setup command:

npx create-next-app@latest . --ts --eslint --tailwind --no-src-dir --app --import-alias "@/*"
  • .: Installs in the current directory.
  • --ts: TypeScript.
  • --eslint: ESLint setup.
  • --tailwind: Tailwind CSS setup.
  • --no-src-dir: Doesn’t use a separate src directory.
  • --app: Uses the App Router.
  • --import-alias "@/*": Configures path alias.

This will create the necessary Next.js files (app, public, package.json, config files, etc.) alongside your existing contracts directory.

Step 2: Install Shadcn UI

Initialize Shadcn UI for pre-built components:

npx shadcn-ui@latest init

Accept the defaults (or customize as needed). This will create components.json and potentially components/ui and lib/utils.ts.

Step 3: Install Web3 Dependencies

Install RainbowKit, Wagmi, and Viem:

npm install @rainbow-me/rainbowkit wagmi viem@2.x @tanstack/react-query

Step 4: Configure RainbowKit/Wagmi Providers

We need to wrap our application with the necessary Web3 providers. Aider can help create this wrapper.

  • Add Files to Aider: Make Aider aware of the new frontend structure.

    /add app/layout.tsx app/page.tsx package.json tsconfig.json next.config.ts tailwind.config.ts postcss.config.mjs globals.css
  • Prompt for Provider Setup:

    I have installed Next.js, Tailwind, Shadcn UI, RainbowKit, Wagmi, Viem, and @tanstack/react-query. Please create a new provider component file, `app/providers.tsx`, that sets up the Wagmi config and wraps children with `WagmiProvider`, `QueryClientProvider`, and `RainbowKitProvider`. Configure it for the Anvil local development network (chain id 31337) and potentially Sepolia for later use. Use a placeholder WalletConnect Project ID for now. Then, update `app/layout.tsx` to import and use this `Providers` component to wrap the main content. Make sure the layout includes the necessary RainbowKit CSS import.

Aider should generate app/providers.tsx and modify app/layout.tsx. You’ll need to replace 'YOUR_PROJECT_ID' in providers.tsx with your actual WalletConnect Project ID if you plan to use WalletConnect features.

Step 5: Prompting the Main Page UI

Now, let’s ask Aider to create the main token sale interface in app/page.tsx.

Okay, the providers are set up. Now, please modify the main page component in `app/page.tsx`. Create a visually appealing token sale page using Tailwind CSS and Shadcn UI components (like `Button` and `Alert`). The page should: 1. Display a title like "AIDER Token Sale". 2. Show the price (0.1 ETH per AID). 3. Include a RainbowKit `<ConnectButton />`. 4. If the wallet is connected: - Show a "Buy 1 AID Token for 0.1 ETH" button (use Shadcn Button). - When clicked, this button should trigger a transaction using Wagmi's `useWriteContract` hook to call the `buyTokens` function on our deployed `AiderToken` contract. Remember to send 0.1 ETH as the `value`. - Use the contract address deployed locally (we'll paste the actual address later, use a placeholder like "0x5FbDB2315678afecb367f032d93F642f64180aa3" for now). Define the minimal ABI needed for `buyTokens`. - Disable the button while the transaction is pending or confirming. - Use `useWaitForTransactionReceipt` to track the transaction status. - Display status messages using Shadcn `Alert` components: - Show the transaction hash while waiting for confirmation. - Show a success message upon confirmation. - Show an error message if the transaction fails (display `error.shortMessage`). 5. If the wallet is not connected, display a message prompting the user to connect. Make the overall page look cool and web3-like, maybe with a gradient background. Include a simple footer mentioning the tech stack.

Aider will generate the code for app/page.tsx. Review it carefully.

Step 6: Add Required UI Components

Aider might use Shadcn components like Button and Alert that haven’t been explicitly added to your project yet. Add them using the Shadcn CLI in your terminal:

npx shadcn-ui@latest add button alert

5. Deployment and Interaction

Now, let’s deploy the contract locally and interact with the frontend.

Step 1: Start Local Blockchain (Anvil)

Open a new terminal window, navigate to your project root, and start Anvil:

anvil

Anvil will start, displaying available accounts and private keys. Keep this terminal running.

Step 2: Deploy the Smart Contract

  1. Set Private Key: In another terminal window, set the PRIVATE_KEY environment variable using one of the keys provided by Anvil.

    # Example for Linux/macOS/WSL export PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 # Example for Windows Command Prompt # set PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 # Example for Windows PowerShell # $env:PRIVATE_KEY = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
  2. Run Deployment Script: Navigate to the contracts directory and run the Foundry deployment script:

    cd contracts forge script script/AiderToken.s.sol:DeployScript --rpc-url http://127.0.0.1:8545 --private-key $PRIVATE_KEY --broadcast cd ..
    • Replace AiderToken.s.sol:DeployScript if Aider named the script or contract differently.
    • Foundry will compile the contract and execute the script, deploying AiderToken.
    • Copy the deployed contract address from the output.

Step 3: Update Frontend Contract Address

Paste the deployed contract address into app/page.tsx, replacing the placeholder:

// app/page.tsx // ... // --- Contract Configuration --- const contractAddress = "YOUR_DEPLOYED_CONTRACT_ADDRESS_HERE"; // <-- PASTE ADDRESS HERE // ...

You can even ask Aider to do this:

/edit app/page.tsx

Then provide the instruction:

Please replace the placeholder contract address "0x5FbDB2315678afecb367f032d93F642f64180aa3" with the actual deployed address: YOUR_DEPLOYED_CONTRACT_ADDRESS_HERE

Step 4: Configure MetaMask

  1. Add Anvil as a custom network in MetaMask (RPC URL: http://127.0.0.1:8545, Chain ID: 31337).
  2. Import one of the Anvil accounts into MetaMask using its private key. Ensure this account has ETH (Anvil accounts start with 10000 ETH).

Step 5: Run the Frontend

Start the Next.js development server from your project root:

npm run dev

Open your browser to http://localhost:3000.

Step 6: Interact!

  1. Connect your MetaMask wallet (ensure you’re on the Anvil network and using the imported Anvil account).
  2. Click the ā€œBuy 1 AID Tokenā€ button.
  3. MetaMask will pop up asking you to confirm the transaction (sending 0.1 ETH).
  4. Confirm the transaction.
  5. The frontend should display the transaction hash and then a success message once confirmed on Anvil (which is usually instant).

You’ve successfully built and interacted with a full-stack dApp using AI assistance!

6. Reflections: AI as a Web3 Co-Pilot

This journey demonstrates the potential and the current reality of using AI tools like Aider and Gemini for Web3 development:

Strengths:

  • Speed: AI significantly accelerates boilerplate setup, frontend generation, and implementing standard patterns.
  • Context Awareness: Aider’s ability to work across the whole repo is powerful for refactoring and feature implementation.
  • Frontend Proficiency: LLMs trained on vast amounts of web data excel at generating React/Next.js code, integrating libraries like RainbowKit, and styling with Tailwind.
  • Debugging Assistance: Feeding errors back to the AI can often lead to quick fixes, especially for common syntax or logic errors.

Weaknesses/Challenges:

  • Solidity Nuances: AI can struggle with subtle Solidity concepts like decimal handling, gas optimization, security patterns (reentrancy), and the exact behavior of EVM features. Human oversight is critical.
  • Hallucinations/Incorrect Assumptions: AI might invent libraries (like foundry-devops-tools) or make incorrect assumptions about function visibility or testing setups (sender vs prank).
  • Over-Reliance Risk: Blindly accepting AI code without understanding and testing is dangerous, especially for smart contracts holding value.
  • Debugging Still Required: You still need strong debugging skills to identify why AI code fails and guide the AI towards the correct solution. AI is a powerful assistant, not a replacement for understanding.
  • Prompt Engineering: The quality of the output heavily depends on the clarity and detail of your prompts.

Conclusion:

AI tools like Aider + Gemini are transformative co-pilots for Web3 development. They can handle much of the heavy lifting, especially on the frontend, allowing developers to focus on core logic, security, and architecture. However, they are not magic wands. Deep understanding of Solidity, security best practices, and the underlying blockchain principles remains essential. Use AI to accelerate, augment, and learn, but always verify, test rigorously, and remain the captain of your ship. Happy building!

Last updated on