一键导入
mvx-sc-best-practices
Expert guidelines for developing, auditing, and optimizing MultiversX Smart Contracts (Rust).
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Expert guidelines for developing, auditing, and optimizing MultiversX Smart Contracts (Rust).
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Guidelines for establishing context before an audit.
Perform a comprehensive on-chain security audit of a deployed MultiversX smart contract. Use when reviewing a contract's security posture, permissions, state, and economic safety without source code.
Read on-chain state in MultiversX smart contracts. Use when accessing caller info, account balances, block timestamps, ESDT token metadata, local roles, code metadata, or any data from self.blockchain().
Gas-optimized cache patterns for MultiversX smart contracts using Drop-based write-back caches. Use when building contracts that read/write multiple storage values per transaction, DeFi protocols, or any gas-sensitive contract.
Identify ambiguous requirements and ask targeted clarifying questions for MultiversX development. Use when user requests are vague, missing technical constraints, or have conflicting requirements.
Comprehensive code analysis toolkit for MultiversX smart contracts. Covers differential review (version comparison, upgrade safety), fix verification (validate patches, regression testing), and variant analysis (find similar bugs across codebase). Use when reviewing PRs, verifying security patches, or hunting for bug variants.
| name | mvx-sc-best-practices |
| description | Expert guidelines for developing, auditing, and optimizing MultiversX Smart Contracts (Rust). |
This skill provides expert-level guidance on writing secure, gas-efficient, and idiomatic Smart Contracts on MultiversX using the multiversx-sc framework.
Storage is the most expensive resource.
SingleValueMapper: Use for individual items (flags, configs, IDs).
#[storage_mapper("myValue")] fn my_value(&self) -> SingleValueMapper<MyType>;VecMapper: Use for ordered lists where you need index access.
VecMapper on-chain if it can grow indefinitely. This is a DoS vector (Gas Loop).UnorderedSetMapper: Use for unique collections or whitelists.
O(1) membership checks.MapMapper: AVOID unless strictly necessary.
SingleValueMapper.SingleValueMapper keyed by a hash or composite key.BigUint for tokens, prices, and financial math.
u64/u32 for money. Only use them for loop counters or small IDs.require!).#[callback] function. Do not assume the async call succeeded just because it was sent.#[only_owner] for admin functions.only_admin module from the multiversx-sc-modules crate. It provides a standard implementation for managing multiple admins.MultiESDTNFTTransfer (built-in function) over 2 transactions (Approve + TransferFrom).#[payable] to accept tokens and self.call_value().all() to inspect them..scen.json) are mandatory for integration testing.4).#[cfg(test)] modules with multiversx_sc_scenario::imports::* to test internal functions without deploying.#[endpoint].#[view].#[event] for indexing, but don't store critical data solely in events.token_id. Don't assume the user sent the correct token.ManagedBuffer, ManagedAddress, ManagedVec instead of standard Rust Vec, String to avoid serialization overhead.Use a Drop-trait cache struct to batch storage reads/writes:
pub struct StorageCache<'a, C: crate::storage::StorageModule> {
sc_ref: &'a C,
pub field_a: BigUint<C::Api>,
pub field_b: BigUint<C::Api>,
}
impl<'a, C: crate::storage::StorageModule> StorageCache<'a, C> {
pub fn new(sc_ref: &'a C) -> Self {
StorageCache {
field_a: sc_ref.field_a().get(),
field_b: sc_ref.field_b().get(),
sc_ref,
}
}
}
impl<C: crate::storage::StorageModule> Drop for StorageCache<'_, C> {
fn drop(&mut self) {
self.sc_ref.field_a().set(&self.field_a);
self.sc_ref.field_b().set(&self.field_b);
}
}
// errors.rs — static byte strings for gas efficiency
pub static ERROR_NOT_ACTIVE: &[u8] = b"Not active";
pub static ERROR_UNAUTHORIZED: &[u8] = b"Unauthorized";
pub static ERROR_ZERO_AMOUNT: &[u8] = b"Zero amount";
#[multiversx_sc::module]
pub trait EventsModule {
#[event("deposit")]
fn deposit_event(&self, #[indexed] caller: &ManagedAddress, amount: &BigUint);
}
Keep all #[view] endpoints in a dedicated views.rs module for clarity.
Centralize all require! checks in a validation.rs module so security rules are auditable in one place.
Use #[storage_mapper_from_address("key")] to read other contracts' storage without async call overhead:
#[storage_mapper_from_address("reserve")]
fn external_reserve(&self, addr: ManagedAddress, token: &TokenIdentifier)
-> SingleValueMapper<BigUint, ManagedAddress>;
Only works same-shard. Read-only. Key must match target contract exactly.