LiquidityManager (LiquidityManager.sol)
This is a decentralised Uniswap v3 position manager; for liquidity of the Mementos token.
The key feature of this contract is:
- Automated protocol managed token liquidity
flowchart TD
T["fas:fa-coins Mementos (MOTE)"<br>ERC-20 Tokens<br>0% Transfer Fees 0,0]
MP(* Mining Pool<br>61.8034% MOTE Supply)
LP(* Liquidity Pools)
LP2(* Liquidity v2 Pool<br>LP Tokens Burned)
LP3Weth(* Liquidity Pool<br>Locked in Protocol)
LP3Reth(* Liquidity Pool<br>Locked in Protocol)
T --> |61.8034% MOTE Supply| MP
T --> |38.1966% MOTE Supply| LP
LP --> |Only at init<br>0.5 ETH| LP2
LP --> LP3Weth
LP --> LP3Reth
MP -->|post-mine<br>unmined MOTE supply| B
LP2 --> |LP Tokens| B
LP3Weth --> |post mine<br>+3 day| F
LP3Reth --> |post mine<br>+3 day| F
F --> |Collected ETH| LP
F --> |Collected MOTE| B
F{Collect Position Fees<br>or Adjust Floor Position}
B[Burn -> 0xdEaD]
Non-standard EOA callable non-view functions on this contract
allocateToResilience() returns (bool)- Checks has been 3 days since last call, or trade start
- Sets next call time to be 3 days from now
- Calls
_injectLiquidityfor MOTE/WETH pool - Calls
_injectLiquidityfor MOTE/RETH pool
streamlineReserves() returns (bool)- Checks has been 3 days since last call, or trade start
- Sets next call time to be 3 days from now
- Find if any position can be removed by calling
prospectNadir() - Calls
_consolidateLiquidityfor the selected pool - If was the last position in the start set, also calls
_removeBandon the floor position for that pool
Notable public view only functions on this contract
-
prospectNadir() returns (address)Finds the liquidity pool with the most distant lower liquidity band and sees if it can be removed while maintaining the protocol's liquidity coverage for 25% of the token supply.
- Gets the MOTE/RETH price reverting if beyond an acceptable distance of the TWAP
- Gets the MOTE/WETH price reverting if beyond an acceptable distance of the TWAP
- Check how many tokens the MOTE/WETH pool can absorb
- Check how many tokens the MOTE/RETH pool can absorb
- Simulate a sale of remaining tokens from the 25% of outstanding supply to v2 pool and get a price.
- If v2 after price is higher than MOTE/WETH pool's lowest band it can be removed
- If both prices are higher than MOTE/RETH pool's lowest band it can be removed instead
Ecosystem only callable methods on this contract
-
initializePools() payable onlyHBHContractCalled by the
HalfBakedHeroesfunctionconstructor(); initializes the 3 liquidity pools.- Creates Uniswap v2 pair (MOTE/WETH)
- Creates Uniswap v3 pair (MOTE/WETH)
- Initializes v3 pair pool (MOTE/WETH)
- Gets current RETH/WETH price
- Creates Uniswap v3 pair (MOTE/RETH)
- Recalibrates WETH pool ticks for RETH price
- Initializes v3 pair pool (MOTE/RETH)
-
activateTradeWinds() payable onlyHBHContractThis function enables trading on the Mementos token by adding all the initial liquidity to the pools.
- Converts the sent ETH to WETH
- Calls
_setUpLiquidityto set up the liquidity positions - Sets
nextConsolidationandnextInjectionto be 3 days in the future - Renounces ownership of this contract
-
addToLiquidity(address) payable onlyHBHContract returns (uint256)- Checks is coming from HBH Contract
- Calls
_selectPool()to choose v2 or v3 pool, exiting if neither - Use 20% of ETH to covert to RETH if more favorable MOTE pool
- Use the ETH or RETH to buy MOTE to replenish the rewards pool
- Convert any remaining ETH to WETH
-
replenishRewards(address) payable onlyHBHContract returns (uint256)- Checks is coming from HBH Contract
- Calls
_selectPool()to choose v2 or v3 pool, exiting if neither - Works out if the V2 or V3 WETH/MOTE price will get more tokens
- Works out if the RETH pool will give more tokens than the selected WETH pool
- If RETH, swaps ETH to RETH
- Calls
LiquidityreplenishRewardsspecifying whether to use WETH or RETH and to return the MOTE to thesenderparameter returning the amount of Mementos
-
harvestAndRecycleFees() payable- Checks is
Mementostoken calling from_afterTokenTransfer - Iterates a single band collecting any liquidity fees if available; switching between each pool for each invocation
- Any fees in RETH are kept in the
LiquidityManager(e.g. no action) - Any fees in WETH are sent to the
CertificateOfAuthenticityfor distribution - Any fees in Mementos token are burnt
- Any fees in RETH are kept in the
- Checks is
Notable private or internal functions on this contract
-
_selectPool()- Works out if the V2 or V3 WETH/MOTE price will get more tokens
- Returns the price and version of pool
-
_setUpLiquidity(uint256) private- Adds liquidity to the Uniswap v2 position (0.5 WETH); burning the LP tokens.
- Calls
_setUpUniswapV3(uint256)passing the count of remaining WETH
-
_setUpUniswapV3(uint256) private- Splits the WETH by Golden ratio (1.618) with larger fraction (61.8%) being allocated to RETH pool.
- Converts the initial WETH for RETH into RETH
- Sets up the Uniswap v3 position bands by calling
_setUpPositionsfor each v3 pool and stores the returned floor position - Burns any unallocated Memento tokens
-
_setUpPositionsCalled twice. Once for MOTE/WETH and once for MOTE/RETH pool; minting
- Queries v3 pool for the initial price
- Mints 32 Uniswap v3 liquidity positions (64 including both pools)
- at precalculated ticks
_wethTicksor_rethTicks, approximately Fibonacci tick positions (1.618), with 0.382 retracement widths - linear distribution of tokens per band, except in the initial 8 where it is reduced so someone cannot scoop up a large amount of supply with a very small buy
- inserts them in the position array backwards; in order of high price to low price; so when removing positions (starting at lows) the length of the array can be reduced by one rather than shuffling up.
- at precalculated ticks
- Add a full range (start price to infinity) band at index 0 so it isn't considered for removal and there is liquidity between the main 32 positions.
- Add a support floor band below price that just contains the WETH and no tokens; for mined token liquidity.
32 (regular) + 1 (full range) + 1 (floor) = 34 liquidity positions are minted per invocation. This makes 68 uniswap positions across the two pools.
-
_consolidateLiquidity(uint256[POSITIONS],uint256) private- get the liquidity amount in the position
- call
_removeBand(uint256,uint128)with the liquidity to remove and Uniswap's positionId - burn any Memento's token received in liquidity fees
-
_removeBand(uint256,uint128) private- Decrease the liquidity in the position to 0
- Collect any fees or tokens from the position
- Burn the Uniswap v3 position
-
_getIndexForPrice(uint160,int24[TICKS]) private view returns (uint256)- Given the current price, searches the tick array to find the nearest position index to price (either price in, or next above).
-
_injectLiquidity(IUniswapV3Pool,address,int24[TICKS],uint256[POSITIONS],uint256) private returns (bool)- If price is far away from TWAP, early exit
- Find the liquidity position index below price
- If not enough pair token to inject early exit
- Find how much pair liquidity in position band above
- Cap the amount of liquidity injected at 1% of balance or the pair liquidity in higher band, whichever is smaller
- Split the liquidity into 3 bands below price: Near, Far, Support
- 20% goes to the Support band
- If bearish price action (price below TWAP); 60% to Far band, 20% to Near band
- If bullish price action (price above TWAP); 40% to Far band, 40% to Near band
- Call
_increaseLiquidityon each of the positions with the designated amount - Emits
DeployingMoreCapitalSteadyLads(address,uint256,uint256,uint256)