Daniil Ogurtsov
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # Vulnerable spots of lending protocols In this article we will try to go through core security vulnerabilities common for lending protocol. Lending protocols gathered the long list of hacks, so they can be categorized. The understanding of these vulnerabilities is a perfect tool for an auditor - lending protocol have same vulnerable spots and typical attack vectors. It is a good idea for an auditor to start the analysis from investigating these vectors or, at least, to have these vectors in mind when auditing, as a tool applied to lending protocols. It is applicable both for forked lending protocols and those with unique logic. ## The market overview for an auditor The idea of lending protocols is very straightforward. **1) Users can borrow** You put 1 ETH as collateral (1000$ value) and is allowed to take 700 USDC. Yes, it is required that you borrow less value than your collateral. Is may sound useless, but the usecase is the following: No matter how token prices go - you can get back 1 ETH only if you return 700 USDC. In this sense, a lending protocol allows you fix the price of USDC/ETH. **2) Users can lend** Previously borrowed 700 USDC are not taken from nowhere. Lenders are those who put capital. These tokens are stored on smart contracts, some portion of these token lies untouched, not borrowed by anyone. [Tokens Borrowed] / [Tokens Lent] = is called “Utilization”. “60% Utilization” means that lenders put 10 ETH on smart contract, but borrowers borrowed only 6 ETH. **3) Lenders earn when funds are borrowed** Previously we said that that you should give back 700 USDC to receive your collateralized 1 ETH. Well, it is not so true - be ready to give back 702 USDC. Funds borrowed accrue interest in time, like 6% annually, for instance. These 2 USDC is the earning for lenders, and it is their motivation to provide liquidity. **4) The rate is dynamic and usually (but not always) depends on Utilization** Protocols experiment with the exact formulas. But in the majority of cases the rate rises with the utilization rising. **5) As prices move, protocols protect themselves so that your funds borrowed do not exceed funds collaterized** Market price of your assets changes in time. So the protocol tracks that your value borrowed is not above the value of your collateral. Even worse, not above ~80% of your collateral. This 80% is Max LTV - Max Loan-To-Value coefficient. **6) You can lose your right to repay your borrowed funds to receive your collateral** When the LTV of your position is above Max LTV, liquidation happens. Your collateral is sold and you lose your initial opportunity to receive your 1 ETH for 700 USDC, your position is closed. ### Leverage usecase It is very common for DeFi users to utilize a “folding” strategy. Imagine you have 1000 ETH. You deposit 1000 ETH on Lido and receive 1000 stETH. This is your investment in liquid staking and you will receive gradual returns. Then you put 1000 stETH as collateral on Aave. Then you borrow 700 ETH. Then you deposit them on Lido and receive 700 stETH. Then put 700stETH as collateral on Aave…. … and repeat multiple times. It turns out that you deposited in Lido = 1000 ETH + 700 ETH + 490 ETH …. So you receive “leverage” on your return on Lido. It is simple when you expect that stETH and ETH exchange rate is not volatile. But things become complicated when you have non-correlated assets - little price move would destroy all the folding, as positions will be liquidated. ### Types of projects The audit process for a lending protocol depends on its type. There are two categories: **1) Aave/Compound forks** These projects copy the codebase of Aave or Compound. One of the options for an auditor is to focus on spots where a project is different from Aave or Compound. As practice shows, these differences are usually the targets for a hacker, as they allow new transaction flows, not possible on Aave and Compound. The vast majority of projects are forks, and usually they differentiate with the list of allowed tokens and oracles for these tokens. They are straightforward for security analysis, because: - Aave and Compound code is highly researched in the industry, with many audits done (for Aave and Compound themselves and for their forks). Also, it is likely that an auditor has at least one Aave/Compound fork previously audited in experience. - The majority of lending protocol hacks touched these forks (usually because they introduced new logic, tokens or oracle logic). So auditors are aware of things that attract vulnerabilities. **2) Projects with specifics** They are not forks. They introduce new mechanics. Auditors treat such a project just as a DeFi project, in general, meaning the whole set of audit instruments and practices is helpful here. By the way, common attacks on Aave/Compound forks are still an issue here, as we have the same attack vectors possible here. So it is a great practice trying to prove a project is secure from these attacks. Here are some examples of projects in this category: - Projects with the factory allowing to build isolated markets. Imagine that the project can create a few smaller mini-Aaves and mini-Compounds. They have different lists of tokens, and their liquidity is separated. In isolated markets risks of assets in one market has no effect on other markets and the whole system. (Fuse from Rari Capital) - Projects working with isolated pairs. They are like isolated markets, but only with two tokens: one token is allowed for borrowing&lending, and the second token accepted as collateral (Fraxlend, Kashi from Sushi) - Projects introducing fixed rates (Examples: Notional Finance) and etc. # Common attack vectors The overall idea for all hacks is to borrow more, than was deposited. Every type of attack is a technique to achieve this. ## Oracle attacks In this type of attacks the goal is the same - to borrow more than deposited. But in this category attackers try to make the protocol think that the value deposited is high, or that the value borrowed is low. It is a success if an attacker deposits 1000 USD, but oracle manipulations make a protocol think that 5000 USD was deposited. In will allow to borrow 3000 USD value, and LTV check will pass. The most obvious issues happen when a protocol takes prices from Uniswap pairs either by getReserves() or by balanceOf(). This is a redflag in the majority of cases. Even beginner hackers know that it easy to take a flashloan and set any price in the pair - either very high or extremely low. Only very old projects did such mistakes, or scammy projects with low liquidity. But, when analyzing the biggest Lending hacks you may find that the mispriced assets are **LP tokens** or shares in vaults. Lets take the Warp Finance as an example. [https://rekt.news/warp-finance-rekt/](https://rekt.news/warp-finance-rekt/) Warp Finance allowed LP tokens to be deposited as collateral. LP tokens usually are not so liquid, so protocol introduce some logic to price these tokens. In Warp the team calculated LP token price as [Pair TVL] / [LP tokens minted]. Sounds quite reasonable, but this was the bad idea for a Uniswap pair. Uniswap pair keeps k constant, but TVL is not guaranteed to remain constant. The TVL formula was = (reserve0 * price0) + (reserve1 * price1). The team took secure price feeds (TWAP). Also, k is always constant, but the whole TVL return can go up and down dramatically when large swaps happen. ![](https://i.imgur.com/WKNsfVP.png) Source: [https://cmichel.io/pricing-lp-tokens/](https://cmichel.io/pricing-lp-tokens/) So that is what happened - the hacker took flashloan and manipulated the TVL calculation for the pair, effecting the LP token value. This issue is perfectly explained here: [https://cmichel.io/pricing-lp-tokens/](https://cmichel.io/pricing-lp-tokens/) You can find the same idea but with more complex steps in lending projects that accepted shares of vaults at Yearn. Lets take CREAM. CREAM had multiple of attacks, and one of them is related to yUSD - vault share, an LP token with the simple stablecoin strategy on Curve. [https://mudit.blog/cream-hack-analysis/](https://mudit.blog/cream-hack-analysis/) CREAM used yUSD.pricePerShare() to receive the value of yUSD. Function logic is straightforward = [TotalUnderlyingInPool] / [TotalSupplyShares]. The only option to manipulate this formula is to increase TotalUnderlyingInPool. Is may seem that it is one way operation - anyone can transfer tokens to the pool, but there is no way to extract tokens from the pool, so the operation is complicated. But it is not. One can flashloan millions to deposit funds to Yearn and become the biggest Yearn vault investor, so that to withdraw the proportional share of token in anytime. So these prerequisites allow anyone to manipulate the return of pricePerShare(). Check some other hacks based on wrong token evaluation: - Inverse Finance [https://halborn.com/explained-the-inverse-finance-hack-june-2022/](https://halborn.com/explained-the-inverse-finance-hack-june-2022/) - Cheese Bank [https://peckshield.medium.com/cheese-bank-incident-root-cause-analysis-d076bf87a1e7](https://peckshield.medium.com/cheese-bank-incident-root-cause-analysis-d076bf87a1e7) **Recommendations when auditing:** 1) strictly check the price source for all tokens - you should be confident that no element in the formula can be manipulated. 2) use Chainlink oracle 3) use TWAP price when Chainlink price is not available (but it is bad advice in some cases, check the following chapter) ### **On using TWAP as the price feed** The price from TWAP is hardly manipulated in one transaction and block. But being atomic is not the requirement for an attacker. TWAP is just a formula using onchain sources, and it is the question of time and cost to attack TWAP. Here is an article researching the cost of TWAP attacks. [https://eprint.iacr.org/2022/445.pdf](https://eprint.iacr.org/2022/445.pdf) To sum up, attack on TWAP for low liquidity tokens can be profitable. Lets take a look on Inverse Finance attack example: [https://twitter.com/FrankResearcher/status/1510239094777032713?s=20&t=RBNXo-6wEDCiBE5a9nO0-Q](https://twitter.com/FrankResearcher/status/1510239094777032713?s=20&t=RBNXo-6wEDCiBE5a9nO0-Q) In this hack no flashloan is used, and the attacker had to use own 901 ETH. This attack is not available for everyone, but still an option for some DeFi users. It cost 500 ETH to change the value of the collateral and borrow 15M USD when only 0.65M USD in INV tokens was deposited. The same hack happened with Moola. [https://www.coindesk.com/markets/2022/10/19/celo-protocol-moola-market-loses-over-10m-in-market-manipulation-attack/](https://www.coindesk.com/markets/2022/10/19/celo-protocol-moola-market-loses-over-10m-in-market-manipulation-attack/) Take a look at the price chart - that is a good representation how the TWAP manipulation happens in time. ![](https://i.imgur.com/ogqgPuT.png) So be aware, that using TWAP is not always helpful. But sometimes it is necessary when no better price feed is available. For such a case the cost of attack must be taken into account. It is ok, when the cost of the attack is more than potential returns, so that any TWAP attack will be unprofitable. Also, TWAP can work different in different context. For instance, the aforementioned Warp Finance used TWAP correctly, for a pair with much liquidity (ETH/DAI). But Warp Finance used the TWAP price to calculate the value of LP token. Reserves still still left manipulated, as well as the overall TVL calculation (based on reserves * price). ## Reentrancy with hookable tokens This is one of the most common types of hacks. It happens when one of the token on a protocol is hookable. Imagine the protocol that accept USD as collateral and allows borrowing in hookUSD (with hooks). Hookable tokens in the majority cases follow ERC-777 standard: [https://eips.ethereum.org/EIPS/eip-777](https://eips.ethereum.org/EIPS/eip-777) Its transfer functions include three steps: - call token sender before balance change - apply balance change - call token receiver after balance change These calls (hooks) are optional, and the call receiver must allow these calls. In our case - an attacker will definitely allow these calls to the token sender. The flow without an attack will work this way: ![](https://i.imgur.com/IUhCx1z.png) After the hook, an attacker can call any protocol function once again. The goal is to bypass the LTV check. So the attacker calls Borrow once again during the hook. The first Borrow call is still not complete, and token transfer still have not changed balances. So the LTV check will pass, because the protocol has not transferred any tokens yet, so the attacker still has not borrowed anything (if observing the balances). ![](https://i.imgur.com/ttaMBhJ.png) So, any hook with call to Borrow allows to bypass multiple LTV checks. After all hooks the cascade of balance changes happen and the hacker will see the balance 700 * (Number of hooks). This is the simplest example of using hookable tokens for hacks. In practice, they can have different forms. Check the list of some selected examples with the detailed hack descriptions: - CREAM hack [https://blog.merklescience.com/hacktrack/hack-track-analysis-of-cream-finance-hack](https://blog.merklescience.com/hacktrack/hack-track-analysis-of-cream-finance-hack) - Fei Rari (Hook on ETH sending) [https://www.certik.com/resources/blog/6LiXVtPQ8q5AQfqOUPnTOS-revisiting-fei-protocol-incident](https://www.certik.com/resources/blog/6LiXVtPQ8q5AQfqOUPnTOS-revisiting-fei-protocol-incident) - Ola Finance [https://twitter.com/peckshield/status/1509431646818234369](https://twitter.com/peckshield/status/1509431646818234369) - Aagave [https://rekt.news/agave-hundred-rekt/](https://rekt.news/agave-hundred-rekt/) - Hundred Finance [https://rekt.news/agave-hundred-rekt/](https://rekt.news/agave-hundred-rekt/) - Lendf.me [https://slowmist.medium.com/slowmist-details-of-lendf-me-reentrancy-attack-3e168ab5f2b1](https://slowmist.medium.com/slowmist-details-of-lendf-me-reentrancy-attack-3e168ab5f2b1) **Recommendations when auditing:** 1) observe the code as if all tokens transferred are potentially hookable (this will help to identify vulnerable spots) 2) recommend clients to avoid hookable tokens at all 3) take in mind that ETH transfer can be a hook in some cases 4) insist on following check-effect-interaction pattern (but it will not help in all cases) 5) reentrancy protection is likely a good choice ## Summary In this article we categorized major security incidents that lending protocols experienced in last years. Two crucial spots to deep analysis are 1) oracles and 2) listed tokens. Having a special focus on these vectors is a perfect investment of efforts during audits.

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully