Clearly show which links open the external Blockchain explorer

If a link is going to send the user to another page it is better to control the flow of the user on the page by:

1 — adding a clarifying button that states what is going to happen: ie “open in Etherscan”

2 — ad a link-icon for independent block explorers and use it consistently across your UI

📌 back to cheatsheet

2 — (Writing Data) Transparency of Transactions

The user needs to be aware that data will be written to the Blockchain, and especially when it entails the exchange of an economic value (cryptocurrencies or tokens). Even though Wallets do warn the user about this intent, the Dapp should clarify this before launching the transaction request to the wallet.

Types of Transactions

There are different types of transactions that can happen when interacting with the Blockchain and each have different consequences.

The user should be able to differentiate between them through the information provided by the UI in different phases, even before launching the transaction.

2.1 - Value Transfers

— 2.1.1 - ETH

— 2.1.2 - Tokens

2.2 - Function calls

— 2.2.1 - contract methods with value implications

— 2.2.2 - contract methods without value transfers

2.3 - Factories: contract generating functions

Transaction data and costs

Transactions usually have a “payload”, some data attached, for example passed to the contract methods, and that is usually used to write or calculate what to write in the Blockchain.

Moreover writing data to the Blockchain usually has a cost, a “gas fee” to pay for the transaction.

The user should understand these two informations and be made aware of their content.

🔑🔑 Principles 🔑🔑

The Dapp front-end should:

➤ 🌀 (Permanence) clarify actions that are irreversible (all writing Txs)

➤ 🌀 (Value) clarify actions that involve money or value

➤ 🌀 (Privacy) clarify actions that could potentially lead to user identification

This is one of the hardest principles to implement as potentially any writing data can help to identify the user (until ZTKSnarks), and as smart-contract and web3 developers we can be unaware of the current and future sophistication of forensic tools, which are also usually closed source solutions. Just take into account this principle if privacy is a main feature of your Dapp, and use it to guide the design choices of when to clarify what actions are potential risks for your privacy seeking users.

➤ 🌀 (Factory) clarify actions that generate new contracts in the users name

This principle is to be applied only to Dapps that help the user create contracts with their address as the creator of the message. Apply this especially if it’s on MainNet.

Guidelines for all transactions:

➤ 🌀 clarify and confirm in advance the new future State

➤ 🌀 show the data that is being used for a transaction in a human readable format and in the way the Smart Contract requires it (∞link 5.Transparency of Code)

➤ 🌀 clarify suggested values for gas price and how to overwrite the Tx (∞link 9.Gas Price and Transaction Reversals)

➤ 🌀 manage Transaction wait time (∞link > 6.Time/Wait Management)

➤ 🌀 After the transaction is recorded show a relevant summary of the transaction to the user and how she can access the history (∞link 4.User Interaction History)

➤ 🌀 possibly, clarify what actions are NOT transactions and hence safe

How > examples

use css to indicate all irreversible actions

maybe use a warning/highlight colour like red

maybe use a warning/highlight colour like red add a tiny written warnings along with the button

ie: attention irreversible action ahead > learn more

ie: attention irreversible action ahead > learn more use double confirmation:

open a pop-up or toast, after the user presses the button and before calling the wallet/MetaMask, where you can inform the user of all the implications and ask for a confirmation.

Also offer the user to:

— cancel the action

— never show these pop-ups again (because she is an expert user) and when doing so tell the user that she could eventually reactivate the feature in the Chain-View side panel.

open a pop-up or toast, after the user presses the button and before calling the wallet/MetaMask, where you can inform the user of all the implications and ask for a confirmation. Also offer the user to: — cancel the action — never show these pop-ups again (because she is an expert user) and when doing so tell the user that she could eventually reactivate the feature in the Chain-View side panel. clarify & anticipate future expected steps

either with tiny written descriptions, label subtitles or with wizard like flows which have more steps to accomplish an action.

In the case of wizards:

— clearly show the user the number and title of the next steps

— allow the user to inspect the future screens to understand what is going on and what is going to happen (∞link 8.Newbie mode), although you should also grey out the functionality to not confuse the fact that she can have a sneak peak preview with the actual action.

either with tiny written descriptions, label subtitles or with wizard like flows which have more steps to accomplish an action. In the case of wizards: — clearly show the user the number and title of the next steps — allow the user to inspect the future screens to understand what is going on and what is going to happen (∞link 8.Newbie mode), although you should also grey out the functionality to not confuse the fact that she can have a sneak peak preview with the actual action. Add options to the Chain-View side panel

The side panel could be the place for many of these warnings as well as offering an inspector into the transactions, defining

— the type of transaction

— the data associated with the transaction

— the gas costs

— all other relevant information (∞link 5.Transparency of Code)

📌 back to cheatsheet

3 — (Pushed Data) Transparency of Smart Contract Events

Events are the notifications of the Web3 era

(Ethereum) Smart-Contracts can emit Events which are used to both store logs in the Blockchain and to reactively inform Dapps front-ends via Javascript that something has happened.

It is important to understand that Events

— can have parameters, information added to the logs

— are permanently stored in the Blockchain and therefore can be searched for



Events are normally used by developers for various things such as signaling when a certain condition has been fulfilled or when a certain action has happened: a new user has become a token holder, a deposit has been made, or a data has been received from an Oracle, and many more.

The fact that Events can be searched is immensely useful to log the behavior of one specific Dapp, and understand what happened and when, across the thousands or millions of blocks since the Dapp creation.

To better understand why this is so important let me quickly tell you a personal story:

When the Dao was hacked in 2016, I had the chance to collaborate with the group solving one part of the big problem: understanding who was owed what amount of Ether from the ExtraBalance account.

When users bought Dao Tokens during the ICO, according to the fee schedule, different amounts of ether would go into the ExtraBalance.

Two of the group’s problem solvers, Nick Johnson and Bokky Poobah, used the “CreatedToken” Event, to trace all transactions related to the DAO ICO, while I went the “hard route” imagining a situation where Events had not been implemented, and developed a deterministic parser for the Blockchain, a forensic tool very useful in case of malicious or badly planned smart-contracts. I did this also because there wasn’t an Event like “ReceivedByExtraBalance” to pinpoint that part of the transaction.

Here is where it gets interesting: while their scripts would take a few hours, mine would take around one day or more; that is because I had to go through (re-execute) every single transaction in the Blockchain, while they had already access to the (almost) “right” transactions thanks to the Events logs.

Even so, it took the three of us approximately two months to reconcile the numbers and return the whole balance to the original owners.

What does this have to do with Web3 Design Principles?

Events are used by the developers arbitrarily: they can choose to put or not an Event to signal something important about their Dapp. To give access to the front-end user to the Events in the Smart Contract is being transparent about these choices.

A high degree of useful Events can be a sign of a transparent Smart Contract and Dapp, one that is not afraid to let you know what it does internally. While little to no Events can be a sign of a sloppy or even malicious Smart Contract.

As in the above DAO story, the lack of Events would force a user to develop their own deterministic Blockchain parsers to understand what happens inside, a practically impossible task also because she would need an Archival node.

Moreover, Events are useful for developers to create several types of analytics, notifications and reactive data sources, even independently from the Smart Contract owner/creator. Possibly, this power should be made accessible to the front-end user too without needing to code.



Web3 Postulates:

— it isn’t transparency if it requires a humongous effort to find, see and verify the data

— It isn’t transparency if 99% of users are deterred from wanting to look [2]

🔑🔑 Principles 🔑🔑

a Dapp front-end should:

➤ 🌀 clarify and make accessible to the end user all Events, even if they are just for developer purposes

➤ 🌀 apply relevance: show interrupting messages only for information relevant to the current user, but still allow the user to inspect all Events in a separate Interface

➤ 🌀 allow the user to subscribe-to, unsubscribe-from or temporarily mute certain Events

Events are contract specific so these are simple suggestions of possible implementations.

In addition these ideas are better solved by an external tool, service, a plugin, or library, that doesn’t require the Dapp front-end developers to implement all these “non-core” features into their Dapp.

How > examples

have a notification center accessible to the user, this is probably a section in the “Chain-View” side panel

accessible to the user, this is probably a section in the “Chain-View” side panel use toasts for important messages

create filters to select/deselect only certain events or customise notifications based only on certain parameters.

Some filters can be:

— if it contains Ether / tokens

— based on address (mine/the user’s or another address or addresses)

— between timeX and timeY, blockX and blockY

etc.

📌 back to cheatsheet

4 — (History) Accessible and transparent User interaction History

In a future where we interact with hundreds or thousands of Dapps, tokens and probably chains, it makes sense for the user to have a clear history logged of her interactions with each one for future reference.



Wallets already store the history of all transactions, which is a start, but it’s only for one account at a time, and it might therefore be hard to figure out if you interacted across several of them.

Moreover wallets would still be hard unless additional features are built, to filter out only those belonging to a specific Dapp for example.

It is certainly user friendly for a Dapp to help you remember every interaction you did with it, just like you can go back to “purchase history” in any normal app.

It is even more important for Distributed Exchanges and Dapps that could generate hundreds or thousands of transactions for each user.

🔑🔑 Principles 🔑🔑

A Dapp front-end should:

➤ 🌀 provide a history of all transactions from a given address

Allow the user to inspect all interactions ever made with the Smart Contract, probably mainly those of type 2, that write to the Blockchain and therefore modify the state

➤ 🌀 clarify where is the history stored

To provide a history relative to a given user probably means recording her Transaction Hashes on a DB, either on a remote server or better in the user’s local indexDB. This is of course a potential privacy risk, so take note of the privacy principles (∞link 2.Transparency of Transactions) and code transparency principles (∞link 5.Transparency of Code) to clarify to the user where this data is stored.

➤ 🌀 give tools to navigate, search, export, and delete the history cache

How > examples

similar to the Event notification center, have a User-History tab or dedicated page , probably inside the Chain-View side panel

, probably inside the Chain-View side panel allow to filter for different type of transactions (value-eth, value-tokens, function calls, contract generating if pertinent)

(value-eth, value-tokens, function calls, contract generating if pertinent) allow to filter by date, from the beginning or between dates

optional user friendly addition: allow users to add a non-chain note field to the transaction , such as a simple reminder if they want to simply have a human readable and searchable plaintext

, such as a simple reminder if they want to simply have a human readable and searchable plaintext optional: have a search field in case there are hundreds of interactions and if it’s relevant to your Dapp

ie: Decentralised Exchanges might want to add such a feature to allow the user to search for transactions relating only to specific tokens

ie: Decentralised Exchanges might want to add such a feature to allow the user to search for transactions relating only to specific tokens export: allow user to optionally export the data in csv and explore it through other means, again, especially appropriate in case of large datasets

allow user to optionally export the data in csv and explore it through other means, again, especially appropriate in case of large datasets delete: allow the user to delete the History from the local cache, but of course clarify that the real history of transactions is not deleted neither from their wallet nor from the Blockchain

allow the user to delete the History from the local cache, but of course clarify that the real history of transactions is not deleted neither from their wallet nor from the Blockchain import: it makes sense to add an import option only if the Dapp allows the user to add custom notes to each transaction, otherwise the information can be simply reconstructed from the Blockchain

📌 back to cheatsheet

5 — (Code & Environment) Transparency of Code

If a Dapp can be trusted also means if the code being executed can be trusted.

To be trusted, Dapps should be as transparent as possible about all the aspects of their code.

Web3 Postulates

— for a Dapp to be trusted, it’s code needs to be trusted

— for code to be somewhat trusted, it needs to be transparent, independently executable and verifiable

🔑🔑 Principles 🔑🔑

a Dapp front-end should:

➤ 🌀 Clarify which Blockchain is being used

it seems obvious but in a scenario with proliferating Dapps many can be Blockchain agnostic or run different versions on different chains. Also with Plasma, Polkadot, Cosmos and other scaling solutions it is possible that a Dapp might be tracking transactions in it’s own sub-chain nested deep down a tree of other Plasma chains or other parachains or Cosmos Zones or Hubs. The user should be made aware of where their data is being written and therefore be aware of the technical variables (security, speed, etc) and where to independently verify the data.

➤ 🌀 Clarify the address of the Smart Contract(s) that are being used for read and write operations

and link to independent Blockchain explorers (∞link 1.Transparency of Data Provenance).

➤ 🌀 Clarify which code is open source and where to find it.

➤ 🌀 Clarify where code is being run (local vs Remote Server)

This might be one of the most difficult and cumbersome to implement at a visual level, but if parts need to run on a server have at least a page explaining which parts and why and point to it from any relevant part of the UI.

If the “chain-view” mode seen in the examples of the first principles (∞link 1.Transparency of Data Provenance) has been implemented, that would be a good place where to add these other views.



➤ 🌀 Clarify the web3 provider / Blockchain node (local node, Dapp controlled node, Infura, MetaMask?, or other node)

Why? Because instrumented nodes can record data, like etherscan, and could potentially be a source of privacy risks for the user.



- If possible or relevant allow users to switch to their own node

Although this is already taken care by providers like MetaMask, this principle applies in case your web3 Dapp, for some reason, does broadcasts transactions to specific nodes. Also, transactions going through your own private node can be faster to execute because they avoid the potential queues of public nodes especially during high demand events like crowdsales.

➤ 🌀 Clarify if the Dapp is running on MainNet or on TestNet

Although the web3 provider takes care of this, especially make sure that the user understands that actions are being run on the MainNet if it’s the case (resort also to the other principles in ∞link 2.Transparency of Transactions)

➤ 🌀 Clarify which data read from the chain come from Oracles or has been influenced by oracles

User friendly additions

➤ 🌀 Allow for DIY code execution

allow more advanced users to see the transaction function call before it is sent so that they could verify it and reproduce the action by themselves via command line.

This might seem as an exaggeration because the Dapp front-end is there to simplify the user and hide certain technical matters, but a skeptical/paranoid user would want to verify even single transactions: if the Blockchain is like a distributed database then a user should be able to perform the writing operations independently and the Dapp should still work.

In a radical transparency attitude towards the code, a Dapp that allows this feature is signaling “Don’t Trust. Verify” https://blog.wizsec.jp/2018/02/kleiman-v-craig-wright-bitcoins.html?m=1

An enhanced version of the Data Provenance where the users can also copy paste the code to retrieve the data by themselves

➤ 🌀 Clarify the inputs required by the Smart Contract:

Smart Contracts require often big numbers with a lot of zeros, which are unfriendly to the user, especially because it’s very easy to make costly mistakes. It is normal and advisable that the Dapp UI simplifies this process to the user, allowing smaller numbers in a more understandable and less error prone range, like 0 to 100. However, in light of the previous transparency of code principles, it should be made clear to the user where those inputs are being simplified by the UI and clarify, especially in the DIY code inspector, the actual input that the Smart Contract is expecting.

A real case where this was confusing was raised in a discussion with Jorge Izquierdo about the Aragon Voting app . Developers can use the same solution presented for that case and clarify to the user some examples with: the simple number, the scientific notation and the actual input (with all zeros) that the Smart Contract is expecting.

detail of the example from the Aragon wiki

How > examples

have a “Code Transparency” page always accessible like the Terms of Service or Privacy Policy pages

always accessible like the Terms of Service or Privacy Policy pages link to your github repos in several places

repos in several places add to the “chain-view” panel (shown in the examples of chapter 1.Transparency of Data Provenance) a section dedicated to code transparency with

○ information on:

— the Blockchain in use,

— the properties of such Blockchain, especially the average block confirmation time (∞link 6.Time/Wait Management)

— wither it’s MainNet or TestNet

— the web3 provider in use (allow for switching),

— the contract addresses,

— possibly a simplified version of the contract’s ABI with just the methods actually called by the code

— if there is any part of the code being run not-locally (textual explanation and motivation)

— the link to the github repos

○ switches, filters or options to:

— display, with icons and/or by changing colors, which parts / components have data that is processed on a server

— display, with (the “cloud-to-chain” oracle) link-icons and/or by changing colors, which data comes from oracles

— if relevant, change the web3 provider

— a preview of transactions being called with the function calls that could be copied and executed on the command line

with notes on the inputs if relevant.