Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
bc0e535
temp
fourlen Mar 25, 2025
8b489c1
+reblaanceManager
fourlen Mar 25, 2025
79c02d4
sorry
fourlen Mar 25, 2025
0851a13
Merge remote-tracking branch 'origin/integral-v1.2.1' into alm-plugin
debych Mar 26, 2025
c2643ae
[Plugin] add authorize in initializeALM
debych Mar 26, 2025
9af2a9b
[Plugin] add setters
debych Mar 26, 2025
2f87ae1
[Plugin] add alm-vault package in npm
debych Mar 26, 2025
d4c4502
[Plugin] create BaseRebalanceManager.sol
debych Mar 26, 2025
4d5e7ea
[Plugin] add ALM tests
debych Mar 26, 2025
1ca0116
bug fix
fourlen Mar 26, 2025
360959f
fix alm plugin factory
IliaAzhel Mar 26, 2025
30ca550
+fixtures
fourlen Mar 26, 2025
1b56985
add base testnet to hardhat config & deploy script fixes
IliaAzhel Mar 26, 2025
0314abc
first alm test
fourlen Mar 27, 2025
b4f2429
change comment
fourlen Mar 27, 2025
8243c09
fix unreachable code
fourlen Mar 27, 2025
2b6f8f0
-logs
fourlen Mar 27, 2025
c23f14e
-failed obtain twap
fourlen Mar 27, 2025
171ff0b
top fix
fourlen Mar 28, 2025
db2beac
top2 fix
fourlen Mar 28, 2025
17d8de0
[Plugin] swapAmount -> 0
debych Mar 28, 2025
94ac0f3
issue fixes
fourlen Mar 31, 2025
231a232
if -> require
fourlen Mar 31, 2025
021873b
add alm custom pool deployer
IliaAzhel Apr 1, 2025
5ff8b1e
add custom plugin deployer test
IliaAzhel Apr 1, 2025
b21a794
remove farming from alm custom pool deployer
IliaAzhel Apr 1, 2025
ff4bcef
-comments
fourlen Apr 2, 2025
021efe2
-more comments
fourlen Apr 2, 2025
1ae46a7
token1Decimals -> pairedTokenDecimals
fourlen Apr 2, 2025
2824012
-logs
fourlen Apr 2, 2025
b63cf0b
+test
fourlen Apr 3, 2025
88bf37d
only plugin
fourlen Apr 3, 2025
7cb21a2
Merge branch 'alm-plugin-custom' into alm-plugin
IliaAzhel Apr 4, 2025
6d5be5f
add base chain to hh config
IliaAzhel Apr 4, 2025
55014ef
Add deploy script
debych Apr 4, 2025
4d691fb
add factory address to the constructor
debych Apr 4, 2025
4024746
fix state, add some tests
fourlen Apr 10, 2025
9970bab
-comments
fourlen Apr 10, 2025
82c0778
-failedToObtainTWAPs, +tests
fourlen Apr 11, 2025
72ab616
some fixes, +tests
fourlen Apr 21, 2025
d07f460
fix tests
fourlen Apr 22, 2025
7de653b
+tests
fourlen Apr 30, 2025
4e2fe00
??
fourlen May 27, 2025
b95d2c4
+tests
fourlen May 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion deploys.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{}
{"poolDeployer":"0x32e3F485696b2C6dBBc5C83A5Cb803Af72e1ecF3","factory":"0x5E4F01767A1068C5570c29fDF9bf743b0Aa637d7","vault":"0xCEeAfFE7E3DfEB7656B1E7E9c3516455A7Bb7aF9","vaultFactory":"0xe1909bcA4E528f7361b63F82330269d3001011e1","BasePluginV1Factory":"0x5dee969A86c9F99642Bdc14bdffFB6173228501c","wrapped":"0x4200000000000000000000000000000000000006","entryPoint":"0x8aD26dc9f724c9A7319E0E25b907d15626D9a056","tickLens":"0x3aA96eDb755C44F3E50C5408a36abb52f28326Ba","quoter":"0xc58874216AFe47779ADED27B8AAd77E8Bd6eBEBb","quoterV2":"0x4e73E421480a7E0C24fB3c11019254edE194f736","swapRouter":"0x4b2A38344b9aAc2F4e82130f35F1630C80ED94Bb","proxy":"0x348b694d0b6E43D6C7D9d6E2E1E2e9C739De5a74","nonfungiblePositionManager":"0x9ea4459c8DefBF561495d95414b9CF1E2242a3E2","eternal":"0xf3b57fE4d5D0927C3A5e549CB6aF1866687e2D62","fc":"0x211BD8917d433B7cC1F4497AbA906554Ab6ee479"}
19 changes: 16 additions & 3 deletions hardhat.base.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,14 @@ export default {
chainId: 41,
accounts: [`0x${MNEMONIC || '1000000000000000000000000000000000000000000000000000000000000000'}`],
},
beraTestnet: {
url: `https://artio.rpc.berachain.com/`,
chainId: 80085,
baseTestnet: {
url: `https://base-sepolia-rpc.publicnode.com`,
chainId: 84532,
accounts: [`0x${MNEMONIC || '1000000000000000000000000000000000000000000000000000000000000000'}`],
},
base: {
url: `https://base-mainnet.public.blastapi.io`,
chainId: 8453,
accounts: [`0x${MNEMONIC || '1000000000000000000000000000000000000000000000000000000000000000'}`],
},
maticMainnet: {
Expand Down Expand Up @@ -117,6 +122,14 @@ export default {
browserURL: 'https://seitrace.com/',
},
},
{
network: 'baseTestnet',
chainId: 84532,
urls: {
apiURL: 'https://api-sepolia.basescan.org/api',
browserURL: 'https://sepolia.basescan.org/',
},
},
{
network: 'mode',
chainId: 34443,
Expand Down
2 changes: 1 addition & 1 deletion src/periphery/scripts/deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ async function main() {
let deploysData = JSON.parse(fs.readFileSync(deployDataPath, 'utf8'));

// WNativeTokenAddress
const WNativeTokenAddress = '0x94373a4919b3240d86ea41593d5eba789fef3848';
const WNativeTokenAddress = '0x4200000000000000000000000000000000000006';
const signers = await hre.ethers.getSigners();
const ProxyAdmin = signers[0].address;

Expand Down
Binary file added src/plugin/.DS_Store
Binary file not shown.
67 changes: 67 additions & 0 deletions src/plugin/contracts/AlgebraALMCustomPluginDeployer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.20;

import '@cryptoalgebra/integral-periphery/contracts/interfaces/IAlgebraCustomPoolEntryPoint.sol';
import './interfaces/IAlgebraALMCustomPoolDeployer.sol';
import './libraries/AdaptiveFee.sol';
import './AlgebraBasePluginALM.sol';

/// @title Algebra Integral 1.2.1 ALM custom plugin deployer
contract AlgebraALMCustomPoolDeployer is IAlgebraALMCustomPoolDeployer {
/// @inheritdoc IAlgebraALMCustomPoolDeployer
bytes32 public constant override ALGEBRA_CUSTOM_PLUGIN_ADMINISTRATOR = keccak256('ALGEBRA_CUSTOM_PLUGIN_ADMINISTRATOR');

/// @inheritdoc IAlgebraALMCustomPoolDeployer
address public immutable override algebraFactory;

/// @inheritdoc IAlgebraALMCustomPoolDeployer
address public immutable entryPoint;

/// @inheritdoc IAlgebraALMCustomPoolDeployer
AlgebraFeeConfiguration public override defaultFeeConfiguration; // values of constants for sigmoids in fee calculation formula

/// @inheritdoc IAlgebraALMCustomPoolDeployer
mapping(address poolAddress => address pluginAddress) public override pluginByPool;

modifier onlyAdministrator() {
require(IAlgebraFactory(algebraFactory).hasRoleOrOwner(ALGEBRA_CUSTOM_PLUGIN_ADMINISTRATOR, msg.sender), 'Only administrator');
_;
}

constructor(address _algebraFactory, address _entryPoint) {
entryPoint = _entryPoint;
algebraFactory = _algebraFactory;
defaultFeeConfiguration = AdaptiveFee.initialFeeConfiguration();
}

/// @inheritdoc IAlgebraPluginFactory
function beforeCreatePoolHook(address pool, address, address, address, address, bytes calldata) external override returns (address) {
require(msg.sender == entryPoint);
return _createPlugin(pool);
}

/// @inheritdoc IAlgebraPluginFactory
function afterCreatePoolHook(address, address, address) external view override {
require(msg.sender == entryPoint);
}

function _createPlugin(address pool) internal returns (address) {
require(pluginByPool[pool] == address(0), 'Already created');
address plugin = address(new AlgebraBasePluginALM(pool, algebraFactory, address(this), defaultFeeConfiguration));
pluginByPool[pool] = plugin;
return address(plugin);
}

/// @inheritdoc IAlgebraALMCustomPoolDeployer
function createCustomPool(address creator, address tokenA, address tokenB, bytes calldata data) external returns (address customPool) {
return IAlgebraCustomPoolEntryPoint(entryPoint).createCustomPool(address(this), creator, tokenA, tokenB, data);
}

/// @inheritdoc IAlgebraALMCustomPoolDeployer
function setDefaultFeeConfiguration(AlgebraFeeConfiguration calldata newConfig) external override onlyAdministrator {
AdaptiveFee.validateFeeConfiguration(newConfig);
defaultFeeConfiguration = newConfig;
emit DefaultFeeConfiguration(newConfig);
}

}
89 changes: 89 additions & 0 deletions src/plugin/contracts/AlgebraBasePluginALM.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.20;

import '@cryptoalgebra/integral-core/contracts/libraries/Plugins.sol';

import '@cryptoalgebra/integral-core/contracts/interfaces/plugin/IAlgebraPlugin.sol';

import './plugins/DynamicFeePlugin.sol';
import './plugins/AlmPlugin.sol';
import './plugins/SlidingFeePlugin.sol';
import './plugins/VolatilityOraclePlugin.sol';

/// @title Algebra Integral 1.2.1 ALM plugin
contract AlgebraBasePluginALM is AlmPlugin, DynamicFeePlugin, VolatilityOraclePlugin {
using Plugins for uint8;

/// @inheritdoc IAlgebraPlugin
uint8 public constant override defaultPluginConfig =
uint8(Plugins.AFTER_INIT_FLAG | Plugins.BEFORE_SWAP_FLAG | Plugins.AFTER_SWAP_FLAG | Plugins.DYNAMIC_FEE);

constructor(
address _pool,
address _factory,
address _pluginFactory,
AlgebraFeeConfiguration memory _config
) AlgebraBasePlugin(_pool, _factory, _pluginFactory) DynamicFeePlugin(_config) {}

// ###### HOOKS ######

function beforeInitialize(address, uint160) external override onlyPool returns (bytes4) {
_updatePluginConfigInPool(defaultPluginConfig);
return IAlgebraPlugin.beforeInitialize.selector;
}

function afterInitialize(address, uint160, int24 tick) external override onlyPool returns (bytes4) {
_initialize_TWAP(tick);
return IAlgebraPlugin.afterInitialize.selector;
}

/// @dev unused
function beforeModifyPosition(address, address, int24, int24, int128, bytes calldata) external override onlyPool returns (bytes4, uint24) {
_updatePluginConfigInPool(defaultPluginConfig); // should not be called, reset config
return (IAlgebraPlugin.beforeModifyPosition.selector, 0);
}

/// @dev unused
function afterModifyPosition(address, address, int24, int24, int128, uint256, uint256, bytes calldata) external override onlyPool returns (bytes4) {
_updatePluginConfigInPool(defaultPluginConfig); // should not be called, reset config
return IAlgebraPlugin.afterModifyPosition.selector;
}

function beforeSwap(address, address, bool, int256, uint160, bool, bytes calldata) external override onlyPool returns (bytes4, uint24, uint24) {
_writeTimepoint();
uint88 volatilityAverage = _getAverageVolatilityLast();
uint24 fee = _getCurrentFee(volatilityAverage);
return (IAlgebraPlugin.beforeSwap.selector, fee, 0);
}

function afterSwap(address, address, bool, int256, uint160, int256, int256, bytes calldata) external override onlyPool returns (bytes4) {
if (rebalanceManager != address(0)) {
if (!_ableToGetTimepoints(slowTwapPeriod)) return IAlgebraPlugin.afterSwap.selector;
(, int24 currentTick, , ) = _getPoolState();
uint32 lastBlockTimestamp = _getLastBlockTimestamp();

int24 slowTwapTick = _getTwapTick(slowTwapPeriod);
int24 fastTwapTick = _getTwapTick(fastTwapPeriod);

_obtainTWAPAndRebalance(currentTick, slowTwapTick, fastTwapTick, lastBlockTimestamp);
}
return IAlgebraPlugin.afterSwap.selector;
}

/// @dev unused
function beforeFlash(address, address, uint256, uint256, bytes calldata) external override onlyPool returns (bytes4) {
_updatePluginConfigInPool(defaultPluginConfig); // should not be called, reset config
return IAlgebraPlugin.beforeFlash.selector;
}

/// @dev unused
function afterFlash(address, address, uint256, uint256, uint256, uint256, bytes calldata) external override onlyPool returns (bytes4) {
_updatePluginConfigInPool(defaultPluginConfig); // should not be called, reset config
return IAlgebraPlugin.afterFlash.selector;
}

function getCurrentFee() external view override returns (uint16 fee) {
uint88 volatilityAverage = _getAverageVolatilityLast();
fee = _getCurrentFee(volatilityAverage);
}
}
80 changes: 80 additions & 0 deletions src/plugin/contracts/AlgebraBasePluginALMFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.20;

import './interfaces/IBasePluginV1Factory.sol';
import './libraries/AdaptiveFee.sol';
import './AlgebraBasePluginALM.sol';

/// @title Algebra Integral 1.2.1 ALM plugin factory
/// @notice This contract creates Algebra adaptive fee plugins for Algebra liquidity pools
/// @dev This plugin factory can only be used for Algebra base pools
contract AlgebraBasePluginALMFactory is IBasePluginV1Factory {
/// @inheritdoc IBasePluginV1Factory
bytes32 public constant override ALGEBRA_BASE_PLUGIN_FACTORY_ADMINISTRATOR = keccak256('ALGEBRA_BASE_PLUGIN_FACTORY_ADMINISTRATOR');

/// @inheritdoc IBasePluginV1Factory
address public immutable override algebraFactory;

/// @inheritdoc IBasePluginV1Factory
AlgebraFeeConfiguration public override defaultFeeConfiguration; // values of constants for sigmoids in fee calculation formula

/// @inheritdoc IBasePluginV1Factory
address public override farmingAddress;

/// @inheritdoc IBasePluginV1Factory
mapping(address poolAddress => address pluginAddress) public override pluginByPool;

modifier onlyAdministrator() {
require(IAlgebraFactory(algebraFactory).hasRoleOrOwner(ALGEBRA_BASE_PLUGIN_FACTORY_ADMINISTRATOR, msg.sender), 'Only administrator');
_;
}

constructor(address _algebraFactory) {
algebraFactory = _algebraFactory;
defaultFeeConfiguration = AdaptiveFee.initialFeeConfiguration();
emit DefaultFeeConfiguration(defaultFeeConfiguration);
}

/// @inheritdoc IAlgebraPluginFactory
function beforeCreatePoolHook(address pool, address, address, address, address, bytes calldata) external override returns (address) {
require(msg.sender == algebraFactory);
return _createPlugin(pool);
}

/// @inheritdoc IAlgebraPluginFactory
function afterCreatePoolHook(address, address, address) external view override {
require(msg.sender == algebraFactory);
}

/// @inheritdoc IBasePluginV1Factory
function createPluginForExistingPool(address token0, address token1) external override returns (address) {
IAlgebraFactory factory = IAlgebraFactory(algebraFactory);
require(factory.hasRoleOrOwner(factory.POOLS_ADMINISTRATOR_ROLE(), msg.sender));

address pool = factory.poolByPair(token0, token1);
require(pool != address(0), 'Pool not exist');

return _createPlugin(pool);
}

function _createPlugin(address pool) internal returns (address) {
require(pluginByPool[pool] == address(0), 'Already created');
IDynamicFeeManager volatilityOracle = new AlgebraBasePluginALM(pool, algebraFactory, address(this), defaultFeeConfiguration);
pluginByPool[pool] = address(volatilityOracle);
return address(volatilityOracle);
}

/// @inheritdoc IBasePluginV1Factory
function setDefaultFeeConfiguration(AlgebraFeeConfiguration calldata newConfig) external override onlyAdministrator {
AdaptiveFee.validateFeeConfiguration(newConfig);
defaultFeeConfiguration = newConfig;
emit DefaultFeeConfiguration(newConfig);
}

/// @inheritdoc IBasePluginV1Factory
function setFarmingAddress(address newFarmingAddress) external override onlyAdministrator {
require(farmingAddress != newFarmingAddress);
farmingAddress = newFarmingAddress;
emit FarmingAddress(newFarmingAddress);
}
}
44 changes: 44 additions & 0 deletions src/plugin/contracts/RebalanceManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.20;

import './base/BaseRebalanceManager.sol';

contract RebalanceManager is BaseRebalanceManager {
constructor(address _vault, uint32 _minTimeBetweenRebalances, Thresholds memory _thresholds) {
require(_vault != address(0), 'Invalid vault address');
paused = false;
vault = _vault;
pool = IAlgebraVault(vault).pool();
factory = IAlgebraPool(pool).factory();

tickSpacing = IAlgebraPool(pool).tickSpacing();

bool _allowToken1 = IAlgebraVault(vault).allowToken1();

minTimeBetweenRebalances = _minTimeBetweenRebalances;

allowToken1 = _allowToken1;
state = State.OverInventory;
lastRebalanceTimestamp = 0;
lastRebalanceCurrentPrice = 0;

_validateThresholds(_thresholds);
thresholds = _thresholds;

address token0 = IAlgebraVault(_vault).token0();
address token1 = IAlgebraVault(_vault).token1();

address _pairedToken = _allowToken1 ? token0 : token1;
pairedToken = _pairedToken;
uint8 _pairedTokenDecimals = _getPairedTokenDecimals();
pairedTokenDecimals = _pairedTokenDecimals;

address _depositToken = _allowToken1 ? token1 : token0;
depositToken = _depositToken;
uint8 _depositTokenDecimals = _getDepositTokenDecimals();
depositTokenDecimals = _depositTokenDecimals;

decimalsSum = _depositTokenDecimals + _pairedTokenDecimals;
tokenDecimals = _allowToken1 ? _pairedTokenDecimals : _depositTokenDecimals;
}
}
Loading