面向 Solidity 开发者的 Cairo 教程

本文是 Cairo 编程的入门教程,面向有 Solidity 经验的开发者,旨在帮助他们快速上手 Cairo 语言。教程介绍了 Cairo 的基本概念、安装配置、项目结构,以及Cairo与Solidity的异同,还包括Starknet账户创建和初始化,以及如何避免旧版本 Cairo 代码的问题。

Cairo 是一种受 Rust 启发的语言,它可以编译成字节码,并在 Cairo 虚拟机上运行。Cairo 虚拟机是一种零知识虚拟机 (ZKVM),Starknet 区块链使用它来执行智能合约。在本教程系列中,我们不假设你事先有 Rust 或零知识证明的经验。但是,本教程系列假设你事先有 Solidity 的经验。我们希望读者知道如何编写 ERC-20 和 ERC-721,并且对 Uniswap V2 等 dApp 的工作方式有一个概念性的了解。

Cairo 经过精心设计,可以帮助 Solidity 开发人员快速学习这门语言,本系列重点介绍它们之间的相似之处,以便 Solidity 开发人员可以重用从 Solidity 中获得的思维模型来快速理解 Cairo。

Cairo 入门

要开始编写 Cairo 智能合约,你需要 Scarb(Cairo 的包管理器和构建工具)和 Starknet Foundry(用于开发、部署和测试 Cairo 智能合约的工具链)。

安装

安装这些工具的最简单方法是使用 starkup,它可以通过一个命令自动安装 Scarb、Starknet Foundry 和 Cairo 编译器。

但是,在撰写本文时,starkup 安装的 Scarb 版本是 2.11.4,snforge 版本是 0.48.1

对于本教程系列,我们需要 Scarb v2.12.0 和 snforge 0.48.0,以避免兼容性问题,因为本系列中的某些语法可能会导致其他版本表现不同或无法编译某些示例。

要使用这些特定版本,我们建议通过 asdf 安装,因为它允许精确的版本控制以及管理不同编程工具的多个版本的能力。如果你没有安装 asdf,请按照安装指南

注意:本指南使用 asdf v0.16.0 或更新版本。如果你使用的是较旧的版本,我们建议更新到最新版本。

设置 Scarb 版本 v2.12.0

  • 将 Scarb 插件添加到 asdf:
asdf plugin add scarb
  • 安装 Scarb 版本 2.12.0:
asdf install scarb 2.12.0
  • 为 2.12.0 设置版本:
## 全局设置所有项目
asdf set scarb 2.12.0

设置 Starknet Foundry v0.48.0

  • 将 Starknet Foundry 插件添加到 asdf:
asdf plugin add starknet-foundry
  • 安装版本 0.48.0:
asdf install starknet-foundry 0.48.0
  • 为 0.48.0 设置版本:
## 全局设置所有项目
asdf set starknet-foundry 0.48.0
  • 重新启动 shell 以使更改生效:
exec zsh  # or exec bash if using bash

验证安装:

scarb --version
snforge --version

显示正在运行 scarb 和 snforge 版本命令的终端

创建你的第一个项目

创建一个只包含小写字母和下划线的空目录(例如,hello_world)。避免使用大写字母或破折号 (-),因为 Scarb 包名称必须遵循 snake_case 约定。进入目录,然后运行:

scarb init

出现提示时,从选项列表中选择 Starknet Foundry (默认)

显示选择 Starknet Foundry 的终端

这将创建一个简单的 Cairo 合约,用于存储和更新单个 balance 值(类似于 Foundry 用于 Solidity 的默认 Counter 合约)。

项目结构

在代码编辑器中打开项目时,你将看到以下项目结构:

hello_world/
├── src/
│   └── lib.cairo           # 你的主要合约代码
├── tests/
│   └── test_contract.cairo # 测试文件放在这里
├── Scarb.toml              # 项目配置和依赖项
├── Scarb.lock              # 精确依赖项版本的锁定文件
├── snfoundry.toml          # Starknet Foundry 配置
└── .gitignore              # Git 忽略文件
  • src/ 是合约文件所在的位置。 lib.cairo 是主要的入口点;默认情况下,Scarb 会生成一个简单的 HelloStarknet 合约来管理余额。
  • tests/ 包含用于验证合约功能的测试文件。
  • Scarb.toml 定义项目依赖项、Cairo 编译器版本、包元数据和构建设置(类似于 Node.js 中的 package.json 或 Rust 中的 Cargo.toml)。你可以在此处管理合约使用的库。
  • Scarb.lock 记录精确的依赖项版本。
  • snfoundry.toml 配置 Starknet Foundry 设置:RPC 端点、帐户配置和测试执行选项。虽然 Scarb.toml 管理你的项目和依赖项,但 snfoundry.toml 配置 Foundry 工具。

设置语法高亮

如果你使用 VS Code 或它的一个分支,安装 Cairo 1.0 扩展 来进行语法高亮。安装后,VS Code 将识别 .cairo 文件,并提供自动完成和错误高亮等功能。请注意,伪造的 VSCode 扩展是一种常见的社会工程策略,因此请仔细检查发布者。

显示搜索 Cairo 语言扩展的图片

打开 src/lib.cairo 查看 Scarb 生成的代码。我们将在下一章中解释语法。

scarb 创建的默认代码

要编译你的合约,运行:

scarb build

这将编译你的 Cairo 代码,并在 target/ 目录中生成已编译的合约文件。这些文件是你将部署到 Starknet 的文件。

然后你可以使用以下命令测试项目:

scarb test

类似于 Solidity 的 Cairo 概念

Cairo 智能合约有一个“存储变量”的概念,它支持 Solidity 开发人员习惯的类型,例如整数、字符串、映射、数组、布尔值等等。

以下概念与 Solidity 有 1 对 1 或几乎 1 对 1 的类比:

  • 存储变量和存储槽
  • 发出事件
  • public、internal 和 view 函数
  • require 语句
  • msg.senderblock.timestampblock.number
  • 构造函数
  • 用于声明外部函数的接口
  • 合约可以调用其他合约,并使用 ABI 来知道如何调用其他合约
  • 合约可以创建其他合约
  • 交易花费“gas”来阻止垃圾邮件
  • OpenZeppelin 作为该语言的事实上的“标准库”

与 Solidity 的主要区别

与 Solidity 相比,Cairo 合约具有以下功能和/或差异:

  • Cairo 支持内存哈希映射(Solidity 仅支持存储映射)
  • Solidity 内存数组在声明时必须具有定义的大小,但 Cairo 没有此限制
  • Cairo 具有从 Rust 继承的更具表现力的控制流语法(例如模式匹配)
  • 与 Rust 一样,Cairo 不是面向对象的,因此不支持继承。但是,Cairo 提供了其他将代码组合在一起的方法
  • Solidity 合约通过代理模式升级;但是,Cairo 合约可以在保持存储不变的情况下升级其字节码
  • Cairo 中没有“原生代币”,因此没有 msg.value。默认情况下,gas 是使用 STRK 代币支付的,STRK 代币是一种 ERC-20 代币。你可以在此处的浏览器上查看该代币。
  • Starknet 在协议中内置了帐户抽象,因此不存在“外部拥有地址 (EOA)”

最后一点可能会给来自 EVM 兼容链的开发人员带来一些困惑,但不用担心,我们将在稍后详细探讨这一点。

Starknet 上的帐户创建

要了解 Starknet 上帐户创建的生命周期,你可以使用 Ready(以前的 Argent)或 Braavos 钱包创建一个钱包。下面的视频展示了使用浏览器扩展创建 Ready 钱包的过程。

安装钱包后,请注意它默认设置为主网。对于本教程,通过单击 Ready 钱包顶部的网络选择器并选择“Sepolia”来切换到 Sepolia 测试网。然后按照下面的视频中显示的过程在 Sepolia 上创建一个新帐户:

接下来,复制你的钱包地址并将其粘贴到 Starknet 区块浏览器中。你可以使用 StarkscanVoyager。确保也将浏览器切换到 Sepolia 测试网(在页面右上角)。

由于这是一个新创建的钱包,没有交易历史记录,因此浏览器不会显示任何结果。

没有交易历史记录的钱包

要开始交易,我们需要 STRK 代币来支付 gas 费用。转到 Starknet 水龙头,粘贴你的钱包地址,然后请求测试网代币。

初始化帐户方法 1:发送交易

Starknet 帐户是通过发送其第一笔交易来初始化的。让我们从钱包向自己发送 1 个 STRK:

现在,再次将你的地址粘贴到浏览器搜索中。你将看到一个合约已部署在你的钱包地址。正如以下图片所示,第一笔交易会自动部署你的帐户合约:

浏览器中显示的 deploycontract 交易

初始化帐户方法 2:直接部署智能钱包

或者,你可以直接部署帐户合约。将 STRK 代币收到你的钱包后,你将看到一个用于部署帐户合约的选项。来自 Ready 的 GIF 在主网上说明了这一点(该过程对于 Sepolia 来说是相同的):

钱包初始化 gif

Starknet 没有 EOA

在 Starknet 中,没有 EOA。每个地址都有字节码和存储。

那么,我们如何区分智能合约(例如 DeFi 应用程序)和旨在持有“我们的资金”的合约呢?

旨在用作钱包的合约必须实现一个称为 SNIP-6 的特定 trait(接口)。我们将在以后的教程中详细讨论这一点,但现在足以说 SNIP-6 合约必须实现一个 __execute__ 函数,这就是它如何从用户那里接收指令的方式。

以下是区别:

在 Ethereum 中,私钥用于派生 Ethereum 地址,其他智能合约可以将其称为帐户。

在 Starknet 中,私钥不会变成地址。相反,它们用于在调用 __execute__ 命令时进行身份验证。

这是 Ethereum 和 Starknet 之间的另一个重要区别。在 Ethereum 中,运行时验证钱包交易的加密签名。在 Starknet 中,具有 __execute__ 函数的钱包可以使用它想要的任何身份验证方法——这意味着 Starknet 可以支持诸如Passkey和量子安全密码学身份验证方法等功能,而无需硬分叉。所需要的只是对智能合约帐户进行编程以支持所需的加密算法。

你的钱包中显示的“Starknet 地址”是智能合约地址(如果合约尚不存在,则为“反事实地址”)。当钱包应用程序(你设备上的链下软件)生成你的种子短语时,它会派生出一个私钥并预测合约稍后将在哪里部署。钱包为了方便起见,向你显示此预测地址作为你的“地址”,即使该合约在链上不存在,直到你初始化它。

你的“钱包”(链下软件)不可能在 Starknet 上“拥有”任何东西。与 Ethereum 中签名直接证明所有权不同,Starknet 需要链上智能合约来持有资产。你的钱包应用程序只是创建你的链上钱包合约在执行交易(例如发送代币或调用其他合约)之前验证的签名。我们将在以后关于帐户抽象的章节中更详细地探讨这个概念。

提防较旧的 Cairo 版本

在撰写本文时,当前的 Cairo 版本是 2.12.0。请注意,互联网搜索和法学硕士查询通常返回为 Cairo 1.x 或更早版本 (0.x) 编写的代码,这些代码与 Cairo 2.x 不兼容。版本之间的语法发生了重大变化,因此来自较旧版本的代码将无法工作。复制代码示例时,请务必检查 Cairo 版本。

如果遇到困难的提示技术

与其他为区块链设计的语言一样,Cairo 的网络存在感不如 JavaScript 或 Python 等语言。

  • 要解决编译问题,请询问如何解决 Rust 中的问题。如果你用 Rust 编写代码,你将遇到的 80% 的编译问题可能都是相同的编译问题。
  • Scarb 与 Rust cargo 非常相似。如果你遇到 Scarb 问题,请使用“cargo”而不是 Scarb 在互联网上搜索你的错误消息,以增加找到相关解决方案的机会。

在下一章中,我们将编写我们的第一个 Cairo 程序。

本文是 Starknet 上的 Cairo 编程 教程系列的一部分

  • 原文链接: rareskills.io/post/cairo...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
RareSkills
RareSkills
https://www.rareskills.io/