Commit 092b0901 authored by Mark Tyneway's avatar Mark Tyneway

contracts-bedrock: fix deposit helpers

There is a solidity contract for computing the L2 tx hash
so that its easy for devs to compute it with an `eth_call`.
This makes it easy for users that do not have a custom library
written in their language to compute the L2 tx hash.

Also fix the typescript implementation of the deposit tx type
so that the correct tx hash is computed.
parent 28138a34
---
'@eth-optimism/contracts-bedrock': patch
---
Update to new L2 tx hash style for deposits
......@@ -105,7 +105,7 @@ library CrossDomainHashing {
raw[6] = Lib_RLPWriter.writeBytes(_data);
bytes memory encoded = Lib_RLPWriter.writeList(raw);
return abi.encodePacked(uint8(0x7e), encoded);
return abi.encodePacked(uint8(0x7e), uint8(0x0), encoded);
}
/**
......
......@@ -14,10 +14,10 @@ contract CrossDomainHashing_Test is CommonTest {
// TODO(tynes): turn this into differential fuzzing
// it is very easy to do so with the typescript
function test_l2TransactionHash() external {
bytes32 l1BlockHash = 0xd1a498e053451fc90bd8a597051a1039010c8e55e2659b940d3070b326e4f4c5;
uint256 logIndex = 0x0;
address from = address(0xDe3829A23DF1479438622a08a116E8Eb3f620BB5);
address to = address(0xB7e390864a90b7b923C9f9310C6F98aafE43F707);
bytes32 l1BlockHash = 0xd25df7858efc1778118fb133ac561b138845361626dfb976699c5287ed0f4959;
uint256 logIndex = 0x1;
address from = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266;
address to = 0xB79f76EF2c5F0286176833E7B2eEe103b1CC3244;
bool isCreate = false;
uint256 mint = 0xe043da617250000;
uint256 value = 0xde0b6b3a7640000;
......@@ -31,7 +31,7 @@ contract CrossDomainHashing_Test is CommonTest {
assertEq(
sourceHash,
0x77fc5994647d128a4d131d273a5e89e0306aac472494068a4f1fceab83dd0735
0xf923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc
);
bytes memory raw = CrossDomainHashing.L2Transaction(
......@@ -48,11 +48,11 @@ contract CrossDomainHashing_Test is CommonTest {
assertEq(
raw,
hex"7ef862a077fc5994647d128a4d131d273a5e89e0306aac472494068a4f1fceab83dd073594de3829a23df1479438622a08a116e8eb3f620bb594b7e390864a90b7b923c9f9310c6f98aafe43f707880e043da617250000880de0b6b3a7640000832dc6c080"
hex"7e00f862a0f923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc94f39fd6e51aad88f6f4ce6ab8827279cfffb9226694b79f76ef2c5f0286176833e7b2eee103b1cc3244880e043da617250000880de0b6b3a7640000832dc6c080"
);
bytes32 digest = CrossDomainHashing.L2TransactionHash(
l1BlockHash,
l1BlockHash,
logIndex,
from,
to,
......@@ -65,7 +65,7 @@ contract CrossDomainHashing_Test is CommonTest {
assertEq(
digest,
0xf5f97d03e8be48a4b20ed70c9d8b11f1c851bf949bf602b7580985705bb09077
0xf58e30138cb01330f6450b9a5e717a63840ad2e21f17340105b388ad3c668749
);
}
}
......@@ -49,7 +49,7 @@ interface DepositTxOpts {
sequenceNumber?: BigNumberish
}
interface DepostTxExtraOpts {
interface DepositTxExtraOpts {
domain?: SourceHashDomain
l1BlockHash?: string
logIndex?: BigNumberish
......@@ -57,7 +57,8 @@ interface DepostTxExtraOpts {
}
export class DepositTx {
public type = '0x7E'
public type = 0x7e
public version = 0x00
private _sourceHash?: string
public from: string
public to: string | null
......@@ -135,13 +136,21 @@ export class DepositTx {
this.data || '0x',
]
return ethers.utils.hexConcat([this.type, ethers.utils.RLP.encode(fields)])
return ethers.utils.hexConcat([
BigNumber.from(this.type).toHexString(),
BigNumber.from(this.version).toHexString(),
ethers.utils.RLP.encode(fields),
])
}
decode(raw: BytesLike, extra: DepostTxExtraOpts = {}) {
decode(raw: BytesLike, extra: DepositTxExtraOpts = {}) {
const payload = ethers.utils.arrayify(raw)
const transaction = ethers.utils.RLP.decode(payload.slice(1))
if (payload[0] !== this.type) {
throw new Error(`Invalid type ${payload[0]}`)
}
this.version = payload[1]
const transaction = ethers.utils.RLP.decode(payload.slice(2))
this._sourceHash = transaction[0]
this.from = handleAddress(transaction[1])
this.to = handleAddress(transaction[2])
......@@ -165,7 +174,7 @@ export class DepositTx {
return this
}
static decode(raw: BytesLike, extra?: DepostTxExtraOpts): DepositTx {
static decode(raw: BytesLike, extra?: DepositTxExtraOpts): DepositTx {
return new this().decode(raw, extra)
}
......
import { task, types } from 'hardhat/config'
import { Contract, providers, utils, Wallet, Event } from 'ethers'
import { providers, utils, Wallet, Event } from 'ethers'
import dotenv from 'dotenv'
import 'hardhat-deploy'
import { DepositTx } from '../src'
......@@ -31,22 +32,14 @@ task('deposit', 'Deposits funds onto L2.')
process.env.PRIVATE_KEY,
types.string
)
.addOptionalParam(
'depositContractAddr',
'Address of deposit contract.',
'deaddeaddeaddeaddeaddeaddeaddeaddead0001',
types.string
)
.setAction(async (args, hre) => {
const {
l1ProviderUrl,
l2ProviderUrl,
to,
amountEth,
depositContractAddr,
privateKey,
} = args
const depositFeedArtifact = await hre.deployments.get('OptimismPortal')
const { l1ProviderUrl, l2ProviderUrl, to, amountEth, privateKey } = args
const proxy = await hre.deployments.get('OptimismPortalProxy')
const OptimismPortal = await hre.ethers.getContractAt(
'OptimismPortal',
proxy.address
)
const l1Provider = new providers.JsonRpcProvider(l1ProviderUrl)
const l2Provider = new providers.JsonRpcProvider(l2ProviderUrl)
......@@ -65,16 +58,11 @@ task('deposit', 'Deposits funds onto L2.')
throw new Error(`${from} has no balance`)
}
const depositFeed = new Contract(
depositContractAddr,
depositFeedArtifact.abi
).connect(l1Wallet)
const amountWei = utils.parseEther(amountEth)
const value = amountWei.add(utils.parseEther('0.01'))
console.log(`Depositing ${amountEth} ETH to ${to}`)
// Below adds 0.01 ETH to account for gas.
const tx = await depositFeed.depositTransaction(
const tx = await OptimismPortal.depositTransaction(
to,
amountWei,
'3000000',
......@@ -84,6 +72,9 @@ task('deposit', 'Deposits funds onto L2.')
)
console.log(`Got TX hash ${tx.hash}. Waiting...`)
const receipt = await tx.wait()
console.log(
`Included in block ${receipt.blockHash} with index ${receipt.logIndex}`
)
// find the transaction deposited event and derive
// the deposit transaction from it
......@@ -91,6 +82,7 @@ task('deposit', 'Deposits funds onto L2.')
(e: Event) => e.event === 'TransactionDeposited'
)
const l2tx = DepositTx.fromL1Event(event)
console.log(`Deposit has log index ${event.logIndex}`)
const hash = l2tx.hash()
console.log(`Waiting for L2 TX hash ${hash}`)
......
......@@ -11,26 +11,26 @@ describe('Helpers', () => {
// constants serialized using optimistic-geth
// TODO(tynes): more tests
const hash =
'0xf5f97d03e8be48a4b20ed70c9d8b11f1c851bf949bf602b7580985705bb09077'
'0xf58e30138cb01330f6450b9a5e717a63840ad2e21f17340105b388ad3c668749'
const raw =
'0x7ef862a077fc5994647d128a4d131d273a5e89e0306aac472494068a4f1fceab83dd073594de3829a23df1479438622a08a116e8eb3f620bb594b7e390864a90b7b923c9f9310c6f98aafe43f707880e043da617250000880de0b6b3a7640000832dc6c080'
'0x7e00f862a0f923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc94f39fd6e51aad88f6f4ce6ab8827279cfffb9226694b79f76ef2c5f0286176833e7b2eee103b1cc3244880e043da617250000880de0b6b3a7640000832dc6c080'
const tx = new DepositTx({
from: '0xDe3829A23DF1479438622a08a116E8Eb3f620BB5',
from: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
gas: '0x2dc6c0',
data: '0x',
to: '0xB7e390864a90b7b923C9f9310C6F98aafE43F707',
to: '0xB79f76EF2c5F0286176833E7B2eEe103b1CC3244',
value: '0xde0b6b3a7640000',
domain: SourceHashDomain.UserDeposit,
l1BlockHash:
'0xd1a498e053451fc90bd8a597051a1039010c8e55e2659b940d3070b326e4f4c5',
logIndex: 0,
'0xd25df7858efc1778118fb133ac561b138845361626dfb976699c5287ed0f4959',
logIndex: 1,
mint: '0xe043da617250000',
})
const sourceHash = tx.sourceHash()
expect(sourceHash).to.deep.eq(
'0x77fc5994647d128a4d131d273a5e89e0306aac472494068a4f1fceab83dd0735'
'0xf923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc'
)
const encoded = tx.encode()
......
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