Membership Pass
A time-limited membership pass. The owner issues passes that expire, and expiry extends rather than resets when renewed early.
MembershipPass.sol
// SPDX-License-Identifier: MITpragma solidity ^0.8.20; contract MembershipPass { string public name; string public symbol; address public owner; uint256 public durationSeconds; mapping(address => uint256) public expiresAt; event PassIssued(address indexed holder, uint256 expiresAt); event PassRevoked(address indexed holder); event OwnerChanged(address indexed newOwner); constructor(string memory name_, string memory symbol_, uint256 durationSeconds_, address initialOwner_) { require(initialOwner_ != address(0), "ZERO_OWNER"); require(durationSeconds_ > 0, "ZERO_DURATION"); name = name_; symbol = symbol_; durationSeconds = durationSeconds_; owner = initialOwner_; } modifier onlyOwner() { require(msg.sender == owner, "NOT_OWNER"); _; } function issue(address holder) external onlyOwner returns (uint256) { require(holder != address(0), "ZERO_HOLDER"); uint256 base = expiresAt[holder] > block.timestamp ? expiresAt[holder] : block.timestamp; uint256 newExpiry = base + durationSeconds; expiresAt[holder] = newExpiry; emit PassIssued(holder, newExpiry); return newExpiry; } function revoke(address holder) external onlyOwner { expiresAt[holder] = 0; emit PassRevoked(holder); } function isValid(address holder) external view returns (bool) { return expiresAt[holder] > block.timestamp; } function transferOwnership(address newOwner) external onlyOwner { require(newOwner != address(0), "ZERO_OWNER"); owner = newOwner; emit OwnerChanged(newOwner); }}