Getting started

Primitive types

uint/int become sized Rust integers, address becomes AccountId, bytes/string map to Rust equivalents — and you pick the width yourself.

Solidity has a handful of value types with uint256 as the comfortable default. Rust gives you the same primitives but sized explicitly — you choose u8…u128 — and a few NEAR-specific ones for accounts and money.

The common types, side by side
Solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

contract Types {
    bool    public flag = true;
    uint256 public big = 1_000_000;
    int32   public signed = -7;
    address public who;
    bytes32 public hash;
    string  public name = "near.mom";
}
Rust
use near_sdk::near;
use near_sdk::AccountId;

#[near(contract_state)]
pub struct Types {
    flag: bool,
    big: u128,          // pick the width; no 256-bit default
    signed: i32,
    who: Option<AccountId>,
    hash: [u8; 32],     // fixed 32 bytes, like bytes32
    name: String,
}

impl Default for Types {
    fn default() -> Self {
        Self {
            flag: true,
            big: 1_000_000,
            signed: -7,
            who: None,
            hash: [0u8; 32],
            name: "near.mom".to_string(),
        }
    }
}
Coming from EVM

uint256 / uintN ↔ u128 / u64 / u32 … — Rust has no 256-bit default, so you size it. intN ↔ iN. For method arguments and returns above 2^53, wrap large ints as U128 / U64 (JSON precision).

address ↔ AccountId; bytes32 ↔ [u8; 32]; bytes ↔ Vec<u8>; string ↔ String. There is no null address — an unset account is Option<AccountId> (None).

Arithmetic overflow panics in a release build (reverting the call), where Solidity 0.8+ also reverts on overflow — same safety, enforced by the compiler rather than inserted checks.