Solana 智能合约 101:从零完成第一次合约编译与部署

·

关键词:Solana、智能合约、开发网、合约部署、BPF 编译、Rust、Solana CLI

一、准备工作:工具与环境检查

在进入实操之前,先确保你已在本地完整安装 Solana CLI(包含秘钥生成器 solana-keygen 与编译工具集)。执行以下命令快速验证:

solana --version
cargo --version

若提示找不到命令,请先回到官方文档完成安装,再继续阅读。——工具 OK,就可以开始实战了。

二、连接 Solana 开发网(Devnet)

主网节点的维护成本高、上链费用大,Solana 官方提供了与主网逻辑一致的 开发网(Devnet) 作为沙盒。你只须一条指令切换:

solana config set --url https://devnet.solana.com

执行完毕后会看到:

RPC URL: https://devnet.solana.com
WebSocket URL: wss://devnet.solana.com/

网络重置后,默认向开发网发出所有 solana 子命令。👉 还没装好节点环境?这里把安装环境踩坑点一次说清

三、准备账号:支付账号 + 程序账号

每个 Onchain Program 实质也是一个 Account,但标记为 executable: true。要把它写进链,需要先创建:

  1. 支付账号:存 SOL 付租金与 gas。

    solana-keygen new
    solana-keygen pubkey ~/.config/solana/id.json

    示例公钥:7FqW6xXE4sMmZSeVxFsoTr83He4MhhePvA1vRAv9zgQf

  2. 给支付账号领测试 SOL

    solana airdrop 10 7FqW6xXE4sMmZSeVxFsoTr83He4MhhePvA1vRAv9zgQf
    solana balance 7FqW6xXE4sMmZSeVxFsoTr83He4MhhePvA1vRAv9zgQf  # 验证
  3. 程序账号:核心文件发布的地址。

    solana-keygen new -o solana_memo_program.json

保存好 solana_memo_program.json,一会用于部署。

四、编译合约:memo 示例实战

官方提供了完整示例仓库:

git clone https://github.com/solana-labs/solana-program-library.git
cd solana-program-library/memo/program
cargo build-bpf

第一次编译时若遇到 cannot find Scrt1.o,安装 32 位扩展库即可:

sudo apt install gcc-multilib

成功后会提示:

To deploy this program:
$ solana deploy .../spl_memo.so

五、部署合约:一行指令上链

获取程序账号的公钥:

solana-keygen pubkey ~/solana_memo_program.json

得到示例:D8Cnv1UcThay2WijWP4SQ8G683UuVsKPaZEU7TNVKW1j

正式上链:

solana deploy target/deploy/spl_memo.so ~/solana_memo_program.json

日志中出现 { "programId": "D8Cnv1UcThay2WijWP4SQ8G683UuVsKPaZEU7TNVKW1j" } 即部署成功。

打开 Solana Explorer,切换网络至「Devnet」,粘贴上面程序地址即可查看合约详情。👉 把合约部署到主网前,这几个测试陷阱建议先来回避

六、前端调用:用 @solana/web3.js 发交易

  1. 初始化 Node 项目

    yarn init -y
    yarn add @solana/web3.js
  2. 新建 src/index.js

    const solanaWeb3 = require('@solana/web3.js');
    
    async function testMemo(connection, payerKeypair) {
      const ix = new solanaWeb3.TransactionInstruction({
        keys: [],
        programId: new solanaWeb3.PublicKey('D8Cnv1UcThay2WijWP4SQ8G683UuVsKPaZEU7TNVKW1j'),
        data: Buffer.from('cztest')
      });
    
      await solanaWeb3.sendAndConfirmTransaction(
        connection,
        new solanaWeb3.Transaction().add(ix),
        [payerKeypair],
        { skipPreflight: true, commitment: "singleGossip" }
      );
      console.log('done');
    }
    
    async function main() {
      const connection = new solanaWeb3.Connection('https://devnet.solana.com', 'singleGossip');
      const payerKeypair = new solanaWeb3.Keypair();
      await connection.requestAirdrop(payerKeypair.publicKey, 10 * 1e9);
      testMemo(connection, payerKeypair);
    }
    
    main();

运行后,前端先空投 10 SOL,再向程序发送 cztest;链上记录 hex: 637a74657374,翻译回来正是 cztest,调用成功。

七、手写一个新合约

多次跑示例后,如何从零构建自己的合约?流程几乎与普通 Rust 库无异:

1. 新建项目

cargo new onchain_program

2. 修改 Cargo.toml

[package]
name = "onchain_program"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
solana-program = "1.4"

新增 Xargo.toml 指定 BPF 目标:

[target.bpfel-unknown-unknown.dependencies.std]
features = []

3. 编写代码

src/lib.rs 定义入口:

use solana_program::{
    account_info::AccountInfo, entrypoint, entrypoint::ProgramResult,
    program_error::ProgramError, pubkey::Pubkey,
};

entrypoint!(process_instruction);

pub fn process_instruction(
    _program_id: &Pubkey,
    _accounts: &[AccountInfo],
    _instruction_data: &[u8],
) -> ProgramResult {
    Ok(())
}

至此,「不做事直接返回成功」的最小合约就写好了。

4. 编译

cd onchain_program
cargo build-bpf

控制台输出路径后,复制 .so 使用前述 solana deploy 命令即可一键上链。

八、FAQ:开发者最常问的几件事

Q1:开发网 SOL 领完了怎么办?
A:Solana 官方每天提供 2 SOL 的自动水龙头,如需大额可直接换账号或等待下次重置。

Q2:为何一定要 32 位依赖?
A:目前的 BPF 编译工具链仍依赖 32 bit glibc 支持,安装 gcc-multilib 即可解决。

Q3:主网与开发网的 Program 大小限制一致吗?
A:一致,均为 1232 bytes;超出需做压缩或分片,详见 max-retuned-data 字段。

Q4:Rust 特性全部可用吗?
A:不是。标准库部分功能(如 std::thread)在 BPF 运行时被裁剪,完整限制可阅读官方Rust-limitations

Q5:前端交易确认慢怎么优化?
A:在 @solana/web3.js 中启用 processed 级别的 commitment,可显著缩短确认延迟;正式上线前再切回 confirmedfinalized 以保证安全性。

Q6:部署后还能更新合约吗?
A:不可直接更新。Solana Program 是一旦上链即不可修改,需要采用「升级代理合约方案」或重新部署新地址并迁移资产。


总结:从环境、账号、编译到部署再到前端调用,这篇文章帮你走完 Solana 智能合约的最小闭环。掌握工具链核心原理后,无论是写 AMM、NFT 还是游戏链逻辑,都只是换接口、换业务的数据结构而已。祝你在 Solana 生态里代码一路绿灯!