diff --git a/da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol b/da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol new file mode 100644 index 000000000..e7473cffb --- /dev/null +++ b/da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +import {IL1DAValidator, L1DAValidatorOutput} from "../../IL1DAValidator.sol"; +import {ValL1DAWrongInputLength} from "../../DAContractsErrors.sol"; + +contract EigenDAL1Validator is IL1DAValidator { + function checkDA( + uint256, // _chainId + uint256, // _batchNumber + bytes32, // _l2DAValidatorOutputHash + bytes calldata _operatorDAInput, + uint256 maxBlobsSupported + ) external override returns (L1DAValidatorOutput memory output) { + // TODO: Implement real validation logic. + // For Validiums, we expect the operator to just provide the data for us. + // We don't need to do any checks with regard to the l2DAValidatorOutputHash. + if (_operatorDAInput.length < 32) { + revert ValL1DAWrongInputLength(_operatorDAInput.length, 32); + } + bytes32 stateDiffHash = abi.decode(_operatorDAInput[:32], (bytes32)); + + output.stateDiffHash = stateDiffHash; + + output.blobsLinearHashes = new bytes32[](maxBlobsSupported); + output.blobsOpeningCommitments = new bytes32[](maxBlobsSupported); + } +} diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index 5dd225453..487ec52a8 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -176,6 +176,15 @@ contract DeployL1Script is Script, DeployUtils { ); } + function getEigenDAL2ValidatorAddress() internal returns (address) { + return + Utils.getL2AddressViaCreate2Factory( + bytes32(0), + L2ContractHelper.hashL2Bytecode(L2ContractsBytecodesLib.readEigenDAL2ValidatorBytecode()), + hex"" + ); + } + function deployDAValidators() internal { vm.broadcast(msg.sender); address rollupDAManager = address(new RollupDAManager()); @@ -202,6 +211,13 @@ contract DeployL1Script is Script, DeployUtils { addresses.daAddresses.availL1DAValidator = config.contracts.availL1DAValidator; } + if (config.contracts.eigenDAL1Validator == address(0)) { + addresses.daAddresses.eigenDAL1Validator = deployViaCreate2(Utils.readEigenDAL1ValidatorBytecode(), ""); + console.log("EigenDAL1Validator deployed at:", addresses.daAddresses.eigenDAL1Validator); + } else { + addresses.daAddresses.eigenDAL1Validator = config.contracts.eigenDAL1Validator; + } + vm.startBroadcast(msg.sender); RollupDAManager(rollupDAManager).updateDAPair(address(rollupDAValidator), getRollupL2ValidatorAddress(), true); vm.stopBroadcast(); @@ -707,6 +723,11 @@ contract DeployL1Script is Script, DeployUtils { "avail_l1_da_validator_addr", addresses.daAddresses.availL1DAValidator ); + vm.serializeAddress( + "deployed_addresses", + "eigenda_l1_validator_addr", + addresses.daAddresses.eigenDAL1Validator + ); string memory deployedAddresses = vm.serializeAddress( "deployed_addresses", @@ -725,6 +746,7 @@ contract DeployL1Script is Script, DeployUtils { vm.serializeAddress("root", "expected_rollup_l2_da_validator_addr", getRollupL2ValidatorAddress()); vm.serializeAddress("root", "expected_no_da_validium_l2_validator_addr", getNoDAValidiumL2ValidatorAddress()); vm.serializeAddress("root", "expected_avail_l2_da_validator_addr", getAvailL2ValidatorAddress()); + vm.serializeAddress("root", "expected_eigenda_l2_validator_addr", getEigenDAL2ValidatorAddress()); string memory toml = vm.serializeAddress("root", "owner_address", config.ownerAddress); vm.writeToml(toml, outputPath); diff --git a/l1-contracts/deploy-scripts/DeployL2Contracts.sol b/l1-contracts/deploy-scripts/DeployL2Contracts.sol index fab4e3dd0..d5f4529db 100644 --- a/l1-contracts/deploy-scripts/DeployL2Contracts.sol +++ b/l1-contracts/deploy-scripts/DeployL2Contracts.sol @@ -170,7 +170,7 @@ contract DeployL2Script is Script { } else if (config.validatorType == DAValidatorType.Avail) { bytecode = L2ContractsBytecodesLib.readAvailL2DAValidatorBytecode(); } else if (config.validatorType == DAValidatorType.EigenDA) { - bytecode = L2ContractsBytecodesLib.readNoDAL2DAValidatorBytecode(); // TODO: update to EigenDA + bytecode = L2ContractsBytecodesLib.readEigenDAL2ValidatorBytecode(); } else { revert("Invalid DA validator type"); } diff --git a/l1-contracts/deploy-scripts/DeployUtils.s.sol b/l1-contracts/deploy-scripts/DeployUtils.s.sol index 44c56ce42..e79516904 100644 --- a/l1-contracts/deploy-scripts/DeployUtils.s.sol +++ b/l1-contracts/deploy-scripts/DeployUtils.s.sol @@ -102,6 +102,7 @@ struct DataAvailabilityDeployedAddresses { address l1RollupDAValidator; address noDAValidiumL1DAValidator; address availL1DAValidator; + address eigenDAL1Validator; } // solhint-disable-next-line gas-struct-packing @@ -165,6 +166,7 @@ struct ContractsConfig { bytes32 bootloaderHash; bytes32 defaultAAHash; address availL1DAValidator; + address eigenDAL1Validator; } struct TokensConfig { @@ -240,6 +242,10 @@ contract DeployUtils is Script { config.contracts.availL1DAValidator = toml.readAddress("$.contracts.avail_l1_da_validator"); } + if (vm.keyExistsToml(toml, "$.contracts.eigenda_l1_validator")) { + config.contracts.eigenDAL1Validator = toml.readAddress("$.contracts.eigenda_l1_validator"); + } + config.tokens.tokenWethAddress = toml.readAddress("$.tokens.token_weth_address"); } diff --git a/l1-contracts/deploy-scripts/L2ContractsBytecodesLib.sol b/l1-contracts/deploy-scripts/L2ContractsBytecodesLib.sol index e0644d220..51914dba3 100644 --- a/l1-contracts/deploy-scripts/L2ContractsBytecodesLib.sol +++ b/l1-contracts/deploy-scripts/L2ContractsBytecodesLib.sol @@ -82,6 +82,12 @@ library L2ContractsBytecodesLib { return Utils.readZKFoundryBytecodeL2("AvailL2DAValidator.sol", "AvailL2DAValidator"); } + /// @notice Reads the bytecode of the ValidiumL2DAValidator contract for EigenDA. + /// @return The bytecode of the ValidiumL2DAValidator contract. + function readEigenDAL2ValidatorBytecode() internal view returns (bytes memory) { + return Utils.readZKFoundryBytecodeL2("EigenDAL2Validator.sol", "EigenDAL2Validator"); + } + /// @notice Reads the bytecode of the ValidiumL2DAValidator contract for NoDA validium. /// @return The bytecode of the ValidiumL2DAValidator contract. function readNoDAL2DAValidatorBytecode() internal view returns (bytes memory) { diff --git a/l1-contracts/deploy-scripts/Utils.sol b/l1-contracts/deploy-scripts/Utils.sol index a67341785..72c63fd13 100644 --- a/l1-contracts/deploy-scripts/Utils.sol +++ b/l1-contracts/deploy-scripts/Utils.sol @@ -1031,6 +1031,10 @@ library Utils { bytecode = readFoundryBytecode("/../da-contracts/out/DummyAvailBridge.sol/DummyAvailBridge.json"); } + function readEigenDAL1ValidatorBytecode() internal view returns (bytes memory bytecode) { + bytecode = readFoundryBytecode("/../da-contracts/out/EigenDAL1Validator.sol/EigenDAL1Validator.json"); + } + // add this to be excluded from coverage report function test() internal {} } diff --git a/l2-contracts/contracts/data-availability/EigenDAL2Validator.sol b/l2-contracts/contracts/data-availability/EigenDAL2Validator.sol new file mode 100644 index 000000000..567849494 --- /dev/null +++ b/l2-contracts/contracts/data-availability/EigenDAL2Validator.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +import {IL2DAValidator} from "../interfaces/IL2DAValidator.sol"; + +/// Rollup DA validator. It will publish data that would allow to use either calldata or blobs. +contract EigenDAL2Validator is IL2DAValidator { + function validatePubdata( + // The rolling hash of the user L2->L1 logs. + bytes32, + // The root hash of the user L2->L1 logs. + bytes32, + // The chained hash of the L2->L1 messages + bytes32, + // The chained hash of uncompressed bytecodes sent to L1 + bytes32, + // Operator data, that is related to the DA itself + bytes calldata + ) external returns (bytes32 outputHash) { + // Since we do not need to publish anything to L1, we can just return 0. + // Note, that Rollup validator sends the hash of uncompressed state diffs, since the + // correctness of the publish pubdata depends on it. However Validium doesn't sent anything, + // so we don't need to publish even that. + // TODO: Implement real validation logic. + outputHash = bytes32(0); + } +}