Skip to content

Commit

Permalink
[Plugin] add DynamicFeeModule
Browse files Browse the repository at this point in the history
  • Loading branch information
fourlen committed May 6, 2024
1 parent 1cb8583 commit f898413
Showing 1 changed file with 107 additions and 0 deletions.
107 changes: 107 additions & 0 deletions src/plugin/contracts/modules/DynamicFeeModule.sol
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);
}
}
}

0 comments on commit f898413

Please sign in to comment.