Privacy Policy

Terms of Service

Refund Policy

Aave

Aave

Aave

Aave Aave Aave Aave

Aave

Skip to main content

Slay, Yeoja-Boss!: The Misuse of AAVE in Modern K-Pop Culture

Slay, Yeoja-Boss!: The Misuse of AAVE in Modern K-Pop Culture

Author: Phoebe Ham
Advisor: Prof. Kira Hall, TA Forest Stuart
Class: LING 1000: Language in US Society
Semester: Fall 2022
LURA 2023

In recent years, the popularity of Korean pop sensations such as BTS and BLACKPINK has blown up and expanded well past the continent from which they originated, taking over streaming services, award shows, and more. As more and more k-pop groups appeal to Western audiences and seek out global acknowledgment, foreign fans, especially in the United States, find themselves unable to ignore this versatile genre of music. However, a large number of newer fans and “locals”–people who are not proclaimed fans of said groups–are unaware of the racist past attributed to many Korean artists working within this genre of music.

K-pop idols such as Im Changkyun of Monsta X (known by his stage name I.M) and Jessi Ho (known as Jessi) are two examples of Korean American k-pop entertainers whose work I studied for this LING 1000 project, as pictured in the photographs below.

In-text image 1

I.M was born in South Korea but moved to Boston, Massachusetts, where he spent most of his early life before moving back to South Korea. As one of the lyricists and producers for the group, he writes most of his own raps, many of which are littered with misused and out of place features of what linguists call AAVE (African American Vernacular English). It can be assumed that I.M includes AAVE phrases like “Fantastic, that’s me ‘cause I slay,” “Yo, I go loco… check my flow,” “... no cap, cap (no cap),” and “I ain’t got no limit” in the songs “ FANTASIA ” and “ Rush Hour ” to attempt to fit into African American hip hop culture. Many Korean rappers find inspiration in this genre, even going so far as to mimic their style as well as their language.

Although I.M is not viewed as an offender in the area of cultural appropriation, Jessi has been accused of blackfishing throughout her entire musical career. Jessi was born in New York City and raised in New Jersey, and in interviews with other Korean-American idols she retains a classic Jersey accent. It can be presumed that this is her natural way of speaking. For instance, in the pronunciation of certain words, such as “sauce,” she fully embraces said Jersey accent and accentuates the medial vowel sound so that the standard pronunciation  /sɑs/ (in IPA transcription)  sounds more like /sɔːs/. This is a common trait of New Jersey accents. However, in a video with the FO Squad, all of whom are African American, she speaks differently, with what some call a “blaccent.” She starts using AAVE terms more frequently, such as “bish” instead of “bitch” and “ya” instead of “you.” This is reminiscent of the vocabulary she uses in her songs, as heard in “ Cold Blooded ” and “ ZOOM .” In these songs she frequently uses slang that originated in African American culture alongside syntactic features identified for AAVE, such as the double negative and zero copula. She also makes strong use of what sociolinguists call /aɪ/ monophthongization, common to both Southern and AAVE accents, so that words like “right” sound more like “raht.”

Interestingly enough, although I.M was born in Boston, he retains little to no signs of a classic Boston accent. According to Wolfram and Schilling, the unmistakable Boston accent was “established by emigrants” originally from Southeastern England (Wolfram and Schilling, 2016, pp. 28). A classic Boston accent includes certain pronunciations and elongation of vowels, as well as the elimination of consonants depending on the exact word. In an interview with Zach Sang from late 2021, Sang questions I.M on his unique accent, which surprisingly has no discernible​ nods to his childhood dialect. I.M lacks the dropping of the postvocalic [r] that originated from the initial rhotic British-English dialects, and instead sounds more ‘Australian,’ as stated by Sang. Interestingly enough, Boston is not particularly known for having a large African-American community, and AAVE features are not included in the classic Boston accent. This brings up the question of where he discovered AAVE: Why does I.M choose to use AAVE in his songs when he did not grow up in an AAVE-speaking community? To clarify, both I.M and Ho codeswitch between standard English and AAVE to an extent, depending on whether they’re on or off stage. However, while I.M’s speaking voice retains no hints of the frequent (mis)use of AAVE that he uses in his performing voice, Ho’s does the opposite. Ho uses terms that originated in AAVE in her every day speech, though it seems to heighten even more when she is around African American individuals, such as in the video with the Fo Squad.

Though I.M and Ho are not the only offenders of misusing AAVE in their music, they are two of the most obvious examples. Other idols that are fluent in English, such as Bang Chan of Stray Kids, Huh Yunjin of LE SSERAFIM, and Yoon Keeho of P1Harmony are also well-known in terms of their use of AAVE and cultural appropriation. Linguistically, it seems that multiple American English-speaking k-pop idols raised in the United States seem to be comfortable with the insensitivity that comes with cultural appropriation, much more than those who were born and raised in the non-English speaking country of Korea. However, this difference could also point towards the popularization of AAVE terms in Generation Z vocabulary, as younger idols of the newest k-pop generation are often seen as quirky and relatable because of their use of AAVE.

​The roots of linguistic cultural appropriation and disrespect in k-pop go all the way back to the beginnings of the music genre. Their hold on newer generations of k-pop idols has only deepened in recent years. Although it is debatable whether or not the linguistic choices of these idols is offensive, it is undeniable that the language practices identified in this blog perpetuate deep ties to stereotypes of African-American English, both within the genre and the k-pop industry itself.


Image credit

https://www.youtube.com/watch?v=AQ0tR4RXMHY

References

  1. Wolfram, W., & Schilling, N. (2016). Why Dialects? In American English: Dialects and

    Variation (3rd ed., pp. 27–34). John Wiley and Sons, Inc.

  2. Zach Sang Show. (2021, December 15). Monsta X Talks The Dreaming Album & Movie, Success, Recording In Different Languages & More! [Video]. YouTube. https://www.youtube.com/watch?v=UTw_nkADesg

  3. Labov, W. (2006). 13. The Social Stratification of (r) in New York City Department Stores. In The Social Stratification of English in New York City (pp. 168–179). essay, Cambridge University Press.

  4. Irwin, P., & Nagy, N. (2007, October). University of Pennsylvania Working Papers in Linguistics . Penn Libraries. Retrieved December 5, 2022, from https://repository.upenn.edu/cgi/viewcontent.cgi?article=1009&context=pwpl

  5. DIVE Studios / 다이브 스튜디오. (2020b, September 9). Catching Up: Jessi ( 제시) (FULL Episode) I KPDB Ep. #73 [Video]. YouTube. https://www.youtube.com/watch?v=uB8Gzw9wSwg

  6. Lippi-Green, R., Barrett, R., Cramer, J., & McGowan, K. B. (2023). English With An Accent: Language, Ideology and Discrimination in the United States . Routledge.


?> Slay, Yeoja-Boss!: The Misuse of AAVE in Modern K-Pop Culture | Department of Linguistics | University of Colorado Boulder

Privacy Policy

Terms of Service

Refund Policy

Aave

Aave

Aave

Aave Aave Aave Aave

Aave

Skip to main content

Slay, Yeoja-Boss!: The Misuse of AAVE in Modern K-Pop Culture

Slay, Yeoja-Boss!: The Misuse of AAVE in Modern K-Pop Culture

Author: Phoebe Ham
Advisor: Prof. Kira Hall, TA Forest Stuart
Class: LING 1000: Language in US Society
Semester: Fall 2022
LURA 2023

In recent years, the popularity of Korean pop sensations such as BTS and BLACKPINK has blown up and expanded well past the continent from which they originated, taking over streaming services, award shows, and more. As more and more k-pop groups appeal to Western audiences and seek out global acknowledgment, foreign fans, especially in the United States, find themselves unable to ignore this versatile genre of music. However, a large number of newer fans and “locals”–people who are not proclaimed fans of said groups–are unaware of the racist past attributed to many Korean artists working within this genre of music.

K-pop idols such as Im Changkyun of Monsta X (known by his stage name I.M) and Jessi Ho (known as Jessi) are two examples of Korean American k-pop entertainers whose work I studied for this LING 1000 project, as pictured in the photographs below.

In-text image 1

I.M was born in South Korea but moved to Boston, Massachusetts, where he spent most of his early life before moving back to South Korea. As one of the lyricists and producers for the group, he writes most of his own raps, many of which are littered with misused and out of place features of what linguists call AAVE (African American Vernacular English). It can be assumed that I.M includes AAVE phrases like “Fantastic, that’s me ‘cause I slay,” “Yo, I go loco… check my flow,” “... no cap, cap (no cap),” and “I ain’t got no limit” in the songs “ FANTASIA ” and “ Rush Hour ” to attempt to fit into African American hip hop culture. Many Korean rappers find inspiration in this genre, even going so far as to mimic their style as well as their language.

Although I.M is not viewed as an offender in the area of cultural appropriation, Jessi has been accused of blackfishing throughout her entire musical career. Jessi was born in New York City and raised in New Jersey, and in interviews with other Korean-American idols she retains a classic Jersey accent. It can be presumed that this is her natural way of speaking. For instance, in the pronunciation of certain words, such as “sauce,” she fully embraces said Jersey accent and accentuates the medial vowel sound so that the standard pronunciation  /sɑs/ (in IPA transcription)  sounds more like /sɔːs/. This is a common trait of New Jersey accents. However, in a video with the FO Squad, all of whom are African American, she speaks differently, with what some call a “blaccent.” She starts using AAVE terms more frequently, such as “bish” instead of “bitch” and “ya” instead of “you.” This is reminiscent of the vocabulary she uses in her songs, as heard in “ Cold Blooded ” and “ ZOOM .” In these songs she frequently uses slang that originated in African American culture alongside syntactic features identified for AAVE, such as the double negative and zero copula. She also makes strong use of what sociolinguists call /aɪ/ monophthongization, common to both Southern and AAVE accents, so that words like “right” sound more like “raht.”

Interestingly enough, although I.M was born in Boston, he retains little to no signs of a classic Boston accent. According to Wolfram and Schilling, the unmistakable Boston accent was “established by emigrants” originally from Southeastern England (Wolfram and Schilling, 2016, pp. 28). A classic Boston accent includes certain pronunciations and elongation of vowels, as well as the elimination of consonants depending on the exact word. In an interview with Zach Sang from late 2021, Sang questions I.M on his unique accent, which surprisingly has no discernible​ nods to his childhood dialect. I.M lacks the dropping of the postvocalic [r] that originated from the initial rhotic British-English dialects, and instead sounds more ‘Australian,’ as stated by Sang. Interestingly enough, Boston is not particularly known for having a large African-American community, and AAVE features are not included in the classic Boston accent. This brings up the question of where he discovered AAVE: Why does I.M choose to use AAVE in his songs when he did not grow up in an AAVE-speaking community? To clarify, both I.M and Ho codeswitch between standard English and AAVE to an extent, depending on whether they’re on or off stage. However, while I.M’s speaking voice retains no hints of the frequent (mis)use of AAVE that he uses in his performing voice, Ho’s does the opposite. Ho uses terms that originated in AAVE in her every day speech, though it seems to heighten even more when she is around African American individuals, such as in the video with the Fo Squad.

Though I.M and Ho are not the only offenders of misusing AAVE in their music, they are two of the most obvious examples. Other idols that are fluent in English, such as Bang Chan of Stray Kids, Huh Yunjin of LE SSERAFIM, and Yoon Keeho of P1Harmony are also well-known in terms of their use of AAVE and cultural appropriation. Linguistically, it seems that multiple American English-speaking k-pop idols raised in the United States seem to be comfortable with the insensitivity that comes with cultural appropriation, much more than those who were born and raised in the non-English speaking country of Korea. However, this difference could also point towards the popularization of AAVE terms in Generation Z vocabulary, as younger idols of the newest k-pop generation are often seen as quirky and relatable because of their use of AAVE.

​The roots of linguistic cultural appropriation and disrespect in k-pop go all the way back to the beginnings of the music genre. Their hold on newer generations of k-pop idols has only deepened in recent years. Although it is debatable whether or not the linguistic choices of these idols is offensive, it is undeniable that the language practices identified in this blog perpetuate deep ties to stereotypes of African-American English, both within the genre and the k-pop industry itself.


Image credit

https://www.youtube.com/watch?v=AQ0tR4RXMHY

References

  1. Wolfram, W., & Schilling, N. (2016). Why Dialects? In American English: Dialects and

    Variation (3rd ed., pp. 27–34). John Wiley and Sons, Inc.

  2. Zach Sang Show. (2021, December 15). Monsta X Talks The Dreaming Album & Movie, Success, Recording In Different Languages & More! [Video]. YouTube. https://www.youtube.com/watch?v=UTw_nkADesg

  3. Labov, W. (2006). 13. The Social Stratification of (r) in New York City Department Stores. In The Social Stratification of English in New York City (pp. 168–179). essay, Cambridge University Press.

  4. Irwin, P., & Nagy, N. (2007, October). University of Pennsylvania Working Papers in Linguistics . Penn Libraries. Retrieved December 5, 2022, from https://repository.upenn.edu/cgi/viewcontent.cgi?article=1009&context=pwpl

  5. DIVE Studios / 다이브 스튜디오. (2020b, September 9). Catching Up: Jessi ( 제시) (FULL Episode) I KPDB Ep. #73 [Video]. YouTube. https://www.youtube.com/watch?v=uB8Gzw9wSwg

  6. Lippi-Green, R., Barrett, R., Cramer, J., & McGowan, K. B. (2023). English With An Accent: Language, Ideology and Discrimination in the United States . Routledge.


?> Aave - Decentralized Liquidity Protocol for Lending and Borrowing Crypto Assets

Aave is the Leading Decentralized Lending Protocol Revolutionizing DeFi

Aave is one of the most innovative and influential decentralized finance protocols in the cryptocurrency ecosystem. Since its inception, Aave has transformed how users interact with digital assets by enabling permissionless lending and borrowing without traditional financial intermediaries. This comprehensive guide explores everything you need to know about Aave, from its fundamental mechanics to its advanced features that have made it a cornerstone of the DeFi landscape.

Understanding What Aave Represents in Decentralized Finance

Aave is a non-custodial liquidity protocol that allows users to participate as depositors or borrowers. Depositors provide liquidity to the market to earn passive income through interest, while borrowers can obtain loans in either overcollateralized or undercollateralized fashion. The name Aave comes from the Finnish word for ghost, symbolizing the protocol's commitment to creating a transparent and open infrastructure for decentralized finance.

What makes Aave particularly revolutionary is its approach to decentralization. Unlike traditional banks where a central authority controls all lending decisions, Aave operates through smart contracts on the Ethereum blockchain and other networks. This means that Aave functions autonomously, with rules encoded directly into the protocol rather than enforced by human administrators.

The Historical Journey of Aave

Aave was originally launched as ETHLend in 2017 by Stani Kulechov. The initial concept focused on peer-to-peer lending, but the team quickly recognized the limitations of this model. In 2018, the project rebranded to Aave and pivoted to a liquidity pool model, which proved far more efficient and scalable. This strategic shift positioned Aave to become one of the dominant forces in decentralized lending.

The evolution of Aave continued with the launch of Aave V2 in December 2020, introducing features like credit delegation, flash loans optimization, and improved gas efficiency. Subsequently, Aave V3 launched in March 2022, bringing even more sophisticated capabilities including cross-chain functionality, high-efficiency mode, and isolation mode for new assets.

How Aave Works: Core Mechanics Explained

Aave operates through a system of liquidity pools where users can deposit various cryptocurrency assets. When you deposit assets into Aave, you receive aTokens in return. These aTokens represent your deposit plus accumulated interest and can be redeemed at any time for the underlying assets. The interest rates on Aave are determined algorithmically based on supply and demand dynamics within each pool.

Supplying Assets on Aave

When users supply assets to Aave, they contribute to the liquidity available for borrowers. In exchange, suppliers receive aTokens that accrue interest in real-time. The beauty of Aave's design is that your aToken balance increases continuously as interest accumulates, providing a seamless earning experience. Suppliers on Aave can withdraw their assets at any time, assuming there is sufficient liquidity in the pool.

Borrowing Through Aave

Borrowing on Aave requires users to first deposit collateral. The amount you can borrow depends on the collateral factor of your deposited assets and the loan-to-value ratios established by Aave governance. Aave offers both stable and variable interest rate options, giving borrowers flexibility in managing their positions. The stable rate provides predictability, while the variable rate may offer lower costs during certain market conditions.

Innovative Features That Set Aave Apart

Aave has introduced several groundbreaking features that distinguish it from other lending protocols. These innovations have not only enhanced the user experience but have also expanded the possibilities within decentralized finance.

Flash Loans: Aave's Revolutionary Invention

Aave pioneered the concept of flash loans, which are uncollateralized loans that must be borrowed and repaid within a single blockchain transaction. This innovation by Aave has enabled entirely new use cases in DeFi, including arbitrage opportunities, collateral swaps, and self-liquidation strategies. Flash loans on Aave require no upfront collateral because the smart contract ensures that if the loan is not repaid within the same transaction, the entire operation is reversed.

Credit Delegation on Aave

Aave introduced credit delegation, allowing depositors to delegate their credit lines to other users. This feature enables trusted parties to borrow without posting their own collateral, using the delegator's deposited assets as backing instead. Credit delegation on Aave opens possibilities for undercollateralized lending within a trustless framework, representing a significant step toward more capital-efficient DeFi systems.

Efficiency Mode in Aave V3

Aave V3 introduced E-Mode, or efficiency mode, which allows borrowers to extract higher borrowing power when supplying and borrowing correlated assets. For example, if you supply stablecoins and borrow other stablecoins on Aave, E-Mode can provide significantly higher loan-to-value ratios because the price correlation between these assets reduces liquidation risk.

The Aave Token and Governance System

Aave operates with its native governance token, also called AAVE. This token serves multiple purposes within the ecosystem. Holders of AAVE can participate in governance decisions, voting on proposals that affect the protocol's parameters, supported assets, and future development direction. The decentralized governance of Aave ensures that the community has a direct say in how the protocol evolves.

Staking AAVE in the Safety Module

Aave features a Safety Module where AAVE holders can stake their tokens to secure the protocol. Stakers in the Aave Safety Module earn rewards for providing this security backstop. In the event of a shortfall event, up to thirty percent of staked AAVE can be slashed to cover the deficit. This mechanism aligns the incentives of token holders with the security of the Aave protocol.

Governance Proposals and Voting

The governance process on Aave involves several stages, from initial discussion to on-chain voting. Community members can submit Aave Improvement Proposals covering various aspects of the protocol. The transparent governance structure of Aave has resulted in numerous successful upgrades and parameter adjustments driven entirely by community consensus.

Aave Across Multiple Blockchain Networks

While Aave originally launched on Ethereum, the protocol has expanded to multiple blockchain networks. Aave is now available on Polygon, Avalanche, Arbitrum, Optimism, and several other chains. This multi-chain presence allows Aave to serve users who prefer different networks, often offering lower transaction fees and faster confirmation times compared to Ethereum mainnet.

Cross-Chain Functionality with Aave V3

Aave V3 introduced portals, a feature designed to facilitate cross-chain liquidity flow. This capability allows Aave to maintain liquidity efficiency across different networks, enabling users to seamlessly move positions between chains. The cross-chain architecture of Aave represents a significant advancement in making DeFi more accessible and interconnected.

Security Measures and Risk Management on Aave

Security is paramount for Aave, and the protocol employs multiple layers of protection. Aave has undergone numerous security audits from leading firms in the blockchain security space. Additionally, Aave maintains a bug bounty program that incentivizes security researchers to identify and report vulnerabilities responsibly.

Liquidation Mechanisms

Aave implements robust liquidation mechanisms to protect the protocol from bad debt. When a borrower's health factor falls below one, their position becomes eligible for liquidation. Liquidators on Aave can repay a portion of the debt and receive the collateral at a discount, ensuring that the protocol remains solvent even during volatile market conditions.

Risk Parameters and Asset Listing

Each asset supported on Aave has specific risk parameters determined by governance. These include loan-to-value ratios, liquidation thresholds, and liquidation bonuses. The careful calibration of these parameters by Aave governance helps manage systemic risk while maximizing capital efficiency for users.

Use Cases and Applications of Aave

Aave serves various use cases beyond simple lending and borrowing. Users leverage Aave for yield optimization strategies, portfolio management, and accessing liquidity without selling their crypto holdings. The composability of Aave with other DeFi protocols has spawned an entire ecosystem of applications built on top of its infrastructure.

Leveraged Trading Strategies

Traders use Aave to create leveraged positions by depositing assets, borrowing against them, and reinvesting the borrowed funds. This recursive strategy amplifies exposure to price movements and is popular among sophisticated DeFi users who understand the associated risks.

Yield Farming and Optimization

Aave integrates seamlessly with yield aggregators and optimization protocols. Users can deposit into Aave through these aggregators to automatically maximize their returns through various strategies. The reliable infrastructure of Aave makes it a preferred base layer for many yield optimization services.

The Future Roadmap of Aave

Aave continues to evolve with ambitious plans for the future. The development team and community are working on expanding the protocol's capabilities, improving user experience, and exploring new frontiers in decentralized finance. Aave's commitment to innovation suggests that the protocol will remain at the forefront of DeFi development.

GHO Stablecoin

Aave has launched GHO, a decentralized stablecoin native to the Aave ecosystem. GHO is minted by borrowers on Aave and represents the protocol's expansion into the stablecoin market. This development strengthens Aave's position as a comprehensive DeFi platform rather than just a lending protocol.

Conclusion: Why Aave Matters in the Crypto Ecosystem

Aave has established itself as an essential pillar of decentralized finance through continuous innovation, robust security, and community-driven governance. The protocol's influence extends far beyond its immediate functionality, having introduced concepts like flash loans that have become fundamental to DeFi. As the cryptocurrency ecosystem continues to mature, Aave remains well-positioned to lead the evolution of decentralized lending and borrowing services.

Whether you are a newcomer exploring DeFi or an experienced user seeking sophisticated financial tools, Aave offers a comprehensive platform that caters to diverse needs. The combination of accessibility, innovation, and security makes Aave a protocol worth understanding for anyone interested in the future of finance.

Search on Youtube!

Aave is the Leading Decentralized Lending Protocol Revolutionizing DeFi

Aave is one of the most significant innovations in the decentralized finance ecosystem, representing a fundamental shift in how people interact with financial services. As a decentralized non-custodial money market protocol, Aave has transformed the traditional lending and borrowing landscape by eliminating intermediaries and providing users with unprecedented control over their assets. The protocol has experienced remarkable growth since its inception, establishing itself as a cornerstone of the DeFi movement and attracting billions of dollars in total value locked.

Understanding the Core Functionality of Aave

Aave operates as a decentralized platform where users can participate either as depositors or borrowers without requiring permission from any centralized authority. The protocol enables depositors to provide liquidity to various markets and earn passive income through interest payments generated by borrowers. This peer-to-pool model distinguishes Aave from traditional peer-to-peer lending platforms, creating more efficient liquidity utilization and better rates for all participants.

The Aave protocol is implemented as a sophisticated set of smart contracts deployed on the Ethereum blockchain, ensuring transparency, security, and trustless execution of all transactions. These smart contracts eliminate the need for middlemen, reducing costs and increasing efficiency while maintaining the highest standards of security. Unlike traditional financial institutions, Aave does not require Know Your Customer procedures or anti-money laundering verification, making it accessible to anyone with an internet connection and a cryptocurrency wallet.

How Lending Works on Aave

When users deposit assets into Aave, they receive corresponding aTokens that represent their share of the liquidity pool. These aTokens accrue interest in real-time, meaning your balance increases continuously as borrowers pay interest on their loans. The interest rates on Aave are determined algorithmically based on supply and demand dynamics within each market, ensuring optimal rates for both lenders and borrowers.

Aave supports a wide variety of cryptocurrency assets, allowing users to deposit popular tokens like Ethereum, stablecoins such as USDC and DAI, and numerous other ERC-20 tokens. This diversity provides depositors with multiple options to earn yield on their holdings while contributing to the overall liquidity of the Aave ecosystem.

Borrowing Mechanisms on Aave

Borrowers on Aave can access liquidity by providing collateral that exceeds the value of their loan, a mechanism known as over-collateralization. This approach protects lenders from default risk and maintains the stability of the protocol. Aave offers flexible borrowing options, including variable interest rates that fluctuate based on market conditions and stable interest rates that provide predictability for longer-term borrowing strategies.

One of the innovative features that sets Aave apart from other lending protocols is the flash loan functionality. Flash loans on Aave allow users to borrow assets without providing any collateral, provided the loan is repaid within the same blockchain transaction. This groundbreaking feature has enabled numerous use cases including arbitrage opportunities, collateral swaps, and self-liquidation mechanisms.

The Evolution and History of Aave

Aave began its journey under a different name, originally launching as ETHLend in 2017. The project conducted one of the earliest initial coin offerings in the DeFi space, raising funds to build a decentralized peer-to-peer lending platform. However, the team recognized limitations in the peer-to-peer model and pivoted to the liquidity pool approach that defines Aave today.

The rebranding to Aave occurred in 2020, with the name derived from the Finnish word for ghost, reflecting the protocol's goal of creating a transparent and open financial infrastructure. This transformation marked a significant milestone as Aave introduced its innovative pool-based lending model that would eventually capture significant market share in the DeFi lending sector.

The growth trajectory of Aave has been nothing short of remarkable. During the DeFi summer of 2020, Aave experienced exponential growth in both user adoption and total value locked. The protocol's native governance token saw extraordinary price appreciation, with gains exceeding six thousand percent over certain periods, demonstrating the market's confidence in the Aave ecosystem and its long-term potential.

Key Features That Distinguish Aave

Flash Loans Innovation

Aave pioneered the concept of flash loans in the DeFi space, creating an entirely new financial primitive that did not exist in traditional finance. Flash loans on Aave enable sophisticated users and developers to access substantial amounts of liquidity instantly without collateral requirements. The only condition is that the borrowed amount plus fees must be returned within the same transaction block.

This innovation has spawned numerous applications and use cases within the broader DeFi ecosystem. Developers have built arbitrage bots, liquidation tools, and complex financial strategies that leverage Aave flash loans to maximize efficiency and profitability. The flash loan functionality represents one of the most creative applications of smart contract technology and demonstrates how Aave continues to push the boundaries of decentralized finance.

Rate Switching Flexibility

Aave provides borrowers with unique flexibility through its rate switching feature. Users can seamlessly switch between stable and variable interest rates depending on market conditions and their personal preferences. This capability allows borrowers to optimize their borrowing costs and manage risk more effectively than on competing platforms.

The stable rate option on Aave provides predictability for users who prefer to know their exact borrowing costs over time. Conversely, the variable rate option may offer lower rates during periods of low demand, making it attractive for short-term borrowing or for users willing to accept rate fluctuations in exchange for potentially lower costs.

Credit Delegation

Aave introduced credit delegation as another innovative feature that expands the possibilities of decentralized lending. Through credit delegation, depositors can delegate their borrowing power to trusted third parties, enabling under-collateralized or even uncollateralized loans based on off-chain agreements. This feature bridges the gap between DeFi and traditional finance by introducing trust-based lending relationships within the Aave ecosystem.

The Aave Governance Token

The Aave protocol is governed by holders of the AAVE token, which serves as the governance and utility token of the ecosystem. AAVE token holders can participate in protocol governance by voting on Aave Improvement Proposals that determine the future direction of the platform. This decentralized governance model ensures that the community has a voice in important decisions affecting the protocol.

Beyond governance rights, AAVE tokens can be staked in the Safety Module, a mechanism designed to protect the protocol against shortfall events. Stakers earn rewards for providing this backstop security, aligning incentives between token holders and the overall health of the Aave ecosystem. The Safety Module represents a crucial component of Aave's risk management framework.

The tokenomics of Aave were carefully designed to ensure long-term sustainability and value accrual. A portion of protocol fees is used to buy back and distribute AAVE tokens to stakers, creating a deflationary pressure on the token supply while rewarding those who contribute to protocol security.

Security and Risk Management on Aave

Security is paramount in decentralized finance, and Aave has invested heavily in ensuring the safety of user funds. The protocol has undergone multiple security audits by leading blockchain security firms, and its smart contracts have been battle-tested through billions of dollars in transaction volume. Aave maintains a bug bounty program that incentivizes security researchers to identify and report potential vulnerabilities.

The risk management framework on Aave includes carefully calibrated parameters for each supported asset. Loan-to-value ratios, liquidation thresholds, and liquidation bonuses are set based on comprehensive risk assessments that consider factors such as market liquidity, price volatility, and smart contract risk. These parameters are regularly reviewed and adjusted through governance to maintain the protocol's safety.

Aave also implements a sophisticated oracle system to ensure accurate price feeds for all supported assets. The protocol primarily relies on Chainlink oracles, which aggregate price data from multiple sources to provide reliable and manipulation-resistant pricing information. This robust oracle infrastructure is essential for the proper functioning of liquidations and collateral valuations.

Aave Across Multiple Blockchain Networks

While Aave initially launched on Ethereum, the protocol has expanded to multiple blockchain networks to provide users with more options and lower transaction costs. Aave is now available on Polygon, Avalanche, Arbitrum, Optimism, and other networks, bringing decentralized lending to users who may find Ethereum gas fees prohibitive.

This multi-chain strategy has significantly expanded the reach of Aave and attracted new users who prefer the lower costs and faster transaction times offered by alternative networks. Each deployment maintains the same high standards of security and functionality that users expect from Aave while adapting to the specific characteristics of each blockchain.

The cross-chain expansion of Aave demonstrates the protocol's commitment to accessibility and its vision of becoming the universal liquidity protocol for decentralized finance. By meeting users where they are, Aave has solidified its position as the leading lending protocol across multiple ecosystems.

Aave Version 3 and Protocol Improvements

Aave V3 represents the latest major upgrade to the protocol, introducing numerous improvements in efficiency, security, and user experience. The new version includes features such as Portal, which enables seamless asset transfers between Aave markets on different networks, and Efficiency Mode, which allows higher borrowing power for correlated assets.

The isolation mode feature in Aave V3 enables the listing of new assets with limited exposure, reducing systemic risk while still providing users access to emerging tokens. This balanced approach allows Aave to support a broader range of assets without compromising the safety of the overall protocol.

Gas optimization was another major focus of Aave V3, with the new version achieving significant reductions in transaction costs compared to previous iterations. These improvements make Aave more accessible to users with smaller positions and contribute to a better overall user experience.

The Ecosystem and Integrations Around Aave

Aave has become a foundational building block in the DeFi ecosystem, with numerous protocols and applications integrating with its liquidity pools. Yield aggregators, portfolio management tools, and structured products all leverage Aave as a source of yield and liquidity. This composability is a key strength of the Aave protocol and contributes to its network effects.

The developer community around Aave is vibrant and active, continuously building new tools and applications that enhance the protocol's functionality. Aave provides comprehensive documentation and developer resources to support builders who want to integrate with the protocol or create new use cases on top of its infrastructure.

Partnerships with established financial institutions and emerging crypto projects have further expanded the reach of Aave. These collaborations bring new users to the protocol and validate the potential of decentralized lending as a legitimate alternative to traditional financial services.

Future Outlook for Aave

The future of Aave looks promising as the protocol continues to innovate and expand its offerings. The team has outlined ambitious plans for further development, including enhanced governance mechanisms, new product offerings, and deeper integration with both DeFi and traditional finance.

As regulatory clarity improves around decentralized finance, Aave is well-positioned to capture institutional interest and mainstream adoption. The protocol's track record of security, its transparent governance, and its robust risk management make it an attractive option for sophisticated investors seeking exposure to DeFi yields.

Aave remains committed to its mission of creating open, transparent, and accessible financial infrastructure for everyone. Through continuous innovation and community-driven development, Aave is helping to build the future of finance, one block at a time. The protocol stands as a testament to what is possible when traditional financial concepts are reimagined through the lens of blockchain technology and decentralized governance.

For anyone interested in exploring decentralized finance, Aave provides an excellent starting point with its user-friendly interface, comprehensive documentation, and proven track record. Whether you are looking to earn passive income on your cryptocurrency holdings or access liquidity without selling your assets, Aave offers powerful tools that put you in control of your financial future.

Search on Youtube!
Convergence '25 Recap is Live | Watch All Talks

Aave Protocol Audit

The Aave team asked us to review and audit a pre-production version of their protocol. We looked at the code and now publish our results.

The audited commit is 1f8e5e65a99a887a5a13ad9af6486ebf93f57d02 and all Solidity contracts in the aave-tech/dlp/contracts/contracts folder were in scope. Note that all links to the project’s code in this audit report refer to a private repository, thus are only accessible to Aave’s development team.

Before moving to the full list of issues found in the project, some introductory remarks about the project’s current status are in order.

Project status

With the Aave protocol, Aave set out to implement a decentralized on-chain lending platform based on a “pool strategy” (instead of peer-to-peer lending). Lenders become liquidity providers by depositing cryptocurrencies in a pool, from which borrowers take out loans after having placed enough collateral. Interest rates are calculated fully on-chain, algorithmically deduced from the state of the available pools. Novel features of the protocol include variable and stable-rate loans (with the ability to switch between them) and flash loans – a type of loan taken and repaid in the same transaction.

The Aave team is aware that the audited version of the code base is a work-in-progress and not ready for production. In view of the project’s maturity, this first security audit round should be taken as the initial step forward in the way to reach the highest levels of code quality and robustness demanded by systems intended to handle large sums of financial assets. We identified numerous opportunities for improvement in the project’s documentation, test suite, and code itself, which are highlighted throughout the report. They will require not only specific patches in several code segments, but also great efforts in terms of testing and documentation. While these issues could be considered symptoms of the inherent difficulty of building a sustainable complex financial system, by no means are they to be taken lightly. Further security reviews of the entire protocol are in order, which along with our recommendations in this report, should help bring the project to a production-ready state.

Privileged roles

The Aave team currently administers all aspects of the protocol to decide which assets can be loaned and how price feeds and market rates are obtained. They also control various economic parameters, such as the size of the incentive used to encourage third parties to liquidate under-collateralized loans. All sensitive actions that owners / privileged roles can carry out (the most sensitive ones listed below) are instant and forced, with no opt-in nor opt-out mechanism for users of the protocol.

The owner of the LendingPoolParametersProvider contract can:

  • Update the maximum fixed rate borrow size.
  • Update the delta between the current fixed rate and the user fixed rate at which any borrow position can be rebalanced.

The owner of the FeeProvider contract can:

  • Update the fee charged in all loans (called “origination fee”).
  • Update the address that receives all fees.

The owner of the LendingPoolAddressesProvider (if functions were marked with onlyOwner , see issue “[H01] Lack of access controls” ) can:

  • Update the address of the LendingPool , DefaultReserveInterestRateStrategy , LendingPoolCore , LendingPoolConfigurator , LendingPoolLiquidationManager , LendingPoolDataProvider , LendingPoolParametersProvider , FeeProvider and NetworkMetadataProvider contracts. In other words, the owner is allowed to modify the whole logic of the protocol.
  • Update the address of lending rate and price oracles.
  • Update the address of the “LendingPool manager” role.

The “LendingPool manager” role, set in the LendingPoolAddressesProvider contract, can (regardless of the current state of the protocol):

  • Enable / disable borrowing on any reserve.
  • Enable / disable use of reserves as collateral.
  • Enable / disable borrowing at a fixed-rate in any reserve.
  • Activate / deactivate reserves.
  • Update a reserve’s liquidation threshold, liquidation bonus and interest rate strategy ( i.e. how interest rates are calculated).

These decisions and parameters can significantly affect the usefulness and safety of the system. Although the Aave team plans to grant these privileges to a governance system that will watch over the protocol in the near future, it is unclear whether a single externally owned account or a multisig will represent these roles at the time of audit. As for now, it requires users to fully trust the Aave team with these privileged roles before the governance system is introduced.

Oracles

The Aave protocol relies on two different oracles that feed rates and prices to the system.

The first is the Lending Rate Oracle, which should provide information on the actual market rates of other lending platforms. This oracle should compute an average market lending rate, based on the lending rate and borrowing volume of each external platform. Interaction with the Lending Rate Oracle can be seen in the calculateInterestRates function of the DefaultReserveInterestRateStrategy contract.

The second oracle is the Price Oracle, which should provide an asset’s price (in Ether) when queried. Interaction with this oracle can be seen when:

We must state that none of these oracles were included in this audit’s scope, so they were assumed to be uncompromised, reliable and always available. For further reference on how trusting on-chain decentralized oracles can affect lending platforms, read an insightful article by samczsun .

Following, we present the full list of findings.

Audit Update

The Aave team applied several fixes based on our recommendations. We address below the fixes introduced as part of this first audit. Note that some of the original issues reported have been identified as non-issues, but are still kept for completeness. Some final remarks after reviewing the fixes:

  • We only reviewed specific patches to the issues reported. The code base underwent unrelated changes we have not audited, and can be reviewed in depth in a future round of auditing.
  • As we always recommend to all audited projects, the development team should strive to keep high standards in their software development life cycle with practices of continuous integration testing and mandatory peer-reviews. This greatly adds to the project’s overall quality and prevents regression errors such as the one reported in “[M11] Miscalculation of requested borrow amount in ETH” .
  • Before the code is open-sourced and the project launched, we encourage the Aave team to add a “Security” section in the main README of the project, including instructions for the responsible disclosure of any security vulnerabilities found in the project.

Critical severity

[C01] Users can steal funds

Whenever users deposit assets into a particular reserve, they choose whether the assets can be used as collateral against future loans, in addition to earning interest. This decision is stored as a flag in a UserReserveData object that handles the association between a particular account and reserve contract. However, if the user already has deposits in the same reserve, the existing flag is simply overwritten. This can be leveraged by malicious users to unlock and withdraw any collateral, even if it is required to secure a loan.

The identified attack vector goes as follows:

  1. A user deposits assets into a reserve with the _useAsCollateral flag set to true, receiving aTokens in exchange.
  2. They borrow assets from a different reserve, using the original deposits as collateral. At this stage, they cannot transfer their aTokens , since the balanceDecreaseAllowed function would return false , causing the isTransferAllowed check to fail.
  3. Next, they deposit any number of assets (even zero) into the initial reserve with the _useAsCollateral flag set to false .
  4. Now the user can successfully transfer their aTokens to a fresh account, since the balanceDecreaseAllowed function will bypass the insolvency check and return true .
  5. They can now redeem (or sell) the aTokens to receive their original collateral. At this point they have taken a loan with no collateral, effectively stealing from the lending pool.

Consider preventing users from setting the _useAsCollateral flag to false when their existing deposits in the reserve are required to secure an outstanding loan. Once the fix is applied, related unit tests are in order to avoid reintroducing this critical issue in future modifications to the code base.

Update : Fixed in MR#38 . Users can no longer choose whether deposits are considered collateral. Instead, when the user’s balance in the reserve is zero, the deposit function will now default to mark the next deposit in the reserve as collateral. Users can opt-out by calling the setUserUseReserveAsCollateral function of the LendingPool contract, which performs the appropriate solvency checks. We suggest better documenting this scenario to avoid unexpected behaviors. Additionally, the event ReserveUsedAsCollateralEnabled should be emitted in the deposit function after calling the setUserUseReserveAsCollateral function of the LendingPoolCore contract.

[C02] Borrowers can avoid liquidation

When a loan is liquidated, the reduction in the remaining principal and the corresponding reduction in the total borrows (either fixed or variable ) is calculated by subtracting the accrued interest from the amount to be repaid.

Conceptually, this is a combination of two separate operations: the accrued interest is added to the principal when constructing the new loan and then the amount repaid is subtracted. However, combining them into a single operation will cause the transaction to revert whenever the repayment is less than the accrued interest.

In addition to preventing valid repayments, this behavior could be exploited by borrowers to prevent liquidation.

Since the size of each liquidation transaction is restricted by the amount of collateral that can be recovered from the specified reserve, a borrower could spread their collateral across many different assets in order to ensure the maximum liquidation amount is lower than their accrued interest.

Alternatively, the liquidation amount is also restricted by the protocol’s close factor , which means a user could simply allow their loan to grow until the interest exceeds this threshold. In practice, this will likely take years to occur.

In either case, when a borrower cannot be liquidated they no longer have any incentive to remain collateralized.

Consider updating the principal and total borrows variables in two independent steps that account for the accrued interest and the loan repayment respectively.

Update : Fixed in MR#56 and MR#58 . The principal and total borrows are updated in two steps.

[C03] Deposits not marked as collateral can still be liquidated

When a user deposits an asset into the lending pool, they can choose whether the asset functions as collateral by means of the _useAsCollateral flag . While the expected behavior is that only assets marked as collateral can be liquidated, this restriction is not enforced.

The issue is due to a logic flaw in the liquidationCall function . This function should require that the reserve is enabled as collateral and the user has marked that reserve as collateral. However, the conditional statement in lines 92 and 93 is erroneous. Consequently, assuming the other liquidation requirements hold, liquidationCall succeeds when either:

  • The reserve _collateral is enabled as collateral (regardless of the user preference)
  • The reserve _collateral is not enabled as collateral and the user did not mark it as collateral

Consider modifying the conditional statement in lines 92 and 93 to core.isReserveUsageAsCollateralEnabled(_collateral) && core.isUserUseReserveAsCollateralEnabled(_collateral, _user); . Afterwards, implementing thorough related unit tests is highly advisable.

Update : Fixed in MR#59 . Specific unit tests covering this case are still missing.

[C04] Rogue borrower can manipulate other account’s borrow balance

The rebalanceFixedBorrowRate function of the LendingPool contract is intended to allow anyone to rebalance the fixed interest rate of a borrower when certain requirements are met. All the caller needs to specify is the reserve (in the _reserve parameter) and the borrower’s account to be rebalanced (in the _user parameter).

When querying the borrow balances , the function calls the getUserBorrowBalances function mistakenly passing msg.sender as the argument. Consequently, the compoundedBalance and balanceIncrease local variables will hold the caller’s borrow balances, and not those of the account to be rebalanced ( i.e. the address in _user ). From then on, balanceIncrease is used to update the reserve’s data. It is fundamental to note that on line 514 the increaseUserPrincipalBorrowBalance function increases the _user ‘s borrow balance by balanceIncrease .

Any rogue borrower whose compoundedBalance is greater than zero can leverage this critical vulnerability to manipulate another borrower’s borrow balance. An attacker holding a large borrow can call rebalanceFixedBorrowRate with the victim’s address as the _user parameter. Thus increasing the victim’s principal borrow balance.

The attacker can further benefit by particularly targeting accounts close to being liquidated. The increase in their borrow balance would effectively push victims into a “liquidatable” position, allowing the attacker to liquidate them. To prevent front-runs from other liquidators, this attack can be conducted in a single atomic transaction through a malicious contract that first increases the victim’s borrow balance and then liquidates them.

A second attack vector allows rogue borrowers to distort their accrued interest. They can call the rebalanceFixedBorrowRate function passing their account in the _user parameter, from an account with a very small borrow. This would effectively update their own lastUpdateTimestamp without accruing nearly as much interest as they should actually accrue.

To prevent malicious borrowers from exploiting this vulnerability, consider replacing msg.sender with _user as the argument passed to the getUserBorrowBalances function. Please note that this issue is closely tied to critical issue “[H09] Fixed-rate loans can be repeatedly rebalanced” and high severity issue “[H06] It is impossible to rebalance another account’s fixed borrow rate” .

Update : Fixed in MR#61 .

[C05] Loans of Ether cannot be repaid

Any user that has taken out a loan in the Aave protocol should be able to repay it by calling the repay function of the LendingPool contract. However, a flaw in this function makes it (typically) impossible to repay an Ether loan.

During the process of repaying an Ether loan the caller is expected to send Ether along with the transaction. That Ether should be split in two, to first pay the origination fee and then to pay down the loan. These operations are executed in lines 375 and 412 . Both transfers are sent to the LendingPoolCore contract, which forwards the fee to a “fee collection address” during the first transfer. Even though the LendingPoolCore contract is the destination in both cases, it expects to receive the repayment component in the second transfer. Consequently, the LendingPool contract will (typically) have insufficient Ether to complete the second transfer, which will cause the entire transaction to revert.

Consider either returning the excess ether to the LendingPool contract in the transferToFeeCollectionAddres function or recognizing if Ether was sent with the repay function and forwarding the exact amounts in both transfers.

Update : Fixed in MR#48 . However, note that an erroneous inline comment has been introduced stating “sending the total msg.value if the transfer is ETH”. In this case, when the function executes an ETH transfer, only the amount msg.value.sub(vars.originationFee) is transferred.

High severity

[H01] Lack of access controls

Contracts LendingPoolAddressesProvider and NetworkMetadataProvider include several setter functions that allow the caller to change addresses of fundamental contracts of the protocol and modify system-wide parameters. The main purpose of these functions is to allow upgrades in the protocol’s logic. However, none of these functions currently implement any access control mechanisms, thus allowing anyone to execute them. Affected functions are listed below.

In LendingPoolAddressesProvider contract: setLendingPool , setInterestRateStrategy , setLendingPoolCore , setLendingPoolConfigurator , setLendingPoolManager , setLendingPoolDataProvider , setNetworkMetadataProvider , setLendingPoolParametersProvider , setPriceOracle , setLendingRateOracle , setFeeProvider and setLendingPoolLiquidationManager .

In NetworkMetadataProvider contract: setBlocksPerYear and setEthereumAddress .

The Aave team acknowledges the lack of access controls for these extremely sensitive features (with inline comments in the code that read // TODO: add access control rules under DAO ), and is set out to build a governance system that would be the only actor allowed to trigger them. We must highlight that such a governance system is currently not implemented and was left entirely out of the scope of this audit.

Regardless of the nature of the access control mechanisms chosen, it must be stressed that the system should not be put in production without the necessary restrictions (and related unit tests) in place.

Update : Fixed in MR#52 by adding the missing onlyOwner modifiers. According to the Aave team:

“Ownership of these contracts will be assigned upon deployment to the correspondent governance infrastructure”.

[H02] Anyone can disable the flash loan feature

The Aave protocol allows borrowers to take out a special type of loan that must be repaid (along with a fee) in the same transaction. This functionality is implemented in the flashLoan function of the LendingPool contract. Among the preconditions checked before effectively emitting the loan, the function validates in a require statement that the available liquidity matches the actual balance of the LendingPoolCore contract. From the comment above the check, this is done “for added security”. Yet, this require statement allows anyone to permanently disable the entire flash loan mechanism.

All a malicious user would need to do to effectively conduct the attack would be to send a small amount of assets to the LendingPoolCore contract. As a consequence, the balance of the contract would be increased without increasing the available liquidity of the protocol. The mismatch would disable the flash loan feature for a reserve, as the require statement in line 624 would inevitably fail. It should be noted that to disable the flash loan for the Ether reserve, the attacker must send the ETH from a contract .

Since the validation in line 624 of LendingPool.sol does not appear to be mandatory to ensure the correct behavior of the flashLoan function, consider removing it.

Update : Fixed in MR#53 .

[H03] Deactivated collateral reserve can be used in liquidation

All asset reserves in the Aave protocol can be deactivated by a high-privileged account. When a reserve is deactivated, no actions should be allowed to be executed over it. This validation is implemented by means of the onlyActiveReserve modifier .

The liquidationCall function in the LendingPool contract does use this modifier, but only to validate that the reserve specified in the _reserve argument is active. However, no similar validations are in place for the reserve address passed in the _collateral argument. As a consequence, a liquidation can be executed over a collateral reserve that is expected to be deactivated and suffer no modifications at all. Furthermore, this issue is aggravated by the fact that the LiquidationCall event does not log which collateral reserve is being affected by the liquidation, hindering off-chain clients’ task of effectively tracking modifications to a deactivated collateral reserve.

Consider preventing modifications to a deactivated collateral reserve via the liquidationCall function. This can be achieved by validating that the address passed in the _collateral argument corresponds to an active reserve.

Update : Fixed in MR#64 .

[H04] Liquidators cannot reclaim underlying asset when there is enough liquidity

When calling the liquidationCall function to liquidate a borrow position, liquidators can choose to get the collateral either by reclaiming the aTokens or the underlying asset. This is indicated by the _receiveAToken boolean parameter of the function, where false means the caller is willing to receive the underlying asset. In this scenario, the protocol will first attempt to validate whether there is enough liquidity in the collateral’s reserve , which should be achieved by comparing the available liquidity and the maximum amount of collateral to liquidate.

However, as the comparison is inverted, the function will return an error when there is enough liquidity to proceed with the liquidation. Specifically, a LiquidationErrors.NOT_ENOUGH_LIQUIDITY error is returned when currentAvailableCollateral >= maxCollateralToLiquidate .

While this issue does not pose a security risk on its own, the erroneous comparison breaks an entire feature, preventing liquidators from liquidating a position and getting the underlying asset in exchange. It should be noted that this issue could have been prevented with more thorough unit testing, but only tests where _receiveAToken is true are currently included (see LiquidationCall.spec.js ).

Consider inverting the mentioned comparison so that liquidationCall returns an error when currentAvailableCollateral < maxCollateralToLiquidate . Once the fix is applied, it is highly advisable to add related unit tests to ensure the behavior is expected. Moreover, the new tests should help prevent this issue from being reintroduced in future changes to the code base.

Update : Fixed in MR#73 .

[H05] Maximum size of fixed-rate loans can be bypassed

The borrow function of the LendingPool contract attempts to set a hard cap on the size of fixed-rate loans. The limit depends on the reserve’s available liquidity, and is implemented solely for fixed-rate loans . An attack vector that allows any borrower to bypass the limit has been identified. First, the borrower takes out an arbitrarily large loan at a variable rate. Afterwards, the borrower takes out a second loan on the same reserve, even for an amount of zero – but this time setting the interest rate mode to fixed. Effectively, the borrower obtained an arbitrarily large loan at a fixed rate. Note that this operation can be carried out by a smart contract in a single transaction. To prevent this particular issue, consider tightening the restrictions to switch from variable to fixed rate loans. Nonetheless, we understand that this issue should not be analyzed in isolation. The simplicity of the attack vector described stems from larger shortcomings at the design level of the Aave protocol and how it handles fixed and variable rate loans. Refer to the “[N03] Fixed interest rate loans feature is loosely encapsulated” issue for more details.

Update : Not an issue. In Aave’s words:

“The goal of the maximum size enforcement on stable- rate loans is to avoid having borrowers taking liquidity at a rate that is too competitive. In fact, there is a fundamental difference in the two scenarios of a) taking a stable-rate loan directly and b) taking a variable-rate loan, and switching to stable. The difference is in the interest rate. In case a) in fact, without a hard cap on the loan size, borrowers are theoretically able to snatch the whole liquidity at a very competitive rate, as the stable rate only increases after the loan has been taken. In scenario b), on the other hand, the loan at variable rate can be arbitrarily big, as it poses no issues on the interest rate (variable rates increase as borrowers take more liquidity). In scenario b) also, when a user borrows at variable it might cause the stable rate to rise as well, especially if the loan is of a relevant size. Hence in this case a rate swap poses no issues, as the borrower would swap to the most recent, increased stable rate, rather than to the lower stable rate that he would have been able to benefit if he would have borrowed with a stable rate directly”.

[H06] It is impossible to rebalance another account’s fixed borrow rate

In the rebalanceFixedBorrowRate function of the LendingPool contract, the call to core.updateUserFixedBorrowRate is executed passing the msg.sender address as argument. As a consequence, successful rebalance calls will only ever update the fixed borrow rates of the caller, rather than the target address defined by the _user parameter. This breaks the intended feature of being able to rebalance other accounts.

Consider changing the msg.sender address used in line 537 to _user . Related issues that must also be taken into consideration are “[C04] Rogue borrower can manipulate other account’s borrow balance” and “[H09] Fixed-rate loans can be repeatedly rebalanced” .

Update : Fixed in MR#61 .

[H07] Users cannot fixed-rate borrow from a reserve no longer containing their collateral

To prevent abuses in the protocol, borrowing at a fixed rate (from the same reserve where the borrower deposited collateral) is only allowed if the amount being borrowed is greater than the collateral. This restriction is implemented within the borrow function on lines 216 to 221 of LendingPool.sol .

However, the restriction currently disallows users borrowing at a fixed rate from a reserve where they previously had collateral (but no longer do). After a user withdraws all collateral from a reserve, the system does not automatically toggle to false the isUserUseReserveAsCollateralEnabled flag . When the user attempts to borrow from that reserve, the condition in line 220 will fail, thus reverting the transaction. As a result, the user is unable to borrow from this reserve even if they are not currently holding any collateral in it.

Consider programmatically toggling to false the useAsCollateral flag once a user has withdrawn all collateral from a reserve.

Update : After applying a patch in MR#74 , the Aave team correctly pointed out that we misinterpreted the function’s behavior and this is not an issue. The fix will still remain in place, and the development team will include relevant test cases to programmatically confirm this is indeed not an issue.

[H08] Counterproductive incentives

The Aave protocol requires all loans to be backed by more-than-100% collateral in other asset pools. To maintain this condition as the asset prices vary, there is a safety mechanism that allows anyone to repay loans that are at risk of becoming insolvent. Typically, this encourages arbitrageurs to improve the health of the loans but there are some conditions where the safety mechanism behaves counter-productively, and takes at-risk loans and actively pushes them into insolvency.

Consider a borrower with collateral in various markets worth a total of C , and a total debt worth D . They are located at point ( D , C ) in the following diagram:

After accounting for the distribution of collateral and the thresholds associated with each reserve, they are assigned a liquidation threshold . With these definitions, we can describe the important regions:

  • Users in the green region above the liquidation threshold are fully collateralized. Their collateral exceeds their debt by an acceptable safety margin.
  • Users in the red region are insolvent. Their debt is larger than their collateral and they no longer have any incentive to repay it. Users in this region can be a major problem for the system because they continue accruing interest while removing liquidity from the reserve, ensuring at least some aToken holders will be unable to redeem their assets.
  • Users in the purple region are under-collateralized. They still have more assets than debt in the system, but the protocol deems them to be at risk of becoming insolvent.

When a borrower is under-collateralized, anyone can repay some of their debt in exchange for collateral at better-than-market rates. This mechanism is parameterized by two global values:

  • Liquidation close factor percentage: the maximum fraction of the original loan that can be liquidated (currently set at 50%)
  • Liquidation bonus L : how much collateral do arbitrageurs receive (as a multiplier of the amount paid)

The liquidation line on the diagram has slope L and passes through the origin. When an arbitrageur repays x debt, they receive x*L collateral from the borrower. In other words, they force the borrower to the bottom-left of the diagram on a trajectory parallel to the liquidation line. The crucial observation is that this process can never cause a borrower to cross the liquidation line. Borrowers above the line are liquidated until they are fully collateralized, but borrowers below the line are actually pushed further towards insolvency by the liquidation process.

Whenever the leftover debt is more than the leftover collateral after a liquidation event, the user is insolvent. If we additionally denote the close factor as Cf :

The maximum liquidation amount would be Cf * D with the remaining debt being (1 - Cf) * D .

The value of collateral the liquidator receives (including the bonus) would be Cf * D * L , so the remaining collateral becomes C - Cf * L * D .

The would become insolvent if the remaining debt is greater than the remaining collateral. This occurs when ( 1 - Cf ) * D > C - Cf * L * D , or rearranging, D / C > 1 / ( 1 + Cf * (L - 1)) . If we assume a liquidation bonus of 1.05 and a close factor of 0.5, then when a borrower’s debt rises to at least 1 / 1.05 = 95.2% of the value of their collateral the liquidations start increasing their debt-to-collateral ratio and at 97.6% it is possible for a liquidation to force them into insolvency .

Ideally, they would have already been liquidated before they cross the threshold, but this may not happen depending on various factors outside of the protocol, such as the speed of price changes, the liveness of the oracles, the congestion of Ethereum and the responsiveness and liquidity of arbitrageurs. To this end, it may prove useful to run off-chain monitoring of all above mentioned parameters, along with auto-liquidation mechanisms, to address the risk as early as possible.

Nevertheless, in the event that the borrower crosses the liquidation line, the protocol can no longer sustain the same bonus, since each liquidation event now increases the risk to the protocol. This observation has the unfortunate consequence that the incentive for arbitrageurs to liquidate a risky loan is weaker when it is more crucial. Even so, a weakly productive incentive (or indeed no incentive at all) is still preferable to a counterproductive one. The reduced incentive may be compensated by increasing the close factor for the most at-risk loans or perhaps even allowing arbitrageurs to liquidate 100% of the loan in exchange for 100% of the remaining collateral.

Consider adjusting the parameters in the liquidation mechanism to ensure it is always pushes borrowers and the protocol towards solvency.

Update : The Aave team acknowledges the issue:

“We consider this issue as a part of the dynamics of the protocol, and there is no easy solution as reducing or removing the liquidation incentives in case of extreme undercollateralization would remove the incentive for external liquidators to execute the liquidation, which would still bring insolvency. In the future, we plan to challenge this issue with i) Automated liquidation through decentralized exchanges, to be implemented together with external liquidation and ii) An insurance fund to cover liqudation risk.”

[H09] Fixed-rate loans can be repeatedly rebalanced

Any user’s fixed-rate loan can be rebalanced if the rate falls outside an acceptable range. The lower boundary of this range is the current liquidity rate, while the upper boundary is intended to be a configurable percentage higher than the reserve’s fixed borrow rate.

However, the upper threshold is set below the reserve’s fixed borrow rate . This means that new loans will start outside the acceptable range and will remain that way after rebalancing so that “fixed-rate loans” are actually vulnerable to any change in the market rate.

Consider redefining the upper threshold to be higher than the reserve rate (by the configurable down-rate delta parameter) rather than lower by that percentage. Related issues that must be taken into consideration are “[H06] It is impossible to rebalance another account’s fixed borrow rate” and “[C04] Rogue borrower can manipulate other account’s borrow balance” .

Update : Fixed in MR#44 . This issue was originally labeled as Critical since it implies fixed-rate loans can be made to follow the variable rate. After discussing with the Aave team, it has been downgraded to High. In Aave’s words:

“Although the logic flaw exposed caused unwanted behavior that needed fix, this issue didn’t actually pose any security risk for the protocol, and is actually ending up in a potentially acceptable use case”.

Medium severity

[M01] Fee-less loans

The calculateLoanOriginationFee function of the FeeProvider contract is in charge of calculating the origination fee for a loan of the specified amount. To do so, it multiplies the given amount by the originationFeePercentage – a hardcoded value set during construction to 0.0025 * 1e18 .

Due to how the wadMul multiplication works in this particular case, calculateLoanOriginationFee can return 0 for amounts greater than 0. Such unexpected behavior would allow for a user to take loans that would not pay an origination fee. In particular, all loans with an amount lower than 200 will be granted without accounting for a fee (see this simple mathematical proof for validation).

Should loans be expected to always charge a fee, consider implementing the necessary validations in calculateLoanOriginationFee so that the transaction reverts in case the calculated fee is zero. Otherwise, consider clearly documenting this behavior to prevent unexpected outcomes. Either way, it is highly advisable to implement thorough unit tests related to this feature, as no unit tests were found for the calculateLoanOriginationFee function.

Update : Fixed in MR#75 . Now all loans that would not pay a fee are rejected.

[M02] Anyone can open a flash loan for an unprotected receiver

The flashLoan function in the LendingPool contract allows anyone to execute a flash loan on the Aave protocol. The caller can specify in the _receiver argument any contract address that implements the IFlashLoanReceiver interface .

Should the receiver contract not implement the necessary validations to identify who originally triggered the transaction, it may be possible for an attacker to force any IFlashLoanReceiver contract to open arbitrary flash loans in the Aave protocol that would inevitably pay the corresponding fees. This can potentially drain all funds (ETH or tokens) from the vulnerable contract implementing the IFlashLoanReceiver interface. It should be highlighted that the provided FlashLoanReceiverBase contract does not include any security measure, nor warning documentation, to prevent this issue.

To reduce the attack surface, it is advisable to modify the flashLoan function so that only the receiver of the loan can execute it. If opening flash loans on behalf of IFlashLoanReceiver contracts is an intended feature, then consider adding user-friendly documentation to raise awareness, along with sample implementations showcasing how to defend from attackers that attempt to open flash loans on behalf of unprotected IFlashLoanReceiver contracts.

Update : The Aave team understands this is not an actual security issue of the Aave protocol, but will still provide enough documentation to raise awareness in developers. In Aave’s words:

“We believe that this should not be reported as a security issue of the protocol as it doesn’t actually show any risk for the protocol itself, but rather a potential risk on an unsafe implementation of a IFlashLoanReceiver . Moreover, the solution proposed greatly diminishes the possibility of avoiding front-running by using a multiple contracts strategy, which was the reason why the flashLoan method does not place any safety check on the caller of the function. As the potential security issue might not be immediately visible to a developer of a flash loan receiver, we will make sure to properly document this issue and provide the developers with adequate code samples.”

[M03] Incorrect refund address during repay

The repay function allows repayment of a loan on behalf of other accounts. In a scenario where the caller overpays Ether on behalf of another account, the function will refund the excess Ether to the target address ( i.e. the address passed in the _onBehalfOf parameter ) and not the caller.

Whenever a loan is overpaid with Ether, consider returning all excess Ether to the actual repayer and not the account on whose behalf the loan is being repaid.

Update : Fixed in MR#76 . All excess Ether is now returned to the actual repayer (i.e. the caller).

[M04] Borrower cannot partially repay interest of a loan

The repay function of the LendingPool contract allows a borrower to repay a loan in a specific reserve. However, it is currently impossible for the borrower to partially repay the interest of a loan. This is due to the fact that whenever the borrowBalanceIncrease is greater than the paybackAmountMinusFees , the transaction will be reverted .

Should this be the function’s intended behavior, consider explicitly documenting it in docstrings. Otherwise, consider implementing the necessary logic to prevent repay from reverting when borrowBalanceIncrease is greater than the paybackAmountMinusFees , allowing borrowers to partially repay their loan’s interest.

Update : Fixed in MR#77 .

[M05] Push-payments pattern may render ETH deposits impossible to redeem

When redeeming ETH deposits, the LendingPoolCore contract follows the push-payments pattern to return the deposited Ether. Such a pattern, implemented using the transfer function, has some notable shortcomings when the redeemer is a smart contract, which can render ETH deposits impossible to redeem. Specifically, the redeem will inevitably fail when:

  • The redeemer smart contract does not implement a payable fallback function.
  • The redeemer smart contract implements a payable fallback function which uses more than 2300 gas units.
  • The redeemer smart contract implements a payable fallback function which needs less than 2300 gas units, but is called through a proxy that raises the call’s gas usage above 2300.

Note that the upcoming Istanbul fork can further aggravate this issue, since payable fallback functions that today do not consume more than 2300 gas units may effectively go above the threshold after the fork. This is due to EIP 1884 .

To prevent unexpected behavior and potential loss of funds, consider explicitly warning end-users about the mentioned shortcomings to raise awareness before they deposit Ether into the Aave protocol. Additionally, note that the low-level call call.value(_amount)("") can be used to transfer the redeemed Ether without being limited to 2300 gas units. Risks of reentrancy stemming from the use of this low-level call can be mitigated by tightly following the “Check-effects-interactions” pattern and using OpenZeppelin’s ReentrancyGuard contract .

Update : Partially fixed in MR#78 . We consider it “Partially fixed” since the fact that redeemer smart contracts must implement a payable fallback function is still not documented. As suggested, functions transferToUser , transferToFeeCollectionAddress and transferToReserve replaced the call to transfer with a low-level call. Furthermore, we have our reservations around hard-coding a gas limit on Ether transfers, but the fix works as intended. In Aave’s words:

“As a further safety check, we decided to limit the maximum gas consumption of the receiver default function to 50.000, which is below the minimum cost of any user-oriented function on the LendingPool contract. This limit might be revised in the future and/or moved to a global configuration parameter”.

[M06] Successful redeem of aTokens may not pay assets in exchange

The redeem function in the AToken contract allows holders of aTokens to redeem them for the underlying asset. Assuming all necessary conditions for a successful redeem are met, the expected behavior would be that for every token redeemed a certain amount (given by the exchange rate) of the underlying asset is taken from the pool and transferred to the redeemer.

However, when the amount of aTokens to be redeemed is lower than the amount of aTokens the system exchanges per unit of the underlying asset, the transaction does not revert. In such cases, the system would still take the aTokens, burn them , and transfer 0 units of the underlying asset to the redeemer. Therefore, the caller would lose all redeemed aTokens and the total supply of aTokens would be reduced without modifying the underlying asset reserve’s liquidity.

To prevent unexpected behaviors that may lead to losses of aTokens, consider reverting the transaction when the amount of redeemed tokens is not enough to receive at least one unit of the underlying asset in exchange.

Update : Fixed in MR#79 . The transaction is now reverted when the amount of redeemed tokens is not enough to receive at least one unit of the underlying asset in exchange.

[M07] Lack of event emission after rebalancing fixed borrow rate

The rebalanceFixedBorrowRate function in the LendingPool contract allows anyone to rebalance the fixed interest rate of a user under specific circumstances. However, the function does not emit an event after the rebalancing is executed.

As such a sensitive change is of utter importance to users, consider defining and emitting an event in order to notify clients about it.

Update : Fixed in MR#80 . A RebalanceStableBorrowRate event has been defined and is now emitted after successful rebalances of stable-rate loans.

[M08] Interest may compound unpredictably

In the Aave protocol, loans’ interest is compounded after relevant “interest accruing” transactions occur (with a difference between fixed-rate and variable-rate loans, reported in “[N02] Fixed-rate loans may never compound” ). Between two such transactions, the system uses a simple interest rate model.

The code is designed to accrue interest as frequently as possible, but this requirement expands the responsibility of accruing interest into otherwise unrelated functions. Additionally, the size of the discrepancy between the computed and theoretical interest will depend on the volume of transactions being handled by the Aave protocol, which may change unpredictably.

To improve predictability and functional encapsulation, consider calculating interest with the compound interest formula, rather than simulating it through repeated transactions. The modexp precompile may assist in lowering gas fees. Alternatively, consider informing users that the protocol’s interest rates are merely estimations rather than exact rates.

Update : The Aave team acknowledges this issue:

“We acknowledge this issue, as also strictly correlated with N02. As a result, we will evaluate before the mainnet release what will be the implementation cost and the benefits of switching to a compounded interest rate formula, and eventually modify the implementation accordingly.”

[M09] Sensitive mathematical operations are not explicitly documented

Intending to make the platform as transparent as possible, the Aave team has implemented most of the calculations the Aave protocol relies on in their smart contracts. Such calculations usually entail complex arithmetic operations over balances, timestamps, rates, percentages, prices, decimals, among others, that are measured in several different units. It is of utmost importance for such operations to work flawlessly, considering that the Aave protocol is set out to handle large amounts of valuable assets, and any error may cause outstanding financial losses. However, such sensitive operations were found to be sparsely documented, the most important shortcoming being the lack of explicit units for each term involved.

This lack of explicit units for state variables, parameters and return values greatly hindered the auditing process. While attempts to validate all calculations spread throughout the code base were made, still the manual process was unreliable and error-prone. Mapping formulas to the provided whitepaper was not straightforward either, because there are many mismatches – as reported in “[L18] Whitepaper issues” . Assessing for correctness becomes difficult when there is no way to straightforwardly understand the units used in each calculation, regardless of their simplicity. These are the reasons why we are listing this issue with Medium severity.

Great efforts must be made in term of documenting calculations and explicitly stating all units of the terms involved. This should greatly improve the readability of the code, which should add to the platform’s transparency and the users’ overall experience. As the process of manually auditing all sensitive arithmetic operations has been proven hard-to-follow, unreliable and potentially error-prone, thorough unit testing of all critical calculations is in order to programmatically ensure that the code’s current behavior is expected.

Update : Partially fixed. The most recent whitepaper shared with us is significantly clearer. However, the units of the variables in the CoreLibrary.sol structs are still undocumented.

[M10] Missing test coverage report

There is no automated test coverage report. Without this report it is impossible to know whether there are parts of the code never executed by the automated tests; so for every change, a full manual test suite has to be executed to make sure that nothing is broken or misbehaving. High test coverage is of utter importance in projects like the Aave protocol, where large sums of valuable assets are expected to be handled safely and bugs can cause important financial losses.

Consider adding the test coverage report, and making it reach at least 95% of the source code.

Update : Acknowledged, and fix in progress. The Aave team was working on setting up coverage on a separate branch during our audit. Given the tools are still immature and unstable, some problems arised in the process which are now being solved by customizing the coverage tools to Aave’s needs. The team is fully aware of the importance of high test coverage, and is striving to reach at least 95% coverage before launch.

[M11] Miscalculation of requested borrow amount in ETH

Note for the reader: This issue was detected during our review of the fixes for the first audit round. The specific commit where the issue was introduced is 8521bcd , which was not present in the audited commit. It must be noted that the PR that finally merged this commit to the master branch was created and merged by the same author, without any kind of peer-review nor CI testing process. The commit to which we link in the issue’s description is the latest in the master branch at the moment of writing.

To validate whether there is enough collateral to cover a borrow, the borrow function of the LendingPool contract first calculates how much ETH the amount borrowed represents . This calculation is intended to take into account the borrow fee paid by the borrower. However, the borrow fee is only calculated after it is first used . This means that when the requested borrow amount in ETH is calculated, the vars.borrowFee variable is zero. As a consequence, the calculated borrow amount in ETH will be lower than expected, inevitably lowering the actual amount of collateral needed in ETH to accept the borrow operation.

Consider refactoring the borrow function to first calculate the borrow fee, and only then using the vars.borrowFee variable for further operations. Note that this issue should have been caught if the borrow function and its calculations were thoroughly tested (as suggested throughout our original assessment).

Update : Fixed in MR#116 .

Low severity

[L01] Minimum interest can be within one block

To lessen the impact of potential interest-free loans (refer to the first high-severity issue in our Compound audit ), the Aave protocol adds 1 wei as “symbolic cumulated interest” . However, this mechanism does not check whether time has passed, so it would accrue the symbolic interest in the same block as the loan.

Before adding the symbolic cumulated interest of 1 wei, consider adding a check to ensure that the last update’s timestamp is different from the current’s block timestamp.

Update : Fixed in MR#81 . The getCompoundedBorrowBalance function now checks the block timestamp before accruing symbolic interest.

[L02] Truncation when casting Ray to Wad

The rayToWad function of the WadRayMath library truncates the input Ray value (with 27 decimal digits of precision) when casting it to a Wad value (with only 18 digits of precision). However, the other functions in the library round instead of truncating when discarding precision.

Consider creating a second function that rounds to the nearest Wad . This could be used in the getCompoundedBorrowBalance function of the CoreLibrary to return a slightly more accurate value, favoring accruing more interest for the protocol. The original rayToWad functionality in underlyingAmountToATokenAmount and aTokenAmountToUnderlyingAmount functions should be kept, as it favors rounding down (truncation) when calculating how many tokens to send out of the protocol.

Update : Fixed in MR#82 . The rayToWad function has been modified, and now always rounds to the nearest Wad . Note that the applied fix does not strictly follow our suggestion of having two separate functions.

[L03] Conversion to aToken units implicitly assumes 18 decimals

The underlyingAmountToATokenAmount function of the AToken contract never takes into account the decimals of the overlying asset ( i.e. the aToken). While it works under the assumption that all aTokens have 18 decimals, there is nothing in the code to ensure this assumption always holds.

This issue does not pose a current security risk, as the Aave developers are in control of how many decimals aTokens have. However, the underlyingAmountToATokenAmount function should programmatically enforce all conditions needed to operate normally, since dangerous unexpected behavior could arise otherwise.

To favor explicitness and prevent bugs in future modifications to the code base, consider modifying the underlyingAmountToATokenAmount function to explicitly account for the decimals of the overlying aToken. Otherwise, warning documentation should be included in the function docstrings. One alternative, less flexible, course of action is to programmatically enforce that all created aTokens have 18 decimals in the AToken contract constructor .

Update : Fixed in MR#83 . The AToken constructor now programmatically enforces all aTokens to have 18 decimals.

[L04] Redundant underflow prevention

Function decreaseUserPrincipalBorrowBalance unnecessarily implements an underflow protection ensuring that user.principalBorrowBalance is greater or equal than _amount . This validation is already in place in OpenZeppelin SafeMath’s sub function , so consider removing it.

Update : Not an issue, as the code correctly follows the “Fail early and loudly” principle.

[L05] Fixed-rate borrow can be rebalanced in inactive reserve

The rebalanceFixedBorrowRate function of the LendingPool contract does not validate whether the reserve passed as an argument is active. As a consequence, an inactive reserve can suffer unexpected changes in its parameters.

This issue should be disregarded if the behavior is expected. Otherwise, consider requiring that the reserve is active by means of the onlyActiveReserve modifier .

Update : Fixed in MR#84 .

[L06] Collateral can be deposited in a reserve where usage as collateral is disabled

The deposit function of the LendingPool contract allows users to deposit assets as collateral (by setting the _useAsCollateral parameter to true ) in reserves where usage as collateral may be disabled system-wise. Specifically, in reserves where usageAsCollateralEnabled is false .

This issue does not pose a security risk, as such deposits will not account for collateral when the reserve is disabled as collateral system-wise . Yet, such behavior can cause confusion in users. Consider reverting the transaction whenever a user attempts a deposit of assets as collateral (with the _useAsCollateral argument set to true ) in a reserve where usage as collateral is disabled system-wise.

Update : Not an issue. The Aave team understands this is the protocol’s intended behavior:

“The dominant configuration parameter which determines first and foremost if a deposit can be used as collateral is the usageAsCollateralEnabled . The _useAsCollateral parameter was intended only as a user preference. [By fixing C01] The possibility of setting this preference has been removed from the deposit function. We believe that being an user preference, the user should be able to set in wathever way he wants independently from the platform configuration, especially considering that the platform configuration may change in the future. We will make sure to document more in detail this function though to ensure better understanding of the meaning of the flag for users.”

[L07] Potential division by zero

The balanceDecreaseAllowed function in the LendingPoolDataProvider contract is used to validate decreases in an account’s collateral balance. Once it calculates the collateral balance after the decrease , the function computes the resulting liquidation threshold. However, in this last calculation the new collateral balance is used as a divisor without previously validating whether it is zero.

While this does not pose a security issue, since the div function of OpenZeppelin SafeMath is used, it should be noted that the division by zero will cause the transaction to revert with an unexpected and not user-friendly error message from the SafeMath library. Therefore, to avoid unexpected behaviors, consider returning false if the collateralBalancefterDecrease variable is zero.

Update : Fixed in MR#85 .

[L08] Erroneous data logged in LiquidationCall event

The liquidationCall function in the LendingPool contract emits a LiquidationCall event to notify off-chain clients about successful liquidations. However, it currently logs erroneous data.

  • While the event logs the _purchaseAmount argument passed by the liquidator, this argument can be higher than the actual amount liquidated (as seen in lines 110 to 114 of LendingPoolLiquidationManager.sol ). The amount logged should match the actual amount liquidated.
  • The first argument passed to the event should be _collateral (instead of liquidationManager ).

It must be highlighted that currently there are no unit tests covering the emission of the LiquidationCall event and the data it logs. Therefore, consider implementing related unit tests to prevent these errors from being reintroduced in future changes to the code base.

Update : Fixed in MR#87 .

[L09] Erroneous data logged in Repay event

The repay function in the LendingPool contract emits a Repay event to notify off-chain clients about successful repayments. When a user passes a value higher than the debt (including UINT_MAX_VALUE ) in the _amount parameter , the function assumes the user is willing to repay the entire borrow (whatever the actual amount to be repaid is). In this scenario, after the successful repayment is completed, the function will emit the Repay event logging _amount as the repaid amount, where it should actually log the amount effectively paid ( i.e. paybackAmount ).

Consider modifying the amount logged by the Repay event so that it matches the actual amount paid by the user. It should be noted that currently there are no unit tests covering the emission of the Repay event and the data it logs. Therefore, consider implementing related unit tests to prevent this error from being reintroduced in future changes to the code base.

Update : Fixed in MR#47 .

[L10] Redundant BurnOnRedeem event

The burnOnRedeemInternal function of the AToken contract emits a BurnOnRedeem event that logs the account and the number of tokens burned. However, this immediately follows a call to OpenZeppelin’s ERC20 contract _burn function which emits a Transfer event with the same information.

To favor simplicity and avoid redundant operations, consider removing the BurnOnRedeem event.

Update : Fixed in bc43147 .

[L11] MintOnDeposit event logs amount of underlying asset

The MintOnDeposit event logs the amount of underlying asset sent instead of the number of aTokens minted. This might be considered intended behavior since the _mint function already emits a Transfer event logging the number of aTokens. However, it is inconsistent with the data logged in the Redeem event of the redeem function.

Consider modifying the MintOnDeposit event to log both the amount of the underlying asset sent and the number of aTokens minted.

Update : Fixed in MR#36 .

[L12] Unfulfillable condition

The first condition in the require statement in line 211 of LendingPool.sol (inside the borrow function), checks whether the user-controlled argument _interestRateMode is equal to uint256(CoreLibrary.InterestRateMode.VARIABLE) . This is an unfulfillable condition, considering that the if statement in line 207 already ensures _interestRateMode is going to be equal to uint256(CoreLibrary.InterestRateMode.FIXED) .

To favor readability and avoid unnecessary validations, consider removing the unfulfillable condition.

Update : Fixed in MR#89 .

[L13] Inconsistent validations

The transferToFeeCollectionAddress function of the LendingPoolCore contract does not currently prevent users from sending ETH along an ERC20 transfer operation like the transferToReserve function does. To favor consistency and prevent unexpected behaviors, consider implementing this validation in the transferToFeeCollectionAddress function.

Update : Fixed in MR#88 .

[L14] Tests not passing

After following the instructions in the README file of the project, the testing suite finishes with six failing tests. Such tests are:

- Contract: LendingPool - token economy tests
- BORROW - Test user cannot borrow using the same currency as collateral

- Contract: LendingPool FlashLoan function
- FLASH LOAN - Takes ETH Loan, returns the funds correctly:

- Contract: LendingPool FlashLoan function
- FLASH LOAN - Takes ETH Loan, does not return the funds:

- Contract: LendingPool FlashLoan function
- FLASH LOAN - Takes out a 500 DAI Loan, returns the funds correctly:

- Contract: LendingPool FlashLoan function
- FLASH LOAN - Takes out a 500 DAI Loan, does not return the funds:

- Contract: LendingPool liquidation
- LIQUIDATION - Liquidates the borrow

As the test suite was left outside the audit’s scope, please consider thoroughly reviewing the test suite to make sure all tests run successfully. Furthermore, it is advisable to only merge code that does not break the existing tests (nor decreases coverage).

Update : The Aave team acknowledges this issue, and has now revamped the test suite:

“Test were breaking on the audited commit because of an issue in the migration scripts. As the test system has been completely revamped, these tests are not failing anymore and more than 60 other unit tests have been added.”

[L15] Missing comprehensive docstrings

Many of the contracts and functions in the code base lack comprehensive documentation. This hinders reviewers’ understanding of the code’s intention, which is fundamental to correctly assess not only security, but also correctness. Additionally, docstrings improve readability and ease maintenance. In general, docstrings should explicitly explain the purpose or intention of functions and its parameters, the scenarios under which they can fail, the roles allowed to call them, the values returned and the events emitted.

Consider thoroughly documenting all functions (and their parameters) that are part of the contracts’ public API. Functions implementing sensitive functionality, even if not public, should be clearly documented as well. When writing docstrings, consider consistently following the Ethereum Natural Specification format (NatSpec).

Update : The Aave team acknowledges this issue:

“We will make sure to add improved documentation following the NatSpec format.”

[L16] Erroneous docstrings and comments

Several docstrings and inline comments throughout the code base were found to be erroneous and should be fixed. In particular:

Update : Fixed in MR#90 and MR#98 .

[L17] Misleading error messages

  • The LendingPoolCore contract’s fallback function intends to only allow transfers of ETH from contracts. However, given the current implementation, transfers of ETH would fail with a misleading error message whenever executed from contracts’ constructors. Consider clarifying such behavior in an inline comment to prevent unexepected behaviors.
  • In line 463 of LendingPool.sol , the error message does not match the actual checked condition, and should therefore be modified to “[…] an amount that is equal or smaller than […]” .
  • While the error message in line 610 of LendingPool.sol states that “The caller of this function must be a contract” , the flashLoan function can be called by both contracts and externally-owned accounts.

Update : Not fixed. The issue is tracked in #98 .

[L18] Whitepaper issues

The commit audited includes the Aave protocol whitepaper in the docs folder . Following we include a list of issues related to the whitepaper that must be addressed:

  • Throughout the entire whitepaper, “ray” and “Ray” are used interchangeably.
  • The definition for the Health Factor does not match the code , and should be updated.
  • In section 1.2, “Block height at which […]” should say “Timestamp at which […]”. Additionally, Bl should be replaced with Tl .
  • There is an unfinished sentence in section 1.9, where it says “Check paragraph X where […]”.
  • There are two sections numbered 1.15. More importantly, they correspond to a circular definition between the “Current liquidity rate” and the “Borrow/Liquidity Rate delta”.
  • In section 1.16, “ Ci Is” should say “ Ci is” (a blank space is missing). Moreover, the last sentence is not coherent and should say “The formula to calculate Ci at a specific point in time […]”.
  • In section 1.17, the definition for the “Reserve normalized income” is incorrect, as it was copied from section 1.16.
  • In the last sentence of section 1.21, BΔu should be replaced with TΔu .
  • The last paragraph of section 2.3 refers to “chapter 4” that does not exist in the whitepaper.
  • In section 3.1, the formula of “Average Market Lending Rate” defines a weighted sum. To obtain the average, it should be divided by the total volume of the platforms.
  • The symbol Bf is mistakenly used instead of Rf to refer to the “Current fixed borrow rate”.
  • In the “Flash Loan” section, the actual method executed on the external contract is executeOperation and not executeAction as stated.
  • In the “Current fixed borrow rate” section, the formula does not specify what occurs when the utilization rate U is equal to the threshold Tr . Additionally, the whitepaper states that the utilization rate threshold is set to 0.25 * 1e18 , but in the code it is set to 1e27 / 2 .
  • In the “Fixed rates Rebalancing” section, the inequality for the rebalancing up is in the wrong direction (it should be Bfu > Lr ).
  • In the “Fixed rates Rebalancing” section, the formula for rebalancing down should say (1 + delta) instead of (1 – delta).

Update : Partially fixed. The whitepaper has been significantly improved. The new version of the whitepaper still has minor issues to be addressed. In particular:

  • The new version of the whitepaper states that the utilization rate threshold is now set to 1e27/2 , but in the code it is set to 1e27 / 4 .
  • In the “The Rebalancing Process” section, the function rebalanceFixedBorrowRate should be renamed to rebalanceStableBorrowRate .
  • Section 1.2 mentions a LendingPoolLibrary.sol file that does not exist.
  • References to decreaseTotalBorrowsFixedAndUpdateAverageRate and increaseTotalBorrowsFixedAndUpdateAverageRate function should be updated to account for the “fixed” to “stable” renaming.
  • In the introduction to section 4, the term “fixed rate” is used
  • In section 4.4, “fixed borrow rate of user x” should be changed to “stable borrow rate of user x”.
  • Figure 14 is missing a “Yes” label in the second conditional block.
  • Consider using the subscript s (instead of f ) to refer to the stable rate parameters. Since s is already used to reference scaling variables, consider using a synonym like multiplier with the subscript m`.
  • Typo in section 2.6: “all votes are biding”.

Notes and Additional information

[N01] Markets can become insolvent

When the value of all collateral is worth less than the value of all borrowed assets, we say the market is insolvent. Approaches to reduce the risk of market insolvency include: prudent selection of collateral-ratios, incentivizing third-party collateral liquidation, and careful selection of which tokens are listed on the platform, among others. However, the risk of insolvency cannot be entirely eliminated, and there are numerous ways a market can become insolvent. As examples:

  • The price of the underlying (or borrowed) asset makes a big, quick move during a time of high network congestion — resulting in the market becoming insolvent before enough liquidation transactions can be mined.
  • The price oracle temporarily goes offline during a time of high market volatility. This could result in the oracle not updating the asset prices until after the market has become insolvent. In this case, there will never have been an opportunity for liquidation to occur.
  • Administrators list an ERC20 token with a later-discovered bug that allows minting of arbitrarily many tokens. This bad token is used as collateral to borrow funds that it never intends to repay.

In any case, the effects of an insolvent market could be disastrous. It would mean that aToken contracts would effectively be running a fractional reserve. This could result in a “run on the bank”, with the last suppliers losing their money.

This risk is not unique to the Aave protocol, and was also highlighted in our Compound audit . All collateralized loans (even non-blockchain loans) have a risk of insolvency. However, it is important to raise awareness on this risk, and that it can be difficult to recover from even a small dip into insolvency.

Update : The Aave team acknowledges the note, accepting it as a inherent risk of the basic economic model.

[N02] Fixed-rate loans may never compound

The Aave protocol allows borrowers to take out loans either at a fixed or variable interest rate.

Variable-rate loans compound interest every time any user updates the reserve from which the loan was taken. Conversely, fixed-rate loans do not compound when there are updates on the reserve. They only compound interest when the particular loan is updated . In other words, unless the borrower who took out the fixed-rate loan borrows again, repays part of the loan, swaps the rate mode, rebalances the fixed rate, or is liquidated, their loan interest will never be compounded.

Even though this issue does not pose a security risk, it is important to explicitly state this fundamental difference between the two types of loans, so as to raise end-user awareness.

Update : The Aave team acknowledges the note and will clarify better in the documentation this particular difference between variable and stable rate loans.

[N03] Fixed interest rate loans feature is loosely encapsulated

Throughout the code base, the boundary and interplay between fixed-rate loans and variable-rate loans is not well defined, which can lead to surprising or undesirable behavior. To investigate this idea it is useful to explore a few different examples, some that are already mentioned in this report, while viewing them as consequences of an underlying architecture.

Since each user can have only one active loan from each reserve, the borrow function must close the existing loan and create a new one. This may implicitly convert between fixed and variable rate loans. However, this allows users to bypass the size and collateral restrictions placed on new fixed-rate loans, or loans that are explicitly swapped with the swapBorrowRateMode function .

In fact, the reason for the size restrictions in the first place is that it is possible to manipulate the utilization rate (through deposits and borrows). This in turn effects the rate applied to a new fixed-rate loan, which will not respond to the subsequent changes to utilization rate when the manipulation is reversed. The Aave team acknowledges that the size and collateral requirements adds a barrier, but does not remove the possibility of such a manipulation occurring at a small scale using a single account, or at a larger scale using multiple accounts. Ultimately, this attack is possible due to the fact that fixed-rate and variable-rate loans share the same asset pool and utilization rate, but respond differently to market changes.

This also leads to another security requirement, where the fixed rate must always be higher than the liquidity variable rate to avoid users borrowing from and loaning into the same pool. The solution of rebalancing the loans when this occurs has some undesirable consequences. Firstly, it means that the rate of fixed-rate loans can actually vary. Secondly, it introduces a discontinuity, where someone with a loan at the bottom of the window can suddenly find their rate increase to the current market rate. Lastly, this condition is manipulable through the utilization rate, which means that users can intentionally make themselves or other users vulnerable to rebalancing (in either direction).

Lastly, variable-rate loans compound whenever any user updates the reserve but fixed-rate loans only compound when the particular loan is updated. This may be surprising to users, and even to developers with some familiarity with the code given the similarity between the supporting data structures and update functions.

Although these issues can be addressed individually, we believe them to be symptoms of the loose encapsulation of fixed-rate loans, where the implementation shares data structures and the reserve pool with variable-rate loans and lenders. Consider defining clear boundaries around the fixed-rate loan feature (with documentation and code separation) to simplify the system and make it easier to reason about.

Update : The Aave team understands that the current behavior of the feature is intended, and is satisfied with its design. While we still keep our reservations around the stable rate feature, the renaming from “fixed” to “stable” is a step forward in better clarifying the real behavior of the protocol. The upcoming documentation for N02 should also help to better delineate the nature of both types of rates.

[N04] Upgrades should update cached addresses

The Aave protocol is intended to be upgraded in the future by means of a to-be-implemented governance system. These upgrades should occur when new addresses are set by privileged accounts in the LendingPoolAddressesProvider contract (see “[H01] Lack of access controls” ) related issue).

Several components of the system are not isolated but depend on each other. For efficiency, they cache addresses in storage (to avoid querying the LendingPoolAddressesProvider contract too often). As a consequence, setting a new address in the LendingPoolAddressesProvider must always be considered as just one of potentially many steps of the upgrade process. All addresses cached in contracts that depend on the upgraded one must be updated as well.

Following we include a list detailing which addresses are cached in contracts of the system.

Update : The Aave team acknowledges the issue:

“The future Aave governance framework will be in charge of controlling and updating the cached addresses once any update on any affecting contract is applied.”

[N05] Missing relevant data in events

Some emitted events may benefit from logging additional relevant data. In particular:

Update : Fixed in MR#47 .

[N06] Unused LiquidationCompleted event

Line 51 of LendingPoolLiquidationManager.sol declares a LiquidationCompleted event. As it is never emitted, consider removing the declaration or emitting the event appropriately.

Update : Fixed in MR#57 .

[N07] Flash loan reverts when amount equals available liquidity

The flashLoan function of the LendingPool contract requires the amount of the loan to be strictly lower than the reserve’s available liquidity. However, this restriction will revert the transaction when both amounts are equal, with a misleading error message informing that there is not enough liquidity.

Update : Fixed in MR#55 .

[N08] Function redeem can be called with amount zero

The redeem function of the AToken contract can be called with argument _amount as zero. To prevent unncessary event emissions, and following the “fail early and loudly” pattern, consider adding a require statement to validate that _amount is greater than zero.

Update : Fixed in MR#60 .

[N09] Refactor getReserveUtilizationRate function

To calculate the total borrows of a reserve, the getReserveUtilizationRate function of CoreLibrary should reuse the available getter getTotalBorrows instead of repeating the code _self.totalBorrowsFixed.add(_self.totalBorrowsVariable) .

Update : Fixed in MR#62 .

[N10] Reuse modifier onlyReserveWithEnabledBorrowingOrCollateral

The require statement and assignment of reserve in lines 677 to 682 of LendingPoolCore.sol accomplish the same functionality as the onlyReserveWithEnabledBorrowingOrCollateral modifier .

Consider removing these lines and adding the modifier to the transferToReserve function declaration.

Update : Fixed MR#63 .

[N11] Redundant getters

To favor simplicity and encapsulation, consider removing all these redundant functions, ensuring that there is always at most one publicly accessible getter for exposed data.

Update : Not an issue. Redundancy is intended.

[N12] Implicit upcasting of uint40 variable

To favor explicitness and code readability, consider explicitly casting the _lastUpdateTimestamp variable from uint40 to uint256 in line 314 of CoreLibrary.sol .

Update : Fixed in MR#65 .

[N13] Unclear use of a struct for function local variables

The borrow function of the LendingPool contract uses a struct called BorrowLocalVars instead of declaring local variables. A similar situation occurs in the calculateUserGlobalData function of LendingPoolDataProvider , which uses the UserGlobalDataLocalVars struct.

As the purpose of such implementations is unclear, consider including an inline comment to clearly explain why these functions favor the use of the structs over local variables. This should add to the code’s readability, preventing developers from introducing undesired changes to the code base in the future.

Update : Fixed in MR#66 .

[N14] Unused state variable

In the LendingPoolLiquidationManager contract, the state variable parametersProvider is never used and should therefore be removed.

Update : Not an issue. Even though the state variable parametersProvider is not used, it does help keep the storage’s layout aligned to the storage of the LendingPool contract (which delegatecall s to LendingPoolLiquidationManager ).

[N15] Lack of explicit visibility in state variables

The following state variables and constants are implicitly using the default visibility:

To favor readability, consider explicitly declaring the visibility of all state variables and constants.

Update : Fixed in MR#68 .

[N16] Named return variables

There is an inconsistent use of named return variables across the entire code base. Consider removing all named return variables, explicitly declaring them as local variables, and adding the necessary return statements where appropriate. This should favor both explicitness and readability of the project.

Update : Aave acknowledges the inconsistency and plans to consistently unify the return statement declarations in the future, in one way or another.

[N17] Naming issues

Several variables, parameters and functions throughout the code base might benefit from better naming to favor readability and avoid confusions. Specifically:

  • Modifier whenTranferAllowed should be called whenTransferAllowed .
  • State variable initialExchangeRate of AToken contract is not self-explanatory enough. It should denote the “direction” of the exchange rate. That is, either [aToken / asset] or [asset / aToken].
  • The struct field collateralBalancefterDecrease should be called collateralBalanceAfterDecrease .
  • All forms of liquidationDiscount should be changed to liquidationBonus , as they refer to a value greater than 1.
  • The currentLtv variable used in the calculateUserGlobalData function of the LendingPoolDataProvider contract is not the actual “current loan-to-value” because it is not averaged over the total collateral balance in ETH yet. This step is done by reassigning this variable in line 119 . The same can be said for the currentLiquidationThreshold variable .
  • The same name usageAsCollateralEnabled is used to refer to two different states of a reseve. On one hand, it can mean that the user has enabled a certain reserve to be used as collateral (see line 369 of LendingPoolDataProvider.sol ). On the other, it denotes whether a reserve has been set up to be used as collateral system-wide (see line 273 of LendingPoolDataProvider.sol ) by the administrators.

Update : Acknowledged by Aave:

“As this issue poses further groundwork since it impacts other off-chain services, we acknowledge this issue and provide better naming for those variables in a future revision.”

[N18] Typos

Update : Fixed in MR#69 .

[N19] Unnecessary use of Ownable contract

The LendingPoolCore , LendingPoolDataProvider and LendingPoolConfigurator contracts all unnecessarily inherit from OpenZeppelin’s Ownable contract . Given features from Ownable are never used in these contracts, consider removing it from their inheritance chains.

Update : Fixed in MR#70 .

[N20] Unnecessary imports

There are several import statements that are not used and can be removed. Namely:

  • Imports in lines 7 , 11 , 15 and 16 of LendingPoolLiquidationManager.sol .
  • Import in line 3 of AToken.sol .
  • Import in lines 6 and 10 of LendingPool.sol .
  • Import in line 6 and 9 of LendingPoolConfigurator.sol .
  • Import in line 10 of LendingPoolCore.sol .

Update : Fixed in MR#71

[N21] TODOs in code

There are “TODO” comments in the code base that should be removed and instead tracked in the project’s issues backlog. See for example line 627 of LendingPool.sol .

Update : Fixed in MR#55 , MR#52 and MR#97 .

[N22] Coding style

Minor deviations from the Solidity Style guide were seen throughout the code base. To favor code readability, consider consistently following Solidity’s coding style guide, which can be enforced across the entire project by means of a linter tool, such as Solhint .

Update : Aave acknowledges the code style deviations and will adapt them in the next iterations of the code base.

[N23] Declare uint as uint256

To favor explicitness, all instances of uint should be declared as uint256 .

Update : Fixed in MR#72 .

Conclusion

Originally, 6 critical and 8 high-severity issues were found. Several changes were proposed to follow best practices and reduce potential attack surface. After reviewing all issues reported with the Aave team, we downgraded 1 critical issue and considered 2 high-severity issues as non-issues. The severe attack vectors and broken features identified, together with the meager test suite and sparse documentation, are the reflection of a work-in-progress code base. As stated in the Audit Update section, and in each particular issue as well, all severe issues identified have been correctly fixed .

This first audit round has been Aave’s initial step on its way to reach the needed level of maturity for projects intended to handle large sums of financial assets. So as to further help the project reach a production-ready state, we highly advise additional rounds of security reviews.