关于 cairo-deploy
Cairo Deploy 是使用 Starknet Foundry 的 sncast 在 Starknet 部署和操作 Cairo 智能合约的参考技能,面向合约开发与部署流程。内容涵盖账户和网络配置、类声明、部署、验证及合约调用。
主要功能
- 01使用 Scarb 构建合约
- 02设置部署账户和网络配置
- 03声明类并部署实例
- 04执行写入调用和读取查询
- 05运行批量调用及部署脚本
- 06验证已部署合约
适用场景
- 01将 Cairo 合约部署到 Sepolia 或主网
- 02配置账户和 RPC 端点
- 03调用已部署合约的读写函数
- 04验证合约源代码
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ keep-starknet-strange/ starknet-agentic --skill cairo-deploy安装后在 Claude Code 中输入/cairo-deploy确认已加载。
附带文件agents/openai.yaml
详细介绍
Cairo 部署
使用 sncast(Starknet Foundry)在 Starknet 上部署 Cairo 智能合约的参考指南。
适用场景
- 将合约部署到 Starknet devnet、Sepolia 或主网
- 声明合约类
- 设置部署账户
- 配置网络端点
- 验证已部署的合约
- 调用已部署的合约
不适用场景
- 编写或重构合约逻辑(
cairo-contract-authoring)。 - 单元、集成或模糊测试(
cairo-testing)。 - Gas 或性能优化(
cairo-optimization)。 - 对现有代码进行安全审查(
cairo-auditor)。
快速开始
- 使用
scarb build构建,然后使用sncast声明并部署。 - 如果任务转为编写、测试或审计,请使用技能目录。
设置
安装 Starknet Foundry
# Install via asdf (recommended for version pinning)
asdf plugin add starknet-foundry
asdf install starknet-foundry 0.56.0
asdf global starknet-foundry 0.56.0
# Or install directly
curl -L https://raw.githubusercontent.com/foundry-rs/starknet-foundry/master/scripts/install.sh | sh
snfoundryup
.tool-versions
固定版本以确保构建可复现:
scarb 2.15.1
starknet-foundry 0.56.0
注意: snforge 0.56.0 要求 Scarb >= 2.12.0。请查看 github.com/foundry-rs/starknet-foundry/releases 获取最新版本。
构建
# Build contracts (generates Sierra + CASM)
scarb build
输出位于 target/dev/:
myproject_MyContract.contract_class.json(Sierra)myproject_MyContract.compiled_contract_class.json(CASM)
账户设置
创建新账户
# Generate account on Sepolia
sncast account create \
--url https://starknet-sepolia.g.alchemy.com/v2/YOUR_KEY \
--name my-deployer
# This outputs the account address — fund it with ETH/STRK before deploying
# Deploy the account contract
sncast account deploy \
--url https://starknet-sepolia.g.alchemy.com/v2/YOUR_KEY \
--name my-deployer
导入现有账户
sncast account import \
--url https://starknet-sepolia.g.alchemy.com/v2/YOUR_KEY \
--name my-deployer \
--address 0x123... \
--private-key 0xabc... \
--type oz
账户类型:oz(OpenZeppelin)、argent、braavos
sncast.toml
配置默认值,避免重复指定标志:
[default]
url = "https://starknet-sepolia.g.alchemy.com/v2/YOUR_KEY"
account = "my-deployer"
accounts-file = "~/.starknet_accounts/starknet_open_zeppelin_accounts.json"
wait = true
[mainnet]
url = "https://starknet-mainnet.g.alchemy.com/v2/YOUR_KEY"
account = "mainnet-deployer"
使用配置文件:sncast --profile mainnet declare ...
声明(注册类)
部署前,先在链上声明合约类:
# Declare contract
sncast declare \
--contract-name MyContract
# Output:
# class_hash: 0x1234...
# transaction_hash: 0xabcd...
如果该类已声明,sncast 会提示你——这很正常,请使用现有的类哈希。
部署(创建实例)
# Deploy with constructor args
sncast deploy \
--class-hash 0x1234... \
--constructor-calldata 0xOWNER_ADDRESS
# Multiple constructor args (space-separated)
sncast deploy \
--class-hash 0x1234... \
--constructor-calldata 0xOWNER 0xTOKEN_ADDRESS 1000
构造函数调用数据编码
参数以 felt252 值的形式传递:
ContractAddress— 以十六进制形式传递,例如0x123...u256— 作为两个 felt 传递:low high(例如,1000 表示为1000 0)felt252— 直接传递bool— true 传递1,false 传递0ByteArray(字符串)— 使用 sncast 的字符串编码,或直接传递原始值
调用(写入)
# Call a write function
sncast invoke \
--contract-address 0xCONTRACT \
--function "transfer" \
--calldata 0xRECIPIENT 1000 0
调用(读取)
# Call a view function (free, no tx)
sncast call \
--contract-address 0xCONTRACT \
--function "get_balance" \
--calldata 0xACCOUNT
以编程方式部署(starknet.js)
import { Account, CallData, Contract, RpcProvider } from "starknet";
const provider = new RpcProvider({ nodeUrl: process.env.STARKNET_RPC! });
const account = new Account(provider, process.env.ACCOUNT_ADDRESS!, process.env.PRIVATE_KEY!);
const declareTx = await account.declare({ contract: compiledSierra, casm: compiledCasm });
await provider.waitForTransaction(declareTx.transaction_hash);
const deployTx = await account.deploy({
classHash: declareTx.class_hash,
constructorCalldata: CallData.compile({ owner: process.env.OWNER! }),
});
await provider.waitForTransaction(deployTx.transaction_hash);
const contract = new Contract(abi, deployTx.contract_address[0], provider).connect(account);
await contract.invoke("set_fee", [10]);
const fee = await contract.call("get_fee", []);
console.log({ fee });
多重调用
在单笔交易中执行多个调用:
# Create a multicall file
cat > multicall.toml << 'EOF'
[[call]]
call_type = "deploy"
class_hash = "0x1234..."
inputs = ["0xOWNER"]
[[call]]
call_type = "invoke"
contract_address = "0xTOKEN"
function = "approve"
inputs = ["0xSPENDER", "1000", "0"]
EOF
sncast multicall run --path multicall.toml
部署脚本模式
对于复杂部署,请使用脚本:
#!/bin/bash
set -euo pipefail
RPC_URL="https://starknet-sepolia.g.alchemy.com/v2/YOUR_KEY"
ACCOUNT="my-deployer"
echo "Building..."
scarb build
echo "Declaring MyToken..."
TOKEN_CLASS=$(sncast --json declare --contract-name MyToken --url $RPC_URL --account $ACCOUNT | jq -r '.class_hash')
echo "Token class: $TOKEN_CLASS"
echo "Deploying MyToken..."
TOKEN_ADDR=$(sncast --json deploy --class-hash $TOKEN_CLASS --constructor-calldata 0xOWNER --url $RPC_URL --account $ACCOUNT | jq -r '.contract_address')
echo "Token deployed at: $TOKEN_ADDR"
echo "Declaring AMM..."
AMM_CLASS=$(sncast --json declare --contract-name AMM --url $RPC_URL --account $ACCOUNT | jq -r '.class_hash')
echo "Deploying AMM..."
AMM_ADDR=$(sncast --json deploy --class-hash $AMM_CLASS --constructor-calldata $TOKEN_ADDR --url $RPC_URL --account $ACCOUNT | jq -r '.contract_address')
echo "AMM deployed at: $AMM_ADDR"
echo "Done. Addresses:"
echo " Token: $TOKEN_ADDR"
echo " AMM: $AMM_ADDR"
网络端点
| 网络 | RPC URL |
|---|---|
| Devnet(本地) | http://localhost:5050 |
| Sepolia(测试网) | https://starknet-sepolia.g.alchemy.com/v2/KEY |
| Mainnet | https://starknet-mainnet.g.alchemy.com/v2/KEY |
其他服务提供商:Infura、Blast、Nethermind(提供免费套餐)。
本地 Devnet
# Install and run starknet-devnet-rs
cargo install starknet-devnet
starknet-devnet --seed 42
# Devnet provides pre-funded accounts — use them for testing
合约验证
在 Voyager 或 Starkscan 上验证源代码:
# Verify on Voyager (manual: upload Sierra JSON via web UI)
# https://sepolia.voyager.online/contract/0xADDRESS#code
# Or use Walnut for programmatic verification
# https://app.walnut.dev
注意:
sncast verify支持 Walnut 和 Voyager 两种后端。请明确使用--verifier walnut或--verifier voyager。
可升级合约
对于使用 OZ UpgradeableComponent 的合约:
# 1. Declare new class
sncast declare --contract-name MyContractV2
# 2. Call upgrade on existing contract
sncast invoke \
--contract-address 0xEXISTING_CONTRACT \
--function "upgrade" \
--calldata 0xNEW_CLASS_HASH
常见错误
| 错误 | 原因 | 解决方法 |
|---|---|---|
Contract not found | 账户尚未部署 | 运行 sncast account deploy |
Insufficient max fee | ETH/STRK 不足以支付 Gas | 为部署账户充值 |
Class already declared | 相同的类哈希已存在 | 部署时使用现有的类哈希 |
Entry point not found | 函数名称错误 | 检查合约 ABI |
Invalid calldata | 参数数量或类型错误 | 检查构造函数签名,记住 u256 = 2 个 felts |