> ## Documentation Index
> Fetch the complete documentation index at: https://compact-by-example.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Mappings

> Key-value storage in Compact: declare ledger Maps, insert and look up entries, nest maps, and handle missing keys safely on Midnight.

## The Contract

<Accordion title="View Contract Code">
  ```compact theme={null}
  pragma language_version >= 0.23;

  import CompactStandardLibrary;

  // Simple balance tracker
  export ledger balances: Map<Either<ZswapCoinPublicKey, ContractAddress>, Uint<128>>;

  // Get balance for an account
  export circuit getBalance(account: Either<ZswapCoinPublicKey, ContractAddress>): Uint<128> {
      // Check if account exists in map
      if (!balances.member(disclose(account))) {
          return 0; // Return 0 for accounts with no balance
      }
      return balances.lookup(disclose(account));
  }

  // Set balance for an account
  export circuit setBalance(
      account: Either<ZswapCoinPublicKey, ContractAddress>,
      amount: Uint<128>
  ): [] {
      balances.insert(disclose(account), disclose(amount));
  }

  // Add to existing balance
  export circuit addBalance(
      account: Either<ZswapCoinPublicKey, ContractAddress>,
      amount: Uint<128>
  ): [] {
      const MAX_UINT128: Uint<128> = 340282366920938463463374607431768211455 as Uint<128>;
      const currentBalance = getBalance(account);

      // Check for overflow before casting back
      assert(currentBalance <= MAX_UINT128 - amount, "Balance overflow");

      const newBalance: Uint<128> = (currentBalance + amount) as Uint<128>;
      balances.insert(disclose(account), disclose(newBalance));
  }

  // Subtract from balance
  export circuit subtractBalance(
      account: Either<ZswapCoinPublicKey, ContractAddress>,
      amount: Uint<128>
  ): [] {
      const currentBalance = getBalance(account);

      // Check sufficient balance
      assert(currentBalance >= amount, "Insufficient balance");

      const newBalance = currentBalance - amount;
      balances.insert(disclose(account), disclose(newBalance));
  }
  ```
</Accordion>

## How It Works

### Map Declaration

```compact theme={null}
export ledger balances: Map<Either<ZswapCoinPublicKey, ContractAddress>, Uint<128>>;
```

Maps have key and value type parameters. This one maps accounts to balance amounts.

### Checking Membership

```compact theme={null}
if (!balances.member(disclose(account))) {
    return 0;
}
```

Use `member(key)` to check if a key exists before lookup.

### Looking Up Values

```compact theme={null}
return balances.lookup(disclose(account));
```

Use `lookup(key)` to get the value for a key.

### Inserting or Updating

```compact theme={null}
balances.insert(disclose(account), disclose(amount));
```

Use `insert(key, value)` to add or update an entry.

### Safe Arithmetic

```compact theme={null}
const MAX_UINT128: Uint<128> = 340282366920938463463374607431768211455 as Uint<128>;
const currentBalance = getBalance(account);

// Check for overflow before casting the widened sum back to Uint<128>
assert(currentBalance <= MAX_UINT128 - amount, "Balance overflow");

const newBalance: Uint<128> = (currentBalance + amount) as Uint<128>;
balances.insert(disclose(account), disclose(newBalance));
```

Compact arithmetic widens the result type, so the sum must be **asserted to fit and then explicitly cast back** to `Uint<128>` before storing. See [Overflow Protection](/basics/overflow-protection).

<Warning>
  **`setBalance` and `addBalance` have no authentication.** Anyone can overwrite
  any account's balance. The pattern here is for illustration; production token
  contracts must gate writes with the [Access Control](/basics/access-control)
  keypair pattern.
</Warning>

## Common Patterns

### Initialize with Default

```compact theme={null}
export circuit ensureAccount(account: Either<ZswapCoinPublicKey, ContractAddress>): [] {
    if (!balances.member(disclose(account))) {
        balances.insert(disclose(account), 0);
    }
}
```

Create an entry if it doesn't exist.

### Nested Maps

```compact theme={null}
// Allowances: owner -> (spender -> amount)
export ledger allowances: Map<
    Either<ZswapCoinPublicKey, ContractAddress>,
    Map<Either<ZswapCoinPublicKey, ContractAddress>, Uint<128>>
>;

export circuit getAllowance(
    owner: Either<ZswapCoinPublicKey, ContractAddress>,
    spender: Either<ZswapCoinPublicKey, ContractAddress>
): Uint<128> {
    if (!allowances.member(disclose(owner))) {
        return 0;
    }

    const spenderAllowances = allowances.lookup(disclose(owner));
    if (!spenderAllowances.member(disclose(spender))) {
        return 0;
    }

    return spenderAllowances.lookup(disclose(spender));
}
```

Maps can contain other Maps for complex relationships (used in approval systems).

### Iterating Over Maps

Compact doesn't support iterating over Map keys directly. Track keys separately if needed.

## What's Next

<CardGroup cols={2}>
  <Card title="Transfer Function" icon="arrow-right-arrow-left" href="/basics/transfer">
    Build a token transfer system
  </Card>

  <Card title="ERC20 Token" icon="coins" href="/applications/erc20-token">
    See Maps in a complete token
  </Card>
</CardGroup>
