Skip to content

Using Foundry to Deploy To Moonbeam

Foundry Create Project

Introduction

Foundry is an Ethereum development environment written in Rust that helps developers manage dependencies, compile projects, run tests, deploy contracts, and interact with blockchains from the command line. Foundry can directly interact with Moonbeam's Ethereum API so it can be used to deploy smart contracts into Moonbeam.

There are three tools that make up Foundry:

  • Forge - compiles, tests, and deploys contracts
  • Cast - a command line interface for interacting with contracts
  • Anvil - a local TestNet node for development purposes that can fork preexisting networks

This guide will cover how to use Foundry to compile, deploy, and debug Ethereum smart contracts on the Moonbase Alpha TestNet. This guide can also be adapted for Moonbeam, Moonriver, or a Moonbeam development node.

Checking Prerequisites

To get started, you will need the following:

  • Have an account with funds. You can get DEV tokens for testing on Moonbase Alpha once every 24 hours from the Moonbase Alpha Faucet
  • To test out the examples in this guide on Moonbeam or Moonriver, you will need to have your own endpoint and API key which you can get from one of the supported Endpoint Providers.
  • Have Foundry installed

Creating a Foundry Project

You will need to create a Foundry project if you don't already have one. You can create one by completing the following steps:

  1. Install Foundry if you haven't already. If on Linux or MacOS, you can run these commands:

    curl -L https://foundry.paradigm.xyz | bash
    foundryup
    

    If on Windows, you'll have to install Rust & then build Foundry from source:

    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs/ | sh
    cargo install --git https://github.com/foundry-rs/foundry foundry-cli anvil --bins --locked
    
  2. Create the project, which will create a folder with three folders within it:

    forge init foundry
    

With the default project created, you should see three folders.

  • lib - all of the project's dependencies in the form of git submodules
  • src - where to put your smart contracts (with functionality)
  • test - where to put the forge tests for your project, which are written in Solidity

In addition to these three folders, a git project will also be created along with a prewritten .gitignore file with relevant file types and folders ignored.

The Source Folder

The src folder may already contain Contract.sol, a minimal Solidity contract. Feel free to delete it. Instead, you will be deploying an ERC-20 contract. In the contracts directory, you can create the MyToken.sol file:

cd src
touch MyToken.sol

Open the file and add the following contract to it:

pragma solidity ^0.8.0;

// Import OpenZeppelin Contract
import "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";

// This ERC-20 contract mints the specified amount of tokens to the contract creator
contract MyToken is ERC20 {
  constructor(uint256 initialSupply) ERC20("MyToken", "MYTOK") {
    _mint(msg.sender, initialSupply);
  }
}

Before you attempt to compile, install OpenZeppelin contracts as a dependency. You may have to commit previous changes to git beforehand. By default, Foundry uses git submodules instead of npm packages, so the traditional npm import path and command are not used. Instead, use the name of OpenZeppelin's Github repository:

forge install OpenZeppelin/openzeppelin-contracts

Compiling Solidity

Once all dependencies have been installed, you can compile the contract:

forge build

Foundry Contract Compile

After compilation, two folders will be created: out and cache. The ABI and bytecode for your contracts will be contained within the out folder. These two folders are already ignored by the .gitignore included in the default Foundry project initialization.

Deploying the Contract

Deploying the contract with Forge takes a single command, but you will need to include an RPC endpoint, a funded private key, and constructor arguments. MyToken.sol asks for an initial supply of tokens in its constructor, so each of the following commands include 100 as a constructor argument. You can deploy the MyToken.sol contract using the command for the correct network:

forge create --rpc-url RPC-API-ENDPOINT-HERE \
--constructor-args 100 \
--private-key YOUR_PRIVATE_KEY \
src/MyToken.sol:MyToken 
forge create --rpc-url RPC-API-ENDPOINT-HERE \
--constructor-args 100 \
--private-key YOUR_PRIVATE_KEY \
src/MyToken.sol:MyToken 
forge create --rpc-url https://rpc.api.moonbase.moonbeam.network \
--constructor-args 100 \
--private-key YOUR_PRIVATE_KEY \
src/MyToken.sol:MyToken 
forge create --rpc-url http://127.0.0.1:9933 \
--constructor-args 100 \
--private-key YOUR_PRIVATE_KEY \
src/MyToken.sol:MyToken 

After a few seconds, the contract is deployed, and you should see the address in the terminal.

Foundry Contract Deploy

Congratulations, your contract is live! Save the address, as you will use it to interact with this contract instance in the next step.

Interacting with the Contract

Foundry includes cast, a CLI for performing Ethereum RPC calls.

Try to retreive your token's name using cast, where YOUR_CONTRACT_ADDRESS is the address of the contract that you deployed in the previous section:

cast call YOUR_CONTRACT_ADDRESS "name()" --rpc-url RPC-API-ENDPOINT-HERE
cast call YOUR_CONTRACT_ADDRESS "name()" --rpc-url RPC-API-ENDPOINT-HERE
cast call YOUR_CONTRACT_ADDRESS "name()" --rpc-url https://rpc.api.moonbase.moonbeam.network
cast call YOUR_CONTRACT_ADDRESS "name()" --rpc-url http://127.0.0.1:9933

You should get this data in hexidecimal format:

0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000074d79546f6b656e00000000000000000000000000000000000000000000000000

This is far from readable, but you can use cast to convert it into your desired format. In this case, the data is text, so you can convert it into ascii characters to see "My Token":

Foundry Contract View

cast --to-ascii 0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000074d79546f6b656e00000000000000000000000000000000000000000000000000

You can also mutate data with cast as well. Try burning tokens by sending them to the zero address.

cast send --private-key YOUR_PRIVATE_KEY \
--rpc-url RPC-API-ENDPOINT-HERE \
--chain 1284 \
YOUR_CONTRACT_ADDRESS \
"transfer(address,uint256)" 0x0000000000000000000000000000000000000001 1
cast send --private-key YOUR_PRIVATE_KEY \
--rpc-url RPC-API-ENDPOINT-HERE \
--chain 1285 \
YOUR_CONTRACT_ADDRESS \
"transfer(address,uint256)" 0x0000000000000000000000000000000000000001 1
cast send --private-key YOUR_PRIVATE_KEY \
--rpc-url https://rpc.api.moonbase.moonbeam.network \
--chain 1287 \
YOUR_CONTRACT_ADDRESS \
"transfer(address,uint256)" 0x0000000000000000000000000000000000000001 1
cast send --private-key YOUR_PRIVATE_KEY \
--rpc-url http://127.0.0.1:9933 \
--chain 1281 \
YOUR_CONTRACT_ADDRESS \
"transfer(address,uint256)" 0x0000000000000000000000000000000000000001 1

The transaction will be signed by your Moonbase account and be broadcasted to the network. The output should look similar to:

Foundry Contract Interaction

Congratulations, you have successfully deployed and interacted with a contract using Foundry!

The information presented herein has been provided by third parties and is made available solely for general information purposes. Moonbeam does not endorse any project listed and described on the Moonbeam Doc Website (https://docs.moonbeam.network/). Moonbeam Foundation does not warrant the accuracy, completeness or usefulness of this information. Any reliance you place on such information is strictly at your own risk. Moonbeam Foundation disclaims all liability and responsibility arising from any reliance placed on this information by you or by anyone who may be informed of any of its contents. All statements and/or opinions expressed in these materials are solely the responsibility of the person or entity providing those materials and do not necessarily represent the opinion of Moonbeam Foundation. The information should not be construed as professional or financial advice of any kind. Advice from a suitably qualified professional should always be sought in relation to any particular matter or circumstance. The information herein may link to or integrate with other websites operated or content provided by third parties, and such other websites may link to this website. Moonbeam Foundation has no control over any such other websites or their content and will have no liability arising out of or related to such websites or their content. The existence of any such link does not constitute an endorsement of such websites, the content of the websites, or the operators of the websites. These links are being provided to you only as a convenience and you release and hold Moonbeam Foundation harmless from any and all liability arising from your use of this information or the information provided by any third-party website or service.