반응형
Solidity를 사용하면서 겪었던 스토리지 충돌 관련 이슈 정리
Proxy - delegateCall()호출 시, 스토리지 충돌 문제
- 컨트랙의 변경을 위해(Smart Contract는 원칙상 변경이 불가하다) Proxy를 만들 수 있는 방법을 찾다가 delegateCall() 발견
- 데이터 로직을 담당하는 컨트랙(A)에서 데이터 저장소를 담당하는 컨트랙(B)에 접근할 때 delegateCall() 사용
- 이슈 발생
- delegateCall()은 현재 컨트랙의 컨텍스트에서 사용하고자 하는 컨트랙의 함수에 접근하여 사용 가능 (msg.sender가 동일하기 때문에 프록시로 사용하기 유용하다)
- 문제는 Solidity에서 Storage 변수를 다룰 때, Slot이라는 저장소에 변수를 선언 된 순서대로 저장하게 되는데,
- 다음과 같이 A 컨트랙과 B 컨트랙의 변수가 선언되어 있으면서 A가 B의 함수를 호출하는 동시에 B의 변수에 접근할 때 문제가 된다.
- 각 컨트랙에서 두 변수의 Slot순서가 같은 경우가 문제가 발생하는 이유는 A에서 delegateCall()을 통해 호출한 B의 함수는 A의 컨텍스트를 갖고 있기 때문에 A의 Slot에 접근하게 된다.
- 따라서 위 사진처럼 Implemetation의 함수에서 _owner로 명시적으로 접근할지라도, 실질적으로 호출되는 부분은 Slot[0]이기 때문에 Proxy의 Slot[0]이 호출되게 된다.
- 여기서 스토리지 충돌이 발생하게 되었다.
이미 ERC-1967에 Bug Fix 된 사항이었다.
- https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies
- 처음 Solidity를 회사에 도입하면서 사내에 solidity에 대한 지식이 전무한 상태였기 때문에 openzeppelin도 모르는 상태에서 개발을 진행했었다.
- 역시 개발쪽은 직접 부딪혀가며 일 해야 는다고 했던가!
결론
- 요즘 라이브러리나 프레임워크가 너무 잘 설계되어있어서 무지성으로 쓰는 일이 많았다.
- "아, 이거 라이브러리로 있는데", 물론 급박한 개발 기한에서 라이브러리 검증 없이 사용할 수도 있지만,
- 가끔 이렇게 무언가를 검증해가면서 기존에 존재하는 라이브러리를 보면 조금 더 의미있게 사용할 수 있게 될듯하다.
반응형
LIST
'언어 > Solidity' 카테고리의 다른 글
Solidity + Web3j + Ganache를 통한 Smart Contract 배포 (1) | 2023.10.14 |
---|---|
Solidity Gas Cost (0) | 2023.09.26 |