Skip to content

Conversation

bergben
Copy link

@bergben bergben commented Aug 31, 2022

Implements flash mint functionality for Set tokens with wrapped components.
Wrapping info is passed in as calldata. Only allowlisted wrap-callTargets are enabled (and when wrap callTarget == set token component, e.g. for CompoundV2).
Uses wrap adapters directly, only the integrationName is passed in which is used to fetch the wrap adapter directly from the IntegrationRegistry.
This Flash mint contract is generalized and can be used for any protocol, given that WrapAdapters behave the same way.

This contract also supports flash minting for Set tokens that contain both unwrapped and wrapped components (technically speaking it would even support token sets with no wrapped components at all).
Does not support debt positions on Set token.
Wrapping / Unwrapping is skipped for a component if ComponentSwapData[component_index].underlyingERC20 address == set component address.

If the set contains both the wrapped and unwrapped version of a token (e.g. DAI and cDAI) -> two separate component data points have to be supplied in _swapData and _wrapData
e.g. for issue
Set components at index 0 = DAI; then -> ComponentSwapData[0].underlyingERC20 = DAI; (no wrapping will happen)
Set components at index 1 = cDAI; then -> ComponentSwapData[1].underlyingERC20 = DAI; (wrapping will happen)

Compatible with:
IssuanceModules: DebtIssuanceModule, DebtIssuanceModuleV2, IWrapV2Adapter

Caveat
There might be cases where some wrapped components dust may stay in the flashMintContract because the exchange rate or swap rate might change a tiny bit. Setting a tiny tolerance is the task of the caller...
There is still the check of maxAmountInputSpent / minAmountOutput
This is because the exchange rate from wrapped to unwrapped is used for computation of the actual amounts moments before the actual transaction with the input data is triggered.
This could only be solved by passing in a selector method that returns the exchange rate for each wrapped token (to directly compute everything just-in-time on-chain). It gets complicated... and costs more gas...
The contract is withdrawable, so that dust can be collected

@bergben
Copy link
Author

bergben commented Aug 31, 2022

@FlattestWhite could you give this a first look? Is it in line with the thoughts you had for the implementation of this?

I yet have to implement the tests

@bergben bergben marked this pull request as ready for review September 12, 2022 19:37
@bergben
Copy link
Author

bergben commented Sep 12, 2022

@FlattestWhite I changed the description of the PR. Please have a look at the caveat and let me know what you think...

Copy link
Collaborator

@ckoopmann ckoopmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using user provided calldata seems dangerous to me, especially when the calltarget is an erc20 token.
In general there seem to be a few places where we might need additional checks to make sure that attackers can't steal leftover transactions from previous issuance / redemption transactions.

Otherwise great work though 👍

@bergben
Copy link
Author

bergben commented Sep 15, 2022

@FlattestWhite @ckoopmann FYI
This are the results for transaction fee comparison (in Gwei on localhost, not accurate but should give an idea):
Note that this does not include the necessary additional check discussed in this PR for redemption

#issueExactSetFromETH: paying with ETH
1097542 Direct wrap adapters
1069513 Wrap call data

#issueExactSetFromERC20: paying with USDC
1121616 Direct wrap adapters
1093689 Wrap call data

#issueExactSetFromERC20: paying with DAI
1130365 Direct wrap adapters
1102438 Wrap call data

#redeemExactSetForETH: receiving ETH
1016465 Direct wrap adapters
982453 Wrap call data

#redeemExactSetForERC20: receiving USDC
996310 Direct wrap adapters
962363 Wrap call data

#redeemExactSetForERC20: receiving DAI
1055592 Direct wrap adapters
1021645 Wrap call data

@bergben bergben requested review from FlattestWhite and removed request for FlattestWhite September 15, 2022 19:41
@bergben bergben requested a review from ckoopmann September 15, 2022 19:41
Copy link
Collaborator

@ckoopmann ckoopmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Also thanks for the detailed gas analysis 👍

@FlattestWhite FlattestWhite self-requested a review September 18, 2022 02:45
Copy link
Contributor

@FlattestWhite FlattestWhite left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

had one question but other than that lgtm

@bergben
Copy link
Author

bergben commented Sep 20, 2022

@FlattestWhite fixed everything you pointed out and added test cases for

  • Set token with only unwrapped components
  • Set token with mixed components (cDAI, USDC, cUSDT)

@FlattestWhite FlattestWhite merged commit 4e117b6 into IndexCoop:feat/FlashMintCompound Sep 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants