diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b0b8c247..62501c44 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,7 +4,7 @@ on: pull_request: env: - FOUNDRY_PROFILE: ci + FOUNDRY_PROFILE: default jobs: check: diff --git a/contracts/foundry.toml b/contracts/foundry.toml index a05d9b18..3396b05c 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -19,3 +19,7 @@ fs_permissions = [ { access='read', path='./test/nitro-attestation/' }, { access='read-write', path='./deployments/' }, ] + +# workaround for https://github.com/foundry-rs/foundry/issues/11668 +[lint] +lint_on_build = false diff --git a/contracts/script/DeploySystem.s.sol b/contracts/script/DeploySystem.s.sol index 6a57d8a8..dbf3d2fd 100644 --- a/contracts/script/DeploySystem.s.sol +++ b/contracts/script/DeploySystem.s.sol @@ -327,7 +327,9 @@ contract DeploySystem is Deploy { _upgradeAndCallViaSafe({ _proxy: payable(l2OutputOracleProxy), _implementation: l2OutputOracle, - _innerCallData: abi.encodeCall(OutputOracle.initialize, (SystemConfigOwnable(systemConfigProxy), 0, 0, false)) + _innerCallData: abi.encodeCall( + OutputOracle.initialize, (SystemConfigOwnable(systemConfigProxy), 0, 0, false) + ) }); OutputOracle oracle = OutputOracle(l2OutputOracleProxy); diff --git a/contracts/script/UpgradeSystemConfigGlobal.s.sol b/contracts/script/UpgradeSystemConfigGlobal.s.sol index 25f35bdb..d5cbee69 100644 --- a/contracts/script/UpgradeSystemConfigGlobal.s.sol +++ b/contracts/script/UpgradeSystemConfigGlobal.s.sol @@ -22,7 +22,8 @@ contract UpgradeSystemConfigGlobal is Script, Artifacts { address addr_ = address(new SystemConfigGlobal{salt: _implSalt()}(ICertManager(mustGetAddress("CertManager")))); bytes memory data = abi.encodeCall(ProxyAdmin.upgrade, (payable(mustGetAddress("SystemConfigGlobalProxy")), address(addr_))); - IGnosisSafe(mustGetAddress("SystemOwnerSafe")).execTransaction({ + IGnosisSafe(mustGetAddress("SystemOwnerSafe")) + .execTransaction({ to: mustGetAddress("ProxyAdmin"), value: 0, data: data, diff --git a/contracts/script/UpgradeSystemConfigOwnable.s.sol b/contracts/script/UpgradeSystemConfigOwnable.s.sol index cd53d603..8ecb8fd8 100644 --- a/contracts/script/UpgradeSystemConfigOwnable.s.sol +++ b/contracts/script/UpgradeSystemConfigOwnable.s.sol @@ -22,7 +22,8 @@ contract UpgradeSystemConfigOwnable is Script { SystemConfigOwnable config = new SystemConfigOwnable(OwnerConfig(ownerConfig)); bytes memory data = abi.encodeCall(ProxyAdmin.upgrade, (payable(proxy), address(config))); - IGnosisSafe(safe).execTransaction({ + IGnosisSafe(safe) + .execTransaction({ to: admin, value: 0, data: data, diff --git a/contracts/src/DeployChain.sol b/contracts/src/DeployChain.sol index 765431b4..0683ff57 100644 --- a/contracts/src/DeployChain.sol +++ b/contracts/src/DeployChain.sol @@ -223,19 +223,22 @@ contract DeployChain is Ownable { DeployAddresses memory addresses, bool proofsEnabled ) internal { - OutputOracle(addresses.l2OutputOracle).initialize( - SystemConfigOwnable(addresses.systemConfig), hashes.configHash, hashes.genesisOutputRoot, proofsEnabled - ); - - Portal(payable(addresses.optimismPortal)).initialize( - OutputOracle(addresses.l2OutputOracle), - ISystemConfig(addresses.systemConfig), - ISuperchainConfig(superchainConfig) - ); + OutputOracle(addresses.l2OutputOracle) + .initialize( + SystemConfigOwnable(addresses.systemConfig), hashes.configHash, hashes.genesisOutputRoot, proofsEnabled + ); + + Portal(payable(addresses.optimismPortal)) + .initialize( + OutputOracle(addresses.l2OutputOracle), + ISystemConfig(addresses.systemConfig), + ISuperchainConfig(superchainConfig) + ); SystemConfig.Addresses memory systemAddresses = _createSystemAddresses(addresses, gasConfig.gasToken); - SystemConfigOwnable(addresses.systemConfig).initialize({ + SystemConfigOwnable(addresses.systemConfig) + .initialize({ _basefeeScalar: gasConfig.basefeeScalar, _blobbasefeeScalar: gasConfig.blobbasefeeScalar, _batcherHash: bytes32(uint256(uint160(addressConfig.batcher))), @@ -247,21 +250,22 @@ contract DeployChain is Ownable { _addresses: systemAddresses }); - L1CrossDomainMessenger(addresses.l1CrossDomainMessenger).initialize( - ISuperchainConfig(superchainConfig), - IOptimismPortal(payable(addresses.optimismPortal)), - ISystemConfig(addresses.systemConfig) - ); - - L1StandardBridge(payable(addresses.l1StandardBridge)).initialize( - ICrossDomainMessenger(addresses.l1CrossDomainMessenger), - ISuperchainConfig(superchainConfig), - ISystemConfig(addresses.systemConfig) - ); - - L1ERC721Bridge(addresses.l1ERC721Bridge).initialize( - ICrossDomainMessenger(addresses.l1CrossDomainMessenger), ISuperchainConfig(superchainConfig) - ); + L1CrossDomainMessenger(addresses.l1CrossDomainMessenger) + .initialize( + ISuperchainConfig(superchainConfig), + IOptimismPortal(payable(addresses.optimismPortal)), + ISystemConfig(addresses.systemConfig) + ); + + L1StandardBridge(payable(addresses.l1StandardBridge)) + .initialize( + ICrossDomainMessenger(addresses.l1CrossDomainMessenger), + ISuperchainConfig(superchainConfig), + ISystemConfig(addresses.systemConfig) + ); + + L1ERC721Bridge(addresses.l1ERC721Bridge) + .initialize(ICrossDomainMessenger(addresses.l1CrossDomainMessenger), ISuperchainConfig(superchainConfig)); OptimismMintableERC20Factory(addresses.optimismMintableERC20Factory).initialize(addresses.l1StandardBridge); } diff --git a/contracts/src/OutputOracle.sol b/contracts/src/OutputOracle.sol index 0767b3f2..7d0a33a5 100644 --- a/contracts/src/OutputOracle.sol +++ b/contracts/src/OutputOracle.sol @@ -82,9 +82,7 @@ contract OutputOracle is Initializable, ISemver { configHash = _configHash; l2Outputs.push( Types.OutputProposal({ - outputRoot: _genesisOutputRoot, - timestamp: uint128(block.timestamp), - l2BlockNumber: uint128(0) + outputRoot: _genesisOutputRoot, timestamp: uint128(block.timestamp), l2BlockNumber: uint128(0) }) ); proofsEnabled = _proofsEnabled; @@ -136,9 +134,7 @@ contract OutputOracle is Initializable, ISemver { emit OutputProposed(_outputRoot, latestOutputIndex, _l2BlockNumber, block.timestamp); Types.OutputProposal memory op = Types.OutputProposal({ - outputRoot: _outputRoot, - timestamp: uint128(block.timestamp), - l2BlockNumber: uint128(_l2BlockNumber) + outputRoot: _outputRoot, timestamp: uint128(block.timestamp), l2BlockNumber: uint128(_l2BlockNumber) }); if (l2Outputs.length < maxOutputCount) { l2Outputs.push(op); diff --git a/contracts/src/Portal.sol b/contracts/src/Portal.sol index 8fe07422..1ccc922b 100644 --- a/contracts/src/Portal.sol +++ b/contracts/src/Portal.sol @@ -383,12 +383,7 @@ contract Portal is Initializable, ResourceMetering, ISemver { } _depositTransaction({ - _to: _to, - _mint: _mint, - _value: _value, - _gasLimit: _gasLimit, - _isCreation: _isCreation, - _data: _data + _to: _to, _mint: _mint, _value: _value, _gasLimit: _gasLimit, _isCreation: _isCreation, _data: _data }); } @@ -410,12 +405,7 @@ contract Portal is Initializable, ResourceMetering, ISemver { if (token != Constants.ETHER && msg.value != 0) revert NoValue(); _depositTransaction({ - _to: _to, - _mint: msg.value, - _value: _value, - _gasLimit: _gasLimit, - _isCreation: _isCreation, - _data: _data + _to: _to, _mint: msg.value, _value: _value, _gasLimit: _gasLimit, _isCreation: _isCreation, _data: _data }); } diff --git a/contracts/src/SystemConfigGlobal.sol b/contracts/src/SystemConfigGlobal.sol index f994511d..771a77fc 100644 --- a/contracts/src/SystemConfigGlobal.sol +++ b/contracts/src/SystemConfigGlobal.sol @@ -58,7 +58,8 @@ contract SystemConfigGlobal is OwnableManagedUpgradeable, ISemver, NitroValidato bytes32 pcr0 = attestationTbs.keccak(ptrs.pcrs[0]); require(validPCR0s[pcr0], "invalid pcr0 in attestation"); - require(ptrs.timestamp + MAX_AGE > block.timestamp, "attestation too old"); + uint64 timestampSeconds = ptrs.timestamp / 1000; + require(timestampSeconds + MAX_AGE > block.timestamp, "attestation too old"); // The publicKey is encoded in the form specified in section 4.3.6 of ANSI X9.62, which is a // 0x04 byte followed by the x and y coordinates of the public key. We ignore the first byte. diff --git a/contracts/src/SystemConfigOwnable.sol b/contracts/src/SystemConfigOwnable.sol index 36ec5727..46802127 100644 --- a/contracts/src/SystemConfigOwnable.sol +++ b/contracts/src/SystemConfigOwnable.sol @@ -298,12 +298,8 @@ contract SystemConfigOwnable is OwnableConfig, ISemver, IGasToken { // Set the gas paying token in storage and in the OptimismPortal. GasPayingToken.set({_token: _token, _decimals: GAS_PAYING_TOKEN_DECIMALS, _name: name, _symbol: symbol}); - IOptimismPortal(payable(optimismPortal())).setGasPayingToken({ - _token: _token, - _decimals: GAS_PAYING_TOKEN_DECIMALS, - _name: name, - _symbol: symbol - }); + IOptimismPortal(payable(optimismPortal())) + .setGasPayingToken({_token: _token, _decimals: GAS_PAYING_TOKEN_DECIMALS, _name: name, _symbol: symbol}); } } diff --git a/contracts/test/SystemConfigGlobal.t.sol b/contracts/test/SystemConfigGlobal.t.sol index ba9c6fdd..d7839e64 100644 --- a/contracts/test/SystemConfigGlobal.t.sol +++ b/contracts/test/SystemConfigGlobal.t.sol @@ -10,12 +10,12 @@ contract SystemConfigGlobalTest is Test { SystemConfigGlobal systemConfigGlobal; function setUp() public { - vm.warp(1708930774); CertManager certManager = new CertManager(); systemConfigGlobal = new SystemConfigGlobal(certManager); } function test_validateAttestation() public { + vm.warp(1708930774); vm.startPrank(systemConfigGlobal.owner()); systemConfigGlobal.registerPCR0( @@ -29,4 +29,21 @@ contract SystemConfigGlobalTest is Test { address expectedSigner = 0x874a4c5675cd4850dB08bD9A1e3184ED239087e4; assertTrue(systemConfigGlobal.validSigners(expectedSigner)); } + + function test_expiredAttestation() public { + vm.warp(1708930922 + 60 minutes); + vm.startPrank(systemConfigGlobal.owner()); + + systemConfigGlobal.registerPCR0( + hex"17BF8F048519797BE90497001A7559A3D555395937117D76F8BAAEDF56CA6D97952DE79479BC0C76E5D176D20F663790" + ); + + bytes memory attestation = vm.readFileBinary("./test/nitro-attestation/sample_attestation.bin"); + (bytes memory attestationTbs, bytes memory signature) = systemConfigGlobal.decodeAttestationTbs(attestation); + vm.expectRevert("attestation too old"); + systemConfigGlobal.registerSigner(attestationTbs, signature); + + address expectedSigner = 0x874a4c5675cd4850dB08bD9A1e3184ED239087e4; + assertFalse(systemConfigGlobal.validSigners(expectedSigner)); + } }