BasisStrategy
Inherits: Initializable, PausableUpgradeable, OwnableUpgradeable, IBasisStrategy, AutomationCompatibleInterface
Author: Logarithm Labs
BasisStrategy implements a delta-neutral basis trading strategy. By simultaneously buying a spot asset and selling a perpetual contract, the strategy seeks to hedge the price risk of the spot position while generating revenue from funding payments. The contract allows depositors to provide capital through the connected vault, which is then deployed across both the spot and perpetual markets. Profits are derived from the funding payments collected from the short perpetual position, aiming for yield independent of price direction.
SpotManager and HedgeManager are connected as separated smart contracts to manage spot and hedge positions. BasisStrategy is an upgradeable smart contract, deployed through a beacon proxy pattern.
State Variables
BasisStrategyStorageLocation
bytes32 private constant BasisStrategyStorageLocation =
0x3176332e209c21f110843843692adc742ac2f78c16c19930ebc0f9f8747e5200;
Functions
_getBasisStrategyStorage
function _getBasisStrategyStorage() private pure returns (BasisStrategyStorage storage $);
authCaller
Authorize caller if it is authorized one.
modifier authCaller(address authorized);
onlyOwnerOrVault
Authorize caller if it is owner and vault.
modifier onlyOwnerOrVault();
whenIdle
Validates if strategy is in IDLE status, otherwise reverts calling.
modifier whenIdle();
initialize
function initialize(
address _config,
address _product,
address _vault,
address _oracle,
address _operator,
uint256 _targetLeverage,
uint256 _minLeverage,
uint256 _maxLeverage,
uint256 _safeMarginLeverage
) external initializer;
_setLeverages
function _setLeverages(uint256 _targetLeverage, uint256 _minLeverage, uint256 _maxLeverage, uint256 _safeMarginLeverage)
internal;
_setOperator
function _setOperator(address newOperator) internal;
setSpotManager
Sets the spot manager.
function setSpotManager(address newSpotManager) external onlyOwner;
setHedgeManager
Sets the hedge manager.
function setHedgeManager(address newHedgeManager) external onlyOwner;
setOperator
Sets the operator.
function setOperator(address newOperator) external onlyOwner;
setLeverages
Sets the leverages.
function setLeverages(uint256 _targetLeverage, uint256 _minLeverage, uint256 _maxLeverage, uint256 _safeMarginLeverage)
external
onlyOwner;
pause
Pauses strategy, disabling utilizing and deutilizing for withdraw requests, while all logics related to keeping are still available.
function pause() external onlyOwnerOrVault whenNotPaused;
unpause
Unpauses strategy.
function unpause() external onlyOwnerOrVault whenPaused;
stop
Pauses strategy while swapping all products back to assets and closing the hedge position.
function stop() external onlyOwnerOrVault whenNotPaused;
utilize
Utilizes assets to increase the spot size. Right after the increase, the hedge position is also increased as the same amount as the spot size increased.
Uses assets in vault. Callable only by the operator.
function utilize(uint256 amount, ISpotManager.SwapType swapType, bytes calldata swapData)
external
virtual
authCaller(operator())
whenIdle;
Parameters
amount
uint256
The underlying asset amount to be utilized.
swapType
ISpotManager.SwapType
The swap type in which the underlying asset is swapped.
swapData
bytes
The data used in swapping.
deutilize
Deutilizes products to decrease the spot size. Right after the decrease, the hedge position is also decreased as the same amount as the spot size decreased.
Called when processing withdraw requests, when deleveraging the position, and when there are funding risks. Callable only by the operator.
function deutilize(uint256 amount, ISpotManager.SwapType swapType, bytes calldata swapData)
external
authCaller(operator())
whenIdle;
Parameters
amount
uint256
The product amount to be deutilized.
swapType
ISpotManager.SwapType
The swap type in which the product is swapped.
swapData
bytes
The data used in swapping.
processAssetsToWithdraw
Processes assets in Strategy for the withdraw requests.
Callable by anyone and only when strategy is in the IDLE status.
function processAssetsToWithdraw() public whenIdle;
checkUpkeep
method that is simulated by the keepers to see if any work actually needs to be performed. This method does does not actually need to be executable, and since it is only ever simulated it can consume lots of gas.
To ensure that it is never called, you may want to add the cannotExecute modifier from KeeperBase to your implementation of this method.
function checkUpkeep(bytes memory) public view returns (bool upkeepNeeded, bytes memory performData);
Parameters
<none>
bytes
Returns
upkeepNeeded
bool
boolean to indicate whether the keeper should call performUpkeep or not.
performData
bytes
bytes that the keeper should call performUpkeep with, if upkeep is needed. If you would like to encode data to decode later, try abi.encode
.
performUpkeep
method that is actually executed by the keepers, via the registry. The data returned by the checkUpkeep simulation will be passed into this method to actually be executed.
The input to this method should not be trusted, and the caller of the method should not even be restricted to any single registry. Anyone should be able call it, and the input should be validated, there is no guarantee that the data passed in is the performData returned from checkUpkeep. This could happen due to malicious keepers, racing keepers, or simply a state change while the performUpkeep transaction is waiting for confirmation. Always validate the data passed in.
function performUpkeep(bytes calldata) external whenIdle;
Parameters
<none>
bytes
spotBuyCallback
Called after product is bought. Increases the hedge position size if the swap operation is for utilizing.
function spotBuyCallback(uint256 assetDelta, uint256 productDelta) external authCaller(spotManager());
spotSellCallback
Called after product is sold. Decreases the hedge position if the swap operation is not for reverting.
function spotSellCallback(uint256 assetDelta, uint256 productDelta) external authCaller(spotManager());
afterAdjustPosition
Callback function dispatcher of the hedge position adjustment.
function afterAdjustPosition(IHedgeManager.AdjustPositionPayload calldata params) external authCaller(hedgeManager());
pendingUtilizations
Returns available pending utilization and deutilization amounts.
The operator uses these values on offchain side to decide the parameters for calling utilize or deutilize functions. Both of those values can’t be none-zero at the same time.
function pendingUtilizations()
public
view
returns (uint256 pendingUtilizationInAsset, uint256 pendingDeutilizationInProduct);
Returns
pendingUtilizationInAsset
uint256
The available pending utilization amount in asset.
pendingDeutilizationInProduct
uint256
The available pending deutilzation amount in product. The calculation of this amount depends on the goal of deutilizing whether it is for processing withdraw requests or for rebalancing down.
utilizedAssets
The total underlying asset amount that has been utilized by this strategy.
Includes the product balance, the position net balance, and the asset balance of this strategy.
function utilizedAssets() public view returns (uint256);
assetsToWithdraw
The asset balance of this strategy.
This value should be transferred to the vault after finishing strategy operations.
function assetsToWithdraw() public view returns (uint256);
assetsToDeutilize
The total asset amount that is needed to be withdrawn from strategy to vault to process withdraw requests.
function assetsToDeutilize() public view returns (uint256);
_adjustPosition
Validate the position adjustment parameters before requesting.
function _adjustPosition(uint256 sizeDeltaInTokens, uint256 collateralDeltaAmount, bool isIncrease)
internal
virtual
returns (bool);
_checkUpkeep
Common function of checkUpkeep and performUpkeep.
function _checkUpkeep() private view returns (InternalCheckUpkeepResult memory result);
_afterIncreasePosition
Called after the hedge position is increased.
function _afterIncreasePosition(IHedgeManager.AdjustPositionPayload calldata responseParams)
private
returns (bool shouldPause);
_afterDecreasePosition
Called after the hedge position is decreased.
function _afterDecreasePosition(IHedgeManager.AdjustPositionPayload calldata responseParams)
private
returns (bool shouldPause);
_processAssetsToWithdraw
Processes assetsToWithdraw for the withdraw requests
function _processAssetsToWithdraw(address _asset) private;
_pendingUtilization
This return value should be 0 when rebalancing down or when paused or when the totalSupply is 0.
function _pendingUtilization(
uint256 totalSupply,
uint256 idleAssets,
uint256 _targetLeverage,
bool _processingRebalanceDown,
bool _paused
) private pure returns (uint256);
_pendingDeutilization
This return value should be 0 when paused and not processing rebalance down.
function _pendingDeutilization(InternalPendingDeutilization memory params) private view returns (uint256);
_clamp
function _clamp(uint256 min, uint256 value, uint256 max) internal pure returns (uint256 result);
_checkDeviation
Should be called under the condition that denominator != 0. Note: check if response of position adjustment is in the allowed deviation
function _checkDeviation(uint256 numerator, uint256 denominator, uint256 deviationThreshold)
internal
pure
returns (bool exceedsThreshold, int256 deviation);
_checkNeedRebalance
Checks if current leverage is not near to the target leverage
function _checkNeedRebalance(uint256 _currentLeverage, uint256 _targetLeverage, uint256 _rebalanceDeviationThreshold)
internal
pure
returns (bool rebalanceUpNeeded, bool rebalanceDownNeeded);
_checkRebalance
Checks if current leverage is out of the min and max leverage
function _checkRebalance(
uint256 currentLeverage,
uint256 _minLeverage,
uint256 _maxLeverage,
uint256 _safeMarginLeverage
) internal pure returns (bool rebalanceUpNeeded, bool rebalanceDownNeeded, bool deleverageNeeded);
_checkHedgeDeviation
Checks the difference between spot and hedge sizes if it is over the configured threshold.
function _checkHedgeDeviation(IHedgeManager _hedgeManager, uint256 _hedgeDeviationThreshold)
internal
view
returns (int256);
_calculateDeltaCollateralForRebalance
collateral adjustment for rebalancing currentLeverage = notional / collateral notional = currentLeverage collateral targetLeverage = notional / targetCollateral targetCollateral = notional / targetLeverage targetCollateral = collateral * currentLeverage / targetLeverage*
function _calculateDeltaCollateralForRebalance(
uint256 positionNetBalance,
uint256 _currentLeverage,
uint256 _targetLeverage
) internal pure returns (uint256);
_validateStrategyStatus
Validates the strategy status if it is desired one.
function _validateStrategyStatus(StrategyStatus targetStatus) private view;
_setStrategyStatus
Sets the strategy status.
function _setStrategyStatus(StrategyStatus newStatus) private;
vault
The address of connected vault.
function vault() public view returns (address);
spotManager
The address of the spot manager which buys and sells product in spot markets.
function spotManager() public view returns (address);
hedgeManager
The address of the position manager which hedges the spot by opening perpetual positions.
function hedgeManager() public view returns (address);
oracle
The address of system oracle.
function oracle() public view returns (address);
operator
The address of operator which is responsible for calling utilize/deutilize.
function operator() public view returns (address);
asset
The address of underlying asset.
function asset() public view returns (address);
product
The address of product.
function product() public view returns (address);
config
The address of Config smart contract that is used throughout all strategies for their configurations.
function config() public view returns (IStrategyConfig);
strategyStatus
The strategy status.
function strategyStatus() public view returns (StrategyStatus);
targetLeverage
The target leverage at which the hedge position is increased.
function targetLeverage() public view returns (uint256);
minLeverage
The minimum leverage value to which the hedge position can be reached down.
function minLeverage() public view returns (uint256);
maxLeverage
The maximum leverage value to which the hedge position can be reached up.
function maxLeverage() public view returns (uint256);
safeMarginLeverage
The maximum leverage value where normal rebalancing down is applied. If the leverage overshoots it, emergency rebalancing down is executed.
function safeMarginLeverage() public view returns (uint256);
pendingDecreaseCollateral
The value that couldn’t be decreased due to size limits. Accumulated overtime and executed to decrease collateral by keeping logic once the size satisfies the conditions.
function pendingDecreaseCollateral() public view returns (uint256);
processingRebalanceDown
Tells if strategy is in rebalancing down.
function processingRebalanceDown() public view returns (bool);
Events
Utilize
Emitted when assets are utilized.
event Utilize(address indexed caller, uint256 assetDelta, uint256 productDelta);
Deutilize
Emitted when assets are deutilized.
event Deutilize(address indexed caller, uint256 productDelta, uint256 assetDelta);
PositionAdjusted
Emitted when the hedge position gets adjusted.
event PositionAdjusted(uint256 sizeDeltaInTokens, uint256 collateralDeltaAmount, bool isIncrease);
LeverageConfigUpdated
Emitted when leverage config gets changed.
event LeverageConfigUpdated(
address indexed account,
uint256 targetLeverage,
uint256 minLeverage,
uint256 maxLeverage,
uint256 safeMarginLeverage
);
SpotManagerUpdated
Emitted when the spot manager is changed.
event SpotManagerUpdated(address indexed account, address indexed newSpotManager);
HedgeManagerUpdated
Emitted when the position manager is changed.
event HedgeManagerUpdated(address indexed account, address indexed newPositionManager);
OperatorUpdated
Emitted when the operator is changed.
event OperatorUpdated(address indexed account, address indexed newOperator);
Stopped
Emitted when strategy is stopped.
event Stopped(address indexed account);
Structs
InternalPendingDeutilization
Used internally to optimize params of deutilization.
struct InternalPendingDeutilization {
IHedgeManager hedgeManager;
address asset;
address product;
uint256 totalSupply;
bool processingRebalanceDown;
bool paused;
}
InternalCheckUpkeepResult
Used internally as a result of checkUpkeep function.
struct InternalCheckUpkeepResult {
uint256 emergencyDeutilizationAmount;
uint256 deltaCollateralToIncrease;
bool clearProcessingRebalanceDown;
int256 hedgeDeviationInTokens;
bool hedgeManagerNeedKeep;
bool processPendingDecreaseCollateral;
uint256 deltaCollateralToDecrease;
}
BasisStrategyStorage
struct BasisStrategyStorage {
IERC20 product;
IERC20 asset;
ILogarithmVault vault;
ISpotManager spotManager;
IHedgeManager hedgeManager;
IOracle oracle;
address operator;
address config;
uint256 targetLeverage;
uint256 minLeverage;
uint256 maxLeverage;
uint256 safeMarginLeverage;
uint256 pendingDeutilizedAssets;
uint256 pendingDecreaseCollateral;
StrategyStatus strategyStatus;
bool processingRebalanceDown;
IHedgeManager.AdjustPositionPayload requestParams;
}
Enums
StrategyStatus
Used to specify strategy’s operations.
enum StrategyStatus {
IDLE,
KEEPING,
UTILIZING,
PARTIAL_DEUTILIZING,
FULL_DEUTILIZING
}
Last updated