Skip to content
This repository has been archived by the owner on Jan 18, 2023. It is now read-only.

STIP 006 - Trade Rebates #12

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 41 additions & 19 deletions STIPS/STIP-005.md → STIPS/STIP-006.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# STIP-005
# STIP-006
*Using template v0.1*
## Abstract
The current TradeModule and GeneralIndexModule do not support volume based fees or rebates for the manager. This is in contrast to the issuance module. There is demand for additional fee types that managers can charge, specifically to be on par with exchanges where there are rebate / volume fee discounts.

## Motivation
This feature is a new version of a TradeModule (and GeneralIndexModule) that allows the manager to charge a volume fee from their followers. This will be denominated in the output token similar to the protocol fee assessed. In contrast to centralized exchanges, the fee rebates will be automatic per trade.
This feature is a new version of a TradeModule (and GeneralIndexModule) that allows governance to specify a protocol fee and rebate split percentage which is sent to the manager's address. This will be denominated in the output token similar to the protocol fee assessed. The fee rebates will be automatic per trade.

TradeModuleV2 will be used in upcoming TokenSets deployments on other chains, and can replace the existing on Polygon and Mainnet. GeneralIndexModuleV2 can be used by index coop products to generate additional revenue

Expand All @@ -16,6 +16,7 @@ We have previously implemented the TradeModule and GeneralIndexModule. This will
- No, we can encourage in the UI instead for retail managers. This would also break for cases where the manager is a smart contract
- [ ] Should we name this TradeModuleV2 or TradeModuleWithRebates (GeneralIndexModuleV2 or GeneralIndexModuleWithRebates)?
- [ ] How do we prevent managers charging an 100% fee and rugging the Set on a trade?
- We will only allow governance to change rebate %s

## Feasibility Analysis

Expand All @@ -28,26 +29,23 @@ uint256 protocolFeeTotal = getModuleFee(TRADE_MODULE_PROTOCOL_FEE_INDEX, _exchan
```

#### Option 2
Adding a managerFee and a protocol feeSplit % (similar to DebtIssuanceModule). This will make TradeModule and GeneralIndexModule fees variable in the protocol (if a manager charges 0 fees here, then protocol will always make 0) which is a departure from TradeModule V1
Governance specifies a protocol fee % and a rebate split %. The split gives the manager a rebate on a percentage of protocol fees. Manager has no say and cannot rug.

```
uint256 protocolFeeSplit = controller.getModuleFee(address(this), ISSUANCE_MODULE_PROTOCOL_FEE_SPLIT_INDEX);
uint256 totalFeeRate = _isIssue ? setIssuanceSettings.managerIssueFee : setIssuanceSettings.managerRedeemFee;
uint256 protocolFeeSplit = controller.getModuleFee(address(this), PROTOCOL_FEE_SPLIT_INDEX);

uint256 totalFee = totalFeeRate.preciseMul(_quantity);
protocolFee = totalFee.preciseMul(protocolFeeSplit);
managerFee = totalFee.sub(protocolFee);
uint256 protocolDirectFee = controller.getModuleFee(address(this), PROTOCOL_DIRECT_FEE_SPLIT_INDEX);
protocolFee = protocolDirectFee.preciseMul(protocolFeeSplit);
rebateFee = protocolDirectFee.sub(protocolFee);
```

#### Option 3
Manager charges a managerFee that is split with the protocol based on a feeSplit % determined by governance. Additionally, the protocol can charge a direct fee % (similar to NAVIssuanceModule). This will be a superset of TradeModule fees charged
#### Recommendation
Option 4 gives us protection against rugging while providing us a base rebate mechanism. This means we will charge a protocol fee to start in order to activate rebates. E.g. start with a 10 bps protocol fee and 5 bps rebate.

```
uint256 protocolDirectFeePercent = controller.getModuleFee(address(this), _protocolDirectFeeIndex);
```
Because the rebate % is fixed by governance across all Sets, the only variable is AUM of the Set. The more user AUM vs manager AUM the more rebates managers receive (which eventually will become negative).

#### Recommendation
Option 1 will require the least code changes while giving us the ability to emulate fee rebates. The maxManagerFee can be enforced either on initialization (still susceptible to manager rugging by removing and reinitializing) or stored on the Controller by governance
#### Future work
Tiered rebates: With this base rebate mechanism, manager contracts can be built on top in the future. Individual managers will always have the ability to specify a fee recipient address as their own, but manager contracts for a specific product (e.g. social trading) can abstract away the fee recipient to a shared peripheral contract. This central trading contract tracks cumulative volume done through trading all the Sets that are linked, and perform calculations that split the rebates collected. This way, at the base module level, rebates are flat across Sets but at the manager contract level, rebates can be tiered
Copy link
Contributor

Choose a reason for hiding this comment

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

One more thing I'd add here as potential future feature is potentially updating the TradeModule to allow each Set to have its own rebate percentage (instead of a global one for now). This could be negotiated with large managers/applications that use the protocol.


## Timeline
- Spec + review: 2 days
Expand All @@ -59,16 +57,40 @@ Option 1 will require the least code changes while giving us the ability to emul
- Write docs: 1 day

## Checkpoint 1
Before more in depth design of the contract flows lets make sure that all the work done to this point has been exhaustive. It should be clear what we're doing, why, and for who. All necessary information on external protocols should be gathered and potential solutions considered. At this point we should be in alignment with product on the non-technical requirements for this feature. It is up to the reviewer to determine whether we move onto the next step.

**Reviewer**:

## Proposed Architecture Changes
A diagram would be helpful here to see where new feature slot into the system. Additionally a brief description of any new contracts is helpful.

### TradeModuleV2
- Inherit TradeModule
- Override `trade`
- Add `virtual` to TradeModule V1
Copy link
Contributor

Choose a reason for hiding this comment

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

Don't think you have to do this. Would rather not touch the V1 code.

- Add `_accrueManagerFee`
- Override constructor to add `managerRebateRecipient`
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you mean initialize?


### GeneralIndexModuleV2
- Inherit GeneralIndexModule
- Override `trade` and `tradeRemainingWETH`
- Add `virtual` to GeneralIndexModule trade functions
- Add `_accrueManagerFee`
- Override constructor to add `managerRebateRecipient`
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comments here as above


## Requirements
These should be a distillation of the previous two sections taking into account the decided upon high-level implementation. Each flow should have high level requirements taking into account the needs of participants in the flow (users, managers, market makers, app devs, etc)
- GeneralIndexModule requires no changes to the IC extension contracts except a redeployment
- External trading interfaces stay exactly the same
- Manager fee recipient automatically receives the rebate in their wallet

## User Flows
- Highlight *each* external flow enabled by this feature. It's helpful to use diagrams (add them to the `assets` folder). Examples can be very helpful, make sure to highlight *who* is initiating this flow, *when* and *why*. A reviewer should be able to pick out what requirements are being covered by this flow.
![flow diagram](../assets/tradeModuleRebates.png)
### A manager is looking to trade 10 ETH to USDC.
1. Manager calls trade() on `TradeModule` passing in the input tokens, output tokens, path, slippage tolerance, and `SushiswapExchangeAdapter` as the exchange
2. `TradeModule` gets approval and trade calldata via `SushiswapExchangeAdapter`
3. `TradeModule` calls invoke on the SetToken, with the calldata to execute an approval and trade transaction.
4. The trade is executed on Sushiswap and USDC is returned to the SetToken and validated
5. The `TradeModuleV2` calculates the protocol fee % and sends the protocol's share to the Controller fee recipient
6. The `TradeModuleV2` calculates the rebate fee % and sends the manager's share to the manager fee recipient

## Checkpoint 2
Before we spec out the contract(s) in depth we want to make sure that we are aligned on all the technical requirements and flows for contract interaction. Again the who, what, when, why should be clearly illuminated for each flow. It is up to the reviewer to determine whether we move onto the next step.

Expand Down
Binary file added assets/tradeModuleRebates.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.