본문 바로가기
Hack/Cryptocurrency

Contract Application Binary Interface (ABI)

by Becoming a Hacker 2023. 7. 1.
반응형

Contract Application Binary Interface (ABI)란

Solidity 환경에서의 ABI는 블록체인 외부 환경과 Smart Contract 또는 Smart Contract 간에 상호 작용하는 표준 방법을 의미 합니다.

 

이러한 상호 작용을 위해서는 ABI 포맷으로 Encoding 하거나, Encoding된 ABI를 Decoding 할 수 있어야 합니다. 실제 Encoding된 ABI Data를 통하여 이러한 방식을 알아보도록 하겠습니다.

※ 이번 포스팅에서는 비표준 방식의 ABI Encoding은 다루지 않을 계획입니다!

 

ABI Encode

  • ABI Encoding된 데이터는 아래와 같은 포맷을 가지게 됨
    • 정적 타입 - 일반 타입, <type>[M]와 같이 배열 크기가 고정된 경우
      • 4Byte : Method에 대한 Signature
      • 32Byte : 첫 번째 인자의 값
    • 동적 타입 - bytes, string, <type>[]와 같이 배열 크기가 선언되지 않은 경우
      • 4Byte : Method에 대한 Signature
      • 32Byte : 첫 번째 인자에 대한 Offset (해당 Block 기준)
      • 32Byte : 첫 번째 인자의 배열 크기 X
      • 32Byte ~ : 첫 번째 인자에 대한 배열 요소 (X번 반복)

※ Contract Creation Code 안에 있는 Constructor Arguments는 Method Type에 해당하는 4Byte 값이 포함되어 있지 않음

 

샘플 코드

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;

contract Foo {
    function bar(bytes3[2] memory) public pure {}
    function baz(uint32 x, bool y) public pure returns (bool r) { r = x > 32 || y; }
    function sam(bytes memory, bool, uint[] memory) public pure {}
}
  • Foo 샘플 코드에서 baz(69,true) 호출 시 ABI Encoding 과정
    • 0xcdcd77c00000000000000000000000000000000000000000000000000000000000000045000000000000000
      0000000000000000000000000000000000000000000000001 (68Byte)
      • 0xcdcd77c0 (4Byte)
        • baz(uint32,bool) Method에 대한 Signature 값
      • 0x0000000000000000000000000000000000000000000000000000000000000045 (32Byte)
        • 첫 번째 인자 값 : 0x45 (69)
      • 0x0000000000000000000000000000000000000000000000000000000000000001 (32Byte)
        • 두 번째 인자 값 : 0x1 (true)
    • 이에 대한 Return Type은 false로 output은 아래와 같이 구성됨
      • 0x0000000000000000000000000000000000000000000000000000000000000000 (32Byte)
        • Return : 0x0 (false)

 

  • Foo 샘플 코드에서 bar(["abc","def") 호출 시 ABI Encoding 과정
    • 0xfce353f661626300000000000000000000000000000000000000000000000000000000006465660000000000
      000000000000000000000000000000000000000000000000 (68Byte)
      • 0xfce353f6 (4Byte)
        • bar(bytes3[2]) Method에 대한 Signature 값
      • 0x6162630000000000000000000000000000000000000000000000000000000000 (32Byte)
        • 첫 번째 인자 값 : 0x616263 (abc)
      • 0x6465660000000000000000000000000000000000000000000000000000000000 (32Byte)
        • 두 번째 인자 값 : 0x646566 (def)

 

  • Foo 샘플 코드에서 sam("dave",true,[1,2,3]) 호출 시 ABI Encoding 과정
    • 0xa5643bf200000000000000000000000000000000000000000000000000000000000000600000000000000000
      00000000000000000000000000000000000000000000000100000000000000000000000000000000000000000
      000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464
      61766500000000000000000000000000000000000000000000000000000000000000000000000000000000000
      00000000000000000000000000000000000030000000000000000000000000000000000000000000000000000
      00000000000100000000000000000000000000000000000000000000000000000000000000020000000000000
      000000000000000000000000000000000000000000000000003 (292Byte)
      • 0xa5643bf2 (4Byte)
        • sam(bytes,bool,uint256[]) Method에 대한 Signature 값
        • uint 형식의 경우 표준 형식인 uint256으로 변경됨
      • 0x0000000000000000000000000000000000000000000000000000000000000060 (32Byte)
        • 동적 타입의 첫 번째 인자 Offset을 나타내며, Magic Signature 이후 Block 위치를 기준으로 Byte 단위로 측정됨
        • 이 경우에는 0x60으로 측정
      • 0x0000000000000000000000000000000000000000000000000000000000000001 (32Byte)
        • 두 번째 인자 값 : 0x1 (true)
      • 0x00000000000000000000000000000000000000000000000000000000000000a0 (32Byte)
        • 동적 타입의 세 번째 인자 Offset을 나타내며, 이 경우 0xa0으로 측정
      • 0x0000000000000000000000000000000000000000000000000000000000000004 (32Byte)
        • 첫 번째 인자 데이터의 배열 길이를 나타내며, 이경우 0x4로 측정
      • 0x6461766500000000000000000000000000000000000000000000000000000000 (32Byte)
        • 첫 번째 인자 값 : 0x64617665 (dave)
      • 0x0000000000000000000000000000000000000000000000000000000000000003 (32Byte)
        • 세 번째 인자 데이터의 배열 길이를 나타내며, 이 경우 0x3으로 측정
      • 0x0000000000000000000000000000000000000000000000000000000000000001 (32Byte)
        • 세 번째 인자 첫 번재 요소 값 : 0x1
      • 0x0000000000000000000000000000000000000000000000000000000000000002 (32Byte)
        • 세 번째 인자 두 번재 요소 값 : 0x2
      • 0x0000000000000000000000000000000000000000000000000000000000000003 (32Byte)
        • 세 번째 인자 세 번재 요소 값 : 0x3

 

Reference

 

Contract ABI Specification — Solidity 0.8.21 documentation

Contract ABI Specification Edit on GitHub Contract ABI Specification Basic Design The Contract Application Binary Interface (ABI) is the standard way to interact with contracts in the Ethereum ecosystem, both from outside the blockchain and for contract-to

docs.soliditylang.org

 

댓글