블록체인 Block-Chain - 서로 다른 네트워크간 동일한 Contract Address로 배포하기 ( CREATE1, CREATE2 )

dev_swan·2022년 12월 13일
1

블록체인

목록 보기
34/36
post-thumbnail

서로 다른 체인간 계약 주소가 동일할 수 있을까?

결론부터 얘기하면 서도 다른 체인, 즉 이더리움 네트워크와 클레이튼 네트워크에 동일한 계약주소로 계약을 배포할 수 있습니다.

계약주소를 생성할 때 기본적으로 사용되는 CREATE opcode는 아래와 같은 식으로 2개의 인자값으로 계약 주소를 생성합니다.

keccak256(rlp([sender, nonce])) [12:]

  • sender = 배포 지갑 주소
  • nonce = 해당 배포 지갑 주소의 Nonce

CREATE opcode로 지갑 주소를 생성할 때는 nonce 값은 Transaction이 생성할 때 1씩 증가하기 때문에 계약주소가 계속 다르게 나옵니다.

EIP-1014( 이더리움 개선 제안 )에서 추가된 CREATE2 opcode는 아래와 같은 식으로 4개의 인자값이 필요합니다.

keccak256( 0xff ++ address ++ salt ++ keccak256(init_code)[12:]

  • 0xff = 고정값으로 생성된 주소가 기존의 CREATE opcode를 사용하여 생성된 주소와의 충돌을 방지하는 역할을 합니다.
  • address = 배포 지갑 주소
  • salt = 작성자가 제공한 임의의 salt
  • keccak256(init_code) = 배포중인 바이트코드의 해시

CREATE2 opcode로 계약주소를 생성할 때는 nonce를 사용하지 않고 0xff, address, salt, init code를 사용해서 계약주소를 생성합니다.

따라서 address, salt, init code를 같은 값으로 각 네트워크에 배포를 하면 모두 동일한 계약주소값으로 배포할 수 있습니다.

하지만 CREATE2를 이용해서 같은 계약주소를 두 번 이상 배포할 수는 없습니다.

CREATE, CREATE2로 생성된 컨트랙트는 nonce가 1로 설정됩니다. 컨트랙트를 생성할 때 nonce가 0인지 확인하고 0이 아닐경우 컨트랙트 배포를 되돌립니다.

CREATE2를 이용하여 컨트랙트 배포

CREATE2 Smart Contract

컨트랙트를 배포할 때 사용할 컨트랙트는 아래와 같습니다.
DeployWithCreate2 컨트랙트를 Create2Factory 컨트랙트를 사용하여 배포해보겠습니다.

Remix IDE

Remix IDE를 사용하여 컨트랙트를 배포할 컨트랙트인 Create2Factory 컨트랙트를 배포합니다.

배포한 컨트랙트의 getBytecode를 이용하여 컨트랙트 배포에 사용예정인 Bytecode를 구합니다.

구한 Bytecode와 임의의 salt값을 넣어 컨트랙트를 배포할 때 사용될 계약주소를 확인합니다.

배포될 계약 주소는 다음과 같습니다 0x8b915AB430Ca70456596B2bfE7382e6Fe611D1Be
아직 컨트랙트를 배포하지 않았으니 해당 계약주소를 검색하여 확인합니다.

이제 사용한 salt 값으로 컨트랙트를 배포하고 확인해봅시다.

계약주소앞에 Address부분이 Contract로 변경되며 계약주소로 변경된것을 확인할 수 있습니다.

CREATE1를 이용하여 컨트랙트 배포

CREATE2를 사용하여 컨트랙트를 배포했을때는 Contract를 배포할 수 있는 부모 컨트랙트를 가지고 자식 컨트랙트를 배포하는 방식이었습니다.

이런 방법으로 다른 네트워크에 컨트랙트를 배포하려고 한다면 여러분은 각 네트워크마다 다른 컨트랙트 값이 나올 것 입니다.

CREATE2를 사용하여 컨트랙트를 배포하기 전 우리는 컨트랙트를 배포할 컨트랙트, 즉 부모 컨트랙트를 먼저 배포 후, 자식 컨트랙트를 배포하는것이죠.

하지만 CREATE2는 위에서 봤듯이 계약주소를 생성하는데 아래와 같은 식을 사용합니다.

keccak256( 0xff ++ address ++ salt ++ keccak256(init_code)[12:]

여기서 address가 배포 주소입니다.
예를 들어, 이더리움 네트워크에 부모 컨트랙트를 배포하고 폴리곤 네트워크에 부모 컨트랙트를 배포한다고 했을 때, 두 부모 컨트랙트의 주소값이 다르기 때문에 같은 bytecodesalt 값으로 컨트랙트를 배포한다고 해도 전혀 다른값이 나오는 것 입니다.

그렇다면 여러분들이 알게모르게 자주 사용하셨을 CREATE1로 다른 네트워크로 배포를 해봅시다.
CREATE1은 아래와 같은 방법으로 계약주소를 생성합니다.

keccak256(rlp([sender, nonce])) [12:]

여기서 nonce는 해당 배포 지값의 nonce값 이라고 설명을 드렸었는데, 그렇다면 모든 네트워크에서 Transaction을 보내지 않은 새로운 지갑으로 계약을 배포한다면 해당 지갑은 모든 네트워크에 nonce가 0일테니 모든 네트워크의 계약주소가 동일하게 나오지 않을까요?

새로운 지갑 생성

테스트하기 위해서는 우선 새로운 지갑이 필요합니다.
메타마스크에서 아주 간단하게 새로운 지갑을 생성할 수 있으니, 생성해보도록 하겠습니다.

계정 생성을 클릭하시고 지갑 이름을 설정해주시면 바로 지갑이 생성된 것을 확인하실 수 있습니다.
지갑까지 생성했다면, 아래 주소에서 컨트랙트를 배포할 때 사용할 goerli ETHBaobab Klay를 받아놓읍시다.

Goerli ETH
Baobab KLAY

자 이렇게 배포할 지갑 세팅은 완료했고, 배포할 간단한 컨트랙트를 준비합니다.

Remix IDE

컨트랙트를 작성했다면 Remix IDE를 통해 배포를 해보도록 하겠습니다.

Goerli testnet 먼저 아래와 같이 배포하였습니다.
배포된 계약주소는 다음과 같습니다. 0xBaAB8337376b24342117458F635fC017DcB927D7

다음으로 Klaytn testnet에 아래와 같이 배포하였습니다.
배포된 계약주소를 확인해보면 0xBaAB8337376b24342117458F635fC017DcB927D7Goerli testnet에 배포된 계약주소와 같은것을 확인하실 수 있습니다.

이렇게 다른 네트워크라 하더라도 CREATE1으로 계약 배포 지갑 주소와 nonce만 일치하다면 동일한 계약주소가 생성되는것을 확인해보았습니다.

0개의 댓글