Rapid Dapp Prototyping

DAO? + NFT! + DEFI? = WTF?!?

Austin Thomas Griffith
9 min readAug 30, 2019

This is a walkthrough of the curriculum of my workshop for the Blockchain Training Conference 2019 (BTC2019). I have many similar tutorials like my Intro to Ethereum Development and BUIDLGUIDL 0x00, 0x01, and 0x02.

For this workshop we will be using Clevis & Dappartus my tools for rapid prototyping decentralized applications. We will also use ganache-cli to run a local EVM blockchain. Let’s get started.

Let’s install and fire up our local chain:

npm install -g ganache-cli; ganache-cli

Usually I start with some project idea or name. Judging by this summary of the ETHBerlin submissions, DAOs, DeFi, and NFTs are pretty popular. Let’s come up with the minimum viable all-of-those-things. We’ll call it NiftyDao!

There is no way I can build a fully fledged product in the 50 minutes I have, but we’ll cherry pick some code here and there and cut all the right corners. Plus, this barely will count as “DeFi”. Throwing that term around loosely here…

Let’s initialize our project with Clevis:

mkdir niftydao
cd niftydao
npx clevis init;npm i

(You will be prompted for what directories to use, just use the defaults.)

As you’ll read in the Clevis repo, you can install it globally, or you can install it locally and run:

alias clevis='./node_modules/clevis/bin.js'

To make sure Clevis is solid and the latest version let’s run:

clevis version

The goal of using these tools is to rapidly prototype decentralized applications. That will mean building the frontend and smart contracts in parallel. This allows for a very powerful and instant feedback loop.

Let’s fire up the frontend with:

npm start

Navigate to:

http://localhost:3000

If you are using MetaMask make sure it is pointed to localhost:8545

You do not need MetaMask. Dapparatus will detect if you have web3 injected and if not, it will generate an ephemeral Ethereum key pair.

Either way, now you have a dApp and an Ethereum account ready to interact with it.

Let’s send some test ETH to our account:

clevis send 1 0 0x318f227735378a34ef39266f5b5935847d8635d5

All is good, our frontend is representing our local chain correctly and Clevis is working:

Let’s create our smart contract and make sure it’s wired up with the frontend display:

clevis create NiftyDao

Let’s add a string to our contract called name that will be public:

string public purpose = "Rapid Dapp Prototyping - BTC2019";
clevis compile NiftyDao
clevis deploy NiftyDao 0

Take a look at what those two commands create. You’ll see the the ABI that gets created and the bytecode that gets deployed. You’ll see the resulting address of the deployment.

We can even poke at our smart contract from the command line:

But CLIs are for nerds, let’s publish the contract to our frontend:

clevis test publish

We need to load our contract into the frontend. That means supplying it an ABI and address. Luckily, in the name of rapid prototyping, there is a ContractLoader in Dapparatus ready for us to uncomment:

Might as well uncomment the <Transactions/> component while you’re at it!

You’ll see that as soon as we save that we can see the contract in the console:

Let’s grab the purpose from our smart contract when the contracts are loaded:

Then let’s uncomment the UI section of the Dapp, carve out just what we need, and display the purpose :

Finally the key to rapid prototyping is a tight dev loop. How long does it take us to change the purpose, compile, deploy, and publish to the Dapp?

clevis test full

Now we reach a fork in the road about how to proceed. I think the best way to demonstrate the benefits of rapid prototyping would be to build something quickly. But if the group is interested in working slowly through some basic concepts I’ll jump over to this article. (Where we create a function, set the name from the UI, allow others to set the name if they pay, collect the money from the contract, etc. Very cool stuff, but pretty basic. Really, it’s up to the crowd!)

Assuming at this point the fundamentals are covered and we are ready for the next step, let’s bring in the Open Zeppelin contracts to start building a ERC721MetadataMintable token:

npm install --save openzeppelin-solidity

Our contract is going to inherit from a few different contracts:

You will have a handful of dependencies to load too, grab those here. Once you have your contract, your dependencies, and your arguments, compile:

clevis compile NiftyDao

Great, so technically we have a mintable and burnable NFT. We will extend that later, but let’s look at the simplest aspects of a DAO. We’ll need members and a way for members to vote in new members.

You can grab all of this working code in this git commit.

clevis test full

Now let’s add the functionality in on the frontend to poll (maybe explain why this is bad) and display the members:

Again, you can get all the code for this commit here.

To test it all out:

clevis test full
clevis contract addMember NiftyDao 0 **YOUR ADDRESS**

You can try bringing in a third member to prove that it takes both members.

Now that our “DAO” is working, let’s allow members to vote in token URIs:

An ERC721 is a non-fungible token that has a unique id, owner, and a URI that can point to an off-chain data source like a JSON file. In this example we will use a simple image location in S3.

We will want the URI to be a string in the NFT so in our contract we will represent any given token type by its URI. Let’s add the code to allow DAO members to vote in token URIs.

Thinking ahead a bit to the “DeFi” section, tokens will have a price and curve too. Let’s make sure that is part of the vote, but we can gloss over the details until later:

You can grab all this code at the git commit here.

clevis test full

To the frontend! We’ll need a UI to allow DAO members to vote on token URIs:

clevis contract addToken NiftyDao 0 http://badges.xdai.io.s3.amazonaws.com/ethdenver/v1/images/Hippo 250000000000000000 20000000000000000

When we call addToken and a new URI gets voted in, it will fire an event. Thankfully, Dapparatus has a handy component to listen for events and keep the state populated:

Then when we poll, let’s also read the data from the contract for each token event that has fired:

From there we have the tokens in our state and we need to display them:

All of this frontend code is available in this git commit.

Rad. Now we have the NFT and DAO sections working, but this is programmable money… let’s work on a thin layer of “DeFi”. What we want to do is allow users to buy and sell the NFTs on a bonding curve. This provides instant liquidity and pressure to buy and sell.

For the sake of brevity we will make some oversimplifications. One nice decision that is already made for us is we are selling the tokens one at a time so no need for heady calculus in Solidity. All we have to do is increase the price of the tokens when one is purchased and decrease the price when one is sold.

To do this we will go back to that tokenCurve variable we set earlier. We will increase the tokenPrice by tokenCurve after a purchase and we will decrease the tokenPrice by tokenCurve before a sale. This makes a very boring, linear bonding c̶u̶r̶v̶e̶ line. 😅 Hardly “DeFi”, but it’s a fun demo. Plus, liquidity! 💦

The full contract code is available in this git commit.

⛔️ One note, you will have to edit one of the Open Zeppelin contracts to allow our contract to access a function that is set to external:

node_modules/openzeppelin-solidity/contracts/token/ERC721/ERC721Metadata.sol

We need the function tokenURI() to be public instead of external:

Everything should compile and deploy fine after that:

clevis test full

Let’s go ahead and add in a token with our one and only DAO member:

clevis contract addToken NiftyDao 0 http://badges.xdai.io.s3.amazonaws.com/ethdenver/v1/images/Hippo 250000000000000000 20000000000000000

Now let’s build out the rest of the UI so we can build and sell tokens. Let’s load up the totalTokenCount and then loop through all tokens loading them in and checking if any of them are owned by the user:

This is a bad idea, but it’s a POC. With enough tokens this will eventually take forever.

We’ll add the tokenCount into the token information that we poll for:

And we’ll save all this information to the state:

We will replace the current token display with a more advanced UI that allows us to buy and sell. Plus, it will display our tokens as we purchase them:

The full frontend code above can be viewed in this git commit.

That should do it. 🍾 As we buy and sell each different URI of token we will see the price fluctuate:

Right now there isn’t any specific market for these NFTs but thanks to permissionless extensibility any number of contracts can trigger based on the ownership of the hippo above. This is just the base layer.

Disclaimer: there are a bunch of reasons why something like this should NOT be deployed to production. It is a demonstration of how fast a POC can be built. Going the distance to production is an entirely different beast.

The full repo for all of this code is available here: https://github.com/austintgriffith/niftydao

--

--