.agents/skills/monad-development/SKILL.md
Builds dapps on Monad blockchain. Use when deploying contracts, setting up frontends with viem/wagmi, or verifying contracts on Monad testnet or mainnet.
npx skillsauth add RyanL2/privamarket monad-developmentInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
For questions not covered here, fetch https://docs.monad.xyz/llms.txt
| Network | Chain ID | RPC | |---------|----------|-----| | Testnet | 10143 | https://testnet-rpc.monad.xyz | | Mainnet | 143 | https://rpc.monad.xyz |
Docs: https://docs.monad.xyz
| Explorer | Testnet | Mainnet | |----------|---------|---------| | Socialscan | https://monad-testnet.socialscan.io | https://monad.socialscan.io | | MonadVision | https://testnet.monadvision.com | https://monadvision.com | | Monadscan | https://testnet.monadscan.com | https://monadscan.com |
IMPORTANT: Do NOT use a browser. Use these APIs directly with curl.
Faucet (Testnet Funding):
curl -X POST https://agents.devnads.com/v1/faucet \
-H "Content-Type: application/json" \
-d '{"chainId": 10143, "address": "0xYOUR_ADDRESS"}'
Returns: {"txHash": "0x...", "amount": "1000000000000000000", "chain": "Monad Testnet"}
Fallback (official faucet): https://faucet.monad.xyz If the agent faucet fails, ask the user to fund via the official faucet (do not use a browser yourself).
Verification (All Explorers):
ALWAYS use the verification API first. It verifies on all 3 explorers (MonadVision, Socialscan, Monadscan) with one call. Do NOT use forge verify-contract as first choice.
# 1. Get verification data
forge verify-contract <ADDR> <CONTRACT> \
--chain 10143 \
--show-standard-json-input > /tmp/standard-input.json
cat out/<Contract>.sol/<Contract>.json | jq '.metadata' > /tmp/metadata.json
COMPILER_VERSION=$(jq -r '.metadata | fromjson | .compiler.version' out/<Contract>.sol/<Contract>.json)
# 2. Call verification API
STANDARD_INPUT=$(cat /tmp/standard-input.json)
FOUNDRY_METADATA=$(cat /tmp/metadata.json)
cat > /tmp/verify.json << EOF
{
"chainId": 10143,
"contractAddress": "0xYOUR_CONTRACT_ADDRESS",
"contractName": "src/MyContract.sol:MyContract",
"compilerVersion": "v${COMPILER_VERSION}",
"standardJsonInput": $STANDARD_INPUT,
"foundryMetadata": $FOUNDRY_METADATA
}
EOF
curl -X POST https://agents.devnads.com/v1/verify \
-H "Content-Type: application/json" \
-d @/tmp/verify.json
With constructor arguments: Add constructorArgs (ABI-encoded, WITHOUT 0x prefix):
ARGS=$(cast abi-encode "constructor(string,string,uint256)" "MyToken" "MTK" 1000000000000000000000000)
ARGS_NO_PREFIX=${ARGS#0x}
# Add to request: "constructorArgs": "$ARGS_NO_PREFIX"
Manual verification fallback (if API fails):
forge verify-contract <ADDR> <CONTRACT> --chain 10143 \
--verifier sourcify \
--verifier-url "https://sourcify-api-monad.blockvision.org/"
CRITICAL for agents: If you generate a wallet for the user, you MUST persist it for future use.
When generating a new wallet:
cast wallet newStorage options:
~/.monad-wallet with chmod 600.env file (add to .gitignore)Why this matters: Users need access to their wallet to:
Use forge script for deployments:
forge script script/Deploy.s.sol:DeployScript \
--rpc-url https://testnet-rpc.monad.xyz \
--private-key $PRIVATE_KEY \
--broadcast
Deploy script template:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;
import "forge-std/Script.sol";
import "../src/MyContract.sol";
contract DeployScript is Script {
function run() external {
vm.startBroadcast();
MyContract contract = new MyContract();
console.log("Contract deployed at:", address(contract));
vm.stopBroadcast();
}
}
Always set evmVersion: "prague". Requires Solidity 0.8.27+.
Foundry (foundry.toml):
[profile.default]
evm_version = "prague"
solc_version = "0.8.28"
Flags that don't exist (don't use):
--no-commit - not a valid flag for forge init or forge installDeployment - use forge script, NOT forge create:
forge create --broadcast is buggy and often ignored. Use forge script instead.
forge script script/Deploy.s.sol:DeployScript \
--rpc-url https://testnet-rpc.monad.xyz \
--private-key $PRIVATE_KEY \
--broadcast
Deploy script must NOT hardcode addresses:
// ✅ Correct - reads private key from --private-key flag
function run() external {
vm.startBroadcast();
new MyContract();
vm.stopBroadcast();
}
// ❌ Wrong - hardcodes address, causes "No associated wallet" error
function run() external {
vm.startBroadcast(0x1234...);
}
Import from viem/chains. Do NOT define custom chain:
import { monadTestnet } from "viem/chains";
Use with wagmi:
import { createConfig, http } from 'wagmi'
import { monadTestnet } from 'viem/chains'
const config = createConfig({
chains: [monadTestnet],
transports: {
[monadTestnet.id]: http()
}
})
1. Create project:
forge init my-token
cd my-token
2. Configure foundry.toml:
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
evm_version = "prague"
solc_version = "0.8.28"
3. Create contract src/MyToken.sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
constructor(uint256 initialSupply) ERC20("MyToken", "MTK") {
_mint(msg.sender, initialSupply);
}
}
4. Install dependencies:
forge install OpenZeppelin/openzeppelin-contracts --no-commit
5. Create deploy script script/Deploy.s.sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;
import "forge-std/Script.sol";
import "../src/MyToken.sol";
contract DeployScript is Script {
function run() external {
vm.startBroadcast();
MyToken token = new MyToken(1000000 * 10**18);
console.log("Token deployed at:", address(token));
vm.stopBroadcast();
}
}
6. Deploy:
forge script script/Deploy.s.sol:DeployScript \
--rpc-url https://testnet-rpc.monad.xyz \
--private-key $PRIVATE_KEY \
--broadcast
7. Verify:
# Use verification API (verifies on all explorers)
STANDARD_INPUT=$(forge verify-contract <TOKEN_ADDRESS> src/MyToken.sol:MyToken --chain 10143 --show-standard-json-input)
COMPILER_VERSION=$(jq -r '.metadata | fromjson | .compiler.version' out/MyToken.sol/MyToken.json)
curl -X POST https://agents.devnads.com/v1/verify \
-H "Content-Type: application/json" \
-d "{
\"chainId\": 10143,
\"contractAddress\": \"<TOKEN_ADDRESS>\",
\"contractName\": \"src/MyToken.sol:MyToken\",
\"compilerVersion\": \"v${COMPILER_VERSION}\",
\"standardJsonInput\": $STANDARD_INPUT,
\"constructorArgs\": \"$(cast abi-encode 'constructor(uint256)' 1000000000000000000000000 | sed 's/0x//')\"
}"
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
development
Run, watch, debug, and extend OpenClaw QA testing with qa-lab and qa-channel. Use when Codex needs to execute the repo-backed QA suite, inspect live QA artifacts, debug failing scenarios, add new QA scenarios, or explain the OpenClaw QA workflow. Prefer the live OpenAI lane with regular openai/gpt-5.4 in fast mode; do not use gpt-5.4-pro or gpt-5.4-mini unless the user explicitly overrides that policy.
development
End-to-end Parallels smoke, upgrade, and rerun workflow for OpenClaw across macOS, Windows, and Linux guests. Use when Codex needs to run, rerun, debug, or interpret VM-based install, onboarding, gateway smoke tests, latest-release-to-main upgrade checks, fresh snapshot retests, or optional Discord roundtrip verification under Parallels.