Skip to main content
Let’s explore the basic anatomy of a simple “Hello World” contract to understand how NEAR smart contracts are structured.

Importing the SDK

All contracts import the NEAR SDK, enabling them to access the execution environment, call other contracts, transfer tokens, and much more.
use near_sdk::near;
You can also use third-party libraries, though some might not work due to the limitations of the contract runtime.

Contract Structure

The contract is described through a structure:
  • The attributes define which data the contract stores
  • The functions define its public (and private) interface
use near_sdk::near;

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

#[near]
impl Contract {
    #[init]
    pub fn new() -> Self {
        Self {
            greeting: "Hello".to_string(),
        }
    }

    pub fn get_greeting(&self) -> String {
        self.greeting.clone()
    }

    pub fn set_greeting(&mut self, greeting: String) {
        self.greeting = greeting;
    }
}
Contract Struct MacroThe #[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.

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".
#[near(contract_state)]
pub struct Contract {
    greeting: String,  // This field is stored in the contract's state
}

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

Learn More About State

Deep dive into contract state management and storage

Read-Only Functions

Contract functions can be read-only, meaning they don’t modify the state. Calling them is free for everyone, and does not require having a NEAR account.
// Read-only functions take an immutable reference to self
pub fn get_greeting(&self) -> String {
    self.greeting.clone()
}
In Rust, read-only functions are those that take an immutable reference to self (&self).

Learn More About Functions

Explore all function types and their use cases

State-Changing Functions

Functions that modify the state or call other contracts are considered state-changing functions. It is necessary to have a NEAR account to call them, as they require a transaction to be sent to the network.
// State-changing functions take a mutable reference to self
pub fn set_greeting(&mut self, greeting: String) {
    near_sdk::log!("Saving greeting: {}", greeting);
    self.greeting = greeting;
}
In Rust, state-changing functions are those that take a mutable reference to self (&mut self).

Contextual Information

The SDK provides contextual information about the execution environment, such as:
  • Who called the function - predecessor_account_id
  • Current block timestamp - block_timestamp
  • Attached deposit - attached_deposit
  • Available gas - prepaid_gas
use near_sdk::{env, AccountId, Balance};

pub fn get_caller(&self) -> AccountId {
    env::predecessor_account_id()
}

pub fn get_timestamp(&self) -> u64 {
    env::block_timestamp()
}

#[payable]
pub fn get_deposit(&self) -> Balance {
    env::attached_deposit().as_yoctonear()
}

Internal Functions

Contracts can also have private internal functions - such as helper or utility functions - that are not exposed to the outside world.
#[near]
impl Contract {
    // Public function - exposed to external callers
    pub fn increment(&mut self) {
        self.internal_increment();
    }

    // Private function - not exposed externally
    fn internal_increment(&mut self) {
        self.counter += 1;
    }
}
To create internal private methods in Rust, do not declare them as public (pub fn).

Next Steps

Functions

Learn about all function types

Storage

Understand state management

Cross-Contract Calls

Call other contracts

Testing

Test your contracts

Build docs developers (and LLMs) love