Solana 学习开发之旅

2025年04月03日更新 33 人订阅
原价: ¥ 20 限时优惠
专栏简介 【Solana】使用 CLI 创建 SPL 标准的 Token 以及基础使用 【Solana】完善 SPL Token 名称和 Logo 【Solana】创建 SPL 标准的 NFT 以及完善 metadata 【Solana】一些基本的js脚本 【Solana】Anchor 框架使用笔记 【Solana】Anchor 示例:通过 CPI 实现 Sol 转账与手续费收取 Solana Hello World: 安装与开发指南 Solana 与 Rust 算术入门—从 Solidity 到 Anchor Solana Anchor 程序接口定义语言(IDL) Solana Anchor 框架下的 Require 与自定义错误 Solana 程序:支持升级与无构造函数实现 Solidity 开发者必知的 Rust 语法基础 Rust 的独特语法解析 Rust 类函数宏解析 Rust 结构体、属性宏与自定义派生宏 Rust 与 Solana 中的可见性及模块化复用 Solana 中的时钟与其他区块变量 Solana 系统变量详解 Solana 日志、事件日志与历史交易查询 Solana 中的Tx.origin、msg.sender 和 onlyOwner Solana 计算单元与交易费用概述 Solana 与 Anchor 中的账户初始化 Solana 计数器教程:账户数据的读写 使用 Solana Web3.js 和 Anchor 读取账户数据 在 Solana 中实现映射表与嵌套映射表 Solana 存储成本、最大容量与账户调整 在 Anchor 中读取账户余额:Solana 的 address(account).balance Solana 中的函数修饰符与 Fallback 函数:为何不存在 Solana 中的 SOL 转移与分割:取代 msg.value 的设计 使用不同签名者修改账户:Solana 中的权限控制 PDA 与密钥对账户:Solana 中的地址与权限模型 Anchor 中的 init_if_needed 与重新初始化攻击防范 Solana 中的 Multicall:批处理交易和交易大小的限制 Solana 中的 Owner 和 Authority 删除和关闭 Solana 中的账户和程序 在 Anchor 中的 #[derive(Accounts)] 不同类型的账户 在链上读取另一个 Anchor 程序的账户数据 Anchor 中的跨程序调用

Solana 与 Rust 算术入门—从 Solidity 到 Anchor

  • 0xE
  • 发布于 2025-03-21 15:03
  • 阅读 1290

本文将通过一个简单的 Solana 程序,展示如何用 Anchor 实现类似 Solidity 的算术功能,并深入探讨 Rust 在 Solana 中的基本类型、算术运算及计算单元(Compute Units)。

本文将通过一个简单的 Solana 程序,展示如何用 Anchor 实现类似 Solidity 的算术功能,并深入探讨 Rust 在 Solana 中的基本类型、算术运算及计算单元(Compute Units)。我们将创建一个 arithmetic 程序,模拟以下 Solidity 合约:

contract Arithmetic {
    event Result(uint256);
    event Who(string, address);

    function doSomeMath(uint256 a, uint256 b) public {
        uint256 result = a + b;
        emit Result(result);
    }

    function sayHelloToMe() public {
        emit Who("Hello World", msg.sender);
    }
}

环境配置与项目初始化

设置开发环境

确保以下工具已安装(具体安装命令见上一节):

  • Rust:笔者用的 1.78.0。
  • Solana CLI:使用 stable 通道(如 1.18.17)。
  • Anchor:推荐课程配套环境 0.29.0。
  • Yarn:用于运行测试。

启动本地验证器:

solana-test-validator

创建项目

初始化 Anchor 项目并同步密钥:

anchor init arithmetic
cd arithmetic
solana config set --url localhost
  • 验证:运行 anchor test --skip-local-validator,确保环境正常。

实现基本功能

传递参数:整数与字符串

Solana 使用 u64(类似 Solidity 的 uint64)作为标准无符号整数,而非 uint256。修改 lib.rs:

use anchor_lang::prelude::*;

declare_id!("F9h68899K9Mo4cn1gJsXsGZMukYyWmEzZaaomqiFHLXN");

#[program]
pub mod arithmetic {
    use super::*;

    pub fn initialize(ctx: Context<Initialize>, a: u64, b: u64, message: String) -> Result<()> {
        msg!("You said {:?}", message);
        msg!("You sent {} and {}", a, b);
        Ok(())
    }
}

#[derive(Accounts)]
pub struct Initialize {}

复制完代码后,使用 anchor keys sync 命令同步密钥。

更新 tests/arithmetic.ts:

it("Is initialized!", async () => {
    const tx = await program.methods
        .initialize(new anchor.BN(777), new anchor.BN(888), "hello")
        .rpc();
    console.log("Your transaction signature", tx);
});

运行测试:

anchor test --skip-local-validator
  • 日志输出

    Program log: You said "hello"
    Program log: You sent 777 and 888
  • 注意:anchor.BN 用于处理大整数,避免 JavaScript 的精度问题。


处理数组

Rust 使用 Vec<T> 表示动态数组,类似 Solidity 的 array。添加新函数:

pub fn array(ctx: Context&lt;Initialize>, arr: Vec&lt;u64>) -> Result&lt;()> {
    msg!("Your array {:?}", arr);
    Ok(())
}

更新测试:

it("Array test", async () => {
    const tx = await program.methods
        .array([new anchor.BN(777), new anchor.BN(888)])
        .rpc();
    console.log("Your transaction signature", tx);
});

运行测试后日志:

Program log: Your array [777, 888]

Solana 中的算术运算

整数运算与溢出保护

Solana 的计算单元(CU)限制为 200,000,算术操作需高效。Rust 默认不检查溢出,但有两种方法防范:

  1. 全局溢出检查在 Cargo.toml 中启用:

    [profile.release]
    overflow-checks = true
    • 优点:编译时自动检查溢出。
    • 缺点:增加少量计算成本。
  2. 手动检查使用 checked_* 方法:

    let x: u64 = y + z;
    let xSafe: u64 = y.checked_add(z).unwrap();
    • 优点:精确控制,节省 CU。
    • 日志:若溢出,交易失败并显示错误。

指数运算

Rust 使用 .pow() 替代 Solidity 的 **:

let x: u64 = 2;
let y = 3;
let result = x.pow(y);

浮点数运算

Rust 支持浮点数(如 f32、f64),但 Solana 不推荐,因其消耗更多 CU。例如,计算立方根:

pub fn cube_root(ctx: Context&lt;Initialize>, a: f32) -> Result&lt;()> {
    msg!("Cube root of {} is {}", a, a.cbrt());
    Ok(())
}

测试:

it("Cube root test", async () => {
    await program.methods.cube_root(50.0).rpc();
});
  • 日志

    Program log: Cube root of 50 is 3.6840315
    Program consumed 3597 of 200000 compute units
  • 对比:普通加法仅耗 ~700 CU,浮点运算成本高 4-5 倍。


故障排查

账户空间不足

若部署失败:

Error: account data too small for instruction

解决:

  1. 检查程序大小,输出会显示当前账户的 Data Len(数据长度):

    solana program show &lt;PROGRAM_ID>
  2. 扩展空间:

    solana program extend &lt;PROGRAM_ID> 20000 -u http://127.0.0.1:8899 -k ~/.config/solana/id.json
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论