Proposed Trustless DAO Design

The Trustless Team
July 21, 2022
The Trustless DAO has several design constraints: 

  • Lockups: Everyone has lockups, including creators, builders, users, etc.
  • Immediate Rewards: Some portion of tokens rewarded are available immediately and are not subject to lockup, allowing holders to trade the protocol token freely. 
  • Voting Incentives: There is token inflation for voting for or against a proposal to incentivize participation in the process. 
  • Voting Incentive Alignment: Only tokens locked into the DAO contract can be used to vote. This means that to vote in governance and earn inflation rewards, one must be long-term incentive aligned with the protocol's success.
  • Quorum: In order for a proposal to be successful, the yes votes need to outweigh the no votes, and there must be at least a certain threshold of yes votes.
  • Perpetual Foundation Funding: Every time the protocol mints a protocol token for any reason, some percentage (likely 20% of that value) is minted to the foundation. This ensures that the foundation will always be at least minimally funded and able to support the protocol.
  • Fully decentralized governance: Anyone can participate in the governance process, and those who control some threshold of voting power can propose new resolutions.
  • Continuous unlocks: At all times, users can claim more locked tokens. This means that there are no cliffs to coordinate selling tokens. 
  • Instant execution: for a strictly limited amount of time, passing proposals can be instantly executed. This means that early on when there are more likely to be bugs, a fix can be proposed, voted on, and implemented within minutes if the required votes can be quickly collected. 

The Problem

The following paragraphs are highly logically technical. Feel free to skip to the "Proposed Solution" section. 

Creating a governance DAO that meets all of these requirements is conceptually simple. However, there are some technical design challenges due to how solidity works. Implicit in the above requirements is the following requirement: Any time someone wants to withdraw locked tokens, the protocol needs to look back at every single time tokens were allocated to a user account and calculate what portion of those tokens are now available due the passage of time, and add all of those up. Then when the user withdraws tokens, it is not clear which "allocation event" those withdrawn tokens come from. Once a corresponding allocation event is decided due to some optimization, the additional data of how many tokens were claimed needs to be stored for each allocation event. The protocol could create a virtually infinite number of allocation events if the user is actively claiming rewards whenever they are available. Depending on the allocation events chosen for a withdrawal event, the system may need to look back through years of allocation events every time a user claims some of their tokens.

Implementing this system to these implicit requirements is complex, bug-prone, and would take a vast amount of on-chain computation and storage, making the protocol more expensive to use. A couple of quick shortcuts to alleviate, but not solve, the drawbacks come to mind: 

  • Batch allocation events by day instead of by second. (The finest time interval on Ethereum-based block-chains is one second). This means there are no more than 365 allocation events to look through for a given one-year period. That is still a considerable number of potential allocation events while still creating some small cliffs for users. You could imagine a user setting up a script to claim and sell tokens every day at the same time and providing that script to other users, in which case there is a "small cliff" every day. 
  • Batch allocation events by week. This would mean at most 52 allocation events per year to process but would create a cliff weekly. 
  • Batch allocation events by month. This would mean at most 12 allocation events per year to process, but would create a cliff monthly. 

By this time, we can see a clear zero-sum tradeoff: larger batches mean realistic computational (and monetary cost) complexity but larger cliffs. Another solution comes to mind: 

  • Batch allocation events by month, meaning at most 12 allocation events per year, offset the day at which someone can claim tokens relative to the start of that month based on the remainder of the account address divided by 30. This would create a pseudo-random day offset, meaning that people generally have different "cliffs" throughout the month. We call this "pseudo-random" because anyone could manipulate the outcome by creating a few addresses to find one that corresponds to a day offset they like and using that one in the system. 

The Proposed Solution

None of these options or tradeoffs seem great. Either you have big cliffs, or you have more expensive and computationally intensive transactions, and regardless you have high complexity code with a high risk of bugs. What if we try something completely different? This is a solution with its own set of tradeoffs but also has its own potentially desirable characteristics. 

Store three values per user account: 

  • count of unlocked tokens available instantly
  • the last time that a user claimed locked tokens
  • count of tokens locked long term

When the protocol allocates tokens to a user: 

  • 20% are allocated to the instantly available count, 
  • 80% are allocated to the locked token number, and 
  • 20% more are minted to the foundation. 

If this is the first time the account has received an allocation, the protocol sets the "last time tokens claimed" variable to the current time. If the user has received an allocation before, the count is increased only. 

The user can then claim instantly available tokens at any time but is no longer able to vote with them and earn voting rewards with them. The user can claim long-term locked tokens at any time. The locked token count available uses a simple algorithm. All locked tokens are available after two years since the last time tokens were claimed. If the time since the last time tokens were claimed is less than two years, a proportional number of tokens are available. For example, if the count of tokens locked is 100 and it's been one year since the user last claimed tokens, then 50 tokens are available to claim. When the user claims those tokens, they can no longer vote/earn voting rewards with them, AND the last time tokens were claimed number is updated. 

This is far easier to implement without making any mistakes and is less gas, storage, and computation expensive. However, this also has some interesting characteristics, which can be illustrated by example: 

The Proposed Solution by Example

A user was allocated 125 tokens one year ago. Twenty-five tokens are instantly available and can be withdrawn at any time. The user is eligible to withdraw 50 of the remaining tokens since one year has passed. If they wait another year, they can withdraw 100 tokens AND all additional tokens earned during that time through voting or protocol participation. If they withdraw 50 tokens now, they will have 50 remaining tokens locked with a start date of NOW, so they will have to wait another two years to claim those 50 tokens and any additional tokens they earn during that time. If in another year they withdraw 25 tokens, they will have to wait another two years to withdraw the remaining 25 tokens, for a total of four years for 100 tokens. If they had waited two years, they would have received all 100 tokens in two years, along with voting inflation rewards on all 100 tokens. 


This proposed DAO structure incentivizes people to hold tokens for the longer term and to vote with them, aligning the user's incentives with the protocol. In addition, this solution is simple to implement and cheap to execute on-chain. If the user wants more tokens earlier, they can have them, which means that the remaining tokens will be locked up for longer. They will therefore be disincentivized to abandon the project or make poor governance decisions due to the remaining value locked. Aligning incentives is what the block-chain is built for.

What are your thoughts? Do you have an alternative solution? Share them in Discord and help shape the Trustless DAO!

Next: DAO Design Update >