eIP 3: Contract Upgrades

Exec module


  • liquidity, detailedLiquidity, getPrice, and getPriceFull

    • These functions have had their re-entrancy guards removed, since all they do is delegatecall to methods in RiskManager that are views (as of the previous update). Ideally we would like to mark these functions as views themselves, however the solidity compiler does not allow a function that uses delegatecall to be a view.
    • To get around this compiler limitation, a staticDelegate modifier is added: This is an empty modifier that has no effect on the compiled code, but instead signals to our build system that such methods are safe to be invoked with staticcall and so their exported interfaces are adjusted to be views.
  • usePermit, usePermitAllowed, usePermitPacked

    • These are new functions that allow a user to invoke permit() on token contracts so that signed permit messages can be applied within batch transactions, and users don’t need to issue separate approval transactions.
    • There are three variations because in order to support the most common variants implemented by tokens.
    • Although these methods allow an external user to cause the Euler contract to call an arbitrary external address, there are restrictions in place to prevent this from causing harm:
      • The target address must’ve been activated on Euler so it needs to be at least a partially compliant ERC-20 token with a uniswap pair, and cannot be an internal Euler contract
      • The only function signatures allowed are the 3 identified common permit signatures
      • The owner/holder parameter must be the address that is invoking the function, and the spender parameter is always the Euler contract address.
  • doStaticCall

    • This is a new view method that calls staticcall on an arbitrary address with arbitrary arguments
    • It is useful for querying the state of the blockchain within a batch transaction that is invoked off-chain (ie using the callStatic ethers method), to determine what the updated chain state would be after applying a batch. This will be useful for our “Transaction Builder 2.0” re-design project.

EToken module


  • convertBalanceToUnderlying and convertUnderlyingToBalance view functions were added
    • These allow convenient conversion between internal EToken accounting units and underlying units, which will be helpful for integrations
  • transferFromMax
    • A wrapper method that allows users to transfer their entire EToken balances
    • Useful in batch transactions after a swap, where you don’t necessarily know the precise balance you will have at transaction creation time.

RiskManager module


  • Self collateralisation
    • The computeLiquidityRaw function has been refactored to implement special collateralisation logic for the case where an account has assets and liabilities on the same asset. In the normal case, rational users would not do this, since they will be paying more interest than they are receiving and have no exposure to price movements. However, with liquidity mining users who take out loans will receive EUL tokens as compensation, which can compensate for this loss due to interest.
    • A new constant SELF_COLLATERAL_FACTOR was added, which represents the effective collateral factor available for self-collaterised loans. This defaults to 0.95 (20x leverage).
    • In order to simplify the analysis of liquidations, self-collateralised loans are always borrow isolated, even if the asset itself is not borrow isolated.



  • When a self-collateralised loan is liquidated, the entire self-collateralised debt is allowed to be repaid. This simplifies the analysis of the liquidation.
  • A divide by 0 error will no longer be thrown during a liquidation if the borrow factor is set to 0.



  • Bugfix: During a swap, when the new eToken amount was being credited, the poolSize member of AssetCache was updated assuming the token had 18 decimals. In cases where the underlying asset has fewer decimals, this caused the AssetStatus log entry to contain an incorrect value for poolSize. Additionally, this incorrect value was used as an input to compute the new interest rate on the asset. Fortunately this effect is typically very small and the interest rate is corrected the next time any operation is performed on the asset.

Updates to shared code/libraries

  • An optimisation to unpackTrailingParamMsgSender and unpackTrailingParams will save a small amount of gas when calling functions in most modules.

  • There was a bugfix to transferBorrow, but all the contracts that actually use this code were already deployed.


happy to see eIP 3: Contract Upgrades

1 Like

I’m curious what the reasoning is for increasing the minimum uniswap oracle cardinality MIN_UNISWAP3_OBSERVATION_CARDINALITY = 144

great…wish someday to see new updates about systematically reducing trading cost

1 Like

Hi! Good question.

This constant controls the uniswap observation cardinality that will be guaranteed when a market is activated. If the uniswap pool that is selected for pricing has a smaller cardinality, the market activator will pay the gas to increase this to 144.

144 was selected because it is on-average sufficient to satisfy the default TWAP window of 30 minutes, assuming 12.5 second block times.

One thing to note though: The code that uses this value of 144 has already been live and was deployed on a previous update to RiskManager. The reason you are seeing this update in these diffs is that these modules haven’t been upgraded since then, so the shared Constants.sol file that all modules pull in will show these updates, even though the modules in question don’t actually use this constant.

1 Like

This update does have a few minor optimisations, such as the improvement to unpackTrailingParamMsgSender, although I agree it would be great to do more also.

Did you have any operations in particular you think are too expensive? We’ve designed the system so that there are often pretty significant gas savings if complex operations are done in batch operations as opposed to multiple transactions.

1 Like

I don’t see how upgrading the contracts for the better could be harmful.

Audit & deploy! ;p

1 Like

Thanks! Yep, these are being looked at as we speak :slight_smile:


maybe after Layer2 it’s gona be cheap…i understand it’s not Euler’s problem

A quick update on this: These changes have been reviewed by external parties and no issues have been found. We’ve also deployed the changes to ropsten testnet and there haven’t been any issues discovered there either.

We’re aiming to coordinate this release to mainnet in the next couple days.


One thing to note about this upgrade:

If an account currently has a “self-collateralised” loan (both supplying and borrowing the same token simultaneously), as well as a borrow for a separate token, then this upgrade will cause that account to go into borrow isolation violation. This is easy to fix, of course, by repaying one or more of the loans, but could potentially cause confusion and disruption for users.

Because of this, we’ve added a feature on the website that alerts users who are in this state. We’re also trying to get the word out and give users some extra notice. Once this is done, we’ll deploy this eIP.

1 Like

Layer2 it’s gona be cheap