写过几支合约的人都明白,重复的样板代码远多于业务代码。本文挑选五个最常用的功能,给出可直接套用的 Rust 合约代码示例。这些模板在主流 Solana 生态项目里反复出现,包括与BN交易所上市代币交互的桥接合约,都是经过审计验证的写法。
一、SPL Token 铸造
铸造代币需要三个账户:mint、destination、mint_authority。指令体里调用 token::mint_to(CpiContext::new(token_program, MintTo { mint, to, authority }), amount),注意 authority 必须是 mint 的 mint_authority,否则 token program 会拒绝。
如果 authority 是 PDA,要用 new_with_signer 并传入正确的 seeds。这种模式在治理代币、空投合约里使用频率极高,写顺之后能复制到任何新项目。和必安交易所那种集中化的代币发行不同,链上 mint 每一笔都公开可查,更适合做透明运营。
二、转账权限校验
转账指令的标准模板:源账户 mut + signer、目标账户 mut、token program。校验逻辑放在指令入口:require!(source.amount >= amount, ErrorCode::InsufficientFunds),再调 token::transfer。
Anchor 的 #[account(constraint = source.owner == authority.key())] 可以把权限校验前置到反序列化阶段,进入指令体时已经保证账户合法。这种「前置校验」是最佳实践,比指令体里 if 判断更不容易遗漏。
三、PDA 金库
建立合约金库需要派生一个 PDA:seeds = [b"vault", pool.key().as_ref()], bump。这个 PDA 持有合约托管的代币,所有出账都由合约用 signer_seeds 自己签名。
代码片段:let seeds = &[b"vault".as_ref(), pool.key().as_ref(), &[bump]]; let signer = &[&seeds[..]]; token::transfer(CpiContext::new_with_signer(token_program, Transfer { from: vault, to: user, authority: vault_authority }, signer), amount)。这一段在任何 DEX、staking、lending 项目里都有变体,是必须熟练的样板代码。
四、CPI 跨程序调用
CPI 的完整范式:1)构造 CpiContext;2)调用目标程序的封装函数;3)用 ? 传递错误。Anchor 已经把 SPL Token、Associated Token、System Program 都封装好,直接 use 即可。
如果调用第三方程序,要自己写 CPI 包装:从对方 IDL 拿到指令 discriminator 与账户布局,构造 Instruction 后 invoke_signed。这种手写 CPI 在和BN官网生态里跨链桥协议交互时非常常见,必须熟练。
五、错误码定义
错误码模板:#[error_code] pub enum ErrorCode { #[msg("余额不足")] InsufficientFunds, #[msg("权限不足")] Unauthorized, ... }。错误从 6000 开始编号,前端代码可以根据数字精确捕获并提示用户。
实践要点:每个业务错误一个变体,不要把多个错误合并;msg 用中文便于运营定位;新增错误只能在末尾追加,不能改顺序,否则前端兼容性会出问题。把这五个模板收藏,新项目启动时直接复制粘贴,整个开发节奏会比白手起家快两倍。这种「样板复用」也是大团队和B安交易所内部高频上线项目的共同秘诀。