lido
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Write
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
      • Invitee
    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Sharing URL Help
Menu
Options
Versions and GitHub Sync Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Write
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
Invitee
Publish Note

Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

Your note will be visible on your profile and discoverable by anyone.
Your note is now live.
This note is visible on your profile and discoverable online.
Everyone on the web can find and read all notes of this public team.
See published notes
Unpublish note
Please check the box to agree to the Community Guidelines.
View profile
Engagement control
Commenting
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
  • Everyone
Suggest edit
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
Emoji Reply
Enable
Import from Dropbox Google Drive Gist Clipboard
   owned this note    owned this note      
Published Linked with GitHub
Subscribed
  • Any changes
    Be notified of any changes
  • Mention me
    Be notified of mention me
  • Unsubscribe
Subscribe
--- tags: spec, treasury, swap, stonks, dao-ops --- # Lido Stonks. Specification ## Problem statement Lido DAO faces a major challenge in optimizing treasury operations, especially in the areas of token usage, market adaptation and crisis response, as exemplified by cases such as the depeg of DAI and USDC. To solve this problem, it is necessary to create a specialized [treasury management committee](https://research.lido.fi/t/proposal-to-approve-lido-dao-treasury-management-principles-and-authorize-the-formation-of-a-treasury-management-committee/4279) (TMC) and provide it with a technical solution that should ensure efficient and secure management of assets by the committee, while limiting direct access to funds. ### General requirements * proposed solution should be able to be used by both TMC and Lido DAO; * funds should only be available for a limited set of transactions, pre-approved by Lido DAO; * proposed solution should have limited access to the Lido DAO treasury. ### Technical requirements * every trade should be MEV-protected; * every trade should be "price-guaranteed" (the trade is expected to be canceled if the minimum exchange amount is not received); * beneficiary of every trade should be Lido DAO (treasury); * variety of tokens for trade (both input and output) should be strictly limited by DAO; * TMC should has the ability to operate trades (move funds from treasury, place orders, move funds back to treasury in case of unsuccessful trade); * TMC should never take custody of Aragon funds ([post on the research forum](https://research.lido.fi/t/proposal-to-approve-lido-dao-treasury-management-principles-and-authorize-the-formation-of-a-treasury-management-committee/4279)). ### Primary use-cases * selling stETHs to stables (DAI/USDC/USDT) * rebalancing the amounts of different stables (DAI/USDC/USDT) ## Proposed solution Since there are already two ways to transfer funds from the treasury, it is proposed to develop a new technical solution `Stonks`, which will contain a fixed set of necessary operations for exchanging funds and managing the treasury. ### Components 1. [Easy Track](https://github.com/lidofinance/easy-track) (`TopUpAllowedRecipient` factory) or Aragon vote (in case of emergency) for token transfering. These contracts will be used as is. 2. [Stonks](https://github.com/lidofinance/stonks) - set of contracts is receiver of tokens from the first step and container of swap operations set by Lido DAO; 3. [Cow Protocol](https://cow.fi) - a fully permissionless trading protocol that enables batch auctions to maximize liquidity via Coincidence of Wants (CoWs) in addition to tapping all available on-chain liquidity; 4. [ChainLink](https://chain.link) - a decentralized oracle network that provides the USD price of Ethereum’s native cryptocurrency and tokens. There are two directions of tokens movement between components: 1. Swap (happy path) - when tokens are transferred from the DAO Treasury to Stonks for swapping using CoW Protocol. Swap proceeds are sent directly to the DAO Treasury (CoW Protocol API allows it). 2. Recovery (contingency) - if the swap doesn’t execute for any reason, tokens must be returned to the DAO Treasury. ### Happy path ![image](https://hackmd.io/_uploads/SkfavhEhT.png) **Step 0.** DAO Treasury committee creates (in a permissionless way) a new `Stonks` instance with specific params and proposes DAO to add that contract to the EasyTrack allowed recipients. **Step 1.** Tokens are transfered from the DAO Treasury to the `Stonks` instance via Easy Track limited factories or Aragon vote via regular ERC-20 `transfer`. **Step 2. Order placement.** Manager (TMC multisig) makes `Stonks` to deploy of a new `Order` contract via `placeOrder` function and it automatically sends all available assets there. After deploy `Order` creates allowance to the CoW vault relater contract and waits until this order is completed. **Step 3. Order creation.** Easy Track UI checks events and allows manager to create offchain order on Cow Protocol. This UI is trustless and can be used by anyone. **Step 4. The Swap.** At the moment of order fulfilment CoW Protocol debits funds from `Order` contract & sends all exchanged assets to the DAO Treasury. ## Recovery (contingency) flow ![image](https://hackmd.io/_uploads/SJLg_h43T.png) If for any reason swap isn't going through, there must be method to recover the tokens. Tokens can be at `Stonks` (before the swap is requested) or at `Order` (once the swap is requested on `Stonks`). **Step 4.** The swap hasn't happened and order is expired. Anyone can permissionlessly return all funds to the `Stonks` contract for further actions. From this moment `Order` contract becomes inactive. **Step 5.** At the moment in case of market turbulency manager (or DAO) can decide what to do next: * send all funds to the DAO Treasury back; * create a new order again. ## Design ### Assumptions and limitations Trades are conducted in the model `sell X -> buy S`, where: - S is a USD/ETH/EUR-pegged coin. - X is a token that is permitted to be transferred from the Treasury. Adjustments for permissions may be required in accordance with [LIP-13](https://github.com/lidofinance/lido-improvement-proposals/blob/develop/LIPS/lip-13.md), and new factories for limited payments might need to be deployed as per [LIP-19](https://github.com/lidofinance/lido-improvement-proposals/blob/develop/LIPS/lip-19.md). - X has an established price feed in the Chainlink registry for USD/ETH/EUR. The following cases are not covered on the current implementation: - `sell S -> buy LDO` (LDO isn't pegged to ETH/USD/EUR). These clarifications help to better understand the limitations and capabilities of the proposed system, providing clarity on the types of transactions that are supported within the current design. ### General diagram ![image](https://hackmd.io/_uploads/r1ASBaEnT.png) ### Factory deployment approach It was decided that deploying contracts from a contract factory is a more convenient solution, which makes it possible to flexibly set instance parameters, while being sure that the bytecode of the contracts is completely the same. Given the need to set certain parameters for all contract instances, it is very convenient to use immutable variables in the factory contract: this way we guarantee that when deploying a new contract, critical parameters (for example, the treasury address) cannot be changed. All other parameters are set during instance deployment, which makes it possible to create multiple instances in a flexible way. As a result, there are two factory contracts: #### AmountConverterFactory Stores an immutable variables: - [`feedRegistry`](https://docs.chain.link/data-feeds/feed-registry) address When deploying a new instance, you need to set converter parameters: - `conversionTarget` ([explanation](#Price-checking)) - `allowedTokensToSell` - `allowedTokensToBuy` - `priceFeedsHeartbeatTimeouts` **Note**: Lido DAO should accept the token list. This should happen at the moment when the recipient of tokens in EasyTrack `TopUpAllowedRecipients` factory is set to a specific instance of Stonks which works with specific `AmountConverter` instance. #### StonksFactory During factory deployment, a sample order is created, which will then be used to create a minimal proxy in Stonks. Stores an immutable variables: - `agent` - `orderSample` When deploying a new instance, you need to set [trade parameters](#Trade-parameters). ### Setting up trade parameters In order to set the parameters of upcoming swaps, it is necessary to deploy new instance of the `Stonks` contract. After deploying an instance, all parameters are fixed and only the number of tokens for sale can change (depending on the balance on the instance). **Note**: `Stonks` instance supports the only swap direction (for example `stETH` -> `DAI`) and immutable set of trade paramters. To use any other swap direction it is neccessary to deploy new `Stonks` instance with required parameters. #### Trade parameters: - `manager` - `tokenFrom` - `tokenTo` - `amountConverter` - `orderDurationInSeconds` - `marginInBasisPoints` - `priceToleranceInBasisPoints` **Note**: Every `Stonks` requires to be added as a recipient of `TopUpAllowedRecipient` EasyTrack factory so in this case TMC can operate funds from Lido DAO treasury. `Stonks` also can be filled up with any amount token from any user. In this case TMC could recover this tokens to Lido DAO treasury or proceed the trade. ### Order placement Each time a new order is going to be placed, the Stonks contract initiates the creation of a new `Order` contract instance. This is achieved through making a minimal proxy of the master template of the `Order` contract. The cloning process, powered by the OpenZeppelin Clones library, is a gas-efficient way to create a new contract instance for each trade. These clones are intended for single-use, ensuring that every transaction is processed with a new contract instance. This isolation is critical for maintaining the integrity of each trade, preventing any potential interference or overlap between different swaps. It also enhances the security of the system by ensuring that each contract instance handles only its designated trade. During the order placement, the required amount (all tokens on balance) of the `tokenFrom` is transferred from the `Stonks` contract to the newly created `Order` contract. This step is crucial as it earmarks the funds for the specific trade, effectively locking them in the `Order` contract until the trade is executed or invalidated. After the fund transfer, the new `Order` contract is initialized with specific [trade parameters](#Trade-parameters) received from `Stonks`. This initialization is essential for setting up the trade according to the strategy and market conditions at the time of order placement. As a result `Order` contract sets allowance for CoW vault relayer and creates an event to be picked up for offchain UI/script and sent to the CoW Protocol offchain API ([details](#CoW-Protocol-onchain-order-creation)). ### Price checking To ensure the security of the transaction concerning the amount of tokens to be received as a result of the exchange, it's needed to determine a minimum acceptable amount at the moment of the order creation to ensure that trade is corresponds to market conditions and maximum acceptable amount for order invalidation at the moment of order fullfilment in case market conditions has been changed. ![image](https://hackmd.io/_uploads/SyBVmm8T6.png) It is decided to use ChainLink price feeds against `conversionTarget` [stETH/USD, USDC/USD, USDT/USD, DAI/USD] using a [chainling feed registry](https://docs.chain.link/data-feeds/feed-registry) for our purposes to avoid double convertation and increasing sensivity during token comparing (stETH/USD -> USD/DAI). So at this stage, we consciously decide to refuse transfers to another token and expect that the exchange rate of the token to the `conversionTarget` will always be equal or close to equal. When an order is created, `Order` contract invokes the `estimateTradeOutput` function to determine the expected amount of `tokenTo`, based on the current balance of `tokenFrom`. Once the output amount is obtained, `estimateTradeOutput` calculates the margin amount using the `marginInBasisPoints` parameter and then deducts this margin from the trade's output amount. Since this moment `estimateTradeOutput` is set in `Order` as `buyAmount` contract until order fulfilment. This calculation is necessary in order to: - cover the exchange fees of the CoW Protocol - cover the possible chainlink price deviation (chainlink price feed has specific sensitivity thresholds, at which the price might not get updated) ![image](https://hackmd.io/_uploads/Bk4UFpE2p.png) **Note**: Since we are using the CoW Protocol, setting the `buyAmount` value ensures that the Order is invalid if fewer amount is offered. At the moment of order fulfillment it's necessary to account for the potential scenario of a sudden market condition changes. For example: 1. An order is created with a price of 1eth=1000usd. 2. The price suddenly rises so that 1eth=1100usd. 3. At this stage, the order should be invalidated because of a potential loss. When the `Order` is ready for execution, the CoW Protocol relayer calls `isValidSignature` (since `Order` is using the `eip1271` signature) method on the contract to check the validity of the swap. At this stage it is very convenient to put a second price check and invalidate the order in case the current transaction conditions are no longer satisfactory. At this moment `Order` contract invokes the `estimateTradeOutput` function again to determine the expected amount of `tokenTo` for this exact moment. If price spike happend, `Order` contract computes `priceToleranceAmount` (computed using the `priceToleranceInBasisPoints` parameter) from `buyAmount` set on the previous step to tolerate new market condition. If difference between newly received `currentCalculatedBuyAmount` and `buyAmount` is bigger than `priceToleranceAmount` order becomes invalidated. ![image](https://hackmd.io/_uploads/H1Qaq6N26.png) ### Token recovery It's necessary to anticipate scenarios in which tokens are accidentally transferred to the `Stonks` or `Order` contract due to unforeseen circumstances. For this purpose, it's needed to implement `AssetRecoverer` contract with `recoverERC20`, `recoverEther`, `recoverERC721`, `recoverERC1155` methods, which will allow tokens to be withdrawn from the balance and sent to the Treasury (it's essential that the Treasury is the final recipient of any token). Only the manager or DAO can execute these methods, preventing accidental triggers. It's important to remember that tokens awaiting exchange might be stored on the `Order` contract. To ensure the security of the transaction, the execution of `recoverERC20` shouldn't be allowed for tokens involved in an ongoing transaction until the transaction is deemed invalid by time. Both contracts `Stonks` and `Order` are inherited from `AssetRecoverer` contract and eligible to recover tokens. Moreover, it's necessary to allow to recover tokens that were going to be traded, but trade hasn't happend by any reason. For this purpose `Order` contract should has `recoverTokenFrom` method that allows to move `tokenFrom` tokens back to `Stonks` contract to be decided what to do next. **Note**: The only constraint for this method is: `tokenFrom` cannot be recovered until `Order` is invalidated. ## CoW Protocol onchain order creation To generate an order in Cow Protocol, it's necessary to create offchain data, execute an API request, passing that data as a parameter. The response to this request will be the UID of the offchain order. Since the creation of an offchain order doesn't require permission, it's essential to ensure its non-execution if any parameters are altered. For this purpose, we will use an onchain order and its hash value. This hash will be saved in the order contract and will be checked every time CoW Protocol attempts to execute the order. If a malicious actor creates an offchain order with parameters different from those fixed in the contract, the hash values will not match, and the order will not be executed. Each onchain order must comply with the [GPv2Order](https://github.com/cowprotocol/contracts/blob/main/src/contracts/libraries/GPv2Order.sol#L11) interface, which includes: - `sellToken` - `buyToken` - `sellAmount` - `buyAmount` - `validTo` - `feeAmount` - `receiver` - `kind` - `partiallyFillable` as well as several technical meta parameters: - `appData` - `sellTokenBalance` - `buyTokenBalance` This struct is going to be hashed by [EIP-712](https://eips.ethereum.org/EIPS/eip-712) using [GPv2Order.hash](https://github.com/cowprotocol/contracts/blob/main/src/contracts/libraries/GPv2Order.sol#L133) method of CoW Protocol contract. For signing this type of transaction [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) should be used. Cow Protocol [allows](https://docs.cow.fi/tutorials/how-to-place-erc-1271-smart-contract-orders) to create smart contract orders with EIP-1271 signatures for offchain trades so trade parameters should be checked in the `isValidSignature` method of the `Order` contract as well. ### Token to buy/sell These parameters are set in immutable variables of the Stonks contract. It indicates the tokens are going to be exchanged. Each Stonks contract is fixed to work with only two tokens and only in one direction. To exchange other tokens, a different contract must be used. ### Amount to buy/sell and kind of order To limit the possibility of non-optimal use of funds to create a new order, it was decided to use the entire amount on the balance of the `Stonks` contract. Consequently, the `sellAmount` parameter emerges from executing `balanceOf(this)` on the `Stonks` contract and is can't be changed by committee. The `KIND` parameter plays a pivotal role in the transaction calculation math: When set to `SELL`, it signals to CowSwap the intention to sell a fixed quantity of N tokens. As a result, the `buyAmount` parameter becomes variable during the exchange. Conversely, when `BUY` is selected, it indicates a commitment to purchase a fixed number of N tokens. This setting causes the `sellAmount` parameter to fluctuate throughout the transaction. The decision is made to utilize `KIND=sell`. ### Partially fillable This parameter dictates the feasibility of partially fulfilling an order over a specified time frame. When set to `true`, it allows, for example, an exchange order of 100 ETH to be executed in 10 batches. This approach can be advantageous as it may lead to a more favorable price. However, there is a drawback: the order might only be partially completed before exceeding its validity date. Subsequently, the unfulfilled portion would need to be returned to the Stonks contract, necessitating a restart of the process. Conversely, setting the parameter to `false` ensures that the order is either fully executed or not executed at all. In this context, the decision is made to set the parameter to `false`. ### Fee amount The choice to utilize limit orders is made due to the impact of trade size on price formation when using regular market orders. The aim is to establish a minimum acceptable amount to receive for the order, hence the preference for limit orders. When opting to place a limit order, it is mandatory to set the fee amount to 0, as per the guidelines for limit order fees. Key Features - Price Specification: Users determine a specific price level for buying or selling tokens. - Quantity: The user specifies the number of tokens to be traded. - Expiration: Limit orders can be set with a specific duration, known as time-to-live (TTL), after which unfilled orders are automatically cancelled. - Non-Guaranteed Execution: Execution of a limit order is not assured if the market price never meets the order's specified level. ## CoW Protocol offchain order creation To make a token swap, it's necessary to notify CoW Protocol that a specific order needs to be added to the order book. This requires transmitting the parameters for creating the order to the CoW API. After the order creation onchain, a bot (bot/frontend/etc.) should be triggered, which will take data from the event and form the data for the CoW API. It's important to remember that for validating the order, the hash of the onchain transaction parameters is used, which prevents any alteration of the final transaction amount or other parameters. ## Technical specification ### Contract `Ownable` <details> The `Ownable` contract designed to provide a basic access control mechanism. It allows for two distinct roles: an agent and a manager. The agent is defined at the time of contract deployment and is immutable, while the manager can be appointed and potentially changed by the agent. #### `constructor` Initializes the contract by setting the agent. ```solidity! constructor(address agent_) ``` #### Constraints: - Ensures the agent is not the zero address. #### `setManager` Allows the agent to set or change the manager. ```solidity! function setManager(address manager_) external onlyAgent ``` #### `onlyAgent` Restricts function access exclusively to the agent. ```solidity! modifier onlyAgent() ``` #### `onlyAgentOrManager` Restricts function access to either the agent or the manager. ```solidity! modifier onlyAgentOrManager() ``` </details> ### Contract `AssetRecoverer` (inherits `Ownable`) <details> The AssetRecoverer contract implements a mechanism to recover ERC20, ERC721, ERC1155 tokens and Ethers that have been mistakenly sent to a contract. This is useful in scenarios where a user has accidentally transferred tokens to the contract's address, providing a means to return the tokens to their owner. Such a contract typically includes functions to check balances and transfer tokens back to the owner or an authorized agent. #### `recoverERC20` Allows the agent or manager to recover ERC20 tokens held by the contract. ```solidity! function recoverERC20(address tokenAddress, uint256 amount) public onlyAgentOrManager ``` #### Constraints: - The function should ensure that the contract has a sufficient amount of tokens to recover before calling transfer. - There should be a check for the successful execution of the transfer function. - Can send tokens only on Agent address. #### `recoverERC721` Allows the agent or manager to recover ERC721 tokens held by the contract. ```solidity! function recoverERC721(address token, uint256 tokenId) external onlyAgentOrManager ``` #### Constraints: - There should be a check for the successful execution of the transfer function. - Can send tokens only on Agent address. #### `recoverERC1155` Allows the agent or manager to recover ERC721 tokens held by the contract. ```solidity! function recoverERC1155(address token, uint256 tokenId) external onlyAgentOrManager ``` #### Constraints: - There should be a check for the successful execution of the transfer function. - Can send tokens only on Agent address. #### `recoverEther` Allows the agent or manager to recover Ether tokens held by the contract. ```solidity! function recoverEther() external onlyAgentOrManager ``` #### Constraints: - There should be a check for the successful execution of the transfer function. - Can send tokens only on Agent address. </details> ### Contract `Stonks` (inherits `AssetRecoverer`) <details> The `Stonks` contract serves as a trading facilitator between two specified ERC20 tokens. It enables the creation and management of orders through an associated `Order` contract instance. The contract is designed to interact with an external `AmountConverter` (via Chainlink price feed) and after initialization funds become withdrawable for an offchain settlement (CoW Protocol). It inherits from the `AssetRecoverer` contract to ensure safe recovery of ERC20, etc. tokens. #### `constructor` Initializes the Stonks contract with key trading parameters. Stores essential parameters for trade execution in immutable variables, ensuring consistency and security of trades. ```solidity! constructor( address agent_, address manager_, address tokenFrom_, address tokenTo_, address amountConverter_, address orderSample_, uint256 orderDurationInSeconds_, uint256 marginInBasisPoints_, uint256 priceToleranceInBasisPoints_ ) AssetRecoverer(agent_) ``` #### Constraints: - None of the address parameters can be the zero address. - The `tokenFrom_` and `tokenTo_` addresses must not be the same. - `marginInBasisPoints_` and `priceToleranceInBasisPoints_` can't be more than `BASIS_POINTS_PARAMETERS_LIMIT` = 1000. - `orderDurationInSeconds_` can't be less than `60 seconds` and more than `24 hours`. #### `placeOrder` Initiates a new trading order by creating an Order contract clone. Transfers the `tokenFrom` balance to the Order clone and initializes it with the `Stonks` manager settings for execution. Sets the minimal acceptable result amount of the trade. ```solidity! function placeOrder(uint256 minBuyAmount) external onlyAgentOrManager ``` #### Constraints: - There must be a balance of the `tokenFrom` in the Stonks contract before placing an order. - To avoid order spamming with rebasable tokens (stETH for example), order creation should be restricted with minimal amount (10 wei). #### `estimateTradeOutput` Estimates output amount for a given trade input amount. Uses `AmountConverter` for output estimation. ```solidity! function estimateTradeOutput(uint256 amount) public view returns (uint256) ``` #### `estimateTradeOutputFromCurrentBalance` Estimates trade output based on current input token balance. Uses `estimateTradeOutput` for output estimation. ```solidity! function estimateOutputFromCurrentBalance() external view returns (uint256) ``` #### Constraints: - Amount shouldn't be 0. #### `getOrderParameters` Returns trading parameters from Stonks for use in the Order contract. ```solidity! function getOrderParameters() external view returns (address tokenFrom, address tokenTo, uint256 orderDurationInSeconds) ``` #### `getPriceTolerance` Returns price tolerance parameter from Stonks for use in the Order contract. ```solidity! function getPriceTolerance() external view returns (uint256 priceToleranceInBasisPoints) ``` </details> ### Contract `Order` (inherits `AssetRecoverer`) <details> Handles the execution of individual trading orders for the Stonks contract on CoW P. #### `constructor` This constructor sets up necessary parameters and state variables to enable the contract's interaction with the CoW Swap protocol. Used immutable variables. ```solidity! constructor(address agent_, address settlement_, address relayer_) AssetRecoverer(agent_) ``` #### `initialize` Initializes the contract for trading by defining order parameters and approving tokens. This function sets the buy amount (if buy amount received from chainlink based on market conditions is lower then minBuyAmount, sets minBuyAmount), sets the order parameters, and approves the token for trading. ```solidity! function initialize(uint256 minBuyAmount_, address manager_) external ``` #### Constraints: - Can only be executed once as it is intended for a single trade setup. #### `isValidSignature` Validates the order's signature and ensures compliance with price and timing constraints. Implements EIP-1271 for onchain signature. #### Parameters: - `bytes32 hash`: The hash of the order to verify. - `bytes calldata signature`: The signature to validate (unused, as the verification is implicit). #### Returns: `bytes4`: Returns the magic value `ERC1271_MAGIC_VALUE` if the signature is valid. #### Constraints: - The provided hash must match the stored order hash. - The current block timestamp must be less than or equal to validTo. - The function should check for the current token prices to check that there are no price spikes on market. #### `recoverTokenFrom` Allows for the cancellation of the order and returns the tokens to the `Stonks` contract if the order has expired. ```solidity! function recoverTokenFrom() external ``` #### Constraints: - Can only be executed if the order has expired (validTo is less than the current block timestamp). #### `recoverERC20` Facilitates the recovery of ERC20 tokens from the contract, except for the token involved in the order. ```solidity! function recoverERC20(address token_, uint256 amount) public override onlyAgentOrManager ``` #### Constraints: - Cannot be used to recover the `tokenFrom`. - Can only be executed by the manager or an authorized agent. #### Event `OrderCreated` Emitted when a new order is initialized. #### Parameters: - `address indexed order`: The address of the order contract. - `bytes32 orderHash`: The hash of the order. - `GPv2Order.Data orderData`: The data struct containing the order details. </details> ### Contract `AmountConverter` <details> This contract provides functionalities to retrieve expected token conversion rates based on the Chainlink Price Feed. The primary function `getExpectedOut` is the main point of interaction. It fetches the price of the provided token to `conversionTarget` from the Chainlink Price Feed and then calculates the expected amount of the output token based on the input amount of the sellToken. #### `constructor` The constructor initializes the contract with the Chainlink Feed Registry address and lists of tokens that are allowed to be sold and stable tokens that can be purchased. ```solidity! constructor( address feedRegistry_, address conversionTarget_, address[] memory allowedTokensToSell_, address[] memory allowedTokensToBuy_, uint256[] memory priceFeedsHeartbeatTimeouts_ ) ``` #### Restrictions - The `_feedRegistry` must not be the zero address. - Each address in `_allowedTokensToSell` and `_allowedStableTokensToBuy` must not be the zero address. - Each token in `_allowedTokensToSell` must have an associated price feed in the Chainlink Feed Registry. - `priceFeedsHeartbeatTimeouts_` should be in sync by index with `allowedTokensToSell_` #### `getExpectedOut` Calculates the expected amount of `tokenTo_` that one would receive for a given amount of `tokenFrom_`. This function computes the expected output amount of `tokenTo_` when selling `tokenFrom_`. It uses the Chainlink Price Feed to get the current price of `tokenFrom_` in terms of the `conversionTarget` (usually USD). The function then adjusts this price based on the token decimals and returns the expected amount of `tokenTo_` one would receive for the specified `amountFrom_` of `tokenFrom_`. This function assumes that `tokenTo_` is equivalent in value to the `conversionTarget`. ```solidity function getExpectedOut(address tokenFrom_, address tokenTo_, uint256 amountFrom_) external view returns (uint256 expectedOutputAmount) ``` #### Returns - `expectedOutputAmount`: The calculated amount of `_tokenTo` tokens expected to be received. #### Restrictions - `_tokenFrom` and `_tokenTo` must not be the same address. - `_tokenFrom` must be an allowed token to sell. - `_tokenTo` must be an allowed stable token to buy. </details>

Import from clipboard

Paste your markdown or webpage here...

Advanced permission required

Your current role can only read. Ask the system administrator to acquire write and comment permission.

This team is disabled

Sorry, this team is disabled. You can't edit this note.

This note is locked

Sorry, only owner can edit this note.

Reach the limit

Sorry, you've reached the max length this note can be.
Please reduce the content or divide it to more notes, thank you!

Import from Gist

Import from Snippet

or

Export to Snippet

Are you sure?

Do you really want to delete this note?
All users will lose their connection.

Create a note from template

Create a note from template

Oops...
This template has been removed or transferred.
Upgrade
All
  • All
  • Team
No template.

Create a template

Upgrade

Delete template

Do you really want to delete this template?
Turn this template into a regular note and keep its content, versions, and comments.

This page need refresh

You have an incompatible client version.
Refresh to update.
New version available!
See releases notes here
Refresh to enjoy new features.
Your user state has changed.
Refresh to load new user state.

Sign in

Forgot password

or

By clicking below, you agree to our terms of service.

Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
Wallet ( )
Connect another wallet

New to HackMD? Sign up

Help

  • English
  • 中文
  • Français
  • Deutsch
  • 日本語
  • Español
  • Català
  • Ελληνικά
  • Português
  • italiano
  • Türkçe
  • Русский
  • Nederlands
  • hrvatski jezik
  • język polski
  • Українська
  • हिन्दी
  • svenska
  • Esperanto
  • dansk

Documents

Help & Tutorial

How to use Book mode

Slide Example

API Docs

Edit in VSCode

Install browser extension

Contacts

Feedback

Discord

Send us email

Resources

Releases

Pricing

Blog

Policy

Terms

Privacy

Cheatsheet

Syntax Example Reference
# Header Header 基本排版
- Unordered List
  • Unordered List
1. Ordered List
  1. Ordered List
- [ ] Todo List
  • Todo List
> Blockquote
Blockquote
**Bold font** Bold font
*Italics font* Italics font
~~Strikethrough~~ Strikethrough
19^th^ 19th
H~2~O H2O
++Inserted text++ Inserted text
==Marked text== Marked text
[link text](https:// "title") Link
![image alt](https:// "title") Image
`Code` Code 在筆記中貼入程式碼
```javascript
var i = 0;
```
var i = 0;
:smile: :smile: Emoji list
{%youtube youtube_id %} Externals
$L^aT_eX$ LaTeX
:::info
This is a alert area.
:::

This is a alert area.

Versions and GitHub Sync
Get Full History Access

  • Edit version name
  • Delete

revision author avatar     named on  

More Less

Note content is identical to the latest version.
Compare
    Choose a version
    No search result
    Version not found
Sign in to link this note to GitHub
Learn more
This note is not linked with GitHub
 

Feedback

Submission failed, please try again

Thanks for your support.

On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

Please give us some advice and help us improve HackMD.

 

Thanks for your feedback

Remove version name

Do you want to remove this version name and description?

Transfer ownership

Transfer to
    Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

      Link with GitHub

      Please authorize HackMD on GitHub
      • Please sign in to GitHub and install the HackMD app on your GitHub repo.
      • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
      Learn more  Sign in to GitHub

      Push the note to GitHub Push to GitHub Pull a file from GitHub

        Authorize again
       

      Choose which file to push to

      Select repo
      Refresh Authorize more repos
      Select branch
      Select file
      Select branch
      Choose version(s) to push
      • Save a new version and push
      • Choose from existing versions
      Include title and tags
      Available push count

      Pull from GitHub

       
      File from GitHub
      File from HackMD

      GitHub Link Settings

      File linked

      Linked by
      File path
      Last synced branch
      Available push count

      Danger Zone

      Unlink
      You will no longer receive notification when GitHub file changes after unlink.

      Syncing

      Push failed

      Push successfully