multiversx-static-analysis

MultiversX Static Analysis

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "multiversx-static-analysis" with this command: npx skills add multiversx/mx-ai-skills/multiversx-mx-ai-skills-multiversx-static-analysis

MultiversX Static Analysis

Comprehensive static analysis guide for MultiversX codebases, covering both Rust smart contracts (multiversx-sc ) and Go protocol code (mx-chain-go ). This skill provides grep patterns, manual review techniques, and tool recommendations.

When to Use

  • Starting security code reviews

  • Setting up automated vulnerability scanning

  • Creating analysis checklists for audits

  • Training new security reviewers

  • Investigating specific vulnerability classes

  1. Rust Smart Contracts (multiversx-sc )

Critical Grep Patterns

Unsafe Code

Unsafe blocks - valid only for FFI or specific optimizations

grep -rn "unsafe" src/

Generally forbidden in smart contracts unless justified

Risk: Memory corruption, undefined behavior Action: Require justification for each unsafe block

Panic Inducers

Direct unwrap - can panic

grep -rn ".unwrap()" src/

Expect - also panics

grep -rn ".expect(" src/

Index access - can panic on out of bounds

grep -rn "[.*]" src/ | grep -v "storage_mapper"

Risk: Contract halts, potential DoS Action: Replace with unwrap_or_else(|| sc_panic!(...)) or proper error handling

Floating Point Arithmetic

f32 type

grep -rn "f32" src/

f64 type

grep -rn "f64" src/

Float casts

grep -rn "as f32|as f64" src/

Risk: Non-deterministic behavior, consensus failure Action: Use BigUint /BigInt for all calculations

Unchecked Arithmetic

Direct arithmetic operators

grep -rn "[^_a-zA-Z]+ [^_a-zA-Z]" src/ # Addition grep -rn "[^_a-zA-Z]- [^_a-zA-Z]" src/ # Subtraction grep -rn "[^_a-zA-Z]* [^_a-zA-Z]" src/ # Multiplication

Without checked variants

grep -rn "checked_add|checked_sub|checked_mul" src/

Risk: Integer overflow/underflow Action: Use BigUint or checked arithmetic for all financial calculations

Map Iteration (DoS Risk)

Iterating storage mappers

grep -rn ".iter()" src/

Especially dangerous patterns

grep -rn "for.in..iter()" src/ grep -rn ".collect()" src/

Risk: Gas exhaustion DoS Action: Add pagination or bounds checking

Logical Pattern Analysis (Manual Review)

Token ID Validation

Search for payment handling:

grep -rn "call_value()" src/ grep -rn "all_esdt_transfers" src/ grep -rn "single_esdt" src/

For each occurrence, verify:

  • Token ID checked against expected value

  • Token nonce validated (for NFT/SFT)

  • Amount validated (non-zero, within bounds)

// VULNERABLE #[payable("*")] fn deposit(&self) { let payment = self.call_value().single_esdt(); self.balances().update(|b| *b += payment.amount); // No token ID check! Accepts any token }

// SECURE #[payable("*")] fn deposit(&self) { let payment = self.call_value().single_esdt(); require!( payment.token_identifier == self.accepted_token().get(), "Wrong token" ); require!(payment.amount > 0, "Zero amount"); self.balances().update(|b| *b += payment.amount); }

Callback State Assumptions

Search for callbacks:

grep -rn "#[callback]" src/

For each callback, verify:

  • Does NOT assume async call succeeded

  • Handles error case explicitly

  • Reverts state changes on failure if needed

// VULNERABLE - assumes success #[callback] fn on_transfer(&self) { self.transfer_count().update(|c| *c += 1); }

// SECURE - handles both cases #[callback] fn on_transfer(&self, #[call_result] result: ManagedAsyncCallResult<()>) { match result { ManagedAsyncCallResult::Ok() => { self.transfer_count().update(|c| *c += 1); }, ManagedAsyncCallResult::Err() => { // Handle failure - funds returned automatically } } }

Access Control

Search for endpoints:

grep -rn "#[endpoint]" src/ grep -rn "#[only_owner]" src/

For each endpoint, verify:

  • Appropriate access control applied

  • Sensitive operations restricted

  • Admin functions documented

// VULNERABLE - public sensitive function #[endpoint] fn set_fee(&self, new_fee: BigUint) { self.fee().set(new_fee); }

// SECURE - restricted #[only_owner] #[endpoint] fn set_fee(&self, new_fee: BigUint) { self.fee().set(new_fee); }

Reentrancy (CEI Pattern)

Search for external calls:

grep -rn ".send()." src/ grep -rn ".tx()" src/ grep -rn "async_call" src/

Verify Checks-Effects-Interactions pattern:

  • All checks (require!) before state changes

  • State changes before external calls

  • No state changes after external calls in same function

  1. Go Protocol Code (mx-chain-go )

Concurrency Issues

Goroutine Loop Variable Capture

grep -rn "go func" *.go

Check for loop variable capture bug:

// VULNERABLE for _, item := range items { go func() { process(item) // item may have changed! }() }

// SECURE for _, item := range items { item := item // Create local copy go func() { process(item) }() }

Map Race Conditions

grep -rn "map[" *.go | grep -v "sync.Map"

Verify maps accessed from goroutines are protected:

// VULNERABLE var balances = make(map[string]int) // Accessed from multiple goroutines without mutex

// SECURE var balances = sync.Map{} // Or use mutex protection

Determinism Issues

Map Iteration Order

grep -rn "for.*range.*map" *.go

Map iteration in Go is random. Never use for:

  • Generating hashes

  • Creating consensus data

  • Any deterministic output

// VULNERABLE - non-deterministic func hashAccounts(accounts map[string]int) []byte { var data []byte for k, v := range accounts { // Random order! data = append(data, []byte(k)...) } return hash(data) }

// SECURE - sort keys first func hashAccounts(accounts map[string]int) []byte { keys := make([]string, 0, len(accounts)) for k := range accounts { keys = append(keys, k) } sort.Strings(keys)

var data []byte
for _, k := range keys {
    data = append(data, []byte(k)...)
}
return hash(data)

}

Time Functions

grep -rn "time.Now()" *.go

time.Now() is forbidden in block processing:

// VULNERABLE func processBlock(block *Block) { timestamp := time.Now().Unix() // Non-deterministic! }

// SECURE func processBlock(block *Block) { timestamp := block.Header.TimeStamp // Deterministic }

  1. Analysis Checklist

Smart Contract Review Checklist

Access Control

  • All endpoints have appropriate access restrictions

  • Owner/admin functions use #[only_owner] or explicit checks

  • No privilege escalation paths

Payment Handling

  • Token IDs validated in all #[payable] endpoints

  • Amounts validated (non-zero, bounds)

  • NFT nonces validated where applicable

Arithmetic

  • No raw arithmetic on u64/i64 with external inputs

  • BigUint used for financial calculations

  • No floating point

State Management

  • Checks-Effects-Interactions pattern followed

  • Callbacks handle failure cases

  • Storage layout upgrade-safe

Gas & DoS

  • No unbounded iterations

  • Storage growth is bounded

  • Pagination for large data sets

Error Handling

  • No unwrap() without justification

  • Meaningful error messages

  • Consistent error handling patterns

Protocol Review Checklist

Concurrency

  • All shared state properly synchronized

  • No goroutine loop variable capture bugs

  • Channel usage is correct

Determinism

  • No map iteration for consensus data

  • No time.Now() in block processing

  • No random number generation without deterministic seed

Memory Safety

  • Bounds checking on slices

  • No nil pointer dereferences

  • Proper error handling

  1. Automated Tools

Semgrep Rules

See multiversx-semgrep-creator skill for custom rule creation.

Clippy (Rust)

cargo clippy -- -D warnings

Useful lints:

- clippy::arithmetic_side_effects

- clippy::indexing_slicing

- clippy::unwrap_used

Go Vet & Staticcheck

go vet ./... staticcheck ./...

Race detection

go build -race

  1. Vulnerability Categories Quick Reference

Category Grep Pattern Severity

Unsafe code unsafe

Critical

Float arithmetic f32|f64

Critical

Panic inducers unwrap()|expect(

High

Unbounded iteration .iter()

High

Missing access control #[endpoint] without #[only_owner]

High

Token validation call_value() without require High

Callback assumptions #[callback] without error handling Medium

Raw arithmetic

  • | - | * on u64 Medium

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Research

multiversx-variant-analysis

No summary provided by upstream source.

Repository SourceNeeds Review
General

multiversx-clarification-expert

No summary provided by upstream source.

Repository SourceNeeds Review
General

multiversx-smart-contracts

No summary provided by upstream source.

Repository SourceNeeds Review
General

multiversx-protocol-experts

No summary provided by upstream source.

Repository SourceNeeds Review