> For the complete documentation index, see [llms.txt](https://whs3-doge5k.gitbook.io/smartcontract-security-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://whs3-doge5k.gitbook.io/smartcontract-security-docs/basics/3.-evm/evm-2.md).

# EVM의 스토리지 슬롯

### **개념**

<figure><img src="https://2462457462-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLf9vwRuaws92ULgGvzTi%2Fuploads%2FpssCGqJ6FudHuQru59f9%2Fimage.png?alt=media&amp;token=7372dfec-f8f7-48e2-ac91-696a7220a7a2" alt=""><figcaption></figcaption></figure>

이더리움 스마트 컨트랙트에서 스토리지(Storage)는 컨트랙트의 상태(state) 데이터를 영구적으로 저장하는 공간을 의미한다. 이 공간은 트랜잭션이 종료된 이후에도 블록체인 상에 영구적으로 남기 때문에, 이후에 다른 트랜잭션이나 외부 호출에서도 해당 데이터를 그대로 참조할 수 있다는 특징이 있다. 이러한 영속성은 이더리움의 상태(state)를 블록체인 전체 노드가 공유하고 있다는 점에서 비롯되며, 이에 따라 읽기 및 쓰기에 상당한 **가스 비용**이 수반된다.

스토리지는 내부적으로 최대 2²⁵⁶개의 슬롯(slot)으로 구성된 **거대한 key-value 저장소**이다. 각 슬롯은 위의그림과 같이 정확히 32바이트(256비트)의 데이터를 저장할 수 있으며, Solidity에서 선언한 상태 변수들은 이 슬롯들에 자동으로 배치된다. 예를 들어, `uint256`, `address`, `bool` 등의 기본 자료형은 하나의 슬롯을 차지하며, 구조체나 배열, 매핑 등 복합 자료형의 경우에는 별도의 슬롯 계산 규칙에 따라 저장된다.

이때 사용되는 슬롯(Slot)은 단순한 저장 단위를 넘어서, 상태 변수들의 위치와 직접적으로 연관되는 중요한 개념이다. Solidity 컴파일러는 상태 변수들의 선언 순서, 크기 및 정렬 기준에 따라 슬롯을 배치하는데, 예를 들어 크기가 작은 변수들은 가능한 한 같은 슬롯에 패킹(packing)되기도 한다. 슬롯은 **index 0부터 시작하는 배열처럼 동작**하며, 컴파일러가 정해진 방식으로 각 변수의 위치를 결정한다.

스토리지의 접근은 EVM 명령어인 `SLOAD`와 `SSTORE`를 통해 이루어진다. 읽기 연산(`SLOAD`)은 약 2100 gas, 쓰기 연산(`SSTORE`)은 데이터에 따라 최대 20,000 gas의 비용이 발생할 수 있다. 이는 계산 스택(stack) 기반 연산보다 현저히 높은 비용이다. 외부에서는 `getStorageAt` 같은 RPC 함수를 이용해 누구나 컨트랙트의 슬롯을 조회할 수 있는데, 이로 인해 `private` 변수라도 단순히 슬롯에 평문으로 저장되어 있다면 **보안상 노출될 수 있다**. 따라서 민감한 데이터는 해시화하거나 암호화하여 저장하는 것이 권장된다.

스토리지는 주로 **컨트랙트의 상태 유지**에 사용되며, 예를 들어 토큰 잔액, 소유자 주소, 투표 여부 등과 같이 지속적으로 참조되고 변경되는 데이터가 저장된다. 반면, EVM의 스택(Stack)은 함수 호출 중에만 존재하는 일시적 메모리로, 연산에 필요한 값을 임시로 저장하는 용도로 사용되며 호출이 종료되면 사라진다.

결과적으로, 스토리지는 상태 보존과 장기 데이터 유지에 필수적인 요소이며, 슬롯은 그 구조를 결정짓는 핵심 단위이다. Solidity로 스마트 컨트랙트를 설계할 때는 이러한 슬롯 구조를 이해함으로써 **데이터의 저장 방식, 가스 효율성, 보안성까지도 고려한 안전한 설계**가 가능하다.

***

### **패킹(packing)**

32바이트 슬롯의 빈 공간을 효율적으로 채우기 위해, 크기가 작은 상태 변수들을 하나의 슬롯에 연속해서 저장하는 최적화 기법이다. 만약 32바이트를 모두 채우지 못하면, 다음 상태변수는 남은 공간에 저장되고, 담기지 못한 값은 다음 슬롯으로 넘어간다.

***

### **정리**

| 항목    | 스토리지 (Storage)                                 | 슬롯 (Slot)                                    |
| ----- | ---------------------------------------------- | -------------------------------------------- |
| 정의    | 이더리움 스마트 컨트랙트의 영구적인 저장 공간                      | 스토리지 내의 개별 저장 단위 (index로 구분되는 32바이트 공간)      |
| 구성    | 2²⁵⁶개의 슬롯으로 구성된 key-value 저장소                  | `uint256` 키로 구분되며, 각 슬롯은 32바이트 크기의 value를 저장 |
| 용도    | 상태 변수, 토큰 잔액, owner 주소 등 영구 상태 저장              | 개별 상태 변수를 저장하기 위한 위치 (Solidity 컴파일러가 자동 배정)  |
| 접근 방법 | `SLOAD`, `SSTORE`, `getStorageAt` 등으로 직접 접근 가능 | 인덱스로 접근되며, 컴파일러가 각 변수에 대한 슬롯 번호를 자동 할당       |
| 가스 비용 | `SLOAD` 약 2100 gas / `SSTORE` 최대 20,000 gas    | 슬롯 그 자체로는 비용 없음. 접근 시 스토리지 비용이 발생            |
| 보안 특성 | 외부에서 `getStorageAt`으로 읽을 수 있어 민감 데이터는 암호화 필요   | `private` 변수도 슬롯에 평문으로 남음 → 보안 취약점 발생 가능     |

***

<details>

<summary><strong>파운드리 명령어 (참고)</strong></summary>

**명령어**

```bash
cast storage [컨트랙트 주소] [슬롯 index] --rpc-url [rpc-url]
```

foundry의 "cast storage" 명령어를 사용하여 슬롯의 상태 변수를 읽을 수 있다.

</details>

[<mark style="background-color:blue;">출처</mark>](https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html)
