跳转到内容

Anchor — Solana 合约开发框架

是什么

Anchor 是 Solana 智能合约的开发框架——你用 Rust 写一份合约,它替你自动生成账户校验、指令分派、还有给前端用的 TypeScript 客户端。日常类比:像装修队的”全包”——你只说”我要个三室一厅,主卧朝南”,它把水电、墙面、家电、合同全办完。

写原生 Solana 合约的痛苦:每个指令进来你得自己解析字节、检查每个账户的所有者、校验签名、做反序列化、手写前端 SDK。一份业务逻辑可能要配三份样板代码。

Anchor 的解法是三个宏 + 一份 IDL#[program] 让 Rust 函数自动变成指令;#[derive(Accounts)] 把账户约束写进结构体;编译时输出 idl.json 描述合约接口,TS 客户端直接读它生成类型化调用。

#[program]
mod counter {
pub fn increment(ctx: Context<Increment>) -> Result<()> {
ctx.accounts.counter.count += 1;
Ok(())
}
}

为什么重要

不理解 Anchor,下面这些事都没法解释:

  • 为什么 Solana dapp 开发体验比早期好那么多——Jupiter / Drift / Marinade 几乎都靠它
  • 为什么 Solana 圈说”账户混淆漏洞”基本绝迹——Anchor 的约束宏在编译期就堵了
  • 为什么 Solana 合约部署后前端不用手写 ABI 解析——IDL + 自动生成 TS 客户端
  • 为什么有人把 Anchor 比作 foundry 之于以太坊——一套 DSL 把繁琐细节藏进框架

核心要点

Anchor 的工程价值可以拆成 三层魔法

  1. 指令分派宏#[program] 标在一个 Rust mod 上,里面每个 pub fn 都自动变成一条链上指令。类比:把函数签到一个”前台名册”,请求一来按名字派单。背后是 procedural macro 在编译期生成 8 字节 discriminator(SHA256 前缀)做路由。

  2. 账户约束 DSL#[derive(Accounts)] 让结构体字段自带”我必须可写、我必须有签名、我必须是 PDA”等检查。类比:海关申报单——填错字段直接拦下,不让进货。mut / signer / seeds / has_one 这些关键字组合起来覆盖 90% 安全检查。

  3. IDL + 客户端自动生成anchor build 把宏元数据序列化成 idl.json,里面有所有指令名、参数类型、账户结构。前端 @coral-xyz/anchor 包读 IDL 后给你一个完全类型化的 program.methods.foo().rpc() 调用。类比:合约编译完顺手吐出一份”接口说明书”,TS 客户端拿来直接对号入座。

三层加起来,让开发者写一份 Rust,前后端一起搞定。

实践案例

案例 1:最简 Counter 合约

#[program]
mod counter {
pub fn initialize(ctx: Context<Init>, start: u64) -> Result<()> {
ctx.accounts.counter.count = start;
Ok(())
}
}
#[derive(Accounts)]
pub struct Init<'info> {
#[account(init, payer = user, space = 8 + 8)]
pub counter: Account<'info, Counter>,
#[account(mut)]
pub user: Signer<'info>,
pub system_program: Program<'info, System>,
}

逐部分解释:init 让 Anchor 自动调系统程序创账户;space = 8 + 8 是 8 字节 discriminator + 8 字节 u64;Signer 强制 user 必须签名。

案例 2:PDA 派生地址

每个用户给自己开一个 vault:

#[derive(Accounts)]
pub struct Deposit<'info> {
#[account(
mut,
seeds = [b"vault", user.key().as_ref()],
bump,
)]
pub vault: Account<'info, Vault>,
pub user: Signer<'info>,
}

seeds + bump 让 Anchor 在合约和客户端用同一套规则推导出确定性地址。这是 Solana 没有 mapping 的原因——所有”按 key 查 value”都靠 PDA。

案例 3:TypeScript 客户端类型化调用

import { Program } from '@coral-xyz/anchor'
import idl from './idl/counter.json'
const program = new Program<Counter>(idl, provider)
await program.methods
.increment()
.accounts({ counter: counterPda })
.rpc()

Program<Counter> 的泛型从 IDL 生成的 Counter 类型来;编辑器能补全 methods.increment,写错字段名当场红线。整套流程不用手写一行 ABI 解析。

踩过的坑

  1. PDA seeds 双方对不上:合约写 [b"vault", user.key()],客户端 findProgramAddressSync(["vault", user.toBuffer()])——少了 b 前缀字符串编码不一致,交易报 ConstraintSeeds 但根因要扒源码。

  2. #[account(mut)] 漏写:只读约束的账户在指令里被改写 state,运行时报 ProgramFailedToComplete,新人很难定位到是缺了一个 mut 标注。

  3. space 算错:Anchor 不会替你自动算结构体字节数,initspace = ... 写小了或加字段忘改,下次 realloc 直接失败,且改完要重部署整个合约。

  4. 升级后 IDL 没同步:合约改了指令签名却忘了 anchor idl upgrade,前端 TS 客户端用老 IDL 类型,调用新指令在链上 discriminator 不匹配,报 InstructionFallbackNotFound。

适用 vs 不适用场景

适用

  • 95% 的 Solana 合约项目——DeFi、NFT、游戏、SocialFi 主流 dapp 都用它
  • 需要前后端类型一致的项目——IDL + TS 客户端省下大量手写 binding
  • 团队多人协作——账户约束 DSL 让 review 时安全问题一眼看出

不适用

  • 极致性能 / compute units 优化场景——宏生成的代码会比手写多几百 CU,吃紧时要回到原生
  • 需要复杂动态分派或非常规账户布局——Anchor 的约束语法不够灵活,硬塞会很别扭
  • 与其他链共享代码——Anchor 是 Solana 专属,跨链场景反而是负担
  • 链下密集计算——智能合约本身就不该干这事,跟框架无关

历史小故事(可跳过)

  • 2021 年初:Armani Ferrante 在做 Serum DEX 合约时受不了样板代码,开了个叫 anchor-lang 的 side project
  • 2021 中:Anchor 0.10 发布,已经能用 IDL 生成 TS 客户端,社区开始迁移
  • 2022 年:FTX/Alameda 倒闭,Serum 项目变冷,coral-xyz 组织接手 Anchor 维护
  • 2024 年:Anchor 0.30 发布,重构了 IDL 格式(从老 anchor IDL 升级到 codama 风格),向后兼容做了大量工作
  • 2026 年:仍是 Solana 官方推荐框架,绝大多数新合约模板基于它

学到什么

  • 一个好框架的核心是”把对的东西变成默认”——Anchor 把账户校验从可选变成必选,安全漏洞自然减少
  • IDL 是合约和客户端之间的契约,自动生成比人工同步可靠 100 倍——这点和 protobuf / OpenAPI 思路一致
  • Rust procedural macro 的威力——一个 #[derive(Accounts)] 能展开几十行校验代码,开发者完全不感知
  • 框架选型的取舍永远在”灵活性 vs 安全/便捷”之间——Anchor 选了后者,性能极致党会去手写

延伸阅读

  • 官方文档:anchor-lang.com/docs(中英双语,含 PDA / IDL / 测试一整套教程)
  • 视频入门:Solana Bytes — Anchor 101(30 分钟跑通第一个合约)
  • 源码:github.com/coral-xyz/anchor(lang/syn/cli 三个核心 crate)
  • solana —— Anchor 是 Solana 上的工具,先看底层账户模型才看得懂为什么需要 Anchor
  • foundry —— 以太坊侧的同类对比:Foundry 是 EVM 工具链,Anchor 是 Solana 工具链

关联

  • solana —— Anchor 跑在 Solana 上,账户模型、PDA、租金都是 Solana 概念,Anchor 只是包了一层
  • foundry —— EVM 世界的同类——Foundry 偏测试和部署,Anchor 偏合约 DSL,定位略有差异
  • cairo-lang —— Starknet 的合约语言,类似定位但更激进(自己造语言而不是 eDSL)
  • ape-framework —— Python 系 EVM 开发框架,跨链对比的另一个参照
  • remix-ide —— EVM 在线 IDE,对应 Anchor 是命令行工具栈,工作流非常不同
  • uniswap-v3 —— 以太坊主流 DeFi 合约,技术栈和 Anchor 生态下的 Jupiter / Drift 形成对比
  • safe-contracts —— Gnosis Safe 多签合约,体现 EVM 侧合约工程化的另一极

反向链接

  • ape-framework —— Ape Framework — Python 智能合约开发一条龙
  • aptos-core —— Aptos — Move 系高性能 L1
  • cairo-lang —— Cairo — Starknet 的 zk 友好编程语言
  • cosmos-sdk —— Cosmos SDK — 应用链开发框架
  • cosmwasm —— CosmWasm — Cosmos 上的 wasm 智能合约
  • foundry —— Foundry — Paradigm 出品的 Rust 合约工具链
  • ipfs —— IPFS / Kubo — 按内容哈希定位的去中心化文件系统
  • move-language —— Move — 资源型智能合约语言
  • openzeppelin-contracts —— OpenZeppelin Contracts — 以太坊智能合约的事实标准库
  • remix-ide —— Remix IDE — 浏览器内 Solidity IDE
  • safe-contracts —— Safe — 多签智能账户合约
  • solana —— Solana — Rust 写的高性能 PoH 链
  • sui —— Sui — 把链上资产拆成一个个独立对象的 L1
  • uniswap-v3 —— Uniswap V3 — 集中流动性 AMM 核心合约
  • viem —— viem — 现代 TypeScript EVM 库