From c8a8f1509ce0315e583b71e039655700b02913ad Mon Sep 17 00:00:00 2001 From: kasperpawlowski <25374117+kasperpawlowski@users.noreply.github.com> Date: Thu, 18 Jan 2024 11:34:50 +0000 Subject: [PATCH 1/2] fix: remove faq, remove vault-related specs --- docs/faq.md | 114 --------------------------- docs/specs.md | 211 -------------------------------------------------- 2 files changed, 325 deletions(-) delete mode 100644 docs/faq.md diff --git a/docs/faq.md b/docs/faq.md deleted file mode 100644 index bb14d66b..00000000 --- a/docs/faq.md +++ /dev/null @@ -1,114 +0,0 @@ -# Frequently Asked Questions (FAQ) - - - - -* [What is the Ethereum Vault Connector?](#what-is-the-ethereum-vault-connector) -* [How does the EVC work in principle?](#how-does-the-evc-work-in-principle) -* [What are the benefits of building on the EVC?](#what-are-the-benefits-of-building-on-the-evc) -* [What can be built using the EVC?](#what-can-be-built-using-the-evc) -* [What is a Controller in the context of EVC?](#what-is-a-controller-in-the-context-of-evc) -* [What are Account Status Checks?](#what-are-account-status-checks) -* [What are Vault Status Checks?](#what-are-vault-status-checks) -* [What are checks deferrals and how do they work?](#what-are-checks-deferrals-and-how-do-they-work) -* [What is an Operator?](#what-is-an-operator) -* [What is the concept of sub-accounts in the EVC?](#what-is-the-concept-of-sub-accounts-in-the-evc) -* [What is the purpose of the `batch` function in the EVC?](#what-is-the-purpose-of-the-batch-function-in-the-evc) -* [How does the EVC handle gasless transactions?](#how-does-the-evc-handle-gasless-transactions) -* [How does the EVC support simulations?](#how-does-the-evc-support-simulations) -* [What is the purpose of the `controlCollateral` function in the EVC?](#what-is-the-purpose-of-the-`controlcollateral`-function-in-the-evc) -* [How does the EVC interact with other smart contracts?](#how-does-the-evc-interact-with-other-smart-contracts) - - - -## What is the Ethereum Vault Connector? - -The Ethereum Vault Connector (EVC) is a foundational layer designed to facilitate the core functionality required for a lending market. It serves as a base building block for various protocols, providing a robust and flexible framework for developers to build upon. The EVC primarily mediates between vaults, contracts that implement the [ERC-4626](https://ethereum.org/en/developers/docs/standards/tokens/erc-4626/) interface and contain additional logic for interfacing with other vaults. - -## How does the EVC work in principle? - -When users wish to borrow, they must link their accounts and collateral vaults to the borrowed-from vault via the EVC. The liability vault, also known as the "controller", is then consulted whenever a user wants to perform an action potentially impacting the account's solvency, such as withdrawing collateral. The EVC is responsible for calling the controller to determine whether the action is allowed or should be blocked to prevent account insolvency. - -## What are the benefits of building on the EVC? - -The EVC contains the functionality required to build flexible products, both for EOAs and smart contracts. It provides a common base ecosystem and reduces complexity in the core lending/borrowing contracts, allowing them to focus on their differentiating factors such as pricing and risk management. - -The EVC helps create the network effect by offering access to unified liquidity and interoperability, allowing protocols to accept deposits in other vaults as collateral. It does not enforce specific properties about the assets and provides a standardized approach to account liquidity checks and vault constraints enforcement. Lastly, amongst others, the EVC supports batch operations, sub-accounts, checks deferrals, automations, gasless transactions and provides an interface for simulating operations. - -## What can be built using the EVC? - -The EVC provides a robust and flexible framework for developers to build various new products. These include but are not limited to: - -* Traditional, overcollateralized lending products -* Uncollateralized lending products -* Real World Assets (RWA) lending products -* NFT lending products -* P2P lending products -* Oracle-free lending products -* Lending products based on alternate oracles -* Novel risk management solutions -* Novel interest rate models -* Transaction relayers -* Intent-based systems -* Automations (conditional orders, custom liquidation flows, strategies, position managers, optimizers, guardians etc.) -* Smart contract tooling (i.e. swap hubs using new dexes or new dex aggregators) -* Integrations - -These are just a few examples of what can be built using the EVC. The possibilities are vast and limited only by the creativity and ingenuity of the developer community. - -## What is a Controller in the context of EVC? - -In the context of the EVC, a Controller is a type of Vault that a user enables in order to borrow from it. When a user enables a Controller Vault, they submit their account to the rules encoded in the Controller Vault's code. The Controller Vault indirectly controls all the funds in all the enabled Collateral Vaults of the user. Whenever a user wants to perform an action such as removing collateral, the Controller Vault is consulted to determine whether the action is allowed, or whether it should be blocked since it would make the account insolvent. -The Controller Vault plays a crucial role in the liquidation process. If a user's account becomes insolvent, the Controller Vault is allowed to seize the collateral from the enabled Collateral Vaults to repay the debt. - -## What are Account Status Checks? - -Account status checks are implemented by vaults to enforce account solvency. Vaults must expose an external `checkAccountStatus` function that will receive an account's address and this account's list of enabled collateral vaults. If the account has not borrowed anything from this vault then the function should return a special magic success value. Otherwise, the vault should evaluate application-specific logic to determine whether or not the account is in an acceptable state. - -## What are Vault Status Checks? - -Some vaults may have constraints that should be enforced globally. For example, supply and/or borrow caps that restrict the maximum amount of assets that can be supplied or borrowed, as a risk minimisation. Vaults may expose an external `checkVaultStatus` function in which application-specific logic should be evaluated to determine whether or not the vault is in an acceptable state. - -## What are checks deferrals, and how do they work? - -Checks deferrals are the EVC feature that allows for the deferral of account and vault status checks until the end of the outermost checks-deferrable call. This means that checks for account solvency and vault constraints, which are usually performed immediately, can be postponed until the end of the call. -This feature is particularly useful in scenarios where multiple operations need to be performed in a specific sequence, and where the intermediate states of the account or vault might not meet the usual constraints. By deferring the checks, the EVC allows for a transient violation of account solvency or vault constraints, which can be useful in certain complex operations. -However, it's important to note that the checks are still performed at the end of the outermost call, ensuring that the final state of the account and vault still meet the necessary constraints. The entire operation will fail if the final state does not meet these constraints. - -## What is an Operator? - -Operators are a more flexible and powerful version of approvals. These are EOAs or smart contracts that have been granted a permission to operate on behalf of the account. This includes interacting with vaults (i.e. withdrawing/borrowing funds), enabling vaults as collateral, etc. Because of this, it is recommended that only trusted and audited contracts, or EOAs held by a trusted individuals, be installed as operators. Operator concept can be used to build flexible products on top of the EVC, i.e. various automations, intents support, stop-loss/take-profit/trailing-stop/etc modifiers, position managers etc. - -## What is the concept of sub-accounts in the EVC? - -In the EVC, a sub-account is a concept that allows users to create multiple isolated positions within their single owner account. The sub-accounts belonging to the same owner share the first 19 bytes of their address and differ only in the last byte. This allows for the creation of isolated positions, where each sub-account can have its own set of enabled collateral vaults and a controller vault. -Sub-accounts provide flexibility and control to the user. They can be used to manage different investment strategies or risk profiles within the same Ethereum address. Each sub-account can be independently liquidated without affecting the others, providing a level of risk isolation. - -## What is the purpose of the `batch` function in the EVC? - -The `batch` function in the EVC allows for the execution of a list of operations atomically, meaning that all operations either succeed together or fail together, ensuring consistency. The `batch` function defers account and vault status checks until the end of the outermost call. This allows for a transient violation of account solvency or vault constraints, which not only saves gas but can be useful in certain complex operations. - -## How does the EVC handle gasless transactions? - -The EVC handles gasless transactions, also known as meta-transactions, through a `permit` function. Permit function supports EIP-712 typed data messages that allow arbitrary calldata execution on the EVC on behalf of the signer (Account Owner or Account Operator) of the message. This means that a user can sign a message off-chain, which can then be sent to the EVC by another party who pays for the gas. -This feature is particularly useful in scenarios where a user might not have enough native currency to pay for gas, or in applications that want to abstract away the concept of gas for a better user experience. - -## How does the EVC support simulations? - -The EVC supports simulations through a dedicated interface that allows for the execution of a batch of operations without actually modifying the state. This is particularly useful for inspecting the outcome of a batch before executing it, which can aid in decision-making and risk assessment. - -## What is the purpose of the `controlCollateral` function in the EVC? - -In the EVC, the `controlCollateral` function is a key mechanism that allows an enabled Controller Vault to execute arbitrary calldata on any of its enabled Collateral Vaults on behalf of a specified account. -This function is particularly useful during the liquidation process. When a user's account becomes insolvent, a liquidator initiates the liquidation process. As part of this process, the Controller Vault, using the `controlCollateral` function, seizes the collateral from the enabled Collateral Vaults to repay the debt. -In essence, the `controlCollateral` function provides a mechanism for enforcing the rules and conditions set by the Controller Vault, including the management of collateral during liquidations. - -## How does the EVC interact with other smart contracts? - -The EVC interacts with other smart contracts, including vaults, through several key functions: `call`, `batch`, and `controlCollateral`. - -1. `call`: The function allows to execute arbitrary calldata on external smart contract with account and vault status checks deferred. If the target contract is `msg.sender`, the EVC execution context is set as per the account specified. If the target contract is not `msg.sender`, only the Account Owner or Account Operator are allowed to execute arbitrary calldata on behalf of the specified account. This function may also be used when a vault is called directly and wants to imitate being called through the EVC or when the remaining value needs to be recovered from the EVC. - -1. `batch`: The function allows for the execution of a list of operations atomically. This means that all operations either succeed together or fail together. This function is used when the EVC needs to interact with multiple smart contracts in a specific sequence. - -1. `controlCollateral`: The function allows an enabled Controller Vault to execute arbitrary calldata on any of its enabled Collateral Vaults on behalf of a specified account. This function is particularly useful for liquidation flows, where the Controller Vault needs to interact with Collateral Vaults to seize collateral. diff --git a/docs/specs.md b/docs/specs.md index 7bac0467..82c3a3b0 100644 --- a/docs/specs.md +++ b/docs/specs.md @@ -97,214 +97,3 @@ NOTE: While it might be tempting for the Controller to allow a broad range of Co NOTE: Accounts are fully isolated and can be treated as independent positions. Failing Account Status Check (ruled by enabled Controller Vault) may affect the ability to interact with the Account, including operations on the Vaults that are not enabled as Collaterals. In order to make the Account fully functional again, one MUST satisfy the Controller Vault conditions. NOTE: Because the EVC contract can be made to invoke any arbitrary target contract with any arbitrary calldata, it SHOULD never be given any privileges, or hold any value or tokens. - - -## Vault Specification - -1. A Vault MAY either only allow to be called through the EVC or MAY allow to be called both through the EVC and directly. When the Vault is called through the EVC, it MUST rely on the `getCurrentOnBehalfOfAccount` function for the currently authenticated Account on behalf of which the operation is being performed. The Vault MUST consider this the true value of `msg.sender` for authorization purposes. If the Vault is called directly, the Vault MAY perform the authentication itself and OPTIONALLY use the `call` function on the EVC. -1. In more complex cases, to avoid status-check-related issues, it is advised to use the `call` function in the callback manner (meaning a Vault can call back itself using `call`) when the Vault is called directly. It will ensure the Account and Vault Status Checks are always deferred, at least until the end of the `call`. -1. `call` function SHALL only be used if `msg.sender` is not the EVC, in other words, if the Vault is called directly. -1. Before using `call` in the callback manner, the Vault is REQUIRED to authenticate the `msg.sender`. It is strongly advised to pass the `msg.sender` address as `onBehalfOfAccount` input of the `call` function unless there's a legitimate reason not to do so. -1. In order to support sub-accounts, operators, collateral control, and permits, a Vault MUST be invoked via the EVC. -1. When a user requests to perform an operation such as borrow, a Vault MUST call into the EVC in order to ensure that the Account has enabled this Vault as a Controller. For that purpose `getCurrentOnBehalfOfAccount` or `isControllerEnabled` functions SHOULD be used. -1. Due to the fact that only the Controller can disable itself for the Account, a Vault MUST implement a standard `disableController` function that can be called by a user in order to disable the Controller if vault-specific conditions are met (typically, the Vault SHOULD check whether the Account has repaid its debt in full). If the vault-specific conditions are not met, the function MUST revert. -1. After each operation potentially affecting the Account's solvency (also on a non-borrowable Vault), a Vault MUST invoke the EVC in order to require the Account Status Check. The EVC determines whether the check should be deferred or performed immediately. -1. Vault MUST implement `checkAccountStatus` function which gets called for the accounts that have enabled this Vault as Controller. The function receives the Account address and the list of Collateral Vaults enabled for the Account. The function MUST determine whether or not the Account is in an acceptable state by returning the magic value or throwing an exception. If the Vault is deposit-only, the function SHOULD always return the appropriate magic value unless there's a need to implement custom logic. -1. `checkAccountStatus` is not called if there is no Controller enabled for the Account at the time of the checks, or when the only Controller was disabled before the checks are performed. -1. Vault MAY implement `checkVaultStatus` function which gets called if the Vault requires that via the EVC. The EVC determines whether the check should be deferred or performed immediately. This is an OPTIONAL functionality that allows the Vault to enforce its constraints (like supply/borrow caps, invariants checks, etc.). If implemented, the Vault Status Check MUST always be required by the Vault after each operation affecting the Vault's state. The `checkVaultStatus` function MUST determine whether or not the Vault is in an acceptable state by returning the magic value or throwing an exception. If the Vault doesn't implement this function, the Vault MUST NOT require the Vault Status Check. -1. In order to evaluate the Vault Status, `checkVaultStatus` MAY need access to a snapshot of the initial Vault state which SHOULD be taken at the beginning of the action that requires the check. -1. Both Account and Vault Status Check SHOULD be required at the very end of the operation. -1. The Controller MAY need to forgive the Account Status Check in order for the operation to succeed, i.e. during liquidations. However, the Account Status Check forgiveness MUST be done with care by ensuring that the forgiven Account's Status Check hadn't been deferred before the operation and that the call requiring the Account Status Check (i.e. ControlCollateral) does not perform any unexpected operations down the call path. -1. Vault MUST NOT allow calls to arbitrary contracts in an uncontrolled manner, including the EVC. - -NOTE: It may be tempting to allow a large set of collateral assets for a vault. However, vault creators MUST be careful about which assets they accept. A malicious vault could lie about the amount of assets it holds, or reject liquidations when a user is in violation. For this reason, vaults should restrict allowed collaterals to a known-good set of audited addresses, or look up the addresses in a registry or factory contract to ensure they were created by known-good, audited contracts. - -NOTE: There is a subtle complication that vault implementations should consider if they use re-entrancy guards (which is recommended). When a vault is invoked without Status Checks being deferred (i.e. vault called directly, not via the EVC), if it calls `require(Account|Vault)StatusCheck` on the EVC, the EVC will immediately call back into the vault's `check(Account|Vault)Status` function. A normal re-entrancy guard would fail upon re-entering at this point. To avoid this, vaults may wish to use the `call` EVC function or the vault implementation should relax the re-entrancy modifier to allow `check(Account|Vault)Status` call while invoking `require(Account|Vault)StatusCheck`. - -NOTE: It MAY be critical to protect `check(Account|Vault)Status` functions against re-entrancy (depends on individual implementation). Additionally, the following check SHOULD be included as well: `require(msg.sender == address(evc) && evc.areChecksInProgress());` - -NOTE: Care MUST be taken not to transfer any assets to the Accounts other than the Account Owner (ID 0). Otherwise, the assets may be lost. If unsure, a vault SHOULD call `getAccountOwner()` function that returns an address of the Account Owner if it's already registered on the EVC. - -NOTE: If a vault attempted to read the collateral or controller sets of an account in order to enforce some policy of its own, then it is possible that a user could defer checks in a batch in order to be able to transiently violate them to satisfy the vault's policy. For this reason, vaults should not rely on the controller or collateral sets of an account if checks are deferred. - - -## Collateralized Borrowable Vault Implementation Guide - -See the [diagrams](./diagrams) too! - -### Deposit/mint considerations -1. Ensure re-entrancy protection -1. Authorize the appropriate account (the account from which the tokens will be pulled) depending on whether the vault is being called directly or through the EVC -1. Take the snapshot of the initial vault state if not taken yet in this context -1. Perform the operation -1. Require the Vault Status Check - -### Withdraw/redeem considerations -1. Ensure re-entrancy protection -1. Authorize the appropriate account (the deposit owner or the account that was approved to withdraw/redeem) depending on whether the vault is being called directly or through the EVC -1. Take the snapshot of the initial vault state if not taken yet in this context -1. Perform the operation -1. Require the Account Status Check on the deposit owner -1. Require the Vault Status Check - -### Borrow considerations -1. Ensure re-entrancy protection -1. Authorize the appropriate account (the account taking on the debt) depending on whether the vault is being called directly or through the EVC -1. Check whether the account taking on the debt has enabled the vault as a controller -1. Take the snapshot of the initial vault state if not taken yet in this context -1. Perform the operation -1. Require the Account Status Check on the account which took on the debt -1. Require the Vault Status Check - -### Repay considerations -1. Ensure re-entrancy protection -1. Authorize the appropriate account (the account from which the tokens will be pulled) depending on whether the vault is being called directly or through the EVC -1. Take the snapshot of the initial vault state if not taken yet in this context -1. Perform the operation -1. Require the Vault Status Check - -### Shares transfer considerations -1. Ensure re-entrancy protection -1. Authorize the appropriate account (the `from` account or the account that was approved to transfer) depending on whether the vault is being called directly or through the EVC -1. Take the snapshot of the initial vault state if not taken yet in this context -1. Perform the operation -1. Require the Account Status Check on the `from` account -1. Require the Vault Status Check - -### Debt transfer considerations -1. Ensure re-entrancy protection -1. Authorize the appropriate account (the account that will receive the debt) depending on whether the vault is being called directly or through the EVC -1. Check whether the account that will receive the debt has enabled the vault as a controller -1. Take the snapshot of the initial vault state if not taken yet in this context -1. Perform the operation -1. Require the Account Status Check on the `to` account -1. Require the Vault Status Check - -### Liquidation considerations -1. Ensure re-entrancy protection -1. Authorize the appropriate account (the liquidator account) depending on whether the vault is being called directly or through the EVC -1. Check whether the liquidator has enabled the vault as a controller -1. Ensure that the liquidator is not liquidating itself -1. Ensure that the violator does not have the Account Status Check deferred -1. Ensure that the collateral to be liquidated is accepted and trusted -1. Take the snapshot of the initial vault state if not taken yet in this context -1. Ensure that the violator is indeed in violation -1. Perform the operation -- Perform all the necessary calculations -- Decrease the violator's debt, increase the liquidator's debt -- Seize the collateral. If it's an internal balance, decrease the violator's balance and increase the liquidator's balance. If it's an external vault, use collateral control functionality to transfer the shares from the violator to the liquidator. After collateral control functionality is used, forgive the Account Status Check on the violator -1. Require the Account Status Check on the liquidator account -1. Require the Vault Status Check - -### Account Status Check considerations -1. Check whether it's the EVC calling -1. Check whether checks are in progress -1. Calculate the collateral and liability value -1. Return the magic value if the account is healthy - -### Vault Status Check considerations -1. Check whether it's the EVC calling -1. Check whether checks are in progress -1. Ensure that the snapshot status is valid -1. Compare the snapshot with the current vault state (invariant check, supply/borrow cap enforcement, etc.) -1. Clear the old snapshot -1. Return the magic value if the vault is healthy - -### Other considerations -1. The vault MUST only be released from being a controller if the account has the debt fully repaid -1. The vault has the freedom to implement the Account Status Check. It MAY price all the assets according to its preference, without depending on potentially untrustworthy oracles -1. The vault has the freedom to implement the Vault Status Check. Depending on the implementation, the initial state snapshotting MAY not be needed. Depending on the implementation, not all the actions MAY require the Vault Status Check (i.e. vault share transfers). If the snapshot is needed, note that it MAY require a prior vault state update (i.e. interest rate accrual). -1. One SHOULD be careful when forgiving the Account Status Check after using `controlCollateral`. A malicious target collateral could manipulate the process leading to a bad debt accrual. To prevent that, one MUST ensure that only trusted collaterals that behave in the expected way are being called using the control collateral functionality -1. When sending regular ERC20 tokens from a vault to an address, one SHOULD ensure that the address is not a sub-account but a valid EOA/contract address by getting an account owner from the EVC - -### Typical implementation pattern of the EVC-compliant function for a vault - -```solidity -function func() external callThroughEVC nonReentrant { - // retrieve the "true" message sender from the EVC. whether _msgSender or _msgSenderForBorrow should be called, - // depends on whether it's a debt-related functionality - address msgSender = _msgSender(); // or _msgSenderForBorrow(); - - // accrue the interest before the snapshot if it relies on it. otherwise, it can be accrued after or never if - // the vault does not implement the interest accrual - _accrueInterest(); - - // take the snapshot if the given functionality requires it - takeVaultSnapshot(); - - - - // CUSTOM FUNCTION LOGIC HERE - - - - // after all the custom logic has been executed, trigger the account status check and vault status check, if - // the latter one is needed. the account for which the account status check is required may differ and depends on - // the function logic. i.e.: - // - for shares transfer the `from` account should be checked - // - for debt transfer the `to` account should be checked - // - for borrow the account taking on the debt should be checked - // hence, the account checked is not always the `msgSender` - requireAccountStatusCheck(account); - requireVaultStatusCheck(); -} -``` - -where `callThroughEVC` can be implemented as follows: - -```solidity -/// @notice Ensures that the msg.sender is the EVC by using the EVC call functionality if necessary. -modifier callThroughEVC() { - if (msg.sender == address(evc)) { - _; - } else { - bytes memory result = evc.call(address(this), msg.sender, 0, msg.data); - - assembly { - return(add(32, result), mload(result)) - } - } -} -``` - -where `_msgSender` and `_msgSenderForBorrow` can be implemented as follows: - -```solidity -/// @notice Retrieves the message sender in the context of the EVC. -/// @dev This function returns the account on behalf of which the current operation is being performed, which is -/// either msg.sender or the account authenticated by the EVC. -/// @return The address of the message sender. -function _msgSender() internal view returns (address) { - address sender = msg.sender; - - if (sender == address(evc)) { - (sender,) = evc.getCurrentOnBehalfOfAccount(address(0)); - } - - return sender; -} -``` - -```solidity -/// @notice Retrieves the message sender in the context of the EVC for a borrow operation. -/// @dev This function returns the account on behalf of which the current operation is being performed, which is -/// either msg.sender or the account authenticated by the EVC. This function reverts if the vault is not enabled as -/// a controller for the account on behalf of which the operation is being executed. -/// @return The address of the message sender. -function _msgSenderForBorrow() internal view returns (address) { - address sender = msg.sender; - bool controllerEnabled; - - if (sender == address(evc)) { - (sender, controllerEnabled) = evc.getCurrentOnBehalfOfAccount(address(this)); - } else { - controllerEnabled = evc.isControllerEnabled(sender, address(this)); - } - - if (!controllerEnabled) { - revert ControllerDisabled(); - } - - return sender; -} -``` From b52edb3532cbf0d2681b99c207c06ff66a3dc0f9 Mon Sep 17 00:00:00 2001 From: kasperpawlowski <25374117+kasperpawlowski@users.noreply.github.com> Date: Thu, 18 Jan 2024 11:42:57 +0000 Subject: [PATCH 2/2] fix: readme refactor --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7d8b7261..d0acfbf3 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ The Ethereum Vault Connector (EVC) is a foundational layer designed to facilitate the core functionality required for a lending market. It serves as a base building block for various protocols, providing a robust and flexible framework for developers to build upon. The EVC primarily mediates between vaults, contracts that implement the [ERC-4626](https://ethereum.org/en/developers/docs/standards/tokens/erc-4626/) interface and contain additional logic for interfacing with other vaults. The EVC not only provides a common base ecosystem but also reduces complexity in the core lending/borrowing contracts, allowing them to focus on their differentiating factors. -For more information refer to the [WHITEPAPER](https://github.com/euler-xyz/ethereum-vault-connector/tree/master/docs/whitepaper.md) and the [SPECS](https://github.com/euler-xyz/ethereum-vault-connector/tree/master/docs/specs.md). +For more information, visit the EVC [website](https://evc.wtf/) or refer to the [whitepaper](https://github.com/euler-xyz/ethereum-vault-connector/tree/master/docs/whitepaper.md) and the [specs](https://github.com/euler-xyz/ethereum-vault-connector/tree/master/docs/specs.md). --- @@ -34,7 +34,7 @@ forge install euler-xyz/ethereum-vault-connector The Ethereum Vault Connector comes with a comprehensive set of tests written in Solidity, which can be executed using Foundry. -For a detailed understanding of the Ethereum Vault Connector and considerations for its integration, please refer to the [WHITEPAPER](https://github.com/euler-xyz/ethereum-vault-connector/tree/master/docs/whitepaper.md) and the [SPECS](https://github.com/euler-xyz/ethereum-vault-connector/tree/master/docs/specs.md). You can find examples of vaults utilizing the Ethereum Vault Connector in the [EVC Playground](https://github.com/euler-xyz/evc-playground/tree/master/src) repository. However, these example vaults are not meant for production use as they have not been audited and are intended solely for testing and experimentation purposes. +For a detailed understanding of the Ethereum Vault Connector and considerations for its integration, please refer to the [EVC website](https://evc.wtf/), the [whitepaper](https://github.com/euler-xyz/ethereum-vault-connector/tree/master/docs/whitepaper.md) and the [specs](https://github.com/euler-xyz/ethereum-vault-connector/tree/master/docs/specs.md). You can find examples of vaults utilizing the Ethereum Vault Connector in the [EVC Playground](https://github.com/euler-xyz/evc-playground/tree/master/src) repository. However, these example vaults are not meant for production use as they have not been audited and are intended solely for testing and experimentation purposes. To install Foundry: @@ -106,7 +106,7 @@ Refer to the [WHITEPAPER](https://github.com/euler-xyz/ethereum-vault-connector/ ## Contributing -The code is currently in an experimental phase leading up to the first audits. Feedback or ideas for improving the Ethereum Vault Connector are appreciated. Contributions are welcome from anyone interested in conducting security research, writing more tests including formal verification, improving readability and documentation, optimizing, simplifying, or developing integrations. +The code is currently in an experimental phase. Feedback or ideas for improving the Ethereum Vault Connector are appreciated. Contributions are welcome from anyone interested in conducting security research, writing more tests including formal verification, improving readability and documentation, optimizing, simplifying, or developing integrations. ## License