Solidity v0.7.0 Breaking Changes
Solidity v0.7.0 Breaking Changes
이 절은 Solidity 버전 0.7.0에서 도입된 주요 breaking change와, 그 변경의 이유, 그리고 영향을 받는 코드를 업데이트하는 방법을 강조해요. 전체 목록은 릴리스 changelog를 확인해요.
출처: 문서
본문
이 절은 Solidity 버전 0.7.0에서 도입된 주요 breaking change와 그 뒤의 이유, 그리고 영향을 받는 코드를 업데이트하는 방법을 강조해요. 전체 목록은 릴리스 changelog를 확인해요.
의미의 조용한 변경 (Silent Changes of the Semantics)
- 리터럴을 비-리터럴로 지수화하거나 시프트하는 것(예:
1 << x또는2 ** x)은 이제 항상uint256(음이 아닌 리터럴) 또는int256(음수 리터럴) 타입을 사용해 연산을 수행해요. 이전에는 시프트 양/지수의 타입으로 연산이 수행돼 오해의 소지가 있었어요.
문법 변경 (Changes to the Syntax)
- 외부 함수 및 컨트랙트 생성 호출에서 Ether와 가스는 이제 새 구문으로 지정돼요:
x.f{gas: 10000, value: 2 ether}(arg1, arg2). 옛 구문x.f.gas(10000).value(2 ether)(arg1, arg2)은 에러를 일으켜요. - 전역 변수
now는 이제 비권장이며, 그 자리에block.timestamp를 사용해야 해요. 단일 식별자now는 전역 변수로는 너무 일반적이고, 트랜잭션 처리 중에 바뀌는 것처럼 인상줄 수 있는 반면,block.timestamp는 블록의 속성일 뿐이라는 사실을 정확히 반영해요. - 변수의 NatSpec 주석은 public 상태 변수에만 허용되고, 로컬 또는 내부 변수에는 허용되지 않아요.
gwei토큰은 이제 키워드예요(예: 숫자2 gwei를 지정하는 데 사용) 그리고 식별자로 사용할 수 없어요.- 문자열 리터럴은 이제 인쇄 가능한 ASCII 문자만 포함할 수 있으며, 여기에는 16진수(
\xff)와 유니코드 이스케이프(\u20ac) 같은 다양한 이스케이프 시퀀스도 포함돼요. - 유효한 UTF-8 시퀀스를 수용하기 위해 유니코드 문자열 리터럴이 이제 지원돼요.
unicode접두사로 식별돼요:unicode"Hello 😃". - 상태 가변성(State Mutability): 함수의 상태 가변성은 이제 상속 중에 제한할 수 있어요. 기본 상태 가변성을 가진 함수는
pure와view함수로 오버라이드될 수 있고,view함수는pure함수로 오버라이드될 수 있어요. 동시에 public 상태 변수는view로 간주되고, 상수라면pure로도 간주돼요.
인라인 어셈블리 (Inline Assembly)
- 인라인 어셈블리에서 사용자 정의 함수와 변수 이름에
.을 허용하지 않아요. Solidity를 Yul-only 모드로 사용하면 여전히 유효해요. - 스토리지 포인터 변수
x의 슬롯과 오프셋은x_slot과x_offset대신x.slot과x.offset으로 접근해요.
사용하지 않거나 안전하지 않은 기능의 제거 (Removal of Unused or Unsafe Features)
스토리지 밖의 매핑 (Mappings outside Storage)
- 구조체나 배열이 매핑을 포함하면 스토리지에서만 사용할 수 있어요. 이전에는 매핑 멤버가 메모리에서 조용히 건너뛰어져 혼란스럽고 오류가 나기 쉬웠어요.
- 매핑을 포함하는 구조체나 배열에 대한 스토리지에서의 할당은 동작하지 않아요. 이전에는 복사 연산 중 매핑이 조용히 건너뛰어져 오해의 소지가 있고 오류가 나기 쉬웠어요.
함수와 이벤트 (Functions and Events)
- 생성자에는 더 이상 가시성(
public/internal)이 필요하지 않아요. 컨트랙트가 생성되는 것을 막으려면abstract로 표시할 수 있어요. 이로써 생성자의 가시성 개념은 쓸모없어졌어요. - 타입 검사기(Type Checker): 라이브러리 함수에
virtual을 허용하지 않아요. 라이브러리는 상속될 수 없으므로 라이브러리 함수는virtual이면 안 돼요. - 같은 상속 계층에서 같은 이름과 파라미터 타입을 가진 여러 이벤트를 허용하지 않아요.
using A for B는 그것이 언급된 컨트랙트에만 영향을 줘요. 이전에는 그 효과가 상속됐어요. 이제는 그 기능을 사용하는 모든 파생 컨트랙트에서using문을 반복해야 해요.
표현식 (Expressions)
- 부호 있는 타입으로 시프트하는 것을 허용하지 않아요. 이전에는 음수 양으로 시프트하는 것이 허용됐지만 런타임에 revert했어요.
finney와szabo단위가 제거됐어요. 그것들은 거의 사용되지 않고 실제 금액을 쉽게 보이게 하지 못해요. 대신1e20같은 명시적 값이나 매우 흔한gwei를 사용할 수 있어요.
선언 (Declarations)
var키워드를 더 이상 사용할 수 없어요. 이전에는 이 키워드가 파싱되지만 타입 에러와 사용할 타입에 대한 제안을 내놓았어요. 이제는 파서 에러를 일으켜요.
인터페이스 변경 (Interface Changes)
- JSON AST: 16진 문자열 리터럴을
kind: "hexString"으로 표시해요. - JSON AST: 값이
null인 멤버를 JSON 출력에서 제거해요. - NatSpec: 생성자와 함수가 일관된 userdoc 출력을 가져요.
코드를 업데이트하는 방법 (How to update your code)
이 절은 각 breaking change에 대해 이전 코드를 업데이트하는 방법을 상세히 설명해요.
x.f.value(...)()를x.f{value: ...}()로 바꿔요. 마찬가지로(new C).value(...)()를new C{value: ...}()로,x.f.gas(...).value(...)()를x.f{gas: ..., value: ...}()로 바꿔요.now를block.timestamp로 바꿔요.- 시프트 연산자에서 오른쪽 피연산자의 타입을 부호 없는 타입으로 바꿔요. 예를 들어
x >> (256 - y)를x >> uint(256 - y)로 바꿔요. - 필요하면 모든 파생 컨트랙트에서
using A for B문을 반복해요. - 모든 생성자에서
public키워드를 제거해요. - 모든 생성자에서
internal키워드를 제거하고 컨트랙트에abstract를 추가해요(아직 없다면). - 인라인 어셈블리에서
_slot과_offset접미사를 각각.slot과.offset으로 바꿔요.