Oracle free peer to peer perpetual lending Before diving into the codebase and this implementation of the Blend lending protocol, it is recommended that you read the original paper by Paradigm and Blur: https://www.paradigm.xyz/2023/05/blend#continuous-loans
All contracts in
src are in scope.
src/ ├── Beedle.sol ├── Fees.sol ├── Lender.sol ├── Staking.sol ├── interfaces │ ├── IERC20.sol │ └── ISwapRouter.sol └── utils ├── Errors.sol ├── Ownable.sol └── Structs.sol
Oracle free peer to peer perpetual lending
Before diving into the codebase and this implementation of the Blend lending protocol, it is recommended that you read the original paper by Paradigm and Blur
forge install OpenZeppelin/openzeppelin-contracts
forge install vectorized/solady
first copy the
.example.env file and create your own
forge script script/LenderScript.s.sol:LenderScript --rpc-url $GOERLI_RPC_URL --broadcast --verify -vvvv
Lender is the main singleton contract for Beedle. It handles all borrowing, repayment, and refinancing.
In order to be a lender you must create a lending pool. Lending pools are based on token pairs and any lender can have one pool per lending pair. When creating a pool, lenders choose several key inputs
loanToken - the token they are lending out
collateralToken - the token they are taking in as collateral
minLoanSize - the minimum loan size they are willing to take (this is to prevent griefing a lender with dust loans)
poolBalance - the amount of
loanToken they want to deposit into the pool
maxLoanRatio - the highest LTV they are willing to take on the loan (this is multiplied by 10^18)
auctionLength - the length of liquidation auctions for their loans
interestRate - the interest rate they charge for their loans
After creating a pool, lenders can update these values at any time.
Once lending pools are created by lenders, anyone can borrow from a pool. When borrowing you will choose your
loanRatio (aka LTV) and the amount you want to borrow. Most other loan parameters are set by the pool creator and not the borrower. After borrowing from a pool there are several things that can happen which we will break down next.
RepayingRepayment is the most simple of all outcomes. When a user repays their loan, they send back the principal and any interest accrued. The repayment goes back to the lenders pool and the user gets their collateral back.
RefinancingRefinancing can only be called by the borrower. In a refinance, the borrower is able to move their loan to a new pool under new lending conditions. The contract does not force the borrower to fully repay their debt when moving potisitions. When refinancing, you must maintain the same loan and collateral tokens, but otherwise, all other parameters are able to be changed.
Giving A LoanWhen a lender no longer desires to be lending anymore they have two options. They can either send the loan into a liquidation auction (which we will get into next) or they can give the loan to another lender. Lenders can give away their loan at any point so long as, the pool they are giving it to offers same or better lending terms.
Auctioning A LoanWhen a lender no longer wants to be in a loan, but there is no lending pool available to give the loan to, lenders are able to put the loan up for auction. This is a Dutch Auction where the variable changing over time is the interest rate and it is increasing linearly. Anyone is able to match an active pool with a live auction when the parameters of that pool match that of the auction or are more favorable to the borrower. This is called buying the loan. If the auction finishes without anyone buying the loan, the loan is liquidated. Then the lender is able to withdraw the borrowers collateral and the loan is closed.
This is a contract based on the code of
yveCRV originally created by Andre Cronje. It tracks user balances over time and updates their share of a distribution on deposits and withdraws.