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
b0582a31
Unverified
Commit
b0582a31
authored
Jan 22, 2022
by
Matthew Slipper
Committed by
GitHub
Jan 22, 2022
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into feat/eng-1906-geth-init-url
parents
ae96d784
f8531d88
Changes
21
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
523 additions
and
478 deletions
+523
-478
early-hairs-smash.md
.changeset/early-hairs-smash.md
+5
-0
config.yml
.circleci/config.yml
+38
-0
.env.example
integration-tests/.env.example
+11
-0
hardhat.config.ts
integration-tests/hardhat.config.ts
+3
-2
package.json
integration-tests/package.json
+0
-3
basic-l1-l2-communication.spec.ts
integration-tests/test/basic-l1-l2-communication.spec.ts
+75
-37
bridged-tokens.spec.ts
integration-tests/test/bridged-tokens.spec.ts
+40
-44
fee-payment.spec.ts
integration-tests/test/fee-payment.spec.ts
+40
-43
native-eth-ovm-calls.spec.ts
integration-tests/test/native-eth-ovm-calls.spec.ts
+3
-3
native-eth.spec.ts
integration-tests/test/native-eth.spec.ts
+71
-81
ovmcontext.spec.ts
integration-tests/test/ovmcontext.spec.ts
+12
-8
queue-ingestion.spec.ts
integration-tests/test/queue-ingestion.spec.ts
+7
-4
replica.spec.ts
integration-tests/test/replica.spec.ts
+10
-10
rpc.spec.ts
integration-tests/test/rpc.spec.ts
+51
-47
setup-docker-compose-network.ts
integration-tests/test/setup-docker-compose-network.ts
+0
-7
docker-compose.ts
integration-tests/test/shared/docker-compose.ts
+0
-62
env.ts
integration-tests/test/shared/env.ts
+11
-3
stress-test-helpers.ts
integration-tests/test/shared/stress-test-helpers.ts
+4
-4
utils.ts
integration-tests/test/shared/utils.ts
+131
-95
stress-tests.spec.ts
integration-tests/test/stress-tests.spec.ts
+6
-5
yarn.lock
yarn.lock
+5
-20
No files found.
.changeset/early-hairs-smash.md
0 → 100644
View file @
b0582a31
---
'
@eth-optimism/integration-tests'
:
minor
---
Updates to work with a live network
.circleci/config.yml
View file @
b0582a31
...
...
@@ -141,6 +141,32 @@ jobs:
kubectl rollout restart statefulset nightly-dtl --namespace nightly
kubectl rollout restart deployment nightly-gas-oracle --namespace nightly
kubectl rollout restart deployment edge-proxyd --namespace nightly
run-itests-nightly
:
docker
:
-
image
:
cimg/base:2021.04
steps
:
-
setup_remote_docker
:
version
:
19.03.13
-
run
:
name
:
Run integration tests
command
:
|
docker run \
--env PRIVATE_KEY=$NIGHTLY_ITESTS_PRIVKEY \
--env L1_URL=https://nightly-l1.optimism-stacks.net \
--env L2_URL=https://nightly-l2.optimism-stacks.net \
--env ADDRESS_MANAGER=0x22D4E211ef8704f2ca2d6dfdB32125E2530ACE3e \
--env L2_CHAINID=69 \
--env MOCHA_BAIL=true \
--env MOCHA_TIMEOUT=300000 \
--env L1_GAS_PRICE=onchain \
--env L2_GAS_PRICE=onchain \
--env RUN_DEBUG_TRACE_TESTS=false \
--env RUN_REPLICA_TESTS=false \
--env RUN_STRESS_TESTS=false \
--env OVMCONTEXT_SPEC_NUM_TXS=1 \
--env DTL_ENQUEUE_CONFIRMATIONS=12 \
"$STACKMAN_REPO/integration-tests:nightly" \
yarn test:integration:live
notify
:
docker
:
-
image
:
cimg/base:2021.04
...
...
@@ -152,6 +178,18 @@ jobs:
workflows
:
nightly-itests
:
triggers
:
-
schedule
:
cron
:
"
0
1
*
*
*
"
filters
:
branches
:
only
:
-
develop
jobs
:
-
run-itests-nightly
:
context
:
-
optimism
nightly
:
triggers
:
-
schedule
:
...
...
integration-tests/.env.example
View file @
b0582a31
...
...
@@ -4,3 +4,14 @@ L1_URL=
L2_URL=
ADDRESS_MANAGER=
L2_CHAINID=
DTL_ENQUEUE_CONFIRMATIONS=
OVMCONTEXT_SPEC_NUM_TXS=1
# Can be set to true below if the withdrawal window is short enough
RUN_WITHDRAWAL_TESTS=false
RUN_DEBUG_TRACE_TESTS=false
RUN_REPLICA_TESTS=false
RUN_STRESS_TESTS=false
# Can be configured up or down as necessary
MOCHA_TIMEOUT=300000
# Set to true to make Mocha stop after the first failed test.
MOCHA_BAIL=false
\ No newline at end of file
integration-tests/hardhat.config.ts
View file @
b0582a31
...
...
@@ -4,7 +4,7 @@ import { HardhatUserConfig } from 'hardhat/types'
import
'
@nomiclabs/hardhat-ethers
'
import
'
@nomiclabs/hardhat-waffle
'
import
'
hardhat-gas-reporter
'
import
{
isLiveNetwork
}
from
'
./test/shared/utils
'
import
{
envConfig
}
from
'
./test/shared/utils
'
const
enableGasReport
=
!!
process
.
env
.
ENABLE_GAS_REPORT
...
...
@@ -15,7 +15,8 @@ const config: HardhatUserConfig = {
},
},
mocha
:
{
timeout
:
isLiveNetwork
()
?
300
_000
:
75
_000
,
timeout
:
envConfig
.
MOCHA_TIMEOUT
,
bail
:
envConfig
.
MOCHA_BAIL
,
},
solidity
:
{
compilers
:
[
...
...
integration-tests/package.json
View file @
b0582a31
...
...
@@ -41,7 +41,6 @@
"@types/chai-as-promised"
:
"^7.1.4"
,
"@types/mocha"
:
"^8.2.2"
,
"@types/rimraf"
:
"^3.0.0"
,
"@types/shelljs"
:
"^0.8.8"
,
"@typescript-eslint/eslint-plugin"
:
"^4.26.0"
,
"@typescript-eslint/parser"
:
"^4.26.0"
,
"@uniswap/v3-core"
:
"1.0.0"
,
...
...
@@ -52,7 +51,6 @@
"chai"
:
"^4.3.4"
,
"chai-as-promised"
:
"^7.1.1"
,
"commander"
:
"^8.3.0"
,
"docker-compose"
:
"^0.23.8"
,
"dotenv"
:
"^10.0.0"
,
"envalid"
:
"^7.1.0"
,
"eslint"
:
"^7.27.0"
,
...
...
@@ -71,7 +69,6 @@
"mocha"
:
"^8.4.0"
,
"prom-client"
:
"^14.0.1"
,
"rimraf"
:
"^3.0.2"
,
"shelljs"
:
"^0.8.4"
,
"typescript"
:
"^4.3.5"
,
"uniswap-v3-deploy-plugin"
:
"^0.1.0"
}
...
...
integration-tests/test/basic-l1-l2-communication.spec.ts
View file @
b0582a31
...
...
@@ -8,7 +8,13 @@ import { applyL1ToL2Alias, awaitCondition } from '@eth-optimism/core-utils'
/* Imports: Internal */
import
{
Direction
}
from
'
./shared/watcher-utils
'
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
isMainnet
}
from
'
./shared/utils
'
import
{
DEFAULT_TEST_GAS_L1
,
DEFAULT_TEST_GAS_L2
,
envConfig
,
sleep
,
withdrawalTest
,
}
from
'
./shared/utils
'
describe
(
'
Basic L1<>L2 Communication
'
,
async
()
=>
{
let
Factory__L1SimpleStorage
:
ContractFactory
...
...
@@ -37,42 +43,42 @@ describe('Basic L1<>L2 Communication', async () => {
beforeEach
(
async
()
=>
{
L1SimpleStorage
=
await
Factory__L1SimpleStorage
.
deploy
()
await
L1SimpleStorage
.
deploy
Transaction
.
wait
()
await
L1SimpleStorage
.
deploy
ed
()
L2SimpleStorage
=
await
Factory__L2SimpleStorage
.
deploy
()
await
L2SimpleStorage
.
deploy
Transaction
.
wait
()
await
L2SimpleStorage
.
deploy
ed
()
L2Reverter
=
await
Factory__L2Reverter
.
deploy
()
await
L2Reverter
.
deploy
Transaction
.
wait
()
await
L2Reverter
.
deploy
ed
()
})
describe
(
'
L2 => L1
'
,
()
=>
{
it
(
'
should be able to perform a withdrawal from L2 -> L1
'
,
async
function
()
{
if
(
await
isMainnet
(
env
))
{
console
.
log
(
'
Skipping withdrawals test on mainnet.
'
)
this
.
skip
()
return
}
const
value
=
`0x
${
'
77
'
.
repeat
(
32
)}
`
// Send L2 -> L1 message.
const
transaction
=
await
env
.
l2Messenger
.
sendMessage
(
L1SimpleStorage
.
address
,
L1SimpleStorage
.
interface
.
encodeFunctionData
(
'
setValue
'
,
[
value
]),
5000000
)
await
transaction
.
wait
()
await
env
.
relayXDomainMessages
(
transaction
)
await
env
.
waitForXDomainTransaction
(
transaction
,
Direction
.
L2ToL1
)
withdrawalTest
(
'
should be able to perform a withdrawal from L2 -> L1
'
,
async
()
=>
{
const
value
=
`0x
${
'
77
'
.
repeat
(
32
)}
`
// Send L2 -> L1 message.
const
transaction
=
await
env
.
l2Messenger
.
sendMessage
(
L1SimpleStorage
.
address
,
L1SimpleStorage
.
interface
.
encodeFunctionData
(
'
setValue
'
,
[
value
]),
5000000
,
{
gasLimit
:
DEFAULT_TEST_GAS_L2
,
}
)
await
transaction
.
wait
()
await
env
.
relayXDomainMessages
(
transaction
)
await
env
.
waitForXDomainTransaction
(
transaction
,
Direction
.
L2ToL1
)
expect
(
await
L1SimpleStorage
.
msgSender
()).
to
.
equal
(
env
.
l1Messenger
.
address
)
expect
(
await
L1SimpleStorage
.
xDomainSender
()).
to
.
equal
(
env
.
l2Wallet
.
address
)
expect
(
await
L1SimpleStorage
.
value
()).
to
.
equal
(
value
)
expect
((
await
L1SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
1
)
})
expect
(
await
L1SimpleStorage
.
msgSender
()).
to
.
equal
(
env
.
l1Messenger
.
address
)
expect
(
await
L1SimpleStorage
.
xDomainSender
()).
to
.
equal
(
env
.
l2Wallet
.
address
)
expect
(
await
L1SimpleStorage
.
value
()).
to
.
equal
(
value
)
expect
((
await
L1SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
1
)
}
)
})
describe
(
'
L1 => L2
'
,
()
=>
{
...
...
@@ -83,7 +89,10 @@ describe('Basic L1<>L2 Communication', async () => {
const
transaction
=
await
env
.
l1Messenger
.
sendMessage
(
L2SimpleStorage
.
address
,
L2SimpleStorage
.
interface
.
encodeFunctionData
(
'
setValue
'
,
[
value
]),
5000000
5000000
,
{
gasLimit
:
DEFAULT_TEST_GAS_L1
,
}
)
await
env
.
waitForXDomainTransaction
(
transaction
,
Direction
.
L1ToL2
)
...
...
@@ -101,19 +110,41 @@ describe('Basic L1<>L2 Communication', async () => {
expect
((
await
L2SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
1
)
})
it
(
'
should deposit from L1 -> L2 directly via enqueue
'
,
async
()
=>
{
it
(
'
should deposit from L1 -> L2 directly via enqueue
'
,
async
function
()
{
this
.
timeout
(
envConfig
.
MOCHA_TIMEOUT
*
2
+
envConfig
.
DTL_ENQUEUE_CONFIRMATIONS
*
15000
)
const
value
=
`0x
${
'
42
'
.
repeat
(
32
)}
`
// Send L1 -> L2 message.
await
env
.
ctc
const
tx
=
await
env
.
ctc
.
connect
(
env
.
l1Wallet
)
.
enqueue
(
L2SimpleStorage
.
address
,
5000000
,
L2SimpleStorage
.
interface
.
encodeFunctionData
(
'
setValueNotXDomain
'
,
[
value
,
])
]),
{
gasLimit
:
DEFAULT_TEST_GAS_L1
,
}
)
const
receipt
=
await
tx
.
wait
()
const
waitUntilBlock
=
receipt
.
blockNumber
+
envConfig
.
DTL_ENQUEUE_CONFIRMATIONS
let
currBlock
=
await
env
.
l1Provider
.
getBlockNumber
()
while
(
currBlock
<=
waitUntilBlock
)
{
const
progress
=
envConfig
.
DTL_ENQUEUE_CONFIRMATIONS
-
(
waitUntilBlock
-
currBlock
)
console
.
log
(
`Waiting for
${
progress
}
/
${
envConfig
.
DTL_ENQUEUE_CONFIRMATIONS
}
confirmations.`
)
await
sleep
(
5000
)
currBlock
=
await
env
.
l1Provider
.
getBlockNumber
()
}
console
.
log
(
'
Enqueue should be confirmed.
'
)
await
awaitCondition
(
async
()
=>
{
...
...
@@ -138,8 +169,12 @@ describe('Basic L1<>L2 Communication', async () => {
const
transaction
=
await
env
.
l1Messenger
.
sendMessage
(
L2SimpleStorage
.
address
,
L2SimpleStorage
.
interface
.
encodeFunctionData
(
'
setValue
'
,
[
value
]),
5000000
5000000
,
{
gasLimit
:
DEFAULT_TEST_GAS_L1
,
}
)
await
transaction
.
wait
()
const
{
remoteReceipt
}
=
await
env
.
waitForXDomainTransaction
(
transaction
,
...
...
@@ -155,7 +190,10 @@ describe('Basic L1<>L2 Communication', async () => {
const
transaction
=
await
env
.
l1Messenger
.
sendMessage
(
L2Reverter
.
address
,
L2Reverter
.
interface
.
encodeFunctionData
(
'
doRevert
'
,
[]),
5000000
5000000
,
{
gasLimit
:
DEFAULT_TEST_GAS_L1
,
}
)
const
{
remoteReceipt
}
=
await
env
.
waitForXDomainTransaction
(
...
...
integration-tests/test/bridged-tokens.spec.ts
View file @
b0582a31
...
...
@@ -5,7 +5,7 @@ import { ethers } from 'hardhat'
import
*
as
L2Artifact
from
'
@eth-optimism/contracts/artifacts/contracts/standards/L2StandardERC20.sol/L2StandardERC20.json
'
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
isLiveNetwork
,
isMainne
t
}
from
'
./shared/utils
'
import
{
withdrawalTes
t
}
from
'
./shared/utils
'
import
{
Direction
}
from
'
./shared/watcher-utils
'
describe
(
'
Bridged tokens
'
,
()
=>
{
...
...
@@ -25,14 +25,16 @@ describe('Bridged tokens', () => {
const
other
=
Wallet
.
createRandom
()
otherWalletL1
=
other
.
connect
(
env
.
l1Wallet
.
provider
)
otherWalletL2
=
other
.
connect
(
env
.
l2Wallet
.
provider
)
await
env
.
l1Wallet
.
sendTransaction
({
let
tx
=
await
env
.
l1Wallet
.
sendTransaction
({
to
:
otherWalletL1
.
address
,
value
:
utils
.
parseEther
(
'
0.01
'
),
})
await
env
.
l2Wallet
.
sendTransaction
({
await
tx
.
wait
()
tx
=
await
env
.
l2Wallet
.
sendTransaction
({
to
:
otherWalletL2
.
address
,
value
:
utils
.
parseEther
(
'
0.01
'
),
})
await
tx
.
wait
()
L1Factory__ERC20
=
await
ethers
.
getContractFactory
(
'
ERC20
'
,
env
.
l1Wallet
)
L2Factory__ERC20
=
new
ethers
.
ContractFactory
(
...
...
@@ -77,7 +79,7 @@ describe('Bridged tokens', () => {
expect
(
await
L2__ERC20
.
balanceOf
(
env
.
l2Wallet
.
address
)).
to
.
deep
.
equal
(
BigNumber
.
from
(
1000
)
)
})
.
timeout
(
isLiveNetwork
()
?
300
_000
:
120
_000
)
})
it
(
'
should transfer tokens on L2
'
,
async
()
=>
{
const
tx
=
await
L2__ERC20
.
transfer
(
otherWalletL1
.
address
,
500
)
...
...
@@ -90,46 +92,40 @@ describe('Bridged tokens', () => {
)
})
it
(
'
should withdraw tokens from L2 to the depositor
'
,
async
function
()
{
if
(
await
isMainnet
(
env
))
{
console
.
log
(
'
Skipping withdrawals test on mainnet.
'
)
this
.
skip
()
return
withdrawalTest
(
'
should withdraw tokens from L2 to the depositor
'
,
async
()
=>
{
const
tx
=
await
env
.
l2Bridge
.
withdraw
(
L2__ERC20
.
address
,
500
,
2000000
,
'
0x
'
)
await
env
.
relayXDomainMessages
(
tx
)
await
env
.
waitForXDomainTransaction
(
tx
,
Direction
.
L2ToL1
)
expect
(
await
L1__ERC20
.
balanceOf
(
env
.
l1Wallet
.
address
)).
to
.
deep
.
equal
(
BigNumber
.
from
(
999500
)
)
expect
(
await
L2__ERC20
.
balanceOf
(
env
.
l2Wallet
.
address
)).
to
.
deep
.
equal
(
BigNumber
.
from
(
0
)
)
}
const
tx
=
await
env
.
l2Bridge
.
withdraw
(
L2__ERC20
.
address
,
500
,
2000000
,
'
0x
'
)
await
env
.
relayXDomainMessages
(
tx
)
await
env
.
waitForXDomainTransaction
(
tx
,
Direction
.
L2ToL1
)
expect
(
await
L1__ERC20
.
balanceOf
(
env
.
l1Wallet
.
address
)).
to
.
deep
.
equal
(
BigNumber
.
from
(
999500
)
)
expect
(
await
L2__ERC20
.
balanceOf
(
env
.
l2Wallet
.
address
)).
to
.
deep
.
equal
(
BigNumber
.
from
(
0
)
)
}).
timeout
(
isLiveNetwork
()
?
300
_000
:
120
_000
)
it
(
'
should withdraw tokens from L2 to the transfer recipient
'
,
async
function
()
{
if
(
await
isMainnet
(
env
))
{
console
.
log
(
'
Skipping withdrawals test on mainnet.
'
)
this
.
skip
()
return
)
withdrawalTest
(
'
should withdraw tokens from L2 to the transfer recipient
'
,
async
()
=>
{
const
tx
=
await
env
.
l2Bridge
.
connect
(
otherWalletL2
)
.
withdraw
(
L2__ERC20
.
address
,
500
,
2000000
,
'
0x
'
)
await
env
.
relayXDomainMessages
(
tx
)
await
env
.
waitForXDomainTransaction
(
tx
,
Direction
.
L2ToL1
)
expect
(
await
L1__ERC20
.
balanceOf
(
otherWalletL1
.
address
)).
to
.
deep
.
equal
(
BigNumber
.
from
(
500
)
)
expect
(
await
L2__ERC20
.
balanceOf
(
otherWalletL2
.
address
)).
to
.
deep
.
equal
(
BigNumber
.
from
(
0
)
)
}
const
tx
=
await
env
.
l2Bridge
.
connect
(
otherWalletL2
)
.
withdraw
(
L2__ERC20
.
address
,
500
,
2000000
,
'
0x
'
)
await
env
.
relayXDomainMessages
(
tx
)
await
env
.
waitForXDomainTransaction
(
tx
,
Direction
.
L2ToL1
)
expect
(
await
L1__ERC20
.
balanceOf
(
otherWalletL1
.
address
)).
to
.
deep
.
equal
(
BigNumber
.
from
(
500
)
)
expect
(
await
L2__ERC20
.
balanceOf
(
otherWalletL2
.
address
)).
to
.
deep
.
equal
(
BigNumber
.
from
(
0
)
)
}).
timeout
(
isLiveNetwork
()
?
300
_000
:
120
_000
)
)
})
integration-tests/test/fee-payment.spec.ts
View file @
b0582a31
...
...
@@ -6,14 +6,11 @@ import { serialize } from '@ethersproject/transactions'
import
{
predeploys
,
getContractFactory
}
from
'
@eth-optimism/contracts
'
/* Imports: Internal */
import
{
isLiveNetwork
}
from
'
./shared/utils
'
import
{
hardhatTest
}
from
'
./shared/utils
'
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
Direction
}
from
'
./shared/watcher-utils
'
const
setPrices
=
async
(
env
:
OptimismEnv
,
value
:
number
|
BigNumber
)
=>
{
if
(
isLiveNetwork
())
{
return
}
const
gasPrice
=
await
env
.
gasPriceOracle
.
setGasPrice
(
value
)
await
gasPrice
.
wait
()
const
baseFee
=
await
env
.
gasPriceOracle
.
setL1BaseFee
(
value
)
...
...
@@ -28,24 +25,25 @@ describe('Fee Payment Integration Tests', async () => {
env
=
await
OptimismEnv
.
new
()
})
if
(
!
isLiveNetwork
())
{
it
(
`should return eth_gasPrice equal to OVM_GasPriceOracle.gasPrice`
,
async
()
=>
{
hardhatTest
(
`should return eth_gasPrice equal to OVM_GasPriceOracle.gasPrice`
,
async
()
=>
{
const
assertGasPrice
=
async
()
=>
{
const
gasPrice
=
await
env
.
l2Wallet
.
getGasPrice
()
const
oracleGasPrice
=
await
env
.
gasPriceOracle
.
gasPrice
()
expect
(
gasPrice
).
to
.
deep
.
equal
(
oracleGasPrice
)
}
assertGasPrice
()
a
wait
a
ssertGasPrice
()
// update the gas price
const
tx
=
await
env
.
gasPriceOracle
.
setGasPrice
(
1000
)
await
tx
.
wait
()
assertGasPrice
()
}
)
}
a
wait
a
ssertGasPrice
()
}
)
i
t
(
'
Paying a nonzero but acceptable gasPrice fee
'
,
async
()
=>
{
hardhatTes
t
(
'
Paying a nonzero but acceptable gasPrice fee
'
,
async
()
=>
{
await
setPrices
(
env
,
1000
)
const
amount
=
utils
.
parseEther
(
'
0.0000001
'
)
...
...
@@ -97,7 +95,7 @@ describe('Fee Payment Integration Tests', async () => {
await
setPrices
(
env
,
1
)
})
i
t
(
'
should compute correct fee
'
,
async
()
=>
{
hardhatTes
t
(
'
should compute correct fee
'
,
async
()
=>
{
await
setPrices
(
env
,
1000
)
const
preBalance
=
await
env
.
l2Wallet
.
getBalance
()
...
...
@@ -149,39 +147,38 @@ describe('Fee Payment Integration Tests', async () => {
await
expect
(
env
.
sequencerFeeVault
.
withdraw
()).
to
.
be
.
rejected
})
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
balanceBefore
=
await
env
.
l1Wallet
.
provider
.
getBalance
(
l1FeeWallet
)
const
withdrawalAmount
=
await
env
.
sequencerFeeVault
.
MIN_WITHDRAWAL_AMOUNT
()
// Transfer the minimum required to withdraw.
const
tx
=
await
env
.
l2Wallet
.
sendTransaction
({
to
:
env
.
sequencerFeeVault
.
address
,
value
:
withdrawalAmount
,
gasLimit
:
500000
,
})
await
tx
.
wait
()
hardhatTest
(
'
should be able to withdraw fees back to L1 once the minimum is met
'
,
async
()
=>
{
const
l1FeeWallet
=
await
env
.
sequencerFeeVault
.
l1FeeWallet
()
const
balanceBefore
=
await
env
.
l1Wallet
.
provider
.
getBalance
(
l1FeeWallet
)
const
withdrawalAmount
=
await
env
.
sequencerFeeVault
.
MIN_WITHDRAWAL_AMOUNT
()
// Transfer the minimum required to withdraw.
const
tx
=
await
env
.
l2Wallet
.
sendTransaction
({
to
:
env
.
sequencerFeeVault
.
address
,
value
:
withdrawalAmount
,
gasLimit
:
500000
,
})
await
tx
.
wait
()
const
vaultBalance
=
await
env
.
ovmEth
.
balanceOf
(
env
.
sequencerFeeVault
.
address
)
const
vaultBalance
=
await
env
.
ovmEth
.
balanceOf
(
env
.
sequencerFeeVault
.
address
)
const
withdrawTx
=
await
env
.
sequencerFeeVault
.
withdraw
()
const
withdrawTx
=
await
env
.
sequencerFeeVault
.
withdraw
()
// Wait for the withdrawal to be relayed to L1.
await
withdrawTx
.
wait
()
await
env
.
relayXDomainMessages
(
withdrawTx
)
await
env
.
waitForXDomainTransaction
(
withdrawTx
,
Direction
.
L2ToL1
)
// Wait for the withdrawal to be relayed to L1.
await
withdrawTx
.
wait
()
await
env
.
relayXDomainMessages
(
withdrawTx
)
await
env
.
waitForXDomainTransaction
(
withdrawTx
,
Direction
.
L2ToL1
)
// Balance difference should be equal to old L2 balance.
const
balanceAfter
=
await
env
.
l1Wallet
.
provider
.
getBalance
(
l1FeeWallet
)
expect
(
balanceAfter
.
sub
(
balanceBefore
)).
to
.
deep
.
equal
(
BigNumber
.
from
(
vaultBalance
)
)
})
// Balance difference should be equal to old L2 balance.
const
balanceAfter
=
await
env
.
l1Wallet
.
provider
.
getBalance
(
l1FeeWallet
)
expect
(
balanceAfter
.
sub
(
balanceBefore
)).
to
.
deep
.
equal
(
BigNumber
.
from
(
vaultBalance
)
)
}
)
})
integration-tests/test/native-eth-ovm-calls.spec.ts
View file @
b0582a31
...
...
@@ -45,7 +45,7 @@ describe('Native ETH value integration tests', () => {
const
there
=
await
wallet
.
sendTransaction
({
to
:
other
.
address
,
value
,
gasPrice
:
await
gasPriceForL2
(
env
),
gasPrice
:
await
gasPriceForL2
(),
})
const
thereReceipt
=
await
there
.
wait
()
const
thereGas
=
thereReceipt
.
gasUsed
.
mul
(
there
.
gasPrice
)
...
...
@@ -63,7 +63,7 @@ describe('Native ETH value integration tests', () => {
const
backAgain
=
await
other
.
sendTransaction
({
to
:
wallet
.
address
,
value
:
backVal
,
gasPrice
:
await
gasPriceForL2
(
env
),
gasPrice
:
await
gasPriceForL2
(),
})
const
backReceipt
=
await
backAgain
.
wait
()
const
backGas
=
backReceipt
.
gasUsed
.
mul
(
backAgain
.
gasPrice
)
...
...
@@ -169,7 +169,7 @@ describe('Native ETH value integration tests', () => {
it
(
'
should allow ETH to be sent
'
,
async
()
=>
{
const
sendAmount
=
15
const
tx
=
await
ValueCalls0
.
simpleSend
(
ValueCalls1
.
address
,
sendAmount
,
{
gasPrice
:
await
gasPriceForL2
(
env
),
gasPrice
:
await
gasPriceForL2
(),
})
await
tx
.
wait
()
...
...
integration-tests/test/native-eth.spec.ts
View file @
b0582a31
...
...
@@ -9,11 +9,15 @@ import { expectApprox } from '@eth-optimism/core-utils'
/* Imports: Internal */
import
{
Direction
}
from
'
./shared/watcher-utils
'
import
{
isMainnet
,
PROXY_SEQUENCER_ENTRYPOINT_ADDRESS
}
from
'
./shared/utils
'
import
{
DEFAULT_TEST_GAS_L1
,
DEFAULT_TEST_GAS_L2
,
envConfig
,
PROXY_SEQUENCER_ENTRYPOINT_ADDRESS
,
withdrawalTest
,
}
from
'
./shared/utils
'
import
{
OptimismEnv
}
from
'
./shared/env
'
const
DEFAULT_TEST_GAS_L1
=
330
_000
const
DEFAULT_TEST_GAS_L2
=
1
_300_000
// TX size enforced by CTC:
const
MAX_ROLLUP_TX_SIZE
=
50
_000
...
...
@@ -183,13 +187,7 @@ describe('Native ETH Integration Tests', async () => {
).
to
.
be
.
reverted
})
it
(
'
withdraw
'
,
async
function
()
{
if
(
await
isMainnet
(
env
))
{
console
.
log
(
'
Skipping withdrawals test on mainnet.
'
)
this
.
skip
()
return
}
withdrawalTest
(
'
withdraw
'
,
async
()
=>
{
const
withdrawAmount
=
BigNumber
.
from
(
3
)
const
preBalances
=
await
getBalances
(
env
)
expect
(
...
...
@@ -231,13 +229,7 @@ describe('Native ETH Integration Tests', async () => {
)
})
it
(
'
withdrawTo
'
,
async
function
()
{
if
(
await
isMainnet
(
env
))
{
console
.
log
(
'
Skipping withdrawals test on mainnet.
'
)
this
.
skip
()
return
}
withdrawalTest
(
'
withdrawTo
'
,
async
()
=>
{
const
withdrawAmount
=
BigNumber
.
from
(
3
)
const
preBalances
=
await
getBalances
(
env
)
...
...
@@ -295,73 +287,71 @@ describe('Native ETH Integration Tests', async () => {
)
})
it
(
'
deposit, transfer, withdraw
'
,
async
function
()
{
if
(
await
isMainnet
(
env
))
{
console
.
log
(
'
Skipping withdrawals test on mainnet.
'
)
this
.
skip
()
return
}
// 1. deposit
const
amount
=
utils
.
parseEther
(
'
1
'
)
await
env
.
waitForXDomainTransaction
(
env
.
l1Bridge
.
depositETH
(
DEFAULT_TEST_GAS_L2
,
'
0xFFFF
'
,
{
value
:
amount
,
gasLimit
:
DEFAULT_TEST_GAS_L1
,
}),
Direction
.
L1ToL2
)
// 2. transfer to another address
const
other
=
Wallet
.
createRandom
().
connect
(
env
.
l2Wallet
.
provider
)
const
tx
=
await
env
.
l2Wallet
.
sendTransaction
({
to
:
other
.
address
,
value
:
amount
,
})
await
tx
.
wait
()
const
l1BalanceBefore
=
await
other
.
connect
(
env
.
l1Wallet
.
provider
)
.
getBalance
()
// 3. do withdrawal
const
withdrawnAmount
=
utils
.
parseEther
(
'
0.95
'
)
const
transaction
=
await
env
.
l2Bridge
.
connect
(
other
)
.
withdraw
(
predeploys
.
OVM_ETH
,
withdrawnAmount
,
DEFAULT_TEST_GAS_L1
,
'
0xFFFF
'
withdrawalTest
(
'
deposit, transfer, withdraw
'
,
async
()
=>
{
// 1. deposit
const
amount
=
utils
.
parseEther
(
'
1
'
)
await
env
.
waitForXDomainTransaction
(
env
.
l1Bridge
.
depositETH
(
DEFAULT_TEST_GAS_L2
,
'
0xFFFF
'
,
{
value
:
amount
,
gasLimit
:
DEFAULT_TEST_GAS_L1
,
}),
Direction
.
L1ToL2
)
await
transaction
.
wait
()
await
env
.
relayXDomainMessages
(
transaction
)
const
receipts
=
await
env
.
waitForXDomainTransaction
(
transaction
,
Direction
.
L2ToL1
)
// Compute the L1 portion of the fee
const
l1Fee
=
await
env
.
gasPriceOracle
.
getL1Fee
(
serialize
({
nonce
:
transaction
.
nonce
,
value
:
transaction
.
value
,
gasPrice
:
transaction
.
gasPrice
,
gasLimit
:
transaction
.
gasLimit
,
to
:
transaction
.
to
,
data
:
transaction
.
data
,
// 2. transfer to another address
const
other
=
Wallet
.
createRandom
().
connect
(
env
.
l2Wallet
.
provider
)
const
tx
=
await
env
.
l2Wallet
.
sendTransaction
({
to
:
other
.
address
,
value
:
amount
,
})
)
await
tx
.
wait
()
const
l1BalanceBefore
=
await
other
.
connect
(
env
.
l1Wallet
.
provider
)
.
getBalance
()
// 3. do withdrawal
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
(
transaction
,
Direction
.
L2ToL1
)
// check that correct amount was withdrawn and that fee was charged
const
l2Fee
=
receipts
.
tx
.
gasPrice
.
mul
(
receipts
.
receipt
.
gasUsed
)
// Compute the L1 portion of the fee
const
l1Fee
=
await
env
.
gasPriceOracle
.
getL1Fee
(
serialize
({
nonce
:
transaction
.
nonce
,
value
:
transaction
.
value
,
gasPrice
:
transaction
.
gasPrice
,
gasLimit
:
transaction
.
gasLimit
,
to
:
transaction
.
to
,
data
:
transaction
.
data
,
})
)
const
fee
=
l1Fee
.
add
(
l2Fee
)
const
l1BalanceAfter
=
await
other
.
connect
(
env
.
l1Wallet
.
provider
)
.
getBalance
()
const
l2BalanceAfter
=
await
other
.
getBalance
()
expect
(
l1BalanceAfter
).
to
.
deep
.
eq
(
l1BalanceBefore
.
add
(
withdrawnAmount
))
expect
(
l2BalanceAfter
).
to
.
deep
.
eq
(
amount
.
sub
(
withdrawnAmount
).
sub
(
fee
))
})
// check that correct amount was withdrawn and that fee was charged
const
l2Fee
=
receipts
.
tx
.
gasPrice
.
mul
(
receipts
.
receipt
.
gasUsed
)
const
fee
=
l1Fee
.
add
(
l2Fee
)
const
l1BalanceAfter
=
await
other
.
connect
(
env
.
l1Wallet
.
provider
)
.
getBalance
()
const
l2BalanceAfter
=
await
other
.
getBalance
()
expect
(
l1BalanceAfter
).
to
.
deep
.
eq
(
l1BalanceBefore
.
add
(
withdrawnAmount
))
expect
(
l2BalanceAfter
).
to
.
deep
.
eq
(
amount
.
sub
(
withdrawnAmount
).
sub
(
fee
))
},
envConfig
.
MOCHA_TIMEOUT
*
3
)
})
integration-tests/test/ovmcontext.spec.ts
View file @
b0582a31
...
...
@@ -7,7 +7,12 @@ import { predeploys } from '@eth-optimism/contracts'
import
{
Contract
,
BigNumber
}
from
'
ethers
'
/* Imports: Internal */
import
{
l2Provider
,
l1Provider
,
IS_LIVE_NETWORK
}
from
'
./shared/utils
'
import
{
l2Provider
,
l1Provider
,
envConfig
,
DEFAULT_TEST_GAS_L1
,
}
from
'
./shared/utils
'
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
Direction
}
from
'
./shared/watcher-utils
'
...
...
@@ -41,11 +46,7 @@ describe('OVM Context: Layer 2 EVM Context', () => {
await
Multicall
.
deployTransaction
.
wait
()
})
let
numTxs
=
5
if
(
IS_LIVE_NETWORK
)
{
// Tests take way too long if we don't reduce the number of txs here.
numTxs
=
1
}
const
numTxs
=
envConfig
.
OVMCONTEXT_SPEC_NUM_TXS
it
(
'
enqueue: L1 contextual values are correctly set in L2
'
,
async
()
=>
{
for
(
let
i
=
0
;
i
<
numTxs
;
i
++
)
{
...
...
@@ -54,7 +55,10 @@ describe('OVM Context: Layer 2 EVM Context', () => {
const
tx
=
await
env
.
l1Messenger
.
sendMessage
(
OVMContextStorage
.
address
,
'
0x
'
,
2
_000_000
2
_000_000
,
{
gasLimit
:
DEFAULT_TEST_GAS_L1
,
}
)
// Wait for the transaction to be sent over to L2.
...
...
@@ -89,7 +93,7 @@ describe('OVM Context: Layer 2 EVM Context', () => {
const
coinbase
=
await
OVMContextStorage
.
coinbases
(
i
)
expect
(
coinbase
).
to
.
equal
(
predeploys
.
OVM_SequencerFeeVault
)
}
})
.
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
()
=>
{
for
(
let
i
=
0
;
i
<
numTxs
;
i
++
)
{
...
...
integration-tests/test/queue-ingestion.spec.ts
View file @
b0582a31
...
...
@@ -7,7 +7,7 @@ import { injectL2Context, applyL1ToL2Alias } from '@eth-optimism/core-utils'
/* Imports: External */
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
Direction
}
from
'
./shared/watcher-utils
'
import
{
isLiveNetwork
}
from
'
./shared/utils
'
import
{
DEFAULT_TEST_GAS_L1
,
envConfig
}
from
'
./shared/utils
'
describe
(
'
Queue Ingestion
'
,
()
=>
{
let
env
:
OptimismEnv
...
...
@@ -21,7 +21,7 @@ describe('Queue Ingestion', () => {
// that are in the queue and submit them. L2 will pick up the
// sequencer batch appended event and play the transactions.
it
(
'
should order transactions correctly
'
,
async
()
=>
{
const
numTxs
=
5
const
numTxs
=
envConfig
.
OVMCONTEXT_SPEC_NUM_TXS
// Enqueue some transactions by building the calldata and then sending
// the transaction to Layer 1
...
...
@@ -30,7 +30,10 @@ describe('Queue Ingestion', () => {
const
tx
=
await
env
.
l1Messenger
.
sendMessage
(
`0x
${
`
${
i
}
`
.
repeat
(
40
)}
`
,
`0x0
${
i
}
`
,
1
_000_000
1
_000_000
,
{
gasLimit
:
DEFAULT_TEST_GAS_L1
,
}
)
await
tx
.
wait
()
txs
.
push
(
tx
)
...
...
@@ -62,5 +65,5 @@ describe('Queue Ingestion', () => {
)
expect
(
l2Tx
.
l1BlockNumber
).
to
.
equal
(
l1TxReceipt
.
blockNumber
)
}
})
.
timeout
(
isLiveNetwork
()
?
300
_000
:
100
_000
)
})
})
integration-tests/test/replica.spec.ts
View file @
b0582a31
...
...
@@ -4,26 +4,26 @@ import {
defaultTransactionFactory
,
gasPriceForL2
,
sleep
,
isLiveNetwork
,
envConfig
,
}
from
'
./shared/utils
'
import
{
TransactionReceipt
}
from
'
@ethersproject/abstract-provider
'
describe
(
'
Replica Tests
'
,
()
=>
{
let
env
:
OptimismEnv
before
(
async
()
=>
{
before
(
async
function
()
{
if
(
!
envConfig
.
RUN_REPLICA_TESTS
)
{
this
.
skip
()
return
}
env
=
await
OptimismEnv
.
new
()
})
describe
(
'
Matching blocks
'
,
()
=>
{
if
(
isLiveNetwork
())
{
console
.
log
(
'
Skipping replica tests on live network
'
)
return
}
it
(
'
should sync a transaction
'
,
async
()
=>
{
const
tx
=
defaultTransactionFactory
()
tx
.
gasPrice
=
await
gasPriceForL2
(
env
)
tx
.
gasPrice
=
await
gasPriceForL2
()
const
result
=
await
env
.
l2Wallet
.
sendTransaction
(
tx
)
let
receipt
:
TransactionReceipt
...
...
@@ -48,7 +48,7 @@ describe('Replica Tests', () => {
const
tx
=
{
...
defaultTransactionFactory
(),
nonce
:
await
env
.
l2Wallet
.
getTransactionCount
(),
gasPrice
:
await
gasPriceForL2
(
env
),
gasPrice
:
await
gasPriceForL2
(),
chainId
:
null
,
// Disables EIP155 transaction signing.
}
const
signed
=
await
env
.
l2Wallet
.
signTransaction
(
tx
)
...
...
@@ -76,7 +76,7 @@ describe('Replica Tests', () => {
const
tx
=
{
...
defaultTransactionFactory
(),
nonce
:
await
env
.
l2Wallet
.
getTransactionCount
(),
gasPrice
:
await
gasPriceForL2
(
env
),
gasPrice
:
await
gasPriceForL2
(),
}
const
signed
=
await
env
.
l2Wallet
.
signTransaction
(
tx
)
const
result
=
await
env
.
replicaProvider
.
sendTransaction
(
signed
)
...
...
integration-tests/test/rpc.spec.ts
View file @
b0582a31
...
...
@@ -10,8 +10,10 @@ import {
defaultTransactionFactory
,
fundUser
,
L2_CHAINID
,
isLiveNetwork
,
gasPriceForL2
,
isHardhat
,
hardhatTest
,
envConfig
,
}
from
'
./shared/utils
'
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
...
...
@@ -56,7 +58,7 @@ describe('Basic RPC tests', () => {
describe
(
'
eth_sendRawTransaction
'
,
()
=>
{
it
(
'
should correctly process a valid transaction
'
,
async
()
=>
{
const
tx
=
defaultTransactionFactory
()
tx
.
gasPrice
=
await
gasPriceForL2
(
env
)
tx
.
gasPrice
=
await
gasPriceForL2
()
const
nonce
=
await
wallet
.
getTransactionCount
()
const
result
=
await
wallet
.
sendTransaction
(
tx
)
...
...
@@ -70,7 +72,7 @@ describe('Basic RPC tests', () => {
it
(
'
should not accept a transaction with the wrong chain ID
'
,
async
()
=>
{
const
tx
=
{
...
defaultTransactionFactory
(),
gasPrice
:
await
gasPriceForL2
(
env
),
gasPrice
:
await
gasPriceForL2
(),
chainId
:
(
await
wallet
.
getChainId
())
+
1
,
}
...
...
@@ -83,7 +85,7 @@ describe('Basic RPC tests', () => {
const
tx
=
{
...
defaultTransactionFactory
(),
nonce
:
await
wallet
.
getTransactionCount
(),
gasPrice
:
await
gasPriceForL2
(
env
),
gasPrice
:
await
gasPriceForL2
(),
chainId
:
null
,
// Disables EIP155 transaction signing.
}
const
signed
=
await
wallet
.
signTransaction
(
tx
)
...
...
@@ -97,7 +99,7 @@ describe('Basic RPC tests', () => {
it
(
'
should accept a transaction with a value
'
,
async
()
=>
{
const
tx
=
{
...
defaultTransactionFactory
(),
gasPrice
:
await
gasPriceForL2
(
env
),
gasPrice
:
await
gasPriceForL2
(),
chainId
:
await
env
.
l2Wallet
.
getChainId
(),
data
:
'
0x
'
,
value
:
ethers
.
utils
.
parseEther
(
'
0.1
'
),
...
...
@@ -117,7 +119,7 @@ describe('Basic RPC tests', () => {
const
balance
=
await
env
.
l2Wallet
.
getBalance
()
const
tx
=
{
...
defaultTransactionFactory
(),
gasPrice
:
await
gasPriceForL2
(
env
),
gasPrice
:
await
gasPriceForL2
(),
chainId
:
await
env
.
l2Wallet
.
getChainId
(),
data
:
'
0x
'
,
value
:
balance
.
add
(
ethers
.
utils
.
parseEther
(
'
1
'
)),
...
...
@@ -137,32 +139,29 @@ describe('Basic RPC tests', () => {
})
it
(
'
should reject a transaction with too low of a fee
'
,
async
()
=>
{
if
(
isLiveNetwork
())
{
console
.
log
(
'
Skipping too low of a fee test on live network
'
)
return
const
isHH
=
await
isHardhat
()
let
gasPrice
if
(
isHH
)
{
gasPrice
=
await
env
.
gasPriceOracle
.
gasPrice
()
await
env
.
gasPriceOracle
.
setGasPrice
(
1000
)
}
const
gasPrice
=
await
env
.
gasPriceOracle
.
gasPrice
()
await
env
.
gasPriceOracle
.
setGasPrice
(
1000
)
const
tx
=
{
...
defaultTransactionFactory
(),
gasPrice
:
1
,
}
await
expect
(
env
.
l2Wallet
.
sendTransaction
(
tx
)).
to
.
be
.
rejectedWith
(
`gas price too low: 1 wei, use at least tx.gasPrice = 1000 wei`
/gas price too low: 1 wei, use at least tx
\.
gasPrice =
\d
+ wei/
)
// Reset the gas price to its original price
await
env
.
gasPriceOracle
.
setGasPrice
(
gasPrice
)
})
it
(
'
should reject a transaction with too high of a fee
'
,
async
()
=>
{
if
(
isLiveNetwork
())
{
console
.
log
(
'
Skpping too high of a fee test on live network
'
)
return
if
(
isHH
)
{
// Reset the gas price to its original price
await
env
.
gasPriceOracle
.
setGasPrice
(
gasPrice
)
}
})
it
(
'
should reject a transaction with too high of a fee
'
,
async
()
=>
{
const
gasPrice
=
await
env
.
gasPriceOracle
.
gasPrice
()
const
largeGasPrice
=
gasPrice
.
mul
(
10
)
const
tx
=
{
...
...
@@ -332,7 +331,7 @@ describe('Basic RPC tests', () => {
it
(
'
includes L1 gas price and L1 gas used
'
,
async
()
=>
{
const
tx
=
await
env
.
l2Wallet
.
populateTransaction
({
to
:
env
.
l2Wallet
.
address
,
gasPrice
:
isLiveNetwork
()
?
10000
:
1
,
gasPrice
:
await
gasPriceForL2
()
,
})
const
raw
=
serialize
({
...
...
@@ -367,7 +366,7 @@ describe('Basic RPC tests', () => {
describe
(
'
eth_getTransactionByHash
'
,
()
=>
{
it
(
'
should be able to get all relevant l1/l2 transaction data
'
,
async
()
=>
{
const
tx
=
defaultTransactionFactory
()
tx
.
gasPrice
=
await
gasPriceForL2
(
env
)
tx
.
gasPrice
=
await
gasPriceForL2
()
const
result
=
await
wallet
.
sendTransaction
(
tx
)
await
result
.
wait
()
...
...
@@ -382,7 +381,7 @@ describe('Basic RPC tests', () => {
it
(
'
should return the block and all included transactions
'
,
async
()
=>
{
// Send a transaction and wait for it to be mined.
const
tx
=
defaultTransactionFactory
()
tx
.
gasPrice
=
await
gasPriceForL2
(
env
)
tx
.
gasPrice
=
await
gasPriceForL2
()
const
result
=
await
wallet
.
sendTransaction
(
tx
)
const
receipt
=
await
result
.
wait
()
...
...
@@ -408,32 +407,31 @@ describe('Basic RPC tests', () => {
// 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
(
isLiveNetwork
())
{
this
.
skip
()
}
// Get latest block once to start.
const
prev
=
await
provider
.
getBlockWithTransactions
(
'
latest
'
)
// set wait to null to allow a deep object comparison
prev
.
transactions
[
0
].
wait
=
null
// Over ten seconds, repeatedly check the latest block to make sure nothing has changed.
for
(
let
i
=
0
;
i
<
5
;
i
++
)
{
const
latest
=
await
provider
.
getBlockWithTransactions
(
'
latest
'
)
latest
.
transactions
[
0
].
wait
=
null
// Check each key of the transaction individually
// for easy debugging if one field changes
for
(
const
[
key
,
value
]
of
Object
.
entries
(
latest
.
transactions
[
0
]))
{
expect
(
value
).
to
.
deep
.
equal
(
prev
.
transactions
[
0
][
key
],
`mismatch
${
key
}
`
)
hardhatTest
(
'
should return the same result when new transactions are not applied
'
,
async
()
=>
{
// Get latest block once to start.
const
prev
=
await
provider
.
getBlockWithTransactions
(
'
latest
'
)
// set wait to null to allow a deep object comparison
prev
.
transactions
[
0
].
wait
=
null
// Over ten seconds, repeatedly check the latest block to make sure nothing has changed.
for
(
let
i
=
0
;
i
<
5
;
i
++
)
{
const
latest
=
await
provider
.
getBlockWithTransactions
(
'
latest
'
)
latest
.
transactions
[
0
].
wait
=
null
// Check each key of the transaction individually
// for easy debugging if one field changes
for
(
const
[
key
,
value
]
of
Object
.
entries
(
latest
.
transactions
[
0
]))
{
expect
(
value
).
to
.
deep
.
equal
(
prev
.
transactions
[
0
][
key
],
`mismatch
${
key
}
`
)
}
expect
(
latest
).
to
.
deep
.
equal
(
prev
)
await
sleep
(
2000
)
}
expect
(
latest
).
to
.
deep
.
equal
(
prev
)
await
sleep
(
2000
)
}
}
)
)
})
describe
(
'
eth_getBalance
'
,
()
=>
{
...
...
@@ -489,6 +487,12 @@ describe('Basic RPC tests', () => {
})
describe
(
'
debug_traceTransaction
'
,
()
=>
{
before
(
async
function
()
{
if
(
!
envConfig
.
RUN_DEBUG_TRACE_TESTS
)
{
this
.
skip
()
}
})
it
(
'
should match debug_traceBlock
'
,
async
()
=>
{
const
storage
=
await
ethers
.
getContractFactory
(
'
SimpleStorage
'
,
...
...
integration-tests/test/setup-docker-compose-network.ts
deleted
100644 → 0
View file @
ae96d784
import
{
DockerComposeNetwork
}
from
'
./shared/docker-compose
'
before
(
async
()
=>
{
if
(
!
process
.
env
.
NO_NETWORK
)
{
await
new
DockerComposeNetwork
().
up
()
}
})
integration-tests/test/shared/docker-compose.ts
deleted
100644 → 0
View file @
ae96d784
import
*
as
compose
from
'
docker-compose
'
import
*
as
shell
from
'
shelljs
'
import
*
as
path
from
'
path
'
type
ServiceNames
=
|
'
batch_submitter
'
|
'
dtl
'
|
'
l2geth
'
|
'
relayer
'
|
'
verifier
'
|
'
replica
'
const
OPS_DIRECTORY
=
path
.
join
(
process
.
cwd
(),
'
../ops
'
)
const
DEFAULT_SERVICES
:
ServiceNames
[]
=
[
'
batch_submitter
'
,
'
dtl
'
,
'
l2geth
'
,
'
relayer
'
,
]
export
class
DockerComposeNetwork
{
constructor
(
private
readonly
services
:
ServiceNames
[]
=
DEFAULT_SERVICES
)
{}
async
up
(
options
?:
compose
.
IDockerComposeOptions
)
{
const
out
=
await
compose
.
upMany
(
this
.
services
,
{
cwd
:
OPS_DIRECTORY
,
...
options
,
})
const
{
err
,
exitCode
}
=
out
if
(
!
err
||
exitCode
)
{
console
.
error
(
err
)
throw
new
Error
(
'
Unexpected error when starting docker-compose network, dumping output
'
)
}
if
(
err
.
includes
(
'
Creating
'
))
{
console
.
info
(
'
🐳 Tests required starting containers. Waiting for sequencer to ready.
'
)
shell
.
exec
(
`
${
OPS_DIRECTORY
}
/scripts/wait-for-sequencer.sh`
,
{
cwd
:
OPS_DIRECTORY
,
})
}
return
out
}
async
logs
()
{
return
compose
.
logs
(
this
.
services
,
{
cwd
:
OPS_DIRECTORY
})
}
async
stop
(
service
:
ServiceNames
)
{
return
compose
.
stopOne
(
service
,
{
cwd
:
OPS_DIRECTORY
})
}
async
rm
()
{
return
compose
.
rm
({
cwd
:
OPS_DIRECTORY
})
}
}
integration-tests/test/shared/env.ts
View file @
b0582a31
...
...
@@ -19,6 +19,8 @@ import {
getL1Bridge
,
getL2Bridge
,
sleep
,
envConfig
,
DEFAULT_TEST_GAS_L1
,
}
from
'
./utils
'
import
{
initWatcher
,
...
...
@@ -83,8 +85,10 @@ export class OptimismEnv {
// fund the user if needed
const
balance
=
await
l2Wallet
.
getBalance
()
if
(
balance
.
lt
(
utils
.
parseEther
(
'
1
'
)))
{
await
fundUser
(
watcher
,
l1Bridge
,
utils
.
parseEther
(
'
1
'
).
sub
(
balance
))
const
min
=
envConfig
.
L2_WALLET_MIN_BALANCE_ETH
.
toString
()
const
topUp
=
envConfig
.
L2_WALLET_TOP_UP_AMOUNT_ETH
.
toString
()
if
(
balance
.
lt
(
utils
.
parseEther
(
min
)))
{
await
fundUser
(
watcher
,
l1Bridge
,
utils
.
parseEther
(
topUp
))
}
const
l1Messenger
=
getContractFactory
(
'
L1CrossDomainMessenger
'
)
.
connect
(
l1Wallet
)
...
...
@@ -156,6 +160,7 @@ export class OptimismEnv {
tx
:
Promise
<
TransactionResponse
>
|
TransactionResponse
):
Promise
<
void
>
{
tx
=
await
tx
await
tx
.
wait
()
let
messagePairs
=
[]
while
(
true
)
{
...
...
@@ -187,7 +192,10 @@ export class OptimismEnv {
message
.
sender
,
message
.
message
,
message
.
messageNonce
,
proof
proof
,
{
gasLimit
:
DEFAULT_TEST_GAS_L1
*
10
,
}
)
await
result
.
wait
()
break
...
...
integration-tests/test/shared/stress-test-helpers.ts
View file @
b0582a31
...
...
@@ -23,7 +23,7 @@ export const fundRandomWallet = async (
const
fundTx
=
await
env
.
l1Wallet
.
sendTransaction
({
gasLimit
:
25
_000
,
to
:
wallet
.
address
,
gasPrice
:
await
gasPriceForL1
(
env
),
gasPrice
:
await
gasPriceForL1
(),
value
,
})
await
fundTx
.
wait
()
...
...
@@ -47,7 +47,7 @@ export const executeL1ToL2Transaction = async (
),
MESSAGE_GAS
,
{
gasPrice
:
await
gasPriceForL1
(
env
),
gasPrice
:
await
gasPriceForL1
(),
}
)
)
...
...
@@ -71,7 +71,7 @@ export const executeL2ToL1Transaction = async (
),
MESSAGE_GAS
,
{
gasPrice
:
gasPriceForL2
(
env
),
gasPrice
:
gasPriceForL2
(),
}
)
)
...
...
@@ -90,7 +90,7 @@ export const executeL2Transaction = async (
tx
.
contract
.
connect
(
signer
)
.
functions
[
tx
.
functionName
](...
tx
.
functionParams
,
{
gasPrice
:
gasPriceForL2
(
env
),
gasPrice
:
gasPriceForL2
(),
})
)
await
result
.
wait
()
...
...
integration-tests/test/shared/utils.ts
View file @
b0582a31
...
...
@@ -14,32 +14,54 @@ import {
predeploys
,
}
from
'
@eth-optimism/contracts
'
import
{
injectL2Context
,
remove0x
,
Watcher
}
from
'
@eth-optimism/core-utils
'
import
{
cleanEnv
,
str
,
num
,
bool
}
from
'
envalid
'
import
{
cleanEnv
,
str
,
num
,
bool
,
makeValidator
}
from
'
envalid
'
import
dotenv
from
'
dotenv
'
dotenv
.
config
()
/* Imports: Internal */
import
{
Direction
,
waitForXDomainTransaction
}
from
'
./watcher-utils
'
import
{
OptimismEnv
}
from
'
./env
'
export
const
GWEI
=
BigNumber
.
from
(
1
e9
)
export
const
isLiveNetwork
=
()
=>
{
return
process
.
env
.
IS_LIVE_NETWORK
===
'
true
'
}
if
(
isLiveNetwork
())
{
dotenv
.
config
()
}
export
const
HARDHAT_CHAIN_ID
=
31337
export
const
DEFAULT_TEST_GAS_L1
=
330
_000
export
const
DEFAULT_TEST_GAS_L2
=
1
_300_000
export
const
ON_CHAIN_GAS_PRICE
=
'
onchain
'
const
gasPriceValidator
=
makeValidator
((
gasPrice
)
=>
{
if
(
gasPrice
===
'
onchain
'
)
{
return
gasPrice
}
const
env
=
cleanEnv
(
process
.
env
,
{
return
num
().
_parse
(
gasPrice
).
toString
()
})
const
procEnv
=
cleanEnv
(
process
.
env
,
{
L1_GAS_PRICE
:
gasPriceValidator
({
default
:
'
0
'
,
}),
L1_URL
:
str
({
default
:
'
http://localhost:9545
'
}),
L2_URL
:
str
({
default
:
'
http://localhost:8545
'
}),
VERIFIER_URL
:
str
({
default
:
'
http://localhost:8547
'
}),
REPLICA_URL
:
str
({
default
:
'
http://localhost:8549
'
}),
L1_POLLING_INTERVAL
:
num
({
default
:
10
}),
L2_CHAINID
:
num
({
default
:
420
}),
L2_GAS_PRICE
:
gasPriceValidator
({
default
:
'
onchain
'
,
}),
L2_URL
:
str
({
default
:
'
http://localhost:8545
'
}),
L2_POLLING_INTERVAL
:
num
({
default
:
10
}),
VERIFIER_POLLING_INTERVAL
:
num
({
default
:
10
}),
L2_WALLET_MIN_BALANCE_ETH
:
num
({
default
:
2
,
}),
L2_WALLET_TOP_UP_AMOUNT_ETH
:
num
({
default
:
3
,
}),
REPLICA_URL
:
str
({
default
:
'
http://localhost:8549
'
}),
REPLICA_POLLING_INTERVAL
:
num
({
default
:
10
}),
PRIVATE_KEY
:
str
({
default
:
'
0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
'
,
...
...
@@ -51,31 +73,53 @@ const env = cleanEnv(process.env, {
default
:
'
0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba
'
,
}),
L2_CHAINID
:
num
({
default
:
420
}),
IS_LIVE_NETWORK
:
bool
({
default
:
false
}),
OVMCONTEXT_SPEC_NUM_TXS
:
num
({
default
:
5
,
}),
DTL_ENQUEUE_CONFIRMATIONS
:
num
({
default
:
0
,
}),
RUN_WITHDRAWAL_TESTS
:
bool
({
default
:
true
,
}),
RUN_REPLICA_TESTS
:
bool
({
default
:
true
,
}),
RUN_DEBUG_TRACE_TESTS
:
bool
({
default
:
true
,
}),
RUN_STRESS_TESTS
:
bool
({
default
:
true
,
}),
MOCHA_TIMEOUT
:
num
({
default
:
120
_000
,
}),
MOCHA_BAIL
:
bool
({
default
:
false
,
}),
})
export
const
envConfig
=
procEnv
// The hardhat instance
export
const
l1Provider
=
new
providers
.
JsonRpcProvider
(
e
nv
.
L1_URL
)
l1Provider
.
pollingInterval
=
e
nv
.
L1_POLLING_INTERVAL
export
const
l1Provider
=
new
providers
.
JsonRpcProvider
(
procE
nv
.
L1_URL
)
l1Provider
.
pollingInterval
=
procE
nv
.
L1_POLLING_INTERVAL
export
const
l2Provider
=
injectL2Context
(
new
providers
.
JsonRpcProvider
(
e
nv
.
L2_URL
)
new
providers
.
JsonRpcProvider
(
procE
nv
.
L2_URL
)
)
l2Provider
.
pollingInterval
=
env
.
L2_POLLING_INTERVAL
export
const
verifierProvider
=
injectL2Context
(
new
providers
.
JsonRpcProvider
(
env
.
VERIFIER_URL
)
)
verifierProvider
.
pollingInterval
=
env
.
VERIFIER_POLLING_INTERVAL
l2Provider
.
pollingInterval
=
procEnv
.
L2_POLLING_INTERVAL
export
const
replicaProvider
=
injectL2Context
(
new
providers
.
JsonRpcProvider
(
e
nv
.
REPLICA_URL
)
new
providers
.
JsonRpcProvider
(
procE
nv
.
REPLICA_URL
)
)
replicaProvider
.
pollingInterval
=
e
nv
.
REPLICA_POLLING_INTERVAL
replicaProvider
.
pollingInterval
=
procE
nv
.
REPLICA_POLLING_INTERVAL
// The sequencer private key which is funded on L1
export
const
l1Wallet
=
new
Wallet
(
e
nv
.
PRIVATE_KEY
,
l1Provider
)
export
const
l1Wallet
=
new
Wallet
(
procE
nv
.
PRIVATE_KEY
,
l1Provider
)
// A random private key which should always be funded with deposits from L1 -> L2
// if it's using non-0 gas price
...
...
@@ -83,7 +127,7 @@ export const l2Wallet = l1Wallet.connect(l2Provider)
// The owner of the GasPriceOracle on L2
export
const
gasPriceOracleWallet
=
new
Wallet
(
e
nv
.
GAS_PRICE_ORACLE_PRIVATE_KEY
,
procE
nv
.
GAS_PRICE_ORACLE_PRIVATE_KEY
,
l2Provider
)
...
...
@@ -92,13 +136,12 @@ export const PROXY_SEQUENCER_ENTRYPOINT_ADDRESS =
'
0x4200000000000000000000000000000000000004
'
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
L2_CHAINID
=
procEnv
.
L2_CHAINID
export
const
getAddressManager
=
(
provider
:
any
)
=>
{
return
getContractFactory
(
'
Lib_AddressManager
'
)
.
connect
(
provider
)
.
attach
(
e
nv
.
ADDRESS_MANAGER
)
.
attach
(
procE
nv
.
ADDRESS_MANAGER
)
}
// Gets the bridge contract
...
...
@@ -115,33 +158,17 @@ export const getL1Bridge = async (wallet: Wallet, AddressManager: Contract) => {
throw
new
Error
(
'
Proxy__OVM_L1StandardBridge not found
'
)
}
const
L1StandardBridge
=
new
Contract
(
ProxyBridgeAddress
,
l1BridgeInterface
,
wallet
)
return
L1StandardBridge
return
new
Contract
(
ProxyBridgeAddress
,
l1BridgeInterface
,
wallet
)
}
export
const
getL2Bridge
=
async
(
wallet
:
Wallet
)
=>
{
const
L2BridgeInterface
=
getContractInterface
(
'
L2StandardBridge
'
)
const
L2StandardBridge
=
new
Contract
(
predeploys
.
L2StandardBridge
,
L2BridgeInterface
,
wallet
)
return
L2StandardBridge
return
new
Contract
(
predeploys
.
L2StandardBridge
,
L2BridgeInterface
,
wallet
)
}
export
const
getOvmEth
=
(
wallet
:
Wallet
)
=>
{
const
OVM_ETH
=
new
Contract
(
OVM_ETH_ADDRESS
,
getContractInterface
(
'
OVM_ETH
'
),
wallet
)
return
OVM_ETH
return
new
Contract
(
OVM_ETH_ADDRESS
,
getContractInterface
(
'
OVM_ETH
'
),
wallet
)
}
export
const
fundUser
=
async
(
...
...
@@ -152,12 +179,54 @@ export const fundUser = async (
)
=>
{
const
value
=
BigNumber
.
from
(
amount
)
const
tx
=
recipient
?
bridge
.
depositETHTo
(
recipient
,
1
_300_000
,
'
0x
'
,
{
value
})
:
bridge
.
depositETH
(
1
_300_000
,
'
0x
'
,
{
value
})
?
bridge
.
depositETHTo
(
recipient
,
DEFAULT_TEST_GAS_L2
,
'
0x
'
,
{
value
,
gasLimit
:
DEFAULT_TEST_GAS_L1
,
})
:
bridge
.
depositETH
(
DEFAULT_TEST_GAS_L2
,
'
0x
'
,
{
value
,
gasLimit
:
DEFAULT_TEST_GAS_L1
,
})
await
waitForXDomainTransaction
(
watcher
,
tx
,
Direction
.
L1ToL2
)
}
export
const
conditionalTest
=
(
condition
:
(
env
?:
OptimismEnv
)
=>
Promise
<
boolean
>
,
name
,
fn
,
message
?:
string
,
timeout
?:
number
)
=>
{
it
(
name
,
async
function
()
{
const
shouldRun
=
await
condition
()
if
(
!
shouldRun
)
{
console
.
log
(
message
)
this
.
skip
()
return
}
await
fn
()
}).
timeout
(
timeout
||
envConfig
.
MOCHA_TIMEOUT
)
}
export
const
withdrawalTest
=
(
name
,
fn
,
timeout
?:
number
)
=>
conditionalTest
(
()
=>
Promise
.
resolve
(
procEnv
.
RUN_WITHDRAWAL_TESTS
),
name
,
fn
,
`Skipping withdrawal test.`
,
timeout
)
export
const
hardhatTest
=
(
name
,
fn
)
=>
conditionalTest
(
isHardhat
,
name
,
fn
,
'
Skipping test on non-Hardhat environment.
'
)
export
const
sleep
=
(
ms
:
number
)
=>
new
Promise
((
r
)
=>
setTimeout
(
r
,
ms
))
const
abiCoder
=
new
utils
.
AbiCoder
()
...
...
@@ -175,56 +244,23 @@ export const defaultTransactionFactory = () => {
}
}
export
const
waitForL2Geth
=
async
(
provider
:
providers
.
JsonRpcProvider
):
Promise
<
providers
.
JsonRpcProvider
>
=>
{
let
ready
:
boolean
=
false
while
(
!
ready
)
{
try
{
await
provider
.
getNetwork
()
ready
=
true
}
catch
(
error
)
{
await
sleep
(
1000
)
}
}
return
injectL2Context
(
provider
)
}
// eslint-disable-next-line @typescript-eslint/no-shadow
export
const
gasPriceForL2
=
async
(
env
:
OptimismEnv
)
=>
{
// The integration tests enforce fees on L2
// which run against hardhat on L1. Update if
// geth --dev is adopted for L1
const
chainId
=
await
env
.
l1Wallet
.
getChainId
()
if
((
await
isMainnet
(
env
))
||
chainId
===
31337
)
{
return
env
.
l2Wallet
.
getGasPrice
()
export
const
gasPriceForL2
=
async
()
=>
{
if
(
procEnv
.
L2_GAS_PRICE
===
ON_CHAIN_GAS_PRICE
)
{
return
l2Wallet
.
getGasPrice
()
}
if
(
isLiveNetwork
())
{
return
Promise
.
resolve
(
BigNumber
.
from
(
10000
))
}
return
Promise
.
resolve
(
BigNumber
.
from
(
0
))
return
utils
.
parseUnits
(
procEnv
.
L2_GAS_PRICE
,
'
wei
'
)
}
// 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
)
export
const
gasPriceForL1
=
async
()
=>
{
if
(
procEnv
.
L1_GAS_PRICE
===
ON_CHAIN_GAS_PRICE
)
{
return
l1Wallet
.
getGasPrice
()
}
return
utils
.
parseUnits
(
procEnv
.
L1_GAS_PRICE
,
'
wei
'
)
}
// eslint-disable-next-line @typescript-eslint/no-shadow
export
const
isMainnet
=
async
(
env
:
OptimismEnv
)
=>
{
const
chainId
=
await
env
.
l1Wallet
.
getChainId
()
return
chainId
===
1
export
const
isHardhat
=
async
()
=>
{
const
chainId
=
await
l1Wallet
.
getChainId
()
return
chainId
===
HARDHAT_CHAIN_ID
}
integration-tests/test/stress-tests.spec.ts
View file @
b0582a31
...
...
@@ -17,12 +17,12 @@ import {
}
from
'
./shared/stress-test-helpers
'
/* Imports: Artifacts */
import
{
fundUser
,
isLiveNetwork
,
isMainnet
}
from
'
./shared/utils
'
import
{
envConfig
,
fundUser
}
from
'
./shared/utils
'
// 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
// so I'm instead setting it for every test.
const
STRESS_TEST_TIMEOUT
=
isLiveNetwork
()
?
500
_000
:
1
_200_000
const
STRESS_TEST_TIMEOUT
=
envConfig
.
MOCHA_TIMEOUT
*
5
describe
(
'
stress tests
'
,
()
=>
{
const
numTransactions
=
3
...
...
@@ -32,13 +32,14 @@ describe('stress tests', () => {
const
wallets
:
Wallet
[]
=
[]
before
(
async
function
()
{
env
=
await
OptimismEnv
.
new
()
if
(
await
isMainnet
(
env
))
{
console
.
log
(
'
Skipping stress tests on mainnet.
'
)
if
(
!
envConfig
.
RUN_STRESS_TESTS
)
{
console
.
log
(
'
Skipping stress tests.
'
)
this
.
skip
()
return
}
env
=
await
OptimismEnv
.
new
()
for
(
let
i
=
0
;
i
<
numTransactions
;
i
++
)
{
wallets
.
push
(
Wallet
.
createRandom
())
}
...
...
yarn.lock
View file @
b0582a31
...
...
@@ -3210,14 +3210,6 @@
"@types/mime" "^1"
"@types/node" "*"
"@types/shelljs@^0.8.8":
version "0.8.9"
resolved "https://registry.yarnpkg.com/@types/shelljs/-/shelljs-0.8.9.tgz#45dd8501aa9882976ca3610517dac3831c2fbbf4"
integrity sha512-flVe1dvlrCyQJN/SGrnBxqHG+RzXrVKsmjD8WS/qYHpq5UPjfq7UWFBENP0ZuOl0g6OpAlL6iBoLSvKYUUmyQw==
dependencies:
"@types/glob" "*"
"@types/node" "*"
"@types/sinon-chai@^3.2.3", "@types/sinon-chai@^3.2.5":
version "3.2.5"
resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-3.2.5.tgz#df21ae57b10757da0b26f512145c065f2ad45c48"
...
...
@@ -6247,13 +6239,6 @@ directory-tree@^2.2.7:
resolved "https://registry.yarnpkg.com/directory-tree/-/directory-tree-2.3.1.tgz#78b8aa84878eb84dd29a51dcd664ded4cd0247c7"
integrity sha512-hxolIHCtQ/a56CUywaLzGD/V78zPwFihI+UK/4ZjOp7GoV4Mptmtv95yavOn/RlnTi7cCMjszvfcNrwCoWLH+Q==
docker-compose@^0.23.8:
version "0.23.13"
resolved "https://registry.yarnpkg.com/docker-compose/-/docker-compose-0.23.13.tgz#77d37bd05b6a966345f631e6d05e961c79514f06"
integrity sha512-/9fYC4g3AO+qsqxIZhmbVnFvJJPcYEV2yJbAPPXH+6AytU3urIY8lUAXOlvY8sl4u25pdKu1JrOfAmWC7lJDJg==
dependencies:
yaml "^1.10.2"
doctrine@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
...
...
@@ -13963,7 +13948,7 @@ shebang-regex@^3.0.0:
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
shelljs@^0.8.3
, shelljs@^0.8.4
:
shelljs@^0.8.3:
version "0.8.5"
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c"
integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==
...
...
@@ -15138,9 +15123,9 @@ trim-newlines@^3.0.0:
integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==
trim-off-newlines@^1.0.0:
version "1.0.
1
"
resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.
1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3
"
integrity sha
1-n5up2e+odkw4dpi8v+sshI8RrbM
=
version "1.0.
3
"
resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.
3.tgz#8df24847fcb821b0ab27d58ab6efec9f2fe961a1
"
integrity sha
512-kh6Tu6GbeSNMGfrrZh6Bb/4ZEHV1QlB4xNDBeog8Y9/QwFlKTRyWvY3Fs9tRDAMZliVUwieMgEdIeL/FtqjkJg=
=
trim-right@^1.0.1:
version "1.0.1"
...
...
@@ -16639,7 +16624,7 @@ yallist@^4.0.0:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
yaml@^1.10.0
, yaml@^1.10.2
:
yaml@^1.10.0:
version "1.10.2"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
...
...
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