diff --git a/.gas-snapshot b/.gas-snapshot index a0733a1..e63f7d4 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -75,6 +75,8 @@ DAVerifierRegistryTest:test_isRegistered_returnsTrueAfterAdd() (gas: 34462) DAVerifierRegistryTest:test_remove() (gas: 26284) DAVerifierRegistryTest:test_remove_RevertIf_NotRegistered() (gas: 13624) DAVerifierRegistryTest:test_remove_emitsEvent() (gas: 28380) +DeployCoreV2Test:test_confirmationDepthLeavesProcessingBlock() (gas: 17373496) +DeployCoreV2Test:test_rejectsConfirmationDepthWithoutProcessingBlock() (gas: 17373477) DeployCoreWithStagingIntegrationTest:test_AddAssertionWithOnChainDAVerifierOnBothOracles() (gas: 393263) DeployCoreWithStagingIntegrationTest:test_AddToWhitelistOnBothOracles() (gas: 91286) DeployCoreWithStagingIntegrationTest:test_BothOraclesDeployed() (gas: 5105) diff --git a/Makefile b/Makefile index 172db1c..5d8be28 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: check-storage-layout update-storage-layout +.PHONY: check-storage-layout update-storage-layout check-v2-size check-storage-layout: @bash shell/check_storage_layout.sh @@ -6,3 +6,6 @@ check-storage-layout: update-storage-layout: forge inspect StateOracle storage-layout --json > .storage-layout @echo "Storage layout snapshot updated." + +check-v2-size: + FOUNDRY_PROFILE=v2 forge build --sizes diff --git a/foundry.toml b/foundry.toml index a546f5b..46a32a6 100644 --- a/foundry.toml +++ b/foundry.toml @@ -11,6 +11,11 @@ evm_version = "cancun" [profile.snapshot] no_match_test = "^invariant_" +[profile.v2] +optimizer = true +optimizer_runs = 200 +evm_version = "cancun" + [lint] exclude_lints = ["mixed-case-function", "mixed-case-variable"] diff --git a/script/DeployCoreV2.s.sol b/script/DeployCoreV2.s.sol new file mode 100644 index 0000000..b30935d --- /dev/null +++ b/script/DeployCoreV2.s.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: CC0-1.0 +pragma solidity ^0.8.28; + +import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {console2} from "forge-std/console2.sol"; + +import {StateOracleV2} from "../src/StateOracleV2.sol"; +import {IAdminVerifier} from "../src/interfaces/IAdminVerifier.sol"; +import {IDAVerifier} from "../src/interfaces/IDAVerifier.sol"; +import {ITriggerManifestValidator} from "../src/interfaces/ITriggerManifestValidator.sol"; +import {TriggerManifestValidatorV1} from "../src/verification/TriggerManifestValidatorV1.sol"; +import {DeployCore} from "./DeployCore.s.sol"; + +/// @notice Production-only fresh deployment for StateOracleV2. +contract DeployCoreV2 is DeployCore { + uint256 internal eventConfirmationDepth; + + function setUp() public override { + assertionTimelockBlocks = vm.envUint("STATE_ORACLE_ASSERTION_TIMELOCK_BLOCKS"); + eventConfirmationDepth = vm.envUint("STATE_ORACLE_EVENT_CONFIRMATION_DEPTH"); + admin = vm.envAddress("STATE_ORACLE_ADMIN_ADDRESS"); + daProver = vm.envAddress("DA_PROVER_ADDRESS"); + deployOwnerVerifier = vm.envBool("DEPLOY_ADMIN_VERIFIER_OWNER"); + deployWhitelistVerifier = vm.envBool("DEPLOY_ADMIN_VERIFIER_WHITELIST"); + whitelistAdmin = vm.envOr("ADMIN_VERIFIER_WHITELIST_ADMIN_ADDRESS", address(0)); + + assert(daProver != address(0)); + assert(admin != address(0)); + assert(assertionTimelockBlocks > 0); + assert(_validEventTiming(assertionTimelockBlocks, eventConfirmationDepth)); + assert(deployWhitelistVerifier && whitelistAdmin != address(0) || !deployWhitelistVerifier); + } + + function _validEventTiming(uint256 timelockBlocks, uint256 confirmationDepth) internal pure returns (bool) { + return confirmationDepth != 0 && confirmationDepth < type(uint256).max && confirmationDepth + 1 < timelockBlocks; + } + + function run() public override broadcast { + _fundPersistentAccounts(); + address[] memory adminVerifierAddresses = _deployAdminVerifiers(); + address[] memory daVerifierAddresses = new address[](2); + daVerifierAddresses[0] = _deployDAVerifierECDSA(); + daVerifierAddresses[1] = _deployDAVerifierOnChain(); + + TriggerManifestValidatorV1 validator = new TriggerManifestValidatorV1(admin); + StateOracleV2 implementation = new StateOracleV2(assertionTimelockBlocks); + + IAdminVerifier[] memory adminVfrs = new IAdminVerifier[](adminVerifierAddresses.length); + for (uint256 i; i < adminVerifierAddresses.length; ++i) { + adminVfrs[i] = IAdminVerifier(adminVerifierAddresses[i]); + } + IDAVerifier[] memory daVfrs = new IDAVerifier[](daVerifierAddresses.length); + for (uint256 i; i < daVerifierAddresses.length; ++i) { + daVfrs[i] = IDAVerifier(daVerifierAddresses[i]); + } + + bytes memory initData = abi.encodeCall( + StateOracleV2.initialize, + (admin, adminVfrs, daVfrs, validator.SCHEMA_ID(), ITriggerManifestValidator(address(validator))) + ); + address proxy = address(new TransparentUpgradeableProxy(address(implementation), admin, initData)); + + console2.log("Trigger Manifest Validator V1 deployed at", address(validator)); + console2.log("State Oracle V2 Implementation deployed at", address(implementation)); + console2.log("State Oracle V2 Proxy deployed at", proxy); + } +} diff --git a/shell/create_artifacts.sh b/shell/create_artifacts.sh index f59dae7..7b838d2 100755 --- a/shell/create_artifacts.sh +++ b/shell/create_artifacts.sh @@ -39,6 +39,8 @@ mkdir -p "$ARTIFACTS" \ # Extract ABIs for main contracts extract_abi "$ROOT_DIR/out/StateOracle.sol/StateOracle.json" "${ARTIFACTS}" +extract_abi "$ROOT_DIR/out/StateOracleV2.sol/StateOracleV2.json" "${ARTIFACTS}" +extract_abi "$ROOT_DIR/out/TriggerManifestValidatorV1.sol/TriggerManifestValidatorV1.json" "${ARTIFACTS}" extract_abi "$ROOT_DIR/out/AdminVerifierOwner.sol/AdminVerifierOwner.json" "${ARTIFACTS}" extract_abi "$ROOT_DIR/out/DAVerifierECDSA.sol/DAVerifierECDSA.json" "${ARTIFACTS}" @@ -47,6 +49,7 @@ INTERFACES="${ARTIFACTS}/interfaces" extract_abi "$ROOT_DIR/out/IBatch.sol/IBatch.json" "${INTERFACES}" extract_abi "$ROOT_DIR/out/IDAVerifier.sol/IDAVerifier.json" "${INTERFACES}" extract_abi "$ROOT_DIR/out/IAdminVerifier.sol/IAdminVerifier.json" "${INTERFACES}" +extract_abi "$ROOT_DIR/out/ITriggerManifestValidator.sol/ITriggerManifestValidator.json" "${INTERFACES}" # Extract ABIs for libraries LIBRARIES="${ARTIFACTS}/libraries" diff --git a/test/DeployCoreV2.t.sol b/test/DeployCoreV2.t.sol new file mode 100644 index 0000000..f363b63 --- /dev/null +++ b/test/DeployCoreV2.t.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: CC0-1.0 +pragma solidity ^0.8.28; + +import {DeployCoreV2} from "../script/DeployCoreV2.s.sol"; + +contract DeployCoreV2Harness is DeployCoreV2 { + function validEventTiming(uint256 timelockBlocks, uint256 confirmationDepth) external pure returns (bool) { + return _validEventTiming(timelockBlocks, confirmationDepth); + } +} + +contract DeployCoreV2Test { + function test_confirmationDepthLeavesProcessingBlock() public { + assert(new DeployCoreV2Harness().validEventTiming(66, 64)); + } + + function test_rejectsConfirmationDepthWithoutProcessingBlock() public { + assert(!new DeployCoreV2Harness().validEventTiming(65, 64)); + } +}