Build on Ink
Deploying a Smart Contract
Foundry

Deploying a Smart Contract with Foundry

This guide will walk you through setting up a new project using Foundry, a blazing fast toolkit for Ethereum application development written in Rust.

Installing Foundry

First, you'll need to install Foundry. Run this command in your terminal:

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

Then run:

foundryup

This will install forge, cast, and anvil - the core tools of Foundry. You can also use foundryup to update the tools to the latest version.

Creating a New Project

To create a new project, navigate to the directory where you want to create your project and use the forge init command:

forge init my_project
cd my_project

This will create a new directory with the following structure:

my_project/
β”œβ”€β”€ lib/
β”œβ”€β”€ src/
β”‚   └── Counter.sol
β”œβ”€β”€ test/
β”‚   └── Counter.t.sol
β”œβ”€β”€ script/
β”œβ”€β”€ .gitignore
└── foundry.toml

Writing Your First Contract

Remove the default Counter example contract:

rm -rf src/Counter.sol script/Counter.s.sol test/Counter.t.sol

Create a new contract and put it in the file src/InkContract.sol:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
contract InkContract {
    string public greeting = "Hello, Ink!";
 
    function setGreeting(string memory _greeting) public {
        greeting = _greeting;
    }
}

Create the tests for this contract in the file test/InkContract.t.sol:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
 
import {Test} from "forge-std/Test.sol";
import {InkContract} from "../src/InkContract.sol";
 
contract InkContractTest is Test {
    InkContract public ink;
 
    function setUp() public {
        ink = new InkContract();
    }
 
    function test_DefaultGreeting() public view {
        assertEq(ink.greeting(), "Hello, Ink!");
    }
 
    function test_SetGreeting() public {
        string memory newGreeting = "New greeting!";
        ink.setGreeting(newGreeting);
        assertEq(ink.greeting(), newGreeting);
    }
 
    function testFuzz_SetGreeting(string memory randomGreeting) public {
        ink.setGreeting(randomGreeting);
        assertEq(ink.greeting(), randomGreeting);
    }
}

Building and Testing

Build your project:

forge build

Run tests:

forge test

Deployment

  1. First, create a .env file in your project root:
PRIVATE_KEY=your_private_key_here
RPC_URL=https://rpc-gel-sepolia.inkonchain.com/
BLOCKSCOUT_API_KEY=your_blockscout_api_key_here
  1. Create a deployment script in script/Deploy.s.sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "forge-std/Script.sol";
import "../src/InkContract.sol";
 
contract DeployScript is Script {
    function run() external {
        uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
 
        vm.startBroadcast(deployerPrivateKey);
 
        new InkContract();
 
        vm.stopBroadcast();
    }
}
  1. Deploy your contract:
# Load environment variables
source .env
 
# Deploy to InkSepolia Testnet
forge script script/Deploy.s.sol:DeployScript --rpc-url $RPC_URL --broadcast --verify

Verifying Your Contract

If you want to verify your contract on Etherscan:

forge verify-contract <DEPLOYED_CONTRACT_ADDRESS> src/InkContract.sol:InkContract \
    --chain-id 763373 \
    --etherscan-api-key $BLOCKSCOUT_API_KEY

Additional Configuration

You can customize your Foundry setup in foundry.toml:

[profile.default]
src = "src"
out = "out"
libs = ["lib"]
solc = "0.8.19"
optimizer = true
optimizer_runs = 200
 
[rpc_endpoints]
inksepolia = "${INKSEPOLIA_RPC_URL}"

Next Steps

ℹ️
This guide currently references Ink Sepolia (testnet) however it can be used for Ink mainnet as well. Please be sure to change the necessary parameters based on your network of choice.
Made with πŸ’œ by the Ink team