diff --git a/docs/README.md b/docs/README.md index 5c452e5..ae0f704 100644 --- a/docs/README.md +++ b/docs/README.md @@ -25,3 +25,8 @@ While VM integration is certainly the quickest and probably most accessible one For indexing purposes, it is required that you provide a [substreams](https://substreams.streamingfast.io/) package that emits a specified set of messages. If your protocol already has a [substreams package](https://github.com/messari/substreams) for indexing implemented, you can adjust it to emit the required messages. **VM Integration** Currently the only supported integration is for EVM protocols in order to complement the Solidity protocol logic. [**Read more here.**](https://github.com/propeller-heads/propeller-venue-lib/blob/main/docs/indexing/vm-integration/README.md) **Custom Entity Integration** Coming soon, this integration will complement the upcoming native Rust protocol logic. + +### Execution + +For execution purposes, the implementation of the `SwapExecutor` interface is required. Without this component, trades cannot be executed on-chain, making it a critical part of the integration. +The `SwapExecutor` is responsible for performing swaps by interacting with the underlying liquidity pools, handling token approvals, managing input/output amounts, and ensuring gas-efficient and secure execution. Each protocol must implement its own `SwapExecutor`, tailored to its specific logic and requirements. diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index ba86ac7..008d00e 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -15,3 +15,6 @@ - [VM Integration](indexing/vm-integration/README.md) - [Native Integration](indexing/native-integration.md) - [Reserved Attributes](indexing/reserved-attributes.md) + +## Execution +- [Swap Executor](execution/swap-executor.md) \ No newline at end of file diff --git a/docs/execution/swap-executor.md b/docs/execution/swap-executor.md new file mode 100644 index 0000000..1daddc9 --- /dev/null +++ b/docs/execution/swap-executor.md @@ -0,0 +1,39 @@ +# Implementing a SwapExecutor for a Protocol + +## Overview + +The `ISwapExecutor` interface is designed to perform swaps on a liquidity pool. +It allows for flexible interaction by accepting either the amount of the input token or the amount of the output token +as parameters, returning the corresponding swapped amount. +This interface is essential for creating a `SwapExecutor` specific to a protocol. + +## Key Methods + +- **swap(uint256 givenAmount, bytes calldata data)** + - **Purpose**: To perform a token swap, either specifying the input amount to get the output amount or vice versa. + - **Parameters**: + - `givenAmount`: The amount of the token (input or output) for the swap. + - `data`: Encoded information necessary for the swap (e.g., pool address, token addresses - depends on the protocol). + - **Returns**: The amount of the token swapped. + +## Implementation Steps + +1. **Define Protocol-Specific Logic**: Implement the `swap` function to interact with the protocol's liquidity pool. +Use the `data` parameter to encode necessary information like pool and token addresses. +2. **Handling Input and Output**: Depending on the provided `givenAmount`, determine whether it's an input or output +swap. Calculate the corresponding swapped amount based on the pool's pricing logic. +3. **Error Handling**: Use `ISwapExecutorErrors` (`InvalidParameterLength` and `UnknownPoolType`) to manage potential +errors, such as invalid parameter lengths or unknown pool types in the swap logic. +4. **Token Approvals**: If the protocol requires token approvals (allowances) before swaps can occur, +manage these approvals within the implementation to ensure smooth execution of the swap. +5. **Token Transfer Support**: Ensure that the implementation supports transferring received tokens to a designated +receiver address, either within the swap function or through an additional transfer step. +6. **Gas Efficiency**: Ensure the implementation is gas-efficient. Strive for optimal performance in the swap logic. +7. **Security Considerations**: Follow common security best practices, such as validating inputs, ensuring proper +access control, and safeguarding against reentrancy attacks. + + + +## Example Implementation + +See the example implementation of a `SwapExecutor` for Balancer here (TODO: paste link) \ No newline at end of file diff --git a/docs/logic/vm-integration/README.md b/docs/logic/vm-integration/README.md index f6083cd..81892a7 100644 --- a/docs/logic/vm-integration/README.md +++ b/docs/logic/vm-integration/README.md @@ -40,7 +40,7 @@ Following exchanges have been integrated using VM approach: ### Understanding the ISwapAdapter -Read the the documentation of the [Ethereum Solidity interface](ethereum-solidity.md). It describes the functions that need to be implemented as well as the manifest file. Additionally read through the docstring of the [ISwapAdapter.sol](https://github.com/propeller-heads/propeller-venue-lib/blob/main/evm/src/interfaces/ISwapAdapter.sol) interface and the [ISwapAdapterTypes.sol](https://github.com/propeller-heads/propeller-venue-lib/blob/main/evm/src/interfaces/ISwapAdapterTypes.sol) interface which defines the data types and errors used by the adapter interface. You can also generate the documentation locally and the look at the generated documentation in the `./docs` folder: +Read the documentation of the [Ethereum Solidity interface](ethereum-solidity.md). It describes the functions that need to be implemented as well as the manifest file. Additionally read through the docstring of the [ISwapAdapter.sol](https://github.com/propeller-heads/propeller-venue-lib/blob/main/evm/src/interfaces/ISwapAdapter.sol) interface and the [ISwapAdapterTypes.sol](https://github.com/propeller-heads/propeller-venue-lib/blob/main/evm/src/interfaces/ISwapAdapterTypes.sol) interface which defines the data types and errors used by the adapter interface. You can also generate the documentation locally and the look at the generated documentation in the `./docs` folder: ```bash cd ./evm/ diff --git a/evm/src/interfaces/ISwapExecutor.sol b/evm/src/interfaces/ISwapExecutor.sol new file mode 100644 index 0000000..798946f --- /dev/null +++ b/evm/src/interfaces/ISwapExecutor.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.7.5; + +import "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; + +pragma abicoder v2; + +interface ISwapExecutor { + /** + * @notice Performs a swap on a liquidity pool. + * @dev This method can either take the amount of the input token or the + * amount + * of the output token that we would like to swap. If called with the amount + * of + * the input token, the amount of the output token will be returned, and + * vice + * versa. Whether it is the input or output that is given, is encoded in the + * data + * parameter. + * + * Note Part of the informal interface is that the executor supports sending + * the received + * tokens to a receiver address. If the underlying smart contract does not + * provide this + * functionality consider adding an additional transfer in the + * implementation. + * + * This function is marked as `payable` to accommodate delegatecalls, which + * can forward + * a potential `msg.value` to it. + * + * @param givenAmount The amount of either the input token or output token + * to swap. + * @param data Data that holds information necessary to perform the swap. + * @return calculatedAmount The amount of either the input token or output + * token + * swapped, depending on the givenAmount inputted. + */ + function swap(uint256 givenAmount, bytes calldata data) + external + payable + returns (uint256 calculatedAmount); +} + +interface ISwapExecutorErrors { + error InvalidParameterLength(uint256); + error UnknownPoolType(uint8); +}