Blocks
Block Architecture
A "block" is a standardized smart contract that performs a specific action on a DeFi protocol. Each block must implement the functions of the following interface:
interface IStrategCommonBlock {
/// @notice The IPFS hash of the block metadata file
function ipfsHash() external view returns (string memory);
/// @notice Return dynamic parameters needed for the block execution
/// @param _exec The type of block execution
/// @param _parameters The parameters of the block execution
/// @param _oracleState The state of the oracle
/// @param _percent The percentage of the block execution
/// @return dynParamsNeeded Whether the strategy block execution needs dynamic parameters
/// @return dynParamsType The type of dynamic parameters needed
/// @return dynParamsInfo The information of the dynamic parameters needed
function dynamicParamsInfo(
DataTypes.BlockExecutionType _exec,
bytes memory _parameters,
DataTypes.OracleState memory _oracleState,
uint256 _percent
) external view returns (bool, DataTypes.DynamicParamsType, bytes memory);
}
ipfsHash
returns an IPFS hash of a JSON file containing its metadata(s).dynamicParamsInfo
function indicates if the block needs dynamic parameters during execution. Dynamic parameters are offchain parameters, computed by operators during vault operations._exec
represents the execution context (ENTER, EXIT or HARVEST)._parameters
is a byte containing block parameters._oracleState
contains the list of assets available during execution._percent
is the percentage in basis points in the exit context (withdraw). In other contexts, it is always equal to 100%.
Block Metadata(s)
The underlying file must be a JSON file containing block metadata. For example, the deposit on Aave V3 contains the following metadata.
{
"id":"AAVE_V3_DEPOSIT",
"type":"block",
"gitUrl":"https://github.com/StrategProtocol/strateg-protocol-block-aave-v3",
"resolver":"QmP9yBZwnRcpEh1dqyFDkkha3dGXPgcgaYgjVfvGJzNKT4",
"name":"Aave V3 Deposit Strateg. Block",
"description":"Block to deposit a token on Aave V3",
"action":"Deposit",
"protocolId":"AAVE_V3",
"protocolName":"Aave v3",
"paramsTuple":"tuple(uint256 tokenInPercent, address token)",
"params":[
{
"attribute":"tokenInPercent",
"name":"Amount",
"type":"percent",
"underlyingType":"uint256"
},
{
"attribute":"token",
"name":"Deposit",
"type":"ERC20",
"underlyingType":"address",
"resolved":"true"
}
]
}
id: It corresponds to the unique block identifier for a single chain. It must be composed of the protocol identifier followed by the action in uppercase Camel.
type: There are three possible values for this attribute:
block: Define the block as a strategy block. The block contract must be compliant with the StrategStrategyBlock interface.
harvest-block: Define the block as a harvest block. The block contract must be compliant with the StrategHarvestBlock interface.
position-manager: Define the block as a position manager, which an extension of the StrategStrategyBlock interface. For this type of block, a remote contract from the borrow module must be deployed during the vault deployment process.
gitUrl: The link to the public git repository containing smart contracts code.
resolver: IPFS hash containing a typescript file executed as a lambda that returns all available configurations of the block.
name: Human readable block name.
description: Human readable description explaining block action(s).
action: Human readable short action description (1 or 2 words).
protocolId: Protocol identifier uppercase and camelcase.
protocolName: Human readable protocol name.
paramsTuple: Tuple of parameters taken by the block when the strategy is defined.
params: List of object describing block's parameters for frontend rendering.
Block Types
There are two different types of blocks.
Strategy Block
Strategy blocks are primarily responsible for managing the vault strategy execution. This includes entering and exiting positions. They must implement the following interface functions.
interface IStrategStrategyBlock is IStrategCommonBlock {
/// @notice Execute hook block function
/// @param _index The index of the block
/// @param _executionType execution type: Enter for deposit and Exit for withdraw
function hook(uint256 _index, DataTypes.BlockExecutionType _executionType) external;
/// @notice Execute enter block function
/// @param _index The index of the block
function enter(uint256 _index) external;
/// @notice Execute exit block function
/// @param _index The index of the block
/// @param _percent The percentage of the assets used for the exit execution
function exit(uint256 _index, uint256 _percent) external;
/// @notice Execute the oracle enter function
/// @param previous The previous state of the oracle
/// @param parameters The parameters of the oracle enter
/// @return The new state of the oracle
function oracleEnter(DataTypes.OracleState memory previous, bytes memory parameters)
external
view
returns (DataTypes.OracleState memory);
/// @notice Execute the oracle exit function
/// @param previous The previous state of the oracle
/// @param parameters The parameters of the oracle exit
/// @param _percent The percentage of the assets used for the exit execution
/// @return The new state of the oracle
function oracleExit(DataTypes.OracleState memory previous, bytes memory parameters, uint256 _percent)
external
view
returns (DataTypes.OracleState memory);
}
hook
function is executed during a deposit or withdraw action on the vault before the internal TVL computation. It is useful to update the remote protocol state beforehand, to avoid TVL computation based on obsolete data._index
number is given to the function, enabling the block to retrieve its parameters using a storage pointer pointing to a byte variable._executionType
determines the execution context in the strategy.
enter
function is called by the vault via a delegate call, which is executed within the vault context. The function must execute the action for which the block is written for._index
number is given to the function, enabling the block to retrieve its parameters using a storage pointer pointing to a byte variable.
exit
function is called by the vault via a delegate call, which is executed within the vault context. The function must execute the opposit action of what theenter
function is written for._index
number is given to the function, enabling the block to retrieve its parameters using a storage pointer pointing to a byte variable._percent
is the percentage of assets used, in basis points.
enterOracle
function is called by the vault to simulate theenter
function.OracleState
is used by the function, with simulated tokens amounts at block execution time. The goal is to have the same parameters as the execution function.parameters
bytes are the same as those received by the corresponding execution function.
exitOracle
function is called by the vault to simulate theexit
function.OracleState
is used by the function, with simulated tokens amounts at block execution time. The goal is to have the same parameters as the execution function.parameters
bytes are the same as those received by the corresponding execution function._percent
is the percentage of assets used, in basis points.
Harvest Block
Harvest block is based on the same concept as the strategy block, where the harvest block list is executed on vault harvest.
interface IStrategStrategyBlock is IStrategCommonBlock {
/// @notice Execute harvest block function
/// @param _index The index of the block
function harvest(uint256 _index) external;
/// @notice Execute the oracle harvest function
/// @param previous The previous state of the oracle
/// @param parameters The parameters of the oracle enter
/// @return The new state of the oracle
function oracleHarvest(DataTypes.OracleState memory previous, bytes memory parameters)
external
returns (DataTypes.OracleState memory);
}
harvest
executes the harvest block function._index
number is given to the function, enabling the block to retrieve its parameters using a storage pointer pointing to a byte variable.
oracleHarvest
is a non view function to be usable with Curve like claims on which there is a need to update a local variable.OracleState
is used by the function, with simulated tokens amounts at block execution time. The goal is to have the same parameters as the execution function.parameters
bytes are the same as those received by the corresponding execution function.
Last updated