mvx-sc-best-practices
Expert guidelines for writing secure and gas-efficient MultiversX smart contracts in Rust.
Install
mkdir -p .claude/skills/mvx-sc-best-practices && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/16057" && unzip -o skill.zip -d .claude/skills/mvx-sc-best-practices && rm skill.zipInstalls to .claude/skills/mvx-sc-best-practices
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Expert guidelines for developing, auditing, and optimizing MultiversX Smart Contracts (Rust).Key capabilities
- →Optimize smart contract storage
- →Ensure arithmetic safety with BigUint
- →Implement reentrancy protection patterns
- →Manage access control for contract functions
- →Test smart contracts with Mandos scenarios
How it works
It provides guidelines for storage optimization, security patterns like arithmetic safety and reentrancy protection, and testing methodologies for MultiversX smart contracts.
Inputs & outputs
When to use mvx-sc-best-practices
- →Auditing smart contract code
- →Optimizing gas usage
- →Implementing security patterns
About this skill
MultiversX Smart Contract Best Practices
This skill provides expert-level guidance on writing secure, gas-efficient, and idiomatic Smart Contracts on MultiversX using the multiversx-sc framework.
1. Storage Optimization (Critical)
Storage is the most expensive resource.
SingleValueMapper: Use for individual items (flags, configs, IDs).- Gas: Cheapest (~1 slot write).
- Pattern:
#[storage_mapper("myValue")] fn my_value(&self) -> SingleValueMapper<MyType>;
VecMapper: Use for ordered lists where you need index access.- Warning: NEVER iterate a
VecMapperon-chain if it can grow indefinitely. This is a DoS vector (Gas Loop). - Gas: Medium.
- Warning: NEVER iterate a
UnorderedSetMapper: Use for unique collections or whitelists.- Gas: Checks existence before insert. Good for
O(1)membership checks.
- Gas: Checks existence before insert. Good for
MapMapper: AVOID unless strictly necessary.- Why: It uses a linked-list structure (4 storage writes per entry). It is ~4x more expensive than
SingleValueMapper. - Alternative: If you don't need to iterate keys, use a
SingleValueMapperkeyed by a hash or composite key.
- Why: It uses a linked-list structure (4 storage writes per entry). It is ~4x more expensive than
2. Security Patterns
Arithmetic Safety
- Always use
BigUintfor tokens, prices, and financial math.- Why: Prevents overflow/underflow and matches the VM's native big int implementation.
- Avoid
u64/u32for money. Only use them for loop counters or small IDs.
Reentrancy Protection
- Checks-Effects-Interactions:
- Checks: Validate inputs (
require!). - Effects: Update storage (deduct balance, update state).
- Interactions: Send tokens or call other contracts.
- Checks: Validate inputs (
- Async Calls: MultiversX async calls are safer than synchronous calls regarding reentrancy of the same execution context, but state changes happen in a separate transaction (callback).
- Callback Verification: Always validate the state in the
#[callback]function. Do not assume the async call succeeded just because it was sent.
Access Control
- Use
#[only_owner]for admin functions. - For fine-grained control, use the
only_adminmodule from themultiversx-sc-modulescrate. It provides a standard implementation for managing multiple admins.
3. Data Flow & Testing
Transfer-Execute Pattern
- When sending tokens to a contract, prefer
MultiESDTNFTTransfer(built-in function) over 2 transactions (Approve + TransferFrom). - In the contract, use
#[payable]to accept tokens andself.call_value().all()to inspect them.
Testing (Mandos/Scenarios)
- Mandos (
.scen.json) are mandatory for integration testing. - Cover all pathways:
- Happy path.
- Error path (expect status
4).
- Whitebox Testing: Use
#[cfg(test)]modules withmultiversx_sc_scenario::imports::*to test internal functions without deploying.
4. Code Structure
- Endpoints: Public functions
#[endpoint]. - Views: Read-only
#[view]. - Private: Helper functions (no annotation, or pure Rust).
- Events:
#[event]for indexing, but don't store critical data solely in events.
5. Common Pitfalls / "Sharp Edges"
- Token Identifier Validation: Always validate
token_id. Don't assume the user sent the correct token. - Gas Limit: Be aware of the block gas limit (1.5B gas). Large loops will revert.
- Managed Types: Use
ManagedBuffer,ManagedAddress,ManagedVecinstead of standard RustVec,Stringto avoid serialization overhead.
6. Production Patterns (Advanced)
Cache-Based Gas Optimization
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);
}
}
Error Constants Organization
// 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";
Event Trait Composition
#[multiversx_sc::module]
pub trait EventsModule {
#[event("deposit")]
fn deposit_event(&self, #[indexed] caller: &ManagedAddress, amount: &BigUint);
}
View Endpoint Separation
Keep all #[view] endpoints in a dedicated views.rs module for clarity.
Validation Module Pattern
Centralize all require! checks in a validation.rs module so security rules are auditable in one place.
Cross-Contract Storage Reads
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.
When not to use it
- →When iterating a `VecMapper` on-chain if it can grow indefinitely
- →When using `MapMapper` unless strictly necessary
- →When using `u64`/`u32` for tokens, prices, or financial math
Limitations
- →Iterating a `VecMapper` on-chain if it can grow indefinitely is a DoS vector
- →`MapMapper` is ~4x more expensive than `SingleValueMapper`
- →Block gas limit (1.5B gas) must be considered for large loops
How it compares
This skill offers expert-level, framework-specific best practices for MultiversX smart contract development, focusing on gas efficiency and security within the `multiversx-sc` framework.
Compared to similar skills
mvx-sc-best-practices side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| mvx-sc-best-practices (this skill) | 0 | 1mo | Review | Advanced |
| blockchain-developer | 6 | 4mo | No flags | Advanced |
| solana-dev | 0 | 4mo | Review | Advanced |
| solana-dev | 0 | 4mo | No flags | Beginner |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
blockchain-developer
sickn33
Build production-ready Web3 applications, smart contracts, and decentralized systems. Implements DeFi protocols, NFT platforms, DAOs, and enterprise blockchain integrations. Use PROACTIVELY for smart contracts, Web3 apps, DeFi protocols, or blockchain infrastructure.
solana-dev
mashharuki
Use when user asks to "build a Solana dapp", "write an Anchor program", "create a token", "debug Solana errors", "set up wallet connection", "test my Solana program", "deploy to devnet", or "explain Solana concepts" (rent, accounts, PDAs, CPIs, etc.). End-to-end Solana development playbook covering
solana-dev
solanabr
Unified skill hub for Solana development. Routes to external submodule skills (solana-foundation, sendai, solana-game, trailofbits, cloudflare, qedgen, colosseum) and local skills. Progressive disclosure — read only what you need.
tauri-syntax-permissions
OpenAEC-Foundation
>
crypto-firewall-security
chartingshow
The agent should prioritize safety, correctness, and explicit validation over convenience or performance shortcuts.
tauri
EpicenterHQ
Tauri path handling, cross-platform file operations, and API usage. Use when working with file paths in Tauri frontend code, accessing filesystem APIs, or handling platform differences in desktop apps.