Skip to content

Commit

Permalink
Merge pull request #4 from blockful-io/feat#3SessionBadges
Browse files Browse the repository at this point in the history
Feat#3 session badges
  • Loading branch information
LeonardoVieira1630 authored Oct 31, 2024
2 parents 8e727e6 + 848ea79 commit 9c52e94
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 0 deletions.
30 changes: 30 additions & 0 deletions src/interfaces/IResolver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ interface IResolver {
REPLY
}

/// @notice A struct representing a single Session.
struct Session {
address host; // Host of the session
string title; // Title of the session
uint256 startTime; // The time when the session was created (Unix timestamp).
uint256 endTime; // The time when the session was ended (Unix timestamp).
}

/// @notice Checks if the resolver can be sent ETH.
/// @return Whether the resolver supports ETH transfers.
function isPayable() external pure returns (bool);
Expand Down Expand Up @@ -58,8 +66,30 @@ interface IResolver {
/// @param action The action that the role can perform on the schema.
function setSchema(bytes32 uid, uint256 action) external;

/// @notice Creates a new session with a specified duration and title.
/// @param duration The duration of the session in seconds.
/// @param sessionTitle The title of the session.
/// @return sessionId The unique identifier of the created session.
function createSession(
uint256 duration,
string memory sessionTitle
) external returns (bytes32 sessionId);

/// @notice Removes an existing session.
/// @param sessionTitle The title of the session to be removed.
/// @param sessionOwner The address of the owner of the session.
function removeSesison(string memory sessionTitle, address sessionOwner) external;

/// @notice Retrieves session details by session ID.
/// @param sessionTitle The title of the session.
/// @param sessionOwner The address of the owner of the session.
/// @return The session details.
function getSession(
string memory sessionTitle,
address sessionOwner
) external view returns (Session memory);

/// @notice Closes an existing session.
/// @param sessionId The id of the session to be closed.
function closeSession(bytes32 sessionId) external;
}
69 changes: 69 additions & 0 deletions src/resolver/Resolver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ error NotPayable();
error Unauthorized();
error InvalidSession();
error NotHostOfTheSession();
error SessionAlreadyEnded();

/// @author Blockful | 0xneves
/// @notice ZuVillage Resolver contract for Ethereum Attestation Service.
Expand Down Expand Up @@ -52,6 +53,38 @@ contract Resolver is IResolver, AccessControl {
// Define a constant for default SESSION_DURATION (30 days in seconds)
uint256 private constant DEFAULT_SESSION_DURATION = 30 days;

/// @notice Emitted when a new session is created
/// @param sessionId The unique identifier of the session
/// @param host The address of the session host
/// @param title The title of the session
/// @param startTime The timestamp when the session starts
/// @param endTime The timestamp when the session ends
event sessionCreated(
bytes32 indexed sessionId,
address indexed host,
string title,
uint256 startTime,
uint256 endTime
);

/// @notice Emitted when a session is closed
/// @param sessionId The unique identifier of the closed session
/// @param host The address of the session host
/// @param title The title of the closed session
/// @param startTime The timestamp when the session started
/// @param endTime The timestamp when the session ended
event sessionClosed(
bytes32 indexed sessionId,
address indexed host,
string title,
uint256 startTime,
uint256 endTime
);

/// @notice Emitted when a session is removed
/// @param sessionId The unique identifier of the removed session
event sessionRemoved(bytes32 indexed sessionId);

/// @dev Creates a new resolver.
/// @param eas The address of the global EAS contract.
constructor(IEAS eas) {
Expand Down Expand Up @@ -318,6 +351,8 @@ contract Resolver is IResolver, AccessControl {
//Store the session
_session[sessionId] = session;

emit sessionCreated(sessionId, msg.sender, sessionTitle, session.startTime, session.endTime);

//Enable the host and attendee attestation related to the session
string memory hostAttestationTitle = string(abi.encodePacked("Host_", sessionTitle));
_allowedAttestationTitles[keccak256(abi.encode(hostAttestationTitle))] = true;
Expand All @@ -327,6 +362,40 @@ contract Resolver is IResolver, AccessControl {
return sessionId;
}

/// @dev Remove a session.
function removeSesison(
string memory sessionTitle,
address sessionOwner
) external onlyRole(ROOT_ROLE) {
bytes32 sessionId = keccak256(abi.encodePacked(sessionOwner, sessionTitle));
delete _session[sessionId];
emit sessionRemoved(sessionId);
}

/// @dev Get a session.
function getSession(
string memory sessionTitle,
address sessionOwner
) external view returns (Session memory) {
bytes32 sessionId = keccak256(abi.encodePacked(sessionOwner, sessionTitle));
return _session[sessionId];
}

/// @dev Close a session.
function closeSession(bytes32 sessionId) public onlyRole(VILLAGER_ROLE) {
Session storage session = _session[sessionId];

if (session.endTime < block.timestamp) {
revert SessionAlreadyEnded();
}
if ((session.host != msg.sender) && !hasRole(MANAGER_ROLE, msg.sender)) {
revert Unauthorized();
}

session.endTime = block.timestamp;
emit sessionClosed(sessionId, msg.sender, session.title, session.startTime, session.endTime);
}

/// @dev ETH callback.
receive() external payable virtual {
if (!isPayable()) {
Expand Down
44 changes: 44 additions & 0 deletions test/Resolver.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -349,4 +349,48 @@ contract ResolverTest is Test {

vm.stopPrank();
}

function test_remove_session() public {
address villager = roleReceiver;
string memory sessionTitle = "Test Session";
uint256 duration = 1 days;

grantRole(VILLAGER_ROLE, villager);

vm.startPrank(villager);
bytes32 sessionId = resolver.createSession(duration, sessionTitle);
vm.stopPrank();
assert(sessionId != bytes32(0));

vm.startPrank(deployer);
resolver.removeSesison(sessionTitle, villager);
vm.stopPrank();
address host = resolver.getSession(sessionTitle, villager).host;
assert(host == address(0));
}

function test_closeSession() public {
// Setup
address villager = roleReceiver;
string memory sessionTitle = "Test Session";
uint256 duration = 1 days;

grantRole(VILLAGER_ROLE, villager);

// Create a session
vm.startPrank(villager);
bytes32 sessionId = resolver.createSession(duration, sessionTitle);
vm.stopPrank();

// Fast forward time to ensure the session can be closed
vm.warp(block.timestamp + duration - 1);

// Close the session
vm.startPrank(villager);
resolver.closeSession(sessionId);
vm.stopPrank();

Resolver.Session memory session = resolver.getSession(sessionTitle, villager);
assert(session.endTime == block.timestamp);
}
}

0 comments on commit 9c52e94

Please sign in to comment.