Guardian's review of Periphery Contracts for Axis Finance, published August 2024. The report records 35 findings across 2 review rounds, including 2 critical and 9 high.
- Published
- Review window
- July 23 to August 17, 2024
- Rounds
- Main Review, Remediation Review
- Language
- Solidity
- Chains
- Ethereum, Arbitrum, Base, Berachain, Blast, BNB Chain, Mantle, Sonic
- Sector
- Token launches
- 2 Critical
- 9 High
- 7 Medium
- 17 Low
- 0 Informational
Scope
5 files in scope · 615 nSLOC
| File | nSLOC | Lines |
|---|---|---|
src/callbacks/liquidity/UniswapV3DTL.sol | 110 | 224 |
src/callbacks/liquidity/UniswapV2DTL.sol | 55 | 122 |
src/callbacks/liquidity/BaseDTL.sol | 192 | 385 |
src/callbacks/liquidity/BaselineV2/BaselineAxisLaunch.sol | 210 | 523 |
dependencies/axis-core-1.0.0/src/bases/BaseCallback.sol | 48 | 192 |
Findings 35
Main Review
28 findings · July 23 to 29, 2024-
C-01 Critical Gaming Uni V3 Initialization DoS Resolved
Description
Through initializing the Uniswap V3 pool, a malicious user can manipulate the price of the tokens from an auction and sell their newly purchased tokens for a profit. This attack is possible because any person can call
settle()and set themaxSlippageto an unreasonably high number. In order to execute this attack, a malicious user would need to:- Buy tokens in an auction.
- Initialize a Uniswap V3 Pool with a high price.
- Call
settle()withmaxSlippageset to100e2. - Sell their tokens in the Uniswap V3 Pool.
It is also worth noting that if
settle()is first called by the seller with a reasonable slippage tolerance, the transaction will revert, and the attacker will be able to follow up and execute the transaction with the proper slippage.Recommendation
There are two possible solutions for this issue. The first is to make
settle()only callable by the seller, so that they can specify the slippage tolerance. Then wrap the callback in atry/catchblock. Inside thecatch, transfer the tokens back to the seller if the transaction reverts.Alternatively if you do not wish to make changes to the core system, add
minSlippageAmtOutToken0andminSlippageAmtOutToken1toDTLConfiguration. This way the owner can be certain that slippage is not set to an intolerable amount, regardless of who callssettle(). -
C-02 Critical Uniswap V2 Auction Settlement DoS Logical Error Resolved
Description
When a UniV2 pool is used as apart of the token launch the settle function will attempt to add liquidity to the pair. However this will only be successful if the pool has either a non-zero balance of both assets. Or a zero balance of both assets.
If the pair has a non-zero reserve for one asset and a zero reserve for the other it will revert when attempting to add liquidity.
This is due to the following check when the
addLiquidityfunction calls thequotefunction.require(reserveA > 0 && reserveB > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');Typically it is not possible to get a pair into this state as the first time adding liquidity to a pair, both assets must be added.
However an attacker can bypass this by donating a dust amount of one of the assets to the pair and then calling
sync. By doing this the reserves of that pair will update and to having one reserve being zero and the other being non-zero. Thus causing the revert when the auction tries to settle.All an attacker would need to do in this case is monitor Axis auction creations, create the pair ahead of time and donate 1 wei of the quote token. By doing this the auction will not be able to settle.
Recommendation
Calculate the amount to be minted to the pair and call the
mintfunction instead ofaddLiquidityto avoid this DOS case. -
H-01 High Curator Fees Will DoS Auction Settlement Logical Error Resolved
Description
Auction seller can opt to set a curator in charge of approving a batch auction lot. This curator will receive some base tokens.
The issue relies on Baseline auctions, as curator fees were not expected to be enabled, but fees in bAssets are actually minted during the
onCuratecallback, as this permission flag is enabled in the callback contract.This additional bAssets minted will cause the
onSettlecallback to revert, as curator fees increases the bAsset spot supply, breaking the capacity invariant (capacity ratio < 100%) and causing a DoS on auction settlementRecommendation
If curator fees are enabled for Baseline Auctions, consider accounting for these fees during
onSettlecallback. Otherwise, revert during theonCuratecallback. -
H-02 High Pool Percentage Causes DoS DoS Resolved
Description
For Baseline, allowing a user to set the
poolPercent, can cause a revert in_onSettle(). If thepoolPercentis not configured to 100%, the revert will occur due to thecapacityRationot being within a tolerable range. ThecapacityRatiois not satisfied because there is not enough backing liquidity to support the Baseline system. Since the revert is not caught in_onCreate(), an auction will be carried out, but then it will become unsettleable.Recommendation
Do not allow the user to configure
poolPercent, it should be set to 100%. -
H-03 High Baseline Settlement DoS Via External Liquidity DoS Resolved
Description
Reserves added as liquidity during Baseline token launches must have enough capacity to buy back all circulating
bAssets at the floor price. This verification is conducted in the_onSettlefunction, and the total capacity must fall within the range of 100% to 102%.The calculation of capacity involves the total liquidity amounts of the BPOOL contract in floor, anchor, and discovery ranges. However, anyone can add liquidity on behalf of the BPOOL before settlement, increasing the total capacity beyond 102% and causing the
_onSettlecallback to fail.Recommendation
It is suggested to verify the LP token balance of the BPOOL before adding reserves/liquidity to the underlying pool and burn these tokens. Alternatively, consider allowing any capacity ratio above 100% without restricting it to 102%.
-
H-04 High bAsset Price Set Below Floor Gaming Partially resolved
Description
The Uniswap pool is set up and initialized with the BPOOL contract before the auction begins.
The pool will initially have 0 liquidity, as a result, a malicious actor may trigger a swap with 0 bAsset input amount and a priceLimit to set the price where they wish.
The pool price can then be assigned to below the floor tick, perturbing the launch of the system.
Recommendation
Consider implementing logic in the
_onSettlecallback to re-adjust the price back to the upper tick of the anchor range by swapping with 1 wei reserves in with a priceLimit at the desired price to assign the price to the bottom of the upper tick range of the Anchor. -
H-05 High Malicious Sellers Can Steal Auction Proceeds Gaming Resolved
Description
Uniswap V2
onCreatecallback requires that the pair does not exist, but theonSettlecallback will not revert if someone creates it before the auction settlement.Therefore, a malicious auction seller can create the pair just before the auction ends, adds liquidity in a proportion that results in a higher pool price, settle the auction and steal most of the quote tokens from the proceeds as a refund.
Recommendation
Consider creating the UniswapV2 pair during auction settlement.
Alternatively, make sure the AuctionHouse receives both the capacity and the tokens required for liquidity up front. Be advice that some sellers will be deterred as they may need these tokens in their protocol treasury.
-
H-06 High Anchor Width Param Will DoS Auction Settlement DoS Resolved
Description
Auction seller can set some initial params for the Baseline callback, like the
anchorTickWidth. TheonCreatefunction requires this value to be between 0 and 10.However, setting a high anchor width increases the
ANCHORcapacity, increasing thecapacityRatio, DoS'ing the auctions settlement.Recommendation
Instead of having a fixed anchor width, follow the same pattern as the
BaselineInitpolicy, passing the desiredfloorTickLand calculating theanchorTickLwith:int24 anchorTickL = max(activeTS - (ANCHOR_WIDTH * T_S), _floorTickL + T_S);. -
H-07 High Lot Creation DoS Through Uniswap Pair DoS Resolved
Description
Upon creating a lot which uses a DTL callback, the
onCreatecallback is invoked. For theUniswapV2DTLandUniswapV3DTLcallbacks, the__onCreatefunction validates that the pair for the baseToken and quoteToken combination does not already exist.However a malicious actor may observe the transaction to create a lot and frontrun this transaction to create a Uniswap V2 or V3 pair with the same baseToken and quoteToken. Notice that this action does not require owning either of the tokens in the pair.
As a result the
onCreatecallback will revert, causing the lot creation to revert.Recommendation
Remove the pair existence validation in the
__onCreatefunction in the both theUniswapV2DTLandUniswapV3DTLfiles as it is unnecessary and introduces a DoS vector. -
H-08 High Baseline Launches Can Not Be Done DoS Resolved
Description
When the BPOOL contract is deployed, token transfers are locked and must be unlocked via policy contracts. In the underlying Baseline protocol, the
BaselineInitpolicy unlocks transfers after launch.The
BaselineAxisLaunchcontract serves as theBaselineInitpolicy. However, it does not have permission to call thesetTransferLockfunction.An auction with BPOOL tokens can be created since this action only requires minting and does not require a base token transfer. However, other actions such as cancelling an auction, settling an auction, or using base tokens for swaps are not possible due to transfers being locked.
Recommendation
Include the
setTransferLock.selectorin therequestPermissionsfunction when configuring the policy, and unlock transfers after an auction is created. -
M-01 Medium
discoveryTickWidthConfigured Too Low Logical Error ResolvedDescription
Baseline sets
DISCOVERY_WIDTHto 350 inMarketMaking.sol, however_onCreate()only validates that it is set to at least one. Setting it to 350 will ensure that there is enough liquidity spread out through a range that will not cause the price of the base token to increase in an unprecedented manner. Having a larger discovery range will also mint morebAssets, making it harder to break through the discovery range without affecting the capacity ratio check.The protocol allows for anchor range widths between 1 and 10, as well as discovery range widths above 0. However, in the underlying Baseline protocol, anchor and discovery range widths are fixed values of 10 and 350, respectively.
When the
sweeporslidefunctions in theMarketMakingcontract are called, liquidity structure will be rebalanced based on these constant values from Baseline, regardless of the initial configuration.Additionally, reserves will be moved from the floor range to the anchor range during
sweepin this case, which is an unwanted situation in Baseline. This happens becausesweepfunction adds liquidity to anchor first, and then adds reserves to floor. However, the same amount of liquidity for a much wider anchor range will require more reserves, causing floor reserves to decrease.Also, it is crucial for the discovery range to be wide enough and filled with BPOOL tokens in order to provide sufficient liquidity for swaps and ensure healthy price movements. A narrow discovery range could result in a single swap moving the current price tick well above the upper discovery tick, where there is minimal liquidity.
Other differences compared to Baseline are
floorReservesPercentvalue being configurable (which affects liquidity thickness), and lack of gap between floor and anchor ranges. In baseline, floor has the thickest liquidity and anchor liquidity is much lower compared to floor.Recommendation
Set the discovery range to 350 tick spacings. Consider using the Baseline range widths instead of allowing them to be configured by the seller. Also make sure that floor range has much more reserves compared to anchor.
-
M-02 Medium Inconsistent Prices Between Pool and Auction Validation Resolved
Description
The seller of the
bAssetdetermines the open price for the Uniswap V3 Pool when creating theBPool. This is done by passing_initialActiveTickin the constructor. Fixed-Priced Auctions are intended to sell the asset at an opening price, but there is no validation that the Auction price matches the Uniswap V3 Pool price. Since no validation occurs, a malicious seller can perform two different dishonest actions:- Set the price of the
bAssetto a lower price than the Auction. This will cause any users who bought tokens in an auction to immediately incur an unrealized loss. Additionally, the seller can purchase tokens at a discount. - Set the price of the
bAssetto a higher price than the Auction. In this scenario, a seller can set themself as the curator, and sell the curator reward. This action can also push the Uniswap V3 Pool price back to the Fixed-Priced Auction price.
Recommendation
Verify that the price being initialized is the same price that is being used for Fixed-Price Auction.
- Set the price of the
-
M-03 Medium Incorrect Liquidity Structure Deployed Logical Error Resolved
Description
Baseline auction settlement will revert if the
capacityRatiois not between 100% and 102%. This makes sure that the total capacity on the system is greater than the spot supply ofbAssets.However, the 102% check is specific for 1% fee tier pools. If the Baseline auction is used for a lower fee tier, the liquidity structure deployed might be invalid, but the
onSettlecallback might not revert.This issue allows
MarketMaking.bump()to be executed just after the liquidity is deployed, granting arbitrageurs an opportunity to extract quote tokens from the positions.Recommendation
Consider calling
MarketMaking.bumpjust after the capacity ratio check, inside a try/catch, and revert if the bump succeeds. Refer to: https://github.com/0xBaseline/baseline-v2/blob/main/test/TestFoundation.sol#L276 -
M-04 Medium Auction Settlement DoS’d By Creator DoS Acknowledged
Description
In the
BaseDTLcallback contract theonSettlecallback assumes that the auction creator has the necessary balance of base tokens and has set the correct approval to the callback. However a malicious auction creator may neglect to approve the callback contract to transfer the base tokens, therefore DoSing the settlement of the auction and preventing users from claiming their bids.This results in user’s funds being held captive during the auction period until the auction can be aborted.
Recommendation
Consider requiring that the Axis core system or the callback contract is pre-funded with the base tokens which will be used to create the initial liquidity during settlement.
-
M-05 Medium Blacklisted Addresses Halt Auction Settlement DoS Acknowledged
Description
In the
onSettlecallback any remaining quote tokens in the contract which weren’t used up due to theproceedsUtilisationPercentor imbalance when providing liquidity are sent back to the auction seller. However since the seller never has to directly handle the quote tokens from the auction, it is possible that the seller is blacklisted for the quote token.Thus the
onSettlecallback will always revert when there are leftover quote tokens that would be transferred to the seller. A malicious owner of a blacklisted address could leverage this to create an auction that can never be settled using a Uniswap callback. This would lock the funds of bidders and effectively create an auction which becomes a honey pot.Recommendation
Consider leaving extra tokens in the callback contract and tracked in a mapping to be pulled by the seller address after settlement in a separate transaction.
Otherwise consider donating the additional quote tokens to a protocol address in the event that they cannot be transferred due to a blacklisted seller, thus allowing the onSettle callback to complete, similar to how GMX does this here: https://github.com/gmx-io/gmx-synthetics/blob/1938e365dc009342aa288aa6b42fc1fd3cd9e45d/contracts/token/TokenUtils.sol#L80
-
M-06 Medium Outdated Vesting Modules Used Logical Error Acknowledged
Description
In the
_onSettlefunction, if configured, a vest is created for the LP tokens created from the callback. The linearVestingModule is ensured to be the latest vesting module in the_onCreatecallback when thelotConfigurationis set, however by the time the lot is settled thelatestVersionorisSunsetvalues are not checked.Therefore it is possible that a lot is settled with a
linearVestingModulethat is not the latest version or is sunsetted.In the event that a vulnerability is identified in the
linearVestingModulethe protocol will not be able to wait for the current vests to end and be settled to update the module.Recommendation
Fetch the latest
linearVestingModulewith the_getLatestLinearVestingModulewhen settling the lot. -
L-01 Low
console.logPresent in Code Best Practices AcknowledgedDescription
It is inadvisable to deploy code to a live blockchain with
console.logs present. This will waste users’ gas, with no benefit added.Recommendation
Remove all occurrences of
console.log. -
L-02 Low
slideInoperable Due To Floor Config Validation ResolvedDescription
When verifying the
floorReservesPercent, the validation only checks if the value is less than or equal to 99%. This can allow a user to deploy a pool with 0% of tokens allocated to the floor. This means that even if allbAssetholders were to sell their tokens, the floor could never be reached. This will prevent the baseline market making featureslide()from being operable.Consider the following scenario:
FLOOR 200 - 400
ANCHOR 400-600
DISCOVERY 600 - 5000
ACTIVE TICK = 500
SLIDE TICK = 500 - 200 = 300
Since 300 resides in the floor,
slide()will not be callable.Recommendation
Require the
floorReservesPercentto be set to at least 50% -
L-03 Low Early Unvesting Is Possible Logical Error Resolved
Description
Auction sellers might need to vest their LP tokens after an auction has settled. Start time and expiry time of a vesting are provided by the seller.
The protocol allows vesting start time to be before
block.timestampto prevent a DoS by delaying the settlements. However, this allows sellers to unvest most of their LP tokens immediately after auction.Normal scenario (start is current timestamp):
- start:
block.timestamp - expiry:
block.timestamp+ 1 year - LP amount: 100
In this 1 year vesting scenario, seller can unvest 25 tokens after 3 months.
Alternative scenario (seller sets vesting start 9 years ago):
- start:
block.timestamp- 9 years - expiry:
block.timestamp+ 1 year - LP amount: 100
Here, seller can unvest 90 tokens right after settlement without waiting any time.
Recommendation
One option might be storing the total vesting period, and updating expiry based on this period after minting derivative tokens during settlement.
Another option to consider is determining a maximum time that can be before
block.timestamp. It would still allow malicious seller to perform this but can decrease the impact. - start:
-
L-04 Low Unused active Flag Validation Resolved
Description
In the
_onCancelcallback implementation the active flag is set to false for thelotConfiguration, however the active flag is not used to validate whether a lot is active anywhere.Recommendation
Although there are mechanisms in place to prevent the
onSettleandonCuratefunctions being called for a cancelled lot, consider implementing additional safeguards on the BaseDTL callback side to prevent these callbacks from being called for cancelled lots. -
L-05 Low Discovery Range Loose Validations Validation Acknowledged
Description
In the onCreate callback the
discoveryRangeUpperis validated to be within theMAX_TICK, however if thediscoveryRangeUpperis assigned such that it is even close to theMAX_TICKthis can lead to a DoS of the Baseline liquidity operations down the road.For example:
TickSpacing: 20
Discovery ticks: [MaxTick - 200, MaxTick]
A sweep cannot be triggered in this case as it would cause the discovery upper tick to exceed the max tick.
Although it is unlikely that a configuration is made where the
discoveryUpperTickis close to theMAX_TICK, such a configuration should not be allowed.Recommendation
Consider restricting the validation on the
discoveryMaxTickfurther to an expected range. -
L-06 Low Unused Error Best Practices Resolved
Description
Callback_Params_PoolTickMismatcherror is defined but never used.Recommendation
Remove unused errors.
-
L-07 Low High floorReservesPercent Causes DoS Validation Resolved
Description
In the onCreate callback the
floorReservesPercentis validated to be no more than 99%, however this loose validation allows users to create a liquidity structure where the majority of the liquidity is allocated to the Floor position.As a result a malicious actor is able to buy through all of the Anchor and Discovery range liquidity as it can be very thin. The malicious actor can then set an LP outside of the discovery range in order to assign the price outside of the liquidity structure.
Once the active price is allowed to exceed the Discovery range liquidity operations will be DoS’d as a sweep cannot occur.
Recommendation
Consider making the floorReservesPercent more strict such that it is unlikely that a liquidity structure can be deployed where a malicious actor can easily buy through all of the available liquidity to DoS the system.
-
L-08 Low Arbitrary Byte Length Risk Warning Resolved
Description
params.implParamsbytes are saved into storage within_onCreate, and operations may appear fine from the perspective of the user. During settlement callback whenmintAndDepositis executed, theimplParamsare loaded into memory:(uint24 poolFee) = abi.decode(lotConfiguration[lotId].implParams, (uint24));The first 24 bits can be decoded properly into a
uint24, but there is no guarantee that the bytes do not have arbitrary padding afterwards that inflate the payload. Consequently, there will be extremely large gas costs associated with the load into memory upon settlement. It's important to note that there isn't a large risk since the callbacks do not have a predetermined max gas limit, but noteworthy for future-proofing operations.Recommendation
Consider documenting this or placing a cap on the length of the bytes.
-
L-09 Low Esoteric Token Pairs Are Not Supported Warning Acknowledged
Description
The
getSqrtPriceX96function used for theUniswapV3DTLcallback computes theratioX192and stores it as auint256before taking the square root to compute thesqrtPriceX96Temp.As a result with some esoteric token pairs which have a large difference in amounts, the intermediate
ratioX192value can overflow theuint256size.For example
uint160 price = SqrtPriceMath.getSqrtPriceX96(address(_baseToken), _BASELINE_QUOTE_TOKEN, 1e6, 1e26);causes such an overflow.Such a combination of tokens may arise when one token has low precision, such as USDC and another one has high precision such as YAMv2 or a very low price.
Recommendation
Be wary of this when supporting tokens and token prices in auctions. It is unlikely that supported token pairs would cause this issue. However it may be worth adding validations to disallow auctions which would cause this logic to revert based on token decimals and prices.
-
L-10 Low Launches Restrict Liquidity Structure Validation Resolved
Description
In the _onCreate callback the validation correctly requires that the anchor range cannot exceed a width of 10 tick spacings, however the floor range upper tick is always assigned to the lower tick of the anchor range. Therefore there can be no liquidity structures with a gap in between the upper floor tick and the lower anchor tick as will commonly be the case where there is a significant premium to the baseline value.
As a result the initial liquidity structure configuration is limited in that the active price (upper tick range of the anchor position) cannot be more than 10 ticks above the floor position.
Recommendation
Consider allowing a separate configuration variable for the upper floor tick, where the liquidity structure can have a gap between the floor and the lower anchor range.
Be sure to maintain the existing Anchor width validation and add relevant validation such that the anchor cannot collide with the floor and the anchor and floor are within a reasonable distance from each other. Additionally, if the Anchor range is within 10 tick spacings of the floor range there should be no gap between the two positions.
-
L-11 Low Misleading Comment Best Practices Resolved
Description
"Send the LP tokens to the seller" comment in L359 of the
BaseDTLcontract is misleading since LP tokens are transferred to therecipientnot to the seller.Recommendation
Consider updating the comment.
-
L-12 Low Seller May Receive All Proceeds Logical Error Resolved
Description
Both Uniswap and Baseline auction callbacks allow the owner to set a percentage of the proceeds when adding liquidity during auction settlement.
The issue relies on the validation for this percentage. Baseline auction requires this value to be within 1% and 100%, while Uniswap requires 0% to 100%.
This allows auction sellers to set a very small value, and receive most of the proceeds which were meant to be added as liquidity.
Recommendation
Consider increasing the lower limit for the proceeds used for liquidity providing.
Remediation Review
7 findings · August 15 to 17, 2024-
H-02 High Capacity Validation Doesn’t Account For Fees Logical Error Acknowledged
Description
In the onCreate callback in the
BaselineAxisLaunchthecapacity_value passed by the auction house is the total capacity of the auction:However in the onSettle callback the
proceeds_value is based on the total sold less the fees taken by the protocol and referrer.Therefore the
_onCreatefunction will overestimate the amount of circulating supply which can be supported by the resulting liquidity structure upon settlement. This is because the_onCreatefunction assumes that the entireauctionPrice * capacity_will be theexpectedProceeds, when in reality this amount less the fees will be split by thepoolPercentand deployed into the liquidity structure.Recommendation
Compute the total fees which would be taken if the entire capacity of the auction were to sell out and deduct this amount from the
expectedProceeds. Additionally, ensure this fee amount cannot change in the time between auction creation and settlement. -
M-01 Medium Baseline Launch Create DoS DoS Acknowledged
Description
In the onCreate callback for the
BaselineAxisLaunchthere are several checks against the active tick.The first of which compares the result of
BPOOL.getActiveTSto the assigned Anchor upper tick on line 404.The second compares the auctionTick to the
activeTickto ensure that theactiveTickis greater than or equal to theauctionTickso that auction bidders are not disincentivized.Both of these validations can be manipulated to fail in the same way described in H-X from the main review. This would lead to a DoS of the creation transaction.
The risk of frontrunning to cause this DoS is limited as the Baseline launches are planned for Blast, however this issue highlights that these validations are likely not the best that could be performed in the
onCreatefunction, since the actual baselineactiveTicklaunch price is simply re-assigned in the settle callback based on the upper anchor tick.Recommendation
Instead of the current validation in
onCreate, we propose the following changes to the validations and Baseline launch tick:- Validate that
upperAnchorTick - 1 TS <= auctionTick < upperAnchorTickin theonCreatecallback
This way there is no reliance on the activeTick of the pool and we know that the upperAnchorTick (which is more permanent than whatever the current active tick is at time of creation is) correctly encapsulates the auction price.
- Set the
targetSqrtPriceto the auction price in thesettlecallback
Using the upper price of the anchor position creates a weird behavior where the result of
BPOOL.getActiveTSis no longer theupperAnchorTickright on launch, this is because the getActiveTS function rounds up to the next full tick when on an even tick spacing.Additionally now the price can be exactly that of the auction.
- Validate that
-
L-01 Low Uniswap V2 Auctions Can Be DoS’d With Many Quote Tokens Warning Acknowledged
Description
In the
_mitigateDonationfunction base tokens are sent to the Uniswap V2 pool and additional quote tokens are removed to assign the price as desired.However in some rare circumstances a malicious actor may still DoS Uniswap V2 pools by donating a large amount of quote tokens to the pair.
For example:
- Consider a base token with 6 decimals and a quote token with 18 decimals
- Price is such that 1 base token == 1 quote token
- The attacker initially donates 1e24 quote tokens to the uniswap pair
- The auction settles and the _migrateDonation logic sends a single wei of base tokens to the pair before syncing
- Then roughly 1e6 base tokens are transferred in and (1e24-1e18) quote tokens are requested out
- The Uniswap K value based on reserves is 1e24 * 1 = 1e24
- The Uniswap K value after the swap at the desired reserves is 1e18 * 1e6 = 1e24
- The swap would take 30 basis points fees and so the Uniswap K value validation would revert
This is unlikely as typically a base token within Axis will have 18 decimals and it will often be very costly to donate this amount of quote tokens.
Recommendation
This finding serves merely as a warning to be aware of this case.
-
L-02 Low Lacking safeTransfer Usage Best Practices Acknowledged
Description
When transferring the
quoteTokensToTransferto the Uniswap V2 pool, transfer is used, however the quote token may be a token which returns false upon transfer failure. Though it is unlikely that this transfer fails, consider using safeTransfer to ensure that the transfer reverts instead of silently failing.Recommendation
safeTransfershould be used instead oftransfer. -
L-03 Low Unnecessary totalCollatSupply Optimization Acknowledged
Description
The
totalCollatSupplyis deducted from thetotalSpotSupplyand then added back to thetotalSpotSupplywhen computing the capacityRatio. ThetotalSpotSupplywith the deductedtotalCollatSupplyis not used anywhere else.Recommendation
Remove the unnecessary
totalCollatSupplydeduction and remove the subsequent addition on line 831. -
L-04 Low Missing auctionComplete Check Validation Acknowledged
Description
In the
_onCuratefunction there is no validation that theauctionCompleteboolean is false as there is in the other callbacks.Recommendation
Consider implementing an
auctionCompletevalidation in the_onCuratefunction. -
L-05 Low Loop Vault Capacity Is Not Included Warning Acknowledged
Description
At the end of the
onSettlecallback validation is performed to ensure the solvency of the launched system, however this solvency check does not include the capacity from the loop vault.This may be fine as it is unclear whether the loop vault will be a part of the Axis launches, and even if it is, would be unlikely to have any debt at the time of auction settlement.
Recommendation
Confirm whether or not the new Baseline loop vault would be included in the Axis launches, and if so, consider adding the
LOOPS.totalDebt()value when calculating thedebtCapacity.
No findings match.
Put your code through the same review.
This review started with a conversation about scope. Tell us what you are building and we will plan yours with you.
