home / skills / multiversx / mx-ai-skills / mvx_cross_contract_storage

mvx_cross_contract_storage skill

/antigravity/skills/mvx_cross_contract_storage

This skill enables same-shard cross-contract storage reads without gas via storage_mapper_from_address, simplifying access to external data.

npx playbooks add skill multiversx/mx-ai-skills --skill mvx_cross_contract_storage

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
2.1 KB
---
name: mvx_cross_contract_storage
description: Read another contract's storage directly using storage_mapper_from_address for same-shard contracts.
---

# MultiversX Cross-Contract Storage Reads

Read another contract's storage mappers directly — zero gas overhead from proxy calls, no async complexity.

## When to Use

| Criteria | `storage_mapper_from_address` | Proxy Call |
|---|---|---|
| Same shard only | Yes (required) | Works cross-shard |
| Read-only | Yes | Read + Write |
| Needs computation on target | No | Yes |
| Gas cost | ~storage read cost | ~execution + storage |
| Requires knowing storage keys | Yes | No (uses ABI) |

## Core Pattern

```rust
#[multiversx_sc::module]
pub trait ExternalStorageModule {
    // Simple value
    #[storage_mapper_from_address("total_supply")]
    fn external_total_supply(&self, contract_address: ManagedAddress) -> SingleValueMapper<BigUint, ManagedAddress>;

    // Composite key (token-specific)
    #[storage_mapper_from_address("balance")]
    fn external_balance(&self, contract_address: ManagedAddress, token_id: &TokenIdentifier) -> SingleValueMapper<BigUint, ManagedAddress>;

    // Module-prefixed key
    #[storage_mapper_from_address("pause_module:paused")]
    fn external_paused(&self, contract_address: ManagedAddress) -> SingleValueMapper<bool, ManagedAddress>;
}
```

### Key Rules
1. String must EXACTLY match storage key in target contract
2. First param must be `ManagedAddress`
3. Return type's second generic must be `ManagedAddress`
4. Additional params become composite key parts

## How to Discover Storage Keys
1. Source code: `#[storage_mapper("key")]` in target
2. ABI: `.abi.json` lists all keys
3. Module keys: prefixed like `pause_module:paused`

## Security

- **Same-shard only**: Cross-shard reads return defaults silently — no error
- **Stale data**: Reflects target's state as of current block
- **Key changes**: If target renames keys in upgrade, reads break silently
- **Read-only**: Cannot write to another contract's storage

## Anti-Patterns
- Not validating empty results (get default 0/false silently)
- Not validating target is on same shard

Overview

This skill enables direct, read-only access to another contract's storage on the same shard using storage_mapper_from_address. It avoids proxy call overhead and asynchronous complexity by mapping storage keys from a target contract address. Use it when you need cheap, immediate reads and you can identify the exact storage keys on the target contract.

How this skill works

Declare storage mappers that take a ManagedAddress as the first parameter and use storage_mapper_from_address with the exact storage key string. The mapper returns a mapper type whose second generic is ManagedAddress. Additional function parameters form composite key parts. Reads are executed locally for same-shard targets and return the target contract's value or default zero/false if the key is missing.

When to use it

  • You need low-cost, immediate read access to another contract on the same shard.
  • You already know the exact storage keys or can find them in source/ABI.
  • Reading state only (no writes or cross-contract execution required).
  • You prefer to avoid proxy call gas and async handling.
  • You must fetch simple or composite storage values (e.g., balances, flags).

Best practices

  • Confirm the target contract is on the same shard before relying on results.
  • Validate for default results (0, false, empty) and handle missing keys explicitly.
  • Use exact storage key strings; module prefixes must match (e.g., pause_module:paused).
  • Keep read-only logic here; perform any needed computation locally or via explicit cross-contract calls when required.
  • Document the target storage keys in your code or deployment notes to avoid silent breakage after upgrades.

Example use cases

  • Read total supply from a token contract for display without paying proxy gas.
  • Fetch per-token balances using a composite key (contract address + token ID).
  • Check a pause flag in another contract's module-prefixed storage key before proceeding.
  • Aggregate on-chain metrics across same-shard contracts with minimal cost.
  • Build dashboards that sample multiple contracts’ state efficiently.

FAQ

What happens if the target contract is on a different shard?

Cross-shard reads return default values (0 or false) silently; always verify shard locality before relying on results.

How do I find the exact storage key string?

Inspect the target contract source for #[storage_mapper("key")] annotations or check the contract's .abi.json which lists storage keys and module prefixes.