본문으로 건너뛰기

상태 & 자료구조

각 컨트랙트에는 고유한 상태(스토리지)가 있으며, 이는 해당 컨트랙트에 의해서만 수정 가능하지만 누구나 볼 수 있습니다.

컨트랙트는 모든 데이터를 키-값 스토리지에 저장합니다. 그러나 이는 SDK에 의한 직렬화를 통해 추상화됩니다.

:::info 컨트랙트는 잔고의 일부를 잠그는 방식으로 스토리지 비용을 지불합니다. 현재 100KB를 저장하는 데 ~1Ⓝ 만큼의 비용이 듭니다.

상태의 정의

컨트랙트의 상태는 핵심 클래스 속성에 의해 정의되며, 이를 통해 접근 가능합니다.

상태에는 상수, 기본 자료형 및 복합 객체를 저장할 수 있습니다. SDK 컬렉션은 직렬화된 키-값 스토리지에 최적화되어 있기 때문입니다.

storage-js/src/index.ts
loading...

Data Structures

The NEAR SDK exposes a series of structures (Vectors, Sets, Maps and Trees) to simplify storing data in an efficient way.

Instantiation

All structures need to be initialized using a unique prefix, which will be used to identify the structure's keys in the serialized state

storage-js/src/index.ts
loading...

Vector

Implements a vector/array which persists in the contract's storage. Please refer to the Rust and AS SDK's for a full reference on their interfaces.

storage-js/src/index.ts
loading...

Map

Implements a map/dictionary which persists in the contract's storage. Please refer to the Rust and AS SDK's for a full reference on their interfaces.

storage-js/src/index.ts
loading...
Nesting of Objects - Temporary Solution

In the JS SDK, you can store and retrieve elements from a nested map or object, but first you need to construct or deconstruct the structure from state. This is a temporary solution until the improvements have been implemented to the SDK. Here is an example of how to do this:

import { NearBindgen, call, view, near, UnorderedMap } from "near-sdk-js";

@NearBindgen({})
class StatusMessage {
records: UnorderedMap;
constructor() {
this.records = new UnorderedMap("a");
}

@call({})
set_status({ message, prefix }: { message: string; prefix: string }) {
let account_id = near.signerAccountId();

const inner: any = this.records.get("b" + prefix);
const inner_map: UnorderedMap = inner
? UnorderedMap.deserialize(inner)
: new UnorderedMap("b" + prefix);

inner_map.set(account_id, message);

this.records.set("b" + prefix, inner_map);
}

@view({})
get_status({ account_id, prefix }: { account_id: string; prefix: string }) {
const inner: any = this.records.get("b" + prefix);
const inner_map: UnorderedMap = inner
? UnorderedMap.deserialize(inner)
: new UnorderedMap("b" + prefix);
return inner_map.get(account_id);
}
}

Set

Implements a set which persists in the contract's storage. Please refer to the Rust and AS SDK's for a full reference on their interfaces.

storage-js/src/index.ts
loading...

Tree

An ordered equivalent of Map. The underlying implementation is based on an AVL. You should use this structure when you need to: have a consistent order, or access the min/max keys.

storage-rs/contract/src/tree.rs
loading...

Storage Cost

Your contract needs to lock a portion of their balance proportional to the amount of data they stored in the blockchain. This means that:

  • If more data is added and the storage increases ↑, then your contract's balance decreases ↓.
  • If data is deleted and the storage decreases ↓, then your contract's balance increases ↑.

Currently, it cost approximately 1 Ⓝ to store 100kb of data.

정보

You can save on smart contract storage if using NEAR Account IDs by encoding them using base32. Since they consist of [a-z.-_] characters with a maximum length of 64 characters, they can be encoded using 5 bits per character, with terminal \0. Going to a size of 65 * 5 = 325 bits from the original (64 + 4) * 8 = 544 bits. This is a 40% reduction in storage costs.

주의

An error will raise if your contract tries to increase its state while not having NEAR to cover for storage.

warning

Be mindful of potential small deposit attacks

Was this page helpful?