Venture-Miner / Linea-Dev-Cook-Off-Mini-Bootcamp

Material for the Linea Dev Cook-Off Mini-Bootcamp
GNU General Public License v3.0
9 stars 2 forks source link

Linea Dev Cook-Off Mini-Bootcamp

Material for the Linea Dev Cook-Off Mini-Bootcamp

Join our Academy Telegram Group to participate in our future workshops and bootcamps.

Part 1: Smart Contract Basics

Smart Contract Basics

Kickstart your blockchain journey with our Linea Dev Cook-Off series!

This tutorial is your gateway to mastering smart contract development using Solidity. Perfect for beginners or as a refresher, we'll guide you through everything from the basics of Solidity syntax to deploying your first ERC20 contract on Linea.

What You'll Learn:

Prerequisites

Getting Started

  1. Complete the Setup your Wallet guide to interact with Linea
  2. Follow the Fund your accounts guide to add some testnet tokens to your wallet
  3. Follow the Remix guide to deploy your first sample smart contract

Using Remix

  1. Visit the Documentation to learn the main features of Remix for smart contract development
  2. Create a new Workspace for this tutorial using the Remix Default option
  3. Use the File Explorer to find and open a file named 1_Storage.sol
  4. Use the Solidity Compiler to compile the smart contract that is open in the editor
    • Make sure the compiler version is set to 0.8.19 for this tutorial, since we are going to deploy the contracts on Linea
    • It's advised to turn on the Auto compile option to automatically compile the contract whenever you make changes
  5. Use the Deploy & Run Transactions tab to deploy the compiled smart contract
    • You can use the default Virtual Machine environment to test deploying and interacting with the smart contracts in a quick and practical way, even if you don't have testnet tokens
  6. Connect your browser wallet to Remix by selecting the Injected Web3 environment
    • Make sure the environment is set to Injected Web3 and the account is connected to your wallet (e.g., Metamask)
    • You can use the Deploy button to deploy the contract
      • Differently from the Virtual Machine environment, you will need testnet tokens to deploy the contract, and you will be prompted to confirm the transaction on your wallet
  7. Interact with the deployed contract using the Deployed Contracts section

Introduction to Solidity in Practice

  1. Visit the Solidity Documentation

  2. Using Remix, create a new file named FrogJump.sol

  3. Put an SPDX-License-Identifier at the top of the file and a pragma statement to specify the compiler version according to the Layout of a Solidity Source File specifications

  4. Plan the Structure of the contract

    • The deployer should deploy the contract and set a name to the frog
    • Anyone should be able to call a function to get the name of the frog
  5. Create a contract definition for the FrogJump contract

  6. Add a State Variable named name of type string, and put it as public Visibility to allow anyone to easily read it

    • Marking a state variable as public automatically creates a Getter function for it
    • Marking a state variable as public doesn't allow writing to it directly from outside of this contract, like in other OOP languages
  7. Create a Constructor function to set the name of the frog

    • The constructor should receive a string parameter and set the name state variable
    • Solidity requires us to pick a data location for passing strings as parameters, and we should use memory for this case
      • You can read more about it here and here
    • Your code should look like this:

      // SPDX-License-Identifier: MIT
      pragma solidity 0.8.19;
      
      contract FrogJump {
       string public name;
      
       constructor(string memory name_) {
           name = name_;
       }
      }
  8. Compile the contract using Remix

  9. Deploy to a Virtual Machine environment and test the contract

  10. Append the contract to add a jumps state variable

    • The jumps state variable should be an Unsigned Integer (uint256) type and of public visibility
  11. Append the contract to add a jump function

  12. Implement the jump function

    • The jump function should increment the jumps state variable by one every time it is called
    • Your code should look like this:

      // SPDX-License-Identifier: MIT
      pragma solidity 0.8.19;
      
      contract FrogJump {
       string public name;
       uint public jumps;
      
       constructor(string memory name_) {
           name = name_;
       }
      
       function jump() public {
           jumps++;
       }
      }

Solidity Advanced Concepts

  1. Creating an Interface for IFrog and IJumper

    // SPDX-License-Identifier: MIT
    pragma solidity 0.8.19;
    
    interface IFrog {
       function name() external view returns (string memory);
       function jumps() external view returns (uint256);
    }
    
    interface IJumper {
       function jump() external; 
    }
    
    contract FrogJump is IFrog, IJumper {
       string public name;
       uint256 public jumps;
    
       constructor(string memory _name) {
           name = _name;
       }
    
       function jump() public {
           jumps++;
       }
    }
  2. Create another contract named PayFrogJump that inherits from IFrog and IJumper

  3. Create a Constant named PRICE of type uint256 and set it to 1000000000000000000

    • Alternatively, you can use the 1 ether unit to set the value in a more readable way
  4. Make the jump function Payable

  5. Create an IPayableJumper interface similar to IJumper but sets the jump function as payable

  6. Modify the jumps increment to be a function of the amount of Ether sent to the function

    • You can use the msg.value transaction property to get the amount of Ether sent
      • The best practice is to use a Requirement (require) statement to check if the amount of Ether sent is equal to the PRICE constant, or an exact multiple of it
    • Use a division to calculate the number of jumps based on the amount of Ether sent
      • This is not a good practice since the division may result in a remainder, that will be rounded towards zero
      • We are doing this way to visualize the problem in practice
    interface IPayableJumper {
       function jump() external payable; 
    }
    
    contract PayFrogJump is IFrog, IPayableJumper {
       string public name;
       uint256 public jumps;
       uint256 public constant PRICE = 1 ether;
    
       constructor(string memory _name) {
           name = _name;
       }
    
       function jump() public payable {
           jumps += msg.value / PRICE;
       }
    }
  7. Compile and deploy the PayFrogJump contract using Remix

  8. Test the contract in a Virtual Machine environment by sending some Ether to the jump function

    • Remember to choose the right contract in the Contract dropdown before deploying
    • Input a number of Ether that is a multiple of the PRICE constant in the Value field and select Ether in the unit dropdown before clicking in the red jump button
      • You should notice the jumps value increasing by the amount of Ether sent divided by the PRICE constant
    • If you send an amount of Ether that is not a multiple of the PRICE constant, the division will result in a remainder that will be rounded towards zero
      • For example, if you send 1.5 ether (1500000000000000000 wei ), the division will result in 1, and the jumps value will increase by 1
      • Another extreme example, if you send 999999999999999999 wei, the division will result in 0, and the jumps value will not increase, even though you sent almost 1 ether to the contract

Deploying on Linea

  1. Change the PRICE constant to 0.001 ether or lower in the PayFrogJump contract
    • Since we haven't coded an withdraw function, we will not be able to get the Ether back from the contract, so it's better to use a lower value for testing and avoid running out of testnet tokens
  2. Compile the PayFrogJump contract using Remix
  3. Deploy the contract to Linea using the Injected Web3 environment
    • Confirm that you are connected to the Linea Sepolia testnet
      • You should see Custom (59141) network under the Environment dropdown in Remix
    • Make sure you have some testnet tokens in your wallet
    • Confirm the transactions on your wallet when prompted
  4. You can view the status of your transaction on the Linea Sepolia Explorer

Using Tokens

  1. Get to know the Ethereum Improvement Proposals and the Application-level standards and conventions for Ethereum

  2. Check the ERC-20: Token Standard

  3. Create a new ERC20 compliant contract named FrogToken

    • Instead of creating a new contract from scratch, we will use the OpenZeppelin Contracts library to create an ERC20 token
    • Remix has a tool for creating workspaces with contract templates for OpenZeppelin Contracts
    • When creating a new workspace, select the ERC20 option under the OpenZeppelin section, and then leave all options as default
  4. Rename the MyToken.sol contract to FrogToken.sol

  5. Change the code of the FrogToken contract to set the name and symbol as FrogToken and FROG, respectively

  6. Implement a premint feature in contract to set the initial supply

    • You can use the Contracts Wizard to quickly generate the code for this smart contract
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.19;
    
    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
    import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
    
    contract FrogToken is ERC20, ERC20Permit {
       constructor() ERC20("FrogToken", "FROG") ERC20Permit("FrogToken") {
           _mint(msg.sender, 1000 * 10 ** decimals());
       }
    }
  7. Compile the FrogToken contract using Remix

  8. Deploy the contract to Linea using the Injected Web3 environment

  9. Add the FrogToken contract to your wallet

    • You can use the + Import Tokens feature in Metamask to add the FrogToken contract to your wallet
    • You will need the Token Address to add the token to your wallet
      • You can find the Token Address in the Deployed Contracts section in Remix, and also in your past transactions on the Linea Sepolia Explorer
  10. Interact with the token by sending to other wallets, checking the balance, and approving transactions

Part 2: Build an E2E Dapp with ScaffoldETH

Build an E2E Dapp with ScaffoldETH

Unlock the potential of dApp development for the Linea Dev Cook-Off with Scaffold ETH!

This tutorial covers everything from blockchain interaction and Linea integration to deploying smart contracts and crafting user interfaces.

What You'll Learn:

Prerequisites for ScaffoldETH

  1. Install Git CLI

  2. Install Yarn and learn how to use it

  3. Install VSCode and learn how to use it

Setting up our development environment

Recommendation: Before starting, make sure that you have the correct version of Node installed in your system.

You can check your current version by running node -v in your terminal.

# For Linux/MacOS
nvm install --lts
...
nvm use --lts
...
node -v
v20.11.1

Suggestion: use nvm-windows from Corey Butler's community package for Windows.

# For windows
nvm install lts
...
nvm use lts
...
node -v
v20.11.1

Getting Started with ScaffoldETH-2

  1. Clone the ScaffoldETH repository

    git clone https://github.com/scaffold-eth/scaffold-eth-2.git
    cd scaffold-eth-2
  2. Install the dependencies

    yarn install
  3. Start the local blockchain

    yarn chain
  4. Deploy the contracts

    Suggestion: since your terminal is busy running the local blockchain, you can open a new terminal tab or window to run the next commands

    yarn deploy
  5. Start the frontend

    yarn start
    • You should see the frontend running at http://localhost:3000/

Using ScaffoldETH-2 for dApp Development

  1. Import your contracts to the ScaffoldETH project

    • Create a new file in the packages/hardhat/contracts directory and paste the FrogJump.sol contract code from previous lesson in it
  2. Create a deployment script for your contract

    • Create a new file named 01_deploy_frog.ts in the packages/hardhat/deploy directory and paste the following code in it
    const deployFrogJump: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
     const { deployer } = await hre.getNamedAccounts();
     const { deploy } = hre.deployments;
     await deploy("FrogJump", {
       from: deployer,
       args: ["Froggy"],
       log: true,
       autoMine: true,
     });
    };
    
    export default deployFrogJump;
  3. Change the version settings for the solidity compiler in the hardhat.config.ts to be 0.8.19 (line 24)

    • You can find this file in the packages/hardhat directory
  4. Deploy the FrogJump contract and interact with it in the frontend using the debugger page

Building a dApp with ScaffoldETH-2

  1. Visit Speedrun Ethereum
  2. Follow the Challenge #0: 🎟 Simple NFT Example
  3. Replace the nftsMetadata.ts file under packages/nextjs/utils/simpleNFT with the file in this repository
    • Credits to the Efrogs maintainers for the NFT Collection and Element Market for hosting the images
    • You may want to edit the NFTCard.tsx component under packages/nextjs/components/simpleNFT folder to display the frog images correctly
      • For example, you can change the className of the NFT Image to display a squared box by using className="h-60 w-60" (read more about this in the Tailwind docs)
  4. Complete the challenge and deploy your dApp to Linea Sepolia testnet
  5. Verify your contract
  6. View your collection in Testnets Opensea
  7. (Optional) Deploy your dApp to a hosting service like Vercel or similar