HomeEIPs
EIPsERC-3722
ERC-3722

Poster

A ridiculously simple general purpose social media smart contract.
StagnantStandards Track: ERC
Created: 2021-07-31
Auryn Macmillan (@auryn-macmillan)
DiscussionsOriginal linkEdit
1 min read

ERC-3722: Poster is a proposed Ethereum Improvement Proposal (EIP) for a simple social media smart contract that allows users to make posts and tag them with keywords. The contract takes two strings as parameters (content and tag) and emits those strings, along with the address of the user who made the post, as an event. The EIP also includes a proposed standard JSON format for a Twitter-like application, where each post() call can include multiple posts and/or operations. The assumption is that application state will be constructed off-chain via some indexer. The motivation behind Poster is to provide a base layer for decentralized social media that can be deployed to the same address on any EVM compatible network. Any Ethereum account can make posts to the deployment of Poster on its local network. The specification includes the contract code, ABI, and event details. The EIP is still in draft form and has not yet been accepted as an official Ethereum standard.

Videos

PEEPanEIP#53: EIP-3722: Poster with Auryn Macmillan

Original

Poster

Abstract

A ridiculously simple general purpose social media smart contract. It takes two strings (content and tag) as parameters and emits those strings, along with msg.sender, as an event. That's it. The EIP also includes a proposed standard json format for a Twitter-like application, where each post() call can include multiple posts and/or operations. The assumption being that application state will be constructed off-chain via some indexer.

Motivation

Poster is intended to be used as a base layer for decentralized social media. It can be deployed to the same address (via the singleton factory) on just about any EVM compatible network. Any Ethereum account can make posts to the deployment of Poster on its local network.

Specification

Contract

contract Poster { event NewPost(address indexed user, string content, string indexed tag); function post(string calldata content, string calldata tag) public { emit NewPost(msg.sender, content, tag); } }

ABI

[ { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "user", "type": "address" }, { "indexed": false, "internalType": "string", "name": "content", "type": "string" }, { "indexed": true, "internalType": "string", "name": "tag", "type": "string" } ], "name": "NewPost", "type": "event" }, { "inputs": [ { "internalType": "string", "name": "content", "type": "string" }, { "internalType": "string", "name": "tag", "type": "string" } ], "name": "post", "outputs": [], "stateMutability": "nonpayable", "type": "function" } ]

Standard json format for Twitter-like posts

{ "content": [ { "type": "microblog", "text": "this is the first post in a thread" }, { "type": "microblog", "text": "this is the second post in a thread", "replyTo": "this[0]" }, { "type": "microblog", "text": "this is a reply to some other post", "replyTo": "some_post_id" }, { "type": "microblog", "text": "this is a post with an image", "image": "ipfs://ipfs_hash" }, { "type": "microblog", "text": "this post replaces a previously posted post", "edit": "some_post_id" }, { "type": "delete", "target": "some_post_id" }, { "type": "like", "target": "some_post_id" }, { "type": "repost", "target": "some_post_id" }, { "type": "follow", "target": "some_account" }, { "type": "unfollow", "target": "some_account" }, { "type": "block", "target": "some_account" }, { "type": "report", "target": "some_account or some_post_id" }, { "type": "permissions", "account": "<account_to_set_permissions>", "permissions": { "post": true, "delete": true, "like": true, "follow": true, "block": true, "report": true, "permissions": true } }, { "type": "microblog", "text": "This is a post from an account with permissions to post on behalf of another account.", "from": "<from_address>" } ] }

Rationale

There was some discussion around whether or not an post ID should also be emitted, whether the content should be a string or bytes, and whether or not anything at all should actually be emitted.

We decided not to emit an ID, since it meant adding state or complexity to the contract and there is a fairly common pattern of assigning IDs on the indexer layer based on transactionHash + logIndex.

We decided to emit a string, rather than bytes, simply because that would make content human readable on many existing interfaces, like Etherscan for example. This did, unfortunately, eliminate some of the benefit that we might have gotten from a more compact encoding scheme like CBOR, rather than JSON. But this also would not have satisfied the human readable criteria.

While there would have been some gas savings if we decided against emitting anything at all, it would have redically increased the node requirements to index posts. As such, we decided it was worth the extra gas to actually emit the content.

Reference Implementation

Poster has been deployed at 0x000000000000cd17345801aa8147b8D3950260FF on multiple networks using the Singleton Factory. If it is not yet deployed on your chosen network, you can use the Singleton Factory to deploy an instance of Poster at the same address on just about any EVM compatible network using these parameters:

initCode: 0x608060405234801561001057600080fd5b506101f6806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80630ae1b13d14610030575b600080fd5b61004361003e3660046100fa565b610045565b005b8181604051610055929190610163565b60405180910390203373ffffffffffffffffffffffffffffffffffffffff167f6c7f3182d7e4cb876251f9ae1489975fdbbf15d9f35d393f2ac9b1ff57cec69f86866040516100a5929190610173565b60405180910390a350505050565b60008083601f8401126100c4578182fd5b50813567ffffffffffffffff8111156100db578182fd5b6020830191508360208285010111156100f357600080fd5b9250929050565b6000806000806040858703121561010f578384fd5b843567ffffffffffffffff80821115610126578586fd5b610132888389016100b3565b9096509450602087013591508082111561014a578384fd5b50610157878288016100b3565b95989497509550505050565b6000828483379101908152919050565b60006020825282602083015282846040840137818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016010191905056fea2646970667358221220ee0377bd266748c5dbaf0a3f15ebd97be153932f2d14d460d9dd4271fee541b564736f6c63430008000033

salt: 0x9245db59943806d06245bc7847b3efb2c899d11b621a0f01bb02fd730e33aed2

When verifying on the source code on a block explorer, make sure to set the optimizer to yes and the runs to 10000000.

The source code is available in the Poster contract repo.

Security Considerations

Given the ridiculously simple implementation of Poster, there does not appear to be any real security concerns at the contract level.

At the application level, clients should confirm that posts including a "from" field that differs from msg.sender have been authorized by the "from" address via a "permissions" post, otherwise they should be considerred invalid or a post from msg.sender.

Clients should also be sure to sanitize post data.

Copyright and related rights waived via CC0.

Further reading
Anyone may contribute to propose contents.
Go propose
Adopted by projects
Anyone may contribute to propose contents.
Go propose

Not miss a beat of EIPs' update?

Subscribe EIPs Fun to receive the latest updates of EIPs Good for Buidlers to follow up.

View all
Serve Ethereum Builders, Scale the Community.
Resources
GitHub
Supported by