Skip to content

Commit

Permalink
feat(sdk): add Bedrock support to SDK (#3086)
Browse files Browse the repository at this point in the history
* core-utils: add bedrock types

* sdk: implement bedrock functionality

* tests: update for bedrock

* sdk: add hardhat deposit task

* circleci: run deposit task in ci

* tsconfig: cleanup

* contracts-bedrock: make commitment interval larger

* changeset: add

Co-authored-by: Mark Tyneway <mark.tyneway@gmail.com>
  • Loading branch information
smartcontracts and tynes committed Aug 2, 2022
1 parent 28649d6 commit dac4a9f
Show file tree
Hide file tree
Showing 23 changed files with 890 additions and 287 deletions.
7 changes: 7 additions & 0 deletions .changeset/wise-ads-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@eth-optimism/sdk': minor
'@eth-optimism/contracts-bedrock': patch
'@eth-optimism/core-utils': patch
---

Updates the SDK to be compatible with Bedrock (via the "bedrock: true" constructor param). Updates the build pipeline for contracts-bedrock to export a properly formatted dist folder that matches our other packages.
4 changes: 4 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,10 @@ jobs:
--private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
--network devnetL1
working_directory: packages/contracts-bedrock
- run:
name: Deposit ERC20 through the bridge
command: npx hardhat deposit --network devnetL1
working_directory: packages/sdk
- run:
name: Check the status
command: npx hardhat check-op-node
Expand Down
2 changes: 1 addition & 1 deletion packages/contracts-bedrock/deploy-config/devnetL1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const l1GenesisTimestamp =
: Math.floor(Date.now() / 1000)

const config = {
submissionInterval: 6,
submissionInterval: 20,
genesisOutput: ethers.constants.HashZero,
historicalBlocks: 0,
l1StartingBlockTag: 'earliest',
Expand Down
29 changes: 29 additions & 0 deletions packages/core-utils/src/optimism/hashing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,42 @@ import {
big1,
} from './encoding'

/**
* Bedrock output oracle data.
*/
export interface BedrockOutputData {
outputRoot: string
l1Timestamp: number
l2BlockNumber: number
}

/**
* Bedrock state commitment
*/
export interface OutputRootProof {
version: string
stateRoot: string
withdrawerStorageRoot: string
latestBlockhash: string
}

/**
* Bedrock proof data required to finalize an L2 to L1 message.
*/
export interface BedrockCrossChainMessageProof {
outputRootProof: OutputRootProof
withdrawalProof: string
}

/**
* Parameters that govern the L2OutputOracle.
*/
export type L2OutputOracleParameters = {
submissionInterval: number
startingBlockNumber: number
l2BlockTime: number
}

/**
* Hahses a cross domain message.
*
Expand Down
22 changes: 22 additions & 0 deletions packages/sdk/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import { HardhatUserConfig } from 'hardhat/types'

import '@nomiclabs/hardhat-ethers'
import '@nomiclabs/hardhat-waffle'
import 'hardhat-deploy'

import './tasks/deposit'

const config: HardhatUserConfig = {
solidity: {
Expand All @@ -10,6 +13,25 @@ const config: HardhatUserConfig = {
paths: {
sources: './test/contracts',
},
networks: {
devnetL1: {
url: 'http://localhost:8545',
accounts: [
'ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',
],
},
},
external: {
contracts: [
{
artifacts: '../contracts-bedrock/artifacts',
},
],
deployments: {
devnetL1: ['../contracts-bedrock/deployments/devnetL1'],
goerli: ['../contracts-bedrock/deployments/goerli'],
},
},
}

export default config
2 changes: 2 additions & 0 deletions packages/sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,15 @@
"ethereum-waffle": "^3.4.0",
"ethers": "^5.6.8",
"hardhat": "^2.9.6",
"hardhat-deploy": "^0.11.4",
"nyc": "^15.1.0",
"typedoc": "^0.22.13",
"mocha": "^10.0.0"
},
"dependencies": {
"@eth-optimism/contracts": "0.5.31",
"@eth-optimism/core-utils": "0.9.2",
"@eth-optimism/contracts-bedrock": "0.5.2",
"lodash": "^4.17.21",
"merkletreejs": "^0.2.27",
"rlp": "^2.2.7"
Expand Down
34 changes: 20 additions & 14 deletions packages/sdk/src/adapters/eth-bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ export class ETHBridgeAdapter extends StandardBridgeAdapter {
.map((event) => {
return {
direction: MessageDirection.L1_TO_L2,
from: event.args._from,
to: event.args._to,
from: event.args.from,
to: event.args.to,
l1Token: ethers.constants.AddressZero,
l2Token: predeploys.OVM_ETH,
amount: event.args._amount,
data: event.args._data,
amount: event.args.amount,
data: event.args.extraData,
logIndex: event.logIndex,
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
Expand Down Expand Up @@ -76,19 +76,19 @@ export class ETHBridgeAdapter extends StandardBridgeAdapter {
.filter((event) => {
// Only find ETH withdrawals.
return (
hexStringEquals(event.args._l1Token, ethers.constants.AddressZero) &&
hexStringEquals(event.args._l2Token, predeploys.OVM_ETH)
hexStringEquals(event.args.l1Token, ethers.constants.AddressZero) &&
hexStringEquals(event.args.l2Token, predeploys.OVM_ETH)
)
})
.map((event) => {
return {
direction: MessageDirection.L2_TO_L1,
from: event.args._from,
to: event.args._to,
l1Token: event.args._l1Token,
l2Token: event.args._l2Token,
amount: event.args._amount,
data: event.args._data,
from: event.args.from,
to: event.args.to,
l1Token: event.args.l1Token,
l2Token: event.args.l2Token,
amount: event.args.amount,
data: event.args.extraData,
logIndex: event.logIndex,
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
Expand Down Expand Up @@ -178,7 +178,10 @@ export class ETHBridgeAdapter extends StandardBridgeAdapter {
amount,
0, // L1 gas not required.
'0x', // No data.
opts?.overrides || {}
{
...omit(opts?.overrides || {}, 'value'),
value: this.messenger.bedrock ? amount : 0,
}
)
} else {
return this.l2Bridge.populateTransaction.withdrawTo(
Expand All @@ -187,7 +190,10 @@ export class ETHBridgeAdapter extends StandardBridgeAdapter {
amount,
0, // L1 gas not required.
'0x', // No data.
opts?.overrides || {}
{
...omit(opts?.overrides || {}, 'value'),
value: this.messenger.bedrock ? amount : 0,
}
)
}
},
Expand Down
45 changes: 23 additions & 22 deletions packages/sdk/src/adapters/standard-bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import {
TransactionResponse,
BlockTag,
} from '@ethersproject/abstract-provider'
import { getContractInterface, predeploys } from '@eth-optimism/contracts'
import { predeploys } from '@eth-optimism/contracts'
import { getContractInterface } from '@eth-optimism/contracts-bedrock'
import { hexStringEquals } from '@eth-optimism/core-utils'

import {
Expand Down Expand Up @@ -54,7 +55,7 @@ export class StandardBridgeAdapter implements IBridgeAdapter {
)
this.l2Bridge = new Contract(
toAddress(opts.l2Bridge),
getContractInterface('IL2ERC20Bridge'),
getContractInterface('L2StandardBridge'),
this.messenger.l2Provider
)
}
Expand Down Expand Up @@ -82,19 +83,19 @@ export class StandardBridgeAdapter implements IBridgeAdapter {
// adapter. Bridges that are not the ETH bridge should not be able to handle or even
// present ETH deposits or withdrawals.
return (
!hexStringEquals(event.args._l1Token, ethers.constants.AddressZero) &&
!hexStringEquals(event.args._l2Token, predeploys.OVM_ETH)
!hexStringEquals(event.args.l1Token, ethers.constants.AddressZero) &&
!hexStringEquals(event.args.l2Token, predeploys.OVM_ETH)
)
})
.map((event) => {
return {
direction: MessageDirection.L1_TO_L2,
from: event.args._from,
to: event.args._to,
l1Token: event.args._l1Token,
l2Token: event.args._l2Token,
amount: event.args._amount,
data: event.args._data,
from: event.args.from,
to: event.args.to,
l1Token: event.args.l1Token,
l2Token: event.args.l2Token,
amount: event.args.amount,
data: event.args.extraData,
logIndex: event.logIndex,
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
Expand Down Expand Up @@ -125,19 +126,19 @@ export class StandardBridgeAdapter implements IBridgeAdapter {
// adapter. Bridges that are not the ETH bridge should not be able to handle or even
// present ETH deposits or withdrawals.
return (
!hexStringEquals(event.args._l1Token, ethers.constants.AddressZero) &&
!hexStringEquals(event.args._l2Token, predeploys.OVM_ETH)
!hexStringEquals(event.args.l1Token, ethers.constants.AddressZero) &&
!hexStringEquals(event.args.l2Token, predeploys.OVM_ETH)
)
})
.map((event) => {
return {
direction: MessageDirection.L2_TO_L1,
from: event.args._from,
to: event.args._to,
l1Token: event.args._l1Token,
l2Token: event.args._l2Token,
amount: event.args._amount,
data: event.args._data,
from: event.args.from,
to: event.args.to,
l1Token: event.args.l1Token,
l2Token: event.args.l2Token,
amount: event.args.amount,
data: event.args.extraData,
logIndex: event.logIndex,
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
Expand All @@ -156,10 +157,9 @@ export class StandardBridgeAdapter implements IBridgeAdapter {
try {
const contract = new Contract(
toAddress(l2Token),
getContractInterface('L2StandardERC20'),
getContractInterface('OptimismMintableERC20'),
this.messenger.l2Provider
)

// Don't support ETH deposits or withdrawals via this bridge.
if (
hexStringEquals(toAddress(l1Token), ethers.constants.AddressZero) ||
Expand All @@ -170,6 +170,7 @@ export class StandardBridgeAdapter implements IBridgeAdapter {

// Make sure the L1 token matches.
const remoteL1Token = await contract.l1Token()

if (!hexStringEquals(remoteL1Token, toAddress(l1Token))) {
return false
}
Expand Down Expand Up @@ -203,7 +204,7 @@ export class StandardBridgeAdapter implements IBridgeAdapter {

const token = new Contract(
toAddress(l1Token),
getContractInterface('L2StandardERC20'), // Any ERC20 will do
getContractInterface('OptimismMintableERC20'), // Any ERC20 will do
this.messenger.l1Provider
)

Expand Down Expand Up @@ -270,7 +271,7 @@ export class StandardBridgeAdapter implements IBridgeAdapter {

const token = new Contract(
toAddress(l1Token),
getContractInterface('L2StandardERC20'), // Any ERC20 will do
getContractInterface('OptimismMintableERC20'), // Any ERC20 will do
this.messenger.l1Provider
)

Expand Down

0 comments on commit dac4a9f

Please sign in to comment.