옵티미즘 ERC721 배포 & 테스트
해당 문서는 토카막 옵티미스틱 롤업에 ERC721 컨트랙트를 배포하는 과정을 담고 있으며 우분투 16.04에서 수행 되었다. 토카막 옵티미즘 테스트넷은 링키비를 사용한다.
배포해야 하는 컨트랙트는 레이어1에서 두개(L1_ERC721, L1_ERC721Gateway), 레이어2에서 한개(L2_ERC721)해서 총 3개이며 L1_ERC721과 같은 경우는 기존에 배포되어 있는 ERC721 컨트랙트가 있다면 기존 컨트랙트를 사용해도 된다.
롤업에서는 web3.js 대신 ethers.js를, truffle 대신 hardhat을 사용하고 있다. ethers.js와 hardhat 등은 web3와 truffle 등과 비교했을 때 여러 장점들이 있어 최근 많은 스마트 컨트랙트 프로젝트에서 사용하고 있다.
컨트랙트와 서비스 설정
소스코드 다운로드 및 패키지 설치
아래 명령어를 이용해 소스코드를 복제하고 패키지들을 설치한 후 컨트랙트를 컴파일한다.
$ git clone https://github.com/Onther-Tech/l1-l2-deposit-withdrawal.git
$ cd l1-l2-deposit-withdrawal && yarn && yarn compile
패키지 설치를 마치면 다음 단계를 진행하면 된다.
const ethers = require('ethers')
const { Watcher } = require('@eth-optimism/watcher')
const { getContractFactory } = require('@eth-optimism/contracts')
// Set up some contract factories. You can ignore this stuff. 
const factory = (name, ovm = false) => {
  const artifact = require(`./artifacts${ovm ? '-ovm' : ''}/contracts/${name}.sol/${name}.json`)
  return new ethers.ContractFactory(artifact.abi, artifact.bytecode)
}   
const factory__L1_ERC721 = factory('ERC721')
const factory__L2_ERC721 = factory('L2DepositedERC721', true)
const factory__L1_ERC721Gateway = getContractFactory('OVM_L1ERC721Gateway')
async function main() {
  // Set up our RPC provider connections.
  const l1RpcProvider = new ethers.providers.JsonRpcProvider('<rinkeby rpc address>')
  const l2RpcProvider = new ethers.providers.JsonRpcProvider('https://testnet1.optimism.tokamak.network')
  // Set up our wallets (using a default private key with 10k ETH allocated to it).
  // Need two wallets objects, one for interacting with L1 and one for interacting with L2.
  // Both will use the same private key.
  const key = '<private key>'
  const l1Wallet = new ethers.Wallet(key, l1RpcProvider)
  const l2Wallet = new ethers.Wallet(key, l2RpcProvider)
  // L1 messenger address depends on the deployment, this is default for our testnet1
  const l1MessengerAddress = '0xaFD9bB316D38aBB0400a53963A9324AB26eda97C' 
  // L2 messenger address is always the same.
  const l2MessengerAddress = '0x47210000000000000000000000000000000000007'
l1RpcProvider에는 링키비 rpc주소를 입력하면되며, 컨트랙트 배포에 사용할 계정의 개인키를 key에 입력하면 된다. 해당 계정에는 링키비용 이더가 있어야 한다.
그 다음 아래 코드를 통해 컨트랙트를 배포하면 된다. 배포되는 컨트랙트는 각 레이어에 배포되는 ERC721 컨트랙트(L1_ERC721, L2_ERC721)와 해당 ERC721의 레이어 간 이동을 지원하는 L1_ERC721Gateway 컨트랙트이다.
 // Deploy an ERC721 token on L1.
  console.log('Deploying L1 ERC721...')
  const L1_ERC721 = await factory__L1_ERC721.connect(l1Wallet).deploy(
    1234, //initialSupply
    'L1 ERC721', //name
  )
  await L1_ERC721.deployTransaction.wait()
  // Deploy the paired ERC721 token to L2.
  console.log('Deploying L2 ERC721...')
  const L2_ERC721 = await factory__L2_ERC721.connect(l2Wallet).deploy(
    l2MessengerAddress,
    'L2 ERC721', //name
    {
      gasPrice: 0
    }
  )
  await L2_ERC721.deployTransaction.wait()
  // Create a gateway that connects the two contracts.
  console.log('Deploying L1 ERC721 Gateway...')
  const L1_ERC721Gateway = await factory__L1_ERC721Gateway.connect(l1Wallet).deploy(
    L1_ERC721.address,
    L2_ERC721.address,
    l1MessengerAddress
  )
  await L1_ERC721Gateway.deployTransaction.wait()
  // Make the L2 ERC721 aware of the gateway contract.
  console.log('Initializing L2 ERC721...')
  const tx0 = await L2_ERC721.init(
    L1_ERC721Gateway.address,
    {
      gasPrice: 0
    }
  )
  await tx0.wait()
배포가 정상적으로 종료되면 아래와 같은 결과를 확인할 수 있다.
Deploying L1 ERC721...
Deploying L2 ERC721...
Deploying L1 ERC721 Gateway...
Initializing L2 ERC721...
