• Maurelian's avatar
    Pass additional information across domains via token gateways (#824) · e29fab10
    Maurelian authored
    * feat(contracts): add from and data args to L1ERC20Gateway
    
    fix(integration): add gasLimit to fundUser
    
    refactor(contracts): add data to gateway events
    add changeset
    
    fix(integration): provide data in outboundTransfer
    
    refactor(contracts): reset Abs_L2TokenGateway to Abs_L2DepositedToken
    
    refactor(contracts): fix mismatched names
    
    * feat[contracts]: add custom gas arg to gateway
    
    fix(contracts): take max of user vs. default gas
    
    * fix(integrations): update ovm-eth function call
    
    * fix(integration): remove unecessary explicit gasLimit
    
    * test(contracts): 32kb transfer, 9MM gas
    
    * fix(contracts): fixup comment, bytes arg last
    
    * fix(integration): args order in integrations
    
    * fix(contracts): remove unused L2 gas arg
    
    * fix(contracts): limit data that can be passed to L2
    
    * fix(integration): better tests for data length
    
    * test: check for error on too large data
    
    * Experimental: specify gaslimit in before hook
    
    * fix(integration): add l2 gas argument
    
    * fix: increase gas on fundUser
    
    * fix(contracts): remove duplicate max size limit
    
    * fix(integration): fine tune gas amounts
    
    * lint
    
    * fix: large data test
    
    * fix(integration): set gas closer to real cost
    
    * fix(contracts): remove unused bridge variables
    These variables were the default gas amounts for cross domain messages
    
    * fix(contracts): Reorder args
    
    Place dynamic length args last
    
    * fix(integration): update estimateGas values
    
    * fix(integration): reset eth withdraw estimate to 21000
    
    * fix(integration): update expected gas amount
    
    * fix(integration): reduce gas amount for ETH withdraw
    e29fab10
utils.ts 3.33 KB
import { Direction, waitForXDomainTransaction } from './watcher-utils'

import {
  getContractFactory,
  getContractInterface,
  predeploys,
} from '@eth-optimism/contracts'
import { remove0x, Watcher } from '@eth-optimism/core-utils'
import {
  Contract,
  Wallet,
  constants,
  providers,
  BigNumberish,
  BigNumber,
  utils,
} from 'ethers'
import { cleanEnv, str, num } from 'envalid'

export const GWEI = BigNumber.from(1e9)

const env = cleanEnv(process.env, {
  L1_URL: str({ default: 'http://localhost:9545' }),
  L2_URL: str({ default: 'http://localhost:8545' }),
  VERIFIER_URL: str({ default: 'http://localhost:8547' }),
  L1_POLLING_INTERVAL: num({ default: 10 }),
  L2_POLLING_INTERVAL: num({ default: 10 }),
  VERIFIER_POLLING_INTERVAL: num({ default: 10 }),
  PRIVATE_KEY: str({
    default:
      '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',
  }),
  ADDRESS_MANAGER: str({
    default: '0x5FbDB2315678afecb367f032d93F642f64180aa3',
  }),
})

// The hardhat instance
export const l1Provider = new providers.JsonRpcProvider(env.L1_URL)
l1Provider.pollingInterval = env.L1_POLLING_INTERVAL

export const l2Provider = new providers.JsonRpcProvider(env.L2_URL)
l2Provider.pollingInterval = env.L2_POLLING_INTERVAL

export const verifierProvider = new providers.JsonRpcProvider(env.VERIFIER_URL)
verifierProvider.pollingInterval = env.VERIFIER_POLLING_INTERVAL

// The sequencer private key which is funded on L1
export const l1Wallet = new Wallet(env.PRIVATE_KEY, l1Provider)

// A random private key which should always be funded with deposits from L1 -> L2
// if it's using non-0 gas price
export const l2Wallet = l1Wallet.connect(l2Provider)

// Predeploys
export const PROXY_SEQUENCER_ENTRYPOINT_ADDRESS =
  '0x4200000000000000000000000000000000000004'
export const OVM_ETH_ADDRESS = predeploys.OVM_ETH

export const getAddressManager = (provider: any) => {
  return getContractFactory('Lib_AddressManager')
    .connect(provider)
    .attach(env.ADDRESS_MANAGER)
}

// Gets the gateway using the proxy if available
export const getGateway = async (wallet: Wallet, AddressManager: Contract) => {
  const l1GatewayInterface = getContractInterface('OVM_L1ETHGateway')
  const ProxyGatewayAddress = await AddressManager.getAddress(
    'Proxy__OVM_L1ETHGateway'
  )
  const addressToUse =
    ProxyGatewayAddress !== constants.AddressZero
      ? ProxyGatewayAddress
      : await AddressManager.getAddress('OVM_L1ETHGateway')

  const OVM_L1ETHGateway = new Contract(
    addressToUse,
    l1GatewayInterface,
    wallet
  )

  return OVM_L1ETHGateway
}

export const getOvmEth = (wallet: Wallet) => {
  const OVM_ETH = new Contract(
    OVM_ETH_ADDRESS,
    getContractInterface('OVM_ETH'),
    wallet
  )

  return OVM_ETH
}

export const fundUser = async (
  watcher: Watcher,
  gateway: Contract,
  amount: BigNumberish,
  recipient?: string
) => {
  const value = BigNumber.from(amount)
  const tx = recipient
    ? gateway.depositTo(recipient, 1_000_000, '0xFFFF', { value })
    : gateway.deposit(1_000_000, '0xFFFF', { value })

  await waitForXDomainTransaction(watcher, tx, Direction.L1ToL2)
}

export const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms))

const abiCoder = new utils.AbiCoder()
export const encodeSolidityRevertMessage = (_reason: string): string => {
  return '0x08c379a0' + remove0x(abiCoder.encode(['string'], [_reason]))
}