Ethereum Gas에 대한 이해

이홍석
TOMAK
Published in
9 min readJul 26, 2018

1. 요약

이더리움에서는 모든 트랜잭션에 대해 Gas가 사용된다. 자신이 원하는(허용 가능한) Gas내에서 트랜잭션을 처리하고 싶다면 Gas에 대해 잘 알아야하고 코드를 최적화 해야한다. Gas를 계산하는 방식과 코드를 최적화 하는 방법을 안다면 이더리움 위에서 하고싶은 작업을 높은 효율로 처리할 수 있다.

2. 필요한 배경지식

2.1. PoW

2.2. EVM

2.3. Smart Contract

3. 서론

이더리움에서 사용되는 모든 트랜잭션, 스마트 컨트랙트는 gas를 사용한다. gas는 이더리움의 수수료이고 송금을 할 때나 스마트 컨트랙트의 코드를 실행할 때 사용된다. 송금할 때에는 gas의 최대량과 각 가스당 가격을 적어서 보낸다. 이 수치를 늘리면 이더리움은 더 빨리 송금될 가능성이 높아진다.

스마트 컨트랙트를 작성할 때도 gas가 사용된다. 어떤 경우는 gas가 많이 소모되고 어떤 경우는 gas가 적게 소모된다. 같은 결과를 내는 코드임에도 불구하고 gas의 소모량이 다른 경우도 많다. 왜 이런일이 일어날까? 이에 대해서도 본문에서 알아보자.

4. 본론

이더리움에서 Gas는 이더리움 기반의 토큰은 아니고 일반적으로 이더리움 트랜잭션의 수수료라고 보면된다. 하지만 좀 더 깊게 들어가보자. Gas는 EVM에서 돌아가는 opcode마다 붙어있는 가중치라고 할 수 있다.

위의 그림은 이더리움 yellow paper에 나와있는 opcode표이다. 그림과 같이 각 opcode에는 Gas라는 값이 붙어있다. 각 opcode를 한번이라도 실행하려면 그에 해당하는 Gas가 필요하다는 의미이다.

이더리움에서 사용되는 모든 트랜잭션과 스마트 컨트랙트는 사실 EVM Level로 봤을 땐 모두 opcode로 이루어져있다. 그래서 송금을 하려고 할 때도 Gas가 소모되는 것이다.

Gas라는 용어를 사용하는 곳들 중 이더리움의 메시지의 헤더에는 Gas Limit, Gas Price라는 값이 들어있다.

위의 소스는 이더리움에서 사용하는 메시지의 헤더다. 보면 gasLimit과 gasPrice라는 항목이 보일 것이다. 이것은 무엇을 의미할까? 다음의 그림을 보며 이해해보자.

먼저 내가 차를 타고 목적지에 가기위해 총 10L의 기름이 필요할 것 같다고 생각해보자. 기름이 없어서 10L를 주요소에서 주유했다. 이때 유가는 1600원/L 였다고 해보자. 그럼 총 나는 16000원을 내야한다. 자 여기서 10L는 gaslimit(gas)을 의미하고 1600원/L가 gasprice (Gwei)를 의미한다. 따라서 내가 목적지에 도달하기까지 필요한 금액은 16000원이므로 이것이 tx fee가 된다.

그렇다면 gas는 정확히 말하자면 진짜 ether는 아니고 수수료의 단위라고 할 수 있다. 여기에 각 gas마다 가격을 붙이면 그것이 진짜 ether와 바꿀 수 있는 수수료가 되는 것이다. (참고로 1 Gwei는 10–9 Ether 이다)

그 다음은 스마트 컨트랙트에서의 Gas를 생각해보자. 다음과 같은 Solidity Code가 있다고 하자.

https://gist.github.com/Rinuys/11e1e2e93ae035fcd3becf774419af51

위와 같은 코드는 아래의 opcode들을 사용하고 gas를 소모한다.

처음에 transaction을 만들고 올리는 과정도 비싸지만 실행했을 때 코드에서 변환되는 opcode들도 gas를 많이 소모한다. 따라서 스마트 컨트랙트를 개발할 때엔 최대한 수수료를 적게 실행할 수 있도록 코드 최적화를 진행해야한다. 트랜잭션 비용은 거래 비용 + 실행 비용으로 나타낼 수 있다. 위 코드를 Remix를 통해 돌려보면 다음과 같다.

위 그림에서 transaction cost는 이 트랜잭션 비용이고 execution cost는 실행 비용이다. 따라서 거래 비용은 이 둘을 뺀 21464가 된다. 이것의 계산은 다음과 같다. 트랜잭션을 보낼 때 21000 gas가 소모되고 input의 non-zero 바이트와 zero 바이트의 가스값을 합산한 값이다. non-zero 바이트는 총 5바이트이고 zero 바이트는 31개다. 따라서 거래 비용은 다음과 같다.

21464 (거래 비용) = 21000 (트랜잭션 보냄) + 68 * 5 (non-zero) + 4 * 31 (zero)

실행비용은 계산이 매우 복잡하다. 왜냐하면 opcode가 짧은 소스에도 많이 생성되기 때문이다. 예로 위의 솔리디티 코드의 execution opcode는 다음과 같다.

GAS Instruction
3 000 PUSH1 60
3 002 PUSH1 40
3 004 MSTORE
3 005 PUSH1 04
2 007 CALLDATASIZE
3 008 LT
3 009 PUSH1 3f
10 011 JUMPI
3 012 PUSH1 00
3 014 CALLDATALOAD
3 015 PUSH29 0100000000000000000000000000000000000000000000000000000000
3 045 SWAP1
5 046 DIV
3 047 PUSH4 ffffffff
3 052 AND
3 053 DUP1
3 054 PUSH4 348218ec
3 059 EQ
3 060 PUSH1 44
10 062 JUMPI
1 068 JUMPDEST
2 069 CALLVALUE
3 070 ISZERO
3 071 PUSH1 4e
10 073 JUMPI
3 074 PUSH1 00
3 076 DUP1
1 078 JUMPDEST
3 079 PUSH1 62
3 081 PUSH1 04
3 083 DUP1
3 084 DUP1
3 085 CALLDATALOAD
3 086 SWAP1
3 087 PUSH1 20
3 089 ADD
3 090 SWAP1
3 091 SWAP2
3 092 SWAP1
2 093 POP
2 094 POP
3 095 PUSH1 64
8 097 JUMP
1 100 JUMPDEST
3 101 DUP1
3 102 PUSH1 00
3 104 DUP2
3 105 SWAP1
20000 106 SSTORE
2 107 POP
2 108 POP
8 109 JUMP
1 098 JUMPDEST
0 099 STOP

솔리디티 버전이 올라가면서 위와 달라질 수 있다. 그리고 명령어가 매우 많으므로 계산과정은 생략한다.

5. 분석

5.1. 송금시 적당한 수수료는?

트랜잭션의 gas가 너무 적으면 마이너는 이를 선택하지 않는다. 따라서 트랜잭션의 gas는 충분히 있어야 하고 gas limit을 다 사용하지 못해 남는 gas는 어차피 반환된다. 거래를 할 때에는 gas를 충분히 보내자. gas price도 적당히 높여야 한다. gas만 많이 보낸다고 거래가 빨라지지는 않는다. 마이너는 이 둘을 곱한 tx fee를 보고 선택하기 때문이다. 중요한 거래가 있을 경우 다음의 사이트를 이용하여 미리 계산해보도록 하자.

https://ethgasstation.info/

5.2. 컨트랙트 코드를 짤 때 당연히 생각해야할 수수료

본문에서 봤듯이 컨트랙트는 정말 gas를 많이 먹는다. 버튼 하나로 이더가 확확 빠져나간다면 누가 쓰겠는가.. 따라서 remix와 같은 툴을 이용하여 미리 계산을 해보도록 하자. 또 다음과 같은 경우도 있다. 코드에 의미가 없는 연산을 넣는 경우가 있다. 이것은 프로그래머가 실수를 했거나 조금 이상하게(?) 생각하여 벌어지는 일이다. 그 예로 다음과 같은 상황이 있을 수 있다.

위의 패턴 1에서는 두번째 if가 아무 의미도 없는 문장이 된다. 이미 5보다 큰 x가 첫번째 if를 거치는데 어떻게 제곱이 20보다 작겠는가. 코드 전체를 트랜잭션의 input으로 바꾸면 코드가 짧을수록 좋다. 패턴 2도 또한 아무 의미 없는 if 문이 끼어있다. 5보다 큰데 1보다 크다고 하면 포함관계에 따라 아무 의미 없는 코드가 된다. 따라서 우리는 이런 실수를 하지 않도록 하고 이를 잡아주는 툴도 있다. GASPER 라는 툴이고 컨트랙트 개발자면 꼭 사용해서 gas를 줄이도록 하자. (참고 : https://arxiv.org/pdf/1703.03994v1.pdf, 이 논문에는 다양한 패턴이 나와있으니 필요시 참고)

6. 결론

이더리움의 Gas는 없어서는 안될 아주 중요한 요소이다. solidity의 튜링 완전성을 보장하고 DoS의 공격도 방어할 수 있다. 또 마이너는 이를 처리하며 보상을 받는 구조에도 사용된다. 하지만 gas는 이더리움 네트워크를 사용하려는 마이너 이외의 사람들에겐 수수료와 같은 존재다. 이를 적절히 조절하여 자신이 원하는 작업을 효율적으로 처리하도록 하자.

7. Reference

--

--