<!-- canonical: https://0xsimao.com/reports/maple-finance-iii-2024 -->

# Maple Finance audit

Three Sigma · Institutional lending · 10th April 2024

A private security review of Maple Finance (institutional lending), conducted with Three Sigma and completed on 10th April 2024 over 12 days. 0xSimao disclosed 35 findings: 6 high severity, 6 medium, 9 low and 14 informational.

## What Maple Finance is

Maple Finance runs institutional lending pools on Ethereum. Lenders deposit into ERC-4626-style pools, a pool delegate underwrites borrowers and deploys the capital into fixed-term and open-term loans, and first-loss cover staked by the delegate absorbs defaults ahead of lenders. Withdrawals are not a simple redeem: they queue in a withdrawal manager and settle against the liquidity the pool actually holds.

The system is built as a constellation of small, proxied contracts: MapleGlobals holds protocol-wide authority and timelocks, PoolManager wires each pool to its loan managers, fee manager and withdrawal manager, and separate loan-manager implementations track fixed-term and open-term debt with their own interest accrual and impairment logic. Nearly every privileged action flows through governor or delegate roles checked against Globals, so the trust model is as much a part of the code as the accounting.

## Scope

The Three Sigma review covered the full loan and pool stack: the fixed-term and open-term loan contracts, the loan managers, the pool and its withdrawal manager, the fee manager and the protocol globals.

## High severity findings

- [Fixed term loans can be deployed with a wrong fee manager and possibly steal all funds.](https://0xsimao.com/findings/maple-finance-iii-loans-deployed-fee-steal)
- [Pool Delegates can set a really high origination fee and steal all pool funds.](https://0xsimao.com/findings/maple-finance-iii-really-origination-fee-steal)
- [Pool Delegates can steal all the pool's funds by setting a malicious Withdrawal Manager.](https://0xsimao.com/findings/maple-finance-iii-delegates-steal-setting-withdrawal)
- [Pool Delegates can set an unreasonably large delegate management fee rate at anytime](https://0xsimao.com/findings/maple-finance-iii-unreasonably-delegate-fee-anytime)
- [Liquidation can be finished without calling triggerDefault() (and repossessing the loan) if pool delegate or governor call finishCollateralLiquidation(...) after impairment.](https://0xsimao.com/findings/maple-finance-iii-liquidation-repossessing-delegate-collateral)
- [Malicious refinancer danger due to fixed term loan upgrades.](https://0xsimao.com/findings/maple-finance-iii-refinancer-danger-term-upgrades)

## Medium severity findings

- [Open term loans can be created with zero platform service fee if borrowers create them right after a pool has been deployed.](https://0xsimao.com/findings/maple-finance-iii-zero-platform-fee-right)
- [fundLoan() can be DoSed if returnFunds() is called before it.](https://0xsimao.com/findings/maple-finance-iii-fund-sed-return-called)
- [A pool delegate should not be allowed to be a borrower](https://0xsimao.com/findings/maple-finance-iii-pool-delegate-borrower)
- [MapleGlobals, activatePoolManager() has no check that the pool manager is actually a valid pool manager.](https://0xsimao.com/findings/maple-finance-iii-globals-activate-actually-valid)
- [DoS attack if assets are transferred before a fundLoan() call.](https://0xsimao.com/findings/maple-finance-iii-attack-assets-transferred-fund)
- [Pool Delegates can accidentally lock out of their funds LPs in the middle of redeeming.](https://0xsimao.com/findings/maple-finance-iii-accidentally-lock-middle-redeeming)

## Low severity findings

- [MapleLoan, proposeNewTerms() could have a check for duplicate selectors.](https://0xsimao.com/findings/maple-finance-iii-propose-terms-duplicate-selectors)
- [MapleLoan, skim() has no zero address transfer check.](https://0xsimao.com/findings/maple-finance-iii-skim-zero-address-transfer)
- [In MapleLoanInitializer, the Borrower can choose a different fundsAsset than the lender.](https://0xsimao.com/findings/maple-finance-iii-initializer-borrower-choose-different)
- [Borrowers can prevent MapleLoanInitializer from initializing a loan by using a vanity address.](https://0xsimao.com/findings/maple-finance-iii-borrowers-initializer-initializing-vanity)
- [Consider using a time lock on critical permissioned functions.](https://0xsimao.com/findings/maple-finance-iii-consider-lock-critical-permissioned)
- [In MapleGlobals, there is no check in the dataHash argument when unscheduling a call.](https://0xsimao.com/findings/maple-finance-iii-globals-hash-argument-unscheduling)
- [Consider adding a check to ensure that fees, delegate cover and so on have been explicitly set.](https://0xsimao.com/findings/maple-finance-iii-ensure-fees-delegate-explicitly)
- [In PoolManager, setOpenToPublic(), there is no way to unset openToPublic.](https://0xsimao.com/findings/maple-finance-iii-open-public-way-unset)
- [Throughout code-base: missing address checks.](https://0xsimao.com/findings/maple-finance-iii-throughout-code-address-checks)

## Informational findings

- [MapleLoan variables read from storage more than once.](https://0xsimao.com/findings/maple-finance-iii-maple-variables-read-storage)
- [MapleLoanStorage storage slot optimization.](https://0xsimao.com/findings/maple-finance-iii-maple-storage-slot-optimization)
- [MapleLoan change the order of require to save on gas.](https://0xsimao.com/findings/maple-finance-iii-change-require-save-gas)
- [In PoolManager, requestFunds(...) repeated variable fetching from storage.](https://0xsimao.com/findings/maple-finance-iii-repeated-variable-fetching-storage)
- [In MapleLoanFactory, isLoan has the same functionality of isInstance and thus can be removed.](https://0xsimao.com/findings/maple-finance-iii-functionality-instance-thus-removed)
- [LoanManager code optimizations: no need to load payment struct from storage if loan is unimpaired.](https://0xsimao.com/findings/maple-finance-iii-optimizations-load-storage-unimpaired)
- [LoanManager code optimizations: redundant impairment functions.](https://0xsimao.com/findings/maple-finance-iii-optimizations-redundant-impairment-functions)
- [Throughout code base: use Solidity native errors implementation instead of string errors.](https://0xsimao.com/findings/maple-finance-iii-solidity-native-implementation-string)
- [open-term-loan-private: check dateFunded!=0 first to save gas.](https://0xsimao.com/findings/maple-finance-iii-term-date-funded-gas)
- [pool-v2-private: cache list length in memory and uncheck i_ to save gas.](https://0xsimao.com/findings/maple-finance-iii-private-cache-uncheck-gas)
- [Throughout code-base: Homogenize how access control is done.](https://0xsimao.com/findings/maple-finance-iii-homogenize-access-control-done)
- [Missing documentation for MapleLoan, SetPendingLender and AcceptLender being implemented on MapleLoan but not on LoanManager.](https://0xsimao.com/findings/maple-finance-iii-documentation-pending-accept-implemented)
- [Multiple documentation fixes throughout the repository.](https://0xsimao.com/findings/maple-finance-iii-multiple-documentation-fixes-repository)
- [globals-v2-private: typo in function name.](https://0xsimao.com/findings/maple-finance-iii-globals-private-typo-name)

## The report

[Download the report (PDF)](https://0xsimao.com/reports/2024-04-10-maple-finance-iii.pdf)
