Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added access control to block clock scheduler #103

Merged
merged 1 commit into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions script/examples/BlockTime.s.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.26;
Expand All @@ -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))
);

_;
}
Expand Down
7 changes: 3 additions & 4 deletions src/interfaces/IBlockTime.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down
17 changes: 11 additions & 6 deletions src/utilities/BlockTime.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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() {
Expand All @@ -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
Expand All @@ -60,5 +66,4 @@ contract BlockTime is IBlockTime, AccessControl, ReentrancyGuard {
function getMaxBlockWidth() public view returns (uint256) {
return maxBlockWidth;
}

}
2 changes: 1 addition & 1 deletion src/utilities/TimeToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ contract TimeToken is ERC20, Ownable {

emit BatchMinted(to, amounts);
}
}
}
64 changes: 36 additions & 28 deletions test/examples/BlockTime/BlockTimeScheduler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}