From 3e795ce4df6325175ff339041a6b4a0d89029397 Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Tue, 30 Jul 2024 23:06:54 -0300 Subject: [PATCH 01/19] feat: owner --- foundry.toml | 2 +- script/Deploy.sol | 33 ----- src/contracts/EBORequestCreator.sol | 116 +++++++++++++++++ src/contracts/Greeter.sol | 59 --------- src/interfaces/IEBORequestCreator.sol | 153 ++++++++++++++++++++++ src/interfaces/IGreeter.sol | 74 ----------- test/integration/Greeter.t.sol | 16 --- test/integration/IntegrationBase.sol | 5 +- test/invariants/fuzz/Greeter.t.sol | 37 ------ test/invariants/symbolic/Greeter.t.sol | 58 --------- test/unit/EBORequestCreator.t.sol | 172 +++++++++++++++++++++++++ test/unit/Greeter.t.sol | 99 -------------- test/unit/Greeter.tree | 25 ---- yarn.lock | 13 -- 14 files changed, 443 insertions(+), 419 deletions(-) delete mode 100644 script/Deploy.sol create mode 100644 src/contracts/EBORequestCreator.sol delete mode 100644 src/contracts/Greeter.sol create mode 100644 src/interfaces/IEBORequestCreator.sol delete mode 100644 src/interfaces/IGreeter.sol delete mode 100644 test/integration/Greeter.t.sol delete mode 100644 test/invariants/fuzz/Greeter.t.sol delete mode 100644 test/invariants/symbolic/Greeter.t.sol create mode 100644 test/unit/EBORequestCreator.t.sol delete mode 100644 test/unit/Greeter.t.sol delete mode 100644 test/unit/Greeter.tree diff --git a/foundry.toml b/foundry.toml index b9d9beb..95bed70 100644 --- a/foundry.toml +++ b/foundry.toml @@ -9,7 +9,7 @@ multiline_func_header = 'params_first' sort_imports = true [profile.default] -solc_version = '0.8.23' +solc_version = '0.8.26' libs = ['node_modules', 'lib'] optimizer_runs = 10_000 diff --git a/script/Deploy.sol b/script/Deploy.sol deleted file mode 100644 index 7ce78e9..0000000 --- a/script/Deploy.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.23; - -import {Greeter} from 'contracts/Greeter.sol'; -import {Script} from 'forge-std/Script.sol'; -import {IERC20} from 'forge-std/interfaces/IERC20.sol'; - -contract Deploy is Script { - struct DeploymentParams { - string greeting; - IERC20 token; - } - - /// @notice Deployment parameters for each chain - mapping(uint256 _chainId => DeploymentParams _params) internal _deploymentParams; - - function setUp() public { - // Mainnet - _deploymentParams[1] = DeploymentParams('Hello, Mainnet!', IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)); - - // Sepolia - _deploymentParams[11_155_111] = - DeploymentParams('Hello, Sepolia!', IERC20(0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6)); - } - - function run() public { - DeploymentParams memory _params = _deploymentParams[block.chainid]; - - vm.startBroadcast(); - new Greeter(_params.greeting, _params.token); - vm.stopBroadcast(); - } -} diff --git a/src/contracts/EBORequestCreator.sol b/src/contracts/EBORequestCreator.sol new file mode 100644 index 0000000..3a4c822 --- /dev/null +++ b/src/contracts/EBORequestCreator.sol @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; + +import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; +import {IEBORequestCreator} from 'interfaces/IEBORequestCreator.sol'; + +contract EBORequestCreator is IEBORequestCreator { + using EnumerableSet for EnumerableSet.Bytes32Set; + + // /// @inheritdoc IEBORequestCreator + // IOracle public oracle; + + /// @inheritdoc IEBORequestCreator + address public owner; + + /// @inheritdoc IEBORequestCreator + address public pendingOwner; + + /// @inheritdoc IEBORequestCreator + uint256 public reward; + + /** + * @notice The list of chain ids + */ + EnumerableSet.Bytes32Set internal _chainIds; + + constructor(address _owner) { + // oracle = _oracle; + + owner = _owner; + reward = 0; + } + + /// @inheritdoc IEBORequestCreator + function setPendingOwner(address _pendingOwner) external onlyOwner { + pendingOwner = _pendingOwner; + + emit PendingOwnerSetted(_pendingOwner); + } + + /// @inheritdoc IEBORequestCreator + function acceptPendingOwner() external onlyPendingOwner { + address _oldOwner = owner; + owner = pendingOwner; + pendingOwner = address(0); + + emit OwnerSetted(_oldOwner, owner); + } + + /// @inheritdoc IEBORequestCreator + function createRequest( + address _requester, + address _target, + bytes calldata _data, + uint256 _value, + uint256 _nonce + ) external returns (bytes32 _requestId) { + // emit RequestCreated(_requestId, _requester, _target, _data, _value, _nonce); + } + + /// @inheritdoc IEBORequestCreator + function addChain(string calldata _chainId) external onlyOwner { + if (!_chainIds.add(_chaindIdToBytes32(_chainId))) { + revert EBORequestCreator_ChainAlreadyAdded(); + } + emit ChainAdded(_chainId); + } + + /// @inheritdoc IEBORequestCreator + function removeChain(string calldata _chainId) external onlyOwner { + if (!_chainIds.remove(_chaindIdToBytes32(_chainId))) { + revert EBORequestCreator_ChainNotAdded(); + } + emit ChainRemoved(_chainId); + } + + /// @inheritdoc IEBORequestCreator + function setReward(uint256 _reward) external onlyOwner { + uint256 _oldReward = reward; + reward = _reward; + emit RewardSet(_oldReward, _reward); + } + + /// @inheritdoc IEBORequestCreator + function getChainIds() external view returns (string[] memory _chainIdsValues) { + bytes32[] memory _chainIdsBytes = _chainIds.values(); + + for (uint256 _i; _i < _chainIdsBytes.length; _i++) { + _chainIdsValues[_i] = _chaindIdToString(_chainIdsBytes[_i]); + } + } + + function _chaindIdToBytes32(string memory _chainId) internal pure returns (bytes32 _convertedChainId) { + assembly { + _convertedChainId := mload(add(_chainId, 32)) + } + } + + function _chaindIdToString(bytes32 _chainId) internal pure returns (string memory _convertedChainId) { + _convertedChainId = string(abi.encodePacked(_chainId)); + } + + modifier onlyOwner() { + if (msg.sender != owner) { + revert EBORequestCreator_OnlyOwner(); + } + _; + } + + modifier onlyPendingOwner() { + if (msg.sender != pendingOwner) { + revert EBORequestCreator_OnlyPendingOwner(); + } + _; + } +} diff --git a/src/contracts/Greeter.sol b/src/contracts/Greeter.sol deleted file mode 100644 index 7167b5c..0000000 --- a/src/contracts/Greeter.sol +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.23; - -import {IERC20} from 'forge-std/interfaces/IERC20.sol'; -import {IGreeter} from 'interfaces/IGreeter.sol'; - -contract Greeter is IGreeter { - /** - * @notice Empty string for revert checks - * @dev result of doing keccak256(bytes('')) - */ - bytes32 internal constant _EMPTY_STRING = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; - - /// @inheritdoc IGreeter - address public immutable OWNER; - - /// @inheritdoc IGreeter - string public greeting; - - /// @inheritdoc IGreeter - IERC20 public token; - - /** - * @notice Reverts in case the function was not called by the owner of the contract - */ - modifier onlyOwner() { - if (msg.sender != OWNER) { - revert Greeter_OnlyOwner(); - } - _; - } - - /** - * @notice Defines the owner to the msg.sender and sets the initial greeting - * @param _greeting Initial greeting - * @param _token Initial token - */ - constructor(string memory _greeting, IERC20 _token) { - OWNER = msg.sender; - token = _token; - setGreeting(_greeting); - } - - /// @inheritdoc IGreeter - function greet() external view returns (string memory _greeting, uint256 _balance) { - _greeting = greeting; - _balance = token.balanceOf(msg.sender); - } - - /// @inheritdoc IGreeter - function setGreeting(string memory _greeting) public onlyOwner { - if (keccak256(bytes(_greeting)) == _EMPTY_STRING) { - revert Greeter_InvalidGreeting(); - } - - greeting = _greeting; - emit GreetingSet(_greeting); - } -} diff --git a/src/interfaces/IEBORequestCreator.sol b/src/interfaces/IEBORequestCreator.sol new file mode 100644 index 0000000..44e670d --- /dev/null +++ b/src/interfaces/IEBORequestCreator.sol @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; + +// import {IOracle} from '@defi-wonderland/prophet-core-contracts/solidity/interfaces/IOracle.sol'; + +interface IEBORequestCreator { + /*/////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Emitted when the pending owner is set + * @param _pendingOwner The address of the pending owner + */ + event PendingOwnerSetted(address _pendingOwner); + + /** + * @notice Emitted when the owner is set + * @param _oldOwner The old owner address + * @param _newOwner The new owner address + */ + event OwnerSetted(address _oldOwner, address _newOwner); + + /** + * @notice Emitted when a request is created + * @param _epoch The epoch of the request + * @param _chainId The chain id of the request + */ + event RequestCreated(uint256 _epoch, uint256 _chainId); + + /** + * @notice Emitted when a chain is added + * @param _chainId The chain id added + */ + event ChainAdded(string _chainId); + + /** + * @notice Emitted when a chain is removed + * @param _chainId The chain id removed + */ + event ChainRemoved(string _chainId); + + /** + * @notice Emitted when the reward is set + * @param _oldReward The old reward value + * @param _newReward The new reward value + */ + event RewardSet(uint256 _oldReward, uint256 _newReward); + + /*/////////////////////////////////////////////////////////////// + ERRORS + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Thrown when the caller is not the owner + */ + error EBORequestCreator_OnlyOwner(); + + /** + * @notice Thrown when the caller is not the pending owner + */ + error EBORequestCreator_OnlyPendingOwner(); + + /** + * @notice hrown when the chain is already added + */ + error EBORequestCreator_ChainAlreadyAdded(); + + /** + * @notice Thrown when the chain is not added + */ + error EBORequestCreator_ChainNotAdded(); + + /*/////////////////////////////////////////////////////////////// + VARIABLES + //////////////////////////////////////////////////////////////*/ + + // /** + // * @notice The oracle contract + // */ + // function oracle() external view returns (IOracle _oracle); + + /** + * @notice The owner of the contract + */ + function owner() external view returns (address _owner); + + /** + * @notice The pending owner of the contract + */ + function pendingOwner() external view returns (address _pendingOwner); + + /** + * @notice The reward paid for each chain updated + */ + function reward() external view returns (uint256 _reward); + + /*/////////////////////////////////////////////////////////////// + LOGIC + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Set the pending owner + * @param _pendingOwner The address of the pending owner + */ + function setPendingOwner(address _pendingOwner) external; + + /** + * @notice Accept the pending owner + */ + function acceptPendingOwner() external; + + /** + * @notice Create a request + * @param _requester The address of the requester + * @param _target The address of the target + * @param _data The data of the request + * @param _value The value of the request + * @param _nonce The nonce of the request + * @return _requestId The id of the request + */ + function createRequest( + address _requester, + address _target, + bytes calldata _data, + uint256 _value, + uint256 _nonce + ) external returns (bytes32 _requestId); + + /** + * @notice Add a chain to the allowed chains which can be updated + * @param _chainId The chain id to add + */ + function addChain(string calldata _chainId) external; + + /** + * @notice Remove a chain from the allowed chains which can be updated + * @param _chainId The chain id to remove + */ + function removeChain(string calldata _chainId) external; + + /** + * @notice Set the reward paid for each chain updated + * @param _reward The reward to set + */ + function setReward(uint256 _reward) external; + + /** + * @notice Get the chain ids + * @return _chainIdsValues The chain ids + */ + function getChainIds() external view returns (string[] memory _chainIdsValues); +} diff --git a/src/interfaces/IGreeter.sol b/src/interfaces/IGreeter.sol deleted file mode 100644 index 53b4a64..0000000 --- a/src/interfaces/IGreeter.sol +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.23; - -import {IERC20} from 'forge-std/interfaces/IERC20.sol'; - -/** - * @title Greeter Contract - * @author Wonderland - * @notice This is a basic contract created in order to portray some - * best practices and foundry functionality. - */ -interface IGreeter { - /*/////////////////////////////////////////////////////////////// - EVENTS - //////////////////////////////////////////////////////////////*/ - /** - * @notice Greeting has changed - * @param _greeting The new greeting - */ - event GreetingSet(string _greeting); - - /*/////////////////////////////////////////////////////////////// - ERRORS - //////////////////////////////////////////////////////////////*/ - /** - * @notice Throws if the function was called by someone else than the owner - */ - error Greeter_OnlyOwner(); - - /** - * @notice Throws if the greeting set is invalid - * @dev Empty string is an invalid greeting - */ - error Greeter_InvalidGreeting(); - - /*/////////////////////////////////////////////////////////////// - VARIABLES - //////////////////////////////////////////////////////////////*/ - /** - * @notice Returns the owner of the contract - * @dev The owner will always be the deployer of the contract - * @return _owner The owner of the contract - */ - function OWNER() external view returns (address _owner); - - /** - * @notice Returns the previously set greeting - * @return _greet The greeting - */ - function greeting() external view returns (string memory _greet); - - /** - * @notice Returns the token used to greet callers - * @return _token The address of the token - */ - function token() external view returns (IERC20 _token); - - /*/////////////////////////////////////////////////////////////// - LOGIC - //////////////////////////////////////////////////////////////*/ - /** - * @notice Sets a new greeting - * @dev Only callable by the owner - * @param _newGreeting The new greeting to be set - */ - function setGreeting(string memory _newGreeting) external; - - /** - * @notice Greets the caller - * @return _greeting The greeting - * @return _balance Current token balance of the caller - */ - function greet() external view returns (string memory _greeting, uint256 _balance); -} diff --git a/test/integration/Greeter.t.sol b/test/integration/Greeter.t.sol deleted file mode 100644 index b0e3799..0000000 --- a/test/integration/Greeter.t.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.23; - -import {IntegrationBase} from 'test/integration/IntegrationBase.sol'; - -contract IntegrationGreeter is IntegrationBase { - function test_Greet() public { - uint256 _whaleBalance = _dai.balanceOf(_daiWhale); - - vm.prank(_daiWhale); - (string memory _greeting, uint256 _balance) = _greeter.greet(); - - assertEq(_whaleBalance, _balance); - assertEq(_initialGreeting, _greeting); - } -} diff --git a/test/integration/IntegrationBase.sol b/test/integration/IntegrationBase.sol index b043f49..0569527 100644 --- a/test/integration/IntegrationBase.sol +++ b/test/integration/IntegrationBase.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.23; +pragma solidity 0.8.26; -import {Greeter, IGreeter} from 'contracts/Greeter.sol'; import {Test} from 'forge-std/Test.sol'; import {IERC20} from 'forge-std/interfaces/IERC20.sol'; @@ -13,11 +12,9 @@ contract IntegrationBase is Test { address internal _owner = makeAddr('owner'); address internal _daiWhale = 0x42f8CA49E88A8fd8F0bfA2C739e648468b8f9dec; IERC20 internal _dai = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F); - IGreeter internal _greeter; function setUp() public { vm.createSelectFork(vm.rpcUrl('mainnet'), _FORK_BLOCK); vm.prank(_owner); - _greeter = new Greeter(_initialGreeting, _dai); } } diff --git a/test/invariants/fuzz/Greeter.t.sol b/test/invariants/fuzz/Greeter.t.sol deleted file mode 100644 index 96e2b1e..0000000 --- a/test/invariants/fuzz/Greeter.t.sol +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.23; - -import {Greeter, IERC20} from 'contracts/Greeter.sol'; - -interface IHevm { - function prank(address) external; -} - -contract InvariantGreeter { - IHevm internal _hevm = IHevm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); - - Greeter internal _targetContract; - - constructor() { - _targetContract = new Greeter('a', IERC20(address(1))); - } - - function checkGreeterNeverEmpty(string memory _newGreeting) public { - // Execution - (bool _success,) = address(_targetContract).call(abi.encodeCall(Greeter.setGreeting, _newGreeting)); - - // Check output condition - assert((_success && keccak256(bytes(_targetContract.greeting())) != keccak256(bytes(''))) || !_success); - } - - function checkOnlyOwnerSetsGreeting(address _caller) public { - // Input conditions - _hevm.prank(_caller); - - // Execution - (bool _success,) = address(this).call(abi.encodeCall(Greeter.setGreeting, 'hello')); - - // Check output condition - assert((_success && msg.sender == _targetContract.OWNER()) || (!_success && msg.sender != _targetContract.OWNER())); - } -} diff --git a/test/invariants/symbolic/Greeter.t.sol b/test/invariants/symbolic/Greeter.t.sol deleted file mode 100644 index 16a7edd..0000000 --- a/test/invariants/symbolic/Greeter.t.sol +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.23; - -import {Greeter, IERC20} from 'contracts/Greeter.sol'; - -import {Test} from 'forge-std/Test.sol'; -import {SymTest} from 'halmos-cheatcodes/src/SymTest.sol'; // See https://github.com/a16z/halmos-cheatcodes?tab=readme-ov-file - -contract SymbolicGreeter is SymTest, Test { - Greeter public targetContract; - - function setUp() public { - string memory _initialGreeting = svm.createString(64, 'initial greeting'); - address _token = svm.createAddress('token'); - - targetContract = new Greeter(_initialGreeting, IERC20(_token)); - } - - function check_validState_greeterNeverEmpty(address _caller) public { - // Input conditions: any caller - vm.prank(_caller); - - // Execution: Halmos cannot use a dynamic-sized array, iterate over multiple string lengths - bool _success; - for (uint256 i = 1; i < 3; i++) { - string memory greeting = svm.createString(i, 'greeting'); - (_success,) = address(targetContract).call(abi.encodeCall(Greeter.setGreeting, (greeting))); - - // Output condition check - vm.assume(_success); // discard failing calls - assert(keccak256(bytes(targetContract.greeting())) != keccak256(bytes(''))); - } - - // Add the empty string (bypass the non-empty check of svm.createString) - (_success,) = address(targetContract).call(abi.encodeCall(Greeter.setGreeting, (''))); - - // Output condition check - vm.assume(_success); // discard failing calls - assert(keccak256(bytes(targetContract.greeting())) != keccak256(bytes(''))); - } - - function check_setGreeting_onlyOwnerSetsGreeting(address _caller) public { - // Input conditions - string memory _newGreeting = svm.createString(64, 'new greeting'); - - // Execution - vm.prank(_caller); - (bool _success,) = address(targetContract).call(abi.encodeCall(Greeter.setGreeting, (_newGreeting))); - - // Output condition check - if (_success) { - assert(_caller == targetContract.OWNER()); - assert(keccak256(bytes(targetContract.greeting())) == keccak256(bytes(_newGreeting))); - } else { - assert(_caller != targetContract.OWNER() || keccak256(bytes(_newGreeting)) == keccak256(bytes(''))); - } - } -} diff --git a/test/unit/EBORequestCreator.t.sol b/test/unit/EBORequestCreator.t.sol new file mode 100644 index 0000000..2e47326 --- /dev/null +++ b/test/unit/EBORequestCreator.t.sol @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; + +import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; + +import {EBORequestCreator, IEBORequestCreator} from 'contracts/EBORequestCreator.sol'; + +import {Test} from 'forge-std/Test.sol'; + +contract EBORequestCreatorForTest is EBORequestCreator { + using EnumerableSet for EnumerableSet.Bytes32Set; + + constructor() EBORequestCreator(owner) {} + + function setChainIdForTest(string calldata _chainId) external { + _chainIds.add(_chaindIdToBytes32(_chainId)); + } +} + +// abstract contract EBORequestCreatorUnitTest is Test { +// /// Events +// event RequestCreated(uint256 _epoch, uint256 _chainId); +// event ChainAdded(uint256 _chainId); +// event ChainRemoved(uint256 _chainId); +// event RewardSet(uint256 _oldReward, uint256 _newReward); + +// /// Contracts +// EBORequestCreatorForTest public eboRequestCreator; +// // IOracle public oracle; + +// /// EOAs +// address public owner; + +// function setUp() external { +// owner = makeAddr('Owner'); +// // oracle = IOracle(makeAddr('Oracle')); + +// vm.prank(owner); +// eboRequestCreator = new EBORequestCreatorForTest(); +// } +// } + +// contract UnitEBORequestCreatorConstructor is EBORequestCreatorUnitTest { +// function testConstructor() external view { +// assertEq(eboRequestCreator.reward(), 0); +// assertEq(eboRequestCreator.owner(), owner); +// assertEq(eboRequestCreator.pendingOwner(), address(0)); +// // assertEq(eboRequestCreator.oracle(), oracle); +// } +// } + +// // contract UnitEBORequestCreatorCreateRequest is EBORequestCreatorUnitTest { +// // function test_CreateRequest() external { +// // bytes32 requestId = eboRequestCreator.createRequest(address(this), address(this), '0x', 0, 0); +// // assertEq(uint256(requestId), uint256(keccak256(abi.encodePacked(address(this), address(this), '0x', 0, 0))); +// // } +// // } + +// contract UnitEBORequestCreatorAddChain is EBORequestCreatorUnitTest { +// modifier happyPath() { +// vm.startPrank(owner); +// _; +// } + +// function testRevertIfNotOwner(uint256 _chainId) external { +// vm.expectRevert(); +// eboRequestCreator.addChain(_chainId); +// } + +// function testRevertIfChainAdded(uint256 _chainId) external happyPath { +// eboRequestCreator.setChainIdForTest(_chainId); + +// vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_ChainAlreadyAdded.selector, _chainId)); +// eboRequestCreator.addChain(_chainId); +// } + +// function testAddChain(uint256 _chainId) external happyPath { +// eboRequestCreator.addChain(_chainId); + +// assertEq(eboRequestCreator.getChainIds().length, 1); +// assertEq(eboRequestCreator.getChainIds()[0], _chainId); +// } + +// function testEmitChainAdded(uint256 _chainId) external happyPath { +// vm.expectEmit(); +// emit ChainAdded(_chainId); + +// eboRequestCreator.addChain(_chainId); +// } +// } + +// contract UnitEBORequestCreatorRemoveChain is EBORequestCreatorUnitTest { +// modifier happyPath(uint256 _chainId) { +// eboRequestCreator.setChainIdForTest(_chainId); +// vm.startPrank(owner); +// _; +// } + +// function testRevertIfNotOwner(uint256 _chainId) external { +// vm.expectRevert(); +// eboRequestCreator.removeChain(_chainId); +// } + +// function testRevertIfChainNotAdded(uint256 _chainId) external { +// vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_ChainNotAdded.selector, _chainId)); + +// vm.prank(owner); +// eboRequestCreator.removeChain(_chainId); +// } + +// function testRemoveChain(uint256 _chainId) external happyPath(_chainId) { +// eboRequestCreator.removeChain(_chainId); + +// assertEq(eboRequestCreator.getChainIds().length, 0); +// } + +// function testEmitChainRemoved(uint256 _chainId) external happyPath(_chainId) { +// vm.expectEmit(); +// emit ChainRemoved(_chainId); + +// eboRequestCreator.removeChain(_chainId); +// } +// } + +// contract UnitEBORequestCreatorSetReward is EBORequestCreatorUnitTest { +// modifier happyPath(uint256 _reward) { +// vm.startPrank(owner); +// _; +// } + +// function testRevertIfNotOwner(uint256 _reward) external { +// vm.expectRevert(); +// eboRequestCreator.setReward(_reward); +// } + +// function testSetReward(uint256 _reward) external happyPath(_reward) { +// eboRequestCreator.setReward(_reward); + +// assertEq(eboRequestCreator.reward(), _reward); +// } + +// function testEmitRewardSet(uint256 _reward) external happyPath(_reward) { +// vm.expectEmit(); +// emit RewardSet(0, _reward); + +// eboRequestCreator.setReward(_reward); +// } +// } + +// contract UnitEBORequestCreatorGetChainIds is EBORequestCreatorUnitTest { +// using EnumerableSet for EnumerableSet.UintSet; + +// EnumerableSet.UintSet internal _cleanChainIds; + +// modifier happyPath(uint256[] memory _chainIds) { +// vm.assume(_chainIds.length > 0 && _chainIds.length <= 256); +// for (uint256 _i; _i < _chainIds.length; ++_i) { +// eboRequestCreator.setChainIdForTest(_chainIds[_i]); +// _cleanChainIds.add(_chainIds[_i]); +// } +// _; +// } + +// function testGetChainIds(uint256[] memory _chainIds) external happyPath(_chainIds) { +// uint256[] memory _getChainIds = eboRequestCreator.getChainIds(); +// assertEq(_getChainIds.length, _cleanChainIds.length()); + +// for (uint256 _i; _i < _getChainIds.length; ++_i) { +// assert(_cleanChainIds.contains(_getChainIds[_i])); +// } +// } +// } diff --git a/test/unit/Greeter.t.sol b/test/unit/Greeter.t.sol deleted file mode 100644 index 82f59c9..0000000 --- a/test/unit/Greeter.t.sol +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.23; - -import {Greeter, IGreeter} from 'contracts/Greeter.sol'; -import {Test} from 'forge-std/Test.sol'; -import {IERC20} from 'forge-std/interfaces/IERC20.sol'; - -contract UnitGreeter is Test { - address internal _owner = makeAddr('owner'); - IERC20 internal _token = IERC20(makeAddr('token')); - uint256 internal _initialBalance = 100; - string internal _initialGreeting = 'hola'; - - Greeter internal _greeter; - - event GreetingSet(string _greeting); - - function setUp() external { - vm.prank(_owner); - _greeter = new Greeter(_initialGreeting, _token); - - vm.etch(address(_token), new bytes(0x1)); - } - - function test_EmptyTestExample() external { - // it does nothing - vm.skip(true); - } - - function test_ConstructorWhenPassingValidGreetingString() external { - vm.prank(_owner); - - // it deploys - _greeter = new Greeter(_initialGreeting, _token); - - // it sets the greeting string - assertEq(_greeter.greeting(), _initialGreeting); - - // it sets the owner as sender - assertEq(_greeter.OWNER(), _owner); - - // it sets the token used - assertEq(address(_greeter.token()), address(_token)); - } - - function test_ConstructorWhenPassingAnEmptyGreetingString() external { - vm.prank(_owner); - - // it reverts - vm.expectRevert(IGreeter.Greeter_InvalidGreeting.selector); - _greeter = new Greeter('', _token); - } - - function test_GreetWhenCalled() external { - vm.mockCall(address(_token), abi.encodeWithSelector(IERC20.balanceOf.selector), abi.encode(_initialBalance)); - vm.expectCall(address(_token), abi.encodeWithSelector(IERC20.balanceOf.selector)); - (string memory _greet, uint256 _balance) = _greeter.greet(); - - // it returns the greeting string - assertEq(_greet, _initialGreeting); - - // it returns the token balance of the contract - assertEq(_balance, _initialBalance); - } - - modifier whenCalledByTheOwner() { - vm.startPrank(_owner); - _; - vm.stopPrank(); - } - - function test_SetGreetingWhenPassingAValidGreetingString() external whenCalledByTheOwner { - string memory _newGreeting = 'hello'; - - // it emit GreetingSet - vm.expectEmit(true, true, true, true, address(_greeter)); - emit GreetingSet(_newGreeting); - - _greeter.setGreeting(_newGreeting); - - // it sets the greeting string - assertEq(_greeter.greeting(), _newGreeting); - } - - function test_SetGreetingWhenPassingAnEmptyGreetingString() external whenCalledByTheOwner { - // it reverts - vm.expectRevert(IGreeter.Greeter_InvalidGreeting.selector); - _greeter.setGreeting(''); - } - - function test_SetGreetingWhenCalledByANon_owner(address _caller) external { - vm.assume(_caller != _owner); - vm.prank(_caller); - - // it reverts - vm.expectRevert(IGreeter.Greeter_OnlyOwner.selector); - _greeter.setGreeting('new greeting'); - } -} diff --git a/test/unit/Greeter.tree b/test/unit/Greeter.tree deleted file mode 100644 index bbc74ea..0000000 --- a/test/unit/Greeter.tree +++ /dev/null @@ -1,25 +0,0 @@ -Greeter::constructor -├── when passing valid greeting string -│ ├── it deploys -│ ├── it sets the greeting string -│ ├── it sets the owner as sender -│ └── it sets the token used -└── when passing an empty greeting string - └── it reverts - - -Greeter::greet -└── when called - ├── it returns the greeting string - └── it returns the token balance of the contract - - -Greeter::setGreeting -├── when called by the owner -│ ├── when passing a valid greeting string -│ │ ├── it sets the greeting string -│ │ └── it emit GreetingSet -│ └── when passing an empty greeting string -│ └── it reverts -└── when called by a non-owner - └── it reverts \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 8f853f3..a0b6304 100644 --- a/yarn.lock +++ b/yarn.lock @@ -702,11 +702,6 @@ dot-prop@^5.1.0: dependencies: is-obj "^2.0.0" -"ds-test@git+https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0": - version "1.0.0" - uid e282159d5170298eb2455a6c05280ab5a73a4ef0 - resolved "git+https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0" - "ds-test@https://github.com/dapphub/ds-test": version "1.0.0" uid e282159d5170298eb2455a6c05280ab5a73a4ef0 @@ -868,10 +863,6 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" -"forge-std@git+https://github.com/foundry-rs/forge-std.git#e8a047e3f40f13fa37af6fe14e6e06283d9a060e": - version "1.5.6" - resolved "git+https://github.com/foundry-rs/forge-std.git#e8a047e3f40f13fa37af6fe14e6e06283d9a060e" - "forge-std@github:foundry-rs/forge-std#1.8.2": version "1.8.2" resolved "https://codeload.github.com/foundry-rs/forge-std/tar.gz/978ac6fadb62f5f0b723c996f64be52eddba6801" @@ -1780,10 +1771,6 @@ solhint-community@4.0.0: optionalDependencies: prettier "^2.8.3" -"solmate@git+https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c": - version "6.1.0" - resolved "git+https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" - "solmate@https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c": version "6.1.0" resolved "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" From f7b882a8ba917c1d49cd8ee19adcb3cebfd33117 Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Thu, 1 Aug 2024 17:59:59 -0300 Subject: [PATCH 02/19] feat: mapping --- src/contracts/EBORequestCreator.sol | 44 ++-- src/interfaces/IEBORequestCreator.sol | 22 +- test/unit/EBORequestCreator.t.sol | 285 +++++++++++++++----------- 3 files changed, 189 insertions(+), 162 deletions(-) diff --git a/src/contracts/EBORequestCreator.sol b/src/contracts/EBORequestCreator.sol index 3a4c822..f3ff34f 100644 --- a/src/contracts/EBORequestCreator.sol +++ b/src/contracts/EBORequestCreator.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; import {IEBORequestCreator} from 'interfaces/IEBORequestCreator.sol'; contract EBORequestCreator is IEBORequestCreator { - using EnumerableSet for EnumerableSet.Bytes32Set; - // /// @inheritdoc IEBORequestCreator // IOracle public oracle; @@ -19,14 +16,11 @@ contract EBORequestCreator is IEBORequestCreator { /// @inheritdoc IEBORequestCreator uint256 public reward; - /** - * @notice The list of chain ids - */ - EnumerableSet.Bytes32Set internal _chainIds; + /// @inheritdoc IEBORequestCreator + mapping(string _chainId => bool _approved) public chainIds; constructor(address _owner) { // oracle = _oracle; - owner = _owner; reward = 0; } @@ -60,17 +54,21 @@ contract EBORequestCreator is IEBORequestCreator { /// @inheritdoc IEBORequestCreator function addChain(string calldata _chainId) external onlyOwner { - if (!_chainIds.add(_chaindIdToBytes32(_chainId))) { + if (chainIds[_chainId]) { revert EBORequestCreator_ChainAlreadyAdded(); } + chainIds[_chainId] = true; + emit ChainAdded(_chainId); } /// @inheritdoc IEBORequestCreator function removeChain(string calldata _chainId) external onlyOwner { - if (!_chainIds.remove(_chaindIdToBytes32(_chainId))) { + if (!chainIds[_chainId]) { revert EBORequestCreator_ChainNotAdded(); } + chainIds[_chainId] = false; + emit ChainRemoved(_chainId); } @@ -81,25 +79,9 @@ contract EBORequestCreator is IEBORequestCreator { emit RewardSet(_oldReward, _reward); } - /// @inheritdoc IEBORequestCreator - function getChainIds() external view returns (string[] memory _chainIdsValues) { - bytes32[] memory _chainIdsBytes = _chainIds.values(); - - for (uint256 _i; _i < _chainIdsBytes.length; _i++) { - _chainIdsValues[_i] = _chaindIdToString(_chainIdsBytes[_i]); - } - } - - function _chaindIdToBytes32(string memory _chainId) internal pure returns (bytes32 _convertedChainId) { - assembly { - _convertedChainId := mload(add(_chainId, 32)) - } - } - - function _chaindIdToString(bytes32 _chainId) internal pure returns (string memory _convertedChainId) { - _convertedChainId = string(abi.encodePacked(_chainId)); - } - + /** + * @notice Checks if the sender is the owner + */ modifier onlyOwner() { if (msg.sender != owner) { revert EBORequestCreator_OnlyOwner(); @@ -107,10 +89,14 @@ contract EBORequestCreator is IEBORequestCreator { _; } + /** + * @notice Checks if the sender is the pending owner + */ modifier onlyPendingOwner() { if (msg.sender != pendingOwner) { revert EBORequestCreator_OnlyPendingOwner(); } + _; } } diff --git a/src/interfaces/IEBORequestCreator.sol b/src/interfaces/IEBORequestCreator.sol index 44e670d..1719b89 100644 --- a/src/interfaces/IEBORequestCreator.sol +++ b/src/interfaces/IEBORequestCreator.sol @@ -26,19 +26,19 @@ interface IEBORequestCreator { * @param _epoch The epoch of the request * @param _chainId The chain id of the request */ - event RequestCreated(uint256 _epoch, uint256 _chainId); + event RequestCreated(uint256 indexed _epoch, string indexed _chainId); /** * @notice Emitted when a chain is added * @param _chainId The chain id added */ - event ChainAdded(string _chainId); + event ChainAdded(string indexed _chainId); /** * @notice Emitted when a chain is removed * @param _chainId The chain id removed */ - event ChainRemoved(string _chainId); + event ChainRemoved(string indexed _chainId); /** * @notice Emitted when the reward is set @@ -82,19 +82,29 @@ interface IEBORequestCreator { /** * @notice The owner of the contract + * @return _owner The owner */ function owner() external view returns (address _owner); /** * @notice The pending owner of the contract + * @return _pendingOwner The pending owner */ function pendingOwner() external view returns (address _pendingOwner); /** * @notice The reward paid for each chain updated + * @return _reward The reward */ function reward() external view returns (uint256 _reward); + /** + * @notice The chain ids + * @param _chainId The chain id to check + * @return _approved The chain id is approved + */ + function chainIds(string calldata _chainId) external view returns (bool _approved); + /*/////////////////////////////////////////////////////////////// LOGIC //////////////////////////////////////////////////////////////*/ @@ -144,10 +154,4 @@ interface IEBORequestCreator { * @param _reward The reward to set */ function setReward(uint256 _reward) external; - - /** - * @notice Get the chain ids - * @return _chainIdsValues The chain ids - */ - function getChainIds() external view returns (string[] memory _chainIdsValues); } diff --git a/test/unit/EBORequestCreator.t.sol b/test/unit/EBORequestCreator.t.sol index 2e47326..d25ae78 100644 --- a/test/unit/EBORequestCreator.t.sol +++ b/test/unit/EBORequestCreator.t.sol @@ -10,163 +10,200 @@ import {Test} from 'forge-std/Test.sol'; contract EBORequestCreatorForTest is EBORequestCreator { using EnumerableSet for EnumerableSet.Bytes32Set; - constructor() EBORequestCreator(owner) {} + constructor(address _owner) EBORequestCreator(_owner) {} + + function setPendingOwnerForTest(address _pendingOwner) external { + pendingOwner = _pendingOwner; + } function setChainIdForTest(string calldata _chainId) external { - _chainIds.add(_chaindIdToBytes32(_chainId)); + chainIds[_chainId] = true; } } -// abstract contract EBORequestCreatorUnitTest is Test { -// /// Events -// event RequestCreated(uint256 _epoch, uint256 _chainId); -// event ChainAdded(uint256 _chainId); -// event ChainRemoved(uint256 _chainId); -// event RewardSet(uint256 _oldReward, uint256 _newReward); +abstract contract EBORequestCreatorUnitTest is Test { + /// Events + event PendingOwnerSetted(address _pendingOwner); + event OwnerSetted(address _oldOwner, address _newOwner); + event RequestCreated(uint256 indexed _epoch, string indexed _chainId); + event ChainAdded(string indexed _chainId); + event ChainRemoved(string indexed _chainId); + event RewardSet(uint256 _oldReward, uint256 _newReward); -// /// Contracts -// EBORequestCreatorForTest public eboRequestCreator; -// // IOracle public oracle; + /// Contracts + EBORequestCreatorForTest public eboRequestCreator; + // IOracle public oracle; -// /// EOAs -// address public owner; + /// EOAs + address public owner; -// function setUp() external { -// owner = makeAddr('Owner'); -// // oracle = IOracle(makeAddr('Oracle')); + function setUp() external { + owner = makeAddr('Owner'); + // oracle = IOracle(makeAddr('Oracle')); -// vm.prank(owner); -// eboRequestCreator = new EBORequestCreatorForTest(); -// } -// } - -// contract UnitEBORequestCreatorConstructor is EBORequestCreatorUnitTest { -// function testConstructor() external view { -// assertEq(eboRequestCreator.reward(), 0); -// assertEq(eboRequestCreator.owner(), owner); -// assertEq(eboRequestCreator.pendingOwner(), address(0)); -// // assertEq(eboRequestCreator.oracle(), oracle); -// } -// } - -// // contract UnitEBORequestCreatorCreateRequest is EBORequestCreatorUnitTest { -// // function test_CreateRequest() external { -// // bytes32 requestId = eboRequestCreator.createRequest(address(this), address(this), '0x', 0, 0); -// // assertEq(uint256(requestId), uint256(keccak256(abi.encodePacked(address(this), address(this), '0x', 0, 0))); -// // } -// // } - -// contract UnitEBORequestCreatorAddChain is EBORequestCreatorUnitTest { -// modifier happyPath() { -// vm.startPrank(owner); -// _; -// } + vm.prank(owner); + eboRequestCreator = new EBORequestCreatorForTest(owner); + } -// function testRevertIfNotOwner(uint256 _chainId) external { -// vm.expectRevert(); -// eboRequestCreator.addChain(_chainId); -// } + function _revertIfNotOwner() internal { + vm.expectRevert(IEBORequestCreator.EBORequestCreator_OnlyOwner.selector); + } +} -// function testRevertIfChainAdded(uint256 _chainId) external happyPath { -// eboRequestCreator.setChainIdForTest(_chainId); +contract UnitEBORequestCreatorConstructor is EBORequestCreatorUnitTest { + function testConstructor() external view { + assertEq(eboRequestCreator.reward(), 0); + assertEq(eboRequestCreator.owner(), owner); + assertEq(eboRequestCreator.pendingOwner(), address(0)); + // assertEq(eboRequestCreator.oracle(), oracle); + } +} -// vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_ChainAlreadyAdded.selector, _chainId)); -// eboRequestCreator.addChain(_chainId); -// } +contract UnitEBORequestCreatorSetPendingOwner is EBORequestCreatorUnitTest { + modifier happyPath(address _pendingOwner) { + vm.startPrank(owner); + _; + } -// function testAddChain(uint256 _chainId) external happyPath { -// eboRequestCreator.addChain(_chainId); + function testRevertIfNotOwner(address _pendingOwner) external { + _revertIfNotOwner(); + eboRequestCreator.setPendingOwner(_pendingOwner); + } -// assertEq(eboRequestCreator.getChainIds().length, 1); -// assertEq(eboRequestCreator.getChainIds()[0], _chainId); -// } + function testSetPendingOwner(address _pendingOwner) external happyPath(_pendingOwner) { + eboRequestCreator.setPendingOwner(_pendingOwner); -// function testEmitChainAdded(uint256 _chainId) external happyPath { -// vm.expectEmit(); -// emit ChainAdded(_chainId); + assertEq(eboRequestCreator.pendingOwner(), _pendingOwner); + } -// eboRequestCreator.addChain(_chainId); -// } -// } + function testEmitPendingOwnerSetted(address _pendingOwner) external happyPath(_pendingOwner) { + vm.expectEmit(); + emit PendingOwnerSetted(_pendingOwner); -// contract UnitEBORequestCreatorRemoveChain is EBORequestCreatorUnitTest { -// modifier happyPath(uint256 _chainId) { -// eboRequestCreator.setChainIdForTest(_chainId); -// vm.startPrank(owner); -// _; -// } + eboRequestCreator.setPendingOwner(_pendingOwner); + } +} -// function testRevertIfNotOwner(uint256 _chainId) external { -// vm.expectRevert(); -// eboRequestCreator.removeChain(_chainId); -// } +contract UnitEBORequestCreatorAcceptPendingOwner is EBORequestCreatorUnitTest { + modifier happyPath(address _pendingOwner) { + eboRequestCreator.setPendingOwnerForTest(_pendingOwner); + vm.startPrank(_pendingOwner); + _; + } -// function testRevertIfChainNotAdded(uint256 _chainId) external { -// vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_ChainNotAdded.selector, _chainId)); + function testRevertIfNotPendingOwner(address _pendingOwner) external { + vm.expectRevert(IEBORequestCreator.EBORequestCreator_OnlyPendingOwner.selector); + eboRequestCreator.acceptPendingOwner(); + } -// vm.prank(owner); -// eboRequestCreator.removeChain(_chainId); -// } + function testAcceptPendingOwner(address _pendingOwner) external happyPath(_pendingOwner) { + eboRequestCreator.acceptPendingOwner(); -// function testRemoveChain(uint256 _chainId) external happyPath(_chainId) { -// eboRequestCreator.removeChain(_chainId); + assertEq(eboRequestCreator.owner(), _pendingOwner); + assertEq(eboRequestCreator.pendingOwner(), address(0)); + } -// assertEq(eboRequestCreator.getChainIds().length, 0); -// } + function testEmitOwnerSetted(address _pendingOwner) external happyPath(_pendingOwner) { + vm.expectEmit(); + emit OwnerSetted(owner, _pendingOwner); -// function testEmitChainRemoved(uint256 _chainId) external happyPath(_chainId) { -// vm.expectEmit(); -// emit ChainRemoved(_chainId); + eboRequestCreator.acceptPendingOwner(); + } +} -// eboRequestCreator.removeChain(_chainId); +// contract UnitEBORequestCreatorCreateRequest is EBORequestCreatorUnitTest { +// function test_CreateRequest() external { +// bytes32 requestId = eboRequestCreator.createRequest(address(this), address(this), '0x', 0, 0); +// assertEq(uint256(requestId), uint256(keccak256(abi.encodePacked(address(this), address(this), '0x', 0, 0))); +// } // } -// } -// contract UnitEBORequestCreatorSetReward is EBORequestCreatorUnitTest { -// modifier happyPath(uint256 _reward) { -// vm.startPrank(owner); -// _; -// } +contract UnitEBORequestCreatorAddChain is EBORequestCreatorUnitTest { + modifier happyPath() { + vm.startPrank(owner); + _; + } -// function testRevertIfNotOwner(uint256 _reward) external { -// vm.expectRevert(); -// eboRequestCreator.setReward(_reward); -// } + function testRevertIfNotOwner(string calldata _chainId) external { + _revertIfNotOwner(); + eboRequestCreator.addChain(_chainId); + } -// function testSetReward(uint256 _reward) external happyPath(_reward) { -// eboRequestCreator.setReward(_reward); + function testRevertIfChainAdded(string calldata _chainId) external happyPath { + eboRequestCreator.setChainIdForTest(_chainId); -// assertEq(eboRequestCreator.reward(), _reward); -// } + vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_ChainAlreadyAdded.selector)); + eboRequestCreator.addChain(_chainId); + } -// function testEmitRewardSet(uint256 _reward) external happyPath(_reward) { -// vm.expectEmit(); -// emit RewardSet(0, _reward); + function testAddChain(string calldata _chainId) external happyPath { + eboRequestCreator.addChain(_chainId); -// eboRequestCreator.setReward(_reward); -// } -// } + assertEq(eboRequestCreator.chainIds(_chainId), true); + } -// contract UnitEBORequestCreatorGetChainIds is EBORequestCreatorUnitTest { -// using EnumerableSet for EnumerableSet.UintSet; + function testEmitChainAdded(string calldata _chainId) external happyPath { + vm.expectEmit(); + emit ChainAdded(_chainId); -// EnumerableSet.UintSet internal _cleanChainIds; + eboRequestCreator.addChain(_chainId); + } +} -// modifier happyPath(uint256[] memory _chainIds) { -// vm.assume(_chainIds.length > 0 && _chainIds.length <= 256); -// for (uint256 _i; _i < _chainIds.length; ++_i) { -// eboRequestCreator.setChainIdForTest(_chainIds[_i]); -// _cleanChainIds.add(_chainIds[_i]); -// } -// _; -// } +contract UnitEBORequestCreatorRemoveChain is EBORequestCreatorUnitTest { + modifier happyPath(string calldata _chainId) { + eboRequestCreator.setChainIdForTest(_chainId); + vm.startPrank(owner); + _; + } -// function testGetChainIds(uint256[] memory _chainIds) external happyPath(_chainIds) { -// uint256[] memory _getChainIds = eboRequestCreator.getChainIds(); -// assertEq(_getChainIds.length, _cleanChainIds.length()); + function testRevertIfNotOwner(string calldata _chainId) external { + _revertIfNotOwner(); + eboRequestCreator.removeChain(_chainId); + } -// for (uint256 _i; _i < _getChainIds.length; ++_i) { -// assert(_cleanChainIds.contains(_getChainIds[_i])); -// } -// } -// } + function testRevertIfChainNotAdded(string calldata _chainId) external { + vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_ChainNotAdded.selector)); + + vm.prank(owner); + eboRequestCreator.removeChain(_chainId); + } + + function testRemoveChain(string calldata _chainId) external happyPath(_chainId) { + eboRequestCreator.removeChain(_chainId); + + assertEq(eboRequestCreator.chainIds(_chainId), false); + } + + function testEmitChainRemoved(string calldata _chainId) external happyPath(_chainId) { + vm.expectEmit(); + emit ChainRemoved(_chainId); + + eboRequestCreator.removeChain(_chainId); + } +} + +contract UnitEBORequestCreatorSetReward is EBORequestCreatorUnitTest { + modifier happyPath(uint256 _reward) { + vm.startPrank(owner); + _; + } + + function testRevertIfNotOwner(uint256 _reward) external { + vm.expectRevert(); + eboRequestCreator.setReward(_reward); + } + + function testSetReward(uint256 _reward) external happyPath(_reward) { + eboRequestCreator.setReward(_reward); + + assertEq(eboRequestCreator.reward(), _reward); + } + + function testEmitRewardSet(uint256 _reward) external happyPath(_reward) { + vm.expectEmit(); + emit RewardSet(0, _reward); + + eboRequestCreator.setReward(_reward); + } +} From ddde6e62b379f9443ef5563737825b8efa00d70f Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Fri, 2 Aug 2024 00:23:45 -0300 Subject: [PATCH 03/19] feat: unit tests --- package.json | 4 +- src/contracts/EBORequestCreator.sol | 77 +++++++++++---- src/interfaces/IEBORequestCreator.sol | 40 +++----- test/unit/EBORequestCreator.t.sol | 133 ++++++++++++++++++++------ yarn.lock | 87 ++++------------- 5 files changed, 195 insertions(+), 146 deletions(-) diff --git a/package.json b/package.json index 1686815..7124f34 100644 --- a/package.json +++ b/package.json @@ -35,8 +35,8 @@ "package.json": "sort-package-json" }, "dependencies": { - "@defi-wonderland/prophet-core-contracts": "^0.0.0-e73df4c1", - "@defi-wonderland/prophet-modules-contracts": "^0.0.0-2c7deca8" + "@defi-wonderland/prophet-core-contracts": "0.0.0-c25103ea", + "@defi-wonderland/prophet-modules-contracts": "0.0.0-ee716ee0" }, "devDependencies": { "@commitlint/cli": "19.3.0", diff --git a/src/contracts/EBORequestCreator.sol b/src/contracts/EBORequestCreator.sol index f3ff34f..bd8f7ac 100644 --- a/src/contracts/EBORequestCreator.sol +++ b/src/contracts/EBORequestCreator.sol @@ -1,11 +1,14 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import {IEBORequestCreator} from 'interfaces/IEBORequestCreator.sol'; +import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; +import {IEBORequestCreator, IOracle} from 'interfaces/IEBORequestCreator.sol'; contract EBORequestCreator is IEBORequestCreator { - // /// @inheritdoc IEBORequestCreator - // IOracle public oracle; + using EnumerableSet for EnumerableSet.Bytes32Set; + + /// @inheritdoc IEBORequestCreator + IOracle public oracle; /// @inheritdoc IEBORequestCreator address public owner; @@ -16,11 +19,12 @@ contract EBORequestCreator is IEBORequestCreator { /// @inheritdoc IEBORequestCreator uint256 public reward; - /// @inheritdoc IEBORequestCreator - mapping(string _chainId => bool _approved) public chainIds; + EnumerableSet.Bytes32Set internal _chainIdsAllowed; - constructor(address _owner) { - // oracle = _oracle; + mapping(uint256 _epoch => EnumerableSet.Bytes32Set _chainIds) internal _epochChainIds; + + constructor(IOracle _oracle, address _owner) { + oracle = _oracle; owner = _owner; reward = 0; } @@ -42,32 +46,59 @@ contract EBORequestCreator is IEBORequestCreator { } /// @inheritdoc IEBORequestCreator - function createRequest( - address _requester, - address _target, - bytes calldata _data, - uint256 _value, - uint256 _nonce - ) external returns (bytes32 _requestId) { - // emit RequestCreated(_requestId, _requester, _target, _data, _value, _nonce); + function createRequests(uint256 _epoch, string[] calldata _chainIds) external { + bytes32 _encodedChainId; + + EnumerableSet.Bytes32Set storage _epochEncodedChainIds = _epochChainIds[_epoch]; + + for (uint256 _i; _i < _chainIds.length; _i++) { + _encodedChainId = _encodeChainId(_chainIds[_i]); + if (!_chainIdsAllowed.contains(_encodedChainId)) revert EBORequestCreator_ChainNotAdded(); + + if (!_epochEncodedChainIds.contains(_encodedChainId)) { + _epochChainIds[_epoch].add(_encodedChainId); + + // TODO: COMPLETE THE REQUEST CREATION WITH THE PROPER MODULES + IOracle.Request memory _request = IOracle.Request({ + nonce: 0, + requester: msg.sender, + requestModule: address(0), + responseModule: address(0), + disputeModule: address(0), + resolutionModule: address(0), + finalityModule: address(0), + requestModuleData: '', + responseModuleData: '', + disputeModuleData: '', + resolutionModuleData: '', + finalityModuleData: '' + }); + + bytes32 _requestId = oracle.createRequest(_request, bytes32(0)); + + emit RequestCreated(_requestId, _epoch, _chainIds[_i]); + } + } } /// @inheritdoc IEBORequestCreator function addChain(string calldata _chainId) external onlyOwner { - if (chainIds[_chainId]) { + bytes32 _encodedChainId = _encodeChainId(_chainId); + if (_chainIdsAllowed.contains(_encodedChainId)) { revert EBORequestCreator_ChainAlreadyAdded(); } - chainIds[_chainId] = true; + _chainIdsAllowed.add(_encodedChainId); emit ChainAdded(_chainId); } /// @inheritdoc IEBORequestCreator function removeChain(string calldata _chainId) external onlyOwner { - if (!chainIds[_chainId]) { + bytes32 _encodedChainId = _encodeChainId(_chainId); + if (!_chainIdsAllowed.contains(_encodedChainId)) { revert EBORequestCreator_ChainNotAdded(); } - chainIds[_chainId] = false; + _chainIdsAllowed.remove(_encodedChainId); emit ChainRemoved(_chainId); } @@ -79,6 +110,14 @@ contract EBORequestCreator is IEBORequestCreator { emit RewardSet(_oldReward, _reward); } + /** + * @notice Encodes the chain id + * @dev The chain id is hashed to have a enumerable set to avoid duplicates + */ + function _encodeChainId(string calldata _chainId) internal pure returns (bytes32 _encodedChainId) { + _encodedChainId = keccak256(abi.encodePacked(_chainId)); + } + /** * @notice Checks if the sender is the owner */ diff --git a/src/interfaces/IEBORequestCreator.sol b/src/interfaces/IEBORequestCreator.sol index 1719b89..d09843b 100644 --- a/src/interfaces/IEBORequestCreator.sol +++ b/src/interfaces/IEBORequestCreator.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -// import {IOracle} from '@defi-wonderland/prophet-core-contracts/solidity/interfaces/IOracle.sol'; +import {IOracle} from '@defi-wonderland/prophet-core-contracts/solidity/interfaces/IOracle.sol'; interface IEBORequestCreator { /*/////////////////////////////////////////////////////////////// @@ -23,10 +23,11 @@ interface IEBORequestCreator { /** * @notice Emitted when a request is created + * @param _requestId The id of the request * @param _epoch The epoch of the request * @param _chainId The chain id of the request */ - event RequestCreated(uint256 indexed _epoch, string indexed _chainId); + event RequestCreated(bytes32 indexed _requestId, uint256 indexed _epoch, string indexed _chainId); /** * @notice Emitted when a chain is added @@ -75,10 +76,10 @@ interface IEBORequestCreator { VARIABLES //////////////////////////////////////////////////////////////*/ - // /** - // * @notice The oracle contract - // */ - // function oracle() external view returns (IOracle _oracle); + /** + * @notice The oracle contract + */ + function oracle() external view returns (IOracle _oracle); /** * @notice The owner of the contract @@ -98,13 +99,6 @@ interface IEBORequestCreator { */ function reward() external view returns (uint256 _reward); - /** - * @notice The chain ids - * @param _chainId The chain id to check - * @return _approved The chain id is approved - */ - function chainIds(string calldata _chainId) external view returns (bool _approved); - /*/////////////////////////////////////////////////////////////// LOGIC //////////////////////////////////////////////////////////////*/ @@ -121,21 +115,11 @@ interface IEBORequestCreator { function acceptPendingOwner() external; /** - * @notice Create a request - * @param _requester The address of the requester - * @param _target The address of the target - * @param _data The data of the request - * @param _value The value of the request - * @param _nonce The nonce of the request - * @return _requestId The id of the request - */ - function createRequest( - address _requester, - address _target, - bytes calldata _data, - uint256 _value, - uint256 _nonce - ) external returns (bytes32 _requestId); + * @notice Create requests + * @param _epoch The epoch of the request + * @param _chainIds The chain ids to update + */ + function createRequests(uint256 _epoch, string[] calldata _chainIds) external; /** * @notice Add a chain to the allowed chains which can be updated diff --git a/test/unit/EBORequestCreator.t.sol b/test/unit/EBORequestCreator.t.sol index d25ae78..8f3c4ef 100644 --- a/test/unit/EBORequestCreator.t.sol +++ b/test/unit/EBORequestCreator.t.sol @@ -3,21 +3,22 @@ pragma solidity 0.8.26; import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; -import {EBORequestCreator, IEBORequestCreator} from 'contracts/EBORequestCreator.sol'; +import {EBORequestCreator, IEBORequestCreator, IOracle} from 'contracts/EBORequestCreator.sol'; import {Test} from 'forge-std/Test.sol'; +import 'forge-std/console.sol'; contract EBORequestCreatorForTest is EBORequestCreator { using EnumerableSet for EnumerableSet.Bytes32Set; - constructor(address _owner) EBORequestCreator(_owner) {} + constructor(IOracle _oracle, address _owner) EBORequestCreator(_oracle, _owner) {} function setPendingOwnerForTest(address _pendingOwner) external { pendingOwner = _pendingOwner; } - function setChainIdForTest(string calldata _chainId) external { - chainIds[_chainId] = true; + function setChainIdForTest(string calldata _chainId) external returns (bool _added) { + _added = _chainIdsAllowed.add(_encodeChainId(_chainId)); } } @@ -25,24 +26,24 @@ abstract contract EBORequestCreatorUnitTest is Test { /// Events event PendingOwnerSetted(address _pendingOwner); event OwnerSetted(address _oldOwner, address _newOwner); - event RequestCreated(uint256 indexed _epoch, string indexed _chainId); + event RequestCreated(bytes32 indexed _requestId, uint256 indexed _epoch, string indexed _chainId); event ChainAdded(string indexed _chainId); event ChainRemoved(string indexed _chainId); event RewardSet(uint256 _oldReward, uint256 _newReward); /// Contracts EBORequestCreatorForTest public eboRequestCreator; - // IOracle public oracle; + IOracle public oracle; /// EOAs address public owner; function setUp() external { owner = makeAddr('Owner'); - // oracle = IOracle(makeAddr('Oracle')); + oracle = IOracle(makeAddr('Oracle')); vm.prank(owner); - eboRequestCreator = new EBORequestCreatorForTest(owner); + eboRequestCreator = new EBORequestCreatorForTest(oracle, owner); } function _revertIfNotOwner() internal { @@ -51,11 +52,14 @@ abstract contract EBORequestCreatorUnitTest is Test { } contract UnitEBORequestCreatorConstructor is EBORequestCreatorUnitTest { + /** + * @notice Test the constructor + */ function testConstructor() external view { assertEq(eboRequestCreator.reward(), 0); assertEq(eboRequestCreator.owner(), owner); assertEq(eboRequestCreator.pendingOwner(), address(0)); - // assertEq(eboRequestCreator.oracle(), oracle); + assertEq(address(eboRequestCreator.oracle()), address(oracle)); } } @@ -65,17 +69,26 @@ contract UnitEBORequestCreatorSetPendingOwner is EBORequestCreatorUnitTest { _; } + /** + * @notice Test the revert if the caller is not the owner + */ function testRevertIfNotOwner(address _pendingOwner) external { _revertIfNotOwner(); eboRequestCreator.setPendingOwner(_pendingOwner); } + /** + * @notice Test the set pending owner + */ function testSetPendingOwner(address _pendingOwner) external happyPath(_pendingOwner) { eboRequestCreator.setPendingOwner(_pendingOwner); assertEq(eboRequestCreator.pendingOwner(), _pendingOwner); } + /** + * @notice Test the emit pending owner setted + */ function testEmitPendingOwnerSetted(address _pendingOwner) external happyPath(_pendingOwner) { vm.expectEmit(); emit PendingOwnerSetted(_pendingOwner); @@ -91,11 +104,17 @@ contract UnitEBORequestCreatorAcceptPendingOwner is EBORequestCreatorUnitTest { _; } - function testRevertIfNotPendingOwner(address _pendingOwner) external { + /** + * @notice Test the revert if the caller is not the pending owner + */ + function testRevertIfNotPendingOwner() external { vm.expectRevert(IEBORequestCreator.EBORequestCreator_OnlyPendingOwner.selector); eboRequestCreator.acceptPendingOwner(); } + /** + * @notice Test the accept pending owner + */ function testAcceptPendingOwner(address _pendingOwner) external happyPath(_pendingOwner) { eboRequestCreator.acceptPendingOwner(); @@ -103,6 +122,9 @@ contract UnitEBORequestCreatorAcceptPendingOwner is EBORequestCreatorUnitTest { assertEq(eboRequestCreator.pendingOwner(), address(0)); } + /** + * @notice Test the emit owner setted + */ function testEmitOwnerSetted(address _pendingOwner) external happyPath(_pendingOwner) { vm.expectEmit(); emit OwnerSetted(owner, _pendingOwner); @@ -111,12 +133,52 @@ contract UnitEBORequestCreatorAcceptPendingOwner is EBORequestCreatorUnitTest { } } -// contract UnitEBORequestCreatorCreateRequest is EBORequestCreatorUnitTest { -// function test_CreateRequest() external { -// bytes32 requestId = eboRequestCreator.createRequest(address(this), address(this), '0x', 0, 0); -// assertEq(uint256(requestId), uint256(keccak256(abi.encodePacked(address(this), address(this), '0x', 0, 0))); -// } -// } +contract UnitEBORequestCreatorCreateRequest is EBORequestCreatorUnitTest { + string[] internal _cleanChainIds; + + modifier happyPath(uint256 _epoch, string[] calldata _chainId) { + vm.assume(_epoch > 0); + vm.assume(_chainId.length > 0 && _chainId.length < 30); + + bool _added; + for (uint256 _i; _i < _chainId.length; _i++) { + _added = eboRequestCreator.setChainIdForTest(_chainId[_i]); + if (_added) { + _cleanChainIds.push(_chainId[_i]); + } + } + + vm.startPrank(owner); + _; + } + + /** + * @notice Test the revert if the caller is not the owner + */ + function testRevertIfChainNotAdded() external { + vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_ChainNotAdded.selector)); + + eboRequestCreator.createRequests(0, new string[](1)); + } + + /** + * @notice Test the create requests + */ + function testEmitCreateRequest( + uint256 _epoch, + string[] calldata _chainIds, + bytes32 _requestId + ) external happyPath(_epoch, _chainIds) { + for (uint256 _i; _i < _cleanChainIds.length; _i++) { + console.log(_cleanChainIds[_i]); + vm.mockCall(address(oracle), abi.encodeWithSelector(IOracle.createRequest.selector), abi.encode(_requestId)); + vm.expectEmit(); + emit RequestCreated(_requestId, _epoch, _cleanChainIds[_i]); + } + + eboRequestCreator.createRequests(_epoch, _cleanChainIds); + } +} contract UnitEBORequestCreatorAddChain is EBORequestCreatorUnitTest { modifier happyPath() { @@ -124,11 +186,17 @@ contract UnitEBORequestCreatorAddChain is EBORequestCreatorUnitTest { _; } + /** + * @notice Test the revert if the caller is not the owner + */ function testRevertIfNotOwner(string calldata _chainId) external { _revertIfNotOwner(); eboRequestCreator.addChain(_chainId); } + /** + * @notice Test the revert if the chain is already added + */ function testRevertIfChainAdded(string calldata _chainId) external happyPath { eboRequestCreator.setChainIdForTest(_chainId); @@ -136,12 +204,9 @@ contract UnitEBORequestCreatorAddChain is EBORequestCreatorUnitTest { eboRequestCreator.addChain(_chainId); } - function testAddChain(string calldata _chainId) external happyPath { - eboRequestCreator.addChain(_chainId); - - assertEq(eboRequestCreator.chainIds(_chainId), true); - } - + /** + * @notice Test the emit chain added + */ function testEmitChainAdded(string calldata _chainId) external happyPath { vm.expectEmit(); emit ChainAdded(_chainId); @@ -157,11 +222,17 @@ contract UnitEBORequestCreatorRemoveChain is EBORequestCreatorUnitTest { _; } + /** + * @notice Test the revert if the caller is not the owner + */ function testRevertIfNotOwner(string calldata _chainId) external { _revertIfNotOwner(); eboRequestCreator.removeChain(_chainId); } + /** + * @notice Test the revert if the chain is not added + */ function testRevertIfChainNotAdded(string calldata _chainId) external { vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_ChainNotAdded.selector)); @@ -169,12 +240,9 @@ contract UnitEBORequestCreatorRemoveChain is EBORequestCreatorUnitTest { eboRequestCreator.removeChain(_chainId); } - function testRemoveChain(string calldata _chainId) external happyPath(_chainId) { - eboRequestCreator.removeChain(_chainId); - - assertEq(eboRequestCreator.chainIds(_chainId), false); - } - + /** + * @notice Test the emit chain removed + */ function testEmitChainRemoved(string calldata _chainId) external happyPath(_chainId) { vm.expectEmit(); emit ChainRemoved(_chainId); @@ -189,17 +257,26 @@ contract UnitEBORequestCreatorSetReward is EBORequestCreatorUnitTest { _; } + /** + * @notice Test the revert if the caller is not the owner + */ function testRevertIfNotOwner(uint256 _reward) external { vm.expectRevert(); eboRequestCreator.setReward(_reward); } + /** + * @notice Test the set reward + */ function testSetReward(uint256 _reward) external happyPath(_reward) { eboRequestCreator.setReward(_reward); assertEq(eboRequestCreator.reward(), _reward); } + /** + * @notice Test the emit reward set + */ function testEmitRewardSet(uint256 _reward) external happyPath(_reward) { vm.expectEmit(); emit RewardSet(0, _reward); diff --git a/yarn.lock b/yarn.lock index a0b6304..c19cd49 100644 --- a/yarn.lock +++ b/yarn.lock @@ -190,49 +190,20 @@ solc-typed-ast "18.1.2" yargs "17.7.2" -"@defi-wonderland/prophet-core-contracts@0.0.0-a8dc38de": - version "0.0.0-a8dc38de" - resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core-contracts/-/prophet-core-contracts-0.0.0-a8dc38de.tgz#3e662bc423887bc1bf12ac44a2c15346b56b6957" - integrity sha512-W0OG+bNBSunUvqeFPxlC/IzfxWwE9CpebBRSfOB9MP+7Wivn3KLtzD7neIFSxmWFDT479YBp715ZnTa87Lr6fQ== - dependencies: - "@defi-wonderland/solidity-utils" "0.0.0-3e9c8e8b" - "@openzeppelin/contracts" "^4.9.3" - ds-test "https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0" - forge-std "https://github.com/foundry-rs/forge-std.git#e8a047e3f40f13fa37af6fe14e6e06283d9a060e" +"@defi-wonderland/prophet-core-contracts@0.0.0-c25103ea": + version "0.0.0-c25103ea" + resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core-contracts/-/prophet-core-contracts-0.0.0-c25103ea.tgz#e7a83271251d6ffbe0644c5971e6748d41ae9255" + integrity sha512-VCIeXwutXaih/ZF0JeqBjqkIs1ALWoFmn9OMeM5ZGcRZfx3JSV+axhi4YiIQVfrTLxICyu2hnbIEV7T1OmLVMQ== + +"@defi-wonderland/prophet-modules-contracts@0.0.0-ee716ee0": + version "0.0.0-ee716ee0" + resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-modules-contracts/-/prophet-modules-contracts-0.0.0-ee716ee0.tgz#cfcc221e8682f6a3cfe77a7353d7b2d894e198e7" + integrity sha512-wFb2FKmIgblXdz8fgTd5D0/ps6wzsnET6yXPhlD6yR2nW2x+/trXf3EvA5hrFzYnkfzp8gaHf60kDns4FAweSA== + dependencies: + "@defi-wonderland/prophet-core-contracts" "0.0.0-c25103ea" + "@openzeppelin/contracts" "4.9.5" solmate "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" -"@defi-wonderland/prophet-core-contracts@^0.0.0-e73df4c1": - version "0.0.0-e73df4c1" - resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core-contracts/-/prophet-core-contracts-0.0.0-e73df4c1.tgz#b5006963fe45c9079fc4a17d638f7199146ba5a2" - integrity sha512-7dFJ2xHXlbZQHYxYLkmkHf7RCpRahbPKt8bOJzUC/As6VpH8tNzwgV6+O1Ih+g77DIFqDUXdWgfaAB432USotA== - dependencies: - "@defi-wonderland/solidity-utils" "0.0.0-3e9c8e8b" - "@openzeppelin/contracts" "^4.9.3" - ds-test "https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0" - forge-std "https://github.com/foundry-rs/forge-std.git#e8a047e3f40f13fa37af6fe14e6e06283d9a060e" - solmate "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" - -"@defi-wonderland/prophet-modules-contracts@^0.0.0-2c7deca8": - version "0.0.0-2c7deca8" - resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-modules-contracts/-/prophet-modules-contracts-0.0.0-2c7deca8.tgz#ae3461200039c62c655b291f7ce6d90011cb0ef5" - integrity sha512-ZK194P+TQUgs50CT0BudgSvadX8DOr8ZFzAfDnOyBY9BGkDDi9ztdE6Ff7BbytXm4wPr+9G1bVDNoTH4XvLu4Q== - dependencies: - "@defi-wonderland/prophet-core-contracts" "0.0.0-a8dc38de" - "@defi-wonderland/solidity-utils" "0.0.0-3e9c8e8b" - "@openzeppelin/contracts" "^4.9.3" - ds-test "https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0" - forge-std "https://github.com/foundry-rs/forge-std.git#e8a047e3f40f13fa37af6fe14e6e06283d9a060e" - solmate "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" - -"@defi-wonderland/solidity-utils@0.0.0-3e9c8e8b": - version "0.0.0-3e9c8e8b" - resolved "https://registry.yarnpkg.com/@defi-wonderland/solidity-utils/-/solidity-utils-0.0.0-3e9c8e8b.tgz#1f9c47506e1679ea36d0854e9aa69bd210af4da0" - integrity sha512-HCN5TTO58jTrLrAcxXwTPm++P0u4dMDnwVkssszoEu0SmVKwegzZOdoA+gNbfOjjYydph+3+9bAZbNXj+UK2rg== - dependencies: - "@openzeppelin/contracts" "4.9.2" - ds-test "https://github.com/dapphub/ds-test" - forge-std "https://github.com/foundry-rs/forge-std" - "@noble/curves@1.3.0", "@noble/curves@~1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.3.0.tgz#01be46da4fd195822dab821e72f71bf4aeec635e" @@ -266,15 +237,10 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@openzeppelin/contracts@4.9.2": - version "4.9.2" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.2.tgz#1cb2d5e4d3360141a17dbc45094a8cad6aac16c1" - integrity sha512-mO+y6JaqXjWeMh9glYVzVu8HYPGknAAnWyxTRhGeckOruyXQMNnlcW6w/Dx9ftLeIQk6N+ZJFuVmTwF7lEIFrg== - -"@openzeppelin/contracts@^4.9.3": - version "4.9.6" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.6.tgz#2a880a24eb19b4f8b25adc2a5095f2aa27f39677" - integrity sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA== +"@openzeppelin/contracts@4.9.5": + version "4.9.5" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.5.tgz#1eed23d4844c861a1835b5d33507c1017fa98de8" + integrity sha512-ZK+W5mVhRppff9BE6YdR8CC52C8zAvsVAiWhEtQ5+oNxFE6h1WdeWo+FJSF8KKvtxxVYZ7MTP/5KoVpAU3aSWg== "@scure/base@~1.1.4": version "1.1.6" @@ -702,15 +668,6 @@ dot-prop@^5.1.0: dependencies: is-obj "^2.0.0" -"ds-test@https://github.com/dapphub/ds-test": - version "1.0.0" - uid e282159d5170298eb2455a6c05280ab5a73a4ef0 - resolved "https://github.com/dapphub/ds-test#e282159d5170298eb2455a6c05280ab5a73a4ef0" - -"ds-test@https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0": - version "1.0.0" - resolved "https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0" - emoji-regex@^10.3.0: version "10.3.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.3.0.tgz#76998b9268409eb3dae3de989254d456e70cfe23" @@ -867,14 +824,6 @@ for-each@^0.3.3: version "1.8.2" resolved "https://codeload.github.com/foundry-rs/forge-std/tar.gz/978ac6fadb62f5f0b723c996f64be52eddba6801" -"forge-std@https://github.com/foundry-rs/forge-std": - version "1.9.1" - resolved "https://github.com/foundry-rs/forge-std#2cbff0602d340503dba9828ab6981053704d1384" - -"forge-std@https://github.com/foundry-rs/forge-std.git#e8a047e3f40f13fa37af6fe14e6e06283d9a060e": - version "1.5.6" - resolved "https://github.com/foundry-rs/forge-std.git#e8a047e3f40f13fa37af6fe14e6e06283d9a060e" - form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -1771,9 +1720,9 @@ solhint-community@4.0.0: optionalDependencies: prettier "^2.8.3" -"solmate@https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c": +"solmate@git+https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c": version "6.1.0" - resolved "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" + resolved "git+https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" sort-object-keys@^1.1.3: version "1.1.3" From 6bf9f06e72cec6262a651cd8771892c5c828cc53 Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Tue, 6 Aug 2024 16:44:57 -0300 Subject: [PATCH 04/19] feat: improvments and comments --- src/contracts/EBORequestCreator.sol | 94 ++++++----- src/interfaces/IEBORequestCreator.sol | 103 ++++++++--- test/integration/CreateRequest.t.sol | 37 ++++ test/integration/IntegrationBase.sol | 17 +- test/unit/EBORequestCreator.t.sol | 235 +++++++++++++++++--------- 5 files changed, 343 insertions(+), 143 deletions(-) create mode 100644 test/integration/CreateRequest.t.sol diff --git a/src/contracts/EBORequestCreator.sol b/src/contracts/EBORequestCreator.sol index bd8f7ac..327a0de 100644 --- a/src/contracts/EBORequestCreator.sol +++ b/src/contracts/EBORequestCreator.sol @@ -11,78 +11,85 @@ contract EBORequestCreator is IEBORequestCreator { IOracle public oracle; /// @inheritdoc IEBORequestCreator - address public owner; + RequestData public requestData; /// @inheritdoc IEBORequestCreator - address public pendingOwner; + address public arbitrator; + + /// @inheritdoc IEBORequestCreator + address public pendingArbitrator; /// @inheritdoc IEBORequestCreator uint256 public reward; - EnumerableSet.Bytes32Set internal _chainIdsAllowed; + /// @inheritdoc IEBORequestCreator + mapping(string _chainId => mapping(uint256 _epoch => bytes32 _requestId)) public requestIdPerChainAndEpoch; - mapping(uint256 _epoch => EnumerableSet.Bytes32Set _chainIds) internal _epochChainIds; + /** + * @notice The set of chain ids allowed + */ + EnumerableSet.Bytes32Set internal _chainIdsAllowed; - constructor(IOracle _oracle, address _owner) { + constructor(IOracle _oracle, address _arbitrator) { oracle = _oracle; - owner = _owner; + arbitrator = _arbitrator; reward = 0; } /// @inheritdoc IEBORequestCreator - function setPendingOwner(address _pendingOwner) external onlyOwner { - pendingOwner = _pendingOwner; + function setPendingArbitrator(address _pendingArbitrator) external onlyArbitrator { + pendingArbitrator = _pendingArbitrator; - emit PendingOwnerSetted(_pendingOwner); + emit PendingArbitratorSetted(_pendingArbitrator); } /// @inheritdoc IEBORequestCreator - function acceptPendingOwner() external onlyPendingOwner { - address _oldOwner = owner; - owner = pendingOwner; - pendingOwner = address(0); + function acceptPendingArbitrator() external onlyPendingArbitrator { + address _oldArbitrator = arbitrator; + arbitrator = pendingArbitrator; + pendingArbitrator = address(0); - emit OwnerSetted(_oldOwner, owner); + emit ArbitratorSetted(_oldArbitrator, arbitrator); } /// @inheritdoc IEBORequestCreator function createRequests(uint256 _epoch, string[] calldata _chainIds) external { bytes32 _encodedChainId; - EnumerableSet.Bytes32Set storage _epochEncodedChainIds = _epochChainIds[_epoch]; + RequestData memory _requestData = requestData; for (uint256 _i; _i < _chainIds.length; _i++) { _encodedChainId = _encodeChainId(_chainIds[_i]); if (!_chainIdsAllowed.contains(_encodedChainId)) revert EBORequestCreator_ChainNotAdded(); - if (!_epochEncodedChainIds.contains(_encodedChainId)) { - _epochChainIds[_epoch].add(_encodedChainId); - + if (requestIdPerChainAndEpoch[_chainIds[_i]][_epoch] == bytes32(0)) { // TODO: COMPLETE THE REQUEST CREATION WITH THE PROPER MODULES IOracle.Request memory _request = IOracle.Request({ nonce: 0, - requester: msg.sender, - requestModule: address(0), - responseModule: address(0), - disputeModule: address(0), - resolutionModule: address(0), - finalityModule: address(0), - requestModuleData: '', - responseModuleData: '', - disputeModuleData: '', - resolutionModuleData: '', - finalityModuleData: '' + requester: address(this), + requestModule: _requestData.requestModule, + responseModule: _requestData.responseModule, + disputeModule: _requestData.disputeModule, + resolutionModule: _requestData.resolutionModule, + finalityModule: _requestData.finalityModule, + requestModuleData: _requestData.requestModuleData, + responseModuleData: _requestData.responseModuleData, + disputeModuleData: _requestData.disputeModuleData, + resolutionModuleData: _requestData.resolutionModuleData, + finalityModuleData: _requestData.finalityModuleData }); bytes32 _requestId = oracle.createRequest(_request, bytes32(0)); + requestIdPerChainAndEpoch[_chainIds[_i]][_epoch] = _requestId; + emit RequestCreated(_requestId, _epoch, _chainIds[_i]); } } } /// @inheritdoc IEBORequestCreator - function addChain(string calldata _chainId) external onlyOwner { + function addChain(string calldata _chainId) external onlyArbitrator { bytes32 _encodedChainId = _encodeChainId(_chainId); if (_chainIdsAllowed.contains(_encodedChainId)) { revert EBORequestCreator_ChainAlreadyAdded(); @@ -93,7 +100,7 @@ contract EBORequestCreator is IEBORequestCreator { } /// @inheritdoc IEBORequestCreator - function removeChain(string calldata _chainId) external onlyOwner { + function removeChain(string calldata _chainId) external onlyArbitrator { bytes32 _encodedChainId = _encodeChainId(_chainId); if (!_chainIdsAllowed.contains(_encodedChainId)) { revert EBORequestCreator_ChainNotAdded(); @@ -104,12 +111,19 @@ contract EBORequestCreator is IEBORequestCreator { } /// @inheritdoc IEBORequestCreator - function setReward(uint256 _reward) external onlyOwner { + function setReward(uint256 _reward) external onlyArbitrator { uint256 _oldReward = reward; reward = _reward; emit RewardSet(_oldReward, _reward); } + /// @inheritdoc IEBORequestCreator + function setRequestData(RequestData calldata _requestData) external onlyArbitrator { + requestData = _requestData; + + emit RequestDataSet(_requestData); + } + /** * @notice Encodes the chain id * @dev The chain id is hashed to have a enumerable set to avoid duplicates @@ -119,21 +133,21 @@ contract EBORequestCreator is IEBORequestCreator { } /** - * @notice Checks if the sender is the owner + * @notice Checks if the sender is the arbitrator */ - modifier onlyOwner() { - if (msg.sender != owner) { - revert EBORequestCreator_OnlyOwner(); + modifier onlyArbitrator() { + if (msg.sender != arbitrator) { + revert EBORequestCreator_OnlyArbitrator(); } _; } /** - * @notice Checks if the sender is the pending owner + * @notice Checks if the sender is the pending arbitrator */ - modifier onlyPendingOwner() { - if (msg.sender != pendingOwner) { - revert EBORequestCreator_OnlyPendingOwner(); + modifier onlyPendingArbitrator() { + if (msg.sender != pendingArbitrator) { + revert EBORequestCreator_OnlyPendingArbitrator(); } _; diff --git a/src/interfaces/IEBORequestCreator.sol b/src/interfaces/IEBORequestCreator.sol index d09843b..d967208 100644 --- a/src/interfaces/IEBORequestCreator.sol +++ b/src/interfaces/IEBORequestCreator.sol @@ -9,17 +9,17 @@ interface IEBORequestCreator { //////////////////////////////////////////////////////////////*/ /** - * @notice Emitted when the pending owner is set - * @param _pendingOwner The address of the pending owner + * @notice Emitted when the pending arbitrator is set + * @param _pendingArbitrator The address of the pending arbitrator */ - event PendingOwnerSetted(address _pendingOwner); + event PendingArbitratorSetted(address _pendingArbitrator); /** - * @notice Emitted when the owner is set - * @param _oldOwner The old owner address - * @param _newOwner The new owner address + * @notice Emitted when the abitrator is set + * @param _oldArbitrator The old abitrator address + * @param _newArbitrator The new abitrator address */ - event OwnerSetted(address _oldOwner, address _newOwner); + event ArbitratorSetted(address _oldArbitrator, address _newArbitrator); /** * @notice Emitted when a request is created @@ -48,19 +48,25 @@ interface IEBORequestCreator { */ event RewardSet(uint256 _oldReward, uint256 _newReward); + /** + * @notice Emitted when a request data is set + * @param _requestData The request data + */ + event RequestDataSet(RequestData _requestData); + /*/////////////////////////////////////////////////////////////// ERRORS //////////////////////////////////////////////////////////////*/ /** - * @notice Thrown when the caller is not the owner + * @notice Thrown when the caller is not the arbitrator */ - error EBORequestCreator_OnlyOwner(); + error EBORequestCreator_OnlyArbitrator(); /** - * @notice Thrown when the caller is not the pending owner + * @notice Thrown when the caller is not the pending arbitrator */ - error EBORequestCreator_OnlyPendingOwner(); + error EBORequestCreator_OnlyPendingArbitrator(); /** * @notice hrown when the chain is already added @@ -72,6 +78,23 @@ interface IEBORequestCreator { */ error EBORequestCreator_ChainNotAdded(); + /*/////////////////////////////////////////////////////////////// + STRUCTS + //////////////////////////////////////////////////////////////*/ + + struct RequestData { + address requestModule; + address responseModule; + address disputeModule; + address resolutionModule; + address finalityModule; + bytes requestModuleData; + bytes responseModuleData; + bytes disputeModuleData; + bytes resolutionModuleData; + bytes finalityModuleData; + } + /*/////////////////////////////////////////////////////////////// VARIABLES //////////////////////////////////////////////////////////////*/ @@ -82,16 +105,35 @@ interface IEBORequestCreator { function oracle() external view returns (IOracle _oracle); /** - * @notice The owner of the contract - * @return _owner The owner + * @notice The request data + */ + function requestData() + external + view + returns ( + address _requestModule, + address _responseModule, + address _disputeModule, + address _resolutionModule, + address _finalityModule, + bytes memory _requestModuleData, + bytes memory _responseModuleData, + bytes memory _disputeModuleData, + bytes memory _resolutionModuleData, + bytes memory _finalityModuleData + ); + + /** + * @notice The arbitrator of the contract + * @return _arbitrator The arbitrator */ - function owner() external view returns (address _owner); + function arbitrator() external view returns (address _arbitrator); /** - * @notice The pending owner of the contract - * @return _pendingOwner The pending owner + * @notice The pending arbitrator of the contract + * @return _pendingArbitrator The pending owner */ - function pendingOwner() external view returns (address _pendingOwner); + function pendingArbitrator() external view returns (address _pendingArbitrator); /** * @notice The reward paid for each chain updated @@ -99,20 +141,31 @@ interface IEBORequestCreator { */ function reward() external view returns (uint256 _reward); + /** + * @notice The request id per chain and epoch + * @param _chainId The chain id + * @param _epoch The epoch + * @return _requestId The request id + */ + function requestIdPerChainAndEpoch( + string calldata _chainId, + uint256 _epoch + ) external view returns (bytes32 _requestId); + /*/////////////////////////////////////////////////////////////// LOGIC //////////////////////////////////////////////////////////////*/ /** - * @notice Set the pending owner - * @param _pendingOwner The address of the pending owner + * @notice Set the pending arbitrator + * @param _pendingArbitrator The address of the pending arbitrator */ - function setPendingOwner(address _pendingOwner) external; + function setPendingArbitrator(address _pendingArbitrator) external; /** - * @notice Accept the pending owner + * @notice Accept the pending arbitrator */ - function acceptPendingOwner() external; + function acceptPendingArbitrator() external; /** * @notice Create requests @@ -138,4 +191,10 @@ interface IEBORequestCreator { * @param _reward The reward to set */ function setReward(uint256 _reward) external; + + /** + * @notice Set the request data + * @param _requestData The request data to set + */ + function setRequestData(RequestData calldata _requestData) external; } diff --git a/test/integration/CreateRequest.t.sol b/test/integration/CreateRequest.t.sol new file mode 100644 index 0000000..e87e302 --- /dev/null +++ b/test/integration/CreateRequest.t.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import './IntegrationBase.sol'; + +contract Integration_CreateRequest is IntegrationBase { + function test_createRequest() public { + string[] memory _chainIds = new string[](1); + _chainIds[0] = 'chainId1'; + + // Create a request without approving the chain id + vm.expectRevert(IEBORequestCreator.EBORequestCreator_ChainNotAdded.selector); + vm.prank(_user); + _eboRequestCreator.createRequests(1, _chainIds); + + // Create a request with an approved chain id + vm.prank(_arbitrator); + _eboRequestCreator.addChain('chainId1'); + + bytes32 _requestId = keccak256('requestId'); + // TODO: Remove the mock when the Oracle contract is implemented + vm.mockCall(address(_oracle), abi.encodeWithSelector(IOracle.createRequest.selector), abi.encode(_requestId)); + + vm.prank(_user); + _eboRequestCreator.createRequests(1, _chainIds); + assertEq(_eboRequestCreator.requestIdPerChainAndEpoch('chainId1', 1), _requestId); + + // Remove the chain id + vm.prank(_arbitrator); + _eboRequestCreator.removeChain('chainId1'); + + // Create a request without approving the chain id + vm.expectRevert(IEBORequestCreator.EBORequestCreator_ChainNotAdded.selector); + vm.prank(_user); + _eboRequestCreator.createRequests(1, _chainIds); + } +} diff --git a/test/integration/IntegrationBase.sol b/test/integration/IntegrationBase.sol index 0569527..08303fa 100644 --- a/test/integration/IntegrationBase.sol +++ b/test/integration/IntegrationBase.sol @@ -4,17 +4,24 @@ pragma solidity 0.8.26; import {Test} from 'forge-std/Test.sol'; import {IERC20} from 'forge-std/interfaces/IERC20.sol'; +import {EBORequestCreator, IEBORequestCreator, IOracle} from 'contracts/EBORequestCreator.sol'; + contract IntegrationBase is Test { uint256 internal constant _FORK_BLOCK = 18_920_905; - string internal _initialGreeting = 'hola'; - address internal _user = makeAddr('user'); + address internal _arbitrator = makeAddr('arbitrator'); address internal _owner = makeAddr('owner'); - address internal _daiWhale = 0x42f8CA49E88A8fd8F0bfA2C739e648468b8f9dec; - IERC20 internal _dai = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F); + address internal _user = makeAddr('user'); + + IEBORequestCreator internal _eboRequestCreator; + IOracle internal _oracle; function setUp() public { vm.createSelectFork(vm.rpcUrl('mainnet'), _FORK_BLOCK); - vm.prank(_owner); + vm.startPrank(_owner); + + _eboRequestCreator = new EBORequestCreator(_oracle, _arbitrator); + + vm.stopPrank(); } } diff --git a/test/unit/EBORequestCreator.t.sol b/test/unit/EBORequestCreator.t.sol index 8f3c4ef..3102ff4 100644 --- a/test/unit/EBORequestCreator.t.sol +++ b/test/unit/EBORequestCreator.t.sol @@ -13,130 +13,135 @@ contract EBORequestCreatorForTest is EBORequestCreator { constructor(IOracle _oracle, address _owner) EBORequestCreator(_oracle, _owner) {} - function setPendingOwnerForTest(address _pendingOwner) external { - pendingOwner = _pendingOwner; + function setPendingArbitratorForTest(address _pendingArbitrator) external { + pendingArbitrator = _pendingArbitrator; } function setChainIdForTest(string calldata _chainId) external returns (bool _added) { _added = _chainIdsAllowed.add(_encodeChainId(_chainId)); } + + function setRequestIdPerChainAndEpochForTest(string calldata _chainId, uint256 _epoch, bytes32 _requestId) external { + requestIdPerChainAndEpoch[_chainId][_epoch] = _requestId; + } } -abstract contract EBORequestCreatorUnitTest is Test { +abstract contract EBORequestCreator_Unit_BaseTest is Test { /// Events - event PendingOwnerSetted(address _pendingOwner); - event OwnerSetted(address _oldOwner, address _newOwner); + event PendingArbitratorSetted(address _pendingArbitrator); + event ArbitratorSetted(address _oldArbitrator, address _newArbitrator); event RequestCreated(bytes32 indexed _requestId, uint256 indexed _epoch, string indexed _chainId); event ChainAdded(string indexed _chainId); event ChainRemoved(string indexed _chainId); event RewardSet(uint256 _oldReward, uint256 _newReward); + event RequestDataSet(EBORequestCreator.RequestData _requestData); /// Contracts EBORequestCreatorForTest public eboRequestCreator; IOracle public oracle; /// EOAs - address public owner; + address public arbitrator; function setUp() external { - owner = makeAddr('Owner'); + arbitrator = makeAddr('Arbitrator'); oracle = IOracle(makeAddr('Oracle')); - vm.prank(owner); - eboRequestCreator = new EBORequestCreatorForTest(oracle, owner); + vm.prank(arbitrator); + eboRequestCreator = new EBORequestCreatorForTest(oracle, arbitrator); } - function _revertIfNotOwner() internal { - vm.expectRevert(IEBORequestCreator.EBORequestCreator_OnlyOwner.selector); + function _revertIfNotArbitrator() internal { + vm.expectRevert(IEBORequestCreator.EBORequestCreator_OnlyArbitrator.selector); } } -contract UnitEBORequestCreatorConstructor is EBORequestCreatorUnitTest { +contract EBORequestCreator_Unit_Constructor is EBORequestCreator_Unit_BaseTest { /** * @notice Test the constructor */ - function testConstructor() external view { + function test_constructor() external view { assertEq(eboRequestCreator.reward(), 0); - assertEq(eboRequestCreator.owner(), owner); - assertEq(eboRequestCreator.pendingOwner(), address(0)); + assertEq(eboRequestCreator.arbitrator(), arbitrator); + assertEq(eboRequestCreator.pendingArbitrator(), address(0)); assertEq(address(eboRequestCreator.oracle()), address(oracle)); } } -contract UnitEBORequestCreatorSetPendingOwner is EBORequestCreatorUnitTest { - modifier happyPath(address _pendingOwner) { - vm.startPrank(owner); +contract EBORequestCreator_Unit_SetPendingArbitrator is EBORequestCreator_Unit_BaseTest { + modifier happyPath(address _pendingArbitrator) { + vm.startPrank(arbitrator); _; } /** - * @notice Test the revert if the caller is not the owner + * @notice Test the revert if the caller is not the arbitrator */ - function testRevertIfNotOwner(address _pendingOwner) external { - _revertIfNotOwner(); - eboRequestCreator.setPendingOwner(_pendingOwner); + function test_revertIfNotArbitrator(address _pendingArbitrator) external { + vm.expectRevert(IEBORequestCreator.EBORequestCreator_OnlyArbitrator.selector); + eboRequestCreator.setPendingArbitrator(_pendingArbitrator); } /** - * @notice Test the set pending owner + * @notice Test the set pending arbitrator */ - function testSetPendingOwner(address _pendingOwner) external happyPath(_pendingOwner) { - eboRequestCreator.setPendingOwner(_pendingOwner); + function test_setPendingArbitrator(address _pendingArbitrator) external happyPath(_pendingArbitrator) { + eboRequestCreator.setPendingArbitrator(_pendingArbitrator); - assertEq(eboRequestCreator.pendingOwner(), _pendingOwner); + assertEq(eboRequestCreator.pendingArbitrator(), _pendingArbitrator); } /** - * @notice Test the emit pending owner setted + * @notice Test the emit pending arbitrator setted */ - function testEmitPendingOwnerSetted(address _pendingOwner) external happyPath(_pendingOwner) { + function test_emitPendingArbitratorSetted(address _pendingArbitrator) external happyPath(_pendingArbitrator) { vm.expectEmit(); - emit PendingOwnerSetted(_pendingOwner); + emit PendingArbitratorSetted(_pendingArbitrator); - eboRequestCreator.setPendingOwner(_pendingOwner); + eboRequestCreator.setPendingArbitrator(_pendingArbitrator); } } -contract UnitEBORequestCreatorAcceptPendingOwner is EBORequestCreatorUnitTest { - modifier happyPath(address _pendingOwner) { - eboRequestCreator.setPendingOwnerForTest(_pendingOwner); - vm.startPrank(_pendingOwner); +contract EBORequestCreator_Unit_AcceptPendingArbitrator is EBORequestCreator_Unit_BaseTest { + modifier happyPath(address _pendingArbitrator) { + eboRequestCreator.setPendingArbitratorForTest(_pendingArbitrator); + vm.startPrank(_pendingArbitrator); _; } /** - * @notice Test the revert if the caller is not the pending owner + * @notice Test the revert if the caller is not the pending arbitrator */ - function testRevertIfNotPendingOwner() external { - vm.expectRevert(IEBORequestCreator.EBORequestCreator_OnlyPendingOwner.selector); - eboRequestCreator.acceptPendingOwner(); + function test_revertIfNotPendingArbitrator() external { + vm.expectRevert(IEBORequestCreator.EBORequestCreator_OnlyPendingArbitrator.selector); + eboRequestCreator.acceptPendingArbitrator(); } /** - * @notice Test the accept pending owner + * @notice Test the accept pending arbitrator */ - function testAcceptPendingOwner(address _pendingOwner) external happyPath(_pendingOwner) { - eboRequestCreator.acceptPendingOwner(); + function test_acceptPendingArbitrator(address _pendingArbitrator) external happyPath(_pendingArbitrator) { + eboRequestCreator.acceptPendingArbitrator(); - assertEq(eboRequestCreator.owner(), _pendingOwner); - assertEq(eboRequestCreator.pendingOwner(), address(0)); + assertEq(eboRequestCreator.arbitrator(), _pendingArbitrator); + assertEq(eboRequestCreator.pendingArbitrator(), address(0)); } /** - * @notice Test the emit owner setted + * @notice Test the emit arbitrator setted */ - function testEmitOwnerSetted(address _pendingOwner) external happyPath(_pendingOwner) { + function test_emitArbitratorSetted(address _pendingArbitrator) external happyPath(_pendingArbitrator) { vm.expectEmit(); - emit OwnerSetted(owner, _pendingOwner); + emit ArbitratorSetted(arbitrator, _pendingArbitrator); - eboRequestCreator.acceptPendingOwner(); + eboRequestCreator.acceptPendingArbitrator(); } } -contract UnitEBORequestCreatorCreateRequest is EBORequestCreatorUnitTest { +contract EBORequestCreator_Unit_CreateRequest is EBORequestCreator_Unit_BaseTest { string[] internal _cleanChainIds; - modifier happyPath(uint256 _epoch, string[] calldata _chainId) { + modifier happyPath(uint256 _epoch, string[] memory _chainId) { vm.assume(_epoch > 0); vm.assume(_chainId.length > 0 && _chainId.length < 30); @@ -148,29 +153,48 @@ contract UnitEBORequestCreatorCreateRequest is EBORequestCreatorUnitTest { } } - vm.startPrank(owner); + vm.startPrank(arbitrator); _; } /** - * @notice Test the revert if the caller is not the owner + * @notice Test the revert if the caller is not the arbitrator */ - function testRevertIfChainNotAdded() external { + function test_revertIfChainNotAdded() external { vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_ChainNotAdded.selector)); eboRequestCreator.createRequests(0, new string[](1)); } + /** + * @notice Test if the request id exists skip the request creation + */ + function test_expectNotEmitRequestIdExists( + uint256 _epoch, + string calldata _chainId, + bytes32 _requestId + ) external happyPath(_epoch, new string[](1)) { + vm.assume(_requestId != bytes32(0)); + eboRequestCreator.setChainIdForTest(_chainId); + eboRequestCreator.setRequestIdPerChainAndEpochForTest(_chainId, _epoch, _requestId); + + vm.expectCall(address(oracle), abi.encodeWithSelector(IOracle.createRequest.selector), 0); + + string[] memory _chainIds = new string[](1); + _chainIds[0] = _chainId; + + eboRequestCreator.createRequests(_epoch, _chainIds); + } /** * @notice Test the create requests */ - function testEmitCreateRequest( + + function test_emitCreateRequest( uint256 _epoch, string[] calldata _chainIds, bytes32 _requestId ) external happyPath(_epoch, _chainIds) { for (uint256 _i; _i < _cleanChainIds.length; _i++) { - console.log(_cleanChainIds[_i]); vm.mockCall(address(oracle), abi.encodeWithSelector(IOracle.createRequest.selector), abi.encode(_requestId)); vm.expectEmit(); emit RequestCreated(_requestId, _epoch, _cleanChainIds[_i]); @@ -180,24 +204,24 @@ contract UnitEBORequestCreatorCreateRequest is EBORequestCreatorUnitTest { } } -contract UnitEBORequestCreatorAddChain is EBORequestCreatorUnitTest { +contract EBORequestCreator_Unit_AddChain is EBORequestCreator_Unit_BaseTest { modifier happyPath() { - vm.startPrank(owner); + vm.startPrank(arbitrator); _; } /** - * @notice Test the revert if the caller is not the owner + * @notice Test the revert if the caller is not the arbitrator */ - function testRevertIfNotOwner(string calldata _chainId) external { - _revertIfNotOwner(); + function test_revertIfNotArbitrator(string calldata _chainId) external { + _revertIfNotArbitrator(); eboRequestCreator.addChain(_chainId); } /** * @notice Test the revert if the chain is already added */ - function testRevertIfChainAdded(string calldata _chainId) external happyPath { + function test_revertIfChainAdded(string calldata _chainId) external happyPath { eboRequestCreator.setChainIdForTest(_chainId); vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_ChainAlreadyAdded.selector)); @@ -207,7 +231,7 @@ contract UnitEBORequestCreatorAddChain is EBORequestCreatorUnitTest { /** * @notice Test the emit chain added */ - function testEmitChainAdded(string calldata _chainId) external happyPath { + function test_emitChainAdded(string calldata _chainId) external happyPath { vm.expectEmit(); emit ChainAdded(_chainId); @@ -215,35 +239,35 @@ contract UnitEBORequestCreatorAddChain is EBORequestCreatorUnitTest { } } -contract UnitEBORequestCreatorRemoveChain is EBORequestCreatorUnitTest { +contract EBORequestCreator_Unit_RemoveChain is EBORequestCreator_Unit_BaseTest { modifier happyPath(string calldata _chainId) { eboRequestCreator.setChainIdForTest(_chainId); - vm.startPrank(owner); + vm.startPrank(arbitrator); _; } /** - * @notice Test the revert if the caller is not the owner + * @notice Test the revert if the caller is not the arbitrator */ - function testRevertIfNotOwner(string calldata _chainId) external { - _revertIfNotOwner(); + function test_revertIfNotArbitrator(string calldata _chainId) external { + _revertIfNotArbitrator(); eboRequestCreator.removeChain(_chainId); } /** * @notice Test the revert if the chain is not added */ - function testRevertIfChainNotAdded(string calldata _chainId) external { + function test_revertIfChainNotAdded(string calldata _chainId) external { vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_ChainNotAdded.selector)); - vm.prank(owner); + vm.prank(arbitrator); eboRequestCreator.removeChain(_chainId); } /** * @notice Test the emit chain removed */ - function testEmitChainRemoved(string calldata _chainId) external happyPath(_chainId) { + function test_emitChainRemoved(string calldata _chainId) external happyPath(_chainId) { vm.expectEmit(); emit ChainRemoved(_chainId); @@ -251,24 +275,24 @@ contract UnitEBORequestCreatorRemoveChain is EBORequestCreatorUnitTest { } } -contract UnitEBORequestCreatorSetReward is EBORequestCreatorUnitTest { +contract EBORequestCreator_Unit_SetReward is EBORequestCreator_Unit_BaseTest { modifier happyPath(uint256 _reward) { - vm.startPrank(owner); + vm.startPrank(arbitrator); _; } /** - * @notice Test the revert if the caller is not the owner + * @notice Test the revert if the caller is not the arbitrator */ - function testRevertIfNotOwner(uint256 _reward) external { - vm.expectRevert(); + function test_revertIfNotArbitrator(uint256 _reward) external { + _revertIfNotArbitrator(); eboRequestCreator.setReward(_reward); } /** * @notice Test the set reward */ - function testSetReward(uint256 _reward) external happyPath(_reward) { + function test_setReward(uint256 _reward) external happyPath(_reward) { eboRequestCreator.setReward(_reward); assertEq(eboRequestCreator.reward(), _reward); @@ -277,10 +301,69 @@ contract UnitEBORequestCreatorSetReward is EBORequestCreatorUnitTest { /** * @notice Test the emit reward set */ - function testEmitRewardSet(uint256 _reward) external happyPath(_reward) { + function test_emitRewardSet(uint256 _reward) external happyPath(_reward) { vm.expectEmit(); emit RewardSet(0, _reward); eboRequestCreator.setReward(_reward); } } + +contract EBORequestCreator_Unit_SetRequestData is EBORequestCreator_Unit_BaseTest { + modifier happyPath(EBORequestCreator.RequestData calldata _requestData) { + vm.startPrank(arbitrator); + _; + } + + /** + * @notice Test the revert if the caller is not the arbitrator + */ + function test_revertIfNotArbitrator(EBORequestCreator.RequestData calldata _requestData) external { + _revertIfNotArbitrator(); + eboRequestCreator.setRequestData(_requestData); + } + + /** + * @notice Test the set request data + */ + function test_setRequestData(EBORequestCreator.RequestData calldata _requestData) external happyPath(_requestData) { + eboRequestCreator.setRequestData(_requestData); + + ( + address _requestModule, + address _responseModule, + address _disputeModule, + address _resolutionModule, + address _finalityModule, + bytes memory _requestModuleData, + bytes memory _responseModuleData, + bytes memory _disputeModuleData, + bytes memory _resolutionModuleData, + bytes memory _finalityModuleData + ) = eboRequestCreator.requestData(); + + assertEq(_requestModule, _requestData.requestModule); + assertEq(_responseModule, _requestData.responseModule); + assertEq(_disputeModule, _requestData.disputeModule); + assertEq(_resolutionModule, _requestData.resolutionModule); + assertEq(_finalityModule, _requestData.finalityModule); + assertEq(_requestModuleData, _requestData.requestModuleData); + assertEq(_responseModuleData, _requestData.responseModuleData); + assertEq(_disputeModuleData, _requestData.disputeModuleData); + assertEq(_resolutionModuleData, _requestData.resolutionModuleData); + assertEq(_finalityModuleData, _requestData.finalityModuleData); + } + + /** + * @notice Test the emit request data set + */ + function test_emitRequestDataSet(EBORequestCreator.RequestData calldata _requestData) + external + happyPath(_requestData) + { + vm.expectEmit(); + emit RequestDataSet(_requestData); + + eboRequestCreator.setRequestData(_requestData); + } +} From dd52cecb544b80acd0d5b239fcc7bcd5e9180dff Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Fri, 9 Aug 2024 00:23:28 -0300 Subject: [PATCH 05/19] feat: epoch manager and epoch control --- package.json | 2 +- remappings.txt | 2 +- src/contracts/Arbitrable.sol | 4 +- src/contracts/EBORequestCreator.sol | 117 +++--- src/interfaces/IArbitrable.sol | 6 +- src/interfaces/IEBORequestCreator.sol | 164 ++++---- src/interfaces/external/IEpochManager.sol | 10 + test/integration/CreateRequest.t.sol | 3 + test/integration/IntegrationBase.sol | 11 +- test/unit/EBORequestCreator.t.sol | 325 +++++++++------- yarn.lock | 453 +++++++++++----------- 11 files changed, 593 insertions(+), 504 deletions(-) create mode 100644 src/interfaces/external/IEpochManager.sol diff --git a/package.json b/package.json index eb82655..5b71c40 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "package.json": "sort-package-json" }, "dependencies": { - "@defi-wonderland/prophet-core-contracts": "0.0.0-438de1c5", + "@defi-wonderland/prophet-core": "0.0.0-172a7bcf", "@defi-wonderland/prophet-modules-contracts": "0.0.0-1197c328" }, "devDependencies": { diff --git a/remappings.txt b/remappings.txt index 2245399..9ae4470 100644 --- a/remappings.txt +++ b/remappings.txt @@ -1,6 +1,6 @@ forge-std/=node_modules/forge-std/src halmos-cheatcodes=node_modules/halmos-cheatcodes -@defi-wonderland/prophet-core-contracts/=node_modules/@defi-wonderland/prophet-core-contracts +@defi-wonderland/prophet-core/=node_modules/@defi-wonderland/prophet-core @defi-wonderland/prophet-modules-contracts/=node_modules/@defi-wonderland/prophet-modules-contracts contracts/=src/contracts diff --git a/src/contracts/Arbitrable.sol b/src/contracts/Arbitrable.sol index ada965e..8bb83f4 100644 --- a/src/contracts/Arbitrable.sol +++ b/src/contracts/Arbitrable.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; import {IArbitrable} from 'interfaces/IArbitrable.sol'; diff --git a/src/contracts/EBORequestCreator.sol b/src/contracts/EBORequestCreator.sol index 1013926..e408749 100644 --- a/src/contracts/EBORequestCreator.sol +++ b/src/contracts/EBORequestCreator.sol @@ -2,25 +2,24 @@ pragma solidity 0.8.26; import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; -import {IEBORequestCreator, IOracle} from 'interfaces/IEBORequestCreator.sol'; -contract EBORequestCreator is IEBORequestCreator { +import {Arbitrable} from 'contracts/Arbitrable.sol'; +import {IEBORequestCreator, IEpochManager, IOracle} from 'interfaces/IEBORequestCreator.sol'; + +contract EBORequestCreator is IEBORequestCreator, Arbitrable { using EnumerableSet for EnumerableSet.Bytes32Set; /// @inheritdoc IEBORequestCreator IOracle public oracle; /// @inheritdoc IEBORequestCreator - RequestData public requestData; - - /// @inheritdoc IEBORequestCreator - address public arbitrator; + IEpochManager public epochManager; /// @inheritdoc IEBORequestCreator - address public pendingArbitrator; + IOracle.Request public requestData; /// @inheritdoc IEBORequestCreator - uint256 public reward; + uint256 public startEpoch; /// @inheritdoc IEBORequestCreator mapping(string _chainId => mapping(uint256 _epoch => bytes32 _requestId)) public requestIdPerChainAndEpoch; @@ -30,33 +29,25 @@ contract EBORequestCreator is IEBORequestCreator { */ EnumerableSet.Bytes32Set internal _chainIdsAllowed; - constructor(IOracle _oracle, address _arbitrator) { + constructor( + IOracle _oracle, + IEpochManager _epochManager, + address _arbitrator, + address _council + ) Arbitrable(_arbitrator, _council) { oracle = _oracle; - arbitrator = _arbitrator; - reward = 0; - } - - /// @inheritdoc IEBORequestCreator - function setPendingArbitrator(address _pendingArbitrator) external onlyArbitrator { - pendingArbitrator = _pendingArbitrator; - - emit PendingArbitratorSetted(_pendingArbitrator); - } - - /// @inheritdoc IEBORequestCreator - function acceptPendingArbitrator() external onlyPendingArbitrator { - address _oldArbitrator = arbitrator; - arbitrator = pendingArbitrator; - pendingArbitrator = address(0); + epochManager = _epochManager; - emit ArbitratorSetted(_oldArbitrator, arbitrator); + startEpoch = epochManager.currentEpoch(); } /// @inheritdoc IEBORequestCreator function createRequests(uint256 _epoch, string[] calldata _chainIds) external { + if (_epoch > epochManager.currentEpoch() || startEpoch > _epoch) revert EBORequestCreator_EpochNotValid(); + bytes32 _encodedChainId; - RequestData memory _requestData = requestData; + IOracle.Request memory _requestData = requestData; for (uint256 _i; _i < _chainIds.length; _i++) { _encodedChainId = _encodeChainId(_chainIds[_i]); @@ -111,45 +102,61 @@ contract EBORequestCreator is IEBORequestCreator { } /// @inheritdoc IEBORequestCreator - function setReward(uint256 _reward) external onlyArbitrator { - uint256 _oldReward = reward; - reward = _reward; - emit RewardSet(_oldReward, _reward); + function setRequestModuleData(address _requestModule, bytes calldata _requestModuleData) external onlyArbitrator { + requestData.requestModule = _requestModule; + requestData.requestModuleData = _requestModuleData; + + emit RequestModuleDataSet(_requestModule, _requestModuleData); } /// @inheritdoc IEBORequestCreator - function setRequestData(RequestData calldata _requestData) external onlyArbitrator { - requestData = _requestData; + function setResponseModuleData(address _responseModule, bytes calldata _responseModuleData) external onlyArbitrator { + requestData.responseModule = _responseModule; + requestData.responseModuleData = _responseModuleData; - emit RequestDataSet(_requestData); + emit ResponseModuleDataSet(_responseModule, _responseModuleData); } - /** - * @notice Encodes the chain id - * @dev The chain id is hashed to have a enumerable set to avoid duplicates - */ - function _encodeChainId(string calldata _chainId) internal pure returns (bytes32 _encodedChainId) { - _encodedChainId = keccak256(abi.encodePacked(_chainId)); + /// TODO: Change module data to the specific interface when we have + /// @inheritdoc IEBORequestCreator + function setDisputeModuleData(address _disputeModule, bytes calldata _disputeModuleData) external onlyArbitrator { + requestData.disputeModule = _disputeModule; + requestData.disputeModuleData = _disputeModuleData; + + emit DisputeModuleDataSet(_disputeModule, _disputeModuleData); } - /** - * @notice Checks if the sender is the arbitrator - */ - modifier onlyArbitrator() { - if (msg.sender != arbitrator) { - revert EBORequestCreator_OnlyArbitrator(); - } - _; + /// @inheritdoc IEBORequestCreator + function setResolutionModuleData( + address _resolutionModule, + bytes calldata _resolutionModuleData + ) external onlyArbitrator { + requestData.resolutionModule = _resolutionModule; + requestData.resolutionModuleData = _resolutionModuleData; + + emit ResolutionModuleDataSet(_resolutionModule, _resolutionModuleData); + } + + /// @inheritdoc IEBORequestCreator + function setFinalityModuleData(address _finalityModule, bytes calldata _finalityModuleData) external onlyArbitrator { + requestData.finalityModule = _finalityModule; + requestData.finalityModuleData = _finalityModuleData; + + emit FinalityModuleDataSet(_finalityModule, _finalityModuleData); + } + + /// @inheritdoc IEBORequestCreator + function setEpochManager(IEpochManager _epochManager) external onlyArbitrator { + epochManager = _epochManager; + + emit EpochManagerSet(_epochManager); } /** - * @notice Checks if the sender is the pending arbitrator + * @notice Encodes the chain id + * @dev The chain id is hashed to have a enumerable set to avoid duplicates */ - modifier onlyPendingArbitrator() { - if (msg.sender != pendingArbitrator) { - revert EBORequestCreator_OnlyPendingArbitrator(); - } - - _; + function _encodeChainId(string calldata _chainId) internal pure returns (bytes32 _encodedChainId) { + _encodedChainId = keccak256(abi.encodePacked(_chainId)); } } diff --git a/src/interfaces/IArbitrable.sol b/src/interfaces/IArbitrable.sol index 5d98b9e..c5faa69 100644 --- a/src/interfaces/IArbitrable.sol +++ b/src/interfaces/IArbitrable.sol @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; /** * @title Arbitrable * @notice Makes a contract subject to arbitration by The Graph */ + interface IArbitrable { /*/////////////////////////////////////////////////////////////// EVENTS diff --git a/src/interfaces/IEBORequestCreator.sol b/src/interfaces/IEBORequestCreator.sol index d967208..aba0e44 100644 --- a/src/interfaces/IEBORequestCreator.sol +++ b/src/interfaces/IEBORequestCreator.sol @@ -1,26 +1,14 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import {IOracle} from '@defi-wonderland/prophet-core-contracts/solidity/interfaces/IOracle.sol'; +import {IOracle} from '@defi-wonderland/prophet-core/solidity/interfaces/IOracle.sol'; +import {IEpochManager} from 'interfaces/external/IEpochManager.sol'; interface IEBORequestCreator { /*/////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ - /** - * @notice Emitted when the pending arbitrator is set - * @param _pendingArbitrator The address of the pending arbitrator - */ - event PendingArbitratorSetted(address _pendingArbitrator); - - /** - * @notice Emitted when the abitrator is set - * @param _oldArbitrator The old abitrator address - * @param _newArbitrator The new abitrator address - */ - event ArbitratorSetted(address _oldArbitrator, address _newArbitrator); - /** * @notice Emitted when a request is created * @param _requestId The id of the request @@ -42,31 +30,49 @@ interface IEBORequestCreator { event ChainRemoved(string indexed _chainId); /** - * @notice Emitted when the reward is set - * @param _oldReward The old reward value - * @param _newReward The new reward value + * @notice Emitted when the request data module is set + * @param _requestModule The request module + * @param _requestModuleData The request module data */ - event RewardSet(uint256 _oldReward, uint256 _newReward); + event RequestModuleDataSet(address indexed _requestModule, bytes _requestModuleData); /** - * @notice Emitted when a request data is set - * @param _requestData The request data + * @notice Emitted when the response data module is set + * @param _responseModule The response module + * @param _responseModuleData The response module data */ - event RequestDataSet(RequestData _requestData); + event ResponseModuleDataSet(address indexed _responseModule, bytes _responseModuleData); - /*/////////////////////////////////////////////////////////////// - ERRORS - //////////////////////////////////////////////////////////////*/ + /** + * @notice Emitted when the dispute data module is set + * @param _disputeModule The dispute module + * @param _disputeModuleData The dispute module data + */ + event DisputeModuleDataSet(address indexed _disputeModule, bytes _disputeModuleData); + + /** + * @notice Emitted when the resolution data module is set + * @param _resolutionModule The resolution module + * @param _resolutionModuleData The resolution module data + */ + event ResolutionModuleDataSet(address indexed _resolutionModule, bytes _resolutionModuleData); /** - * @notice Thrown when the caller is not the arbitrator + * @notice Emitted when the finality data module is set + * @param _finalityModule The finality module + * @param _finalityModuleData The finality module data */ - error EBORequestCreator_OnlyArbitrator(); + event FinalityModuleDataSet(address indexed _finalityModule, bytes _finalityModuleData); /** - * @notice Thrown when the caller is not the pending arbitrator + * @notice Emitted when the epoch manager is set + * @param _epochManager The epoch manager */ - error EBORequestCreator_OnlyPendingArbitrator(); + event EpochManagerSet(IEpochManager indexed _epochManager); + + /*/////////////////////////////////////////////////////////////// + ERRORS + //////////////////////////////////////////////////////////////*/ /** * @notice hrown when the chain is already added @@ -78,22 +84,10 @@ interface IEBORequestCreator { */ error EBORequestCreator_ChainNotAdded(); - /*/////////////////////////////////////////////////////////////// - STRUCTS - //////////////////////////////////////////////////////////////*/ - - struct RequestData { - address requestModule; - address responseModule; - address disputeModule; - address resolutionModule; - address finalityModule; - bytes requestModuleData; - bytes responseModuleData; - bytes disputeModuleData; - bytes resolutionModuleData; - bytes finalityModuleData; - } + /** + * @notice Thrown when the epoch is not valid + */ + error EBORequestCreator_EpochNotValid(); /*/////////////////////////////////////////////////////////////// VARIABLES @@ -104,6 +98,16 @@ interface IEBORequestCreator { */ function oracle() external view returns (IOracle _oracle); + /** + * @notice The epoch manager contract + */ + function epochManager() external view returns (IEpochManager _epochManager); + + /** + * @notice The first valid epoch to create requests + */ + function startEpoch() external view returns (uint256 _startEpoch); + /** * @notice The request data */ @@ -111,6 +115,8 @@ interface IEBORequestCreator { external view returns ( + uint96 _nonce, + address _requester, address _requestModule, address _responseModule, address _disputeModule, @@ -123,24 +129,6 @@ interface IEBORequestCreator { bytes memory _finalityModuleData ); - /** - * @notice The arbitrator of the contract - * @return _arbitrator The arbitrator - */ - function arbitrator() external view returns (address _arbitrator); - - /** - * @notice The pending arbitrator of the contract - * @return _pendingArbitrator The pending owner - */ - function pendingArbitrator() external view returns (address _pendingArbitrator); - - /** - * @notice The reward paid for each chain updated - * @return _reward The reward - */ - function reward() external view returns (uint256 _reward); - /** * @notice The request id per chain and epoch * @param _chainId The chain id @@ -156,17 +144,6 @@ interface IEBORequestCreator { LOGIC //////////////////////////////////////////////////////////////*/ - /** - * @notice Set the pending arbitrator - * @param _pendingArbitrator The address of the pending arbitrator - */ - function setPendingArbitrator(address _pendingArbitrator) external; - - /** - * @notice Accept the pending arbitrator - */ - function acceptPendingArbitrator() external; - /** * @notice Create requests * @param _epoch The epoch of the request @@ -187,14 +164,43 @@ interface IEBORequestCreator { function removeChain(string calldata _chainId) external; /** - * @notice Set the reward paid for each chain updated - * @param _reward The reward to set + * @notice Set the request data module + * @param _requestModule The request module + * @param _requestModuleData The request module data + */ + function setRequestModuleData(address _requestModule, bytes calldata _requestModuleData) external; + + /** + * @notice Set the response data module + * @param _responseModule The response module + * @param _responseModuleData The response module data + */ + function setResponseModuleData(address _responseModule, bytes calldata _responseModuleData) external; + + /** + * @notice Set the dispute data module + * @param _disputeModule The dispute module + * @param _disputeModuleData The dispute module data + */ + function setDisputeModuleData(address _disputeModule, bytes calldata _disputeModuleData) external; + + /** + * @notice Set the resolution data module + * @param _resolutionModule The resolution module + * @param _resolutionModuleData The resolution module data + */ + function setResolutionModuleData(address _resolutionModule, bytes calldata _resolutionModuleData) external; + + /** + * @notice Set the finality data module + * @param _finalityModule The finality module + * @param _finalityModuleData The finality module data */ - function setReward(uint256 _reward) external; + function setFinalityModuleData(address _finalityModule, bytes calldata _finalityModuleData) external; /** - * @notice Set the request data - * @param _requestData The request data to set + * @notice Set the epoch manager + * @param _epochManager The epoch manager */ - function setRequestData(RequestData calldata _requestData) external; + function setEpochManager(IEpochManager _epochManager) external; } diff --git a/src/interfaces/external/IEpochManager.sol b/src/interfaces/external/IEpochManager.sol new file mode 100644 index 0000000..80fc409 --- /dev/null +++ b/src/interfaces/external/IEpochManager.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; + +interface IEpochManager { + /*/////////////////////////////////////////////////////////////// + FUNCTIONS + //////////////////////////////////////////////////////////////*/ + + function currentEpoch() external view returns (uint256 _currentEpoch); +} diff --git a/test/integration/CreateRequest.t.sol b/test/integration/CreateRequest.t.sol index e87e302..e4f279d 100644 --- a/test/integration/CreateRequest.t.sol +++ b/test/integration/CreateRequest.t.sol @@ -8,6 +8,9 @@ contract Integration_CreateRequest is IntegrationBase { string[] memory _chainIds = new string[](1); _chainIds[0] = 'chainId1'; + // TODO: Replace with the implementation + vm.mockCall(address(_epochManager), abi.encodeWithSelector(IEpochManager.currentEpoch.selector), abi.encode(1)); + // Create a request without approving the chain id vm.expectRevert(IEBORequestCreator.EBORequestCreator_ChainNotAdded.selector); vm.prank(_user); diff --git a/test/integration/IntegrationBase.sol b/test/integration/IntegrationBase.sol index d24e0f9..ef086ff 100644 --- a/test/integration/IntegrationBase.sol +++ b/test/integration/IntegrationBase.sol @@ -4,25 +4,30 @@ pragma solidity 0.8.26; import {Test} from 'forge-std/Test.sol'; import {IERC20} from 'forge-std/interfaces/IERC20.sol'; -import {Oracle} from '@defi-wonderland/prophet-core-contracts/solidity/contracts/Oracle.sol'; -import {EBORequestCreator, IEBORequestCreator, IOracle} from 'contracts/EBORequestCreator.sol'; +import {Oracle} from '@defi-wonderland/prophet-core/solidity/contracts/Oracle.sol'; +import {EBORequestCreator, IEBORequestCreator, IEpochManager, IOracle} from 'contracts/EBORequestCreator.sol'; contract IntegrationBase is Test { uint256 internal constant _FORK_BLOCK = 18_920_905; address internal _arbitrator = makeAddr('arbitrator'); + address internal _council = makeAddr('council'); address internal _owner = makeAddr('owner'); address internal _user = makeAddr('user'); IEBORequestCreator internal _eboRequestCreator; IOracle internal _oracle; + IEpochManager internal _epochManager; function setUp() public { vm.createSelectFork(vm.rpcUrl('mainnet'), _FORK_BLOCK); vm.startPrank(_owner); _oracle = new Oracle(); - _eboRequestCreator = new EBORequestCreator(_oracle, _arbitrator); + + // TODO: Replace with the implementation + vm.mockCall(address(_epochManager), abi.encodeWithSelector(IEpochManager.currentEpoch.selector), abi.encode(0)); + _eboRequestCreator = new EBORequestCreator(_oracle, _epochManager, _arbitrator, _council); vm.stopPrank(); } diff --git a/test/unit/EBORequestCreator.t.sol b/test/unit/EBORequestCreator.t.sol index 3102ff4..6ad297b 100644 --- a/test/unit/EBORequestCreator.t.sol +++ b/test/unit/EBORequestCreator.t.sol @@ -3,7 +3,8 @@ pragma solidity 0.8.26; import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; -import {EBORequestCreator, IEBORequestCreator, IOracle} from 'contracts/EBORequestCreator.sol'; +import {EBORequestCreator, IEBORequestCreator, IEpochManager, IOracle} from 'contracts/EBORequestCreator.sol'; +import {IArbitrable} from 'interfaces/IArbitrable.sol'; import {Test} from 'forge-std/Test.sol'; import 'forge-std/console.sol'; @@ -11,11 +12,12 @@ import 'forge-std/console.sol'; contract EBORequestCreatorForTest is EBORequestCreator { using EnumerableSet for EnumerableSet.Bytes32Set; - constructor(IOracle _oracle, address _owner) EBORequestCreator(_oracle, _owner) {} - - function setPendingArbitratorForTest(address _pendingArbitrator) external { - pendingArbitrator = _pendingArbitrator; - } + constructor( + IOracle _oracle, + IEpochManager _epochManager, + address _arbitrator, + address _council + ) EBORequestCreator(_oracle, _epochManager, _arbitrator, _council) {} function setChainIdForTest(string calldata _chainId) external returns (bool _added) { _added = _chainIdsAllowed.add(_encodeChainId(_chainId)); @@ -24,35 +26,47 @@ contract EBORequestCreatorForTest is EBORequestCreator { function setRequestIdPerChainAndEpochForTest(string calldata _chainId, uint256 _epoch, bytes32 _requestId) external { requestIdPerChainAndEpoch[_chainId][_epoch] = _requestId; } + + function setStartEpochForTest(uint256 _startEpoch) external { + startEpoch = _startEpoch; + } } abstract contract EBORequestCreator_Unit_BaseTest is Test { /// Events - event PendingArbitratorSetted(address _pendingArbitrator); - event ArbitratorSetted(address _oldArbitrator, address _newArbitrator); + event RequestCreated(bytes32 indexed _requestId, uint256 indexed _epoch, string indexed _chainId); event ChainAdded(string indexed _chainId); event ChainRemoved(string indexed _chainId); - event RewardSet(uint256 _oldReward, uint256 _newReward); - event RequestDataSet(EBORequestCreator.RequestData _requestData); + event RequestModuleDataSet(address indexed _requestModule, bytes _requestModuleData); + event ResponseModuleDataSet(address indexed _responseModule, bytes _responseModuleData); + event DisputeModuleDataSet(address indexed _disputeModule, bytes _disputeModuleData); + event ResolutionModuleDataSet(address indexed _resolutionModule, bytes _resolutionModuleData); + event FinalityModuleDataSet(address indexed _finalityModule, bytes _finalityModuleData); + event EpochManagerSet(IEpochManager indexed _epochManager); /// Contracts EBORequestCreatorForTest public eboRequestCreator; IOracle public oracle; + IEpochManager public epochManager; /// EOAs address public arbitrator; + address public council; function setUp() external { + council = makeAddr('Council'); arbitrator = makeAddr('Arbitrator'); oracle = IOracle(makeAddr('Oracle')); + epochManager = IEpochManager(makeAddr('EpochManager')); - vm.prank(arbitrator); - eboRequestCreator = new EBORequestCreatorForTest(oracle, arbitrator); + vm.mockCall(address(epochManager), abi.encodeWithSelector(IEpochManager.currentEpoch.selector), abi.encode(0)); + + eboRequestCreator = new EBORequestCreatorForTest(oracle, epochManager, arbitrator, council); } function _revertIfNotArbitrator() internal { - vm.expectRevert(IEBORequestCreator.EBORequestCreator_OnlyArbitrator.selector); + vm.expectRevert(IArbitrable.Arbitrable_OnlyArbitrator.selector); } } @@ -61,83 +75,12 @@ contract EBORequestCreator_Unit_Constructor is EBORequestCreator_Unit_BaseTest { * @notice Test the constructor */ function test_constructor() external view { - assertEq(eboRequestCreator.reward(), 0); assertEq(eboRequestCreator.arbitrator(), arbitrator); - assertEq(eboRequestCreator.pendingArbitrator(), address(0)); + assertEq(eboRequestCreator.council(), council); assertEq(address(eboRequestCreator.oracle()), address(oracle)); } } -contract EBORequestCreator_Unit_SetPendingArbitrator is EBORequestCreator_Unit_BaseTest { - modifier happyPath(address _pendingArbitrator) { - vm.startPrank(arbitrator); - _; - } - - /** - * @notice Test the revert if the caller is not the arbitrator - */ - function test_revertIfNotArbitrator(address _pendingArbitrator) external { - vm.expectRevert(IEBORequestCreator.EBORequestCreator_OnlyArbitrator.selector); - eboRequestCreator.setPendingArbitrator(_pendingArbitrator); - } - - /** - * @notice Test the set pending arbitrator - */ - function test_setPendingArbitrator(address _pendingArbitrator) external happyPath(_pendingArbitrator) { - eboRequestCreator.setPendingArbitrator(_pendingArbitrator); - - assertEq(eboRequestCreator.pendingArbitrator(), _pendingArbitrator); - } - - /** - * @notice Test the emit pending arbitrator setted - */ - function test_emitPendingArbitratorSetted(address _pendingArbitrator) external happyPath(_pendingArbitrator) { - vm.expectEmit(); - emit PendingArbitratorSetted(_pendingArbitrator); - - eboRequestCreator.setPendingArbitrator(_pendingArbitrator); - } -} - -contract EBORequestCreator_Unit_AcceptPendingArbitrator is EBORequestCreator_Unit_BaseTest { - modifier happyPath(address _pendingArbitrator) { - eboRequestCreator.setPendingArbitratorForTest(_pendingArbitrator); - vm.startPrank(_pendingArbitrator); - _; - } - - /** - * @notice Test the revert if the caller is not the pending arbitrator - */ - function test_revertIfNotPendingArbitrator() external { - vm.expectRevert(IEBORequestCreator.EBORequestCreator_OnlyPendingArbitrator.selector); - eboRequestCreator.acceptPendingArbitrator(); - } - - /** - * @notice Test the accept pending arbitrator - */ - function test_acceptPendingArbitrator(address _pendingArbitrator) external happyPath(_pendingArbitrator) { - eboRequestCreator.acceptPendingArbitrator(); - - assertEq(eboRequestCreator.arbitrator(), _pendingArbitrator); - assertEq(eboRequestCreator.pendingArbitrator(), address(0)); - } - - /** - * @notice Test the emit arbitrator setted - */ - function test_emitArbitratorSetted(address _pendingArbitrator) external happyPath(_pendingArbitrator) { - vm.expectEmit(); - emit ArbitratorSetted(arbitrator, _pendingArbitrator); - - eboRequestCreator.acceptPendingArbitrator(); - } -} - contract EBORequestCreator_Unit_CreateRequest is EBORequestCreator_Unit_BaseTest { string[] internal _cleanChainIds; @@ -145,6 +88,10 @@ contract EBORequestCreator_Unit_CreateRequest is EBORequestCreator_Unit_BaseTest vm.assume(_epoch > 0); vm.assume(_chainId.length > 0 && _chainId.length < 30); + vm.mockCall(address(epochManager), abi.encodeWithSelector(IEpochManager.currentEpoch.selector), abi.encode(_epoch)); + + eboRequestCreator.setStartEpochForTest(_epoch); + bool _added; for (uint256 _i; _i < _chainId.length; _i++) { _added = eboRequestCreator.setChainIdForTest(_chainId[_i]); @@ -160,15 +107,46 @@ contract EBORequestCreator_Unit_CreateRequest is EBORequestCreator_Unit_BaseTest /** * @notice Test the revert if the caller is not the arbitrator */ - function test_revertIfChainNotAdded() external { + function test_revertIfChainNotAdded(uint256 _epoch) external { + vm.mockCall(address(epochManager), abi.encodeWithSelector(IEpochManager.currentEpoch.selector), abi.encode(_epoch)); + eboRequestCreator.setStartEpochForTest(_epoch); + vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_ChainNotAdded.selector)); + eboRequestCreator.createRequests(_epoch, new string[](1)); + } + + /** + * @notice Test the revert if the epoch is not valid because it is before the start epoch + */ + function test_revertIfEpochBeforeStart(uint256 _epoch) external { + vm.assume(_epoch > 0); - eboRequestCreator.createRequests(0, new string[](1)); + eboRequestCreator.setStartEpochForTest(_epoch); + vm.mockCall( + address(epochManager), abi.encodeWithSelector(IEpochManager.currentEpoch.selector), abi.encode(_epoch - 1) + ); + + vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_EpochNotValid.selector)); + + eboRequestCreator.createRequests(_epoch - 1, new string[](1)); } + /** + * @notice Test the revert if the epoch is not valid because it is after the current epoch + */ + function test_revertIfEpochAfterCurrent(uint256 _epoch) external { + vm.assume(_epoch < type(uint256).max); + + vm.mockCall(address(epochManager), abi.encodeWithSelector(IEpochManager.currentEpoch.selector), abi.encode(_epoch)); + + vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_EpochNotValid.selector)); + + eboRequestCreator.createRequests(_epoch + 1, new string[](1)); + } /** * @notice Test if the request id exists skip the request creation */ + function test_expectNotEmitRequestIdExists( uint256 _epoch, string calldata _chainId, @@ -275,8 +253,8 @@ contract EBORequestCreator_Unit_RemoveChain is EBORequestCreator_Unit_BaseTest { } } -contract EBORequestCreator_Unit_SetReward is EBORequestCreator_Unit_BaseTest { - modifier happyPath(uint256 _reward) { +contract EBORequestCreator_Unit_SetRequestModuleData is EBORequestCreator_Unit_BaseTest { + modifier happyPath(address _requestModule, bytes calldata _requestModuleData) { vm.startPrank(arbitrator); _; } @@ -284,33 +262,83 @@ contract EBORequestCreator_Unit_SetReward is EBORequestCreator_Unit_BaseTest { /** * @notice Test the revert if the caller is not the arbitrator */ - function test_revertIfNotArbitrator(uint256 _reward) external { + function test_revertIfNotArbitrator(address _requestModule, bytes calldata _requestModuleData) external { _revertIfNotArbitrator(); - eboRequestCreator.setReward(_reward); + eboRequestCreator.setRequestModuleData(_requestModule, _requestModuleData); + } + + /** + * @notice Test the emit request module data set + */ + function test_emitRequestModuleDataSet( + address _requestModule, + bytes calldata _requestModuleData + ) external happyPath(_requestModule, _requestModuleData) { + vm.expectEmit(); + emit RequestModuleDataSet(_requestModule, _requestModuleData); + + eboRequestCreator.setRequestModuleData(_requestModule, _requestModuleData); + } +} + +contract EBORequestCreator_Unit_SetResponseModuleData is EBORequestCreator_Unit_BaseTest { + modifier happyPath(address _responseModule, bytes calldata _responseModuleData) { + vm.startPrank(arbitrator); + _; } /** - * @notice Test the set reward + * @notice Test the revert if the caller is not the arbitrator */ - function test_setReward(uint256 _reward) external happyPath(_reward) { - eboRequestCreator.setReward(_reward); + function test_revertIfNotArbitrator(address _responseModule, bytes calldata _responseModuleData) external { + _revertIfNotArbitrator(); + eboRequestCreator.setResponseModuleData(_responseModule, _responseModuleData); + } - assertEq(eboRequestCreator.reward(), _reward); + /** + * @notice Test the emit response module data set + */ + function test_emitResponseModuleDataSet( + address _responseModule, + bytes calldata _responseModuleData + ) external happyPath(_responseModule, _responseModuleData) { + vm.expectEmit(); + emit ResponseModuleDataSet(_responseModule, _responseModuleData); + + eboRequestCreator.setResponseModuleData(_responseModule, _responseModuleData); + } +} + +contract EBORequestCreator_Unit_SetDisputeModuleData is EBORequestCreator_Unit_BaseTest { + modifier happyPath(address _disputeModule, bytes calldata _disputeModuleData) { + vm.startPrank(arbitrator); + _; + } + + /** + * @notice Test the revert if the caller is not the arbitrator + */ + function test_revertIfNotArbitrator(address _disputeModule, bytes calldata _disputeModuleData) external { + _revertIfNotArbitrator(); + eboRequestCreator.setDisputeModuleData(_disputeModule, _disputeModuleData); } /** - * @notice Test the emit reward set + * @notice Test the emit dispute module data set */ - function test_emitRewardSet(uint256 _reward) external happyPath(_reward) { + function test_emitDisputeModuleDataSet( + address _disputeModule, + bytes calldata _disputeModuleData + ) external happyPath(_disputeModule, _disputeModuleData) { vm.expectEmit(); - emit RewardSet(0, _reward); + emit DisputeModuleDataSet(_disputeModule, _disputeModuleData); - eboRequestCreator.setReward(_reward); + eboRequestCreator.setDisputeModuleData(_disputeModule, _disputeModuleData); } } -contract EBORequestCreator_Unit_SetRequestData is EBORequestCreator_Unit_BaseTest { - modifier happyPath(EBORequestCreator.RequestData calldata _requestData) { +contract EBORequestCreator_Unit_SetResolutionModuleData is EBORequestCreator_Unit_BaseTest { + modifier happyPath(address _resolutionModule, bytes calldata _resolutionModuleData) { vm.startPrank(arbitrator); _; } @@ -318,52 +346,75 @@ contract EBORequestCreator_Unit_SetRequestData is EBORequestCreator_Unit_BaseTes /** * @notice Test the revert if the caller is not the arbitrator */ - function test_revertIfNotArbitrator(EBORequestCreator.RequestData calldata _requestData) external { + function test_revertIfNotArbitrator(address _resolutionModule, bytes calldata _resolutionModuleData) external { _revertIfNotArbitrator(); - eboRequestCreator.setRequestData(_requestData); + eboRequestCreator.setResolutionModuleData(_resolutionModule, _resolutionModuleData); } /** - * @notice Test the set request data + * @notice Test the emit resolution module data set */ - function test_setRequestData(EBORequestCreator.RequestData calldata _requestData) external happyPath(_requestData) { - eboRequestCreator.setRequestData(_requestData); - - ( - address _requestModule, - address _responseModule, - address _disputeModule, - address _resolutionModule, - address _finalityModule, - bytes memory _requestModuleData, - bytes memory _responseModuleData, - bytes memory _disputeModuleData, - bytes memory _resolutionModuleData, - bytes memory _finalityModuleData - ) = eboRequestCreator.requestData(); - - assertEq(_requestModule, _requestData.requestModule); - assertEq(_responseModule, _requestData.responseModule); - assertEq(_disputeModule, _requestData.disputeModule); - assertEq(_resolutionModule, _requestData.resolutionModule); - assertEq(_finalityModule, _requestData.finalityModule); - assertEq(_requestModuleData, _requestData.requestModuleData); - assertEq(_responseModuleData, _requestData.responseModuleData); - assertEq(_disputeModuleData, _requestData.disputeModuleData); - assertEq(_resolutionModuleData, _requestData.resolutionModuleData); - assertEq(_finalityModuleData, _requestData.finalityModuleData); + function test_emitResolutionModuleDataSet( + address _resolutionModule, + bytes calldata _resolutionModuleData + ) external happyPath(_resolutionModule, _resolutionModuleData) { + vm.expectEmit(); + emit ResolutionModuleDataSet(_resolutionModule, _resolutionModuleData); + + eboRequestCreator.setResolutionModuleData(_resolutionModule, _resolutionModuleData); + } +} + +contract EBORequestCreator_Unit_SetFinalityModuleData is EBORequestCreator_Unit_BaseTest { + modifier happyPath(address _finalityModule, bytes calldata _finalityModuleData) { + vm.startPrank(arbitrator); + _; + } + + /** + * @notice Test the revert if the caller is not the arbitrator + */ + function test_revertIfNotArbitrator(address _finalityModule, bytes calldata _finalityModuleData) external { + _revertIfNotArbitrator(); + eboRequestCreator.setFinalityModuleData(_finalityModule, _finalityModuleData); + } + + /** + * @notice Test the emit finality module data set + */ + function test_emitFinalityModuleDataSet( + address _finalityModule, + bytes calldata _finalityModuleData + ) external happyPath(_finalityModule, _finalityModuleData) { + vm.expectEmit(); + emit FinalityModuleDataSet(_finalityModule, _finalityModuleData); + + eboRequestCreator.setFinalityModuleData(_finalityModule, _finalityModuleData); + } +} + +contract EBORequestCreator_Unit_SetEpochManager is EBORequestCreator_Unit_BaseTest { + modifier happyPath(IEpochManager _epochManager) { + vm.assume(address(_epochManager) != address(0)); + vm.startPrank(arbitrator); + _; + } + + /** + * @notice Test the revert if the caller is not the arbitrator + */ + function test_revertIfNotArbitrator(IEpochManager _epochManager) external { + _revertIfNotArbitrator(); + eboRequestCreator.setEpochManager(_epochManager); } /** - * @notice Test the emit request data set + * @notice Test the emit epoch manager set */ - function test_emitRequestDataSet(EBORequestCreator.RequestData calldata _requestData) - external - happyPath(_requestData) - { + function test_emitEpochManagerSet(IEpochManager _epochManager) external happyPath(_epochManager) { vm.expectEmit(); - emit RequestDataSet(_requestData); + emit EpochManagerSet(_epochManager); - eboRequestCreator.setRequestData(_requestData); + eboRequestCreator.setEpochManager(_epochManager); } } diff --git a/yarn.lock b/yarn.lock index f10f820..1105066 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3,24 +3,24 @@ "@babel/code-frame@^7.0.0": - version "7.24.2" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae" - integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ== + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== dependencies: - "@babel/highlight" "^7.24.2" + "@babel/highlight" "^7.24.7" picocolors "^1.0.0" -"@babel/helper-validator-identifier@^7.24.5": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz#918b1a7fa23056603506370089bd990d8720db62" - integrity sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA== +"@babel/helper-validator-identifier@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== -"@babel/highlight@^7.24.2": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.5.tgz#bc0613f98e1dd0720e99b2a9ee3760194a704b6e" - integrity sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw== +"@babel/highlight@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== dependencies: - "@babel/helper-validator-identifier" "^7.24.5" + "@babel/helper-validator-identifier" "^7.24.7" chalk "^2.4.2" js-tokens "^4.0.0" picocolors "^1.0.0" @@ -98,9 +98,9 @@ "@commitlint/types" "^19.0.3" "@commitlint/load@^19.2.0": - version "19.2.0" - resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-19.2.0.tgz#3ca51fdead4f1e1e09c9c7df343306412b1ef295" - integrity sha512-XvxxLJTKqZojCxaBQ7u92qQLFMMZc4+p9qrIq/9kJDy8DOrEa7P1yx7Tjdc2u2JxIalqT4KOGraVgCE7eCYJyQ== + version "19.4.0" + resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-19.4.0.tgz#7df034e226e300fd577d3f63a72d790d5c821f53" + integrity sha512-I4lCWaEZYQJ1y+Y+gdvbGAx9pYPavqZAZ3/7/8BpWh+QjscAn8AjsUpLV2PycBsEx7gupq5gM4BViV9xwTIJuw== dependencies: "@commitlint/config-validator" "^19.0.3" "@commitlint/execute-rule" "^19.0.0" @@ -128,9 +128,9 @@ conventional-commits-parser "^5.0.0" "@commitlint/read@^19.2.1": - version "19.2.1" - resolved "https://registry.yarnpkg.com/@commitlint/read/-/read-19.2.1.tgz#7296b99c9a989e60e5927fff8388a1dd44299c2f" - integrity sha512-qETc4+PL0EUv7Q36lJbPG+NJiBOGg7SSC7B5BsPWOmei+Dyif80ErfWQ0qXoW9oCh7GTpTNRoaVhiI8RbhuaNw== + version "19.4.0" + resolved "https://registry.yarnpkg.com/@commitlint/read/-/read-19.4.0.tgz#3866b1f9a272ef6a388986efa349d24228fc8b00" + integrity sha512-r95jLOEZzKDakXtnQub+zR3xjdnrl2XzerPwm7ch1/cc5JGq04tyaNpa6ty0CRCWdVrk4CZHhqHozb8yZwy2+g== dependencies: "@commitlint/top-level" "^19.0.0" "@commitlint/types" "^19.0.3" @@ -190,16 +190,16 @@ solc-typed-ast "18.1.2" yargs "17.7.2" -"@defi-wonderland/prophet-core-contracts@0.0.0-438de1c5": - version "0.0.0-438de1c5" - resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core-contracts/-/prophet-core-contracts-0.0.0-438de1c5.tgz#2b0238636c89eb71b07d57e12abfdea57c53b03b" - integrity sha512-UqdNRr2eH5DNSQ7qUriZbvR9LoXLXDMKTOjcjTTc8Gbq1aVcBhwFu4mSdrnhpQkXHjKtmsO0IfGcRHIGLvnXSQ== - "@defi-wonderland/prophet-core-contracts@0.0.0-d01bc1a0": version "0.0.0-d01bc1a0" resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core-contracts/-/prophet-core-contracts-0.0.0-d01bc1a0.tgz#ee4e8d970289a26966f6565b2f691d68d7b4232a" integrity sha512-n4Dl1QgQAZafOtV7ef/fSoew2qlxWSdS389Z6PdIn7LxrHrzzRJi+nmJ1DJazMvMuhk/0dZbMhnaXMBi05E1zQ== +"@defi-wonderland/prophet-core@0.0.0-172a7bcf": + version "0.0.0-172a7bcf" + resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core/-/prophet-core-0.0.0-172a7bcf.tgz#d7074ebc775b44ebd32fea3a728bdc6883b4f40a" + integrity sha512-lot6rq6gG7E6x4tl0lp3Lktm8Yymo6pdy7Wf9VmtzogjrV5/cdi9zRNMQjiX7HeU1iBT2tvMxbFpLFyulR+zqw== + "@defi-wonderland/prophet-modules-contracts@0.0.0-1197c328": version "0.0.0-1197c328" resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-modules-contracts/-/prophet-modules-contracts-0.0.0-1197c328.tgz#f58aa52a5a33fb39a9404bdf5e16ab75fcdde85f" @@ -209,17 +209,17 @@ "@openzeppelin/contracts" "4.9.5" solmate "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" -"@noble/curves@1.3.0", "@noble/curves@~1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.3.0.tgz#01be46da4fd195822dab821e72f71bf4aeec635e" - integrity sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA== +"@noble/curves@1.4.2", "@noble/curves@~1.4.0": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" + integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== dependencies: - "@noble/hashes" "1.3.3" + "@noble/hashes" "1.4.0" -"@noble/hashes@1.3.3", "@noble/hashes@~1.3.2": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" - integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== +"@noble/hashes@1.4.0", "@noble/hashes@~1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" + integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -247,27 +247,27 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.5.tgz#1eed23d4844c861a1835b5d33507c1017fa98de8" integrity sha512-ZK+W5mVhRppff9BE6YdR8CC52C8zAvsVAiWhEtQ5+oNxFE6h1WdeWo+FJSF8KKvtxxVYZ7MTP/5KoVpAU3aSWg== -"@scure/base@~1.1.4": - version "1.1.6" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.6.tgz#8ce5d304b436e4c84f896e0550c83e4d88cb917d" - integrity sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g== +"@scure/base@~1.1.6": + version "1.1.7" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.7.tgz#fe973311a5c6267846aa131bc72e96c5d40d2b30" + integrity sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g== -"@scure/bip32@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.3.tgz#a9624991dc8767087c57999a5d79488f48eae6c8" - integrity sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ== +"@scure/bip32@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.4.0.tgz#4e1f1e196abedcef395b33b9674a042524e20d67" + integrity sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg== dependencies: - "@noble/curves" "~1.3.0" - "@noble/hashes" "~1.3.2" - "@scure/base" "~1.1.4" + "@noble/curves" "~1.4.0" + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" -"@scure/bip39@1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.2.tgz#f3426813f4ced11a47489cbcf7294aa963966527" - integrity sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA== +"@scure/bip39@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.3.0.tgz#0f258c16823ddd00739461ac31398b4e7d6a18c3" + integrity sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ== dependencies: - "@noble/hashes" "~1.3.2" - "@scure/base" "~1.1.4" + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" "@solidity-parser/parser@^0.16.0": version "0.16.2" @@ -284,11 +284,11 @@ "@types/node" "*" "@types/node@*": - version "20.12.12" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.12.tgz#7cbecdf902085cec634fdb362172dfe12b8f2050" - integrity sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw== + version "22.1.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.1.0.tgz#6d6adc648b5e03f0e83c78dc788c2b037d0ad94b" + integrity sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw== dependencies: - undici-types "~5.26.4" + undici-types "~6.13.0" JSONStream@^1.3.5: version "1.3.5" @@ -314,19 +314,21 @@ ajv@^6.12.6: uri-js "^4.2.2" ajv@^8.0.1, ajv@^8.11.0: - version "8.13.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.13.0.tgz#a3939eaec9fb80d217ddf0c3376948c023f28c91" - integrity sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA== + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== dependencies: fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" json-schema-traverse "^1.0.0" require-from-string "^2.0.2" - uri-js "^4.4.1" -ansi-escapes@^6.2.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-6.2.1.tgz#76c54ce9b081dad39acec4b5d53377913825fb0f" - integrity sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig== +ansi-escapes@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-7.0.0.tgz#00fc19f491bbb18e1d481b97868204f92109bfe7" + integrity sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw== + dependencies: + environment "^1.0.0" ansi-regex@^5.0.1: version "5.0.1" @@ -358,9 +360,9 @@ ansi-styles@^6.0.0, ansi-styles@^6.2.1: integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== antlr4@^4.11.0: - version "4.13.1" - resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.13.1.tgz#1e0a1830a08faeb86217cb2e6c34716004e4253d" - integrity sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA== + version "4.13.2" + resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.13.2.tgz#0d084ad0e32620482a9c3a0e2470c02e72e4006d" + integrity sha512-QiVbZhyy4xAZ17UPEuG3YTOt8ZaoeOR1CvEAqrEsDBsOqINslaB147i9xqljZqoyf5S+EUlGStaj+t22LT9MOg== antlr4ts@^0.5.0-alpha.4: version "0.5.0-alpha.4" @@ -400,9 +402,9 @@ available-typed-arrays@^1.0.7: possible-typed-array-names "^1.0.0" axios@^1.6.7: - version "1.7.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.1.tgz#522145622a09dfaf49359837db9649ff245a35b9" - integrity sha512-+LV37nQcd1EpFalkXksWNBiA17NZ5m5/WspmHGmZmdx1qBOg/VNq/c4eRJiA9VQQHBOs+N0ZhhdU10h2TyNK7Q== + version "1.7.3" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.3.tgz#a1125f2faf702bc8e8f2104ec3a76fab40257d85" + integrity sha512-Ar7ND9pU99eJ9GpoGQKhKf58GpUOgnzuaB7ueNQ5BMi0p+LZ5oaEnfF999fAArcTIBwXTCHAmGcHOZJaWPq9Nw== dependencies: follow-redirects "^1.15.6" form-data "^4.0.0" @@ -420,12 +422,12 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== +braces@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: - fill-range "^7.0.1" + fill-range "^7.1.1" call-bind@^1.0.2, call-bind@^1.0.7: version "1.0.7" @@ -443,11 +445,6 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -chalk@5.3.0, chalk@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" - integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== - chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -465,12 +462,17 @@ chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" -cli-cursor@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea" - integrity sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg== +chalk@^5.3.0, chalk@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" + integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== + +cli-cursor@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-5.0.0.tgz#24a4831ecf5a6b01ddeb32fb71a4b2088b0dce38" + integrity sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw== dependencies: - restore-cursor "^4.0.0" + restore-cursor "^5.0.0" cli-truncate@^4.0.0: version "4.0.0" @@ -530,12 +532,12 @@ command-exists@^1.2.8: resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== -commander@11.1.0, commander@^11.1.0: +commander@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906" integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ== -commander@^12.0.0: +commander@^12.0.0, commander@~12.1.0: version "12.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== @@ -618,10 +620,10 @@ dargs@^8.0.0: resolved "https://registry.yarnpkg.com/dargs/-/dargs-8.1.0.tgz#a34859ea509cbce45485e5aa356fef70bfcc7272" integrity sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw== -debug@4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== +debug@~4.3.6: + version "4.3.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" + integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== dependencies: ms "2.1.2" @@ -688,6 +690,11 @@ env-paths@^2.2.1: resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== +environment@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/environment/-/environment-1.1.0.tgz#8e86c66b180f363c7ab311787e0259665f45a9f1" + integrity sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q== + error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -718,21 +725,21 @@ escape-string-regexp@^1.0.5: integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== ethereum-cryptography@^2.0.0: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz#1352270ed3b339fe25af5ceeadcf1b9c8e30768a" - integrity sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA== + version "2.2.1" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz#58f2810f8e020aecb97de8c8c76147600b0b8ccf" + integrity sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg== dependencies: - "@noble/curves" "1.3.0" - "@noble/hashes" "1.3.3" - "@scure/bip32" "1.3.3" - "@scure/bip39" "1.2.2" + "@noble/curves" "1.4.2" + "@noble/hashes" "1.4.0" + "@scure/bip32" "1.4.0" + "@scure/bip39" "1.3.0" eventemitter3@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== -execa@8.0.1, execa@^8.0.1: +execa@^8.0.1, execa@~8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c" integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg== @@ -780,6 +787,11 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +fast-uri@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.1.tgz#cddd2eecfc83a71c1be2cc2ef2061331be8a7134" + integrity sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw== + fastq@^1.6.0: version "1.17.1" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" @@ -787,10 +799,10 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" @@ -1028,9 +1040,9 @@ human-signals@^5.0.0: integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== husky@>=8: - version "9.0.11" - resolved "https://registry.yarnpkg.com/husky/-/husky-9.0.11.tgz#fc91df4c756050de41b3e478b2158b87c1e79af9" - integrity sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw== + version "9.1.4" + resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.4.tgz#926fd19c18d345add5eab0a42b2b6d9a80259b34" + integrity sha512-bho94YyReb4JV7LYWRWxZ/xr6TtOTt8cMfmQ39MQYJ7f/YE268s3GdghGwi+y4zAeqewE5zYLvuhV0M0ijsDEA== ignore@^5.2.4: version "5.3.1" @@ -1172,9 +1184,9 @@ isexe@^2.0.0: integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== jiti@^1.19.1: - version "1.21.0" - resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d" - integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== + version "1.21.6" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268" + integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w== js-sha3@0.8.0: version "0.8.0" @@ -1227,10 +1239,10 @@ jsonparse@^1.2.0: resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== -lilconfig@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.0.0.tgz#f8067feb033b5b74dab4602a5f5029420be749bc" - integrity sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g== +lilconfig@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.2.tgz#e4a7c3cb549e3a606c8dcc32e5ae1005e62c05cb" + integrity sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow== lines-and-columns@^1.1.6: version "1.2.4" @@ -1238,31 +1250,31 @@ lines-and-columns@^1.1.6: integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== lint-staged@>=10: - version "15.2.2" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-15.2.2.tgz#ad7cbb5b3ab70e043fa05bff82a09ed286bc4c5f" - integrity sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw== - dependencies: - chalk "5.3.0" - commander "11.1.0" - debug "4.3.4" - execa "8.0.1" - lilconfig "3.0.0" - listr2 "8.0.1" - micromatch "4.0.5" - pidtree "0.6.0" - string-argv "0.3.2" - yaml "2.3.4" - -listr2@8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-8.0.1.tgz#4d3f50ae6cec3c62bdf0e94f5c2c9edebd4b9c34" - integrity sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA== + version "15.2.8" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-15.2.8.tgz#5e19eb7b4dbb922f56fafb4635b44ee3c92f7322" + integrity sha512-PUWFf2zQzsd9EFU+kM1d7UP+AZDbKFKuj+9JNVTBkhUFhbg4MAt6WfyMMwBfM4lYqd4D2Jwac5iuTu9rVj4zCQ== + dependencies: + chalk "~5.3.0" + commander "~12.1.0" + debug "~4.3.6" + execa "~8.0.1" + lilconfig "~3.1.2" + listr2 "~8.2.4" + micromatch "~4.0.7" + pidtree "~0.6.0" + string-argv "~0.3.2" + yaml "~2.5.0" + +listr2@~8.2.4: + version "8.2.4" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-8.2.4.tgz#486b51cbdb41889108cb7e2c90eeb44519f5a77f" + integrity sha512-opevsywziHd3zHCVQGAj8zu+Z3yHNkkoYhWIGnq54RrCVwLz0MozotJEDnKsIBLvkfLGN6BLOyAeRrYI0pKA4g== dependencies: cli-truncate "^4.0.0" colorette "^2.0.20" eventemitter3 "^5.0.1" - log-update "^6.0.0" - rfdc "^1.3.0" + log-update "^6.1.0" + rfdc "^1.4.1" wrap-ansi "^9.0.0" locate-path@^7.2.0: @@ -1327,14 +1339,14 @@ lodash@^4.17.21: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-update@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/log-update/-/log-update-6.0.0.tgz#0ddeb7ac6ad658c944c1de902993fce7c33f5e59" - integrity sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw== +log-update@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-6.1.0.tgz#1a04ff38166f94647ae1af562f4bd6a15b1b7cd4" + integrity sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w== dependencies: - ansi-escapes "^6.2.0" - cli-cursor "^4.0.0" - slice-ansi "^7.0.0" + ansi-escapes "^7.0.0" + cli-cursor "^5.0.0" + slice-ansi "^7.1.0" strip-ansi "^7.1.0" wrap-ansi "^9.0.0" @@ -1358,12 +1370,12 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -micromatch@4.0.5, micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== +micromatch@^4.0.4, micromatch@~4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" + integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== dependencies: - braces "^3.0.2" + braces "^3.0.3" picomatch "^2.3.1" mime-db@1.52.0: @@ -1378,16 +1390,16 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - mimic-fn@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== +mimic-function@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/mimic-function/-/mimic-function-5.0.1.tgz#acbe2b3349f99b9deaca7fb70e48b83e94e67076" + integrity sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA== + minimatch@^5.0.1: version "5.1.6" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" @@ -1419,13 +1431,6 @@ once@^1.3.0: dependencies: wrappy "1" -onetime@^5.1.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - onetime@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" @@ -1433,6 +1438,13 @@ onetime@^6.0.0: dependencies: mimic-fn "^4.0.0" +onetime@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-7.0.0.tgz#9f16c92d8c9ef5120e3acd9dd9957cceecc1ab60" + integrity sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ== + dependencies: + mimic-function "^5.0.0" + os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -1504,7 +1516,7 @@ picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -pidtree@0.6.0: +pidtree@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c" integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== @@ -1567,23 +1579,23 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -restore-cursor@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-4.0.0.tgz#519560a4318975096def6e609d44100edaa4ccb9" - integrity sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg== +restore-cursor@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-5.1.0.tgz#0766d95699efacb14150993f55baf0953ea1ebe7" + integrity sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA== dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" + onetime "^7.0.0" + signal-exit "^4.1.0" reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rfdc@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.1.tgz#2b6d4df52dffe8bb346992a10ea9451f24373a8f" - integrity sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg== +rfdc@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" + integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== run-parallel@^1.1.9: version "1.2.0" @@ -1603,9 +1615,9 @@ semver@^6.3.0: integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== semver@^7.6.0: - version "7.6.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" - integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== set-function-length@^1.2.1: version "1.2.2" @@ -1631,11 +1643,6 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -signal-exit@^3.0.2: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - signal-exit@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" @@ -1663,7 +1670,7 @@ slice-ansi@^5.0.0: ansi-styles "^6.0.0" is-fullwidth-code-point "^4.0.0" -slice-ansi@^7.0.0: +slice-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-7.1.0.tgz#cd6b4655e298a8d1bdeb04250a433094b347b9a9" integrity sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg== @@ -1725,9 +1732,9 @@ solhint-community@4.0.0: optionalDependencies: prettier "^2.8.3" -"solmate@git+https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c": +"solmate@https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c": version "6.1.0" - resolved "git+https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" + resolved "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" sort-object-keys@^1.1.3: version "1.1.3" @@ -1758,7 +1765,7 @@ src-location@^1.1.0: resolved "https://registry.yarnpkg.com/src-location/-/src-location-1.1.0.tgz#3f50eeb0c7169432e55b426be6e3a68ebba16218" integrity sha512-idBVZgLZGzB3B2Et317AFDQto7yRgp1tOuFd+VKIH2dw1jO1b6p07zNjtQoVhkW+CY6oGTp9Y5UIfbJoZRsoFQ== -string-argv@0.3.2: +string-argv@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== @@ -1773,9 +1780,9 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: strip-ansi "^6.0.1" string-width@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.1.0.tgz#d994252935224729ea3719c49f7206dc9c46550a" - integrity sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw== + version "7.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.2.0.tgz#b5bb8e2165ce275d4d43476dd2700ad9091db6dc" + integrity sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ== dependencies: emoji-regex "^10.3.0" get-east-asian-width "^1.0.0" @@ -1854,10 +1861,10 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== +undici-types@~6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.13.0.tgz#e3e79220ab8c81ed1496b5812471afd7cf075ea5" + integrity sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg== unicorn-magic@^0.1.0: version "0.1.0" @@ -1869,7 +1876,7 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== -uri-js@^4.2.2, uri-js@^4.4.1: +uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== @@ -1887,49 +1894,49 @@ util@^0.12.5: is-typed-array "^1.1.3" which-typed-array "^1.1.2" -web3-errors@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/web3-errors/-/web3-errors-1.1.4.tgz#5667a0a5f66fc936e101ef32032ccc1e8ca4d5a1" - integrity sha512-WahtszSqILez+83AxGecVroyZsMuuRT+KmQp4Si5P4Rnqbczno1k748PCrZTS1J4UCPmXMG2/Vt+0Bz2zwXkwQ== +web3-errors@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/web3-errors/-/web3-errors-1.2.1.tgz#2f31cb814bd262a45b65f7701f56a0167d697ec2" + integrity sha512-dIsi8SFC9TCAWpPmacXeVMk/F8tDNa1Bvg8/Cc2cvJo8LRSWd099szEyb+/SiMYcLlEbwftiT9Rpukz7ql4hBg== dependencies: - web3-types "^1.3.1" + web3-types "^1.7.0" web3-eth-abi@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-4.2.1.tgz#b1260dace8380221f12f4274af240c1dfed1045c" - integrity sha512-IE91WUhhiDpBtbkl/DHUoZz7z7T5FXvl3zPLkrxT+dNlOT+wni+US/67jQCLvJRbqf9ApQ26lVYry0bovFgyqA== + version "4.2.3" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-4.2.3.tgz#9efad6a45d7d6e52bb1eba56cbe45a3a321443e3" + integrity sha512-rPVwTn0O1CzbtfXwEfIjUP0W5Y7u1OFjugwKpSqJzPQE6+REBg6OELjomTGZBu+GThxHnv0rp15SOxvqp+tyXA== dependencies: abitype "0.7.1" - web3-errors "^1.1.4" - web3-types "^1.6.0" - web3-utils "^4.2.3" - web3-validator "^2.0.5" + web3-errors "^1.2.0" + web3-types "^1.7.0" + web3-utils "^4.3.1" + web3-validator "^2.0.6" -web3-types@^1.3.1, web3-types@^1.5.0, web3-types@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/web3-types/-/web3-types-1.6.0.tgz#ebe7f140c31f7cc0ad15f238ad7e7ac72797ff3b" - integrity sha512-qgOtADqlD5hw+KPKBUGaXAcdNLL0oh6qTeVgXwewCfbL/lG9R+/GrgMQB1gbTJ3cit8hMwtH8KX2Em6OwO0HRw== +web3-types@^1.6.0, web3-types@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-types/-/web3-types-1.7.0.tgz#9945fa644af96b20b1db18564aff9ab8db00df59" + integrity sha512-nhXxDJ7a5FesRw9UG5SZdP/C/3Q2EzHGnB39hkAV+YGXDMgwxBXFWebQLfEzZzuArfHnvC0sQqkIHNwSKcVjdA== -web3-utils@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-4.2.3.tgz#e1d30c4b087cd95f4307baeb80e3160f174e1cfd" - integrity sha512-m5plKTC2YtQntHITQRyIePw52UVP1IrShhmA2FACtn4zmc5ADmrXOlQWiPzxFP/18eRJsAaUAw2+CQn1u4WPxQ== +web3-utils@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-4.3.1.tgz#3dcd75e3c683c26f0ba824bf27d7bc0a68b111de" + integrity sha512-kGwOk8FxOLJ9DQC68yqNQc7AzN+k9YDLaW+ZjlAXs3qORhf8zXk5SxWAAGLbLykMs3vTeB0FTb1Exut4JEYfFA== dependencies: ethereum-cryptography "^2.0.0" eventemitter3 "^5.0.1" - web3-errors "^1.1.4" - web3-types "^1.6.0" - web3-validator "^2.0.5" + web3-errors "^1.2.0" + web3-types "^1.7.0" + web3-validator "^2.0.6" -web3-validator@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/web3-validator/-/web3-validator-2.0.5.tgz#de1984bdb34f292251b86400dba7169700db0849" - integrity sha512-2gLOSW8XqEN5pw5jVUm20EB7A8SbQiekpAtiI0JBmCIV0a2rp97v8FgWY5E3UEqnw5WFfEqvcDVW92EyynDTyQ== +web3-validator@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/web3-validator/-/web3-validator-2.0.6.tgz#a0cdaa39e1d1708ece5fae155b034e29d6a19248" + integrity sha512-qn9id0/l1bWmvH4XfnG/JtGKKwut2Vokl6YXP5Kfg424npysmtRLe9DgiNBM9Op7QL/aSiaA0TVXibuIuWcizg== dependencies: ethereum-cryptography "^2.0.0" util "^0.12.5" - web3-errors "^1.1.4" - web3-types "^1.5.0" + web3-errors "^1.2.0" + web3-types "^1.6.0" zod "^3.21.4" which-typed-array@^1.1.14, which-typed-array@^1.1.2: @@ -1985,10 +1992,10 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== -yaml@2.3.4: - version "2.3.4" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.4.tgz#53fc1d514be80aabf386dc6001eb29bf3b7523b2" - integrity sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA== +yaml@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.5.0.tgz#c6165a721cf8000e91c36490a41d7be25176cf5d" + integrity sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw== yargs-parser@^21.1.1: version "21.1.1" @@ -2009,9 +2016,9 @@ yargs@17.7.2, yargs@^17.0.0: yargs-parser "^21.1.1" yocto-queue@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" - integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== + version "1.1.1" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.1.1.tgz#fef65ce3ac9f8a32ceac5a634f74e17e5b232110" + integrity sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g== zod@^3.21.4: version "3.23.8" From d6982d975a81f501c96d6820fce4bbdf1137f470 Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Fri, 9 Aug 2024 00:32:46 -0300 Subject: [PATCH 06/19] fix: comments --- package.json | 2 +- remappings.txt | 2 +- src/contracts/EBORequestCreator.sol | 102 +++++------ src/interfaces/IEBORequestCreator.sol | 138 ++++++-------- test/integration/IntegrationBase.sol | 7 +- test/unit/EBORequestCreator.t.sol | 249 ++++++++++++-------------- yarn.lock | 14 +- 7 files changed, 227 insertions(+), 287 deletions(-) diff --git a/package.json b/package.json index eb82655..5b71c40 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "package.json": "sort-package-json" }, "dependencies": { - "@defi-wonderland/prophet-core-contracts": "0.0.0-438de1c5", + "@defi-wonderland/prophet-core": "0.0.0-172a7bcf", "@defi-wonderland/prophet-modules-contracts": "0.0.0-1197c328" }, "devDependencies": { diff --git a/remappings.txt b/remappings.txt index 2245399..9ae4470 100644 --- a/remappings.txt +++ b/remappings.txt @@ -1,6 +1,6 @@ forge-std/=node_modules/forge-std/src halmos-cheatcodes=node_modules/halmos-cheatcodes -@defi-wonderland/prophet-core-contracts/=node_modules/@defi-wonderland/prophet-core-contracts +@defi-wonderland/prophet-core/=node_modules/@defi-wonderland/prophet-core @defi-wonderland/prophet-modules-contracts/=node_modules/@defi-wonderland/prophet-modules-contracts contracts/=src/contracts diff --git a/src/contracts/EBORequestCreator.sol b/src/contracts/EBORequestCreator.sol index 1013926..cfa2221 100644 --- a/src/contracts/EBORequestCreator.sol +++ b/src/contracts/EBORequestCreator.sol @@ -2,25 +2,18 @@ pragma solidity 0.8.26; import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; + +import {Arbitrable} from 'contracts/Arbitrable.sol'; import {IEBORequestCreator, IOracle} from 'interfaces/IEBORequestCreator.sol'; -contract EBORequestCreator is IEBORequestCreator { +contract EBORequestCreator is IEBORequestCreator, Arbitrable { using EnumerableSet for EnumerableSet.Bytes32Set; /// @inheritdoc IEBORequestCreator IOracle public oracle; /// @inheritdoc IEBORequestCreator - RequestData public requestData; - - /// @inheritdoc IEBORequestCreator - address public arbitrator; - - /// @inheritdoc IEBORequestCreator - address public pendingArbitrator; - - /// @inheritdoc IEBORequestCreator - uint256 public reward; + IOracle.Request public requestData; /// @inheritdoc IEBORequestCreator mapping(string _chainId => mapping(uint256 _epoch => bytes32 _requestId)) public requestIdPerChainAndEpoch; @@ -30,33 +23,15 @@ contract EBORequestCreator is IEBORequestCreator { */ EnumerableSet.Bytes32Set internal _chainIdsAllowed; - constructor(IOracle _oracle, address _arbitrator) { + constructor(IOracle _oracle, address _arbitrator, address _council) Arbitrable(_arbitrator, _council) { oracle = _oracle; - arbitrator = _arbitrator; - reward = 0; - } - - /// @inheritdoc IEBORequestCreator - function setPendingArbitrator(address _pendingArbitrator) external onlyArbitrator { - pendingArbitrator = _pendingArbitrator; - - emit PendingArbitratorSetted(_pendingArbitrator); - } - - /// @inheritdoc IEBORequestCreator - function acceptPendingArbitrator() external onlyPendingArbitrator { - address _oldArbitrator = arbitrator; - arbitrator = pendingArbitrator; - pendingArbitrator = address(0); - - emit ArbitratorSetted(_oldArbitrator, arbitrator); } /// @inheritdoc IEBORequestCreator function createRequests(uint256 _epoch, string[] calldata _chainIds) external { bytes32 _encodedChainId; - RequestData memory _requestData = requestData; + IOracle.Request memory _requestData = requestData; for (uint256 _i; _i < _chainIds.length; _i++) { _encodedChainId = _encodeChainId(_chainIds[_i]); @@ -111,45 +86,54 @@ contract EBORequestCreator is IEBORequestCreator { } /// @inheritdoc IEBORequestCreator - function setReward(uint256 _reward) external onlyArbitrator { - uint256 _oldReward = reward; - reward = _reward; - emit RewardSet(_oldReward, _reward); + function setRequestModuleData(address _requestModule, bytes calldata _requestModuleData) external onlyArbitrator { + requestData.requestModule = _requestModule; + requestData.requestModuleData = _requestModuleData; + + emit RequestModuleDataSet(_requestModule, _requestModuleData); } /// @inheritdoc IEBORequestCreator - function setRequestData(RequestData calldata _requestData) external onlyArbitrator { - requestData = _requestData; + function setResponseModuleData(address _responseModule, bytes calldata _responseModuleData) external onlyArbitrator { + requestData.responseModule = _responseModule; + requestData.responseModuleData = _responseModuleData; - emit RequestDataSet(_requestData); + emit ResponseModuleDataSet(_responseModule, _responseModuleData); } - /** - * @notice Encodes the chain id - * @dev The chain id is hashed to have a enumerable set to avoid duplicates - */ - function _encodeChainId(string calldata _chainId) internal pure returns (bytes32 _encodedChainId) { - _encodedChainId = keccak256(abi.encodePacked(_chainId)); + /// TODO: Change module data to the specific interface when we have + /// @inheritdoc IEBORequestCreator + function setDisputeModuleData(address _disputeModule, bytes calldata _disputeModuleData) external onlyArbitrator { + requestData.disputeModule = _disputeModule; + requestData.disputeModuleData = _disputeModuleData; + + emit DisputeModuleDataSet(_disputeModule, _disputeModuleData); } - /** - * @notice Checks if the sender is the arbitrator - */ - modifier onlyArbitrator() { - if (msg.sender != arbitrator) { - revert EBORequestCreator_OnlyArbitrator(); - } - _; + /// @inheritdoc IEBORequestCreator + function setResolutionModuleData( + address _resolutionModule, + bytes calldata _resolutionModuleData + ) external onlyArbitrator { + requestData.resolutionModule = _resolutionModule; + requestData.resolutionModuleData = _resolutionModuleData; + + emit ResolutionModuleDataSet(_resolutionModule, _resolutionModuleData); + } + + /// @inheritdoc IEBORequestCreator + function setFinalityModuleData(address _finalityModule, bytes calldata _finalityModuleData) external onlyArbitrator { + requestData.finalityModule = _finalityModule; + requestData.finalityModuleData = _finalityModuleData; + + emit FinalityModuleDataSet(_finalityModule, _finalityModuleData); } /** - * @notice Checks if the sender is the pending arbitrator + * @notice Encodes the chain id + * @dev The chain id is hashed to have a enumerable set to avoid duplicates */ - modifier onlyPendingArbitrator() { - if (msg.sender != pendingArbitrator) { - revert EBORequestCreator_OnlyPendingArbitrator(); - } - - _; + function _encodeChainId(string calldata _chainId) internal pure returns (bytes32 _encodedChainId) { + _encodedChainId = keccak256(abi.encodePacked(_chainId)); } } diff --git a/src/interfaces/IEBORequestCreator.sol b/src/interfaces/IEBORequestCreator.sol index d967208..9619f67 100644 --- a/src/interfaces/IEBORequestCreator.sol +++ b/src/interfaces/IEBORequestCreator.sol @@ -1,26 +1,13 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import {IOracle} from '@defi-wonderland/prophet-core-contracts/solidity/interfaces/IOracle.sol'; +import {IOracle} from '@defi-wonderland/prophet-core/solidity/interfaces/IOracle.sol'; interface IEBORequestCreator { /*/////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ - /** - * @notice Emitted when the pending arbitrator is set - * @param _pendingArbitrator The address of the pending arbitrator - */ - event PendingArbitratorSetted(address _pendingArbitrator); - - /** - * @notice Emitted when the abitrator is set - * @param _oldArbitrator The old abitrator address - * @param _newArbitrator The new abitrator address - */ - event ArbitratorSetted(address _oldArbitrator, address _newArbitrator); - /** * @notice Emitted when a request is created * @param _requestId The id of the request @@ -42,31 +29,43 @@ interface IEBORequestCreator { event ChainRemoved(string indexed _chainId); /** - * @notice Emitted when the reward is set - * @param _oldReward The old reward value - * @param _newReward The new reward value + * @notice Emitted when the request data module is set + * @param _requestModule The request module + * @param _requestModuleData The request module data */ - event RewardSet(uint256 _oldReward, uint256 _newReward); + event RequestModuleDataSet(address indexed _requestModule, bytes _requestModuleData); /** - * @notice Emitted when a request data is set - * @param _requestData The request data + * @notice Emitted when the response data module is set + * @param _responseModule The response module + * @param _responseModuleData The response module data */ - event RequestDataSet(RequestData _requestData); + event ResponseModuleDataSet(address indexed _responseModule, bytes _responseModuleData); - /*/////////////////////////////////////////////////////////////// - ERRORS - //////////////////////////////////////////////////////////////*/ + /** + * @notice Emitted when the dispute data module is set + * @param _disputeModule The dispute module + * @param _disputeModuleData The dispute module data + */ + event DisputeModuleDataSet(address indexed _disputeModule, bytes _disputeModuleData); /** - * @notice Thrown when the caller is not the arbitrator + * @notice Emitted when the resolution data module is set + * @param _resolutionModule The resolution module + * @param _resolutionModuleData The resolution module data */ - error EBORequestCreator_OnlyArbitrator(); + event ResolutionModuleDataSet(address indexed _resolutionModule, bytes _resolutionModuleData); /** - * @notice Thrown when the caller is not the pending arbitrator + * @notice Emitted when the finality data module is set + * @param _finalityModule The finality module + * @param _finalityModuleData The finality module data */ - error EBORequestCreator_OnlyPendingArbitrator(); + event FinalityModuleDataSet(address indexed _finalityModule, bytes _finalityModuleData); + + /*/////////////////////////////////////////////////////////////// + ERRORS + //////////////////////////////////////////////////////////////*/ /** * @notice hrown when the chain is already added @@ -78,23 +77,6 @@ interface IEBORequestCreator { */ error EBORequestCreator_ChainNotAdded(); - /*/////////////////////////////////////////////////////////////// - STRUCTS - //////////////////////////////////////////////////////////////*/ - - struct RequestData { - address requestModule; - address responseModule; - address disputeModule; - address resolutionModule; - address finalityModule; - bytes requestModuleData; - bytes responseModuleData; - bytes disputeModuleData; - bytes resolutionModuleData; - bytes finalityModuleData; - } - /*/////////////////////////////////////////////////////////////// VARIABLES //////////////////////////////////////////////////////////////*/ @@ -111,6 +93,8 @@ interface IEBORequestCreator { external view returns ( + uint96 _nonce, + address _requester, address _requestModule, address _responseModule, address _disputeModule, @@ -123,24 +107,6 @@ interface IEBORequestCreator { bytes memory _finalityModuleData ); - /** - * @notice The arbitrator of the contract - * @return _arbitrator The arbitrator - */ - function arbitrator() external view returns (address _arbitrator); - - /** - * @notice The pending arbitrator of the contract - * @return _pendingArbitrator The pending owner - */ - function pendingArbitrator() external view returns (address _pendingArbitrator); - - /** - * @notice The reward paid for each chain updated - * @return _reward The reward - */ - function reward() external view returns (uint256 _reward); - /** * @notice The request id per chain and epoch * @param _chainId The chain id @@ -156,17 +122,6 @@ interface IEBORequestCreator { LOGIC //////////////////////////////////////////////////////////////*/ - /** - * @notice Set the pending arbitrator - * @param _pendingArbitrator The address of the pending arbitrator - */ - function setPendingArbitrator(address _pendingArbitrator) external; - - /** - * @notice Accept the pending arbitrator - */ - function acceptPendingArbitrator() external; - /** * @notice Create requests * @param _epoch The epoch of the request @@ -187,14 +142,37 @@ interface IEBORequestCreator { function removeChain(string calldata _chainId) external; /** - * @notice Set the reward paid for each chain updated - * @param _reward The reward to set + * @notice Set the request data module + * @param _requestModule The request module + * @param _requestModuleData The request module data + */ + function setRequestModuleData(address _requestModule, bytes calldata _requestModuleData) external; + + /** + * @notice Set the response data module + * @param _responseModule The response module + * @param _responseModuleData The response module data + */ + function setResponseModuleData(address _responseModule, bytes calldata _responseModuleData) external; + + /** + * @notice Set the dispute data module + * @param _disputeModule The dispute module + * @param _disputeModuleData The dispute module data + */ + function setDisputeModuleData(address _disputeModule, bytes calldata _disputeModuleData) external; + + /** + * @notice Set the resolution data module + * @param _resolutionModule The resolution module + * @param _resolutionModuleData The resolution module data */ - function setReward(uint256 _reward) external; + function setResolutionModuleData(address _resolutionModule, bytes calldata _resolutionModuleData) external; /** - * @notice Set the request data - * @param _requestData The request data to set + * @notice Set the finality data module + * @param _finalityModule The finality module + * @param _finalityModuleData The finality module data */ - function setRequestData(RequestData calldata _requestData) external; + function setFinalityModuleData(address _finalityModule, bytes calldata _finalityModuleData) external; } diff --git a/test/integration/IntegrationBase.sol b/test/integration/IntegrationBase.sol index d24e0f9..77416e7 100644 --- a/test/integration/IntegrationBase.sol +++ b/test/integration/IntegrationBase.sol @@ -4,13 +4,14 @@ pragma solidity 0.8.26; import {Test} from 'forge-std/Test.sol'; import {IERC20} from 'forge-std/interfaces/IERC20.sol'; -import {Oracle} from '@defi-wonderland/prophet-core-contracts/solidity/contracts/Oracle.sol'; +import {Oracle} from '@defi-wonderland/prophet-core/solidity/contracts/Oracle.sol'; import {EBORequestCreator, IEBORequestCreator, IOracle} from 'contracts/EBORequestCreator.sol'; contract IntegrationBase is Test { uint256 internal constant _FORK_BLOCK = 18_920_905; address internal _arbitrator = makeAddr('arbitrator'); + address internal _council = makeAddr('council'); address internal _owner = makeAddr('owner'); address internal _user = makeAddr('user'); @@ -22,7 +23,9 @@ contract IntegrationBase is Test { vm.startPrank(_owner); _oracle = new Oracle(); - _eboRequestCreator = new EBORequestCreator(_oracle, _arbitrator); + + // TODO: Replace with the implementation + _eboRequestCreator = new EBORequestCreator(_oracle, _arbitrator, _council); vm.stopPrank(); } diff --git a/test/unit/EBORequestCreator.t.sol b/test/unit/EBORequestCreator.t.sol index 3102ff4..f106824 100644 --- a/test/unit/EBORequestCreator.t.sol +++ b/test/unit/EBORequestCreator.t.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.26; import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; import {EBORequestCreator, IEBORequestCreator, IOracle} from 'contracts/EBORequestCreator.sol'; +import {IArbitrable} from 'interfaces/IArbitrable.sol'; import {Test} from 'forge-std/Test.sol'; import 'forge-std/console.sol'; @@ -11,11 +12,7 @@ import 'forge-std/console.sol'; contract EBORequestCreatorForTest is EBORequestCreator { using EnumerableSet for EnumerableSet.Bytes32Set; - constructor(IOracle _oracle, address _owner) EBORequestCreator(_oracle, _owner) {} - - function setPendingArbitratorForTest(address _pendingArbitrator) external { - pendingArbitrator = _pendingArbitrator; - } + constructor(IOracle _oracle, address _arbitrator, address _council) EBORequestCreator(_oracle, _arbitrator, _council) {} function setChainIdForTest(string calldata _chainId) external returns (bool _added) { _added = _chainIdsAllowed.add(_encodeChainId(_chainId)); @@ -28,13 +25,15 @@ contract EBORequestCreatorForTest is EBORequestCreator { abstract contract EBORequestCreator_Unit_BaseTest is Test { /// Events - event PendingArbitratorSetted(address _pendingArbitrator); - event ArbitratorSetted(address _oldArbitrator, address _newArbitrator); + event RequestCreated(bytes32 indexed _requestId, uint256 indexed _epoch, string indexed _chainId); event ChainAdded(string indexed _chainId); event ChainRemoved(string indexed _chainId); - event RewardSet(uint256 _oldReward, uint256 _newReward); - event RequestDataSet(EBORequestCreator.RequestData _requestData); + event RequestModuleDataSet(address indexed _requestModule, bytes _requestModuleData); + event ResponseModuleDataSet(address indexed _responseModule, bytes _responseModuleData); + event DisputeModuleDataSet(address indexed _disputeModule, bytes _disputeModuleData); + event ResolutionModuleDataSet(address indexed _resolutionModule, bytes _resolutionModuleData); + event FinalityModuleDataSet(address indexed _finalityModule, bytes _finalityModuleData); /// Contracts EBORequestCreatorForTest public eboRequestCreator; @@ -42,17 +41,18 @@ abstract contract EBORequestCreator_Unit_BaseTest is Test { /// EOAs address public arbitrator; + address public council; function setUp() external { + council = makeAddr('Council'); arbitrator = makeAddr('Arbitrator'); oracle = IOracle(makeAddr('Oracle')); - vm.prank(arbitrator); - eboRequestCreator = new EBORequestCreatorForTest(oracle, arbitrator); + eboRequestCreator = new EBORequestCreatorForTest(oracle, arbitrator, council); } function _revertIfNotArbitrator() internal { - vm.expectRevert(IEBORequestCreator.EBORequestCreator_OnlyArbitrator.selector); + vm.expectRevert(IArbitrable.Arbitrable_OnlyArbitrator.selector); } } @@ -61,83 +61,12 @@ contract EBORequestCreator_Unit_Constructor is EBORequestCreator_Unit_BaseTest { * @notice Test the constructor */ function test_constructor() external view { - assertEq(eboRequestCreator.reward(), 0); assertEq(eboRequestCreator.arbitrator(), arbitrator); - assertEq(eboRequestCreator.pendingArbitrator(), address(0)); + assertEq(eboRequestCreator.council(), council); assertEq(address(eboRequestCreator.oracle()), address(oracle)); } } -contract EBORequestCreator_Unit_SetPendingArbitrator is EBORequestCreator_Unit_BaseTest { - modifier happyPath(address _pendingArbitrator) { - vm.startPrank(arbitrator); - _; - } - - /** - * @notice Test the revert if the caller is not the arbitrator - */ - function test_revertIfNotArbitrator(address _pendingArbitrator) external { - vm.expectRevert(IEBORequestCreator.EBORequestCreator_OnlyArbitrator.selector); - eboRequestCreator.setPendingArbitrator(_pendingArbitrator); - } - - /** - * @notice Test the set pending arbitrator - */ - function test_setPendingArbitrator(address _pendingArbitrator) external happyPath(_pendingArbitrator) { - eboRequestCreator.setPendingArbitrator(_pendingArbitrator); - - assertEq(eboRequestCreator.pendingArbitrator(), _pendingArbitrator); - } - - /** - * @notice Test the emit pending arbitrator setted - */ - function test_emitPendingArbitratorSetted(address _pendingArbitrator) external happyPath(_pendingArbitrator) { - vm.expectEmit(); - emit PendingArbitratorSetted(_pendingArbitrator); - - eboRequestCreator.setPendingArbitrator(_pendingArbitrator); - } -} - -contract EBORequestCreator_Unit_AcceptPendingArbitrator is EBORequestCreator_Unit_BaseTest { - modifier happyPath(address _pendingArbitrator) { - eboRequestCreator.setPendingArbitratorForTest(_pendingArbitrator); - vm.startPrank(_pendingArbitrator); - _; - } - - /** - * @notice Test the revert if the caller is not the pending arbitrator - */ - function test_revertIfNotPendingArbitrator() external { - vm.expectRevert(IEBORequestCreator.EBORequestCreator_OnlyPendingArbitrator.selector); - eboRequestCreator.acceptPendingArbitrator(); - } - - /** - * @notice Test the accept pending arbitrator - */ - function test_acceptPendingArbitrator(address _pendingArbitrator) external happyPath(_pendingArbitrator) { - eboRequestCreator.acceptPendingArbitrator(); - - assertEq(eboRequestCreator.arbitrator(), _pendingArbitrator); - assertEq(eboRequestCreator.pendingArbitrator(), address(0)); - } - - /** - * @notice Test the emit arbitrator setted - */ - function test_emitArbitratorSetted(address _pendingArbitrator) external happyPath(_pendingArbitrator) { - vm.expectEmit(); - emit ArbitratorSetted(arbitrator, _pendingArbitrator); - - eboRequestCreator.acceptPendingArbitrator(); - } -} - contract EBORequestCreator_Unit_CreateRequest is EBORequestCreator_Unit_BaseTest { string[] internal _cleanChainIds; @@ -160,10 +89,9 @@ contract EBORequestCreator_Unit_CreateRequest is EBORequestCreator_Unit_BaseTest /** * @notice Test the revert if the caller is not the arbitrator */ - function test_revertIfChainNotAdded() external { + function test_revertIfChainNotAdded(uint256 _epoch) external { vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_ChainNotAdded.selector)); - - eboRequestCreator.createRequests(0, new string[](1)); + eboRequestCreator.createRequests(_epoch, new string[](1)); } /** @@ -275,8 +203,8 @@ contract EBORequestCreator_Unit_RemoveChain is EBORequestCreator_Unit_BaseTest { } } -contract EBORequestCreator_Unit_SetReward is EBORequestCreator_Unit_BaseTest { - modifier happyPath(uint256 _reward) { +contract EBORequestCreator_Unit_SetRequestModuleData is EBORequestCreator_Unit_BaseTest { + modifier happyPath(address _requestModule, bytes calldata _requestModuleData) { vm.startPrank(arbitrator); _; } @@ -284,33 +212,55 @@ contract EBORequestCreator_Unit_SetReward is EBORequestCreator_Unit_BaseTest { /** * @notice Test the revert if the caller is not the arbitrator */ - function test_revertIfNotArbitrator(uint256 _reward) external { + function test_revertIfNotArbitrator(address _requestModule, bytes calldata _requestModuleData) external { _revertIfNotArbitrator(); - eboRequestCreator.setReward(_reward); + eboRequestCreator.setRequestModuleData(_requestModule, _requestModuleData); } /** - * @notice Test the set reward + * @notice Test the emit request module data set */ - function test_setReward(uint256 _reward) external happyPath(_reward) { - eboRequestCreator.setReward(_reward); + function test_emitRequestModuleDataSet( + address _requestModule, + bytes calldata _requestModuleData + ) external happyPath(_requestModule, _requestModuleData) { + vm.expectEmit(); + emit RequestModuleDataSet(_requestModule, _requestModuleData); + + eboRequestCreator.setRequestModuleData(_requestModule, _requestModuleData); + } +} - assertEq(eboRequestCreator.reward(), _reward); +contract EBORequestCreator_Unit_SetResponseModuleData is EBORequestCreator_Unit_BaseTest { + modifier happyPath(address _responseModule, bytes calldata _responseModuleData) { + vm.startPrank(arbitrator); + _; + } + + /** + * @notice Test the revert if the caller is not the arbitrator + */ + function test_revertIfNotArbitrator(address _responseModule, bytes calldata _responseModuleData) external { + _revertIfNotArbitrator(); + eboRequestCreator.setResponseModuleData(_responseModule, _responseModuleData); } /** - * @notice Test the emit reward set + * @notice Test the emit response module data set */ - function test_emitRewardSet(uint256 _reward) external happyPath(_reward) { + function test_emitResponseModuleDataSet( + address _responseModule, + bytes calldata _responseModuleData + ) external happyPath(_responseModule, _responseModuleData) { vm.expectEmit(); - emit RewardSet(0, _reward); + emit ResponseModuleDataSet(_responseModule, _responseModuleData); - eboRequestCreator.setReward(_reward); + eboRequestCreator.setResponseModuleData(_responseModule, _responseModuleData); } } -contract EBORequestCreator_Unit_SetRequestData is EBORequestCreator_Unit_BaseTest { - modifier happyPath(EBORequestCreator.RequestData calldata _requestData) { +contract EBORequestCreator_Unit_SetDisputeModuleData is EBORequestCreator_Unit_BaseTest { + modifier happyPath(address _disputeModule, bytes calldata _disputeModuleData) { vm.startPrank(arbitrator); _; } @@ -318,52 +268,77 @@ contract EBORequestCreator_Unit_SetRequestData is EBORequestCreator_Unit_BaseTes /** * @notice Test the revert if the caller is not the arbitrator */ - function test_revertIfNotArbitrator(EBORequestCreator.RequestData calldata _requestData) external { + function test_revertIfNotArbitrator(address _disputeModule, bytes calldata _disputeModuleData) external { _revertIfNotArbitrator(); - eboRequestCreator.setRequestData(_requestData); + eboRequestCreator.setDisputeModuleData(_disputeModule, _disputeModuleData); } /** - * @notice Test the set request data + * @notice Test the emit dispute module data set */ - function test_setRequestData(EBORequestCreator.RequestData calldata _requestData) external happyPath(_requestData) { - eboRequestCreator.setRequestData(_requestData); - - ( - address _requestModule, - address _responseModule, - address _disputeModule, - address _resolutionModule, - address _finalityModule, - bytes memory _requestModuleData, - bytes memory _responseModuleData, - bytes memory _disputeModuleData, - bytes memory _resolutionModuleData, - bytes memory _finalityModuleData - ) = eboRequestCreator.requestData(); - - assertEq(_requestModule, _requestData.requestModule); - assertEq(_responseModule, _requestData.responseModule); - assertEq(_disputeModule, _requestData.disputeModule); - assertEq(_resolutionModule, _requestData.resolutionModule); - assertEq(_finalityModule, _requestData.finalityModule); - assertEq(_requestModuleData, _requestData.requestModuleData); - assertEq(_responseModuleData, _requestData.responseModuleData); - assertEq(_disputeModuleData, _requestData.disputeModuleData); - assertEq(_resolutionModuleData, _requestData.resolutionModuleData); - assertEq(_finalityModuleData, _requestData.finalityModuleData); + function test_emitDisputeModuleDataSet( + address _disputeModule, + bytes calldata _disputeModuleData + ) external happyPath(_disputeModule, _disputeModuleData) { + vm.expectEmit(); + emit DisputeModuleDataSet(_disputeModule, _disputeModuleData); + + eboRequestCreator.setDisputeModuleData(_disputeModule, _disputeModuleData); + } +} + +contract EBORequestCreator_Unit_SetResolutionModuleData is EBORequestCreator_Unit_BaseTest { + modifier happyPath(address _resolutionModule, bytes calldata _resolutionModuleData) { + vm.startPrank(arbitrator); + _; + } + + /** + * @notice Test the revert if the caller is not the arbitrator + */ + function test_revertIfNotArbitrator(address _resolutionModule, bytes calldata _resolutionModuleData) external { + _revertIfNotArbitrator(); + eboRequestCreator.setResolutionModuleData(_resolutionModule, _resolutionModuleData); + } + + /** + * @notice Test the emit resolution module data set + */ + function test_emitResolutionModuleDataSet( + address _resolutionModule, + bytes calldata _resolutionModuleData + ) external happyPath(_resolutionModule, _resolutionModuleData) { + vm.expectEmit(); + emit ResolutionModuleDataSet(_resolutionModule, _resolutionModuleData); + + eboRequestCreator.setResolutionModuleData(_resolutionModule, _resolutionModuleData); + } +} + +contract EBORequestCreator_Unit_SetFinalityModuleData is EBORequestCreator_Unit_BaseTest { + modifier happyPath(address _finalityModule, bytes calldata _finalityModuleData) { + vm.startPrank(arbitrator); + _; + } + + /** + * @notice Test the revert if the caller is not the arbitrator + */ + function test_revertIfNotArbitrator(address _finalityModule, bytes calldata _finalityModuleData) external { + _revertIfNotArbitrator(); + eboRequestCreator.setFinalityModuleData(_finalityModule, _finalityModuleData); } /** - * @notice Test the emit request data set + * @notice Test the emit finality module data set */ - function test_emitRequestDataSet(EBORequestCreator.RequestData calldata _requestData) - external - happyPath(_requestData) - { + function test_emitFinalityModuleDataSet( + address _finalityModule, + bytes calldata _finalityModuleData + ) external happyPath(_finalityModule, _finalityModuleData) { vm.expectEmit(); - emit RequestDataSet(_requestData); + emit FinalityModuleDataSet(_finalityModule, _finalityModuleData); - eboRequestCreator.setRequestData(_requestData); + eboRequestCreator.setFinalityModuleData(_finalityModule, _finalityModuleData); } } diff --git a/yarn.lock b/yarn.lock index f10f820..2116915 100644 --- a/yarn.lock +++ b/yarn.lock @@ -190,16 +190,16 @@ solc-typed-ast "18.1.2" yargs "17.7.2" -"@defi-wonderland/prophet-core-contracts@0.0.0-438de1c5": - version "0.0.0-438de1c5" - resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core-contracts/-/prophet-core-contracts-0.0.0-438de1c5.tgz#2b0238636c89eb71b07d57e12abfdea57c53b03b" - integrity sha512-UqdNRr2eH5DNSQ7qUriZbvR9LoXLXDMKTOjcjTTc8Gbq1aVcBhwFu4mSdrnhpQkXHjKtmsO0IfGcRHIGLvnXSQ== - "@defi-wonderland/prophet-core-contracts@0.0.0-d01bc1a0": version "0.0.0-d01bc1a0" resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core-contracts/-/prophet-core-contracts-0.0.0-d01bc1a0.tgz#ee4e8d970289a26966f6565b2f691d68d7b4232a" integrity sha512-n4Dl1QgQAZafOtV7ef/fSoew2qlxWSdS389Z6PdIn7LxrHrzzRJi+nmJ1DJazMvMuhk/0dZbMhnaXMBi05E1zQ== +"@defi-wonderland/prophet-core@0.0.0-172a7bcf": + version "0.0.0-172a7bcf" + resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core/-/prophet-core-0.0.0-172a7bcf.tgz#d7074ebc775b44ebd32fea3a728bdc6883b4f40a" + integrity sha512-lot6rq6gG7E6x4tl0lp3Lktm8Yymo6pdy7Wf9VmtzogjrV5/cdi9zRNMQjiX7HeU1iBT2tvMxbFpLFyulR+zqw== + "@defi-wonderland/prophet-modules-contracts@0.0.0-1197c328": version "0.0.0-1197c328" resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-modules-contracts/-/prophet-modules-contracts-0.0.0-1197c328.tgz#f58aa52a5a33fb39a9404bdf5e16ab75fcdde85f" @@ -1725,9 +1725,9 @@ solhint-community@4.0.0: optionalDependencies: prettier "^2.8.3" -"solmate@git+https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c": +"solmate@https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c": version "6.1.0" - resolved "git+https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" + resolved "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" sort-object-keys@^1.1.3: version "1.1.3" From 6ab31cbaf6f5bdbf70e1c619ba39298dc3b12be3 Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Fri, 9 Aug 2024 00:34:59 -0300 Subject: [PATCH 07/19] fix: echidna --- .github/workflows/tests.yml | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1862446..f7256a8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -26,7 +26,7 @@ jobs: uses: actions/setup-node@v4 with: node-version: 20.x - cache: 'yarn' + cache: "yarn" - name: Install dependencies run: yarn --frozen-lockfile --network-concurrency 1 @@ -53,7 +53,7 @@ jobs: uses: actions/setup-node@v4 with: node-version: 20.x - cache: 'yarn' + cache: "yarn" - name: Install dependencies run: yarn --frozen-lockfile --network-concurrency 1 @@ -83,7 +83,7 @@ jobs: uses: actions/setup-node@v4 with: node-version: 20.x - cache: 'yarn' + cache: "yarn" - name: Install dependencies run: yarn --frozen-lockfile --network-concurrency 1 @@ -92,14 +92,6 @@ jobs: run: | forge build --build-info - - name: Run Echidna - uses: crytic/echidna-action@v2 - with: - files: . - contract: InvariantGreeter - test-mode: assertion - crytic-args: --ignore-compile - halmos-tests: name: Run symbolic execution tests runs-on: ubuntu-latest @@ -115,7 +107,7 @@ jobs: uses: actions/setup-node@v4 with: node-version: 20.x - cache: 'yarn' + cache: "yarn" - name: Install dependencies run: yarn --frozen-lockfile --network-concurrency 1 @@ -146,9 +138,9 @@ jobs: uses: actions/setup-node@v4 with: node-version: 20.x - cache: 'yarn' + cache: "yarn" - name: Install dependencies run: yarn --frozen-lockfile --network-concurrency 1 - - run: yarn lint:check \ No newline at end of file + - run: yarn lint:check From bd14bb0aa9c44ca2cf924d64f4494fd6007e321a Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Fri, 9 Aug 2024 00:35:24 -0300 Subject: [PATCH 08/19] fix: echidna --- .github/workflows/tests.yml | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1862446..f7256a8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -26,7 +26,7 @@ jobs: uses: actions/setup-node@v4 with: node-version: 20.x - cache: 'yarn' + cache: "yarn" - name: Install dependencies run: yarn --frozen-lockfile --network-concurrency 1 @@ -53,7 +53,7 @@ jobs: uses: actions/setup-node@v4 with: node-version: 20.x - cache: 'yarn' + cache: "yarn" - name: Install dependencies run: yarn --frozen-lockfile --network-concurrency 1 @@ -83,7 +83,7 @@ jobs: uses: actions/setup-node@v4 with: node-version: 20.x - cache: 'yarn' + cache: "yarn" - name: Install dependencies run: yarn --frozen-lockfile --network-concurrency 1 @@ -92,14 +92,6 @@ jobs: run: | forge build --build-info - - name: Run Echidna - uses: crytic/echidna-action@v2 - with: - files: . - contract: InvariantGreeter - test-mode: assertion - crytic-args: --ignore-compile - halmos-tests: name: Run symbolic execution tests runs-on: ubuntu-latest @@ -115,7 +107,7 @@ jobs: uses: actions/setup-node@v4 with: node-version: 20.x - cache: 'yarn' + cache: "yarn" - name: Install dependencies run: yarn --frozen-lockfile --network-concurrency 1 @@ -146,9 +138,9 @@ jobs: uses: actions/setup-node@v4 with: node-version: 20.x - cache: 'yarn' + cache: "yarn" - name: Install dependencies run: yarn --frozen-lockfile --network-concurrency 1 - - run: yarn lint:check \ No newline at end of file + - run: yarn lint:check From 0c7079340b1f9dfa2b2e31ebde81c31144a8134c Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Mon, 12 Aug 2024 15:51:39 -0300 Subject: [PATCH 09/19] feat: comments --- package.json | 4 ++-- src/contracts/EBORequestCreator.sol | 28 ++++++------------------ src/interfaces/IEBORequestCreator.sol | 2 +- yarn.lock | 31 +++++++++++---------------- 4 files changed, 23 insertions(+), 42 deletions(-) diff --git a/package.json b/package.json index 5b71c40..bb2f368 100644 --- a/package.json +++ b/package.json @@ -35,8 +35,8 @@ "package.json": "sort-package-json" }, "dependencies": { - "@defi-wonderland/prophet-core": "0.0.0-172a7bcf", - "@defi-wonderland/prophet-modules-contracts": "0.0.0-1197c328" + "@defi-wonderland/prophet-core": "0.0.0-2e39539b", + "@defi-wonderland/prophet-modules": "0.0.0-e52f8cce" }, "devDependencies": { "@commitlint/cli": "19.3.0", diff --git a/src/contracts/EBORequestCreator.sol b/src/contracts/EBORequestCreator.sol index cfa2221..e9ac6b9 100644 --- a/src/contracts/EBORequestCreator.sol +++ b/src/contracts/EBORequestCreator.sol @@ -33,28 +33,16 @@ contract EBORequestCreator is IEBORequestCreator, Arbitrable { IOracle.Request memory _requestData = requestData; + _requestData.nonce = uint96(0); + _requestData.requester = address(this); + for (uint256 _i; _i < _chainIds.length; _i++) { _encodedChainId = _encodeChainId(_chainIds[_i]); if (!_chainIdsAllowed.contains(_encodedChainId)) revert EBORequestCreator_ChainNotAdded(); if (requestIdPerChainAndEpoch[_chainIds[_i]][_epoch] == bytes32(0)) { - // TODO: COMPLETE THE REQUEST CREATION WITH THE PROPER MODULES - IOracle.Request memory _request = IOracle.Request({ - nonce: uint96(0), - requester: address(this), - requestModule: _requestData.requestModule, - responseModule: _requestData.responseModule, - disputeModule: _requestData.disputeModule, - resolutionModule: _requestData.resolutionModule, - finalityModule: _requestData.finalityModule, - requestModuleData: _requestData.requestModuleData, - responseModuleData: _requestData.responseModuleData, - disputeModuleData: _requestData.disputeModuleData, - resolutionModuleData: _requestData.resolutionModuleData, - finalityModuleData: _requestData.finalityModuleData - }); - - bytes32 _requestId = oracle.createRequest(_request, bytes32(0)); + // TODO: CREATE REQUEST DATA + bytes32 _requestId = oracle.createRequest(_requestData, bytes32(0)); requestIdPerChainAndEpoch[_chainIds[_i]][_epoch] = _requestId; @@ -66,10 +54,9 @@ contract EBORequestCreator is IEBORequestCreator, Arbitrable { /// @inheritdoc IEBORequestCreator function addChain(string calldata _chainId) external onlyArbitrator { bytes32 _encodedChainId = _encodeChainId(_chainId); - if (_chainIdsAllowed.contains(_encodedChainId)) { + if (!_chainIdsAllowed.add(_encodedChainId)) { revert EBORequestCreator_ChainAlreadyAdded(); } - _chainIdsAllowed.add(_encodedChainId); emit ChainAdded(_chainId); } @@ -77,10 +64,9 @@ contract EBORequestCreator is IEBORequestCreator, Arbitrable { /// @inheritdoc IEBORequestCreator function removeChain(string calldata _chainId) external onlyArbitrator { bytes32 _encodedChainId = _encodeChainId(_chainId); - if (!_chainIdsAllowed.contains(_encodedChainId)) { + if (!_chainIdsAllowed.remove(_encodedChainId)) { revert EBORequestCreator_ChainNotAdded(); } - _chainIdsAllowed.remove(_encodedChainId); emit ChainRemoved(_chainId); } diff --git a/src/interfaces/IEBORequestCreator.sol b/src/interfaces/IEBORequestCreator.sol index 9619f67..ffc8792 100644 --- a/src/interfaces/IEBORequestCreator.sol +++ b/src/interfaces/IEBORequestCreator.sol @@ -68,7 +68,7 @@ interface IEBORequestCreator { //////////////////////////////////////////////////////////////*/ /** - * @notice hrown when the chain is already added + * @notice Thrown when the chain is already added */ error EBORequestCreator_ChainAlreadyAdded(); diff --git a/yarn.lock b/yarn.lock index 2116915..3793e60 100644 --- a/yarn.lock +++ b/yarn.lock @@ -190,22 +190,17 @@ solc-typed-ast "18.1.2" yargs "17.7.2" -"@defi-wonderland/prophet-core-contracts@0.0.0-d01bc1a0": - version "0.0.0-d01bc1a0" - resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core-contracts/-/prophet-core-contracts-0.0.0-d01bc1a0.tgz#ee4e8d970289a26966f6565b2f691d68d7b4232a" - integrity sha512-n4Dl1QgQAZafOtV7ef/fSoew2qlxWSdS389Z6PdIn7LxrHrzzRJi+nmJ1DJazMvMuhk/0dZbMhnaXMBi05E1zQ== - -"@defi-wonderland/prophet-core@0.0.0-172a7bcf": - version "0.0.0-172a7bcf" - resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core/-/prophet-core-0.0.0-172a7bcf.tgz#d7074ebc775b44ebd32fea3a728bdc6883b4f40a" - integrity sha512-lot6rq6gG7E6x4tl0lp3Lktm8Yymo6pdy7Wf9VmtzogjrV5/cdi9zRNMQjiX7HeU1iBT2tvMxbFpLFyulR+zqw== - -"@defi-wonderland/prophet-modules-contracts@0.0.0-1197c328": - version "0.0.0-1197c328" - resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-modules-contracts/-/prophet-modules-contracts-0.0.0-1197c328.tgz#f58aa52a5a33fb39a9404bdf5e16ab75fcdde85f" - integrity sha512-78IRF5dSoHvVIzS9/NSqkuQrzPLrVKzRnBvOeSWt/vzoKy3Pm6rkcT5qzWZynIXbFNyMXGTa8HKYBWKFNlaE9A== - dependencies: - "@defi-wonderland/prophet-core-contracts" "0.0.0-d01bc1a0" +"@defi-wonderland/prophet-core@0.0.0-2e39539b": + version "0.0.0-2e39539b" + resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core/-/prophet-core-0.0.0-2e39539b.tgz#dbf01ed05a9af302841123c77e84bc0b3b4a6176" + integrity sha512-EdYpDEO1XeO08uQikhOQ6NzG0LWYxANFk272j4vCyLSJ8kRyJNMv69JJCLcq5kV0B9IzXybmqjreemkZ05z3kQ== + +"@defi-wonderland/prophet-modules@0.0.0-e52f8cce": + version "0.0.0-e52f8cce" + resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-modules/-/prophet-modules-0.0.0-e52f8cce.tgz#5b0cee1c75d1127267ccee29cdcdb2b3a2bfe5dd" + integrity sha512-zNx602Z/GuisTqi120JLgoWcs3wiMKDYvnXJ/6xdYUCNNBQKk2GyCmS6M5Hu1vTbSfDlNRrugy1cDOkG5sSGdg== + dependencies: + "@defi-wonderland/prophet-core" "0.0.0-2e39539b" "@openzeppelin/contracts" "4.9.5" solmate "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" @@ -1725,9 +1720,9 @@ solhint-community@4.0.0: optionalDependencies: prettier "^2.8.3" -"solmate@https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c": +"solmate@git+https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c": version "6.1.0" - resolved "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" + resolved "git+https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" sort-object-keys@^1.1.3: version "1.1.3" From 242ab9fecb64576ea2b2b6529630921f3e6e2e96 Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Mon, 12 Aug 2024 16:35:57 -0300 Subject: [PATCH 10/19] feat: arbitrum integration and comments --- foundry.toml | 2 ++ src/contracts/EBORequestCreator.sol | 2 +- src/interfaces/IEBORequestCreator.sol | 2 +- test/integration/Constants.sol | 4 ++++ .../{ => arbitrum}/CreateRequest.t.sol | 19 +++++++++++++------ .../{ => arbitrum}/IntegrationBase.sol | 9 ++++----- test/unit/EBORequestCreator.t.sol | 4 ++-- 7 files changed, 27 insertions(+), 15 deletions(-) create mode 100644 test/integration/Constants.sol rename test/integration/{ => arbitrum}/CreateRequest.t.sol (70%) rename test/integration/{ => arbitrum}/IntegrationBase.sol (72%) diff --git a/foundry.toml b/foundry.toml index 95bed70..1fd9249 100644 --- a/foundry.toml +++ b/foundry.toml @@ -30,7 +30,9 @@ runs = 1000 [rpc_endpoints] mainnet = "${MAINNET_RPC}" sepolia = "${SEPOLIA_RPC}" +arbitrum = "${ARBITRUM_RPC}" [etherscan] mainnet = { key = "${ETHERSCAN_API_KEY}", chain = "mainnet" } sepolia = { key = "${ETHERSCAN_API_KEY}", chain = "sepolia" } +arbitrum = { key = "${ARBITRUM_API_KEY}", chain = "arbitrum" } diff --git a/src/contracts/EBORequestCreator.sol b/src/contracts/EBORequestCreator.sol index e408749..2f5012e 100644 --- a/src/contracts/EBORequestCreator.sol +++ b/src/contracts/EBORequestCreator.sol @@ -43,7 +43,7 @@ contract EBORequestCreator is IEBORequestCreator, Arbitrable { /// @inheritdoc IEBORequestCreator function createRequests(uint256 _epoch, string[] calldata _chainIds) external { - if (_epoch > epochManager.currentEpoch() || startEpoch > _epoch) revert EBORequestCreator_EpochNotValid(); + if (_epoch > epochManager.currentEpoch() || startEpoch > _epoch) revert EBORequestCreator_InvalidEpoch(); bytes32 _encodedChainId; diff --git a/src/interfaces/IEBORequestCreator.sol b/src/interfaces/IEBORequestCreator.sol index aba0e44..0e749ed 100644 --- a/src/interfaces/IEBORequestCreator.sol +++ b/src/interfaces/IEBORequestCreator.sol @@ -87,7 +87,7 @@ interface IEBORequestCreator { /** * @notice Thrown when the epoch is not valid */ - error EBORequestCreator_EpochNotValid(); + error EBORequestCreator_InvalidEpoch(); /*/////////////////////////////////////////////////////////////// VARIABLES diff --git a/test/integration/Constants.sol b/test/integration/Constants.sol new file mode 100644 index 0000000..973a74b --- /dev/null +++ b/test/integration/Constants.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +address constant _EPOCH_MANAGER = 0x5A843145c43d328B9bB7a4401d94918f131bB281; diff --git a/test/integration/CreateRequest.t.sol b/test/integration/arbitrum/CreateRequest.t.sol similarity index 70% rename from test/integration/CreateRequest.t.sol rename to test/integration/arbitrum/CreateRequest.t.sol index e4f279d..0d9fe82 100644 --- a/test/integration/CreateRequest.t.sol +++ b/test/integration/arbitrum/CreateRequest.t.sol @@ -8,13 +8,20 @@ contract Integration_CreateRequest is IntegrationBase { string[] memory _chainIds = new string[](1); _chainIds[0] = 'chainId1'; - // TODO: Replace with the implementation - vm.mockCall(address(_epochManager), abi.encodeWithSelector(IEpochManager.currentEpoch.selector), abi.encode(1)); + // Should revert if the epoch is invalid + vm.expectRevert(IEBORequestCreator.EBORequestCreator_InvalidEpoch.selector); + vm.prank(_user); + _eboRequestCreator.createRequests(1, _chainIds); + + // New epoch + vm.roll(242_000_000); + // Get the current epoch + uint256 _currentEpoch = _epochManager.currentEpoch(); // Create a request without approving the chain id vm.expectRevert(IEBORequestCreator.EBORequestCreator_ChainNotAdded.selector); vm.prank(_user); - _eboRequestCreator.createRequests(1, _chainIds); + _eboRequestCreator.createRequests(_currentEpoch, _chainIds); // Create a request with an approved chain id vm.prank(_arbitrator); @@ -25,8 +32,8 @@ contract Integration_CreateRequest is IntegrationBase { vm.mockCall(address(_oracle), abi.encodeWithSelector(IOracle.createRequest.selector), abi.encode(_requestId)); vm.prank(_user); - _eboRequestCreator.createRequests(1, _chainIds); - assertEq(_eboRequestCreator.requestIdPerChainAndEpoch('chainId1', 1), _requestId); + _eboRequestCreator.createRequests(_currentEpoch, _chainIds); + assertEq(_eboRequestCreator.requestIdPerChainAndEpoch('chainId1', _currentEpoch), _requestId); // Remove the chain id vm.prank(_arbitrator); @@ -35,6 +42,6 @@ contract Integration_CreateRequest is IntegrationBase { // Create a request without approving the chain id vm.expectRevert(IEBORequestCreator.EBORequestCreator_ChainNotAdded.selector); vm.prank(_user); - _eboRequestCreator.createRequests(1, _chainIds); + _eboRequestCreator.createRequests(_currentEpoch, _chainIds); } } diff --git a/test/integration/IntegrationBase.sol b/test/integration/arbitrum/IntegrationBase.sol similarity index 72% rename from test/integration/IntegrationBase.sol rename to test/integration/arbitrum/IntegrationBase.sol index ef086ff..40a73de 100644 --- a/test/integration/IntegrationBase.sol +++ b/test/integration/arbitrum/IntegrationBase.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.26; +import {_EPOCH_MANAGER} from '../Constants.sol'; import {Test} from 'forge-std/Test.sol'; -import {IERC20} from 'forge-std/interfaces/IERC20.sol'; import {Oracle} from '@defi-wonderland/prophet-core/solidity/contracts/Oracle.sol'; import {EBORequestCreator, IEBORequestCreator, IEpochManager, IOracle} from 'contracts/EBORequestCreator.sol'; contract IntegrationBase is Test { - uint256 internal constant _FORK_BLOCK = 18_920_905; + uint256 internal constant _FORK_BLOCK = 240_000_000; address internal _arbitrator = makeAddr('arbitrator'); address internal _council = makeAddr('council'); @@ -20,13 +20,12 @@ contract IntegrationBase is Test { IEpochManager internal _epochManager; function setUp() public { - vm.createSelectFork(vm.rpcUrl('mainnet'), _FORK_BLOCK); + vm.createSelectFork(vm.rpcUrl('arbitrum'), _FORK_BLOCK); vm.startPrank(_owner); _oracle = new Oracle(); - // TODO: Replace with the implementation - vm.mockCall(address(_epochManager), abi.encodeWithSelector(IEpochManager.currentEpoch.selector), abi.encode(0)); + _epochManager = IEpochManager(_EPOCH_MANAGER); _eboRequestCreator = new EBORequestCreator(_oracle, _epochManager, _arbitrator, _council); vm.stopPrank(); diff --git a/test/unit/EBORequestCreator.t.sol b/test/unit/EBORequestCreator.t.sol index 6ad297b..bf903e6 100644 --- a/test/unit/EBORequestCreator.t.sol +++ b/test/unit/EBORequestCreator.t.sol @@ -126,7 +126,7 @@ contract EBORequestCreator_Unit_CreateRequest is EBORequestCreator_Unit_BaseTest address(epochManager), abi.encodeWithSelector(IEpochManager.currentEpoch.selector), abi.encode(_epoch - 1) ); - vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_EpochNotValid.selector)); + vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_InvalidEpoch.selector)); eboRequestCreator.createRequests(_epoch - 1, new string[](1)); } @@ -139,7 +139,7 @@ contract EBORequestCreator_Unit_CreateRequest is EBORequestCreator_Unit_BaseTest vm.mockCall(address(epochManager), abi.encodeWithSelector(IEpochManager.currentEpoch.selector), abi.encode(_epoch)); - vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_EpochNotValid.selector)); + vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_InvalidEpoch.selector)); eboRequestCreator.createRequests(_epoch + 1, new string[](1)); } From dfbc84163a689f9dc9563840b62d994ed33b4472 Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Mon, 12 Aug 2024 16:48:26 -0300 Subject: [PATCH 11/19] feat: tests constructor --- test/unit/EBORequestCreator.t.sol | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/test/unit/EBORequestCreator.t.sol b/test/unit/EBORequestCreator.t.sol index bf903e6..f91f6dc 100644 --- a/test/unit/EBORequestCreator.t.sol +++ b/test/unit/EBORequestCreator.t.sol @@ -72,13 +72,39 @@ abstract contract EBORequestCreator_Unit_BaseTest is Test { contract EBORequestCreator_Unit_Constructor is EBORequestCreator_Unit_BaseTest { /** - * @notice Test the constructor + * @notice Test arbitrator set in the constructor */ - function test_constructor() external view { + function test_arbitratorSet() external view { assertEq(eboRequestCreator.arbitrator(), arbitrator); + } + + /** + * @notice Test council set in the constructor + */ + function test_councilSet() external view { assertEq(eboRequestCreator.council(), council); + } + + /** + * @notice Test oracle set in the constructor + */ + function test_oracleSet() external view { assertEq(address(eboRequestCreator.oracle()), address(oracle)); } + + /** + * @notice Test epoch manager set in the constructor + */ + function test_epochManagerSet() external view { + assertEq(address(eboRequestCreator.epochManager()), address(epochManager)); + } + + /** + * @notice Test start epoch set in the constructor + */ + function test_startEpochSet() external view { + assertEq(eboRequestCreator.startEpoch(), 0); + } } contract EBORequestCreator_Unit_CreateRequest is EBORequestCreator_Unit_BaseTest { From e9d28d93f5cbaf660439f0e255712b041c86ec78 Mon Sep 17 00:00:00 2001 From: shaito Date: Mon, 12 Aug 2024 18:58:36 -0300 Subject: [PATCH 12/19] fix: arbitrum integration --- .env.example | 7 ++----- .github/workflows/tests.yml | 3 +-- README.md | 10 ++-------- foundry.toml | 4 ---- package.json | 3 +-- yarn.lock | 12 ++++++------ 6 files changed, 12 insertions(+), 27 deletions(-) diff --git a/.env.example b/.env.example index fe295b7..e3c05d2 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,4 @@ -MAINNET_RPC= -MAINNET_DEPLOYER_PK= - -SEPOLIA_RPC= -SEPOLIA_DEPLOYER_PK= +ARBITRUM_RPC= +ARBITRUM_DEPLOYER_PK= ETHERSCAN_API_KEY= diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f7256a8..fc88dbb 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,8 +7,7 @@ concurrency: cancel-in-progress: true env: - MAINNET_RPC: ${{ secrets.MAINNET_RPC }} - SEPOLIA_RPC: ${{ secrets.SEPOLIA_RPC }} + ARBITRUM_RPC: ${{ secrets.ARBITRUM_RPC }} jobs: unit-tests: diff --git a/README.md b/README.md index 7f35072..1986897 100644 --- a/README.md +++ b/README.md @@ -106,16 +106,10 @@ yarn coverage Configure the `.env` variables. -### Sepolia +### Arbitrum ```bash -yarn deploy:sepolia -``` - -### Mainnet - -```bash -yarn deploy:mainnet +yarn deploy:arbitrum ``` The deployments are stored in ./broadcast diff --git a/foundry.toml b/foundry.toml index 1fd9249..fd6c1eb 100644 --- a/foundry.toml +++ b/foundry.toml @@ -28,11 +28,7 @@ src = 'src/interfaces/' runs = 1000 [rpc_endpoints] -mainnet = "${MAINNET_RPC}" -sepolia = "${SEPOLIA_RPC}" arbitrum = "${ARBITRUM_RPC}" [etherscan] -mainnet = { key = "${ETHERSCAN_API_KEY}", chain = "mainnet" } -sepolia = { key = "${ETHERSCAN_API_KEY}", chain = "sepolia" } arbitrum = { key = "${ARBITRUM_API_KEY}", chain = "arbitrum" } diff --git a/package.json b/package.json index 5b71c40..2e139ed 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,7 @@ "build": "forge build", "build:optimized": "FOUNDRY_PROFILE=optimized forge build", "coverage": "forge coverage --report summary --report lcov --match-path 'test/unit/*'", - "deploy:mainnet": "bash -c 'source .env && forge script Deploy -vvvvv --rpc-url $MAINNET_RPC --broadcast --chain mainnet --private-key $MAINNET_DEPLOYER_PK'", - "deploy:sepolia": "bash -c 'source .env && forge script Deploy -vvvvv --rpc-url $SEPOLIA_RPC --broadcast --chain sepolia --private-key $SEPOLIA_DEPLOYER_PK'", + "deploy:arbitrum": "bash -c 'source .env && forge script Deploy -vvvvv --rpc-url $ARBITRUM_RPC --broadcast --chain arbitrum --private-key $ARBITRUM_DEPLOYER_PK'", "lint:check": "yarn lint:sol-tests && yarn lint:sol-logic && forge fmt --check", "lint:fix": "sort-package-json && forge fmt && yarn lint:sol-tests --fix && yarn lint:sol-logic --fix", "lint:natspec": "npx @defi-wonderland/natspec-smells --config natspec-smells.config.js", diff --git a/yarn.lock b/yarn.lock index f37accb..8b9cd00 100644 --- a/yarn.lock +++ b/yarn.lock @@ -190,22 +190,22 @@ solc-typed-ast "18.1.2" yargs "17.7.2" -"@defi-wonderland/prophet-core-contracts@0.0.0-d01bc1a0": - version "0.0.0-d01bc1a0" - resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core-contracts/-/prophet-core-contracts-0.0.0-d01bc1a0.tgz#ee4e8d970289a26966f6565b2f691d68d7b4232a" - integrity sha512-n4Dl1QgQAZafOtV7ef/fSoew2qlxWSdS389Z6PdIn7LxrHrzzRJi+nmJ1DJazMvMuhk/0dZbMhnaXMBi05E1zQ== - "@defi-wonderland/prophet-core@0.0.0-172a7bcf": version "0.0.0-172a7bcf" resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core/-/prophet-core-0.0.0-172a7bcf.tgz#d7074ebc775b44ebd32fea3a728bdc6883b4f40a" integrity sha512-lot6rq6gG7E6x4tl0lp3Lktm8Yymo6pdy7Wf9VmtzogjrV5/cdi9zRNMQjiX7HeU1iBT2tvMxbFpLFyulR+zqw== +"@defi-wonderland/prophet-core@0.0.0-2e39539b": + version "0.0.0-2e39539b" + resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core/-/prophet-core-0.0.0-2e39539b.tgz#dbf01ed05a9af302841123c77e84bc0b3b4a6176" + integrity sha512-EdYpDEO1XeO08uQikhOQ6NzG0LWYxANFk272j4vCyLSJ8kRyJNMv69JJCLcq5kV0B9IzXybmqjreemkZ05z3kQ== + "@defi-wonderland/prophet-modules-contracts@0.0.0-1197c328": version "0.0.0-1197c328" resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-modules-contracts/-/prophet-modules-contracts-0.0.0-1197c328.tgz#f58aa52a5a33fb39a9404bdf5e16ab75fcdde85f" integrity sha512-78IRF5dSoHvVIzS9/NSqkuQrzPLrVKzRnBvOeSWt/vzoKy3Pm6rkcT5qzWZynIXbFNyMXGTa8HKYBWKFNlaE9A== dependencies: - "@defi-wonderland/prophet-core" "0.0.0-2e39539b" + "@defi-wonderland/prophet-core-contracts" "0.0.0-d01bc1a0" "@openzeppelin/contracts" "4.9.5" solmate "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" From 83268993b43ec5ebe892e25237fc4f568b259ea6 Mon Sep 17 00:00:00 2001 From: shaito Date: Mon, 12 Aug 2024 19:02:20 -0300 Subject: [PATCH 13/19] fix: prophet package --- package.json | 4 ++-- yarn.lock | 19 +++++++------------ 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 2e139ed..58637b9 100644 --- a/package.json +++ b/package.json @@ -34,8 +34,8 @@ "package.json": "sort-package-json" }, "dependencies": { - "@defi-wonderland/prophet-core": "0.0.0-172a7bcf", - "@defi-wonderland/prophet-modules-contracts": "0.0.0-1197c328" + "@defi-wonderland/prophet-core": "0.0.0-2e39539b", + "@defi-wonderland/prophet-modules": "0.0.0-e52f8cce" }, "devDependencies": { "@commitlint/cli": "19.3.0", diff --git a/yarn.lock b/yarn.lock index 8b9cd00..170ec75 100644 --- a/yarn.lock +++ b/yarn.lock @@ -190,22 +190,17 @@ solc-typed-ast "18.1.2" yargs "17.7.2" -"@defi-wonderland/prophet-core@0.0.0-172a7bcf": - version "0.0.0-172a7bcf" - resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core/-/prophet-core-0.0.0-172a7bcf.tgz#d7074ebc775b44ebd32fea3a728bdc6883b4f40a" - integrity sha512-lot6rq6gG7E6x4tl0lp3Lktm8Yymo6pdy7Wf9VmtzogjrV5/cdi9zRNMQjiX7HeU1iBT2tvMxbFpLFyulR+zqw== - "@defi-wonderland/prophet-core@0.0.0-2e39539b": version "0.0.0-2e39539b" resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core/-/prophet-core-0.0.0-2e39539b.tgz#dbf01ed05a9af302841123c77e84bc0b3b4a6176" integrity sha512-EdYpDEO1XeO08uQikhOQ6NzG0LWYxANFk272j4vCyLSJ8kRyJNMv69JJCLcq5kV0B9IzXybmqjreemkZ05z3kQ== -"@defi-wonderland/prophet-modules-contracts@0.0.0-1197c328": - version "0.0.0-1197c328" - resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-modules-contracts/-/prophet-modules-contracts-0.0.0-1197c328.tgz#f58aa52a5a33fb39a9404bdf5e16ab75fcdde85f" - integrity sha512-78IRF5dSoHvVIzS9/NSqkuQrzPLrVKzRnBvOeSWt/vzoKy3Pm6rkcT5qzWZynIXbFNyMXGTa8HKYBWKFNlaE9A== +"@defi-wonderland/prophet-modules@0.0.0-e52f8cce": + version "0.0.0-e52f8cce" + resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-modules/-/prophet-modules-0.0.0-e52f8cce.tgz#5b0cee1c75d1127267ccee29cdcdb2b3a2bfe5dd" + integrity sha512-zNx602Z/GuisTqi120JLgoWcs3wiMKDYvnXJ/6xdYUCNNBQKk2GyCmS6M5Hu1vTbSfDlNRrugy1cDOkG5sSGdg== dependencies: - "@defi-wonderland/prophet-core-contracts" "0.0.0-d01bc1a0" + "@defi-wonderland/prophet-core" "0.0.0-2e39539b" "@openzeppelin/contracts" "4.9.5" solmate "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" @@ -1732,9 +1727,9 @@ solhint-community@4.0.0: optionalDependencies: prettier "^2.8.3" -"solmate@https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c": +"solmate@git+https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c": version "6.1.0" - resolved "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" + resolved "git+https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" sort-object-keys@^1.1.3: version "1.1.3" From 640568e8ab63a480a85461c4a2b3ad1b2f496125 Mon Sep 17 00:00:00 2001 From: 0xJabberwock <0xjabberwock@defi.sucks> Date: Tue, 13 Aug 2024 16:33:45 -0300 Subject: [PATCH 14/19] feat: EBOFinalityModule (#2) --- package.json | 4 +- remappings.txt | 4 +- src/contracts/EBOFinalityModule.sol | 86 ++++++++ src/interfaces/IEBOFinalityModule.sol | 97 +++++++++ test/unit/EBOFinalityModule.t.sol | 271 ++++++++++++++++++++++++++ yarn.lock | 27 ++- 6 files changed, 469 insertions(+), 20 deletions(-) create mode 100644 src/contracts/EBOFinalityModule.sol create mode 100644 src/interfaces/IEBOFinalityModule.sol create mode 100644 test/unit/EBOFinalityModule.t.sol diff --git a/package.json b/package.json index eb82655..bb2f368 100644 --- a/package.json +++ b/package.json @@ -35,8 +35,8 @@ "package.json": "sort-package-json" }, "dependencies": { - "@defi-wonderland/prophet-core-contracts": "0.0.0-438de1c5", - "@defi-wonderland/prophet-modules-contracts": "0.0.0-1197c328" + "@defi-wonderland/prophet-core": "0.0.0-2e39539b", + "@defi-wonderland/prophet-modules": "0.0.0-e52f8cce" }, "devDependencies": { "@commitlint/cli": "19.3.0", diff --git a/remappings.txt b/remappings.txt index 2245399..37f3fdd 100644 --- a/remappings.txt +++ b/remappings.txt @@ -1,7 +1,7 @@ forge-std/=node_modules/forge-std/src halmos-cheatcodes=node_modules/halmos-cheatcodes -@defi-wonderland/prophet-core-contracts/=node_modules/@defi-wonderland/prophet-core-contracts -@defi-wonderland/prophet-modules-contracts/=node_modules/@defi-wonderland/prophet-modules-contracts +@defi-wonderland/prophet-core/=node_modules/@defi-wonderland/prophet-core +@defi-wonderland/prophet-modules/=node_modules/@defi-wonderland/prophet-modules contracts/=src/contracts interfaces/=src/interfaces diff --git a/src/contracts/EBOFinalityModule.sol b/src/contracts/EBOFinalityModule.sol new file mode 100644 index 0000000..b420400 --- /dev/null +++ b/src/contracts/EBOFinalityModule.sol @@ -0,0 +1,86 @@ +// 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 {IEBOFinalityModule} from 'interfaces/IEBOFinalityModule.sol'; + +/** + * @title EBOFinalityModule + * @notice Module allowing users to index data into the subgraph + * as a result of a request being finalized + */ +contract EBOFinalityModule is Module, Arbitrable, IEBOFinalityModule { + /// @inheritdoc IEBOFinalityModule + 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 IEBOFinalityModule + function finalizeRequest( + IOracle.Request calldata _request, + IOracle.Response calldata _response, + address _finalizer + ) external override(Module, IEBOFinalityModule) onlyOracle { + if (_request.requester != eboRequestCreator) revert EBOFinalityModule_InvalidRequester(); + + if (_response.requestId != 0) { + _validateResponse(_request, _response); + + // TODO: Redeclare the `Response` struct + // emit NewEpoch(_response.epoch, _response.chainId, _response.block); + } + + emit RequestFinalized(_response.requestId, _response, _finalizer); + } + + /// @inheritdoc IEBOFinalityModule + function amendEpoch( + uint256 _epoch, + uint256[] calldata _chainIds, + uint256[] calldata _blockNumbers + ) external onlyArbitrator { + uint256 _length = _chainIds.length; + if (_length != _blockNumbers.length) revert EBOFinalityModule_LengthMismatch(); + + for (uint256 _i; _i < _length; ++_i) { + emit AmendEpoch(_epoch, _chainIds[_i], _blockNumbers[_i]); + } + } + + /// @inheritdoc IEBOFinalityModule + function setEBORequestCreator(address _eboRequestCreator) external onlyArbitrator { + _setEBORequestCreator(_eboRequestCreator); + } + + /// @inheritdoc IModule + function moduleName() external pure returns (string memory _moduleName) { + _moduleName = 'EBOFinalityModule'; + } + + /** + * @notice Sets the address of the EBORequestCreator + * @param _eboRequestCreator The address of the EBORequestCreator + */ + function _setEBORequestCreator(address _eboRequestCreator) private { + eboRequestCreator = _eboRequestCreator; + emit SetEBORequestCreator(_eboRequestCreator); + } +} diff --git a/src/interfaces/IEBOFinalityModule.sol b/src/interfaces/IEBOFinalityModule.sol new file mode 100644 index 0000000..a247f44 --- /dev/null +++ b/src/interfaces/IEBOFinalityModule.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IOracle} from '@defi-wonderland/prophet-core/solidity/interfaces/IOracle.sol'; +import {IFinalityModule} from '@defi-wonderland/prophet-core/solidity/interfaces/modules/finality/IFinalityModule.sol'; + +import {IArbitrable} from 'interfaces/IArbitrable.sol'; + +/** + * @title EBOFinalityModule + * @notice Module allowing users to index data into the subgraph + * as a result of a request being finalized + */ +interface IEBOFinalityModule is IFinalityModule, IArbitrable { + /*/////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Emitted when the block number has been resolved for a particular epoch-chainId pair + * @param _epoch The new epoch + * @param _chainId The chain ID + * @param _blockNumber The block number for the epoch-chainId pair + */ + event NewEpoch(uint256 _epoch, uint256 indexed _chainId, uint256 _blockNumber); + + /** + * @notice Emitted when a block number is amended + * @param _epoch The epoch to amend + * @param _chainId The chain ID to amend + * @param _blockNumber The amended block number + */ + event AmendEpoch(uint256 _epoch, uint256 indexed _chainId, uint256 _blockNumber); + + /** + * @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 EBOFinalityModule_InvalidRequester(); + + /** + * @notice Thrown when the lengths of chain IDs and block numbers do not match + */ + error EBOFinalityModule_LengthMismatch(); + + /*/////////////////////////////////////////////////////////////// + VARIABLES + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Returns the address of the EBORequestCreator + * @return _eboRequestCreator The address of the EBORequestCreator + */ + function eboRequestCreator() external view returns (address _eboRequestCreator); + + /*/////////////////////////////////////////////////////////////// + LOGIC + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Finalizes the request by publishing the response + * @dev Callable only by the Oracle + * @param _request The request being finalized + * @param _response The final response + * @param _finalizer The address that initiated the finalization + */ + function finalizeRequest( + IOracle.Request calldata _request, + IOracle.Response calldata _response, + address _finalizer + ) external; + + /** + * @notice Allows to amend data in case of an error or an emergency + * @dev Callable only by The Graph's Arbitrator + * @param _epoch The epoch to amend + * @param _chainIds The chain IDs to amend + * @param _blockNumbers The amended block numbers + */ + function amendEpoch(uint256 _epoch, uint256[] calldata _chainIds, uint256[] calldata _blockNumbers) 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; +} diff --git a/test/unit/EBOFinalityModule.t.sol b/test/unit/EBOFinalityModule.t.sol new file mode 100644 index 0000000..b959fc4 --- /dev/null +++ b/test/unit/EBOFinalityModule.t.sol @@ -0,0 +1,271 @@ +// 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 {IValidator} from '@defi-wonderland/prophet-core/solidity/interfaces/IValidator.sol'; +import {ValidatorLib} from '@defi-wonderland/prophet-core/solidity/libraries/ValidatorLib.sol'; + +import {IArbitrable} from 'interfaces/IArbitrable.sol'; +import {IEBOFinalityModule} from 'interfaces/IEBOFinalityModule.sol'; + +import {EBOFinalityModule} from 'contracts/EBOFinalityModule.sol'; + +import 'forge-std/Test.sol'; + +contract EBOFinalityModule_Unit_BaseTest is Test { + EBOFinalityModule public eboFinalityModule; + + IOracle public oracle; + address public eboRequestCreator; + address public arbitrator; + address public council; + + uint256 public constant FUZZED_ARRAY_LENGTH = 32; + + event NewEpoch(uint256 _epoch, uint256 indexed _chainId, uint256 _blockNumber); + event AmendEpoch(uint256 _epoch, uint256 indexed _chainId, uint256 _blockNumber); + event SetEBORequestCreator(address _eboRequestCreator); + 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'); + + eboFinalityModule = new EBOFinalityModule(oracle, eboRequestCreator, arbitrator, council); + } + + function _getId(IOracle.Request memory _request) internal pure returns (bytes32 _id) { + _id = keccak256(abi.encode(_request)); + } + + function _getId(IOracle.Response memory _response) internal pure returns (bytes32 _id) { + _id = keccak256(abi.encode(_response)); + } + + function _getDynamicArray( + uint256[FUZZED_ARRAY_LENGTH] calldata _staticArray + ) internal pure returns (uint256[] memory _dynamicArray) { + _dynamicArray = new uint256[](FUZZED_ARRAY_LENGTH); + for (uint256 _i; _i < FUZZED_ARRAY_LENGTH; ++_i) { + _dynamicArray[_i] = _staticArray[_i]; + } + } +} + +contract EBOFinalityModule_Unit_Constructor is EBOFinalityModule_Unit_BaseTest { + struct ConstructorParams { + IOracle oracle; + address eboRequestCreator; + address arbitrator; + address council; + } + + function test_setOracle(ConstructorParams calldata _params) public { + eboFinalityModule = + new EBOFinalityModule(_params.oracle, _params.eboRequestCreator, _params.arbitrator, _params.council); + + assertEq(address(eboFinalityModule.ORACLE()), address(_params.oracle)); + } + + function test_setArbitrator(ConstructorParams calldata _params) public { + eboFinalityModule = + new EBOFinalityModule(_params.oracle, _params.eboRequestCreator, _params.arbitrator, _params.council); + + assertEq(eboFinalityModule.arbitrator(), _params.arbitrator); + } + + function test_emitSetArbitrator(ConstructorParams calldata _params) public { + vm.expectEmit(); + emit SetArbitrator(_params.arbitrator); + new EBOFinalityModule(_params.oracle, _params.eboRequestCreator, _params.arbitrator, _params.council); + } + + function test_setCouncil(ConstructorParams calldata _params) public { + eboFinalityModule = + new EBOFinalityModule(_params.oracle, _params.eboRequestCreator, _params.arbitrator, _params.council); + + assertEq(eboFinalityModule.council(), _params.council); + } + + function test_emitSetCouncil(ConstructorParams calldata _params) public { + vm.expectEmit(); + emit SetCouncil(_params.council); + new EBOFinalityModule(_params.oracle, _params.eboRequestCreator, _params.arbitrator, _params.council); + } + + function test_setEBORequestCreator(ConstructorParams calldata _params) public { + eboFinalityModule = + new EBOFinalityModule(_params.oracle, _params.eboRequestCreator, _params.arbitrator, _params.council); + + assertEq(eboFinalityModule.eboRequestCreator(), _params.eboRequestCreator); + } + + function test_emitSetEBORequestCreator(ConstructorParams calldata _params) public { + vm.expectEmit(); + emit SetEBORequestCreator(_params.eboRequestCreator); + new EBOFinalityModule(_params.oracle, _params.eboRequestCreator, _params.arbitrator, _params.council); + } +} + +contract EBOFinalityModule_Unit_FinalizeRequest is EBOFinalityModule_Unit_BaseTest { + struct FinalizeRequestParams { + IOracle.Request request; + IOracle.Response response; + address finalizer; + uint128 responseCreatedAt; + bool finalizeWithResponse; + } + + modifier happyPath(FinalizeRequestParams memory _params) { + _params.request.requester = eboRequestCreator; + + if (_params.finalizeWithResponse) { + _params.response.requestId = _getId(_params.request); + + vm.assume(_params.responseCreatedAt != 0); + vm.mockCall( + address(oracle), + abi.encodeCall(IOracle.responseCreatedAt, (_getId(_params.response))), + abi.encode(_params.responseCreatedAt) + ); + } else { + _params.response.requestId = 0; + } + + vm.startPrank(address(oracle)); + _; + } + + function test_revertOnlyOracle(FinalizeRequestParams memory _params) public happyPath(_params) { + vm.stopPrank(); + vm.expectRevert(IModule.Module_OnlyOracle.selector); + eboFinalityModule.finalizeRequest(_params.request, _params.response, _params.finalizer); + } + + function test_revertInvalidRequester( + FinalizeRequestParams memory _params, + address _requester + ) public happyPath(_params) { + vm.assume(_requester != eboRequestCreator); + _params.request.requester = _requester; + + vm.expectRevert(IEBOFinalityModule.EBOFinalityModule_InvalidRequester.selector); + eboFinalityModule.finalizeRequest(_params.request, _params.response, _params.finalizer); + } + + function test_revertInvalidResponseBody( + FinalizeRequestParams memory _params, + bytes32 _requestId + ) public happyPath(_params) { + vm.assume(_params.finalizeWithResponse); + vm.assume(_requestId != 0); + vm.assume(_requestId != _getId(_params.request)); + _params.response.requestId = _requestId; + + vm.expectRevert(ValidatorLib.ValidatorLib_InvalidResponseBody.selector); + eboFinalityModule.finalizeRequest(_params.request, _params.response, _params.finalizer); + } + + function test_revertInvalidResponse(FinalizeRequestParams memory _params) public happyPath(_params) { + vm.assume(_params.finalizeWithResponse); + vm.mockCall(address(oracle), abi.encodeCall(IOracle.responseCreatedAt, (_getId(_params.response))), abi.encode(0)); + + vm.expectRevert(IValidator.Validator_InvalidResponse.selector); + eboFinalityModule.finalizeRequest(_params.request, _params.response, _params.finalizer); + } + + function test_emitNewEpoch(FinalizeRequestParams memory _params) public happyPath(_params) { + vm.assume(_params.finalizeWithResponse); + + vm.skip(true); + // vm.expectEmit(); + // emit NewEpoch(_params.response.epoch, _params.response.chainId, _params.response.block); + eboFinalityModule.finalizeRequest(_params.request, _params.response, _params.finalizer); + } + + function test_emitRequestFinalized(FinalizeRequestParams memory _params) public happyPath(_params) { + vm.expectEmit(); + emit RequestFinalized(_params.response.requestId, _params.response, _params.finalizer); + eboFinalityModule.finalizeRequest(_params.request, _params.response, _params.finalizer); + } +} + +contract EBOFinalityModule_Unit_AmendEpoch is EBOFinalityModule_Unit_BaseTest { + struct AmendEpochParams { + uint256 epoch; + uint256[FUZZED_ARRAY_LENGTH] chainIds; + uint256[FUZZED_ARRAY_LENGTH] blockNumbers; + } + + modifier happyPath() { + vm.startPrank(arbitrator); + _; + } + + function test_revertOnlyArbitrator(AmendEpochParams calldata _params) public happyPath { + uint256[] memory _chainIds = _getDynamicArray(_params.chainIds); + uint256[] memory _blockNumbers = _getDynamicArray(_params.blockNumbers); + + vm.stopPrank(); + vm.expectRevert(IArbitrable.Arbitrable_OnlyArbitrator.selector); + eboFinalityModule.amendEpoch(_params.epoch, _chainIds, _blockNumbers); + } + + function test_revertLengthMismatch( + AmendEpochParams calldata _params, + uint256[] calldata _chainIds, + uint256[] calldata _blockNumbers + ) public happyPath { + vm.assume(_chainIds.length != _blockNumbers.length); + + vm.expectRevert(IEBOFinalityModule.EBOFinalityModule_LengthMismatch.selector); + eboFinalityModule.amendEpoch(_params.epoch, _chainIds, _blockNumbers); + } + + function test_emitAmendEpoch(AmendEpochParams calldata _params) public happyPath { + uint256[] memory _chainIds = _getDynamicArray(_params.chainIds); + uint256[] memory _blockNumbers = _getDynamicArray(_params.blockNumbers); + + for (uint256 _i; _i < _chainIds.length; ++_i) { + vm.expectEmit(); + emit AmendEpoch(_params.epoch, _chainIds[_i], _blockNumbers[_i]); + } + eboFinalityModule.amendEpoch(_params.epoch, _chainIds, _blockNumbers); + } +} + +contract EBOFinalityModule_Unit_SetEBORequestCreator is EBOFinalityModule_Unit_BaseTest { + modifier happyPath() { + vm.startPrank(arbitrator); + _; + } + + function test_revertOnlyArbitrator(address _eboRequestCreator) public happyPath { + vm.stopPrank(); + vm.expectRevert(IArbitrable.Arbitrable_OnlyArbitrator.selector); + eboFinalityModule.setEBORequestCreator(_eboRequestCreator); + } + + function test_setEBORequestCreator(address _eboRequestCreator) public happyPath { + eboFinalityModule.setEBORequestCreator(_eboRequestCreator); + + assertEq(eboFinalityModule.eboRequestCreator(), _eboRequestCreator); + } + + function test_emitSetEBORequestCreator(address _eboRequestCreator) public happyPath { + vm.expectEmit(); + emit SetEBORequestCreator(_eboRequestCreator); + eboFinalityModule.setEBORequestCreator(_eboRequestCreator); + } +} + +contract EBOFinalityModule_Unit_ModuleName is EBOFinalityModule_Unit_BaseTest { + function test_returnModuleName() public view { + assertEq(eboFinalityModule.moduleName(), 'EBOFinalityModule'); + } +} diff --git a/yarn.lock b/yarn.lock index f10f820..3793e60 100644 --- a/yarn.lock +++ b/yarn.lock @@ -190,22 +190,17 @@ solc-typed-ast "18.1.2" yargs "17.7.2" -"@defi-wonderland/prophet-core-contracts@0.0.0-438de1c5": - version "0.0.0-438de1c5" - resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core-contracts/-/prophet-core-contracts-0.0.0-438de1c5.tgz#2b0238636c89eb71b07d57e12abfdea57c53b03b" - integrity sha512-UqdNRr2eH5DNSQ7qUriZbvR9LoXLXDMKTOjcjTTc8Gbq1aVcBhwFu4mSdrnhpQkXHjKtmsO0IfGcRHIGLvnXSQ== - -"@defi-wonderland/prophet-core-contracts@0.0.0-d01bc1a0": - version "0.0.0-d01bc1a0" - resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core-contracts/-/prophet-core-contracts-0.0.0-d01bc1a0.tgz#ee4e8d970289a26966f6565b2f691d68d7b4232a" - integrity sha512-n4Dl1QgQAZafOtV7ef/fSoew2qlxWSdS389Z6PdIn7LxrHrzzRJi+nmJ1DJazMvMuhk/0dZbMhnaXMBi05E1zQ== - -"@defi-wonderland/prophet-modules-contracts@0.0.0-1197c328": - version "0.0.0-1197c328" - resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-modules-contracts/-/prophet-modules-contracts-0.0.0-1197c328.tgz#f58aa52a5a33fb39a9404bdf5e16ab75fcdde85f" - integrity sha512-78IRF5dSoHvVIzS9/NSqkuQrzPLrVKzRnBvOeSWt/vzoKy3Pm6rkcT5qzWZynIXbFNyMXGTa8HKYBWKFNlaE9A== - dependencies: - "@defi-wonderland/prophet-core-contracts" "0.0.0-d01bc1a0" +"@defi-wonderland/prophet-core@0.0.0-2e39539b": + version "0.0.0-2e39539b" + resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core/-/prophet-core-0.0.0-2e39539b.tgz#dbf01ed05a9af302841123c77e84bc0b3b4a6176" + integrity sha512-EdYpDEO1XeO08uQikhOQ6NzG0LWYxANFk272j4vCyLSJ8kRyJNMv69JJCLcq5kV0B9IzXybmqjreemkZ05z3kQ== + +"@defi-wonderland/prophet-modules@0.0.0-e52f8cce": + version "0.0.0-e52f8cce" + resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-modules/-/prophet-modules-0.0.0-e52f8cce.tgz#5b0cee1c75d1127267ccee29cdcdb2b3a2bfe5dd" + integrity sha512-zNx602Z/GuisTqi120JLgoWcs3wiMKDYvnXJ/6xdYUCNNBQKk2GyCmS6M5Hu1vTbSfDlNRrugy1cDOkG5sSGdg== + dependencies: + "@defi-wonderland/prophet-core" "0.0.0-2e39539b" "@openzeppelin/contracts" "4.9.5" solmate "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" From e7efafbde6a8fee7037604583cec73535272c18f Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Wed, 14 Aug 2024 02:09:56 -0300 Subject: [PATCH 15/19] fix: comments --- test/unit/EBORequestCreator.t.sol | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/unit/EBORequestCreator.t.sol b/test/unit/EBORequestCreator.t.sol index 3820f4d..8113653 100644 --- a/test/unit/EBORequestCreator.t.sol +++ b/test/unit/EBORequestCreator.t.sol @@ -11,6 +11,7 @@ import 'forge-std/console.sol'; contract EBORequestCreatorForTest is EBORequestCreator { using EnumerableSet for EnumerableSet.Bytes32Set; + using stdStorage for StdStorage; constructor( IOracle _oracle, @@ -145,10 +146,6 @@ contract EBORequestCreator_Unit_CreateRequest is EBORequestCreator_Unit_BaseTest function test_revertIfEpochBeforeStart(uint256 _epoch) external { vm.assume(_epoch > 0); - vm.store(address(eboRequestCreator), bytes32(uint256(1)), bytes32(uint256(_epoch))); - - console.log(eboRequestCreator.START_EPOCH()); - vm.mockCall( address(epochManager), abi.encodeWithSelector(IEpochManager.currentEpoch.selector), abi.encode(_epoch - 1) ); From 2ba458d1c127ad1e9e12c6f893565af05a6831ba Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Wed, 14 Aug 2024 02:19:59 -0300 Subject: [PATCH 16/19] feat: constructor --- src/contracts/EBORequestCreator.sol | 14 ++++++++++---- src/interfaces/IEBORequestCreator.sol | 4 ++++ test/integration/IntegrationBase.sol | 5 ++++- test/unit/EBORequestCreator.t.sol | 14 ++++++++++++-- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/contracts/EBORequestCreator.sol b/src/contracts/EBORequestCreator.sol index e9ac6b9..b42e2f5 100644 --- a/src/contracts/EBORequestCreator.sol +++ b/src/contracts/EBORequestCreator.sol @@ -23,8 +23,17 @@ contract EBORequestCreator is IEBORequestCreator, Arbitrable { */ EnumerableSet.Bytes32Set internal _chainIdsAllowed; - constructor(IOracle _oracle, address _arbitrator, address _council) Arbitrable(_arbitrator, _council) { + constructor( + IOracle _oracle, + address _arbitrator, + address _council, + IOracle.Request memory _requestData + ) Arbitrable(_arbitrator, _council) { oracle = _oracle; + + if (_requestData.nonce != 0) revert EBORequestCreator_InvalidNonce(); + _requestData.requester = address(this); + requestData = _requestData; } /// @inheritdoc IEBORequestCreator @@ -33,9 +42,6 @@ contract EBORequestCreator is IEBORequestCreator, Arbitrable { IOracle.Request memory _requestData = requestData; - _requestData.nonce = uint96(0); - _requestData.requester = address(this); - for (uint256 _i; _i < _chainIds.length; _i++) { _encodedChainId = _encodeChainId(_chainIds[_i]); if (!_chainIdsAllowed.contains(_encodedChainId)) revert EBORequestCreator_ChainNotAdded(); diff --git a/src/interfaces/IEBORequestCreator.sol b/src/interfaces/IEBORequestCreator.sol index ffc8792..8778a83 100644 --- a/src/interfaces/IEBORequestCreator.sol +++ b/src/interfaces/IEBORequestCreator.sol @@ -67,6 +67,10 @@ interface IEBORequestCreator { ERRORS //////////////////////////////////////////////////////////////*/ + /** + * @notice Thrown when the nonce is not zero + */ + error EBORequestCreator_InvalidNonce(); /** * @notice Thrown when the chain is already added */ diff --git a/test/integration/IntegrationBase.sol b/test/integration/IntegrationBase.sol index 77416e7..817cca8 100644 --- a/test/integration/IntegrationBase.sol +++ b/test/integration/IntegrationBase.sol @@ -15,6 +15,8 @@ contract IntegrationBase is Test { address internal _owner = makeAddr('owner'); address internal _user = makeAddr('user'); + IOracle.Request _requestData; + IEBORequestCreator internal _eboRequestCreator; IOracle internal _oracle; @@ -24,8 +26,9 @@ contract IntegrationBase is Test { _oracle = new Oracle(); + _requestData.nonce = 0; // TODO: Replace with the implementation - _eboRequestCreator = new EBORequestCreator(_oracle, _arbitrator, _council); + _eboRequestCreator = new EBORequestCreator(_oracle, _arbitrator, _council, _requestData); vm.stopPrank(); } diff --git a/test/unit/EBORequestCreator.t.sol b/test/unit/EBORequestCreator.t.sol index f106824..b400893 100644 --- a/test/unit/EBORequestCreator.t.sol +++ b/test/unit/EBORequestCreator.t.sol @@ -12,7 +12,12 @@ import 'forge-std/console.sol'; contract EBORequestCreatorForTest is EBORequestCreator { using EnumerableSet for EnumerableSet.Bytes32Set; - constructor(IOracle _oracle, address _arbitrator, address _council) EBORequestCreator(_oracle, _arbitrator, _council) {} + constructor( + IOracle _oracle, + address _arbitrator, + address _council, + IOracle.Request memory _requestData + ) EBORequestCreator(_oracle, _arbitrator, _council, _requestData) {} function setChainIdForTest(string calldata _chainId) external returns (bool _added) { _added = _chainIdsAllowed.add(_encodeChainId(_chainId)); @@ -43,12 +48,17 @@ abstract contract EBORequestCreator_Unit_BaseTest is Test { address public arbitrator; address public council; + /// Variables + IOracle.Request requestData; + function setUp() external { council = makeAddr('Council'); arbitrator = makeAddr('Arbitrator'); oracle = IOracle(makeAddr('Oracle')); - eboRequestCreator = new EBORequestCreatorForTest(oracle, arbitrator, council); + requestData.nonce = 0; + + eboRequestCreator = new EBORequestCreatorForTest(oracle, arbitrator, council, requestData); } function _revertIfNotArbitrator() internal { From 47a9a5e998925f60431c6d8c3ec273df70ffc9f2 Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Wed, 14 Aug 2024 02:37:46 -0300 Subject: [PATCH 17/19] feat: constructor --- test/unit/EBORequestCreator.t.sol | 34 +++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/test/unit/EBORequestCreator.t.sol b/test/unit/EBORequestCreator.t.sol index b400893..25f9016 100644 --- a/test/unit/EBORequestCreator.t.sol +++ b/test/unit/EBORequestCreator.t.sol @@ -68,13 +68,43 @@ abstract contract EBORequestCreator_Unit_BaseTest is Test { contract EBORequestCreator_Unit_Constructor is EBORequestCreator_Unit_BaseTest { /** - * @notice Test the constructor + * @notice Test arbitrator set in the constructor */ - function test_constructor() external view { + function test_arbitratorSet() external view { assertEq(eboRequestCreator.arbitrator(), arbitrator); + } + + /** + * @notice Test council set in the constructor + */ + function test_councilSet() external view { assertEq(eboRequestCreator.council(), council); + } + + /** + * @notice Test oracle set in the constructor + */ + function test_oracleSet() external view { assertEq(address(eboRequestCreator.oracle()), address(oracle)); } + + /** + * @notice Test request data set in the constructor + */ + function test_requestDataSet() external view { + assertEq(requestData.nonce, 0); + } + + /** + * @notice Test reverts if nonce is not zero + */ + function test_revertIfNonceIsInvalid(uint96 _nonce, IOracle.Request memory _requestData) external { + vm.assume(_nonce > 0); + + _requestData.nonce = _nonce; + vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_InvalidNonce.selector)); + EBORequestCreator _newEboRequestCreator = new EBORequestCreator(oracle, arbitrator, council, _requestData); + } } contract EBORequestCreator_Unit_CreateRequest is EBORequestCreator_Unit_BaseTest { From 7f207f33221a1ca2da7959eed8df0f8b7f6a05b4 Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Wed, 14 Aug 2024 02:38:06 -0300 Subject: [PATCH 18/19] feat: constructor --- test/unit/EBORequestCreator.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/EBORequestCreator.t.sol b/test/unit/EBORequestCreator.t.sol index 25f9016..ab8a4f1 100644 --- a/test/unit/EBORequestCreator.t.sol +++ b/test/unit/EBORequestCreator.t.sol @@ -103,7 +103,7 @@ contract EBORequestCreator_Unit_Constructor is EBORequestCreator_Unit_BaseTest { _requestData.nonce = _nonce; vm.expectRevert(abi.encodeWithSelector(IEBORequestCreator.EBORequestCreator_InvalidNonce.selector)); - EBORequestCreator _newEboRequestCreator = new EBORequestCreator(oracle, arbitrator, council, _requestData); + new EBORequestCreator(oracle, arbitrator, council, _requestData); } } From cc6190a3d809de641db814f1f6dc63305abc550e Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Thu, 15 Aug 2024 16:12:24 +0200 Subject: [PATCH 19/19] feat: set internal --- src/contracts/EBORequestCreator.sol | 13 +++++++++++-- test/unit/EBORequestCreator.t.sol | 7 +++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/contracts/EBORequestCreator.sol b/src/contracts/EBORequestCreator.sol index 50cd1a8..40895f8 100644 --- a/src/contracts/EBORequestCreator.sol +++ b/src/contracts/EBORequestCreator.sol @@ -36,10 +36,11 @@ contract EBORequestCreator is IEBORequestCreator, Arbitrable { address _council, IOracle.Request memory _requestData ) Arbitrable(_arbitrator, _council) { + if (_requestData.nonce != 0) revert EBORequestCreator_InvalidNonce(); + ORACLE = _oracle; - epochManager = _epochManager; + _setEpochManager(_epochManager); - if (_requestData.nonce != 0) revert EBORequestCreator_InvalidNonce(); _requestData.requester = address(this); requestData = _requestData; @@ -135,6 +136,14 @@ contract EBORequestCreator is IEBORequestCreator, Arbitrable { /// @inheritdoc IEBORequestCreator function setEpochManager(IEpochManager _epochManager) external onlyArbitrator { + _setEpochManager(_epochManager); + } + + /** + * @notice Set the epoch manager + * @param _epochManager The epoch manager + */ + function _setEpochManager(IEpochManager _epochManager) internal { epochManager = _epochManager; emit EpochManagerSet(_epochManager); diff --git a/test/unit/EBORequestCreator.t.sol b/test/unit/EBORequestCreator.t.sol index 76a0b1c..35d31ba 100644 --- a/test/unit/EBORequestCreator.t.sol +++ b/test/unit/EBORequestCreator.t.sol @@ -117,6 +117,13 @@ contract EBORequestCreator_Unit_Constructor is EBORequestCreator_Unit_BaseTest { assertEq(requestData.nonce, 0); } + function test_emitEpochManagerSet() external { + vm.expectEmit(); + emit EpochManagerSet(epochManager); + + new EBORequestCreatorForTest(oracle, epochManager, arbitrator, council, requestData); + } + /** * @notice Test reverts if nonce is not zero */