Security Series I: Timelock
TL;DR
- Timelocks are crucial for yield farms.
- The Timelock goal is to cool down transactions against the MasterChef.
- They are an extra layer of security against rug pulls and any malicious action.
Introduction
In this series of posts we will try to illustrate which are the most important considerations to take into account when analyzing how secure a yield farm is.
Today, we will focus on one of the most important players of this complex ecosystem: Timelock.
A Yield-Farm can be thought of as a combination of things (such as front-end services, smart contracts and governance tokens among others) where the key player is the MasterChef. This Smart Contract (SC) is the one that actually holds the whole logic of what we call yield farming. It’s the one that knows every liquidity pool of every staking pool being offered and knows how to interact with them. Furthermore, it is the contract where all the assets are going to be stored. In other words, when you stake BNB-BUSD LP Tokens in a yield farm, all those tokens go directly to the MasterChef contract.
Timelock: What’s is it?
So… What’s the Timelock? It’s yet another Smart Contract, part of the farm ecosystem. It’s presence is super important and, as a general recommendation, don’t invest in farms which have no Timelock at all.
To explain the Timelock’s functionality, let’s think about the following situation:
We know that the MasterChef holds all of the farm assets. Furthermore, we know that Smart Contracts usually exposes several sensitive functionalities only callable by the owner of the contract. So what stops the owner of the MasterChef (usually dev of the project) to do nasty things (like, steal all the tokens?). SPOILER ALERT: Nothing!
Here is when the Timelock comes to the rescue. This SC was basically designed to be a layer between the DEV and the MasterChef SC.
The owner of the MC should be the Timelock and the owner (technically is called admin for this SC, not owner but the role is similar) of the Timelock should be the Dev. Now, every time the DEV wants to make some change to the MasterChef SC, it will have to do it through the Timelock.
Timelock: Technical description
In order to better illustrate this part, we are going to use as an example the Goose Finance Timelock (which is the same contract that here at Prism Finance we are going to use in our farm). You can review the source code here.
So.. what does the Timelock do?
The Timelock will basically cool down all transactions performed by the DEV by a fixed time. For instance, if the DEV wants to call transaction X of the MC, they will have to call first the queueTransaction of the Timelock with the corresponding parameters. Then, after a period of time (defined by the delay function), the transaction is able to be executed trough the executeTransaction function of the Timelock. Let’s quickly analyze the source code of both functions:
function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public returns (bytes32) {
[1] require(msg.sender == admin, "Timelock::queueTransaction: Call must come from admin.");
[2] require(eta >= getBlockTimestamp().add(delay), "Timelock::queueTransaction: Estimated execution block must satisfy delay.")...
[4] queuedTransactions[txHash] = true;
The [1] line basically ensures that the calling entity is not other person than the admin itself (usually the dev of the project).
The [2] line basically ensures that the transaction will be executed after a period of time greater than delay.
The [4] line sets the queue state for that transaction inside an internal array, by setting its value to true.
function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public payable returns (bytes memory) {
[1] require(msg.sender == admin, "Timelock::executeTransaction: Call must come from admin.");...
[2] require(queuedTransactions[txHash], "Timelock::executeTransaction: Transaction hasn't been queued.");
[3] require(getBlockTimestamp() >= eta, "Timelock::executeTransaction: Transaction hasn't surpassed time lock.");
The [1] line does the same as the previous function.
The [2] line ensures that the transaction that is being executed was already queued! Otherwise, it will fail.
The [3] line ensures that the transaction has been queued for at least the delay time.
In conclusion, the Timelock SC forces the DEV of the project to queue every transaction they want to execute for a period of time.
This gives time to the farm investors to know what changes are actually going to be applied in the near future. Therefore, if a DEV wants to do a rugpull, all its community will realize about it’s malicious actions before they actually steal the money.
Final words
Having a Timelock is far from saying that a project is safe. There are hundred of things that can happen. Remember that it’s a Smart Contract, which code inside that can do whatever nasty thing they want. Besides a developer with bad intentions, it could happen that the SC (as any other piece of software in the world) has security vulnerabilities that could be leveraged by malicious users.
So, how to be sure the Timelock SC is 100% safe?
It’s really really difficult, in fact, 100% safe it’s almost impossible. However, there are few things that can really ensure that it seems to be legit:
- Read the SC yourself and understand each part.
- Trust on security experts.
The first one will be very difficult if you’re not a developer. Nevertheless, the second is relatively easy to accomplish: The farm must be audited by a well-known auditing company.
Here at Prism Finance, due to we are a fork of Goose finance which is an extensively audited farm, it’s not necessary to go for a second audit. However, we decided to do it anyways so our investors are more comfortable investing in our farms! We are going to talk a bit more about auditing in a future post of the series.
We hope this gives you a better understanding and transparency of the whole ecosystem.
See you in the next post of this Security Series!
Prism, farming made simple.