Skip to main content
In this guide you will scaffold a Foundry project, write a WKRC payment contract, deploy it to StableNet Testnet, and verify it on the Explorer. Time: ~15 minutes Tools: Foundry (forge, cast) Network: StableNet Testnet (Chain ID 8283)

Prerequisites

Before you start, make sure you have:
  • Foundry installed — run forge --version to check. If not, install it:
    curl -L https://foundry.paradigm.xyz | bash
    foundryup
    
  • A funded testnet wallet. Get free KRC from the faucet:

    Faucet

    Request testnet KRC — no sign-up required.

    Explorer

    Verify your balance before deploying.
StableNet enforces a minimum priority fee of 27,600 Gwei. The deploy commands in this guide include this value. Transactions below this threshold will be rejected.

Network Details

ParameterValue
Chain ID8283
RPC URLhttps://api.test.stablenet.network
Explorerexplorer.stablenet.network
Faucetfaucet.stablenet.network
WKRC Contract0x0000000000000000000000000000000000001000
Minimum Gas Tip27,600 Gwei
WKRC is the native coin of StableNet, exposed as a standard ERC-20 token via the NativeCoinAdapter system contract at the address above. The same balance you use to pay gas is also the balance tracked by WKRC.balanceOf().

Steps

1

Scaffold your project

Create a new Foundry project and install forge-std:
forge init stablenet-demo
cd stablenet-demo
Your project structure:
stablenet-demo/
├── src/          # Contract source files
├── script/       # Deployment scripts
├── test/         # Test files
└── foundry.toml  # Foundry configuration
2

Configure foundry.toml

Open foundry.toml and add the StableNet Testnet RPC endpoint:
[profile.default]
src = "src"
out = "out"
libs = ["lib"]

[rpc_endpoints]
stablenet_testnet = "https://api.test.stablenet.network"
3

Write WKRCPayment.sol

Delete the placeholder src/Counter.sol and create src/WKRCPayment.sol:
rm src/Counter.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface IERC20 {
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
}

/// @title WKRCPayment
/// @notice Accepts WKRC payments from an approved sender.
///         The sender must approve this contract first (see Step 4).
contract WKRCPayment {
    /// @dev NativeCoinAdapter (WKRC) — fixed system contract address on StableNet.
    IERC20 public constant WKRC =
        IERC20(0x0000000000000000000000000000000000001000);

    event Payment(address indexed from, address indexed to, uint256 amount);

    /// @notice Pull `amount` of WKRC from msg.sender and forward it to `to`.
    ///         Requires prior WKRC.approve(address(this), amount).
    function pay(address to, uint256 amount) external {
        require(WKRC.transferFrom(msg.sender, to, amount), "WKRC transfer failed");
        emit Payment(msg.sender, to, amount);
    }

    /// @notice Check how much WKRC `owner` has approved for this contract.
    function allowanceOf(address owner) external view returns (uint256) {
        return WKRC.allowance(owner, address(this));
    }
}
Compile to confirm there are no errors:
forge build
Expected output:
[⠒] Compiling...
[⠢] Compiling 1 files with 0.8.x
[⠆] Solc 0.8.x finished in Xs
Compiler run successful!
4

Write the deploy script

Create script/DeployWKRCPayment.s.sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

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

contract DeployWKRCPayment is Script {
    function run() external {
        vm.startBroadcast();
        WKRCPayment payment = new WKRCPayment();
        console.log("WKRCPayment deployed at:", address(payment));
        vm.stopBroadcast();
    }
}
5

Deploy to Testnet

Export your private key and run the deploy script:
export PRIVATE_KEY=0xYourPrivateKey

forge script script/DeployWKRCPayment.s.sol \
  --rpc-url https://api.test.stablenet.network \
  --private-key $PRIVATE_KEY \
  --priority-gas-price 27600000000000 \
  --broadcast
Never commit PRIVATE_KEY to version control. Use a .env file and add it to .gitignore.
Block inclusion may take up to 1–2 minutes. If cast times out, your transaction is still in the mempool and will be confirmed shortly.
Successful output looks like:
Script ran successfully.

== Logs ==
WKRCPayment deployed at: 0xABC...

## Setting up 1 EVM.
Chain 8283

Estimated gas price: X gwei
Estimated total gas used for script: Y

✅ Hash: 0xDEF...
Contract Address: 0xABC...
Block: NNNN
Save the Contract Address — you will need it in the next step.
6

Approve WKRC and send a payment

Before calling pay(), your wallet must approve the deployed contract to pull WKRC. Use cast to send both transactions:
export CONTRACT=0xABC...              # your deployed WKRCPayment address
export RECIPIENT=0xRecipientAddress
export AMOUNT=1000000000000000000     # 1 WKRC (18 decimals)
export WKRC=0x0000000000000000000000000000000000001000

# Step A: approve the contract to spend 1 WKRC
cast send $WKRC \
  "approve(address,uint256)" $CONTRACT $AMOUNT \
  --rpc-url https://api.test.stablenet.network \
  --private-key $PRIVATE_KEY \
  --priority-gas-price 27600000000000

# Step B: call pay() to transfer to the recipient
cast send $CONTRACT \
  "pay(address,uint256)" $RECIPIENT $AMOUNT \
  --rpc-url https://api.test.stablenet.network \
  --private-key $PRIVATE_KEY \
  --priority-gas-price 27600000000000
Do not raise --priority-gas-price above 27,600 Gwei. Higher values can trigger a NativeCoinAdapter balance error during gas estimation.
Confirm the allowance was consumed:
export YOUR_ADDRESS=0x<your-wallet-address>

cast call $CONTRACT \
  "allowanceOf(address)(uint256)" $YOUR_ADDRESS \
  --rpc-url https://api.test.stablenet.network
# Should return: 0
7

Verify on Explorer

Open explorer.stablenet.network and search for your contract address.You should see:
  • The deployment transaction
  • The approve transaction on the WKRC contract
  • The pay call on your contract, with a Payment event in the logs
The Payment event confirms that the WKRC transfer was recorded on-chain.

What just happened?

  • WKRC is the KRW-pegged native coin of StableNet. It works exactly like any ERC-20 token — approve, transferFrom, and balanceOf all follow the standard interface.
  • WKRCPayment.pay() uses the ERC-20 transferFrom pattern: the user first approves the contract as a spender, then the contract pulls the tokens. This is the standard pattern for on-chain payment flows.
  • 27,600 Gwei priority fee is enforced by the network’s GovValidator governance contract. All transactions — including contract deploys — must meet this minimum.

Troubleshooting

  • “replacement transaction underpriced” — use --gas-price 80000000000000 --priority-gas-price 35000000000000
  • “transfer amount exceeds balance” — lower the gas price and retry

Next Steps

EVM Compatibility Reference

Supported eth_* RPC methods, StableNet vs Ethereum differences, and fee delegation (tx type 0x16).

Network Information

Full network parameters — Chain IDs, system contract addresses.

API Reference

JSON-RPC methods with curl and ethers.js examples.

Explorer

Inspect your contract and transactions on-chain.