Cryptorisks Beginners #1 - Custody Risk
What is Custody Risk and what kind of risks can one expect from a protocol that is controlled by multisigs / previleged owners.
Before diving into Custody Risk, here’s a short primer on multisigs.
A primer on multisigs
Multisig (or multi-signature) wallets offer the unique feature called multi-signature transactions. In practice, an on-chain transaction (on Ethereum, for example) can only be sent to the miner if more than one wallets approve and sign that transaction. This technology offers a myriad of use-cases, some of which are detailed in the following.
A couple could hold and manage funds that require a 2-of-2 multisig wallet (so, two independent wallets on the multisig, requiring both parties to sign a transaction).
A family could offer a 2-of-3 multisig for managing their children’s funds, and
A group of entrepreneurs can manage company resources via an m-of-n multisig wallet.
One person owns a multisig, requiring multiple wallets to be compromised to steal user funds: significantly harder than compromising a single wallet. Useful for whales throwing size.
There are several interesting use cases for newer entrants into the world of Decentralised Finance since setting up a multisig wallet is made simple by tried, tested and adopted multisig wallet providers such as Gnosis Safe.
Imagine having a spouse who loves apeing into the latest rug: a multisig can make sure you ape safely together.
Multisigs solve security problems and allow teams to collaborate on how decentralised finance protocols evolve. Multisigs remain one key ingredient in today’s DeFi protocols and secure several tens of billions (of US Dollars) of on-chain value. For example, USDC (or Circle USD, a market cap of 50+ billion USD), an on-chain example of a US-dollar stablecoin, is secured by a set of multisigs for minting, burning and blacklisting on-chain USDC.
Multisigs run modern-day defi, whether some like it or not, and they’re here to stay.
Primer on how defi differs from tradfi
The thing about decentralised finance is that it brings back all the homework you never wanted to do or didn’t even know you had to.
In traditional finance, much of your access to your funds is determined by rules set out by centralised parties (banks, stock trading apps, governments). How these financial systems run is completely abstracted away from the user to focus on one thing alone - yield. Security is not a big priority since the users place unconscious trust assumptions that the government will not rug their funds. In essence, traditional finance is custodial finance wherein the user agrees to a set of rules which can be changed/interpreted arbitrarily by the custodian of their funds. Some of the unfortunate realities of such a system include a government freezing protestor’s bank accounts, stifling dissent and not allowing free speech.
In DeFi, you’re on your own.
If you didn’t read the contract before apeing 10k into a suspicious-looking DeFi protocol that has five users with 1 million in liquidity, some dog-related meme mascot in its front-end, and chances are you can say that 10k goodbye. Gary Gensler cannot save you here since there is no regulation, and you aped into seemingly transparent rules.
Understanding Custody Risk
The European Central Bank defines custody risk as to the following:
The risk of a loss being incurred on securities in custody as a result of a custodian’s insolvency, negligence, misuse of assets, fraud, poor administration or inadequate record-keeping.
If your funds are in a tradfi service, it is by definition custodial and incurs custodial risk. With defi, since smart contracts hold the funds you deposit into them, one could argue if it is custodial or not - after all, there is no human intervention needed for the contract to function usually.
How to avoid custody risk in defi
Depending on the user’s level of knowledge, there are two methods that we propose the users follow for their due diligence into ape-ing into shitcoins.
The easy route.
Defi may be permissionless and open, but it has some of the worst user experience, especially for new entrants. The most common maxim in web3 has been:
Don’t trust. Verify.
… which could be the clearest example of how user-unfriendly crypto really is. More recent entrants cannot be expected to verify if their shitcoins are safu to ape into or not, much less so if they do not possess any technical skill in interpreting these smart contracts. In place of simple verification methods for newer entrants, one could make the following two assumptions:
Most people are risk-averse / favour security.
Birds of the same feather flock together.
1 + 2 leads to:
Generally, the protocol with a high TVL is safer because more liquidity is locked in their smart contracts.
This general logic encompasses all sorts of risks. So if you’re in a pinch and you want to delegate your due diligence to the safety of the crowd, this isn’t such a bad idea. You’re assuming enough people looked into this, which is why the contract is secure
Fair warning: this might not be a reasonable assumption, so please don’t ape irresponsibly if you see contracts with lots of liquidity locked in. We have seen several hundred million USD being stolen from contracts in a snap of a finger.
The technical route
Answer the following questions sequentially.
Does the smart contract have an ‘owner’, i.e. a wallet that controls the smart contract (it could be a liquidity pool, a decentralised bank, etc.)?
If the answer to the above is yes, is the ‘owner’ a single address or a multisig? Usually, it is a multisig. If you find yourself ape-ing into a contract owned by a single address, you need to answer the following questions quickly.
Can the ‘owner’ of the contract touch your funds in any way possible? Can they send your funds to any address they wish? If yes, then exit immediately. If not, then there is one final question to answer.
Can the ‘owner’ of the contract change any property of the contract such that they can rug your funds without needing to transfer them directly? Think of increasing interest rates to infinity and sending the paid interest to an on-chain treasury address that a team multisig controls.
I will demonstrate my workflow for determining custody risk: this is an involved approach and can be seen as a beginner’s guide for more technically-savvy users.
Demo #1 - Curve Finance
Let’s look at one of the most popular contracts in Decentralised Finance: Curve Finance’s 3pool contract. This is a liquidity pool that handles user funds and enables a specialised automated market maker for the three most popular dollar stablecoin assets: USDC (by Circle), USDT (by Tether) and DAI (by MakerDAO). These three stablecoins are behemoths in modern-day DeFi, and for some reason, enough people trust Curve’s 3pool contract to deposit a total of 4 billion of liquidity in it:
So, why do people trust the contract so much? Let’s try to go through our 4 step questionnaire to find out. We will be using Etherscan extensively for this.
Does the contract have an owner?
To find out about this, let’s first check if the contract has an ‘owner’ or an ‘admin’ variable that it stores on-chain. We can access this information under the contracts tab on Etherscan. The variables are accessible under ‘Read Contract’ as shown below:
We then observe that there is indeed an Owner to this contract, which then points to another contract: 0xeCb456EA5365865EbAb8a2661B0c503410e9B347. This is Curve’s pool owner contract.
So, we just established that 3pool indeed has an owner, and it is actually a contract with multiple owners, one of which is a multisig for emergency conditions; the other two are end-contracts that execute the wishes of the Curve DAO.
Is the owner a single address or a multisig: The direct owner of a Curve pool is a contract that subsequently has three admins, two DAO contracts and a multisig address. So, the generic answer would be that pool is somewhat controlled by multisigs.
Knowing this, Can the ‘owner’ of the contract touch your funds in any way possible?
This part is a bit more involved: we will need to look into the contract code to determine the extent that a contract owner can touch user funds. We are specifically looking for privileged access in the contract code. In Vyper, the primary smart contract language used by Curve Core developers, this is achieved by the following statement:
assert msg.sender == self.owner # dev: only owner
Contracts that use the more popular Solidity smart contract language typically adopt the OpenZepplin industry standard for Access Controls:
pragma solidity ^0.5.0;
import "@openzeppelin/contracts/ownership/Ownable.sol";
contract MyContract is Ownable {
function normalThing() public {
// anyone can call this normalThing()
}
function specialThing() public onlyOwner {
// only the owner can call specialThing()!
}
}
So we would look for the onlyOwner
modifier to scope out methods that privileged access, and then look into the contents of the method (I did warn you it would be quite involved).
In the case of 3pool, the methods with privileged access include:
ramp_A
(parameter change only)stop_ramp_A
(parameter only)commit_new_fee
(parameter only)apply_new_fee
(parameter only)revert_new_parameters
(parameter only)commit_transfer_ownership
(parameter only)apply_transfer_ownership
(parameter only)revert_transfer_ownership
(parameter only)withdraw_admin_fees
(touches contract’s token balances)donate_admin_fees
(touches contract’s token balances)kill_me
(parameter only)unkill_me
(parameter only)
Two out of the 12 methods touch token balances, whereas the other methods alter contract variables (hence altering the contract’s behaviour). The method donate_admin_fees
actually gives up any fees the contract owner (which we ascertained was the DAO) collects to the liquidity providers in the pool. On the other hand, withdraw_admin_fees
collects fees accrued by traders to the DAO.
Homework: Figure out how admin fees are calculated by 3pool. Hint: look for exchange method and self.balances variable.
Now, we have ascertained that the owner is a DAO and can only pull out liquidity that was accrued to it by a logic that it controls. This answers the first three questions but leaves out the last one: Can the ‘owner’ of the contract change any property of the contract such that they can rug your funds without needing to transfer them directly? Answering this question requires specific knowledge of the contract and a deeper dive than what is possible in an article aimed at novices. The summary of such an investigation is as follows.
In the case of 3pool, there are few things that can be done by an admin other than claiming fees: killing/unkilling the pool and ramping up and down the amplification coefficient. Killing and unkilling the pool are methods available to the DAO and the emergencyDAO, the latter being a multisig of people who do not work in Curve: https://dao.curve.fi/emergencymembers. The amplification factor changes the pool’s behaviour and offers tighter spreads in swaps but has no real effect on rugging users in any way possible.
So, Curve’s 3pool is safe. Can you give an example of an unsafe contract?
Demo #2 - Platypus Finance
A simple example of an unsafe contract is detailed in the following Twitter thread.
The contracts are written by anonymous/pseudonymous developers of Platypus Finance, who have written in a backdoor to user funds: the owner of the contract has unfettered access to 165 million USD of user funds, rugged in the following manner.
Transfer method with privileged access:
Platypus Finance contracts are written in Solidity. We previously showed examples of privileged functions in solidity smart contracts. What’s interesting in Platypus Finance contracts is the onlyPool modifier, which grants privileged access to a method that allows draining user funds from the contract to any address.
The modifies checks whether msg.sender
is this _pool
address.
The _pool
variable can be set to any address by the contract’s owner. This is a very risky contract to trust since there is a clear path for the owner of the contract to touch a user’s funds (whereas in the previous example, this is impossible). In general, it is wise to avoid such malicious contracts, yet there’s quite some liquidity entrusted to this contract.
Final thoughts …
If you aren’t scared yet, you should be. And yet, DeFi is still worth it. Nothing beats having your funds handled by a time-tested, secure, well audited, autonomous piece of software with clear, transparent rules run on a public blockchain.
That being said, there are real risks involved when the contract you ape into has privileged access to contract methods that can touch your funds or alter the behaviour of the smart contract in any way possible.
It makes sense to do bare minimum due diligence on custody risk. This is perhaps the easiest check to make. Detecting smart contract risk would be the next step.
We hope this article has equipped you with some skills to do your own research!