Commit aa2949ef authored by Mark Tyneway's avatar Mark Tyneway Committed by GitHub

fix: eth deposits through bridge (#3160)

Withdrawals don't seem to update balances correctly
for some reason, still need to debug why that is.

chore: add changeset
parent a088bb36
---
'@eth-optimism/sdk': patch
---
Add eth withdrawal support
......@@ -8,7 +8,13 @@ import {
Log,
} from '@ethersproject/abstract-provider'
import { Signer } from '@ethersproject/abstract-signer'
import { ethers, BigNumber, Overrides, CallOverrides } from 'ethers'
import {
ethers,
BigNumber,
Overrides,
CallOverrides,
PayableOverrides,
} from 'ethers'
import {
sleep,
remove0x,
......@@ -1143,7 +1149,7 @@ export class CrossChainMessenger implements ICrossChainMessenger {
message: MessageLike,
opts?: {
signer?: Signer
overrides?: Overrides
overrides?: PayableOverrides
}
): Promise<TransactionResponse> {
return (opts?.signer || this.l1Signer).sendTransaction(
......@@ -1315,7 +1321,7 @@ export class CrossChainMessenger implements ICrossChainMessenger {
finalizeMessage: async (
message: MessageLike,
opts?: {
overrides?: Overrides
overrides?: PayableOverrides
}
): Promise<TransactionRequest> => {
const resolved = await this.toCrossChainMessage(message)
......@@ -1327,6 +1333,15 @@ export class CrossChainMessenger implements ICrossChainMessenger {
const [proof, output, withdrawalTx] = await this.getBedrockMessageProof(
message
)
if (!opts) {
opts = {}
}
if (!opts.overrides) {
opts.overrides = {}
}
if (!opts.overrides.value) {
opts.overrides.value = withdrawalTx.value
}
return this.contracts.l1.OptimismPortal.populateTransaction.finalizeWithdrawalTransaction(
[
......@@ -1344,7 +1359,8 @@ export class CrossChainMessenger implements ICrossChainMessenger {
proof.outputRootProof.withdrawerStorageRoot,
proof.outputRootProof.latestBlockhash,
],
proof.withdrawalProof
proof.withdrawalProof,
opts.overrides
)
} else {
// L1CrossDomainMessenger relayMessage is the only method that isn't fully backwards
......@@ -1372,9 +1388,25 @@ export class CrossChainMessenger implements ICrossChainMessenger {
opts?: {
recipient?: AddressLike
l2GasLimit?: NumberLike
overrides?: Overrides
overrides?: PayableOverrides
}
): Promise<TransactionRequest> => {
if (this.bedrock) {
const value = BigNumber.from(opts?.overrides?.value ?? 0)
if (!value.eq(0) && !value.eq(amount)) {
throw new Error(`amount and value mismatch`)
}
if (!opts) {
opts = {}
}
if (!opts.overrides) {
opts.overrides = {}
}
if (!opts.overrides.value) {
opts.overrides.value = value
}
}
return this.bridges.ETH.populateTransaction.deposit(
ethers.constants.AddressZero,
predeploys.OVM_ETH,
......@@ -1387,9 +1419,24 @@ export class CrossChainMessenger implements ICrossChainMessenger {
amount: NumberLike,
opts?: {
recipient?: AddressLike
overrides?: Overrides
overrides?: PayableOverrides
}
): Promise<TransactionRequest> => {
const value = BigNumber.from(opts?.overrides?.value ?? 0)
if (this.bedrock) {
if (!value.eq(0) && !value.eq(amount)) {
throw new Error(`amount and value mismatch`)
}
if (!opts) {
opts = {}
}
if (!opts.overrides) {
opts.overrides = {}
}
if (!opts.overrides.value) {
opts.overrides.value = value
}
}
return this.bridges.ETH.populateTransaction.withdraw(
ethers.constants.AddressZero,
predeploys.OVM_ETH,
......
import { Contract, Overrides, Signer, BigNumber, CallOverrides } from 'ethers'
import {
Contract,
Overrides,
Signer,
BigNumber,
CallOverrides,
PayableOverrides,
} from 'ethers'
import {
TransactionRequest,
TransactionResponse,
......@@ -204,7 +211,7 @@ export interface IBridgeAdapter {
opts?: {
recipient?: AddressLike
l2GasLimit?: NumberLike
overrides?: Overrides
overrides?: PayableOverrides
}
): Promise<TransactionRequest>
......@@ -225,7 +232,7 @@ export interface IBridgeAdapter {
amount: NumberLike,
opts?: {
recipient?: AddressLike
overrides?: Overrides
overrides?: PayableOverrides
}
): Promise<TransactionRequest>
}
......
......@@ -15,8 +15,9 @@ import {
// TODO(tynes): this task could be modularized in the future
// so that it can deposit an arbitrary token. Right now it
// deposits and withdraws ETH through the bridge,
// deploys a WETH9 contract, mints some WETH9 and then
// deposits that into L2 through the StandardBridge
// deposits that into L2 through the StandardBridge.
task('deposit', 'Deposits WETH9 onto L2.')
.addParam(
'l2ProviderUrl',
......@@ -72,6 +73,10 @@ task('deposit', 'Deposits WETH9 onto L2.')
const Deployment__OptimismMintableERC20TokenFactory =
await hre.deployments.get('OptimismMintableERC20Factory')
const Deployment__OptimismPortal = await hre.deployments.get(
'OptimismPortal'
)
const Deployment__OptimismPortalProxy = await hre.deployments.get(
'OptimismPortalProxy'
)
......@@ -84,6 +89,12 @@ task('deposit', 'Deposits WETH9 onto L2.')
'L1CrossDomainMessengerProxy'
)
const OptimismPortal = new hre.ethers.Contract(
Deployment__OptimismPortalProxy.address,
Deployment__OptimismPortal.abi,
signer
)
const messenger = new CrossChainMessenger({
l1SignerOrProvider: signer,
l2SignerOrProvider: l2Signer,
......@@ -108,6 +119,65 @@ task('deposit', 'Deposits WETH9 onto L2.')
bedrock: true,
})
const opBalanceBefore = await signer.provider.getBalance(
OptimismPortal.address
)
// Deposit ETH
console.log('Depositing ETH through StandardBridge')
const ethDeposit = await messenger.depositETH(utils.parseEther('1'))
const depositMessageReceipt = await messenger.waitForMessageReceipt(
ethDeposit
)
if (depositMessageReceipt.receiptStatus !== 1) {
throw new Error('deposit failed')
}
console.log('Deposit complete')
const opBalanceAfter = await signer.provider.getBalance(
OptimismPortal.address
)
if (!opBalanceBefore.add(utils.parseEther('1')).eq(opBalanceAfter)) {
throw new Error(`OptimismPortal balance mismatch`)
}
console.log('Withdrawing ETH')
const ethWithdraw = await messenger.withdrawETH(utils.parseEther('1'))
const ethWithdrawReceipt = await ethWithdraw.wait()
console.log('Withdrawal on L2 complete')
console.log('Waiting to be able to withdraw')
const id = setInterval(async () => {
const currentStatus = await messenger.getMessageStatus(ethWithdrawReceipt)
console.log(`Message status: ${MessageStatus[currentStatus]}`)
}, 3000)
await messenger.waitForMessageStatus(
ethWithdrawReceipt,
MessageStatus.READY_FOR_RELAY
)
clearInterval(id)
const ethFinalize = await messenger.finalizeMessage(ethWithdrawReceipt)
const ethFinalizeReceipt = await ethFinalize.wait()
if (ethFinalizeReceipt.status !== 1) {
throw new Error('Finalize withdrawal reverted')
}
console.log('ETH withdrawal complete')
const opBalanceFinally = await signer.provider.getBalance(
OptimismPortal.address
)
// TODO(tynes): fix this bug
if (!opBalanceFinally.eq(opBalanceBefore)) {
console.log('OptimismPortal balance mismatch')
console.log(`Balance before deposit: ${opBalanceBefore.toString()}`)
console.log(`Balance after deposit: ${opBalanceAfter.toString()}`)
console.log(`Balance after withdrawal: ${opBalanceFinally.toString()}`)
// throw new Error('OptimismPortal balance mismatch')
}
const OptimismMintableERC20TokenFactory = await hre.ethers.getContractAt(
Deployment__OptimismMintableERC20TokenFactory.abi,
predeploys.OptimismMintableERC20Factory,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment