이더리움 이스탄불 하드포크에 대하여

이스탄불 하드포크 이후, 스마트 컨트랙트 개발자가 유의해야 할 점

KALOS Security
HAECHI AUDIT
14 min readDec 9, 2019

--

Intro

12월 8일 (한국 기준), 이더리움 네트워크에는 ‘이스탄불 업데이트(Istanbul Update)’로 알려진 이더리움 이스탄불 하드포크가 완료되었습니다.

이번 하드포크 이후 EVM(이더리움 가상 머신)에 생기는 변화로 인해 기존 스마트 컨트랙트들의 일부 기능이 작동을 멈추게 됩니다.

따라서 이번 글에서는 해당 이슈에 대해 자세히 알아보고, 이번 이스탄불 하드포크로 인해 스마트 컨트랙트 개발자들이 새롭게 숙지해야 하는 올바른 스마트 컨트랙트 작성 방법에 대해 소개합니다.

이스탄불 하드포크

이스탄불 하드포크는 완벽한 Ethereum 2.0으로의 전환 이전에 성능 및 UX(User experience) 개선을 위한 Ethereum 1.x 업데이트 중 하나 입니다. 추후에 예정되어 있는 Berlin/London 하드포크 또한, Ethereum 1.x에 해당하는 업데이트라고 할 수 있습니다.

이스탄불 하드포크는 Etheruem 1.x에서 이루고자 하는 큰 기능을 수행 할 수 있도록 하는 데에 초석이 되는 다음 EIP(Ethereum Improvement Proposal)들로 구성되어 있습니다.

  • EIP-152: Add Blake2 compression function F precompile
  • EIP-1108: Reduce alt_bn128 precompile gas costs
  • EIP-1344: Add ChainID opcode
  • EIP-1884: Repricing for trie-size-dependent opcodes
  • EIP-2028: Calldata gas cost reduction
  • EIP-2200: Rebalance net-metered SSTORE gas cost with consideration of SLOAD gas cost change

이번 글에서는 위에 언급한 EIP 중에서도 ‘스마트 컨트랙트 작성시 유의해야 할 점’을 포함하고 있는 EIP1884에 대해 알아보도록 하겠습니다.

EIP1884 제안 배경

EVM 상에는 여러가지 OPCODE가 존재합니다. OPCODE를 실행하기 위해서는 일정 수준의 컴퓨터 자원이 소모되는데, 각각의 OPCODE들이 실행될 때 소모되는 컴퓨터 자원이 다르기 때문에 각기 다른 가스 비용(gas cost)이 산정되어있습니다. 이 때 만약 OPCODE의 가스 비용이 실제 소모하는 컴퓨터 자원을 제대로 반영하지 못한다면, DoS 공격이 발생할 수 있습니다. 그뿐만 아니라, 저평가된 OPCODE가 많이 들어있는 블록은 동일한 가스 사용량을 가진 다른 블록에 비해 연산이 오래 걸리게 되어 block gas limit이 왜곡될 수 있습니다.

EVM에서 사용되는 OPCODE들 중 State를 조회하는 OPCODE들이 존재합니다. 이런 OPCODE들은 이더리움의 State-trie의 크기가 커지면 커질 수록 State 조회하는 데 필요한 연산 시간이 늘어나게 됩니다. 최근 이더리움에 저장되는 데이터 양이 증가하면서 State-trie의 크기가 증가하였고, 자연스럽게 해당 OPCODE의 연산 시간이 증가하였습니다.

이러한 현상에 해당되는 OPCODE들은 다음과 같습니다.

  • SLOAD
  • BALANCE
  • EXTCODEHASH

그 중에서 가장 대표적인 SLOAD를 실행할 때 gas당 소모되는 연산 시간의 그래프를 살펴보겠습니다.

https://eips.ethereum.org/EIPS/eip-1884

위 그래프에서 이동평균 그래프를 확인해보면(검정색) 단위 gas당 연산 시간이 23ms에서 145ms 부근까지 증가한 것을 확인할 수 있습니다.

따라서 EIP1884에서는 1. 이렇듯 저평가된 OPCODE들의 가스 비용을 늘리고, 2. 특정 상황에서 더 적은 컴퓨터 자원을 소모하면서 State 조회를 할 수 있는 새로운 OPCODE를 추가하였습니다.

EIP1884 제안 상세 내용

  • SLOAD의 가스 비용이 200에서 800으로 증가
  • BALANCE의 가스 비용이 400에서 700으로 증가
  • EXTCODEHASH의 가스 비용이 400에서 700으로 증가
  • 5 gas 를 소모하는 SELFBALANCE OPCODE 추가

EIP1884 의 나비효과

이런 변화로 인해, 기존에 배포된 스마트 컨트랙트들 중 일부 기능이 더이상 기능이 작동하지 않는 경우가 있습니다. 대표적으로 Kyber Network, Gods Unchained, Aragon이 있습니다. 각 프로젝트에서 배포한 Solidity 코드에 대해서 살펴보고, 이번 EIP1884의 변화로 각 프로젝트 팀들은 어떻게 대응했는지에 대해서 자세히 설명하겠습니다.

각 팀들이 제작한 Solidity 코드를 자세히 살펴보기 앞서, 예제에 대한 이해를 돕기 위해 Solidity 코드에 대한 배경지식을 알아보도록 하겠습니다.

  1. <address>.transfer() 와 <address>.send()는 2,300 gas 만을 forwarding합니다.
    <address>.transfer()/<address>.send()는 스마트 컨트랙트에서 ether를 전송할 때 자주 쓰입니다. 만약 이 함수가 실행중에 남은 가스량을 전부 전달하면 Reentrancy 위험에 노출될 수 있습니다. 따라서 해당 함수는 트랜잭션을 생성할 때 실행 중 남은 가스량 중 2,300 gas만을 전달하고 2,300 gas를 넘는 연산이 있는 경우 tx 전체가 취소됩니다.
  2. fallback 함수는 이더리움을 받는 경우 혹은 호출하는 함수가 선언되어 있지 않은 경우에 자동으로 실행됩니다.
    스마트 컨트랙트에 fallback 함수가 payable로 선언되어있는 경우, 해당 스마트 컨트랙트로 이더리움을 보내면 이 fallback 함수가 자동으로 실행됩니다. 또한 스마트 컨트랙트에 트랜잭션이 발생됐지만, 해당 트랜잭션에서 실행하고자 하는 함수가 존재하지 않는 경우에도 fallback함수가 실행됩니다.
  3. 스마트 컨트랙트 간에 ether를 전송할 때, 주로 <address>.transfer()를 사용합니다. 이 경우, ether를 받는 쪽 스마트 컨트랙트의 fallback 함수가 payable로 선언되어 있다면, fallback 함수가 자동으로 실행됩니다.

위에서 설명 드린 바를 종합하면, <address>.transfer()함수로 fallback이 실행되는 경우, 해당 fallback에서 실행할 수 있는 가스의 총량은 2,300 gas로 고정됩니다.

EVM과 Solidity 에서 다른 개발 환경에서는 볼 수 없었던 이런 특수성을 가지고 있기 때문에, fallback 함수에 많은 연산 과정을 넣은 경우 EIP1884이전에도 정상적으로 동작 하지 않는 경우가 있었습니다.

하지만, EIP1884에서는 작동하던 fallback함수들이 동작하지 않게 되는 경우들이 있었습니다. 앞서 말씀 드렸던 Kyber, Gods Unchained, Aragon의 코드들이 기존에는 정상 작동하다가 EIP 1884 이후 작동하지 않게 되는 예시입니다. 자세히 보여드리도록 하겠습니다.

Kyber Network의 예시

Kyber Network의 컨트랙트는 다음과 같이 fallback 함수가 작성되어 있었습니다. 이 함수는 Ether를 다른 토큰과 교환할 때 Ether를 받아들이는 함수로 작동합니다.

[As-Is]

해당 함수는 Kyber Reserve 스마트 컨트랙트가 ether를 <address>.transfer()로 전송해주면서 실행되는 구조입니다.(sample TX) 해당 fallback 함수는 transfer()로 2,300 gas를 forwarding 받은 경우 약 300 gas 가량이 남는 구조였습니다.

변경 전 KyberNetwork 컨트랙트의 fallback 함수

[Issue]

하지만 2번째 줄 require구문 에서 SLOAD를 실행하게 됩니다. 이스탄불 하드포크 이후 600 gas 가 더 소모되므로, 하드포크 이후에는 2,300 gas 안에서 fallback 함수를 실행할 수 없게 되었습니다. 실제로 Kyber의 개발자는 EIP1884를 논의 하는 페이지에서 해당 이슈에 대해 설명하기도 했습니다.

[To-Be]

EIP1884가 업데이트 되면서, Kyber 팀은 falll back 함수에서 저장된 데이터를 읽지 않도록 수정하고 해당 함수가 담긴 스마트 컨트랙트를 재배포 하는 것으로 대응하였습니다.

변경 후 KyberNetwork 컨트랙트의 fallback 함수

Gods Unchained의 예시

Gods Unchained의 Capped Vault 컨트랙트 역시 Kyber Network와 같은 이유로 EIP1884의 영향을 받는 스마트 컨트랙트 입니다.

[As-Is]

Capped Vault 컨트랙트는 현재 Gods Unchained의 Rare Pack Four라는 카드팩을 구매하는 스마트 컨트랙트에서 purchase()함수, 즉 구매를 실행 하는 경우에 Ether를 받아주는 컨트랙트로 작용합니다.

따라서 해당 fallback함수가 작동하지 않는 경우, 구매를 할 수 없는 상황이 발생 됩니다.

Fallback 함수는 다음과 같이 작성되어 있습니다.

변경 전 GodsUnchainedCappedVault 컨트랙트의 fallback 함수

[Issue]

require 구문을 살펴보면, total() 함수에서 SLOAD, BALANCE를 한번씩, limit 변수값을 불러오면서 SLOAD를 한번 호출하기 때문에, 기존보다 1500(600 + 300 + 600)만큼의 추가적인 gas 지출이 있습니다. 따라서 기존에는 2,300 gas 중에 1,342 gas가 남았지만, 더이상 2,300 gas로 실행할 수 없는 함수가 된 것입니다.

Aragon의 예시

마지막으로 Aragon의 DepositableDelegateProxy가 있습니다.

해당 스마트 컨트랙트는 aragon 조직마다 한개씩 배포되며, 해당 스마트 컨트랙트로 들어오는 대부분의 함수 호출을 impletmentation이라는 스마트 컨트랙트로 포워딩 하는 역할을 합니다.

이때, Aragon은 fallback함수를 2가지 경우에 대해 분리하여 작성해두었습니다.

  1. transfer/send로 자산이 들어오는경우
  2. 그 외의 경우

코드는 다음과 같습니다.

변경 전 DepositableDelegateProxy 컨트랙트 fallback 함수

[As-Is]

이 때, transfer/send 로 전송되었으면 (1)의 경우에 해당하므로 if문에 해당하는 10~12줄을 실행하게 됩니다. 이스탄불 하드포크가 일어나기 전에는 1,759 gas 를 소비하여 문제가 없었습니다.

[Issue]

하지만, 이스탄불 하드포크 이후에는 isDepositable()함수에서 SLOAD연산을 실행하기 때문에 600 gas 가 증가할 예정으로 총 2,359 gas를 소비하게 됩니다.

[To-Be]

해당 이슈에 대해서 Aragon 에서는 토론을 거쳐 최종적으로 SLOAD를 사용하지만, 사용하는 gas 양을 최적화 하는 assembly 코드를 작성하였습니다.

이스탄불 하드포크 이후 올바른 스마트 컨트랙트 작성방법

위 3가지 예시를 통해 이스탄불 하드포크 이후, 몇몇 스마트 컨트랙트들이 fallback 함수에서 작동을 멈출 수 있다는 것을 확인할 수 있었습니다. EVM의 업데이트가 Istanbul로 멈추지 않고 추후에도 계속 될 것이라는 점, 그리고 이더리움의 State trie 크기가 꾸준히 증가 할 것이라는 점을 고려했을 때, SLOAD 뿐만 아니라 다른 OPCODE들도 gas cost가 증가할 가능성이 있을 것으로 보입니다.

De-fi나 DEX(Decentralized EXchange)등의 프로토콜처럼 다른 컨트랙트와 상호작용하는 스마트 컨트랙트들이 점점 더 많아지고 있기 때문에, 스마트 컨트랙트를 새로 배포하는 입장에서 EIP1884와 같은 변화에 대응하기 위해선, fallback 함수 작성시에 gas cost의 소모가 적은 방식으로 작성 하는 것이 필수적이라고 할 수 있겠습니다.

따라서 가장 안전한 스마트 컨트랙트 개발 방법은 fallback 함수에서 SLOAD와 같은 gas cost가 증가할 가능성이 높은 OPCODE를 실행시키지 않는 것입니다.

물론 스마트 컨트랙트를 개발하는 사람들이 <address>.transfer() 혹은 <address>.send() 함수를 사용하지 않고, 다른 방식으로 gas를 한정시켜 트랜잭션을 발생 시키는 것이 좋겠습니다. 다만, 저 함수들은 이미 보편화된 개발 방법이므로 이러한 함수를 사용하는 것을 막기보다는 이에 대응할 수 있도록 안전한 스마트 컨트랙트를 작성하는 것이 중요하겠습니다.

결론

이번 글을 통해서 이스탄불 하드포크가 진행됨에 따라 EVM에 생기는 변화가 기존 스마트 컨트랙트에 미치게 될 영향에 대해 알아보았습니다. 특히 EIP1884에 대해 자세히 살펴보며 향후 개발자들이 스마트 컨트랙트 작성 시에 유의해야할 점에 대해서 알 수 있었습니다. 실제로 Kyber Network, Gods Unchained, Aragon은 기존에 작성한 스마트 컨트랙트 중 일부의 기능이 더이상 작동하지 않는 것을 확인할 수 있었습니다.

이스탄불 하드포크 이후 스마트 컨트랙트를 새로 배포하는 경우에는 1) fallback 함수 작성시 gas cost의 소모가 적은 방식으로 작성 하는 것이 필수적이라는 점, 그리고 2) fallback 함수에서 SLOAD와 같이 추후 gas cost가 증가할 가능성이 높은 OPCODE를 실행 시키지 않는 것이 안전하다는 점을 기억해두시면 좋을 것 같습니다.

또한, Kyber Network의 경우에는 Ether를 전송하는 대상 컨트랙트를 변경 가능하도록 제작함으로써 EIP1884에 대응하였습니다. 다만, Kyber Network처럼 변경 가능한 컨트랙트를 제작하는 것보다 더욱 원론적인 대응 방법은 gas cost에 의존적인 로직을 설계하지 않는 것이라는 점을 말씀드리며 글을 마무리하도록 하겠습니다.

HAECHI AUDIT은 이스탄불 하드포크 이후에도 안전한 스마트 컨트랙트 보안감사 및 개발 서비스를 제공합니다. 언제든지 audit@haechi.io으로 문의주시면, 담당자 확인 후 빠르게 답변드리도록 하겠습니다.

감사합니다.

[About Us]

HAECHI AUDIT은 글로벌 블록체인 업계를 선도하는 스마트 컨트랙트 보안 감사 및 개발 전문 기업입니다.

다년간 블록체인 기술 연구 개발 경험을 보유하고 있는 전문가들로 구성되어 있으며, 가장 신뢰할 수 있는 스마트 컨트랙트 보안 감사 및 개발 서비스를 제공합니다.

대표적인 포트폴리오로는 SK텔레콤, Kakao 블록체인 자회사인 Ground X, Carry 프로토콜 등이 있으며, 약 50여 곳 이상의 글로벌 프로젝트들을 대상으로 보안 감사를 진행한 경험을 보유하고 있습니다.

또한, 우수한 기술력을 인정받아 삼성전자, 서울시, KB금융그룹, 신한은행, 한화그룹 등의 지원을 받고 있으며, 이더리움 재단으로부터 개발 장려금을 수여한 바 있습니다.

스마트 컨트랙트 보안감사 및 개발 서비스 문의 : audit@haechi.io
공식 웹사이트 : https://audit.haechi.io/

--

--

KALOS Security
HAECHI AUDIT

Making Web3 Space Safe For Everyone | Pioneering a safer space since 2018