Skip to content

Latest commit

 

History

History
74 lines (52 loc) · 2.78 KB

interactive-adapters.md

File metadata and controls

74 lines (52 loc) · 2.78 KB

Interactive adapters

Create an interactive adapter

{% hint style="info" %} The current version of code for interactive adapters is placed in interactive-updates branch. {% endhint %}

To create new token adapter, one has to implement InteractiveAdapter interface. It inherits ProtocolAdapter, so one has to implement it, too.

InteractiveAdapters should implement 2 main functions: deposit() and withdraw().

{% hint style="info" %} InteractiveAdapters should not have any storage variables used within deposit and withdraw functions. Use internal constant or immutable constant. {% endhint %}

function deposit(TokenAmount[] calldata tokenAmounts, bytes calldata data)
        external
        payable
        override
        returns (address[] memory tokensToBeWithdrawn)

tokenAmounts — tokens that will be used in the action (e.g. DAI in case of deposit to Compound).

{% hint style="info" %} Add require() if length of tokenAmounts should be fixed. Use the abbreviation of the contract name to use in revert()/require() errors (later referred to as ABBR_OF_NAME). {% endhint %}

Usually, tokenAmounts are decomposed in token and amount like that:

address token = tokenAmounts[0].token;
uint256 amount = getAbsoluteAmountDeposit(tokenAmounts[0]);

{% hint style="info" %} Use getAbsoluteAmountDeposit() in deposit() function and getAbsoluteAmountWithdraw() in withdraw() function. {% endhint %}

If tokens are required to be approved, use the following function:

ERC20(token).safeApproveMax(APPROVE_RECEIVER, amount, ABBR_OF_NAME);

Get additional data (e.g. user address or the desired derivative address) required for the interaction from bytes data using abi.decode like that:

address userAddress = abi.decode(data, (address));

Interact with the protocol using try-catch syntax:

try
    Interface(callee).foo{ value: value }(arg1, arg2)
returns (returntype1, returntype2) {} catch Error(string memory reason) {
    // solhint-disable-previous-line no-empty-blocks
    revert(reason);
} catch {
    revert("ABBR_OF_NAME: deposit fail");
}

Fill in tokensToBeWithdrawn array. It should consist of tokens returning to the user (e.g. cDAI in case of deposit to Compound).

Remove names of unused arguments.

Use npx prettier ./contracts/**/*.sol --write to fix linter issues.

Add tests for interactions it test/ directory, use Uniswap, Weth, and other required adapters.