Architecture overview

The Dether system

All the main smart contracts are described in this section: what they do and why. You can find all the addresses of the deployed contracts below:



  • ZoneFactory is the contract that handles the zone creation mechanism through the onTokenTransfer() function.
    We use the EIP1167CloneFactory.sol to deploy new Zone.sol and Teller.sol contract to save gas cost.

  • Once created, you can get the zone contract address through different getters:

mapping(bytes6 => address) public geohashToZone; // get the zone contract if exist
mapping(address => bytes6) public zoneToGeohash; // get the geohash associated with the zone contract
mapping(address => address) public ownerToZone; // get the zone owned from the owner address
mapping(address => address[]) public zoneToAuctionBidders; // get bidder on a zone auction
mapping(address => address) public activeBidderToZone; // get the zone a user address is an active bidder on
  • It's also the contract to listen for all the events going through the protocol. All the zone contracts will emit events through this ZoneFactory.sol contract.



  • Each geohash6 on Earth has its own Zone.sol contract, in charge of managing its ownership and get taxes. There are two kinds of taxes on the Zone.sol contract.
    Zone owner taxes: every day, a zone owner pays 0.04% of what he has staked in DTH to occupy the zone. It's around 15% APR.
    Auction taxes: if a user wants to open an auction on a zone, he needs to pay 4% in DTH tokens to be able to start bidding on this zone.

  • The auction management goes through the onTokenTransfer() function, by sending DTH to the Zone.sol contract, with the info in the _data field.



  • Each geohash6 contract has its associated teller contract. This contract is in charge for managing the teller's information. There is a comment section, supposed to get hash of IPFS comments. The comments are associated with the current teller owner. As a result, if a zone ownership changes, a new comment will not be associated with the old zone owner.



  • This contract handles all actions related to Shops. When a shop registers itself on the map, it's only necessary to use the onTokenTransfer() of this contract.
    It is needed to provide a geohash of 12 characters to determine the shop's position. If this geohash is on a zone where there is no zone owner, the shops stakes 42 DTH without the need to pay any taxes. If the zone is owned by a teller, the shops stakes (a minimum of) the amount of DTH determined by the zone owner and pays to the the zone owner a daily fee of 1/42 of what the shop's staked in DTH.



  • This contract handles the country data. We mapped the entire world by groups of geohash of 4 characters representing a country. Each country group is associated with a ISO country code 2. When a user wants to open a zone, we are able to verify the information by comparing the first 4 characters of the geohash provided if the geohash6 is on an open country.
    Anyone is free to open a new country where they want to operate using the Dether protocol. The Dether team opened a specific list of countries where we decided to operate in our front-end app.



  • This contract handles all the global parameters of the protocol. Only the Voting contract can change these parameters through vote on the DAO. These parameters are global, meaning that they’re related to all countries of the Dether Protocol.
GlobalParams public globalParams =
bidPeriod: 48 hours,
cooldownPeriod: 24 hours,
entryFee: 4,
zoneTax: 4,
minRaise: 6
  • Bid Period
    It represents the time that a zone auction lasts (set by default to 48 hours)

  • Cool down Period
    The cool down period represents the amount of time a seller has to wait before being able to open an auction on a zone that has just been created or auctioned (the cool down period is currently set at 24 hours).

  • Entry fees
    It represents the fees taken in DTH to the seller when he opens an auction. To open or join an auction, a seller must pay an entry fee of (set by default of 4%) of the DTH tokens staked by the current owner.

  • Minimum raise
    It represents the minimum amount to raise when joining an opened auction on a zone. Currently, to open or join an auction, you must always bid at least 6% more than the current highest bid.

  • Zone taxes
    Based on the Harberger tax principles, it represents the daily fee paid by the zone owner on what he has staked in DTH to own the zone. Every 24 hours, zone owners pay a tax of 0.04% to the DAO of their own staked DTH.

mapping(bytes2 => uint256) floorStakesPrices;
  • When a zone is free, tellers need to stake the licensing fees (the minimum being 100 DTH). Currently, the country floor price is set by default at 100 DTH per zone for all countries.
    However, as the economical situation changes from one country to another, the DetherDAO will be able to change it to a minimum of 1 DTH and more per zone. Moreover, the change will be able to occur per country delimited by geohash within the the Dether Protocol smart contract
function withdrawDth(
address _recipient,
uint256 _amount,
string calldata _id
  • All taxes paid in DTH via the Dether Protocol (and that are not going to the zone owner) such as the zone tax, will directly go to the DAO Treasury Fund.
    Dether DAO participants will have the ability to create a proposal and vote on sending these collecting taxes in DTH to any address. As a result, external teams and builders willing to create projects on top of the Dether Protocol will be able to create a proposal in order to be funded in DTH by the Dether DAO via the collected DTH taxes.



  • This is the DAO contract, it handles all the proposals and vote.
enum ProposalKind {GlobalParams, CountryFloorPrice, SendDth}
function createProposal(
ProposalKind _proposalKind,
bytes calldata _proposalArgs
  • There's 3 kinds of proposals you can create, if you own enough WDTH (Wrapped DTH). 50k WDTH from your balance will be locked during the voting period (5 days). They will ba automatically unlock, once execute() is called.
function placeVote(uint256 _proposalId, bool _voteYes)
  • Then all WDTH holder at the proposal time block can vote yes or no on the proposal
function execute(uint256 _proposalId)
  • If the proposal reach enough support, currently 25% quorum on WDTH circulating supply at the proposal creatin block and 60% support, execute() function need to be called.



  • In order to participate in the Voting contract, DTH tokens holders need to wrap their DTH tokens to WDTH, the governance token needed to participate in the Dether DAO.
function deposit(uint256 _amount)
function withdraw(uint256 _amount)
  • Users just need to call deposit() when they want to create a proposals or participate on the next vote or withdraw() to get their DTH back.