diff --git a/contracts/global/LagrangeDistributor.sol b/contracts/global/LagrangeDistributor.sol index a66e95b..1a7cc27 100644 --- a/contracts/global/LagrangeDistributor.sol +++ b/contracts/global/LagrangeDistributor.sol @@ -5,9 +5,8 @@ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@1inch/solidity-utils/contracts/libraries/SafeERC20.sol"; -import {ILPNClient} from "../interfaces/lagrange/ILPNClient.sol"; -import {ILPNRegistry} from "../interfaces/lagrange/ILPNRegistry.sol"; -import {QueryParams} from "../interfaces/lagrange/QueryParams.sol"; +import {ILPNClientV1} from "../interfaces/lagrange/ILPNClientV1.sol"; +import {ILPNRegistryV1, QueryOutput} from "../interfaces/lagrange/ILPNRegistryV1.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; struct RewardData { @@ -57,10 +56,19 @@ interface ILagrangeDistributorExceptions { /// @dev Precision for the propotional balance integral uint256 constant PROPORTIONAL_BALANCE_PRECISION = 10 ** 18; -contract LagrangeDistributor is Ownable, ILPNClient, ILagrangeDistributorExceptions, ILagrangeDistributorEvents { - using QueryParams for QueryParams.ERC20QueryParams; +contract LagrangeDistributor is Ownable, ILPNClientV1, ILagrangeDistributorExceptions, ILagrangeDistributorEvents { using SafeERC20 for IERC20; + /// @notice Columns expected in the query result + struct ExpectedResultRow { + uint256 integral; + } + + // TODO: Register a query and fill this in + /// @notice The query hash corresponding to a proportionate balance query of a particular ERC20 table + bytes32 public constant GEARBOX_PROPORTIONATE_BALANCE_QUERY_HASH = + 0x0000000000000000000000000000000000000000000000000000000000000000; + /// @notice Address of the LPN registry address public immutable lpnRegistry; @@ -92,11 +100,14 @@ contract LagrangeDistributor is Ownable, ILPNClient, ILagrangeDistributorExcepti /// @notice Callback function called by the LPNRegistry contract. /// @param requestId The ID of the request. - /// @param results The result of the request. - function lpnCallback(uint256 requestId, uint256[] calldata results) external lpnRegistryOnly { + /// @param result The result of the request. + function lpnCallback(uint256 requestId, QueryOutput calldata result) external lpnRegistryOnly { uint256 campaignId = requestData[requestId].campaignId; address holder = requestData[requestId].holder; - uint256 integral = results[0]; + + if (result.rows.length == 0) return; + + uint256 integral = abi.decode(result.rows[0], (ExpectedResultRow)).integral; if (integral == 0) return; @@ -130,11 +141,12 @@ contract LagrangeDistributor is Ownable, ILPNClient, ILagrangeDistributorExcepti endBlock = block.number > endBlock ? endBlock : block.number; endBlock = endBlock - 1; - uint256 requestId = ILPNRegistry(lpnRegistry).request{value: ILPNRegistry(lpnRegistry).gasFee()}( - queriedToken, - QueryParams.newERC20QueryParams(holder, uint88(PROPORTIONAL_BALANCE_PRECISION)).toBytes32(), - startBlock, - endBlock + bytes32[] memory placeholders = new bytes32[](2); + placeholders[0] = bytes32(bytes20(holder)); + placeholders[1] = bytes32(PROPORTIONAL_BALANCE_PRECISION); + + uint256 requestId = ILPNRegistryV1(lpnRegistry).request{value: ILPNRegistryV1(lpnRegistry).gasFee()}( + GEARBOX_PROPORTIONATE_BALANCE_QUERY_HASH, placeholders, startBlock, endBlock ); _campaigns[campaignId].blockLU[holder] = block.number; diff --git a/contracts/interfaces/lagrange/ILPNClient.sol b/contracts/interfaces/lagrange/ILPNClientV1.sol similarity index 54% rename from contracts/interfaces/lagrange/ILPNClient.sol rename to contracts/interfaces/lagrange/ILPNClientV1.sol index d95c049..4238006 100644 --- a/contracts/interfaces/lagrange/ILPNClient.sol +++ b/contracts/interfaces/lagrange/ILPNClientV1.sol @@ -1,14 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +import {QueryOutput} from "./ILPNRegistryV1.sol"; + /** * @title ILPNClient * @notice Interface for the LPNClientV0 contract. */ -interface ILPNClient { +interface ILPNClientV1 { /// @notice Callback function called by the LPNRegistry contract. /// @param requestId The ID of the request. - /// @param results The result of the request. - function lpnCallback(uint256 requestId, uint256[] calldata results) - external; -} \ No newline at end of file + /// @param result The result of the request. + function lpnCallback(uint256 requestId, QueryOutput calldata result) external; +} diff --git a/contracts/interfaces/lagrange/ILPNRegistry.sol b/contracts/interfaces/lagrange/ILPNRegistryV1.sol similarity index 52% rename from contracts/interfaces/lagrange/ILPNRegistry.sol rename to contracts/interfaces/lagrange/ILPNRegistryV1.sol index 48dbf72..f0ae4e8 100644 --- a/contracts/interfaces/lagrange/ILPNRegistry.sol +++ b/contracts/interfaces/lagrange/ILPNRegistryV1.sol @@ -1,35 +1,33 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -/// @title ILPNRegistry -/// @notice Interface for the LPNRegistryV0 contract. -interface ILPNRegistry { - /// @notice Event emitted when a new client registers. - /// @param storageContract The address of the smart contract to be indexed. - /// @param client The address of the client who requested this contract to be indexed. - /// @param mappingSlot The storage slot of the client's mapping to be computed and proved over. - /// @param lengthSlot The storage slot of the variable storing the length of the client's mapping. - event NewRegistration( - address indexed storageContract, address indexed client, uint256 mappingSlot, uint256 lengthSlot - ); +/// The query output struct returned from the processQuery function +struct QueryOutput { + // Total number of the all matching rows + uint256 totalMatchedRows; + // Returned rows of the current cursor + bytes[] rows; +} +/// @title IQueryManager +/// @notice +interface IQueryManager { /// @notice Event emitted when a new request is made. /// @param requestId The ID of the request. - /// @param storageContract The address of the smart contract with the storage associated with the request. + /// @param queryHash The identifier of the SQL query associated with the request. /// @param client The address of the client who made this request. - /// @param params The query params associated with this query type. + /// @param placeholders Values for the numbered placeholders in the query. /// @param startBlock The starting block for the computation. /// @param endBlock The ending block for the computation. /// @param proofBlock The requested block for the proof to be computed against. /// Currently required for OP Stack chains event NewRequest( uint256 indexed requestId, - address indexed storageContract, + bytes32 indexed queryHash, address indexed client, - bytes32 params, + bytes32[] placeholders, uint256 startBlock, uint256 endBlock, - uint256 offset, uint256 gasFee, uint256 proofBlock ); @@ -37,25 +35,16 @@ interface ILPNRegistry { /// @notice Event emitted when a response is received. /// @param requestId The ID of the request. /// @param client The address of the client who made the matching request. - /// @param results The computed results for the request. - event NewResponse(uint256 indexed requestId, address indexed client, uint256[] results); - - /// @notice The gas fee paid for on request to reimburse the response transaction. - function gasFee() external returns (uint256); - - /// @notice Registers a client with the provided mapping and length slots. - /// @param storageContract The address of the contract to be queried. - /// @param mappingSlot The storage slot of the client's mapping to be computed and proved over. - /// @param lengthSlot The storage slot of the variable storing the length of the client's mapping. - function register(address storageContract, uint256 mappingSlot, uint256 lengthSlot) external; + /// @param result The computed results for the request. + event NewResponse(uint256 indexed requestId, address indexed client, QueryOutput result); /// @notice Submits a new request to the registry. - /// @param storageContract The address of the smart contract with the storage associated with the request. - /// @param params The query params associated with this query type. + /// @param queryHash The identifier of the SQL query associated with the request. + /// @param placeholders Values for the numbered placeholders in the query. /// @param startBlock The starting block for the computation. /// @param endBlock The ending block for the computation. /// @return The ID of the newly created request. - function request(address storageContract, bytes32 params, uint256 startBlock, uint256 endBlock) + function request(bytes32 queryHash, bytes32[] calldata placeholders, uint256 startBlock, uint256 endBlock) external payable returns (uint256); @@ -69,3 +58,25 @@ interface ILPNRegistry { /// @param blockNumber The block number of the block hash corresponding to the proof. function respond(uint256 requestId_, bytes32[] calldata data, uint256 blockNumber) external; } + +/// @title IRegistrationManager +/// @notice +interface IRegistrationManager { + event NewTableRegistration( + bytes32 indexed hash, + address indexed contractAddr, + uint256 chainId, + uint256 genesisBlock, + string name, + string schema + ); + + event NewQueryRegistration(bytes32 indexed hash, bytes32 indexed tableHash, string sql); + + function registerQuery(bytes32 hash, bytes32 tableHash, string calldata sql) external; +} + +interface ILPNRegistryV1 is IQueryManager, IRegistrationManager { + /// @notice The gas fee paid for on request to reimburse the response transaction. + function gasFee() external returns (uint256); +}