diff --git a/script/examples/BlockTime.s.sol b/script/examples/BlockTime.s.sol index b505ad4..d06a968 100644 --- a/script/examples/BlockTime.s.sol +++ b/script/examples/BlockTime.s.sol @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.26; @@ -21,10 +20,10 @@ contract DeployBlockTime is Script, BaseDeployer { modifier computeCreate2(bytes32 salt) { _callBreaker = vm.envAddress("CALL_BREAKER_ADDRESS"); - _blockTime = - computeCreate2Address(salt, hashInitCode(type(BlockTime).creationCode, abi.encode())); - _blockTimeScheduler = - computeCreate2Address(salt, hashInitCode(type(BlockTimeScheduler).creationCode, abi.encode(_callBreaker, _blockTime))); + _blockTime = computeCreate2Address(salt, hashInitCode(type(BlockTime).creationCode, abi.encode())); + _blockTimeScheduler = computeCreate2Address( + salt, hashInitCode(type(BlockTimeScheduler).creationCode, abi.encode(_callBreaker, _blockTime)) + ); _; } diff --git a/src/interfaces/IBlockTime.sol b/src/interfaces/IBlockTime.sol index 380d1d9..a50af4b 100644 --- a/src/interfaces/IBlockTime.sol +++ b/src/interfaces/IBlockTime.sol @@ -5,7 +5,6 @@ import "openzeppelin-contracts/contracts/access/IAccessControl.sol"; import "openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; interface IBlockTime { - struct Chronicle { uint256 epoch; address timeKeeper; @@ -18,9 +17,9 @@ interface IBlockTime { /// @param receivers List of addresses that will receive TimeToken rewards /// @param amounts List of amounts of TimeToken to be minted for each receiver function moveTime( - Chronicle[] calldata chronicles, - uint256 meanCurrentEarthTime, - address[] calldata receivers, + Chronicle[] calldata chronicles, + uint256 meanCurrentEarthTime, + address[] calldata receivers, uint256[] calldata amounts ) external; diff --git a/src/utilities/BlockTime.sol b/src/utilities/BlockTime.sol index b6b73ca..70f7eee 100644 --- a/src/utilities/BlockTime.sol +++ b/src/utilities/BlockTime.sol @@ -8,7 +8,6 @@ import "src/interfaces/IBlockTime.sol"; contract BlockTime is IBlockTime, AccessControl, ReentrancyGuard { bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); - bytes32 public constant TIME_KEEPER = keccak256("TIME_KEEPER"); bytes32 public constant SCHEDULER_ROLE = keccak256("SCHEDULER_ROLE"); /// @dev minimum number of signed time values needed @@ -26,10 +25,12 @@ contract BlockTime is IBlockTime, AccessControl, ReentrancyGuard { uint256 public currentEarthTimeAvg; /// @notice The ERC20 timeToken that will be transferred to users on successfull time updation - TimeToken public timeToken; + TimeToken public timeToken; event Tick(uint256 currentEarthTimeBlockStart, uint256 currentEarthTimeBlockEnd); - event EarthTimeUpdated(uint256 newEarthTime, Chronicle[] chronicles, address[] timeTokenReceivers, uint256[] amounts); + event BlockTimeUpdated( + uint256 newEarthTime, Chronicle[] chronicles, address[] timeTokenReceivers, uint256[] amounts + ); event MaxBlockWidthSet(uint256 maxBlockWidth); constructor() { @@ -39,10 +40,15 @@ contract BlockTime is IBlockTime, AccessControl, ReentrancyGuard { } /// @notice changes earth avg time - function moveTime(Chronicle[] calldata chronicles, uint256 meanCurrentEarthTime, address[] calldata receivers, uint256[] calldata amounts) external onlyRole(SCHEDULER_ROLE) nonReentrant { + function moveTime( + Chronicle[] calldata chronicles, + uint256 meanCurrentEarthTime, + address[] calldata receivers, + uint256[] calldata amounts + ) external onlyRole(SCHEDULER_ROLE) nonReentrant { currentEarthTimeAvg = meanCurrentEarthTime; timeToken.batchMint(receivers, amounts); - emit EarthTimeUpdated(meanCurrentEarthTime, chronicles, receivers, amounts); + emit BlockTimeUpdated(meanCurrentEarthTime, chronicles, receivers, amounts); } /// @notice returns current block time @@ -60,5 +66,4 @@ contract BlockTime is IBlockTime, AccessControl, ReentrancyGuard { function getMaxBlockWidth() public view returns (uint256) { return maxBlockWidth; } - } diff --git a/src/utilities/TimeToken.sol b/src/utilities/TimeToken.sol index 34bf0aa..c37ee64 100644 --- a/src/utilities/TimeToken.sol +++ b/src/utilities/TimeToken.sol @@ -26,4 +26,4 @@ contract TimeToken is ERC20, Ownable { emit BatchMinted(to, amounts); } -} \ No newline at end of file +} diff --git a/test/examples/BlockTime/BlockTimeScheduler.sol b/test/examples/BlockTime/BlockTimeScheduler.sol index 301d46a..5a4df29 100644 --- a/test/examples/BlockTime/BlockTimeScheduler.sol +++ b/test/examples/BlockTime/BlockTimeScheduler.sol @@ -4,56 +4,64 @@ pragma solidity 0.8.26; import "src/interfaces/IBlockTime.sol"; import "src/timetravel/CallBreaker.sol"; import "src/timetravel/SmarterContract.sol"; -import "openzeppelin-contracts/contracts/access/Ownable.sol"; +import "openzeppelin-contracts/contracts/access/AccessControl.sol"; import "openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol"; /** * @notice This is an POC example of a block scheduler */ -contract BlockTimeScheduler is SmarterContract, Ownable { +contract BlockTimeScheduler is SmarterContract, AccessControl { + bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); + bytes32 public constant TIME_SOLVER = keccak256("TIME_SOLVER"); - struct BlockTimeData { - IBlockTime.Chronicle[] chronicles; - uint256 meanCurrentErathTime; - BatchMintData mintTokensData; - } + // TODO: To be used to reduce repeated external call to CallBreaker + // struct BlockTimeData { + // IBlockTime.Chronicle[] chronicles; + // uint256 meanCurrentEarthTime; + // BatchMintData mintTokensData; + // } - struct BatchMintData { - address[] receiver; - uint256[] amounts; - } + // struct BatchMintData { + // address[] receiver; + // uint256[] amounts; + // } bool public shouldContinue; address public callBreaker; IBlockTime public blockTime; - constructor(address _callBreaker, address _blockTime) SmarterContract(_callBreaker) Ownable(msg.sender) { + constructor(address _callBreaker, address _blockTime) SmarterContract(_callBreaker) { callBreaker = _callBreaker; blockTime = IBlockTime(_blockTime); shouldContinue = true; + + _grantRole(DEFAULT_ADMIN_ROLE, _msgSender()); + _grantRole(ADMIN_ROLE, _msgSender()); } /// @dev The onlyOwner modifier will be later changed to execute calls through a governance proposal - function updateTime() external onlyOwner { - bytes32 key = keccak256(abi.encodePacked("MoveTimeData")); - bytes memory data = CallBreaker(payable(callBreaker)).fetchFromAssociatedDataStore(key); - - BlockTimeData memory moveTimeData = abi.decode(data, (BlockTimeData)); - blockTime.moveTime(moveTimeData.chronicles, moveTimeData.meanCurrentErathTime, moveTimeData.mintTokensData.receiver, moveTimeData.mintTokensData.amounts); - - CallObject memory callObj = CallObject({ - amount: 0, - addr: address(this), - gas: 1000000, - callvalue: abi.encodeWithSignature("verifySignature(bytes)", data) - }); + function updateTime() external onlyRole(TIME_SOLVER) { + bytes memory chroniclesData = + CallBreaker(payable(callBreaker)).fetchFromAssociatedDataStore(keccak256(abi.encodePacked("Chronicles"))); + bytes memory meanTimeData = CallBreaker(payable(callBreaker)).fetchFromAssociatedDataStore( + keccak256(abi.encodePacked("CurrentMeanTime")) + ); + bytes memory recievers = + CallBreaker(payable(callBreaker)).fetchFromAssociatedDataStore(keccak256(abi.encodePacked("Recievers"))); + bytes memory amounts = + CallBreaker(payable(callBreaker)).fetchFromAssociatedDataStore(keccak256(abi.encodePacked("Amounts"))); - assertFutureCallTo(callObj, 1); + blockTime.moveTime( + abi.decode(chroniclesData, (IBlockTime.Chronicle[])), + abi.decode(meanTimeData, (uint256)), + abi.decode(recievers, (address[])), + abi.decode(amounts, (uint256[])) + ); } /// @notice function to be checked by Laminator before rescheduling a call to disburseKITNs /// @dev The onlyOwner modifier will be later changed to execute calls through a governance proposal - function setContinue(bool _shouldContinue) external onlyOwner { + function setContinue(bool _shouldContinue) external onlyRole(ADMIN_ROLE) { shouldContinue = _shouldContinue; } -} \ No newline at end of file +}