Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
397 changes: 397 additions & 0 deletions src/interfaces/dependencies/vault/IDelegationManager.sol

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions src/interfaces/dependencies/vault/ILendingPool.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import {DataTypes} from '../../../dependencies/vault/DataTypes.sol';

interface ILendingPool {
/**
* @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
Expand Down Expand Up @@ -29,4 +31,12 @@ interface ILendingPool {
*
*/
function withdraw(address asset, uint256 amount, address to) external returns (uint256);

/**
* @notice Returns the state and configuration of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The state and configuration data of the reserve
*/
function getReserveData(address asset) external view returns (DataTypes.ReserveData memory);

}
162 changes: 162 additions & 0 deletions src/interfaces/dependencies/vault/ISlasher.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
// SPDX-License-Identifier: LGPL-3.0
pragma solidity ^0.8.19;

import './IStrategyManager.sol';

/**
* @title Interface for the primary 'slashing' contract for Pell.
* @notice See the `Slasher` contract itself for implementation details.
*/
interface ISlasher {
// struct used to store information about the current state of an operator's obligations to middlewares they are serving
struct MiddlewareTimes {
// The update timestamp for the middleware whose most recent update was earliest, i.e. the 'stalest' update out of all middlewares the operator is serving
uint32 stalestUpdateTimestamp;
// The latest 'serveUntilTimestamp' from all of the middleware that the operator is serving
uint32 latestServeUntilTimestamp;
}

// struct used to store details relevant to a single middleware that an operator has opted-in to serving
struct MiddlewareDetails {
// the timestamp at which the contract begins being able to finalize the operator's registration with the service via calling `recordFirstStakeUpdate`
uint32 registrationMayBeginAtTimestamp;
// the timestamp before which the contract is allowed to slash the user
uint32 contractCanSlashOperatorUntilTimestamp;
// the timestamp at which the middleware's view of the operator's stake was most recently updated
uint32 latestUpdateTimestamp;
}

/// @notice Emitted when a middleware times is added to `operator`'s array.
event MiddlewareTimesAdded(address operator, uint256 index, uint32 stalestUpdateTimestamp, uint32 latestServeUntilTimestamp);

/// @notice Emitted when `operator` begins to allow `contractAddress` to slash them.
event OptedIntoSlashing(address indexed operator, address indexed contractAddress);

/// @notice Emitted when `contractAddress` signals that it will no longer be able to slash `operator` after the `contractCanSlashOperatorUntilTimestamp`.
event SlashingAbilityRevoked(address indexed operator, address indexed contractAddress, uint32 contractCanSlashOperatorUntilTimestamp);

/**
* @notice Emitted when `slashingContract` 'freezes' the `slashedOperator`.
* @dev The `slashingContract` must have permission to slash the `slashedOperator`, i.e. `canSlash(slasherOperator, slashingContract)` must return 'true'.
*/
event OperatorFrozen(address indexed slashedOperator, address indexed slashingContract);

/// @notice Emitted when `previouslySlashedAddress` is 'unfrozen', allowing them to again move deposited funds within Pell.
event FrozenStatusReset(address indexed previouslySlashedAddress);

/**
* @notice Gives the `contractAddress` permission to slash the funds of the caller.
* @dev Typically, this function must be called prior to registering for a middleware.
*/
function optIntoSlashing(address contractAddress) external;

/**
* @notice Used for 'slashing' a certain operator.
* @param toBeFrozen The operator to be frozen.
* @dev Technically the operator is 'frozen' (hence the name of this function), and then subject to slashing pending a decision by a human-in-the-loop.
* @dev The operator must have previously given the caller (which should be a contract) the ability to slash them, through a call to `optIntoSlashing`.
*/
function freezeOperator(address toBeFrozen) external;

/**
* @notice Removes the 'frozen' status from each of the `frozenAddresses`
* @dev Callable only by the contract owner (i.e. governance).
*/
function resetFrozenStatus(address[] calldata frozenAddresses) external;

/**
* @notice this function is a called by middlewares during an operator's registration to make sure the operator's stake at registration
* is slashable until serveUntil
* @param operator the operator whose stake update is being recorded
* @param serveUntilTimestamp the timestamp until which the operator's stake at the current timestamp is slashable
* @dev adds the middleware's slashing contract to the operator's linked list
*/
function recordFirstStakeUpdate(address operator, uint32 serveUntilTimestamp) external;

/**
* @notice this function is a called by middlewares during a stake update for an operator (perhaps to free pending withdrawals)
* to make sure the operator's stake at updateTimestamp is slashable until serveUntil
* @param operator the operator whose stake update is being recorded
* @param updateTimestamp the timestamp for which the stake update is being recorded
* @param serveUntilTimestamp the timestamp until which the operator's stake at updateTimestamp is slashable
* @param insertAfter the element of the operators linked list that the currently updating middleware should be inserted after
* @dev insertAfter should be calculated offchain before making the transaction that calls this. this is subject to race conditions,
* but it is anticipated to be rare and not detrimental.
*/
function recordStakeUpdate(address operator, uint32 updateTimestamp, uint32 serveUntilTimestamp, uint256 insertAfter) external;

/**
* @notice this function is a called by middlewares during an operator's deregistration to make sure the operator's stake at deregistration
* is slashable until serveUntil
* @param operator the operator whose stake update is being recorded
* @param serveUntilTimestamp the timestamp until which the operator's stake at the current timestamp is slashable
* @dev removes the middleware's slashing contract to the operator's linked list and revokes the middleware's (i.e. caller's) ability to
* slash `operator` once `serveUntil` is reached
*/
function recordLastStakeUpdateAndRevokeSlashingAbility(address operator, uint32 serveUntilTimestamp) external;

/// @notice The StrategyManager contract of Pell
function strategyManager() external view returns (IStrategyManager);

/**
* @notice Used to determine whether `staker` is actively 'frozen'. If a staker is frozen, then they are potentially subject to
* slashing of their funds, and cannot cannot deposit or withdraw from the strategyManager until the slashing process is completed
* and the staker's status is reset (to 'unfrozen').
* @param staker The staker of interest.
* @return Returns 'true' if `staker` themselves has their status set to frozen, OR if the staker is delegated
* to an operator who has their status set to frozen. Otherwise returns 'false'.
*/
function isFrozen(address staker) external view returns (bool);

/// @notice Returns true if `slashingContract` is currently allowed to slash `toBeSlashed`.
function canSlash(address toBeSlashed, address slashingContract) external view returns (bool);

/// @notice Returns the timestamp until which `serviceContract` is allowed to slash the `operator`.
function contractCanSlashOperatorUntilTimestamp(address operator, address serviceContract) external view returns (uint32);

/// @notice Returns the timestamp at which the `serviceContract` last updated its view of the `operator`'s stake
function latestUpdateTimestamp(address operator, address serviceContract) external view returns (uint32);

/// @notice A search routine for finding the correct input value of `insertAfter` to `recordStakeUpdate` / `_updateMiddlewareList`.
function getCorrectValueForInsertAfter(address operator, uint32 updateTimestamp) external view returns (uint256);

/**
* @notice Returns 'true' if `operator` can currently complete a withdrawal started at the `withdrawalStartTimestamp`, with `middlewareTimesIndex` used
* to specify the index of a `MiddlewareTimes` struct in the operator's list (i.e. an index in `operatorToMiddlewareTimes[operator]`). The specified
* struct is consulted as proof of the `operator`'s ability (or lack thereof) to complete the withdrawal.
* This function will return 'false' if the operator cannot currently complete a withdrawal started at the `withdrawalStartTimestamp`, *or* in the event
* that an incorrect `middlewareTimesIndex` is supplied, even if one or more correct inputs exist.
* @param operator Either the operator who queued the withdrawal themselves, or if the withdrawing party is a staker who delegated to an operator,
* this address is the operator *who the staker was delegated to* at the time of the `withdrawalStartTimestamp`.
* @param withdrawalStartTimestamp The timestamp at which the withdrawal was initiated.
* @param middlewareTimesIndex Indicates an index in `operatorToMiddlewareTimes[operator]` to consult as proof of the `operator`'s ability to withdraw
* @dev The correct `middlewareTimesIndex` input should be computable off-chain.
*/
function canWithdraw(address operator, uint32 withdrawalStartTimestamp, uint256 middlewareTimesIndex) external returns (bool);

/**
* operator =>
* [
* (
* the least recent update timestamp of all of the middlewares it's serving/served,
* latest time that the stake bonded at that update needed to serve until
* )
* ]
*/
function operatorToMiddlewareTimes(address operator, uint256 arrayIndex) external view returns (MiddlewareTimes memory);

/// @notice Getter function for fetching `operatorToMiddlewareTimes[operator].length`
function middlewareTimesLength(address operator) external view returns (uint256);

/// @notice Getter function for fetching `operatorToMiddlewareTimes[operator][index].stalestUpdateTimestamp`.
function getMiddlewareTimesIndexStalestUpdateTimestamp(address operator, uint32 index) external view returns (uint32);

/// @notice Getter function for fetching `operatorToMiddlewareTimes[operator][index].latestServeUntil`.
function getMiddlewareTimesIndexServeUntilTimestamp(address operator, uint32 index) external view returns (uint32);

/// @notice Getter function for fetching `_operatorToWhitelistedContractsByUpdate[operator].size`.
function operatorWhitelistedContractsLinkedListSize(address operator) external view returns (uint256);

/// @notice Getter function for fetching a single node in the operator's linked list (`_operatorToWhitelistedContractsByUpdate[operator]`).
function operatorWhitelistedContractsLinkedListEntry(address operator, address node) external view returns (bool, uint256, uint256);
}
93 changes: 93 additions & 0 deletions src/interfaces/dependencies/vault/IStrategy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// SPDX-License-Identifier: LGPL-3.0
pragma solidity ^0.8.19;

import '@openzeppelin/contracts/token/ERC20/IERC20.sol';

/**
* @title Minimal interface for an `Strategy` contract.
* @notice Custom `Strategy` implementations may expand extensively on this interface.
*/
interface IStrategy {
/**
* @notice Used to deposit tokens into this Strategy
* @param token is the ERC20 token being deposited
* @param amount is the amount of token being deposited
* @dev This function is only callable by the strategyManager contract. It is invoked inside of the strategyManager's
* `depositIntoStrategy` function, and individual share balances are recorded in the strategyManager as well.
* @return newShares is the number of new shares issued at the current exchange ratio.
*/
function deposit(IERC20 token, uint256 amount) external returns (uint256);

/**
* @notice Used to withdraw tokens from this Strategy, to the `recipient`'s address
* @param recipient is the address to receive the withdrawn funds
* @param token is the ERC20 token being transferred out
* @param amountShares is the amount of shares being withdrawn
* @dev This function is only callable by the strategyManager contract. It is invoked inside of the strategyManager's
* other functions, and individual share balances are recorded in the strategyManager as well.
*/
function withdraw(address recipient, IERC20 token, uint256 amountShares) external;

/**
* @notice Used to convert a number of shares to the equivalent amount of underlying tokens for this strategy.
* @notice In contrast to `sharesToUnderlyingView`, this function **may** make state modifications
* @param amountShares is the amount of shares to calculate its conversion into the underlying token
* @return The amount of underlying tokens corresponding to the input `amountShares`
* @dev Implementation for these functions in particular may vary significantly for different strategies
*/
function sharesToUnderlying(uint256 amountShares) external returns (uint256);

/**
* @notice Used to convert an amount of underlying tokens to the equivalent amount of shares in this strategy.
* @notice In contrast to `underlyingToSharesView`, this function **may** make state modifications
* @param amountUnderlying is the amount of `underlyingToken` to calculate its conversion into strategy shares
* @return The amount of underlying tokens corresponding to the input `amountShares`
* @dev Implementation for these functions in particular may vary significantly for different strategies
*/
function underlyingToShares(uint256 amountUnderlying) external returns (uint256);

/**
* @notice convenience function for fetching the current underlying value of all of the `user`'s shares in
* this strategy. In contrast to `userUnderlyingView`, this function **may** make state modifications
*/
function userUnderlying(address user) external returns (uint256);

/**
* @notice convenience function for fetching the current total shares of `user` in this strategy, by
* querying the `strategyManager` contract
*/
function shares(address user) external view returns (uint256);

/**
* @notice Used to convert a number of shares to the equivalent amount of underlying tokens for this strategy.
* @notice In contrast to `sharesToUnderlying`, this function guarantees no state modifications
* @param amountShares is the amount of shares to calculate its conversion into the underlying token
* @return The amount of shares corresponding to the input `amountUnderlying`
* @dev Implementation for these functions in particular may vary significantly for different strategies
*/
function sharesToUnderlyingView(uint256 amountShares) external view returns (uint256);

/**
* @notice Used to convert an amount of underlying tokens to the equivalent amount of shares in this strategy.
* @notice In contrast to `underlyingToShares`, this function guarantees no state modifications
* @param amountUnderlying is the amount of `underlyingToken` to calculate its conversion into strategy shares
* @return The amount of shares corresponding to the input `amountUnderlying`
* @dev Implementation for these functions in particular may vary significantly for different strategies
*/
function underlyingToSharesView(uint256 amountUnderlying) external view returns (uint256);

/**
* @notice convenience function for fetching the current underlying value of all of the `user`'s shares in
* this strategy. In contrast to `userUnderlying`, this function guarantees no state modifications
*/
function userUnderlyingView(address user) external view returns (uint256);

/// @notice The underlying token for shares in this Strategy
function underlyingToken() external view returns (IERC20);

/// @notice The total number of extant shares in this Strategy
function totalShares() external view returns (uint256);

/// @notice Returns either a brief string explaining the strategy's goal & purpose, or a link to metadata that explains in more detail.
function explanation() external view returns (string memory);
}
Loading