Tracked Token Timelocks
The Problem
The Paperclip DAO wanted to reward $CLIP to traders that brought NFT trades participating in the DAO's mission. However, we didn't want these tokens to be available to trade or on the open market until the DAO has finished the first set of trades.
If you have these timelocked tokens, they should look fairly normal as a token but missing a few features. Receiving the timelocked tokens you'll see them go into your wallet balance but attempting to send them to a another wallet or approve them for trading will result in an error. The only valid operation for these tokens is to claim them after the claim period has finished: execute the claim() function when the tokens are unlocked. You can see when the unlock is set for in the getTimeUnlock function and claim your tokens after this period with the claim function. A standard front end is coming soon, but etherscan also works well to interact with the token.
We chose to reward ERC20 tokens over NFTs for this exercise since it allowed a clearer stake and fungibility of the DAO, along with the ability to use with snapshot voting, collab.land and others. However, this approach could be expanded to also work with NFTs.
The DAO wanted to trustlessly show that these token balances are owned by those who proposed the clip but couldn’t be sold or handled like a normal token until after the project swapping was over.
The Solution
I first looked into Timelock.sol from OpenZeppelin, however, we wanted to send out many grants and their Timelock contract supported only one grant address and time with no recovery method. Other grant methods required a secret hash reveal and were more complex than we needed. I decided to take inspiration from OpenZeppelin contract and build an approach that fuffilled the DAOs needs.
The original implementation of the token Timelock was a simple custody contract that grants could be added to which would pull the number of granted tokens into the contract and keep track of the grantees. After a timestamp passed on the blockchain, the grantees could retrieve their grants. A secondary timestamp was added for the DAO to recover unclaimed tokens after a reasonable period of time in order to redistribute them as necessary (token lost seed phase, issue with claim etc.) after the grant period.
However, we wanted better discoverability and interaction with tools such as snapshot, collab.land, and Etherscan so grantees could trust that they were actually granted this token. The ERC20 standard methods and events are proxied through the Timelock interface showing as another ERC20 token prefixed with "Timelocked ". This token is completely readonly: the only transfer action that could happen with these tokens was when the grant was claimed the tokens would be burned and replaced with the underlying held asset after the grant lock expiry.
What could this be useful for?
This is a useful tool for startups granting tokens for contractors and as bonuses but don’t want those tokens yet on the market. These tokens can grant community access and are clearly reflected in the wallet of the user. This could also be reflected as a vesting schedule that converts the locked tokens to normal tokens on a time scale.
A community that could use these locked tokens well is FWB. They organize their community into different seasons. Token timelock could allow members to timelock their profile NFTs or their membership tokens ensuring more market stability during seasons for key contributors. FWB could send the token up front to allow access to the community with a one or two season lock period. Then, the locked token from grant could be used to access initiatives and tools within the community without a concern of that token being put on the market until the token unlock. Grants can be for different amounts in the same timelock and user’s granted tokens can also be increased.
Another added benefit of creating the shadow token for this Timelock approach is that a hodler could forget about their grant but then find it in a token tracker and see that the contract has a balance and a claim for them. Additionally, since the token cannot be traded/the grant to address cannot be changed it cannot be used to participate in decentralized finance protocols or be redirected. OpenZeppelin explains this vulnerability of reassignable Timelocks that this contract code solves. It also increases trust in the community both on the side of organizers that liquidity will not be introduced too early but also on the receiver’s side that they can know their grant cannot be retroactively pulled by the granting party.
Looking Ahead
The code is licensed under GPL version 3. The code is available on an as-is basis with no audits or associated warranty. Using this code is entirely at your own risk. Moving ahead, if a team wants to use this code sponsoring an audit of the contracts would be a great first step on making this more production-friendly. Feel free to reach out with any questions.