EIP-7017: Notifications Interface for a more engaging blockchain

Introduction

With the adoption of web3 applications, an increasing necessity arises to be informed about certain events happening on-chain. Some examples include:

  • DAO governance voting on important matters where member’s participation is fundamental.
  • DEX informing about a certain price limit being reached, for example a stop-loss or a margin-call.
  • An NFT marketplace informing an NFT owner about an offer being made to one of it’s NFTs.
  • A metaverse informing about an important event.
  • Warning about an ENS domain expiration date approaching.

Users are used to being informed, whether it be about news or updates of their favorite applications. As we are in a time of instant data feeds on social media, instant messaging apps and notifications of events that users care about, notifications are a feature in practically every application that exists in web2. They mostly come to email inboxes, SMSs, inside the applications, or in the notification inbox in the operating system.

If they would be taken away, the engagement on these web2 applications would sink. This is not different with web3 applications: users cannot be left in the dark about what is going on in them. Not only that, for some applications, all that matters is the participation of users on certain events, like governance on a DAO.

This whitepaper aims at proposing a decentralized approach to send and receive notifications from and to ethereum addresses, including smart contracts, in a private and easy way.

The problem

There are a number of reasons why there isn’t a mainstream notification standard in ethereum and why it’s a lot harder than in web2 applications.

First, let’s list some facts about the nature of ethereum that put to evidence the difficulty of the matter:

  • The owner of an address is unknown and no contact information comes with an ethereum address.
  • The owner of an address is most of the time unwilling to link personal contact information on the blockchain because of reasons like security, taxation and spam.
  • Everything that is published on the blockchain is completely public. Moreover, smart contracts don’t have private keys, so they can’t encrypt or decrypt data.

These are technical reasons that make it harder to do it than in web2. But it’s likely that the biggest reason relies elsewhere.

In web2, most of the user account’s are linked to an email address that is required at sign-up. This makes it easy to send notifications to specific users. This requires no further complexity. In web3, on the other hand, there is no obvious inbox to send notifications to. Every smart contract can define its own event’s to which one can listen to, but for each of them, a change has to be done in the frontend to listen to that specific contract and event structure. This poses a problem of coordination between smart contracts and web3 applications that can notify users.

The true challenge is coming up with a standard that is appealing to use and that dapps all over the ecosystem integrate.

Solution

A definitive solution would need to overcome these problems without having to rely on a centralized party, as this would involve not only giving out personal information to that party, but trusting them with the notifications they send. It has to allow smart contracts and addresses to broadcast data to other addresses, and for the owner of the addresses to be able to subscribe to any notification sent to their address.

An approach that is both simple, decentralized and easy to implement is to use a notifications smart contract standard to be able to emit notifications to one address or broadcast them to anyone that wants to listen. Whitelists would record all addresses a user wants to allow receiving messages from. This is useful for direct messages from one address to another. Subscription lists would indicate which addresses they want to listen for general broadcasts. This is useful for receiving updates on a project.

The user should not be required to record its whitelist and subscription list on-chain. Anyone can emit notifications to anyone else and the filtering would occur off-chain on the front-end.

If a Smart Contract implements at least one of following events it would be a Notification Contract and, once deployed, it will be responsible for emitting notifications.

event DirectMsg (address indexed from, address indexed to, string subject, string body)
event BroadcastMsg (address indexed from, string subject, string body)

For the DirectMsg events, the contract shall also implement at least one of the following methods. These two functions differ only on the sender. In one, the sender is set as the address executing the function and in the second, as the address of the smart contract emitting the message:

function senderDirectMsg(address to, string memory subject, string memory body) public

function contractDirectMsg(address to, string memory subject, string memory body) public

The same applies to BroadcastMsg event, where the contract shall implement at least one of the following methods:


function senderBroadcastMsg(address to, string memory subject, string memory body) public

function contractBroadcastMsg(address to, string memory subject, string memory body) public

Here’s an example Notification smart contract:


pragma solidity ^0.8.7;

contract Notifications {

event directMsg(
address from,
address to,
string subject,
string body
);

event broadcastMsg(
address from,
string subject,
string body
);

/**
* @dev Send a notification to an address from the address executing the function
* @param to address to send a notification to
* @param subject subject of the message to send
* @param body body of the message to send
*/
function senderDirectMsg(address to, string memory subject, string memory body) public {
emit directMsg(msg.sender, to, subject, body);
}

/**
* @dev Send a notification to an address from the smart contract
* @param to address to send a notification to
* @param subject subject of the message to send
* @param body body of the message to send
*/
function contractDirectMsg(address to, string memory subject, string memory body) public {
emit directMsg(address(this), to, subject, body);
}

/**
* @dev Send a general notification from the address executing the function
* @param subject subject of the message to broadcast
* @param body body of the message to broadcast
*/
function senderBroadcastMsg(string memory subject, string memory body) public {
emit broadcastMsg(msg.sender, subject, body);
}

/**
* @dev Send a general notification from the address executing the function
* @param subject subject of the message to broadcast
* @param body body of the message to broadcast
*/
function contractBroadcastMsg(string memory subject, string memory body) public {
emit broadcastMsg(address(this), subject, body);
}
}

Sending a notification

To send a notification to any address in ethereum, simply execute a DirectMsg event passing both the receiver, the subject and the message to it.

In case of a project, it may broadcast a message by using the broadcastMsg event. Here, all that is needed is the sender’s address, the message subject and the message body.

Receiving notifications

To receive notifications we have to go off-chain, as the email services and phone notification centers are outside of it. But this doesn’t mean a centralized approach is necessary, nor that the identity of the user has to go public.

All that needs to be done is to set up a listener to the notifications smart contract and whenever a notification is sent to the address being listened to or broadcasted by an address one is subscribed to, the user gets notified. This is possible to do from any user interface or application. Appealing options are:

  • Metamask wallet (in web-browser and mobile app)
  • Email service
  • In-app push notifications

As the notifications filter is set by the user off-chain, spam can easily be avoided with zero cost to the receiver, but >0 cost for the spammer.

Encrypted notifications

Blockchains use asymmetric cryptography to operate. Without it, bitcoin could never have existed, as it is what allows users to have a secret and to be able to prove they own it without sharing their secret. What is important here is that asymmetric cryptography is available in ethereum and that we can make use of it for encrypting messages.

As some use cases of ethereum notifications may require privacy of data, this becomes useful.

As all messages are public, an easy way to send a message that is secret is to encrypt it using the receiver’s public key. Then, the receiver can simply decrypt it using its private key. This is what asymmetric cryptography was invented for.

Note that this use case only makes sense when the message is encrypted off-chain. That means that a smart contract could not generate the message since it can’t hold a secret. It should only emit the event holding the message, but it should come from a regular address.

Integration in web3 applications

A user-friendly approach is for web3 applications to get users to add the app’s smart contract to its subscription list on a web browser plugin. This way, the user is listening to the web3 application smart contract whenever it makes an announcement.

Also, it can add it to its whitelist so that the contract can send a message informing about something specific to the user.

The web3 applications should talk with a browser extension that in turn can listen to the notification smart contract.

How does it solve the problem?

Currently, in order to listen to the events in a smart contract, a programmer needs to develop a custom listener for the smart contract in question (unless it’s already standardized). This listener then can be integrated into different applications, but usually only if a big percentage of the app’s users needs the feature. Otherwise it doesn’t make sense to have it on the app. Listeners exist for example for token transactions, as they all adhere to a standard so it’s easy to implement for all of them at once.

In case of notifications, there is no easy way to alert a user about an important event.

With the solution presented an app would only need to integrate one update for it to be able to listen to any smart contract that the user needs to listen to. The user must not execute any transaction for this use case, only the sender has to. The cost for broadcasting a message is usually less than 1 dollar at current gas and eth prices and it can reach any number of users.

A call to action

The solution presented in this whitepaper is likely not the best solution to the problem. Collaboration is what yields the best results. The best way to have collaboration and to deliver a standard to the ecosystem is to develop an Ethereum Improvement Proposal with the idea presented in this paper. The community shall present its veto here on the Ethereum Magicians Forum.

Working on a draft implementation

Could the body of the notification be bytes[] instead of string, allows for greater composabilty

1 Like

Sure!
Thank you @pxrv

The people at Push Protocol (aka EPNS) have designed a really good process around push notifications. You might want to check that out. It solves a lot of problems mentioned in your problem statement.

The owner of the address is identified by the address itself. IMHP no other contact information should be necessary for sending notifs. The ERC standards should be made around base-cases. If any more contact information is required, thats a prerogative of the dapp itself.

EPNS solves this problem by allowing users to approve notifications only from specific senders. This again is pseudo-anonymous so the only thing that needs to be disclosed is the address itself.

After an admittedly cursory glance, I couldn’t find out if Push provides an encrypted notif service. This should be a trivial implementation though if reqd.

Standardizing a format for notifications (as mentioned in the title of the topic) doesn’t define where those notifications are sent. Push provides a browser extension, and IOS and android apps that act as an inbox for your notifications.
Building an app that forwards your Push notifications to an email would be an interesting side project - definitely not an EIP.

Happy building :slight_smile:

I looked at Push Protocol before writing the idea. I find it has several problems that make it more problematic than the EIP I’m proposing. This problems are:

  1. Despite what they say, their protocol is not really decentralized, as described in their whitepaper. For example, to send a notification, you send a JSON to their API, which they can then pass over to the users that are listening. This is done off-chain and has no way to be verified. There has to be trust in the server running the protocol.

  2. As described in “subscribing-to-channel” section of their whitepaper, their protocol requires subscribers to do a transaction in order to subscribe or unsubscribe. The lists are stored on-chain, which is something that isn’t necessary, as users could choose who to sisten from by doing a filter in the frontend.

  3. To ease this problem, they decided to incentivize the subscribers by paying them for subscribing. This is a cost that goes to the entities emitting the messages, as they are required to stake DAI on behalf of the protocol. This is yet another cost to consider.

  4. Sending and receiving notifications is not only costly, but involves a process that is unnecessarily tied to their servers. The processes involved are uneasy to implement. Sender’s can’t simply send a message from their smart contract at low cost, but they have to go to a DeFi protocol, create an account, stake DAI, develop a way to deliver the message to the protocol, etc. All of this with poor documentation and transparency.

  5. As described in the governance section of their whitepaper, the protocol is not run by users. All decisions will be made by “the Company”. There is no actual governance mechanism in place.

I know I’m biased, but I hope this can be compared to the EIP approach. In my point of view, an ERC standard is what is needed here in order for any project, no matter how small, to implement notifications to it’s users, without extensive development, and in a way that is trustless and decentralized.

This is true. I expect that as an ERC standard arises, wallets could implement it in an easy way, just as how I guess it happend with most of the standards. An EIP here would serve as a foundation for notification protocols, not as a way to deliver them to an inbox. I should keep inboxes out of the reach of the EIP tho, as it’s out of the scope of the EIP.

True. This would be a cool side project. Emails are definitely not to be defined inside an EIP.

Do I edit the idea to include a refutation of Push Protocol and also to clarify the points you mentioned? I’m sorry for asking this. I’m kind of new around here.

Thank you very much for your help @pxrv.

Here’s a draft ready for being submitted.
Please give it some feedback:
Notification Standard - HackMD

@pxrv

As the notifications filter is set by the user off-chain, spam can easily be avoided with zero cost to the receiver, but >0 cost for the spammer.

There could be instances where publisher (sender/broadcaster) would like to send multiple notifications which could cost higher fees. Utilizing batching could save the gas fees in this scenario. Thereafter, it is up to the frontend clients to group them together by timestamp for user friendliness.

Here is the EIP pull request (EIP-7017) on ethereum’s GitHub:

I think it’s time to define in greater detail how the body of a notification should be standarized. A good read to better understand what a notification needs in order to succesfully fulfill it’s function is this artice: A Comprehensive Guide to Notification Design | Toptal®

Most of the topics are regarding frontend and content of the notifications, but a few questions came to my mind regarding broadcastMsg events:

  • should there be a maximum size for the title and body so that frontend implementations can better accomodate them?
  • Should notifications be classified by the three attention levels: high, medium, and low? (so frontends can differentiate between them with colors or where they show them)

Also, two other topics are important to mention:

  • If we want notifications to have images, there should also be a standard as how to include them in the message.
  • In case of DirectMsg events, they should have the option to be encrypted using the receiver’s public key. The front-end should then recognize this and ask for the receiver to decrypt the message in case it’s encrypted.

To solve all this topics, the body should be standarized, as it is an array of bytes. This is my suggestion for the body’s structure of a broadcastMsg event:

[
"0": "The message itself, a string, with a maximum size of X characters",
"1": "The attention level (1, 2 or 3)",
"2": "An image URI (optional)"
]

The maximum number of characters should of course be carfefully discussed based on common sizes used for notifications.

On the other hand, the DirectMsg events bodies could be standarized as follows:

[
"0": "The message itself, a string, with no maximum size",
"1": "Is encrypred (1 or 0)",
"2": "An image URI (optional)"
]

Would this be the best way to implement it? Or should the structure be defined as an event arguments instead of inside the body?