monad-wingman
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMonad Wingman
Monad 助手
Comprehensive Monad blockchain development guide for AI agents. Covers smart contract development on Monad (parallel execution EVM-compatible L1), DeFi protocols, security best practices, deployment workflows, and the SpeedRun Ethereum curriculum adapted for Monad.
面向AI Agent的Monad区块链开发综合指南。涵盖Monad(兼容并行执行EVM的Layer1公链)上的智能合约开发、DeFi协议、安全最佳实践、部署工作流,以及适配Monad的SpeedRun Ethereum学习课程。
MONAD CRITICAL DIFFERENCES FROM ETHEREUM
Monad与以太坊的核心差异
Before doing ANYTHING, internalize these Monad-specific rules:
在开展任何工作前,请牢记这些Monad专属规则:
Chain Configuration
链配置
- Mainnet chain ID: 143 | Testnet chain ID: 10143
- DEFAULT TO TESTNET unless the user explicitly says mainnet
- Native token: MON (18 decimals) — NOT ETH
- RPC (testnet):
https://testnet-rpc.monad.xyz - RPC (mainnet):
https://rpc.monad.xyz - Block explorers: MonadVision, Monadscan, Socialscan
- 主网链ID: 143 | 测试网链ID: 10143
- 默认使用测试网,除非用户明确指定主网
- 原生代币: MON(18位小数)—— 不是ETH
- 测试网RPC:
https://testnet-rpc.monad.xyz - 主网RPC:
https://rpc.monad.xyz - 区块浏览器: MonadVision、Monadscan、Socialscan
Solidity & Compilation
Solidity与编译
- EVM version: MUST be — set in
pragueasfoundry.tomlevm_version = "prague" - Solidity version: 0.8.27+ required, 0.8.28 recommended
- Max contract size: 128KB (vs Ethereum's 24.5KB) — much more room
- EVM版本: 必须设置为——在
prague中配置foundry.tomlevm_version = "prague" - Solidity版本: 要求0.8.27及以上,推荐0.8.28
- 最大合约大小: 128KB(以太坊为24.5KB)——拥有更大的开发空间
Deployment Rules (CRITICAL)
部署规则(至关重要)
- ALWAYS use flag — Monad does NOT support EIP-1559 type 2 transactions
--legacy - ALWAYS use — NEVER use
forge scriptforge create - No blob transactions — EIP-4844 type 3 txs are NOT supported
- Gas is charged on gas_limit, not actual usage — set gas limits carefully
- No global mempool — transactions go directly to the block producer
- 必须使用参数——Monad不支持EIP-1559类型2交易
--legacy - 必须使用——绝对不要使用
forge scriptforge create - 不支持Blob交易——EIP-4844类型3交易不受支持
- Gas费用按gas_limit收取,而非实际使用量——需谨慎设置gas上限
- 无全局内存池——交易直接发送给区块生产者
Wallet Persistence
钱包持久化
- Store keys at with
~/.monad-walletchmod 600 - Mainnet key safety: use ,
--ledger, or keystore files — NEVER--trezorfor mainnet--private-key
- 将密钥存储在,并设置权限
~/.monad-walletchmod 600 - 主网密钥安全: 使用、
--ledger或密钥库文件——绝对不要在主网部署时使用--trezor--private-key
Monad Architecture
Monad架构
- Parallel execution = optimistic concurrency, produces same results as sequential
- Reserve Balance mechanism — understand this for DeFi
- Historical state NOT available on full nodes — do not rely on archive queries
- secp256r1 (P256) precompile at address — enables passkey/WebAuthn signing
0x0100
- 并行执行 = 乐观并发,产生与顺序执行相同的结果
- 储备余额机制——开发DeFi时需理解此机制
- 全节点不提供历史状态——不要依赖归档查询
- secp256r1 (P256)预编译合约位于地址——支持passkey/WebAuthn签名
0x0100
Faucet (Testnet)
测试网水龙头
bash
curl -X POST https://agents.devnads.com/v1/faucet \
-H "Content-Type: application/json" \
-d '{"chainId": 10143, "address": "0xYOUR_ADDRESS"}'bash
curl -X POST https://agents.devnads.com/v1/faucet \
-H "Content-Type: application/json" \
-d '{"chainId": 10143, "address": "0xYOUR_ADDRESS"}'Contract Verification
合约验证
bash
curl -X POST https://agents.devnads.com/v1/verify \
-H "Content-Type: application/json" \
-d '{"chainId": 10143, "address": "0xCONTRACT", "source": "...", "compilerVersion": "0.8.28"}'bash
curl -X POST https://agents.devnads.com/v1/verify \
-H "Content-Type: application/json" \
-d '{"chainId": 10143, "address": "0xCONTRACT", "source": "...", "compilerVersion": "0.8.28"}'AI AGENT INSTRUCTIONS - READ THIS FIRST
AI Agent 指令 - 请先阅读
Dual Workflow: Foundry (Primary) + Scaffold-Monad
双工作流:Foundry(首选)+ Scaffold-Monad
Monad development supports two workflows. Use Foundry for contracts-only projects; use Scaffold-Monad for fullstack dApps.
Monad开发支持两种工作流。纯合约项目使用Foundry;全栈dApp使用Scaffold-Monad。
Workflow A: Foundry (Primary — Contracts Only)
工作流A:Foundry(首选——纯合约)
Step 1: Initialize Foundry Project
bash
forge init my-monad-project
cd my-monad-projectStep 2: Configure foundry.toml for Monad
toml
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
evm_version = "prague"
solc_version = "0.8.28"
[rpc_endpoints]
monad_testnet = "https://testnet-rpc.monad.xyz"
monad_mainnet = "https://rpc.monad.xyz"Step 3: Write and Test Contracts
bash
forge testStep 4: Deploy to Monad Testnet
bash
forge script script/Deploy.s.sol:DeployScript \
--rpc-url https://testnet-rpc.monad.xyz \
--private-key $PRIVATE_KEY \
--broadcast \
--legacyNEVER use . ALWAYS use with .
forge createforge script--legacyStep 5: Verify Contract
bash
curl -X POST https://agents.devnads.com/v1/verify \
-H "Content-Type: application/json" \
-d '{"chainId": 10143, "address": "0xDEPLOYED", "source": "...", "compilerVersion": "0.8.28"}'步骤1:初始化Foundry项目
bash
forge init my-monad-project
cd my-monad-project步骤2:为Monad配置foundry.toml
toml
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
evm_version = "prague"
solc_version = "0.8.28"
[rpc_endpoints]
monad_testnet = "https://testnet-rpc.monad.xyz"
monad_mainnet = "https://rpc.monad.xyz"步骤3:编写并测试合约
bash
forge test步骤4:部署到Monad测试网
bash
forge script script/Deploy.s.sol:DeployScript \
--rpc-url https://testnet-rpc.monad.xyz \
--private-key $PRIVATE_KEY \
--broadcast \
--legacy绝对不要使用。必须使用带参数的。
forge create--legacyforge script步骤5:验证合约
bash
curl -X POST https://agents.devnads.com/v1/verify \
-H "Content-Type: application/json" \
-d '{"chainId": 10143, "address": "0xDEPLOYED", "source": "...", "compilerVersion": "0.8.28"}'Workflow B: Scaffold-Monad (Fullstack dApps)
工作流B:Scaffold-Monad(全栈dApp)
Step 1: Create Project
bash
undefined步骤1:创建项目
bash
undefinedFoundry variant (recommended)
推荐使用Foundry变体
git clone https://github.com/monad-developers/scaffold-monad-foundry.git my-dapp
cd my-dapp
**Step 2: Configure for Monad**
Edit `packages/nextjs/scaffold.config.ts`:
```typescript
import { monadTestnet } from "viem/chains";
const scaffoldConfig = {
targetNetworks: [monadTestnet],
pollingInterval: 3000, // 3 seconds (default 30000 is too slow)
};IMPORTANT: Import from . Do NOT define a custom chain object.
monadTestnetviem/chainsStep 3: Configure Foundry for Monad
Edit :
packages/foundry/foundry.tomltoml
evm_version = "prague"
solc_version = "0.8.28"Step 4: Install and Start
bash
cd <project-name>
yarn install
yarn startStep 5: Deploy
bash
yarn deploy --network monadTestnetStep 6: Fund Wallet via Faucet
bash
curl -X POST https://agents.devnads.com/v1/faucet \
-H "Content-Type: application/json" \
-d '{"chainId": 10143, "address": "0xYOUR_BURNER_WALLET"}'Step 7: Test the Frontend
- Navigate to
http://localhost:3000 - Take a snapshot to get page elements
- Fund the wallet via faucet (MON, not ETH)
- Click through the app to verify functionality
git clone https://github.com/monad-developers/scaffold-monad-foundry.git my-dapp
cd my-dapp
**步骤2:为Monad配置项目**
编辑`packages/nextjs/scaffold.config.ts`:
```typescript
import { monadTestnet } from "viem/chains";
const scaffoldConfig = {
targetNetworks: [monadTestnet],
pollingInterval: 3000, // 3秒(默认30000太慢)
};重要提示:从导入。不要自定义链对象。
viem/chainsmonadTestnet步骤3:为Monad配置Foundry
编辑:
packages/foundry/foundry.tomltoml
evm_version = "prague"
solc_version = "0.8.28"步骤4:安装依赖并启动项目
bash
cd <project-name>
yarn install
yarn start步骤5:部署合约
bash
yarn deploy --network monadTestnet步骤6:通过水龙头为钱包充值
bash
curl -X POST https://agents.devnads.com/v1/faucet \
-H "Content-Type: application/json" \
-d '{"chainId": 10143, "address": "0xYOUR_BURNER_WALLET"}'步骤7:测试前端
- 访问
http://localhost:3000 - 快照页面获取页面元素
- 通过水龙头为钱包充值(使用MON,而非ETH)
- 点击操作应用验证功能
Fork Mode (Testing Against Live Monad State)
分叉模式(针对Monad实时状态测试)
bash
anvil --fork-url https://rpc.monad.xyz --block-time 1Or for testnet:
bash
anvil --fork-url https://testnet-rpc.monad.xyz --block-time 1bash
anvil --fork-url https://rpc.monad.xyz --block-time 1测试网分叉:
bash
anvil --fork-url https://testnet-rpc.monad.xyz --block-time 1DO NOT:
禁止操作:
- Use (use
forge createwithforge scriptinstead)--legacy - Send EIP-1559 type 2 transactions (always use )
--legacy - Send blob transactions (EIP-4844 type 3 not supported)
- Use for mainnet deployments (use
--private-key/--ledger/keystore)--trezor - Define custom chain objects in frontend (use )
import { monadTestnet } from 'viem/chains' - Rely on historical state queries (not available on full nodes)
- Assume gas is charged on usage (it is charged on gas_limit)
- 不要使用(请使用带
forge create参数的--legacy替代)forge script - 不要发送EIP-1559类型2交易(始终使用)
--legacy - 不要发送Blob交易(不支持EIP-4844类型3交易)
- 主网部署时不要使用(使用
--private-key/--ledger/密钥库文件)--trezor - 前端不要自定义链对象(使用)
import { monadTestnet } from 'viem/chains' - 不要依赖历史状态查询(全节点不提供)
- 不要假设Gas费用按实际使用量收取(按gas_limit收取)
Monad Deployment Workflow
Monad部署工作流
Deploy Script Template
部署脚本模板
solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import "forge-std/Script.sol";
import "../src/MyContract.sol";
contract DeployScript is Script {
function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);
MyContract myContract = new MyContract();
vm.stopBroadcast();
console.log("MyContract deployed to:", address(myContract));
}
}solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import "forge-std/Script.sol";
import "../src/MyContract.sol";
contract DeployScript is Script {
function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);
MyContract myContract = new MyContract();
vm.stopBroadcast();
console.log("MyContract deployed to:", address(myContract));
}
}Deploy Commands
部署命令
bash
undefinedbash
undefinedTestnet (default)
测试网(默认)
forge script script/Deploy.s.sol:DeployScript
--rpc-url https://testnet-rpc.monad.xyz
--private-key $PRIVATE_KEY
--broadcast
--legacy
--rpc-url https://testnet-rpc.monad.xyz
--private-key $PRIVATE_KEY
--broadcast
--legacy
forge script script/Deploy.s.sol:DeployScript
--rpc-url https://testnet-rpc.monad.xyz
--private-key $PRIVATE_KEY
--broadcast
--legacy
--rpc-url https://testnet-rpc.monad.xyz
--private-key $PRIVATE_KEY
--broadcast
--legacy
Mainnet (use hardware wallet!)
主网(使用硬件钱包!)
forge script script/Deploy.s.sol:DeployScript
--rpc-url https://rpc.monad.xyz
--ledger
--broadcast
--legacy
--rpc-url https://rpc.monad.xyz
--ledger
--broadcast
--legacy
---forge script script/Deploy.s.sol:DeployScript
--rpc-url https://rpc.monad.xyz
--ledger
--broadcast
--legacy
--rpc-url https://rpc.monad.xyz
--ledger
--broadcast
--legacy
---THE MOST CRITICAL CONCEPT
最核心的概念
NOTHING IS AUTOMATIC ON ANY EVM CHAIN, INCLUDING MONAD.
Smart contracts cannot execute themselves. There is no cron job, no scheduler, no background process. For EVERY function that "needs to happen":
- Make it callable by ANYONE (not just admin)
- Give callers a REASON (profit, reward, their own interest)
- Make the incentive SUFFICIENT to cover gas + profit
Always ask: "Who calls this function? Why would they pay gas?"
If you cannot answer this, your function will not get called.
Monad note: Gas on Monad is cheap due to parallel execution throughput, but the incentive principle still applies. Gas is charged on gas_limit, not usage — so set limits carefully.
在任何EVM链上,包括Monad,没有任何功能是自动执行的。
智能合约无法自行执行。没有定时任务、调度器或后台进程。对于每一个“需要自动执行”的函数:
- 让任何人都能调用(不局限于管理员)
- 给调用者一个理由(利润、奖励、自身利益)
- 确保激励足够覆盖Gas费用+利润
始终要问:“谁会调用这个函数?他们为什么愿意支付Gas费用?”
如果无法回答这个问题,你的函数将永远不会被调用。
Monad提示:由于并行执行的高吞吐量,Monad的Gas费用很低,但激励原则仍然适用。Gas费用按gas_limit收取,而非实际使用量——因此需谨慎设置上限。
Examples of Proper Incentive Design
合理激励设计示例
solidity
// LIQUIDATIONS: Caller gets bonus collateral
function liquidate(address user) external {
require(getHealthFactor(user) < 1e18, "Healthy");
uint256 bonus = collateral * 5 / 100; // 5% bonus
collateralToken.transfer(msg.sender, collateral + bonus);
}
// YIELD HARVESTING: Caller gets % of harvest
function harvest() external {
uint256 yield = protocol.claimRewards();
uint256 callerReward = yield / 100; // 1%
token.transfer(msg.sender, callerReward);
}
// CLAIMS: User wants their own tokens
function claimRewards() external {
uint256 reward = pendingRewards[msg.sender];
pendingRewards[msg.sender] = 0;
token.transfer(msg.sender, reward);
}solidity
// 清算:调用者获得额外抵押品
function liquidate(address user) external {
require(getHealthFactor(user) < 1e18, "健康账户");
uint256 bonus = collateral * 5 / 100; // 5%额外奖励
collateralToken.transfer(msg.sender, collateral + bonus);
}
// 收益收割:调用者获得部分收益
function harvest() external {
uint256 yield = protocol.claimRewards();
uint256 callerReward = yield / 100; // 1%
token.transfer(msg.sender, callerReward);
}
// 领取奖励:用户想要自己的代币
function claimRewards() external {
uint256 reward = pendingRewards[msg.sender];
pendingRewards[msg.sender] = 0;
token.transfer(msg.sender, reward);
}Critical Gotchas (Memorize These)
关键陷阱(牢记)
1. Token Decimals Vary
1. 代币小数位数不同
USDC = 6 decimals, not 18!
solidity
// BAD: Assumes 18 decimals - transfers 1 TRILLION USDC!
uint256 oneToken = 1e18;
// GOOD: Check decimals
uint256 oneToken = 10 ** token.decimals();Common decimals:
- USDC, USDT: 6 decimals
- WBTC: 8 decimals
- Most tokens (DAI, WMON): 18 decimals
- MON (native): 18 decimals
USDC的小数位数是6位,不是18位!
solidity
// 错误:假设18位小数——会转移1万亿USDC!
uint256 oneToken = 1e18;
// 正确:检查小数位数
uint256 oneToken = 10 ** token.decimals();常见小数位数:
- USDC、USDT:6位小数
- WBTC:8位小数
- 大多数代币(DAI、WMON):18位小数
- MON(原生代币):18位小数
2. ERC-20 Approve Pattern Required
2. 必须使用ERC-20授权模式
Contracts cannot pull tokens directly. Two-step process:
solidity
// Step 1: User approves
token.approve(spenderContract, amount);
// Step 2: Contract pulls tokens
token.transferFrom(user, address(this), amount);Never use infinite approvals:
solidity
// DANGEROUS
token.approve(spender, type(uint256).max);
// SAFE
token.approve(spender, exactAmount);合约无法直接提取代币。需分两步操作:
solidity
// 步骤1:用户授权
token.approve(spenderContract, amount);
// 步骤2:合约提取代币
token.transferFrom(user, address(this), amount);绝对不要使用无限授权:
solidity
// 危险
token.approve(spender, type(uint256).max);
// 安全
token.approve(spender, exactAmount);3. No Floating Point in Solidity
3. Solidity不支持浮点数
Use basis points (1 bp = 0.01%):
solidity
// BAD: This equals 0
uint256 fivePercent = 5 / 100;
// GOOD: Basis points
uint256 FEE_BPS = 500; // 5% = 500 basis points
uint256 fee = (amount * FEE_BPS) / 10000;使用基点(1 bp = 0.01%):
solidity
// 错误:结果为0
uint256 fivePercent = 5 / 100;
// 正确:使用基点
uint256 FEE_BPS = 500; // 5% = 500基点
uint256 fee = (amount * FEE_BPS) / 10000;4. Reentrancy Attacks
4. 重入攻击
External calls can call back into your contract:
solidity
// SAFE: Checks-Effects-Interactions pattern
function withdraw() external nonReentrant {
uint256 bal = balances[msg.sender];
balances[msg.sender] = 0; // Effect BEFORE interaction
(bool success,) = msg.sender.call{value: bal}("");
require(success);
}Always use OpenZeppelin's ReentrancyGuard. Reentrancy is still possible on Monad despite parallel execution — parallel execution produces the same results as sequential.
外部调用可以回调到你的合约:
solidity
// 安全:检查-影响-交互模式
function withdraw() external nonReentrant {
uint256 bal = balances[msg.sender];
balances[msg.sender] = 0; // 先执行影响,再执行交互
(bool success,) = msg.sender.call{value: bal}("");
require(success);
}始终使用OpenZeppelin的ReentrancyGuard。尽管Monad支持并行执行,但重入攻击仍然可能——并行执行产生的结果与顺序执行一致。
5. Never Use DEX Spot Prices as Oracles
5. 不要使用DEX现货价格作为预言机
Flash loans can manipulate spot prices instantly:
solidity
// SAFE: Use Chainlink or Pyth
function getPrice() internal view returns (uint256) {
(, int256 price,, uint256 updatedAt,) = priceFeed.latestRoundData();
require(block.timestamp - updatedAt < 3600, "Stale");
require(price > 0, "Invalid");
return uint256(price);
}On Monad, use Chainlink or Pyth for oracle feeds.
闪电贷可以瞬间操纵现货价格:
solidity
// 安全:使用Chainlink或Pyth
function getPrice() internal view returns (uint256) {
(, int256 price,, uint256 updatedAt,) = priceFeed.latestRoundData();
require(block.timestamp - updatedAt < 3600, "数据过时");
require(price > 0, "无效价格");
return uint256(price);
}在Monad上,使用Chainlink或Pyth作为预言机数据源。
6. Vault Inflation Attack
6. 金库通胀攻击
First depositor can steal funds via share manipulation:
solidity
// Mitigation: Virtual offset
function convertToShares(uint256 assets) public view returns (uint256) {
return assets.mulDiv(totalSupply() + 1e3, totalAssets() + 1);
}第一个存款人可以通过份额操纵窃取资金:
solidity
// 缓解方案:虚拟偏移
function convertToShares(uint256 assets) public view returns (uint256) {
return assets.mulDiv(totalSupply() + 1e3, totalAssets() + 1);
}7. Use SafeERC20
7. 使用SafeERC20
Some tokens (USDT) don't return bool on transfer:
solidity
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
using SafeERC20 for IERC20;
token.safeTransfer(to, amount); // Handles non-standard tokens部分代币(如USDT)的transfer方法不返回布尔值:
solidity
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
using SafeERC20 for IERC20;
token.safeTransfer(to, amount); // 处理非标准代币8. Monad-Specific Gotchas
8. Monad专属陷阱
Gas limit billing: Monad charges gas on , NOT actual gas used. Over-estimating gas wastes real MON. Always benchmark and set tight gas limits in production.
gas_limitNo EIP-1559: Always use flag. Type 2 transactions will be rejected.
--legacyNo blob txs: EIP-4844 type 3 transactions are not supported.
No global mempool: Transactions go directly to the block producer. MEV strategies that rely on mempool monitoring do not work the same way.
Parallel execution safety: Monad's parallel execution is deterministic — it produces the same results as sequential execution. Your contracts do NOT need special handling for parallelism. Standard Solidity patterns work as-is.
Historical state: Full nodes do not serve historical state. Do not rely on at past block numbers.
eth_call128KB contract limit: Monad allows contracts up to 128KB (vs Ethereum's 24.5KB). This is generous but not infinite — still optimize if approaching the limit.
Gas上限计费:Monad按收取Gas费用,而非实际使用量。高估Gas上限会浪费真实的MON。生产环境中务必基准测试并谨慎设置上限。
gas_limit不支持EIP-1559:始终使用参数。类型2交易将被拒绝。
--legacy不支持Blob交易:EIP-4844类型3交易不受支持。
无全局内存池:交易直接发送给区块生产者。依赖内存池监控的MEV策略无法以相同方式工作。
并行执行安全性:Monad的并行执行是确定性的——产生与顺序执行相同的结果。你的合约无需为并行执行做特殊处理。标准Solidity模式可直接使用。
历史状态:全节点不提供历史状态。不要依赖过去区块高度的查询。
eth_call128KB合约大小限制:Monad允许最大128KB的合约(以太坊为24.5KB)。尽管空间充裕,但接近上限时仍需优化。
Scaffold-Monad Development
Scaffold-Monad开发
Project Structure
项目结构
packages/
├── foundry/ # Smart contracts
│ ├── contracts/ # Your Solidity files
│ └── script/ # Deploy scripts
└── nextjs/
├── app/ # React pages
└── contracts/ # Generated ABIs + externalContracts.tspackages/
├── foundry/ # 智能合约
│ ├── contracts/ # Solidity文件
│ └── script/ # 部署脚本
└── nextjs/
├── app/ # React页面
└── contracts/ # 生成的ABI + externalContracts.tsEssential Hooks
核心Hooks
typescript
// Read contract data
const { data } = useScaffoldReadContract({
contractName: "YourContract",
functionName: "greeting",
});
// Write to contract
const { writeContractAsync } = useScaffoldWriteContract("YourContract");
// Watch events
useScaffoldEventHistory({
contractName: "YourContract",
eventName: "Transfer",
fromBlock: 0n,
});typescript
// 读取合约数据
const { data } = useScaffoldReadContract({
contractName: "YourContract",
functionName: "greeting",
});
// 写入合约
const { writeContractAsync } = useScaffoldWriteContract("YourContract");
// 监听事件
useScaffoldEventHistory({
contractName: "YourContract",
eventName: "Transfer",
fromBlock: 0n,
});Frontend Chain Configuration
前端链配置
typescript
// CORRECT: Import from viem/chains
import { monadTestnet } from "viem/chains";
// WRONG: Do NOT define a custom chain object
const monadTestnet = { id: 10143, ... }; // NEVER DO THIStypescript
// 正确:从viem/chains导入
import { monadTestnet } from "viem/chains";
// 错误:不要自定义链对象
const monadTestnet = { id: 10143, ... }; // 绝对不要这么做SpeedRun Ethereum Challenges
SpeedRun Ethereum挑战
These challenges use Scaffold-ETH 2 and target Ethereum. They teach EVM fundamentals that are directly applicable to Monad development. Use them for learning, then deploy your projects to Monad.
| Challenge | Concept | Key Lesson |
|---|---|---|
| 0: Simple NFT | ERC-721 | Minting, metadata, tokenURI |
| 1: Staking | Coordination | Deadlines, escrow, thresholds |
| 2: Token Vendor | ERC-20 | Approve pattern, buy/sell |
| 3: Dice Game | Randomness | On-chain randomness is insecure |
| 4: DEX | AMM | x*y=k formula, slippage |
| 5: Oracles | Price Feeds | Chainlink, manipulation resistance |
| 6: Lending | Collateral | Health factor, liquidation incentives |
| 7: Stablecoins | Pegging | CDP, over-collateralization |
| 8: Prediction Markets | Resolution | Outcome determination |
| 9: ZK Voting | Privacy | Zero-knowledge proofs |
| 10: Multisig | Signatures | Threshold approval |
| 11: SVG NFT | On-chain Art | Generative, base64 encoding |
这些挑战基于Scaffold-ETH 2,目标是以太坊。它们教授的EVM基础知识可直接应用于Monad开发。可用于学习,之后将项目部署到Monad。
| 挑战 | 概念 | 核心知识点 |
|---|---|---|
| 0: 简单NFT | ERC-721 | 铸造、元数据、tokenURI |
| 1: 质押 | 协同机制 | 截止时间、托管、阈值 |
| 2: 代币供应商 | ERC-20 | 授权模式、买卖 |
| 3: 骰子游戏 | 随机性 | 链上随机性不安全 |
| 4: DEX | AMM | x*y=k公式、滑点 |
| 5: 预言机 | 价格数据源 | Chainlink、抗操纵 |
| 6: 借贷 | 抵押品 | 健康因子、清算激励 |
| 7: 稳定币 | 锚定机制 | CDP、超额抵押 |
| 8: 预测市场 | 结果判定 | 结果确定方式 |
| 9: ZK投票 | 隐私 | 零知识证明 |
| 10: 多签 | 签名 | 阈值授权 |
| 11: SVG NFT | 链上艺术 | 生成式、base64编码 |
DeFi Protocol Patterns on Monad
Monad上的DeFi协议模式
Euler (Lending)
Euler(借贷)
- Modular lending protocol on Monad
- Supply collateral, borrow assets
- Health factor = collateral value / debt value
- Liquidation when health factor < 1
- Monad上的模块化借贷协议
- 存入抵押品、借入资产
- 健康因子 = 抵押品价值 / 债务价值
- 健康因子<1时触发清算
Morpho (Optimized Lending)
Morpho(优化借贷)
- Peer-to-peer lending optimization layer
- Better rates through direct matching
- Compatible with Monad's parallel execution
- 点对点借贷优化层
- 通过直接匹配获得更优利率
- 兼容Monad的并行执行
AMM / DEX Patterns
AMM/DEX模式
- Constant product formula: x * y = k
- Slippage protection required
- LP tokens represent pool share
- 恒定乘积公式:x * y = k
- 需设置滑点保护
- LP代币代表池份额
Oracles on Monad
Monad上的预言机
- Chainlink: Standard price feeds,
latestRoundData() - Pyth: Pull-based oracle with sub-second updates, well-suited to Monad's speed
solidity
// Chainlink on Monad
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
function getLatestPrice() public view returns (uint256) {
(, int256 price,, uint256 updatedAt,) = priceFeed.latestRoundData();
require(block.timestamp - updatedAt < 3600, "Stale price");
require(price > 0, "Invalid price");
return uint256(price);
}- Chainlink: 标准价格数据源,
latestRoundData() - Pyth: 拉取式预言机,亚秒级更新,适配Monad的速度
solidity
// Monad上的Chainlink使用示例
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
function getLatestPrice() public view returns (uint256) {
(, int256 price,, uint256 updatedAt,) = priceFeed.latestRoundData();
require(block.timestamp - updatedAt < 3600, "价格过时");
require(price > 0, "无效价格");
return uint256(price);
}ERC-4626 (Tokenized Vaults)
ERC-4626(代币化金库)
- Standard interface for yield-bearing vaults
- deposit/withdraw with share accounting
- Protect against inflation attacks
- 生息金库的标准接口
- 存入/取出时的份额记账
- 防范通胀攻击
Security Review Checklist
安全审查清单
Before deployment, verify:
- Access control on all admin functions
- Reentrancy protection (CEI + nonReentrant)
- Token decimal handling correct
- Oracle manipulation resistant (Chainlink or Pyth, not DEX spot)
- Integer overflow handled (0.8+ or SafeMath)
- Return values checked (SafeERC20)
- Input validation present
- Events emitted for state changes
- Incentives designed for maintenance functions
- NO infinite approvals (use exact amounts, NEVER type(uint256).max)
部署前,请验证:
- 所有管理员函数的访问控制
- 重入保护(CEI模式 + nonReentrant修饰器)
- 代币小数位数处理正确
- 预言机抗操纵(使用Chainlink或Pyth,而非DEX现货价格)
- 整数溢出处理(0.8+版本或SafeMath)
- 返回值检查(使用SafeERC20)
- 输入验证存在
- 状态变更时触发事件
- 维护函数的激励设计合理
- 无无限授权(使用精确金额,绝对不要用type(uint256).max)
Monad-Specific Checks
Monad专属检查项
- in foundry.toml
evm_version = "prague" - Solidity version 0.8.27+ (recommend 0.8.28)
- All deploy commands use flag
--legacy - All deploy commands use (not
forge script)forge create - Gas limits set carefully (charged on limit, not usage)
- No reliance on historical state queries
- No EIP-4844 blob transactions
- Mainnet deployments use hardware wallet (not )
--private-key - Contract size under 128KB
- Wallet files stored at with chmod 600
~/.monad-wallet
- foundry.toml中设置
evm_version = "prague" - Solidity版本为0.8.27+(推荐0.8.28)
- 所有部署命令使用参数
--legacy - 所有部署命令使用(而非
forge script)forge create - 谨慎设置Gas上限(按上限计费,而非实际使用量)
- 不依赖历史状态查询
- 不使用EIP-4844 Blob交易
- 主网部署使用硬件钱包(而非)
--private-key - 合约大小低于128KB
- 钱包文件存储在,并设置权限chmod 600
~/.monad-wallet
Response Guidelines
响应指南
When helping developers:
- Default to testnet - Chain ID 10143 unless user says mainnet
- Answer directly - Address their question first
- Show code - Provide working examples with Monad config
- Always use - Remind about no EIP-1559 support
--legacy - Always use - Never suggest
forge scriptforge create - Warn about gotchas - Proactively mention relevant pitfalls
- Reference challenges - Point to SpeedRun Ethereum for practice (note: they target Ethereum)
- Ask about incentives - For any "automatic" function, ask who calls it and why
- Gas limit awareness - Remind that gas is charged on limit, not usage
- Verification - Always include contract verification step after deployment
协助开发者时:
- 默认使用测试网——链ID 10143,除非用户指定主网
- 直接回答问题——先解决用户的核心疑问
- 提供代码示例——给出带有Monad配置的可运行示例
- 始终提醒使用——强调不支持EIP-1559
--legacy - 始终推荐——绝对不要建议使用
forge scriptforge create - 提前预警陷阱——主动提及相关的潜在问题
- 参考学习挑战——引导用户使用SpeedRun Ethereum练习(注意:这些挑战针对以太坊)
- 询问激励机制——对于任何“自动执行”的函数,询问谁会调用以及调用动机
- Gas上限意识——提醒用户Gas费用按上限计费,而非实际使用量
- 验证步骤——部署后始终包含合约验证步骤