diff --git a/contracts/ethereum/.openzeppelin/goerli.json b/contracts/ethereum/.openzeppelin/goerli.json index 24a2cece1..9ecdc83c6 100644 --- a/contracts/ethereum/.openzeppelin/goerli.json +++ b/contracts/ethereum/.openzeppelin/goerli.json @@ -1275,7 +1275,7 @@ "label": "manager", "offset": 2, "slot": "0", - "type": "t_contract(ICasimirManager)12500", + "type": "t_contract(ICasimirManager)13507", "contract": "CasimirViews", "src": "src/v1/CasimirViews.sol:18" }, @@ -1297,7 +1297,7 @@ "label": "bool", "numberOfBytes": "1" }, - "t_contract(ICasimirManager)12500": { + "t_contract(ICasimirManager)13507": { "label": "contract ICasimirManager", "numberOfBytes": "20" }, @@ -4989,7 +4989,7 @@ "label": "factory", "offset": 1, "slot": "153", - "type": "t_contract(ICasimirFactory)12016", + "type": "t_contract(ICasimirFactory)4697", "contract": "CasimirUpkeep", "src": "src/v1/CasimirUpkeep.sol:28" }, @@ -4997,7 +4997,7 @@ "label": "manager", "offset": 0, "slot": "154", - "type": "t_contract(ICasimirManager)12500", + "type": "t_contract(ICasimirManager)5181", "contract": "CasimirUpkeep", "src": "src/v1/CasimirUpkeep.sol:30" }, @@ -5013,7 +5013,7 @@ "label": "reportStatus", "offset": 0, "slot": "156", - "type": "t_enum(ReportStatus)12754", + "type": "t_enum(ReportStatus)5197", "contract": "CasimirUpkeep", "src": "src/v1/CasimirUpkeep.sol:34" }, @@ -5109,7 +5109,7 @@ "label": "reportRequests", "offset": 0, "slot": "167", - "type": "t_mapping(t_bytes32,t_enum(RequestType)12750)", + "type": "t_mapping(t_bytes32,t_enum(RequestType)5193)", "contract": "CasimirUpkeep", "src": "src/v1/CasimirUpkeep.sol:58" }, @@ -5219,15 +5219,15 @@ "label": "contract FunctionsOracleInterface", "numberOfBytes": "20" }, - "t_contract(ICasimirFactory)12016": { + "t_contract(ICasimirFactory)4697": { "label": "contract ICasimirFactory", "numberOfBytes": "20" }, - "t_contract(ICasimirManager)12500": { + "t_contract(ICasimirManager)5181": { "label": "contract ICasimirManager", "numberOfBytes": "20" }, - "t_enum(ReportStatus)12754": { + "t_enum(ReportStatus)5197": { "label": "enum ICasimirUpkeep.ReportStatus", "members": [ "FINALIZED", @@ -5236,7 +5236,7 @@ ], "numberOfBytes": "1" }, - "t_enum(RequestType)12750": { + "t_enum(RequestType)5193": { "label": "enum ICasimirUpkeep.RequestType", "members": [ "NONE", @@ -5249,7 +5249,1132 @@ "label": "mapping(bytes32 => address)", "numberOfBytes": "32" }, - "t_mapping(t_bytes32,t_enum(RequestType)12750)": { + "t_mapping(t_bytes32,t_enum(RequestType)5193)": { + "label": "mapping(bytes32 => enum ICasimirUpkeep.RequestType)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + }, + "ccb491134736bae5bbad5e7f3e0f6f521f840ea057f9d978de854d65e1efa0cc": { + "address": "0x7a584c8B8C6665e30ba1D87B449646c0774A71d9", + "txHash": "0x84a56e1da8a9e47b1ba217907a4d3351f7babdc6500d18321d63f3a5c078bc83", + "layout": { + "solcVersion": "0.8.18", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_status", + "offset": 0, + "slot": "101", + "type": "t_uint256", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:38" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:88" + }, + { + "label": "s_oracle", + "offset": 0, + "slot": "151", + "type": "t_contract(FunctionsOracleInterface)548", + "contract": "FunctionsClient", + "src": "src/v1/vendor/FunctionsClient.sol:13" + }, + { + "label": "s_pendingRequests", + "offset": 0, + "slot": "152", + "type": "t_mapping(t_bytes32,t_address)", + "contract": "FunctionsClient", + "src": "src/v1/vendor/FunctionsClient.sol:14" + }, + { + "label": "compoundStake", + "offset": 0, + "slot": "153", + "type": "t_bool", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:24" + }, + { + "label": "factory", + "offset": 1, + "slot": "153", + "type": "t_contract(ICasimirFactory)4735", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:28" + }, + { + "label": "manager", + "offset": 0, + "slot": "154", + "type": "t_contract(ICasimirManager)5219", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:30" + }, + { + "label": "previousReportTimestamp", + "offset": 0, + "slot": "155", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:32" + }, + { + "label": "reportStatus", + "offset": 0, + "slot": "156", + "type": "t_enum(ReportStatus)5235", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:34" + }, + { + "label": "reportPeriod", + "offset": 1, + "slot": "156", + "type": "t_uint32", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:36" + }, + { + "label": "reportRemainingRequests", + "offset": 0, + "slot": "157", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:38" + }, + { + "label": "reportRequestBlock", + "offset": 0, + "slot": "158", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:40" + }, + { + "label": "reportTimestamp", + "offset": 0, + "slot": "159", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:42" + }, + { + "label": "reportSweptBalance", + "offset": 0, + "slot": "160", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:44" + }, + { + "label": "reportBeaconBalance", + "offset": 0, + "slot": "161", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:46" + }, + { + "label": "reportActivatedDeposits", + "offset": 0, + "slot": "162", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:48" + }, + { + "label": "reportForcedExits", + "offset": 0, + "slot": "163", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:50" + }, + { + "label": "reportCompletedExits", + "offset": 0, + "slot": "164", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:52" + }, + { + "label": "reportCompoundablePoolIds", + "offset": 0, + "slot": "165", + "type": "t_array(t_uint32)5_storage", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:54" + }, + { + "label": "finalizableCompoundablePoolIds", + "offset": 0, + "slot": "166", + "type": "t_array(t_uint32)5_storage", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:56" + }, + { + "label": "reportRequests", + "offset": 0, + "slot": "167", + "type": "t_mapping(t_bytes32,t_enum(RequestType)5231)", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:58" + }, + { + "label": "reportResponseError", + "offset": 0, + "slot": "168", + "type": "t_bytes_storage", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:60" + }, + { + "label": "requestSource", + "offset": 0, + "slot": "169", + "type": "t_string_storage", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:62" + }, + { + "label": "defaultRequestArgs", + "offset": 0, + "slot": "170", + "type": "t_array(t_string_storage)dyn_storage", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:64" + }, + { + "label": "fulfillGasLimit", + "offset": 0, + "slot": "171", + "type": "t_uint32", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:66" + }, + { + "label": "reportRequested", + "offset": 4, + "slot": "171", + "type": "t_bool", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:68" + }, + { + "label": "previousReportBlock", + "offset": 0, + "slot": "172", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:70" + }, + { + "label": "transmitterAddress", + "offset": 0, + "slot": "173", + "type": "t_address", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:72" + }, + { + "label": "__gap", + "offset": 0, + "slot": "174", + "type": "t_array(t_uint256)48_storage", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:74" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_string_storage)dyn_storage": { + "label": "string[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_array(t_uint32)5_storage": { + "label": "uint32[5]", + "numberOfBytes": "32" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes_storage": { + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(FunctionsOracleInterface)548": { + "label": "contract FunctionsOracleInterface", + "numberOfBytes": "20" + }, + "t_contract(ICasimirFactory)4735": { + "label": "contract ICasimirFactory", + "numberOfBytes": "20" + }, + "t_contract(ICasimirManager)5219": { + "label": "contract ICasimirManager", + "numberOfBytes": "20" + }, + "t_enum(ReportStatus)5235": { + "label": "enum ICasimirUpkeep.ReportStatus", + "members": [ + "FINALIZED", + "REQUESTING", + "PROCESSING" + ], + "numberOfBytes": "1" + }, + "t_enum(RequestType)5231": { + "label": "enum ICasimirUpkeep.RequestType", + "members": [ + "NONE", + "BALANCES", + "DETAILS" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_bytes32,t_address)": { + "label": "mapping(bytes32 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_enum(RequestType)5231)": { + "label": "mapping(bytes32 => enum ICasimirUpkeep.RequestType)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + }, + "33980974cea8eb57bc8343a4fa9082630dec86f1622bceb7c11daff6254ad9ea": { + "address": "0xc64319Cc29c9a48652a545a9a0ef279ff173B19c", + "txHash": "0xb569aafb82eb6b091f3be136e2f134c3f9cfc924458eddf43611d59f5614c8d4", + "layout": { + "solcVersion": "0.8.18", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_status", + "offset": 0, + "slot": "101", + "type": "t_uint256", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:38" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:88" + }, + { + "label": "s_oracle", + "offset": 0, + "slot": "151", + "type": "t_contract(FunctionsOracleInterface)548", + "contract": "FunctionsClient", + "src": "src/v1/vendor/FunctionsClient.sol:13" + }, + { + "label": "s_pendingRequests", + "offset": 0, + "slot": "152", + "type": "t_mapping(t_bytes32,t_address)", + "contract": "FunctionsClient", + "src": "src/v1/vendor/FunctionsClient.sol:14" + }, + { + "label": "compoundStake", + "offset": 0, + "slot": "153", + "type": "t_bool", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:24" + }, + { + "label": "factory", + "offset": 1, + "slot": "153", + "type": "t_contract(ICasimirFactory)12075", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:28" + }, + { + "label": "manager", + "offset": 0, + "slot": "154", + "type": "t_contract(ICasimirManager)12559", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:30" + }, + { + "label": "previousReportTimestamp", + "offset": 0, + "slot": "155", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:32" + }, + { + "label": "reportStatus", + "offset": 0, + "slot": "156", + "type": "t_enum(ReportStatus)12813", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:34" + }, + { + "label": "reportPeriod", + "offset": 1, + "slot": "156", + "type": "t_uint32", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:36" + }, + { + "label": "reportRemainingRequests", + "offset": 0, + "slot": "157", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:38" + }, + { + "label": "reportRequestBlock", + "offset": 0, + "slot": "158", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:40" + }, + { + "label": "reportTimestamp", + "offset": 0, + "slot": "159", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:42" + }, + { + "label": "reportSweptBalance", + "offset": 0, + "slot": "160", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:44" + }, + { + "label": "reportBeaconBalance", + "offset": 0, + "slot": "161", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:46" + }, + { + "label": "reportActivatedDeposits", + "offset": 0, + "slot": "162", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:48" + }, + { + "label": "reportForcedExits", + "offset": 0, + "slot": "163", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:50" + }, + { + "label": "reportCompletedExits", + "offset": 0, + "slot": "164", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:52" + }, + { + "label": "reportCompoundablePoolIds", + "offset": 0, + "slot": "165", + "type": "t_array(t_uint32)5_storage", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:54" + }, + { + "label": "finalizableCompoundablePoolIds", + "offset": 0, + "slot": "166", + "type": "t_array(t_uint32)5_storage", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:56" + }, + { + "label": "reportRequests", + "offset": 0, + "slot": "167", + "type": "t_mapping(t_bytes32,t_enum(RequestType)12809)", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:58" + }, + { + "label": "reportResponseError", + "offset": 0, + "slot": "168", + "type": "t_bytes_storage", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:60" + }, + { + "label": "requestSource", + "offset": 0, + "slot": "169", + "type": "t_string_storage", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:62" + }, + { + "label": "defaultRequestArgs", + "offset": 0, + "slot": "170", + "type": "t_array(t_string_storage)dyn_storage", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:64" + }, + { + "label": "fulfillGasLimit", + "offset": 0, + "slot": "171", + "type": "t_uint32", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:66" + }, + { + "label": "reportRequested", + "offset": 4, + "slot": "171", + "type": "t_bool", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:68" + }, + { + "label": "previousReportBlock", + "offset": 0, + "slot": "172", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:70" + }, + { + "label": "transmitterAddress", + "offset": 0, + "slot": "173", + "type": "t_address", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:72" + }, + { + "label": "__gap", + "offset": 0, + "slot": "174", + "type": "t_array(t_uint256)48_storage", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:74" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_string_storage)dyn_storage": { + "label": "string[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_array(t_uint32)5_storage": { + "label": "uint32[5]", + "numberOfBytes": "32" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes_storage": { + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(FunctionsOracleInterface)548": { + "label": "contract FunctionsOracleInterface", + "numberOfBytes": "20" + }, + "t_contract(ICasimirFactory)12075": { + "label": "contract ICasimirFactory", + "numberOfBytes": "20" + }, + "t_contract(ICasimirManager)12559": { + "label": "contract ICasimirManager", + "numberOfBytes": "20" + }, + "t_enum(ReportStatus)12813": { + "label": "enum ICasimirUpkeep.ReportStatus", + "members": [ + "FINALIZED", + "REQUESTING", + "PROCESSING" + ], + "numberOfBytes": "1" + }, + "t_enum(RequestType)12809": { + "label": "enum ICasimirUpkeep.RequestType", + "members": [ + "NONE", + "BALANCES", + "DETAILS" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_bytes32,t_address)": { + "label": "mapping(bytes32 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_enum(RequestType)12809)": { + "label": "mapping(bytes32 => enum ICasimirUpkeep.RequestType)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + }, + "efc7bf29bd0ae7809938bbb6c15eacf722f8efc6374299773d5feca84023b7d8": { + "address": "0x5984D9717F5c72b42016d031bE6EDFe962cb4dE6", + "txHash": "0x1fa9afab0a0c1ae13cb8902552bc4a5fe76ded7154a31b0e7264aa62bba8a209", + "layout": { + "solcVersion": "0.8.18", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_status", + "offset": 0, + "slot": "101", + "type": "t_uint256", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:38" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:88" + }, + { + "label": "s_oracle", + "offset": 0, + "slot": "151", + "type": "t_contract(FunctionsOracleInterface)548", + "contract": "FunctionsClient", + "src": "src/v1/vendor/FunctionsClient.sol:13" + }, + { + "label": "s_pendingRequests", + "offset": 0, + "slot": "152", + "type": "t_mapping(t_bytes32,t_address)", + "contract": "FunctionsClient", + "src": "src/v1/vendor/FunctionsClient.sol:14" + }, + { + "label": "compoundStake", + "offset": 0, + "slot": "153", + "type": "t_bool", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:24" + }, + { + "label": "factory", + "offset": 1, + "slot": "153", + "type": "t_contract(ICasimirFactory)13023", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:28" + }, + { + "label": "manager", + "offset": 0, + "slot": "154", + "type": "t_contract(ICasimirManager)13507", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:30" + }, + { + "label": "previousReportTimestamp", + "offset": 0, + "slot": "155", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:32" + }, + { + "label": "reportStatus", + "offset": 0, + "slot": "156", + "type": "t_enum(ReportStatus)13761", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:34" + }, + { + "label": "reportPeriod", + "offset": 1, + "slot": "156", + "type": "t_uint32", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:36" + }, + { + "label": "reportRemainingRequests", + "offset": 0, + "slot": "157", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:38" + }, + { + "label": "reportRequestBlock", + "offset": 0, + "slot": "158", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:40" + }, + { + "label": "reportTimestamp", + "offset": 0, + "slot": "159", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:42" + }, + { + "label": "reportSweptBalance", + "offset": 0, + "slot": "160", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:44" + }, + { + "label": "reportBeaconBalance", + "offset": 0, + "slot": "161", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:46" + }, + { + "label": "reportActivatedDeposits", + "offset": 0, + "slot": "162", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:48" + }, + { + "label": "reportForcedExits", + "offset": 0, + "slot": "163", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:50" + }, + { + "label": "reportCompletedExits", + "offset": 0, + "slot": "164", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:52" + }, + { + "label": "reportCompoundablePoolIds", + "offset": 0, + "slot": "165", + "type": "t_array(t_uint32)5_storage", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:54" + }, + { + "label": "finalizableCompoundablePoolIds", + "offset": 0, + "slot": "166", + "type": "t_array(t_uint32)5_storage", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:56" + }, + { + "label": "reportRequests", + "offset": 0, + "slot": "167", + "type": "t_mapping(t_bytes32,t_enum(RequestType)13757)", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:58" + }, + { + "label": "reportResponseError", + "offset": 0, + "slot": "168", + "type": "t_bytes_storage", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:60" + }, + { + "label": "requestSource", + "offset": 0, + "slot": "169", + "type": "t_string_storage", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:62" + }, + { + "label": "defaultRequestArgs", + "offset": 0, + "slot": "170", + "type": "t_array(t_string_storage)dyn_storage", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:64" + }, + { + "label": "fulfillGasLimit", + "offset": 0, + "slot": "171", + "type": "t_uint32", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:66" + }, + { + "label": "reportRequested", + "offset": 4, + "slot": "171", + "type": "t_bool", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:68" + }, + { + "label": "previousReportBlock", + "offset": 0, + "slot": "172", + "type": "t_uint256", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:70" + }, + { + "label": "transmitterAddress", + "offset": 0, + "slot": "173", + "type": "t_address", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:72" + }, + { + "label": "__gap", + "offset": 0, + "slot": "174", + "type": "t_array(t_uint256)48_storage", + "contract": "CasimirUpkeep", + "src": "src/v1/CasimirUpkeep.sol:74" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_string_storage)dyn_storage": { + "label": "string[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_array(t_uint32)5_storage": { + "label": "uint32[5]", + "numberOfBytes": "32" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes_storage": { + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(FunctionsOracleInterface)548": { + "label": "contract FunctionsOracleInterface", + "numberOfBytes": "20" + }, + "t_contract(ICasimirFactory)13023": { + "label": "contract ICasimirFactory", + "numberOfBytes": "20" + }, + "t_contract(ICasimirManager)13507": { + "label": "contract ICasimirManager", + "numberOfBytes": "20" + }, + "t_enum(ReportStatus)13761": { + "label": "enum ICasimirUpkeep.ReportStatus", + "members": [ + "FINALIZED", + "REQUESTING", + "PROCESSING" + ], + "numberOfBytes": "1" + }, + "t_enum(RequestType)13757": { + "label": "enum ICasimirUpkeep.RequestType", + "members": [ + "NONE", + "BALANCES", + "DETAILS" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_bytes32,t_address)": { + "label": "mapping(bytes32 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_enum(RequestType)13757)": { "label": "mapping(bytes32 => enum ICasimirUpkeep.RequestType)", "numberOfBytes": "32" }, diff --git a/contracts/ethereum/arguments.js b/contracts/ethereum/arguments.js index 331e4cf1d..28f5437e5 100644 --- a/contracts/ethereum/arguments.js +++ b/contracts/ethereum/arguments.js @@ -3,31 +3,6 @@ * npm run verify --workspace @casimir/ethereum -- --constructor-args arguments.js --network goerli CONTRACT_ADDRESS */ -const { ETHEREUM_CONTRACTS } = require("@casimir/env"); - // const { ETHEREUM_CONTRACTS } = require("@casimir/env"); -module.exports = [ - // Manager - // ETHEREUM_CONTRACTS['TESTNET'].FUNCTIONS_BILLING_REGISTRY_ADDRESS, - // ETHEREUM_CONTRACTS['TESTNET'].KEEPER_REGISTRAR_ADDRESS, - // ETHEREUM_CONTRACTS['TESTNET'].KEEPER_REGISTRY_ADDRESS, - // ETHEREUM_CONTRACTS['TESTNET'].LINK_TOKEN_ADDRESS, - // ETHEREUM_CONTRACTS['TESTNET'].SSV_NETWORK_ADDRESS, - // ETHEREUM_CONTRACTS['TESTNET'].SSV_TOKEN_ADDRESS, - // ETHEREUM_CONTRACTS['TESTNET'].SWAP_FACTORY_ADDRESS, - // ETHEREUM_CONTRACTS['TESTNET'].SWAP_ROUTER_ADDRESS, - // ETHEREUM_CONTRACTS['TESTNET'].WETH_TOKEN_ADDRESS, - - // Functions Billing Registry - // ETHEREUM_CONTRACTS['TESTNET'].LINK_TOKEN_ADDRESS, - // ETHEREUM_CONTRACTS['TESTNET'].LINK_ETH_FEED_ADDRESS, - // ETHEREUM_CONTRACTS['TESTNET'].FUNCTIONS_ORACLE_ADDRESS - - // factoryAddress, - // functionsOracleAddress, - // compoundStake - ETHEREUM_CONTRACTS['TESTNET'].FACTORY_ADDRESS, - ETHEREUM_CONTRACTS['TESTNET'].FUNCTIONS_ORACLE_ADDRESS, - true -] \ No newline at end of file +// module.exports = [] \ No newline at end of file diff --git a/contracts/ethereum/helpers/upkeep.ts b/contracts/ethereum/helpers/upkeep.ts index 4b38e3c11..70598fc28 100644 --- a/contracts/ethereum/helpers/upkeep.ts +++ b/contracts/ethereum/helpers/upkeep.ts @@ -46,19 +46,23 @@ export async function fulfillReport({ const requestIds = (await upkeep.queryFilter(upkeep.filters.RequestSent())).slice(-2).map((event) => event.args.id) const balancesRequestId = requestIds[0] + const balancesResponse = ethers.utils.defaultAbiCoder.encode( ['uint128', 'uint128'], [ethers.utils.parseEther(beaconBalance.toString()), ethers.utils.parseEther(sweptBalance.toString())] ) - const fulfillBalances = await upkeep.connect(donTransmitter).fulfillRequestDirect(balancesRequestId, balancesResponse) - await fulfillBalances.wait() - // await fulfillFunctionsRequest({ - // donTransmitter, - // functionsBillingRegistry, - // requestId: balancesRequestId, - // response: balancesResponse - // }) + await fulfillFunctionsRequest({ + donTransmitter, + functionsBillingRegistry, + requestId: balancesRequestId, + response: balancesResponse + }) + + console.log(ethers.utils.defaultAbiCoder.encode(['uint32'], [activatedDeposits])) + console.log(ethers.utils.defaultAbiCoder.encode(['uint32'], [forcedExits])) + console.log(ethers.utils.defaultAbiCoder.encode(['uint32'], [completedExits])) + console.log(ethers.utils.defaultAbiCoder.encode(['uint32[5]'], [compoundablePoolIds])) const detailsRequestId = requestIds[1] const detailsResponse = ethers.utils.defaultAbiCoder.encode( @@ -66,44 +70,43 @@ export async function fulfillReport({ [activatedDeposits, forcedExits, completedExits, compoundablePoolIds] ) - const fulfillDetails = await upkeep.connect(donTransmitter).fulfillRequestDirect(detailsRequestId, detailsResponse) - await fulfillDetails.wait() - // await fulfillFunctionsRequest({ - // donTransmitter, - // functionsBillingRegistry, - // requestId: detailsRequestId, - // response: detailsResponse - // }) + console.log('DETAILS', JSON.stringify({ detailsRequestId, detailsResponse })) + await fulfillFunctionsRequest({ + donTransmitter, + functionsBillingRegistry, + requestId: detailsRequestId, + response: detailsResponse + }) } -// export async function fulfillFunctionsRequest({ -// donTransmitter, -// functionsBillingRegistry, -// requestId, -// response -// }: { -// donTransmitter: SignerWithAddress, -// functionsBillingRegistry: FunctionsBillingRegistry, -// requestId: string, -// response: string -// }) { -// const dummyTransmitter = donTransmitter.address -// const dummySigners = Array(31).fill(dummyTransmitter) +export async function fulfillFunctionsRequest({ + donTransmitter, + functionsBillingRegistry, + requestId, + response +}: { + donTransmitter: SignerWithAddress, + functionsBillingRegistry: FunctionsBillingRegistry, + requestId: string, + response: string +}) { + const dummyTransmitter = donTransmitter.address + const dummySigners = Array(31).fill(dummyTransmitter) -// // const { success, result, resultLog } = await simulateRequest(requestConfig) + // const { success, result, resultLog } = await simulateRequest(requestConfig) -// const fulfillAndBill = await functionsBillingRegistry.connect(donTransmitter).fulfillAndBill( -// requestId, -// response, -// '0x', -// dummyTransmitter, -// dummySigners, -// 4, -// 100_000, -// 500_000, -// { -// gasLimit: 500_000, -// } -// ) -// await fulfillAndBill.wait() -// } + const fulfillAndBill = await functionsBillingRegistry.connect(donTransmitter).fulfillAndBill( + requestId, + response, + '0x', + dummyTransmitter, + dummySigners, + 4, + 100_000, + 500_000, + { + gasLimit: 500_000, + } + ) + await fulfillAndBill.wait() +} diff --git a/contracts/ethereum/scripts/deploy.ts b/contracts/ethereum/scripts/deploy.ts index b76170a1f..6fd5391f5 100644 --- a/contracts/ethereum/scripts/deploy.ts +++ b/contracts/ethereum/scripts/deploy.ts @@ -136,7 +136,7 @@ void async function () { await factory.deployed() console.log(`CasimirFactory contract deployed at ${factory.address}`) - const defaultStrategy = { + const baseStrategy = { minCollateral: ethers.utils.parseEther('1.0'), lockPeriod: 0, userFee: 5, @@ -149,23 +149,21 @@ void async function () { const deployBaseManager = await factory.deployManager( daoOracle.address, functionsOracle.address, - defaultStrategy + baseStrategy ) await deployBaseManager.wait() const [managerId] = await factory.getManagerIds() const [managerAddress, registryAddress, upkeepAddress, viewsAddress] = await factory.getManagerConfig(managerId) - console.log(`Default CasimirManager contract deployed to ${managerAddress}`) - console.log(`Default CasimirRegistry contract deployed to ${registryAddress}`) - console.log(`Default CasimirUpkeep contract deployed to ${upkeepAddress}`) - console.log(`Default CasimirViews contract deployed to ${viewsAddress}`) + console.log(`Base CasimirManager contract deployed to ${managerAddress}`) + console.log(`Base CasimirRegistry contract deployed to ${registryAddress}`) + console.log(`Base CasimirUpkeep contract deployed to ${upkeepAddress}`) + console.log(`Base CasimirViews contract deployed to ${viewsAddress}`) const upkeep = await ethers.getContractAt('CasimirUpkeep', upkeepAddress) as CasimirUpkeep requestConfig.args[1] = viewsAddress const fulfillGasLimit = 300000 const setRequest = await upkeep.setFunctionsRequest(requestConfig.source, requestConfig.args, fulfillGasLimit) await setRequest.wait() - const setTransmitter = await upkeep.setTransmitter(donTransmitter.address) - await setTransmitter.wait() await functionsBillingRegistry.setAuthorizedSenders([donTransmitter.address, functionsOracle.address]) await functionsOracle.setRegistry(functionsBillingRegistry.address) diff --git a/contracts/ethereum/scripts/report.ts b/contracts/ethereum/scripts/report.ts index 0a33f0b7c..0cf2e92b3 100644 --- a/contracts/ethereum/scripts/report.ts +++ b/contracts/ethereum/scripts/report.ts @@ -1,22 +1,21 @@ import { ethers } from 'hardhat' -import { CasimirFactory, CasimirUpkeep, FunctionsBillingRegistry } from '../build/@types' +import { CasimirFactory, CasimirUpkeep } from '../build/@types' import ICasimirFactoryAbi from '../build/abi/ICasimirFactory.json' import ICasimirUpkeepAbi from '../build/abi/ICasimirUpkeep.json' -import FunctionsBillingRegistryAbi from '../build/abi/FunctionsBillingRegistry.json' -import FunctionsOracleAbi from '../build/abi/FunctionsOracle.json' import { ETHEREUM_CONTRACTS, ETHEREUM_RPC_URL } from '@casimir/env' void async function() { - if (!process.env.ETHEREUM_RPC_URL) throw new Error('No ethereum rpc url provided') - const [owner, , donTransmitter] = await ethers.getSigners() + process.env.ETHEREUM_RPC_URL = ETHEREUM_RPC_URL['TESTNET'] + process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS = ETHEREUM_CONTRACTS['TESTNET'].FUNCTIONS_BILLING_REGISTRY_ADDRESS + process.env.FUNCTIONS_ORACLE_ADDRESS = ETHEREUM_CONTRACTS['TESTNET'].FUNCTIONS_ORACLE_ADDRESS + const [owner] = await ethers.getSigners() const provider = new ethers.providers.JsonRpcProvider(ETHEREUM_RPC_URL['TESTNET']) - const factory = new ethers.Contract(ETHEREUM_CONTRACTS['TESTNET'].FACTORY_ADDRESS, ICasimirFactoryAbi, provider) as CasimirFactory const [managerId] = await factory.getManagerIds() const managerConfig = await factory.getManagerConfig(managerId) const upkeep = new ethers.Contract(managerConfig.upkeepAddress, ICasimirUpkeepAbi, provider) as CasimirUpkeep // const resetReport = await upkeep.connect(owner).resetReport(0, 0, 0, 0, 0) // await resetReport.wait() - // const requestReport = await upkeep.connect(owner).requestReport() - // await requestReport.wait() + const requestReport = await upkeep.connect(owner).requestReport() + await requestReport.wait() }() \ No newline at end of file diff --git a/contracts/ethereum/scripts/upgrade-proxies.ts b/contracts/ethereum/scripts/upgrade-proxies.ts index 25b1ca07b..e6043737a 100644 --- a/contracts/ethereum/scripts/upgrade-proxies.ts +++ b/contracts/ethereum/scripts/upgrade-proxies.ts @@ -4,7 +4,6 @@ import { ethers, upgrades } from 'hardhat' * Upgrade ethereum contracts */ void async function () { - // Redeploying functions billing registry for updates if (!process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS) throw new Error('No functions billing registry address provided') if (!process.env.BEACON_LIBRARY_ADDRESS) throw new Error('No beacon library address provided') if (!process.env.MANAGER_BEACON_ADDRESS) throw new Error('No manager beacon address provided') diff --git a/contracts/ethereum/src/v1/CasimirUpkeep.sol b/contracts/ethereum/src/v1/CasimirUpkeep.sol index 47d370638..ddf57a120 100644 --- a/contracts/ethereum/src/v1/CasimirUpkeep.sol +++ b/contracts/ethereum/src/v1/CasimirUpkeep.sol @@ -52,7 +52,7 @@ contract CasimirUpkeep is uint256 private reportCompletedExits; /// @dev Current report compoundable pools uint32[5] private reportCompoundablePoolIds; - /// @dev Finalizable compoundable pools + /// @dev Finalizable compoundable pools (not used, will be removed in future version) uint32[5] private finalizableCompoundablePoolIds; /// @dev Current report request mapping(bytes32 => RequestType) private reportRequests; @@ -68,7 +68,7 @@ contract CasimirUpkeep is bool private reportRequested; /// @dev Previous report block uint256 private previousReportBlock; - /// @dev DON transmitter address + /// @dev DON transmitter address (not used, will be removed in future version) address private transmitterAddress; /// @dev Storage gap uint256[48] private __gap; @@ -158,17 +158,6 @@ contract CasimirUpkeep is emit UpkeepPerformed(reportStatus); } - /// @inheritdoc ICasimirUpkeep - function fulfillRequestDirect(bytes32 requestId, bytes memory response) external { - onlyTransmitter(); - RequestType requestType = reportRequests[requestId]; - if (requestType == RequestType.NONE) { - revert InvalidRequest(); - } - handleResponse(requestId, requestType, response); - emit DirectResponseReceived(requestId, requestType, response); - } - /// @inheritdoc ICasimirUpkeep function requestReport() external { onlyFactoryOwner(); @@ -193,7 +182,12 @@ contract CasimirUpkeep is previousReportBlock = resetPreviousReportBlock; previousReportTimestamp = resetPreviousReportTimestamp; reportRemainingRequests = 0; - reportRequestBlock = 0; + reportBeaconBalance = 0; + reportSweptBalance = 0; + reportActivatedDeposits = 0; + reportForcedExits = 0; + reportCompletedExits = 0; + reportCompoundablePoolIds = [0, 0, 0, 0, 0]; } /// @inheritdoc ICasimirUpkeep @@ -216,12 +210,6 @@ contract CasimirUpkeep is emit FunctionsRequestSet(newRequestSource, newRequestArgs, newFulfillGasLimit); } - /// @inheritdoc ICasimirUpkeep - function setTransmitter(address newTransmitterAddress) external { - onlyFactoryOwner(); - transmitterAddress = newTransmitterAddress; - } - /// @inheritdoc ICasimirUpkeep function checkUpkeep(bytes memory) public view override returns (bool upkeepNeeded, bytes memory checkData) { if (reportStatus == ReportStatus.FINALIZED) { @@ -278,7 +266,6 @@ contract CasimirUpkeep is reportForcedExits = forcedExits; reportCompletedExits = completedExits; reportCompoundablePoolIds = compoundablePoolIds; - finalizableCompoundablePoolIds = compoundablePoolIds; if (reportActivatedDeposits > 0) { emit ActivationsRequested(activatedDeposits); } @@ -318,11 +305,4 @@ contract CasimirUpkeep is revert Unauthorized(); } } - - /// @dev Validate the caller is the transmitter - function onlyTransmitter() private view { - if (msg.sender != transmitterAddress) { - revert Unauthorized(); - } - } } diff --git a/contracts/ethereum/src/v1/dev/CasimirUpkeepDev.sol b/contracts/ethereum/src/v1/dev/CasimirUpkeepDev.sol new file mode 100644 index 000000000..cd5b31e04 --- /dev/null +++ b/contracts/ethereum/src/v1/dev/CasimirUpkeepDev.sol @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: Apache +pragma solidity 0.8.18; + +import "../interfaces/ICasimirFactory.sol"; +import "../interfaces/ICasimirManager.sol"; +import "./interfaces/ICasimirUpkeepDev.sol"; +import "../vendor/FunctionsClient.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol"; + +/// @title Upkeep contract that automates reporting operations +contract CasimirUpkeepDev is + ICasimirUpkeepDev, + Initializable, + OwnableUpgradeable, + ReentrancyGuardUpgradeable, + FunctionsClient +{ + using Functions for Functions.Request; + + /// @inheritdoc ICasimirUpkeepDev + bool public compoundStake; + /// @dev Report-to-report heartbeat duration + uint256 private constant REPORT_HEARTBEAT = 1 days; + /// @dev Factory contract + ICasimirFactory private factory; + /// @dev Manager contract + ICasimirManager private manager; + /// @dev Previous report timestamp + uint256 private previousReportTimestamp; + /// @dev Current report status + ReportStatus private reportStatus; + /// @dev Current report period + uint32 private reportPeriod; + /// @dev Current report remaining request count + uint256 private reportRemainingRequests; + /// @dev Current report block + uint256 private reportRequestBlock; + /// @dev Current report request timestamp + uint256 private reportTimestamp; + /// @dev Current report swept balance + uint256 private reportSweptBalance; + /// @dev Current report beacon chain balance + uint256 private reportBeaconBalance; + /// @dev Current report deposit activations + uint256 private reportActivatedDeposits; + /// @dev Current report unexpected exits + uint256 private reportForcedExits; + /// @dev Current report completed exits + uint256 private reportCompletedExits; + /// @dev Current report compoundable pools + uint32[5] private reportCompoundablePoolIds; + /// @dev Finalizable compoundable pools (not used, will be removed in future version) + uint32[5] private finalizableCompoundablePoolIds; + /// @dev Current report request + mapping(bytes32 => RequestType) private reportRequests; + /// @dev Current report response error + bytes private reportResponseError; + /// @dev Request source + string private requestSource; + /// @dev Default request arguments + string[] private defaultRequestArgs; + /// @dev Fulfillment gas limit + uint32 private fulfillGasLimit; + /// @dev Whether a report has been requested + bool private reportRequested; + /// @dev Previous report block + uint256 private previousReportBlock; + /// @dev DON transmitter address (not used, will be removed in future version) + address private transmitterAddress; + /// @dev Storage gap + uint256[48] private __gap; + + /** + * @dev Constructor + * @custom:oz-upgrades-unsafe-allow constructor + */ + constructor() FunctionsClient(address(0)) { + _disableInitializers(); + } + + /** + * Initialize the contract + * @param factoryAddress Factory address + * @param functionsOracleAddress Chainlink functions oracle address + * @param compoundStake_ Whether compound stake is enabled + */ + function initialize( + address factoryAddress, + address functionsOracleAddress, + bool compoundStake_ + ) public initializer { + __Ownable_init(); + __ReentrancyGuard_init(); + factory = ICasimirFactory(factoryAddress); + manager = ICasimirManager(msg.sender); + compoundStake = compoundStake_; + setOracle(functionsOracleAddress); + } + + /// @inheritdoc ICasimirUpkeepDev + function performUpkeep(bytes calldata) external override { + (bool upkeepNeeded, ) = checkUpkeep(""); + if (!upkeepNeeded) { + revert UpkeepNotNeeded(); + } + if (reportStatus == ReportStatus.FINALIZED) { + reportStatus = ReportStatus.REQUESTING; + previousReportBlock = reportRequestBlock; + previousReportTimestamp = reportTimestamp; + reportRequestBlock = block.number; + reportTimestamp = block.timestamp; + reportPeriod = manager.reportPeriod(); + Functions.Request memory request; + request.initializeRequest(Functions.Location.Inline, Functions.CodeLanguage.JavaScript, requestSource); + string[] memory requestArgs = defaultRequestArgs; + requestArgs[7] = StringsUpgradeable.toString(previousReportTimestamp); + requestArgs[8] = StringsUpgradeable.toString(reportTimestamp); + requestArgs[9] = StringsUpgradeable.toString(reportRequestBlock); + sendFunctionsRequest(request, requestArgs, RequestType.BALANCES); + sendFunctionsRequest(request, requestArgs, RequestType.DETAILS); + emit ReportRequestsSent( + reportPeriod, + reportRequestBlock, + reportTimestamp, + previousReportBlock, + previousReportTimestamp + ); + } else { + if ( + manager.requestedWithdrawalBalance() > 0 && + manager.getPendingWithdrawalEligibility(0, reportPeriod) && + manager.requestedWithdrawalBalance() <= manager.getWithdrawableBalance() + ) { + manager.fulfillWithdrawals(5); + } + if (!manager.getPendingWithdrawalEligibility(0, reportPeriod)) { + if (reportRequested) { + reportRequested = false; + } + reportStatus = ReportStatus.FINALIZED; + manager.rebalanceStake({ + beaconBalance: reportBeaconBalance, + sweptBalance: reportSweptBalance, + activatedDeposits: reportActivatedDeposits, + completedExits: reportCompletedExits + }); + manager.compoundRewards(reportCompoundablePoolIds); + reportBeaconBalance = 0; + reportActivatedDeposits = 0; + reportForcedExits = 0; + reportCompletedExits = 0; + reportCompoundablePoolIds = [0, 0, 0, 0, 0]; + } + } + emit UpkeepPerformed(reportStatus); + } + + /// @inheritdoc ICasimirUpkeepDev + function requestReport() external { + onlyFactoryOwner(); + reportRequested = true; + emit ReportRequested(); + } + + /// @inheritdoc ICasimirUpkeepDev + function resetReport( + uint32 resetReportPeriod, + uint256 resetReportBlock, + uint256 resetReportTimestamp, + uint256 resetPreviousReportBlock, + uint256 resetPreviousReportTimestamp + ) external { + onlyFactoryOwner(); + reportStatus = ReportStatus.FINALIZED; + reportRequested = false; + reportPeriod = resetReportPeriod; + reportRequestBlock = resetReportBlock; + reportTimestamp = resetReportTimestamp; + previousReportBlock = resetPreviousReportBlock; + previousReportTimestamp = resetPreviousReportTimestamp; + reportRemainingRequests = 0; + reportRequestBlock = 0; + } + + /// @inheritdoc ICasimirUpkeepDev + function setFunctionsOracle(address newFunctionsOracleAddress) external { + onlyFactoryOwner(); + setOracle(newFunctionsOracleAddress); + emit FunctionsOracleAddressSet(newFunctionsOracleAddress); + } + + /// @inheritdoc ICasimirUpkeepDev + function setFunctionsRequest( + string calldata newRequestSource, + string[] calldata newRequestArgs, + uint32 newFulfillGasLimit + ) external { + onlyFactoryOwner(); + requestSource = newRequestSource; + defaultRequestArgs = newRequestArgs; + fulfillGasLimit = newFulfillGasLimit; + emit FunctionsRequestSet(newRequestSource, newRequestArgs, newFulfillGasLimit); + } + + /// @inheritdoc ICasimirUpkeepDev + function getReportRemainingRequests() external view returns (uint256) { + return reportRemainingRequests; + } + + /// @inheritdoc ICasimirUpkeepDev + function getRequestType(bytes32 requestId) external view returns (RequestType) { + return reportRequests[requestId]; + } + + /// @inheritdoc ICasimirUpkeepDev + function checkUpkeep(bytes memory) public view override returns (bool upkeepNeeded, bytes memory checkData) { + if (reportStatus == ReportStatus.FINALIZED) { + bool checkActive = manager.getPendingPoolIds().length + manager.getStakedPoolIds().length > 0; + bool heartbeatLapsed = (block.timestamp - reportTimestamp) >= REPORT_HEARTBEAT; + upkeepNeeded = (checkActive && heartbeatLapsed) || (checkActive && reportRequested); + } else if (reportStatus == ReportStatus.PROCESSING) { + bool finalizeReport = reportActivatedDeposits == manager.finalizableActivations() && + reportCompletedExits == manager.finalizableCompletedExits(); + upkeepNeeded = finalizeReport; + } + return (upkeepNeeded, checkData); + } + + /** + * @dev Callback that is invoked once the DON has resolved the request or hit an error + * @param requestId Request ID, returned by sendRequest() + * @param response Aggregated response from the DON + * @param err Aggregated error from the code execution + */ + function fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override { + RequestType requestType = reportRequests[requestId]; + if (requestType == RequestType.NONE) { + revert InvalidRequest(); + } + reportResponseError = err; + if (err.length == 0) { + handleResponse(requestId, requestType, response); + } + emit OCRResponse(requestId, response, err); + } + + /** + * @dev Handle a fulfilled request + * @param requestId Request ID + * @param requestType Request type + * @param response Response + */ + function handleResponse(bytes32 requestId, RequestType requestType, bytes memory response) private { + delete reportRequests[requestId]; + reportRemainingRequests--; + if (requestType == RequestType.BALANCES) { + (uint128 beaconBalance, uint128 sweptBalance) = abi.decode(response, (uint128, uint128)); + reportBeaconBalance = uint256(beaconBalance); + reportSweptBalance = uint256(sweptBalance); + } else { + ( + uint32 activatedDeposits, + uint32 forcedExits, + uint32 completedExits, + uint32[5] memory compoundablePoolIds + ) = abi.decode(response, (uint32, uint32, uint32, uint32[5])); + reportActivatedDeposits = activatedDeposits; + reportForcedExits = forcedExits; + reportCompletedExits = completedExits; + reportCompoundablePoolIds = compoundablePoolIds; + if (reportActivatedDeposits > 0) { + emit ActivationsRequested(activatedDeposits); + } + if (reportForcedExits > 0) { + emit ForcedExitReportsRequested(forcedExits); + } + if (reportCompletedExits > 0) { + emit CompletedExitReportsRequested(completedExits); + } + } + if (reportRemainingRequests == 0) { + reportStatus = ReportStatus.PROCESSING; + } + } + + /** + * @dev Send a Chainlink functions request + * @param request Chainlink functions request + * @param requestArgs Chainlink functions request arguments + * @param requestType Chainlink functions request type + */ + function sendFunctionsRequest( + Functions.Request memory request, + string[] memory requestArgs, + RequestType requestType + ) private { + requestArgs[10] = StringsUpgradeable.toString(uint256(requestType)); + request.addArgs(requestArgs); + bytes32 requestId = sendRequest(request, manager.functionsId(), fulfillGasLimit); + reportRequests[requestId] = requestType; + reportRemainingRequests++; + } + + /// @dev Validate the caller is the factory owner + function onlyFactoryOwner() private view { + if (msg.sender != factory.getOwner()) { + revert Unauthorized(); + } + } +} diff --git a/contracts/ethereum/src/v1/dev/interfaces/ICasimirUpkeepDev.sol b/contracts/ethereum/src/v1/dev/interfaces/ICasimirUpkeepDev.sol new file mode 100644 index 000000000..d41bfe85e --- /dev/null +++ b/contracts/ethereum/src/v1/dev/interfaces/ICasimirUpkeepDev.sol @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: Apache +pragma solidity 0.8.18; + +import "../../interfaces/ICasimirCore.sol"; +import "@chainlink/contracts/src/v0.8/interfaces/AutomationCompatibleInterface.sol"; + +interface ICasimirUpkeepDev is ICasimirCore, AutomationCompatibleInterface { + /// @dev Functions request type + enum RequestType { + NONE, + BALANCES, + DETAILS + } + + /// @dev Report status + enum ReportStatus { + FINALIZED, + REQUESTING, + PROCESSING + } + + event ActivationsRequested(uint256 count); + event CompletedExitReportsRequested(uint256 count); + event ForcedExitReportsRequested(uint256 count); + event FunctionsOracleAddressSet(address newFunctionsOracleAddress); + event FunctionsRequestSet(string newRequestSource, string[] newRequestArgs, uint32 newFulfillGasLimit); + event OCRResponse(bytes32 indexed requestId, bytes result, bytes err); + event ReportRequested(); + event ReportRequestsSent(uint32, uint256, uint256, uint256, uint256); + event UpkeepPerformed(ReportStatus indexed status); + + error InvalidRequest(); + error UpkeepNotNeeded(); + + /// @notice Perform the upkeep + function performUpkeep(bytes calldata) external; + + /// @notice Request an early report + function requestReport() external; + + /** + * @notice Reset the report + * @param resetReportPeriod Reset report period + * @param resetReportBlock Reset report block + * @param resetReportTimestamp Reset report timestamp + * @param resetPreviousReportBlock Reset previous report block + * @param resetPreviousReportTimestamp Reset previous report timestamp + */ + function resetReport( + uint32 resetReportPeriod, + uint256 resetReportBlock, + uint256 resetReportTimestamp, + uint256 resetPreviousReportBlock, + uint256 resetPreviousReportTimestamp + ) external; + + /** + * @notice Set a new Chainlink functions request + * @param newRequestSource New Chainlink functions source code + * @param newRequestArgs New Chainlink functions arguments + * @param newFulfillGasLimit New Chainlink functions fulfill gas limit + */ + function setFunctionsRequest( + string calldata newRequestSource, + string[] calldata newRequestArgs, + uint32 newFulfillGasLimit + ) external; + + /** + * @notice Set a new Chainlink functions oracle address + * @param newFunctionsOracleAddress New Chainlink functions oracle address + */ + function setFunctionsOracle(address newFunctionsOracleAddress) external; + + /// @notice Get the report remaining requests + function getReportRemainingRequests() external view returns (uint256); + + /** + * @notice Get a request type by ID + * @param requestId Request ID + */ + function getRequestType(bytes32 requestId) external view returns (RequestType); + + /// @notice Check if the upkeep is needed + function checkUpkeep(bytes calldata checkData) external view returns (bool upkeepNeeded, bytes memory); + + /// @notice Whether compound stake is enabled + function compoundStake() external view returns (bool); +} diff --git a/contracts/ethereum/src/v1/interfaces/ICasimirUpkeep.sol b/contracts/ethereum/src/v1/interfaces/ICasimirUpkeep.sol index 3a3df6849..79ea44d59 100644 --- a/contracts/ethereum/src/v1/interfaces/ICasimirUpkeep.sol +++ b/contracts/ethereum/src/v1/interfaces/ICasimirUpkeep.sol @@ -21,7 +21,6 @@ interface ICasimirUpkeep is ICasimirCore, AutomationCompatibleInterface { event ActivationsRequested(uint256 count); event CompletedExitReportsRequested(uint256 count); - event DirectResponseReceived(bytes32 indexed requestId, RequestType requestType, bytes result); event ForcedExitReportsRequested(uint256 count); event FunctionsOracleAddressSet(address newFunctionsOracleAddress); event FunctionsRequestSet(string newRequestSource, string[] newRequestArgs, uint32 newFulfillGasLimit); @@ -36,16 +35,6 @@ interface ICasimirUpkeep is ICasimirCore, AutomationCompatibleInterface { /// @notice Perform the upkeep function performUpkeep(bytes calldata) external; - /** - * @notice Fulfill the request directly without functions billing - * @param requestId Request ID - * @param response Response - */ - function fulfillRequestDirect( - bytes32 requestId, - bytes memory response - ) external; - /// @notice Request an early report function requestReport() external; @@ -83,9 +72,6 @@ interface ICasimirUpkeep is ICasimirCore, AutomationCompatibleInterface { */ function setFunctionsOracle(address newFunctionsOracleAddress) external; - /// @notice Set the transmitter address - function setTransmitter(address newTransmitterAddress) external; - /// @notice Check if the upkeep is needed function checkUpkeep(bytes calldata checkData) external view returns (bool upkeepNeeded, bytes memory); diff --git a/contracts/ethereum/test/fixtures/shared.ts b/contracts/ethereum/test/fixtures/shared.ts index eb3dd76cb..a853c018d 100644 --- a/contracts/ethereum/test/fixtures/shared.ts +++ b/contracts/ethereum/test/fixtures/shared.ts @@ -156,8 +156,6 @@ export async function deploymentFixture() { const fulfillGasLimit = 300000 const setRequest = await upkeep.setFunctionsRequest(requestConfig.source, requestConfig.args, fulfillGasLimit) await setRequest.wait() - const setTransmitter = await upkeep.setTransmitter(donTransmitter.address) - await setTransmitter.wait() await functionsBillingRegistry.setAuthorizedSenders([donTransmitter.address, functionsOracle.address]) await functionsOracle.setRegistry(functionsBillingRegistry.address) diff --git a/contracts/ethereum/test/upgrades.ts b/contracts/ethereum/test/upgrades.ts new file mode 100644 index 000000000..d38f3f73a --- /dev/null +++ b/contracts/ethereum/test/upgrades.ts @@ -0,0 +1,46 @@ +import { ethers, upgrades } from 'hardhat' +import { expect } from 'chai' +import { ETHEREUM_CONTRACTS } from '@casimir/env' +import CasimirFactoryAbi from '../build/abi/CasimirFactory.json' +import CasimirUpkeepDevAbi from '../build/abi/CasimirUpkeepDev.json' +import FunctionsBillingRegistryAbi from '../build/abi/FunctionsBillingRegistry.json' +import { fulfillReport } from '../helpers/upkeep' +import { CasimirUpkeepDev, FunctionsBillingRegistry } from '../build/@types' + +describe('Upgrades', async function () { + + it('Upgrade upkeep with dev', async function () { + const [owner, daoOracle, donTransmitter] = await ethers.getSigners() + + const factory = new ethers.Contract(ETHEREUM_CONTRACTS['TESTNET'].FACTORY_ADDRESS, CasimirFactoryAbi, ethers.provider) + const [managerId] = await factory.getManagerIds() + const managerConfig = await factory.getManagerConfig(managerId) + + const upkeepDevFactory = await ethers.getContractFactory('CasimirUpkeepDev') + const upkeepBeacon = await upgrades.upgradeBeacon(ETHEREUM_CONTRACTS['TESTNET'].UPKEEP_BEACON_ADDRESS, upkeepDevFactory) + await upkeepBeacon.deployed() + console.log(`CasimirUpkeep beacon upgraded at ${upkeepBeacon.address}`) + const upkeep = new ethers.Contract(managerConfig.upkeepAddress, CasimirUpkeepDevAbi, ethers.provider) as CasimirUpkeepDev + + const reportRemainingRequests = await upkeep.getReportRemainingRequests() + console.log('Report remaining requests', reportRemainingRequests) + const requestType = await upkeep.getRequestType('0xaf574e98f82d5ea06b985400ad9c5c2a8cbe9f1e960cc39e66ea276a1cf8408c') + console.log(requestType) + + const checkUpkeepBefore = await upkeep.checkUpkeep('0x') + console.log('Upkeep needed before', checkUpkeepBefore.upkeepNeeded) + const functionsBillingRegistry = new ethers.Contract(ETHEREUM_CONTRACTS['TESTNET'].FUNCTIONS_BILLING_REGISTRY_ADDRESS, FunctionsBillingRegistryAbi, ethers.provider) as FunctionsBillingRegistry + const reportValues = { + beaconBalance: 31.993754780, + sweptBalance: 0, + activatedDeposits: 1, + forcedExits: 0, + completedExits: 0, + compoundablePoolIds: [0, 0, 0, 0, 0] + } + await fulfillReport({ donTransmitter, upkeep, functionsBillingRegistry, values: reportValues }) + const checkUpkeepAfter = await upkeep.checkUpkeep('0x') + console.log('Upkeep needed after', checkUpkeepAfter.upkeepNeeded) + }) + +}) \ No newline at end of file diff --git a/scripts/ethereum/report.ts b/scripts/ethereum/report.ts index ab45c4d05..81cc9f416 100644 --- a/scripts/ethereum/report.ts +++ b/scripts/ethereum/report.ts @@ -1,9 +1,9 @@ import { loadCredentials, getSecret } from '@casimir/aws' -import { ETHEREUM_NETWORK_NAME, ETHEREUM_RPC_URL } from '@casimir/env' +import { ETHEREUM_CONTRACTS, ETHEREUM_NETWORK_NAME } from '@casimir/env' import { run } from '@casimir/shell' /** - * Upgrade ethereum contracts + * Run an ethereum development environment */ void async function () { if (process.env.USE_SECRETS !== 'false') { @@ -14,11 +14,9 @@ void async function () { } console.log(`Your mnemonic seed is ${process.env.BIP39_SEED}`) - process.env.NETWORK = process.env.NETWORK || 'testnet' - process.env.ETHEREUM_RPC_URL = ETHEREUM_RPC_URL[process.env.NETWORK.toUpperCase()] - const networkName = ETHEREUM_NETWORK_NAME[process.env.NETWORK.toUpperCase()] - - console.log(`Using ${networkName} network from ${process.env.ETHEREUM_RPC_URL}`) + process.env.SSV_NETWORK_ADDRESS = ETHEREUM_CONTRACTS['TESTNET'].SSV_NETWORK_ADDRESS + process.env.SSV_VIEWS_ADDRESS = ETHEREUM_CONTRACTS['TESTNET'].SSV_VIEWS_ADDRESS + process.env.SWAP_FACTORY_ADDRESS = ETHEREUM_CONTRACTS['TESTNET'].SWAP_FACTORY_ADDRESS - run(`npm run report --workspace @casimir/ethereum -- --network ${networkName}`) -}() \ No newline at end of file + run(`npm run report --workspace @casimir/ethereum -- --network ${ETHEREUM_NETWORK_NAME['TESTNET']}`) +}() diff --git a/services/functions/API-request-source.js b/services/functions/API-request-source.js index 873d9d7b0..59d4e8929 100644 --- a/services/functions/API-request-source.js +++ b/services/functions/API-request-source.js @@ -35,12 +35,12 @@ async function balancesHandler() { const depositedPoolPublicKeys = await getDepositedPoolPublicKeys(startIndex, endIndex) const validators = await getValidators(depositedPoolPublicKeys) - const beaconBalance = validators.reduce((accumulator, { balance }) => { + const beaconBalance = Functions.gweiToWei(validators.reduce((accumulator, { balance }) => { accumulator += parseFloat(balance) return accumulator - }, 0) + }, 0)) - const sweptBalance = await getSweptBalance(startIndex, endIndex) + const sweptBalance = Functions.gweiToWei(await getSweptBalance(startIndex, endIndex)) console.log("Results", { beaconBalance, @@ -48,8 +48,8 @@ async function balancesHandler() { }) return Buffer.concat([ - encodeUint128(beaconBalance), - encodeUint128(sweptBalance) + Functions.encodeUint128(beaconBalance), + Functions.encodeUint128(sweptBalance) ]) } @@ -252,22 +252,16 @@ async function getValidators(validatorPublicKeys) { return request.data.data } -function encodeUint128(value) { - const buffer = Buffer.alloc(16) - buffer.writeBigUInt64BE(BigInt(value)) - return buffer -} - function encodeUint32(value) { - const buffer = Buffer.alloc(4) - buffer.writeUInt32BE(value) - return buffer + const buffer = Buffer.alloc(32) + buffer.writeUInt32BE(value, 28) + return buffer } function encodeUint32Array(values) { - const buffer = Buffer.alloc(20) - for (let i = 0; i < values.length; i++) { - buffer.writeUInt32BE(values[i], i * 4) - } - return buffer + const buffer = Buffer.alloc(32 * values.length) + for (let i = 0; i < values.length; i++) { + buffer.writeUInt32BE(values[i], i * 32 + 28) + } + return buffer } \ No newline at end of file diff --git a/services/functions/Functions-request-config.js b/services/functions/Functions-request-config.js index b30148f98..8fac8cbc2 100644 --- a/services/functions/Functions-request-config.js +++ b/services/functions/Functions-request-config.js @@ -43,7 +43,7 @@ const requestConfig = { // Args (string only array) can be accessed within the source code with `args[index]` (ie: args[0]). args: [ "1616508000", // genesisTimestamp - "0xc9F69bD5F43153FB485cBF1DB907EE1eb28c9B29", // viewsAddress + "0x394042CBB8bF5444766496897982A5CDd01d5099", // viewsAddress "0x0812a9fe", // getCompoundablePoolIds(uint256,uint256) "0x5d1e0780", // getDepositedPoolCount() "0xdcf25c1d", // getDepositedPoolPublicKeys(uint256,uint256) diff --git a/services/functions/FunctionsSandboxLibrary/Functions.js b/services/functions/FunctionsSandboxLibrary/Functions.js index 089807e87..a9a3c7131 100644 --- a/services/functions/FunctionsSandboxLibrary/Functions.js +++ b/services/functions/FunctionsSandboxLibrary/Functions.js @@ -1,143 +1,167 @@ "use strict" var __importDefault = - (this && this.__importDefault) || - function (mod) { - return mod && mod.__esModule ? mod : { default: mod } - } + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod } + } var _a Object.defineProperty(exports, "__esModule", { value: true }) exports.FunctionsModule = void 0 const axios_1 = __importDefault(require("axios")) class FunctionsModule { - constructor() { - this.buildFunctionsmodule = (numAllowedQueries) => { - return { - makeHttpRequest: this.makeHttpRequestFactory(numAllowedQueries), - encodeUint256: FunctionsModule.encodeUint256, - encodeInt256: FunctionsModule.encodeInt256, - encodeString: FunctionsModule.encodeString, - } - } - this.makeHttpRequestFactory = (maxHttpRequests) => { - let totalHttpRequests = 0 - return async ({ - url, - method = "get", - params, - headers, - data, - // Default timeout of 5 seconds - timeout = 5000, - responseType = "json", - }) => { - if (totalHttpRequests < maxHttpRequests) { - totalHttpRequests++ - let result - if (timeout > 9000) { - throw Error("HTTP request timeout >9000") - } - if (url.length > 2048) { - throw Error("HTTP request URL length >2048") - } - try { - result = await (0, axios_1.default)({ - method: method.toLowerCase(), - url, - params, - headers, - data, - timeout, - responseType, - maxBodyLength: 2000, - maxContentLength: 2000000, // Max response size: 2 megabytes - }) - // Delete the request to avoid exposing system information to the user's code - delete result.request - delete result.config - result.error = false - return result - } catch (untypedError) { - const error = untypedError - delete error.request - delete error.config - if (error.response) { - delete error.response.request + constructor() { + this.buildFunctionsmodule = (numAllowedQueries) => { + return { + makeHttpRequest: this.makeHttpRequestFactory(numAllowedQueries), + encodeUint256: FunctionsModule.encodeUint256, + encodeInt256: FunctionsModule.encodeInt256, + encodeUint128: FunctionsModule.encodeUint128, + encodeString: FunctionsModule.encodeString, + gweiToWei: FunctionsModule.gweiToWei + } + } + this.makeHttpRequestFactory = (maxHttpRequests) => { + let totalHttpRequests = 0 + return async ({ + url, + method = "get", + params, + headers, + data, + // Default timeout of 5 seconds + timeout = 5000, + responseType = "json", + }) => { + if (totalHttpRequests < maxHttpRequests) { + totalHttpRequests++ + let result + if (timeout > 9000) { + throw Error("HTTP request timeout >9000") + } + if (url.length > 2048) { + throw Error("HTTP request URL length >2048") + } + try { + result = await (0, axios_1.default)({ + method: method.toLowerCase(), + url, + params, + headers, + data, + timeout, + responseType, + maxBodyLength: 2000, + maxContentLength: 2000000, // Max response size: 2 megabytes + }) + // Delete the request to avoid exposing system information to the user's code + delete result.request + delete result.config + result.error = false + return result + } catch (untypedError) { + const error = untypedError + delete error.request + delete error.config + if (error.response) { + delete error.response.request + } + error.error = true + return error + } + } + throw Error("exceeded numAllowedQueries") } - error.error = true - return error - } } - throw Error("exceeded numAllowedQueries") - } } - } - get userHttpQueries() { - return [] - } + get userHttpQueries() { + return [] + } } exports.FunctionsModule = FunctionsModule _a = FunctionsModule FunctionsModule.encodeUint256 = (result) => { - if (typeof result === "number") { - if (!Number.isInteger(result)) { - throw Error("encodeUint256 invalid input") + if (typeof result === "number") { + if (!Number.isInteger(result)) { + throw Error("encodeUint256 invalid input") + } + if (result < 0) { + throw Error("encodeUint256 invalid input") + } + return _a.encodeUint256(BigInt(result)) + } + if (typeof result === "bigint") { + if (result > _a.maxUint256) { + throw Error("encodeUint256 invalid input") + } + if (result < BigInt(0)) { + throw Error("encodeUint256 invalid input") + } + if (result === BigInt(0)) { + return Buffer.from("0000000000000000000000000000000000000000000000000000000000000000", "hex") + } + const hex = result.toString(16).padStart(64, "0") + return Buffer.from(hex, "hex") + } + throw Error("encodeUint256 invalid input") +} +FunctionsModule.encodeInt256 = (result) => { + if (typeof result === "number") { + if (!Number.isInteger(result)) { + throw Error("encodeInt256 invalid input") + } + return _a.encodeInt256(BigInt(result)) } - if (result < 0) { - throw Error("encodeUint256 invalid input") + if (typeof result !== "bigint") { + throw Error("encodeInt256 invalid input") } - return _a.encodeUint256(BigInt(result)) - } - if (typeof result === "bigint") { - if (result > _a.maxUint256) { - throw Error("encodeUint256 invalid input") + if (result < _a.maxNegInt256) { + throw Error("encodeInt256 invalid input") } - if (result < BigInt(0)) { - throw Error("encodeUint256 invalid input") + if (result > _a.maxPosInt256) { + throw Error("encodeInt256 invalid input") } - if (result === BigInt(0)) { - return Buffer.from("0000000000000000000000000000000000000000000000000000000000000000", "hex") + if (result < BigInt(0)) { + return _a.encodeNegSignedInt(result) } - const hex = result.toString(16).padStart(64, "0") - return Buffer.from(hex, "hex") - } - throw Error("encodeUint256 invalid input") + return _a.encodePosSignedInt(result) } -FunctionsModule.encodeInt256 = (result) => { - if (typeof result === "number") { - if (!Number.isInteger(result)) { - throw Error("encodeInt256 invalid input") +FunctionsModule.encodeUint128 = (result) => { + if (typeof result === 'number') { + if (!Number.isInteger(result) || result < 0) { + throw Error('encodeUint128 invalid input') + } + result = BigInt(result) } - return _a.encodeInt256(BigInt(result)) - } - if (typeof result !== "bigint") { - throw Error("encodeInt256 invalid input") - } - if (result < _a.maxNegInt256) { - throw Error("encodeInt256 invalid input") - } - if (result > _a.maxPosInt256) { - throw Error("encodeInt256 invalid input") - } - if (result < BigInt(0)) { - return _a.encodeNegSignedInt(result) - } - return _a.encodePosSignedInt(result) + if (result < 0 || result > FunctionsModule.maxUint128) { + throw Error('encodeUint128 out of range') + } + return FunctionsModule.encodeUint256(result) } FunctionsModule.encodeString = (result) => { - if (typeof result !== "string") { - throw Error("encodeString invalid input") - } - return Buffer.from(result) + if (typeof result !== "string") { + throw Error("encodeString invalid input") + } + return Buffer.from(result) } FunctionsModule.encodePosSignedInt = (int) => { - const hex = int.toString(16).padStart(64, "0") - return Buffer.from(hex, "hex") + const hex = int.toString(16).padStart(64, "0") + return Buffer.from(hex, "hex") } FunctionsModule.encodeNegSignedInt = (int) => { - const overflowingHex = (BigInt(2) ** BigInt(256) + int).toString(16) - const int256Hex = overflowingHex.slice(-64) - return Buffer.from(int256Hex, "hex") + const overflowingHex = (BigInt(2) ** BigInt(256) + int).toString(16) + const int256Hex = overflowingHex.slice(-64) + return Buffer.from(int256Hex, "hex") +} +FunctionsModule.gweiToWei = (result) => { + if (typeof result === "number") { + if (!Number.isInteger(result) || result < 0) { + throw Error('gweiToWei invalid input'); + } + return _a.gweiToWei(BigInt(result)) + } + return result * BigInt(1000000000) } +FunctionsModule.maxUint128 = BigInt('340282366920938463463374607431768211455'); FunctionsModule.maxUint256 = BigInt("115792089237316195423570985008687907853269984665640564039457584007913129639935") FunctionsModule.maxPosInt256 = BigInt("57896044618658097711785492504343953926634992332820282019728792003956564819967") FunctionsModule.maxNegInt256 = BigInt("-57896044618658097711785492504343953926634992332820282019728792003956564819968") diff --git a/services/functions/scripts/dev.ts b/services/functions/scripts/dev.ts index 21dfe66b4..2e44f10cf 100644 --- a/services/functions/scripts/dev.ts +++ b/services/functions/scripts/dev.ts @@ -17,12 +17,10 @@ void async function() { const networkKey = process.env.NETWORK?.toUpperCase() || process.env.FORK?.toUpperCase() || 'TESTNET' if (process.env.NETWORK) { process.env.ETHEREUM_RPC_URL = ETHEREUM_RPC_URL[networkKey] - process.env.FACTORY_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.FACTORY_ADDRESS process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.FUNCTIONS_BILLING_REGISTRY_ADDRESS process.env.FUNCTIONS_ORACLE_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.FUNCTIONS_ORACLE_ADDRESS } if (!process.env.ETHEREUM_RPC_URL) throw new Error(`No ethereum rpc url provided for ${networkKey}`) - if (!process.env.FACTORY_ADDRESS) throw new Error(`No factory address provided for ${networkKey}`) if (!process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS) throw new Error(`No functions billing registry address provided for ${networkKey}`) if (!process.env.FUNCTIONS_ORACLE_ADDRESS) throw new Error('No functions oracle address provided') diff --git a/services/functions/src/index.ts b/services/functions/src/index.ts index b7002a308..d59088ceb 100644 --- a/services/functions/src/index.ts +++ b/services/functions/src/index.ts @@ -31,6 +31,8 @@ if (process.env.USE_LOGS === 'true') { startBlock = getStartBlock('block.log') } +console.log(config.ethereumUrl) + const eventsIterable = getEventsIterable({ contractFilters, ethereumUrl: config.ethereumUrl, diff --git a/services/functions/src/providers/config.ts b/services/functions/src/providers/config.ts index 2315f79b8..9c8ba13f9 100644 --- a/services/functions/src/providers/config.ts +++ b/services/functions/src/providers/config.ts @@ -9,9 +9,6 @@ export function getConfig() { const accountPath = 'm/44\'/60\'/0\'/0/2' const wallet = ethers.Wallet.fromMnemonic(mnemonic, accountPath) - const factoryAddress = process.env.FACTORY_ADDRESS - if (!factoryAddress) throw new Error('No factory address provided') - const functionsBillingRegistryAddress = process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS if (!functionsBillingRegistryAddress) throw new Error('No functions billing registry address provided') @@ -20,7 +17,6 @@ export function getConfig() { return { ethereumUrl, - factoryAddress, functionsBillingRegistryAddress, functionsOracleAddress, wallet diff --git a/services/functions/src/providers/handlers.ts b/services/functions/src/providers/handlers.ts index 8d2b5edc7..34efa0f6f 100644 --- a/services/functions/src/providers/handlers.ts +++ b/services/functions/src/providers/handlers.ts @@ -3,12 +3,10 @@ import { decodeDietCBOR } from './format' import requestConfig from '@casimir/functions/Functions-request-config' import { simulateRequest } from '../../FunctionsSandboxLibrary' import { getConfig } from './config' -import { CasimirFactory, CasimirUpkeep/*, FunctionsBillingRegistry*/ } from '@casimir/ethereum/build/@types' +import { FunctionsBillingRegistry } from '@casimir/ethereum/build/@types' import { updateExecutionLog } from '@casimir/logs' import { HandlerInput } from '../interfaces/HandlerInput' -import ICasimirFactoryAbi from '@casimir/ethereum/build/abi/CasimirFactory.json' -import ICasimirUpkeepAbi from '@casimir/ethereum/build/abi/CasimirUpkeep.json' -// import FunctionsBillingRegistryAbi from '@casimir/ethereum/build/abi/FunctionsBillingRegistry.json' +import FunctionsBillingRegistryAbi from '@casimir/ethereum/build/abi/FunctionsBillingRegistry.json' const config = getConfig() @@ -18,22 +16,20 @@ export async function fulfillRequestHandler(input: HandlerInput): Promise if (!data) throw new Error('No data provided') const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl) - const signer = config.wallet.connect(provider) - const factory = new ethers.Contract(config.factoryAddress, ICasimirFactoryAbi, signer) as CasimirFactory - const [managerId] = await factory.getManagerIds() - const managerConfig = await factory.getManagerConfig(managerId) - const upkeep = new ethers.Contract(managerConfig.upkeepAddress, ICasimirUpkeepAbi, signer) as CasimirUpkeep - // const functionsBillingRegistry = new ethers.Contract(config.functionsBillingRegistryAddress, FunctionsBillingRegistryAbi, signer) as ethers.Contract & FunctionsBillingRegistry + const functionsBillingRegistry = new ethers.Contract(config.functionsBillingRegistryAddress, FunctionsBillingRegistryAbi, provider) as FunctionsBillingRegistry const { args } = decodeDietCBOR(data) const currentRequestConfig = { ...requestConfig, args } + const { result, resultLog, success } = await simulateRequest(currentRequestConfig) - if (success) { + if (success) { + console.log('RES', JSON.stringify({ requestId, result })) + // const signer = config.wallet.connect(provider) // const dummySigners = Array(31).fill(signer.address) - // const fulfillAndBill = await functionsBillingRegistry.fulfillAndBill( + // const fulfillAndBill = await functionsBillingRegistry.connect(signer).fulfillAndBill( // requestId, // result, // '0x', @@ -47,11 +43,9 @@ export async function fulfillRequestHandler(input: HandlerInput): Promise // } // ) // await fulfillAndBill.wait() - const fulfillRequestDirect = await upkeep.fulfillRequestDirect(requestId, result) - await fulfillRequestDirect.wait() - if (process.env.USE_LOGS === 'true') { - updateExecutionLog('execution.log', resultLog) - } + // if (process.env.USE_LOGS === 'true') { + // updateExecutionLog('execution.log', resultLog) + // } } else { throw new Error(resultLog) }