Bitroot
  • Bitroot Beginner’s Guide
    • What is Blockchain?
    • Why Use Blockchain?
    • Why Choose Bitroot?
  • About Bitroot
  • Core Products and Solutions
    • Bitroot Protocol Layer
    • BitrootNetwork Parallel Public Chain
    • Bitroot CeDeFi
  • Parallel Architecture and Technical Principles
  • Developer documentation
    • EVM(general)
    • EVM with Hardhat
    • EVM with Foundry
  • Reference
    • Bitroot's EVM RPC
    • Transactions
    • Viewing Tokens in MetaMask
  • Divergence from Ethereum
  • Product Manual and User Guide
    • Bitroot test network information
    • Bitroot Testnet Test Coin Claim
    • Add Bitroot network information
    • Swap
    • Adding Liquidity and Remove Liquidity
  • Token economic model and governance
    • Token issuance and distribution
    • Community Governance and Decision-making Mechanism
  • Participation in ecological co-construction
    • User participation
    • Developer Participation
  • Community, Ecology and Partners
  • Roadmap and future planning
  • Wallets
  • Block Explorers
  • FAQ
  • Brand Kit
  • Bitroot Official Link
Powered by GitBook
On this page
  1. Developer documentation

EVM with Foundry

PreviousEVM with HardhatNextReference

Last updated 1 month ago

Bitroot EVM Smart Contract Development with Foundry

Since Bitroot is an EVM compatible chain, existing EVM tooling like or other could be re-used.

In this example we will be using .

Install the by following this .

Create a new project following the .

Also make sure you have a wallet on Bitroot network.

Once project is created, tweak the contract code to the following, by adding a getCounter function:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;
 
contract Counter {
    uint256 public number;
 
    function setNumber(uint256 newNumber) public {
        number = newNumber;
    }
 
    function increment() public {
        number++;
    }
 
    function getCount() public view returns (uint256) {
        return number;
    }
}
 

And the test code to the following:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;
 
import {Test, console} from "forge-std/Test.sol";
import {Counter} from "../src/Counter.sol";
 
contract CounterTest is Test {
    Counter public counter;
 
    function setUp() public {
        counter = new Counter();
        counter.setNumber(0);
    }
 
    function test_Increment() public {
        counter.increment();
        assertEq(counter.number(), 1);
    }
 
    function testFuzz_SetNumber(uint256 x) public {
        counter.setNumber(x);
        assertEq(counter.number(), x);
    }
 
    function test_GetCount() public {
        uint256 initialCount = counter.getCount();
        counter.increment();
        assertEq(counter.getCount(), initialCount + 1);
    }
}

Run the tests with the following command:

$ forge test

If tests pass, deploy the contract to the Bitroot chain with the following command:

$ forge create --rpc-url $BITROOT_NODE_URI --mnemonic $MNEMONIC src/Counter.sol:Counter --broadcast
[⠒] Compiling...
No files changed, compilation skipped
Deployer: $0X_DEPLOYER_ADDRESS
Deployed to: $0X_CONTRACT_ADDRESS
Transaction hash: $0X_TX_HASH

Let’s use the cast command to query the contract:

$ cast call $0X_CONTRACT_ADDRESS "getCount()(uint256)" --rpc-url $BITROOT_NODE_URI

The command should return 0 as the initial value of the counter.

Now we can use the cast command to call the increment function:

$ cast send $0X_CONTRACT_ADDRESS "increment()" --mnemonic $MNEMONIC --rpc-url $BITROOT_NODE_URI

If command is successful, you will get the transaction hash and other info back.

Now let’s call the getCount function again and this case it should return 1.

$ cast call $0X_CONTRACT_ADDRESS "getCount()(uint256)" --rpc-url $BITROOT_NODE_URI

Foundry generates the ABI for the contract in the out folder. You can use this ABI to interact with the contract from other tools like ethers.js or web3.js.

Calling contract using ethers.js

To call or query the contract from a frontend or a NodeJS script, you could use ethers.js like:

import { ethers } from 'ethers';
 
const privateKey = YOUR_PRIVATE_KEY;
const evmRpcEndpoint = YOUR_EVM_RPC_ENDPOINT;
const provider = new ethers.JsonRpcProvider(evmRpcEndpoint);
const signer = new ethers.Wallet(privateKey, provider);
 
if (!signer) {
    console.log('No signer found');
    return;
}
const abi = [
 {
      "type": "function",
      "name": "setNumber",
      "inputs": [
        {
          "name": "newNumber",
          "type": "uint256",
          "internalType": "uint256"
        }
      ],
      "outputs": [],
      "stateMutability": "nonpayable"
    },
    {
        "type": "function",
        "name": "getCount",
        "inputs": [],
        "outputs": [
            {
                "name": "",
                "type": "int256",
                "internalType": "int256"
            }
        ],
        "stateMutability": "view"
    },
    {
        "type": "function",
        "name": "increment",
        "inputs": [],
        "outputs": [],
        "stateMutability": "nonpayable"
    }
];
 
// Define the address of the deployed contract
const contractAddress = `0X_CONTRACT_ADDRESS`;
 
// Create a new instance of the ethers.js Contract object
const contract = new ethers.Contract(contractAddress, abi, signer);
 
// Call the contract's functions
async function getCount() {
    const count = await contract.getCount();
    console.log(count.toString());
}
 
async function increment() {
    const txResponse = await contract.increment();
    const mintedTx = await txResponse.wait();
    console.log(mintedTx);
}
 
await increment();
await getCount();

Where $BITROOT_NODE_URI is the URI of the Bitroot node and $MNEMONIC is the mnemonic of the account that will deploy the contract. If you run local Bitroot node, the address will be http://localhost:8545 , otherwise you could grab a evm_rpc url from the . If deployment is successful, you will get the EVM contract address in the output.

foundry forge 
foundry tooling 
foundry tooling 
Installation guide 
Creating New Project Guide 
registry