github.com/ethereum-optimism/optimism@v1.7.2/packages/contracts-bedrock/test/Specs.t.sol (about) 1 // SPDX-License-Identifier: MIT 2 pragma solidity ^0.8.15; 3 4 import { CommonTest } from "test/setup/CommonTest.sol"; 5 import { Executables } from "scripts/Executables.sol"; 6 import { console2 as console } from "forge-std/console2.sol"; 7 import { ProtocolVersions } from "src/L1/ProtocolVersions.sol"; 8 import { OptimismPortal } from "src/L1/OptimismPortal.sol"; 9 import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; 10 import { SystemConfig } from "src/L1/SystemConfig.sol"; 11 import { DataAvailabilityChallenge } from "src/L1/DataAvailabilityChallenge.sol"; 12 import { ForgeArtifacts } from "scripts/ForgeArtifacts.sol"; 13 14 /// @title Specification_Test 15 /// @dev Specifies common security properties of entrypoints to L1 contracts, including authorization and 16 /// pausability. 17 /// When adding new functions to the L1 system, the `setUp` function must be updated to document the security 18 /// properties of the new function. The `Spec` struct reppresents this documentation. However, this contract does 19 /// not actually test to verify these properties, only that a spec is defined. 20 contract Specification_Test is CommonTest { 21 struct AbiEntry { 22 string fnName; 23 bytes4 sel; 24 } 25 26 struct Abi { 27 string contractName; 28 AbiEntry[] entries; 29 } 30 31 enum Role { 32 NOAUTH, 33 PROPOSER, 34 CHALLENGER, 35 SYSTEMCONFIGOWNER, 36 GUARDIAN, 37 MESSENGER, 38 L1PROXYADMINOWNER, 39 GOVERNANCETOKENOWNER, 40 MINTMANAGEROWNER, 41 DATAAVAILABILITYCHALLENGEOWNER 42 } 43 44 /// @notice Represents the specification of a function. 45 /// @custom:field name Contract name 46 /// @custom:field sel Function selector 47 /// @custom:field auth Specifies authentication as a requirement 48 /// @custom:field pausable Specifies that the function is pausable 49 struct Spec { 50 string name; 51 bytes4 sel; 52 Role auth; 53 bool pausable; 54 } 55 56 mapping(string => mapping(bytes4 => Spec)) specs; 57 mapping(string => uint256) public numEntries; 58 59 function setUp() public override { 60 super.setUp(); 61 62 // DataAvailabilityChallenge 63 _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("owner()") }); 64 _addSpec({ 65 _name: "DataAvailabilityChallenge", 66 _sel: _getSel("renounceOwnership()"), 67 _auth: Role.DATAAVAILABILITYCHALLENGEOWNER 68 }); 69 _addSpec({ 70 _name: "DataAvailabilityChallenge", 71 _sel: _getSel("transferOwnership(address)"), 72 _auth: Role.DATAAVAILABILITYCHALLENGEOWNER 73 }); 74 _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("version()") }); 75 _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("fixedResolutionCost()") }); 76 _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("variableResolutionCost()") }); 77 _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("variableResolutionCostPrecision()") }); 78 _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("bondSize()") }); 79 _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("challengeWindow()") }); 80 _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("resolveWindow()") }); 81 _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("resolverRefundPercentage()") }); 82 _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("balances(address)") }); 83 _addSpec({ _name: "DataAvailabilityChallenge", _sel: DataAvailabilityChallenge.initialize.selector }); 84 _addSpec({ 85 _name: "DataAvailabilityChallenge", 86 _sel: DataAvailabilityChallenge.setBondSize.selector, 87 _auth: Role.DATAAVAILABILITYCHALLENGEOWNER 88 }); 89 _addSpec({ 90 _name: "DataAvailabilityChallenge", 91 _sel: DataAvailabilityChallenge.setResolverRefundPercentage.selector, 92 _auth: Role.DATAAVAILABILITYCHALLENGEOWNER 93 }); 94 _addSpec({ _name: "DataAvailabilityChallenge", _sel: DataAvailabilityChallenge.deposit.selector }); 95 _addSpec({ _name: "DataAvailabilityChallenge", _sel: DataAvailabilityChallenge.withdraw.selector }); 96 _addSpec({ _name: "DataAvailabilityChallenge", _sel: DataAvailabilityChallenge.getChallenge.selector }); 97 _addSpec({ _name: "DataAvailabilityChallenge", _sel: DataAvailabilityChallenge.getChallengeStatus.selector }); 98 _addSpec({ _name: "DataAvailabilityChallenge", _sel: DataAvailabilityChallenge.validateCommitment.selector }); 99 _addSpec({ _name: "DataAvailabilityChallenge", _sel: DataAvailabilityChallenge.challenge.selector }); 100 _addSpec({ _name: "DataAvailabilityChallenge", _sel: DataAvailabilityChallenge.resolve.selector }); 101 _addSpec({ _name: "DataAvailabilityChallenge", _sel: DataAvailabilityChallenge.unlockBond.selector }); 102 103 // DelayedVetoable 104 _addSpec({ _name: "DelayedVetoable", _sel: _getSel("delay()") }); 105 _addSpec({ _name: "DelayedVetoable", _sel: _getSel("initiator()") }); 106 _addSpec({ _name: "DelayedVetoable", _sel: _getSel("queuedAt(bytes32)") }); 107 _addSpec({ _name: "DelayedVetoable", _sel: _getSel("target()") }); 108 _addSpec({ _name: "DelayedVetoable", _sel: _getSel("version()") }); 109 _addSpec({ _name: "DelayedVetoable", _sel: _getSel("vetoer()") }); 110 111 // L1CrossDomainMessenger 112 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("MESSAGE_VERSION()") }); 113 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("MIN_GAS_CALLDATA_OVERHEAD()") }); 114 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR()") }); 115 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR()") }); 116 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("OTHER_MESSENGER()") }); 117 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("PORTAL()") }); 118 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("RELAY_CALL_OVERHEAD()") }); 119 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("RELAY_CONSTANT_OVERHEAD()") }); 120 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("RELAY_GAS_CHECK_BUFFER()") }); 121 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("RELAY_RESERVED_GAS()") }); 122 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("baseGas(bytes,uint32)") }); 123 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("failedMessages(bytes32)") }); 124 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("initialize(address,address)") }); 125 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("messageNonce()") }); 126 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("paused()") }); 127 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("otherMessenger()") }); 128 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("portal()") }); 129 _addSpec({ 130 _name: "L1CrossDomainMessenger", 131 _sel: _getSel("relayMessage(uint256,address,address,uint256,uint256,bytes)"), 132 _pausable: true 133 }); 134 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("sendMessage(address,bytes,uint32)") }); 135 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("successfulMessages(bytes32)") }); 136 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("superchainConfig()") }); 137 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("version()") }); 138 _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("xDomainMessageSender()") }); 139 140 // L1ERC721Bridge 141 _addSpec({ _name: "L1ERC721Bridge", _sel: _getSel("MESSENGER()") }); 142 _addSpec({ _name: "L1ERC721Bridge", _sel: _getSel("OTHER_BRIDGE()") }); 143 _addSpec({ _name: "L1ERC721Bridge", _sel: _getSel("bridgeERC721(address,address,uint256,uint32,bytes)") }); 144 _addSpec({ 145 _name: "L1ERC721Bridge", 146 _sel: _getSel("bridgeERC721To(address,address,address,uint256,uint32,bytes)") 147 }); 148 _addSpec({ _name: "L1ERC721Bridge", _sel: _getSel("deposits(address,address,uint256)") }); 149 _addSpec({ 150 _name: "L1ERC721Bridge", 151 _sel: _getSel("finalizeBridgeERC721(address,address,address,address,uint256,bytes)"), 152 _pausable: true 153 }); 154 _addSpec({ _name: "L1ERC721Bridge", _sel: _getSel("messenger()") }); 155 _addSpec({ _name: "L1ERC721Bridge", _sel: _getSel("otherBridge()") }); 156 _addSpec({ _name: "L1ERC721Bridge", _sel: _getSel("version()") }); 157 _addSpec({ _name: "L1ERC721Bridge", _sel: _getSel("superchainConfig()") }); 158 _addSpec({ _name: "L1ERC721Bridge", _sel: _getSel("paused()") }); 159 _addSpec({ _name: "L1ERC721Bridge", _sel: _getSel("initialize(address,address)") }); 160 161 // L1StandardBridge 162 _addSpec({ _name: "L1StandardBridge", _sel: _getSel("MESSENGER()") }); 163 _addSpec({ _name: "L1StandardBridge", _sel: _getSel("OTHER_BRIDGE()") }); 164 _addSpec({ _name: "L1StandardBridge", _sel: _getSel("bridgeERC20(address,address,uint256,uint32,bytes)") }); 165 _addSpec({ 166 _name: "L1StandardBridge", 167 _sel: _getSel("bridgeERC20To(address,address,address,uint256,uint32,bytes)") 168 }); 169 _addSpec({ _name: "L1StandardBridge", _sel: _getSel("bridgeETH(uint32,bytes)") }); 170 _addSpec({ _name: "L1StandardBridge", _sel: _getSel("bridgeETHTo(address,uint32,bytes)") }); 171 _addSpec({ _name: "L1StandardBridge", _sel: _getSel("depositERC20(address,address,uint256,uint32,bytes)") }); 172 _addSpec({ 173 _name: "L1StandardBridge", 174 _sel: _getSel("depositERC20To(address,address,address,uint256,uint32,bytes)") 175 }); 176 _addSpec({ _name: "L1StandardBridge", _sel: _getSel("depositETH(uint32,bytes)") }); 177 _addSpec({ _name: "L1StandardBridge", _sel: _getSel("depositETHTo(address,uint32,bytes)") }); 178 _addSpec({ _name: "L1StandardBridge", _sel: _getSel("deposits(address,address)") }); 179 _addSpec({ 180 _name: "L1StandardBridge", 181 _sel: _getSel("finalizeBridgeERC20(address,address,address,address,uint256,bytes)"), 182 _auth: Role.MESSENGER, 183 _pausable: true 184 }); 185 _addSpec({ 186 _name: "L1StandardBridge", 187 _sel: _getSel("finalizeBridgeETH(address,address,uint256,bytes)"), 188 _auth: Role.MESSENGER, 189 _pausable: true 190 }); 191 _addSpec({ 192 _name: "L1StandardBridge", 193 _sel: _getSel("finalizeERC20Withdrawal(address,address,address,address,uint256,bytes)"), 194 _auth: Role.MESSENGER, 195 _pausable: true 196 }); 197 _addSpec({ 198 _name: "L1StandardBridge", 199 _sel: _getSel("finalizeETHWithdrawal(address,address,uint256,bytes)"), 200 _auth: Role.MESSENGER, 201 _pausable: true 202 }); 203 _addSpec({ _name: "L1StandardBridge", _sel: _getSel("initialize(address,address)") }); 204 _addSpec({ _name: "L1StandardBridge", _sel: _getSel("l2TokenBridge()") }); 205 _addSpec({ _name: "L1StandardBridge", _sel: _getSel("messenger()") }); 206 _addSpec({ _name: "L1StandardBridge", _sel: _getSel("otherBridge()") }); 207 _addSpec({ _name: "L1StandardBridge", _sel: _getSel("paused()") }); 208 _addSpec({ _name: "L1StandardBridge", _sel: _getSel("superchainConfig()") }); 209 _addSpec({ _name: "L1StandardBridge", _sel: _getSel("version()") }); 210 211 // L2OutputOracle 212 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("CHALLENGER()") }); 213 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("FINALIZATION_PERIOD_SECONDS()") }); 214 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("L2_BLOCK_TIME()") }); 215 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("PROPOSER()") }); 216 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("SUBMISSION_INTERVAL()") }); 217 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("challenger()") }); 218 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("computeL2Timestamp(uint256)") }); 219 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("deleteL2Outputs(uint256)"), _auth: Role.CHALLENGER }); 220 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("finalizationPeriodSeconds()") }); 221 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("getL2Output(uint256)") }); 222 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("getL2OutputAfter(uint256)") }); 223 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("getL2OutputIndexAfter(uint256)") }); 224 _addSpec({ 225 _name: "L2OutputOracle", 226 _sel: _getSel("initialize(uint256,uint256,uint256,uint256,address,address,uint256)") 227 }); 228 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("l2BlockTime()") }); 229 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("latestBlockNumber()") }); 230 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("latestOutputIndex()") }); 231 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("nextBlockNumber()") }); 232 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("nextOutputIndex()") }); 233 _addSpec({ 234 _name: "L2OutputOracle", 235 _sel: _getSel("proposeL2Output(bytes32,uint256,bytes32,uint256)"), 236 _auth: Role.PROPOSER 237 }); 238 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("proposer()") }); 239 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("startingBlockNumber()") }); 240 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("startingTimestamp()") }); 241 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("submissionInterval()") }); 242 _addSpec({ _name: "L2OutputOracle", _sel: _getSel("version()") }); 243 244 // OptimismPortal 245 _addSpec({ _name: "OptimismPortal", _sel: _getSel("GUARDIAN()") }); 246 _addSpec({ _name: "OptimismPortal", _sel: _getSel("L2_ORACLE()") }); 247 _addSpec({ _name: "OptimismPortal", _sel: _getSel("SYSTEM_CONFIG()") }); 248 _addSpec({ _name: "OptimismPortal", _sel: _getSel("depositTransaction(address,uint256,uint64,bool,bytes)") }); 249 _addSpec({ _name: "OptimismPortal", _sel: _getSel("donateETH()") }); 250 _addSpec({ 251 _name: "OptimismPortal", 252 _sel: OptimismPortal.finalizeWithdrawalTransaction.selector, 253 _pausable: true 254 }); 255 _addSpec({ _name: "OptimismPortal", _sel: _getSel("finalizedWithdrawals(bytes32)") }); 256 _addSpec({ _name: "OptimismPortal", _sel: _getSel("guardian()") }); 257 _addSpec({ _name: "OptimismPortal", _sel: _getSel("initialize(address,address,address)") }); 258 _addSpec({ _name: "OptimismPortal", _sel: _getSel("isOutputFinalized(uint256)") }); 259 _addSpec({ _name: "OptimismPortal", _sel: _getSel("l2Oracle()") }); 260 _addSpec({ _name: "OptimismPortal", _sel: _getSel("l2Sender()") }); 261 _addSpec({ _name: "OptimismPortal", _sel: _getSel("minimumGasLimit(uint64)") }); 262 _addSpec({ _name: "OptimismPortal", _sel: _getSel("params()") }); 263 _addSpec({ _name: "OptimismPortal", _sel: _getSel("paused()") }); 264 _addSpec({ _name: "OptimismPortal", _sel: OptimismPortal.proveWithdrawalTransaction.selector, _pausable: true }); 265 _addSpec({ _name: "OptimismPortal", _sel: _getSel("provenWithdrawals(bytes32)") }); 266 _addSpec({ _name: "OptimismPortal", _sel: _getSel("superchainConfig()") }); 267 _addSpec({ _name: "OptimismPortal", _sel: _getSel("systemConfig()") }); 268 _addSpec({ _name: "OptimismPortal", _sel: _getSel("version()") }); 269 270 // OptimismPortal2 271 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("GUARDIAN()") }); 272 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("SYSTEM_CONFIG()") }); 273 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("depositTransaction(address,uint256,uint64,bool,bytes)") }); 274 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("donateETH()") }); 275 _addSpec({ 276 _name: "OptimismPortal2", 277 _sel: OptimismPortal2.finalizeWithdrawalTransaction.selector, 278 _pausable: true 279 }); 280 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("finalizedWithdrawals(bytes32)") }); 281 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("guardian()") }); 282 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("initialize(address,address,address)") }); 283 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("l2Sender()") }); 284 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("minimumGasLimit(uint64)") }); 285 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("params()") }); 286 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("paused()") }); 287 _addSpec({ _name: "OptimismPortal2", _sel: OptimismPortal2.proveWithdrawalTransaction.selector, _pausable: true }); 288 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("provenWithdrawals(bytes32)") }); 289 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("superchainConfig()") }); 290 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("systemConfig()") }); 291 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("version()") }); 292 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("disputeGameFactory()") }); 293 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("disputeGameBlacklist(address)") }); 294 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("respectedGameType()") }); 295 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("blacklistDisputeGame(address)"), _auth: Role.GUARDIAN }); 296 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("setRespectedGameType(uint32)"), _auth: Role.GUARDIAN }); 297 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("checkWithdrawal(bytes32)") }); 298 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("proofMaturityDelaySeconds()") }); 299 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("disputeGameFinalityDelaySeconds()") }); 300 _addSpec({ _name: "OptimismPortal2", _sel: _getSel("respectedGameTypeUpdatedAt()") }); 301 302 // ProtocolVersions 303 _addSpec({ _name: "ProtocolVersions", _sel: _getSel("RECOMMENDED_SLOT()") }); 304 _addSpec({ _name: "ProtocolVersions", _sel: _getSel("REQUIRED_SLOT()") }); 305 _addSpec({ _name: "ProtocolVersions", _sel: _getSel("VERSION()") }); 306 _addSpec({ _name: "ProtocolVersions", _sel: ProtocolVersions.initialize.selector }); 307 _addSpec({ _name: "ProtocolVersions", _sel: _getSel("owner()") }); 308 _addSpec({ _name: "ProtocolVersions", _sel: ProtocolVersions.recommended.selector }); 309 _addSpec({ _name: "ProtocolVersions", _sel: _getSel("renounceOwnership()"), _auth: Role.SYSTEMCONFIGOWNER }); 310 _addSpec({ _name: "ProtocolVersions", _sel: ProtocolVersions.required.selector }); 311 _addSpec({ 312 _name: "ProtocolVersions", 313 _sel: ProtocolVersions.setRequired.selector, 314 _auth: Role.SYSTEMCONFIGOWNER 315 }); 316 _addSpec({ 317 _name: "ProtocolVersions", 318 _sel: ProtocolVersions.setRecommended.selector, 319 _auth: Role.SYSTEMCONFIGOWNER 320 }); 321 _addSpec({ _name: "ProtocolVersions", _sel: _getSel("transferOwnership(address)") }); 322 _addSpec({ _name: "ProtocolVersions", _sel: _getSel("version()") }); 323 324 // ResourceMetering 325 _addSpec({ _name: "ResourceMetering", _sel: _getSel("params()") }); 326 327 // SuperchainConfig 328 _addSpec({ _name: "SuperchainConfig", _sel: _getSel("GUARDIAN_SLOT()") }); 329 _addSpec({ _name: "SuperchainConfig", _sel: _getSel("PAUSED_SLOT()") }); 330 _addSpec({ _name: "SuperchainConfig", _sel: _getSel("guardian()") }); 331 _addSpec({ _name: "SuperchainConfig", _sel: _getSel("initialize(address,bool)") }); 332 _addSpec({ _name: "SuperchainConfig", _sel: _getSel("pause(string)"), _auth: Role.GUARDIAN }); 333 _addSpec({ _name: "SuperchainConfig", _sel: _getSel("paused()") }); 334 _addSpec({ _name: "SuperchainConfig", _sel: _getSel("unpause()"), _auth: Role.GUARDIAN }); 335 _addSpec({ _name: "SuperchainConfig", _sel: _getSel("version()") }); 336 337 // SystemConfig 338 _addSpec({ _name: "SystemConfig", _sel: _getSel("UNSAFE_BLOCK_SIGNER_SLOT()") }); 339 _addSpec({ _name: "SystemConfig", _sel: _getSel("START_BLOCK_SLOT()") }); 340 _addSpec({ _name: "SystemConfig", _sel: _getSel("VERSION()") }); 341 _addSpec({ _name: "SystemConfig", _sel: _getSel("batcherHash()") }); 342 _addSpec({ _name: "SystemConfig", _sel: _getSel("gasLimit()") }); 343 _addSpec({ _name: "SystemConfig", _sel: SystemConfig.initialize.selector }); 344 _addSpec({ _name: "SystemConfig", _sel: SystemConfig.minimumGasLimit.selector }); 345 _addSpec({ _name: "SystemConfig", _sel: _getSel("overhead()") }); 346 _addSpec({ _name: "SystemConfig", _sel: _getSel("owner()") }); 347 _addSpec({ _name: "SystemConfig", _sel: _getSel("renounceOwnership()"), _auth: Role.SYSTEMCONFIGOWNER }); 348 _addSpec({ _name: "SystemConfig", _sel: SystemConfig.resourceConfig.selector }); 349 _addSpec({ _name: "SystemConfig", _sel: _getSel("scalar()") }); 350 _addSpec({ _name: "SystemConfig", _sel: SystemConfig.setBatcherHash.selector, _auth: Role.SYSTEMCONFIGOWNER }); 351 _addSpec({ _name: "SystemConfig", _sel: SystemConfig.setGasConfig.selector, _auth: Role.SYSTEMCONFIGOWNER }); 352 _addSpec({ _name: "SystemConfig", _sel: SystemConfig.setGasLimit.selector, _auth: Role.SYSTEMCONFIGOWNER }); 353 _addSpec({ _name: "SystemConfig", _sel: SystemConfig.setResourceConfig.selector, _auth: Role.SYSTEMCONFIGOWNER }); 354 _addSpec({ 355 _name: "SystemConfig", 356 _sel: SystemConfig.setUnsafeBlockSigner.selector, 357 _auth: Role.SYSTEMCONFIGOWNER 358 }); 359 _addSpec({ _name: "SystemConfig", _sel: _getSel("transferOwnership(address)"), _auth: Role.SYSTEMCONFIGOWNER }); 360 _addSpec({ _name: "SystemConfig", _sel: SystemConfig.unsafeBlockSigner.selector }); 361 _addSpec({ _name: "SystemConfig", _sel: _getSel("version()") }); 362 _addSpec({ _name: "SystemConfig", _sel: _getSel("l1CrossDomainMessenger()") }); 363 _addSpec({ _name: "SystemConfig", _sel: _getSel("l1ERC721Bridge()") }); 364 _addSpec({ _name: "SystemConfig", _sel: _getSel("l1StandardBridge()") }); 365 _addSpec({ _name: "SystemConfig", _sel: _getSel("l2OutputOracle()") }); 366 _addSpec({ _name: "SystemConfig", _sel: _getSel("optimismPortal()") }); 367 _addSpec({ _name: "SystemConfig", _sel: _getSel("optimismMintableERC20Factory()") }); 368 _addSpec({ _name: "SystemConfig", _sel: _getSel("batchInbox()") }); 369 _addSpec({ _name: "SystemConfig", _sel: _getSel("startBlock()") }); 370 _addSpec({ _name: "SystemConfig", _sel: _getSel("L1_CROSS_DOMAIN_MESSENGER_SLOT()") }); 371 _addSpec({ _name: "SystemConfig", _sel: _getSel("L1_ERC_721_BRIDGE_SLOT()") }); 372 _addSpec({ _name: "SystemConfig", _sel: _getSel("L1_STANDARD_BRIDGE_SLOT()") }); 373 _addSpec({ _name: "SystemConfig", _sel: _getSel("L2_OUTPUT_ORACLE_SLOT()") }); 374 _addSpec({ _name: "SystemConfig", _sel: _getSel("OPTIMISM_PORTAL_SLOT()") }); 375 _addSpec({ _name: "SystemConfig", _sel: _getSel("OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT()") }); 376 _addSpec({ _name: "SystemConfig", _sel: _getSel("BATCH_INBOX_SLOT()") }); 377 378 // ProxyAdmin 379 _addSpec({ _name: "ProxyAdmin", _sel: _getSel("addressManager()") }); 380 _addSpec({ 381 _name: "ProxyAdmin", 382 _sel: _getSel("changeProxyAdmin(address,address)"), 383 _auth: Role.L1PROXYADMINOWNER 384 }); 385 _addSpec({ _name: "ProxyAdmin", _sel: _getSel("getProxyAdmin(address)") }); 386 _addSpec({ _name: "ProxyAdmin", _sel: _getSel("getProxyImplementation(address)") }); 387 _addSpec({ _name: "ProxyAdmin", _sel: _getSel("implementationName(address)") }); 388 _addSpec({ _name: "ProxyAdmin", _sel: _getSel("isUpgrading()") }); 389 _addSpec({ _name: "ProxyAdmin", _sel: _getSel("owner()") }); 390 _addSpec({ _name: "ProxyAdmin", _sel: _getSel("proxyType(address)") }); 391 _addSpec({ _name: "ProxyAdmin", _sel: _getSel("renounceOwnership()"), _auth: Role.L1PROXYADMINOWNER }); 392 _addSpec({ _name: "ProxyAdmin", _sel: _getSel("setAddress(string,address)"), _auth: Role.L1PROXYADMINOWNER }); 393 _addSpec({ _name: "ProxyAdmin", _sel: _getSel("setAddressManager(address)"), _auth: Role.L1PROXYADMINOWNER }); 394 _addSpec({ 395 _name: "ProxyAdmin", 396 _sel: _getSel("setImplementationName(address,string)"), 397 _auth: Role.L1PROXYADMINOWNER 398 }); 399 _addSpec({ _name: "ProxyAdmin", _sel: _getSel("setProxyType(address,uint8)"), _auth: Role.L1PROXYADMINOWNER }); 400 _addSpec({ _name: "ProxyAdmin", _sel: _getSel("setUpgrading(bool)") }); 401 _addSpec({ _name: "ProxyAdmin", _sel: _getSel("transferOwnership(address)"), _auth: Role.L1PROXYADMINOWNER }); 402 _addSpec({ _name: "ProxyAdmin", _sel: _getSel("upgrade(address,address)") }); 403 _addSpec({ 404 _name: "ProxyAdmin", 405 _sel: _getSel("upgradeAndCall(address,address,bytes)"), 406 _auth: Role.L1PROXYADMINOWNER 407 }); 408 409 // GovernanceToken 410 _addSpec({ _name: "GovernanceToken", _sel: _getSel("DOMAIN_SEPARATOR()") }); 411 _addSpec({ _name: "GovernanceToken", _sel: _getSel("allowance(address,address)") }); 412 _addSpec({ _name: "GovernanceToken", _sel: _getSel("approve(address,uint256)") }); 413 _addSpec({ _name: "GovernanceToken", _sel: _getSel("balanceOf(address)") }); 414 _addSpec({ _name: "GovernanceToken", _sel: _getSel("burn(uint256)") }); 415 _addSpec({ _name: "GovernanceToken", _sel: _getSel("burnFrom(address,uint256)") }); 416 _addSpec({ _name: "GovernanceToken", _sel: _getSel("checkpoints(address,uint32)") }); 417 _addSpec({ _name: "GovernanceToken", _sel: _getSel("decimals()") }); 418 _addSpec({ _name: "GovernanceToken", _sel: _getSel("decreaseAllowance(address,uint256)") }); 419 _addSpec({ _name: "GovernanceToken", _sel: _getSel("delegate(address)") }); 420 _addSpec({ 421 _name: "GovernanceToken", 422 _sel: _getSel("delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)") 423 }); 424 _addSpec({ _name: "GovernanceToken", _sel: _getSel("delegates(address)") }); 425 _addSpec({ _name: "GovernanceToken", _sel: _getSel("getPastTotalSupply(uint256)") }); 426 _addSpec({ _name: "GovernanceToken", _sel: _getSel("getPastVotes(address,uint256)") }); 427 _addSpec({ _name: "GovernanceToken", _sel: _getSel("getVotes(address)") }); 428 _addSpec({ _name: "GovernanceToken", _sel: _getSel("increaseAllowance(address,uint256)") }); 429 _addSpec({ _name: "GovernanceToken", _sel: _getSel("mint(address,uint256)"), _auth: Role.GOVERNANCETOKENOWNER }); 430 _addSpec({ _name: "GovernanceToken", _sel: _getSel("name()") }); 431 _addSpec({ _name: "GovernanceToken", _sel: _getSel("nonces(address)") }); 432 _addSpec({ _name: "GovernanceToken", _sel: _getSel("numCheckpoints(address)") }); 433 _addSpec({ _name: "GovernanceToken", _sel: _getSel("owner()") }); 434 _addSpec({ 435 _name: "GovernanceToken", 436 _sel: _getSel("permit(address,address,uint256,uint256,uint8,bytes32,bytes32)") 437 }); 438 _addSpec({ _name: "GovernanceToken", _sel: _getSel("renounceOwnership()") }); 439 _addSpec({ _name: "GovernanceToken", _sel: _getSel("symbol()") }); 440 _addSpec({ _name: "GovernanceToken", _sel: _getSel("totalSupply()") }); 441 _addSpec({ _name: "GovernanceToken", _sel: _getSel("transfer(address,uint256)") }); 442 _addSpec({ _name: "GovernanceToken", _sel: _getSel("transferFrom(address,address,uint256)") }); 443 _addSpec({ _name: "GovernanceToken", _sel: _getSel("transferOwnership(address)") }); 444 445 // MintManager 446 _addSpec({ _name: "MintManager", _sel: _getSel("DENOMINATOR()") }); 447 _addSpec({ _name: "MintManager", _sel: _getSel("MINT_CAP()") }); 448 _addSpec({ _name: "MintManager", _sel: _getSel("MINT_PERIOD()") }); 449 _addSpec({ _name: "MintManager", _sel: _getSel("governanceToken()") }); 450 _addSpec({ _name: "MintManager", _sel: _getSel("mint(address,uint256)"), _auth: Role.MINTMANAGEROWNER }); 451 _addSpec({ _name: "MintManager", _sel: _getSel("mintPermittedAfter()") }); 452 _addSpec({ _name: "MintManager", _sel: _getSel("owner()") }); 453 _addSpec({ _name: "MintManager", _sel: _getSel("renounceOwnership()"), _auth: Role.MINTMANAGEROWNER }); 454 _addSpec({ _name: "MintManager", _sel: _getSel("transferOwnership(address)"), _auth: Role.MINTMANAGEROWNER }); 455 _addSpec({ _name: "MintManager", _sel: _getSel("upgrade(address)"), _auth: Role.MINTMANAGEROWNER }); 456 } 457 458 /// @dev Computes the selector from a function signature. 459 function _getSel(string memory _name) internal pure returns (bytes4) { 460 return bytes4(keccak256(abi.encodePacked(_name))); 461 } 462 463 /// @dev Adds a spec for a function. 464 function _addSpec(string memory _name, bytes4 _sel, Role _auth, bool _pausable) internal { 465 specs[_name][_sel] = Spec({ name: _name, sel: _sel, auth: _auth, pausable: _pausable }); 466 numEntries[_name]++; 467 } 468 469 /// @dev Adds a spec for a function with no auth. 470 function _addSpec(string memory _name, bytes4 _sel, bool _pausable) internal { 471 _addSpec({ _name: _name, _sel: _sel, _auth: Role.NOAUTH, _pausable: _pausable }); 472 } 473 474 /// @dev Adds a spec for a function with no pausability. 475 function _addSpec(string memory _name, bytes4 _sel, Role _auth) internal { 476 _addSpec({ _name: _name, _sel: _sel, _auth: _auth, _pausable: false }); 477 } 478 479 /// @dev Adds a spec for a function with no auth and no pausability. 480 function _addSpec(string memory _name, bytes4 _sel) internal { 481 _addSpec({ _name: _name, _sel: _sel, _auth: Role.NOAUTH, _pausable: false }); 482 } 483 484 /// @notice Ensures that there's an auth spec for every L1 contract function. 485 function testContractAuth() public { 486 Abi[] memory abis = _getL1ContractFunctionAbis(); 487 488 for (uint256 i = 0; i < abis.length; i++) { 489 string memory contractName = abis[i].contractName; 490 assertEq( 491 abis[i].entries.length, numEntries[contractName], "Specification_Test: invalid number of ABI entries" 492 ); 493 494 for (uint256 j = 0; j < abis[i].entries.length; j++) { 495 AbiEntry memory abiEntry = abis[i].entries[j]; 496 console.log( 497 "Checking auth spec for %s: %s(%x)", contractName, abiEntry.fnName, uint256(uint32(abiEntry.sel)) 498 ); 499 Spec memory spec = specs[contractName][abiEntry.sel]; 500 assertTrue(spec.sel != bytes4(0), "Specification_Test: missing spec definition"); 501 assertEq(abiEntry.sel, spec.sel, "Specification_Test: invalid ABI"); 502 } 503 } 504 } 505 506 /// @dev Returns the function ABIs of all L1 contracts. 507 function _getL1ContractFunctionAbis() internal returns (Abi[] memory abis_) { 508 string[] memory command = new string[](3); 509 command[0] = Executables.bash; 510 command[1] = "-c"; 511 command[2] = string.concat( 512 Executables.find, 513 " src/{L1,governance,universal/ProxyAdmin.sol} -type f -exec basename {} \\;", 514 " | ", 515 Executables.sed, 516 " 's/\\.[^.]*$//'", 517 " | ", 518 Executables.jq, 519 " -R -s 'split(\"\n\")[:-1]'" 520 ); 521 string[] memory contractNames = abi.decode(vm.parseJson(string(vm.ffi(command))), (string[])); 522 523 abis_ = new Abi[](contractNames.length); 524 525 for (uint256 i; i < contractNames.length; i++) { 526 string memory contractName = contractNames[i]; 527 string[] memory methodIdentifiers = ForgeArtifacts.getMethodIdentifiers(contractName); 528 abis_[i].contractName = contractName; 529 abis_[i].entries = new AbiEntry[](methodIdentifiers.length); 530 for (uint256 j; j < methodIdentifiers.length; j++) { 531 string memory fnName = methodIdentifiers[j]; 532 bytes4 sel = bytes4(keccak256(abi.encodePacked(fnName))); 533 abis_[i].entries[j] = AbiEntry({ fnName: fnName, sel: sel }); 534 } 535 } 536 } 537 }