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

Commit

Permalink
merged from master (#622)
Browse files Browse the repository at this point in the history
  • Loading branch information
EdNoepel authored Feb 16, 2023
1 parent d640979 commit 0361cfc
Show file tree
Hide file tree
Showing 109 changed files with 8,548 additions and 4,275 deletions.
37 changes: 37 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

<!---
No need to add special tag
src/ & non src/ changes you need the following (that apply):
-->
# Description of change
## High level
* <DESCRIP_OF_CHANGE>
* <DESCRIP_OF_SUBCHANGE>

<!---
Add the `Status: Needs Auditor Approval` tags
CHANGES IN /SRC DIR:
- renaming (not retyping or resizing) of variables & methods
- reordering and moving of functions in files
- lite moving of functions accross files
- comments
src/ changes you need the following (that apply):
-->

# Description of bug or vulnerability and solution
* <PARAGRAPH_EXP_OF_VULN_BUG>
* <PARAGRAPH_EXP_OF_HOW_CHANGE_SOLVES_VULN_OR_BUG>

# Contract size
## Pre Change
<PASTE_OUTPUT_HERE>
## Post Change
<PASTE_OUTPUT_HERE>

# Gas usage
## Pre Change
<PASTE_OUTPUT_HERE>
## Post Change
<PASTE_OUTPUT_HERE>

2 changes: 1 addition & 1 deletion .github/workflows/code-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:

# Report code coverage to discord
- name: Generate coverage
run: forge coverage --report lcov --no-match-test testLoad
run: forge coverage --report lcov --no-match-test "testLoad|invariant"
- name: Setup LCOV
uses: hrishikesh-kadam/setup-lcov@v1
- name: Filter lcov
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ reports/
coverage/
*.info
report/
keystore/
keystore/
broadcast/
7 changes: 4 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ install :; git submodule update --init --recursive
build :; forge clean && forge build

# Tests
test :; forge test --no-match-test testLoad # --ffi # enable if you need the `ffi` cheat code on HEVM
test-with-gas-report :; FOUNDRY_PROFILE=optimized forge test --no-match-test testLoad --gas-report # --ffi # enable if you need the `ffi` cheat code on HEVM
test :; forge test --no-match-test "testLoad|invariant" # --ffi # enable if you need the `ffi` cheat code on HEVM
test-with-gas-report :; FOUNDRY_PROFILE=optimized forge test --no-match-test "testLoad|invariant" --gas-report # --ffi # enable if you need the `ffi` cheat code on HEVM
test-load :; FOUNDRY_PROFILE=optimized forge test --match-test testLoad --gas-report
coverage :; forge coverage --no-match-test testLoad
test-invariant :; forge t --mt invariant
coverage :; forge coverage --no-match-test "testLoad|invariant"

# Generate Gas Snapshots
snapshot :; forge clean && forge snapshot
Expand Down
2 changes: 1 addition & 1 deletion check-code-coverage.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

forge coverage --report lcov --no-match-test testLoad
forge coverage --report lcov --no-match-test "testLoad|invariant"

lcov -r lcov.info "tests/*" -o lcov-filtered.info --rc lcov_branch_coverage=1

Expand Down
4 changes: 2 additions & 2 deletions docs/Functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@

emit events:
- LenderActions.transferLPs():
- TransferLPTokens
- TransferLPs

### kick
external libraries call:
Expand Down Expand Up @@ -370,7 +370,7 @@
- BorrowerActions.drawDebt()
- borrower not sender BorrowerNotSender()
- borrower debt less than pool min debt AmountLTMinDebt()
- limit price reached LimitIndexReached()
- limit price reached LimitIndexExceeded()
- borrower cannot draw more debt BorrowerUnderCollateralized()

emit events:
Expand Down
6 changes: 6 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ optimizer_runs = 200

[fuzz]
runs = 300

[invariant]
runs = 10 # The number of calls to make in the invariant tests
depth = 100 # The number of times to run the invariant tests
call_override = false # Override calls
fail_on_revert = false # Fail the test if the contract reverts
112 changes: 37 additions & 75 deletions src/ERC20Pool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ import { IERC20Taker } from './interfaces/pool/erc20/IERC20Taker.sol';

import {
IPoolLenderActions,
IPoolLiquidationActions,
IERC20Token
IPoolLiquidationActions
} from './interfaces/pool/IPool.sol';
import {
IERC3156FlashBorrower,
Expand All @@ -39,7 +38,10 @@ import {
_roundToScale,
_roundUpToScale
} from './libraries/helpers/PoolHelper.sol';
import { _revertIfAuctionClearable } from './libraries/helpers/RevertsHelper.sol';
import {
_revertIfAuctionClearable,
_revertOnExpiry
} from './libraries/helpers/RevertsHelper.sol';

import { Loans } from './libraries/internal/Loans.sol';
import { Deposits } from './libraries/internal/Deposits.sol';
Expand Down Expand Up @@ -165,7 +167,7 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {

if (amountToBorrow_ != 0) {
// update pool balances state
poolBalances.t0Debt += result.t0DebtChange;
poolBalances.t0Debt = result.t0PoolDebt;

// move borrowed amount from pool to sender
_transferQuoteToken(msg.sender, amountToBorrow_);
Expand All @@ -184,7 +186,9 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {
function repayDebt(
address borrowerAddress_,
uint256 maxQuoteTokenAmountToRepay_,
uint256 collateralAmountToPull_
uint256 collateralAmountToPull_,
address collateralReceiver_,
uint256 limitIndex_
) external nonReentrant {
PoolState memory poolState = _accruePoolInterest();

Expand All @@ -200,7 +204,8 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {
poolState,
borrowerAddress_,
maxQuoteTokenAmountToRepay_,
collateralAmountToPull_
collateralAmountToPull_,
limitIndex_
);

emit RepayDebt(borrowerAddress_, result.quoteTokenToRepay, collateralAmountToPull_, result.newLup);
Expand All @@ -212,7 +217,7 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {

if (result.quoteTokenToRepay != 0) {
// update pool balances state
poolBalances.t0Debt -= result.t0RepaidDebt;
poolBalances.t0Debt = result.t0PoolDebt;
if (result.t0DebtInAuctionChange != 0) {
poolBalances.t0DebtInAuction -= result.t0DebtInAuctionChange;
}
Expand All @@ -224,52 +229,8 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {
// update pool balances state
poolBalances.pledgedCollateral = result.poolCollateral;

// move collateral from pool to sender
_transferCollateral(msg.sender, collateralAmountToPull_);
}
}

/************************************/
/*** Flashloan External Functions ***/
/************************************/

/// @inheritdoc FlashloanablePool
function flashLoan(
IERC3156FlashBorrower receiver_,
address token_,
uint256 amount_,
bytes calldata data_
) external override(IERC3156FlashLender, FlashloanablePool) nonReentrant returns (bool) {
if (token_ == _getArgAddress(QUOTE_ADDRESS)) return _flashLoanQuoteToken(receiver_, token_, amount_, data_);

if (token_ == _getArgAddress(COLLATERAL_ADDRESS)) {
_transferCollateral(address(receiver_), amount_);

if (receiver_.onFlashLoan(msg.sender, token_, amount_, 0, data_) !=
keccak256("ERC3156FlashBorrower.onFlashLoan")) revert FlashloanCallbackFailed();

_transferCollateralFrom(address(receiver_), amount_);
return true;
}

revert FlashloanUnavailableForToken();
}

/// @inheritdoc FlashloanablePool
function flashFee(
address token_,
uint256
) external pure override(IERC3156FlashLender, FlashloanablePool) returns (uint256) {
if (token_ == _getArgAddress(QUOTE_ADDRESS) || token_ == _getArgAddress(COLLATERAL_ADDRESS)) return 0;
revert FlashloanUnavailableForToken();
}

/// @inheritdoc FlashloanablePool
function maxFlashLoan(
address token_
) external view override(IERC3156FlashLender, FlashloanablePool) returns (uint256 maxLoan_) {
if (token_ == _getArgAddress(QUOTE_ADDRESS) || token_ == _getArgAddress(COLLATERAL_ADDRESS)) {
maxLoan_ = IERC20Token(token_).balanceOf(address(this));
// move collateral from pool to address specified as collateral receiver
_transferCollateral(collateralReceiver_, collateralAmountToPull_);
}
}

Expand All @@ -286,8 +247,10 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {
*/
function addCollateral(
uint256 amountToAdd_,
uint256 index_
uint256 index_,
uint256 expiry_
) external override nonReentrant returns (uint256 bucketLPs_) {
_revertOnExpiry(expiry_);
PoolState memory poolState = _accruePoolInterest();

// revert if the dust amount was not exceeded, but round on the scale amount
Expand Down Expand Up @@ -359,12 +322,11 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {
) external override nonReentrant {
PoolState memory poolState = _accruePoolInterest();

uint256 assets = Maths.wmul(poolBalances.t0Debt, poolState.inflator) + _getPoolQuoteTokenBalance();
uint256 assets = Maths.wmul(poolBalances.t0Debt, poolState.inflator) + _getNormalizedPoolQuoteTokenBalance();

uint256 liabilities = Deposits.treeSum(deposits) + auctions.totalBondEscrowed + reserveAuction.unclaimed;

(
,
,
uint256 collateralSettled,
uint256 t0DebtSettled
Expand Down Expand Up @@ -427,18 +389,11 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {
result.quoteTokenAmount = _roundUpToScale(result.quoteTokenAmount, _getArgUint256(QUOTE_SCALE));

// update pool balances state
uint256 t0PoolDebt = poolBalances.t0Debt;
uint256 t0DebtInAuction = poolBalances.t0DebtInAuction;

if (result.t0DebtPenalty != 0) {
t0PoolDebt += result.t0DebtPenalty;
t0DebtInAuction += result.t0DebtPenalty;
}

t0PoolDebt -= result.t0RepayAmount;
t0DebtInAuction += result.t0DebtPenalty;
t0DebtInAuction -= result.t0DebtInAuctionChange;

poolBalances.t0Debt = t0PoolDebt;
poolBalances.t0Debt = result.t0PoolDebt;
poolBalances.t0DebtInAuction = t0DebtInAuction;
poolBalances.pledgedCollateral -= result.collateralAmount;

Expand All @@ -457,7 +412,7 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {
);
}

_transferQuoteTokenFrom(callee_, result.quoteTokenAmount);
_transferQuoteTokenFrom(msg.sender, result.quoteTokenAmount);
}

/**
Expand Down Expand Up @@ -488,18 +443,11 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {
);

// update pool balances state
uint256 t0PoolDebt = poolBalances.t0Debt;
uint256 t0DebtInAuction = poolBalances.t0DebtInAuction;

if (result.t0DebtPenalty != 0) {
t0PoolDebt += result.t0DebtPenalty;
t0DebtInAuction += result.t0DebtPenalty;
}

t0PoolDebt -= result.t0RepayAmount;
t0DebtInAuction += result.t0DebtPenalty;
t0DebtInAuction -= result.t0DebtInAuctionChange;

poolBalances.t0Debt = t0PoolDebt;
poolBalances.t0Debt = result.t0PoolDebt;
poolBalances.t0DebtInAuction = t0DebtInAuction;
poolBalances.pledgedCollateral -= result.collateralAmount;

Expand All @@ -509,6 +457,20 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {
_updateInterestState(poolState, result.newLup);
}

/***************************/
/*** Flashloan Functions ***/
/***************************/

/**
* @inheritdoc FlashloanablePool
* @dev Override default implementation and allows flashloans for both quote and collateral token.
*/
function _isFlashloanSupported(
address token_
) internal virtual view override returns (bool) {
return token_ == _getArgAddress(QUOTE_ADDRESS) || token_ == _getArgAddress(COLLATERAL_ADDRESS);
}

/************************/
/*** Helper Functions ***/
/************************/
Expand Down
8 changes: 5 additions & 3 deletions src/ERC20PoolFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ pragma solidity 0.8.14;

import { ClonesWithImmutableArgs } from '@clones/ClonesWithImmutableArgs.sol';

import { IERC20PoolFactory } from './interfaces/pool/erc20/IERC20PoolFactory.sol';

import { IERC20PoolFactory } from './interfaces/pool/erc20/IERC20PoolFactory.sol';
import { IPoolFactory } from './interfaces/pool/IPoolFactory.sol';
import { IERC20Token, PoolType } from './interfaces/pool/IPool.sol';

import { ERC20Pool } from './ERC20Pool.sol';
Expand Down Expand Up @@ -49,7 +49,9 @@ contract ERC20PoolFactory is PoolDeployer, IERC20PoolFactory {
*/
function deployPool(
address collateral_, address quote_, uint256 interestRate_
) external canDeploy(ERC20_NON_SUBSET_HASH, collateral_, quote_, interestRate_) returns (address pool_) {
) external canDeploy(collateral_, quote_, interestRate_) returns (address pool_) {
if (deployedPools[ERC20_NON_SUBSET_HASH][collateral_][quote_] != address(0)) revert IPoolFactory.PoolAlreadyExists();

uint256 quoteTokenScale = 10 ** (18 - IERC20Token(quote_).decimals());
uint256 collateralScale = 10 ** (18 - IERC20Token(collateral_).decimals());

Expand Down
Loading

0 comments on commit 0361cfc

Please sign in to comment.