Investments Manager

Contract NameGithubDeployed Contract AddressContract ImplementedInitialization Data

InvestmentsManager

Coming soon

Coming soon

IInvestmentsManager, LazyInitCapableElement

_organizationComponentKey, executorRewardPercentage, prestoAddress, tokenFromETHToBurn, _tokensFromETH, firstSwapToETHBlock, _swapToETHInterval, _tokensToETH, _tokensToETHPercentages and LazyInitCapableElement init data

The Investments Manager is an active component that can be linked to an organization (of the root or governance layer), allowing it to execute investment transactions that consist of the purchase and subsequent resale of tokens.

These investment operations can involve:

  • The sale of ETH for tokens

  • The sale of tokens for ETH

  • The sale of ETH for tokens, which are immediately burned

The Investments Manager receives ETH (it can receive ETH from the Treasury Splitter for example), executes swap operations by purchasing tokens, and then allows the tokens to be sold, by swapping them for ETH and sending them to a Components such as a Treasury Manager or the Treasury Splitter.

Swap operations ETH-tokens can be performed every time that the Investments Manager as an ETH balance greater than zero. Swap operations tokens-ETH can only be performed at fixed, preset intervals.

The Investments Manager can be a Component of an Organization at both the root and the governance layers. It can be used by holders of an organization's governance tokens to decide what the organization should invest in.

Investments Manager Initialization

The Investments Manager is a LazyInitCapableElement, and must be initialized following the pattern explained here, passing the following parameters:

function _lazyInit(bytes memory lazyInitData) internal override virtual returns (bytes memory lazyInitResponse) {
    (_organizationComponentKey, executorRewardPercentage, prestoAddress, lazyInitData, lazyInitResponse) = abi.decode(lazyInitData, (bytes32, uint256, address, bytes, bytes));
    _initFromETH(lazyInitData);
    _initToETH(lazyInitResponse);
    lazyInitResponse = "";
}

function _initFromETH(bytes memory fromETHData) private {
    (tokenFromETHToBurn, _tokensFromETH) = abi.decode(fromETHData, (address, address[]));
}

function _initToETH(bytes memory toETHData) private {
    uint256 firstSwapToETHBlock;
    uint256 _swapToETHInterval;
    (firstSwapToETHBlock, _swapToETHInterval, _tokensToETH, _tokensToETHPercentages) = abi.decode(toETHData, (uint256, uint256, address[], uint256[]));
    swapToETHInterval = _swapToETHInterval;
    if(firstSwapToETHBlock != 0 && _swapToETHInterval < firstSwapToETHBlock) {
        lastSwapToETHBlock = firstSwapToETHBlock - _swapToETHInterval;
    }
}
  • bytes32 _organizationComponentKey -> this represents the key of the component to which ETH acquired through the sale of other tokens will be sent (to learn more, see the organizationComponentKey section below).

  • uint256 executorRewardPercentage -> this represents the percentage that the caller--AKA the msg.sender--of the swapFromETH / swapToETH functions of the Investment Manager receives as a reward for calling the TreasurySplit function.

  • address PrestoAddress -> this is the address of the Presto contract [insert here]

  • bytes lazyInitResponse -> this must contain the encoded parameters explained below.

  • bytes toETHData -> this must contain the encoded parameters explained below.

The lazyInitResponse parameter must be populated as follows:

  • address tokenFromETHToBurn -> this represents the (optional) address to which the tokens will be burned after ETH has been swapped for them.

  • address[] _tokensFromETH -> this represents the addresses of the tokens for which ETH will be swapped.

The toETHData parameter must be populated as follows:

  • uint256 firstSwapFromETHBlock -> this is the first block from which swapToETH can be called.

  • uint256 _swapFromETHInhis terval -> this is the block-based interval that must pass between each execution of swapToETH.

  • address[] _tokensToETH -> this represents the addresses of the tokens that will be sold for ETH.

  • uint256[] _tokensToETHPercentages -> this represents, for each token in the _tokensToETH array, the percentage of its balance in the Treasury Manager to sell.

OrganizationComponentKey

The _organizationComponentKey parameter, which is set during initialization of the Investments Manager contract, define the address that will receive the ETH swapped out for ERC20s using the swapToETH function.

If no receivers have been set up (in the _keys parameter during initialization of the TreasurySplitter) to receive the ETH, the entire amount is automatically sent to the Treasury Manager of the Organization to which the InvestmentsManager is attached as a Component.

Investment Swap Operations

From ETH to Tokens

The swapFromETH function is used to sell ETH for ERC20 tokens:

function swapFromETH(PrestoOperation[] calldata tokensFromETHData, PrestoOperation calldata tokenFromETHToBurnData, address executorRewardReceiver) external returns (uint256[] memory tokenAmounts, uint256 tokenFromETHToBurnAmount, uint256 executorReward);

Its inputs are:

  • PrestoOperation[] tokensFromETHData ->this should be passed as empty; the PrestoOperation[] struct(s) is automatically populated by the swapFromETH function.

  • PrestoOPeration tokenFromEHToBurndata -> this should be passed as empty; the PrestoOperation struct is automatically populated by the swapFromETH function.

  • address executorRewardReceiver -> this is the receiver address for the executorReward.

The function is only called if the Investments Manager ETH balance is >0.

Anyone can call it, and whoever does receives a reward that acts as an economic incentive. The executorReward amount is calculated as (the amount to swap * executorReward percentage).

For each token set in _tokensFromETH a swap is performed. For example, if _tokensFromETH consists of $OS, one swap is performed; if it consists of $OS and $UNI, two swaps are performed; and so on.

The amount of ETH to swap is the ETH balance of the Investments Manager is linked. The amount is split among the various operations it has to do. If, for example, it has to swap only ETH for $OS (_tokensFromETH consists of $OS), then the entire balance is spent for that operation; if it must swap ETH for $OS and $UNI (_tokensFromETH consists of $OS and $UNI), the balance is divided by two; and so on.

The function interacts with Presto to perform the swap operations.

From ETH to Tokens and Burn

If tokenToBurn is set in the Investments Manager, a swap-and-burn operation is performed on the purchaesd token. The amount of ETH set aside for the operation is used to buy the token, which is then automatically burned.

From ETH to Tokens and Burn

The swapToETH function is used to sell ERC20 tokens for ETH:

function swapToETH(PrestoOperation[] calldata tokensToETHData, address executorRewardReceiver) external override returns (uint256[] memory executorRewards, uint256[] memory ethAmounts) {

Its inputs are:

  • PrestoOperation[] tokensToETHData -> this should be passed as empty; the PrestoOperation[] struct(s) is automatically populated by the swapToETH function.

  • address executorRewardReceiver -> this is the receiver address for the executorReward.

The function is only called if the _swapToETHInterval is has passed.

Anyone can call it, and whoever does receives a reward that acts as an economic incentive. The executorReward amount is calculated as (the amount to swap * executorReward percentage).

For each token set in _tokensToETH a swap is performed. For example, if _tokensToETH consists of $OS, one swap is performed; if it consists of $OS and $UNI, two swaps are performed; and so on.

The ETH amount gained is sent to the set receiver (_organizationComponentKey).

Last updated