Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
189 changes: 1 addition & 188 deletions src/pages/build/tutorials/deploying-a-smart-contract/foundry.mdx
Original file line number Diff line number Diff line change
@@ -1,188 +1 @@
import CopyableCode from "@/components/CopyableCode";
import { TestnetDisclaimer } from "@/components/TestnetDisclaimer";

# 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:

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

Then run:

```bash
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:

```bash
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:

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

Create a new contract and put it in the file <CopyableCode code="src/InkContract.sol" />:

```solidity
// 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 <CopyableCode code="test/InkContract.t.sol" />:

```solidity
// 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:

```bash
forge build
```

Run tests:

```bash
forge test
```

## Deployment

1. First, create a <CopyableCode code=".env" /> file in your project root:

```env
PRIVATE_KEY=your_private_key_here
RPC_URL=https://rpc-gel-sepolia.inkonchain.com/
BLOCKSCOUT_API_KEY=your_blockscout_api_key_here
```

2. Create a deployment script in <CopyableCode code="script/Deploy.s.sol" />:

```solidity
// 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();
}
}
```

3. Deploy your contract:

```bash
# 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:

```bash
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`:

```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

- Check out [Get Foundry Book](https://book.getfoundry.sh/) for more information on Foundry.

<TestnetDisclaimer />
aW1wb3J0IENvcHlhYmxlQ29kZSBmcm9tICJAL2NvbXBvbmVudHMvQ29weWFibGVDb2RlIjsKaW1wb3J0IHsgVGVzdG5ldERpc2NsYWltZXIgfSBmcm9tICJAL2NvbXBvbmVudHMvVGVzdG5ldERpc2NsYWltZXIiOwoKIyBEZXBsb3lpbmcgYSBTbWFydCBDb250cmFjdCB3aXRoIEZvdW5kcnkKClRoaXMgZ3VpZGUgd2lsbCB3YWxrIHlvdSB0aHJvdWdoIHNldHRpbmcgdXAgYSBuZXcgcHJvamVjdCB1c2luZyBGb3VuZHJ5LCBhIGJsYXppbmcgZmFzdCB0b29sa2l0IGZvciBFdGhlcmV1bSBhcHBsaWNhdGlvbiBkZXZlbG9wbWVudCB3cml0dGVuIGluIFJ1c3QuCgojIyBJbnN0YWxsaW5nIEZvdW5kcnkKCkZpcnN0LCB5b3UnbGwgbmVlZCB0byBpbnN0YWxsIEZvdW5kcnkuIFJ1biB0aGlzIGNvbW1hbmQgaW4geW91ciB0ZXJtaW5hbDoKCmBgYGJhc2gKY3VybCAtTCBodHRwczovL2ZvdW5kcnkucGFyYWRpZ20ueHl6IHwgYmFzaApgYGAKClRoZW4gcnVuOgoKYGBgYmFzaApmb3VuZHJ5dXAKYGBgCgpUaGlzIHdpbGwgaW5zdGFsbCBgZm9yZ2VgLCBgY2FzdGAsIGFuZCBgYW52aWxgIC0gdGhlIGNvcmUgdG9vbHMgb2YgRm91bmRyeS4gWW91IGNhbiBhbHNvIHVzZSBgZm91bmRyeXVwYCB0byB1cGRhdGUgdGhlIHRvb2xzIHRvIHRoZSBsYXRlc3QgdmVyc2lvbi4KCiMjIENyZWF0aW5nIGEgTmV3IFByb2plY3QKClRvIGNyZWF0ZSBhIG5ldyBwcm9qZWN0LCBuYXZpZ2F0ZSB0byB0aGUgZGlyZWN0b3J5IHdoZXJlIHlvdSB3YW50IHRvIGNyZWF0ZSB5b3VyIHByb2plY3QgYW5kIHVzZSB0aGUgYGZvcmdlIGluaXRgIGNvbW1hbmQ6CgpgYGBiYXNoCmZvcmdlIGluaXQgbXlfcHJvamVjdApjZCBteV9wcm9qZWN0CmBgYAoKVGhpcyB3aWxsIGNyZWF0ZSBhIG5ldyBkaXJlY3Rvcnkgd2l0aCB0aGUgZm9sbG93aW5nIHN0cnVjdHVyZToKCmBgYApteV9wcm9qZWN0LwrilJzilIDilIAgbGliLwrilJzilIDilIAgc3JjLwrilIIgICDilJTilIDilIAgQ291bnRlci5zb2wK4pSc4pSA4pSAIHRlc3QvCuKUgiAgIOKUlOKUgOKUgCBDb3VudGVyLnQuc29sCuKUnOKUgOKUgCBzY3JpcHQvCuKUnOKUgOKUgCAuZ2l0aWdub3JlCuKUlOKUgOKUgCBmb3VuZHJ5LnRvbWwKYGBgCgojIyBXcml0aW5nIFlvdXIgRmlyc3QgQ29udHJhY3QKClJlbW92ZSB0aGUgZGVmYXVsdCBDb3VudGVyIGV4YW1wbGUgY29udHJhY3Q6CgpgYGBiYXNoCnJtIC1yZiBzcmMvQ291bnRlci5zb2wgc2NyaXB0L0NvdW50ZXIucy5zb2wgdGVzdC9Db3VudGVyLnQuc29sCmBgYAoKQ3JlYXRlIGEgbmV3IGNvbnRyYWN0IGFuZCBwdXQgaXQgaW4gdGhlIGZpbGUgPENvcHlhYmxlQ29kZSBjb2RlPSJzcmMvSW5rQ29udHJhY3Quc29sIiAvPjoKCmBgYHNvbGlkaXR5Ci8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNSVQKcHJhZ21hIHNvbGlkaXR5IF4wLjguMTk7CmNvbnRyYWN0IElua0NvbnRyYWN0IHsKICAgIHN0cmluZyBwdWJsaWMgZ3JlZXRpbmcgPSAiSGVsbG8sIElnayEiOwoKICAgIGZ1bmN0aW9uIHNldEdyZWV0aW5nKHN0cmluZyBtZW1vcnkgX2dyZWV0aW5nKSBwdWJsaWMgewogICAgICAgIGdyZWV0aW5nID0gX2dyZWV0aW5nOwogICAgfQp9CmBgYAoKQ3JlYXRlIHRoZSB0ZXN0cyBmb3IgdGhpcyBjb250cmFjdCBpbiB0aGUgZmlsZSA8Q29weWFibGVDb2RlIGNvZGU9InRlc3QvSW5rQ29udHJhY3QudC5zb2wiIC8+OgoKYGBgc29saWRpdHkKLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4xOTsKCmltcG9ydCB7VGVzdH0gZnJvbSAiZm9yZ2Utc3RkL1Rlc3Quc29sIjsKaW1wb3J0IHtJbmtDb250cmFjdH0gZnJvbSAiLi4vc3JjL0lua0NvbnRyYWN0LnNvbCI7Cgpjb250cmFjdCBJbmtDb250cmFjdFRlc3QgaXMgVGVzdCB7CiAgICBJbmtDb250cmFjdCBwdWJsaWMgaW5rOwoKICAgIGZ1bmN0aW9uIHNldFVwKCkgcHVibGljIHsKICAgICAgICBpbmsgPSBuZXcgSW5rQ29udHJhY3QoKTsKICAgIH0KCiAgICBmdW5jdGlvbiB0ZXN0X0RlZmF1bHRHcmVldGluZygpIHB1YmxpYyB2aWV3IHsKICAgICAgICBhc3NlcnRFcShpbmsuZ3JlZXRpbmcoKSwgIkhlbGxvLCBJbmshIik7CiAgICB9CgogICAgZnVuY3Rpb24gdGVzdF9TZXRHcmVldGluZygpIHB1YmxpYyB7CiAgICAgICAgc3RyaW5nIG1lbW9yeSBuZXdHcmVldGluZyA9ICJOZXcgZ3JlZXRpbmchIjsKICAgICAgICBpbmsuc2V0R3JlZXRpbmcobmV3R3JlZXRpbmcpOwogICAgICAgIGFzc2VydEVxKGluay5ncmVldGluZygpLCBuZXdHcmVldGluZyk7CiAgICB9CgogICAgZnVuY3Rpb24gdGVzdEZ1enpfU2V0R3JlZXRpbmcoc3RyaW5nIG1lbW9yeSByYW5kb21HcmVldGluZykgcHVibGljIHsKICAgICAgICBpbmsuc2V0R3JlZXRpbmcocmFuZG9tR3JlZXRpbmcpOwogICAgICAgIGFzc2VydEVxKGluay5ncmVldGluZygpLCByYW5kb21HcmVldGluZyk7CiAgICB9Cn0KYGBgCgojIyBCdWlsZGluZyBhbmQgVGVzdGluZwoKQnVpbGQgeW91ciBwcm9qZWN0OgoKYGBgYmFzaApmb3JnZSBidWlsZApgYGAKClJ1biB0ZXN0czoKCmBgYGJhc2gKZm9yZ2UgdGVzdApgYGAKCiMjIERlcGxveW1lbnQKCjEuIEZpcnN0LCBjcmVhdGUgYSA8Q29weWFibGVDb2RlIGNvZGU9Ii5lbnYiIC8+IGZpbGUgaW4geW91ciBwcm9qZWN0IHJvb3Q6CgpgYGBlbnYKUFJJVkFURV9LRVk9eW91cl9wcml2YXRlX2tleV9oZXJlClJQQ19VUkw9aHR0cHM6Ly9ycGMtZ2VsLXNlcG9saWEuaW5rb25jaGFpbi5jb20vCkJMT0NLU0NPVVRfQVBJX0tFWT15b3VyX2Jsb2Nrc2NvdXRfYXBpX2tleV9oZXJlCmBgYAoKMi4gQ3JlYXRlIGEgZGVwbG95bWVudCBzY3JpcHQgaW4gPENvcHlhYmxlQ29kZSBjb2RlPSJzY3JpcHQvRGVwbG95LnMuc29sIiAvPjoKCmBgYHNvbGlkaXR5Ci8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNSVQKcHJhZ21hIHNvbGlkaXR5IF4wLjguMTk7CmltcG9ydCAiZm9yZ2Utc3RkL1NjcmlwdC5zb2wiOwppbXBvcnQgIi4uL3NyYy9JbmtDb250cmFjdC5zb2wiOwoKY29udHJhY3QgRGVwbG95U2NyaXB0IGlzIFNjcmlwdCB7CiAgICBmdW5jdGlvbiBydW4oKSBleHRlcm5hbCB7CiAgICAgICAgdWludDI1NiBkZXBsb3llclByaXZhdGVLZXkgPSB2bS5lbnZVaW50KCJQUklWQVRFX0tFWSIpOwoKICAgICAgICB2bS5zdGFydEJyb2FkY2FzdChkZXBsb3llclByaXZhdGVLZXkpOwoKICAgICAgICBuZXcgSW5rQ29udHJhY3QoKTsKCiAgICAgICAgdm0uc3RvcEJyb2FkY2FzdCgpOwogICAgfQp9CmBgYAoKMy4gRGVwbG95IHlvdXIgY29udHJhY3Q6CgpgYGBiYXNoCiMgTG9hZCBlbnZpcm9ubWVudCB2YXJpYWJsZXMKc291cmNlIC5lbnYKCiMgRGVwbG95IHRvIElua1NlcG9saWEgVGVzdG5ldApmb3JnZSBzY3JpcHQgc2NyaXB0L0RlcGxveS5zLnNvbDpEZXBsb3lTY3JpcHQgLS1ycGMtdXJsICRSUENfVVJMIC0tYnJvYWRjYXN0IC0tdmVyaWZ5CmBgYAoKIyMgVmVyaWZ5aW5nIFlvdXIgQ29udHJhY3QKCklmIHlvdSB3YW50IHRvIHZlcmlmeSB5b3VyIGNvbnRyYWN0IG9uIEJsb2Nrc2NvdXQ6CgpgYGBiYXNoCmZvcmdlIHZlcmlmeS1jb250cmFjdCA8REVQTE9ZRURfQ09OVFJBQ1RfQUREUkVTUz4gc3JjL0lua0NvbnRyYWN0LnNvbDpJbmtDb250cmFjdCBcCiAgICAtLWNoYWluLWlkIDc2MzM3MyBcCiAgICAtLXZlcmlmaWVyIGJsb2Nrc2NvdXQgXAogICAgLS12ZXJpZmllci11cmwgaHR0cHM6Ly9leHBsb3Jlci1zZXBvbGlhLmlua29uY2hhaW4uY29tL2FwaSBcCiAgICAtLXZlcmlmaWVyLWFwaS1rZXkgJEJMT0NLU0NPVVRfQVBJX0tFWQpgYGAKCiMjIEFkZGl0aW9uYWwgQ29uZmlndXJhdGlvbgoKWW91IGNhbiBjdXN0b21pemUgeW91ciBGb3VuZHJ5IHNldHVwIGluIGBmb3VuZHJ5LnRvbWxgOgoKYGBgdG9tbApbcHJvZmlsZS5kZWZhdWx0XQpzcmMgPSAic3JjIgpvdXQgPSAib3V0IgpsaWJzID0gWyJsaWIiXQpzb2xjID0gIjAuOC4xOSIKb3B0aW1pemVyID0gdHJ1ZQpvcHRpbWl6ZXJfcnVucyA9IDIwMAoKW3JwY19lbmRwb2ludHNdCmlua3NlcG9saWEgPSAiJHtJTktTRVBPTElBX1JQQ19VUkx9IgpgYGAKCiMjIE5leHQgU3RlcHMKCi0gQ2hlY2sgb3V0IFtHZXQgRm91bmRyeSBCb29rXShodHRwczovL2Jvb2suZ2V0Zm91bmRyeS5zaC8pIGZvciBtb3JlIGluZm9ybWF0aW9uIG9uIEZvdW5kcnkuCgo8VGVzdG5ldERpc2NsYWltZXIgLz4K