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.