Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
685c8f25
Unverified
Commit
685c8f25
authored
Jun 18, 2021
by
Kelvin Fichter
Committed by
Kelvin Fichter
Jul 06, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat[integration-tests]: make tests work for prod networks
parent
9ed1e38b
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
368 additions
and
208 deletions
+368
-208
.env.example
integration-tests/.env.example
+6
-0
README.md
integration-tests/README.md
+31
-0
hardhat.config.ts
integration-tests/hardhat.config.ts
+8
-3
package.json
integration-tests/package.json
+3
-0
basic-l1-l2-communication.spec.ts
integration-tests/test/basic-l1-l2-communication.spec.ts
+7
-4
fee-payment.spec.ts
integration-tests/test/fee-payment.spec.ts
+18
-9
native-eth.spec.ts
integration-tests/test/native-eth.spec.ts
+61
-39
ovmcontext.spec.ts
integration-tests/test/ovmcontext.spec.ts
+43
-62
queue-ingestion.spec.ts
integration-tests/test/queue-ingestion.spec.ts
+41
-75
rpc.spec.ts
integration-tests/test/rpc.spec.ts
+13
-5
env.ts
integration-tests/test/shared/env.ts
+108
-2
utils.ts
integration-tests/test/shared/utils.ts
+21
-9
Dockerfile.integration-tests
ops/docker/Dockerfile.integration-tests
+3
-0
yarn.lock
yarn.lock
+5
-0
No files found.
integration-tests/.env.example
0 → 100644
View file @
685c8f25
# only need to fill these out if you want to test against a prod network
PRIVATE_KEY=
L1_URL=
L2_URL=
ADDRESS_MANAGER=
L2_CHAINID=
integration-tests/README.md
0 → 100644
View file @
685c8f25
# @eth-optimism/integration-tests
## Setup
Follow installation + build instructions in the
[
primary README
](
../README.md
)
.
Then, run:
```
bash
yarn build:integration
```
## Running tests
### Testing a live network
Create an
`.env`
file and fill it out.
Look at
`.env.example`
to know which variables to include.
Once you have your environment set up, run:
```
bash
yarn
test
:integration:live
```
You can also set environment variables on the command line instead of inside
`.env`
if you want:
```
bash
L1_URL
=
whatever
L2_URL
=
whatever yarn
test
:integration:live
```
Note that this can take an extremely long time (~1hr).
integration-tests/hardhat.config.ts
View file @
685c8f25
...
@@ -9,14 +9,19 @@ import 'hardhat-gas-reporter'
...
@@ -9,14 +9,19 @@ import 'hardhat-gas-reporter'
const
enableGasReport
=
!!
process
.
env
.
ENABLE_GAS_REPORT
const
enableGasReport
=
!!
process
.
env
.
ENABLE_GAS_REPORT
const
config
:
HardhatUserConfig
=
{
const
config
:
HardhatUserConfig
=
{
mocha
:
{
timeout
:
20000
,
},
networks
:
{
networks
:
{
optimism
:
{
optimism
:
{
url
:
process
.
env
.
L2_URL
||
'
http://localhost:8545
'
,
url
:
process
.
env
.
L2_URL
||
'
http://localhost:8545
'
,
ovm
:
true
,
ovm
:
true
,
},
},
'
optimism-live
'
:
{
url
:
process
.
env
.
L2_URL
||
'
http://localhost:8545
'
,
ovm
:
true
,
timeout
:
150000
,
},
},
mocha
:
{
timeout
:
50000
,
},
},
solidity
:
'
0.7.6
'
,
solidity
:
'
0.7.6
'
,
ovm
:
{
ovm
:
{
...
...
integration-tests/package.json
View file @
685c8f25
...
@@ -13,6 +13,7 @@
...
@@ -13,6 +13,7 @@
"build:contracts"
:
"hardhat compile"
,
"build:contracts"
:
"hardhat compile"
,
"build:contracts:ovm"
:
"hardhat compile --network optimism"
,
"build:contracts:ovm"
:
"hardhat compile --network optimism"
,
"test:integration"
:
"hardhat --network optimism test"
,
"test:integration"
:
"hardhat --network optimism test"
,
"test:integration:live"
:
"IS_LIVE_NETWORK=true hardhat --network optimism-live test"
,
"test:sync"
:
"hardhat --network optimism test sync-tests/*.spec.ts --no-compile"
,
"test:sync"
:
"hardhat --network optimism test sync-tests/*.spec.ts --no-compile"
,
"clean"
:
"rimraf cache artifacts artifacts-ovm cache-ovm"
"clean"
:
"rimraf cache artifacts artifacts-ovm cache-ovm"
},
},
...
@@ -20,6 +21,7 @@
...
@@ -20,6 +21,7 @@
"@eth-optimism/contracts"
:
"^0.4.2"
,
"@eth-optimism/contracts"
:
"^0.4.2"
,
"@eth-optimism/core-utils"
:
"^0.5.0"
,
"@eth-optimism/core-utils"
:
"^0.5.0"
,
"@eth-optimism/hardhat-ovm"
:
"^0.2.2"
,
"@eth-optimism/hardhat-ovm"
:
"^0.2.2"
,
"@eth-optimism/message-relayer"
:
"^0.1.6"
,
"@ethersproject/providers"
:
"^5.0.24"
,
"@ethersproject/providers"
:
"^5.0.24"
,
"@nomiclabs/hardhat-ethers"
:
"^2.0.2"
,
"@nomiclabs/hardhat-ethers"
:
"^2.0.2"
,
"@nomiclabs/hardhat-waffle"
:
"^2.0.1"
,
"@nomiclabs/hardhat-waffle"
:
"^2.0.1"
,
...
@@ -33,6 +35,7 @@
...
@@ -33,6 +35,7 @@
"chai"
:
"^4.3.3"
,
"chai"
:
"^4.3.3"
,
"chai-as-promised"
:
"^7.1.1"
,
"chai-as-promised"
:
"^7.1.1"
,
"docker-compose"
:
"^0.23.8"
,
"docker-compose"
:
"^0.23.8"
,
"dotenv"
:
"^10.0.0"
,
"envalid"
:
"^7.1.0"
,
"envalid"
:
"^7.1.0"
,
"babel-eslint"
:
"^10.1.0"
,
"babel-eslint"
:
"^10.1.0"
,
"eslint"
:
"^7.27.0"
,
"eslint"
:
"^7.27.0"
,
...
...
integration-tests/test/basic-l1-l2-communication.spec.ts
View file @
685c8f25
...
@@ -3,13 +3,13 @@ import { expect } from 'chai'
...
@@ -3,13 +3,13 @@ import { expect } from 'chai'
/* Imports: External */
/* Imports: External */
import
{
Contract
,
ContractFactory
}
from
'
ethers
'
import
{
Contract
,
ContractFactory
}
from
'
ethers
'
import
{
predeploys
,
getContractInterface
}
from
'
@eth-optimism/contracts
'
import
{
predeploys
,
getContractInterface
}
from
'
@eth-optimism/contracts
'
import
{
Direction
}
from
'
./shared/watcher-utils
'
/* Imports: Internal */
/* Imports: Internal */
import
l1SimpleStorageJson
from
'
../artifacts/contracts/SimpleStorage.sol/SimpleStorage.json
'
import
l1SimpleStorageJson
from
'
../artifacts/contracts/SimpleStorage.sol/SimpleStorage.json
'
import
l2SimpleStorageJson
from
'
../artifacts-ovm/contracts/SimpleStorage.sol/SimpleStorage.json
'
import
l2SimpleStorageJson
from
'
../artifacts-ovm/contracts/SimpleStorage.sol/SimpleStorage.json
'
import
l2ReverterJson
from
'
../artifacts-ovm/contracts/Reverter.sol/Reverter.json
'
import
l2ReverterJson
from
'
../artifacts-ovm/contracts/Reverter.sol/Reverter.json
'
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
Direction
}
from
'
./shared/watcher-utils
'
import
{
OptimismEnv
,
useDynamicTimeoutForWithdrawals
}
from
'
./shared/env
'
describe
(
'
Basic L1<>L2 Communication
'
,
async
()
=>
{
describe
(
'
Basic L1<>L2 Communication
'
,
async
()
=>
{
let
Factory__L1SimpleStorage
:
ContractFactory
let
Factory__L1SimpleStorage
:
ContractFactory
...
@@ -49,7 +49,9 @@ describe('Basic L1<>L2 Communication', async () => {
...
@@ -49,7 +49,9 @@ describe('Basic L1<>L2 Communication', async () => {
})
})
describe
(
'
L2 => L1
'
,
()
=>
{
describe
(
'
L2 => L1
'
,
()
=>
{
it
(
'
should be able to perform a withdrawal from L2 -> L1
'
,
async
()
=>
{
it
(
'
should be able to perform a withdrawal from L2 -> L1
'
,
async
function
()
{
await
useDynamicTimeoutForWithdrawals
(
this
,
env
)
const
value
=
`0x
${
'
77
'
.
repeat
(
32
)}
`
const
value
=
`0x
${
'
77
'
.
repeat
(
32
)}
`
// Send L2 -> L1 message.
// Send L2 -> L1 message.
...
@@ -58,7 +60,8 @@ describe('Basic L1<>L2 Communication', async () => {
...
@@ -58,7 +60,8 @@ describe('Basic L1<>L2 Communication', async () => {
L1SimpleStorage
.
interface
.
encodeFunctionData
(
'
setValue
'
,
[
value
]),
L1SimpleStorage
.
interface
.
encodeFunctionData
(
'
setValue
'
,
[
value
]),
5000000
5000000
)
)
await
transaction
.
wait
()
await
env
.
relayXDomainMessages
(
transaction
)
await
env
.
waitForXDomainTransaction
(
transaction
,
Direction
.
L2ToL1
)
await
env
.
waitForXDomainTransaction
(
transaction
,
Direction
.
L2ToL1
)
expect
(
await
L1SimpleStorage
.
msgSender
()).
to
.
equal
(
expect
(
await
L1SimpleStorage
.
msgSender
()).
to
.
equal
(
...
...
integration-tests/test/fee-payment.spec.ts
View file @
685c8f25
...
@@ -3,11 +3,12 @@ import chaiAsPromised from 'chai-as-promised'
...
@@ -3,11 +3,12 @@ import chaiAsPromised from 'chai-as-promised'
chai
.
use
(
chaiAsPromised
)
chai
.
use
(
chaiAsPromised
)
/* Imports: External */
/* Imports: External */
import
{
BigNumber
,
Contract
,
utils
}
from
'
ethers
'
import
{
ethers
,
BigNumber
,
Contract
,
utils
}
from
'
ethers
'
import
{
TxGasLimit
,
TxGasPrice
}
from
'
@eth-optimism/core-utils
'
import
{
TxGasLimit
,
TxGasPrice
}
from
'
@eth-optimism/core-utils
'
import
{
predeploys
,
getContractInterface
}
from
'
@eth-optimism/contracts
'
import
{
predeploys
,
getContractInterface
}
from
'
@eth-optimism/contracts
'
/* Imports: Internal */
/* Imports: Internal */
import
{
IS_LIVE_NETWORK
}
from
'
./shared/utils
'
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
Direction
}
from
'
./shared/watcher-utils
'
import
{
Direction
}
from
'
./shared/watcher-utils
'
...
@@ -36,11 +37,11 @@ describe('Fee Payment Integration Tests', async () => {
...
@@ -36,11 +37,11 @@ describe('Fee Payment Integration Tests', async () => {
it
(
'
Should estimateGas with recoverable L2 gasLimit
'
,
async
()
=>
{
it
(
'
Should estimateGas with recoverable L2 gasLimit
'
,
async
()
=>
{
const
gas
=
await
env
.
ovmEth
.
estimateGas
.
transfer
(
const
gas
=
await
env
.
ovmEth
.
estimateGas
.
transfer
(
other
,
other
,
utils
.
parseEther
(
'
0.
5
'
)
utils
.
parseEther
(
'
0.
0000001
'
)
)
)
const
tx
=
await
env
.
ovmEth
.
populateTransaction
.
transfer
(
const
tx
=
await
env
.
ovmEth
.
populateTransaction
.
transfer
(
other
,
other
,
utils
.
parseEther
(
'
0.
5
'
)
utils
.
parseEther
(
'
0.
0000001
'
)
)
)
const
executionGas
=
await
(
env
.
ovmEth
.
provider
as
any
).
send
(
const
executionGas
=
await
(
env
.
ovmEth
.
provider
as
any
).
send
(
'
eth_estimateExecutionGas
'
,
'
eth_estimateExecutionGas
'
,
...
@@ -51,7 +52,7 @@ describe('Fee Payment Integration Tests', async () => {
...
@@ -51,7 +52,7 @@ describe('Fee Payment Integration Tests', async () => {
})
})
it
(
'
Paying a nonzero but acceptable gasPrice fee
'
,
async
()
=>
{
it
(
'
Paying a nonzero but acceptable gasPrice fee
'
,
async
()
=>
{
const
amount
=
utils
.
parseEther
(
'
0.
5
'
)
const
amount
=
utils
.
parseEther
(
'
0.
0000001
'
)
const
balanceBefore
=
await
env
.
l2Wallet
.
getBalance
()
const
balanceBefore
=
await
env
.
l2Wallet
.
getBalance
()
const
feeVaultBalanceBefore
=
await
env
.
l2Wallet
.
provider
.
getBalance
(
const
feeVaultBalanceBefore
=
await
env
.
l2Wallet
.
provider
.
getBalance
(
ovmSequencerFeeVault
.
address
ovmSequencerFeeVault
.
address
...
@@ -84,15 +85,23 @@ describe('Fee Payment Integration Tests', async () => {
...
@@ -84,15 +85,23 @@ describe('Fee Payment Integration Tests', async () => {
await
expect
(
ovmSequencerFeeVault
.
withdraw
()).
to
.
be
.
rejected
await
expect
(
ovmSequencerFeeVault
.
withdraw
()).
to
.
be
.
rejected
})
})
it
(
'
should be able to withdraw fees back to L1 once the minimum is met
'
,
async
()
=>
{
it
(
'
should be able to withdraw fees back to L1 once the minimum is met
'
,
async
function
()
{
const
l1FeeWallet
=
await
ovmSequencerFeeVault
.
l1FeeWallet
()
const
l1FeeWallet
=
await
ovmSequencerFeeVault
.
l1FeeWallet
()
const
balanceBefore
=
await
env
.
l1Wallet
.
provider
.
getBalance
(
l1FeeWallet
)
const
balanceBefore
=
await
env
.
l1Wallet
.
provider
.
getBalance
(
l1FeeWallet
)
const
withdrawalAmount
=
await
ovmSequencerFeeVault
.
MIN_WITHDRAWAL_AMOUNT
()
const
l2WalletBalance
=
await
env
.
l2Wallet
.
getBalance
()
if
(
IS_LIVE_NETWORK
&&
l2WalletBalance
.
lt
(
withdrawalAmount
))
{
console
.
log
(
`NOTICE: must have at least
${
ethers
.
utils
.
formatEther
(
withdrawalAmount
)}
ETH on L2 to execute this test, skipping`
)
this
.
skip
()
}
// Transfer the minimum required to withdraw.
// Transfer the minimum required to withdraw.
await
env
.
ovmEth
.
transfer
(
await
env
.
ovmEth
.
transfer
(
ovmSequencerFeeVault
.
address
,
withdrawalAmount
)
ovmSequencerFeeVault
.
address
,
await
ovmSequencerFeeVault
.
MIN_WITHDRAWAL_AMOUNT
()
)
const
vaultBalance
=
await
env
.
ovmEth
.
balanceOf
(
const
vaultBalance
=
await
env
.
ovmEth
.
balanceOf
(
ovmSequencerFeeVault
.
address
ovmSequencerFeeVault
.
address
...
...
integration-tests/test/native-eth.spec.ts
View file @
685c8f25
import
{
predeploys
}
from
'
@eth-optimism/contracts
'
import
{
expect
}
from
'
chai
'
import
{
expect
}
from
'
chai
'
/* Imports: External */
import
{
Wallet
,
utils
,
BigNumber
}
from
'
ethers
'
import
{
Wallet
,
utils
,
BigNumber
}
from
'
ethers
'
import
{
predeploys
}
from
'
@eth-optimism/contracts
'
/* Imports: Internal */
import
{
Direction
}
from
'
./shared/watcher-utils
'
import
{
Direction
}
from
'
./shared/watcher-utils
'
import
{
import
{
...
@@ -9,7 +12,7 @@ import {
...
@@ -9,7 +12,7 @@ import {
fundUser
,
fundUser
,
PROXY_SEQUENCER_ENTRYPOINT_ADDRESS
,
PROXY_SEQUENCER_ENTRYPOINT_ADDRESS
,
}
from
'
./shared/utils
'
}
from
'
./shared/utils
'
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
OptimismEnv
,
useDynamicTimeoutForWithdrawals
}
from
'
./shared/env
'
const
DEFAULT_TEST_GAS_L1
=
330
_000
const
DEFAULT_TEST_GAS_L1
=
330
_000
const
DEFAULT_TEST_GAS_L2
=
1
_300_000
const
DEFAULT_TEST_GAS_L2
=
1
_300_000
...
@@ -53,7 +56,7 @@ describe('Native ETH Integration Tests', async () => {
...
@@ -53,7 +56,7 @@ describe('Native ETH Integration Tests', async () => {
describe
(
'
estimateGas
'
,
()
=>
{
describe
(
'
estimateGas
'
,
()
=>
{
it
(
'
Should estimate gas for ETH transfer
'
,
async
()
=>
{
it
(
'
Should estimate gas for ETH transfer
'
,
async
()
=>
{
const
amount
=
utils
.
parseEther
(
'
0.
5
'
)
const
amount
=
utils
.
parseEther
(
'
0.
0000001
'
)
const
addr
=
'
0x
'
+
'
1234
'
.
repeat
(
10
)
const
addr
=
'
0x
'
+
'
1234
'
.
repeat
(
10
)
const
gas
=
await
env
.
ovmEth
.
estimateGas
.
transfer
(
addr
,
amount
)
const
gas
=
await
env
.
ovmEth
.
estimateGas
.
transfer
(
addr
,
amount
)
// Expect gas to be less than or equal to the target plus 1%
// Expect gas to be less than or equal to the target plus 1%
...
@@ -61,7 +64,7 @@ describe('Native ETH Integration Tests', async () => {
...
@@ -61,7 +64,7 @@ describe('Native ETH Integration Tests', async () => {
})
})
it
(
'
Should estimate gas for ETH withdraw
'
,
async
()
=>
{
it
(
'
Should estimate gas for ETH withdraw
'
,
async
()
=>
{
const
amount
=
utils
.
parseEther
(
'
0.
5
'
)
const
amount
=
utils
.
parseEther
(
'
0.
0000001
'
)
const
gas
=
await
env
.
l2Bridge
.
estimateGas
.
withdraw
(
const
gas
=
await
env
.
l2Bridge
.
estimateGas
.
withdraw
(
predeploys
.
OVM_ETH
,
predeploys
.
OVM_ETH
,
amount
,
amount
,
...
@@ -186,14 +189,13 @@ describe('Native ETH Integration Tests', async () => {
...
@@ -186,14 +189,13 @@ describe('Native ETH Integration Tests', async () => {
await
expect
(
await
expect
(
env
.
l1Bridge
.
depositETH
(
DEFAULT_TEST_GAS_L2
,
data
,
{
env
.
l1Bridge
.
depositETH
(
DEFAULT_TEST_GAS_L2
,
data
,
{
value
:
depositAmount
,
value
:
depositAmount
,
gasLimit
:
4
_000_000
,
})
})
).
to
.
be
.
revertedWith
(
).
to
.
be
.
reverted
'
Transaction data size exceeds maximum for rollup transaction.
'
)
})
})
it
(
'
withdraw
'
,
async
()
=>
{
it
(
'
withdraw
'
,
async
function
()
{
await
useDynamicTimeoutForWithdrawals
(
this
,
env
)
const
withdrawAmount
=
BigNumber
.
from
(
3
)
const
withdrawAmount
=
BigNumber
.
from
(
3
)
const
preBalances
=
await
getBalances
(
env
)
const
preBalances
=
await
getBalances
(
env
)
expect
(
expect
(
...
@@ -201,31 +203,43 @@ describe('Native ETH Integration Tests', async () => {
...
@@ -201,31 +203,43 @@ describe('Native ETH Integration Tests', async () => {
'
Cannot run withdrawal test before any deposits...
'
'
Cannot run withdrawal test before any deposits...
'
)
)
const
transaction
=
await
env
.
l2Bridge
.
withdraw
(
predeploys
.
OVM_ETH
,
withdrawAmount
,
DEFAULT_TEST_GAS_L2
,
'
0xFFFF
'
)
await
transaction
.
wait
()
await
env
.
relayXDomainMessages
(
transaction
)
const
receipts
=
await
env
.
waitForXDomainTransaction
(
const
receipts
=
await
env
.
waitForXDomainTransaction
(
env
.
l2Bridge
.
withdraw
(
transaction
,
predeploys
.
OVM_ETH
,
withdrawAmount
,
DEFAULT_TEST_GAS_L2
,
'
0xFFFF
'
),
Direction
.
L2ToL1
Direction
.
L2ToL1
)
)
const
fee
=
receipts
.
tx
.
gasLimit
.
mul
(
receipts
.
tx
.
gasPrice
)
const
fee
=
receipts
.
tx
.
gasLimit
.
mul
(
receipts
.
tx
.
gasPrice
)
const
postBalances
=
await
getBalances
(
env
)
const
postBalances
=
await
getBalances
(
env
)
expect
(
postBalances
.
l1BridgeBalance
).
to
.
deep
.
eq
(
// Approximate because there's a fee related to relaying the L2 => L1 message and it throws off the math.
preBalances
.
l1BridgeBalance
.
sub
(
withdrawAmount
)
expectApprox
(
postBalances
.
l1BridgeBalance
,
preBalances
.
l1BridgeBalance
.
sub
(
withdrawAmount
),
{
upperPercentDeviation
:
1
}
)
)
expect
(
postBalances
.
l2UserBalance
).
to
.
deep
.
eq
(
expectApprox
(
preBalances
.
l2UserBalance
.
sub
(
withdrawAmount
.
add
(
fee
))
postBalances
.
l2UserBalance
,
preBalances
.
l2UserBalance
.
sub
(
withdrawAmount
.
add
(
fee
)),
{
upperPercentDeviation
:
1
}
)
)
expect
(
postBalances
.
l1UserBalance
).
to
.
deep
.
eq
(
expectApprox
(
preBalances
.
l1UserBalance
.
add
(
withdrawAmount
)
postBalances
.
l1UserBalance
,
preBalances
.
l1UserBalance
.
add
(
withdrawAmount
),
{
upperPercentDeviation
:
1
}
)
)
})
})
it
(
'
withdrawTo
'
,
async
()
=>
{
it
(
'
withdrawTo
'
,
async
function
()
{
await
useDynamicTimeoutForWithdrawals
(
this
,
env
)
const
withdrawAmount
=
BigNumber
.
from
(
3
)
const
withdrawAmount
=
BigNumber
.
from
(
3
)
const
preBalances
=
await
getBalances
(
env
)
const
preBalances
=
await
getBalances
(
env
)
...
@@ -235,14 +249,17 @@ describe('Native ETH Integration Tests', async () => {
...
@@ -235,14 +249,17 @@ describe('Native ETH Integration Tests', async () => {
'
Cannot run withdrawal test before any deposits...
'
'
Cannot run withdrawal test before any deposits...
'
)
)
const
transaction
=
await
env
.
l2Bridge
.
withdrawTo
(
predeploys
.
OVM_ETH
,
l1Bob
.
address
,
withdrawAmount
,
DEFAULT_TEST_GAS_L2
,
'
0xFFFF
'
)
await
transaction
.
wait
()
await
env
.
relayXDomainMessages
(
transaction
)
const
receipts
=
await
env
.
waitForXDomainTransaction
(
const
receipts
=
await
env
.
waitForXDomainTransaction
(
env
.
l2Bridge
.
withdrawTo
(
transaction
,
predeploys
.
OVM_ETH
,
l1Bob
.
address
,
withdrawAmount
,
DEFAULT_TEST_GAS_L2
,
'
0xFFFF
'
),
Direction
.
L2ToL1
Direction
.
L2ToL1
)
)
const
fee
=
receipts
.
tx
.
gasLimit
.
mul
(
receipts
.
tx
.
gasPrice
)
const
fee
=
receipts
.
tx
.
gasLimit
.
mul
(
receipts
.
tx
.
gasPrice
)
...
@@ -260,7 +277,9 @@ describe('Native ETH Integration Tests', async () => {
...
@@ -260,7 +277,9 @@ describe('Native ETH Integration Tests', async () => {
)
)
})
})
it
(
'
deposit, transfer, withdraw
'
,
async
()
=>
{
it
(
'
deposit, transfer, withdraw
'
,
async
function
()
{
await
useDynamicTimeoutForWithdrawals
(
this
,
env
)
// 1. deposit
// 1. deposit
const
amount
=
utils
.
parseEther
(
'
1
'
)
const
amount
=
utils
.
parseEther
(
'
1
'
)
await
env
.
waitForXDomainTransaction
(
await
env
.
waitForXDomainTransaction
(
...
@@ -282,15 +301,18 @@ describe('Native ETH Integration Tests', async () => {
...
@@ -282,15 +301,18 @@ describe('Native ETH Integration Tests', async () => {
// 3. do withdrawal
// 3. do withdrawal
const
withdrawnAmount
=
utils
.
parseEther
(
'
0.95
'
)
const
withdrawnAmount
=
utils
.
parseEther
(
'
0.95
'
)
const
transaction
=
await
env
.
l2Bridge
.
connect
(
other
)
.
withdraw
(
predeploys
.
OVM_ETH
,
withdrawnAmount
,
DEFAULT_TEST_GAS_L1
,
'
0xFFFF
'
)
await
transaction
.
wait
()
await
env
.
relayXDomainMessages
(
transaction
)
const
receipts
=
await
env
.
waitForXDomainTransaction
(
const
receipts
=
await
env
.
waitForXDomainTransaction
(
env
.
l2Bridge
transaction
,
.
connect
(
other
)
.
withdraw
(
predeploys
.
OVM_ETH
,
withdrawnAmount
,
DEFAULT_TEST_GAS_L1
,
'
0xFFFF
'
),
Direction
.
L2ToL1
Direction
.
L2ToL1
)
)
...
...
integration-tests/test/ovmcontext.spec.ts
View file @
685c8f25
import
{
expect
}
from
'
chai
'
/* Imports: External */
import
{
ethers
}
from
'
hardhat
'
import
{
ethers
}
from
'
hardhat
'
import
{
injectL2Context
}
from
'
@eth-optimism/core-utils
'
import
{
injectL2Context
}
from
'
@eth-optimism/core-utils
'
import
{
expect
}
from
'
chai
'
import
{
Contract
,
BigNumber
}
from
'
ethers
'
import
{
sleep
,
/* Imports: Internal */
l2Provider
,
import
{
l2Provider
,
l1Provider
,
IS_LIVE_NETWORK
}
from
'
./shared/utils
'
l1Provider
,
getAddressManager
,
}
from
'
./shared/utils
'
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
getContractFactory
}
from
'
@eth-optimism/contracts
'
import
{
Direction
}
from
'
./shared/watcher-utils
'
import
{
Contract
,
ContractFactory
,
Wallet
,
BigNumber
}
from
'
ethers
'
/**
/**
* These tests cover the OVM execution contexts. In the OVM execution
* These tests cover the OVM execution contexts. In the OVM execution
...
@@ -17,73 +16,51 @@ import { Contract, ContractFactory, Wallet, BigNumber } from 'ethers'
...
@@ -17,73 +16,51 @@ import { Contract, ContractFactory, Wallet, BigNumber } from 'ethers'
* must be equal to the blocknumber/timestamp of the L1 transaction.
* must be equal to the blocknumber/timestamp of the L1 transaction.
*/
*/
describe
(
'
OVM Context: Layer 2 EVM Context
'
,
()
=>
{
describe
(
'
OVM Context: Layer 2 EVM Context
'
,
()
=>
{
let
address
:
string
let
CanonicalTransactionChain
:
Contract
let
OVMMulticall
:
Contract
let
OVMContextStorage
:
Contract
const
L1Provider
=
l1Provider
const
L2Provider
=
injectL2Context
(
l2Provider
)
const
L2Provider
=
injectL2Context
(
l2Provider
)
let
env
:
OptimismEnv
before
(
async
()
=>
{
before
(
async
()
=>
{
const
env
=
await
OptimismEnv
.
new
()
env
=
await
OptimismEnv
.
new
()
// Create providers and signers
})
const
l1Wallet
=
env
.
l1Wallet
const
l2Wallet
=
env
.
l2Wallet
const
addressManager
=
env
.
addressManager
// deploy the contract
let
OVMMulticall
:
Contract
let
OVMContextStorage
:
Contract
beforeEach
(
async
()
=>
{
const
OVMContextStorageFactory
=
await
ethers
.
getContractFactory
(
const
OVMContextStorageFactory
=
await
ethers
.
getContractFactory
(
'
OVMContextStorage
'
,
'
OVMContextStorage
'
,
l2Wallet
env
.
l2Wallet
)
OVMContextStorage
=
await
OVMContextStorageFactory
.
deploy
()
const
receipt
=
await
OVMContextStorage
.
deployTransaction
.
wait
()
address
=
OVMContextStorage
.
address
const
ctcAddress
=
await
addressManager
.
getAddress
(
'
OVM_CanonicalTransactionChain
'
)
)
const
CanonicalTransactionChainFactory
=
getContractFactory
(
'
OVM_CanonicalTransactionChain
'
)
CanonicalTransactionChain
=
CanonicalTransactionChainFactory
.
connect
(
l1Wallet
).
attach
(
ctcAddress
)
const
OVMMulticallFactory
=
await
ethers
.
getContractFactory
(
const
OVMMulticallFactory
=
await
ethers
.
getContractFactory
(
'
OVMMulticall
'
,
'
OVMMulticall
'
,
l2Wallet
env
.
l2Wallet
)
)
OVMContextStorage
=
await
OVMContextStorageFactory
.
deploy
()
await
OVMContextStorage
.
deployTransaction
.
wait
()
OVMMulticall
=
await
OVMMulticallFactory
.
deploy
()
OVMMulticall
=
await
OVMMulticallFactory
.
deploy
()
await
OVMMulticall
.
deployTransaction
.
wait
()
await
OVMMulticall
.
deployTransaction
.
wait
()
})
})
it
(
'
Enqueue: `block.number` and `block.timestamp` have L1 values
'
,
async
()
=>
{
let
numTxs
=
5
for
(
let
i
=
0
;
i
<
5
;
i
++
)
{
if
(
IS_LIVE_NETWORK
)
{
const
l2Tip
=
await
L2Provider
.
getBlock
(
'
latest
'
)
// Tests take way too long if we don't reduce the number of txs here.
const
tx
=
await
CanonicalTransactionChain
.
enqueue
(
numTxs
=
1
}
it
(
'
enqueue: `block.number` and `block.timestamp` have L1 values
'
,
async
()
=>
{
for
(
let
i
=
0
;
i
<
numTxs
;
i
++
)
{
const
tx
=
await
env
.
l1Messenger
.
sendMessage
(
OVMContextStorage
.
address
,
OVMContextStorage
.
address
,
500
_000
,
'
0x
'
,
'
0x
'
2
_000_000
)
)
const
receipt
=
await
tx
.
wait
()
// Wait for the enqueue to be ingested
while
(
true
)
{
const
tip
=
await
L2Provider
.
getBlock
(
'
latest
'
)
if
(
tip
.
number
===
l2Tip
.
number
+
1
)
{
break
}
await
sleep
(
500
)
}
// Get the receipt
// Get the receipt
const
receipt
=
await
tx
.
wait
()
// The transaction did not revert
// The transaction did not revert
expect
(
receipt
.
status
).
to
.
equal
(
1
)
expect
(
receipt
.
status
).
to
.
equal
(
1
)
await
env
.
waitForXDomainTransaction
(
tx
,
Direction
.
L1ToL2
)
// Get the L1 block that the enqueue transaction was in so that
// Get the L1 block that the enqueue transaction was in so that
// the timestamp can be compared against the layer two contract
// the timestamp can be compared against the layer two contract
const
block
=
await
l1Provider
.
getBlock
(
receipt
.
blockNumber
)
const
block
=
await
l1Provider
.
getBlock
(
receipt
.
blockNumber
)
...
@@ -96,14 +73,18 @@ describe('OVM Context: Layer 2 EVM Context', () => {
...
@@ -96,14 +73,18 @@ describe('OVM Context: Layer 2 EVM Context', () => {
const
timestamp
=
await
OVMContextStorage
.
timestamps
(
i
)
const
timestamp
=
await
OVMContextStorage
.
timestamps
(
i
)
expect
(
block
.
timestamp
).
to
.
deep
.
equal
(
timestamp
.
toNumber
())
expect
(
block
.
timestamp
).
to
.
deep
.
equal
(
timestamp
.
toNumber
())
}
}
})
})
.
timeout
(
150000
)
// this specific test takes a while because it involves L1 to L2 txs
it
(
'
should set correct OVM Context for `eth_call`
'
,
async
()
=>
{
it
(
'
should set correct OVM Context for `eth_call`
'
,
async
()
=>
{
const
tip
=
await
L2Provider
.
getBlockWithTransactions
(
'
latest
'
)
for
(
let
i
=
0
;
i
<
numTxs
;
i
++
)
{
const
start
=
Math
.
max
(
0
,
tip
.
number
-
5
)
// Make an empty transaction to bump the latest block number.
const
dummyTx
=
await
env
.
l2Wallet
.
sendTransaction
({
for
(
let
i
=
start
;
i
<
tip
.
number
;
i
++
)
{
to
:
`0x
${
'
11
'
.
repeat
(
20
)}
`
,
const
block
=
await
L2Provider
.
getBlockWithTransactions
(
i
)
data
:
'
0x
'
,
})
await
dummyTx
.
wait
()
const
block
=
await
L2Provider
.
getBlockWithTransactions
(
'
latest
'
)
const
[,
returnData
]
=
await
OVMMulticall
.
callStatic
.
aggregate
(
const
[,
returnData
]
=
await
OVMMulticall
.
callStatic
.
aggregate
(
[
[
[
[
...
@@ -117,7 +98,7 @@ describe('OVM Context: Layer 2 EVM Context', () => {
...
@@ -117,7 +98,7 @@ describe('OVM Context: Layer 2 EVM Context', () => {
OVMMulticall
.
interface
.
encodeFunctionData
(
'
getCurrentBlockNumber
'
),
OVMMulticall
.
interface
.
encodeFunctionData
(
'
getCurrentBlockNumber
'
),
],
],
],
],
{
blockTag
:
i
}
{
blockTag
:
block
.
number
}
)
)
const
timestamp
=
BigNumber
.
from
(
returnData
[
0
])
const
timestamp
=
BigNumber
.
from
(
returnData
[
0
])
...
...
integration-tests/test/queue-ingestion.spec.ts
View file @
685c8f25
import
{
expect
}
from
'
chai
'
/* Imports: Internal */
/* Imports: Internal */
import
{
providers
}
from
'
ethers
'
import
{
injectL2Context
}
from
'
@eth-optimism/core-utils
'
import
{
injectL2Context
}
from
'
@eth-optimism/core-utils
'
import
{
sleep
}
from
'
./shared/utils
'
import
{
OptimismEnv
}
from
'
./shared/env
'
/* Imports: External */
/* Imports: External */
import
{
providers
}
from
'
ethers
'
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
expect
}
from
'
chai
'
import
{
Direction
}
from
'
./shared/watcher-utils
'
// This test ensures that the transactions which get `enqueue`d get
// added to the L2 blocks by the Sync Service (which queries the DTL)
describe
(
'
Queue Ingestion
'
,
()
=>
{
describe
(
'
Queue Ingestion
'
,
()
=>
{
const
RETRIES
=
20
const
numTxs
=
5
let
startBlock
:
number
let
endBlock
:
number
let
env
:
OptimismEnv
let
env
:
OptimismEnv
let
l2Provider
:
providers
.
JsonRpcProvider
let
l2Provider
:
providers
.
JsonRpcProvider
const
receipts
=
[]
before
(
async
()
=>
{
before
(
async
()
=>
{
env
=
await
OptimismEnv
.
new
()
env
=
await
OptimismEnv
.
new
()
l2Provider
=
injectL2Context
(
env
.
l2Wallet
.
provider
as
any
)
l2Provider
=
injectL2Context
(
env
.
l2Wallet
.
provider
as
any
)
})
})
// The transactions are enqueue'd with a `to` address of i.repeat(40)
// meaning that the `to` value is different each iteration in a deterministic
// way. They need to be inserted into the L2 chain in an ascending order.
// Keep track of the receipts so that the blockNumber can be compared
// against the `L1BlockNumber` on the tx objects.
before
(
async
()
=>
{
// Keep track of the L2 tip before submitting any transactions so that
// the subsequent transactions can be queried for in the next test
startBlock
=
(
await
l2Provider
.
getBlockNumber
())
+
1
endBlock
=
startBlock
+
numTxs
-
1
// Enqueue some transactions by building the calldata and then sending
// the transaction to Layer 1
for
(
let
i
=
0
;
i
<
numTxs
;
i
++
)
{
const
input
=
[
'
0x
'
+
`
${
i
}
`
.
repeat
(
40
),
500
_000
,
`0x0
${
i
}
`
]
const
calldata
=
env
.
ctc
.
interface
.
encodeFunctionData
(
'
enqueue
'
,
input
)
const
txResponse
=
await
env
.
l1Wallet
.
sendTransaction
({
data
:
calldata
,
to
:
env
.
ctc
.
address
,
})
const
receipt
=
await
txResponse
.
wait
()
receipts
.
push
(
receipt
)
}
})
// The batch submitter will notice that there are transactions
// The batch submitter will notice that there are transactions
// that are in the queue and submit them. L2 will pick up the
// that are in the queue and submit them. L2 will pick up the
// sequencer batch appended event and play the transactions.
// sequencer batch appended event and play the transactions.
it
(
'
should order transactions correctly
'
,
async
()
=>
{
it
(
'
should order transactions correctly
'
,
async
()
=>
{
// Wait until each tx from the previous test has
const
numTxs
=
5
// been executed
let
i
:
number
for
(
i
=
0
;
i
<
RETRIES
;
i
++
)
{
const
tip
=
await
l2Provider
.
getBlockNumber
()
if
(
tip
>=
endBlock
)
{
break
}
await
sleep
(
1000
)
}
if
(
i
===
RETRIES
)
{
// Enqueue some transactions by building the calldata and then sending
throw
new
Error
(
// the transaction to Layer 1
'
timed out waiting for queued transactions to be inserted
'
const
txs
=
[]
for
(
let
i
=
0
;
i
<
numTxs
;
i
++
)
{
const
tx
=
await
env
.
l1Messenger
.
sendMessage
(
`0x
${
`
${
i
}
`
.
repeat
(
40
)}
`
,
`0x0
${
i
}
`
,
1
_000_000
)
)
await
tx
.
wait
()
txs
.
push
(
tx
)
}
}
const
from
=
await
env
.
l1Wallet
.
getAddress
()
for
(
let
i
=
0
;
i
<
numTxs
;
i
++
)
{
// Keep track of an index into the receipts list and
const
l1Tx
=
txs
[
i
]
// increment it for each block fetched.
const
l1TxReceipt
=
await
txs
[
i
].
wait
()
let
receiptIndex
=
0
const
receipt
=
await
env
.
waitForXDomainTransaction
(
// Fetch blocks
l1Tx
,
for
(
i
=
0
;
i
<
numTxs
;
i
++
)
{
Direction
.
L1ToL2
const
block
=
await
l2Provider
.
getBlock
(
startBlock
+
i
)
)
const
hash
=
block
.
transactions
[
0
]
const
l2Tx
=
(
await
l2Provider
.
getTransaction
(
// Use as any hack because additional properties are
receipt
.
remoteTx
.
hash
// added to the transaction response
))
as
any
const
tx
=
await
(
l2Provider
.
getTransaction
(
hash
)
as
any
)
const
params
=
env
.
l2Messenger
.
interface
.
decodeFunctionData
(
'
relayMessage
'
,
l2Tx
.
data
)
// The `to` addresses are defined in the previous test and
expect
(
params
.
_sender
.
toLowerCase
()).
to
.
equal
(
// increment sequentially.
env
.
l1Wallet
.
address
.
toLowerCase
()
expect
(
tx
.
to
).
to
.
be
.
equal
(
'
0x
'
+
`
${
i
}
`
.
repeat
(
40
))
)
// The queue origin is Layer 1
expect
(
params
.
_target
).
to
.
equal
(
'
0x
'
+
`
${
i
}
`
.
repeat
(
40
))
expect
(
tx
.
queueOrigin
).
to
.
be
.
equal
(
'
l1
'
)
expect
(
l2Tx
.
queueOrigin
).
to
.
equal
(
'
l1
'
)
// the L1TxOrigin is equal to the Layer one from
expect
(
l2Tx
.
l1TxOrigin
.
toLowerCase
()).
to
.
equal
(
expect
(
tx
.
l1TxOrigin
).
to
.
be
.
equal
(
from
.
toLowerCase
())
env
.
l1Messenger
.
address
.
toLowerCase
()
expect
(
typeof
tx
.
l1BlockNumber
).
to
.
be
.
equal
(
'
number
'
)
)
// Get the receipt and increment the recept index
expect
(
l2Tx
.
l1BlockNumber
).
to
.
equal
(
l1TxReceipt
.
blockNumber
)
const
receipt
=
receipts
[
receiptIndex
++
]
expect
(
tx
.
l1BlockNumber
).
to
.
be
.
equal
(
receipt
.
blockNumber
)
}
}
})
})
.
timeout
(
100
_000
)
})
})
integration-tests/test/rpc.spec.ts
View file @
685c8f25
...
@@ -2,7 +2,6 @@ import {
...
@@ -2,7 +2,6 @@ import {
injectL2Context
,
injectL2Context
,
TxGasLimit
,
TxGasLimit
,
TxGasPrice
,
TxGasPrice
,
toRpcHexString
,
}
from
'
@eth-optimism/core-utils
'
}
from
'
@eth-optimism/core-utils
'
import
{
Wallet
,
BigNumber
,
Contract
,
ContractFactory
}
from
'
ethers
'
import
{
Wallet
,
BigNumber
,
Contract
,
ContractFactory
}
from
'
ethers
'
import
{
ethers
}
from
'
hardhat
'
import
{
ethers
}
from
'
hardhat
'
...
@@ -13,6 +12,8 @@ import {
...
@@ -13,6 +12,8 @@ import {
DEFAULT_TRANSACTION
,
DEFAULT_TRANSACTION
,
fundUser
,
fundUser
,
expectApprox
,
expectApprox
,
L2_CHAINID
,
IS_LIVE_NETWORK
,
}
from
'
./shared/utils
'
}
from
'
./shared/utils
'
import
chaiAsPromised
from
'
chai-as-promised
'
import
chaiAsPromised
from
'
chai-as-promised
'
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
OptimismEnv
}
from
'
./shared/env
'
...
@@ -132,10 +133,9 @@ describe('Basic RPC tests', () => {
...
@@ -132,10 +133,9 @@ describe('Basic RPC tests', () => {
gasPrice
:
TxGasPrice
,
gasPrice
:
TxGasPrice
,
}
}
const
fee
=
tx
.
gasPrice
.
mul
(
tx
.
gasLimit
)
const
fee
=
tx
.
gasPrice
.
mul
(
tx
.
gasLimit
)
const
gasLimit
=
5920001
await
expect
(
env
.
l2Wallet
.
sendTransaction
(
tx
)).
to
.
be
.
rejectedWith
(
await
expect
(
env
.
l2Wallet
.
sendTransaction
(
tx
)).
to
.
be
.
rejectedWith
(
`fee too low:
${
fee
}
, use at least tx.gasLimit =
${
gasLimit
}
and tx.gasPrice =
${
TxGasPrice
.
toString
()}
`
`fee too low:
${
fee
}
, use at least tx.gasLimit =`
)
)
})
})
...
@@ -317,7 +317,15 @@ describe('Basic RPC tests', () => {
...
@@ -317,7 +317,15 @@ describe('Basic RPC tests', () => {
// canonical transaction chain. This test catches this by
// canonical transaction chain. This test catches this by
// querying for the latest block and then waits and then queries
// querying for the latest block and then waits and then queries
// the latest block again and then asserts that they are the same.
// the latest block again and then asserts that they are the same.
it
(
'
should return the same result when new transactions are not applied
'
,
async
()
=>
{
//
// Needs to be skipped on Prod networks because this test doesn't work when
// other people are sending transactions to the Sequencer at the same time
// as this test is running.
it
(
'
should return the same result when new transactions are not applied
'
,
async
function
()
{
if
(
IS_LIVE_NETWORK
)
{
this
.
skip
()
}
// Get latest block once to start.
// Get latest block once to start.
const
prev
=
await
provider
.
getBlockWithTransactions
(
'
latest
'
)
const
prev
=
await
provider
.
getBlockWithTransactions
(
'
latest
'
)
...
@@ -341,7 +349,7 @@ describe('Basic RPC tests', () => {
...
@@ -341,7 +349,7 @@ describe('Basic RPC tests', () => {
describe
(
'
eth_chainId
'
,
()
=>
{
describe
(
'
eth_chainId
'
,
()
=>
{
it
(
'
should get the correct chainid
'
,
async
()
=>
{
it
(
'
should get the correct chainid
'
,
async
()
=>
{
const
{
chainId
}
=
await
provider
.
getNetwork
()
const
{
chainId
}
=
await
provider
.
getNetwork
()
expect
(
chainId
).
to
.
be
.
eq
(
420
)
expect
(
chainId
).
to
.
be
.
eq
(
L2_CHAINID
)
})
})
})
})
...
...
integration-tests/test/shared/env.ts
View file @
685c8f25
/* Imports: External */
import
{
Contract
,
utils
,
Wallet
}
from
'
ethers
'
import
{
TransactionResponse
}
from
'
@ethersproject/providers
'
import
{
getContractFactory
,
predeploys
}
from
'
@eth-optimism/contracts
'
import
{
getContractFactory
,
predeploys
}
from
'
@eth-optimism/contracts
'
import
{
Watcher
}
from
'
@eth-optimism/core-utils
'
import
{
Watcher
}
from
'
@eth-optimism/core-utils
'
import
{
Contract
,
utils
,
Wallet
}
from
'
ethers
'
import
{
getMessagesAndProofsForL2Transaction
}
from
'
@eth-optimism/message-relayer
'
/* Imports: Internal */
import
{
import
{
getAddressManager
,
getAddressManager
,
l1Provider
,
l1Provider
,
...
@@ -11,6 +16,8 @@ import {
...
@@ -11,6 +16,8 @@ import {
getOvmEth
,
getOvmEth
,
getL1Bridge
,
getL1Bridge
,
getL2Bridge
,
getL2Bridge
,
IS_LIVE_NETWORK
,
sleep
,
}
from
'
./utils
'
}
from
'
./utils
'
import
{
import
{
initWatcher
,
initWatcher
,
...
@@ -18,7 +25,6 @@ import {
...
@@ -18,7 +25,6 @@ import {
Direction
,
Direction
,
waitForXDomainTransaction
,
waitForXDomainTransaction
,
}
from
'
./watcher-utils
'
}
from
'
./watcher-utils
'
import
{
TransactionResponse
}
from
'
@ethersproject/providers
'
/// Helper class for instantiating a test environment with a funded account
/// Helper class for instantiating a test environment with a funded account
export
class
OptimismEnv
{
export
class
OptimismEnv
{
...
@@ -27,6 +33,7 @@ export class OptimismEnv {
...
@@ -27,6 +33,7 @@ export class OptimismEnv {
l1Bridge
:
Contract
l1Bridge
:
Contract
l1Messenger
:
Contract
l1Messenger
:
Contract
ctc
:
Contract
ctc
:
Contract
scc
:
Contract
// L2 Contracts
// L2 Contracts
ovmEth
:
Contract
ovmEth
:
Contract
...
@@ -53,6 +60,7 @@ export class OptimismEnv {
...
@@ -53,6 +60,7 @@ export class OptimismEnv {
this
.
l1Wallet
=
args
.
l1Wallet
this
.
l1Wallet
=
args
.
l1Wallet
this
.
l2Wallet
=
args
.
l2Wallet
this
.
l2Wallet
=
args
.
l2Wallet
this
.
ctc
=
args
.
ctc
this
.
ctc
=
args
.
ctc
this
.
scc
=
args
.
scc
}
}
static
async
new
():
Promise
<
OptimismEnv
>
{
static
async
new
():
Promise
<
OptimismEnv
>
{
...
@@ -85,10 +93,18 @@ export class OptimismEnv {
...
@@ -85,10 +93,18 @@ export class OptimismEnv {
.
connect
(
l2Wallet
)
.
connect
(
l2Wallet
)
.
attach
(
predeploys
.
OVM_GasPriceOracle
)
.
attach
(
predeploys
.
OVM_GasPriceOracle
)
const
sccAddress
=
await
addressManager
.
getAddress
(
'
OVM_StateCommitmentChain
'
)
const
scc
=
getContractFactory
(
'
OVM_StateCommitmentChain
'
)
.
connect
(
l1Wallet
)
.
attach
(
sccAddress
)
return
new
OptimismEnv
({
return
new
OptimismEnv
({
addressManager
,
addressManager
,
l1Bridge
,
l1Bridge
,
ctc
,
ctc
,
scc
,
l1Messenger
,
l1Messenger
,
ovmEth
,
ovmEth
,
gasPriceOracle
,
gasPriceOracle
,
...
@@ -106,4 +122,94 @@ export class OptimismEnv {
...
@@ -106,4 +122,94 @@ export class OptimismEnv {
):
Promise
<
CrossDomainMessagePair
>
{
):
Promise
<
CrossDomainMessagePair
>
{
return
waitForXDomainTransaction
(
this
.
watcher
,
tx
,
direction
)
return
waitForXDomainTransaction
(
this
.
watcher
,
tx
,
direction
)
}
}
/**
* Relays all L2 => L1 messages found in a given L2 transaction.
*
* @param tx Transaction to find messages in.
*/
async
relayXDomainMessages
(
tx
:
Promise
<
TransactionResponse
>
|
TransactionResponse
):
Promise
<
void
>
{
tx
=
await
tx
let
messagePairs
=
[]
while
(
true
)
{
try
{
messagePairs
=
await
getMessagesAndProofsForL2Transaction
(
l1Provider
,
l2Provider
,
this
.
scc
.
address
,
predeploys
.
OVM_L2CrossDomainMessenger
,
tx
.
hash
)
break
}
catch
(
err
)
{
if
(
err
.
message
.
includes
(
'
unable to find state root batch for tx
'
))
{
await
sleep
(
5000
)
}
else
{
throw
err
}
}
}
for
(
const
{
message
,
proof
}
of
messagePairs
)
{
while
(
true
)
{
try
{
const
result
=
await
this
.
l1Messenger
.
connect
(
this
.
l1Wallet
)
.
relayMessage
(
message
.
target
,
message
.
sender
,
message
.
message
,
message
.
messageNonce
,
proof
)
await
result
.
wait
()
break
}
catch
(
err
)
{
if
(
err
.
message
.
includes
(
'
execution failed due to an exception
'
))
{
await
sleep
(
5000
)
}
else
if
(
err
.
message
.
includes
(
'
message has already been received
'
)
)
{
break
}
else
{
throw
err
}
}
}
}
}
}
/**
* Sets the timeout of a test based on the challenge period of the current network. If the
* challenge period is greater than 60s (e.g., on Mainnet) then we skip this test entirely.
*
* @param testctx Function context of the test to modify (i.e. `this` when inside a test).
* @param env Optimism environment used to resolve the StateCommitmentChain.
*/
export
const
useDynamicTimeoutForWithdrawals
=
async
(
testctx
:
any
,
env
:
OptimismEnv
)
=>
{
if
(
!
IS_LIVE_NETWORK
)
{
return
}
const
challengePeriod
=
await
env
.
scc
.
FRAUD_PROOF_WINDOW
()
if
(
challengePeriod
.
gt
(
60
))
{
console
.
log
(
`WARNING: challenge period is greater than 60s (
${
challengePeriod
.
toString
()}
s), skipping test`
)
testctx
.
skip
()
}
// 60s for state root batch to be published + (challenge period x 4)
const
timeoutMs
=
60000
+
challengePeriod
.
toNumber
()
*
1000
*
4
console
.
log
(
`NOTICE: inside a withdrawal test on a prod network, dynamically setting timeout to
${
timeoutMs
}
ms`
)
testctx
.
timeout
(
timeoutMs
)
}
}
integration-tests/test/shared/utils.ts
View file @
685c8f25
import
{
expect
}
from
'
chai
'
import
{
expect
}
from
'
chai
'
import
{
Direction
,
waitForXDomainTransaction
}
from
'
./watcher-utils
'
/* Imports: External */
import
{
getContractFactory
,
getContractInterface
,
predeploys
,
}
from
'
@eth-optimism/contracts
'
import
{
injectL2Context
,
remove0x
,
Watcher
}
from
'
@eth-optimism/core-utils
'
import
{
import
{
Contract
,
Contract
,
Wallet
,
Wallet
,
...
@@ -17,10 +10,24 @@ import {
...
@@ -17,10 +10,24 @@ import {
BigNumber
,
BigNumber
,
utils
,
utils
,
}
from
'
ethers
'
}
from
'
ethers
'
import
{
cleanEnv
,
str
,
num
}
from
'
envalid
'
import
{
getContractFactory
,
getContractInterface
,
predeploys
,
}
from
'
@eth-optimism/contracts
'
import
{
injectL2Context
,
remove0x
,
Watcher
}
from
'
@eth-optimism/core-utils
'
import
{
cleanEnv
,
str
,
num
,
bool
}
from
'
envalid
'
import
dotenv
from
'
dotenv
'
/* Imports: Internal */
import
{
Direction
,
waitForXDomainTransaction
}
from
'
./watcher-utils
'
export
const
GWEI
=
BigNumber
.
from
(
1
e9
)
export
const
GWEI
=
BigNumber
.
from
(
1
e9
)
if
(
process
.
env
.
IS_LIVE_NETWORK
===
'
true
'
)
{
dotenv
.
config
()
}
const
env
=
cleanEnv
(
process
.
env
,
{
const
env
=
cleanEnv
(
process
.
env
,
{
L1_URL
:
str
({
default
:
'
http://localhost:9545
'
}),
L1_URL
:
str
({
default
:
'
http://localhost:9545
'
}),
L2_URL
:
str
({
default
:
'
http://localhost:8545
'
}),
L2_URL
:
str
({
default
:
'
http://localhost:8545
'
}),
...
@@ -37,6 +44,8 @@ const env = cleanEnv(process.env, {
...
@@ -37,6 +44,8 @@ const env = cleanEnv(process.env, {
ADDRESS_MANAGER
:
str
({
ADDRESS_MANAGER
:
str
({
default
:
'
0x5FbDB2315678afecb367f032d93F642f64180aa3
'
,
default
:
'
0x5FbDB2315678afecb367f032d93F642f64180aa3
'
,
}),
}),
L2_CHAINID
:
num
({
default
:
420
}),
IS_LIVE_NETWORK
:
bool
({
default
:
false
}),
})
})
// The hardhat instance
// The hardhat instance
...
@@ -64,6 +73,9 @@ export const PROXY_SEQUENCER_ENTRYPOINT_ADDRESS =
...
@@ -64,6 +73,9 @@ export const PROXY_SEQUENCER_ENTRYPOINT_ADDRESS =
'
0x4200000000000000000000000000000000000004
'
'
0x4200000000000000000000000000000000000004
'
export
const
OVM_ETH_ADDRESS
=
predeploys
.
OVM_ETH
export
const
OVM_ETH_ADDRESS
=
predeploys
.
OVM_ETH
export
const
L2_CHAINID
=
env
.
L2_CHAINID
export
const
IS_LIVE_NETWORK
=
env
.
IS_LIVE_NETWORK
export
const
getAddressManager
=
(
provider
:
any
)
=>
{
export
const
getAddressManager
=
(
provider
:
any
)
=>
{
return
getContractFactory
(
'
Lib_AddressManager
'
)
return
getContractFactory
(
'
Lib_AddressManager
'
)
.
connect
(
provider
)
.
connect
(
provider
)
...
...
ops/docker/Dockerfile.integration-tests
View file @
685c8f25
...
@@ -13,6 +13,9 @@ COPY --from=builder /optimism/node_modules ./node_modules
...
@@ -13,6 +13,9 @@ COPY --from=builder /optimism/node_modules ./node_modules
COPY --from=builder /optimism/packages/core-utils/package.json ./packages/core-utils/package.json
COPY --from=builder /optimism/packages/core-utils/package.json ./packages/core-utils/package.json
COPY --from=builder /optimism/packages/core-utils/dist ./packages/core-utils/dist
COPY --from=builder /optimism/packages/core-utils/dist ./packages/core-utils/dist
COPY --from=builder /optimism/packages/message-relayer/package.json ./packages/message-relayer/package.json
COPY --from=builder /optimism/packages/message-relayer/dist ./packages/message-relayer/dist
COPY --from=builder /optimism/packages/hardhat-ovm/package.json ./packages/hardhat-ovm/package.json
COPY --from=builder /optimism/packages/hardhat-ovm/package.json ./packages/hardhat-ovm/package.json
COPY --from=builder /optimism/packages/hardhat-ovm/dist ./packages/hardhat-ovm/dist
COPY --from=builder /optimism/packages/hardhat-ovm/dist ./packages/hardhat-ovm/dist
...
...
yarn.lock
View file @
685c8f25
...
@@ -5636,6 +5636,11 @@ dot-prop@^6.0.1:
...
@@ -5636,6 +5636,11 @@ dot-prop@^6.0.1:
dependencies:
dependencies:
is-obj "^2.0.0"
is-obj "^2.0.0"
dotenv@^10.0.0:
version "10.0.0"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81"
integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==
dotenv@^8.2.0:
dotenv@^8.2.0:
version "8.6.0"
version "8.6.0"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment