ERC-3722 -- Poster: A ridiculously simple general purpose social media smart contract

I don’t think there would be a long-term persistence issue here as long as we can read IPFS from the subgraph: the poster contract emits an event with an IPFS hash, which needs to be available long enough for the subgraph to retrieve the data from IPFS, which it then processes as a bunch of events – subgraph then becomes the long term state storage and we don’t really need the IPFS hash anymore.

I think the main issue here is the centralization of packaging a bunch of signed messages and putting them on IPFS – without some decentralized protocol for that, you have to trust the packager not to censor anyone’s messages. This is similar to Snapshot or Gnosis Safe today, so it’s not an issue that would be unique for us.

For now, I’m hopeful we could deploy this on some layer 2s that are essentially free – we need way less security for these media use cases than for DeFi, I think, which hopefully means we can go straight to the cheapest censorship-resistant L2s.

1 Like

I’ve been thinking about this some more and I think it’s worthwhile adding a new operation (permissions) and a new field (from) to the json standard.

A post to grant all permissions to an account.

{
  "content": [
    {
      "type": "permissions",
      "account": "<account_to_set_permissions>",
      "permissions": {
        "post": true,
        "delete": true,
        "like": true,
        "follow": true,
        "block": true,
        "report": true,
        "permissions": true
      }
    }
  ]
}

A post from an account with permissions to post on behalf of another account. If the ‘from’ account has given permission to this account, clients should treat this message as if it came from the ‘from’ address.

{
  "content": [
    {
      "type": "microblog",
      "text": "This is a post from an account with permissions to post on behalf of another account.",
      "from": "<from_address>"
    }
  ]
}

Perhaps some version of this should be PIP-0002? (assuming PIP-0001 is a template similar to EIP-1)

1 Like

Editing (i.e. update) of posts should be included in the standard for posting.

An update is a new post with a reference to a previous post stating that it is an update to replace it. Multiple updates should be allowed.

Clients can show only the latest update to a post (and optionally show previous posts).

1 Like

Great suggestion! I’ll add this to the standard.

1 Like

Have you all checked out my set of JSON schema for Postum? I’m using this pattern:

{
  "action": "CREATE_FORUM",
  "args": {...}
}

With a different schema for each database mutation, e.g. create/edit/delete forum/thread/post. This seems like the right general framework for Poster apps to me.

edit: I guess maybe I’m suggesting a PIP here? Not really keyed into that system at this point, but it would be something like this: content should use the above format or similar (action, args) and the poster community should maintain an action namespace (i.e. only one “CREATE_FORUM” schema), to help make poster apps more interoperable.

1 Like

This seems reasonable to me. Do you see this as conflicting with the proposed json schema for twitter-like posts?

Maybe? I guess we should set up an EIP-like repo for PIPs.

Some thoughts:

  • Is it really okay to “store” the message in blocks but not in the state? As the chain lives longer and longer, there might be less and less people storing the whole block history. I’m confident there will still be people and companies doing it, but when the storage reaches tens of terabytes, it might be highly skewed towards companies offering paid API access (arguably this can be unbundled, decentralized too though). It might be okay, but it’s worth thinking about explicitly. Otoh, storing in the state makes the costs prohibitive.

  • Has someone looked at how Arweave incentivizes storage? They seem to have done some thinking of that front. Maybe something similar can be reproduced / incentivized by a contract?

A different type of general purpose contract can be made via unicodes. Emojis, logographic symbols can be send via this contract as well.

contract Poster {
    event NewPost(address indexed account, uint256[] unicodes);

    function post(uint256[] calldata unicodes) public {
        emit NewPost(msg.send, unicodes);
    }
}

Right, I think the implicit assumption here is that protocols like The Graph will be able to make this data available in a decentralized way.

This is certainly possible, although I’d argue that it should be added as an additional layer to this contract, so as to keep Poster as opinionated as possible.

Is there a reason you couldn’t send these with the current Poster contract? Strings are assumed to be UTF-8 (unicode) encoded anyway.

Hey @auryn, what you have here is somewhat similar to what I proposed here, although this Poster contract is indeed surprisingly simple.

The major difference is your idea uses little storage on-chain, and the messages are not considered to be assets and hence not transferrable. The idea I proposed would treat every single word or logograph in some languages as an asset. The root cause is in the nature of languages.

That’s why I was wondering if this Poster idea could do the same.

Poster doesn’t use any on-chain storage.

Correct. Messages are not intended to be assets in Poster.

Honestly, I have no idea what this means. :sweat_smile:

Postum update: https://postum.on.fleek.co/
https://github.com/ETHPoster/postum/tree/rinkeby

First try deploying, probably won’t stay up too long. Rinkeby only, definitely has some broken stuff. But you should be able to create forums, threads, and posts! I think this decently proves the concept outlined in this thread.

The UX isn’t ideal, but it’s at least part of the way there: you have to wait for the chain to confirm the transaction, but at that point the UI optimistically displays your action without waiting for the subgraph.

Feedback welcome! I’m not sure how much time I’ll have to put into this coming up, but I do think there’s a lot of potential in the forum use-case.

This is such a great start @ezra_w!

1 Like

Just a heads up, EIP-3722 was merged, so it’s now ERC-3722 :tada:

1 Like

Would it make sense to add another indexed field to the event that can be set by the poster?

For example

event NewPost(
  address indexed user, // always msg.sender
  bytes32 indexed tag, 
  string content
);

The idea would be that this could be used for easier querying of events if you don’t want to rely on a subgraph.

It could, potentially, but this feels like a slippery slope towards it becoming more opinionated.
I believe @crazyrabbitLTC also suggested a variety of other parameters that we might include to allow for better filtering for some usecases. We ultimately decided against it in the interest of keeping it as simple, elegant, and opinionated as possible.

Are there specific use-cases you’re thinking about?

I personally with thinking about allowing more direct communication (e.g. similar to a group around a topic).

While using a sub-graph obviously would still allow this when this is part of the content, I feel like it would be nicer to allow more efficient querying of on-chain data via traditional/ direct means would be very helpful and beneficial. Knowing that many nodes impose limits when querying events it would make sense to provide some method of filtering, therefore an additional field would be helpful.

1 Like

@rmeissner what are your thoughts on using string rather than bytes32 for the tag, just to maintain human readability?

I was choosing a bytes32 because values that are indexed are forced to be 32 bytes (to fit in the topic field). So if you use a string it will be hashed and the hash will be store in the event topic (see Contracts — Solidity 0.8.9 documentation). So to be more flexible in what this actually is I was directly proposing to use bytes32, but on a low level using string would be a similar result, so I would be fine either way.

1 Like