Skip to content

Commit

Permalink
feat: ebo request module
Browse files Browse the repository at this point in the history
  • Loading branch information
0xJabberwock committed Aug 13, 2024
1 parent fcfcf26 commit 9ebceb3
Show file tree
Hide file tree
Showing 3 changed files with 357 additions and 0 deletions.
76 changes: 76 additions & 0 deletions src/contracts/EBORequestModule.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import {Module} from '@defi-wonderland/prophet-core/solidity/contracts/Module.sol';
import {IModule} from '@defi-wonderland/prophet-core/solidity/interfaces/IModule.sol';
import {IOracle} from '@defi-wonderland/prophet-core/solidity/interfaces/IOracle.sol';

import {Arbitrable} from 'contracts/Arbitrable.sol';
import {IEBORequestModule} from 'interfaces/IEBORequestModule.sol';

/**
* @title EBORequestModule
* @notice Module allowing users to fetch epoch block data from the oracle
* as a result of a request being created
*/
contract EBORequestModule is Module, Arbitrable, IEBORequestModule {
/// @inheritdoc IEBORequestModule
address public eboRequestCreator;

/**
* @notice Constructor
* @param _oracle The address of the Oracle
* @param _eboRequestCreator The address of the EBORequestCreator
* @param _arbitrator The address of The Graph's Arbitrator
* @param _council The address of The Graph's Council
*/
constructor(
IOracle _oracle,

Check warning on line 28 in src/contracts/EBORequestModule.sol

View workflow job for this annotation

GitHub Actions / Lint Commit Messages

Variable "_oracle" is unused
address _eboRequestCreator,
address _arbitrator,

Check warning on line 30 in src/contracts/EBORequestModule.sol

View workflow job for this annotation

GitHub Actions / Lint Commit Messages

Variable "_arbitrator" is unused
address _council

Check warning on line 31 in src/contracts/EBORequestModule.sol

View workflow job for this annotation

GitHub Actions / Lint Commit Messages

Variable "_council" is unused
) Module(_oracle) Arbitrable(_arbitrator, _council) {
_setEBORequestCreator(_eboRequestCreator);
}

/// @inheritdoc IEBORequestModule
function createRequest(bytes32 _requestId, bytes calldata _data, address _requester) external onlyOracle {
if (_requester != eboRequestCreator) revert EBORequestModule_InvalidRequester();

RequestParameters memory _params = decodeRequestData(_data);

Check warning on line 40 in src/contracts/EBORequestModule.sol

View workflow job for this annotation

GitHub Actions / Lint Commit Messages

Variable "_params" is unused

emit RequestCreated(_requestId, _data, _requester);
}

/// @inheritdoc IEBORequestModule
function setEBORequestCreator(address _eboRequestCreator) external onlyArbitrator {
_setEBORequestCreator(_eboRequestCreator);
}

/// @inheritdoc IModule
function validateParameters(
bytes calldata _encodedParameters
) external view override(IModule, Module) returns (bool _valid) {
RequestParameters memory _params = decodeRequestData(_encodedParameters);

Check warning on line 54 in src/contracts/EBORequestModule.sol

View workflow job for this annotation

GitHub Actions / Lint Commit Messages

Variable "_params" is unused
// TODO: _valid = true;
}

/// @inheritdoc IModule
function moduleName() external pure returns (string memory _moduleName) {
_moduleName = 'EBORequestModule';
}

/// @inheritdoc IEBORequestModule
function decodeRequestData(bytes calldata _data) public pure returns (RequestParameters memory _params) {
_params = abi.decode(_data, (RequestParameters));
}

/**
* @notice Sets the address of the EBORequestCreator
* @param _eboRequestCreator The address of the EBORequestCreator
*/
function _setEBORequestCreator(address _eboRequestCreator) private {
eboRequestCreator = _eboRequestCreator;
emit SetEBORequestCreator(_eboRequestCreator);
}
}
89 changes: 89 additions & 0 deletions src/interfaces/IEBORequestModule.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import {IRequestModule} from '@defi-wonderland/prophet-core/solidity/interfaces/modules/request/IRequestModule.sol';

import {IArbitrable} from 'interfaces/IArbitrable.sol';

/**
* @title EBORequestModule
* @notice Module allowing users to fetch epoch block data from the oracle
* as a result of a request being created
*/
interface IEBORequestModule is IRequestModule, IArbitrable {
/*///////////////////////////////////////////////////////////////
STRUCTS
//////////////////////////////////////////////////////////////*/

/**
* @notice Parameters of the request as stored in the module
*/
struct RequestParameters {
uint256 epoch;
uint256 chainId;
}

/*///////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/

/**
* @notice Emitted when a request is created
* @param _requestId The id of the request
* @param _data The data of the request
* @param _requester The address of the requester
*/
event RequestCreated(bytes32 _requestId, bytes _data, address _requester);

/**
* @notice Emitted when the EBORequestCreator is set
* @param _eboRequestCreator The address of the EBORequestCreator
*/
event SetEBORequestCreator(address _eboRequestCreator);

/*///////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/

/**
* @notice Thrown when the requester is not the EBORequestCreator
*/
error EBORequestModule_InvalidRequester();

/*///////////////////////////////////////////////////////////////
VARIABLES
//////////////////////////////////////////////////////////////*/

/**
* @notice Returns the address of the EBORequestCreator
* @return _eboRequestCreator The address of the EBORequestCreator
*/
function eboRequestCreator() external view returns (address _eboRequestCreator);

/*///////////////////////////////////////////////////////////////
LOGIC
//////////////////////////////////////////////////////////////*/

/**
* @notice Creates a request for RPC data for a specific epoch
* @dev Callable only by the Oracle
* @param _requestId The id of the request
* @param _data The data of the request
* @param _requester The address of the requester
*/
function createRequest(bytes32 _requestId, bytes calldata _data, address _requester) external;

Check warning on line 74 in src/interfaces/IEBORequestModule.sol

View workflow job for this annotation

GitHub Actions / Lint Commit Messages

Function order is incorrect, external function can not go after external view function (line 61)

/**
* @notice Sets the address of the EBORequestCreator
* @dev Callable only by The Graph's Arbitrator
* @param _eboRequestCreator The address of the EBORequestCreator
*/
function setEBORequestCreator(address _eboRequestCreator) external;

/**
* @notice Determines how to decode the inputted request data
* @param _data The encoded request parameters
* @return _params The struct containing the parameters for the request
*/
function decodeRequestData(bytes calldata _data) external pure returns (RequestParameters memory _params);
}
192 changes: 192 additions & 0 deletions test/unit/EBORequestModule.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import {IModule} from '@defi-wonderland/prophet-core/solidity/interfaces/IModule.sol';
import {IOracle} from '@defi-wonderland/prophet-core/solidity/interfaces/IOracle.sol';

import {IArbitrable} from 'interfaces/IArbitrable.sol';
import {IEBORequestModule} from 'interfaces/IEBORequestModule.sol';

import {EBORequestModule} from 'contracts/EBORequestModule.sol';

import 'forge-std/Test.sol';

contract EBORequestModule_Unit_BaseTest is Test {
EBORequestModule public eboRequestModule;

IOracle public oracle;
address public eboRequestCreator;
address public arbitrator;
address public council;

uint256 public constant FUZZED_ARRAY_LENGTH = 32;

event RequestCreated(bytes32 _requestId, bytes _data, address _requester);
event SetEBORequestCreator(address _eboRequestCreator);
// TODO: event RequestFinalized(bytes32 indexed _requestId, IOracle.Response _response, address _finalizer);
event SetArbitrator(address _arbitrator);
event SetCouncil(address _council);

function setUp() public {
oracle = IOracle(makeAddr('Oracle'));
eboRequestCreator = makeAddr('EBORequestCreator');
arbitrator = makeAddr('Arbitrator');
council = makeAddr('Council');

eboRequestModule = new EBORequestModule(oracle, eboRequestCreator, arbitrator, council);
}
}

contract EBORequestModule_Unit_Constructor is EBORequestModule_Unit_BaseTest {
struct ConstructorParams {
IOracle oracle;
address eboRequestCreator;
address arbitrator;
address council;
}

function test_setOracle(ConstructorParams calldata _params) public {
eboRequestModule =
new EBORequestModule(_params.oracle, _params.eboRequestCreator, _params.arbitrator, _params.council);

assertEq(address(eboRequestModule.ORACLE()), address(_params.oracle));
}

function test_setArbitrator(ConstructorParams calldata _params) public {
eboRequestModule =
new EBORequestModule(_params.oracle, _params.eboRequestCreator, _params.arbitrator, _params.council);

assertEq(eboRequestModule.arbitrator(), _params.arbitrator);
}

function test_emitSetArbitrator(ConstructorParams calldata _params) public {
vm.expectEmit();
emit SetArbitrator(_params.arbitrator);
new EBORequestModule(_params.oracle, _params.eboRequestCreator, _params.arbitrator, _params.council);
}

function test_setCouncil(ConstructorParams calldata _params) public {
eboRequestModule =
new EBORequestModule(_params.oracle, _params.eboRequestCreator, _params.arbitrator, _params.council);

assertEq(eboRequestModule.council(), _params.council);
}

function test_emitSetCouncil(ConstructorParams calldata _params) public {
vm.expectEmit();
emit SetCouncil(_params.council);
new EBORequestModule(_params.oracle, _params.eboRequestCreator, _params.arbitrator, _params.council);
}

function test_setEBORequestCreator(ConstructorParams calldata _params) public {
eboRequestModule =
new EBORequestModule(_params.oracle, _params.eboRequestCreator, _params.arbitrator, _params.council);

assertEq(eboRequestModule.eboRequestCreator(), _params.eboRequestCreator);
}

function test_emitSetEBORequestCreator(ConstructorParams calldata _params) public {
vm.expectEmit();
emit SetEBORequestCreator(_params.eboRequestCreator);
new EBORequestModule(_params.oracle, _params.eboRequestCreator, _params.arbitrator, _params.council);
}
}

contract EBORequestModule_Unit_CreateRequest is EBORequestModule_Unit_BaseTest {
struct CreateRequestParams {
bytes32 requestId;
IEBORequestModule.RequestParameters requestData;
address requester;
}

modifier happyPath(CreateRequestParams memory _params) {
_params.requester = eboRequestCreator;

vm.startPrank(address(oracle));
_;
}

function test_revertOnlyOracle(CreateRequestParams memory _params) public happyPath(_params) {
vm.stopPrank();

bytes memory _encodedParams = abi.encode(_params.requestData);

vm.expectRevert(IModule.Module_OnlyOracle.selector);
eboRequestModule.createRequest(_params.requestId, _encodedParams, _params.requester);
}

function test_revertInvalidRequester(
CreateRequestParams memory _params,
address _requester
) public happyPath(_params) {
vm.assume(_requester != eboRequestCreator);
_params.requester = _requester;

bytes memory _encodedParams = abi.encode(_params.requestData);

vm.expectRevert(IEBORequestModule.EBORequestModule_InvalidRequester.selector);
eboRequestModule.createRequest(_params.requestId, _encodedParams, _params.requester);
}

function test_emitRequestCreated(CreateRequestParams memory _params) public happyPath(_params) {
bytes memory _encodedParams = abi.encode(_params.requestData);

vm.expectEmit();
emit RequestCreated(_params.requestId, _encodedParams, _params.requester);
eboRequestModule.createRequest(_params.requestId, _encodedParams, _params.requester);
}
}

contract EBORequestModule_Unit_SetEBORequestCreator is EBORequestModule_Unit_BaseTest {
modifier happyPath() {
vm.startPrank(arbitrator);
_;
}

function test_revertOnlyArbitrator(address _eboRequestCreator) public happyPath {
vm.stopPrank();
vm.expectRevert(IArbitrable.Arbitrable_OnlyArbitrator.selector);
eboRequestModule.setEBORequestCreator(_eboRequestCreator);
}

function test_setEBORequestCreator(address _eboRequestCreator) public happyPath {
eboRequestModule.setEBORequestCreator(_eboRequestCreator);

assertEq(eboRequestModule.eboRequestCreator(), _eboRequestCreator);
}

function test_emitSetEBORequestCreator(address _eboRequestCreator) public happyPath {
vm.expectEmit();
emit SetEBORequestCreator(_eboRequestCreator);
eboRequestModule.setEBORequestCreator(_eboRequestCreator);
}
}

contract EBORequestModule_Unit_ValidateParameters is EBORequestModule_Unit_BaseTest {
function test_returnInvalidParams(IEBORequestModule.RequestParameters memory _params) public view {
bytes memory _encodedParams = abi.encode(_params);

assertFalse(eboRequestModule.validateParameters(_encodedParams));
}

function test_returnValidParams(IEBORequestModule.RequestParameters memory _params) public view {
bytes memory _encodedParams = abi.encode(_params);

Check warning on line 173 in test/unit/EBORequestModule.t.sol

View workflow job for this annotation

GitHub Actions / Lint Commit Messages

Variable "_encodedParams" is unused

// TODO: assertTrue(eboRequestModule.validateParameters(_encodedParams));
}
}

contract EBORequestModule_Unit_ModuleName is EBORequestModule_Unit_BaseTest {
function test_returnModuleName() public view {
assertEq(eboRequestModule.moduleName(), 'EBORequestModule');
}
}

contract EBORequestModule_Unit_DecodeRequestData is EBORequestModule_Unit_BaseTest {
function test_returnDecodedParams(IEBORequestModule.RequestParameters calldata _params) public view {
bytes memory _encodedParams = abi.encode(_params);
IEBORequestModule.RequestParameters memory _decodedParams = eboRequestModule.decodeRequestData(_encodedParams);

assertEq(abi.encode(_decodedParams), abi.encode(_params));
}
}

0 comments on commit 9ebceb3

Please sign in to comment.