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"
]
}
}
}
}}
Submitted on: 2025-10-27 20:58:11
Comments
Log in to comment.
No comments yet.