CoinThreads
0x815f77e52ad8ecec40629abead29a37b29fa3f9a
Verification
Verified
0.8.24+commit.e11b9ed9
Type
Contract
2,532 bytes
ABI entries
10
4 read · 1 write
License
none
Contract information
- Address
- 0x815f77e52ad8ecec40629abead29a37b29fa3f9a
- Chain
- Robinhood Chain (4663)
- Compiler
- 0.8.24+commit.e11b9ed9
- Optimization
- Enabled
- Creator
- 0xC5b0A8B1f1…8fbD83f12a
- Creation tx
- 0x1e77b9bdda…5f26470569
Token
Not a token
This contract does not expose ERC-20 metadata.
Read contract (4)
MAX_LENGTH() → uint256
count(address) → uint256
factory() → address
getComments(address, uint256, uint256) → tuple[]
Events (1)
CommentPosted
ABI
[
{
"inputs": [
{
"internalType": "address",
"name": "factory_",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "CommentTooLong",
"type": "error"
},
{
"inputs": [],
"name": "EmptyComment",
"type": "error"
},
{
"inputs": [],
"name": "UnknownToken",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "token",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "author",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "index",
"type": "uint256"
},
{
"indexed": false,
"internalType": "string",
"name": "text",
"type": "string"
}
],
"name": "CommentPosted",
"type": "event"
},
{
"inputs": [],
"name": "MAX_LENGTH",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
}
],
"name": "count",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "factory",
"outputs": [
{
"internalType": "contract IPumpFactoryCurves",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "uint256",
"name": "start",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "limit",
"type": "uint256"
}
],
"name": "getComments",
"outputs": [
{
"components": [
{
"internalType": "address",
"name": "author",
"type": "address"
},
{
"internalType": "uint64",
"name": "timestamp",
"type": "uint64"
},
{
"internalType": "string",
"name": "text",
"type": "string"
}
],
"internalType": "struct CoinThreads.Comment[]",
"name": "page",
"type": "tuple[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "string",
"name": "text",
"type": "string"
}
],
"name": "post",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @dev Minimal view of PumpFactory used to check a token actually exists,
/// so threads can't be spammed onto arbitrary addresses. Field order must
/// match PumpFactory.Curve exactly (it's the auto-generated getter).
interface IPumpFactoryCurves {
function curves(address token)
external
view
returns (
bool exists,
bool graduated,
bool migrated,
address creator,
uint256 ethReserve,
uint256 tokensSold
);
}
/// @title CoinThreads
/// @notice On-chain comment threads for launchpad coins, pump.fun style.
/// Deliberately simple: append-only per-token comment arrays with a
/// paginated reader. No backend, no moderation layer; the frontend can
/// filter client-side if needed.
contract CoinThreads {
struct Comment {
address author;
uint64 timestamp;
string text;
}
/// @notice The launchpad whose tokens can be commented on.
IPumpFactoryCurves public immutable factory;
/// @notice Max comment length in bytes (~one tweet).
uint256 public constant MAX_LENGTH = 280;
mapping(address => Comment[]) private _threads;
event CommentPosted(
address indexed token,
address indexed author,
uint256 index,
string text
);
error UnknownToken();
error EmptyComment();
error CommentTooLong();
constructor(address factory_) {
factory = IPumpFactoryCurves(factory_);
}
/// @notice Post a comment on `token`'s thread.
function post(address token, string calldata text) external {
(bool exists, , , , , ) = factory.curves(token);
if (!exists) revert UnknownToken();
uint256 len = bytes(text).length;
if (len == 0) revert EmptyComment();
if (len > MAX_LENGTH) revert CommentTooLong();
_threads[token].push(
Comment({author: msg.sender, timestamp: uint64(block.timestamp), text: text})
);
emit CommentPosted(token, msg.sender, _threads[token].length - 1, text);
}
/// @notice Number of comments on `token`'s thread.
function count(address token) external view returns (uint256) {
return _threads[token].length;
}
/// @notice Paginated read: comments [start, start+limit) in post order.
function getComments(address token, uint256 start, uint256 limit)
external
view
returns (Comment[] memory page)
{
Comment[] storage all = _threads[token];
uint256 len = all.length;
if (start >= len) return new Comment[](0);
uint256 end = start + limit;
if (end > len) end = len;
page = new Comment[](end - start);
for (uint256 i = start; i < end; i++) {
page[i - start] = all[i];
}
}
}
Chain explorer6651msChain node87ms