Angle allows users to mint and burn agTokens (stablecoins) in exchange for other tokens. Traders can also open long positions on available collateral/stablecoin pairs. These are not traditional perpetual contracts, as equilibrium does not rely on funding rates, and execution prices come directly from the oracle. Given these use cases, the protocol requires a reliable method to price available assets to offer users fair quotes while protecting itself from front-running transactions. In the FAQ of this article, Samcszun explains why this is not as simple as using spot prices.
Front-running has been a long-standing issue in the market. It comes down to certain participants gaining access to information earlier than others, allowing them to leverage this advantage to extract risk-free profits at the expense of the counterparty. Historically, preventing this phenomenon on-chain has been extremely challenging. The high costs and low speed of Ethereum transactions make it difficult for oracles to update prices quickly and frequently. This introduces delays between off-chain and on-chain prices, creating opportunities for front-runners to exploit.
Not all stablecoin protocols are concerned about front-running risks arising from oracle delays. In the case of Maker’s DAI, oracle delays often benefit the protocol. For instance, if a user sees that her position will be liquidated in the next oracle update due to a price drop, she is incentivized to deposit more funds into the vault, improving the protocol’s health and collateral ratio.
Synthetix, which enables oracle-based value exchanges between synthetic assets and collateral, is a perfect example of a stablecoin protocol facing front-running challenges. Their blog post outlines the protocol’s long history with front-running, including some past attacks they have suffered.
Similar to Synthetix, Angle allows asset swaps at oracle value with zero price slippage. As a result, Angle faces the same front-running issue. The Angle core team has made significant efforts to mitigate front-running. Two key improvements have been implemented: a specific oracle design and a dynamic fee structure. In this article, we will explain Angle’s oracle design and the reasoning behind it.
Before diving into Angle’s solution, let’s first try to understand how front-running can harm the protocol. We will consider an example where ETH is accepted as collateral to back Angle’s stablecoin.
Suppose an attacker is monitoring the off-chain ETH price and sees that the Chainlink oracle is about to update the on-chain data to a higher price (from p0 to p1, where p0 < p1). This attacker can send a transaction to burn x stablecoins at the price of p0 in exchange for x/p0 worth of ETH. Then, after the price updates to p1, the attacker can sell it back to the protocol, making a profit:
Due to this front-running transaction on the oracle update, this portion of the profit is taken from the protocol’s reserves. If we set x = 100 ETH and p1 = 1.01 * p0 (a 1% price increase), this means the attacker has taken 1 ETH from the protocol’s reserves.
Fortunately, increasing transaction fees can mitigate this issue, as they erode the profits of front-runners and reduce opportunities.
For example, if the minting and burning transaction fees are constant and equal to f, an attacker who burns x stablecoins at p0 and then resells them to the protocol for ETH at p1 will have the following final profit:
Compared to the previous scenario, the fees reduce the profit:
When the transaction fee is f = 0.3% and following the example above, the attacker’s profit is now only 0.39 ETH.
To further reduce this opportunity, we can rely on a secondary oracle to provide two potential price sources: pC (Chainlink price) and pU (Uniswap price). The protocol can use the most favorable price (the lower price at minting, when buying the user’s tokens, and the higher price at burning, when selling ETH to the user), making the front-running opportunity less attractive.
Imagine a trader trying to profit from the same opportunity as above, assuming pC0 < pC1.
On the other hand, we can consider that pU is constant and closer to pC0. Therefore, as we will see later, due to the design of Uniswap’s time-weighted average price (TWAP), pU tends to lag behind pC.
In this case, an attacker attempting to profit from the potential opportunity would purchase tokens from the protocol at pC0 (burning stablecoins) and receive x(1-f)/pC0 worth of ETH. Then, they would sell it again at pU1 at a higher price. This would result in a loss for the attacker:
If we keep the numbers from the example, the attacker would ultimately lose 0.6 ETH in this transaction.
Angle’s design is specifically aimed at eliminating the risk of front-running transactions. Therefore, the protocol will implement a mechanism very similar to the example discussed above. In this section, we will explore the potential existing options in more detail, focusing on the specifics of the design we plan to implement and analyzing our choice of the TWAP time window.
The main oracle solutions that could fit Angle’s use case are:
Chainlink is the obvious first choice: it is a widely used decentralized oracle solution that provides multiple data sources covering various assets. The prices come from multiple sources and are relayed through a decentralized network, ensuring that the data is reliable, accessible, and difficult to manipulate. However, some data sources typically update only after “significant” price changes (such as a 0.5% change in ETH/USD) or after a period of time, meaning that Chainlink’s prices are always delayed compared to the actual market price. Therefore, Chainlink’s price updates may be front-run by checking off-chain prices or the mempool.
Uniswap V3’s Time-Weighted Average Price (TWAP) is another obvious and widely used oracle solution. The TWAP can be queried from Uniswap’s contract to get the time-weighted average price of tokens in a pool over a specific time period, ranging from a few seconds to 9 days. The price is calculated based on the average price of the two tokens in the pool during the specified period. This makes manipulating the TWAP require a large amount of capital and a longer period of time, which is inefficient in most cases.
Nonetheless, since TWAP is the average price over past blocks, they are generally delayed compared to real-time off-chain prices or even Chainlink’s price sources. If used alone, they would not be sufficient to protect the protocol from front-running transactions.
Additionally, since TWAP only reports the price of on-chain token pairs, they cannot meet the protocol’s goal of providing access to assets that are not represented on-chain (and therefore not in Uniswap pools), such as forex-backed stablecoins.
Using Maker Oracles could have been another option for Angle, but this would mean trusting MakerDAO and going through a governance process to gain access to the price data. The price sources would also be limited to those used by Maker, which is insufficient for us as we aim to access forex exchange rates.
With this in mind, it was decided to combine Angle Protocol’s Chainlink oracle with a 10-minute Uni V3 TWAP. This allows for the fairest price possible at any given time while protecting the protocol from front-running attacks.
Generally speaking, Angle’s contracts will compare the prices from both channels and use the price that is most favorable to the protocol. With this design, front-running the protocol becomes more complex because in order to exploit the protocol’s exchange rate, an attacker must manipulate or front-run both oracles.
Specifically, our contract will fetch the best price for all volatile asset/stablecoin pairs between Chainlink and Uniswap and use Chainlink’s forex oracle to convert the price to the required fiat currency. Each collateral/stablecoin pair will have a dedicated oracle contract with its own independent price source.
How does it work?
For example, assume a user wants to trade the ETH/agEUR pair. Our contract needs to fetch the prices for ETH/USD and USD/EUR. It will keep the best price for ETH/USD from Chainlink and the 10-minute TWAP from the ETH/USDC UniV3 pool. Then, it will fetch the USD/EUR forex price from Chainlink.
Example: Uniswap ETH/USDC TWAP: 1900 USD (the protocol assumes USDC generally maintains its peg, i.e., 1 USDC equals 1 USD) Chainlink ETH Price: 1850 USD Chainlink USD Price: 1.16 EUR
If the user wants to mint agEUR in this case, the protocol will use the lower ETH/USD price, i.e., Chainlink’s price of 1850 USD per ETH. Conversely, if the user wants to burn agEUR for wETH in the same situation, the protocol will use the higher price, i.e., Uni’s ETH/USDC TWAP of 1900. In both cases, the protocol will use Chainlink’s USD/EUR rate of 1.16 to convert ETH/USD to ETH/EUR.
Similarly, the protocol will use the highest price for users wishing to open a perpetual contract, and the lowest price for those wishing to close it.
More generally:
Angle’s contract will use a 10-minute time window for TWAP. This choice was made after careful consideration, as different time windows can result in significantly different price structures.
In the case of Angle, on one hand, the time window should be sufficiently long to provide enough lag between the protocol’s price and the spot price. This does allow for a larger spread between minting and burning prices during price fluctuations, especially when the risk of front-running on Chainlink is doubled. Additionally, the longer the time window, the harder it is to manipulate the TWAP price, as recent observations have less impact on the price.
On the other hand, the protocol must still offer users fair and up-to-date quotes: using a time window that is too wide will create too large a price gap between the protocol and the current market price, while using a time window that is too narrow will not provide the desired price difference.
Compare 10-minute and 60-minute TWAP with Chainlink price feeds
To give you an understanding of why we ultimately chose a 10-minute time window, here is a comparison between the 10-minute and 60-minute ETH/USDC TWAPs and the Chainlink ETH/USD price as well as the Coinbase closing price.
You can see how the upper and lower rates used by the protocol when users mint/close and burn/open move between the most favorable prices from Chainlink and Uniswap’s TWAP during price transitions.
Although the 60-minute TWAP block often gives prices that are far from the market, the 10-minute TWAP provides a beneficial buffer for Chainlink’s price source, keeping the price sufficiently close to the market.
It is worth noting that, as seen in the first chart, the greater the volatility, the larger the price difference between Chainlink and Uniswap prices. Conversely, when prices remain relatively stable over time, the price sources from Uniswap and Chainlink are closer to each other. Using TWAP as an additional protection against front-running is essentially a way to dynamically charge more in fees during periods of high volatility, as the front-running risk is greater due to delays in on-chain oracles. The cost of these higher effective fees is that it reduces the ability of arbitrage traders to directly reprice stablecoins from the protocol. In most cases, Uniswap and Chainlink prices will be very similar, and users will hardly notice the use of two oracle solutions. However, during periods of high volatility, when the protocol is at risk of front-running due to significant price differences between current and future Chainlink prices, the protocol’s pricing will differ, protecting it from front-running.
Angle’s oracle research is heavily inspired by Synthetix’s governance discussions and related blog posts on front-running. In our research, we also encountered another option they implemented in February 2020, the fee recovery/refund, which eventually became a temporary solution.
What they did was add a waiting period to transactions, during which users couldn’t manipulate the Synth they wanted to use. During this period, oracles could check if the transaction was affected by inconsistencies, specifically whether there was a price difference between the time of execution and the end of the waiting period. If a price difference existed, the difference had to be paid by the user or the protocol to the other party (protocol or user), or it would be settled in the next transaction with Synthetix.
This solution was very effective in reducing front-running, but they had to extend the waiting period and increase fees, which created a very poor user experience for all traders. It also prevented Synth from integrating with other protocols in many use cases. In SIP-120, they replaced this solution with a plan that adds the use of TWAP oracles for large transactions.
Angle’s specific oracle design has two major impacts on the protocol:
Attackers need to manipulate two markets to deceive the protocol, significantly reducing the risk of successful front-running trades.
During market stress periods, the protocol is unlikely to offer users the best possible price.
The latter impact has been discussed in the Fei governance forum. Since providing the best trade execution is not the core goal of the protocol, we believe that front-running resistance is more important to ensure the protocol’s security. In secondary markets during periods of high volatility, better trade execution will be offered.
Our goal in the Angle project is to design a fully supported, efficient stablecoin protocol. Achieving this requires considering many aspects of the protocol to ensure it cannot be deceived into an unfavorable position, one of which is front-running resistance. This is particularly important because the stability of on-chain decentralized stablecoins that rely on oracles depends on the quality of their oracles.
Adding secondary price feeds in the form of TWAP can help the protocol mitigate the potential adverse impacts of high market volatility and the front-running opportunities that arise during those times.
Lastly, it is important to note that this oracle solution maintains flexibility and scalability. On one hand, Angle governance can vote and update its oracle contracts at any time. On the other hand, oracles can be created for any price feed supported by Chainlink. This is the minimum level of support needed to achieve Angle’s vision of bringing financial assets on-chain in a capital-efficient way!
Angle allows users to mint and burn agTokens (stablecoins) in exchange for other tokens. Traders can also open long positions on available collateral/stablecoin pairs. These are not traditional perpetual contracts, as equilibrium does not rely on funding rates, and execution prices come directly from the oracle. Given these use cases, the protocol requires a reliable method to price available assets to offer users fair quotes while protecting itself from front-running transactions. In the FAQ of this article, Samcszun explains why this is not as simple as using spot prices.
Front-running has been a long-standing issue in the market. It comes down to certain participants gaining access to information earlier than others, allowing them to leverage this advantage to extract risk-free profits at the expense of the counterparty. Historically, preventing this phenomenon on-chain has been extremely challenging. The high costs and low speed of Ethereum transactions make it difficult for oracles to update prices quickly and frequently. This introduces delays between off-chain and on-chain prices, creating opportunities for front-runners to exploit.
Not all stablecoin protocols are concerned about front-running risks arising from oracle delays. In the case of Maker’s DAI, oracle delays often benefit the protocol. For instance, if a user sees that her position will be liquidated in the next oracle update due to a price drop, she is incentivized to deposit more funds into the vault, improving the protocol’s health and collateral ratio.
Synthetix, which enables oracle-based value exchanges between synthetic assets and collateral, is a perfect example of a stablecoin protocol facing front-running challenges. Their blog post outlines the protocol’s long history with front-running, including some past attacks they have suffered.
Similar to Synthetix, Angle allows asset swaps at oracle value with zero price slippage. As a result, Angle faces the same front-running issue. The Angle core team has made significant efforts to mitigate front-running. Two key improvements have been implemented: a specific oracle design and a dynamic fee structure. In this article, we will explain Angle’s oracle design and the reasoning behind it.
Before diving into Angle’s solution, let’s first try to understand how front-running can harm the protocol. We will consider an example where ETH is accepted as collateral to back Angle’s stablecoin.
Suppose an attacker is monitoring the off-chain ETH price and sees that the Chainlink oracle is about to update the on-chain data to a higher price (from p0 to p1, where p0 < p1). This attacker can send a transaction to burn x stablecoins at the price of p0 in exchange for x/p0 worth of ETH. Then, after the price updates to p1, the attacker can sell it back to the protocol, making a profit:
Due to this front-running transaction on the oracle update, this portion of the profit is taken from the protocol’s reserves. If we set x = 100 ETH and p1 = 1.01 * p0 (a 1% price increase), this means the attacker has taken 1 ETH from the protocol’s reserves.
Fortunately, increasing transaction fees can mitigate this issue, as they erode the profits of front-runners and reduce opportunities.
For example, if the minting and burning transaction fees are constant and equal to f, an attacker who burns x stablecoins at p0 and then resells them to the protocol for ETH at p1 will have the following final profit:
Compared to the previous scenario, the fees reduce the profit:
When the transaction fee is f = 0.3% and following the example above, the attacker’s profit is now only 0.39 ETH.
To further reduce this opportunity, we can rely on a secondary oracle to provide two potential price sources: pC (Chainlink price) and pU (Uniswap price). The protocol can use the most favorable price (the lower price at minting, when buying the user’s tokens, and the higher price at burning, when selling ETH to the user), making the front-running opportunity less attractive.
Imagine a trader trying to profit from the same opportunity as above, assuming pC0 < pC1.
On the other hand, we can consider that pU is constant and closer to pC0. Therefore, as we will see later, due to the design of Uniswap’s time-weighted average price (TWAP), pU tends to lag behind pC.
In this case, an attacker attempting to profit from the potential opportunity would purchase tokens from the protocol at pC0 (burning stablecoins) and receive x(1-f)/pC0 worth of ETH. Then, they would sell it again at pU1 at a higher price. This would result in a loss for the attacker:
If we keep the numbers from the example, the attacker would ultimately lose 0.6 ETH in this transaction.
Angle’s design is specifically aimed at eliminating the risk of front-running transactions. Therefore, the protocol will implement a mechanism very similar to the example discussed above. In this section, we will explore the potential existing options in more detail, focusing on the specifics of the design we plan to implement and analyzing our choice of the TWAP time window.
The main oracle solutions that could fit Angle’s use case are:
Chainlink is the obvious first choice: it is a widely used decentralized oracle solution that provides multiple data sources covering various assets. The prices come from multiple sources and are relayed through a decentralized network, ensuring that the data is reliable, accessible, and difficult to manipulate. However, some data sources typically update only after “significant” price changes (such as a 0.5% change in ETH/USD) or after a period of time, meaning that Chainlink’s prices are always delayed compared to the actual market price. Therefore, Chainlink’s price updates may be front-run by checking off-chain prices or the mempool.
Uniswap V3’s Time-Weighted Average Price (TWAP) is another obvious and widely used oracle solution. The TWAP can be queried from Uniswap’s contract to get the time-weighted average price of tokens in a pool over a specific time period, ranging from a few seconds to 9 days. The price is calculated based on the average price of the two tokens in the pool during the specified period. This makes manipulating the TWAP require a large amount of capital and a longer period of time, which is inefficient in most cases.
Nonetheless, since TWAP is the average price over past blocks, they are generally delayed compared to real-time off-chain prices or even Chainlink’s price sources. If used alone, they would not be sufficient to protect the protocol from front-running transactions.
Additionally, since TWAP only reports the price of on-chain token pairs, they cannot meet the protocol’s goal of providing access to assets that are not represented on-chain (and therefore not in Uniswap pools), such as forex-backed stablecoins.
Using Maker Oracles could have been another option for Angle, but this would mean trusting MakerDAO and going through a governance process to gain access to the price data. The price sources would also be limited to those used by Maker, which is insufficient for us as we aim to access forex exchange rates.
With this in mind, it was decided to combine Angle Protocol’s Chainlink oracle with a 10-minute Uni V3 TWAP. This allows for the fairest price possible at any given time while protecting the protocol from front-running attacks.
Generally speaking, Angle’s contracts will compare the prices from both channels and use the price that is most favorable to the protocol. With this design, front-running the protocol becomes more complex because in order to exploit the protocol’s exchange rate, an attacker must manipulate or front-run both oracles.
Specifically, our contract will fetch the best price for all volatile asset/stablecoin pairs between Chainlink and Uniswap and use Chainlink’s forex oracle to convert the price to the required fiat currency. Each collateral/stablecoin pair will have a dedicated oracle contract with its own independent price source.
How does it work?
For example, assume a user wants to trade the ETH/agEUR pair. Our contract needs to fetch the prices for ETH/USD and USD/EUR. It will keep the best price for ETH/USD from Chainlink and the 10-minute TWAP from the ETH/USDC UniV3 pool. Then, it will fetch the USD/EUR forex price from Chainlink.
Example: Uniswap ETH/USDC TWAP: 1900 USD (the protocol assumes USDC generally maintains its peg, i.e., 1 USDC equals 1 USD) Chainlink ETH Price: 1850 USD Chainlink USD Price: 1.16 EUR
If the user wants to mint agEUR in this case, the protocol will use the lower ETH/USD price, i.e., Chainlink’s price of 1850 USD per ETH. Conversely, if the user wants to burn agEUR for wETH in the same situation, the protocol will use the higher price, i.e., Uni’s ETH/USDC TWAP of 1900. In both cases, the protocol will use Chainlink’s USD/EUR rate of 1.16 to convert ETH/USD to ETH/EUR.
Similarly, the protocol will use the highest price for users wishing to open a perpetual contract, and the lowest price for those wishing to close it.
More generally:
Angle’s contract will use a 10-minute time window for TWAP. This choice was made after careful consideration, as different time windows can result in significantly different price structures.
In the case of Angle, on one hand, the time window should be sufficiently long to provide enough lag between the protocol’s price and the spot price. This does allow for a larger spread between minting and burning prices during price fluctuations, especially when the risk of front-running on Chainlink is doubled. Additionally, the longer the time window, the harder it is to manipulate the TWAP price, as recent observations have less impact on the price.
On the other hand, the protocol must still offer users fair and up-to-date quotes: using a time window that is too wide will create too large a price gap between the protocol and the current market price, while using a time window that is too narrow will not provide the desired price difference.
Compare 10-minute and 60-minute TWAP with Chainlink price feeds
To give you an understanding of why we ultimately chose a 10-minute time window, here is a comparison between the 10-minute and 60-minute ETH/USDC TWAPs and the Chainlink ETH/USD price as well as the Coinbase closing price.
You can see how the upper and lower rates used by the protocol when users mint/close and burn/open move between the most favorable prices from Chainlink and Uniswap’s TWAP during price transitions.
Although the 60-minute TWAP block often gives prices that are far from the market, the 10-minute TWAP provides a beneficial buffer for Chainlink’s price source, keeping the price sufficiently close to the market.
It is worth noting that, as seen in the first chart, the greater the volatility, the larger the price difference between Chainlink and Uniswap prices. Conversely, when prices remain relatively stable over time, the price sources from Uniswap and Chainlink are closer to each other. Using TWAP as an additional protection against front-running is essentially a way to dynamically charge more in fees during periods of high volatility, as the front-running risk is greater due to delays in on-chain oracles. The cost of these higher effective fees is that it reduces the ability of arbitrage traders to directly reprice stablecoins from the protocol. In most cases, Uniswap and Chainlink prices will be very similar, and users will hardly notice the use of two oracle solutions. However, during periods of high volatility, when the protocol is at risk of front-running due to significant price differences between current and future Chainlink prices, the protocol’s pricing will differ, protecting it from front-running.
Angle’s oracle research is heavily inspired by Synthetix’s governance discussions and related blog posts on front-running. In our research, we also encountered another option they implemented in February 2020, the fee recovery/refund, which eventually became a temporary solution.
What they did was add a waiting period to transactions, during which users couldn’t manipulate the Synth they wanted to use. During this period, oracles could check if the transaction was affected by inconsistencies, specifically whether there was a price difference between the time of execution and the end of the waiting period. If a price difference existed, the difference had to be paid by the user or the protocol to the other party (protocol or user), or it would be settled in the next transaction with Synthetix.
This solution was very effective in reducing front-running, but they had to extend the waiting period and increase fees, which created a very poor user experience for all traders. It also prevented Synth from integrating with other protocols in many use cases. In SIP-120, they replaced this solution with a plan that adds the use of TWAP oracles for large transactions.
Angle’s specific oracle design has two major impacts on the protocol:
Attackers need to manipulate two markets to deceive the protocol, significantly reducing the risk of successful front-running trades.
During market stress periods, the protocol is unlikely to offer users the best possible price.
The latter impact has been discussed in the Fei governance forum. Since providing the best trade execution is not the core goal of the protocol, we believe that front-running resistance is more important to ensure the protocol’s security. In secondary markets during periods of high volatility, better trade execution will be offered.
Our goal in the Angle project is to design a fully supported, efficient stablecoin protocol. Achieving this requires considering many aspects of the protocol to ensure it cannot be deceived into an unfavorable position, one of which is front-running resistance. This is particularly important because the stability of on-chain decentralized stablecoins that rely on oracles depends on the quality of their oracles.
Adding secondary price feeds in the form of TWAP can help the protocol mitigate the potential adverse impacts of high market volatility and the front-running opportunities that arise during those times.
Lastly, it is important to note that this oracle solution maintains flexibility and scalability. On one hand, Angle governance can vote and update its oracle contracts at any time. On the other hand, oracles can be created for any price feed supported by Chainlink. This is the minimum level of support needed to achieve Angle’s vision of bringing financial assets on-chain in a capital-efficient way!