-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
107 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity =0.8.20; | ||
|
||
import '@cryptoalgebra/integral-core/contracts/interfaces/pool/IAlgebraPoolState.sol'; | ||
import '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraFactory.sol'; | ||
import '@cryptoalgebra/integral-core/contracts/base/common/Timestamp.sol'; | ||
import '@cryptoalgebra/integral-core/contracts/libraries/Plugins.sol'; | ||
import '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraPool.sol'; | ||
import '@cryptoalgebra/algebra-modular-hub/contracts/base/AlgebraModule.sol'; | ||
import '@cryptoalgebra/algebra-modular-hub/contracts/interfaces/IAlgebraModularHub.sol'; | ||
import '@cryptoalgebra/algebra-modular-hub/contracts/types/HookParams.sol'; | ||
|
||
import '../types/AlgebraFeeConfigurationU144.sol'; | ||
import '../interfaces/plugins/IDynamicFeeManager.sol'; | ||
import '../interfaces/plugins/IVolatilityOracle.sol'; | ||
import '../libraries/AdaptiveFee.sol'; | ||
import '../libraries/VolatilityOracle.sol'; | ||
|
||
contract DynamicFeeModule is AlgebraModule, IDynamicFeeManager, Timestamp { | ||
using Plugins for uint8; | ||
using AlgebraFeeConfigurationU144Lib for AlgebraFeeConfiguration; | ||
|
||
uint256 internal constant UINT16_MODULO = 65536; | ||
using VolatilityOracle for VolatilityOracle.Timepoint[UINT16_MODULO]; | ||
|
||
|
||
/// @dev The role can be granted in AlgebraFactory | ||
bytes32 public constant ALGEBRA_BASE_PLUGIN_MANAGER = keccak256('ALGEBRA_BASE_PLUGIN_MANAGER'); | ||
|
||
address private immutable factory; | ||
address private immutable pluginFactory; | ||
|
||
/// @dev AlgebraFeeConfiguration struct packed in uint144 | ||
AlgebraFeeConfigurationU144 private _feeConfig; | ||
|
||
address public immutable oracleModule; | ||
address public immutable modularHub; | ||
|
||
constructor(address _factory, address _pluginFactory, address _oracleModule, address _modularHub) { | ||
(factory, pluginFactory, oracleModule, modularHub) = (_factory, _pluginFactory, _oracleModule, _modularHub); | ||
} | ||
|
||
function changeFeeConfiguration(AlgebraFeeConfiguration calldata _config) external override { | ||
require(msg.sender == pluginFactory || IAlgebraFactory(factory).hasRoleOrOwner(ALGEBRA_BASE_PLUGIN_MANAGER, msg.sender)); | ||
AdaptiveFee.validateFeeConfiguration(_config); | ||
|
||
_feeConfig = _config.pack(); // pack struct to uint144 and write in storage | ||
emit IDynamicFeeManager.FeeConfiguration(_config); | ||
} | ||
|
||
/// @inheritdoc IAlgebraDynamicFeePlugin | ||
function getCurrentFee() external view override returns (uint16 fee) { | ||
uint88 volatilityAverage = IVolatilityOracle(oracleModule).getCurrentAverageVolatility(); | ||
return AdaptiveFee.getFee(volatilityAverage, _feeConfig); | ||
} | ||
|
||
function _getFeeAtLastTimepoint( | ||
uint16 lastTimepointIndex, | ||
uint16 oldestTimepointIndex, | ||
int24 currentTick, | ||
AlgebraFeeConfigurationU144 feeConfig_ | ||
) internal view returns (uint16 fee) { | ||
if (feeConfig_.alpha1() | feeConfig_.alpha2() == 0) return feeConfig_.baseFee(); | ||
|
||
uint88 volatilityAverage = IVolatilityOracle(oracleModule).getAverageVolatilityAtLastTimepoint(_blockTimestamp(), currentTick, lastTimepointIndex, oldestTimepointIndex); | ||
return AdaptiveFee.getFee(volatilityAverage, feeConfig_); | ||
} | ||
|
||
function feeConfig() | ||
external | ||
view | ||
override | ||
returns (uint16 alpha1, uint16 alpha2, uint32 beta1, uint32 beta2, uint16 gamma1, uint16 gamma2, uint16 baseFee) | ||
{ | ||
(alpha1, alpha2) = (_feeConfig.alpha1(), _feeConfig.alpha2()); | ||
(beta1, beta2) = (_feeConfig.beta1(), _feeConfig.beta2()); | ||
(gamma1, gamma2) = (_feeConfig.gamma1(), _feeConfig.gamma2()); | ||
baseFee = _feeConfig.baseFee(); | ||
} | ||
|
||
function _getPoolState(address pool) internal view returns (uint160 price, int24 tick, uint16 fee, uint8 pluginConfig) { | ||
(price, tick, fee, pluginConfig, , ) = IAlgebraPoolState(pool).globalState(); | ||
} | ||
|
||
function _afterInitialize( | ||
bytes memory params, | ||
uint16 /* poolFeeCache */ | ||
) internal virtual override { | ||
AfterInitializeParams memory decodedParams = abi.decode(params, (AfterInitializeParams)); | ||
IAlgebraPool(decodedParams.pool).setFee(_feeConfig.baseFee()); | ||
} | ||
|
||
function updateFee( | ||
address pool, | ||
uint16 fee, | ||
uint16 lastTimepointIndex, | ||
uint16 oldestTimepointIndex, | ||
int24 currentTick | ||
) external override { | ||
require(msg.sender == oracleModule, 'Only oracle'); | ||
|
||
uint16 newFee = _getFeeAtLastTimepoint(lastTimepointIndex, oldestTimepointIndex, currentTick, _feeConfig); | ||
if (newFee != fee) { | ||
IAlgebraPool(pool).setFee(newFee); | ||
} | ||
} | ||
} |