LibChain Docs Lib Testnet

Build

Deploy with Foundry

Configure Foundry for Lib Testnet, deploy with forge create or a script, test against the live chain, and read state with cast.

Foundry works with LibChain without plugins. This guide assumes you have it installed (foundryup) and a testnet key funded from the faucet.

#Configure

foundry.toml
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
solc_version = "0.8.28"
evm_version = "cancun"
optimizer = true
optimizer_runs = 200

[rpc_endpoints]
lib_testnet = "https://rpc-testnet.libchain.tech"

Keep your key out of the repository. Put it in an environment variable, or better, in Foundry's encrypted keystore:

Terminal
cast wallet import lib-testnet --interactive   # paste a testnet-only key, set a password
cast wallet address --account lib-testnet

#Deploy a single contract

Terminal
forge create src/Counter.sol:Counter \
  --rpc-url lib_testnet \
  --account lib-testnet \
  --broadcast

Constructor arguments go last: --constructor-args 42 "hello". Without --broadcast, recent Foundry versions only simulate.

#Deploy with a script

script/Deploy.s.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {Script, console} from "forge-std/Script.sol";
import {Counter} from "../src/Counter.sol";

contract Deploy is Script {
    function run() external {
        vm.startBroadcast();
        Counter counter = new Counter();
        counter.setNumber(1);
        vm.stopBroadcast();
        console.log("Counter deployed at", address(counter));
    }
}
Terminal
forge script script/Deploy.s.sol \
  --rpc-url lib_testnet \
  --account lib-testnet \
  --broadcast

Each transaction is final in its block, so the script's receipts are final as soon as Foundry prints them. Broadcast logs are saved under broadcast/.

#Test against the live chain

Fork tests run your tests on a local copy of Lib Testnet's state, so you can call deployed contracts such as WtLIB:

test/WtLIB.t.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {Test} from "forge-std/Test.sol";

interface IWtLIB {
    function deposit() external payable;
    function balanceOf(address) external view returns (uint256);
}

contract WtLIBForkTest is Test {
    IWtLIB constant WTLIB = IWtLIB(0x87052f1f17b2b4054b014e93e53d6ce6dc912bda);

    function setUp() public {
        vm.createSelectFork("lib_testnet");
    }

    function test_wrap() public {
        vm.deal(address(this), 1 ether);
        WTLIB.deposit{value: 1 ether}();
        assertEq(WTLIB.balanceOf(address(this)), 1 ether);
    }
}
Terminal
forge test --match-contract WtLIBForkTest -vv

#Read and write with cast

Terminal
cast block-number --rpc-url lib_testnet
cast balance 0xYourAddress --ether --rpc-url lib_testnet
cast call 0x87052f1f17b2b4054b014e93e53d6ce6dc912bda "totalSupply()(uint256)" --rpc-url lib_testnet
cast send 0xYourContract "setNumber(uint256)" 7 --account lib-testnet --rpc-url lib_testnet
cast receipt 0xTxHash --rpc-url lib_testnet

The public RPC doesn't expose debug_* or trace_* methods, so cast run can't replay a transaction from the chain. Reproduce failures in a fork test instead: forge test -vvvv traces locally.

#Next

Publish your source with Verify a contract, or call your contract from a web page with Build a dApp.

Updated 5 November 2026LibChain Docs · Lib Testnet