1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
'use strict'
import { ethers } from 'ethers'
import { task } from 'hardhat/config'
import * as types from 'hardhat/internal/core/params/argumentTypes'
import { getContractFactory, getContractDefinition } from '../src/contract-defs'
import {
getInput,
color as c,
getEtherscanUrl,
printComparison,
printSectionHead,
} from '../src/validation-utils'
task('validate:chugsplash-dictator')
.addParam(
'dictator',
'Address of the ChugSplashDictator to validate.',
undefined,
types.string
)
.addParam(
'proxy',
'Address of the L1ChugSplashProxy to validate.',
undefined,
types.string
)
.addParam(
'multisig',
'Address of the multisig contract which should be the final owner',
undefined,
types.string
)
.addOptionalParam(
'contractsRpcUrl',
'RPC Endpoint to query for data',
process.env.CONTRACTS_RPC_URL,
types.string
)
.setAction(async (args) => {
if (!args.contractsRpcUrl) {
throw new Error(
c.red('RPC URL must be set in your env, or passed as an argument.')
)
}
const provider = new ethers.providers.JsonRpcProvider(args.contractsRpcUrl)
const network = await provider.getNetwork()
console.log() // the whitespacooooooor
console.log(c.cyan("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
)})`
)
await getInput(c.yellow('OK? Hit enter to continue.'))
console.log()
const dictatorArtifact = getContractDefinition('ChugSplashDictator')
const dictatorCode = await provider.getCode(args.dictator)
printSectionHead(
`Validate the Chugsplash Dictator deployment at\n${getEtherscanUrl(
network,
args.dictator
)}`
)
printComparison(
'Compare 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")
)
// Connect to the deployed ChugSplashDictator.
const dictatorContract = getContractFactory('ChugSplashDictator')
.attach(args.dictator)
.connect(provider)
const finalOwner = await dictatorContract.finalOwner()
printComparison(
'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()
const proxyMessengerSlotVal = await provider.getStorageAt(
args.proxy,
dictatorMessengerSlotKey
)
printComparison(
'Compare the Messenger 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}`,
value: proxyMessengerSlotVal,
},
{
name: `Dictator will setStorage at slot key\n${dictatorMessengerSlotKey}`,
value: dictatorMessengerSlotVal,
}
)
await getInput(c.yellow('OK? Hit enter to continue.'))
console.log()
const dictatorBridgeSlotKey = await dictatorContract.bridgeSlotKey()
const dictatorBridgeSlotVal = await dictatorContract.bridgeSlotVal()
const proxyBridgeSlotVal = await provider.getStorageAt(
args.proxy,
dictatorBridgeSlotKey
)
printComparison(
'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}`,
value: proxyBridgeSlotVal,
},
{
name: `Dictator will setStorage in the proxy at slot key\n${dictatorBridgeSlotKey}`,
value: dictatorBridgeSlotVal,
}
)
await getInput(c.yellow('OK? Hit enter to continue.'))
console.log()
const bridgeArtifact = getContractDefinition('L1StandardBridge')
const expectedCodeHash = ethers.utils.keccak256(
bridgeArtifact.deployedBytecode
)
const actualCodeHash = await dictatorContract.codeHash()
printComparison(
"Compare the Dictator's codeHash against hash of the local L1StandardBridge build artifacts",
"Dictator's codeHash",
{
name: 'Expected codeHash',
value: expectedCodeHash,
},
{
name: 'Actual codeHash',
value: actualCodeHash,
}
)
await getInput(c.yellow('OK? Hit enter to continue.'))
console.log()
console.log(c.green('Chugsplash Dictator Validation complete!'))
})