DeFi and the future of the global economy: Decentralized Exchanges

Federico Reyes Gómez
5 min readMar 5, 2021
Sample ERC20 Token Contract Interface (https://ethereum.org/en/developers/tutorials/understand-the-erc-20-token-smart-contract/)

This blog post is be split up into four sections:

  1. What is Decentralized Finance (DeFi)?
  2. Application 1: Decentralized Exchanges (You are here!)
  3. Application 2: Stablecoins and DAOs
  4. Application 3: Lending Platforms

Part 2: Decentralized Exchanges

One of the simplest and most natural decentralized finance applications is a decentralized exchange. In a traditional exchange, you have a buyer pool that is looking to purchase a specific asset (digital currency in this case) and a seller pool that is looking to sell a specific asset. The most common kinds of exchanges are Foreign Exchange markets that set prices for interchanging traditional fiat currencies.

With the rise of many new digital currencies within specific ecosystems like the Ethereum ecosystem, there is a clear need to be able to exchange ETH for DAI, DAI for BAT, BAT for CryptoKitties, and CryptoKitties back to ETH. Note: For simplicity, we focus only on the Ethereum environment and exclude cross-chain (etc BTC for ETH) exchanges.

As we saw in the first part of this series, decentralized finance allows us to program very complex financial applications on smart contracts in the solidity language. One of these applications is a decentralized exchange.

From the website DeFi Rate, we see the following properties of decentralized exchanges

Non-custodial — Ownership of the underlying assets is never revoked.

Automated — With no intermediaries, DEX trading is instantaneous so long as there is sufficient liquidity.

Cost-Efficient — Many DEXs have minimal trading fees, allowing users to swap assets at little to no cost

Globally Accessible — Most DEXs do note require any sign-ups, and largely come with no counterparty risk.

Intuitive — Newer trends have evolved DEX trading from order books to simple point and click swaps.

Pseudo-anonymous — Users simply connect a wallet of their choice to start trading. No profile or background information is required.

We can start to envision what such a smart contract might look like. For more information, refer to the 0x White Paper, which this code is largely based on. We define our main orderBook data structure that contains buy and sell orders. Upon submitting a buy order, the sell order list is searched until a matching sell order is found. Our (very simplified) smart contract starts to look as follows:

pragma solidity ^0.4.22;/// @title Decentralize Exchange Smart Contract.
contract DEX {

// First we create an order book that mapps a token (address)
// being sold to a token (address) being bought to a sorted
// list of order that buy and sell that combination of tokens
mapping(address, mapping(address, Order[])) orderBook;
function submitOrder(address tokenBought, address tokenSold,
Order order) public
}

which contains Order objects defined as follows:

struct Order { 
string kind; // Buy or Sell
address maker; // Order Creator
address tokenSold; // ERC20 Token being sold
address tokenBought; // ERC20 Token being bought
address valueSell; // Amount of token being sold
address valueBuy; // Amount of token being bought
uint expiration; // Time until order expires
uint feeA; // Fee being paid by seller
uint feeB; // Fee being paid by buyer
}

Now we can further define our `submitOrder` function:

function submitOrder(address tokenBought, address tokenSold, Order 
order) public {
if (order['kind'] == 'sell'){
// Add the order to the order book
orderBook[tokenSold][tokenBought].push(order);
// Sort the order book
sortOrderBook(tokenSold, tokenBought);
} else if (order['kind']== 'buy'){
// Search the order book to find a match
searchOrderBook(tokenSold, tokenBought, order);
}
}

with helper functions

function sortOrderBook(
address tokenSold,
address tokenBought
) private {
// Apply a standard search
orders = orderBook[tokenSold][tokenBought]
orderBook[tokenSold][tokenBought] = sort(orders)
}

and a helper function to find matches and execute trades.

function searchOrderBook(
address tokenSold,
address tokenBought,
Order order
) private return(bool) {
// Find a matching order set, a pairing of orders that
// would make both participants happy
orders = orderBook[tokenSold][tokenBought];
for (uint i = 0; i < orders.length; i++) {
currentOrder = orders[i];
if (currentOrder['valueSell'] == order['valueBuy'] &&
currentOrder['valueBuy'] == order['valueSell']
){
// Execute the trade
tokenSold.transferFrom(
currentOrder['maker'],
order['maker'],
currentOrder['valueSell']
)
tokenBought.transferFrom(
order['maker'],
currentOrder['maker'],
currentOrder['valueBuy']
)

// Trade was successful
return true;
}
}
// Trade failed
return false;
}

Our final contract looks a little something like this:

pragma solidity ^0.4.22;
/// @title Decentralize Exchange Smart Contract.
struct Order {
string kind; // Buy or Sell
address maker; // Order Creator
address tokenSold; // ERC20 Token being sold
address tokenBought; // ERC20 Token being bought
address valueSell; // Amount of token being sold
address valueBuy; // Amount of token being bought
uint expiration; // Time until order expires
uint feeA; // Fee being paid by seller
uint feeB; // Fee being paid by buyer
}
contract DEX {
// First we create an order book that mapps a token (address)
// being sold to a token (address) being bought to a sorted
// list of order that buy and sell that combination of tokens
mapping(address, mapping(address, Order[])) orderBook;

function submitOrder(address tokenBought, address tokenSold, Order order) public {
if (order['kind'] == 'sell'){
// Add the order to the order book
orderBook[tokenSold][tokenBought].push(order);
// Sort the order book
sortOrderBook(tokenSold, tokenBought);
} else if (order['kind']== 'buy'){
// Search the order book to find a match
searchOrderBook(tokenSold, tokenBought, order);
}
}

function sortOrderBook(address tokenSold, address tokenBought) private {
// Apply a standard search
orders = orderBook[tokenSold][tokenBought]
orderBook[tokenSold][tokenBought] = sort(orders)
}

function searchOrderBook(
address tokenSold,
address tokenBought,
Order order
) private return(bool) {
// Find a matching order set, a pairing of orders that
// would make both participants happy
orders = orderBook[tokenSold][tokenBought];
for (uint i = 0; i < orders.length; i++) {
currentOrder = orders[i];
if (currentOrder['valueSell'] == order['valueBuy'] &&
currentOrder['valueBuy'] == order['valueSell']
){
// Execute the trade
tokenSold.transferFrom(
currentOrder['maker'],
order['maker'],
currentOrder['valueSell']
)
tokenBought.transferFrom(
order['maker'],
currentOrder['maker'],
currentOrder['valueBuy']
)

// Trade was successful
return true;
}
}
// Trade failed
return false;
}
}

As always, these smart contracts are merely pedagogical and wouldn’t fully work in practice. You’d need to check balances, authorization, digital signatures on the orders, etc.

This also gives the smart contract owner the ability to customize the matching algorithm to their whim. Ours is a simple linear search that only focuses on a specific context, a perfect match, but any other matching algorithm could be used here in practice, as well as any kind of fee structure.

Hopefully this gives you an idea of what Decentralized Exchanges look like. For more information, refer to deployed exchanges like Uniswap, Sushi, Curve, 1inch, and more!

Thanks for making it this far! Parts 3 and 4 of this blog will focus on Stablecoins (A cryptocurrency whose price is ‘pegged’ to an external currency) and Lending (Peer-to-peer lending infrastructure for lenders to earn interest and borrowers to borrow cryptocurrencies without needing a bank approval)

If you haven’t seen the rest of the series, make sure to check out parts

  1. What is Decentralized Finance (DeFi)?
  2. Application 1: Decentralized Exchanges (You are here!)
  3. Application 2: Stablecoins and DAOs
  4. Application 3: Lending Platforms

--

--