Description:
Multi-signature wallet contract requiring multiple confirmations for transaction execution.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"altitude-v2/contracts/strategies/farming/strategies/morpho/MorphoVault.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/interfaces/IERC4626.sol";
import "../FarmDropStrategy.sol";
import "../../../SkimStrategy.sol";
import "../../../../libraries/uniswap-v3/TransferHelper.sol";
import "../../../../interfaces/internal/strategy/farming/IMorphoVault.sol";
/**
* @title MorphoVault Contract
* @dev Contract for interacting with MetaMorpho vaults
* @author Altitude Labs
**/
contract MorphoVault is FarmDropStrategy, SkimStrategy, IMorphoVault {
IERC4626 public immutable morphoVault;
constructor(
address farmDispatcherAddress_,
address rewardsAddress_,
address swapStrategy_,
IERC4626 morphoVault_,
address[] memory rewardAssets_,
address[] memory nonSkimAssets_
)
FarmDropStrategy(morphoVault_.asset(), farmDispatcherAddress_, rewardsAddress_, rewardAssets_, swapStrategy_)
SkimStrategy(nonSkimAssets_)
{
morphoVault = morphoVault_;
}
/// @notice Deposit into Morpho
/// @param amount Amount of asset to deposit
function _deposit(uint256 amount) internal override {
amount = _swap(asset, farmAsset, amount);
TransferHelper.safeApprove(farmAsset, address(morphoVault), amount);
morphoVault.deposit(amount, address(this));
}
/// @notice Withdraw from Morpho
/// @param amountRequested Amount of asset to withdraw
function _withdraw(uint256 amountRequested) internal override {
uint256 amountToWithdraw = amountRequested;
if (farmAsset != asset) {
// If a conversion is happening, we substitute the requested sum with the
// input amount we'd need to provide to get it in a swap
amountToWithdraw = swapStrategy.getAmountIn(farmAsset, asset, amountToWithdraw);
}
uint256 farmBalance = morphoVault.maxWithdraw(address(this));
if (amountToWithdraw > farmBalance) {
// If requested amount is more than we have, recognise rewards and withdraw all
if (farmBalance > 0) {
morphoVault.withdraw(farmBalance, address(this), address(this));
}
} else {
// Else withdraw the requested amount
if (farmBalance > 0) {
morphoVault.withdraw(amountToWithdraw, address(this), address(this));
}
}
// Swap the farm asset to borrow asset (if required)
_swap(farmAsset, asset, type(uint256).max);
}
/// @notice Withdraw as much as possible from Morpho
function _emergencyWithdraw() internal override {
morphoVault.redeem(morphoVault.maxRedeem(address(this)), address(this), address(this));
}
/// @notice Return farm asset ammount specific for the farm provider
function _getFarmAssetAmount() internal view virtual override returns (uint256 farmAssetAmount) {
uint256 shares = morphoVault.balanceOf(address(this));
if (shares > 0) {
farmAssetAmount = morphoVault.convertToAssets(shares);
}
}
/// @notice Internal reusable function
function _recogniseRewardsInBase() internal override {
for (uint256 i; i < rewardAssets.length; ++i) {
_swap(rewardAssets[i], asset, type(uint256).max);
}
// Update drop percentage
super._recogniseRewardsInBase();
}
}
"
},
"altitude-v2/node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
"
},
"altitude-v2/node_modules/@openzeppelin/contracts/interfaces/IERC4626.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (interfaces/IERC4626.sol)
pragma solidity ^0.8.0;
import "../token/ERC20/IERC20.sol";
import "../token/ERC20/extensions/IERC20Metadata.sol";
/**
* @dev Interface of the ERC4626 "Tokenized Vault Standard", as defined in
* https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
*
* _Available since v4.7._
*/
interface IERC4626 is IERC20, IERC20Metadata {
event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed sender,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
/**
* @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
*
* - MUST be an ERC-20 token contract.
* - MUST NOT revert.
*/
function asset() external view returns (address assetTokenAddress);
/**
* @dev Returns the total amount of the underlying asset that is “managed” by Vault.
*
* - SHOULD include any compounding that occurs from yield.
* - MUST be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT revert.
*/
function totalAssets() external view returns (uint256 totalManagedAssets);
/**
* @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToShares(uint256 assets) external view returns (uint256 shares);
/**
* @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
* through a deposit call.
*
* - MUST return a limited value if receiver is subject to some deposit limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
* - MUST NOT revert.
*/
function maxDeposit(address receiver) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
* call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
* in the same transaction.
* - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
* deposit would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewDeposit(uint256 assets) external view returns (uint256 shares);
/**
* @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* deposit execution, and are accounted for during deposit.
* - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
* - MUST return a limited value if receiver is subject to some mint limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
* - MUST NOT revert.
*/
function maxMint(address receiver) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
* in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
* same transaction.
* - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
* would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by minting.
*/
function previewMint(uint256 shares) external view returns (uint256 assets);
/**
* @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
* execution, and are accounted for during mint.
* - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function mint(uint256 shares, address receiver) external returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
* Vault, through a withdraw call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxWithdraw(address owner) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
* call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
* called
* in the same transaction.
* - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
* the withdrawal would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewWithdraw(uint256 assets) external view returns (uint256 shares);
/**
* @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* withdraw execution, and are accounted for during withdraw.
* - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function withdraw(
uint256 assets,
address receiver,
address owner
) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
* through a redeem call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxRedeem(address owner) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
* in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
* same transaction.
* - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
* redemption would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by redeeming.
*/
function previewRedeem(uint256 shares) external view returns (uint256 assets);
/**
* @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* redeem execution, and are accounted for during redeem.
* - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function redeem(
uint256 shares,
address receiver,
address owner
) external returns (uint256 assets);
}
"
},
"altitude-v2/contracts/strategies/farming/strategies/FarmDropStrategy.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/Ownable.sol";
import "./FarmStrategy.sol";
import "../../../interfaces/internal/strategy/farming/IFarmDropStrategy.sol";
/**
* @title FarmDropStrategy Contract
* @dev Provides tools to monitor drops in the farm balance value
* @author Altitude Labs
**/
abstract contract FarmDropStrategy is Ownable, FarmStrategy, IFarmDropStrategy {
uint256 public override expectedBalance;
uint256 public override dropPercentage;
uint256 public constant override DROP_UNITS = 1e18;
/// @notice Default drop threshold to revert deposit/withdraw calls is 5%
uint256 public override dropThreshold = (DROP_UNITS * 5) / 100;
constructor(
address farmAssetAddress,
address farmDispatcherAddress,
address rewardsAddress,
address[] memory rewardAssets_,
address swapStrategyAddress
) FarmStrategy(farmAssetAddress, farmDispatcherAddress, rewardsAddress, rewardAssets_, swapStrategyAddress) {}
/// @notice Set the threshold for reverting deposit/withdraw
/// @param dropThreshold_ The new threshold in percentage (of DROP_UNITS, 1e18)
function setDropThreshold(uint256 dropThreshold_) external onlyOwner {
if (dropThreshold_ > DROP_UNITS) {
revert FDS_OUT_OF_BOUNDS();
}
dropThreshold = dropThreshold_;
}
/// @notice Deal with a farm drop during deposit
/// If a farm drop is detected, the deposit will be reverted
/// @param amount The amount to deposit
function deposit(uint256 amount) public override(FarmStrategy, IFarmStrategy) {
uint256 currentBalance = balance();
_updateDropPercentage(currentBalance, 0);
if (dropPercentage > dropThreshold) {
revert FDS_DROP_EXCEEDED(dropPercentage, dropThreshold);
}
// deposit and check for any deposit fees
expectedBalance = currentBalance;
super.deposit(amount);
currentBalance = balance();
_updateDropPercentage(currentBalance, amount);
expectedBalance = currentBalance;
}
/// @notice Track and handle any possible farm drop on withdraw
/// If a farm drop is detected, the withdraw will be reverted
/// @param amountRequested The amount to withdraw
function withdraw(
uint256 amountRequested
) public override(FarmStrategy, IFarmStrategy) returns (uint256 amountWithdrawn) {
_updateDropPercentage(balance(), 0);
if (dropPercentage > dropThreshold) {
revert FDS_DROP_EXCEEDED(dropPercentage, dropThreshold);
}
amountWithdrawn = super.withdraw(amountRequested);
expectedBalance = balance();
}
/// @notice Update the drop percentage on emergencyWithdraw
function emergencyWithdraw() public override(FarmStrategy, IFarmStrategy) {
_updateDropPercentage(balance(), 0);
super.emergencyWithdraw();
expectedBalance = balance();
}
/// @notice Update the drop percentage on emergencySwap
/// @param assets The assets to swap
function emergencySwap(
address[] calldata assets
) public override(FarmStrategy, IFarmStrategy) returns (uint256 amountWithdrawn) {
_updateDropPercentage(balance(), 0);
amountWithdrawn = super.emergencySwap(assets);
expectedBalance = balance();
}
/// @notice Account for increase/decrease in the farm drop percentage
/// @param amount Expected balance increase
function _updateDropPercentage(uint256 currentBalance, uint256 amount) internal {
dropPercentage = _calculateDropPercentage(currentBalance, expectedBalance + amount, dropPercentage);
}
/// @notice Calculates the current drop in farm value as percentage
/// @return percentage The total drop in farm value as a percentage
function currentDropPercentage() public view override returns (uint256) {
return _calculateDropPercentage(balance(), expectedBalance, dropPercentage);
}
/// @notice Decrease drop percentage with the rewards that are used to restore it
function _recogniseRewardsInBase() internal virtual override {
/// @dev It is assumed the balance to be bigger than the expected one
// as the rewards have been recognised from the inherited contract
// The drop percentage is to be decreased with the new rewards
_updateDropPercentage(balance(), 0);
}
/// @notice Track and handle any possible farm drop on recogniseRewardsInBase
/// @return rewards The amount of rewards recognised
function recogniseRewardsInBase() public virtual override(FarmStrategy, IFarmStrategy) returns (uint256 rewards) {
rewards = super.recogniseRewardsInBase();
expectedBalance = balance();
}
/// @notice Calculates the drop in farm value as percentage
/// @param currentBalance_ The current amount in farming
/// @param expectedBalance_ The expected amount in farming
/// @param accumulatedDrop_ The drop percentage accumulated so far
/// @return amount The total drop in farm value as a percentage
function _calculateDropPercentage(
uint256 currentBalance_,
uint256 expectedBalance_,
uint256 accumulatedDrop_
) private pure returns (uint256) {
if (expectedBalance_ == 0) {
// If we expect the farm to be empty there can be no drop
return 0;
}
if (currentBalance_ > expectedBalance_) {
// Gained value
uint256 percentage = ((currentBalance_ - expectedBalance_) * DROP_UNITS) / expectedBalance_;
uint256 percentageAdjustment = (accumulatedDrop_ + ((accumulatedDrop_ * percentage) / DROP_UNITS));
if (percentageAdjustment > percentage) {
accumulatedDrop_ = percentageAdjustment - percentage;
} else {
// Farm is at net gain, new peak from where we will start tracking losses
accumulatedDrop_ = 0;
}
} else {
if (currentBalance_ == 0) {
// Lost everything shortcut
accumulatedDrop_ = DROP_UNITS;
} else {
// Lost some
uint256 percentage = ((expectedBalance_ - currentBalance_) * DROP_UNITS) / expectedBalance_;
accumulatedDrop_ = (accumulatedDrop_ - ((accumulatedDrop_ * percentage) / DROP_UNITS)) + percentage;
}
}
return accumulatedDrop_;
}
/// @notice Reset drop percentage
function reset() external override onlyOwner {
dropPercentage = 0;
expectedBalance = balance();
emit ResetDropPercentage();
}
}
"
},
"altitude-v2/contracts/strategies/SkimStrategy.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../libraries/uniswap-v3/TransferHelper.sol";
import "../interfaces/internal/strategy/ISkimStrategy.sol";
/**
* @title SkimStrategy
* @dev Contract for skiming assets
* @author Altitude Labs
**/
contract SkimStrategy is Ownable, ISkimStrategy {
/** @notice Assets that are not allowed for skim */
mapping(address => bool) public nonSkimAssets;
/// @param assets Assets that are not allowed for skim
constructor(address[] memory assets) {
uint256 assetsLength = assets.length;
for (uint256 i; i < assetsLength; ) {
nonSkimAssets[assets[i]] = true;
unchecked {
++i;
}
}
}
/** @notice Transfer tokens out of the strategy
* @dev Used to even out distributions when rewards accrue in batches
* @param assets Token addresses
* @param receiver Receiving account
*/
function skim(address[] calldata assets, address receiver) public override onlyOwner {
if (receiver == address(0)) {
revert SK_INVALID_RECEIVER();
}
uint256 assetsLength = assets.length;
for (uint256 i; i < assetsLength; ) {
if (nonSkimAssets[assets[i]]) {
revert SK_NON_SKIM_ASSET();
}
TransferHelper.safeTransfer(assets[i], receiver, IERC20(assets[i]).balanceOf(address(this)));
unchecked {
++i;
}
}
}
}
"
},
"altitude-v2/contracts/libraries/uniswap-v3/TransferHelper.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.28;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/**
* @title Transfer Helper Library
* @dev Contains helper methods for interacting with ERC20 tokens that do not consistently return true/false
* @author Uniswap
**/
library TransferHelper {
// Tranfer helper library Errors
error TH_SAFE_TRANSFER_FAILED();
error TH_SAFE_TRANSFER_FROM_FAILED();
error TH_SAFE_TRANSFER_NATIVE_FAILED();
error TH_SAFE_APPROVE();
error TH_SAFE_APPROVE_RESET();
function safeTransfer(address token, address to, uint256 value) internal {
bool toThrow = _call(token, abi.encodeWithSelector(IERC20.transfer.selector, to, value));
if (toThrow) {
revert TH_SAFE_TRANSFER_FAILED();
}
}
function safeTransferFrom(address token, address from, address to, uint256 value) internal {
bool toThrow = _call(token, abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
if (toThrow) {
revert TH_SAFE_TRANSFER_FROM_FAILED();
}
}
/// @notice Approves the stipulated contract to spend the given allowance in the given token
/// @dev Errors with 'SA' if transfer fails
/// @param token The contract address of the token to be approved
/// @param to The target of the approval
/// @param value The amount of the given token the target will be allowed to spend
function safeApprove(address token, address to, uint256 value) internal {
// Reset approval first
bool toThrow = _call(token, abi.encodeWithSelector(IERC20.approve.selector, to, 0));
if (toThrow) {
revert TH_SAFE_APPROVE_RESET();
}
toThrow = _call(token, abi.encodeWithSelector(IERC20.approve.selector, to, value));
if (toThrow) {
revert TH_SAFE_APPROVE();
}
}
function _call(address token, bytes memory data) internal returns (bool) {
(bool success, bytes memory resultData) = token.call(data);
if (!success || (resultData.length > 0 && !abi.decode(resultData, (bool)))) {
return true;
}
return false;
}
function safeTransferNative(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
if (!success) {
revert TH_SAFE_TRANSFER_NATIVE_FAILED();
}
}
}
"
},
"altitude-v2/contracts/interfaces/internal/strategy/farming/IMorphoVault.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/interfaces/IERC4626.sol";
import "./IFarmStrategy.sol";
/**
* @author Altitude Protocol
**/
interface IMorphoVault is IFarmStrategy {
function morphoVault() external returns (IERC4626);
}
"
},
"altitude-v2/node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
"
},
"altitude-v2/node_modules/@openzeppelin/contracts/access/Ownable.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
"
},
"altitude-v2/contracts/strategies/farming/strategies/FarmStrategy.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../../swap/SwapStrategyConfiguration.sol";
import "../../../libraries/uniswap-v3/TransferHelper.sol";
import "../../../interfaces/internal/access/IIngress.sol";
import "../../../interfaces/internal/vault/IVaultCore.sol";
import "../../../interfaces/internal/strategy/farming/IFarmStrategy.sol";
import "../../../interfaces/internal/strategy/farming/IFarmDispatcher.sol";
/**
* @title FarmStrategy Contract
* @author Altitude Labs
**/
abstract contract FarmStrategy is Ownable, SwapStrategyConfiguration, IFarmStrategy {
address public override asset; // baseAsset of farmDispatcher
address public override farmAsset; // asset of the farm
address public override farmDispatcher; // farmDispatcher address
address[] public override rewardAssets; // reward tokens to recognise
address public override rewardsRecipient; // where to send rewards
modifier onlyDispatcher() {
if (msg.sender != farmDispatcher) {
revert FS_ONLY_DISPATCHER();
}
_;
}
/// @param farmAssetAddress The address of the token we are farming with
/// @param farmDispatcherAddress The manager of the strategy
/// @param rewardsAddress Where to send any reward tokens
/// @param rewardAssets_ Reward tokens to recognise
/// @param swapStrategyAddress Swap strategy needed in case farmAsset != baseAsset
constructor(
address farmAssetAddress,
address farmDispatcherAddress,
address rewardsAddress,
address[] memory rewardAssets_,
address swapStrategyAddress
) SwapStrategyConfiguration(swapStrategyAddress) {
farmAsset = farmAssetAddress;
farmDispatcher = farmDispatcherAddress;
rewardsRecipient = rewardsAddress;
rewardAssets = rewardAssets_;
asset = IFarmDispatcher(farmDispatcher).asset();
}
/// @notice Sets the reward tokens to be recognised
/// @param rewardAssets_ Token addresses
function setRewardAssets(address[] memory rewardAssets_) external onlyOwner {
emit SetRewardAssets(rewardAssets, rewardAssets_);
rewardAssets = rewardAssets_;
}
/// @notice Deposits own funds into the Farm Provider
/// @param amount amount to deposit
function deposit(uint256 amount) public virtual override onlyDispatcher {
if (amount > 0) {
// Transfer funds from dispatcher
TransferHelper.safeTransferFrom(asset, msg.sender, address(this), amount);
_deposit(IERC20(asset).balanceOf(address(this)));
emit Deposit(amount);
}
}
/// @notice Withdraws from the Farm Provider
/// @param amountRequested The amount to withdraw
/// @return amountWithdrawn The amount actually withdrawn
function withdraw(
uint256 amountRequested
) public virtual override onlyDispatcher returns (uint256 amountWithdrawn) {
if (amountRequested > 0) {
// When trying to withdraw all
if (amountRequested == type(uint256).max) {
// balanceAvailable() skips the swap slippage check, as that will happen in the actual withdraw
amountRequested = balanceAvailable();
}
_withdraw(amountRequested);
amountWithdrawn = IERC20(asset).balanceOf(address(this));
if (amountWithdrawn > 0) {
TransferHelper.safeTransfer(asset, msg.sender, amountWithdrawn);
}
emit Withdraw(amountWithdrawn);
}
}
/// @notice Withdraw everything from the farm with minimal constraints
/// @dev Should be invoked via protected rpc
/// @dev We may want to perform intermediate actions, so this is step one of a two step process
/// @dev Step two is emergencySwap()
function emergencyWithdraw() public virtual onlyOwner {
_emergencyWithdraw();
emit EmergencyWithdraw();
}
/// @notice Swap specified tokens to asset
/// @param assets The assets to swap
/// @return amountWithdrawn The amount withdrawn after swap
function emergencySwap(
address[] calldata assets
) public virtual override onlyOwner returns (uint256 amountWithdrawn) {
_emergencySwap(assets);
amountWithdrawn = IERC20(asset).balanceOf(address(this));
TransferHelper.safeTransfer(asset, farmDispatcher, amountWithdrawn);
emit EmergencySwap();
}
/// @notice Claim and swap reward tokens to base asset. Then transfer to the dispatcher for compounding
/// @return rewards An amount of rewards being recognised
function recogniseRewardsInBase() public virtual override returns (uint256 rewards) {
_recogniseRewardsInBase();
rewards = IERC20(asset).balanceOf(address(this));
TransferHelper.safeTransfer(asset, rewardsRecipient, rewards);
emit RewardsRecognition(rewards);
}
/// @notice Return the balance in borrow asset excluding rewards (includes slippage validations)
/// @dev Reverts if slippage is too high
/// @return balance that can be withdrawn from the farm
function balance() public view virtual returns (uint256) {
// Get amount of tokens
uint256 farmAssetAmount = _getFarmAssetAmount();
(uint256 totalBalance, uint256 swapAmount) = _balance(farmAssetAmount);
if (swapAmount > 0) {
// Validate slippage
uint256 minimumAssetAmount = swapStrategy.getMinimumAmountOut(farmAsset, asset, farmAssetAmount);
if (swapAmount < minimumAssetAmount) {
// Amount is no good since slippage is too high.
// @dev harvest() earnings calculation relies on .balance() so it is important to revert on a bad value
revert SSC_SWAP_AMOUNT(minimumAssetAmount, swapAmount);
}
}
return totalBalance;
}
/// @notice Return the balance in borrow asset excluding rewards (no slippage validations)
/// @dev Function will not revert on high slippage, should used with care in transactions
/// @return availableBalance Balance that can be withdrawn from the farm
function balanceAvailable() public view virtual returns (uint256 availableBalance) {
// No slippage validations
(availableBalance, ) = _balance(_getFarmAssetAmount());
}
/// @notice Return the max amount that can be withdrawn at the moment
/// @param farmAssetAmount The amount from the farm provider
/// @return totalBalance The amount available to be withdrawn (including amount swapped)
/// @return swapAmount Amount of totalBalance that is subject to swapping
function _balance(
uint256 farmAssetAmount
) internal view virtual returns (uint256 totalBalance, uint256 swapAmount) {
totalBalance = IERC20(asset).balanceOf(address(this));
if (farmAssetAmount > 0) {
if (farmAsset == asset) {
totalBalance += farmAssetAmount;
} else {
// amount of borrow asset we'd get if we swap
swapAmount = swapStrategy.getAmountOut(farmAsset, asset, farmAssetAmount);
totalBalance += swapAmount;
}
}
}
function _getFarmAssetAmount() internal view virtual returns (uint256);
function _deposit(uint256 amount) internal virtual;
function _withdraw(uint256 amount) internal virtual;
function _emergencyWithdraw() internal virtual;
function _recogniseRewardsInBase() internal virtual;
/// @notice Swap assets to borrow asset
/// @param assets Array of assets to swap
function _emergencySwap(address[] calldata assets) internal virtual {
for (uint256 i; i < assets.length; ++i) {
_swap(assets[i], asset, type(uint256).max);
}
}
/// @notice Swap between different assets
/// @param inputAsset Input asset address
/// @param outputAsset Output asset address
/// @param amount Amount to swap
function _swap(address inputAsset, address outputAsset, uint256 amount) internal virtual returns (uint256) {
if (inputAsset != outputAsset) {
if (amount == type(uint256).max) {
amount = IERC20(inputAsset).balanceOf(address(this));
}
if (amount > 0) {
TransferHelper.safeApprove(inputAsset, address(swapStrategy), amount);
amount = swapStrategy.swapInBase(inputAsset, outputAsset, amount);
}
}
return amount;
}
}
"
},
"altitude-v2/contracts/interfaces/internal/strategy/farming/IFarmDropStrategy.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0.
pragma solidity 0.8.28;
import "./IFarmStrategy.sol";
/**
* @author Altitude Protocol
**/
interface IFarmDropStrategy is IFarmStrategy {
event ResetDropPercentage();
error FDS_DROP_EXCEEDED(uint256 current, uint256 threshold);
error FDS_OUT_OF_BOUNDS();
function dropThreshold() external view returns (uint256);
function dropPercentage() external view returns (uint256);
function expectedBalance() external view returns (uint256);
function currentDropPercentage() external view returns (uint256);
function DROP_UNITS() external view returns (uint256);
function setDropThreshold(uint256 dropThreshold_) external;
function reset() external;
}
"
},
"altitude-v2/contracts/interfaces/internal/strategy/ISkimStrategy.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0.
pragma solidity 0.8.28;
/**
* @author Altitude Protocol
**/
interface ISkimStrategy {
/** @notice Emitted when an asset is not allowed for skim */
error SK_NON_SKIM_ASSET();
/** @notice Emitted when the receiver address is invalid */
error SK_INVALID_RECEIVER();
function nonSkimAssets(address asset) external view returns (bool);
function skim(address[] calldata assets, address receiver) external;
}
"
},
"altitude-v2/contracts/interfaces/internal/strategy/farming/IFarmStrategy.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0.
pragma solidity 0.8.28;
import "../swap/ISwapStrategyConfiguration.sol";
/**
* @author Altitude Protocol
**/
interface IFarmStrategy is ISwapStrategyConfiguration {
event Deposit(uint256 amount);
event Withdraw(uint256 amount);
event RewardsRecognition(uint256 rewards);
event EmergencyWithdraw();
event EmergencySwap();
event SetRewardAssets(address[] oldAssets, address[] newAssets);
error FS_ONLY_DISPATCHER();
function rewardAssets(uint256) external returns (address);
function asset() external view returns (address);
function farmAsset() external view returns (address);
function farmDispatcher() external view returns (address);
function rewardsRecipient() external view returns (address);
function deposit(uint256 amount) external;
function recogniseRewardsInBase() external returns (uint256 rewards);
function withdraw(uint256 amount) external returns (uint256 amountWithdrawn);
function emergencyWithdraw() external;
function emergencySwap(address[] calldata tokens) external returns (uint256 amountWithdrawn);
function balance() external view returns (uint256);
function balanceAvailable() external view returns (uint256);
function setRewardAssets(address[] memory rewardAssets_) external;
}
"
},
"altitude-v2/node_modules/@openzeppelin/contracts/utils/Context.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
"
},
"altitude-v2/contracts/strategies/swap/SwapStrategyConfiguration.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import "@openzeppelin/contracts/access/Ownable.sol";
import "../../interfaces/internal/strategy/swap/ISwapStrategyConfiguration.sol";
/**
* @title SwapStrategyConfiguration Contract
* @dev Base contract for swap strategy setup
* @author Altitude Labs
**/
contract SwapStrategyConfiguration is Ownable, ISwapStrategyConfiguration {
/** @notice integration with swap provider */
ISwapStrategy public override swapStrategy;
constructor(address swapStrategy_) {
swapStrategy = ISwapStrategy(swapStrategy_);
}
/// @notice Every lending/farming strategy has to deal with reward tokens
/// @notice Because of this, it should use an exchange strategy to swap
/// @notice the reward tokens for the base asset
/// @param newSwapStrategy The exchange strategy
function setSwapStrategy(address newSwapStrategy) external onlyOwner {
swapStrategy = ISwapStrategy(newSwapStrategy);
emit UpdateSwapStrategy(newSwapStrategy);
}
}
"
},
"altitude-v2/contracts/interfaces/internal/access/IIngress.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0.
pragma solidity 0.8.28;
import "@openzeppelin/contracts/access/IAccessControl.sol";
/**
* @title Ingress interface
* @author Altitude Labs
**/
interface IIngress is IAccessControl {
// Type of transactions the rate limit can apply to
enum RateLimitType {
Withdraw,
Borrow,
Claim
}
event UpdateRateLimit(uint256[3] _rateLimitPeriod, uint256[3] _rateLimitAmount);
event UpdateSanctionedList(address[] sanctionedList, bool toSanction);
event UpdateDepositLimits(uint256 userMinDepositLimit, uint256 userMaxDepositLimit, uint256 vaultDepositLimit);
event SetProtocolPause(bool toPause);
event SetFunctionsState(bytes4[] functions, bool toPause);
// Ingress Control Errors
error IN_V1_FUNCTION_PAUSED();
error IN_V1_PROTOCOL_PAUSED();
error IN_V1_CLAIM_RATE_LIMIT();
error IN_V1_BORROW_RATE_LIMIT();
error IN_V1_WITHDRAW_RATE_LIMIT();
error IN_V1_USER_DEPOSIT_MINIMUM_UNMET();
error IN_V1_ACCOUNT_HAS_BEEN_SANCTIONED();
error IN_V1_USER_DEPOSIT_LIMIT_EXCEEDED();
error IN_V1_VAULT_DEPOSIT_LIMIT_EXCEEDED();
error IN_ACCOUNT_CAN_NOT_CALL_THIS_FUNCTION();
function sanctioned(address) external view returns (bool);
function userMinDepositLimit() external view returns (uint256);
function userMaxDepositLimit() external view returns (uint256);
function vaultDepositLimit() external view returns (uint256);
function pause() external view returns (bool);
function setSanctioned(address[] memory _sanctioned, bool toSanction) external;
function isFunctionDisabled(bytes4) external view returns (bool);
function setRateLimit(uint256[3] memory _rateLimitPeriod, uint256[3] memory _rateLimitAmount) external;
function setDepositLimits(
uint256 _userMinDepositLimit,
uint256 _userMaxDepositLimit,
uint256 _vaultDepositLimit
) external;
function setProtocolPause(bool toPause) external;
function setFunctionsPause(bytes4[] memory functions, bool toPause) external;
function validateDeposit(address depositor, address recipient, uint256 amount) external view;
function validateWithdraw(address withdrawer, address recipient, uint256 amount) external;
function validateBorrow(uint256 amount, address onBehalfOf, address receiver) external;
function validateRepay(address repayer, address recipient) external view;
function validateTransfer(address from, address to) external view;
function validateClaimRewards(address claimer, uint256 amount) external;
function validateCommit() external view;
function validateRebalance(address sender) external view;
function validateLiquidateUsers(address liquidator) external view;
function validateSnapshotSupplyLoss(address sender) external view;
}
"
},
"altitude-v2/contracts/interfaces/internal/vault/IVaultCore.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0.
pragma solidity 0.8.28;
import "./IVaultStorage.sol";
import "./extensions/groomable/IGroomableVault.sol";
import "./extensions/snapshotable/ISnapshotableVault.sol";
import "./extensions/liquidatable/ILiquidatableVault.sol";
import "./extensions/configurable/IConfigurableVault.sol";
/**
* @author Altitude Protocol
**/
interface IVaultCoreV1 is
IVaultStorage,
IConfigurableVaultV1,
IGroomableVaultV1,
ILiquidatableVaultV1,
ISnapshotableVaultV1
{
event Deposit(address indexed depositor, address indexed onBehalfOf, uint256 amount);
event Borrow(address indexed borrower, address indexed onBehalfOf, uint256 amount);
event Withdraw(
address indexed withdrawer,
address indexed recipient,
uint256 amount,
uint256 fee,
uint256 lenderFee
);
event Repay(address indexed repayer, address indexed onBehalfOf, uint256 amount);
event RepayBadDebt(address indexed repayer, address indexed onBehalfOf, uint256 amount);
// Vault Core V1 Errors
error VC_V1_USER_HAS_SUPPLY();
error VC_V1_NOT_ENOUGH_SUPPLY();
error VC_V1_INVALID_REPAY_AMOUNT();
error VC_V1_INVALID_BORROW_AMOUNT();
error VC_V1_INVALID_DEPOSIT_AMOUNT();
error VC_V1_INVALID_WITHDRAW_AMOUNT();
error VC_V1_ETH_INSUFFICIENT_AMOUNT();
error VC_V1_FARM_WITHDRAW_INSUFFICIENT();
error VC_V1_NOT_ALLOWED_TO_ACT_ON_BEHALF();
error VC_V1_NOT_AUTHORIZED_TO_DEAL_WITH_TRANSFERS();
error VC_V1_UNHEALTHY_VAULT_RISK();
error VC_V1_NO_DEBT_TO_REPAY();
function preTransfer(address from, address to, uint256 amount, bytes4 transferSelector) external;
function postTransfer(address from, address to) external;
function deposit(uint256 amount, address onBehalfOf) external payable;
function borrow(uint256 amount) external;
function borrowOnBehalfOf(uint256 amount, address onBehalfOf, uint256 deadline, bytes calldata signature) external;
function withdraw(uint256 amount, address to) external returns (uint256);
function repay(uint256 amount, address onBehalfOf) external returns (uint256);
function repayBadDebt(uint256 amount, address onBehalfOf) external returns (uint256);
function depositAndBorrow(uint256 depositAmount, uint256 borrowAmount) external payable;
function repayAndWithdraw(
uint256 repayAmount,
uint256 withdrawAmount,
address to
) external returns (uint256, uint256);
function calcWithdrawFee(address account, uint256 withdrawAmount) external view returns (uint256, uint256);
}
"
},
"altitude-v2/contracts/interfaces/internal/strategy/farming/IFarmDispatcher.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
interface IFarmDispatcher is IAccessControl {
struct Strategy {
bool active;
uint256 maxAmount;
uint256 totalDeposit;
address prev;
address next;
}
event Disable(uint256 amount);
event Enable(uint256 amount);
event Withdraw(uint256 amount);
event WithdrawAll(uint256 amount);
event SetStrategyMax(address strategyAddress, uint256 max);
event SetStrategyPiority(address strategy, address strategyPosition);
event Dispatch(uint256 amount);
event StrategyError(address strategy, bytes lowLevelData);
event DeactivateStrategy(address strategyAddress, bool toWithdraw);
event AddStrategy(address strategyAddress, uint256 max, address position);
event RecogniseRewards(uint256 allRewards, uint256 failedStrategies);
error FD_ONLY_VAULT();
error FD_VAULT_OR_OWNER();
error FD_STRATEGY_EXISTS();
error FD_ZERO_ASSET();
error FS_EMPTY_STRATEGIES();
error FS_STRATEGIES_MISMATCH();
error FD_ZERO_STRATEGY_REMOVAL();
error FD_STRATEGY_PRIORITY_THE_SAME();
error FD_INACTIVE_STRATEGY();
error FD_INACTIVE_STRATEGY_POSITION();
error FD_INVALID_STRATEGY_DISPATCHER();
function vault() external view returns (address);
function asset() external view returns (address);
function STRATEGY_ZERO() external view returns (address);
function strategies(address) external view returns (bool, uint256, uint256, address, address);
function initialize(address vaultAddress, address workingAsset, address owner) external;
function setStrategyPriority(address strategyAddress, address strategyPosition) external;
function setStrategyMax(address strategyAddress, uint256 max) external;
function addStrategy(address strategyAddress, uint256 max, address position) external;
function addStrategies(address[] calldata strategies, uint256[] calldata max, address position) external;
function deactivateStrategy(address strategyAddress, bool toWithdraw) external;
function dispatch() external;
function withdraw(uint256 amountRequested) external returns (uint256 amountWithdrawn);
function balance() external view returns (uint256 totalBalance);
function balanceAvailable() external view returns (uint256 totalBalance, uint256 failedStrategies);
function getNextStrategy(address strategy) external view returns (address);
function recogniseRewards() external returns (uint256 allRewards, uint256 failedStrategies);
function availableLimit() external view returns (uint256 amount);
}
"
},
"altitude-v2/contracts/interfaces/internal/strategy/swap/ISwapStrategyConfiguration.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import "./ISwapStrategy.sol";
interface ISwapStrategyConfiguration {
error SSC_SWAP_AMOUNT(uint256 actualAmount, uint256 expectedAmount);
event UpdateSwapStrategy(address newSwapStrategy);
function swapStrategy() external view returns (ISwapStrategy);
function setSwapStrategy(address newSwapStrategy) external;
}
"
},
"altitude-v2/node_modules/@openzeppelin/contracts/access/IAccessControl.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}
"
},
"altitude-v2/contracts/interfaces/internal/vault/IVaultStorage.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0.
pragma solidity 0.8.28;
import "../tokens/ISupplyToken.sol";
import "../tokens/IDebtToken.sol";
import "../misc/IBorrowVerifier.sol";
/**
* @author Altitude Protocol
**/
interface IVaultStorage {
// Vault Storage V1 Errors
error VS_V1_ONLY_OWNER();
function owner() external view returns (address);
function supplyToken() external view returns (ISupplyToken);
function debtToken() external view returns (IDebtToken);
function supplyUnderlying() external view returns (address);
function borrowUnderlying() external view returns (address);
function borrowVerifier() external view returns (IBorrowVerifier);
function userLastDepositBlock(address) external view returns (uint256);
function withdrawFeeFactor() external view returns (uint256);
function withdrawFeePeriod() external view returns (uint256);
function supplyThreshold() external view returns (uint256);
function liquidationThreshold() external view returns (uint256);
function targetThreshold() external view returns (uint256);
function activeFarmStrategy() external view returns (address);
function activeLenderStrategy() external view returns (address);
function allowOnBehalfList(address, address) external view returns (bool);
function onBehalfFunctions(bytes4) external view returns (bool);
function snapshots(uint256) external view returns (uint256, uint256, uint256, uint256);
function userSnapshots(address) external view returns (uint256);
function configurableManager() external view returns (address);
function swapStrategy() external view returns (address);
function ingressControl() external view returns (address);
}
"
},
"altitude-v2/contracts/interfaces/internal/vault/extensions/groomable/IGroomableVault.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0.
pragma solidity 0.8.28;
import "../../../../../libraries/types/VaultTypes.sol";
import "./IGroomableManager.sol";
/**
* @author Altitude Protocol
**/
interface IGroomableVaultV1 is IGroomableManager {
// Groomable Vault Errors
error GR_V1_MIGRATION_PERCENTAGE_OUT_OF_RANGE();
function migrateLender(address newStrategy) external;
function migrateFarmDispatcher(address newFarmDispatcher) external;
function rebalance() external;
function setGroomableConfig(VaultTypes.GroomableConfig memory) external;
function getGroomableConfig() external view returns (address, address, uint256);
}
"
},
"altitude-v2/contracts/interfaces/internal/vault/extensions/snapshotable/ISnapshotableVault.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0.
pragma solidity 0.8.28;
import "./ISnapshotableManager.sol";
import "../harvestable/IHarvestableVault.sol";
import "../supply-loss/ISupplyLossVault.sol";
import "../../../../../libraries/types/VaultTypes.sol";
/**
* @author Altitude Protocol
**/
interface ISnapshotableVaultV1 is ISnapshotableManager, IHarvestableVaultV1, ISupplyLossVaultV1 {
function setSnapshotableConfig(VaultTypes.SnapshotableConfig memory config) external;
function getSnapshotableConfig() external view returns (address, uint256);
function calcCommitUser(
address account,
uint256 snapshotId
) external view returns (HarvestTypes.UserCommit memory commit);
function totalSnapshots() external view returns (uint256);
function getSnapshot(uint256 id) external view returns (CommonTypes.SnapshotType memory);
}
"
},
"altitude-v2/contracts/interfaces/internal/vault/extensions/liquidatable/ILiquidatableVault.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0.
pragma solidity 0.8.28;
import "./ILiquidatableManager.sol";
import "../../../../../libraries/types/VaultTypes.sol";
/**
* @author Altitude Protocol
**/
interface ILiquidatableVaultV1 is ILiquidatableManager {
function isUserForLiquidation(address us
Submitted on: 2025-10-14 14:22:46
Comments
Log in to comment.
No comments yet.