starknet智能合约编写、部署和调用
OpenZeppelin、Hadhat 和 Foundry都在支持和更新starknet,这是积极信号,尽快学起来 starknet智能合约使用cairo语言编写,最近刚刚更新2.3.0 cairo编程语言类rust,建议搭配学,或者先学rust更好理解 rust编程语言会在未来几年快速流行(仅个人理解)
windows 10 mac和linux请自行配置 vscode 下载cairo1插件(可省略)
cairo 2.3.0 https://github.com/starkware-libs/cairo/tree/main https://book.cairo-lang.org/zh-cn/title-page.html scarb 2.3.0 https://github.com/software-mansion/scarb foundry-rs 0.9.0 https://github.com/foundry-rs/starknet-foundry https://foundry-rs.github.io/starknet-foundry/index.html OpenZeppelin v0.8.0-beta.0 https://github.com/OpenZeppelin/cairo-contracts/tree/main 目前oz稳定版本是v0.7.0,难用且不支持cairo2.3.0 v0.8.0-beta.0主要支持了Components components提供了一种乐高组合合约代码的方式 教程https://book.cairo-lang.org/zh-cn/ch99-01-05-00-components.html
区块链浏览器 https://testnet.starkscan.co/
下载scarb 2.3 下载foundry-rs 0.9.0 bin加入环境变量,并验证
scarb --version
snforge --version
snforge init hello_starknet
Scarb.toml配置如下:
url替换为测试网络rpc
name = "hello_starknet"
version = "0.1.0"
# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html
[dependencies]
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.9.0" }
openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.8.0-beta.0" }
starknet = "2.3.0"
[[target.starknet-contract]]
casm = true
HelloStarknet = { path = "src/lib" }
# foo = { path = "vendor/foo" }
[tool.sncast]
account = "test_user_0"
accounts-file = "accounts.json"
# url = "http://127.0.0.1:5050/rpc"
url = "https://starknet-goerli.g.alchemy.com/v2/66iTEsBmPgN-------"
创建两个账号
sncast account create -n test_user_0
sncast account create -n test_user_1
根目录下会创建accounts.json文件,打开可以看到两个密钥信息(这是我的,你的肯定不一样)
test_user_0:0x3180b441f524c2de2515094fc85ffef278d9764f6ebbb87db68928c094177ff test_user_1:0xdc64f74f50383703de669eb9dd4b7eb7f6ecbc792f34232112193c6ed86d9a
starknet网络转测试eth到这两个账户地址上(否则不能部署账户合约)
eth到账后可部署两个账户合约到starknet网络 test_user_0和test_user_1为accounts.json中账户名
sncast account deploy --name test_user_0 --max-fee 8646000000000
sncast account deploy --name test_user_1 --max-fee 8646000000000
拷贝如下代码到lib.cairo
trait IHelloStarknet<TContractState> {
fn increase_balance(ref self: TContractState, amount: felt252);
fn get_balance(self: @TContractState) -> felt252;
}
#[starknet::contract]
mod HelloStarknet {
use starknet::ContractAddress;
use openzeppelin::access::ownable::Ownable;
component!(path: Ownable, storage: Ownable_owner, event: OwnershipTransferred);
#[abi(embed_v0)]
impl OwnableImpl = Ownable::OwnableImpl<ContractState>;
impl OwnableInternalImpl = Ownable::InternalImpl<ContractState>;
#[storage]
struct Storage {
balance: felt252,
#[substorage(v0)]
Ownable_owner: Ownable::Storage
}
#[event]
#[derive(Drop, starknet::Event)]
enum Event {
OwnershipTransferred: Ownable::Event
}
#[constructor]
fn constructor(ref self: ContractState, owner: ContractAddress) {
self.Ownable_owner.initializer(owner);
}
#[external(v0)]
impl HelloStarknetImpl of super::IHelloStarknet<ContractState> {
fn increase_balance(ref self: ContractState, amount: felt252) {
assert(amount != 0, 'Amount cannot be 0');
self.Ownable_owner.assert_only_owner();
self.balance.write(self.balance.read() + amount);
}
fn get_balance(self: @ContractState) -> felt252 {
self.balance.read()
}
}
}
简单解释: foundry示例代码基础上,配合OZ中Ownerable实现简单权限控制 increase_balance方法只有owner地址可调用 constructor构造中初始化owner
declare合约,如正确会输出class-hash HelloStarknet为Scarb.toml中定义
sncast declare -c HelloStarknet
command: declare class_hash: 0x689fe8545ecf92cc86ffea0350c9093e0c7e4c215cda2ee156b0202ba344c40 transaction_hash: 0x3a67707e712033bdbd32a24f8167bd37eea2224e3fcde41b89142f64de87a6f
deploy合约 --constructor-calldata 为构造参数,配置test_user_0为合约owner
sncast deploy --class-hash 0x689fe8545ecf92cc86ffea0350c9093e0c7e4c215cda2ee156b0202ba344c40 --constructor-calldata 0x3180b441f524c2de2515094fc85ffef278d9764f6ebbb87db68928c094177ff
command: deploy contract_address: 0x454bf4e91e12423c7c279f44c0b1c6f569c2c2635584cb554a62a4c0b2a24e2 transaction_hash: 0x5575459f0905b4f7c0915cee21632a850d018051c392af51116f029ccedde50
稍后可以在区块链浏览器查看合约地址
查询合约owner
sncast call -a 0x454bf4e91e12423c7c279f44c0b1c6f569c2c2635584cb554a62a4c0b2a24e2 -f "owner"
command: call response: [0x3180b441f524c2de2515094fc85ffef278d9764f6ebbb87db68928c094177ff]
查询balance值,初始值应为0
sncast call -a 0x454bf4e91e12423c7c279f44c0b1c6f569c2c2635584cb554a62a4c0b2a24e2 -f "get_balance"
command: call response: [0x0]
test_user_0调用increase_balance方法
sncast -a test_user_0 invoke -a 0x454bf4e91e12423c7c279f44c0b1c6f569c2c2635584cb554a62a4c0b2a24e2 -f "increase_balance" -c 2
command: invoke transaction_hash: 0x2f79663fcc0eb7792c09377087b0cdbc5f069ef911232b62f51e0b1007b9668
再次调用查询get_balance方法,值应为2
sncast call -a 0x454bf4e91e12423c7c279f44c0b1c6f569c2c2635584cb554a62a4c0b2a24e2 -f "get_balance" command: call response: [0x2]
test_user_1调用increase_balance方法
sncast -a test_user_1 invoke -a 0x454bf4e91e12423c7c279f44c0b1c6f569c2c2635584cb554a62a4c0b2a24e2 -f "increase_balance" -c 2
command: invoke error: Transaction reverted: Error in the called contract (0x00dc64f74f50383703de669eb9dd4b7eb7f6ecbc792f34232112193c6ed86d9a): Error at pc=0:81: Got an exception while executing a hint: Hint Error: Execution failed. Failure reason: "Caller is not the owner". Cairo traceback (most recent call last): Unknown location (pc=0:731) Unknown location (pc=0:677) Unknown location (pc=0:291) Unknown location (pc=0:314)
非owner,调用失败
到目前,本教程代码在remix starknet插件中不能编译和运行,期待remix插件升级
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!