Co-Working Space Access Token Contract

// Co-Working Space Access Token Contract : Built By DAO V 0.01.0
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract CoWorkingSpaceAccessToken is ERC721URIStorage, AccessControl, ReentrancyGuard {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIdCounter;

    bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
    bytes32 public constant SPACE_MANAGER_ROLE = keccak256("SPACE_MANAGER_ROLE");
    bytes32 public constant UMBRELLA_CONTRACT_ROLE = keccak256("UMBRELLA_CONTRACT_ROLE");

    // Metadata for co-working space access
    struct SpaceAccessDetails {
        uint256 expirationTimestamp; // Expiration time for the token (daily, weekly, monthly use)
        bool isRenewable; // Whether the token can be renewed for continued access
    }

    // Mapping from token ID to co-working space access details
    mapping(uint256 => SpaceAccessDetails) public spaceAccessDetails;

    // Events
    event CoWorkingAccessTokenMinted(address indexed to, uint256 tokenId, bool isRenewable, uint256 expiration);
    event CoWorkingAccessTokenBurned(uint256 tokenId);

    // Instead of a constructor, using an initialize function to allow deployment by the umbrella contract
    /**
     * @dev Initialize the Co-Working Space Access Token Contract.
     * @param name The name of the token (e.g., "DAO CoWorking Space Token").
     * @param symbol The symbol of the token (e.g., "DCS").
     * @param umbrellaContract The address of the umbrella contract deploying this instance.
     * Note: Ensure these variables are set properly during deployment for specific needs.
     */
    function initialize(string memory name, string memory symbol, address umbrellaContract) external {
        require(hasRole(UMBRELLA_CONTRACT_ROLE, _msgSender()), "Caller is not the umbrella contract");
        _setupRole(DEFAULT_ADMIN_ROLE, umbrellaContract);
        _setupRole(ADMIN_ROLE, umbrellaContract);
        _setupRole(SPACE_MANAGER_ROLE, umbrellaContract);
        _tokenIdCounter.increment(); // Start token IDs at 1

        // Setting up ERC721 name and symbol
        _name = name;
        _symbol = symbol;
    }

    /**
     * @dev Mint a new Co-Working Space Access Token.
     * Only an address with the SPACE_MANAGER_ROLE can mint new tokens.
     * @param to The address that will receive the minted token.
     * @param isRenewable Indicates whether the token can be renewed for future access.
     * @param duration The duration in seconds for which the token is valid (e.g., daily, weekly, or monthly).
     * Note: Ensure to adjust "duration" based on the user's access needs when deploying.
     */
    function mintSpaceAccessToken(address to, bool isRenewable, uint256 duration) external onlyRole(SPACE_MANAGER_ROLE) nonReentrant {
        // Verify that the contract was approved by the umbrella contract before minting
        require(hasRole(UMBRELLA_CONTRACT_ROLE, _msgSender()), "Contract must be approved by umbrella contract");

        uint256 tokenId = _tokenIdCounter.current();
        _safeMint(to, tokenId);

        // Set URI for metadata (to be replaced with actual URI)
        _setTokenURI(tokenId, "https://metadata.uri/for/CoWorkingAccessToken"); // TODO: Replace with actual metadata URI for the specific co-working space

        // Set co-working space access details
        uint256 expirationTimestamp = block.timestamp + duration;
        spaceAccessDetails[tokenId] = SpaceAccessDetails({
            expirationTimestamp: expirationTimestamp,
            isRenewable: isRenewable
        });

        _tokenIdCounter.increment();
        emit CoWorkingAccessTokenMinted(to, tokenId, isRenewable, expirationTimestamp);
    }

    /**
     * @dev Burn a Co-Working Space Access Token.
     * Only the token owner or an admin can burn the token.
     * @param tokenId The ID of the token to be burned.
     * Note: Ensure token holders are aware of the conditions under which tokens may be burned.
     */
    function burnSpaceAccessToken(uint256 tokenId) external nonReentrant {
        require(_isApprovedOrOwner(_msgSender(), tokenId) || hasRole(ADMIN_ROLE, _msgSender()), "Unauthorized to burn");
        _burn(tokenId);
        delete spaceAccessDetails[tokenId];
        emit CoWorkingAccessTokenBurned(tokenId);
    }

    /**
     * @dev Check if a token is still valid.
     * Tokens expire based on their duration (e.g., daily, weekly, or monthly).
     * @param tokenId The ID of the token to check.
     * @return True if the token is still valid, false otherwise.
     * Note: Useful for determining co-working space entry eligibility.
     */
    function isTokenValid(uint256 tokenId) external view returns (bool) {
        require(_exists(tokenId), "Token does not exist");
        return block.timestamp <= spaceAccessDetails[tokenId].expirationTimestamp;
    }

    /**
     * @dev Override transfer function to prevent transfers of co-working space access tokens.
     * Co-working access tokens are non-transferable.
     * @param from Address from which token is being transferred.
     * @param to Address to which token is being transferred.
     * @param tokenId ID of the token being transferred.
     * Note: Space tokens are non-transferable to maintain strict access control.
     */
    function _transfer(address from, address to, uint256 tokenId) internal pure override {
        revert("Co-Working Access Tokens are non-transferable");
    }
}

/*
 Key Features:
 - **Co-Working Space Access Token Contract**: Manages tokens for access to DAO-managed co-working spaces.
 - **Umbrella Contract Integration**: This contract is intended to be deployed and initialized by the **Umbrella Access Token Contract**.
 - **Role-Based Access Control**: Uses role-based control with ADMIN_ROLE, SPACE_MANAGER_ROLE, and UMBRELLA_CONTRACT_ROLE to manage minting, burning, and overall contract administration.
 - **Minting and Burning Mechanisms**: Only space managers can mint tokens, while only the token owner or admins can burn them.
 - **Renewable vs. Non-Renewable**: Tokens can be issued as either **renewable** or **non-renewable** based on user needs for co-working access.
 - **Non-Transferable**: Co-working space access tokens cannot be transferred between users, maintaining strict control over access.
 - **Validity Checks**: Includes functionality to determine if a token is still valid based on its expiration.
 - **Security Features**: Implements ReentrancyGuard to prevent reentrancy attacks, adding another layer of security to mint and burn processes.
 - **Deployment Considerations**: The following variables should be set during deployment:
   - **name** and **symbol** during `initialize()` for token identification.
   - **duration** parameter in `mintSpaceAccessToken()` to match the user's access duration needs.
   - **metadata URI** in `_setTokenURI()` to provide accurate details for the co-working space access.
*/

Last updated

Logo

© Built By DAO Holdings LLC