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
d667bbb8
Unverified
Commit
d667bbb8
authored
Dec 08, 2021
by
Maurelian
Committed by
GitHub
Dec 08, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1753 from ethereum-optimism/maurelian/check-moar-things
parents
5bacd4c0
bbd42e03
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
203 additions
and
54 deletions
+203
-54
famous-sheep-bathe.md
.changeset/famous-sheep-bathe.md
+5
-0
validation-utils.ts
packages/contracts/src/validation-utils.ts
+26
-17
validate-address-dictator.ts
packages/contracts/tasks/validate-address-dictator.ts
+154
-23
validate-chugsplash-dictator.ts
packages/contracts/tasks/validate-chugsplash-dictator.ts
+18
-14
No files found.
.changeset/famous-sheep-bathe.md
0 → 100644
View file @
d667bbb8
---
'
@eth-optimism/contracts'
:
patch
---
Add config checks to validation script
packages/contracts/src/validation-utils.ts
View file @
d667bbb8
...
...
@@ -30,9 +30,9 @@ export const color = Object.fromEntries(
])
)
export
const
getArtifact
=
(
name
:
string
)
=>
{
// Paths to artifacts relative to artifacts/contracts
const
locations
=
{
// helper for finding the right artifact from the deployed name
const
locateArtifact
=
(
name
:
string
)
=>
{
return
{
'
ChainStorageContainer-CTC-batches
'
:
'
L1/rollup/ChainStorageContainer.sol/ChainStorageContainer.json
'
,
'
ChainStorageContainer-SCC-batches
'
:
...
...
@@ -48,9 +48,12 @@ export const getArtifact = (name: string) => {
'
libraries/resolver/Lib_ResolvedDelegateProxy.sol/Lib_ResolvedDelegateProxy.json
'
,
Proxy__OVM_L1StandardBridge
:
'
chugsplash/L1ChugSplashProxy.sol/L1ChugSplashProxy.json
'
,
}
}[
name
]
}
export
const
getArtifactFromManagedName
=
(
name
:
string
)
=>
{
// eslint-disable-next-line @typescript-eslint/no-var-requires
return
require
(
`../artifacts/contracts/
${
locat
ions
[
name
]
}
`
)
return
require
(
`../artifacts/contracts/
${
locat
eArtifact
(
name
)
}
`
)
}
export
const
getEtherscanUrl
=
(
network
,
address
:
string
)
=>
{
...
...
@@ -63,26 +66,32 @@ const truncateLongString = (value: string): string => {
return
value
.
length
>
66
?
`
${
value
.
slice
(
0
,
66
)}
...`
:
value
}
export
const
printSectionHead
=
(
msg
:
string
)
=>
{
console
.
log
(
color
.
cyan
(
msg
))
console
.
log
(
color
.
cyan
(
'
=
'
.
repeat
(
Math
.
max
(...
msg
.
split
(
'
\n
'
).
map
((
s
)
=>
s
.
length
))))
)
}
export
const
printComparison
=
(
action
:
string
,
description
:
string
,
expected
:
{
name
:
string
;
value
:
string
},
deployed
:
{
name
:
string
;
value
:
string
}
expected
:
{
name
:
string
;
value
:
any
},
deployed
:
{
name
:
string
;
value
:
any
}
)
=>
{
console
.
log
(
action
+
'
:
'
)
console
.
log
(
`\n
${
action
}
:`
)
if
(
hexStringEquals
(
expected
.
value
,
deployed
.
value
))
{
console
.
log
(
color
.
green
(
`
${
expected
.
name
}
:
${
truncateLongString
(
expected
.
value
)}
matches
${
deployed
.
name
}
:
${
truncateLongString
(
deployed
.
value
)}
`
)
color
.
green
(
`
${
expected
.
name
}
:
${
truncateLongString
(
expected
.
value
)}
`
)
)
console
.
log
(
'
matches
'
)
console
.
log
(
color
.
green
(
`
${
deployed
.
name
}
:
${
truncateLongString
(
deployed
.
value
)}
`
)
)
console
.
log
(
color
.
green
(
`
${
description
}
looks good! 😎`
))
}
else
{
throw
new
Error
(
`
${
description
}
looks wrong.
${
expected
.
value
}
\ndoes not match\n
${
deployed
.
value
}
.
`
)
throw
new
Error
(
`
${
description
}
looks wrong.
${
expected
.
value
}
\ndoes not match\n
${
deployed
.
value
}
.`
)
}
console
.
log
()
// Add some whitespace
}
packages/contracts/tasks/validate-address-dictator.ts
View file @
d667bbb8
...
...
@@ -4,13 +4,15 @@ import { ethers } from 'ethers'
import
{
task
}
from
'
hardhat/config
'
import
*
as
types
from
'
hardhat/internal/core/params/argumentTypes
'
import
{
hexStringEquals
}
from
'
@eth-optimism/core-utils
'
import
{
getContractFactory
}
from
'
../src/contract-defs
'
import
{
getContractFactory
,
getContractDefinition
}
from
'
../src/contract-defs
'
import
{
names
}
from
'
../src/address-names
'
import
{
getInput
,
color
as
c
,
getArtifact
,
getArtifact
FromManagedName
,
getEtherscanUrl
,
printSectionHead
,
printComparison
,
}
from
'
../src/validation-utils
'
...
...
@@ -49,7 +51,7 @@ task('validate:address-dictator')
const
network
=
await
provider
.
getNetwork
()
console
.
log
()
console
.
log
(
c
.
cyan
(
"
First make sure you're on the right chain:
"
)
)
printSectionHead
(
"
First make sure you're on the right chain:
"
)
console
.
log
(
`Reading from the
${
c
.
red
(
network
.
name
)}
network (Chain ID:
${
c
.
red
(
''
+
network
.
chainId
...
...
@@ -57,16 +59,14 @@ task('validate:address-dictator')
)
await
getInput
(
c
.
yellow
(
'
OK? Hit enter to continue.
'
))
// eslint-disable-next-line @typescript-eslint/no-var-requires
const
dictatorArtifact
=
require
(
'
../artifacts/contracts/L1/deployment/AddressDictator.sol/AddressDictator.json
'
)
const
dictatorArtifact
=
getContractDefinition
(
'
AddressDictator
'
)
const
dictatorCode
=
await
provider
.
getCode
(
args
.
dictator
)
console
.
log
(
c
.
cyan
(
`
Now validating the Address Dictator deployment at\n
${
getEtherscanUrl
(
network
,
args
.
dictator
)}
`
)
)
printSectionHead
(
`
Validate the Address Dictator deployment at\n
${
getEtherscanUrl
(
network
,
args
.
dictator
)}
`
)
printComparison
(
'
Comparing deployed AddressDictator bytecode against local build artifacts
'
,
'
Deployed AddressDictator code
'
,
...
...
@@ -87,12 +87,12 @@ Now validating the Address Dictator deployment at\n${getEtherscanUrl(
{
name
:
'
finalOwner
'
,
value
:
finalOwner
}
)
const
m
anager
=
await
dictatorContract
.
manager
()
const
deployedM
anager
=
await
dictatorContract
.
manager
()
printComparison
(
'
Validating the AddressManager address in the AddressDictator
'
,
'
addressManager
'
,
{
name
:
'
manager
'
,
value
:
args
.
manager
},
{
name
:
'
Address Manager
'
,
value
:
m
anager
}
{
name
:
'
manager
'
,
value
:
args
.
manager
},
{
name
:
'
Address Manager
'
,
value
:
deployedM
anager
}
)
await
getInput
(
c
.
yellow
(
'
OK? Hit enter to continue.
'
))
...
...
@@ -107,15 +107,20 @@ Now validating the Address Dictator deployment at\n${getEtherscanUrl(
// Now we loop over those and compare the addresses/deployedBytecode to deployment artifacts.
for
(
const
pair
of
namedAddresses
)
{
if
(
pair
.
name
===
'
L2CrossDomainMessenger
'
)
{
console
.
log
(
'
L2CrossDomainMessenger is set to:
'
,
pair
.
addr
)
await
getInput
(
c
.
yellow
(
'
OK? Hit enter to continue.
'
))
// This is an L2 predeploy, so we skip bytecode and config validation.
continue
}
const
currentAddress
=
await
managerContract
.
getAddress
(
pair
.
name
)
const
artifact
=
getArtifact
(
pair
.
name
)
const
artifact
=
getArtifact
FromManagedName
(
pair
.
name
)
const
addressChanged
=
!
hexStringEquals
(
currentAddress
,
pair
.
addr
)
if
(
addressChanged
)
{
console
.
log
(
c
.
cyan
(
`
Now validating the
${
pair
.
name
}
deployment.
printSectionHead
(
`Validate the
${
pair
.
name
}
deployment.
Current address:
${
getEtherscanUrl
(
network
,
currentAddress
)}
Upgraded address
${
getEtherscanUrl
(
network
,
pair
.
addr
)}
`
)
Upgraded address
${
getEtherscanUrl
(
network
,
pair
.
addr
)}
`
)
const
code
=
await
provider
.
getCode
(
pair
.
addr
)
...
...
@@ -144,12 +149,138 @@ Upgraded address ${getEtherscanUrl(network, pair.addr)}`)
`Verifying
${
pair
.
name
}
has the correct AddressManager address`
,
`The AddressManager address in
${
pair
.
name
}
`
,
{
name
:
'
Deployed value
'
,
value
:
libAddressManager
},
{
name
:
'
Expected value
'
,
value
:
m
anager
}
{
name
:
'
Expected value
'
,
value
:
deployedM
anager
}
)
await
getInput
(
c
.
yellow
(
'
OK? Hit enter to continue.
'
))
}
}
}
await
getInput
(
c
.
yellow
(
'
OK? Hit enter to continue.
'
)
)
await
validateDeployedConfig
(
provider
,
network
,
args
.
manager
,
pair
)
}
console
.
log
(
c
.
green
(
'
AddressManager Validation complete!
'
))
console
.
log
(
c
.
green
(
'
\n
AddressManager Validation complete!
'
))
})
/**
* Validates that the deployed contracts have the expected storage variables.
*
* @param {*} provider
* @param {{ name: string; addr: string }} pair The contract name and address
*/
const
validateDeployedConfig
=
async
(
provider
,
network
,
manager
,
pair
:
{
name
:
string
;
addr
:
string
}
)
=>
{
printSectionHead
(
`
Ensure that the
${
pair
.
name
}
at\n
${
getEtherscanUrl
(
network
,
pair
.
addr
)}
is configured correctly`
)
if
(
pair
.
name
===
names
.
managed
.
contracts
.
StateCommitmentChain
)
{
const
scc
=
getContractFactory
(
pair
.
name
)
.
attach
(
pair
.
addr
)
.
connect
(
provider
)
// --scc-fraud-proof-window 604800 \
const
fraudProofWindow
=
await
scc
.
FRAUD_PROOF_WINDOW
()
printComparison
(
'
Checking the fraudProofWindow of the StateCommitmentChain
'
,
'
StateCommitmentChain.fraudProofWindow
'
,
{
name
:
'
Configured fraudProofWindow
'
,
value
:
ethers
.
BigNumber
.
from
(
604
_800
).
toHexString
(),
},
{
name
:
'
Deployed fraudProofWindow
'
,
value
:
ethers
.
BigNumber
.
from
(
fraudProofWindow
).
toHexString
(),
}
)
await
getInput
(
c
.
yellow
(
'
OK? Hit enter to continue.
'
))
// --scc-sequencer-publish-window 12592000 \
const
sequencerPublishWindow
=
await
scc
.
SEQUENCER_PUBLISH_WINDOW
()
printComparison
(
'
Checking the sequencerPublishWindow of the StateCommitmentChain
'
,
'
StateCommitmentChain.sequencerPublishWindow
'
,
{
name
:
'
Configured sequencerPublishWindow
'
,
value
:
ethers
.
BigNumber
.
from
(
12592000
).
toHexString
(),
},
{
name
:
'
Deployed sequencerPublishWindow
'
,
value
:
ethers
.
BigNumber
.
from
(
sequencerPublishWindow
).
toHexString
(),
}
)
await
getInput
(
c
.
yellow
(
'
OK? Hit enter to continue.
'
))
}
else
if
(
pair
.
name
===
names
.
managed
.
contracts
.
CanonicalTransactionChain
)
{
const
ctc
=
getContractFactory
(
pair
.
name
)
.
attach
(
pair
.
addr
)
.
connect
(
provider
)
// --ctc-max-transaction-gas-limit 15000000 \
const
maxTransactionGasLimit
=
await
ctc
.
maxTransactionGasLimit
()
printComparison
(
'
Checking the maxTransactionGasLimit of the CanonicalTransactionChain
'
,
'
CanonicalTransactionChain.maxTransactionGasLimit
'
,
{
name
:
'
Configured maxTransactionGasLimit
'
,
value
:
ethers
.
BigNumber
.
from
(
15
_000_000
).
toHexString
(),
},
{
name
:
'
Deployed maxTransactionGasLimit
'
,
value
:
ethers
.
BigNumber
.
from
(
maxTransactionGasLimit
).
toHexString
(),
}
)
await
getInput
(
c
.
yellow
(
'
OK? Hit enter to continue.
'
))
// --ctc-l2-gas-discount-divisor 32 \
const
l2GasDiscountDivisor
=
await
ctc
.
l2GasDiscountDivisor
()
printComparison
(
'
Checking the l2GasDiscountDivisor of the CanonicalTransactionChain
'
,
'
CanonicalTransactionChain.l2GasDiscountDivisor
'
,
{
name
:
'
Configured l2GasDiscountDivisor
'
,
value
:
ethers
.
BigNumber
.
from
(
32
).
toHexString
(),
},
{
name
:
'
Deployed l2GasDiscountDivisor
'
,
value
:
ethers
.
BigNumber
.
from
(
l2GasDiscountDivisor
).
toHexString
(),
}
)
await
getInput
(
c
.
yellow
(
'
OK? Hit enter to continue.
'
))
// --ctc-enqueue-gas-cost 60000 \
const
enqueueGasCost
=
await
ctc
.
enqueueGasCost
()
printComparison
(
'
Checking the enqueueGasCost of the CanonicalTransactionChain
'
,
'
CanonicalTransactionChain.enqueueGasCost
'
,
{
name
:
'
Configured enqueueGasCost
'
,
value
:
ethers
.
BigNumber
.
from
(
60000
).
toHexString
(),
},
{
name
:
'
Deployed enqueueGasCost
'
,
value
:
ethers
.
BigNumber
.
from
(
enqueueGasCost
).
toHexString
(),
}
)
await
getInput
(
c
.
yellow
(
'
OK? Hit enter to continue.
'
))
}
else
if
(
pair
.
name
===
names
.
managed
.
contracts
.
OVM_L1CrossDomainMessenger
)
{
const
messengerManager
=
await
getContractFactory
(
'
L1CrossDomainMessenger
'
)
.
attach
(
pair
.
addr
)
.
connect
(
provider
)
.
libAddressManager
()
printComparison
(
'
Ensure that the L1CrossDomainMessenger (implementation) is initialized with a non-zero Address Manager variable
'
,
"
L1CrossDomainMessenger's Lib_AddressManager
"
,
{
name
:
'
Configured Lib_AddressManager
'
,
value
:
messengerManager
,
},
{
name
:
'
Deployed Lib_AddressManager
'
,
value
:
manager
,
}
)
}
else
{
console
.
log
(
c
.
green
(
`
${
pair
.
name
}
has no config to check`
))
await
getInput
(
c
.
yellow
(
'
OK? Hit enter to continue.
'
))
}
}
packages/contracts/tasks/validate-chugsplash-dictator.ts
View file @
d667bbb8
...
...
@@ -3,13 +3,14 @@
import
{
ethers
}
from
'
ethers
'
import
{
task
}
from
'
hardhat/config
'
import
*
as
types
from
'
hardhat/internal/core/params/argumentTypes
'
import
{
getContractFactory
}
from
'
../src/contract-defs
'
import
{
getContractFactory
,
getContractDefinition
}
from
'
../src/contract-defs
'
import
{
getInput
,
color
as
c
,
getEtherscanUrl
,
printComparison
,
printSectionHead
,
}
from
'
../src/validation-utils
'
task
(
'
validate:chugsplash-dictator
'
)
...
...
@@ -54,24 +55,24 @@ task('validate:chugsplash-dictator')
)}
)`
)
await
getInput
(
c
.
yellow
(
'
OK? Hit enter to continue.
'
))
console
.
log
()
// eslint-disable-next-line @typescript-eslint/no-var-requires
const
dictatorArtifact
=
require
(
'
../artifacts/contracts/L1/deployment/ChugSplashDictator.sol/ChugSplashDictator.json
'
)
const
dictatorArtifact
=
getContractDefinition
(
'
ChugSplashDictator
'
)
const
dictatorCode
=
await
provider
.
getCode
(
args
.
dictator
)
console
.
log
(
c
.
cyan
(
`
Now validating the Chugsplash Dictator deployment at\n
${
getEtherscanUrl
(
printSectionHead
(
`Validate the Chugsplash Dictator deployment at\n
${
getEtherscanUrl
(
network
,
args
.
dictator
)}
`
)
)}
`
)
printComparison
(
'
Compar
ing
deployed ChugSplashDictator bytecode against local build artifacts
'
,
'
Compar
e the
deployed ChugSplashDictator bytecode against local build artifacts
'
,
'
Deployed ChugSplashDictator code
'
,
{
name
:
'
Compiled bytecode
'
,
value
:
dictatorArtifact
.
deployedBytecode
},
{
name
:
'
Deployed bytecode
'
,
value
:
dictatorCode
}
)
await
getInput
(
c
.
yellow
(
'
OK? Hit enter to continue.
'
))
console
.
log
()
console
.
log
(
c
.
cyan
(
"
The next 4 checks will validate the ChugSplashDictator's config
"
)
...
...
@@ -82,12 +83,13 @@ Now validating the Chugsplash Dictator deployment at\n${getEtherscanUrl(
.
connect
(
provider
)
const
finalOwner
=
await
dictatorContract
.
finalOwner
()
printComparison
(
'
1. Comparing
the finalOwner address in the ChugSplashDictator to the multisig address
'
,
'
Compare
the finalOwner address in the ChugSplashDictator to the multisig address
'
,
'
finalOwner
'
,
{
name
:
'
multisig address
'
,
value
:
args
.
multisig
},
{
name
:
'
finalOwner
'
,
value
:
finalOwner
}
)
await
getInput
(
c
.
yellow
(
'
OK? Hit enter to continue.
'
))
console
.
log
()
const
dictatorMessengerSlotKey
=
await
dictatorContract
.
messengerSlotKey
()
const
dictatorMessengerSlotVal
=
await
dictatorContract
.
messengerSlotVal
()
...
...
@@ -96,7 +98,7 @@ Now validating the Chugsplash Dictator deployment at\n${getEtherscanUrl(
dictatorMessengerSlotKey
)
printComparison
(
'
2. Comparing the m
essenger slot key/value to be set, with the current values in the proxy
'
,
'
Compare the M
essenger slot key/value to be set, with the current values in the proxy
'
,
`Storage slot key
${
dictatorMessengerSlotKey
}
`
,
{
name
:
`Value in the proxy at slot key\n
${
dictatorMessengerSlotKey
}
`
,
...
...
@@ -108,6 +110,7 @@ Now validating the Chugsplash Dictator deployment at\n${getEtherscanUrl(
}
)
await
getInput
(
c
.
yellow
(
'
OK? Hit enter to continue.
'
))
console
.
log
()
const
dictatorBridgeSlotKey
=
await
dictatorContract
.
bridgeSlotKey
()
const
dictatorBridgeSlotVal
=
await
dictatorContract
.
bridgeSlotVal
()
...
...
@@ -116,7 +119,7 @@ Now validating the Chugsplash Dictator deployment at\n${getEtherscanUrl(
dictatorBridgeSlotKey
)
printComparison
(
'
3. Comparing the _Bridge_
slot key/value to be set, with the current values in the proxy
'
,
'
Compare the Bridge
slot key/value to be set, with the current values in the proxy
'
,
`Storage slot key
${
dictatorBridgeSlotKey
}
`
,
{
name
:
`Value currently in the proxy at slot key\n
${
dictatorBridgeSlotKey
}
`
,
...
...
@@ -128,15 +131,15 @@ Now validating the Chugsplash Dictator deployment at\n${getEtherscanUrl(
}
)
await
getInput
(
c
.
yellow
(
'
OK? Hit enter to continue.
'
))
console
.
log
()
// eslint-disable-next-line @typescript-eslint/no-var-requires
const
bridgeArtifact
=
require
(
'
../artifacts/contracts/L1/messaging/L1StandardBridge.sol/L1StandardBridge.json
'
)
const
bridgeArtifact
=
getContractDefinition
(
'
L1StandardBridge
'
)
const
expectedCodeHash
=
ethers
.
utils
.
keccak256
(
bridgeArtifact
.
deployedBytecode
)
const
actualCodeHash
=
await
dictatorContract
.
codeHash
()
printComparison
(
"
4. Comparing
the Dictator's codeHash against hash of the local L1StandardBridge build artifacts
"
,
"
Compare
the Dictator's codeHash against hash of the local L1StandardBridge build artifacts
"
,
"
Dictator's codeHash
"
,
{
name
:
'
Expected codeHash
'
,
...
...
@@ -148,5 +151,6 @@ Now validating the Chugsplash Dictator deployment at\n${getEtherscanUrl(
}
)
await
getInput
(
c
.
yellow
(
'
OK? Hit enter to continue.
'
))
console
.
log
()
console
.
log
(
c
.
green
(
'
Chugsplash Dictator Validation complete!
'
))
})
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