GlyfocGuestbook

Description:

Multi-signature wallet contract requiring multiple confirmations for transaction execution.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "contracts/GlyfocGuestbook.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/**
 * GlyfocGuestbook (open)
 * - No token gating; anyone can post.
 * - Cooldown (default 60s) + optional fee (postFeeWei).
 * - Single flexible post() with optional fields + extra payload for future features (e.g., CTA_MINT).
 * - One canonical event PostedV1.
 * - messageHash anchors integrity over full payload + "v1".
 */
interface IERC721Like { function ownerOf(uint256 tokenId) external view returns (address); }

abstract contract Ownable {
  address public owner;
  error NotOwner();
  event OwnershipTransferred(address indexed prev, address indexed next);
  constructor() { owner = msg.sender; emit OwnershipTransferred(address(0), msg.sender); }
  modifier onlyOwner(){ if (msg.sender != owner) revert NotOwner(); _; }
  function transferOwnership(address next) external onlyOwner {
    require(next != address(0), "zero");
    emit OwnershipTransferred(owner, next);
    owner = next;
  }
}

contract GlyfocGuestbook is Ownable {
  /* ---------- Errors ---------- */
  error Cooldown();
  error FeeTooLow();
  error InvalidLink();   // optional: empty or absurdly long

  /* ---------- Event ---------- */
  event PostedV1(
    uint256 indexed id,
    address indexed author,
    string  message,
    string  url,              // "" if none
    address refCollection,    // address(0) if none
    uint256 refTokenId,       // 0 if none
    bytes   extra,            // empty if none
    uint256 timestamp
  );

  /* ---------- State ---------- */
  uint256 public cooldownSeconds = 60; // default 60s
  uint256 public postFeeWei = 0;       // 0 = free
  uint256 public messageCount;
  mapping(address => uint256) public lastPostAt;
  mapping(uint256 => bytes32) public messageHash; // id => keccak256(full payload)

  /* ---------- Admin ---------- */
  function setCooldown(uint256 secs) external onlyOwner { cooldownSeconds = secs; }
  function setPostFeeWei(uint256 weiAmount) external onlyOwner { postFeeWei = weiAmount; }
  function withdraw(address payable to) external onlyOwner { to.transfer(address(this).balance); }

  /* ---------- Post ---------- */
  /**
   * @param message        Required text
   * @param url            Optional link ("" if none)
   * @param refCollection  Optional collection address (0x0 if none)
   * @param refTokenId     Optional token id (0 if none)
   * @param extra          Optional ABI-encoded payload for future features
   *
   * Example extra encodings (front-end):
   * - CTA mint:  abi.encode(bytes32("CTA_MINT"), refCollection)
   * - Reply:     abi.encode(bytes32("REPLY"), parentId)
   */
  function post(
    string calldata message,
    string calldata url,
    address refCollection,
    uint256 refTokenId,
    bytes calldata extra
  ) external payable {
    // Fee
    if (postFeeWei > 0 && msg.value < postFeeWei) revert FeeTooLow();

    // Cooldown
    uint256 last = lastPostAt[msg.sender];
    if (cooldownSeconds > 0 && last + cooldownSeconds > block.timestamp) revert Cooldown();
    lastPostAt[msg.sender] = block.timestamp;

    // (Optional) simple link sanity to prevent griefing with huge strings
    if (bytes(url).length > 0 && bytes(url).length > 2048) revert InvalidLink();

    // (Optional) lightweight existence check when user attaches a token
    if (refCollection != address(0) && refTokenId > 0) {
      // best-effort: if ownerOf reverts, we still allow posting but you can enforce revert by uncommenting:
      try IERC721Like(refCollection).ownerOf(refTokenId) returns (address) {
        // ok
      } catch {
        // do nothing (open guestbook). To enforce: revert InvalidLink();
      }
    }

    // Record & emit
    uint256 id = ++messageCount;
    bytes32 h = keccak256(
      abi.encodePacked(
        msg.sender,
        message,
        url,
        refCollection,
        refTokenId,
        extra,
        block.timestamp,
        "v1"
      )
    );
    messageHash[id] = h;

    emit PostedV1(id, msg.sender, message, url, refCollection, refTokenId, extra, block.timestamp);
  }
}
"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "viaIR": true,
    "evmVersion": "paris",
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    }
  }
}}

Tags:
Multisig, Multi-Signature, Factory|addr:0x77d79320181c7e80e98808f86cee65818f516e50|verified:true|block:23670680|tx:0x5ddee96fe17fb1c0952db473e06ed5edde170d6f2afab9749e709e4cc29b48ff|first_check:1761594698

Submitted on: 2025-10-27 20:51:38

Comments

Log in to comment.

No comments yet.