home / skills / multiversx / mx-ai-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_storageReview the files below or copy the command above to add this skill to your agents.
---
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
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.
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.
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.