Skip to content
by Unity Nodes
docs.near.orgsmart contracts › anatomy › anatomy

Basic Anatomy

Updated 01-11-2026

Learn the basic anatomy of all smart contracts.

Let's illustrate the basic anatomy of a simple "Hello World" contract. The code on this page comes from our Hello NEAR repository on GitHub.

Importing the SDK

All contracts will import the NEAR SDK, enabling them to access the execution environment, call other contracts, transfer tokens, and much more.

You can also use third-party libraries, though some might not work due to the limitations of the contract runtime.

use near_sdk::{log, near};

See code on GitHub

Contract's Main Structure

The contract is described through a structure:

  • The attributes define which data the contract stores
  • The functions define its public (and private) interface

Note that the contract's struct definition and the implementation are decorated with macros

The #[near(contract_state)] macro tells the SDK that this structure defines the contract's state, so it knows:

  1. What to fetch from storage when the contract is loaded
  2. What to store when the contract is done executing

The #[near] macro tells the SDK which functions are exposed to the outside world.

[!NOTE]

Only one struct can be decorated with the #[near(contract_state)] macro.

#[near(contract_state)]
pub struct Contract {
    greeting: String,
}

See code on GitHub

#[near]
impl Contract {
    // Public method - returns the greeting saved, defaulting to DEFAULT_GREETING
    pub fn get_greeting(&self) -> String {
        self.greeting.clone()
    }

    // Public method - accepts a greeting, such as "howdy", and records it
    pub fn set_greeting(&mut self, greeting: String) {
        log!("Saving greeting: {}", greeting);
        self.greeting = greeting;
    }
}

See code on GitHub

[accordion] Interaction with other macros

When near is built for the wasm32 target, it generates the external NEAR contract bindings. To achieve this it is actually generating another function with the signature pub extern "C" fn function_name() that first deserializes the contract struct from NEAR storage and then calls the contract.function_name(parameter1, parameter2, ...).

If you have annotated your function with any attribute-like macros, these are then executed twice. Specifically if the attribute like macro makes any modification to the function signature, or inserts any code that depends on the contract struct (in the form of &self, &mut self, or self) this will fail in the second invocation, because the externally exposed function does not have any concept of this struct.

It is possible to detect this by checking which build target you are building for and limit the execution of the macro to operate only on the first pass.

Storage (State)

We call the data stored in the contract the contract's state.

In our Hello World example, the contract stores a single string (greeting), and the state starts initialized with the default value "Hello".

[!NOTE]

We will cover more about the contract's state in the state section.

pub struct Contract {
    greeting: String,
}

See code on GitHub

impl Default for Contract {
    fn default() -> Self {
        Self {
            greeting: "Hello".to_string(),
        }
    }
}

See code on GitHub

Read Only Functions

Contract's functions can be read-only, meaning they don't modify the state. Calling them is free for everyone, and does not require to have a NEAR account.

[!NOTE]

We will cover more about function types in the functions section.

// Public method - returns the greeting saved, defaulting to DEFAULT_GREETING
pub fn get_greeting(&self) -> String {
    self.greeting.clone()
}

See code on GitHub

State Mutating Functions

Functions that modify the state or call other contracts are considered state mutating functions. It is necessary to have a NEAR account to call them, as they require a transaction to be sent to the network.

[!NOTE]

We will cover more about function types in the functions section.

// Public method - accepts a greeting, such as "howdy", and records it
pub fn set_greeting(&mut self, greeting: String) {
    log!("Saving greeting: {}", greeting);
    self.greeting = greeting;
}

See code on GitHub