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
cee2a464
Unverified
Commit
cee2a464
authored
Oct 28, 2021
by
Matthew Slipper
Committed by
Kelvin Fichter
Nov 10, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: integration-tests core-utils Kovan integration tests
parent
499d8736
Changes
25
Hide whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
529 additions
and
449 deletions
+529
-449
few-gifts-hope.md
.changeset/few-gifts-hope.md
+5
-0
README.md
integration-tests/README.md
+9
-5
hardhat.config.ts
integration-tests/hardhat.config.ts
+2
-1
package.json
integration-tests/package.json
+1
-1
basic-l1-l2-communication.spec.ts
integration-tests/test/basic-l1-l2-communication.spec.ts
+12
-7
fee-payment.spec.ts
integration-tests/test/fee-payment.spec.ts
+23
-21
native-eth-ovm-calls.spec.ts
integration-tests/test/native-eth-ovm-calls.spec.ts
+48
-26
native-eth.spec.ts
integration-tests/test/native-eth.spec.ts
+3
-9
queue-ingestion.spec.ts
integration-tests/test/queue-ingestion.spec.ts
+2
-1
rpc.spec.ts
integration-tests/test/rpc.spec.ts
+23
-14
env.ts
integration-tests/test/shared/env.ts
+10
-0
stress-test-helpers.ts
integration-tests/test/shared/stress-test-helpers.ts
+90
-130
utils.ts
integration-tests/test/shared/utils.ts
+55
-7
watcher-utils.ts
integration-tests/test/shared/watcher-utils.ts
+5
-0
stress-tests.spec.ts
integration-tests/test/stress-tests.spec.ts
+98
-130
000-hardhat-setup.ts
packages/contracts/deploy/000-hardhat-setup.ts
+19
-11
007-OVM_L1CrossDomainMessenger.deploy.ts
...contracts/deploy/007-OVM_L1CrossDomainMessenger.deploy.ts
+11
-8
008-Proxy__OVM_L1CrossDomainMessenger.deploy.ts
...ts/deploy/008-Proxy__OVM_L1CrossDomainMessenger.deploy.ts
+0
-1
011-set-addresses.ts
packages/contracts/deploy/011-set-addresses.ts
+13
-14
012-initialize-Proxy__L1CrossDomainMessenger.ts
...ts/deploy/012-initialize-Proxy__L1CrossDomainMessenger.ts
+12
-11
014-OVM_L1StandardBridge.deploy.ts
packages/contracts/deploy/014-OVM_L1StandardBridge.deploy.ts
+18
-18
015-finalize.ts
packages/contracts/deploy/015-finalize.ts
+9
-8
hardhat-deploy-ethers.ts
packages/contracts/src/hardhat-deploy-ethers.ts
+13
-25
test-utils.ts
packages/core-utils/src/common/test-utils.ts
+18
-0
test-utils.spec.ts
packages/core-utils/test/common/test-utils.spec.ts
+30
-1
No files found.
.changeset/few-gifts-hope.md
0 → 100644
View file @
cee2a464
---
'
@eth-optimism/core-utils'
:
patch
---
Add awaitCondition to core utils
integration-tests/README.md
View file @
cee2a464
...
@@ -13,19 +13,23 @@ yarn build
...
@@ -13,19 +13,23 @@ yarn build
### Testing a live network
### Testing a live network
Create an
`.env`
file and fill it out.
Testing on a live network is a bit more complicated than testing locally. You'll need the following in order to do so:
Look at
`.env.example`
to know which variables to include.
Once you have your environment set up, run:
1.
A pre-funded wallet with at least 40 ETH.
2.
URLs to an L1 and L2 node.
3.
The address of the address manager contract.
4.
The chain ID of the L2.
Once you have all the necessary info, create a
`.env`
file like the one in
`.env.example`
and fill it in with the values above. Then, run:
```
bash
```
bash
yarn
test
:integration:live
yarn
test
:integration:live
```
```
This will take quite a long time. Kovan, for example, takes about 30 minutes to complete.
You can also set environment variables on the command line instead of inside
`.env`
if you want:
You can also set environment variables on the command line instead of inside
`.env`
if you want:
```
bash
```
bash
L1_URL
=
whatever
L2_URL
=
whatever yarn
test
:integration:live
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 @
cee2a464
...
@@ -4,6 +4,7 @@ import { HardhatUserConfig } from 'hardhat/types'
...
@@ -4,6 +4,7 @@ import { HardhatUserConfig } from 'hardhat/types'
import
'
@nomiclabs/hardhat-ethers
'
import
'
@nomiclabs/hardhat-ethers
'
import
'
@nomiclabs/hardhat-waffle
'
import
'
@nomiclabs/hardhat-waffle
'
import
'
hardhat-gas-reporter
'
import
'
hardhat-gas-reporter
'
import
{
isLiveNetwork
}
from
'
./test/shared/utils
'
const
enableGasReport
=
!!
process
.
env
.
ENABLE_GAS_REPORT
const
enableGasReport
=
!!
process
.
env
.
ENABLE_GAS_REPORT
...
@@ -14,7 +15,7 @@ const config: HardhatUserConfig = {
...
@@ -14,7 +15,7 @@ const config: HardhatUserConfig = {
},
},
},
},
mocha
:
{
mocha
:
{
timeout
:
75
_000
,
timeout
:
isLiveNetwork
()
?
300
_000
:
75
_000
,
},
},
solidity
:
{
solidity
:
{
version
:
'
0.8.9
'
,
version
:
'
0.8.9
'
,
...
...
integration-tests/package.json
View file @
cee2a464
...
@@ -11,7 +11,7 @@
...
@@ -11,7 +11,7 @@
"lint:check"
:
"eslint ."
,
"lint:check"
:
"eslint ."
,
"build"
:
"hardhat compile"
,
"build"
:
"hardhat compile"
,
"test:integration"
:
"hardhat --network optimism test"
,
"test:integration"
:
"hardhat --network optimism test"
,
"test:integration:live"
:
"IS_LIVE_NETWORK=true hardhat --network optimism test"
,
"test:integration:live"
:
"
NO_NETWORK=true
IS_LIVE_NETWORK=true hardhat --network optimism 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"
"clean"
:
"rimraf cache artifacts"
},
},
...
...
integration-tests/test/basic-l1-l2-communication.spec.ts
View file @
cee2a464
...
@@ -2,13 +2,14 @@ import { expect } from 'chai'
...
@@ -2,13 +2,14 @@ import { expect } from 'chai'
/* Imports: External */
/* Imports: External */
import
{
Contract
,
ContractFactory
}
from
'
ethers
'
import
{
Contract
,
ContractFactory
}
from
'
ethers
'
import
{
applyL1ToL2Alias
,
sleep
}
from
'
@eth-optimism/core-utils
'
import
{
applyL1ToL2Alias
}
from
'
@eth-optimism/core-utils
'
/* Imports: Internal */
/* Imports: Internal */
import
simpleStorageJson
from
'
../artifacts/contracts/SimpleStorage.sol/SimpleStorage.json
'
import
simpleStorageJson
from
'
../artifacts/contracts/SimpleStorage.sol/SimpleStorage.json
'
import
l2ReverterJson
from
'
../artifacts/contracts/Reverter.sol/Reverter.json
'
import
l2ReverterJson
from
'
../artifacts/contracts/Reverter.sol/Reverter.json
'
import
{
Direction
}
from
'
./shared/watcher-utils
'
import
{
Direction
}
from
'
./shared/watcher-utils
'
import
{
OptimismEnv
,
useDynamicTimeoutForWithdrawals
}
from
'
./shared/env
'
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
awaitCondition
}
from
'
@eth-optimism/core-utils
'
describe
(
'
Basic L1<>L2 Communication
'
,
async
()
=>
{
describe
(
'
Basic L1<>L2 Communication
'
,
async
()
=>
{
let
Factory__L1SimpleStorage
:
ContractFactory
let
Factory__L1SimpleStorage
:
ContractFactory
...
@@ -48,9 +49,7 @@ describe('Basic L1<>L2 Communication', async () => {
...
@@ -48,9 +49,7 @@ describe('Basic L1<>L2 Communication', async () => {
})
})
describe
(
'
L2 => L1
'
,
()
=>
{
describe
(
'
L2 => L1
'
,
()
=>
{
it
(
'
should be able to perform a withdrawal from L2 -> L1
'
,
async
function
()
{
it
(
'
should be able to perform a withdrawal from L2 -> L1
'
,
async
()
=>
{
await
useDynamicTimeoutForWithdrawals
(
this
,
env
)
const
value
=
`0x
${
'
77
'
.
repeat
(
32
)}
`
const
value
=
`0x
${
'
77
'
.
repeat
(
32
)}
`
// Send L2 -> L1 message.
// Send L2 -> L1 message.
...
@@ -114,8 +113,14 @@ describe('Basic L1<>L2 Communication', async () => {
...
@@ -114,8 +113,14 @@ describe('Basic L1<>L2 Communication', async () => {
])
])
)
)
// TODO: We need to have a function that can wait for enqueued txs.
await
awaitCondition
(
await
sleep
(
10000
)
async
()
=>
{
const
sender
=
await
L2SimpleStorage
.
msgSender
()
return
sender
===
env
.
l1Wallet
.
address
},
2000
,
60
)
// No aliasing when an EOA goes directly to L2.
// No aliasing when an EOA goes directly to L2.
expect
(
await
L2SimpleStorage
.
msgSender
()).
to
.
equal
(
env
.
l1Wallet
.
address
)
expect
(
await
L2SimpleStorage
.
msgSender
()).
to
.
equal
(
env
.
l1Wallet
.
address
)
...
...
integration-tests/test/fee-payment.spec.ts
View file @
cee2a464
...
@@ -13,11 +13,14 @@ import {
...
@@ -13,11 +13,14 @@ import {
}
from
'
@eth-optimism/contracts
'
}
from
'
@eth-optimism/contracts
'
/* Imports: Internal */
/* Imports: Internal */
import
{
IS_LIVE_NETWORK
}
from
'
./shared/utils
'
import
{
isLiveNetwork
}
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
'
const
setPrices
=
async
(
env
:
OptimismEnv
,
value
:
number
|
BigNumber
)
=>
{
const
setPrices
=
async
(
env
:
OptimismEnv
,
value
:
number
|
BigNumber
)
=>
{
if
(
isLiveNetwork
())
{
return
}
const
gasPrice
=
await
env
.
gasPriceOracle
.
setGasPrice
(
value
)
const
gasPrice
=
await
env
.
gasPriceOracle
.
setGasPrice
(
value
)
await
gasPrice
.
wait
()
await
gasPrice
.
wait
()
const
baseFee
=
await
env
.
gasPriceOracle
.
setL1BaseFee
(
value
)
const
baseFee
=
await
env
.
gasPriceOracle
.
setL1BaseFee
(
value
)
...
@@ -32,20 +35,22 @@ describe('Fee Payment Integration Tests', async () => {
...
@@ -32,20 +35,22 @@ describe('Fee Payment Integration Tests', async () => {
env
=
await
OptimismEnv
.
new
()
env
=
await
OptimismEnv
.
new
()
})
})
it
(
`should return eth_gasPrice equal to OVM_GasPriceOracle.gasPrice`
,
async
()
=>
{
if
(
!
isLiveNetwork
())
{
const
assertGasPrice
=
async
()
=>
{
it
(
`should return eth_gasPrice equal to OVM_GasPriceOracle.gasPrice`
,
async
()
=>
{
const
gasPrice
=
await
env
.
l2Wallet
.
getGasPrice
()
const
assertGasPrice
=
async
()
=>
{
const
oracleGasPrice
=
await
env
.
gasPriceOracle
.
gasPrice
()
const
gasPrice
=
await
env
.
l2Wallet
.
getGasPrice
()
expect
(
gasPrice
).
to
.
deep
.
equal
(
oracleGasPrice
)
const
oracleGasPrice
=
await
env
.
gasPriceOracle
.
gasPrice
()
}
expect
(
gasPrice
).
to
.
deep
.
equal
(
oracleGasPrice
)
}
assertGasPrice
()
assertGasPrice
()
// update the gas price
// update the gas price
const
tx
=
await
env
.
gasPriceOracle
.
setGasPrice
(
1000
)
const
tx
=
await
env
.
gasPriceOracle
.
setGasPrice
(
1000
)
await
tx
.
wait
()
await
tx
.
wait
()
assertGasPrice
()
assertGasPrice
()
})
})
}
it
(
'
Paying a nonzero but acceptable gasPrice fee
'
,
async
()
=>
{
it
(
'
Paying a nonzero but acceptable gasPrice fee
'
,
async
()
=>
{
await
setPrices
(
env
,
1000
)
await
setPrices
(
env
,
1000
)
...
@@ -152,19 +157,16 @@ describe('Fee Payment Integration Tests', async () => {
...
@@ -152,19 +157,16 @@ describe('Fee Payment Integration Tests', async () => {
})
})
it
(
'
should be able to withdraw fees back to L1 once the minimum is met
'
,
async
function
()
{
it
(
'
should be able to withdraw fees back to L1 once the minimum is met
'
,
async
function
()
{
if
(
isLiveNetwork
())
{
this
.
skip
()
return
}
const
l1FeeWallet
=
await
env
.
sequencerFeeVault
.
l1FeeWallet
()
const
l1FeeWallet
=
await
env
.
sequencerFeeVault
.
l1FeeWallet
()
const
balanceBefore
=
await
env
.
l1Wallet
.
provider
.
getBalance
(
l1FeeWallet
)
const
balanceBefore
=
await
env
.
l1Wallet
.
provider
.
getBalance
(
l1FeeWallet
)
const
withdrawalAmount
=
await
env
.
sequencerFeeVault
.
MIN_WITHDRAWAL_AMOUNT
()
const
withdrawalAmount
=
await
env
.
sequencerFeeVault
.
MIN_WITHDRAWAL_AMOUNT
()
const
l2WalletBalance
=
await
env
.
l2Wallet
.
getBalance
()
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.
const
tx
=
await
env
.
l2Wallet
.
sendTransaction
({
const
tx
=
await
env
.
l2Wallet
.
sendTransaction
({
...
...
integration-tests/test/native-eth-ovm-calls.spec.ts
View file @
cee2a464
import
{
BigNumber
,
Contract
,
ContractFactory
,
Wallet
}
from
'
ethers
'
import
{
BigNumber
,
BigNumberish
,
Contract
,
ContractFactory
,
Wallet
,
}
from
'
ethers
'
import
{
ethers
}
from
'
hardhat
'
import
{
ethers
}
from
'
hardhat
'
import
chai
,
{
expect
}
from
'
chai
'
import
chai
,
{
expect
}
from
'
chai
'
import
{
GWEI
,
fundUser
,
encodeSolidityRevertMessage
}
from
'
./shared/utils
'
import
{
fundUser
,
encodeSolidityRevertMessage
,
gasPriceForL2
,
}
from
'
./shared/utils
'
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
solidity
}
from
'
ethereum-waffle
'
import
{
solidity
}
from
'
ethereum-waffle
'
import
{
sleep
}
from
'
../../packages/core-utils/dist
'
import
{
getContractFactory
,
getContractInterface
,
}
from
'
../../packages/contracts/dist
'
import
{
Interface
}
from
'
ethers/lib/utils
'
chai
.
use
(
solidity
)
chai
.
use
(
solidity
)
...
@@ -32,15 +36,16 @@ describe('Native ETH value integration tests', () => {
...
@@ -32,15 +36,16 @@ describe('Native ETH value integration tests', () => {
]
]
}
}
const
checkBalances
=
async
(
const
expectBalancesWithinRange
=
(
expectedBalances
:
BigNumber
[]
bal
:
BigNumber
,
):
Promise
<
void
>
=>
{
lte
:
BigNumber
,
const
realBalances
=
await
getBalances
()
gte
:
BigNumber
expect
(
realBalances
[
0
]).
to
.
deep
.
eq
(
expectedBalances
[
0
])
)
=>
{
expect
(
realBalances
[
1
]).
to
.
deep
.
eq
(
expectedBalances
[
1
])
expect
(
bal
.
lte
(
lte
)).
to
.
be
.
true
expect
(
bal
.
gte
(
gte
)).
to
.
be
.
true
}
}
const
value
=
10
const
value
=
ethers
.
utils
.
parseEther
(
'
0.01
'
)
await
fundUser
(
env
.
watcher
,
env
.
l1Bridge
,
value
,
wallet
.
address
)
await
fundUser
(
env
.
watcher
,
env
.
l1Bridge
,
value
,
wallet
.
address
)
const
initialBalances
=
await
getBalances
()
const
initialBalances
=
await
getBalances
()
...
@@ -48,23 +53,40 @@ describe('Native ETH value integration tests', () => {
...
@@ -48,23 +53,40 @@ describe('Native ETH value integration tests', () => {
const
there
=
await
wallet
.
sendTransaction
({
const
there
=
await
wallet
.
sendTransaction
({
to
:
other
.
address
,
to
:
other
.
address
,
value
,
value
,
gasPrice
:
0
,
gasPrice
:
await
gasPriceForL2
()
,
})
})
await
there
.
wait
()
const
thereReceipt
=
await
there
.
wait
()
const
thereGas
=
thereReceipt
.
gasUsed
.
mul
(
there
.
gasPrice
)
await
checkBalances
([
const
thereBalances
=
await
getBalances
()
const
thereWithGas
=
initialBalances
[
0
].
sub
(
value
).
sub
(
thereGas
).
sub
(
100000
)
expectBalancesWithinRange
(
thereBalances
[
0
],
initialBalances
[
0
].
sub
(
value
),
initialBalances
[
0
].
sub
(
value
),
initialBalances
[
1
].
add
(
value
),
thereWithGas
])
)
expect
(
initialBalances
[
1
].
add
(
value
).
eq
(
thereBalances
[
1
]))
const
backVal
=
ethers
.
utils
.
parseEther
(
'
0.005
'
)
const
backAgain
=
await
other
.
sendTransaction
({
const
backAgain
=
await
other
.
sendTransaction
({
to
:
wallet
.
address
,
to
:
wallet
.
address
,
value
,
value
:
backVal
,
gasPrice
:
0
,
gasPrice
:
await
gasPriceForL2
()
,
})
})
await
backAgain
.
wait
()
const
backReceipt
=
await
backAgain
.
wait
()
const
backGas
=
backReceipt
.
gasUsed
.
mul
(
backAgain
.
gasPrice
)
await
checkBalances
(
initialBalances
)
const
backBalances
=
await
getBalances
()
expectBalancesWithinRange
(
backBalances
[
0
],
initialBalances
[
0
].
sub
(
thereGas
).
sub
(
backVal
),
initialBalances
[
0
].
sub
(
thereGas
).
sub
(
backVal
).
sub
(
200000
)
)
expectBalancesWithinRange
(
backBalances
[
1
],
initialBalances
[
1
].
add
(
backVal
).
sub
(
backGas
),
initialBalances
[
1
].
add
(
backVal
).
sub
(
backGas
).
sub
(
200000
)
)
})
})
describe
(
`calls between OVM contracts with native ETH value and relevant opcodes`
,
async
()
=>
{
describe
(
`calls between OVM contracts with native ETH value and relevant opcodes`
,
async
()
=>
{
...
@@ -155,7 +177,7 @@ describe('Native ETH value integration tests', () => {
...
@@ -155,7 +177,7 @@ describe('Native ETH value integration tests', () => {
it
(
'
should allow ETH to be sent
'
,
async
()
=>
{
it
(
'
should allow ETH to be sent
'
,
async
()
=>
{
const
sendAmount
=
15
const
sendAmount
=
15
const
tx
=
await
ValueCalls0
.
simpleSend
(
ValueCalls1
.
address
,
sendAmount
,
{
const
tx
=
await
ValueCalls0
.
simpleSend
(
ValueCalls1
.
address
,
sendAmount
,
{
gasPrice
:
0
,
gasPrice
:
await
gasPriceForL2
()
,
})
})
await
tx
.
wait
()
await
tx
.
wait
()
...
...
integration-tests/test/native-eth.spec.ts
View file @
cee2a464
...
@@ -183,9 +183,7 @@ describe('Native ETH Integration Tests', async () => {
...
@@ -183,9 +183,7 @@ describe('Native ETH Integration Tests', async () => {
).
to
.
be
.
reverted
).
to
.
be
.
reverted
})
})
it
(
'
withdraw
'
,
async
function
()
{
it
(
'
withdraw
'
,
async
()
=>
{
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
(
...
@@ -227,9 +225,7 @@ describe('Native ETH Integration Tests', async () => {
...
@@ -227,9 +225,7 @@ describe('Native ETH Integration Tests', async () => {
)
)
})
})
it
(
'
withdrawTo
'
,
async
function
()
{
it
(
'
withdrawTo
'
,
async
()
=>
{
await
useDynamicTimeoutForWithdrawals
(
this
,
env
)
const
withdrawAmount
=
BigNumber
.
from
(
3
)
const
withdrawAmount
=
BigNumber
.
from
(
3
)
const
preBalances
=
await
getBalances
(
env
)
const
preBalances
=
await
getBalances
(
env
)
...
@@ -287,9 +283,7 @@ describe('Native ETH Integration Tests', async () => {
...
@@ -287,9 +283,7 @@ describe('Native ETH Integration Tests', async () => {
)
)
})
})
it
(
'
deposit, transfer, withdraw
'
,
async
function
()
{
it
(
'
deposit, transfer, withdraw
'
,
async
()
=>
{
await
useDynamicTimeoutForWithdrawals
(
this
,
env
)
// 1. deposit
// 1. deposit
const
amount
=
utils
.
parseEther
(
'
1
'
)
const
amount
=
utils
.
parseEther
(
'
1
'
)
await
env
.
waitForXDomainTransaction
(
await
env
.
waitForXDomainTransaction
(
...
...
integration-tests/test/queue-ingestion.spec.ts
View file @
cee2a464
...
@@ -7,6 +7,7 @@ import { injectL2Context, applyL1ToL2Alias } from '@eth-optimism/core-utils'
...
@@ -7,6 +7,7 @@ import { injectL2Context, applyL1ToL2Alias } from '@eth-optimism/core-utils'
/* Imports: External */
/* Imports: External */
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
Direction
}
from
'
./shared/watcher-utils
'
import
{
Direction
}
from
'
./shared/watcher-utils
'
import
{
isLiveNetwork
}
from
'
./shared/utils
'
describe
(
'
Queue Ingestion
'
,
()
=>
{
describe
(
'
Queue Ingestion
'
,
()
=>
{
let
env
:
OptimismEnv
let
env
:
OptimismEnv
...
@@ -61,5 +62,5 @@ describe('Queue Ingestion', () => {
...
@@ -61,5 +62,5 @@ describe('Queue Ingestion', () => {
)
)
expect
(
l2Tx
.
l1BlockNumber
).
to
.
equal
(
l1TxReceipt
.
blockNumber
)
expect
(
l2Tx
.
l1BlockNumber
).
to
.
equal
(
l1TxReceipt
.
blockNumber
)
}
}
}).
timeout
(
100
_000
)
}).
timeout
(
isLiveNetwork
()
?
300
_000
:
100
_000
)
})
})
integration-tests/test/rpc.spec.ts
View file @
cee2a464
...
@@ -6,10 +6,12 @@ import chai, { expect } from 'chai'
...
@@ -6,10 +6,12 @@ import chai, { expect } from 'chai'
import
{
import
{
sleep
,
sleep
,
l2Provider
,
l2Provider
,
DEFAULT_TRANSACTION
,
defaultTransactionFactory
,
fundUser
,
fundUser
,
L2_CHAINID
,
L2_CHAINID
,
IS_LIVE_NETWORK
,
IS_LIVE_NETWORK
,
isLiveNetwork
,
gasPriceForL2
,
}
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
'
...
@@ -57,7 +59,8 @@ describe('Basic RPC tests', () => {
...
@@ -57,7 +59,8 @@ describe('Basic RPC tests', () => {
describe
(
'
eth_sendRawTransaction
'
,
()
=>
{
describe
(
'
eth_sendRawTransaction
'
,
()
=>
{
it
(
'
should correctly process a valid transaction
'
,
async
()
=>
{
it
(
'
should correctly process a valid transaction
'
,
async
()
=>
{
const
tx
=
DEFAULT_TRANSACTION
const
tx
=
defaultTransactionFactory
()
tx
.
gasPrice
=
await
gasPriceForL2
()
const
nonce
=
await
wallet
.
getTransactionCount
()
const
nonce
=
await
wallet
.
getTransactionCount
()
const
result
=
await
wallet
.
sendTransaction
(
tx
)
const
result
=
await
wallet
.
sendTransaction
(
tx
)
...
@@ -70,7 +73,8 @@ describe('Basic RPC tests', () => {
...
@@ -70,7 +73,8 @@ describe('Basic RPC tests', () => {
it
(
'
should not accept a transaction with the wrong chain ID
'
,
async
()
=>
{
it
(
'
should not accept a transaction with the wrong chain ID
'
,
async
()
=>
{
const
tx
=
{
const
tx
=
{
...
DEFAULT_TRANSACTION
,
...
defaultTransactionFactory
(),
gasPrice
:
await
gasPriceForL2
(),
chainId
:
(
await
wallet
.
getChainId
())
+
1
,
chainId
:
(
await
wallet
.
getChainId
())
+
1
,
}
}
...
@@ -81,7 +85,8 @@ describe('Basic RPC tests', () => {
...
@@ -81,7 +85,8 @@ describe('Basic RPC tests', () => {
it
(
'
should not accept a transaction without a chain ID
'
,
async
()
=>
{
it
(
'
should not accept a transaction without a chain ID
'
,
async
()
=>
{
const
tx
=
{
const
tx
=
{
...
DEFAULT_TRANSACTION
,
...
defaultTransactionFactory
(),
gasPrice
:
await
gasPriceForL2
(),
chainId
:
null
,
// Disables EIP155 transaction signing.
chainId
:
null
,
// Disables EIP155 transaction signing.
}
}
...
@@ -92,7 +97,8 @@ describe('Basic RPC tests', () => {
...
@@ -92,7 +97,8 @@ describe('Basic RPC tests', () => {
it
(
'
should accept a transaction with a value
'
,
async
()
=>
{
it
(
'
should accept a transaction with a value
'
,
async
()
=>
{
const
tx
=
{
const
tx
=
{
...
DEFAULT_TRANSACTION
,
...
defaultTransactionFactory
(),
gasPrice
:
await
gasPriceForL2
(),
chainId
:
await
env
.
l2Wallet
.
getChainId
(),
chainId
:
await
env
.
l2Wallet
.
getChainId
(),
data
:
'
0x
'
,
data
:
'
0x
'
,
value
:
ethers
.
utils
.
parseEther
(
'
0.1
'
),
value
:
ethers
.
utils
.
parseEther
(
'
0.1
'
),
...
@@ -103,15 +109,16 @@ describe('Basic RPC tests', () => {
...
@@ -103,15 +109,16 @@ describe('Basic RPC tests', () => {
const
receipt
=
await
result
.
wait
()
const
receipt
=
await
result
.
wait
()
expect
(
receipt
.
status
).
to
.
deep
.
equal
(
1
)
expect
(
receipt
.
status
).
to
.
deep
.
equal
(
1
)
expect
(
await
provider
.
getBalance
(
env
.
l2Wallet
.
address
)).
to
.
deep
.
equal
(
const
balAfter
=
await
provider
.
getBalance
(
env
.
l2Wallet
.
address
)
balanceBefore
.
sub
(
ethers
.
utils
.
parseEther
(
'
0.1
'
))
expect
(
balAfter
.
lte
(
balanceBefore
.
sub
(
ethers
.
utils
.
parseEther
(
'
0.1
'
)))).
to
)
.
be
.
true
})
})
it
(
'
should reject a transaction with higher value than user balance
'
,
async
()
=>
{
it
(
'
should reject a transaction with higher value than user balance
'
,
async
()
=>
{
const
balance
=
await
env
.
l2Wallet
.
getBalance
()
const
balance
=
await
env
.
l2Wallet
.
getBalance
()
const
tx
=
{
const
tx
=
{
...
DEFAULT_TRANSACTION
,
...
defaultTransactionFactory
(),
gasPrice
:
await
gasPriceForL2
(),
chainId
:
await
env
.
l2Wallet
.
getChainId
(),
chainId
:
await
env
.
l2Wallet
.
getChainId
(),
data
:
'
0x
'
,
data
:
'
0x
'
,
value
:
balance
.
add
(
ethers
.
utils
.
parseEther
(
'
1
'
)),
value
:
balance
.
add
(
ethers
.
utils
.
parseEther
(
'
1
'
)),
...
@@ -240,7 +247,7 @@ describe('Basic RPC tests', () => {
...
@@ -240,7 +247,7 @@ describe('Basic RPC tests', () => {
it
(
'
includes L1 gas price and L1 gas used
'
,
async
()
=>
{
it
(
'
includes L1 gas price and L1 gas used
'
,
async
()
=>
{
const
tx
=
await
env
.
l2Wallet
.
populateTransaction
({
const
tx
=
await
env
.
l2Wallet
.
populateTransaction
({
to
:
env
.
l2Wallet
.
address
,
to
:
env
.
l2Wallet
.
address
,
gasPrice
:
1
,
gasPrice
:
isLiveNetwork
()
?
10000
:
1
,
})
})
const
raw
=
serialize
({
const
raw
=
serialize
({
...
@@ -274,7 +281,8 @@ describe('Basic RPC tests', () => {
...
@@ -274,7 +281,8 @@ describe('Basic RPC tests', () => {
describe
(
'
eth_getTransactionByHash
'
,
()
=>
{
describe
(
'
eth_getTransactionByHash
'
,
()
=>
{
it
(
'
should be able to get all relevant l1/l2 transaction data
'
,
async
()
=>
{
it
(
'
should be able to get all relevant l1/l2 transaction data
'
,
async
()
=>
{
const
tx
=
DEFAULT_TRANSACTION
const
tx
=
defaultTransactionFactory
()
tx
.
gasPrice
=
await
gasPriceForL2
()
const
result
=
await
wallet
.
sendTransaction
(
tx
)
const
result
=
await
wallet
.
sendTransaction
(
tx
)
await
result
.
wait
()
await
result
.
wait
()
...
@@ -288,7 +296,8 @@ describe('Basic RPC tests', () => {
...
@@ -288,7 +296,8 @@ describe('Basic RPC tests', () => {
describe
(
'
eth_getBlockByHash
'
,
()
=>
{
describe
(
'
eth_getBlockByHash
'
,
()
=>
{
it
(
'
should return the block and all included transactions
'
,
async
()
=>
{
it
(
'
should return the block and all included transactions
'
,
async
()
=>
{
// Send a transaction and wait for it to be mined.
// Send a transaction and wait for it to be mined.
const
tx
=
DEFAULT_TRANSACTION
const
tx
=
defaultTransactionFactory
()
tx
.
gasPrice
=
await
gasPriceForL2
()
const
result
=
await
wallet
.
sendTransaction
(
tx
)
const
result
=
await
wallet
.
sendTransaction
(
tx
)
const
receipt
=
await
result
.
wait
()
const
receipt
=
await
result
.
wait
()
...
@@ -362,7 +371,7 @@ describe('Basic RPC tests', () => {
...
@@ -362,7 +371,7 @@ describe('Basic RPC tests', () => {
let
lastEstimate
:
BigNumber
let
lastEstimate
:
BigNumber
for
(
let
i
=
0
;
i
<
10
;
i
++
)
{
for
(
let
i
=
0
;
i
<
10
;
i
++
)
{
const
estimate
=
await
l2Provider
.
estimateGas
({
const
estimate
=
await
l2Provider
.
estimateGas
({
to
:
DEFAULT_TRANSACTION
.
to
,
to
:
defaultTransactionFactory
()
.
to
,
value
:
0
,
value
:
0
,
})
})
...
@@ -376,7 +385,7 @@ describe('Basic RPC tests', () => {
...
@@ -376,7 +385,7 @@ describe('Basic RPC tests', () => {
it
(
'
should return a gas estimate for txs with empty data
'
,
async
()
=>
{
it
(
'
should return a gas estimate for txs with empty data
'
,
async
()
=>
{
const
estimate
=
await
l2Provider
.
estimateGas
({
const
estimate
=
await
l2Provider
.
estimateGas
({
to
:
DEFAULT_TRANSACTION
.
to
,
to
:
defaultTransactionFactory
()
.
to
,
value
:
0
,
value
:
0
,
})
})
// 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%
...
...
integration-tests/test/shared/env.ts
View file @
cee2a464
...
@@ -185,6 +185,16 @@ export class OptimismEnv {
...
@@ -185,6 +185,16 @@ export class OptimismEnv {
await
sleep
(
5000
)
await
sleep
(
5000
)
}
else
if
(
err
.
message
.
includes
(
'
Nonce too low
'
))
{
}
else
if
(
err
.
message
.
includes
(
'
Nonce too low
'
))
{
await
sleep
(
5000
)
await
sleep
(
5000
)
}
else
if
(
err
.
message
.
includes
(
'
transaction was replaced
'
))
{
// this happens when we run tests in parallel
await
sleep
(
5000
)
}
else
if
(
err
.
message
.
includes
(
'
another transaction with same nonce in the queue
'
)
)
{
// this happens when we run tests in parallel
await
sleep
(
5000
)
}
else
if
(
}
else
if
(
err
.
message
.
includes
(
'
message has already been received
'
)
err
.
message
.
includes
(
'
message has already been received
'
)
)
{
)
{
...
...
integration-tests/test/shared/stress-test-helpers.ts
View file @
cee2a464
...
@@ -4,6 +4,7 @@ import { ethers } from 'ethers'
...
@@ -4,6 +4,7 @@ import { ethers } from 'ethers'
/* Imports: Internal */
/* Imports: Internal */
import
{
OptimismEnv
}
from
'
./env
'
import
{
OptimismEnv
}
from
'
./env
'
import
{
Direction
}
from
'
./watcher-utils
'
import
{
Direction
}
from
'
./watcher-utils
'
import
{
gasPriceForL1
,
gasPriceForL2
,
sleep
}
from
'
./utils
'
interface
TransactionParams
{
interface
TransactionParams
{
contract
:
ethers
.
Contract
contract
:
ethers
.
Contract
...
@@ -14,13 +15,29 @@ interface TransactionParams {
...
@@ -14,13 +15,29 @@ interface TransactionParams {
// Arbitrary big amount of gas for the L1<>L2 messages.
// Arbitrary big amount of gas for the L1<>L2 messages.
const
MESSAGE_GAS
=
8
_000_000
const
MESSAGE_GAS
=
8
_000_000
export
const
executeL1ToL2Transactions
=
async
(
export
const
fundRandomWallet
=
async
(
env
:
OptimismEnv
,
env
:
OptimismEnv
,
txs
:
TransactionParams
[]
wallet
:
ethers
.
Wallet
,
value
:
ethers
.
BigNumber
):
Promise
<
ethers
.
Wallet
>
=>
{
const
fundTx
=
await
env
.
l1Wallet
.
sendTransaction
({
gasLimit
:
25
_000
,
to
:
wallet
.
address
,
gasPrice
:
await
gasPriceForL1
(
env
),
value
,
})
await
fundTx
.
wait
()
return
wallet
}
export
const
executeL1ToL2Transaction
=
async
(
env
:
OptimismEnv
,
wallet
:
ethers
.
Wallet
,
tx
:
TransactionParams
)
=>
{
)
=>
{
for
(
const
tx
of
txs
)
{
const
signer
=
wallet
.
connect
(
env
.
l1Wallet
.
provider
)
const
signer
=
ethers
.
Wallet
.
createRandom
().
connect
(
env
.
l1Wallet
.
provider
)
const
receipt
=
await
retryOnNonceError
(
async
()
=>
const
receipt
=
await
env
.
l1Messenger
env
.
l1Messenger
.
connect
(
signer
)
.
connect
(
signer
)
.
sendMessage
(
.
sendMessage
(
tx
.
contract
.
address
,
tx
.
contract
.
address
,
...
@@ -30,21 +47,21 @@ export const executeL1ToL2Transactions = async (
...
@@ -30,21 +47,21 @@ export const executeL1ToL2Transactions = async (
),
),
MESSAGE_GAS
,
MESSAGE_GAS
,
{
{
gasPrice
:
0
,
gasPrice
:
await
gasPriceForL1
(
env
)
,
}
}
)
)
)
await
env
.
waitForXDomainTransaction
(
receipt
,
Direction
.
L1ToL2
)
await
env
.
waitForXDomainTransaction
(
receipt
,
Direction
.
L1ToL2
)
}
}
}
export
const
executeL2ToL1Transaction
s
=
async
(
export
const
executeL2ToL1Transaction
=
async
(
env
:
OptimismEnv
,
env
:
OptimismEnv
,
txs
:
TransactionParams
[]
wallet
:
ethers
.
Wallet
,
tx
:
TransactionParams
)
=>
{
)
=>
{
for
(
const
tx
of
txs
)
{
const
signer
=
wallet
.
connect
(
env
.
l2Wallet
.
provider
)
const
signer
=
ethers
.
Wallet
.
createRandom
().
connect
(
env
.
l2Wallet
.
provider
)
const
receipt
=
await
retryOnNonceError
(()
=>
const
receipt
=
await
env
.
l2Messenger
env
.
l2Messenger
.
connect
(
signer
)
.
connect
(
signer
)
.
sendMessage
(
.
sendMessage
(
tx
.
contract
.
address
,
tx
.
contract
.
address
,
...
@@ -54,162 +71,105 @@ export const executeL2ToL1Transactions = async (
...
@@ -54,162 +71,105 @@ export const executeL2ToL1Transactions = async (
),
),
MESSAGE_GAS
,
MESSAGE_GAS
,
{
{
gasPrice
:
0
,
gasPrice
:
gasPriceForL2
()
,
}
}
)
)
)
await
env
.
relayXDomainMessages
(
receipt
)
await
env
.
relayXDomainMessages
(
receipt
)
await
env
.
waitForXDomainTransaction
(
receipt
,
Direction
.
L2ToL1
)
await
env
.
waitForXDomainTransaction
(
receipt
,
Direction
.
L2ToL1
)
}
}
}
export
const
executeL2Transaction
s
=
async
(
export
const
executeL2Transaction
=
async
(
env
:
OptimismEnv
,
env
:
OptimismEnv
,
txs
:
TransactionParams
[]
wallet
:
ethers
.
Wallet
,
tx
:
TransactionParams
)
=>
{
)
=>
{
for
(
const
tx
of
txs
)
{
const
signer
=
wallet
.
connect
(
env
.
l2Wallet
.
provider
)
const
signer
=
ethers
.
Wallet
.
createRandom
().
connect
(
env
.
l2Wallet
.
provider
)
const
result
=
await
retryOnNonceError
(()
=>
const
result
=
await
tx
.
contract
tx
.
contract
.
connect
(
signer
)
.
connect
(
signer
)
.
functions
[
tx
.
functionName
](...
tx
.
functionParams
,
{
.
functions
[
tx
.
functionName
](...
tx
.
functionParams
,
{
gasPrice
:
0
,
gasPrice
:
gasPriceForL2
()
,
})
})
await
result
.
wait
(
)
)
}
await
result
.
wait
()
}
}
export
const
executeRepeatedL1ToL2Transactions
=
async
(
export
const
executeRepeatedL1ToL2Transactions
=
async
(
env
:
OptimismEnv
,
env
:
OptimismEnv
,
tx
:
TransactionParams
,
wallets
:
ethers
.
Wallet
[]
,
count
:
number
tx
:
TransactionParams
)
=>
{
)
=>
{
await
executeL1ToL2Transactions
(
for
(
const
wallet
of
wallets
)
{
env
,
await
executeL1ToL2Transaction
(
env
,
wallet
,
tx
)
[...
Array
(
count
).
keys
()].
map
(()
=>
tx
)
}
)
}
}
export
const
executeRepeatedL2ToL1Transactions
=
async
(
export
const
executeRepeatedL2ToL1Transactions
=
async
(
env
:
OptimismEnv
,
env
:
OptimismEnv
,
tx
:
TransactionParams
,
wallets
:
ethers
.
Wallet
[]
,
count
:
number
tx
:
TransactionParams
)
=>
{
)
=>
{
await
executeL2ToL1Transactions
(
for
(
const
wallet
of
wallets
)
{
env
,
await
executeL2ToL1Transaction
(
env
,
wallet
,
tx
)
[...
Array
(
count
).
keys
()].
map
(()
=>
tx
)
}
)
}
}
export
const
executeRepeatedL2Transactions
=
async
(
export
const
executeRepeatedL2Transactions
=
async
(
env
:
OptimismEnv
,
env
:
OptimismEnv
,
tx
:
TransactionParams
,
wallets
:
ethers
.
Wallet
[]
,
count
:
number
tx
:
TransactionParams
)
=>
{
)
=>
{
await
executeL2Transactions
(
for
(
const
wallet
of
wallets
)
{
env
,
await
executeL2Transaction
(
env
,
wallet
,
tx
)
[...
Array
(
count
).
keys
()].
map
(()
=>
tx
)
}
)
}
}
export
const
executeL1ToL2TransactionsParallel
=
async
(
export
const
executeL1ToL2TransactionsParallel
=
async
(
env
:
OptimismEnv
,
env
:
OptimismEnv
,
txs
:
TransactionParams
[]
wallets
:
ethers
.
Wallet
[],
tx
:
TransactionParams
)
=>
{
)
=>
{
await
Promise
.
all
(
await
Promise
.
all
(
wallets
.
map
((
w
)
=>
executeL1ToL2Transaction
(
env
,
w
,
tx
)))
txs
.
map
(
async
(
tx
)
=>
{
const
signer
=
ethers
.
Wallet
.
createRandom
().
connect
(
env
.
l1Wallet
.
provider
)
const
receipt
=
await
env
.
l1Messenger
.
connect
(
signer
)
.
sendMessage
(
tx
.
contract
.
address
,
tx
.
contract
.
interface
.
encodeFunctionData
(
tx
.
functionName
,
tx
.
functionParams
),
MESSAGE_GAS
,
{
gasPrice
:
0
,
}
)
await
env
.
waitForXDomainTransaction
(
receipt
,
Direction
.
L1ToL2
)
})
)
}
}
export
const
executeL2ToL1TransactionsParallel
=
async
(
export
const
executeL2ToL1TransactionsParallel
=
async
(
env
:
OptimismEnv
,
env
:
OptimismEnv
,
txs
:
TransactionParams
[]
wallets
:
ethers
.
Wallet
[],
tx
:
TransactionParams
)
=>
{
)
=>
{
await
Promise
.
all
(
await
Promise
.
all
(
wallets
.
map
((
w
)
=>
executeL2ToL1Transaction
(
env
,
w
,
tx
)))
txs
.
map
(
async
(
tx
)
=>
{
const
signer
=
ethers
.
Wallet
.
createRandom
().
connect
(
env
.
l2Wallet
.
provider
)
const
receipt
=
await
env
.
l2Messenger
.
connect
(
signer
)
.
sendMessage
(
tx
.
contract
.
address
,
tx
.
contract
.
interface
.
encodeFunctionData
(
tx
.
functionName
,
tx
.
functionParams
),
MESSAGE_GAS
,
{
gasPrice
:
0
,
}
)
await
env
.
relayXDomainMessages
(
receipt
)
await
env
.
waitForXDomainTransaction
(
receipt
,
Direction
.
L2ToL1
)
})
)
}
}
export
const
executeL2TransactionsParallel
=
async
(
export
const
executeL2TransactionsParallel
=
async
(
env
:
OptimismEnv
,
env
:
OptimismEnv
,
txs
:
TransactionParams
[]
wallets
:
ethers
.
Wallet
[],
)
=>
{
tx
:
TransactionParams
await
Promise
.
all
(
txs
.
map
(
async
(
tx
)
=>
{
const
signer
=
ethers
.
Wallet
.
createRandom
().
connect
(
env
.
l2Wallet
.
provider
)
const
result
=
await
tx
.
contract
.
connect
(
signer
)
.
functions
[
tx
.
functionName
](...
tx
.
functionParams
,
{
gasPrice
:
0
,
})
await
result
.
wait
()
})
)
}
export
const
executeRepeatedL1ToL2TransactionsParallel
=
async
(
env
:
OptimismEnv
,
tx
:
TransactionParams
,
count
:
number
)
=>
{
await
executeL1ToL2TransactionsParallel
(
env
,
[...
Array
(
count
).
keys
()].
map
(()
=>
tx
)
)
}
export
const
executeRepeatedL2ToL1TransactionsParallel
=
async
(
env
:
OptimismEnv
,
tx
:
TransactionParams
,
count
:
number
)
=>
{
)
=>
{
await
executeL2ToL1TransactionsParallel
(
await
Promise
.
all
(
wallets
.
map
((
w
)
=>
executeL2Transaction
(
env
,
w
,
tx
)))
env
,
[...
Array
(
count
).
keys
()].
map
(()
=>
tx
)
)
}
}
export
const
executeRepeatedL2TransactionsParallel
=
async
(
const
retryOnNonceError
=
async
(
cb
:
()
=>
Promise
<
any
>
):
Promise
<
any
>
=>
{
env
:
OptimismEnv
,
while
(
true
)
{
tx
:
TransactionParams
,
try
{
count
:
number
return
await
cb
()
)
=>
{
}
catch
(
err
)
{
await
executeL2TransactionsParallel
(
const
msg
=
err
.
message
.
toLowerCase
()
env
,
[...
Array
(
count
).
keys
()].
map
(()
=>
tx
)
if
(
)
msg
.
includes
(
'
nonce too low
'
)
||
msg
.
includes
(
'
nonce has already been used
'
)
||
msg
.
includes
(
'
transaction was replaced
'
)
||
msg
.
includes
(
'
another transaction with same nonce in the queue
'
)
||
msg
.
includes
(
'
reverted without a reason
'
)
)
{
console
.
warn
(
'
Retrying transaction after nonce error.
'
)
await
sleep
(
5000
)
continue
}
throw
err
}
}
}
}
integration-tests/test/shared/utils.ts
View file @
cee2a464
...
@@ -19,10 +19,15 @@ import dotenv from 'dotenv'
...
@@ -19,10 +19,15 @@ import dotenv from 'dotenv'
/* Imports: Internal */
/* Imports: Internal */
import
{
Direction
,
waitForXDomainTransaction
}
from
'
./watcher-utils
'
import
{
Direction
,
waitForXDomainTransaction
}
from
'
./watcher-utils
'
import
{
OptimismEnv
}
from
'
./env
'
export
const
GWEI
=
BigNumber
.
from
(
1
e9
)
export
const
GWEI
=
BigNumber
.
from
(
1
e9
)
if
(
process
.
env
.
IS_LIVE_NETWORK
===
'
true
'
)
{
export
const
isLiveNetwork
=
()
=>
{
return
process
.
env
.
IS_LIVE_NETWORK
===
'
true
'
}
if
(
isLiveNetwork
())
{
dotenv
.
config
()
dotenv
.
config
()
}
}
...
@@ -144,12 +149,14 @@ export const encodeSolidityRevertMessage = (_reason: string): string => {
...
@@ -144,12 +149,14 @@ export const encodeSolidityRevertMessage = (_reason: string): string => {
return
'
0x08c379a0
'
+
remove0x
(
abiCoder
.
encode
([
'
string
'
],
[
_reason
]))
return
'
0x08c379a0
'
+
remove0x
(
abiCoder
.
encode
([
'
string
'
],
[
_reason
]))
}
}
export
const
DEFAULT_TRANSACTION
=
{
export
const
defaultTransactionFactory
=
()
=>
{
to
:
'
0x
'
+
'
1234
'
.
repeat
(
10
),
return
{
gasLimit
:
8
_000_000
,
to
:
'
0x
'
+
'
1234
'
.
repeat
(
10
),
gasPrice
:
0
,
gasLimit
:
8
_000_000
,
data
:
'
0x
'
,
gasPrice
:
BigNumber
.
from
(
0
),
value
:
0
,
data
:
'
0x
'
,
value
:
0
,
}
}
}
export
const
waitForL2Geth
=
async
(
export
const
waitForL2Geth
=
async
(
...
@@ -166,3 +173,44 @@ export const waitForL2Geth = async (
...
@@ -166,3 +173,44 @@ export const waitForL2Geth = async (
}
}
return
injectL2Context
(
provider
)
return
injectL2Context
(
provider
)
}
}
export
const
awaitCondition
=
async
(
cond
:
()
=>
Promise
<
boolean
>
,
rate
=
1000
,
attempts
=
10
)
=>
{
for
(
let
i
=
0
;
i
<
attempts
;
i
++
)
{
const
ok
=
await
cond
()
if
(
ok
)
{
return
}
await
sleep
(
rate
)
}
throw
new
Error
(
'
Timed out.
'
)
}
export
const
gasPriceForL2
=
async
()
=>
{
if
(
isLiveNetwork
())
{
return
Promise
.
resolve
(
BigNumber
.
from
(
10000
))
}
return
Promise
.
resolve
(
BigNumber
.
from
(
0
))
}
// eslint-disable-next-line @typescript-eslint/no-shadow
export
const
gasPriceForL1
=
async
(
env
:
OptimismEnv
)
=>
{
const
chainId
=
await
env
.
l1Wallet
.
getChainId
()
switch
(
chainId
)
{
case
1
:
return
env
.
l1Wallet
.
getGasPrice
()
case
3
:
case
42
:
return
utils
.
parseUnits
(
'
10
'
,
'
gwei
'
)
case
5
:
return
utils
.
parseUnits
(
'
2
'
,
'
gwei
'
)
default
:
return
BigNumber
.
from
(
0
)
}
}
integration-tests/test/shared/watcher-utils.ts
View file @
cee2a464
...
@@ -60,6 +60,11 @@ export const waitForXDomainTransaction = async (
...
@@ -60,6 +60,11 @@ export const waitForXDomainTransaction = async (
// get the message hash which was created on the SentMessage
// get the message hash which was created on the SentMessage
const
[
xDomainMsgHash
]
=
await
watcher
.
getMessageHashesFromTx
(
src
,
tx
.
hash
)
const
[
xDomainMsgHash
]
=
await
watcher
.
getMessageHashesFromTx
(
src
,
tx
.
hash
)
if
(
!
xDomainMsgHash
)
{
throw
new
Error
(
`No x-domain message hash for tx hash
${
tx
.
hash
}
, bailing.`
)
}
// Get the transaction and receipt on the remote layer
// Get the transaction and receipt on the remote layer
const
remoteReceipt
=
await
watcher
.
getTransactionReceipt
(
const
remoteReceipt
=
await
watcher
.
getTransactionReceipt
(
dest
,
dest
,
...
...
integration-tests/test/stress-tests.spec.ts
View file @
cee2a464
import
{
expect
}
from
'
chai
'
import
{
expect
}
from
'
chai
'
/* Imports: External */
/* Imports: External */
import
{
Contract
,
ContractFactory
}
from
'
ethers
'
import
{
Contract
,
ContractFactory
,
Wallet
,
utils
}
from
'
ethers
'
/* Imports: Internal */
/* Imports: Internal */
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
import
{
executeL1ToL2TransactionsParallel
,
executeL2ToL1TransactionsParallel
,
executeL2TransactionsParallel
,
executeRepeatedL1ToL2Transactions
,
executeRepeatedL1ToL2Transactions
,
executeRepeatedL2ToL1Transactions
,
executeRepeatedL2ToL1Transactions
,
executeRepeatedL2Transactions
,
executeRepeatedL2Transactions
,
executeRepeatedL1ToL2TransactionsParallel
,
fundRandomWallet
,
executeRepeatedL2ToL1TransactionsParallel
,
executeRepeatedL2TransactionsParallel
,
}
from
'
./shared/stress-test-helpers
'
}
from
'
./shared/stress-test-helpers
'
/* Imports: Artifacts */
/* Imports: Artifacts */
import
simpleStorageJson
from
'
../artifacts/contracts/SimpleStorage.sol/SimpleStorage.json
'
import
simpleStorageJson
from
'
../artifacts/contracts/SimpleStorage.sol/SimpleStorage.json
'
import
{
fundUser
,
isLiveNetwork
}
from
'
./shared/utils
'
// Need a big timeout to allow for all transactions to be processed.
// Need a big timeout to allow for all transactions to be processed.
// For some reason I can't figure out how to set the timeout on a per-suite basis
// For some reason I can't figure out how to set the timeout on a per-suite basis
// so I'm instead setting it for every test.
// so I'm instead setting it for every test.
const
STRESS_TEST_TIMEOUT
=
5
00
_000
const
STRESS_TEST_TIMEOUT
=
isLiveNetwork
()
?
500
_000
:
1
_2
00_000
describe
(
'
stress tests
'
,
()
=>
{
describe
(
'
stress tests
'
,
()
=>
{
const
numTransactions
=
3
let
env
:
OptimismEnv
let
env
:
OptimismEnv
const
wallets
:
Wallet
[]
=
[]
before
(
async
()
=>
{
before
(
async
()
=>
{
env
=
await
OptimismEnv
.
new
()
env
=
await
OptimismEnv
.
new
()
for
(
let
i
=
0
;
i
<
numTransactions
;
i
++
)
{
wallets
.
push
(
Wallet
.
createRandom
())
}
for
(
const
wallet
of
wallets
)
{
await
fundRandomWallet
(
env
,
wallet
,
utils
.
parseEther
(
'
0.1
'
))
}
for
(
const
wallet
of
wallets
)
{
await
fundUser
(
env
.
watcher
,
env
.
l1Bridge
,
utils
.
parseEther
(
'
0.1
'
),
wallet
.
address
)
}
})
})
let
L2SimpleStorage
:
Contract
let
L2SimpleStorage
:
Contract
...
@@ -48,106 +72,76 @@ describe('stress tests', () => {
...
@@ -48,106 +72,76 @@ describe('stress tests', () => {
})
})
describe
(
'
L1 => L2 stress tests
'
,
()
=>
{
describe
(
'
L1 => L2 stress tests
'
,
()
=>
{
const
numTransactions
=
10
it
(
`
${
numTransactions
}
L1 => L2 transactions (serial)`
,
async
()
=>
{
it
(
`
${
numTransactions
}
L1 => L2 transactions (serial)`
,
async
()
=>
{
await
executeRepeatedL1ToL2Transactions
(
await
executeRepeatedL1ToL2Transactions
(
env
,
wallets
,
{
env
,
contract
:
L2SimpleStorage
,
{
functionName
:
'
setValue
'
,
contract
:
L2SimpleStorage
,
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
functionName
:
'
setValue
'
,
})
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
},
numTransactions
)
expect
((
await
L2SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
expect
((
await
L2SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
numTransactions
wallets
.
length
)
)
}).
timeout
(
STRESS_TEST_TIMEOUT
)
}).
timeout
(
STRESS_TEST_TIMEOUT
)
it
(
`
${
numTransactions
}
L1 => L2 transactions (parallel)`
,
async
()
=>
{
it
(
`
${
numTransactions
}
L1 => L2 transactions (parallel)`
,
async
()
=>
{
await
executeRepeatedL1ToL2TransactionsParallel
(
await
executeL1ToL2TransactionsParallel
(
env
,
wallets
,
{
env
,
contract
:
L2SimpleStorage
,
{
functionName
:
'
setValue
'
,
contract
:
L2SimpleStorage
,
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
functionName
:
'
setValue
'
,
})
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
},
numTransactions
)
expect
((
await
L2SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
expect
((
await
L2SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
numTransactions
wallets
.
length
)
)
}).
timeout
(
STRESS_TEST_TIMEOUT
)
}).
timeout
(
STRESS_TEST_TIMEOUT
)
})
})
describe
(
'
L2 => L1 stress tests
'
,
()
=>
{
describe
(
'
L2 => L1 stress tests
'
,
()
=>
{
const
numTransactions
=
10
it
(
`
${
numTransactions
}
L2 => L1 transactions (serial)`
,
async
()
=>
{
it
(
`
${
numTransactions
}
L2 => L1 transactions (serial)`
,
async
()
=>
{
await
executeRepeatedL2ToL1Transactions
(
await
executeRepeatedL2ToL1Transactions
(
env
,
wallets
,
{
env
,
contract
:
L1SimpleStorage
,
{
functionName
:
'
setValue
'
,
contract
:
L1SimpleStorage
,
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
functionName
:
'
setValue
'
,
})
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
},
numTransactions
)
expect
((
await
L1SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
expect
((
await
L1SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
numTransactions
wallets
.
length
)
)
}).
timeout
(
STRESS_TEST_TIMEOUT
)
}).
timeout
(
STRESS_TEST_TIMEOUT
)
it
(
`
${
numTransactions
}
L2 => L1 transactions (parallel)`
,
async
()
=>
{
it
(
`
${
numTransactions
}
L2 => L1 transactions (parallel)`
,
async
()
=>
{
await
executeRepeatedL2ToL1TransactionsParallel
(
await
executeL2ToL1TransactionsParallel
(
env
,
wallets
,
{
env
,
contract
:
L1SimpleStorage
,
{
functionName
:
'
setValue
'
,
contract
:
L1SimpleStorage
,
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
functionName
:
'
setValue
'
,
})
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
},
numTransactions
)
expect
((
await
L1SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
expect
((
await
L1SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
numTransactions
wallets
.
length
)
)
}).
timeout
(
STRESS_TEST_TIMEOUT
)
}).
timeout
(
STRESS_TEST_TIMEOUT
)
})
})
describe
(
'
L2 transaction stress tests
'
,
()
=>
{
describe
(
'
L2 transaction stress tests
'
,
()
=>
{
const
numTransactions
=
10
it
(
`
${
numTransactions
}
L2 transactions (serial)`
,
async
()
=>
{
it
(
`
${
numTransactions
}
L2 transactions (serial)`
,
async
()
=>
{
await
executeRepeatedL2Transactions
(
await
executeRepeatedL2Transactions
(
env
,
wallets
,
{
env
,
contract
:
L2SimpleStorage
,
{
functionName
:
'
setValueNotXDomain
'
,
contract
:
L2SimpleStorage
,
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
functionName
:
'
setValueNotXDomain
'
,
})
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
},
numTransactions
)
expect
((
await
L2SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
expect
((
await
L2SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
numTransactions
wallets
.
length
)
)
}).
timeout
(
STRESS_TEST_TIMEOUT
)
}).
timeout
(
STRESS_TEST_TIMEOUT
)
it
(
`
${
numTransactions
}
L2 transactions (parallel)`
,
async
()
=>
{
it
(
`
${
numTransactions
}
L2 transactions (parallel)`
,
async
()
=>
{
await
executeRepeatedL2TransactionsParallel
(
await
executeL2TransactionsParallel
(
env
,
wallets
,
{
env
,
contract
:
L2SimpleStorage
,
{
functionName
:
'
setValueNotXDomain
'
,
contract
:
L2SimpleStorage
,
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
functionName
:
'
setValueNotXDomain
'
,
})
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
},
numTransactions
)
expect
((
await
L2SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
expect
((
await
L2SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
numTransactions
numTransactions
...
@@ -156,85 +150,59 @@ describe('stress tests', () => {
...
@@ -156,85 +150,59 @@ describe('stress tests', () => {
})
})
describe
(
'
C-C-C-Combo breakers
'
,
()
=>
{
describe
(
'
C-C-C-Combo breakers
'
,
()
=>
{
const
numTransactions
=
10
it
(
`
${
numTransactions
}
L2 transactions, L1 => L2 transactions, L2 => L1 transactions (txs serial, suites parallel)`
,
async
()
=>
{
it
(
`
${
numTransactions
}
L2 transactions, L1 => L2 transactions, L2 => L1 transactions (txs serial, suites parallel)`
,
async
()
=>
{
await
Promise
.
all
([
await
Promise
.
all
([
executeRepeatedL1ToL2Transactions
(
executeRepeatedL1ToL2Transactions
(
env
,
wallets
,
{
env
,
contract
:
L2SimpleStorage
,
{
functionName
:
'
setValue
'
,
contract
:
L2SimpleStorage
,
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
functionName
:
'
setValue
'
,
}),
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
executeRepeatedL2ToL1Transactions
(
env
,
wallets
,
{
},
contract
:
L1SimpleStorage
,
numTransactions
functionName
:
'
setValue
'
,
),
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
executeRepeatedL2ToL1Transactions
(
}),
env
,
executeRepeatedL2Transactions
(
env
,
wallets
,
{
{
contract
:
L2SimpleStorage
,
contract
:
L1SimpleStorage
,
functionName
:
'
setValueNotXDomain
'
,
functionName
:
'
setValue
'
,
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
}),
},
numTransactions
),
executeRepeatedL2Transactions
(
env
,
{
contract
:
L2SimpleStorage
,
functionName
:
'
setValueNotXDomain
'
,
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
},
numTransactions
),
])
])
expect
((
await
L2SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
expect
((
await
L2SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
numTransactions
*
2
wallets
.
length
*
2
)
)
expect
((
await
L1SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
expect
((
await
L1SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
numTransactions
wallets
.
length
)
)
}).
timeout
(
STRESS_TEST_TIMEOUT
)
}).
timeout
(
STRESS_TEST_TIMEOUT
)
it
(
`
${
numTransactions
}
L2 transactions, L1 => L2 transactions, L2 => L1 transactions (all parallel)`
,
async
()
=>
{
it
(
`
${
numTransactions
}
L2 transactions, L1 => L2 transactions, L2 => L1 transactions (all parallel)`
,
async
()
=>
{
await
Promise
.
all
([
await
Promise
.
all
([
executeRepeatedL1ToL2TransactionsParallel
(
executeL1ToL2TransactionsParallel
(
env
,
wallets
,
{
env
,
contract
:
L2SimpleStorage
,
{
functionName
:
'
setValue
'
,
contract
:
L2SimpleStorage
,
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
functionName
:
'
setValue
'
,
}),
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
executeL2ToL1TransactionsParallel
(
env
,
wallets
,
{
},
contract
:
L1SimpleStorage
,
numTransactions
functionName
:
'
setValue
'
,
),
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
executeRepeatedL2ToL1TransactionsParallel
(
}),
env
,
executeL2TransactionsParallel
(
env
,
wallets
,
{
{
contract
:
L2SimpleStorage
,
contract
:
L1SimpleStorage
,
functionName
:
'
setValueNotXDomain
'
,
functionName
:
'
setValue
'
,
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
}),
},
numTransactions
),
executeRepeatedL2TransactionsParallel
(
env
,
{
contract
:
L2SimpleStorage
,
functionName
:
'
setValueNotXDomain
'
,
functionParams
:
[
`0x
${
'
42
'
.
repeat
(
32
)}
`
],
},
numTransactions
),
])
])
expect
((
await
L2SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
expect
((
await
L2SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
numTransactions
*
2
wallets
.
length
*
2
)
)
expect
((
await
L1SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
expect
((
await
L1SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
numTransactions
wallets
.
length
)
)
}).
timeout
(
STRESS_TEST_TIMEOUT
)
}).
timeout
(
STRESS_TEST_TIMEOUT
)
})
})
...
...
packages/contracts/deploy/000-hardhat-setup.ts
View file @
cee2a464
...
@@ -5,9 +5,9 @@ import {
...
@@ -5,9 +5,9 @@ import {
getContractFromArtifact
,
getContractFromArtifact
,
fundAccount
,
fundAccount
,
sendImpersonatedTx
,
sendImpersonatedTx
,
waitUntilTrue
,
BIG_BALANCE
,
BIG_BALANCE
,
}
from
'
../src/hardhat-deploy-ethers
'
}
from
'
../src/hardhat-deploy-ethers
'
import
{
awaitCondition
}
from
'
@eth-optimism/core-utils
'
const
deployFn
:
DeployFunction
=
async
(
hre
)
=>
{
const
deployFn
:
DeployFunction
=
async
(
hre
)
=>
{
if
((
hre
as
any
).
deployConfig
.
forked
!==
'
true
'
)
{
if
((
hre
as
any
).
deployConfig
.
forked
!==
'
true
'
)
{
...
@@ -39,9 +39,13 @@ const deployFn: DeployFunction = async (hre) => {
...
@@ -39,9 +39,13 @@ const deployFn: DeployFunction = async (hre) => {
})
})
console
.
log
(
`Waiting for owner to be correctly set...`
)
console
.
log
(
`Waiting for owner to be correctly set...`
)
await
waitUntilTrue
(
async
()
=>
{
await
awaitCondition
(
return
(
await
Lib_AddressManager
.
owner
())
===
deployer
async
()
=>
{
})
return
(
await
Lib_AddressManager
.
owner
())
===
deployer
},
5000
,
100
)
// Get a reference to the L1StandardBridge contract.
// Get a reference to the L1StandardBridge contract.
const
Proxy__OVM_L1StandardBridge
=
await
getContractFromArtifact
(
const
Proxy__OVM_L1StandardBridge
=
await
getContractFromArtifact
(
...
@@ -63,13 +67,17 @@ const deployFn: DeployFunction = async (hre) => {
...
@@ -63,13 +67,17 @@ const deployFn: DeployFunction = async (hre) => {
})
})
console
.
log
(
`Waiting for owner to be correctly set...`
)
console
.
log
(
`Waiting for owner to be correctly set...`
)
await
waitUntilTrue
(
async
()
=>
{
await
awaitCondition
(
return
(
async
()
=>
{
(
await
Proxy__OVM_L1StandardBridge
.
callStatic
.
getOwner
({
return
(
from
:
hre
.
ethers
.
constants
.
AddressZero
,
(
await
Proxy__OVM_L1StandardBridge
.
callStatic
.
getOwner
({
}))
===
deployer
from
:
hre
.
ethers
.
constants
.
AddressZero
,
)
}))
===
deployer
})
)
},
5000
,
100
)
}
}
deployFn
.
tags
=
[
'
hardhat
'
,
'
upgrade
'
]
deployFn
.
tags
=
[
'
hardhat
'
,
'
upgrade
'
]
...
...
packages/contracts/deploy/007-OVM_L1CrossDomainMessenger.deploy.ts
View file @
cee2a464
/* Imports: External */
/* Imports: External */
import
{
DeployFunction
}
from
'
hardhat-deploy/dist/types
'
import
{
DeployFunction
}
from
'
hardhat-deploy/dist/types
'
import
{
hexStringEquals
}
from
'
@eth-optimism/core-utils
'
import
{
hexStringEquals
,
awaitCondition
}
from
'
@eth-optimism/core-utils
'
/* Imports: Internal */
/* Imports: Internal */
import
{
import
{
deployAndPostDeploy
,
deployAndPostDeploy
,
getContractFromArtifact
,
getContractFromArtifact
,
waitUntilTrue
,
}
from
'
../src/hardhat-deploy-ethers
'
}
from
'
../src/hardhat-deploy-ethers
'
const
deployFn
:
DeployFunction
=
async
(
hre
)
=>
{
const
deployFn
:
DeployFunction
=
async
(
hre
)
=>
{
...
@@ -29,12 +28,16 @@ const deployFn: DeployFunction = async (hre) => {
...
@@ -29,12 +28,16 @@ const deployFn: DeployFunction = async (hre) => {
await
contract
.
initialize
(
Lib_AddressManager
.
address
)
await
contract
.
initialize
(
Lib_AddressManager
.
address
)
console
.
log
(
`Checking that contract was correctly initialized...`
)
console
.
log
(
`Checking that contract was correctly initialized...`
)
await
waitUntilTrue
(
async
()
=>
{
await
awaitCondition
(
return
hexStringEquals
(
async
()
=>
{
await
contract
.
libAddressManager
(),
return
hexStringEquals
(
Lib_AddressManager
.
address
await
contract
.
libAddressManager
(),
)
Lib_AddressManager
.
address
})
)
},
5000
,
100
)
},
},
})
})
}
}
...
...
packages/contracts/deploy/008-Proxy__OVM_L1CrossDomainMessenger.deploy.ts
View file @
cee2a464
...
@@ -6,7 +6,6 @@ import { hexStringEquals } from '@eth-optimism/core-utils'
...
@@ -6,7 +6,6 @@ import { hexStringEquals } from '@eth-optimism/core-utils'
import
{
import
{
deployAndPostDeploy
,
deployAndPostDeploy
,
getContractFromArtifact
,
getContractFromArtifact
,
waitUntilTrue
,
}
from
'
../src/hardhat-deploy-ethers
'
}
from
'
../src/hardhat-deploy-ethers
'
const
deployFn
:
DeployFunction
=
async
(
hre
)
=>
{
const
deployFn
:
DeployFunction
=
async
(
hre
)
=>
{
...
...
packages/contracts/deploy/011-set-addresses.ts
View file @
cee2a464
/* Imports: External */
/* Imports: External */
import
{
hexStringEquals
}
from
'
@eth-optimism/core-utils
'
import
{
hexStringEquals
,
awaitCondition
}
from
'
@eth-optimism/core-utils
'
import
{
ethers
}
from
'
hardhat
'
import
{
ethers
}
from
'
hardhat
'
import
{
DeployFunction
}
from
'
hardhat-deploy/dist/types
'
import
{
DeployFunction
}
from
'
hardhat-deploy/dist/types
'
/* Imports: Internal */
/* Imports: Internal */
import
{
import
{
getContractFromArtifact
}
from
'
../src/hardhat-deploy-ethers
'
getContractFromArtifact
,
waitUntilTrue
,
}
from
'
../src/hardhat-deploy-ethers
'
const
deployFn
:
DeployFunction
=
async
(
hre
)
=>
{
const
deployFn
:
DeployFunction
=
async
(
hre
)
=>
{
const
{
deployer
}
=
await
hre
.
getNamedAccounts
()
const
{
deployer
}
=
await
hre
.
getNamedAccounts
()
...
@@ -92,18 +89,16 @@ const deployFn: DeployFunction = async (hre) => {
...
@@ -92,18 +89,16 @@ const deployFn: DeployFunction = async (hre) => {
}
}
// Wait for ownership to be transferred to the AddressDictator contract.
// Wait for ownership to be transferred to the AddressDictator contract.
await
waitUntilTrue
(
await
awaitCondition
(
async
()
=>
{
async
()
=>
{
return
hexStringEquals
(
return
hexStringEquals
(
await
Lib_AddressManager
.
owner
(),
await
Lib_AddressManager
.
owner
(),
AddressDictator
.
address
AddressDictator
.
address
)
)
},
},
{
// Try every 30 seconds for 500 minutes.
// Try every 30 seconds for 500 minutes.
30000
,
delay
:
30
_000
,
1000
retries
:
1000
,
}
)
)
// Set the addresses!
// Set the addresses!
...
@@ -112,9 +107,13 @@ const deployFn: DeployFunction = async (hre) => {
...
@@ -112,9 +107,13 @@ const deployFn: DeployFunction = async (hre) => {
// Make sure ownership has been correctly sent back to the original owner.
// Make sure ownership has been correctly sent back to the original owner.
console
.
log
(
'
Verifying final ownership of Lib_AddressManager...
'
)
console
.
log
(
'
Verifying final ownership of Lib_AddressManager...
'
)
await
waitUntilTrue
(
async
()
=>
{
await
awaitCondition
(
return
hexStringEquals
(
await
Lib_AddressManager
.
owner
(),
finalOwner
)
async
()
=>
{
})
return
hexStringEquals
(
await
Lib_AddressManager
.
owner
(),
finalOwner
)
},
500
,
1000
)
}
}
deployFn
.
tags
=
[
'
set-addresses
'
,
'
upgrade
'
]
deployFn
.
tags
=
[
'
set-addresses
'
,
'
upgrade
'
]
...
...
packages/contracts/deploy/012-initialize-Proxy__L1CrossDomainMessenger.ts
View file @
cee2a464
/* Imports: External */
/* Imports: External */
import
{
DeployFunction
}
from
'
hardhat-deploy/dist/types
'
import
{
DeployFunction
}
from
'
hardhat-deploy/dist/types
'
import
{
hexStringEquals
}
from
'
@eth-optimism/core-utils
'
import
{
hexStringEquals
,
awaitCondition
}
from
'
@eth-optimism/core-utils
'
/* Imports: Internal */
/* Imports: Internal */
import
{
import
{
getContractFromArtifact
}
from
'
../src/hardhat-deploy-ethers
'
getContractFromArtifact
,
waitUntilTrue
,
}
from
'
../src/hardhat-deploy-ethers
'
const
deployFn
:
DeployFunction
=
async
(
hre
)
=>
{
const
deployFn
:
DeployFunction
=
async
(
hre
)
=>
{
const
{
deployer
}
=
await
hre
.
getNamedAccounts
()
const
{
deployer
}
=
await
hre
.
getNamedAccounts
()
...
@@ -34,12 +31,16 @@ const deployFn: DeployFunction = async (hre) => {
...
@@ -34,12 +31,16 @@ const deployFn: DeployFunction = async (hre) => {
await
Proxy__OVM_L1CrossDomainMessenger
.
initialize
(
Lib_AddressManager
.
address
)
await
Proxy__OVM_L1CrossDomainMessenger
.
initialize
(
Lib_AddressManager
.
address
)
console
.
log
(
`Checking that contract was correctly initialized...`
)
console
.
log
(
`Checking that contract was correctly initialized...`
)
await
waitUntilTrue
(
async
()
=>
{
await
awaitCondition
(
return
hexStringEquals
(
async
()
=>
{
await
Proxy__OVM_L1CrossDomainMessenger
.
libAddressManager
(),
return
hexStringEquals
(
Lib_AddressManager
.
address
await
Proxy__OVM_L1CrossDomainMessenger
.
libAddressManager
(),
)
Lib_AddressManager
.
address
})
)
},
5000
,
100
)
}
}
deployFn
.
tags
=
[
'
finalize
'
]
deployFn
.
tags
=
[
'
finalize
'
]
...
...
packages/contracts/deploy/014-OVM_L1StandardBridge.deploy.ts
View file @
cee2a464
/* Imports: External */
/* Imports: External */
import
{
DeployFunction
}
from
'
hardhat-deploy/dist/types
'
import
{
DeployFunction
}
from
'
hardhat-deploy/dist/types
'
import
{
ethers
}
from
'
ethers
'
import
{
ethers
}
from
'
ethers
'
import
{
hexStringEquals
}
from
'
@eth-optimism/core-utils
'
import
{
hexStringEquals
,
awaitCondition
}
from
'
@eth-optimism/core-utils
'
/* Imports: Internal */
/* Imports: Internal */
import
{
getContractDefinition
}
from
'
../src/contract-defs
'
import
{
getContractDefinition
}
from
'
../src/contract-defs
'
import
{
import
{
getContractFromArtifact
,
getContractFromArtifact
,
waitUntilTrue
,
deployAndPostDeploy
,
deployAndPostDeploy
,
}
from
'
../src/hardhat-deploy-ethers
'
}
from
'
../src/hardhat-deploy-ethers
'
...
@@ -100,7 +99,7 @@ const deployFn: DeployFunction = async (hre) => {
...
@@ -100,7 +99,7 @@ const deployFn: DeployFunction = async (hre) => {
}
}
// Wait for ownership to be transferred to the AddressDictator contract.
// Wait for ownership to be transferred to the AddressDictator contract.
await
waitUntilTrue
(
await
awaitCondition
(
async
()
=>
{
async
()
=>
{
return
hexStringEquals
(
return
hexStringEquals
(
await
Proxy__OVM_L1StandardBridge
.
connect
(
await
Proxy__OVM_L1StandardBridge
.
connect
(
...
@@ -111,11 +110,8 @@ const deployFn: DeployFunction = async (hre) => {
...
@@ -111,11 +110,8 @@ const deployFn: DeployFunction = async (hre) => {
ChugSplashDictator
.
address
ChugSplashDictator
.
address
)
)
},
},
{
30000
,
// Try every 30 seconds for 500 minutes.
1000
delay
:
30
_000
,
retries
:
1000
,
}
)
)
// Set the addresses!
// Set the addresses!
...
@@ -123,16 +119,20 @@ const deployFn: DeployFunction = async (hre) => {
...
@@ -123,16 +119,20 @@ const deployFn: DeployFunction = async (hre) => {
await
ChugSplashDictator
.
doActions
(
bridgeCode
)
await
ChugSplashDictator
.
doActions
(
bridgeCode
)
console
.
log
(
`Confirming that owner address was correctly set...`
)
console
.
log
(
`Confirming that owner address was correctly set...`
)
await
waitUntilTrue
(
async
()
=>
{
await
awaitCondition
(
return
hexStringEquals
(
async
()
=>
{
await
Proxy__OVM_L1StandardBridge
.
connect
(
return
hexStringEquals
(
Proxy__OVM_L1StandardBridge
.
signer
.
provider
await
Proxy__OVM_L1StandardBridge
.
connect
(
).
callStatic
.
getOwner
({
Proxy__OVM_L1StandardBridge
.
signer
.
provider
from
:
ethers
.
constants
.
AddressZero
,
).
callStatic
.
getOwner
({
}),
from
:
ethers
.
constants
.
AddressZero
,
finalOwner
}),
)
finalOwner
})
)
},
5000
,
100
)
// Deploy a copy of the implementation so it can be successfully verified on Etherscan.
// Deploy a copy of the implementation so it can be successfully verified on Etherscan.
console
.
log
(
`Deploying a copy of the bridge for Etherscan verification...`
)
console
.
log
(
`Deploying a copy of the bridge for Etherscan verification...`
)
...
...
packages/contracts/deploy/015-finalize.ts
View file @
cee2a464
/* Imports: External */
/* Imports: External */
import
{
DeployFunction
}
from
'
hardhat-deploy/dist/types
'
import
{
DeployFunction
}
from
'
hardhat-deploy/dist/types
'
import
{
hexStringEquals
}
from
'
@eth-optimism/core-utils
'
import
{
hexStringEquals
,
awaitCondition
}
from
'
@eth-optimism/core-utils
'
/* Imports: Internal */
/* Imports: Internal */
import
{
import
{
getContractFromArtifact
}
from
'
../src/hardhat-deploy-ethers
'
getContractFromArtifact
,
waitUntilTrue
,
}
from
'
../src/hardhat-deploy-ethers
'
const
deployFn
:
DeployFunction
=
async
(
hre
)
=>
{
const
deployFn
:
DeployFunction
=
async
(
hre
)
=>
{
const
{
deployer
}
=
await
hre
.
getNamedAccounts
()
const
{
deployer
}
=
await
hre
.
getNamedAccounts
()
...
@@ -31,9 +28,13 @@ const deployFn: DeployFunction = async (hre) => {
...
@@ -31,9 +28,13 @@ const deployFn: DeployFunction = async (hre) => {
await
Lib_AddressManager
.
transferOwnership
(
owner
)
await
Lib_AddressManager
.
transferOwnership
(
owner
)
console
.
log
(
`Confirming transfer was successful...`
)
console
.
log
(
`Confirming transfer was successful...`
)
await
waitUntilTrue
(
async
()
=>
{
await
awaitCondition
(
return
hexStringEquals
(
await
Lib_AddressManager
.
owner
(),
owner
)
async
()
=>
{
})
return
hexStringEquals
(
await
Lib_AddressManager
.
owner
(),
owner
)
},
5000
,
100
)
console
.
log
(
`✓ Set owner of Lib_AddressManager to:
${
owner
}
`
)
console
.
log
(
`✓ Set owner of Lib_AddressManager to:
${
owner
}
`
)
}
}
...
...
packages/contracts/src/hardhat-deploy-ethers.ts
View file @
cee2a464
...
@@ -2,29 +2,13 @@
...
@@ -2,29 +2,13 @@
import
{
ethers
,
Contract
}
from
'
ethers
'
import
{
ethers
,
Contract
}
from
'
ethers
'
import
{
Provider
}
from
'
@ethersproject/abstract-provider
'
import
{
Provider
}
from
'
@ethersproject/abstract-provider
'
import
{
Signer
}
from
'
@ethersproject/abstract-signer
'
import
{
Signer
}
from
'
@ethersproject/abstract-signer
'
import
{
sleep
,
hexStringEquals
}
from
'
@eth-optimism/core-utils
'
import
{
sleep
,
hexStringEquals
,
awaitCondition
,
}
from
'
@eth-optimism/core-utils
'
import
{
HttpNetworkConfig
}
from
'
hardhat/types
'
import
{
HttpNetworkConfig
}
from
'
hardhat/types
'
export
const
waitUntilTrue
=
async
(
check
:
()
=>
Promise
<
boolean
>
,
opts
:
{
retries
?:
number
delay
?:
number
}
=
{}
)
=>
{
opts
.
retries
=
opts
.
retries
||
100
opts
.
delay
=
opts
.
delay
||
5000
let
retries
=
0
while
(
!
(
await
check
()))
{
if
(
retries
>
opts
.
retries
)
{
throw
new
Error
(
`check failed after
${
opts
.
retries
}
attempts`
)
}
retries
++
await
sleep
(
opts
.
delay
)
}
}
export
const
deployAndPostDeploy
=
async
({
export
const
deployAndPostDeploy
=
async
({
hre
,
hre
,
name
,
name
,
...
@@ -152,10 +136,14 @@ export const fundAccount = async (
...
@@ -152,10 +136,14 @@ export const fundAccount = async (
])
])
console
.
log
(
`Waiting for balance to reflect...`
)
console
.
log
(
`Waiting for balance to reflect...`
)
await
waitUntilTrue
(
async
()
=>
{
await
awaitCondition
(
const
balance
=
await
hre
.
ethers
.
provider
.
getBalance
(
address
)
async
()
=>
{
return
balance
.
gte
(
amount
)
const
balance
=
await
hre
.
ethers
.
provider
.
getBalance
(
address
)
})
return
balance
.
gte
(
amount
)
},
5000
,
100
)
console
.
log
(
`Account successfully funded.`
)
console
.
log
(
`Account successfully funded.`
)
}
}
...
...
packages/core-utils/src/common/test-utils.ts
View file @
cee2a464
import
{
expect
}
from
'
chai
'
import
{
expect
}
from
'
chai
'
import
{
BigNumber
}
from
'
ethers
'
import
{
BigNumber
}
from
'
ethers
'
import
{
sleep
}
from
'
./misc
'
interface
deviationRanges
{
interface
deviationRanges
{
percentUpperDeviation
?:
number
percentUpperDeviation
?:
number
...
@@ -8,6 +9,23 @@ interface deviationRanges {
...
@@ -8,6 +9,23 @@ interface deviationRanges {
absoluteLowerDeviation
?:
number
absoluteLowerDeviation
?:
number
}
}
export
const
awaitCondition
=
async
(
cond
:
()
=>
Promise
<
boolean
>
,
rate
=
1000
,
attempts
=
10
)
=>
{
for
(
let
i
=
0
;
i
<
attempts
;
i
++
)
{
const
ok
=
await
cond
()
if
(
ok
)
{
return
}
await
sleep
(
rate
)
}
throw
new
Error
(
'
Timed out.
'
)
}
/**
/**
* Assert that a number lies within a custom defined range of the target.
* Assert that a number lies within a custom defined range of the target.
*/
*/
...
...
packages/core-utils/test/common/test-utils.spec.ts
View file @
cee2a464
import
{
expect
}
from
'
../setup
'
import
{
expect
}
from
'
../setup
'
/* Imports: Internal */
/* Imports: Internal */
import
{
expectApprox
}
from
'
../../src
'
import
{
expectApprox
,
awaitCondition
}
from
'
../../src
'
import
{
assert
}
from
'
chai
'
import
{
assert
}
from
'
chai
'
describe
(
'
awaitCondition
'
,
()
=>
{
it
(
'
should try the condition fn until it returns true
'
,
async
()
=>
{
let
i
=
0
const
condFn
=
async
()
=>
{
i
++
return
Promise
.
resolve
(
i
===
2
)
}
await
awaitCondition
(
condFn
,
50
,
3
);
expect
(
i
).
to
.
equal
(
2
)
})
it
(
'
should only try the configured number of attempts
'
,
async
()
=>
{
let
i
=
0
const
condFn
=
async
()
=>
{
i
++
return
Promise
.
resolve
(
i
===
2
)
}
try
{
await
awaitCondition
(
condFn
,
50
,
1
);
}
catch
(
e
)
{
return
;
}
assert
.
fail
(
'
Condition never failed, but it should have.
'
);
})
})
describe
(
'
expectApprox
'
,
()
=>
{
describe
(
'
expectApprox
'
,
()
=>
{
it
(
'
should pass when the actual number is higher, but within the expected range of the target
'
,
async
()
=>
{
it
(
'
should pass when the actual number is higher, but within the expected range of the target
'
,
async
()
=>
{
expectApprox
(
119
,
100
,
{
expectApprox
(
119
,
100
,
{
...
...
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