From 542c19237d9714529817a0b1218ec9497bb62823 Mon Sep 17 00:00:00 2001 From: bookland Date: Mon, 17 Jan 2022 15:02:11 -0800 Subject: [PATCH 01/11] add base for technical spec --- spec/overview.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 spec/overview.md diff --git a/spec/overview.md b/spec/overview.md new file mode 100644 index 0000000..c37c8af --- /dev/null +++ b/spec/overview.md @@ -0,0 +1,11 @@ +# Porter Protocol Technical Specification + +## Bond + +## Repayment + +## Collateral + +### Resources +https://www.auditless.com/codex/how-to-write-a-specification +https://github.com/porter-finance/litepaper#bond-implementation \ No newline at end of file From d40cb05bdb9b19b7c56818077a1d217423afa54c Mon Sep 17 00:00:00 2001 From: bookland Date: Mon, 24 Jan 2022 09:57:15 -0800 Subject: [PATCH 02/11] add basic info --- spec/overview.md | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/spec/overview.md b/spec/overview.md index c37c8af..f47d25d 100644 --- a/spec/overview.md +++ b/spec/overview.md @@ -1,11 +1,34 @@ # Porter Protocol Technical Specification -## Bond +It may help if we start with the simpliest design - no factories - no convertability - no upgradability -imagine we want to create just a single auction. -## Repayment -## Collateral +# EasyAuction +@namaskar fill this out: + +AuctionFactory +new AuctionContract(...auctionDetails, collateralAddress, collateral amount) +This creats a new contract address + +```solidity +contract AuctionFactory { + function CreateAuction(assetAddressToBorrow, maxInterestRate, termLengthDays, maxIssuanceSize, minIssuanceSize, collateralAddress, collateralAmount, convertable ) { + + } +} +``` + +# 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 -### Resources -https://www.auditless.com/codex/how-to-write-a-specification -https://github.com/porter-finance/litepaper#bond-implementation \ No newline at end of file From cc295a98f1e8cb48aabf0841c96770898cd98b96 Mon Sep 17 00:00:00 2001 From: RusseII Date: Mon, 24 Jan 2022 10:13:13 -0800 Subject: [PATCH 03/11] spelling --- spec/overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/overview.md b/spec/overview.md index f47d25d..ea05dce 100644 --- a/spec/overview.md +++ b/spec/overview.md @@ -1,6 +1,6 @@ # Porter Protocol Technical Specification -It may help if we start with the simpliest design - no factories - no convertability - no upgradability -imagine we want to create just a single auction. +It may help if we start with the simpliest design - no factories - no convertibility - no upgradability -imagine we want to create just a single auction. # EasyAuction From 16ca4fff4c0533986f35d7e8f5446674637394c2 Mon Sep 17 00:00:00 2001 From: RusseII Date: Mon, 24 Jan 2022 10:13:40 -0800 Subject: [PATCH 04/11] spelling --- spec/overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/overview.md b/spec/overview.md index ea05dce..ddf30d9 100644 --- a/spec/overview.md +++ b/spec/overview.md @@ -1,6 +1,6 @@ # Porter Protocol Technical Specification -It may help if we start with the simpliest design - no factories - no convertibility - no upgradability -imagine we want to create just a single auction. +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. # EasyAuction From 2d67281034df747c8a703cb285604667d41117e2 Mon Sep 17 00:00:00 2001 From: bookland Date: Wed, 26 Jan 2022 08:56:41 -0800 Subject: [PATCH 05/11] update easyAuction strategy --- spec/overview.md | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/spec/overview.md b/spec/overview.md index f47d25d..a568e2b 100644 --- a/spec/overview.md +++ b/spec/overview.md @@ -6,17 +6,10 @@ It may help if we start with the simpliest design - no factories - no convertabi # EasyAuction @namaskar fill this out: -AuctionFactory -new AuctionContract(...auctionDetails, collateralAddress, collateral amount) -This creats a new contract address +We should probably follow how easyAuction is implemented with a single auction contract that holds all of the auctions. + -```solidity -contract AuctionFactory { - function CreateAuction(assetAddressToBorrow, maxInterestRate, termLengthDays, maxIssuanceSize, minIssuanceSize, collateralAddress, collateralAmount, convertable ) { - } -} -``` # 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. From 728ff807941b6f740f71cfd5184c81bae62c975e Mon Sep 17 00:00:00 2001 From: bookland Date: Wed, 26 Jan 2022 11:11:39 -0800 Subject: [PATCH 06/11] add flash loan draft --- spec/overview.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/spec/overview.md b/spec/overview.md index 7456de5..5a75e30 100644 --- a/spec/overview.md +++ b/spec/overview.md @@ -25,3 +25,36 @@ Bond token is an ERC20 token. `standing` // good | defaulted | paid `maturityDate` // https://github.com/porter-finance/v1-core/issues/2 +# Flash loans for repayment +Imagine a situation where a DAO needs to pay back a 100m DAI loan. + +Let's say they have 90m DAI and 50m in deposited collateral. + +We want to enable them to repay the debt and release the collateral through a flash loan. + +Here's the sequence of events that would need to take place. This would all need to occur in a single transaction. +1. DAO uses `aave` flashloan to borrow 10m DAI +2. DAO uses 10m DAI to payback the porter debt - which releases their collateral +3. DAO withdraws with their collateral and swaps some amount of it for 10m DAI on uniswap +4. DAO repays aave 10m DAI flashloan + + + +How much is possible to borrow with a flash loan? +With AAVE it depends on their avaliable liquidity. +Current liquidity numbers (jan 26 2022): +350m DAI +670m USDC +18m sUSD +6m FEI +26m FRAX +350m USDT + + +Flash loan 2 (in progress) +1. Collateral is withdrawn +2. DAO swaps some amount of the collateral for 10m DAI with uniswap +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 + + From 3af9765d24f65126694341c8a7e1a580a3c9187d Mon Sep 17 00:00:00 2001 From: bookland Date: Wed, 26 Jan 2022 13:53:21 -0800 Subject: [PATCH 07/11] update flash loans example --- spec/overview.md | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/spec/overview.md b/spec/overview.md index 5a75e30..40cd3d8 100644 --- a/spec/overview.md +++ b/spec/overview.md @@ -25,19 +25,20 @@ Bond token is an ERC20 token. `standing` // good | defaulted | paid `maturityDate` // https://github.com/porter-finance/v1-core/issues/2 -# Flash loans for repayment -Imagine a situation where a DAO needs to pay back a 100m DAI loan. +# Flash Loans +Example: +A DAO owes 100m DAI to the porter protocol. They have 10,000 ETH (at $2000/eth, 20m USD) as collateral in the porter protocol, and $90m liquid DAI. -Let's say they have 90m DAI and 50m in deposited collateral. +The DAO can use a flash loan to liquidate part of their collateral to pay back their debt. -We want to enable them to repay the debt and release the collateral through a flash loan. - -Here's the sequence of events that would need to take place. This would all need to occur in a single transaction. -1. DAO uses `aave` flashloan to borrow 10m DAI -2. DAO uses 10m DAI to payback the porter debt - which releases their collateral +Example Transaction: +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 porter debt (which releases their collateral) 3. DAO withdraws with their collateral and swaps some amount of it for 10m DAI on uniswap 4. DAO repays aave 10m DAI flashloan +[Aave example](https://github.com/aave/code-examples-protocol/tree/main/V2/Flash%20Loan%20-%20Batch) + How much is possible to borrow with a flash loan? @@ -50,6 +51,16 @@ Current liquidity numbers (jan 26 2022): 26m FRAX 350m USDT +If a DAO needed to pay back 50m in FEI what could they do? +They could: +1. Borrow 50m USDC from aave +2. Swap 50m USDC to 50m FEI on dex +3. Pay 50m to porter to release their collateral +4. Sell their collateral for enough USDC to repay the debt to aave +5. Repay aave + + + Flash loan 2 (in progress) 1. Collateral is withdrawn From f7222bbe207a4a325cf798b71e445cacd96c9b79 Mon Sep 17 00:00:00 2001 From: bookland Date: Wed, 26 Jan 2022 15:24:21 -0800 Subject: [PATCH 08/11] add flash loan examples --- spec/overview.md | 67 +++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 38 deletions(-) diff --git a/spec/overview.md b/spec/overview.md index 40cd3d8..2ef1a09 100644 --- a/spec/overview.md +++ b/spec/overview.md @@ -26,46 +26,37 @@ Bond token is an ERC20 token. `maturityDate` // https://github.com/porter-finance/v1-core/issues/2 # Flash Loans -Example: -A DAO owes 100m DAI to the porter protocol. They have 10,000 ETH (at $2000/eth, 20m USD) as collateral in the porter protocol, and $90m liquid DAI. +DAOs can use a flash loan to liquidate part of their collateral to pay back their debt. -The DAO 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 Transaction: +### 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 porter debt (which releases their collateral) -3. DAO withdraws with their collateral and swaps some amount of it for 10m DAI on uniswap -4. DAO repays aave 10m DAI flashloan - -[Aave example](https://github.com/aave/code-examples-protocol/tree/main/V2/Flash%20Loan%20-%20Batch) - - - -How much is possible to borrow with a flash loan? -With AAVE it depends on their avaliable liquidity. -Current liquidity numbers (jan 26 2022): -350m DAI -670m USDC -18m sUSD -6m FEI -26m FRAX -350m USDT - -If a DAO needed to pay back 50m in FEI what could they do? -They could: -1. Borrow 50m USDC from aave -2. Swap 50m USDC to 50m FEI on dex -3. Pay 50m to porter to release their collateral -4. Sell their collateral for enough USDC to repay the debt to aave -5. Repay aave - - - - -Flash loan 2 (in progress) -1. Collateral is withdrawn -2. DAO swaps some amount of the collateral for 10m DAI with uniswap -3. DAO pays back their porter debt, which allows DAO to keep their collateral +2. DAO pays back their full 100m DAI porter debt (which releases their collateral) +3. DAO withdraws with their collateral and swaps some amount of it for 10m DAI on a DEX +4. DAO repays Aave 10m DAI flash loan + +### 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 + +[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. + +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 From 6ce2d283580da4980f75a6a41406741cf820cc63 Mon Sep 17 00:00:00 2001 From: bookland Date: Wed, 26 Jan 2022 15:37:19 -0800 Subject: [PATCH 09/11] clarify flash loan examples --- spec/overview.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/overview.md b/spec/overview.md index 2ef1a09..af8a25e 100644 --- a/spec/overview.md +++ b/spec/overview.md @@ -35,8 +35,9 @@ Here are two exampls of how that would work. Fees are ignored for simplicity. 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 with their collateral and swaps some amount of it for 10m DAI on a DEX +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. @@ -45,6 +46,8 @@ A DAO owes 100m FEI to the porter protocol. They have 30,000 stETH (at $2000/eth 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) From 659e8b68d7e661a96eb616aa8a4a317d532b8a05 Mon Sep 17 00:00:00 2001 From: Kyle Date: Tue, 1 Feb 2022 06:40:08 -0800 Subject: [PATCH 10/11] Add auction spec --- spec/overview.md | 80 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 7 deletions(-) diff --git a/spec/overview.md b/spec/overview.md index af8a25e..7b4bdb6 100644 --- a/spec/overview.md +++ b/spec/overview.md @@ -3,13 +3,79 @@ 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. -# EasyAuction -@namaskar fill this out: - -We should probably follow how easyAuction is implemented with a single auction contract that holds all of the auctions. - - - +# 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. + - 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 + +### Structs +``` +AuctionConfig { + IERC20 _auctioningToken + IERC20 _biddingToken + uint256 orderCancellationEndDate + uint256 auctionEndDate + uint96 _auctionedSellAmount + uint96 _minBuyAmount + uint256 minimumBiddingAmountPerOrder + uint256 minFundingThreshold + bool isAtomicClosureAllowed + 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 aucction, all three of these pices 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. From 4505a7f776dd5fa51371abcf5d7b905d3dcb0d3a Mon Sep 17 00:00:00 2001 From: Kyle Date: Tue, 1 Feb 2022 12:44:22 -0500 Subject: [PATCH 11/11] Update spec/overview.md Co-authored-by: RusseII --- spec/overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/overview.md b/spec/overview.md index 7b4bdb6..632346d 100644 --- a/spec/overview.md +++ b/spec/overview.md @@ -48,7 +48,7 @@ CollateralConfig { } ``` ### 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 aucction, all three of these pices must be valid and set when the auction begins as the lenders need to have this information. +`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 ```