文章目录
- Cairo编程语言
- 一、背景
- 二、什么是Cairo
- 工作原理
- 三、Solidity 和 Cairo 的区别
- 四、开发 Starknet 智能合约的工具链
- protostar
- starknet-foundry
- Scarb
- 安装Scarb
- 安装starknet-foundry通过snfoundryup
- Starknet Foundry的snforge 命令行工具如何创建新项目、编译和测试
- sncast 命令
- 创建和部署帐户
- 五、Hello word
- Hello Cairo
- 六、Starkling,学习Cairo的上手题目 starklings-cairo1
- 参考
Cairo编程语言
官网: https://www.cairo-lang.org/
官方推特: https://twitter.com/CairoLang
一、背景
以太坊原生的编程语言 Solidity 非常适合那些 EVM 兼容的区块链,但其常见的数据结构要转译成 STARK 兼容的格式非常昂贵。
所以 StarkWare 团队采用 Cairo 语言。
一个 Cairo 程序的执行会产生一个记录,然后被发送到验证者(prover),验证者(prover)会产生一个 STARK 证明,证明 Cairo 程序所代表的指令或计算的有效性。然后,该证明会被 verifier 检查。
这门语言目前还比较新,会用这门语言的开发者还比较少,也并不兼容 EVM,dApp 很难将以太坊上现有的合约搬过来。
二、什么是Cairo
Cairo 是图灵完备的高级 编程语言和框架,可以为通用计算生成 STARK 证明。应用开发者可以使用 Cairo 定义任何商业逻辑,在链下生成证明,并在链上进行验证,而无需自己编写复杂的“电路”或 AIR。Cairo 已在主网上线,向所有开发者开放。
Cairo 是用来生成通用计算STARK 证明的图灵完备的语言框架。
Cairo GPS(Generic proof service) 允许开发者利用Cairo构建自己的应用,可以实现任意的逻辑。GPS可以生成证明,在链上验证。
总结:Cairo 是一种用于编写可证明程序的编程语言,其中一方可以向另一方证明某个计算已正确执行。 Cairo 和类似的证明系统可用于为区块链提供可扩展性。
Starknet 将 Cairo 编程语言用于其基础设施和编写 Starknet 合约。
目前 Cairo 版本为 2.2.0,基于 Rust,所以语法也很像 Rust,学习 Rust 对学习 Cairo 有很大帮助。
工作原理
此 workshop 是在TestNet上的Starknet Alpha上部署的一组智能contracts 。每个智能contracts 都是exercice/puzzle;每个人都概述了cairo智能contracts语言的功能。完成练习将以ERC20令牌的形式与积分信用。
此workshop 侧重于阅读cairo代码和Starknet智能合约,以了解其语法。您不需要在机器上代码或安装任何内容,以便跟随和完成。入门(做前两个练习)将带你一些时间,以进入教程。不挂断!有一次,事情会更容易流动。你在学习!
三、Solidity 和 Cairo 的区别
-
Cairo 需要自己创建get函数,把数据公开
在Solidity中,如果你想将存储变量设为公开(public),那么使用存储(getter)函数是必要的。在Solidity中,编译器会为所有声明为public的状态变量自动生成getter函数。在Cairo中,所有标记为@storage_var
的变量都是私有的(private)。因此,如果我们想将它们设为公开,我们必须自己创建一个getter函数。😊 -
接口
当我们从一个合约中创建一个 Solidity 实例时,它会继承接口中的所有结构体、错误、事件和函数,同时承诺实现接口中的所有函数。然而,在 Cairo 中,虽然存在接口,但却没有继承。这意味着我们不能仅依靠接口本身来提供合约的基本结构。 -
构造函数
在Cairo中,每个编译的合约只支持一个构造函数(constructor)。换句话说,如果一个合约有多个子合约,那么在所有合约中只能定义一个构造函数。 -
原始数据类型felt
在cairo中,最重要的区别是原始数据类型。只有一种数据类型:felt。
felt(字段元素)是cairo中的原始数据类型,它代表具有高达76位小数的无符号整数。它用于存储地址、字符串、整数等。我们可以这样声明:
let magic_number = 666;
let my_address = "WTF Academy";
Cairo支持最多31个字符的短字符串,这些字符串实际上是存储在"felt"中的。例如,变量hello_string可以存储字符串"Hello world!“。在Cairo中,只有一种执行类型称为"func”。存储变量(除了结构体)如映射、事件、构造函数和函数都使用相同的"func"关键字声明。
@storage_var
func this_is_single_storage_slot() -> (value : felt):
end
@storage_var
func this_is_a_mapping_slot(key : felt) -> (value : felt):
end
@event
func this_is_an_event(event_param1 : felt, event_param2 : felt):
end
Cairo提供了修饰符,可以用在函数声明之上以区分每个函数的作用。这些修饰符都以以下方式开始:
@event - 表示一个事件
@storage_var - 表示合约状态变量(例如映射、地址等)
@constructor - 仅在部署时运行一次的构造函数
@view - 用于从storage_vars中读取数据
@external - 用于向storage_vars中写入数据
@l1_handler - 用于处理从L1合约发送的消息
- 存储变量
@storage_var 装饰器声明一个将作为存储一部分的变量。
@storage_var
func balance() -> (res: felt) {
}
假设我们不再维护一个全局变量balance,而是希望为每个用户保留一个余额(用户将通过他们的STARK公钥进行标识)。我们需要将余额存储变量更改为从公钥(用户)到余额的映射(而不是单个值)。可以通过简单地添加一个参数来实现:
@storage_var
func balance(user: felt) -> (res: felt) {
}
实际上,@storage_var修饰符允许您添加多个参数,以创建更复杂的映射。存储变量不必是单个字段元素,它也可以是几个字段元素的元组。例如,从用户到一对(最小值,最大值)的映射:
@storage_var
func range(user: felt) -> (res: (felt, felt)) {
}
存储变量的参数也可以是结构体或元组,只要它们不包含指针(不包含指针的类型称为“felts-only”类型)。例如:
struct User {
first_name: felt,
last_name: felt,
}
- 函数
Starknet合约没有main()函数。相反,每个函数可以通过@external注解为外部函数,或者通过@view注解为内部函数。
@external. 这种函数可以被Starknet的用户和其他合约调用。允许将新值写入@storage_var。
@view. 这种函数仅
查询状态而不修改它。- 隐式参数
用于跟踪函数调用过程中的内部内存指针。如果没有这些参数,编译器将不知道在函数返回后如何/在何处继续执行代码。三个隐式参数:syscall_ptr,pedersen_ptr和range_check_ptr。
pedersen_ptr:允许计算Pedersen哈希函数。
range_check_ptr:允许比较整数。
syscall_ptr:允许代码调用系统调用。
- 隐式参数
四、开发 Starknet 智能合约的工具链
protostar
github官方:https://github.com/software-mansion/protostar
Protostar是一个用于开发和测试starknet合约的工具链,类似于Solidity中的Foundry,允许我们使用cairo语言创建测试。
但是,官方连接提醒如下:
如果您想使用Cairo 2.0合约,请考虑 starknet-foundry:https://github.com/foundry-rs/starknet-foundry
因此,我们直接看 starknet-foundry!
starknet-foundry
官方github:https://github.com/foundry-rs/starknet-foundry
官方文档:https://foundry-rs.github.io/starknet-foundry/
23年7月19日消息,StarkWare联合创始人Eli Ben-Sasson在巴黎EthCC(Ethereum Community Conference)大会上宣布推出开源项目Starknet Foundry。根据Github,Starknet Foundry是用于开发Starknet合约的极速工具包,由Software Mansion的前Protostar团队设计和开发,基于本地Cairo测试运行器和Blockifie用Rust编写。
Starknet Foundry 是一个用于开发 Starknet 智能合约的工具链。 它有助于编写、部署和测试您的智能合约。 它的灵感来自于 Foundry。
要使用 Starknet Foundry,您需要安装Scarb 并添加到您的 PATH 环境变量中。 您可以找到哪个版本的 Scarb 与您的 Starknet Foundry 版本兼容 在发行说明中。
Scarb
官网:https://docs.swmansion.com/scarb/
Scarb 是 Starknet 生态系统的包管理器和构建工具链。 来自 Rust 生态系统的人会发现 Scarb 与 Cargo 非常相似。
Starknet Foundry 使用Scarb 来:
- 管理依赖关系
- 建造合约
Scarb 的核心概念之一是其清单文件 - Scarb.toml。 它还可用于为 Starknet Foundry 提供配置。 此外,您可以修改 scarb test 的行为以运行 snforge test 作为 描述此处。
最后但并非最不重要的一点是,请记住,为了使用 Starknet Foundry,您必须拥有 Scarb 已安装并添加到PATH环境变量中。
scarb是一个本机命令行应用程序,scarb是Cairo 和 Starknet 生态系统的构建工具链和包管理器。 scarb 就相当于web2 世界中的 gcc(make)工具 加pip(yum)工具
安装Scarb
通过安装脚本安装是启动和运行 Scarb 的最快方法。此方法仅适用于 macOS 和 Linux。
在终端中运行以下命令,然后按照屏幕上的说明进行操作。这将安装最新的稳定版版本。
curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh | sh
安装scarb ,会自动安装 cairo,如下:
# scarb --version
scarb 2.3.1 (0c8def3aa 2023-10-31)
cairo: 2.3.1 (https://crates.io/crates/cairo-lang-compiler/2.3.1)
sierra: 1.3.0
安装starknet-foundry通过snfoundryup
您可以通过运行以下命令来安装它:
curl -L https://raw.githubusercontent.com/foundry-rs/starknet-foundry/master/scripts/install.sh | sh
按照说明进行操作,然后运行:
snfoundryup
请参阅snfoundryup --help
了解更多选项。
要验证 Starknet Foundry 是否已正确安装,请运行 snforge --version
和 sncast --version
。
Starknet Foundry的snforge 命令行工具如何创建新项目、编译和测试
要使用 Starknet Foundry 启动新项目,请运行snforge init
snforge init project_name
我们来看看项目结构
root@good:~/startnet# cd project_name
root@good:~/startnet/project_name# tree . -L 1
.
├── Scarb.toml
├── src
└── tests
2 directories, 1 file
- src/包含您所有合约的源代码。
- tests/包含测试。
- Scarb.toml 包含项目以及 snforge、sncast 等的配置。
sncast 命令
Starknet Foundrysncast 是用于执行 Starknet RPC 调用的命令行工具。有了它,您可以轻松与Starknet合约进行交互!
💡 信息 目前,sncast 仅支持用 Cairo v1 和 v2 编写的合约。
让我们使用sncast来调用合约的函数:
$ sncast --account myuser
–url http://127.0.0.1:5050
call
–contract-address 0x38b7b9507ccf73d79cb42c2cc4e58cf3af1248f342112879bfdf5aa4f606cc9
–function get
–calldata 0x0
–block-id latest
command: call
response: [0x0]
📝 注意 在上面的示例中,我们为强制转换提供了 --account 和 --url 标志。如果 Scarb.toml 存在,并且设置了这些属性,则使用这些标志提供的值将覆盖 Scarb.toml 中的值。详细了解Scarb.toml配置此处。
创建和部署帐户
需要帐户才能与 Starknet 进行交互(没有帐户只能进行呼叫)。 Starknet Foundry 演员阵容支持 使用 sncast account create 和 sncast account deploy 命令的整个帐户管理流程。
这两个命令之间的区别在于第一个命令创建帐户信息(私钥、地址等) 第二个将其部署到网络。部署完成后,即可使用账户与Starknet进行交互。
要从帐户文件中删除帐户,您可以使用 sncast account delete。请注意,这只会删除本地存储的帐户信息 - 这不会从 Starknet 中删除帐户。
💡 信息 目前仅支持 OpenZeppelin 帐户创建。
-
构造函数
一个合约在准备好供公共使用之前可能需要初始化其状态。例如,一个人可能想要指定一个合约所有者,该所有者可以进行其他用户无法进行的某些操作。通过将存储变量设置为所有者,可以通过合约构造函数完成。合约构造函数使用@constructor装饰器进行定义,其名称必须是constructor。构造函数的语义与任何其他外部函数类似,只是构造函数在合约部署后无法再次调用。 -
Uint256
在Cairo里,所有的东西都是用"felt"来表示的。"felt"代表了Field Element(字段元素),是Cairo中唯一的数据类型。它是一个由251位的无符号整数(uint256)构成的。
由于uint256数字的大小为256位,它无法被一个只有251位的"felt"表示。因此,需要将uint256数字拆分为两个部分:低位和高位。低位部分表示uint256数字的低128位,高位部分表示uint256数字的高128位。低位和高位的二进制值分别填充了前导的0,使其达到最大分辨率,并按照顺序拼接在一起,形成uint256数字。
五、Hello word
由于目前Cairo仍处于早期,工具还在开发中,并未成熟。我们可以选择使用本地工具scarb或者在线工具Starknet Remix来编译合约。
创建新项目项目(project和directory可以自定义):
scarb new scarb_project
cd scarb_project
编译合约:
scarb build
如果要构建CASM,需要在Scarb.toml
中添加:
[lib]
casm = true
如果要编译Starknet合约,需要在Scarb.toml
中添加:
[dependencies]
starknet = ">=2.2.0"
[[target.starknet-contract]]
更多Scarb用法见官网文档:https://docs.swmansion.com/scarb/docs.html
Hello Cairo
#[starknet::contract]
mod HelloCairo {
#[storage]
struct Storage {}
#[external(v0)]
fn hello_cairo(self: @ContractState) -> felt252 {
return 'Hello Cairo!';
}
}
第1行利用 #[starknet::contract] 声明了这段代码为 Starknet 合约。如果不声明,则不能部署在 Starknet 上。
#[starknet::contract]
第2行利用 mod 模块关键字创建了合约,名为 HelloCairo。这与 Rust 中的 mod 类似,是一系列元素的集合,包括结构体、函数等。
mod HelloCairo {
}
第3-4行,我们声明了合约的状态变量。在Cairo中,即使合约没有状态变量,也需要声明。
#[storage]
struct Storage {}
之后,我们写了一个函数 hello_cairo。第6行,我们用 #[external(v0)]
属性修饰这个函数。与solidity中的类似external
类似,该函数可以被外部调用。
#[external(v0)]
第7-9行我们声明了 hello_cairo 函数。它只有一个参数self: @ContractState,表示它是view函数。它有一个返回值,类型为felt252:felt(field element,域元素)是 cairo 的基本类型之一,我们会在之后的章节更详细的介绍它。在函数体中,我们将返回值设为用felt252表示的短字符串(长度小于32个字符) Hello Cairo!。
fn hello_cairo(self: @ContractState) -> felt252 {
return 'Hello Cairo!';
}
将上面的合约代码保存到 HelloCairo.cairo 文件中,然后使用 scarb 进行编译:
编译并部署代码
Cairo 2 必须包含 lib.cairo?答: lib.cairo 主要为模块导入和声明服务的
至此,我们成功编译了一个
六、Starkling,学习Cairo的上手题目 starklings-cairo1
官方gitbhub:https://github.com/shramee/starklings-cairo1/
starklings-cairo1是一个互动教程,有56道题目,供对Cairo感兴趣的开发者可以解决的问题。可以边看Cairobook边答题,可让您与CairoV1和Starknet一起运行。
参考
零知识证明 | Cairo 语言介绍
参考URL: https://blog.csdn.net/weixin_45071350/article/details/119465992
StarkNet Cairo 101
参考URL: https://github.com/l-henri/starknet-cairo-101
使用这个简单的教程开始使用cairo。完成谜题,获得积分并了解Starknet Smart 智能合约!