Loading...
Loading...
Compare original and translation side by side
aptos_token_objects::collectionaptos_token_objects::tokenObject<AptosToken>Object<T>aptos_token::token../../../patterns/move/DIGITAL_ASSETS.mdaptos_token_objects::collectionaptos_token_objects::tokenObject<AptosToken>Object<T>aptos_token::token../../../patterns/move/DIGITAL_ASSETS.mdObject<T>Object<T>object::owner(obj) == signer::address_of(user)Object<T>Object<T>object::owner(obj) == signer::address_of(user)assert!(signer::address_of(user) == expected, E_UNAUTHORIZED)&mutassert!(signer::address_of(user) == expected, E_UNAUTHORIZED)&mutobj.is_owner(user)selfvector[index]vector::borrow()@marketplace_addrobj.is_owner(user)selfvector[index]vector::borrow()@marketplace_addrinit_module#[view](seller, price, timestamp)#[view]/// comment#[view]#[view]///#[view](seller, price, timestamp)#[view]///#[view]#[view]///search-aptos-examplessecurity-auditsearch-aptos-examplessecurity-auditstruct 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;
}struct MyObject has key {
name: String,
transfer_ref: object::TransferRef,
delete_ref: object::DeleteRef,
}
// 错误常量
const E_NOT_OWNER: u64 = 1;
const E_EMPTY_STRING: u64 = 2;
const E_NAME_TOO_LONG: u64 = 3;
// 配置常量
const MAX_NAME_LENGTH: u64 = 100;
/// 遵循规范模式创建对象
public fun create_my_object(creator: &signer, name: String): Object<MyObject> {
// 1. 创建对象
let constructor_ref = object::create_object(signer::address_of(creator));
// 2. 在constructor_ref销毁前生成所有需要用到的引用
let transfer_ref = object::generate_transfer_ref(&constructor_ref);
let delete_ref = object::generate_delete_ref(&constructor_ref);
// 3. 获取对象签名者
let object_signer = object::generate_signer(&constructor_ref);
// 4. 把数据存储到对象中
move_to(&object_signer, MyObject {
name,
transfer_ref,
delete_ref,
});
// 5. 返回带类型的对象引用(ConstructorRef会自动销毁)
object::object_from_constructor_ref<MyObject>(&constructor_ref)
}
/// 带所有权验证的更新操作
public entry fun update_object(
owner: &signer,
obj: Object<MyObject>,
new_name: String
) acquires MyObject {
// ✅ 强制要求:验证所有权
assert!(object::owner(obj) == signer::address_of(owner), E_NOT_OWNER);
// ✅ 强制要求:校验输入
assert!(string::length(&new_name) > 0, E_EMPTY_STRING);
assert!(string::length(&new_name) <= MAX_NAME_LENGTH, E_NAME_TOO_LONG);
// 校验通过后执行逻辑
let obj_data = borrow_global_mut<MyObject>(object::object_address(&obj));
obj_data.name = new_name;
}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
}
}struct ListingInfo has store, drop, copy {
seller: address,
price: u64,
listed_at: u64,
}
/// 访问器函数——测试无法直接访问结构体字段
/// 多字段返回使用元组格式
#[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)
}
/// 仅需要单个值时使用单字段访问器
#[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 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
}module my_addr::my_module {
// ============ 导入依赖 ============
use std::signer;
use std::string::String;
use aptos_framework::object::{Self, Object};
use aptos_framework::event;
// ============ 事件定义 ============
#[event]
struct ItemCreated has drop, store {
item: address,
creator: address,
}
// ============ 结构体定义 ============
// 定义你的数据结构
// ============ 常量定义 ============
const E_NOT_OWNER: u64 = 1;
const E_UNAUTHORIZED: u64 = 2;
// ============ 模块初始化 ============
fun init_module(deployer: &signer) {
// 初始化全局状态、注册表等
}
// ============ 公共入口函数 ============
// 面向用户的函数
// ============ 公共函数 ============
// 可组合的通用函数
// ============ 私有函数 ============
// 内部辅助函数
}references/storage-decision-tree.mdreferences/storage-decision-tree.md.length().length()references/storage-patterns.mdreferences/storage-patterns.md| Pattern | Recommended Storage |
|---|---|
| User registry | |
| Staking records | |
| Leaderboard | |
| Transaction log | |
| Whitelist (<100) | |
| Voting records | |
| Config (<50) | |
| DAO proposals | |
| Asset collection | |
| 场景 | 推荐存储类型 |
|---|---|
| 用户注册表 | |
| 质押记录 | |
| 排行榜 | |
| 交易日志 | |
| 白名单(<100条) | |
| 投票记录 | |
| 配置项(<50条) | |
| DAO提案 | |
| 资产集合 | |
Table<address, StakeInfo>BigOrderedMap<u64, address>allocate_spare_slotsTable<address, StakeInfo>BigOrderedMap<u64, address>allocate_spare_slotsreferences/references/aptos_token::token@my_addr"0x...".env~/.aptos/config.yamlaptos_token::token@my_addr"0x...".env~/.aptos/config.yaml| Scenario | Check | Error Code |
|---|---|---|
| Zero amounts | | E_ZERO_AMOUNT |
| Excessive amounts | | E_AMOUNT_TOO_HIGH |
| Empty vectors | | E_EMPTY_VECTOR |
| Empty strings | | E_EMPTY_STRING |
| Strings too long | | E_STRING_TOO_LONG |
| Zero address | | E_ZERO_ADDRESS |
| Overflow | | E_OVERFLOW |
| Underflow | | E_UNDERFLOW |
| Division by zero | | E_DIVISION_BY_ZERO |
| Unauthorized access | | E_UNAUTHORIZED |
| Not object owner | | E_NOT_OWNER |
| 场景 | 校验逻辑 | 错误码 |
|---|---|---|
| 金额为0 | | E_ZERO_AMOUNT |
| 金额超出上限 | | E_AMOUNT_TOO_HIGH |
| 空向量 | | E_EMPTY_VECTOR |
| 空字符串 | | E_EMPTY_STRING |
| 字符串过长 | | E_STRING_TOO_LONG |
| 零地址 | | E_ZERO_ADDRESS |
| 溢出 | | E_OVERFLOW |
| 下溢 | | E_UNDERFLOW |
| 除零错误 | | E_DIVISION_BY_ZERO |
| 未授权访问 | | E_UNAUTHORIZED |
| 非对象所有者操作 | | E_NOT_OWNER |
references/storage-decision-tree.mdreferences/storage-patterns.mdreferences/storage-types.mdreferences/storage-gas-optimization.mdreferences/object-patterns.mdreferences/access-control.mdreferences/safe-arithmetic.mdreferences/initialization.mdreferences/events.mdreferences/v2-syntax.mdreferences/complete-example.md../../../patterns/move/DIGITAL_ASSETS.md../../../patterns/move/OBJECTS.md../../../patterns/move/SECURITY.md../../../patterns/move/MOVE_V2_SYNTAX.mdsearch-aptos-examplesgenerate-testssecurity-auditreferences/storage-decision-tree.mdreferences/storage-patterns.mdreferences/storage-types.mdreferences/storage-gas-optimization.mdreferences/object-patterns.mdreferences/access-control.mdreferences/safe-arithmetic.mdreferences/initialization.mdreferences/events.mdreferences/v2-syntax.mdreferences/complete-example.md../../../patterns/move/DIGITAL_ASSETS.md../../../patterns/move/OBJECTS.md../../../patterns/move/SECURITY.md../../../patterns/move/MOVE_V2_SYNTAX.mdsearch-aptos-examplesgenerate-testssecurity-audit