diff --git a/.gas-snapshot b/.gas-snapshot index f2854ac..b36936f 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,31 +1,34 @@ -AcceptManagerTransfer:testFuzz_acceptManagerTransfer(address) (runs: 256, μ: 185205, ~: 185205) -AcceptManagerTransfer:test_RevertIf_NoPendingManager() (gas: 170816) +AcceptManagerTransfer:testFuzz_acceptManagerTransfer(address) (runs: 256, μ: 185139, ~: 185139) +AcceptManagerTransfer:test_RevertIf_NoPendingManager() (gas: 170772) AcceptManagerTransfer:test_isAdmin() (gas: 953761) -AddAdminVerifier:testFuzz_RevertIf_addAdminVerifierByUnauthorized(address) (runs: 256, μ: 270819, ~: 270819) -AddAdminVerifier:testFuzz_RevertIf_addAdminVerifierTwice(address) (runs: 256, μ: 47771, ~: 47771) -AddAdminVerifier:test_addAdminVerifier(address) (runs: 256, μ: 49506, ~: 49506) +AddAdminVerifier:testFuzz_RevertIf_addAdminVerifierByUnauthorized(address) (runs: 256, μ: 270817, ~: 270817) +AddAdminVerifier:testFuzz_RevertIf_addAdminVerifierTwice(address) (runs: 256, μ: 47899, ~: 47899) +AddAdminVerifier:test_addAdminVerifier(address) (runs: 256, μ: 49570, ~: 49570) AddAdminVerifier:test_isAdmin() (gas: 953695) -AddAssertion:testFuzz_RevertIf_addAssertionByUnauthorized(bytes32,address) (runs: 256, μ: 168554, ~: 168554) -AddAssertion:testFuzz_RevertIf_addAssertionNotRegistered(address,bytes32) (runs: 256, μ: 21802, ~: 21802) -AddAssertion:testFuzz_RevertIf_addDuplicateAssertion(bytes32) (runs: 256, μ: 240904, ~: 240904) -AddAssertion:testFuzz_addAssertion(bytes32) (runs: 256, μ: 234653, ~: 234653) -AddAssertion:testFuzz_addMultipleAssertions(bytes32,bytes32) (runs: 256, μ: 282925, ~: 282925) -AddAssertion:testFuzz_addTooManyAssertions(bytes32) (runs: 256, μ: 511735, ~: 511735) -AddAssertion:testFuzz_expectAssertionAdded(bytes32) (runs: 256, μ: 242023, ~: 242023) -AddAssertion:test_RevertIf_addAssertionWithUnregisteredDAVerifier() (gas: 168781) +AddAssertion:testFuzz_RevertIf_addAssertionByUnauthorized(bytes32,address) (runs: 256, μ: 168510, ~: 168510) +AddAssertion:testFuzz_RevertIf_addAssertionNotRegistered(address,bytes32) (runs: 256, μ: 21780, ~: 21780) +AddAssertion:testFuzz_RevertIf_addDuplicateAssertion(bytes32) (runs: 256, μ: 240838, ~: 240838) +AddAssertion:testFuzz_addAssertion(bytes32) (runs: 256, μ: 234609, ~: 234609) +AddAssertion:testFuzz_addMultipleAssertions(bytes32,bytes32) (runs: 256, μ: 282859, ~: 282859) +AddAssertion:testFuzz_addTooManyAssertions(bytes32) (runs: 256, μ: 511537, ~: 511537) +AddAssertion:testFuzz_expectAssertionAdded(bytes32) (runs: 256, μ: 241979, ~: 241979) +AddAssertion:test_RevertIf_addAssertionWithUnregisteredDAVerifier() (gas: 168737) AddAssertion:test_isAdmin() (gas: 953695) -AddAssertionWithWhitelist:testFuzz_RevertIf_addAssertionByNonWhitelistedManager(bytes32) (runs: 256, μ: 177531, ~: 177531) -AddAssertionWithWhitelist:test_addAssertionAfterAddingToWhitelist() (gas: 254234) -AddAssertionWithWhitelist:test_addAssertionWhenWhitelistDisabled() (gas: 233237) +AddAssertionWithWhitelist:testFuzz_RevertIf_addAssertionByNonWhitelistedManager(bytes32) (runs: 256, μ: 177443, ~: 177443) +AddAssertionWithWhitelist:test_addAssertionAfterAddingToWhitelist() (gas: 254197) +AddAssertionWithWhitelist:test_addAssertionWhenWhitelistDisabled() (gas: 233171) AddAssertionWithWhitelist:test_isAdmin() (gas: 953695) -AddDAVerifier:testFuzz_RevertIf_addDAVerifierByUnauthorized(address) (runs: 256, μ: 26949, ~: 26949) -AddDAVerifier:testFuzz_RevertIf_addDAVerifierTwice(address) (runs: 256, μ: 48425, ~: 48425) -AddDAVerifier:test_addDAVerifier(address) (runs: 256, μ: 52844, ~: 52844) +AddDAVerifier:testFuzz_RevertIf_addDAVerifierByUnauthorized(address) (runs: 256, μ: 26861, ~: 26861) +AddDAVerifier:testFuzz_RevertIf_addDAVerifierTwice(address) (runs: 256, μ: 48381, ~: 48381) +AddDAVerifier:test_addDAVerifier(address) (runs: 256, μ: 52778, ~: 52778) AddDAVerifier:test_isAdmin() (gas: 953695) -AddToWhitelist:testFuzz_RevertIf_addToWhitelistByUnauthorized(address) (runs: 256, μ: 30865, ~: 30865) -AddToWhitelist:test_RevertIf_addAlreadyWhitelistedAccount() (gas: 45839) -AddToWhitelist:test_addToWhitelist() (gas: 54605) +AddToWhitelist:testFuzz_RevertIf_addToWhitelistByUnauthorized(address) (runs: 256, μ: 30933, ~: 30933) +AddToWhitelist:test_RevertIf_addAlreadyWhitelistedAccount() (gas: 45842) +AddToWhitelist:test_addToWhitelist() (gas: 54590) AddToWhitelist:test_isAdmin() (gas: 953695) +AdminVerifierAlwaysApproveTest:test_verifyAdminReturnsTrueForAnyRequester() (gas: 10911) +AdminVerifierAlwaysApproveTest:test_verifyAdminReturnsTrueForZeroAddresses() (gas: 7049) +AdminVerifierAlwaysApproveTest:test_verifyAdminReturnsTrueWithData() (gas: 8290) AdminVerifierSuperAdminTest:test_verifyAdminReflectsOwnershipTransfer() (gas: 23022) AdminVerifierSuperAdminTest:test_verifyAdminReturnsFalseForOthers() (gas: 9984) AdminVerifierSuperAdminTest:test_verifyAdminReturnsTrueForOwner() (gas: 10026) @@ -49,20 +52,20 @@ AdminVerifierWhitelistTest:test_excludeRemovesWhitelistEntry() (gas: 56055) AdminVerifierWhitelistTest:test_releaseExclusionByReleaser() (gas: 32588) AdminVerifierWhitelistTest:test_removeFromWhitelist() (gas: 35882) AdminVerifierWhitelistTest:test_verifyAdmin() (gas: 57812) -Batch:testFuzz_batchResetStorage(bytes32) (runs: 256, μ: 171867, ~: 171867) -Batch:test_batch(bytes32,bytes32) (runs: 256, μ: 316333, ~: 316333) +Batch:testFuzz_batchResetStorage(bytes32) (runs: 256, μ: 171911, ~: 171911) +Batch:test_batch(bytes32,bytes32) (runs: 256, μ: 316223, ~: 316223) Batch:test_isAdmin() (gas: 953739) BatchTest:test_batchExecutesAllCalls() (gas: 34598) BatchTest:test_batchIsNotPayable() (gas: 16262) BatchTest:test_batchRevertsWhenInnerCallFails() (gas: 12304) -Constructor:test_assertionTimelockZero() (gas: 98568) +Constructor:test_assertionTimelockZero() (gas: 98888) Constructor:test_isAdmin() (gas: 953761) DAVerifierECDSATest:testFuzz_RevertIf_verifyDAWithWrongProver(bytes32,bytes,uint256) (runs: 256, μ: 18769, ~: 18765) -DAVerifierECDSATest:testFuzz_RevertIf_verifyDAwithInvalidSignature(bytes32,bytes,bytes) (runs: 256, μ: 11413, ~: 11410) +DAVerifierECDSATest:testFuzz_RevertIf_verifyDAwithInvalidSignature(bytes32,bytes,bytes) (runs: 256, μ: 11412, ~: 11410) DAVerifierECDSATest:testFuzz_verifyDA(bytes32,bytes) (runs: 256, μ: 17575, ~: 17571) -DAVerifierOnChainTest:testFuzz_verifyDA_invalidProof(bytes32,bytes,bytes) (runs: 256, μ: 11683, ~: 11673) -DAVerifierOnChainTest:testFuzz_verifyDA_metadataIgnored(bytes,bytes,bytes) (runs: 256, μ: 11626, ~: 11604) -DAVerifierOnChainTest:testFuzz_verifyDA_validProof(bytes,bytes) (runs: 256, μ: 8575, ~: 8563) +DAVerifierOnChainTest:testFuzz_verifyDA_invalidProof(bytes32,bytes,bytes) (runs: 256, μ: 11682, ~: 11671) +DAVerifierOnChainTest:testFuzz_verifyDA_metadataIgnored(bytes,bytes,bytes) (runs: 256, μ: 11626, ~: 11601) +DAVerifierOnChainTest:testFuzz_verifyDA_validProof(bytes,bytes) (runs: 256, μ: 8574, ~: 8563) DAVerifierOnChainTest:test_verifyDA_deterministicPure() (gas: 10415) DAVerifierOnChainTest:test_verifyDA_emptyProof() (gas: 7323) DAVerifierOnChainTest:test_verifyDA_emptyProofMismatch() (gas: 7397) @@ -75,201 +78,212 @@ DAVerifierRegistryTest:test_isRegistered_returnsTrueAfterAdd() (gas: 34462) DAVerifierRegistryTest:test_remove() (gas: 26284) DAVerifierRegistryTest:test_remove_RevertIf_NotRegistered() (gas: 13624) DAVerifierRegistryTest:test_remove_emitsEvent() (gas: 28380) -DeployCoreWithStagingIntegrationTest:test_AddAssertionWithOnChainDAVerifierOnBothOracles() (gas: 393263) -DeployCoreWithStagingIntegrationTest:test_AddToWhitelistOnBothOracles() (gas: 91286) +DeployAdminVerifiersTest:test_RevertIf_coreDeployWhitelistVerifierWithoutAdmin() (gas: 10651341) +DeployAdminVerifiersTest:test_RevertIf_testingScriptAddsVerifiersWithoutStateOracle() (gas: 2918354) +DeployAdminVerifiersTest:test_RevertIf_testingScriptDeploysSuperAdminVerifierWithoutAdmin() (gas: 2691075) +DeployAdminVerifiersTest:test_RevertIf_testingScriptEntrypointsRunOutsideTestingDeployment() (gas: 2557920) +DeployAdminVerifiersTest:test_coreDeployAdminVerifiersAddsOnlyProductionVerifiersToStateOracle() (gas: 17766308) +DeployAdminVerifiersTest:test_testingScriptAllowsEntrypointsInTestingDeployment() (gas: 2789938) +DeployAdminVerifiersTest:test_testingScriptDeploysAndAddsTestVerifiersToStateOracle() (gas: 8796534) +DeployCoreWithStagingIntegrationTest:test_AddAssertionWithOnChainDAVerifierOnBothOracles() (gas: 393189) +DeployCoreWithStagingIntegrationTest:test_AddToWhitelistOnBothOracles() (gas: 91300) DeployCoreWithStagingIntegrationTest:test_BothOraclesDeployed() (gas: 5105) DeployCoreWithStagingIntegrationTest:test_BothOraclesHaveBothDAVerifiers() (gas: 41415) -DeployCoreWithStagingIntegrationTest:test_BothOraclesShareSameAdminVerifier() (gas: 29848) +DeployCoreWithStagingIntegrationTest:test_BothOraclesShareSameAdminVerifier() (gas: 29804) DeployCoreWithStagingIntegrationTest:test_ECDSAVerifierIsSharedAcrossOracles() (gas: 29871) -DeployCoreWithStagingIntegrationTest:test_FullWorkflow_WhitelistAndRegisterOnBothOracles() (gas: 281775) +DeployCoreWithStagingIntegrationTest:test_FullWorkflow_WhitelistAndRegisterOnBothOracles() (gas: 281701) DeployCoreWithStagingIntegrationTest:test_OnChainVerifierIsSharedAcrossOracles() (gas: 29849) DeployCoreWithStagingIntegrationTest:test_OraclesHaveDifferentConfigs() (gas: 29364) DeployCoreWithStagingIntegrationTest:test_PersistentAccountsFunded() (gas: 8375) -DeployCoreWithStagingIntegrationTest:test_RegisterContractOnBothOracles() (gas: 268796) -DisableWhitelist:testFuzz_RevertIf_disableWhitelistByUnauthorized(address) (runs: 256, μ: 22700, ~: 22700) -DisableWhitelist:test_RevertIf_disableAlreadyDisabledWhitelist() (gas: 25195) -DisableWhitelist:test_disableWhitelist() (gas: 28255) +DeployCoreWithStagingIntegrationTest:test_RegisterContractOnBothOracles() (gas: 268766) +DeployCoreWithStagingScriptIntegrationTest:test_CompleteDeterministicDeploymentSupportsTestingConfiguration() (gas: 24010955) +DeployWizardCreateXIntegrationTest:test_TestingDeploymentUsesCreateXForEveryContract() (gas: 11910662) +DisableWhitelist:testFuzz_RevertIf_disableWhitelistByUnauthorized(address) (runs: 256, μ: 22634, ~: 22634) +DisableWhitelist:test_RevertIf_disableAlreadyDisabledWhitelist() (gas: 25151) +DisableWhitelist:test_disableWhitelist() (gas: 28189) DisableWhitelist:test_isAdmin() (gas: 953761) -DisableWhitelist:test_nonWhitelistedUserWhenDisabled() (gas: 30133) -DisableWhitelist:test_whitelistedUserAfterReenabling() (gas: 60127) -DisableWhitelist:test_whitelistedUserWhenDisabled() (gas: 59811) -EnableWhitelist:testFuzz_RevertIf_enableWhitelistByUnauthorized(address) (runs: 256, μ: 22721, ~: 22721) -EnableWhitelist:test_RevertIf_enableAlreadyEnabledWhitelist() (gas: 25245) -EnableWhitelist:test_enableWhitelist() (gas: 28214) +DisableWhitelist:test_nonWhitelistedUserWhenDisabled() (gas: 30089) +DisableWhitelist:test_whitelistedUserAfterReenabling() (gas: 60090) +DisableWhitelist:test_whitelistedUserWhenDisabled() (gas: 59774) +EnableWhitelist:testFuzz_RevertIf_enableWhitelistByUnauthorized(address) (runs: 256, μ: 22655, ~: 22655) +EnableWhitelist:test_RevertIf_enableAlreadyEnabledWhitelist() (gas: 25201) +EnableWhitelist:test_enableWhitelist() (gas: 28148) EnableWhitelist:test_isAdmin() (gas: 953761) -GrantGuardianAdminRole:testFuzz_RevertIf_nonOwnerGrantsGuardianAdminRole(address) (runs: 256, μ: 18745, ~: 18745) +GrantGuardianAdminRole:testFuzz_RevertIf_nonOwnerGrantsGuardianAdminRole(address) (runs: 256, μ: 18723, ~: 18723) GrantGuardianAdminRole:test_isAdmin() (gas: 953695) -GrantGuardianAdminRole:test_ownerCanGrantGuardianAdminRole() (gas: 50860) -GrantGuardianRole:testFuzz_RevertIf_nonGuardianAdminGrantsGuardianRole(address) (runs: 256, μ: 20748, ~: 20748) -GrantGuardianRole:test_guardianAdminCanGrantGuardianRole() (gas: 51186) +GrantGuardianAdminRole:test_ownerCanGrantGuardianAdminRole() (gas: 50926) +GrantGuardianRole:testFuzz_RevertIf_nonGuardianAdminGrantsGuardianRole(address) (runs: 256, μ: 20814, ~: 20814) +GrantGuardianRole:test_guardianAdminCanGrantGuardianRole() (gas: 51142) GrantGuardianRole:test_isAdmin() (gas: 953761) -GrantOperatorAdminRole:testFuzz_RevertIf_nonOwnerGrantsOperatorAdminRole(address) (runs: 256, μ: 18720, ~: 18720) +GrantOperatorAdminRole:testFuzz_RevertIf_nonOwnerGrantsOperatorAdminRole(address) (runs: 256, μ: 18698, ~: 18698) GrantOperatorAdminRole:test_isAdmin() (gas: 953739) -GrantOperatorAdminRole:test_ownerCanGrantOperatorAdminRole() (gas: 50814) -GrantOperatorRole:testFuzz_RevertIf_nonOperatorAdminGrantsOperatorRole(address) (runs: 256, μ: 28131, ~: 28131) -GrantOperatorRole:testFuzz_RevertIf_nonOperatorAdminGrantsOperatorRoleUsingHelper(address) (runs: 256, μ: 24026, ~: 24026) +GrantOperatorAdminRole:test_ownerCanGrantOperatorAdminRole() (gas: 50882) +GrantOperatorRole:testFuzz_RevertIf_nonOperatorAdminGrantsOperatorRole(address) (runs: 256, μ: 28243, ~: 28243) +GrantOperatorRole:testFuzz_RevertIf_nonOperatorAdminGrantsOperatorRoleUsingHelper(address) (runs: 256, μ: 24071, ~: 24071) GrantOperatorRole:test_isAdmin() (gas: 953783) -GrantOperatorRole:test_ownerCanGrantOperatorRole() (gas: 56290) -GrantOperatorRole:test_ownerCanGrantOperatorRoleUsingHelper() (gas: 51069) -GrantOperatorRole:test_stateOracleAdminHasDefaultAdminRole() (gas: 16070) -GuardianAdminCanManageGuardians:testFuzz_RevertIf_nonGuardianAdminGrantsGuardianRole(address) (runs: 256, μ: 21640, ~: 21640) -GuardianAdminCanManageGuardians:testFuzz_RevertIf_nonGuardianAdminRevokesGuardianRole(address) (runs: 256, μ: 51968, ~: 51968) -GuardianAdminCanManageGuardians:test_guardianAdminCanGrantGuardianRole() (gas: 51908) -GuardianAdminCanManageGuardians:test_guardianAdminCanRevokeGuardianRole() (gas: 42415) +GrantOperatorRole:test_ownerCanGrantOperatorRole() (gas: 56447) +GrantOperatorRole:test_ownerCanGrantOperatorRoleUsingHelper() (gas: 51159) +GrantOperatorRole:test_stateOracleAdminHasDefaultAdminRole() (gas: 16114) +GuardianAdminCanManageGuardians:testFuzz_RevertIf_nonGuardianAdminGrantsGuardianRole(address) (runs: 256, μ: 21706, ~: 21706) +GuardianAdminCanManageGuardians:testFuzz_RevertIf_nonGuardianAdminRevokesGuardianRole(address) (runs: 256, μ: 52101, ~: 52101) +GuardianAdminCanManageGuardians:test_guardianAdminCanGrantGuardianRole() (gas: 51864) +GuardianAdminCanManageGuardians:test_guardianAdminCanRevokeGuardianRole() (gas: 42433) GuardianAdminCanManageGuardians:test_isAdmin() (gas: 953695) -GuardianEmergencyActions:test_guardianCanRemoveAssertion() (gas: 271169) -GuardianEmergencyActions:test_guardianCanRevokeManager() (gas: 181949) -GuardianEmergencyActions:test_guardianCannotAddAdminVerifier() (gas: 264624) -GuardianEmergencyActions:test_guardianCannotAddDAVerifier() (gas: 20692) -GuardianEmergencyActions:test_guardianCannotAddToWhitelist() (gas: 27789) -GuardianEmergencyActions:test_guardianCannotDisableWhitelist() (gas: 19939) -GuardianEmergencyActions:test_guardianCannotEnableWhitelist() (gas: 30615) -GuardianEmergencyActions:test_guardianCannotRemoveAdminVerifier() (gas: 22749) -GuardianEmergencyActions:test_guardianCannotRemoveDAVerifier() (gas: 22794) -GuardianEmergencyActions:test_guardianCannotRemoveFromWhitelist() (gas: 54997) -GuardianEmergencyActions:test_guardianCannotSetMaxAssertionsPerAA() (gas: 20420) +GuardianEmergencyActions:test_guardianCanRemoveAssertion() (gas: 271110) +GuardianEmergencyActions:test_guardianCanRevokeManager() (gas: 181934) +GuardianEmergencyActions:test_guardianCannotAddAdminVerifier() (gas: 264666) +GuardianEmergencyActions:test_guardianCannotAddDAVerifier() (gas: 20648) +GuardianEmergencyActions:test_guardianCannotAddToWhitelist() (gas: 27834) +GuardianEmergencyActions:test_guardianCannotDisableWhitelist() (gas: 19895) +GuardianEmergencyActions:test_guardianCannotEnableWhitelist() (gas: 30549) +GuardianEmergencyActions:test_guardianCannotRemoveAdminVerifier() (gas: 22705) +GuardianEmergencyActions:test_guardianCannotRemoveDAVerifier() (gas: 22750) +GuardianEmergencyActions:test_guardianCannotRemoveFromWhitelist() (gas: 55049) +GuardianEmergencyActions:test_guardianCannotSetMaxAssertionsPerAA() (gas: 20398) GuardianEmergencyActions:test_isAdmin() (gas: 953761) GuardianRoleBase:test_isAdmin() (gas: 953761) GuardianRoleBase:test_isAdmin() (gas: 953761) -Initialize:test_RevertIf_alreadyInitialized() (gas: 21222) -Initialize:test_RevertIf_initializeNonProxy() (gas: 4097793) -Initialize:test_isAdmin() (gas: 953761) -InitializeWhitelist:test_initialNonWhitelistedUser() (gas: 19126) -InitializeWhitelist:test_initialWhitelistState() (gas: 13110) +Initialize:test_RevertIf_alreadyInitialized() (gas: 21244) +Initialize:test_RevertIf_initializeNonProxy() (gas: 4293371) +Initialize:test_initializeWithWhitelistDisabled() (gas: 5459554) +Initialize:test_initializeWithWhitelistEnabledAndInitialAccount() (gas: 5496038) +Initialize:test_isAdmin() (gas: 953783) +InitializeWhitelist:test_initialNonWhitelistedUser() (gas: 19104) +InitializeWhitelist:test_initialWhitelistState() (gas: 13088) InitializeWhitelist:test_isAdmin() (gas: 953761) -OperatorAdminCanManageOperators:testFuzz_RevertIf_nonOperatorAdminGrantsOperatorRole(address) (runs: 256, μ: 24963, ~: 24963) -OperatorAdminCanManageOperators:testFuzz_RevertIf_nonOperatorAdminRevokesOperatorRole(address) (runs: 256, μ: 55290, ~: 55290) +OperatorAdminCanManageOperators:testFuzz_RevertIf_nonOperatorAdminGrantsOperatorRole(address) (runs: 256, μ: 25008, ~: 25008) +OperatorAdminCanManageOperators:testFuzz_RevertIf_nonOperatorAdminRevokesOperatorRole(address) (runs: 256, μ: 55313, ~: 55313) OperatorAdminCanManageOperators:test_isAdmin() (gas: 953739) -OperatorAdminCanManageOperators:test_operatorAdminCanGrantOperatorRole() (gas: 51812) -OperatorAdminCanManageOperators:test_operatorAdminCanRevokeOperatorRole() (gas: 42391) -OperatorAdminCanManageOperators:test_operatorAdminCannotManageWhitelist() (gas: 20800) -OperatorAdminCanManageOperators:test_operatorAdminCannotRemoveAssertionByOwner() (gas: 260112) -OperatorAdminCanManageOperators:test_operatorAdminCannotRevokeManager() (gas: 195238) -OperatorCanManageWhitelist:testFuzz_RevertIf_nonOperatorAddsToWhitelist(address) (runs: 256, μ: 31801, ~: 31801) -OperatorCanManageWhitelist:testFuzz_RevertIf_nonOperatorRemovesFromWhitelist(address) (runs: 256, μ: 60955, ~: 60955) +OperatorAdminCanManageOperators:test_operatorAdminCanGrantOperatorRole() (gas: 51902) +OperatorAdminCanManageOperators:test_operatorAdminCanRevokeOperatorRole() (gas: 42445) +OperatorAdminCanManageOperators:test_operatorAdminCannotManageWhitelist() (gas: 20845) +OperatorAdminCanManageOperators:test_operatorAdminCannotRemoveAssertionByOwner() (gas: 260053) +OperatorAdminCanManageOperators:test_operatorAdminCannotRevokeManager() (gas: 195223) +OperatorCanManageWhitelist:testFuzz_RevertIf_nonOperatorAddsToWhitelist(address) (runs: 256, μ: 31869, ~: 31869) +OperatorCanManageWhitelist:testFuzz_RevertIf_nonOperatorRemovesFromWhitelist(address) (runs: 256, μ: 61030, ~: 61030) OperatorCanManageWhitelist:test_isAdmin() (gas: 953783) -OperatorCanManageWhitelist:test_operatorCanAddToWhitelist() (gas: 51900) -OperatorCanManageWhitelist:test_operatorCanRemoveFromWhitelist() (gas: 41553) +OperatorCanManageWhitelist:test_operatorCanAddToWhitelist() (gas: 51885) +OperatorCanManageWhitelist:test_operatorCanRemoveFromWhitelist() (gas: 41524) OperatorRoleBase:test_isAdmin() (gas: 953761) OwnableTest:test_isAdmin() (gas: 953717) -OwnableTest:test_newOwnerCanGrantRolesAsOwner() (gas: 229628) -OwnableTest:test_ownerIsInitializerOnProxy() (gas: 13577) -OwnableTest:test_ownerIsZeroOnImplementation() (gas: 3833400) -OwnableTest:test_transferOwnership() (gas: 230046) +OwnableTest:test_newOwnerCanGrantRolesAsOwner() (gas: 229518) +OwnableTest:test_ownerIsInitializerOnProxy() (gas: 13555) +OwnableTest:test_ownerIsZeroOnImplementation() (gas: 4028956) +OwnableTest:test_transferOwnership() (gas: 230222) OwnerOnlyFunctionsRemainProtected:test_isAdmin() (gas: 953805) -OwnerOnlyFunctionsRemainProtected:test_operatorCannotAddAdminVerifier() (gas: 264602) -OwnerOnlyFunctionsRemainProtected:test_operatorCannotAddDAVerifier() (gas: 20650) -OwnerOnlyFunctionsRemainProtected:test_operatorCannotDisableWhitelist() (gas: 19961) -OwnerOnlyFunctionsRemainProtected:test_operatorCannotEnableWhitelist() (gas: 30658) -OwnerOnlyFunctionsRemainProtected:test_operatorCannotRemoveAdminVerifier() (gas: 22749) -OwnerOnlyFunctionsRemainProtected:test_operatorCannotRemoveAssertionByOwner() (gas: 260107) -OwnerOnlyFunctionsRemainProtected:test_operatorCannotRemoveDAVerifier() (gas: 22748) -OwnerOnlyFunctionsRemainProtected:test_operatorCannotRevokeManager() (gas: 195232) -OwnerOnlyFunctionsRemainProtected:test_operatorCannotSetMaxAssertionsPerAA() (gas: 20376) +OwnerOnlyFunctionsRemainProtected:test_operatorCannotAddAdminVerifier() (gas: 264644) +OwnerOnlyFunctionsRemainProtected:test_operatorCannotAddDAVerifier() (gas: 20606) +OwnerOnlyFunctionsRemainProtected:test_operatorCannotDisableWhitelist() (gas: 19917) +OwnerOnlyFunctionsRemainProtected:test_operatorCannotEnableWhitelist() (gas: 30592) +OwnerOnlyFunctionsRemainProtected:test_operatorCannotRemoveAdminVerifier() (gas: 22705) +OwnerOnlyFunctionsRemainProtected:test_operatorCannotRemoveAssertionByOwner() (gas: 260048) +OwnerOnlyFunctionsRemainProtected:test_operatorCannotRemoveDAVerifier() (gas: 22704) +OwnerOnlyFunctionsRemainProtected:test_operatorCannotRevokeManager() (gas: 195217) +OwnerOnlyFunctionsRemainProtected:test_operatorCannotSetMaxAssertionsPerAA() (gas: 20354) ProxyHelper:test_isAdmin() (gas: 953783) -Register:testFuzz_RevertIf_registerAssertionAdopterAdminVerifierNotAdded() (gas: 264776) -Register:testFuzz_RevertIf_registerByUnauthorized(address) (runs: 256, μ: 142245, ~: 142245) -Register:test_RevertIf_registerAssertionAdopterTwice() (gas: 167308) -Register:test_expectAssertionAdopterAdded() (gas: 162235) +Register:testFuzz_RevertIf_registerAssertionAdopterAdminVerifierNotAdded() (gas: 264754) +Register:testFuzz_RevertIf_registerByUnauthorized(address) (runs: 256, μ: 142213, ~: 142223) +Register:test_RevertIf_registerAssertionAdopterTwice() (gas: 167264) +Register:test_expectAssertionAdopterAdded() (gas: 162213) Register:test_isAdmin() (gas: 953695) -Register:test_registerByOwner() (gas: 159694) -RegisterAssertionAdopterWithWhitelist:testFuzz_RevertIf_registerByNonWhitelistedUser(address) (runs: 256, μ: 126516, ~: 126516) +Register:test_registerByOwner() (gas: 159672) +RegisterAssertionAdopterWithWhitelist:testFuzz_RevertIf_registerByNonWhitelistedUser(address) (runs: 256, μ: 126494, ~: 126494) RegisterAssertionAdopterWithWhitelist:test_isAdmin() (gas: 953761) -RegisterAssertionAdopterWithWhitelist:test_registerByNonWhitelistedUserWhenDisabled() (gas: 168714) -RegisterAssertionAdopterWithWhitelist:test_registerByWhitelistedUser() (gas: 189529) -RemoveAdminVerifier:testFuzz_RevertIf_removeAdminVerifierByUnauthorized(address) (runs: 256, μ: 303005, ~: 303005) -RemoveAdminVerifier:testFuzz_RevertIf_removeAdminVerifierNotRegistered(address) (runs: 256, μ: 22963, ~: 22963) +RegisterAssertionAdopterWithWhitelist:test_registerByNonWhitelistedUserWhenDisabled() (gas: 168670) +RegisterAssertionAdopterWithWhitelist:test_registerByWhitelistedUser() (gas: 189514) +RemoveAdminVerifier:testFuzz_RevertIf_removeAdminVerifierByUnauthorized(address) (runs: 256, μ: 302981, ~: 302981) +RemoveAdminVerifier:testFuzz_RevertIf_removeAdminVerifierNotRegistered(address) (runs: 256, μ: 22941, ~: 22941) RemoveAdminVerifier:test_isAdmin() (gas: 953695) -RemoveAdminVerifier:test_removeAdminVerifier() (gas: 275567) -RemoveAssertion:testFuzz_RevertIf_removeAssertionAlreadyRemoved(bytes32) (runs: 256, μ: 254138, ~: 254138) -RemoveAssertion:testFuzz_RevertIf_removeAssertionByUnauthorized(bytes32,address) (runs: 256, μ: 240379, ~: 240379) -RemoveAssertion:testFuzz_RevertIf_removeAssertionByUnauthorizedAdmin(bytes32,address) (runs: 256, μ: 252869, ~: 252869) -RemoveAssertion:testFuzz_RevertIf_removeNonExistentAssertion(bytes32) (runs: 256, μ: 164568, ~: 164568) -RemoveAssertion:testFuzz_removeAssertion(bytes32) (runs: 256, μ: 250783, ~: 250783) -RemoveAssertion:testFuzz_removeAssertionByAdmin(bytes32) (runs: 256, μ: 256811, ~: 256811) -RemoveAssertion:test_expectAssertionRemoved(bytes32) (runs: 256, μ: 247151, ~: 247151) +RemoveAdminVerifier:test_removeAdminVerifier() (gas: 275609) +RemoveAssertion:testFuzz_RevertIf_removeAssertionAlreadyRemoved(bytes32) (runs: 256, μ: 254251, ~: 254251) +RemoveAssertion:testFuzz_RevertIf_removeAssertionByUnauthorized(bytes32,address) (runs: 256, μ: 240313, ~: 240313) +RemoveAssertion:testFuzz_RevertIf_removeAssertionByUnauthorizedAdmin(bytes32,address) (runs: 256, μ: 252759, ~: 252759) +RemoveAssertion:testFuzz_RevertIf_removeNonExistentAssertion(bytes32) (runs: 256, μ: 164524, ~: 164524) +RemoveAssertion:testFuzz_removeAssertion(bytes32) (runs: 256, μ: 250717, ~: 250717) +RemoveAssertion:testFuzz_removeAssertionByAdmin(bytes32) (runs: 256, μ: 256723, ~: 256723) +RemoveAssertion:test_expectAssertionRemoved(bytes32) (runs: 256, μ: 247085, ~: 247085) RemoveAssertion:test_isAdmin() (gas: 953761) RemoveAssertionWithWhitelist:test_isAdmin() (gas: 953695) -RemoveAssertionWithWhitelist:test_removeAssertionByNonWhitelistedManager() (gas: 250085) -RemoveDAVerifier:testFuzz_RevertIf_removeDAVerifierByUnauthorized(address) (runs: 256, μ: 59097, ~: 59097) -RemoveDAVerifier:testFuzz_RevertIf_removeDAVerifierNotRegistered(address) (runs: 256, μ: 23005, ~: 23005) +RemoveAssertionWithWhitelist:test_removeAssertionByNonWhitelistedManager() (gas: 250004) +RemoveDAVerifier:testFuzz_RevertIf_removeDAVerifierByUnauthorized(address) (runs: 256, μ: 58965, ~: 58965) +RemoveDAVerifier:testFuzz_RevertIf_removeDAVerifierNotRegistered(address) (runs: 256, μ: 22983, ~: 22983) RemoveDAVerifier:test_isAdmin() (gas: 953695) -RemoveDAVerifier:test_removeDAVerifier() (gas: 39256) -RemoveFromWhitelist:testFuzz_RevertIf_removeFromWhitelistByUnauthorized(address) (runs: 256, μ: 60107, ~: 60107) -RemoveFromWhitelist:test_RevertIf_removeNonWhitelistedAccount() (gas: 21207) +RemoveDAVerifier:test_removeDAVerifier() (gas: 39186) +RemoveFromWhitelist:testFuzz_RevertIf_removeFromWhitelistByUnauthorized(address) (runs: 256, μ: 60182, ~: 60182) +RemoveFromWhitelist:test_RevertIf_removeNonWhitelistedAccount() (gas: 21185) RemoveFromWhitelist:test_isAdmin() (gas: 953761) -RemoveFromWhitelist:test_removeFromWhitelist() (gas: 43248) +RemoveFromWhitelist:test_removeFromWhitelist() (gas: 43219) RenounceOwnershipTest:test_isAdmin() (gas: 953695) -RenounceOwnershipTest:test_renounceOwnershipMaintainsInvariant() (gas: 107828) -ResetStorage:testFuzz_RevertIf_resetStorageByUnauthorized(bytes32,address) (runs: 256, μ: 164399, ~: 164399) -ResetStorage:testFuzz_RevertIf_resetStorageForUnregisteredAdopter(address,bytes32,address) (runs: 256, μ: 16873, ~: 16873) -ResetStorage:testFuzz_resetStorage(bytes32) (runs: 256, μ: 175835, ~: 175835) +RenounceOwnershipTest:test_renounceOwnershipMaintainsInvariant() (gas: 107935) +ResetStorage:testFuzz_RevertIf_resetStorageByUnauthorized(bytes32,address) (runs: 256, μ: 164443, ~: 164443) +ResetStorage:testFuzz_RevertIf_resetStorageForUnregisteredAdopter(address,bytes32,address) (runs: 256, μ: 16939, ~: 16939) +ResetStorage:testFuzz_resetStorage(bytes32) (runs: 256, μ: 175946, ~: 175946) ResetStorage:test_isAdmin() (gas: 953783) -ResetStorage:test_resetStorageAllowsZeroStorageKey() (gas: 168440) -RevokeGuardianAdminRole:testFuzz_RevertIf_nonOwnerRevokesGuardianAdminRole(address) (runs: 256, μ: 18701, ~: 18701) +ResetStorage:test_resetStorageAllowsZeroStorageKey() (gas: 168484) +RevokeGuardianAdminRole:testFuzz_RevertIf_nonOwnerRevokesGuardianAdminRole(address) (runs: 256, μ: 18766, ~: 18766) RevokeGuardianAdminRole:test_isAdmin() (gas: 953739) -RevokeGuardianAdminRole:test_ownerCanRevokeGuardianAdminRole() (gas: 29640) -RevokeGuardianRole:testFuzz_RevertIf_nonGuardianAdminRevokesGuardianRole(address) (runs: 256, μ: 20720, ~: 20720) -RevokeGuardianRole:test_guardianAdminCanRevokeGuardianRole() (gas: 29892) +RevokeGuardianAdminRole:test_ownerCanRevokeGuardianAdminRole() (gas: 29793) +RevokeGuardianRole:testFuzz_RevertIf_nonGuardianAdminRevokesGuardianRole(address) (runs: 256, μ: 20853, ~: 20853) +RevokeGuardianRole:test_guardianAdminCanRevokeGuardianRole() (gas: 29915) RevokeGuardianRole:test_isAdmin() (gas: 953695) -RevokeManager:testFuzz_RevertIf_revokeManagerByUnauthorized(address) (runs: 256, μ: 176360, ~: 176360) -RevokeManager:testFuzz_revokeManager(address) (runs: 256, μ: 171606, ~: 171606) -RevokeManager:test_RevertIf_revokeManagerOfNonExistentAdopter() (gas: 129205) +RevokeManager:testFuzz_RevertIf_revokeManagerByUnauthorized(address) (runs: 256, μ: 176294, ~: 176294) +RevokeManager:testFuzz_revokeManager(address) (runs: 256, μ: 171540, ~: 171540) +RevokeManager:test_RevertIf_revokeManagerOfNonExistentAdopter() (gas: 129183) RevokeManager:test_isAdmin() (gas: 953695) -RevokeOperatorAdminRole:testFuzz_RevertIf_nonOwnerRevokesOperatorAdminRole(address) (runs: 256, μ: 18678, ~: 18678) +RevokeOperatorAdminRole:testFuzz_RevertIf_nonOwnerRevokesOperatorAdminRole(address) (runs: 256, μ: 18745, ~: 18745) RevokeOperatorAdminRole:test_isAdmin() (gas: 953739) -RevokeOperatorAdminRole:test_ownerCanRevokeOperatorAdminRole() (gas: 29662) -RevokeOperatorRole:testFuzz_RevertIf_nonOperatorAdminRevokesOperatorRole(address) (runs: 256, μ: 28131, ~: 28131) -RevokeOperatorRole:testFuzz_RevertIf_nonOperatorAdminRevokesOperatorRoleUsingHelper(address) (runs: 256, μ: 23977, ~: 23977) +RevokeOperatorAdminRole:test_ownerCanRevokeOperatorAdminRole() (gas: 29819) +RevokeOperatorRole:testFuzz_RevertIf_nonOperatorAdminRevokesOperatorRole(address) (runs: 256, μ: 28221, ~: 28221) +RevokeOperatorRole:testFuzz_RevertIf_nonOperatorAdminRevokesOperatorRoleUsingHelper(address) (runs: 256, μ: 24000, ~: 24000) RevokeOperatorRole:test_isAdmin() (gas: 953783) -RevokeOperatorRole:test_ownerCanRevokeOperatorRole() (gas: 35064) -RevokeOperatorRole:test_ownerCanRevokeOperatorRoleUsingHelper() (gas: 29907) +RevokeOperatorRole:test_ownerCanRevokeOperatorRole() (gas: 35199) +RevokeOperatorRole:test_ownerCanRevokeOperatorRoleUsingHelper() (gas: 29975) RevokeOperatorRoleBase:test_isAdmin() (gas: 953761) -SetMaxAssertionsPerAA:testFuzz_RevertIf_setMaxAssertionsPerAAByUnauthorized(uint16,address) (runs: 256, μ: 26703, ~: 26703) -SetMaxAssertionsPerAA:test_AddAssertionsThenLowerMaxAndRevertOnAdd() (gas: 312177) +SetMaxAssertionsPerAA:testFuzz_RevertIf_setMaxAssertionsPerAAByUnauthorized(uint16,address) (runs: 256, μ: 26637, ~: 26637) +SetMaxAssertionsPerAA:test_AddAssertionsThenLowerMaxAndRevertOnAdd() (gas: 312089) SetMaxAssertionsPerAA:test_isAdmin() (gas: 953761) -SetMaxAssertionsPerAA:test_setMaxAssertionsPerAA(uint16) (runs: 256, μ: 23728, ~: 24230) +SetMaxAssertionsPerAA:test_setMaxAssertionsPerAA(uint16) (runs: 256, μ: 23623, ~: 24230) StateOracleAccessControlBase:test_isAdmin() (gas: 953761) StateOracleBase:test_isAdmin() (gas: 953761) -StateOracleOwnerECDSATest:testFuzz_addAssertionWithValidProof(bytes32) (runs: 256, μ: 93774, ~: 93774) -StateOracleOwnerECDSATest:test_RevertIf_addAssertionWithInvalidProof() (gas: 42527) -StateOracleOwnerECDSATest:test_addAndRemoveAssertion() (gas: 113950) -StateOracleOwnerECDSATest:test_addAssertionWithValidProof() (gas: 100965) -StateOracleOwnerECDSATest:test_addMultipleAssertions() (gas: 141263) -StateOracleOwnerECDSATest:test_assertionAddedEventEmitted() (gas: 98593) +StateOracleOwnerECDSATest:testFuzz_addAssertionWithValidProof(bytes32) (runs: 256, μ: 93752, ~: 93752) +StateOracleOwnerECDSATest:test_RevertIf_addAssertionWithInvalidProof() (gas: 42505) +StateOracleOwnerECDSATest:test_addAndRemoveAssertion() (gas: 113906) +StateOracleOwnerECDSATest:test_addAssertionWithValidProof() (gas: 100943) +StateOracleOwnerECDSATest:test_addMultipleAssertions() (gas: 141286) +StateOracleOwnerECDSATest:test_assertionAddedEventEmitted() (gas: 98571) StateOracleOwnerECDSATest:test_isAdmin() (gas: 953695) -StateOracleOwnerOnChainTest:testFuzz_addAssertionWithValidProof(bytes32) (runs: 256, μ: 88319, ~: 88319) -StateOracleOwnerOnChainTest:test_RevertIf_addAssertionWithInvalidProof() (gas: 39504) -StateOracleOwnerOnChainTest:test_addAndRemoveAssertion() (gas: 108495) -StateOracleOwnerOnChainTest:test_addAssertionWithValidProof() (gas: 95510) -StateOracleOwnerOnChainTest:test_addMultipleAssertions() (gas: 130356) -StateOracleOwnerOnChainTest:test_assertionAddedEventEmitted() (gas: 92620) +StateOracleOwnerOnChainTest:testFuzz_addAssertionWithValidProof(bytes32) (runs: 256, μ: 88297, ~: 88297) +StateOracleOwnerOnChainTest:test_RevertIf_addAssertionWithInvalidProof() (gas: 39482) +StateOracleOwnerOnChainTest:test_addAndRemoveAssertion() (gas: 108451) +StateOracleOwnerOnChainTest:test_addAssertionWithValidProof() (gas: 95488) +StateOracleOwnerOnChainTest:test_addMultipleAssertions() (gas: 130379) +StateOracleOwnerOnChainTest:test_assertionAddedEventEmitted() (gas: 92598) StateOracleOwnerOnChainTest:test_isAdmin() (gas: 953695) -StateOracleWhitelistECDSATest:testFuzz_addAssertionWithValidProof(bytes32) (runs: 256, μ: 93774, ~: 93774) -StateOracleWhitelistECDSATest:test_RevertIf_addAssertionWithInvalidProof() (gas: 42527) -StateOracleWhitelistECDSATest:test_addAndRemoveAssertion() (gas: 113950) -StateOracleWhitelistECDSATest:test_addAssertionWithValidProof() (gas: 100965) -StateOracleWhitelistECDSATest:test_addMultipleAssertions() (gas: 141263) -StateOracleWhitelistECDSATest:test_assertionAddedEventEmitted() (gas: 98593) +StateOracleWhitelistECDSATest:testFuzz_addAssertionWithValidProof(bytes32) (runs: 256, μ: 93752, ~: 93752) +StateOracleWhitelistECDSATest:test_RevertIf_addAssertionWithInvalidProof() (gas: 42505) +StateOracleWhitelistECDSATest:test_addAndRemoveAssertion() (gas: 113906) +StateOracleWhitelistECDSATest:test_addAssertionWithValidProof() (gas: 100943) +StateOracleWhitelistECDSATest:test_addMultipleAssertions() (gas: 141286) +StateOracleWhitelistECDSATest:test_assertionAddedEventEmitted() (gas: 98571) StateOracleWhitelistECDSATest:test_isAdmin() (gas: 953695) -StateOracleWhitelistOnChainTest:testFuzz_addAssertionWithValidProof(bytes32) (runs: 256, μ: 88319, ~: 88319) -StateOracleWhitelistOnChainTest:test_RevertIf_addAssertionWithInvalidProof() (gas: 39504) -StateOracleWhitelistOnChainTest:test_addAndRemoveAssertion() (gas: 108495) -StateOracleWhitelistOnChainTest:test_addAssertionWithValidProof() (gas: 95510) -StateOracleWhitelistOnChainTest:test_addMultipleAssertions() (gas: 130356) -StateOracleWhitelistOnChainTest:test_assertionAddedEventEmitted() (gas: 92620) +StateOracleWhitelistOnChainTest:testFuzz_addAssertionWithValidProof(bytes32) (runs: 256, μ: 88297, ~: 88297) +StateOracleWhitelistOnChainTest:test_RevertIf_addAssertionWithInvalidProof() (gas: 39482) +StateOracleWhitelistOnChainTest:test_addAndRemoveAssertion() (gas: 108451) +StateOracleWhitelistOnChainTest:test_addAssertionWithValidProof() (gas: 95488) +StateOracleWhitelistOnChainTest:test_addMultipleAssertions() (gas: 130379) +StateOracleWhitelistOnChainTest:test_assertionAddedEventEmitted() (gas: 92598) StateOracleWhitelistOnChainTest:test_isAdmin() (gas: 953695) -StateOracleWithDAVerifierECDSATest:testFuzz_RevertIf_addAssertionWithWrongProver(bytes32,bytes,uint256) (runs: 256, μ: 42675, ~: 42632) -StateOracleWithDAVerifierECDSATest:testFuzz_addAssertionWithECDSAProof(bytes32,bytes) (runs: 256, μ: 91496, ~: 91306) +StateOracleWithDAVerifierECDSATest:testFuzz_RevertIf_addAssertionWithWrongProver(bytes32,bytes,uint256) (runs: 256, μ: 42658, ~: 42610) +StateOracleWithDAVerifierECDSATest:testFuzz_addAssertionWithECDSAProof(bytes32,bytes) (runs: 256, μ: 91471, ~: 91284) StateOracleWithDAVerifierECDSATest:test_isAdmin() (gas: 953739) StorageIntegrity:test_isAdmin() (gas: 953695) -StorageIntegrity:test_storageIntegrity() (gas: 27097) -StorageIntegrity:test_storageIntegrityAfterDAVerifierRemoval() (gas: 269424) -StorageIntegrity:test_storageIntegrityAfterOperations() (gas: 279138) +StorageIntegrity:test_storageIntegrity() (gas: 27075) +StorageIntegrity:test_storageIntegrityAfterDAVerifierRemoval() (gas: 269292) +StorageIntegrity:test_storageIntegrityAfterOperations() (gas: 279028) TransferManagementBase:test_isAdmin() (gas: 953761) -TransferManager:testFuzz_RevertIf_transferManagerByUnauthorized(address,address) (runs: 256, μ: 203561, ~: 203561) -TransferManager:testFuzz_changePendingManager(address,address) (runs: 256, μ: 199181, ~: 199181) -TransferManager:testFuzz_transferManager(address) (runs: 256, μ: 194926, ~: 194926) -TransferManager:test_RevertIf_transferManagerToZeroAddress() (gas: 169304) +TransferManager:testFuzz_RevertIf_transferManagerByUnauthorized(address,address) (runs: 256, μ: 203407, ~: 203407) +TransferManager:testFuzz_changePendingManager(address,address) (runs: 256, μ: 199071, ~: 199071) +TransferManager:testFuzz_transferManager(address) (runs: 256, μ: 194882, ~: 194882) +TransferManager:test_RevertIf_transferManagerToZeroAddress() (gas: 169260) TransferManager:test_isAdmin() (gas: 953783) WhitelistBase:test_isAdmin() (gas: 953761) \ No newline at end of file diff --git a/.github/workflows/solidity-test.yml b/.github/workflows/solidity-test.yml index ea488e0..de36a60 100644 --- a/.github/workflows/solidity-test.yml +++ b/.github/workflows/solidity-test.yml @@ -113,3 +113,13 @@ jobs: *) echo "::error title=Storage layout check failed to run::shell/check_storage_layout.sh could not inspect the contract." exit 1 ;; esac + + deploy-wizard: + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - name: Test deployment wizard + run: python3 test/shell/test_deploy_wizard.py diff --git a/.storage-layout b/.storage-layout index b185919..f8162ce 100644 --- a/.storage-layout +++ b/.storage-layout @@ -25,7 +25,7 @@ "type": "t_mapping(t_bytes32,t_struct(RoleData)22_storage)" }, { - "astId": 1058, + "astId": 1067, "contract": "src/StateOracle.sol:StateOracle", "label": "assertionAdopters", "offset": 0, @@ -33,23 +33,23 @@ "type": "t_mapping(t_address,t_struct(AssertionAdopter)979_storage)" }, { - "astId": 1064, + "astId": 1073, "contract": "src/StateOracle.sol:StateOracle", "label": "adminVerifiers", "offset": 0, "slot": "4", - "type": "t_mapping(t_contract(IAdminVerifier)2524,t_bool)" + "type": "t_mapping(t_contract(IAdminVerifier)2650,t_bool)" }, { - "astId": 1070, + "astId": 1079, "contract": "src/StateOracle.sol:StateOracle", "label": "daVerifiers", "offset": 0, "slot": "5", - "type": "t_mapping(t_contract(IDAVerifier)2553,t_bool)" + "type": "t_mapping(t_contract(IDAVerifier)2679,t_bool)" }, { - "astId": 1075, + "astId": 1084, "contract": "src/StateOracle.sol:StateOracle", "label": "whitelist", "offset": 0, @@ -57,7 +57,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1078, + "astId": 1087, "contract": "src/StateOracle.sol:StateOracle", "label": "whitelistEnabled", "offset": 0, @@ -65,7 +65,7 @@ "type": "t_bool" }, { - "astId": 1081, + "astId": 1090, "contract": "src/StateOracle.sol:StateOracle", "label": "maxAssertionsPerAA", "offset": 1, @@ -89,12 +89,12 @@ "label": "bytes32", "numberOfBytes": "32" }, - "t_contract(IAdminVerifier)2524": { + "t_contract(IAdminVerifier)2650": { "encoding": "inplace", "label": "contract IAdminVerifier", "numberOfBytes": "20" }, - "t_contract(IDAVerifier)2553": { + "t_contract(IDAVerifier)2679": { "encoding": "inplace", "label": "contract IDAVerifier", "numberOfBytes": "20" @@ -127,16 +127,16 @@ "numberOfBytes": "32", "value": "t_struct(RoleData)22_storage" }, - "t_mapping(t_contract(IAdminVerifier)2524,t_bool)": { + "t_mapping(t_contract(IAdminVerifier)2650,t_bool)": { "encoding": "mapping", - "key": "t_contract(IAdminVerifier)2524", + "key": "t_contract(IAdminVerifier)2650", "label": "mapping(contract IAdminVerifier => bool)", "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_contract(IDAVerifier)2553,t_bool)": { + "t_mapping(t_contract(IDAVerifier)2679,t_bool)": { "encoding": "mapping", - "key": "t_contract(IDAVerifier)2553", + "key": "t_contract(IDAVerifier)2679", "label": "mapping(contract IDAVerifier => bool)", "numberOfBytes": "32", "value": "t_bool" diff --git a/Makefile b/Makefile index 90a1349..17b54e6 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: check-storage-layout update-storage-layout check-abi +.PHONY: check-storage-layout deploy update-storage-layout check-abi check-storage-layout: @bash shell/check_storage_layout.sh @@ -10,3 +10,6 @@ update-storage-layout: # Compares against ABI_BASE_REF, defaulting to origin/main. check-abi: @bash shell/check_abi.sh $(ABI_BASE_REF) + +deploy: + ./shell/deploy_wizard.sh diff --git a/README.md b/README.md index 864d5f2..965ecc1 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,9 @@ Set the following environment variables before running the deployment scripts: - `DEPLOY_ADMIN_VERIFIER_OWNER` (true/false) - `DEPLOY_ADMIN_VERIFIER_WHITELIST` (true/false) - `ADMIN_VERIFIER_WHITELIST_ADMIN_ADDRESS` (required when whitelist verifier is enabled) +- `STATE_ORACLE_WHITELIST_ENABLED` (optional, defaults to true) +- `DEPLOY_ADMIN_VERIFIER_ALWAYS_APPROVE` (optional, defaults to false; testing only) +- `DEPLOYMENT_IS_TESTING` (must be true when the Always Approve verifier is enabled) The following additional variables apply only to `DeployCoreWithStaging.s.sol`: @@ -95,14 +98,28 @@ The following additional variables apply only to `DeployCoreWithStaging.s.sol`: ### Deployment Overview -Running `DeployCore` or `DeployCoreWithCreateX` will: +Running `DeployCore`, `DeployCoreWithCreateX`, or `DeployCoreWithStaging` will: 1. Deploy the DA verifier (ECDSA) and log its address. 2. Deploy the DA verifier (OnChain) and log its address. 3. Deploy `AdminVerifierOwner` if `DEPLOY_ADMIN_VERIFIER_OWNER=true` and log its address. 4. Deploy `AdminVerifierWhitelist` if `DEPLOY_ADMIN_VERIFIER_WHITELIST=true` (using `ADMIN_VERIFIER_WHITELIST_ADMIN_ADDRESS` as constructor default admin and initial whitelist admin) and log its address. -5. Deploy the `StateOracle` implementation and log its address. -6. Deploy the proxy, initialize it with the configured admin verifiers and DA verifiers, and log the proxy address. +5. Deploy `AdminVerifierAlwaysApprove` if `DEPLOY_ADMIN_VERIFIER_ALWAYS_APPROVE=true` and `DEPLOYMENT_IS_TESTING=true`, and log its address. +6. Deploy the `StateOracle` implementation and log its address. +7. Deploy the proxy, initialize it with the configured admin verifiers, DA verifiers, and initial whitelist state, and log the proxy address. + +`DeployCoreWithStaging` repeats the last two steps for the staging oracle. It inherits the CreateX deployment path, so both State Oracle implementations, both proxies, both DA verifiers, and every selected admin verifier use named CREATE3 salts. + +For a local testing deployment with registration whitelisting disabled and the Always Approve verifier enabled, combine the required values above with: + +```sh +DEPLOYMENT_IS_TESTING=true \ +STATE_ORACLE_WHITELIST_ENABLED=false \ +DEPLOY_ADMIN_VERIFIER_OWNER=false \ +DEPLOY_ADMIN_VERIFIER_WHITELIST=false \ +DEPLOY_ADMIN_VERIFIER_ALWAYS_APPROVE=true \ +forge script script/DeployCoreWithStaging.s.sol --rpc-url "$RPC_URL" --private-key "$DEPLOYER_PRIVATE_KEY" --broadcast +``` Console output will include labeled addresses for each deployed contract, e.g.: @@ -115,6 +132,36 @@ State Oracle Implementation deployed at
State Oracle Proxy deployed at ``` +### Interactive deployment wizard + +Run the terminal wizard from the repository root: + +```sh +make deploy +``` + +The wizard uses the deterministic CreateX deployment backend and guides you through: + +- production or testing mode, plus an optional staging State Oracle; +- admin verifier selection and assignment to the production and/or staging oracle; +- ECDSA and/or on-chain DA verification, independently assigned to each State Oracle; +- initial State Oracle whitelist state and addresses; +- optional explorer verification using `ETHERSCAN_API_KEY`; +- all State Oracle limits, timelocks, admins, and verifier-specific addresses; and +- a Foundry keystore account selected from `cast wallet list`. + +The wallet password and explorer API key are read without echoing. The password is checked before +deployment and stored only in a temporary mode-`600` file that is removed when the wizard exits. +Before broadcasting, the wizard prints a redacted Forge command and a complete configuration +summary. After broadcasting, it reads Foundry's receipt file and prints every deployment address, +block number, transaction hash, and proxy admin address. + +Testing mode also exposes the `Super Admin` and `Always Approve` admin verifiers. These options are +rejected by the Solidity deployment backend unless testing mode is explicitly enabled. Both testing +verifiers use named CREATE3 salts, as do every production and staging contract deployed by the wizard. +Every broadcast entrypoint in `DeployTestingAdminVerifiers.s.sol` likewise requires +`DEPLOYMENT_IS_TESTING=true`. + ## Installation 1. Clone the repository: @@ -132,8 +179,9 @@ forge install ### CreateX -The forge script `script/DeployCoreWithCreateX` uses the CreateX contract factory for maintaining and controlling contract addresses -of the protocol. +The forge scripts `script/DeployCoreWithCreateX.s.sol`, `script/DeployCoreWithStaging.s.sol`, `script/DeployWizard.s.sol`, and `script/DeployTestingAdminVerifiers.s.sol` use the CreateX contract factory to maintain stable protocol contract addresses. CREATE3 derives each address from the deployer and a contract-specific salt, so transaction order, deployer nonce, and contract init code do not change it. Production and staging State Oracles use different salts; the testing-only SuperAdmin and AlwaysApprove verifiers also have distinct salts shared by the wizard and standalone testing script. + +The fixed address must be empty when first deployed. On a retained chain, rerunning a salt whose contract already exists will revert; preserve the existing proxy and upgrade it for code changes, or reset the chain before performing a clean redeployment. The deployment address of CreateX is `0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed`. If CreateX is not deployed on your chain, you will find a helper script to deploy CreateX at `shell/deploy_create_x.sh`. @@ -169,6 +217,7 @@ STATE_ORACLE_ADMIN_ADDRESS=0xD2EfB83dd46094775188d927323b2523EaE3d087 \ DA_PROVER_ADDRESS=0x670cFA8781BF365Aefb6c048CDc522B857946C71 \ DEPLOY_ADMIN_VERIFIER_OWNER=true \ DEPLOY_ADMIN_VERIFIER_WHITELIST=true \ +STATE_ORACLE_WHITELIST_ENABLED=true \ ADMIN_VERIFIER_WHITELIST_ADMIN_ADDRESS=0xD2EfB83dd46094775188d927323b2523EaE3d087 \ forge script script/DeployCoreWithCreateX.s.sol --rpc-url http://localhost:8545 --private-key 0xac431098061ca49f5b36121d01a17d30e1d0624227d08b583ff328f1efe0d4a2 --broadcast ``` @@ -193,8 +242,8 @@ Private Key: 0xac431098061ca49f5b36121d01a17d30e1d0624227d08b583ff328f1efe0d4a2 Account: (0x8d63e0FE87CA36E06a076584fCA651A684D4c97d) ``` -When broadcasting `script/DeployCore.s.sol ` with the above key, the contracts will always be deployed -at the same address. Neither the initCode of the contracts nor the nonce influence the address generation. +When broadcasting `script/DeployCoreWithCreateX.s.sol` with the above key, the contracts will always be +deployed at the same addresses on a clean chain. Neither init code nor nonce influences address generation. ## Compatibility Checks diff --git a/package.json b/package.json index f394d15..71a427a 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,10 @@ ], "scripts": { "prepare": "./shell/create_artifacts.sh", - "test": "forge test", + "test": "forge test && python3 test/shell/test_deploy_wizard.py", + "test:deploy-wizard": "python3 test/shell/test_deploy_wizard.py", "build": "forge build", + "deploy:wizard": "./shell/deploy_wizard.sh", "format": "forge fmt", "clean": "forge clean" }, diff --git a/script/CreateXDeployer.s.sol b/script/CreateXDeployer.s.sol new file mode 100644 index 0000000..f24dbfe --- /dev/null +++ b/script/CreateXDeployer.s.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: CC0-1.0 +pragma solidity ^0.8.28; + +import {ICreateX, CREATE_X_ADDRESS} from "./ICreateX.sol"; + +abstract contract CreateXDeployer { + string public constant SALT_DA_VERIFIER_ECDSA_NAME = "credible-layer-da-verifier-ecdsa"; + string public constant SALT_DA_VERIFIER_ONCHAIN_NAME = "credible-layer-da-verifier-onchain"; + string public constant SALT_ADMIN_VERIFIER_OWNER_NAME = "credible-layer-admin-verifier-owner"; + string public constant SALT_ADMIN_VERIFIER_WHITELIST_NAME = "credible-layer-admin-verifier-whitelist"; + string public constant SALT_ADMIN_VERIFIER_SUPER_ADMIN_NAME = "credible-layer-admin-verifier-super-admin"; + string public constant SALT_ADMIN_VERIFIER_ALWAYS_APPROVE_NAME = "credible-layer-admin-verifier-always-approve"; + string public constant SALT_STATE_ORACLE_NAME = "credible-layer-state-oracle-implementation"; + string public constant SALT_STATE_ORACLE_PROXY_NAME = "credible-layer-state-oracle-proxy"; + string public constant SALT_STAGING_STATE_ORACLE_NAME = "credible-layer-staging-state-oracle-implementation"; + string public constant SALT_STAGING_STATE_ORACLE_PROXY_NAME = "credible-layer-staging-state-oracle-proxy"; + + ICreateX internal constant CREATE_X = ICreateX(CREATE_X_ADDRESS); + + function _deployCreate3(string memory name, bytes memory initCode) internal returns (address) { + bytes32 salt = _generateCreateXSalt(msg.sender, name); + return CREATE_X.deployCreate3(salt, initCode); + } + + // Set salt with frontrunning protection, i.e. first 20 bytes = deployer; + // 0 byte to switch off cross-chain redeploy protection; 11 bytes salt + // Details: https://github.com/pcaversaccio/createx#permissioned-deploy-protection-and-cross-chain-redeploy-protection + function _generateCreateXSalt(address sender, string memory name) internal pure returns (bytes32) { + return bytes32(abi.encodePacked(sender, hex"00", bytes11(keccak256(bytes(name))))); + } +} diff --git a/script/DeployCore.s.sol b/script/DeployCore.s.sol index 27caf5e..8fe1a2c 100644 --- a/script/DeployCore.s.sol +++ b/script/DeployCore.s.sol @@ -5,6 +5,7 @@ import {StateOracle} from "../src/StateOracle.sol"; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import {IAdminVerifier} from "../src/interfaces/IAdminVerifier.sol"; import {IDAVerifier} from "../src/interfaces/IDAVerifier.sol"; +import {AdminVerifierAlwaysApprove} from "../src/verification/admin/AdminVerifierAlwaysApprove.sol"; import {AdminVerifierOwner} from "../src/verification/admin/AdminVerifierOwner.sol"; import {DAVerifierECDSA} from "../src/verification/da/DAVerifierECDSA.sol"; import {DAVerifierOnChain} from "../src/verification/da/DAVerifierOnChain.sol"; @@ -29,6 +30,9 @@ contract DeployCore is Script { address daProver; bool deployOwnerVerifier; bool deployWhitelistVerifier; + bool deployAlwaysApproveVerifier; + bool stateOracleWhitelistEnabled; + bool testingDeployment; address whitelistAdmin; function setUp() public virtual { @@ -40,12 +44,18 @@ contract DeployCore is Script { // Verifiers deployOwnerVerifier = vm.envBool("DEPLOY_ADMIN_VERIFIER_OWNER"); deployWhitelistVerifier = vm.envBool("DEPLOY_ADMIN_VERIFIER_WHITELIST"); - whitelistAdmin = vm.envAddress("ADMIN_VERIFIER_WHITELIST_ADMIN_ADDRESS"); + deployAlwaysApproveVerifier = vm.envOr("DEPLOY_ADMIN_VERIFIER_ALWAYS_APPROVE", false); + stateOracleWhitelistEnabled = vm.envOr("STATE_ORACLE_WHITELIST_ENABLED", true); + testingDeployment = vm.envOr("DEPLOYMENT_IS_TESTING", false); + if (deployWhitelistVerifier) { + whitelistAdmin = vm.envAddress("ADMIN_VERIFIER_WHITELIST_ADMIN_ADDRESS"); + } assert(daProver != address(0)); assert(assertionTimelockBlocks > 0); assert(admin != address(0)); assert(deployWhitelistVerifier && whitelistAdmin != address(0) || !deployWhitelistVerifier); + require(testingDeployment || !deployAlwaysApproveVerifier, "Always Approve verifier is test-only"); } modifier broadcast() { @@ -54,6 +64,11 @@ contract DeployCore is Script { vm.stopBroadcast(); } + modifier testingOnly() { + require(testingDeployment, "Always Approve verifier is test-only"); + _; + } + function run() public virtual broadcast { _fundPersistentAccounts(); @@ -102,6 +117,10 @@ contract DeployCore is Script { _deployWhitelistAdminVerifier(); } + function deployAlwaysApproveAdminVerifier() public testingOnly broadcast { + _deployAlwaysApproveAdminVerifier(); + } + function fundPersistentAccounts() public broadcast { _fundPersistentAccounts(); } @@ -122,13 +141,17 @@ contract DeployCore is Script { uint256 count; if (deployOwnerVerifier) count++; if (deployWhitelistVerifier) count++; + if (deployAlwaysApproveVerifier) count++; deployments = new address[](count); uint256 index; if (deployOwnerVerifier) { deployments[index++] = _deployOwnerAdminVerifier(); } if (deployWhitelistVerifier) { - deployments[index] = _deployWhitelistAdminVerifier(); + deployments[index++] = _deployWhitelistAdminVerifier(); + } + if (deployAlwaysApproveVerifier) { + deployments[index] = _deployAlwaysApproveAdminVerifier(); } } @@ -152,8 +175,10 @@ contract DeployCore is Script { for (uint256 i = 0; i < daVerifierAddresses.length; i++) { daVfrs[i] = IDAVerifier(daVerifierAddresses[i]); } - bytes memory initCallData = - abi.encodeWithSelector(StateOracle.initialize.selector, admin, adminVerifiers, daVfrs, maxAssertions); + bytes memory initCallData = abi.encodeCall( + StateOracle.initializeWithWhitelist, + (admin, adminVerifiers, daVfrs, maxAssertions, stateOracleWhitelistEnabled, new address[](0)) + ); address proxyAddress = address(new TransparentUpgradeableProxy(address(stateOracle), admin, initCallData)); console2.log("State Oracle Proxy deployed at", proxyAddress); return proxyAddress; @@ -166,11 +191,18 @@ contract DeployCore is Script { } function _deployWhitelistAdminVerifier() internal virtual returns (address verifier) { + require(whitelistAdmin != address(0), "Invalid whitelist admin"); verifier = address(new AdminVerifierWhitelist(whitelistAdmin)); console2.log("Admin Verifier (Whitelist) deployed at", verifier); return verifier; } + function _deployAlwaysApproveAdminVerifier() internal virtual returns (address verifier) { + verifier = address(new AdminVerifierAlwaysApprove()); + console2.log("Testing Admin Verifier (Always Approve) deployed at", verifier); + return verifier; + } + function _fundPersistentAccounts() internal { _fundIfEmpty(CALLER_ADDRESS, "CALLER_ADDRESS"); _fundIfEmpty(ASSERTION_CONTRACT_ADDRESS, "ASSERTION_CONTRACT_ADDRESS"); diff --git a/script/DeployCoreWithCreateX.s.sol b/script/DeployCoreWithCreateX.s.sol index 04fcdce..e2f7b57 100644 --- a/script/DeployCoreWithCreateX.s.sol +++ b/script/DeployCoreWithCreateX.s.sol @@ -5,26 +5,18 @@ import {StateOracle} from "../src/StateOracle.sol"; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import {IAdminVerifier} from "../src/interfaces/IAdminVerifier.sol"; import {IDAVerifier} from "../src/interfaces/IDAVerifier.sol"; +import {AdminVerifierAlwaysApprove} from "../src/verification/admin/AdminVerifierAlwaysApprove.sol"; import {AdminVerifierOwner} from "../src/verification/admin/AdminVerifierOwner.sol"; import {AdminVerifierWhitelist} from "../src/verification/admin/AdminVerifierWhitelist.sol"; import {DAVerifierECDSA} from "../src/verification/da/DAVerifierECDSA.sol"; import {DAVerifierOnChain} from "../src/verification/da/DAVerifierOnChain.sol"; -import {ICreateX, CREATE_X_ADDRESS} from "./ICreateX.sol"; +import {CreateXDeployer} from "./CreateXDeployer.s.sol"; import {DeployCore} from "./DeployCore.s.sol"; import {console2} from "forge-std/console2.sol"; -contract DeployCoreWithCreateX is DeployCore { - string public constant SALT_DA_VERIFIER_ECDSA_NAME = "credible-layer-da-verifier-ecdsa"; - string public constant SALT_DA_VERIFIER_ONCHAIN_NAME = "credible-layer-da-verifier-onchain"; - string public constant SALT_ADMIN_VERIFIER_OWNER_NAME = "credible-layer-admin-verifier-owner"; - string public constant SALT_ADMIN_VERIFIER_WHITELIST_NAME = "credible-layer-admin-verifier-whitelist"; - string public constant SALT_STATE_ORACLE_NAME = "credible-layer-state-oracle-implementation"; - string public constant SALT_STATE_ORACLE_PROXY_NAME = "credible-layer-state-oracle-proxy"; - - ICreateX internal constant CREATE_X = ICreateX(CREATE_X_ADDRESS); - +contract DeployCoreWithCreateX is DeployCore, CreateXDeployer { function _deployDAVerifierECDSA() internal override returns (address) { - address daVerifier = deployCreate3( + address daVerifier = _deployCreate3( SALT_DA_VERIFIER_ECDSA_NAME, abi.encodePacked(type(DAVerifierECDSA).creationCode, abi.encode(daProver)) ); console2.log("DA Verifier (ECDSA) deployed at", daVerifier); @@ -32,19 +24,19 @@ contract DeployCoreWithCreateX is DeployCore { } function _deployDAVerifierOnChain() internal override returns (address) { - address daVerifierOnChain = deployCreate3(SALT_DA_VERIFIER_ONCHAIN_NAME, type(DAVerifierOnChain).creationCode); + address daVerifierOnChain = _deployCreate3(SALT_DA_VERIFIER_ONCHAIN_NAME, type(DAVerifierOnChain).creationCode); console2.log("DA Verifier (OnChain) deployed at", daVerifierOnChain); return daVerifierOnChain; } function _deployOwnerAdminVerifier() internal override returns (address verifier) { - verifier = deployCreate3(SALT_ADMIN_VERIFIER_OWNER_NAME, type(AdminVerifierOwner).creationCode); + verifier = _deployCreate3(SALT_ADMIN_VERIFIER_OWNER_NAME, type(AdminVerifierOwner).creationCode); console2.log("Admin Verifier (Owner) deployed at", verifier); return verifier; } function _deployWhitelistAdminVerifier() internal override returns (address verifier) { - verifier = deployCreate3( + verifier = _deployCreate3( SALT_ADMIN_VERIFIER_WHITELIST_NAME, abi.encodePacked(type(AdminVerifierWhitelist).creationCode, abi.encode(whitelistAdmin)) ); @@ -52,17 +44,31 @@ contract DeployCoreWithCreateX is DeployCore { return verifier; } + function _deployAlwaysApproveAdminVerifier() internal override returns (address verifier) { + verifier = + _deployCreate3(SALT_ADMIN_VERIFIER_ALWAYS_APPROVE_NAME, type(AdminVerifierAlwaysApprove).creationCode); + console2.log("Testing Admin Verifier (Always Approve) deployed at", verifier); + return verifier; + } + function _deployStateOracle(uint256 assertionTimelockBlocks, string memory contractName) internal override returns (address) { - address stateOracle = deployCreate3( - SALT_STATE_ORACLE_NAME, - abi.encodePacked(type(StateOracle).creationCode, abi.encode(assertionTimelockBlocks)) + address stateOracle = _deployStateOracleWithSalt(assertionTimelockBlocks, contractName, SALT_STATE_ORACLE_NAME); + return stateOracle; + } + + function _deployStateOracleWithSalt( + uint256 assertionTimelockBlocks, + string memory contractName, + string memory saltName + ) internal returns (address stateOracle) { + stateOracle = _deployCreate3( + saltName, abi.encodePacked(type(StateOracle).creationCode, abi.encode(assertionTimelockBlocks)) ); console2.log(string.concat(contractName, " Implementation deployed at"), stateOracle); - return stateOracle; } function _deployStateOracleProxy( @@ -71,6 +77,46 @@ contract DeployCoreWithCreateX is DeployCore { address[] memory daVerifierAddresses, uint16 maxAssertions ) internal override returns (address) { + return _deployStateOracleProxyWithSalt( + stateOracle, + adminVerifierDeployments, + daVerifierAddresses, + maxAssertions, + SALT_STATE_ORACLE_PROXY_NAME, + "State Oracle" + ); + } + + function _deployStateOracleProxyWithSalt( + address stateOracle, + address[] memory adminVerifierDeployments, + address[] memory daVerifierAddresses, + uint16 maxAssertions, + string memory saltName, + string memory contractName + ) internal returns (address proxyAddress) { + return _deployStateOracleProxyWithConfig( + stateOracle, + adminVerifierDeployments, + daVerifierAddresses, + maxAssertions, + stateOracleWhitelistEnabled, + new address[](0), + saltName, + contractName + ); + } + + function _deployStateOracleProxyWithConfig( + address stateOracle, + address[] memory adminVerifierDeployments, + address[] memory daVerifierAddresses, + uint16 maxAssertions, + bool whitelistEnabled, + address[] memory initialWhitelist, + string memory saltName, + string memory contractName + ) internal returns (address proxyAddress) { IAdminVerifier[] memory adminVerifiers = new IAdminVerifier[](adminVerifierDeployments.length); for (uint256 i = 0; i < adminVerifierDeployments.length; i++) { adminVerifiers[i] = IAdminVerifier(adminVerifierDeployments[i]); @@ -79,27 +125,16 @@ contract DeployCoreWithCreateX is DeployCore { for (uint256 i = 0; i < daVerifierAddresses.length; i++) { daVfrs[i] = IDAVerifier(daVerifierAddresses[i]); } - bytes memory initCallData = - abi.encodeWithSelector(StateOracle.initialize.selector, admin, adminVerifiers, daVfrs, maxAssertions); - address proxyAddress = deployCreate3( - SALT_STATE_ORACLE_PROXY_NAME, + bytes memory initCallData = abi.encodeCall( + StateOracle.initializeWithWhitelist, + (admin, adminVerifiers, daVfrs, maxAssertions, whitelistEnabled, initialWhitelist) + ); + proxyAddress = _deployCreate3( + saltName, abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, abi.encode(address(stateOracle), admin, initCallData) ) ); - console2.log("State Oracle Proxy deployed at", proxyAddress); - return proxyAddress; - } - - function deployCreate3(string memory name, bytes memory initCode) private returns (address) { - bytes32 salt = generateCreateXSalt(msg.sender, name); - return CREATE_X.deployCreate3(salt, initCode); - } - - // Set salt with frontrunning protection, i.e. first 20 bytes = deployer; - // 0 byte to switch off cross-chain redeploy protection; 11 bytes salt - // Details: https://github.com/pcaversaccio/createx#permissioned-deploy-protection-and-cross-chain-redeploy-protection - function generateCreateXSalt(address sender, string memory name) internal pure returns (bytes32) { - return bytes32(abi.encodePacked(sender, hex"00", bytes11(keccak256(bytes(name))))); + console2.log(string.concat(contractName, " Proxy deployed at"), proxyAddress); } } diff --git a/script/DeployCoreWithStaging.s.sol b/script/DeployCoreWithStaging.s.sol index 5bab00b..065a063 100644 --- a/script/DeployCoreWithStaging.s.sol +++ b/script/DeployCoreWithStaging.s.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.28; -import {DeployCore} from "./DeployCore.s.sol"; +import {DeployCoreWithCreateX} from "./DeployCoreWithCreateX.s.sol"; -contract DeployCoreWithStaging is DeployCore { +contract DeployCoreWithStaging is DeployCoreWithCreateX { uint256 stagingAssertionTimelockBlocks; uint16 stagingMaxAssertionsPerAA; @@ -44,8 +44,16 @@ contract DeployCoreWithStaging is DeployCore { _deployStateOracleProxy(stateOracle, deployedAdminVerifiers, daVerifiers, maxAssertionsPerAA); // Staging oracle - address stagingOracle = _deployStateOracle(stagingAssertionTimelockBlocks, "Staging State Oracle"); - deployedStagingOracle = - _deployStateOracleProxy(stagingOracle, deployedAdminVerifiers, daVerifiers, stagingMaxAssertionsPerAA); + address stagingOracle = _deployStateOracleWithSalt( + stagingAssertionTimelockBlocks, "Staging State Oracle", SALT_STAGING_STATE_ORACLE_NAME + ); + deployedStagingOracle = _deployStateOracleProxyWithSalt( + stagingOracle, + deployedAdminVerifiers, + daVerifiers, + stagingMaxAssertionsPerAA, + SALT_STAGING_STATE_ORACLE_PROXY_NAME, + "Staging State Oracle" + ); } } diff --git a/script/DeployTestingAdminVerifiers.s.sol b/script/DeployTestingAdminVerifiers.s.sol new file mode 100644 index 0000000..d0296ea --- /dev/null +++ b/script/DeployTestingAdminVerifiers.s.sol @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: CC0-1.0 +pragma solidity ^0.8.28; + +import {StateOracle} from "../src/StateOracle.sol"; +import {IAdminVerifier} from "../src/interfaces/IAdminVerifier.sol"; +import {AdminVerifierAlwaysApprove} from "../src/verification/admin/AdminVerifierAlwaysApprove.sol"; +import {AdminVerifierSuperAdmin} from "../src/verification/admin/AdminVerifierSuperAdmin.sol"; +import {console2} from "forge-std/console2.sol"; +import {Script} from "forge-std/Script.sol"; +import {CreateXDeployer} from "./CreateXDeployer.s.sol"; + +contract DeployTestingAdminVerifiers is Script, CreateXDeployer { + address stateOracle; + address superAdmin; + bool deploySuperAdminVerifierEnabled; + bool deployAlwaysApproveVerifierEnabled; + bool addToStateOracle; + bool testingDeployment; + + function setUp() public virtual { + stateOracle = vm.envOr("TEST_STATE_ORACLE_ADDRESS", address(0)); + superAdmin = vm.envOr("TEST_ADMIN_VERIFIER_SUPER_ADMIN_ADDRESS", address(0)); + deploySuperAdminVerifierEnabled = vm.envOr("DEPLOY_TEST_ADMIN_VERIFIER_SUPER_ADMIN", false); + deployAlwaysApproveVerifierEnabled = vm.envOr("DEPLOY_TEST_ADMIN_VERIFIER_ALWAYS_APPROVE", false); + addToStateOracle = vm.envOr("ADD_TEST_ADMIN_VERIFIERS_TO_STATE_ORACLE", false); + testingDeployment = vm.envOr("DEPLOYMENT_IS_TESTING", false); + } + + modifier broadcast() { + vm.startBroadcast(); + _; + vm.stopBroadcast(); + } + + modifier testingOnly() { + require(testingDeployment, "Testing admin verifiers are test-only"); + _; + } + + function run() public testingOnly broadcast { + _run(); + } + + function deploySuperAdminVerifier(address _superAdmin) public testingOnly broadcast returns (address) { + return _deploySuperAdminVerifier(_superAdmin); + } + + function deployAlwaysApproveAdminVerifier() public testingOnly broadcast returns (address) { + return _deployAlwaysApproveAdminVerifier(); + } + + function deployAndAddSuperAdminVerifier(address _stateOracle, address _superAdmin) + public + testingOnly + broadcast + returns (address verifier) + { + verifier = _deploySuperAdminVerifier(_superAdmin); + _addAdminVerifier(_stateOracle, verifier); + } + + function deployAndAddAlwaysApproveAdminVerifier(address _stateOracle) + public + testingOnly + broadcast + returns (address verifier) + { + verifier = _deployAlwaysApproveAdminVerifier(); + _addAdminVerifier(_stateOracle, verifier); + } + + function addAdminVerifier(address _stateOracle, address verifier) public testingOnly broadcast { + _addAdminVerifier(_stateOracle, verifier); + } + + function _run() internal returns (address[] memory deployments) { + deployments = _deployEnabledAdminVerifiers(); + if (addToStateOracle) { + _addAdminVerifiers(stateOracle, deployments); + } + } + + function _deployEnabledAdminVerifiers() internal returns (address[] memory deployments) { + uint256 count; + if (deploySuperAdminVerifierEnabled) count++; + if (deployAlwaysApproveVerifierEnabled) count++; + require(count > 0, "No test verifiers enabled"); + + deployments = new address[](count); + uint256 index; + if (deploySuperAdminVerifierEnabled) { + deployments[index++] = _deploySuperAdminVerifier(superAdmin); + } + if (deployAlwaysApproveVerifierEnabled) { + deployments[index++] = _deployAlwaysApproveAdminVerifier(); + } + } + + function _deploySuperAdminVerifier(address _superAdmin) internal virtual returns (address verifier) { + require(_superAdmin != address(0), "Invalid super admin"); + verifier = _deployCreate3( + SALT_ADMIN_VERIFIER_SUPER_ADMIN_NAME, + abi.encodePacked(type(AdminVerifierSuperAdmin).creationCode, abi.encode(_superAdmin)) + ); + console2.log("Testing Admin Verifier (Super Admin) deployed at", verifier); + } + + function _deployAlwaysApproveAdminVerifier() internal virtual returns (address verifier) { + verifier = + _deployCreate3(SALT_ADMIN_VERIFIER_ALWAYS_APPROVE_NAME, type(AdminVerifierAlwaysApprove).creationCode); + console2.log("Testing Admin Verifier (Always Approve) deployed at", verifier); + } + + function _addAdminVerifiers(address _stateOracle, address[] memory verifiers) internal { + require(_stateOracle != address(0), "Invalid state oracle"); + for (uint256 i = 0; i < verifiers.length; i++) { + _addAdminVerifier(_stateOracle, verifiers[i]); + } + } + + function _addAdminVerifier(address _stateOracle, address verifier) internal { + require(_stateOracle != address(0), "Invalid state oracle"); + require(verifier != address(0), "Invalid admin verifier"); + StateOracle(_stateOracle).addAdminVerifier(IAdminVerifier(verifier)); + console2.log("Testing admin verifier added to StateOracle", verifier); + } +} diff --git a/script/DeployWizard.s.sol b/script/DeployWizard.s.sol new file mode 100644 index 0000000..de4b58b --- /dev/null +++ b/script/DeployWizard.s.sol @@ -0,0 +1,257 @@ +// SPDX-License-Identifier: CC0-1.0 +pragma solidity ^0.8.28; + +import {DeployCoreWithCreateX} from "./DeployCoreWithCreateX.s.sol"; +import {AdminVerifierSuperAdmin} from "../src/verification/admin/AdminVerifierSuperAdmin.sol"; +import {console2} from "forge-std/console2.sol"; + +/// @notice Deployment backend for shell/deploy_wizard.sh. +/// @dev The wizard adds per-oracle verifier selection and initial whitelist +/// configuration to the deterministic CreateX deployment primitives. +contract DeployWizard is DeployCoreWithCreateX { + struct VerifierDeployments { + address daECDSA; + address daOnChain; + address adminOwner; + address adminWhitelist; + address adminSuperAdmin; + address adminAlwaysApprove; + } + + bool internal deployStaging; + + bool internal daECDSAProduction; + bool internal daECDSAStaging; + bool internal daOnChainProduction; + bool internal daOnChainStaging; + + bool internal adminOwnerProduction; + bool internal adminOwnerStaging; + bool internal adminWhitelistProduction; + bool internal adminWhitelistStaging; + bool internal adminSuperAdminProduction; + bool internal adminSuperAdminStaging; + bool internal adminAlwaysApproveProduction; + bool internal adminAlwaysApproveStaging; + + uint256 internal stagingAssertionTimelockBlocks; + uint16 internal stagingMaxAssertionsPerAA; + address internal testSuperAdmin; + address[] internal initialWhitelist; + + function setUp() public override { + testingDeployment = vm.envOr("DEPLOYMENT_IS_TESTING", false); + deployStaging = vm.envOr("DEPLOY_STAGING_STATE_ORACLE", false); + stateOracleWhitelistEnabled = vm.envOr("STATE_ORACLE_WHITELIST_ENABLED", true); + + admin = vm.envAddress("STATE_ORACLE_ADMIN_ADDRESS"); + require(admin != address(0), "Invalid State Oracle admin"); + + uint256 rawMaxAssertions = vm.envUint("STATE_ORACLE_MAX_ASSERTIONS_PER_AA"); + require(rawMaxAssertions > 0 && rawMaxAssertions <= type(uint16).max, "Invalid max assertions"); + // The bounds check above makes this narrowing conversion safe. + // forge-lint: disable-next-line(unsafe-typecast) + maxAssertionsPerAA = uint16(rawMaxAssertions); + + uint256 rawTimelock = vm.envUint("STATE_ORACLE_ASSERTION_TIMELOCK_BLOCKS"); + require(rawTimelock > 0, "Invalid assertion timelock"); + assertionTimelockBlocks = rawTimelock; + + if (deployStaging) { + uint256 rawStagingMaxAssertions = vm.envUint("STAGING_STATE_ORACLE_MAX_ASSERTIONS_PER_AA"); + require( + rawStagingMaxAssertions > 0 && rawStagingMaxAssertions <= type(uint16).max, + "Invalid staging max assertions" + ); + // The bounds check above makes this narrowing conversion safe. + // forge-lint: disable-next-line(unsafe-typecast) + stagingMaxAssertionsPerAA = uint16(rawStagingMaxAssertions); + + uint256 rawStagingTimelock = vm.envUint("STAGING_STATE_ORACLE_ASSERTION_TIMELOCK_BLOCKS"); + require(rawStagingTimelock > 0, "Invalid staging assertion timelock"); + stagingAssertionTimelockBlocks = rawStagingTimelock; + } + + _loadVerifierConfiguration(); + + initialWhitelist = vm.envOr("STATE_ORACLE_INITIAL_WHITELIST", ",", new address[](0)); + } + + function run() public override broadcast { + _fundPersistentAccounts(); + + VerifierDeployments memory deployed = _deploySelectedVerifiers(); + + _deployConfiguredOracle( + true, + "Production", + _selectedAdminVerifiers(true, deployed), + _selectedDAVerifiers(true, deployed), + assertionTimelockBlocks, + maxAssertionsPerAA + ); + + if (deployStaging) { + _deployConfiguredOracle( + false, + "Staging", + _selectedAdminVerifiers(false, deployed), + _selectedDAVerifiers(false, deployed), + stagingAssertionTimelockBlocks, + stagingMaxAssertionsPerAA + ); + } + } + + function _loadVerifierConfiguration() internal { + daECDSAProduction = vm.envOr("DA_VERIFIER_ECDSA_PRODUCTION", false); + daECDSAStaging = vm.envOr("DA_VERIFIER_ECDSA_STAGING", false); + daOnChainProduction = vm.envOr("DA_VERIFIER_ONCHAIN_PRODUCTION", false); + daOnChainStaging = vm.envOr("DA_VERIFIER_ONCHAIN_STAGING", false); + + require(_selectedDAVerifierCount(true) > 0, "Production requires a DA verifier"); + require(!deployStaging || _selectedDAVerifierCount(false) > 0, "Staging requires a DA verifier"); + require(deployStaging || !(daECDSAStaging || daOnChainStaging), "Staging DA verifier selected without staging"); + + if (daECDSAProduction || daECDSAStaging) { + daProver = vm.envAddress("DA_PROVER_ADDRESS"); + require(daProver != address(0), "Invalid DA prover"); + } + + adminOwnerProduction = vm.envOr("ADMIN_VERIFIER_OWNER_PRODUCTION", false); + adminOwnerStaging = vm.envOr("ADMIN_VERIFIER_OWNER_STAGING", false); + adminWhitelistProduction = vm.envOr("ADMIN_VERIFIER_WHITELIST_PRODUCTION", false); + adminWhitelistStaging = vm.envOr("ADMIN_VERIFIER_WHITELIST_STAGING", false); + adminSuperAdminProduction = vm.envOr("ADMIN_VERIFIER_SUPER_ADMIN_PRODUCTION", false); + adminSuperAdminStaging = vm.envOr("ADMIN_VERIFIER_SUPER_ADMIN_STAGING", false); + adminAlwaysApproveProduction = vm.envOr("ADMIN_VERIFIER_ALWAYS_APPROVE_PRODUCTION", false); + adminAlwaysApproveStaging = vm.envOr("ADMIN_VERIFIER_ALWAYS_APPROVE_STAGING", false); + + require(_selectedAdminVerifierCount(true) > 0, "Production requires an admin verifier"); + require(!deployStaging || _selectedAdminVerifierCount(false) > 0, "Staging requires an admin verifier"); + require( + deployStaging + || !(adminOwnerStaging || adminWhitelistStaging || adminSuperAdminStaging || adminAlwaysApproveStaging), + "Staging admin verifier selected without staging" + ); + + if (adminWhitelistProduction || adminWhitelistStaging) { + whitelistAdmin = vm.envAddress("ADMIN_VERIFIER_WHITELIST_ADMIN_ADDRESS"); + require(whitelistAdmin != address(0), "Invalid admin verifier whitelist owner"); + } + + if (adminSuperAdminProduction || adminSuperAdminStaging) { + require(testingDeployment, "Super Admin verifier is test-only"); + testSuperAdmin = vm.envAddress("TEST_ADMIN_VERIFIER_SUPER_ADMIN_ADDRESS"); + require(testSuperAdmin != address(0), "Invalid test super admin"); + } + require( + testingDeployment || !(adminAlwaysApproveProduction || adminAlwaysApproveStaging), + "Always Approve verifier is test-only" + ); + } + + function _deploySelectedVerifiers() internal returns (VerifierDeployments memory deployed) { + if (daECDSAProduction || daECDSAStaging) { + deployed.daECDSA = _deployDAVerifierECDSA(); + _logDeployment("DA Verifier (ECDSA)", deployed.daECDSA); + } + if (daOnChainProduction || daOnChainStaging) { + deployed.daOnChain = _deployDAVerifierOnChain(); + _logDeployment("DA Verifier (On-chain)", deployed.daOnChain); + } + if (adminOwnerProduction || adminOwnerStaging) { + deployed.adminOwner = _deployOwnerAdminVerifier(); + _logDeployment("Admin Verifier (Owner)", deployed.adminOwner); + } + if (adminWhitelistProduction || adminWhitelistStaging) { + deployed.adminWhitelist = _deployWhitelistAdminVerifier(); + _logDeployment("Admin Verifier (Whitelist)", deployed.adminWhitelist); + } + if (adminSuperAdminProduction || adminSuperAdminStaging) { + deployed.adminSuperAdmin = _deployCreate3( + SALT_ADMIN_VERIFIER_SUPER_ADMIN_NAME, + abi.encodePacked(type(AdminVerifierSuperAdmin).creationCode, abi.encode(testSuperAdmin)) + ); + console2.log("Testing Admin Verifier (Super Admin) deployed at", deployed.adminSuperAdmin); + _logDeployment("Testing Admin Verifier (Super Admin)", deployed.adminSuperAdmin); + } + if (adminAlwaysApproveProduction || adminAlwaysApproveStaging) { + deployed.adminAlwaysApprove = _deployAlwaysApproveAdminVerifier(); + _logDeployment("Testing Admin Verifier (Always Approve)", deployed.adminAlwaysApprove); + } + } + + function _selectedDAVerifiers(bool production, VerifierDeployments memory deployed) + internal + view + returns (address[] memory verifiers) + { + verifiers = new address[](_selectedDAVerifierCount(production)); + uint256 index; + if (production ? daECDSAProduction : daECDSAStaging) verifiers[index++] = deployed.daECDSA; + if (production ? daOnChainProduction : daOnChainStaging) verifiers[index] = deployed.daOnChain; + } + + function _selectedDAVerifierCount(bool production) internal view returns (uint256 count) { + if (production ? daECDSAProduction : daECDSAStaging) count++; + if (production ? daOnChainProduction : daOnChainStaging) count++; + } + + function _selectedAdminVerifiers(bool production, VerifierDeployments memory deployed) + internal + view + returns (address[] memory verifiers) + { + verifiers = new address[](_selectedAdminVerifierCount(production)); + uint256 index; + if (production ? adminOwnerProduction : adminOwnerStaging) verifiers[index++] = deployed.adminOwner; + if (production ? adminWhitelistProduction : adminWhitelistStaging) { + verifiers[index++] = deployed.adminWhitelist; + } + if (production ? adminSuperAdminProduction : adminSuperAdminStaging) { + verifiers[index++] = deployed.adminSuperAdmin; + } + if (production ? adminAlwaysApproveProduction : adminAlwaysApproveStaging) { + verifiers[index] = deployed.adminAlwaysApprove; + } + } + + function _selectedAdminVerifierCount(bool production) internal view returns (uint256 count) { + if (production ? adminOwnerProduction : adminOwnerStaging) count++; + if (production ? adminWhitelistProduction : adminWhitelistStaging) count++; + if (production ? adminSuperAdminProduction : adminSuperAdminStaging) count++; + if (production ? adminAlwaysApproveProduction : adminAlwaysApproveStaging) count++; + } + + function _deployConfiguredOracle( + bool production, + string memory environment, + address[] memory adminVerifierDeployments, + address[] memory daVerifierDeployments, + uint256 timelockBlocks, + uint16 maxAssertions + ) internal returns (address proxyAddress) { + string memory contractName = string.concat(environment, " State Oracle"); + string memory implementationSalt = production ? SALT_STATE_ORACLE_NAME : SALT_STAGING_STATE_ORACLE_NAME; + string memory proxySalt = production ? SALT_STATE_ORACLE_PROXY_NAME : SALT_STAGING_STATE_ORACLE_PROXY_NAME; + address implementation = _deployStateOracleWithSalt(timelockBlocks, contractName, implementationSalt); + _logDeployment(string.concat(environment, " State Oracle Implementation"), implementation); + + proxyAddress = _deployStateOracleProxyWithConfig( + implementation, + adminVerifierDeployments, + daVerifierDeployments, + maxAssertions, + stateOracleWhitelistEnabled, + initialWhitelist, + proxySalt, + contractName + ); + _logDeployment(string.concat(environment, " State Oracle Proxy"), proxyAddress); + } + + function _logDeployment(string memory name, address deployedAddress) internal pure { + console2.log(string.concat("WIZARD_DEPLOYMENT|", name, "|"), deployedAddress); + } +} diff --git a/shell/deploy_wizard.sh b/shell/deploy_wizard.sh new file mode 100755 index 0000000..4ad6734 --- /dev/null +++ b/shell/deploy_wizard.sh @@ -0,0 +1,851 @@ +#!/usr/bin/env bash + +set -Eeuo pipefail + +ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +PASSWORD_FILE="" +FORGE_OUTPUT_FILE="" +CURSOR_HIDDEN=false +COLOR_RESET="" +COLOR_BOLD="" +COLOR_DIM="" +COLOR_RED="" +COLOR_GREEN="" +COLOR_YELLOW="" +COLOR_BLUE="" +COLOR_MAGENTA="" +COLOR_CYAN="" + +cleanup() { + if [[ "$CURSOR_HIDDEN" == "true" ]]; then + { printf '\033[?25h' >/dev/tty; } 2>/dev/null || true + fi + if [[ -n "$PASSWORD_FILE" && -f "$PASSWORD_FILE" ]]; then + rm -f "$PASSWORD_FILE" + fi + if [[ -n "$FORGE_OUTPUT_FILE" && -f "$FORGE_OUTPUT_FILE" ]]; then + rm -f "$FORGE_OUTPUT_FILE" + fi +} +trap cleanup EXIT +trap 'exit 130' INT TERM + +usage() { + cat <<'EOF' +Usage: ./shell/deploy_wizard.sh + +Interactively configures and deploys the Credible Layer contracts. Use the +arrow keys to move, Space to toggle multi-select entries, and Enter to accept. + +The wizard reads existing values from these variables as prompt defaults: + RPC_URL or ETH_RPC_URL + ETHERSCAN_API_KEY + STATE_ORACLE_MAX_ASSERTIONS_PER_AA + STATE_ORACLE_ASSERTION_TIMELOCK_BLOCKS + STATE_ORACLE_ADMIN_ADDRESS + STAGING_STATE_ORACLE_MAX_ASSERTIONS_PER_AA + STAGING_STATE_ORACLE_ASSERTION_TIMELOCK_BLOCKS + DA_PROVER_ADDRESS + ADMIN_VERIFIER_WHITELIST_ADMIN_ADDRESS + TEST_ADMIN_VERIFIER_SUPER_ADMIN_ADDRESS +EOF +} + +die() { + printf '%sError:%s %s\n' "${COLOR_BOLD}${COLOR_RED}" "$COLOR_RESET" "$*" >&2 + exit 1 +} + +init_colors() { + if [[ -n ${NO_COLOR+x} || ${TERM:-} == "dumb" ]]; then + return + fi + + COLOR_RESET=$'\033[0m' + COLOR_BOLD=$'\033[1m' + COLOR_DIM=$'\033[2m' + COLOR_RED=$'\033[31m' + COLOR_GREEN=$'\033[32m' + COLOR_YELLOW=$'\033[33m' + COLOR_BLUE=$'\033[34m' + COLOR_MAGENTA=$'\033[35m' + COLOR_CYAN=$'\033[36m' +} + +tty_print() { + printf '%s' "$*" >/dev/tty +} + +tty_println() { + printf '%s\n' "$*" >/dev/tty +} + +tty_heading() { + tty_println "${COLOR_BOLD}${COLOR_CYAN}$*${COLOR_RESET}" +} + +tty_section() { + tty_println "${COLOR_BOLD}${COLOR_MAGENTA}$*${COLOR_RESET}" +} + +tty_hint() { + tty_println "${COLOR_DIM}$*${COLOR_RESET}" +} + +tty_warn() { + tty_println "${COLOR_BOLD}${COLOR_YELLOW}Warning:${COLOR_RESET} $*" +} + +tty_success() { + tty_println "${COLOR_BOLD}${COLOR_GREEN}$*${COLOR_RESET}" +} + +tty_field() { + local label=$1 + shift + printf ' %s%-21s%s %s%s%s\n' \ + "$COLOR_CYAN" "${label}:" "$COLOR_RESET" "$COLOR_GREEN" "$*" "$COLOR_RESET" >/dev/tty +} + +require_command() { + command -v "$1" >/dev/null 2>&1 || die "Required command not found: $1" +} + +read_key() { + local key suffix + IFS= read -rsn1 key /dev/tty + CURSOR_HIDDEN=true + + while true; do + if [[ $rendered -eq 1 ]]; then + printf '\033[%dA' "$count" >/dev/tty + fi + for ((i = 0; i < count; i++)); do + prefix=" " + if [[ $i -eq $selected ]]; then + prefix="${COLOR_BOLD}${COLOR_BLUE}› " + printf '\r\033[2K%s%s%s\n' "$prefix" "${items[$i]}" "$COLOR_RESET" >/dev/tty + else + printf '\r\033[2K%s%s\n' "$prefix" "${items[$i]}" >/dev/tty + fi + done + rendered=1 + + read_key + case "$KEY_RESULT" in + $'\033[A') + selected=$(((selected - 1 + count) % count)) + ;; + $'\033[B') + selected=$(((selected + 1) % count)) + ;; + "") + break + ;; + esac + done + + printf '\033[?25h' >/dev/tty + CURSOR_HIDDEN=false + MENU_INDEX=$selected + MENU_VALUE=${items[$selected]} +} + +menu_select_many() { + local question=$1 + shift + local items=("$@") + local cursor=0 + local rendered=0 + local count=${#items[@]} + local selected_count i marker prefix + + MULTI_SELECTED=() + for ((i = 0; i < count; i++)); do + MULTI_SELECTED[$i]=0 + done + + tty_println "" + tty_heading "$question" + tty_hint " ↑/↓ move · Space toggle · Enter continue" + printf '\033[?25l' >/dev/tty + CURSOR_HIDDEN=true + + while true; do + if [[ $rendered -eq 1 ]]; then + printf '\033[%dA' "$count" >/dev/tty + fi + for ((i = 0; i < count; i++)); do + marker="[ ]" + prefix=" " + if [[ ${MULTI_SELECTED[$i]} -eq 1 ]]; then + marker="${COLOR_BOLD}${COLOR_GREEN}[x]${COLOR_RESET}" + fi + if [[ $i -eq $cursor ]]; then + prefix="${COLOR_BOLD}${COLOR_BLUE}› ${COLOR_RESET}" + fi + printf '\r\033[2K%s%s %s\n' "$prefix" "$marker" "${items[$i]}" >/dev/tty + done + rendered=1 + + read_key + case "$KEY_RESULT" in + $'\033[A') + cursor=$(((cursor - 1 + count) % count)) + ;; + $'\033[B') + cursor=$(((cursor + 1) % count)) + ;; + " ") + if [[ ${MULTI_SELECTED[$cursor]} -eq 1 ]]; then + MULTI_SELECTED[$cursor]=0 + else + MULTI_SELECTED[$cursor]=1 + fi + ;; + "") + selected_count=0 + for ((i = 0; i < count; i++)); do + selected_count=$((selected_count + MULTI_SELECTED[i])) + done + if [[ $selected_count -gt 0 ]]; then + break + fi + printf '\a' >/dev/tty + ;; + esac + done + + printf '\033[?25h' >/dev/tty + CURSOR_HIDDEN=false +} + +prompt_value() { + local label=$1 + local default_value=${2:-} + local value + + while true; do + if [[ -n "$default_value" ]]; then + printf '%s%s%s %s[%s]%s: ' \ + "$COLOR_BOLD" "$label" "$COLOR_RESET" "$COLOR_DIM" "$default_value" "$COLOR_RESET" >/dev/tty + else + printf '%s%s%s: ' "$COLOR_BOLD" "$label" "$COLOR_RESET" >/dev/tty + fi + IFS= read -r value /dev/tty + IFS= read -rs value /dev/null); then + lower=$(printf '%s' "$checksum" | tr '[:upper:]' '[:lower:]') + if [[ "$lower" != "0x0000000000000000000000000000000000000000" ]]; then + PROMPT_RESULT=$checksum + return + fi + fi + tty_warn "Enter a non-zero Ethereum address." + done +} + +decimal_le() { + local value=$1 + local maximum=$2 + + value=$(printf '%s' "$value" | sed 's/^0*//') + [[ -n "$value" ]] || value=0 + if [[ ${#value} -lt ${#maximum} ]]; then + return 0 + fi + if [[ ${#value} -gt ${#maximum} ]]; then + return 1 + fi + [[ "$value" == "$maximum" || "$value" < "$maximum" ]] +} + +prompt_uint() { + local label=$1 + local default_value=$2 + local maximum=$3 + + while true; do + prompt_value "$label" "$default_value" + if [[ "$PROMPT_RESULT" =~ ^[0-9]+$ ]] && [[ "$PROMPT_RESULT" != "0" ]] \ + && decimal_le "$PROMPT_RESULT" "$maximum"; then + PROMPT_RESULT=$(printf '%s' "$PROMPT_RESULT" | sed 's/^0*//') + [[ -n "$PROMPT_RESULT" ]] || PROMPT_RESULT=0 + return + fi + tty_warn "Enter an integer from 1 through $maximum." + done +} + +bool_for_selection() { + if [[ $1 -eq 1 ]]; then + printf 'true' + else + printf 'false' + fi +} + +join_by_comma() { + local joined="" + local value + for value in "$@"; do + if [[ -n "$joined" ]]; then + joined="${joined},${value}" + else + joined=$value + fi + done + printf '%s' "$joined" +} + +print_redacted_command() { + local item redact_next=false + tty_println "" + tty_section "Wallet password validation command" + printf ' cast wallet address --account %q --password-file