-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Pano Skylakis
committed
Jun 12, 2024
1 parent
1ddb3dd
commit 2ab98e2
Showing
3 changed files
with
157 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// Copyright (c) Immutable Pty Ltd 2018 - 2024 | ||
// SPDX-License-Identifier: Apache 2 | ||
// solhint-disable not-rely-on-time | ||
|
||
pragma solidity ^0.8.19; | ||
|
||
import {AccessControlEnumerable} from "@openzeppelin/contracts/access/AccessControlEnumerable.sol"; | ||
import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol"; | ||
|
||
error Unauthorized(); | ||
error ContractPaused(); | ||
|
||
/** | ||
* @title SessionActivity - A simple contract that emits an event for the purpose of recording session activity on-chain | ||
* @author Immutable | ||
* @dev The SessionActivity contract is not designed to be upgradeable or extended. | ||
*/ | ||
contract SessionActivity is AccessControlEnumerable, Pausable { | ||
/// @notice Indicates that session activity has been recorded for an account | ||
event SessionActivityRecorded(address indexed account, uint256 timestamp); | ||
|
||
/// @notice The name of the contract | ||
string public name; | ||
|
||
/// @notice Role to allow pausing the contract | ||
bytes32 private constant _PAUSE = keccak256("PAUSE"); | ||
|
||
/// @notice Role to allow unpausing the contract | ||
bytes32 private constant _UNPAUSE = keccak256("UNPAUSE"); | ||
|
||
/** | ||
* @notice Sets the DEFAULT_ADMIN, PAUSE and UNPAUSE roles | ||
* @param _admin The address for the admin role | ||
* @param _pauser The address for the pauser role | ||
* @param _unpauser The address for the unpauser role | ||
*/ | ||
constructor(address _admin, address _pauser, address _unpauser, string memory _name) { | ||
_grantRole(DEFAULT_ADMIN_ROLE, _admin); | ||
_grantRole(_PAUSE, _pauser); | ||
_grantRole(_UNPAUSE, _unpauser); | ||
name = _name; | ||
} | ||
|
||
/** | ||
* @notice Pauses the contract | ||
*/ | ||
function pause() external { | ||
if (!hasRole(_PAUSE, msg.sender)) revert Unauthorized(); | ||
_pause(); | ||
} | ||
|
||
/** | ||
* @notice Unpauses the contract | ||
*/ | ||
function unpause() external { | ||
if (!hasRole(_UNPAUSE, msg.sender)) revert Unauthorized(); | ||
_unpause(); | ||
} | ||
|
||
/** | ||
* @notice Function that emits a `SessionActivityRecorded` event | ||
*/ | ||
function recordSessionActivity() external { | ||
if (paused()) revert ContractPaused(); | ||
emit SessionActivityRecorded(msg.sender, block.timestamp); | ||
} | ||
} |
90 changes: 90 additions & 0 deletions
90
contracts/games/session-activity/SessionActivityDeployer.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// Copyright (c) Immutable Pty Ltd 2018 - 2024 | ||
// SPDX-License-Identifier: Apache 2 | ||
// solhint-disable not-rely-on-time | ||
|
||
pragma solidity ^0.8.19; | ||
|
||
import {AccessControlEnumerable} from "@openzeppelin/contracts/access/AccessControlEnumerable.sol"; | ||
import {SessionActivity} from "./SessionActivity.sol"; | ||
|
||
error Unauthorized(); | ||
error NameAlreadyRegistered(); | ||
|
||
/** | ||
* @title SessionActivityDeployer - A factory contract that deploys SessionActivity contracts and tracks their addresses and names | ||
* @author Immutable | ||
* @dev The SessionActivityDeployer contract is not designed to be upgradeable or extended. | ||
*/ | ||
contract SessionActivityDeployer is AccessControlEnumerable { | ||
/// @notice Indicates that an account has registered session activity | ||
event SessionActivityDeployed(address indexed account, string indexed name); | ||
|
||
/// @notice Mapping of deployed SessionActivity contract addresses to their names | ||
/// @dev To get a list of all deployed contract names, iterate over the deployedContracts array and use this mapping | ||
mapping(address deployedContract => string name) public sessionActivityNames; | ||
|
||
/// @notice Mapping of SessionActivity contract names to their addresses | ||
/// @dev To get a list of all deployed contract addresses, iterate over the names array and use this mapping | ||
mapping(string name => address deployedContract) public sessionActivityContracts; | ||
|
||
/// @notice Array of deployed SessionActivity contracts | ||
address[] public deployedContracts; | ||
|
||
/// @notice Array of deployed SessionActivity contract names | ||
string[] public names; | ||
|
||
/// @notice Role to allow deploying SessionActivity contracts | ||
bytes32 private constant _DEPLOYER_ROLE = keccak256("DEPLOYER"); | ||
|
||
/// @notice The address for the pauser role on the SessionActivity contract | ||
address private _pauser; | ||
|
||
/// @notice The address for the unpauser role on the SessionActivity contract | ||
address private _unpauser; | ||
|
||
/** | ||
* @notice Sets the DEFAULT_ADMIN, PAUSE and UNPAUSE roles | ||
* @param admin The address for the admin role | ||
* @param deployer The address for the deployer role | ||
* @param pauser The address for the pauser role on the SessionActivity contract | ||
* @param unpauser The address for the unpauser role on the SessionActivity contract | ||
*/ | ||
constructor(address admin, address deployer, address pauser, address unpauser) { | ||
_grantRole(DEFAULT_ADMIN_ROLE, admin); | ||
_grantRole(_DEPLOYER_ROLE, deployer); | ||
_pauser = pauser; | ||
_unpauser = unpauser; | ||
} | ||
|
||
/** | ||
* @notice Deploys a new SessionActivity contract | ||
* @param name The name of the SessionActivity contract | ||
* @dev Only accounts granted the _DEPLOYER_ROLE can call this function | ||
*/ | ||
function deploy(string memory name) public { | ||
// Ensure the caller has the deployer role | ||
if (!hasRole(_DEPLOYER_ROLE, msg.sender)) revert Unauthorized(); | ||
|
||
// Loop through names and ensure the provided name is unique | ||
for (uint256 i = 0; i < names.length; i++) { | ||
if (keccak256(abi.encodePacked(names[i])) == keccak256(abi.encodePacked(name))) { | ||
revert NameAlreadyRegistered(); | ||
} | ||
} | ||
|
||
// Get the existing admin role | ||
address admin = getRoleMember(DEFAULT_ADMIN_ROLE, 0); | ||
|
||
// Deploy the session activity contract | ||
SessionActivity sessionActivityContract = new SessionActivity(admin, _pauser, _unpauser, name); | ||
|
||
// Register the contract address and name | ||
sessionActivityNames[address(sessionActivityContract)] = name; | ||
deployedContracts.push(address(sessionActivityContract)); | ||
|
||
sessionActivityContracts[name] = address(sessionActivityContract); | ||
names.push(name); | ||
|
||
emit SessionActivityDeployed(msg.sender, name); | ||
} | ||
} |