-
Notifications
You must be signed in to change notification settings - Fork 20
/
TalosStrategyVanilla.sol
171 lines (143 loc) · 7.37 KB
/
TalosStrategyVanilla.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// SPDX-License-Identifier: MIT
// Logic inspired by Popsicle Finance Contracts (PopsicleV3Optimizer/contracts/popsicle-v3-optimizer/PopsicleV3Optimizer.sol)
pragma solidity >=0.8.0;
import {Ownable} from "solady/auth/Ownable.sol";
import {FixedPointMathLib} from "solady/utils/FixedPointMathLib.sol";
import {ERC20} from "solmate/tokens/ERC20.sol";
import {IUniswapV3Pool} from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol";
import {INonfungiblePositionManager} from "@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol";
import {ITalosOptimizer} from "./interfaces/ITalosOptimizer.sol";
import {PoolVariables} from "./libraries/PoolVariables.sol";
import {TalosStrategySimple, TalosBaseStrategy} from "./strategies/TalosStrategySimple.sol";
/// @title Deploy Vanilla
/// @notice This library deploys talos vanilla strategies
library DeployVanilla {
function createTalosV3Vanilla(
IUniswapV3Pool pool,
ITalosOptimizer optimizer,
INonfungiblePositionManager nonfungiblePositionManager,
address strategyManager,
address owner
) public returns (TalosBaseStrategy) {
return new TalosStrategyVanilla(
pool,
optimizer,
nonfungiblePositionManager,
strategyManager,
owner
);
}
}
/// @notice Tokenized Vault implementation for Uniswap V3 Non Fungible Positions.
/// @author Maia DAO (https://github.com/Maia-DAO)
contract TalosStrategyVanilla is TalosStrategySimple {
using FixedPointMathLib for uint256;
using FixedPointMathLib for uint128;
using PoolVariables for IUniswapV3Pool;
/// @notice The protocol's fee in hundredths of a bip, i.e. 1e-6
uint24 private constant protocolFee = 2 * 1e5; //20%
uint24 private constant GLOBAL_DIVISIONER = 1e6;
/**
* @notice Constructs a new TalosStrategyVanilla contract.
* @param _pool The Uniswap V3 pool to manage.
* @param _optimizer The optimizer contract to use.
* @param _nonfungiblePositionManager The Uniswap V3 Non Fungible Position Manager contract.
* @param _strategyManager The strategy manager contract.
* @param _owner The owner of the contract.
*/
constructor(
IUniswapV3Pool _pool,
ITalosOptimizer _optimizer,
INonfungiblePositionManager _nonfungiblePositionManager,
address _strategyManager,
address _owner
) TalosStrategySimple(_pool, _optimizer, _nonfungiblePositionManager, _strategyManager, _owner) {}
/*//////////////////////////////////////////////////////////////
INTERNAL HOOKS LOGIC
//////////////////////////////////////////////////////////////*/
/// @notice Performs the necessary actions before a withdraw can take place
/// @param _tokenId position id that the user is trying to withdraw from
function beforeRedeem(uint256 _tokenId, address) internal override {
_earnFees(_tokenId);
_compoundFees(_tokenId);
}
/// @notice Performs the necessary actions after a withdraw takes place
/// @param _tokenId position id that the user is trying to withdraw from
function afterRedeem(uint256 _tokenId) internal override {}
/// @notice Performs the necessary actions before a deposit can take place
/// @param _tokenId position id that the user wants to deposit in
function beforeDeposit(uint256 _tokenId, address) internal override {
_earnFees(_tokenId);
_compoundFees(_tokenId);
}
/// @notice Performs the necessary actions after a deposit takes place
/// @param _tokenId position id that the user wants to deposit in
function afterDeposit(uint256 _tokenId) internal override {}
/// @notice Performs the necessary actions before a re-range can take place
/// @param _tokenId position id that the user wants to re-range
function beforeRerange(uint256 _tokenId) internal override {
_earnFees(_tokenId);
}
/// @notice Performs the necessary actions after a re-range takes place
/// @param _tokenId position id that the user wants to deposit in
function afterRerange(uint256 _tokenId) internal override {}
/// @notice Collects fees from the pool to the protocol.
/// @param _tokenId position id that the user wants to collect fees from
function _earnFees(uint256 _tokenId) internal {
if (liquidity == 0) return; // no fees to collect when liquidity is zero
(uint256 collect0, uint256 collect1) = nonfungiblePositionManager.collect(
INonfungiblePositionManager.CollectParams({
tokenId: _tokenId,
recipient: address(this),
amount0Max: type(uint128).max,
amount1Max: type(uint128).max
})
);
uint24 _protocolFee = protocolFee;
uint24 _GLOBAL_DIVISIONER = GLOBAL_DIVISIONER;
// Calculate protocol's fees
uint256 earnedProtocolFees0 = (collect0 * _protocolFee) / _GLOBAL_DIVISIONER;
uint256 earnedProtocolFees1 = (collect1 * _protocolFee) / _GLOBAL_DIVISIONER;
protocolFees0 += earnedProtocolFees0;
protocolFees1 += earnedProtocolFees1;
emit CollectFees(earnedProtocolFees0, earnedProtocolFees1, collect0, collect1);
}
/// @notice Compounds fees from the pool from a user prespective
/// @param _tokenId position id that the user wants to compound fees from
function _compoundFees(uint256 _tokenId) internal returns (uint256 amount0, uint256 amount1) {
uint256 balance0 = token0.balanceOf(address(this)) - protocolFees0;
uint256 balance1 = token1.balanceOf(address(this)) - protocolFees1;
emit Snapshot(balance0, balance1);
//Get Liquidity for Optimizer's balances
uint128 _liquidity = pool.liquidityForAmounts(balance0, balance1, tickLower, tickUpper);
// Add liquidity to the pool
if (_liquidity > 0) {
uint128 liquidityDifference;
(liquidityDifference, amount0, amount1) = nonfungiblePositionManager.increaseLiquidity(
INonfungiblePositionManager.IncreaseLiquidityParams({
tokenId: _tokenId,
amount0Desired: balance0,
amount1Desired: balance1,
amount0Min: 0,
amount1Min: 0,
deadline: block.timestamp
})
);
liquidity += liquidityDifference;
emit CompoundFees(amount0, amount1);
}
}
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
/// @notice Emitted when fees was collected from the pool
/// @param feesFromPool0 Total amount of fees collected in terms of token 0
/// @param feesFromPool1 Total amount of fees collected in terms of token 1
/// @param usersFees0 Total amount of fees collected by users in terms of token 0
/// @param usersFees1 Total amount of fees collected by users in terms of token 1
event CollectFees(uint256 feesFromPool0, uint256 feesFromPool1, uint256 usersFees0, uint256 usersFees1);
/// @notice Emitted when fees was compuonded to the pool
/// @param amount0 Total amount of fees compounded in terms of token 0
/// @param amount1 Total amount of fees compounded in terms of token 1
event CompoundFees(uint256 amount0, uint256 amount1);
}