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

Fix forge docs #750

Merged
merged 13 commits into from
Apr 20, 2023
3 changes: 3 additions & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
book*
src/
solidity.min.js
127 changes: 71 additions & 56 deletions src/ERC20Pool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,17 @@ import { TakerActions } from './libraries/external/TakerActions.sol';

/**
* @title ERC20 Pool contract
* @notice Entrypoint of ERC20 Pool actions for pool actors:
* - Lenders: add, remove and move quote tokens; transfer LP
* - Borrowers: draw and repay debt
* - Traders: add, remove and move quote tokens; add and remove collateral
* - Kickers: kick undercollateralized loans; settle auctions; claim bond rewards
* - Bidders: take auctioned collateral
* - Reserve purchasers: start auctions; take reserves
* - Flash borrowers: initiate flash loans on quote tokens and collateral
* @dev Contract is FlashloanablePool with flash loan logic.
* @dev Contract is base Pool with logic to handle ERC20 collateral.
* @dev Calls logic from external PoolCommons, LenderActions, BorrowerActions and auction actions libraries.
* @notice Entrypoint of `ERC20` Pool actions for pool actors:
* - `Lenders`: add, remove and move quote tokens; transfer `LP`
* - `Borrowers`: draw and repay debt
* - `Traders`: add, remove and move quote tokens; add and remove collateral
* - `Kickers`: kick undercollateralized loans; settle auctions; claim bond rewards
* - `Bidders`: take auctioned collateral
* - `Reserve purchasers`: start auctions; take reserves
* - `Flash borrowers`: initiate flash loans on quote tokens and collateral
* @dev Contract is `FlashloanablePool` with flash loan logic.
* @dev Contract is base `Pool` with logic to handle `ERC20` collateral.
* @dev Calls logic from external `PoolCommons`, `LenderActions`, `BorrowerActions` and `Auction` actions libraries.
*/
contract ERC20Pool is FlashloanablePool, IERC20Pool {
using SafeERC20 for IERC20;
Expand All @@ -76,7 +76,7 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {
/*** Constants ***/
/*****************/

// immutable args offset
/// @dev Immutable collateral scale arg offset.
grandizzy marked this conversation as resolved.
Show resolved Hide resolved
uint256 internal constant COLLATERAL_SCALE = 93;

/****************************/
Expand Down Expand Up @@ -111,8 +111,8 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {
}

/// @inheritdoc IERC20Pool
function bucketCollateralDust(uint256 bucketIndex) external pure override returns (uint256) {
return _bucketCollateralDust(bucketIndex);
function bucketCollateralDust(uint256 bucketIndex_) external pure override returns (uint256) {
return _bucketCollateralDust(bucketIndex_);
}

/***********************************/
Expand All @@ -121,12 +121,12 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {

/**
* @inheritdoc IERC20PoolBorrowerActions
* @dev write state:
* - decrement poolBalances.t0DebtInAuction accumulator
* - increment poolBalances.pledgedCollateral accumulator
* - increment poolBalances.t0Debt accumulator
* @dev emit events:
* - DrawDebt
* @dev === Write state ===
* @dev - decrement `poolBalances.t0DebtInAuction` accumulator
* @dev - increment `poolBalances.pledgedCollateral` accumulator
* @dev - increment `poolBalances.t0Debt` accumulator
grandizzy marked this conversation as resolved.
Show resolved Hide resolved
* @dev === Emit events ===
* @dev - `DrawDebt`
*/
function drawDebt(
address borrowerAddress_,
Expand Down Expand Up @@ -189,12 +189,12 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {

/**
* @inheritdoc IERC20PoolBorrowerActions
* @dev write state:
* - decrement poolBalances.t0Debt accumulator
* - decrement poolBalances.t0DebtInAuction accumulator
* - decrement poolBalances.pledgedCollateral accumulator
* @dev emit events:
* - RepayDebt
* @dev === Write state ===
* @dev - decrement `poolBalances.t0Debt accumulator`
* @dev - decrement `poolBalances.t0DebtInAuction accumulator`
* @dev - decrement `poolBalances.pledgedCollateral accumulator`
* @dev === Emit events ===
* @dev - `RepayDebt`
grandizzy marked this conversation as resolved.
Show resolved Hide resolved
*/
function repayDebt(
address borrowerAddress_,
Expand Down Expand Up @@ -262,31 +262,31 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {

/**
* @inheritdoc IERC20PoolLenderActions
* @dev reverts on:
* - DustAmountNotExceeded()
* @dev emit events:
* - AddCollateral
* @dev === Reverts on ===
* @dev - `DustAmountNotExceeded()`
* @dev === Emit events ===
* @dev - `AddCollateral`
*/
function addCollateral(
uint256 amountToAdd_,
uint256 index_,
uint256 expiry_
) external override nonReentrant returns (uint256 bucketLPs_) {
) external override nonReentrant returns (uint256 bucketLP_) {
_revertOnExpiry(expiry_);
PoolState memory poolState = _accruePoolInterest();

// revert if the dust amount was not exceeded, but round on the scale amount
if (amountToAdd_ != 0 && amountToAdd_ < _bucketCollateralDust(index_)) revert DustAmountNotExceeded();
amountToAdd_ = _roundToScale(amountToAdd_, _getArgUint256(COLLATERAL_SCALE));

bucketLPs_ = LenderActions.addCollateral(
bucketLP_ = LenderActions.addCollateral(
buckets,
deposits,
amountToAdd_,
index_
);

emit AddCollateral(msg.sender, index_, amountToAdd_, bucketLPs_);
emit AddCollateral(msg.sender, index_, amountToAdd_, bucketLP_);

// update pool interest rate state
_updateInterestState(poolState, Deposits.getLup(deposits, poolState.debt));
Expand All @@ -297,34 +297,34 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {

/**
* @inheritdoc IPoolLenderActions
* @dev emit events:
* - RemoveCollateral
* @dev === Emit events ===
* @dev - `RemoveCollateral`
*/
function removeCollateral(
uint256 maxAmount_,
uint256 index_
) external override nonReentrant returns (uint256 collateralAmount_, uint256 lpAmount_) {
) external override nonReentrant returns (uint256 removedAmount_, uint256 redeemedLP_) {
_revertIfAuctionClearable(auctions, loans);

PoolState memory poolState = _accruePoolInterest();

// round the collateral amount appropriately based on token precision
maxAmount_ = _roundToScale(maxAmount_, _getArgUint256(COLLATERAL_SCALE));

(collateralAmount_, lpAmount_) = LenderActions.removeMaxCollateral(
(removedAmount_, redeemedLP_) = LenderActions.removeMaxCollateral(
buckets,
deposits,
maxAmount_,
index_
);

emit RemoveCollateral(msg.sender, index_, collateralAmount_, lpAmount_);
emit RemoveCollateral(msg.sender, index_, removedAmount_, redeemedLP_);

// update pool interest rate state
_updateInterestState(poolState, Deposits.getLup(deposits, poolState.debt));

// move collateral from pool to lender
_transferCollateral(msg.sender, collateralAmount_);
_transferCollateral(msg.sender, removedAmount_);
}

/*******************************/
Expand All @@ -333,10 +333,10 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {

/**
* @inheritdoc IPoolSettlerActions
* @dev write state:
* - decrement poolBalances.t0Debt accumulator
* - decrement poolBalances.t0DebtInAuction accumulator
* - decrement poolBalances.pledgedCollateral accumulator
* @dev === Write state ===
* @dev - decrement `poolBalances.t0Debt` accumulator
* @dev - decrement `poolBalances.t0DebtInAuction` accumulator
* @dev - decrement `poolBalances.pledgedCollateral` accumulator
*/
function settle(
address borrowerAddress_,
Expand Down Expand Up @@ -380,14 +380,14 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {

/**
* @inheritdoc IPoolTakerActions
* @dev write state:
* - decrement poolBalances.t0Debt accumulator
* - decrement poolBalances.t0DebtInAuction accumulator
* - decrement poolBalances.pledgedCollateral accumulator
* @dev === Write state ===
* @dev - decrement `poolBalances.t0Debt` accumulator
* @dev - decrement `poolBalances.t0DebtInAuction` accumulator
* @dev - decrement `poolBalances.pledgedCollateral` accumulator
*/
function take(
address borrowerAddress_,
uint256 collateral_,
uint256 maxAmount_,
grandizzy marked this conversation as resolved.
Show resolved Hide resolved
address callee_,
bytes calldata data_
) external override nonReentrant {
Expand All @@ -396,7 +396,7 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {
uint256 collateralDust = _bucketCollateralDust(0);

// round requested collateral to an amount which can actually be transferred
collateral_ = _roundToScale(collateral_, collateralDust);
maxAmount_ = _roundToScale(maxAmount_, collateralDust);

TakeResult memory result = TakerActions.take(
auctions,
Expand All @@ -405,7 +405,7 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {
loans,
poolState,
borrowerAddress_,
collateral_,
maxAmount_,
collateralDust
);
// round quote token up to cover the cost of purchasing the collateral
Expand Down Expand Up @@ -449,10 +449,10 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {

/**
* @inheritdoc IPoolTakerActions
* @dev write state:
* - decrement poolBalances.t0Debt accumulator
* - decrement poolBalances.t0DebtInAuction accumulator
* - decrement poolBalances.pledgedCollateral accumulator
* @dev === Write state ===
* @dev - decrement `poolBalances.t0Debt` accumulator
* @dev - decrement `poolBalances.t0DebtInAuction` accumulator
* @dev - decrement `poolBalances.pledgedCollateral` accumulator
*/
function bucketTake(
address borrowerAddress_,
Expand Down Expand Up @@ -516,17 +516,32 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool {
/*** Helper Functions ***/
/************************/

/**
* @notice Helper function to transfer amount of collateral tokens (in collateral token precision) from sender to pool contract.
* @param from_ Sender address.
* @param amount_ Amount to transfer from sender.
*/
function _transferCollateralFrom(address from_, uint256 amount_) internal {
IERC20(_getArgAddress(COLLATERAL_ADDRESS)).safeTransferFrom(from_, address(this), amount_ / _getArgUint256(COLLATERAL_SCALE));
}

/**
* @notice Helper function to transfer amount of collateral tokens (in collateral token precision) from pool contract.
* @param to_ Receiver address.
* @param amount_ Amount to transfer to receiver.
*/
function _transferCollateral(address to_, uint256 amount_) internal {
IERC20(_getArgAddress(COLLATERAL_ADDRESS)).safeTransfer(to_, amount_ / _getArgUint256(COLLATERAL_SCALE));
}

function _bucketCollateralDust(uint256 bucketIndex) internal pure returns (uint256) {
/**
* @notice Helper function to calculate the minimum amount of collateral an actor may have in a bucket.
* @param bucketIndex_ Bucket index.
* @return Amount of collateral dust amount of the bucket.
*/
function _bucketCollateralDust(uint256 bucketIndex_) internal pure returns (uint256) {
// price precision adjustment will always be 0 for encumbered collateral
uint256 pricePrecisionAdjustment = _getCollateralDustPricePrecisionAdjustment(bucketIndex);
uint256 pricePrecisionAdjustment = _getCollateralDustPricePrecisionAdjustment(bucketIndex_);
// difference between the normalized scale and the collateral token's scale
return Maths.max(_getArgUint256(COLLATERAL_SCALE), 10 ** pricePrecisionAdjustment);
}
Expand Down
25 changes: 13 additions & 12 deletions src/ERC20PoolFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,18 @@ import { PoolDeployer } from './base/PoolDeployer.sol';

/**
* @title ERC20 Pool Factory
* @notice Pool factory contract for creating ERC20 pools. Actors actions:
* - Pool creators: create pool by providing a fungible token for quote and collateral and an interest rate between 1-10%
* @notice Pool factory contract for creating `ERC20` pools. Actors actions:
* - `Pool creators`: create pool by providing a fungible token for quote and collateral and an interest rate between `1%-10%`
* @dev Reverts if pool is already created or if params to deploy new pool are invalid.
*/
contract ERC20PoolFactory is PoolDeployer, IERC20PoolFactory {

using ClonesWithImmutableArgs for address;

/// @dev `ERC20` clonable pool contract used to deploy the new pool.
ERC20Pool public implementation;

/// @dev Default bytes32 hash used by ERC20 Non-NFTSubset pool types
/// @dev Default `bytes32` hash used by `ERC20` `Non-NFTSubset` pool types
bytes32 public constant ERC20_NON_SUBSET_HASH = keccak256("ERC20_NON_SUBSET_HASH");

constructor(address ajna_) {
Expand All @@ -37,15 +38,15 @@ contract ERC20PoolFactory is PoolDeployer, IERC20PoolFactory {
/**
* @inheritdoc IERC20PoolFactory
* @dev immutable args: pool type; ajna, collateral and quote address; quote and collateral scale
* @dev write state:
* - deployedPools mapping
* - deployedPoolsList array
* @dev reverts on:
* - 0x address provided as quote or collateral DeployWithZeroAddress()
* - pool with provided quote / collateral pair already exists PoolAlreadyExists()
* - invalid interest rate provided PoolInterestRateInvalid()
* @dev emit events:
* - PoolCreated
* @dev === Write state ===
* @dev - `deployedPools` mapping
* @dev - `deployedPoolsList` array
* @dev === Reverts on ===
* @dev - `0x` address provided as quote or collateral `DeployWithZeroAddress()`
* @dev - pool with provided quote / collateral pair already exists `PoolAlreadyExists()`
* @dev - invalid interest rate provided `PoolInterestRateInvalid()`
* @dev === Emit events ===
* @dev - `PoolCreated`
*/
function deployPool(
address collateral_, address quote_, uint256 interestRate_
Expand Down
Loading