home / skills / multiversx / mx-ai-skills / mvx_sharp_edges
This skill helps you spot sharp edge patterns in MultiversX contracts, including async callbacks, gas, storage mappers, decimals, upgrades, and block timing.
npx playbooks add skill multiversx/mx-ai-skills --skill mvx_sharp_edgesReview the files below or copy the command above to add this skill to your agents.
---
name: mvx_sharp_edges
description: Identify weird behaviors in WASM, Gas limits, and async call failures specific to MultiversX.
---
# MultiversX Sharp Edges
This skill alerts you to non-obvious behaviors, "gotchas," and platform-specific quirks that often lead to bugs.
## 1. Async Callbacks & Reverts
- **The Edge**: When an Async Call fails, the `#[callback]` is executed.
- **The Sharp Logic**:
- If you don't implement a callback, the funds return to the contract, but state changes in the original transaction are **NOT reverted** automatically.
- *Mitigation*: You must manually revert state in the callback if the sub-call failed (or use the synchronous `back_transfers` carefully).
## 2. Gas Limits & Out of Gas (OOG)
- **The Edge**: OOG raises a specific error but can leave the system in a partial state if not handled.
- **The Sharp Logic**:
- **Cross-shard OOG**: If the destination shard runs OOG, the transaction fails, but the sender shard has already processed the transfer. The callback is triggered with an error.
## 3. Storage Mappers vs Rust Types
- **The Edge**: `VecMapper` is NOT a `Vec`.
- **The Sharp Logic**:
- `Vec` loads everything into WASM memory (RAM spike).
- `VecMapper` loads nothing until you call `get(i)`.
- *Bug*: Using `Vec` for a list of all users = OOG when userbase grows.
## 4. Token Decimal Precision
- **The Edge**: ESDTs can have 0-18 decimals.
- **The Sharp Logic**:
- Hardcoding `10^18` for "One Token" is wrong.
- Always fetch `decimals` or require standard 18-decimal tokens.
## 5. Upgradeability
- **The Edge**: `#[init]` is NOT called on upgrade. `#[upgrade]` is called.
- **The Sharp Logic**:
- If you add a new storage mapper, you must initialize it in `#[upgrade]`.
- Changing the storage layout of existing mappers (e.g. `struct` field order) corrupts data.
## 6. Block Info inside Views
- **The Edge**: `get_block_timestamp_millis()` / `get_block_timestamp_seconds()` in a `#[view]` (off-chain simulation) might return 0 or a different value than on-chain. Since Supernova (0.6s rounds), prefer `get_block_timestamp_millis()` with `TimestampMillis` for sub-second precision.
- **The Sharp Logic**:
- Don't rely on block info for critical off-chain view logic.
This skill surfaces non-obvious MultiversX platform quirks that commonly cause bugs and production incidents. It highlights sharp edges around async callbacks, gas behavior, storage mappers, token decimals, upgradeability, and view-mode block info. Use it to catch subtle failure modes early and design safer contracts.
The skill inspects common code patterns and runtime behaviors and explains the platform-specific outcome you should expect. It focuses on async call semantics and callback execution, cross-shard and local OOG consequences, differences between storage mappers and Rust types, correct token decimal handling, upgrade-time initialization, and block timestamp behavior in views. For each area it gives the faulty pattern, the concrete consequence, and a practical mitigation.
If an async call fails, do I get an automatic revert?
No. The callback runs, but you must explicitly revert or undo state changes there. Funds may be returned to the contract, but original transaction state is not auto-reverted.
When should I prefer VecMapper over Vec?
Use VecMapper for large or growing lists to avoid loading everything into WASM RAM. Vec is fine for small, fixed-size collections.