> 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/undefined-1/string-bytes.md).

# string, bytes

### **특징**

| 항목    | 내용                                                                      |
| ----- | ----------------------------------------------------------------------- |
| 타입명   | string, bytes                                                           |
| 크기    | 동적 (길이에 따라 다름)                                                          |
| 패킹 가능 | O (31바이트 이하면 슬롯 내 packing 저장 가능)                                        |
| 기본 저장 | - 31바이트 이하: 슬롯 자체에 길이+데이터 압축 저장 - 32바이트 이상: keccak256(slot) 위치부터 연속 저장됨 |

***

### **예시1 - 32바이트 이하**

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Example1 {
    bytes public a;
    string public b;

    constructor() {
      a = "hello1";
      b = "hello2";
    }
}
```

<figure><img src="https://2462457462-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLf9vwRuaws92ULgGvzTi%2Fuploads%2FrnSHlcxhCepGBd87pJBm%2Fimage.png?alt=media&amp;token=2ddedc45-10e3-402d-85b8-e3064c11e45d" alt=""><figcaption></figcaption></figure>

```
// 스토리지

address: 0x0000000000000000000000000000000000000000000000000000000000000000
0x68656c6c6f31000000000000000000000000000000000000000000000000000c

address: 0x0000000000000000000000000000000000000000000000000000000000000001
0x68656c6c6f32000000000000000000000000000000000000000000000000000c
```

슬롯 0, 1에 각각 bytes, string 타입이 상위 바이트부터 저장된다.

또한 하위 1바이트에 0x0c 라는 값을 볼 수 있다.

#### length \* 2 + flag

* length: 바이트 수 (최대 31)
* flag: 저장 방식 (packed인지 아닌지)

  * 0 → **packed mode (슬롯 내에 직접 저장됨)**
  * 1  → **external mode (슬롯 밖에 저장됨, keccak 해시로 위치 계산)**

  0x0c 값은 "Hello1" 길이인 6바이트. 6\*2(length) + 0(packed)로 계산되었다.

***

### **예시2 - 32바이트 이상(1)**

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Example2 {
    bytes public a;

    constructor() {
      a = "abcdefghijklmnopqrstuvwxyz123456ABCDEFG";
    }
}
```

<figure><img src="https://2462457462-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLf9vwRuaws92ULgGvzTi%2Fuploads%2FhsjQyqFvVyDyNuw5SAY3%2Fimage.png?alt=media&amp;token=b0a53b7a-519d-4bd4-887e-b2aa95053cdd" alt=""><figcaption></figcaption></figure>

```
// 스토리지

address: 0x0000000000000000000000000000000000000000000000000000000000000000
0x000000000000000000000000000000000000000000000000000000000000004f

address: 0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563
0x6162636465666768696a6b6c6d6e6f707172737475767778797a313233343536

address: 0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e564
0x4142434445464700000000000000000000000000000000000000000000000000
```

슬롯 0에는 데이터의 길이가 위치한다. 따라서 39\*2+1인 4f가 하위 바이트부터 저장되었다.

32바이트를 초과할 경우, keccak(슬롯 주소)를 주소로 지정하고 데이터를 상위 바이트부터 차례대로 작성한다. 만약 데이터 길이가 초과될 경우에는 keccak(슬롯 주소) + 1 순으로 차례대로 늘려간다.

***

### **예시3 - 32바이트 이상(2)**

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Example3 {
    bytes public a;
    string public b;

    constructor() {
      a = "abcdefghijklmnopqrstuvwxyz123456";
      b = "123456abcdefghijklmnopqrstuvwxyz";
    }
}
```

<figure><img src="https://2462457462-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLf9vwRuaws92ULgGvzTi%2Fuploads%2F7bW81dbbzfeKkzRmuRds%2Fimage.png?alt=media&amp;token=83f6f15f-7bc6-45e9-a0d5-6029d54a14a6" alt=""><figcaption></figcaption></figure>

```
// 스토리지

address: 0x0000000000000000000000000000000000000000000000000000000000000000
0x0000000000000000000000000000000000000000000000000000000000000041

address: 0x0000000000000000000000000000000000000000000000000000000000000001
0x0000000000000000000000000000000000000000000000000000000000000041

address: 0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563
0x6162636465666768696a6b6c6d6e6f707172737475767778797a313233343536

address: 0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6
0x3132333435366162636465666768696a6b6c6d6e6f707172737475767778797a
```

만약 32바이트 이상인 문자열 변수가 이어서 선언된다면, 각각 keccak(슬롯 주소)를 주소로 지정한다. 변수 a와 변수 b의값은 각각 keccak(0)과 keccak(1)에 저장되었다.
