블록체인

솔리디티 바이트코드

Snag 2022. 1. 22. 18:49

솔리디티로 작성한 스마트 컨트랙트 코드는 결국 바이트코드로 컴파일되어 트랜잭션 형태로 이더리움 네트워크에 전달된다. Geth와 같은 이더리움 노드들은 이 트랜잭션을 해석하여 대상주소 (To address)가 스마트 컨트랙트일 경우 함수를 실행한다.

다음과 같이 Storage 컨트랙트를 작성하고 Deploy를 했을때 바이트코드가 어떻게 생성되는지 확인해 보겠다.

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

/**
 * @title Storage
 * @dev Store & retrieve value in a variable
 */
contract Storage {

    uint256 number;

    /**
     * @dev Store value in variable
     * @param num value to store
     */
    function store(uint256 num) public {
        number = num;
    }

    /**
     * @dev Return value 
     * @return value of 'number'
     */
    function retrieve() public view returns (uint256){
        return number;
    }
}

이더리움 테스트 네트워크인 Ropsten으로 배포를 하면 아래와 같은 트랜잭션을 얻을 수 있다.

https://ropsten.etherscan.io/tx/0x3f33260d3ce92fe273c0ad7f1ef53c15df34fb4c1d56c41ec3dd064f22affcb6

여기서 Input Data를 살펴보면 아래와 같다. (임의로 줄바꿈)

0x608060405234801561001057600080fd5b50610150806100206000396000f3fe6080604052348015610010576
00080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080
fd5b610043610075565b60405161005091906100d9565b60405180910390f35b610073600480360381019061006
e919061009d565b61007e565b005b60008054905090565b8060008190555050565b600081359050610097816101
03565b92915050565b6000602082840312156100b3576100b26100fe565b5b60006100c184828501610088565b9
1505092915050565b6100d3816100f4565b82525050565b60006020820190506100ee60008301846100ca565b92
915050565b6000819050919050565b600080fd5b61010c816100f4565b811461011757600080fd5b5056fea2646
970667358221220404e37f487a89a932dca5e77faaf6ca2de3b991f93d230604b1b8daaef64766264736f6c6343
0008070033

 

이 바이트코드는 어셈블리 OPCODE를 16진수로 매핑한 것이다. Storage 컨트랙트를 어셈블리어로 먼저 바꾸면 다음과 같다. FULL 코드는 이더스캔을 참고한다. https://ropsten.etherscan.io/address/0xdce8e031f262e8ce8dea62db38bdba5fda8b4ff4#code

PUSH1 0x80
PUSH1 0x40
MSTORE
CALLVALUE
DUP1
ISZERO
//
// ..중략..
//
PUSH24 0xfaaf6ca2de3b991f93d230604b1b8daaef64766264736f6c
PUSH4 0x43000807
STOP
CALLER

어셈블리 코드는 일대일로 16진수와 매핑되는데, 이더리움 문서를 참고하면 PUSH1과 MSTORE가 각각 0x60과 0x52에 매핑되는 것을 확인할 수 있다. https://www.ethervm.io/#opcodes

코드 니모닉 스택 입력 스택 출력 표현식 노트
52 MSTORE offset, value   memory[offset:offset+32] = value 값을 메모리에 저장
60 PUSH1   uint8 PUSH(uint8) 1바이트 값을 스택에 넣는다

어셈블리 코드의 처음 세줄을 바이트 코드로 변환하면 이렇게 된다.

어셈블리 PUSH1, 0x80, PUSH1, 0x40, MSTORE
바이트코드 60 80 60 40 52

모든 스마트 컨트랙트는 바이트코드가 "6080604052"로 시작한다. 이 코드는 스택에 80과 40을 넣고 MSTORE를 실행하기 때문에 40이 먼저 스택에서 POP 되어, 결국 MSTORE 40, 80 이 실행된다. 즉 0x40 메모리 위치에 0x80을 기록한다. 

이더리움은 메모리에서 데이터를 읽을 때 0x40 위치의 32바이트 값을 포인터로 사용한다. 그러므로, 모든 스마트 컨트랙트는 0x40 위치에 0x80을 기록하므로, 메모리 시작 위치는 0x80이라는 얘기가 된다.

이상으로 컴파일된 스마트 컨트랙트의 바이트코드에 대해서 알아봤다.

참고

'블록체인' 카테고리의 다른 글

알케미(Alchemy)  (0) 2022.02.11
DeFi 의 높은 이자는 어디서 나올까?  (0) 2022.02.10
Uniswap v2 핵심원리  (0) 2022.01.22
테라 백서 한글번역  (0) 2022.01.18
이더리움 도메인 하나 등록하는데, 27만원!?  (0) 2021.03.30