Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add v0 technical spec #1

Merged
merged 12 commits into from
Feb 3, 2022
131 changes: 131 additions & 0 deletions spec/overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Porter Protocol Technical Specification

It may help if we start with the simplest design - no factories - no convertibility - no upgradability -imagine we want to create just a single auction.


# Auction
The auction contract adapts the [EasyAuction](https://github.com/gnosis/ido-contracts#easyauction) contract from Gnosis. This contract sets up, accepts bids, and pays out using a [batch auction mechanism](https://github.com/gnosis/ido-contracts#the-batch-auction-mechanism). The auction contract tracks all auctions (current, and past) via an `auctionId` and stores all relevant auction data within a `auctionData` mapping.

The basic flow is:
- An interested auctioneer will first interact with the [Bond Token](#BondToken) - Giving a configuration of bond desires. This is the token that will be awarded at the end of a successful auction. Token will then be taken into the auction contract. This token will be minted either
- At the beginning and passed into the auction itself
- Deployed and minted at successful auction settlement
- The auction contract will check that the configuration exists on that bond contract (external call).
- If that config is validated, the auction config itself will be checked. Length, minimum bid, etc.
- The auction contract will lastly check and store the collateral within the auction contract.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why do you think storing collateral in auction contract makes more sense than the collateral locker?

Copy link
Contributor

Choose a reason for hiding this comment

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

It simplifies things for now. I am not sure what would be best.

- The auction starts accepting bids.
- After the predetermined time is up, the auction ends, with all bids recorded.
- The auction is settled, statuses updated to complete, and the winners can claim their order amount.
- Winners pull from their successful orders
- Bidding tokens are pushed to the auctioneer
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why is this push instead of pull?

Copy link
Contributor

Choose a reason for hiding this comment

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


### Structs
```
AuctionConfig {
IERC20 _auctioningToken
IERC20 _biddingToken
uint256 orderCancellationEndDate
uint256 auctionEndDate
uint96 _auctionedSellAmount
uint96 _minBuyAmount
uint256 minimumBiddingAmountPerOrder
uint256 minFundingThreshold
bool isAtomicClosureAllowed
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you understand why anyone would use isAtomicClosureAllowed?

Copy link
Contributor

Choose a reason for hiding this comment

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

I found this

atomic-closure This parameter enables users to close the auction atomically and submit a final bid by calling the settleAuctionAtomically function in the smart contract once the auction-end-date has been reached. The auctioneer determines whether this parameter is on or off by specifying True or False.
This makes sense mainly for tokens with existing liquidity sources and is less suitable for IDOs.

address accessManagerContract
bytes memory accessManagerContractData
}
```
```
BondConfig {
uint256 maturityDate
bool isConvertible
}
```
```
CollateralConfig {
IERC20 collateralToken
uint256 collateralAmount
}
```
### Methods
`initiateAuction()` The entry-point which is called by a borrower to start the auction process. This function accepts an auction config, bond config, and collateral config. This is because in order to have a valid auction, all three of these pieces must be valid and set when the auction begins as the lenders need to have this information.

Parameters
```
AuctionConfig auctionConfig
CollateralConfig collateralConfig
BondConfig bondConfig
```

`placeBid()` This function is called by a borrower to place a bid. The borrower must have enough tokens to cover the bid.

Parameters
```
uint256 auctionId
uint96[] memory _minBuyAmounts
uint96[] memory _sellAmounts
bytes32[] memory _prevSellOrders
bytes calldata allowListCallData
```
`cancelSellOrders()` If the `orderCancellationEndDate` has not passed, this function can be called by a bidder to cancel their sell order(s).

Parameters
```
uint256 auctionId
bytes32[] memory _sellOrders
```

`getAuctionConfig() view returns(AuctionConfig, BondConfig, CollateralConfig)` This function returns the auction config for a given auction.

# BondToken
Upon the completion of a successful auction a new bond contract is deployed. Terms of the bond were determined by the auction. Bond tokens need minted and sent to investors who won the auction.

Bond token is an ERC20 token.

### Methods
`mint()` `isAuction` // callable by the auction contract to mint bond tokens and send them to investors who won the auction

`redeem()` checks maturity date & bond standing - if it's past maturity date and the loan as been repayed then burn the bonds and send the repayment tokens to the address calling redeem() - maybe we follow the rocketpool method and calculate the % of total bond tokens a user holds, then allow them to claim that % amount of the total repayment tokens

### State Variables
`standing` // good | defaulted | paid
`maturityDate` // https://github.com/porter-finance/v1-core/issues/2

# Flash Loans
DAOs can use a flash loan to liquidate part of their collateral to pay back their debt.

## Examples
Here are two exampls of how that would work. Fees are ignored for simplicity.

### Example 1:
A DAO owes 100m DAI to the porter protocol. They have 10,000 stETH (at $2000/eth, 20m USD) as collateral in the porter protocol. They also have 90m liquid DAI in their treasury.
1. DAO uses [Aave Flash Loan](https://docs.aave.com/developers/guides/flash-loans) to borrow 10m DAI
2. DAO pays back their full 100m DAI porter debt (which releases their collateral)
3. DAO withdraws their collateral and swaps some amount of it for 10m DAI on a DEX
4. DAO repays Aave 10m DAI flash loan
5. DAO now has their porter debt repaid and has their remaining collateral

### Example 2:
A DAO owes 100m FEI to the porter protocol. They have 30,000 stETH (at $2000/eth, 60m USD) as collateral in the porter protocol, and $70m liquid FEI in their treasury.
1. There is not enough FEI liquidity in Aave to take out a 30m FEI flash loan so the DAO takes out a 30m USDC flash loan
2. DAO swaps 30m USDC for 30m FEI on a DEX
3. DAO pays back their full 100m porter debt (which releases their collateral)
4. DAO withdraws with their collateral and swaps some amount of it for 30m FEI on a DEX
5. DAO repays Aave 30m FEI flash loan
6. DAO now has their porter debt repaid and has their remaining collateral


[Aave flash loan example](https://github.com/aave/code-examples-protocol/tree/main/V2/Flash%20Loan%20-%20Batch)

## Flash Loan alternatives considered
Implementing flash loans in our protocol.
Namaskar-1F64F marked this conversation as resolved.
Show resolved Hide resolved

Example 3: \
A DAO owes 100m DAI to the porter protocol. They have 10,000 stETH (at $2000/eth, 20m USD) as collateral in the porter protocol, and $90m liquid DAI in their treasury.
1. DAO withdraws their collateral
2. DAO swaps some amount of the collateral for 10m DAI with a DEX
3. DAO pays back their porter debt, which allows DAO to keep their collateral
4. If they don't pay back the debt in the same transaction everything is reverted

Pros: Avoid .09% aave fee \
Cons: Would need to add flash loan logic to our protocol vs leveraging an existing one