DreamWeaver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
/**
* @title DreamWeaverGraph
* @notice This contract anchors the off-chain DreamWeaver knowledge graph by storing a cryptographic fingerprint (e.g., an IPFS CID)
* of its current state. It is integrated into the broader DreamWeaver ecosystem—only accounts holding a LucidCore token may update it.
*
* In your ecosystem, this contract serves as a verifiable on-chain record of the evolving DreamWeaver graph.
* This contract is upgradeable using the UUPS pattern.
*/
contract DreamWeaverGraph is
Initializable,
OwnableUpgradeable,
UUPSUpgradeable
{
// The LucidCore token contract is used for token gating. Only accounts holding at least one LucidCore token can update the graph.
IERC721 public lucidCoreToken;
// Structure to store individual dream node metadata
struct DreamNode {
string ipfsHash; // IPFS CID that points to detailed dream data (text, images, 3D assets, etc.)
address creator; // Address that submitted the dream
uint256 timestamp; // Timestamp of submission or update
}
// Mapping to store all dream nodes by their unique ID
mapping(uint256 => DreamNode) public dreamNodes;
uint256 public nodeCount;
// Event declarations
event DreamNodeAdded(uint256 indexed nodeId, string ipfsHash, address indexed creator, uint256 timestamp);
event DreamNodeUpdated(uint256 indexed nodeId, string newIpfsHash, uint256 timestamp);
event GraphStateUpdated(string newStateHash, uint256 timestamp);
// This variable stores a cryptographic fingerprint (e.g., an IPFS hash or Merkle root) of the current off-chain DreamWeaver graph state.
string public graphStateHash;
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
/**
* @notice Initializes the contract, replacing the constructor.
* @param initialOwner The initial owner of the contract
* @param _lucidCoreTokenAddress The address of the deployed LucidCore token contract.
*/
function initialize(address initialOwner, address _lucidCoreTokenAddress) public initializer {
__Ownable_init(initialOwner);
__UUPSUpgradeable_init();
require(_lucidCoreTokenAddress != address(0), "Invalid LucidCore token address");
lucidCoreToken = IERC721(_lucidCoreTokenAddress);
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract.
* Called by {upgradeTo} and {upgradeToAndCall}.
*/
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
/**
* @notice Modifier to restrict access to only those accounts that hold a LucidCore token.
*/
modifier onlyLucidCoreHolder() {
require(lucidCoreToken.balanceOf(msg.sender) > 0, "Must hold a LucidCore token to interact");
_;
}
/**
* @notice Adds a new dream node to the on-chain graph.
* @dev Only callable by the owner (or via a trusted oracle) and only if the caller holds a LucidCore token.
* @param _ipfsHash The IPFS hash (or other fingerprint) of the dream node data.
*/
function addDreamNode(string memory _ipfsHash) external onlyOwner onlyLucidCoreHolder {
nodeCount++;
dreamNodes[nodeCount] = DreamNode(_ipfsHash, msg.sender, block.timestamp);
emit DreamNodeAdded(nodeCount, _ipfsHash, msg.sender, block.timestamp);
}
/**
* @notice Updates an existing dream node's data.
* @dev Only callable by the owner and requires the caller to hold a LucidCore token.
* @param _nodeId The unique ID of the dream node.
* @param _newIpfsHash The new IPFS hash representing the updated dream data.
*/
function updateDreamNode(uint256 _nodeId, string memory _newIpfsHash) external onlyOwner onlyLucidCoreHolder {
require(_nodeId > 0 && _nodeId <= nodeCount, "Node does not exist");
dreamNodes[_nodeId].ipfsHash = _newIpfsHash;
dreamNodes[_nodeId].timestamp = block.timestamp;
emit DreamNodeUpdated(_nodeId, _newIpfsHash, block.timestamp);
}
/**
* @notice Retrieves the details of a specific dream node.
* @param _nodeId The unique ID of the dream node.
* @return The IPFS hash, creator, and timestamp of the node.
*/
function getDreamNode(uint256 _nodeId) external view returns (string memory, address, uint256) {
require(_nodeId > 0 && _nodeId <= nodeCount, "Node does not exist");
DreamNode memory node = dreamNodes[_nodeId];
return (node.ipfsHash, node.creator, node.timestamp);
}
/**
* @notice Updates the on-chain fingerprint of the off-chain DreamWeaver graph.
* @dev This function is intended to be called by an off-chain oracle (via owner privileges) that computes the current graph state,
* uploads it to IPFS (or computes a Merkle root), and then updates the on-chain record.
* @param newHash The new graph state fingerprint.
*/
function updateGraphState(string memory newHash) external onlyOwner {
graphStateHash = newHash;
emit GraphStateUpdated(newHash, block.timestamp);
}
/**
* @notice Returns the current graph state fingerprint.
*/
function getGraphState() external view returns (string memory) {
return graphStateHash;
}
}