generated from defi-wonderland/solidity-foundry-boilerplate
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fcfcf26
commit 9ebceb3
Showing
3 changed files
with
357 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
address _eboRequestCreator, | ||
address _arbitrator, | ||
address _council | ||
) 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); | ||
|
||
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); | ||
// 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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
|
||
/** | ||
* @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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
|
||
// 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)); | ||
} | ||
} |