변수 정리

변수 정리 (Cleaning Up Variables)

결국 EVM의 모든 값은 256비트 워드로 저장돼요. 그래서 값의 타입이 256비트보다 작은 경우, 남는 비트를 정리해야 하는 상황이 생겨요. Solidity 컴파일러는 남는 비트의 쓰레기 값 때문에 부정적 영향을 받을 수 있는 연산 전에 이런 정리를 수행하도록 설계돼 있어요.

출처: 문서

본문

결국 EVM의 모든 값은 256비트 워드로 저장돼요. 그래서 어떤 경우에는 값의 타입이 256비트보다 작을 때 남는 비트를 정리해야 해요.

Solidity 컴파일러는 남는 비트의 잠재적 쓰레기 값에 부정적 영향을 받을 수 있는 어떤 연산이든 그 전에 정리를 수행하도록 설계돼 있어요. 예를 들어 값을 메모리에 쓰기 전에는 남는 비트를 지워야 해요. 메모리 내용은 해시를 계산하는 데 쓰이거나 메시지 호출의 데이터로 보내질 수 있기 때문이죠. 마찬가지로 값을 스토리지에 저장하기 전에도 남는 비트를 정리해야 해요. 그렇지 않으면 잘못된(garbled) 값이 관찰될 수 있기 때문이에요.

인라인 어셈블리를 통한 접근은 그런 연산으로 간주되지 않는다는 점에 주의해요. 인라인 어셈블리를 사용해 256비트보다 짧은 Solidity 변수에 접근하면, 컴파일러는 그 값이 제대로 정리됐을 거라고 보장하지 않아요.

게다가 바로 다음 연산이 영향을 받지 않는 경우에는 비트를 정리하지 않아요. 예를 들어 0이 아닌 어떤 값도 JUMPI 명령에서 참으로 간주되므로, 불리언 값을 JUMPI의 조건으로 사용하기 전에는 정리하지 않아요.

위 설계 원칙에 더해, Solidity 컴파일러는 입력 데이터를 스택에 올릴 때도 정리해요.

다음 표는 서로 다른 타입에 적용되는 정리 규칙을 설명해요. 여기서 "높은 비트(higher bits)"란 타입이 256비트보다 작을 때 남는 비트를 가리켜요.

타입 유효한 값 유효하지 않은 값의 정리
멤버가 n개인 enum 0부터 n-1까지 예외를 던짐
bool 0 또는 1 1이 됨
부호 있는 정수 부호 비트로 설정된 높은 비트 현재는 유효한 값으로 조용히 부호 확장(sign-extend)됨, 즉 모든 높은 비트가 부호 비트로 설정됨. 미래에는 예외를 던질 수 있음
부호 없는 정수 0으로 설정된 높은 비트 현재는 유효한 값으로 조용히 마스킹됨, 즉 모든 높은 비트가 0으로 설정됨. 미래에는 예외를 던질 수 있음

유효한 값과 유효하지 않은 값은 타입의 크기에 따라 달라진다는 점에 주의해요. 부호 없는 8비트 타입인 uint8을 살펴볼게요. uint8은 다음과 같은 유효한 값들을 가져요:

0000...0000 0000 0000
0000...0000 0000 0001
0000...0000 0000 0010
....
0000...0000 1111 1111

유효하지 않은 값은 높은 비트가 0으로 설정됩니다:

0101...1101 0010 1010   invalid value
0000...0000 0010 1010   cleaned value

부호 있는 8비트 타입인 int8의 유효한 값은 다음과 같아요:

음수:

1111...1111 1111 1111
1111...1111 1111 1110
....
1111...1111 1000 0000

양수:

0000...0000 0000 0000
0000...0000 0000 0001
0000...0000 0000 0010
....
0000...0000 0111 1111

컴파일러는 음수면 1, 양수면 0인 부호 비트를 부호 확장해서 높은 비트를 덮어써요:

음수:

0010...1010 1111 1111   invalid value
1111...1111 1111 1111   cleaned value

양수:

1101...0101 0000 0100   invalid value
0000...0000 0000 0100   cleaned value

더 알아보기 (Learn more)