State & storage
Collections: mappings & arrays
mapping and dynamic arrays become explicit types from near_sdk::store — LookupMap, Vector — each with its own storage prefix.
Solidity gives you mapping and T[] as language built-ins. NEAR gives you collection types from near_sdk::store that you pick deliberately: LookupMap, Vector, IterableMap, UnorderedSet. Each is a thin wrapper over on-chain key/value storage.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract Points {
mapping(address => uint32) public points;
address[] public members;
function join() external {
if (points[msg.sender] == 0) {
members.push(msg.sender);
}
}
function award(address who, uint32 amount) external {
points[who] += amount;
}
function memberCount() external view returns (uint256) {
return members.length;
}
}use near_sdk::{near, env, AccountId};
use near_sdk::store::{LookupMap, Vector};
#[near(contract_state)]
pub struct Points {
points: LookupMap<AccountId, u32>,
members: Vector<AccountId>,
}
impl Default for Points {
fn default() -> Self {
Self {
// each collection needs its own unique storage prefix
points: LookupMap::new(b"p"),
members: Vector::new(b"m"),
}
}
}
#[near]
impl Points {
pub fn join(&mut self) {
let who = env::predecessor_account_id();
if !self.points.contains_key(&who) {
self.members.push(who.clone());
self.points.insert(who, 0);
}
}
pub fn award(&mut self, who: AccountId, amount: u32) {
let cur = self.points.get(&who).copied().unwrap_or(0);
self.points.insert(who, cur + amount);
}
pub fn points_of(&self, who: AccountId) -> u32 {
self.points.get(&who).copied().unwrap_or(0)
}
pub fn member_count(&self) -> u32 {
self.members.len()
}
}mapping(k => v) ↔ LookupMap<K, V>; a dynamic array ↔ Vector<T>. There is no default value magic — reads return Option, so you unwrap_or(..) the "unset" case yourself.
Each collection takes a unique storage prefix (b"p", b"m") — the byte key its entries are stored under. Two collections sharing a prefix silently corrupt each other, so keep them distinct.
LookupMap is get/set by key but not iterable — the cheapest option. Need to iterate entries or list keys? Use IterableMap (or UnorderedMap). Paying only for what you enumerate is the tradeoff NEAR makes for predictable storage gas.