결론부터 얘기하면 서도 다른 체인, 즉 이더리움 네트워크와 클레이튼 네트워크에 동일한 계약주소로 계약을 배포할 수 있습니다.
계약주소를 생성할 때 기본적으로 사용되는 CREATE opcode
는 아래와 같은 식으로 2개의 인자값으로 계약 주소를 생성합니다.
keccak256(rlp([sender, nonce])) [12:]
Nonce
값CREATE opcode
로 지갑 주소를 생성할 때는 nonce
값은 Transaction
이 생성할 때 1씩 증가하기 때문에 계약주소가 계속 다르게 나옵니다.
EIP-1014( 이더리움 개선 제안 )에서 추가된 CREATE2 opcode
는 아래와 같은 식으로 4개의 인자값이 필요합니다.
keccak256( 0xff ++ address ++ salt ++ keccak256(init_code)[12:]
CREATE opcode
를 사용하여 생성된 주소와의 충돌을 방지하는 역할을 합니다.salt
값CREATE2 opcode
로 계약주소를 생성할 때는 nonce
를 사용하지 않고 0xff
, address
, salt
, init code
를 사용해서 계약주소를 생성합니다.
따라서 address
, salt
, init code
를 같은 값으로 각 네트워크에 배포를 하면 모두 동일한 계약주소값으로 배포할 수 있습니다.
하지만 CREATE2
를 이용해서 같은 계약주소를 두 번 이상 배포할 수는 없습니다.
CREATE
, CREATE2
로 생성된 컨트랙트는 nonce
가 1로 설정됩니다. 컨트랙트를 생성할 때 nonce
가 0인지 확인하고 0이 아닐경우 컨트랙트 배포를 되돌립니다.
컨트랙트를 배포할 때 사용할 컨트랙트는 아래와 같습니다.
DeployWithCreate2
컨트랙트를 Create2Factory
컨트랙트를 사용하여 배포해보겠습니다.
Remix IDE
를 사용하여 컨트랙트를 배포할 컨트랙트인 Create2Factory
컨트랙트를 배포합니다.
배포한 컨트랙트의 getBytecode
를 이용하여 컨트랙트 배포에 사용예정인 Bytecode
를 구합니다.
구한 Bytecode
와 임의의 salt
값을 넣어 컨트랙트를 배포할 때 사용될 계약주소를 확인합니다.
배포될 계약 주소는 다음과 같습니다 0x8b915AB430Ca70456596B2bfE7382e6Fe611D1Be
아직 컨트랙트를 배포하지 않았으니 해당 계약주소를 검색하여 확인합니다.
이제 사용한 salt
값으로 컨트랙트를 배포하고 확인해봅시다.
계약주소앞에 Address
부분이 Contract
로 변경되며 계약주소로 변경된것을 확인할 수 있습니다.
CREATE2
를 사용하여 컨트랙트를 배포했을때는 Contract
를 배포할 수 있는 부모 컨트랙트를 가지고 자식 컨트랙트를 배포하는 방식이었습니다.
이런 방법으로 다른 네트워크에 컨트랙트를 배포하려고 한다면 여러분은 각 네트워크마다 다른 컨트랙트 값이 나올 것 입니다.
CREATE2
를 사용하여 컨트랙트를 배포하기 전 우리는 컨트랙트를 배포할 컨트랙트, 즉 부모 컨트랙트를 먼저 배포 후, 자식 컨트랙트를 배포하는것이죠.
하지만 CREATE2
는 위에서 봤듯이 계약주소를 생성하는데 아래와 같은 식을 사용합니다.
keccak256( 0xff ++ address ++ salt ++ keccak256(init_code)[12:]
여기서 address
가 배포 주소입니다.
예를 들어, 이더리움 네트워크에 부모 컨트랙트를 배포하고 폴리곤 네트워크에 부모 컨트랙트를 배포한다고 했을 때, 두 부모 컨트랙트의 주소값이 다르기 때문에 같은 bytecode
와 salt
값으로 컨트랙트를 배포한다고 해도 전혀 다른값이 나오는 것 입니다.
그렇다면 여러분들이 알게모르게 자주 사용하셨을 CREATE1
로 다른 네트워크로 배포를 해봅시다.
CREATE1
은 아래와 같은 방법으로 계약주소를 생성합니다.
keccak256(rlp([sender, nonce])) [12:]
여기서 nonce
는 해당 배포 지값의 nonce
값 이라고 설명을 드렸었는데, 그렇다면 모든 네트워크에서 Transaction
을 보내지 않은 새로운 지갑으로 계약을 배포한다면 해당 지갑은 모든 네트워크에 nonce
가 0일테니 모든 네트워크의 계약주소가 동일하게 나오지 않을까요?
테스트하기 위해서는 우선 새로운 지갑이 필요합니다.
메타마스크에서 아주 간단하게 새로운 지갑을 생성할 수 있으니, 생성해보도록 하겠습니다.
계정 생성을 클릭하시고 지갑 이름을 설정해주시면 바로 지갑이 생성된 것을 확인하실 수 있습니다.
지갑까지 생성했다면, 아래 주소에서 컨트랙트를 배포할 때 사용할 goerli ETH
와 Baobab Klay
를 받아놓읍시다.
자 이렇게 배포할 지갑 세팅은 완료했고, 배포할 간단한 컨트랙트를 준비합니다.
컨트랙트를 작성했다면 Remix IDE
를 통해 배포를 해보도록 하겠습니다.
Goerli testnet
먼저 아래와 같이 배포하였습니다.
배포된 계약주소는 다음과 같습니다. 0xBaAB8337376b24342117458F635fC017DcB927D7
다음으로 Klaytn testnet
에 아래와 같이 배포하였습니다.
배포된 계약주소를 확인해보면 0xBaAB8337376b24342117458F635fC017DcB927D7
로 Goerli testnet
에 배포된 계약주소와 같은것을 확인하실 수 있습니다.
이렇게 다른 네트워크라 하더라도 CREATE1
으로 계약 배포 지갑 주소와 nonce
만 일치하다면 동일한 계약주소가 생성되는것을 확인해보았습니다.