Time-Capsule Message Contract
What it does:
Allows users to store encrypted messages or data on-chain that can only be accessed or revealed after a predefined unlock time.
Why it matters:
Preserves digital memories, secrets, or instructions securely, ensures immutability, and enables timed disclosure without intermediaries.
How it works:
-
Users submit messages or data hashes with an unlock timestamp
-
Smart contract stores the encrypted message securely on-chain
-
Messages cannot be accessed or modified until the unlock time is reached
-
Once the unlock time arrives, authorized recipients can reveal the message
-
Integrates with NFTs, personal archives, or inheritance systems
-
Dashboards show pending capsules, unlock countdowns, and history
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/access/Ownable.sol";
/**
* @title TimeCapsuleMessage
* @author Nam
* @notice Stores and releases encrypted messages at a future time on-chain
*/
contract TimeCapsuleMessage is Ownable {
struct Capsule {
address creator;
bytes32 messageHash; // hash of the encrypted message
uint256 unlockTime;
bool revealed;
}
mapping(uint256 => Capsule) public capsules;
uint256 public capsuleCount;
mapping(address => bool) public authorizedRecipients;
// -------------------- EVENTS --------------------
event CapsuleCreated(uint256 indexed capsuleId, address creator, uint256 unlockTime);
event CapsuleRevealed(uint256 indexed capsuleId, address recipient);
event RecipientApproved(address recipient);
event RecipientRevoked(address recipient);
// -------------------- RECIPIENT MANAGEMENT --------------------
function approveRecipient(address _recipient) external onlyOwner {
authorizedRecipients[_recipient] = true;
emit RecipientApproved(_recipient);
}
function revokeRecipient(address _recipient) external onlyOwner {
authorizedRecipients[_recipient] = false;
emit RecipientRevoked(_recipient);
}
modifier onlyRecipient() {
require(authorizedRecipients[msg.sender], "Not authorized recipient");
_;
}
// -------------------- CAPSULE MANAGEMENT --------------------
function createCapsule(bytes32 _messageHash, uint256 _unlockTime) external {
require(_unlockTime > block.timestamp, "Unlock time must be in the future");
capsuleCount += 1;
capsules[capsuleCount] = Capsule({
creator: msg.sender,
messageHash: _messageHash,
unlockTime: _unlockTime,
revealed: false
});
emit CapsuleCreated(capsuleCount, msg.sender, _unlockTime);
}
function revealCapsule(uint256 _capsuleId) external onlyRecipient view returns (bytes32) {
Capsule storage c = capsules[_capsuleId];
require(block.timestamp >= c.unlockTime, "Capsule is still locked");
require(!c.revealed, "Capsule already revealed");
// In practice, the recipient would decrypt off-chain using stored messageHash
return c.messageHash;
}
function markAsRevealed(uint256 _capsuleId) external onlyRecipient {
Capsule storage c = capsules[_capsuleId];
require(block.timestamp >= c.unlockTime, "Capsule is still locked");
require(!c.revealed, "Already revealed");
c.revealed = true;
emit CapsuleRevealed(_capsuleId, msg.sender);
}
// -------------------- VIEW FUNCTIONS --------------------
function getCapsule(uint256 _capsuleId) external view returns (Capsule memory) {
return capsules[_capsuleId];
}
}