---
# System prepended metadata

title: Wharf-hardhat

---

# Wharf-hardhat
### AssetPool.sol
* `accumulateRewards()` is missing `onlyLending` modifier, maybe because of tests. But we can add this modifier and keep Alice as a lending address for `AssetPool.test.js`
* No reenterency guard added on deposit/withdraw (maybe we can use on other function calls too depending on their nature)
* `uint256 public totalBorrow;` should be added
* `mapping(address => uint256) public userBorrowed;` can be added for future calculations
* `availableReward()` ❌ calculation should be revised on time based reward index, each address shares will be signed difference from globalIndex to avoid double spending of rewards.
* `transferAsset()` <span style="color:orange">⚠️</span> should keep track of borrows and borrow by address.
* Missing `returnAsset()` for paybacks from `Lending.sol`
* `accumulateReward()` should keep system GlobalIndex for rewards with timestamp, which will help distribute fair reward to everyone

### RateProvider.sol
* `rpow()` from `Compounder.sol` can be used inside `getBorrowRate()` instead of doing `.mul(1e5)`. Unless we are fine with having only 5 decimal places precision
* `rpow()` can be moved to different contract as a acted as a library
* $$ U_{w} $$ is calculated multiple times `mul(borrows).div(available)` and at other place with precision of `mul(1e5)`, I think we should have consistency for precision and think of a way to avoid calculating it again to reduce gas cost
* `uint256 public secondsPerYear` can be a constant `SECONDS_PER_YEAR` and instead of calling it like a function, we can directly call wherever contract have extended it.

### Lending.sol
* `borrow()` ✅
* `payback()` <span style="color:orange">⚠️</span> instead of `IERC20(assetPool.underlyingToken()).safeTransferFrom()`, there should be `returnAsset()` inside `AssetPool.sol` which will allow keeping borrow/supply state of specific address.
* `supplyCollateral()` ✅
* `withdrawCollateral()` ✅
* `liquidate()` <span style="color:orange">⚠️</span> should `preAccrue(debitor)` too and debitor health should be checked after liquidation (*`Good to have, can skip this`*)
    > <span style="color:orange">*have to validate burning and reward on liquidation yet*</span>
 ```sol
    function liquidate(
        address loanAsset,
        address collateralAsset,
        address debitor
    ) external override preAccrue(msg.sender) returns (uint256)
```
* `factor()` ✅ (complexity can be reduced if user `_collateral` and `_loans` are stored in mapping too and will be done in single loop)
* `setCollateralFactor()` ✅ (onlyOwner or governance to be added) (does not support factor in decimal places, only discrete 0-100% and 80.5% is not possible)
* `setInterest()` ✅ (onlyOwner or governance to be added)
* `getCollateral()` ✅
* `getAllCollateral()` ✅
* `getLoan()` ✅ (complexity can be reduced if user `_loans` is stored in mapping too)
* `getAllLoans()` ✅
* `getPrice()` ✅
* `getUnaccruedDebt()` ✅ (complexity will get reduced when `factor()` is getting optimized)
* `accrueInterest()` ✅ 
* `getCurrentRate()` <span style="color:orange">⚠️</span>❌ Denial of service can be fixed when `getBorrows()` is implemented in `AssetPool.sol`
* No reenterency guard added on borrow and payback, also we should think of others functions that might be victim of reenterency.
* <span style="color:#998523">`_loans` could be converted into mapping (considering the fact we have to iterate through all of loans) to avoid multiple loops</span>
* <span style="color:#998523">Overall there are multiple nested function calls and loops inside calls, we should try to minimize these considering fact that each operation gets converted into approx ~2-3 assembly instructions which might make us run out of gas in some of calculations. (Have to look more in-depth)</span>



---
## Next Steps
* Add Governance/Ownable
* Convert contracts to upgradeable 
* Build off-chain liquidation bot
* Treasury Contract
* Wharf-Reserve



---
#### Dependency Graph
```graphviz
digraph G {
  graph [ ratio = "auto", page = "100", compound =true, bgcolor = "#2e3e56" ];
  node [ style = "filled", fillcolor = "#edad56", color = "#edad56", penwidth =3 ];
  edge [ color = "#fcfcfc", penwidth =2, fontname = "helvetica Neue Ultra Light" ];
subgraph "clusterLending" {
  graph [ label = "Lending", color = "#445773", fontcolor = "#f0f0f0", style = "rounded", bgcolor = "#445773" ];
  "Lending.<Constructor>" [ label = "<Constructor>", color = "#FF9797", fillcolor = "#FF9797" ];
  "Lending.preAccrue" [ label = "preAccrue", color = "#1bc6a6", shape =doubleoctagon ];
  "Lending.borrow" [ label = "borrow", color = "#ffbdb9", fillcolor = "#ffbdb9" ];
  "Lending.payback" [ label = "payback", color = "#ffbdb9", fillcolor = "#ffbdb9" ];
  "Lending.supplyCollateral" [ label = "supplyCollateral", color = "#ffbdb9", fillcolor = "#ffbdb9" ];
  "Lending.withdrawCollateral" [ label = "withdrawCollateral", color = "#ffbdb9", fillcolor = "#ffbdb9" ];
  "Lending.liquidate" [ label = "liquidate", color = "#ffbdb9", fillcolor = "#ffbdb9" ];
  "Lending.factor" [ label = "factor" ];
  "Lending.setCollateralFactor" [ label = "setCollateralFactor", color = "#ffbdb9", fillcolor = "#ffbdb9" ];
  "Lending.setInterest" [ label = "setInterest", color = "#ffbdb9", fillcolor = "#ffbdb9" ];
  "Lending.getCollateral" [ label = "getCollateral", color = "#ffbdb9", fillcolor = "#ffbdb9" ];
  "Lending.getAllCollateral" [ label = "getAllCollateral", color = "#ffbdb9", fillcolor = "#ffbdb9" ];
  "Lending.getLoan" [ label = "getLoan" ];
  "Lending.getAllLoans" [ label = "getAllLoans", color = "#ffbdb9", fillcolor = "#ffbdb9" ];
  "Lending.getPrice" [ label = "getPrice" ];
  "Lending.getUnaccruedDebt" [ label = "getUnaccruedDebt" ];
  "Lending.accrueInterest" [ label = "accrueInterest" ];
  "Lending.getCurrentRate" [ label = "getCurrentRate" ];
  "Lending.type" [ label = "type" ];
  "Lending.compound" [ label = "compound" ];
  "Lending.getBorrowRate" [ label = "getBorrowRate" ];
  "Lending.secondsPerYear" [ label = "secondsPerYear" ];
}


subgraph "clusterContext" {
  graph [ label = "Context", color = "#445773", fontcolor = "#f0f0f0", style = "rounded", bgcolor = "#445773" ];
  "Context._msgSender" [ label = "_msgSender", color = "#f2c383", fillcolor = "#f2c383" ];
  "Context._msgData" [ label = "_msgData", color = "#f2c383", fillcolor = "#f2c383" ];
}


subgraph "clusterIOracle" {
  graph [ label = "IOracle  (iface)", color = "#445773", fontcolor = "#f0f0f0", style = "rounded", bgcolor = "#445773" ];
  "IOracle.getPrice" [ label = "getPrice", color = "#ffbdb9", fillcolor = "#ffbdb9" ];
}

subgraph "clusterAssetPool" {
  graph [ label = "AssetPool", color = "#445773", fontcolor = "#f0f0f0", style = "rounded", bgcolor = "#445773" ];
  "AssetPool.underlyingToken" [ label = "underlyingToken" ];
  "AssetPool.burn" [ label = "burn", color = "#ffbdb9", fillcolor = "#ffbdb9" ];
  "AssetPool.transferAsset" [ label = "transferAsset", color = "#ffbdb9", fillcolor = "#ffbdb9" ];
  "AssetPool.totalSupply" [ label = "totalSupply" ];
  "AssetPool.<Constructor>" [ label = "<Constructor>", color = "#FF9797", fillcolor = "#FF9797" ];
  "AssetPool.onlyLending" [ label = "onlyLending", color = "#1bc6a6", shape =doubleoctagon ];
  "AssetPool.decimals" [ label = "decimals", color = "#FF9797", fillcolor = "#FF9797" ];
  "AssetPool.deposit" [ label = "deposit", color = "#ffbdb9", fillcolor = "#ffbdb9" ];
  "AssetPool.withdraw" [ label = "withdraw", color = "#ffbdb9", fillcolor = "#ffbdb9" ];
  "AssetPool.availableReward" [ label = "availableReward" ];
  "AssetPool.claimReward" [ label = "claimReward", color = "#ffbdb9", fillcolor = "#ffbdb9" ];
  "AssetPool._claim" [ label = "_claim" ];
  "AssetPool.accumulateReward" [ label = "accumulateReward", color = "#ffbdb9", fillcolor = "#ffbdb9" ];
  "AssetPool._mint" [ label = "_mint" ];
  "AssetPool.balanceOf" [ label = "balanceOf" ];
  "AssetPool._burn" [ label = "_burn" ];
}

subgraph "clusterCompounder" {
  graph [ label = "Compounder", color = "#445773", fontcolor = "#f0f0f0", style = "rounded", bgcolor = "#445773" ];
  "Compounder.compound" [ label = "compound", color = "#FF9797", fillcolor = "#FF9797" ];
  "Compounder.rpow" [ label = "rpow" ];
}

subgraph "clusterRateProvider" {
  graph [ label = "RateProvider", color = "#445773", fontcolor = "#f0f0f0", style = "rounded", bgcolor = "#445773" ];
  "RateProvider.getBorrowRate" [ label = "getBorrowRate", color = "#FF9797", fillcolor = "#FF9797" ];
  "RateProvider.getSupplyRate" [ label = "getSupplyRate", color = "#FF9797", fillcolor = "#FF9797" ];
}


subgraph "clusterrate" {
  graph [ label = "rate", color = "#e8726d", fontcolor = "#f0f0f0", style = "rounded,dashed", bgcolor = "#3b4b63" ];
  "rate.div" [ label = "div" ];
}

subgraph "clusteramount" {
  graph [ label = "amount", color = "#e8726d", fontcolor = "#f0f0f0", style = "rounded,dashed", bgcolor = "#3b4b63" ];
  "amount.mul" [ label = "mul" ];
}

subgraph "clustershares" {
  graph [ label = "shares", color = "#e8726d", fontcolor = "#f0f0f0", style = "rounded,dashed", bgcolor = "#3b4b63" ];
  "shares.mul" [ label = "mul" ];
}

subgraph "clusterp" {
  graph [ label = "p", color = "#e8726d", fontcolor = "#f0f0f0", style = "rounded,dashed", bgcolor = "#3b4b63" ];
  "p.mul" [ label = "mul" ];
}

subgraph "clusterr" {
  graph [ label = "r", color = "#e8726d", fontcolor = "#f0f0f0", style = "rounded,dashed", bgcolor = "#3b4b63" ];
  "r.add" [ label = "add" ];
}

subgraph "clusterB1" {
  graph [ label = "B1", color = "#e8726d", fontcolor = "#f0f0f0", style = "rounded,dashed", bgcolor = "#3b4b63" ];
  "B1.mul" [ label = "mul" ];
}

subgraph "clusterB2" {
  graph [ label = "B2", color = "#e8726d", fontcolor = "#f0f0f0", style = "rounded,dashed", bgcolor = "#3b4b63" ];
  "B2.mul" [ label = "mul" ];
}

subgraph "clusterborrows" {
  graph [ label = "borrows", color = "#e8726d", fontcolor = "#f0f0f0", style = "rounded,dashed", bgcolor = "#3b4b63" ];
  "borrows.mul" [ label = "mul" ];
}

subgraph "clusterbw" {
  graph [ label = "bw", color = "#e8726d", fontcolor = "#f0f0f0", style = "rounded,dashed", bgcolor = "#3b4b63" ];
  "bw.mul" [ label = "mul" ];
}

  "Lending.preAccrue";
  "Lending.accrueInterest";
  "Lending.borrow";
  "Lending.factor";
  "Lending.payback";
  "AssetPool.underlyingToken";
  "Lending.withdrawCollateral";
  "Lending.liquidate";
  "Lending.type";
  "Lending.getPrice";
  "AssetPool.burn";
  "AssetPool.transferAsset";
  "Lending.getUnaccruedDebt";
  "IOracle.getPrice";
  "Lending.getLoan";
  "Lending.getCurrentRate";
  "Lending.compound";
  "AssetPool.totalSupply";
  "Lending.getBorrowRate";
  "rate.div";
  "Lending.secondsPerYear";
  "AssetPool.deposit";
  "AssetPool._mint";
  "amount.mul";
  "AssetPool.withdraw";
  "AssetPool.availableReward";
  "AssetPool._claim";
  "AssetPool.balanceOf";
  "AssetPool._burn";
  "shares.mul";
  "AssetPool.claimReward";
  "AssetPool.accumulateReward";
  "Compounder.compound";
  "p.mul";
  "Compounder.rpow";
  "r.add";
  "RateProvider.getBorrowRate";
  "B1.mul";
  "B2.mul";
  "borrows.mul";
  "RateProvider.getSupplyRate";
  "bw.mul";
  "Lending.preAccrue" -> "Lending.accrueInterest" [ color = "#80e097" ];
  "Lending.borrow" -> "Lending.factor" [ color = "#80e097" ];
  "Lending.payback" -> "AssetPool.underlyingToken" [ color = "white" ];
  "Lending.withdrawCollateral" -> "Lending.factor" [ color = "#80e097" ];
  "Lending.liquidate" -> "Lending.factor" [ color = "#80e097" ];
  "Lending.liquidate" -> "Lending.type" [ color = "#1bc6a6" ];
  "Lending.liquidate" -> "Lending.getPrice" [ color = "#80e097" ];
  "Lending.liquidate" -> "Lending.getPrice" [ color = "#80e097" ];
  "Lending.liquidate" -> "AssetPool.underlyingToken" [ color = "white" ];
  "Lending.liquidate" -> "AssetPool.burn" [ color = "white" ];
  "Lending.liquidate" -> "AssetPool.transferAsset" [ color = "white" ];
  "Lending.factor" -> "Lending.getPrice" [ color = "#80e097" ];
  "Lending.factor" -> "Lending.getUnaccruedDebt" [ color = "#80e097" ];
  "Lending.factor" -> "Lending.getPrice" [ color = "#80e097" ];
  "Lending.getPrice" -> "IOracle.getPrice" [ color = "white" ];
  "Lending.getUnaccruedDebt" -> "Lending.getLoan" [ color = "#80e097" ];
  "Lending.getUnaccruedDebt" -> "Lending.getCurrentRate" [ color = "#80e097" ];
  "Lending.getUnaccruedDebt" -> "Lending.compound" [ color = "#80e097" ];
  "Lending.accrueInterest" -> "Lending.getCurrentRate" [ color = "#80e097" ];
  "Lending.accrueInterest" -> "Lending.compound" [ color = "#80e097" ];
  "Lending.getCurrentRate" -> "AssetPool.totalSupply" [ color = "white" ];
  "Lending.getCurrentRate" -> "AssetPool.underlyingToken" [ color = "white" ];
  "Lending.getCurrentRate" -> "Lending.getBorrowRate" [ color = "#80e097" ];
  "Lending.getCurrentRate" -> "rate.div" [ color = "white" ];
  "Lending.getCurrentRate" -> "Lending.secondsPerYear" [ color = "#80e097" ];
  "AssetPool.deposit" -> "AssetPool.totalSupply" [ color = "#1bc6a6" ];
  "AssetPool.deposit" -> "AssetPool._mint" [ color = "#1bc6a6" ];
  "AssetPool.deposit" -> "amount.mul" [ color = "white" ];
  "AssetPool.withdraw" -> "AssetPool.availableReward" [ color = "#1bc6a6" ];
  "AssetPool.withdraw" -> "AssetPool._claim" [ color = "#1bc6a6" ];
  "AssetPool.withdraw" -> "AssetPool.balanceOf" [ color = "#1bc6a6" ];
  "AssetPool.withdraw" -> "AssetPool._burn" [ color = "#1bc6a6" ];
  "AssetPool.withdraw" -> "amount.mul" [ color = "white" ];
  "AssetPool.availableReward" -> "AssetPool.balanceOf" [ color = "#1bc6a6" ];
  "AssetPool.availableReward" -> "AssetPool.totalSupply" [ color = "#1bc6a6" ];
  "AssetPool.availableReward" -> "shares.mul" [ color = "white" ];
  "AssetPool.claimReward" -> "AssetPool.availableReward" [ color = "#1bc6a6" ];
  "AssetPool.claimReward" -> "AssetPool._claim" [ color = "#1bc6a6" ];
  "AssetPool.burn" -> "AssetPool._burn" [ color = "#1bc6a6" ];
  "AssetPool.accumulateReward" -> "AssetPool.totalSupply" [ color = "#1bc6a6" ];
  "Compounder.compound" -> "p.mul" [ color = "white" ];
  "Compounder.compound" -> "Compounder.rpow" [ color = "#1bc6a6" ];
  "Compounder.compound" -> "r.add" [ color = "white" ];
  "RateProvider.getBorrowRate" -> "B1.mul" [ color = "white" ];
  "RateProvider.getBorrowRate" -> "B2.mul" [ color = "white" ];
  "RateProvider.getBorrowRate" -> "borrows.mul" [ color = "white" ];
  "RateProvider.getSupplyRate" -> "RateProvider.getBorrowRate" [ color = "#1bc6a6" ];
  "RateProvider.getSupplyRate" -> "bw.mul" [ color = "white" ];
  


rankdir=LR
node [shape=plaintext]
subgraph cluster_01 { 
label = "Legend";
key [label=<<table border="0" cellpadding="2" cellspacing="0" cellborder="0">
  <tr><td align="right" port="i1">Internal Call</td></tr>
  <tr><td align="right" port="i2">External Call</td></tr>
  <tr><td align="right" port="i3">Defined Contract</td></tr>
  <tr><td align="right" port="i4">Undefined Contract</td></tr>
  </table>>]
key2 [label=<<table border="0" cellpadding="2" cellspacing="0" cellborder="0">
  <tr><td port="i1">&nbsp;&nbsp;&nbsp;</td></tr>
  <tr><td port="i2">&nbsp;&nbsp;&nbsp;</td></tr>
  <tr><td port="i3" bgcolor="#445773">&nbsp;&nbsp;&nbsp;</td></tr>
  <tr><td port="i4">
    <table border="1" cellborder="0" cellspacing="0" cellpadding="7" color="#e8726d">
      <tr>
       <td></td>
      </tr>
     </table>
  </td></tr>
  </table>>]
key:i1:e -> key2:i1:w [color="#1bc6a6"]
key:i2:e -> key2:i2:w [color="white"]
}
}


```
