aiken-smart-contracts
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chineseaiken-smart-contracts
Aiken智能合约
When to use
适用场景
- Writing or auditing Aiken validators
- Building and testing smart contracts
- Generating .plutus artifacts for CLI/MeshJS
- 编写或审计Aiken验证器
- 构建和测试智能合约
- 为CLI/MeshJS生成.plutus工件
Operating rules (must follow)
操作规则(必须遵守)
- Confirm Aiken version before generating code
- Verify script hashes after every rebuild
- Test on preprod/preview before mainnet
- Treat datum/redeemer schemas as versioned APIs
- 生成代码前确认Aiken版本
- 每次重新构建后验证脚本哈希
- 主网部署前在预生产/预览环境测试
- 将datum/redeemer架构视为版本化API
Workflow
工作流
1. Initialize project
1. 初始化项目
bash
aiken new my-project
cd my-projectbash
aiken new my-project
cd my-project2. Project structure
2. 项目结构
my-project/
├── aiken.toml # Project config
├── lib/ # Reusable modules
├── validators/ # Validator entry points
│ └── my_validator.ak
└── plutus.json # Generated blueprintmy-project/
├── aiken.toml # 项目配置文件
├── lib/ # 可复用模块
├── validators/ # 验证器入口
│ └── my_validator.ak
└── plutus.json # 自动生成的蓝图文件3. Write validator
3. 编写验证器
aiken
// validators/my_validator.ak
use aiken/transaction.{ScriptContext}
validator {
fn spend(datum: Data, redeemer: Data, ctx: ScriptContext) -> Bool {
// Your validation logic
True
}
}aiken
// validators/my_validator.ak
use aiken/transaction.{ScriptContext}
validator {
fn spend(datum: Data, redeemer: Data, ctx: ScriptContext) -> Bool {
// 你的验证逻辑
True
}
}4. Build and test
4. 构建与测试
bash
undefinedbash
undefinedBuild all validators
构建所有验证器
aiken build
aiken build
Run tests
运行测试
aiken check
aiken check
Format code
格式化代码
aiken fmt
undefinedaiken fmt
undefined5. Generate artifacts
5. 生成工件
bash
undefinedbash
undefinedBlueprint is auto-generated at plutus.json
蓝图会自动生成在plutus.json中
Extract .plutus for cardano-cli:
提取.plutus文件供cardano-cli使用:
aiken blueprint convert > my_validator.plutus
aiken blueprint convert > my_validator.plutus
Get script hash
获取脚本哈希
cardano-cli conway transaction policyid
--script-file my_validator.plutus
--script-file my_validator.plutus
undefinedcardano-cli conway transaction policyid
--script-file my_validator.plutus
--script-file my_validator.plutus
undefined6. Derive script address
6. 派生脚本地址
bash
cardano-cli conway address build \
--payment-script-file my_validator.plutus \
--testnet-magic 1 \
--out-file script.addrbash
cardano-cli conway address build \
--payment-script-file my_validator.plutus \
--testnet-magic 1 \
--out-file script.addrExamples
示例
Example: Simple spending validator
示例:简单支出验证器
User request: "Create a validator that only allows spending by a specific pubkey"
Response:
aiken
// validators/pubkey_lock.ak
use aiken/hash.{Blake2b_224, Hash}
use aiken/transaction.{ScriptContext, Spend}
use aiken/transaction/credential.{VerificationKey}
type Datum {
owner: Hash<Blake2b_224, VerificationKey>
}
type Redeemer {
// Could be unit if no redeemer data needed
}
validator {
fn spend(datum: Datum, _redeemer: Redeemer, ctx: ScriptContext) -> Bool {
let ScriptContext { transaction, purpose } = ctx
expect Spend(_) = purpose
// Check if owner signed the transaction
list.has(transaction.extra_signatories, datum.owner)
}
}bash
undefined用户需求: "创建一个仅允许特定公钥进行支出的验证器"
响应:
aiken
// validators/pubkey_lock.ak
use aiken/hash.{Blake2b_224, Hash}
use aiken/transaction.{ScriptContext, Spend}
use aiken/transaction/credential.{VerificationKey}
type Datum {
owner: Hash<Blake2b_224, VerificationKey>
}
type Redeemer {
// 若不需要redeemer数据,可设为unit
}
validator {
fn spend(datum: Datum, _redeemer: Redeemer, ctx: ScriptContext) -> Bool {
let ScriptContext { transaction, purpose } = ctx
expect Spend(_) = purpose
// 检查所有者是否签署了交易
list.has(transaction.extra_signatories, datum.owner)
}
}bash
undefinedBuild
构建
aiken build
aiken build
Test
测试
aiken check
aiken check
Generate .plutus
生成.plutus文件
aiken blueprint convert > pubkey_lock.plutus
undefinedaiken blueprint convert > pubkey_lock.plutus
undefinedExample: Parameterized validator
示例:参数化验证器
User request: "Create a time-locked validator"
Response:
aiken
// validators/time_lock.ak
use aiken/interval.{Finite, Interval, IntervalBound}
use aiken/transaction.{ScriptContext, ValidityRange}
type Datum {
lock_until: Int // POSIX time in milliseconds
}
validator {
fn spend(datum: Datum, _redeemer: Data, ctx: ScriptContext) -> Bool {
let valid_range: ValidityRange = ctx.transaction.validity_range
// Check if current time is past lock_until
when valid_range.lower_bound.bound_type is {
Finite(tx_earliest_time) -> tx_earliest_time > datum.lock_until
_ -> False
}
}
}用户需求: "创建一个时间锁定验证器"
响应:
aiken
// validators/time_lock.ak
use aiken/interval.{Finite, Interval, IntervalBound}
use aiken/transaction.{ScriptContext, ValidityRange}
type Datum {
lock_until: Int # POSIX时间(毫秒)
}
validator {
fn spend(datum: Datum, _redeemer: Data, ctx: ScriptContext) -> Bool {
let valid_range: ValidityRange = ctx.transaction.validity_range
// 检查当前时间是否已超过lock_until
when valid_range.lower_bound.bound_type is {
Finite(tx_earliest_time) -> tx_earliest_time > datum.lock_until
_ -> False
}
}
}V3 considerations (Conway)
V3版本注意事项(Conway)
- Single unified context argument
- Datum may be optional for some patterns
- Governance script purposes available
- Use if targeting V3
aiken build --plutus-version v3
- 单一统一的上下文参数
- 在某些模式下Datum可以是可选的
- 支持治理脚本用途
- 如果目标是V3版本,使用
aiken build --plutus-version v3
Safety / key handling
安全/密钥处理
- Datum/redeemer are on-chain visible—no secrets
- Version your datum schemas (breaking changes break funds)
- Verify script hash matches after any rebuild
- Always test with small amounts first
- Datum/Redeemer在链上可见——不要存储机密信息
- 对Datum架构进行版本控制(破坏性变更会导致资金无法取出)
- 任何重建后都要验证脚本哈希是否匹配
- 始终先用小额资金进行测试
References
参考资料
shared/PRINCIPLES.md- Aiken documentation
- (for deployment)
cardano-cli-plutus-scripts
shared/PRINCIPLES.md- Aiken官方文档
- (用于部署)
cardano-cli-plutus-scripts