2023-06-23 Audit Report - Osmosis Q2
Security Audit Report
Osmosis Q2 2023
Authors: Aleksandar Ljahovic, Ivan Golubovic
Last revised 23 June, 2023 © 2023 Informal Systems Osmosis Q2 2023
Table of Contents Audit overview............................................................................................................. 1 The Project 1 Scope of this audit 1 Conducted work 1 Conclusions 1 Audit dashboard.......................................................................................................... 2 Target Summary 2 Engagement Summary 3 Severity Summary 3 System Overview......................................................................................................... 4 Concentrated liquidity 4 Threat inspection ...................................................................................................... 10 User categories 10 Threats 10 Findings ..................................................................................................................... 14 Division by zero protection in distribute.go 15 Insufficient validation on gauge creation 17 Optimization opportunity in addToPosition for last position withdrawal 19 Missing validation for negative number of shares when creating accumulator position 21 Redundant checks 23 Store loading optimization 24 Minor code improvements 26 Redundant condition check in loop for qualifyingLiquidity evaluation 27 Alignment issue between comments and code in tick comparison logic 29 Redundancies in GetAllPositionIdsForPoolId() function and ensurePositionOwner() usage 31 Inefficient string concatenation 33 Inefficient comparison methods and unnecessary object creation 35 Appendix: Vulnerability Classification ..................................................................... 37 Impact Score 37 Exploitability Score 37 © 2023 Informal Systems Osmosis Q2 2023
Severity Score 38 Disclaimer.................................................................................................................. 40 © 2023 Informal Systems Osmosis Q2 2023
Audit overview The Project Osmosis has created an innovative take on concentrated liquidity. Drawing inspiration from Uniswap's Automated Market Maker (AMM) design, Osmosis introduces a novel approach that enhances capital efficiency by 200-300 times compared to traditional AMMs. By allowing Liquidity Providers (LPs) to concentrate their capital within specific price ranges, Osmosis ensures assets closely align with their desired spot prices. This targeted liquidity provision offers reduced price impact, increased market stability, and opens up new possibilities for incentivizing LPs based on their proximity to the current price and position duration. With its groundbreaking implementation of concentrated liquidity, Osmosis pioneers more efficient and robust decentralized exchange mechanisms within the DeFi ecosystem.
Scope of this audit Initially scheduled from May 15, 2023, to June 12, 2023, the audit timeline was extended to June 21, 2023, in agreement with Osmosis. The extension allowed for a thorough examination of subsequent changes made after the initial commit, as well as critical issues identified by Osmosis. The audit team consisted of the following personnel: • Ivan Golubovic • Aleksandar Ljahovic During the audit, our focus was on analyzing the x/concentrated-liquidity module and related changes in x/ incentives, x/superfluid, x/gamm, osmoutils/accum, and other relevant areas concerning the concentrated liquidity concept.
Conducted work The audit project encompassed the following activities: • Manual code inspection of the x/concentrated-liquidity module and associated changes in other components. We conducted a thorough examination of the codebase, documenting our insights in the "System Overview" section. The manual code inspection revealed the majority of the findings presented in this report. • Where possible, we attempted to reproduce the findings using Osmosis' integration/unit/end-to-end test suite. Any relevant tests used to reproduce the findings are detailed in the respective sections.
Conclusions Overall, we found the codebase to exhibit exceptional quality, characterized by well-structured and comprehensible code. The comprehensive test suite includes unit, integration, and valuable end-to-end testing environments. During the audit, we identified 1 high severity finding, along with several medium, low, or informational severity findings. Based on our analysis, we recommend the following areas for immediate and relatively low effort improvements: • Optimization in data storage: Some findings highlight potential improvements in how KV stores are utilized. Small adaptations can yield significant enhancements in storage mechanisms. • Performance optimizations: Another noteworthy area pertains to findings related to performance improvements. Although these changes may be small individually, their cumulative impact can lead to substantial overall improvements over time.
Audit overview 1 © 2023 Informal Systems Osmosis Q2 2023
Audit dashboard Target Summary • Type: Specification and Implementation • Platform: Golang • Artifacts: • Commit hash: 9e1ca7beb15efaf027282946b7231a4bdfc4f32f • Additional list of PRs to be reviewed: • Key malleability - possible to claim ownership of someone else's position: https://github.com/ osmosis-labs/osmosis/pull/5467 • Tick rounding issue causing funds drained: https://github.com/osmosis-labs/osmosis/pull/ 5493 • Incorrect bound check for liquidity amounts, allowing to withdraw more than eligible for: https://github.com/osmosis-labs/osmosis/pull/5474 • Incorrect handling of forfeited incentives: https://github.com/osmosis-labs/osmosis/pull/ 5495 • Tick iterator bugs: https://github.com/osmosis-labs/osmosis/pull/5491 • Incentive emission share calculation not accounting for active tick liquidity: https:// github.com/osmosis-labs/osmosis/pull/5417 • remove repeated reallocations in swap step iterations: https://github.com/osmosis-labs/ osmosis/pull/5211 • separate fees into different module account: https://github.com/osmosis-labs/osmosis/pull/ 5230 • MsgSwapExactAmountOut audit: https://github.com/osmosis-labs/osmosis/pull/5179 • v16 upgrade handler updates: https://github.com/osmosis-labs/osmosis/pull/5213 • change KVStore value from posID to boolean byte: https://github.com/osmosis-labs/osmosis/ pull/5237 • update rewards splitting logic to only use bonded classic pool balances: https://github.com/ osmosis-labs/osmosis/pull/5239 • MsgUnlockAndMigrateSharesToFullRangeConcentratedPosition audit (part 2/2): https:// github.com/osmosis-labs/osmosis/pull/5160 • reinvest dust fees back into pool accum: https://github.com/osmosis-labs/osmosis/pull/5245 • iterator improvements for swap in given out and liquidity for full range query: https:// github.com/osmosis-labs/osmosis/pull/5248 • multiple fee tokens gov prop: https://github.com/osmosis-labs/osmosis/pull/5261 • bump sdk fork with sqrt perf improvements: https://github.com/osmosis-labs/osmosis/pull/ 5249 • remove repeated pool exists check: https://github.com/osmosis-labs/osmosis/pull/5278 • avoid refetching ticks during swaps; parse from iterator value: https://github.com/osmosis- labs/osmosis/pull/5288 • liquidity net in direction sdk.Int -> int64: https://github.com/osmosis-labs/osmosis/pull/5299 • liquidity for full range sdk.Int -> int64: https://github.com/osmosis-labs/osmosis/pull/5300 • remove repeated pool unmarshaling and uptime accum refetching overhead in swaps: https://github.com/osmosis-labs/osmosis/pull/5295 • Fix tick range helper and update tests/comments: https://github.com/osmosis-labs/osmosis/ pull/5313 • Fix discount rate bound check: https://github.com/osmosis-labs/osmosis/pull/5314 • expect single synthetic lock per native lock ID: https://github.com/osmosis-labs/osmosis/pull/ 5265 • fungify message audit: https://github.com/osmosis-labs/osmosis/pull/5317 • Remove double rounding in CalcAmount1Delta : https://github.com/osmosis-labs/ osmosis/pull/5326 • pools gov prop supercharge liquidity: https://github.com/osmosis-labs/osmosis/pull/5345
Audit dashboard 2 © 2023 Informal Systems Osmosis Q2 2023
• Update Accumulator while collecting incentives: https://github.com/osmosis-labs/osmosis/ pull/5290 • Make calc accrued incentives nonmutative: https://github.com/osmosis-labs/osmosis/pull/ 5361 • twap record upgrade handler: https://github.com/osmosis-labs/osmosis/pull/5363 • single migration entry point: https://github.com/osmosis-labs/osmosis/pull/5360 • Add 2 week supported uptime: https://github.com/osmosis-labs/osmosis/pull/5349 • Fix SwapInGivenOut to track fees with the correct denom: https://github.com/osmosis-labs/ osmosis/pull/5388 • Delete wrong check in ValidateBasic of MsgUnlockAndMigrateSharesToFullRangeConcentratedPosition :https:// github.com/osmosis-labs/osmosis/pull/5393 • fix uptime Accumulator init genesis: https://github.com/osmosis-labs/osmosis/pull/5411 • Fix incentive emission share calculation: https://github.com/osmosis-labs/osmosis/pull/5417 • redirect distribution record on migrate link: https://github.com/osmosis-labs/osmosis/pull/ 5400 • feat: NoLock gauge type and external gauge creation wiring to CL: https://github.com/ osmosis-labs/osmosis/pull/5459 • refactor/fix(CL): add IDs to incentive record keys to avoid overwriting: https://github.com/ osmosis-labs/osmosis/pull/5496
Engagement Summary • Dates: 15.05.2023 to 21.06.2023 • Method: Manual code review, protocol analysis • Employees Engaged: 2
Severity Summary Finding Severity #
Critical 0
High 1
Medium 1
Low 1
Informational 7
Total 10
Audit dashboard 3 © 2023 Informal Systems Osmosis Q2 2023
System Overview Osmosis is a decentralized blockchain protocol built on top of the Cosmos network. It aims to provide an infrastructure for efficient and secure token exchange. Osmosis focuses on the concept of liquidity pools, allowing users to create and manage pools of tokens for trading purposes. By using the Osmosis platform, users can create and manage liquidity pools by depositing pairs of tokens. These pools enable the exchange of tokens and serve as the basis for price discovery. Liquidity providers earn transaction fees and receive liquidity pool tokens in return for providing liquidity. Osmosis supports multiple pool types (balancer, stableswap) and the scope of this audit is around concentrated liquidity pools.
Concentrated liquidity The design of the Automated Market Maker, introduced by Uniswap, which is based on creating the possibility to liquid in specific price ranges using the concept of ticks is called concentrated liquidity. It allows liquidity providers (LPs) to focus their capital in a specific price range, resulting in higher efficiency and lower price impact for traders. Osmosis team used further developed Uniswap’s design and created its own concentrated liquidity AMM. The architecture of concentrated liquidity introduces the concept of a "position" that concentrates liquidity within a fixed range. Instead of tracking individual token reserves, the design tracks the liquidity amount and the square root of the price ratio. This enables efficient calculation of outcomes for swaps and pool joins. Ticks are discrete points utilized in concentrated liquidity (CL) pools. In the conventional approach, ticks have a fixed difference of 0.01% between adjacent prices. However, Osmosis adopts a geometric tick spacing methodology with additive ranges. This approach offers enhanced granularity and control over tick prices, enabling liquidity providers (LPs) to trade at desired spot prices. The formulas involved in tick spacing establish the relationship between ticks and prices. The precision factor is defined at the starting tick ( exponentAtPriceOne ), and the tick spacing determines the increment distance. By calculating geometric exponents and additive ticks, the corresponding price for a tick can be determined, and vice versa. The decision to employ geometric tick spacing with additive ranges facilitates trading at desired spot prices and enhances the user experience. It eliminates the need for rounding or restricting trades to specific prices. However, multiple ticks may represent the same price, and in such cases, a larger tick representing the same price is chosen when creating a position. Key distinctions between Osmosis' implementation and Uniswap CL are as follows:
- Geometric tick spacing with additive ranges Osmosis improves upon Uniswap's logarithmic spacing by employing geometric tick spacing with additive ranges. The core idea is that by adjusting the precision for each power of 10, human-readable values align with actual tick spots.
- Superfluid full range positions Osmosis introduces the ability to superfluidly stake positions, but only as full range positions within the CL pool. Notably, the balancer position is analogous to a full range CL position, which is why it can be superfluid staked.
- Migration logic It is possible to migrate a position from another pool (e.g., Balancer) to the CL pool. To enable this, a governance-approved connection must exist between a single Balancer pool and a single CL pool when the CL pool is created. Partial migration is also allowed. The Balancer position to be migrated can be in one of four different states, and the migration path is determined based on its current state. These states are: a. superfluid staked and it’s bonded for 14 days, b. superfluid unbonding position (still unbonding, e.g day 7 of 14), c. locked but not superfluid staked, d. not locked at all.
- Shared incentive logic In Osmosis' design, all rewards are calculated based on CL pool positions, but transactions can be
System Overview 4 © 2023 Informal Systems Osmosis Q2 2023
conducted through both the CL and Balancer pools, with both pools receiving incentives. To facilitate this, the Balancer pool is represented as a single full range position within the CL pool. During the calculation process, the funds to which the Balancer pool is entitled are routed based on the calculations for its position within the CL pool. 5. Charging to be qualified for uptime incentives (1ns) Originally, a position was entitled to rewards upon creation but could only collect them after a certain period of uptime. Osmosis deemed this requirement too strict and modified the uptime to 1ns, allowing rewards to be collected immediately. This adjustment serves as an interim approach until their new design for uptimes is finalized. During the audit, two detailed diagrams were created to help in the process of system understanding and finding possible vulnerabilities. The first is showing the interactions with the stores while the other one is showing the flow in migration logic.
System Overview 5 © 2023 Informal Systems Osmosis Q2 2023
It should also be noted that CL pool creation after launching is going to be permissioned. To better explain the core concepts of Osmosis’ design, messages from concentrated liquidity module are described below.
Messages
MsgCreateConcentratedPool Message CreateConcentratedPool is utilized to instantiate a concentrated liquidity pool. The creation process, executed through the poolmanager module, involves validating the creation message, creating and validating the pool itself, and initializing it. Once the initialization is complete, events signaling the pool creation are emitted.
Pool initialization is called from the poolmanager module but is executed within the concentrated- liquidity module. During initialization, the tick spacing, swap fee, and quote denominations (extracted from the creation message) are validated to ensure authorized values. The initialization process also encompasses creating fee and uptime accumulators, setting the timestamp for the last liquidity update, saving the pool to storage, and invoking specific listeners. Initially, pool creation is planned to be invoked by governance proposal after launching the audited scope, but in the future, it will transition to a permissionless approach.
System Overview 6 © 2023 Informal Systems Osmosis Q2 2023
MsgCreatePosition This message is employed to create positions in a concentrated liquidity pool. The message includes the following data: the pool's ID where the position is being created, the address of the message sender, the lower and upper tick bounds of the position, the quantity of tokens provided for the position, and the desired minimum amounts of specific tokens to be added or removed from the pool. To create a position, all the forwarded data in the message undergoes validation and recalculation based on the pool's properties. For instance, the liquidity amounts to be provided are proportionate to the existing reserves. Additionally, the created position and the actual token amounts calculated are checked against the user's desired amounts of tokens to be received or sent. A crucial calculation involved in this message is determining the price based on the provided ticks. Osmosis employs a customized approach to ticks representation and these calculations, which are thoroughly explained in the provided documentation. Finally, once the correct token amounts are obtained, they are transferred from the user to the pool, followed by emitting a specific event.
MsgAddToPosition This message is used to add a certain amount of tokens to already created positions. According to the current design, the position associated with the forwarded ID in the message parameters is deleted during the process, while a new position is created, combining the tokens already positioned under the mentioned ID and the ones sent via the message. The sender of this message must be the same as the creator of the position being updated, and the position must not be superfluidly staked. After initial input validations, the process begins with withdrawing from the position with the current ID. This process also encompasses collecting fees and incentives from that position. Essentially, the withdrawal process represents an update to the position with a new liquidity amount. The amount can be equal to or less than the currently available liquidity, and in the former case, the position is deleted. When withdraw is invoked from MsgAddToPosition , it withdraws the full liquidity amount each time to delete the position to which funds are being added (based on the current design). The withdrawal procedure concludes with the actual transfer of tokens from the pool to the user, followed by emitting an event. The withdrawal process is succeeded by creating the new position with the updated token amounts. An event is also triggered to announce the position creation.
MsgWithdrawPosition The MsgWithdrawPosition message is utilized to withdraw funds from a specific position in the pool and transfer them to the user. Validations for this message include verifying that the owner and creator of the position are the same, ensuring that the withdrawal amount is not negative, and checking that the requested liquidity amount to be withdrawn is not greater than the available liquidity in the specified position. The withdrawal process also includes checks for any underlying locks on the position. In addition to the mentioned validations, this process involves collecting incentives for the position. If the complete liquidity is being withdrawn, fees are also collected. In such cases, the pool must be uninitialized, with the square root price and tick set to zero. Lastly, the position being withdrawn from is updated in terms of the tick and liquidity amount.
System Overview 7 © 2023 Informal Systems Osmosis Q2 2023
MsgCollectFees The MsgCollectFees message is used to collect fees from specified positions. The message contains information about the positions from which the fees should be obtained, including the sender of the message and the position IDs. The sender must also be the owner of the positions. The following process occurs for each
Excerpt (19993 of 76455 characters). Read the whole page on informalsystems/audits ↗