Token导航 LogoToken导航

Agent Skill · 开发

write-contracts(写合同)

write-contracts 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

write-contracts 是开发类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为只读;许可证信息还不明确,第三方扫描有提醒项,按安装量在开发类的 21,746 个 Skill 里排第 15,154。

总安装 624周安装 26GitHub Stars 12下载 208核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:write-contracts(写合同)
来源仓库:https://github.com/aptos-labs/aptos-agent-skills
仓库路径:skills/write-contracts
安装命令:
npx skills add https://github.com/aptos-labs/aptos-agent-skills --skill write-contracts
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/aptos-labs/aptos-agent-skills --skill write-contracts

这个 Skill 是做什么的

开发类 Skill 面向写代码、改代码和排查问题,一般会读写仓库文件,部分还会执行构建或测试命令。

write-contracts 提供 Move 智能合约编写规范,重点覆盖数字资产(NFT)标准和对象模型用法。适用于所有 NFT 相关合约开发,强制使用 Digital Asset 标准而非已废弃的 TokenV1。

必须导入 token_objects 模块,使用 Object<AptosToken> 引用 NFT,禁止裸地址操作。安装命令为 npx skills add https://github.com/aptos-labs/aptos-agent-skills --skill write-contracts。

注意所有对象引用都应通过 Object<T> 类型,并正确生成 TransferRef/DeleteRef 等资源。

来源仓库内路径:skills/write-contracts

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/aptos-labs/aptos-agent-skills --skill write-co…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它标注为只读,先用只读任务试一次,确认行为符合预期再扩大使用范围。

常见问题

6 条

write-contracts 怎么安装?

在终端执行 npx skills add https://github.com/aptos-labs/aptos-agent-skills --skill write-contracts。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

write-contracts 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

write-contracts 需要什么权限?

权限级别是只读。该 Skill 主要提供规则、说明或参考内容,本身偏只读;真正读写文件、联网或执行命令仍取决于宿主 Agent 的任务。

write-contracts 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

write-contracts 用的人多吗?

公开数据是累计安装 624 次,近一周安装 26 次,下载 208 次,GitHub 12 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

write-contracts 安全吗?

第三方扫描有提醒项,说明存在需要人工确认的行为。安装前请打开源码看清它读了什么、联网到哪里。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 标注为只读权限,试用阶段不容易误改本地文件。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方扫描存在提醒项或未通过项,需要人工逐条确认。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理开发类任务、又不想每次都手写提示词的人。
  • 只想先试试效果、不希望它改动本地文件的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

开发类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
skill-vetter

技能审查员 · OpenClaw

8,779,018986操作浏览器MIT-0通过
ontology

本体论 · OpenClaw

6,636,960576只读MIT-0通过
entra-app-registration

内部应用程序注册 · Codex、Claude

6,631,872764接触敏感数据未明确通过
entra-app-registration

内部应用程序注册 · Codex、Claude

3,757,680201接触敏感数据未明确通过
nano-banana-pro

纳米香蕉专业版 · OpenClaw

3,526,898364接触敏感数据MIT-0有提醒
write-contracts

写合同 · 本页

62412只读未明确有提醒

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Write Contracts Skill

Core Rules

Digital Assets (NFTs) ⭐ CRITICAL

  1. ALWAYS use Digital Asset (DA) standard for ALL NFT-related contracts (collections, marketplaces, minting)
  2. ALWAYS import aptos_token_objects::collection and aptos_token_objects::token modules
  3. ALWAYS use Object<AptosToken> for NFT references (NOT generic Object<T>)
  4. NEVER use legacy TokenV1 standard or aptos_token::token module (deprecated)
  5. See ../../../patterns/move/DIGITAL_ASSETS.md for complete NFT patterns

Object Model

  1. ALWAYS use Object<T> for all object references (NEVER raw addresses)
  2. Generate all refs (TransferRef, DeleteRef) in constructor before ConstructorRef destroyed
  3. Return Object<T> from constructors (NEVER return ConstructorRef)
  4. Verify ownership with object::owner(obj) == signer::address_of(user)
  5. Use object::generate_signer(&constructor_ref) for object signers
  6. Use named objects for singletons: object::create_named_object(creator, seed)

Security

  1. ALWAYS verify signer authority in entry functions: assert!(signer::address_of(user) == expected, E_UNAUTHORIZED)
  2. ALWAYS validate inputs: non-zero amounts, address validation, string length checks
  3. NEVER expose &mut references in public functions
  4. NEVER skip signer verification in entry functions

Modern Syntax

  1. Use inline functions and lambdas for iteration
  2. Use receiver-style method calls: obj.is_owner(user) (define first param as self)
  3. Use vector indexing: vector[index] instead of vector::borrow()
  4. Use direct named addresses: @marketplace_addr (NOT helper functions)

Required Patterns

  1. Use init_module for contract initialization on deployment
  2. Emit events for ALL significant activities (create, transfer, update, delete)
  3. Define clear error constants with descriptive names (E_NOT_OWNER, E_INSUFFICIENT_BALANCE)

Testability

  1. Add accessor functions for struct fields - tests in separate modules cannot access struct fields directly
  2. Use #[view] annotation for read-only accessor functions
  3. Return tuples from accessors for multi-field access: (seller, price, timestamp)
  4. Place #[view] BEFORE doc comments - /// comment before #[view] causes compiler warnings. Write #[view] first, then ///

Quick Workflow

  1. Create module structure → Define structs, events, constants, init_module
  2. Implement object creation → Use proper constructor pattern with all refs generated upfront
  3. Add access control → Verify ownership and validate all inputs
  4. Security check → Use security-audit skill before deployment

Key Example: Object Creation Pattern

struct MyObject has key {
    name: String,
    transfer_ref: object::TransferRef,
    delete_ref: object::DeleteRef,
}

// Error constants
const E_NOT_OWNER: u64 = 1;
const E_EMPTY_STRING: u64 = 2;
const E_NAME_TOO_LONG: u64 = 3;

// Configuration constants
const MAX_NAME_LENGTH: u64 = 100;

/// Create object with proper pattern
public fun create_my_object(creator: &signer, name: String): Object<MyObject> {
    // 1. Create object
    let constructor_ref = object::create_object(signer::address_of(creator));

    // 2. Generate ALL refs you'll need BEFORE constructor_ref is destroyed
    let transfer_ref = object::generate_transfer_ref(&constructor_ref);
    let delete_ref = object::generate_delete_ref(&constructor_ref);

    // 3. Get object signer
    let object_signer = object::generate_signer(&constructor_ref);

    // 4. Store data in object
    move_to(&object_signer, MyObject {
        name,
        transfer_ref,
        delete_ref,
    });

    // 5. Return typed object reference (ConstructorRef automatically destroyed)
    object::object_from_constructor_ref<MyObject>(&constructor_ref)
}

/// Update with ownership verification
public entry fun update_object(
    owner: &signer,
    obj: Object<MyObject>,
    new_name: String
) acquires MyObject {
    // ✅ ALWAYS: Verify ownership
    assert!(object::owner(obj) == signer::address_of(owner), E_NOT_OWNER);

    // ✅ ALWAYS: Validate inputs
    assert!(string::length(&new_name) > 0, E_EMPTY_STRING);
    assert!(string::length(&new_name) <= MAX_NAME_LENGTH, E_NAME_TOO_LONG);

    // Safe to proceed
    let obj_data = borrow_global_mut<MyObject>(object::object_address(&obj));
    obj_data.name = new_name;
}

Key Example: Accessor Functions for Testing

struct ListingInfo has store, drop, copy {
    seller: address,
    price: u64,
    listed_at: u64,
}

/// Accessor function - tests cannot access struct fields directly
/// Use tuple returns for multiple fields
#[view]
public fun get_listing_details(nft_addr: address): (address, u64, u64) acquires Listings {
    let listings = borrow_global<Listings>(get_marketplace_address());
    assert!(table::contains(&listings.items, nft_addr), E_NOT_LISTED);
    let listing = table::borrow(&listings.items, nft_addr);
    (listing.seller, listing.price, listing.listed_at)
}

/// Single-field accessor when only one value needed
#[view]
public fun get_staked_amount(user_addr: address): u64 acquires Stakes {
    let stakes = borrow_global<Stakes>(get_vault_address());
    if (table_with_length::contains(&stakes.items, user_addr)) {
        table_with_length::borrow(&stakes.items, user_addr).amount
    } else {
        0
    }
}

Module Structure Template

module my_addr::my_module {
    // ============ Imports ============
    use std::signer;
    use std::string::String;
    use aptos_framework::object::{Self, Object};
    use aptos_framework::event;

    // ============ Events ============
    #[event]
    struct ItemCreated has drop, store {
        item: address,
        creator: address,
    }

    // ============ Structs ============
    // Define your data structures

    // ============ Constants ============
    const E_NOT_OWNER: u64 = 1;
    const E_UNAUTHORIZED: u64 = 2;

    // ============ Init Module ============
    fun init_module(deployer: &signer) {
        // Initialize global state, registries, etc.
    }

    // ============ Public Entry Functions ============
    // User-facing functions

    // ============ Public Functions ============
    // Composable functions

    // ============ Private Functions ============
    // Internal helpers
}

Storage Type Selection

⚠️ When user mentions storage ("store", "track", "registry", "mapping", "list", "collection"):

1. Ask 2-3 Questions (see references/storage-decision-tree.md)

  • Access pattern? (sequential vs key-value vs both)
  • Expected size? (small vs large vs unknown)
  • Need .length()? (conditional)

2. Recommend from Patterns (references/storage-patterns.md)

PatternRecommended Storage
User registryTable<address, UserInfo>
Staking recordsTable<address, StakeInfo>
LeaderboardBigOrderedMap<u64, address>
Transaction logSmartVector<TxRecord> or Vector
Whitelist (<100)Vector<address>
Voting recordsTableWithLength<address, bool>
Config (<50)OrderedMap<String, Value>
DAO proposalsBigOrderedMap<u64, Proposal>
Asset collectionVector<Object<T>> or SmartVector

3. Include Brief Gas Context

Example recommendations:

  • "For staking, I recommend Table<address, StakeInfo> because you'll have unbounded users with concurrent operations (separate slots enable parallel access)"
  • "For leaderboard, I recommend BigOrderedMap<u64, address> because you need sorted iteration (O(log n), use allocate_spare_slots for production)"

Storage Types Available

  • Vector - Small sequential (<100 items)
  • SmartVector - Large sequential (100+ items)
  • Table - Unordered key-value lookups
  • TableWithLength - Table with count tracking
  • OrderedMap - Small sorted maps (<100 items)
  • BigOrderedMap - Large sorted maps (100+ items)

⚠️ NEVER use SmartTable (deprecated, use BigOrderedMap)

Details: See references/ for decision tree, type comparisons, and gas optimization.

Anti-patterns

  1. ❌ Never use legacy TokenV1 standard or import aptos_token::token
  2. ❌ Never use resource accounts (use named objects instead)
  3. ❌ Never return ConstructorRef from public functions
  4. ❌ Never skip signer verification in entry functions
  5. ❌ Never skip input validation (amounts, addresses, strings)
  6. ❌ Never deploy without 100% test coverage
  7. ❌ Never create helper functions that just return named addresses
  8. ❌ Never skip event emission for significant activities
  9. ❌ Never use old syntax when V2 syntax is available
  10. ❌ Never skip init_module for contracts that need initialization
  11. ❌ Never hardcode real private keys or secrets in code — use @my_addr named addresses and "0x..." placeholders
  12. ❌ Never read .env or ~/.aptos/config.yaml — these contain private keys

Edge Cases to Handle

ScenarioCheckError Code
Zero amountsassert!(amount > 0, E_ZERO_AMOUNT)E_ZERO_AMOUNT
Excessive amountsassert!(amount <= MAX, E_AMOUNT_TOO_HIGH)E_AMOUNT_TOO_HIGH
Empty vectorsassert!(vector::length(&v) > 0, E_EMPTY_VECTOR)E_EMPTY_VECTOR
Empty stringsassert!(string::length(&s) > 0, E_EMPTY_STRING)E_EMPTY_STRING
Strings too longassert!(string::length(&s) <= MAX, E_STRING_TOO_LONG)E_STRING_TOO_LONG
Zero addressassert!(addr!= @0x0, E_ZERO_ADDRESS)E_ZERO_ADDRESS
Overflowassert!(a <= MAX_U64 - b, E_OVERFLOW)E_OVERFLOW
Underflowassert!(a >= b, E_UNDERFLOW)E_UNDERFLOW
Division by zeroassert!(divisor > 0, E_DIVISION_BY_ZERO)E_DIVISION_BY_ZERO
Unauthorized accessassert!(signer == expected, E_UNAUTHORIZED)E_UNAUTHORIZED
Not object ownerassert!(object::owner(obj) == user, E_NOT_OWNER)E_NOT_OWNER

References

Detailed Patterns (references/ folder):

  • references/storage-decision-tree.md - ⭐ Storage type selection framework (ask when storage mentioned)
  • references/storage-patterns.md - ⭐ Use-case patterns and smart defaults
  • references/storage-types.md - Detailed comparison of all 6 storage types
  • references/storage-gas-optimization.md - Gas optimization strategies for storage
  • references/object-patterns.md - Named objects, collections, nested objects
  • references/access-control.md - RBAC and permission systems
  • references/safe-arithmetic.md - Overflow/underflow prevention
  • references/initialization.md - init_module patterns and registry creation
  • references/events.md - Event emission patterns
  • references/v2-syntax.md - Modern Move V2 features (method calls, indexing, lambdas)
  • references/complete-example.md - Full annotated NFT collection contract

Pattern Documentation (patterns/ folder):

  • ../../../patterns/move/DIGITAL_ASSETS.md - Digital Asset (NFT) standard - CRITICAL for NFTs
  • ../../../patterns/move/OBJECTS.md - Comprehensive object model guide
  • ../../../patterns/move/SECURITY.md - Security checklist and patterns
  • ../../../patterns/move/MOVE_V2_SYNTAX.md - Modern syntax examples

Official Documentation:

Related Skills:

  • search-aptos-examples - Find similar examples in aptos-core (optional)
  • generate-tests - Write tests for contracts (use AFTER writing contracts)
  • security-audit - Audit contracts before deployment

平台分布

Codex

36.14%
按下载量换算75

Claude

31.3%
按下载量换算65

Cursor

20.11%
按下载量换算42

Gemini CLI

10.15%
按下载量换算21

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

可疑

权限和风险

只读

该 Skill 主要提供规则、说明或参考内容,本身偏只读;真正读写文件、联网或执行命令仍取决于宿主 Agent 的任务。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在提醒或未通过项,安装前请自行复核。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills