Delphus Winter 2020 Update

The Delphus team has been hard at work over the past few months, steadily improving our product with many heavily-requested features. At the same time, we’ve been busy both in and out of the country bringing Delphus to many new people!

Product Updates


We have introduced support for the standard XForms specification, used by software from the Open Data Kit ecosystem. Supporting file uploads, multiple pages, advanced skip logic, and structured data collection, it has greatly improved our support for complex forms and data submissions.

Further, we have also implemented support for XForm imports from other software. This allows researchers to easily migrate to our platform without spending time on retraining or converting battle-tested form designs.

Multi-collateral Dai Support

We have updated to support multi-collateral Dai on the Kovan testnet, connecting to Dai on the Kovan contracts powering Oasis Trade. This is a foundational upgrade that increases the security of our payment storage and compensation system.

Further, we have tested the upgrade with our automated Dai exchange functionality, ensuring that it properly continues operations into the future.

UI Redesigns

We’ve greatly improved the appearance of our landing page to more clearly convey the benefits of using Delphus, with three key points where Delphus helps:

Delphus’s redesigned landing page

We’ve also made improvements to the user interface for both researchers and participants, streamlining the interface to create a study and add data.

Sponsor Awards at ETHWaterloo

Our most interesting weekend was at ETHWaterloo, where we spent time creating Cortex, a decentralized Ethereum identity verification system. It’s our hope to integrate this as a trusted method of organizational verification in Delphus to demonstrate the identities of researchers and to provide it as a Keybase-like service for the Ethereum ecosystem.

We were happy to work with members of several development teams at the event, including NuCypher, Ethereum Name Service, and Torus, integrating their software with ours. We were also honored to be selected for the following prizes:

  • NuCypher Award
  • Ethereum Name Service Award
  • Torus Award

It was a great experience hacking in Waterloo, and we hope to return next year!

Whitepaper Update

As part of our documentation updates, we have updated the whitepaper to include a clearer description of our problem statement and an updated technical architecture. If you haven’t taken a look at it before, please check it out now!

That’s all — best wishes for a wonderful 2020 and a new decade!

Scintillating News

The Making of Delphus Chat: Matrix, Ethereum, & End-to-End Encryption

Delphus, our secure, decentralized research manager, just got a very important new feature: end-to-end encrypted and federated chat, voice, and video calls, powered by Matrix and Riot. Here’s how we built it.

Why Matrix?

End-to-end encryption is necessary for our private researcher-participant communications, where sensitive information is often exchanged. This made Matrix, one of the only chat protocols that truly offers end-to-end encryption, our ideal choice. Its encryption library has been audited by NCC Group and is supported on all platforms, including web, iOS, and Android. Its mission to create a global, open “matrix” of communication also fits well with our own goal to unify and share scientific research.

Further, Matrix’s Synapse server is open source, allowing us to self-host it. It has several useful administration features, such as the ability to send system alerts to all of our users or to automatically add users to a server-wide discussion or announcement room.

Matrix also has a featureful first-party client: Riot. We opted to integrate this client into our app instead of coding one ourselves to take advantage of their end-to-end encryption support and extensive efforts to improve the user experience. Riot also supports voice and video calls through WebRTC.


Unfortunately, Riot is not itself designed to be embeddable. It currently does not expose any hooks to tell when the application is loaded or to trigger specific UI actions.

Since we wanted to integrate it into our application—for example, by adding links to start chats with participants or researchers—we added these hooks by forking Riot. (Changes are open source on our GitLab instance at delphus-riot-web and delphus-matrix-react-sdk.)

At specific locations, such as to mark when the user has logged in, our fork of Riot sends a cross-frame message to Delphus:

    type: "LOAD_COMPLETE",
    matrixId: this._matrixClient.credentials.userId

Using an event listener, the main Delphus application picks up these messages and triggers an action. We save the current load state (loaded, signed in) of Riot in our local state so that buttons in the app can know when Delphus Chat is loaded, e.g. to show a specific chat window.

To show notifications from Riot, we added a similar notification cross-frame message, which is used to update a counter in our code and show a notification badge on the Delphus Chat button (The user can also enable desktop notifications in Riot, which will show notifications as popups on their computer).

To open specific views in Riot, we programmed a way to manipulate the current location of the iframe, since Riot stores its view in the URL. For example, viewing the Matrix HQ (a general chat room about Matrix) is at the URL /#/room/, while viewing my profile is at the URL /#/user/ By manipulating the iframe URL, we can effectively remote-control Riot.

Identity Verification

However, in order to let participants chat with researchers (or vice-versa), we still needed a way to link a user’s Ethereum address (their pseudonymous identifier on our platform) with a Matrix ID (a username on the Matrix side). We decided to write a simple smart contract to handle this:

pragma solidity ^0.5.0;

/// @dev Stores mappings of addresses <-> Matrix IDs as part of the chat
/// system.
contract ChatRegistry {
    mapping (address => string) public matrixIds;

    function setMatrixId(string calldata _mxid) external {
        matrixIds[msg.sender] = _mxid;

This Ethereum smart contract maps a user’s Ethereum address to their Matrix ID.

Then, when we receive the LOAD_COMPLETE message from Riot, containing the user’s Matrix ID, we can compare it to the one saved by ChatRegistry. If the two differ, Delphus triggers a transaction to update the registry.

Thus, when we show Ethereum addresses on other parts of the site (such as when we display the researcher or participants in a study), we can include a “Start chat with this user” button to provide seamless integration. This button will automatically open Riot, load it if not loaded (since Riot is lazy-loaded to reduce the performance impact), and navigate to the specified user.

The end result is that we have a user-friendly, integrated embedded form of Riot on Delphus, allowing users to easily start encrypted chats, voice calls, or video calls with other users on the site.

Interested in learning more about Delphus? Contact us at, or sign up for our mailing list. If you are interested in learning more about Matrix, check out their blog as well.

Scintillating News Uncategorized

Interview with Will Hemond, Co-Founder of Delphus, a student-run entrepreneurial nonprofit group, recently interviewed Will Hemond, co-founder of Scintillating and Delphus.

Check out their article on Medium!

MakerDao's Dai and Delphus

Groundbreaking, Seamless Dai Integration in Existing DApps

Price volatility is the Achilles’ heel of a distributed application, or DApp for short. Nobody wants to deposit funds when Ether dipped 30% in the last month. And, while stablecoins like Dai can solve this issue, they have notoriously poor documentation, as we mentioned in our previous post. Furthermore, most existing DApps are already designed around Ether, which is relatively easy to process, and converting them to use DAI is an arduous and under-documented task.

The UX Problem

Using Dai also poses another issue: the user experience. If a smart contract only accepts Dai, new users will have to manually go to an exchange (of which there are few) to convert their Ether to Dai, then return to the DApp and deposit their Dai. Then, when taking out Dai, they have to manually convert it back to Ether to sell it for fiat on an exchange.

Enter Oasis.Direct.

Oasis.Direct is the prime example of what the UX for a decentralized app could be  a one-click transaction converts your Ether to Dai, without any manual ordering or price setting. Moreover, by integrating it into Dai-accepting smart contracts, it has the potential to make them far easier to use.

Step 1: Connecting to Maker Contracts

First, let’s take a (slightly simplified) look at how the entrypoint for our StudyManager contract looked like before Dai integration:

Ignore the other parameters, what matters is that it’s a payable function to which the user can send Ether. That Ether is then held by the contract and recorded in the new study’s paymentPool.

To convert this function to accept Dai, we have to retool it a little:

We’ve changed the contract to look much like a function that accepts ERC20 tokens which it should, since Dai is, at its heart, an ERC20 token.

However, there are two issues with this approach:

  1. The user still has to manually convert their Ether to Dai.
  2. The user has to manually call dai.approve(YOUR_CONTRACT_ADDRESS, tokenAmount) before calling this function, thanks to the design of the ERC20 standard. This means that the user has to approve two transactions.

Thankfully, we can solve both of these issues simultaneously:

Step 2: Interfacing with OasisDEX

OasisDEX is a decentralized exchange that converts ETH to DAI, running on both the Kovan test network and the main network. Its contract addresses (under “market”), along with Dai’s Kovan and mainnet addresses, can be found in the source code repository.

By interacting with OasisDEX, we can simplify the user flow, automatically converting deposited Ether to Dai for long-term storage.

Let’s see an example from our code:

(Contract interfaces from Oasis.Direct’s code.)

Here, the contract does four things:

  1. It deposits the paid Ether into the WETH contract, which is needed to trade on OasisDEX. Our contract now owns msg.value in WETH.
  2. It gives OasisDEX approval to use as much WETH as it needs to trade it to Dai.
  3. It executes an automatic trade from WETH → DAI, requiring an outcome of at least minBuyAmt DAI or else the trade will fail.
  4. It creates the study as we did in the previous step.

Note that the function has to be passed in the “minimum buy amount” of Dai that they want; it specifies the minimum exchange rate, in effect. You can calculate this on the DApp end by calling (with ethers.js/web3):

Which you can do invisibly before sending the createStudy transaction, in this case.

Step 3: Mocking Maker

Now, there’s one downside with this approach: to test your contracts in the future, you’ll have to use the live OasisDEX contracts on Kovan or the main network. This obviously doesn’t play very well with automated testing like Truffle, as each test would require actual Kovan/mainnet Ether.

First, we tried a new way of testing: with the tool ganache-cli, you can actually do a virtual chain fork by connecting to a mainnet/Kovan node and effectively creating a development blockchain that starts with all the state of the live network. This would let you test cheaply, without incurring costs on the live network, but while still connecting to “real” MakerDAO contracts.

Unfortunately, we ran into issues where our contracts either failed to deploy or didn’t work properly with this setup, so ultimately we ditched it for a more traditional, if more annoying, approach.

Let’s deploy all the Maker contracts on the Truffle development network!

The full code is pretty long, but I’ve put it on a GitHub gist at the end of the post if you’d like to use it. Here are the major steps:

  1. Deploys OasisDEX, WETH, and a FakeDAI contract (just a mintable ERC20 token) from /contracts/maker/.

  2. Whitelists the WETH and FakeDAI pair for fake-trading. This is necessary to prevent the OasisDEX contract from erroring on “untrusted” token pairs.

  3. Creates the WETH to DAI trading side of the exchange and the DAI to WETH side.

    To do this, you have to deposit WETH, approve it for use by OasisDEX, and make a fake WETH → DAI offer at a fake exchange rate. For the other side, you have to mint some fake DAI, approve it for use by OasisDEX, and make a fake DAI → WETH offer.

This creates a marginally-functional OasisDEX contract on the development network which you can use to mock Dai trading.

And there you go! That’s how you convert a contract accepting Ether to one that seamlessly converts it to Dai for long-term storage.

This code was used in our product Delphus, a DApp revolutionizing the management of clinical data in scientific studies. Find out more there!


Other interesting links:

Development Truffle migration script: