Skip to content

feat: liquidate to receive shares#884

Merged
miguelmtzinf merged 25 commits intomainfrom
feat/liquidate-receive-shares
Oct 16, 2025
Merged

feat: liquidate to receive shares#884
miguelmtzinf merged 25 commits intomainfrom
feat/liquidate-receive-shares

Conversation

@yan-man
Copy link
Contributor

@yan-man yan-man commented Oct 9, 2025

  • allow liquidation to receive addedShares rather than underlying collateral asset
  • not possible to receive shares of a collateral reserve that is frozen
  • allow for liquidations to occur even in low liquidity environment by providing collateral to liquidators in the form of supplied shares
@yan-man yan-man changed the title feat: liquidate to receive shares Oct 9, 2025
@yan-man yan-man changed the title [WIP] feat: liquidate to receive shares Oct 10, 2025
@yan-man yan-man requested a review from avniculae October 10, 2025 16:57
@yan-man yan-man marked this pull request as ready for review October 10, 2025 16:57
@codecov
Copy link

codecov bot commented Oct 10, 2025

The author of this PR, yan-man, is not an activated member of this organization on Codecov.
Please activate this user on Codecov to display this PR comment.
Coverage data is still being uploaded to Codecov.io for purposes of overall coverage calculations.
Please don't hesitate to email us at support@codecov.io with any questions.

@github-actions
Copy link

github-actions bot commented Oct 10, 2025

Forge Build Sizes

Contract Runtime Size (B) Initcode Size (B) Runtime Margin (B) Initcode Margin (B)
LiquidationLogic ↑11% (+552) 5,532 ↑11% (+552) 5,584 ↓3% (-552) 19,044 ↓1% (-552) 43,568
LiquidationLogicWrapper ↑14% (+1185) 9,539 ↑15% (+1292) 9,674 ↓7% (-1185) 15,037 ↓3% (-1292) 39,478
MockSpokeInstance ↑0% (+52) 24,181 ↑0% (+52) 24,989 ↓12% (-52) 395 ↓0% (-52) 24,163
SpokeInstance ↑0% (+52) 24,119 ↑0% (+52) 24,855 ↓10% (-52) 457 ↓0% (-52) 24,297
TreasurySpoke ↑1% (+26) 2,355 ↑1% (+26) 2,756 ↓0% (-26) 22,221 ↓0% (-26) 46,396
KeyValueListWrapper 802 830 23,774 48,322
🔕 Unchanged
Contract Runtime Size (B) Initcode Size (B) Runtime Margin (B) Initcode Margin (B)
AaveOracle 1,842 2,580 22,734 46,572
AccessManager 10,198 11,423 14,378 37,729
Address 44 94 24,532 49,058
Arrays 44 94 24,532 49,058
AssetInterestRateStrategy 2,349 2,534 22,227 46,618
AssetLogic 44 94 24,532 49,058
AuthorityUtils 44 94 24,532 49,058
Bytes 44 94 24,532 49,058
Comparators 44 94 24,532 49,058
Constants 378 430 24,198 48,722
ECDSA 44 94 24,532 49,058
EIP712Types 44 94 24,532 49,058
ERC1967Proxy 122 934 24,454 48,218
ERC1967Utils 44 94 24,532 49,058
EnumerableSet 44 94 24,532 49,058
Errors 44 94 24,532 49,058
Hub 20,306 20,540 4,270 28,612
HubConfigurator 9,004 9,277 15,572 39,875
JsonBindings 9,244 9,296 15,332 39,856
KeyValueList 44 94 24,532 49,058
LibBit 44 94 24,532 49,058
Math 44 94 24,532 49,058
MathUtils 44 94 24,532 49,058
MockERC1271Wallet 599 733 23,977 48,419
MockERC20 1,913 2,379 22,663 46,773
MockPriceFeed 642 1,300 23,934 47,852
NativeTokenGateway 4,869 5,398 19,707 43,754
NoncesKeyed 624 652 23,952 48,500
NoncesKeyedMock 735 763 23,841 48,389
Panic 44 94 24,532 49,058
PercentageMath 44 94 24,532 49,058
PercentageMathWrapper 592 620 23,984 48,532
PositionStatusMap 44 94 24,532 49,058
PositionStatusMapWrapper 2,407 2,435 22,169 46,717
ProxyAdmin 977 1,213 23,599 47,939
RescuableWrapper 770 904 23,806 48,248
Roles 153 203 24,423 48,949
SafeCast 44 94 24,532 49,058
SafeERC20 44 94 24,532 49,058
SharesMath 44 94 24,532 49,058
SignatureChecker 44 94 24,532 49,058
SignatureGateway 9,835 10,571 14,741 38,581
SlotDerivation 44 94 24,532 49,058
SpokeConfigurator 7,259 7,532 17,317 41,620
StorageSlot 44 94 24,532 49,058
TestnetERC20 2,810 3,686 21,766 45,466
Time 44 94 24,532 49,058
TransientSlot 44 94 24,532 49,058
TransparentUpgradeableProxy 1,073 3,445 23,503 45,707
UnitPriceFeed 662 1,596 23,914 47,556
Utils 44 94 24,532 49,058
WETH9 1,864 2,330 22,712 46,822
WadRayMath 44 94 24,532 49,058
WadRayMathWrapper 1,252 1,280 23,324 47,872
@github-actions
Copy link

github-actions bot commented Oct 10, 2025

🌈 Test Results
No files changed, compilation skipped

Ran 17 tests for tests/unit/AaveOracle.t.sol:AaveOracleTest
[PASS] test_constructor() (gas: 440456)
[PASS] test_decimals() (gas: 8387)
[PASS] test_deploy_revertsWith_InvalidAddress() (gas: 38089)
[PASS] test_description() (gas: 12094)
[PASS] test_fuzz_constructor(uint8) (runs: 5000, μ: 444411, ~: 444703)
[PASS] test_getReservePrice() (gas: 47409)
[PASS] test_getReservePrice_revertsWith_InvalidPrice() (gas: 46669)
[PASS] test_getReservePrice_revertsWith_InvalidSource() (gas: 10976)
[PASS] test_getReservePrices() (gas: 79551)
[PASS] test_getReservePrices_revertsWith_InvalidSource() (gas: 49352)
[PASS] test_getReserveSource() (gas: 47584)
[PASS] test_setReserveSource() (gas: 44466)
[PASS] test_setReserveSource_revertsWith_InvalidPrice() (gas: 97683)
[PASS] test_setReserveSource_revertsWith_InvalidSource() (gas: 15327)
[PASS] test_setReserveSource_revertsWith_InvalidSourceDecimals() (gas: 15149)
[PASS] test_setReserveSource_revertsWith_OnlySpoke() (gas: 11049)
[PASS] test_spoke() (gas: 10614)
Suite result: ok. 17 passed; 0 failed; 0 skipped; finished in 489.21ms (474.65ms CPU time)

Ran 23 tests for tests/unit/AssetInterestRateStrategy.t.sol:AssetInterestRateStrategyTest
[PASS] test_calculateInterestRate_AtKinkPoint() (gas: 24686)
Logs:
  Bound result 2000
  Bound result 778565440757296803935461404101

[PASS] test_calculateInterestRate_AtMaxUtilization() (gas: 24958)
Logs:
  Bound result 10000
  Bound result 778565440757296803935461404101

[PASS] test_calculateInterestRate_LeftToKinkPoint(uint256) (runs: 5000, μ: 24538, ~: 24690)
[PASS] test_calculateInterestRate_RightToKinkPoint(uint256) (runs: 5000, μ: 25653, ~: 25690)
[PASS] test_calculateInterestRate_ZeroDebtZeroLiquidity() (gas: 18944)
Logs:
  Bound result 0

[PASS] test_calculateInterestRate_fuzz_ZeroDebt(uint256) (runs: 5000, μ: 19168, ~: 18950)
[PASS] test_calculateInterestRate_revertsWith_InterestRateDataNotSet() (gas: 11361)
[PASS] test_deploy_revertsWith_InvalidAddress() (gas: 36318)
[PASS] test_getBaseVariableBorrowRate() (gas: 14864)
[PASS] test_getInterestRateData() (gas: 19653)
[PASS] test_getMaxVariableBorrowRate() (gas: 15312)
[PASS] test_getOptimalUsageRatio() (gas: 14735)
[PASS] test_getVariableRateSlope1() (gas: 14810)
[PASS] test_getVariableRateSlope2() (gas: 14877)
[PASS] test_maxBorrowRate() (gas: 8431)
[PASS] test_maxOptimalRatio() (gas: 8431)
[PASS] test_minOptimalRatio() (gas: 8440)
[PASS] test_setInterestRateData() (gas: 69812)
[PASS] test_setInterestRateData_revertsWith_InvalidMaxRate() (gas: 42072)
[PASS] test_setInterestRateData_revertsWith_InvalidOptimalUsageRatio() (gas: 43120)
[PASS] test_setInterestRateData_revertsWith_InvalidRateData() (gas: 35395)
[PASS] test_setInterestRateData_revertsWith_OnlyHub() (gas: 23786)
[PASS] test_setInterestRateData_revertsWith_Slope2MustBeGteSlope1() (gas: 37980)
Suite result: ok. 23 passed; 0 failed; 0 skipped; finished in 998.30ms (991.90ms CPU time)

Ran 6 tests for tests/unit/Hub/Hub.Access.t.sol:HubAccessTest
[PASS] test_change_authority() (gas: 2314465)
[PASS] test_change_role_responsibility() (gas: 101979)
[PASS] test_hub_access_manager_exposure() (gas: 12706)
[PASS] test_hub_admin_access() (gas: 1134214)
[PASS] test_migrate_role_responsibility() (gas: 397250)
[PASS] test_setInterestRateData_access() (gas: 101156)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 20.24ms (3.77ms CPU time)

Ran 21 tests for tests/unit/Hub/Hub.Add.t.sol:HubAddTest
[PASS] test_add_AddCapReachedButNotExceeded_rounding() (gas: 646962)
[PASS] test_add_fuzz_AddCapReachedButNotExceeded(uint56) (runs: 5000, μ: 156721, ~: 156572)
[PASS] test_add_fuzz_multi_asset_multi_spoke(uint256,uint256,uint256) (runs: 5000, μ: 310062, ~: 310201)
[PASS] test_add_fuzz_revertsWith_AddCapExceeded(uint56) (runs: 5000, μ: 78629, ~: 78479)
[PASS] test_add_fuzz_revertsWith_AddCapExceeded_due_to_interest(uint56,uint256,uint256) (runs: 5000, μ: 283095, ~: 285500)
[PASS] test_add_fuzz_revertsWith_ERC20InsufficientAllowance(uint256) (runs: 5000, μ: 78897, ~: 78622)
[PASS] test_add_fuzz_revertsWith_InvalidShares_due_to_index(uint256,uint256,uint256) (runs: 5000, μ: 216891, ~: 217071)
[PASS] test_add_fuzz_single_asset(uint256,address,uint256) (runs: 5000, μ: 337063, ~: 336997)
[PASS] test_add_fuzz_single_spoke_multi_add(uint256,uint256) (runs: 5000, μ: 819611, ~: 821790)
[PASS] test_add_multi_add_minimal_shares() (gas: 344693)
[PASS] test_add_revertsWith_AmountDowncastOverflow() (gas: 206362)
[PASS] test_add_revertsWith_ERC20InsufficientAllowance() (gas: 75159)
[PASS] test_add_revertsWith_InvalidAddress() (gas: 15722)
[PASS] test_add_revertsWith_InvalidAmount() (gas: 15789)
[PASS] test_add_revertsWith_InvalidShares() (gas: 220762)
[PASS] test_add_revertsWith_SharesDowncastOverflow() (gas: 36540)
[PASS] test_add_revertsWith_SpokeNotActive() (gas: 58210)
[PASS] test_add_revertsWith_SpokePaused() (gas: 58355)
[PASS] test_add_single_asset() (gas: 325001)
Logs:
  Bound result 2
  Bound result 100000000000000000000

[PASS] test_add_with_increased_index() (gas: 324294)
[PASS] test_add_with_increased_index_with_premium() (gas: 670220)
Suite result: ok. 21 passed; 0 failed; 0 skipped; finished in 49.58s (49.56s CPU time)

Ran 5 tests for tests/unit/Spoke/Spoke.Borrow.EdgeCases.t.sol:SpokeBorrowEdgeCasesTest
[PASS] test_borrow_fuzz_rounding_effect(uint256,uint256) (runs: 5000, μ: 1062341, ~: 1062493)
[PASS] test_borrow_fuzz_rounding_effect_inflated_ex_rate(uint256,uint256,uint256) (runs: 5000, μ: 1446755, ~: 1446891)
[PASS] test_borrow_fuzz_rounding_effect_shares(uint256,uint256) (runs: 5000, μ: 1112348, ~: 1112119)
[PASS] test_borrow_rounding_effect_multiple_actions() (gas: 1170828)
[PASS] test_borrow_rounding_effect_shares() (gas: 1111334)
Logs:
  Bound result 5000000000000000000
  Bound result 94608000

Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 68.11s (68.08s CPU time)

Ran 31 tests for tests/unit/Hub/Hub.Config.t.sol:HubConfigTest
[PASS] test_addAsset_fuzz(address,uint8,address) (runs: 5000, μ: 841730, ~: 841763)
[PASS] test_addAsset_fuzz_revertsWith_InvalidAddress_feeReceiver(address,uint8,address) (runs: 5000, μ: 46647, ~: 46948)
[PASS] test_addAsset_fuzz_revertsWith_InvalidAddress_irStrategy(address,uint8,address) (runs: 5000, μ: 46723, ~: 47024)
[PASS] test_addAsset_fuzz_revertsWith_InvalidAddress_underlying(uint8,address,address) (runs: 5000, μ: 37755, ~: 37755)
[PASS] test_addAsset_fuzz_revertsWith_InvalidAssetDecimals(address,uint8,address,address) (runs: 5000, μ: 47184, ~: 47004)
[PASS] test_addAsset_fuzz_revertsWith_InvalidAssetDecimals_tooLow(address,uint8,address,address) (runs: 5000, μ: 47446, ~: 47681)
[PASS] test_addAsset_fuzz_reverts_InvalidIrData(address,uint8,address,address) (runs: 5000, μ: 39822, ~: 36252)
[PASS] test_addAsset_revertsWith_BlockTimestampDowncastOverflow() (gas: 81092)
[PASS] test_addAsset_revertsWith_DrawnRateDowncastOverflow() (gas: 78065)
[PASS] test_addSpoke_fuzz(uint256,(bool,bool,uint56,uint56)) (runs: 5000, μ: 123698, ~: 123767)
[PASS] test_addSpoke_fuzz_revertsWith_AssetNotListed(uint256,(bool,bool,uint56,uint56)) (runs: 5000, μ: 34534, ~: 34522)
[PASS] test_addSpoke_fuzz_revertsWith_InvalidAddress_spoke(uint256,(bool,bool,uint56,uint56)) (runs: 5000, μ: 33121, ~: 33178)
[PASS] test_addSpoke_revertsWith_SpokeAlreadyListed() (gas: 38659)
[PASS] test_hub_deploy_revertsWith_InvalidAddress() (gas: 47100)
[PASS] test_updateAssetConfig_UseExistingSpokeAndListedAsFeeReceiver_revertsWith_SpokeAlreadyListed() (gas: 60191)
[PASS] test_updateAssetConfig_fuzz(uint256,(address,uint16,address,address)) (runs: 5000, μ: 242537, ~: 242410)
[PASS] test_updateAssetConfig_fuzz_FromZeroLiquidityFee(uint256,uint16) (runs: 5000, μ: 756224, ~: 756145)
[PASS] test_updateAssetConfig_fuzz_LiquidityFee(uint256,uint16) (runs: 5000, μ: 654193, ~: 654115)
[PASS] test_updateAssetConfig_fuzz_NewFeeReceiver(uint256) (runs: 5000, μ: 724353, ~: 724410)
[PASS] test_updateAssetConfig_fuzz_NewInterestRateStrategy(uint256) (runs: 5000, μ: 1127791, ~: 1127896)
[PASS] test_updateAssetConfig_fuzz_ReuseFeeReceiver_revertsWith_SpokeAlreadyListed(uint256) (runs: 5000, μ: 764024, ~: 764080)
[PASS] test_updateAssetConfig_fuzz_Scenario(uint256) (runs: 5000, μ: 605895, ~: 605949)
[PASS] test_updateAssetConfig_fuzz_UseExistingSpokeAsFeeReceiver_revertsWith_SpokeAlreadyListed(uint256) (runs: 5000, μ: 59774, ~: 59774)
[PASS] test_updateAssetConfig_fuzz_revertsWith_InvalidInterestRateStrategy(uint256) (runs: 5000, μ: 57832, ~: 57886)
[PASS] test_updateAssetConfig_fuzz_revertsWith_InvalidLiquidityFee(uint256,(address,uint16,address,address)) (runs: 5000, μ: 41090, ~: 40943)
[PASS] test_updateAssetConfig_fuzz_revertsWith_InvalidReinvestmentController() (gas: 495376)
[PASS] test_updateAssetConfig_fuzz_revertsWith_calculateInterestRateReverts(uint256,(address,uint16,address,address)) (runs: 5000, μ: 191556, ~: 191409)
[PASS] test_updateAssetConfig_fuzz_revertsWith_setInterestRateDataReverts(uint256,(address,uint16,address,address)) (runs: 5000, μ: 65204, ~: 65057)
[PASS] test_updateSpokeConfig_fuzz(uint256,(bool,bool,uint56,uint56)) (runs: 5000, μ: 56488, ~: 56559)
[PASS] test_updateSpokeConfig_fuzz_revertsWith_SpokeNotListed(uint256,address,(bool,bool,uint56,uint56)) (runs: 5000, μ: 40402, ~: 40469)
[PASS] test_updateSpokeConfig_revertsWith_AssetNotListed() (gas: 29297)
Suite result: ok. 31 passed; 0 failed; 0 skipped; finished in 99.71s (99.69s CPU time)

Ran 16 tests for tests/unit/Hub/Hub.Draw.t.sol:HubDrawTest
[PASS] test_draw_DifferentSpokes() (gas: 362695)
[PASS] test_draw_fuzz_IncreasedBorrowRate(uint256,uint256) (runs: 5000, μ: 681261, ~: 681326)
[PASS] test_draw_fuzz_amounts_same_block(uint256,uint256) (runs: 5000, μ: 285594, ~: 285456)
[PASS] test_draw_fuzz_revertsWith_DrawCapExceeded(uint56) (runs: 5000, μ: 79865, ~: 79715)
[PASS] test_draw_fuzz_revertsWith_DrawCapExceeded_due_to_interest(uint56,uint256,uint256) (runs: 5000, μ: 298753, ~: 299033)
[PASS] test_draw_fuzz_revertsWith_InsufficientLiquidity(uint256,uint256) (runs: 5000, μ: 33921, ~: 33721)
[PASS] test_draw_fuzz_revertsWith_InsufficientLiquidity_due_to_draw(uint256) (runs: 5000, μ: 183019, ~: 182748)
[PASS] test_draw_fuzz_revertsWith_InsufficientLiquidity_due_to_remove(uint256) (runs: 5000, μ: 129546, ~: 129352)
[PASS] test_draw_fuzz_revertsWith_InvalidAddress(uint256) (runs: 5000, μ: 15782, ~: 15782)
[PASS] test_draw_revertsWith_DrawCapExceeded_due_to_deficit() (gas: 253903)
[PASS] test_draw_revertsWith_InsufficientLiquidity() (gas: 28022)
[PASS] test_draw_revertsWith_InsufficientLiquidity_due_to_draw() (gas: 179301)
[PASS] test_draw_revertsWith_InsufficientLiquidity_due_to_remove() (gas: 126662)
[PASS] test_draw_revertsWith_InvalidAmount() (gas: 15902)
[PASS] test_draw_revertsWith_SpokeNotActive() (gas: 58166)
[PASS] test_draw_revertsWith_SpokePaused() (gas: 58311)
Suite result: ok. 16 passed; 0 failed; 0 skipped; finished in 26.03s (26.01s CPU time)

Ran 6 tests for tests/unit/Hub/Hub.EliminateDeficit.t.sol:HubEliminateDeficitTest
[PASS] test_eliminateDeficit(uint256) (runs: 5000, μ: 501302, ~: 501302)
[PASS] test_eliminateDeficit_allowSpokePaused() (gas: 336850)
[PASS] test_eliminateDeficit_fuzz_revertsWith_InvalidAmount_Excess(uint256) (runs: 5000, μ: 250786, ~: 250786)
[PASS] test_eliminateDeficit_fuzz_revertsWith_callerSpokeNotActive(address) (runs: 5000, μ: 28893, ~: 28893)
[PASS] test_eliminateDeficit_revertsWith_InvalidAmount_ZeroAmountNoDeficit() (gas: 20023)
[PASS] test_eliminateDeficit_revertsWith_InvalidAmount_ZeroAmountWithDeficit() (gas: 251908)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 13.03s (13.01s CPU time)

Ran 7 tests for tests/gas/Hub.Operations.gas.t.sol:HubOperations_Gas_Tests
[PASS] test_add() (gas: 128872)
[PASS] test_deficit() (gas: 1046668)
[PASS] test_draw() (gas: 372111)
[PASS] test_payFee_transferShares() (gas: 923130)
[PASS] test_refreshPremium() (gas: 124914)
[PASS] test_remove() (gas: 278055)
[PASS] test_restore() (gas: 724573)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 27.30ms (4.68ms CPU time)

Ran 17 tests for tests/unit/Spoke/Spoke.Borrow.HealthFactor.t.sol:SpokeBorrowHealthFactorTest
[PASS] test_borrow_fuzz_revertsWith_HealthFactorBelowThreshold_collateral_price_drop(uint256,uint256) (runs: 5000, μ: 895631, ~: 895698)
[PASS] test_borrow_fuzz_revertsWith_HealthFactorBelowThreshold_multiple_colls(uint256,uint256) (runs: 5000, μ: 855892, ~: 856786)
[PASS] test_borrow_fuzz_revertsWith_HealthFactorBelowThreshold_multiple_colls_with_interest(uint256,uint256,uint256) (runs: 5000, μ: 902046, ~: 899390)
[PASS] test_borrow_fuzz_revertsWith_HealthFactorBelowThreshold_multiple_debts(uint256,uint256) (runs: 5000, μ: 1115455, ~: 1115578)
[PASS] test_borrow_fuzz_revertsWith_HealthFactorBelowThreshold_multiple_debts_with_interest(uint256,uint256,uint256) (runs: 5000, μ: 1178458, ~: 1179908)
[PASS] test_borrow_fuzz_revertsWith_HealthFactorBelowThreshold_with_interest(uint256,uint256) (runs: 5000, μ: 690851, ~: 691499)
[PASS] test_borrow_revertsWith_HealthFactorBelowThreshold() (gas: 646881)
[PASS] test_borrow_revertsWith_HealthFactorBelowThreshold_collateral_price_drop_weth() (gas: 889780)
[PASS] test_borrow_revertsWith_HealthFactorBelowThreshold_multiple_colls() (gas: 850386)
[PASS] test_borrow_revertsWith_HealthFactorBelowThreshold_multiple_colls_collateral_price_drop_dai() (gas: 1104039)
[PASS] test_borrow_revertsWith_HealthFactorBelowThreshold_multiple_colls_collateral_price_drop_weth() (gas: 1104083)
[PASS] test_borrow_revertsWith_HealthFactorBelowThreshold_multiple_colls_with_interest() (gas: 902713)
[PASS] test_borrow_revertsWith_HealthFactorBelowThreshold_multiple_debts() (gas: 1108622)
[PASS] test_borrow_revertsWith_HealthFactorBelowThreshold_multiple_debts_with_interest() (gas: 1172683)
[PASS] test_borrow_revertsWith_HealthFactorBelowThreshold_with_interest() (gas: 686771)
[PASS] test_fuzz_borrow_revertsWith_HealthFactorBelowThreshold_multiple_colls_collateral_price_drop_dai(uint256,uint256,uint256) (runs: 5000, μ: 1107711, ~: 1108795)
[PASS] test_fuzz_borrow_revertsWith_HealthFactorBelowThreshold_multiple_colls_collateral_price_drop_weth(uint256,uint256,uint256) (runs: 5000, μ: 1108340, ~: 1108817)
Suite result: ok. 17 passed; 0 failed; 0 skipped; finished in 134.15s (134.14s CPU time)

Ran 6 tests for tests/unit/Hub/Hub.PayFee.t.sol:HubPayFeeTest
[PASS] test_payFee_fuzz(uint256,uint256) (runs: 5000, μ: 665244, ~: 665219)
[PASS] test_payFee_fuzz_with_interest(uint256,uint256,uint256) (runs: 5000, μ: 665505, ~: 665661)
[PASS] test_payFee_revertsWith_AddedSharesExceeded() (gas: 132719)
[PASS] test_payFee_revertsWith_AddedSharesExceeded_with_interest() (gas: 631536)
[PASS] test_payFee_revertsWith_InvalidShares() (gas: 20168)
[PASS] test_payFee_revertsWith_SpokeNotActive() (gas: 58192)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 23.68s (23.66s CPU time)

Ran 10 tests for tests/unit/Hub/Hub.Reclaim.t.sol:HubReclaimTest
[PASS] test_reclaim() (gas: 678856)
Logs:
  Bound result 1000000000000000000000
  Bound result 500000000000000000000
  Bound result 200000000000000000000

[PASS] test_reclaim_fullAmount() (gas: 659584)
[PASS] test_reclaim_fuzz(uint256,uint256,uint256) (runs: 5000, μ: 680306, ~: 679858)
[PASS] test_reclaim_multipleSweepsAndReclaims() (gas: 787580)
[PASS] test_reclaim_revertsWith_AssetNotListed() (gas: 12402)
[PASS] test_reclaim_revertsWith_InvalidAmount_exceedsSwept() (gas: 92247)
[PASS] test_reclaim_revertsWith_InvalidAmount_exceedsSwept_afterSweep() (gas: 466316)
[PASS] test_reclaim_revertsWith_InvalidAmount_zero() (gas: 90579)
[PASS] test_reclaim_revertsWith_OnlyReinvestmentController(address) (runs: 5000, μ: 91557, ~: 91557)
[PASS] test_reclaim_revertsWith_OnlyReinvestmentController_init() (gas: 37982)
Suite result: ok. 10 passed; 0 failed; 0 skipped; finished in 14.62s (14.60s CPU time)

Ran 8 tests for tests/unit/Hub/Hub.RefreshPremium.t.sol:HubRefreshPremiumTest
[PASS] test_refreshPremium_emitsEvent() (gas: 169682)
[PASS] test_refreshPremium_fuzz_positiveDeltas(int256,int256,int256) (runs: 5000, μ: 58066, ~: 58316)
[PASS] test_refreshPremium_fuzz_withAccrual(uint256,uint256,uint256,uint256) (runs: 5000, μ: 561381, ~: 561579)
[PASS] test_refreshPremium_negativeDeltas(int256,int256) (runs: 5000, μ: 472797, ~: 473282)
[PASS] test_refreshPremium_negativeDeltas_withAccrual(uint256,uint256) (runs: 5000, μ: 543448, ~: 552418)
[PASS] test_refreshPremium_pausedSpokesAllowed() (gas: 107841)
[PASS] test_refreshPremium_revertsWith_SpokeNotActive() (gas: 56015)
[PASS] test_refreshPremium_spokePremiumUpdateIsContained() (gas: 737334)
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 20.23s (20.22s CPU time)

Ran 13 tests for tests/unit/Hub/Hub.Remove.t.sol:HubRemoveTest
[PASS] test_remove() (gas: 199759)
Logs:
  Bound result 2
  Bound result 100000000000000000000

[PASS] test_remove_all_with_interest() (gas: 398273)
[PASS] test_remove_fuzz(uint256,uint256) (runs: 5000, μ: 198299, ~: 198105)
[PASS] test_remove_fuzz_all_liquidity_with_interest(uint256,uint256) (runs: 5000, μ: 436002, ~: 438590)
[PASS] test_remove_fuzz_multi_spoke(uint256,uint256) (runs: 5000, μ: 279901, ~: 280054)
[PASS] test_remove_fuzz_multi_spoke_with_interest(uint256,uint256,uint256,uint256) (runs: 5000, μ: 449692, ~: 452883)
[PASS] test_remove_revertsWith_AddedAmountExceeded() (gas: 142218)
[PASS] test_remove_revertsWith_AddedAmountExceeded_zero_added() (gas: 29990)
[PASS] test_remove_revertsWith_InsufficientLiquidity() (gas: 171562)
[PASS] test_remove_revertsWith_InvalidAddress() (gas: 15746)
[PASS] test_remove_revertsWith_InvalidAmount() (gas: 17825)
[PASS] test_remove_revertsWith_SpokeNotActive() (gas: 58225)
[PASS] test_remove_revertsWith_SpokePaused() (gas: 58359)
Suite result: ok. 13 passed; 0 failed; 0 skipped; finished in 31.45s (31.43s CPU time)

Ran 5 tests for tests/unit/Hub/Hub.ReportDeficit.t.sol:HubReportDeficitTest
[PASS] test_reportDeficit_fuzz_revertsWith_SurplusDeficitReported(uint256,uint256,uint256,uint256) (runs: 5000, μ: 160349, ~: 160368)
[PASS] test_reportDeficit_fuzz_with_premium(uint256,uint256,uint256,uint256) (runs: 5000, μ: 333095, ~: 334922)
[PASS] test_reportDeficit_revertsWith_InvalidAmount() (gas: 18170)
[PASS] test_reportDeficit_revertsWith_SpokeNotActive(address) (runs: 5000, μ: 26412, ~: 26412)
[PASS] test_reportDeficit_with_premium() (gas: 333389)
Logs:
  Bound result 10000000000
  Bound result 31536000
  Bound result 5000000000
  Bound result 0

Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 9.80s (9.78s CPU time)

Ran 20 tests for tests/unit/Hub/Hub.Restore.t.sol:HubRestoreTest
[PASS] test_restore_full_amount_with_interest() (gas: 356257)
Logs:
  Bound result 1000000000000000000000
  Bound result 500000000000000000000
  Bound result 31536000

[PASS] test_restore_full_amount_with_interest_and_premium() (gas: 661888)
Logs:
  Bound result 100000000000000000000
  Bound result 50000000000000000000
  Bound result 31536000
  Bound result 1

[PASS] test_restore_fuzz_full_amount_with_interest(uint256,uint256,uint256) (runs: 5000, μ: 354951, ~: 357474)
[PASS] test_restore_fuzz_full_amount_with_interest_and_premium(uint256,uint256,uint256,uint256) (runs: 5000, μ: 645656, ~: 663314)
[PASS] test_restore_fuzz_revertsWith_SurplusAmountRestored_with_interest(uint256,uint256,uint256) (runs: 5000, μ: 249024, ~: 252810)
[PASS] test_restore_fuzz_revertsWith_SurplusAmountRestored_with_interest_and_premium(uint256,uint256,uint256,uint256) (runs: 5000, μ: 630519, ~: 634166)
[PASS] test_restore_partial_drawn() (gas: 331666)
[PASS] test_restore_partial_same_block() (gas: 310436)
[PASS] test_restore_premiumDeltas_twoWeiIncrease_realizedDelta() (gas: 251439)
[PASS] test_restore_revertsWith_InvalidAmount_zero() (gas: 44849)
[PASS] test_restore_revertsWith_InvalidPremiumChange_premiumIncrease() (gas: 193897)
[PASS] test_restore_revertsWith_InvalidPremiumChange_premiumSharesIncrease() (gas: 193917)
[PASS] test_restore_revertsWith_SpokeNotActive_whenPaused() (gas: 155260)
[PASS] test_restore_revertsWith_SpokePaused() (gas: 85402)
[PASS] test_restore_revertsWith_SurplusAmountRestored() (gas: 338859)
[PASS] test_restore_revertsWith_SurplusAmountRestored_with_interest() (gas: 251737)
Logs:
  Bound result 100000000000000000000
  Bound result 50000000000000000000
  Bound result 15768000

[PASS] test_restore_revertsWith_SurplusAmountRestored_with_interest_and_premium() (gas: 632826)
Logs:
  Bound result 100000000000000000000
  Bound result 50000000000000000000
  Bound result 31536000
  Bound result 1

[PASS] test_restore_revertsWith_underflow_offsetIncrease() (gas: 193906)
[PASS] test_restore_two_wei_shares_delta_increase() (gas: 246108)
[PASS] test_restore_when_asset_frozen() (gas: 412924)
Suite result: ok. 20 passed; 0 failed; 0 skipped; finished in 19.14s (19.12s CPU time)

Ran 1 test for tests/unit/Hub/Hub.Rounding.t.sol:HubRoundingTest
[PASS] test_sharePriceWithMultipleDonations() (gas: 702026707)
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.64s (3.62s CPU time)

Ran 8 tests for tests/unit/Hub/Hub.Sweep.t.sol:HubSweepTest
[PASS] test_sweep() (gas: 484704)
Logs:
  Bound result 1000000000000000000000
  Bound result 1000000000000000000000

[PASS] test_sweep_does_not_impact_utilization(uint256,uint256) (runs: 5000, μ: 648240, ~: 649417)
[PASS] test_sweep_fuzz(uint256,uint256) (runs: 5000, μ: 485215, ~: 485228)
[PASS] test_sweep_revertsWith_AssetNotListed() (gas: 12317)
[PASS] test_sweep_revertsWith_InsufficientLiquidity() (gas: 234857)
[PASS] test_sweep_revertsWith_InvalidAmount() (gas: 101549)
[PASS] test_sweep_revertsWith_OnlyReinvestmentController(address) (runs: 5000, μ: 92083, ~: 92083)
[PASS] test_sweep_revertsWith_OnlyReinvestmentController_init() (gas: 37943)
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 18.04s (18.01s CPU time)

Ran 7 tests for tests/unit/Hub/Hub.TransferShares.t.sol:HubTransferSharesTest
[PASS] test_transferShares() (gas: 170871)
Logs:
  Bound result 1000000000000000000000
  Bound result 1000000000000000000000

[PASS] test_transferShares_fuzz(uint256,uint256) (runs: 5000, μ: 174299, ~: 174456)
[PASS] test_transferShares_fuzz_revertsWith_AddedSharesExceeded(uint256) (runs: 5000, μ: 140806, ~: 140532)
[PASS] test_transferShares_revertsWith_AddCapExceeded() (gas: 184283)
[PASS] test_transferShares_revertsWith_SpokeNotActive() (gas: 164956)
[PASS] test_transferShares_revertsWith_SpokePaused() (gas: 167327)
[PASS] test_transferShares_zeroShares_revertsWith_InvalidShares() (gas: 22530)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 6.68s (6.67s CPU time)

Ran 6 tests for tests/unit/Hub/HubAccrueInterest.t.sol:HubAccrueInterestTest
[PASS] test_accrueInterest_NoActionTaken() (gas: 41386)
[PASS] test_accrueInterest_NoInterest_NoDebt(uint32) (runs: 5000, μ: 330496, ~: 330422)
[PASS] test_accrueInterest_NoInterest_OnlyAdd(uint32) (runs: 5000, μ: 187406, ~: 187332)
[PASS] test_accrueInterest_fuzz_BorrowAmountAndElapsed(uint256,uint32) (runs: 5000, μ: 262807, ~: 265179)
[PASS] test_accrueInterest_fuzz_BorrowAmountRateAndElapsed(uint256,uint256,uint32) (runs: 5000, μ: 363200, ~: 366765)
[PASS] test_accrueInterest_fuzz_BorrowAndWait(uint32) (runs: 5000, μ: 264209, ~: 264135)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 21.21s (21.19s CPU time)

Ran 57 tests for tests/unit/HubConfigurator.t.sol:HubConfiguratorTest
[PASS] test_addAsset_fuzz(bool,address,uint8,address,uint16,uint32,uint32,uint32) (runs: 5000, μ: 852255, ~: 852545)
[PASS] test_addAsset_fuzz_revertsWith_InvalidAssetDecimals(bool,address,uint8,address,address) (runs: 5000, μ: 56332, ~: 56767)
[PASS] test_addAsset_fuzz_revertsWith_OwnableUnauthorizedAccount(address) (runs: 5000, μ: 34798, ~: 34798)
[PASS] test_addAsset_revertsWith_InvalidAddress_irStrategy() (gas: 50445)
[PASS] test_addAsset_revertsWith_InvalidAddress_underlying() (gas: 50343)
[PASS] test_addAsset_reverts_invalidIrData() (gas: 44350)
[PASS] test_addSpoke() (gas: 124687)
[PASS] test_addSpokeToAssets() (gas: 219685)
[PASS] test_addSpokeToAssets_revertsWith_MismatchedConfigs() (gas: 24613)
[PASS] test_addSpokeToAssets_revertsWith_OwnableUnauthorizedAccount() (gas: 17213)
[PASS] test_addSpoke_revertsWith_OwnableUnauthorizedAccount() (gas: 16829)
[PASS] test_deactivateAsset() (gas: 155449)
[PASS] test_deactivateAsset_revertsWith_OwnableUnauthorizedAccount() (gas: 18008)
[PASS] test_deactivateSpoke() (gas: 152305)
[PASS] test_deactivateSpoke_revertsWith_OwnableUnauthorizedAccount() (gas: 17950)
[PASS] test_freezeAsset() (gas: 158120)
[PASS] test_freezeAsset_revertsWith_OwnableUnauthorizedAccount() (gas: 17941)
[PASS] test_freezeSpoke() (gas: 155030)
[PASS] test_freezeSpoke_revertsWith_OwnableUnauthorizedAccount() (gas: 18060)
[PASS] test_pauseAsset() (gas: 155446)
[PASS] test_pauseAsset_revertsWith_OwnableUnauthorizedAccount() (gas: 17898)
[PASS] test_pauseSpoke() (gas: 152434)
[PASS] test_pauseSpoke_revertsWith_OwnableUnauthorizedAccount() (gas: 18017)
[PASS] test_updateFeeConfig_Scenario() (gas: 322726)
Logs:
  Bound result 0
  Bound result 1800
  Bound result 0
  Bound result 400
  Bound result 0
  Bound result 0

[PASS] test_updateFeeConfig_fuzz(uint256,uint16,address) (runs: 5000, μ: 174447, ~: 174326)
[PASS] test_updateFeeConfig_fuzz_revertsWith_OwnableUnauthorizedAccount(address) (runs: 5000, μ: 17683, ~: 17683)
[PASS] test_updateFeeConfig_revertsWith_InvalidAddress_spoke() (gas: 48138)
[PASS] test_updateFeeConfig_revertsWith_InvalidLiquidityFee() (gas: 50083)
[PASS] test_updateFeeReceiver_Scenario() (gas: 204758)
[PASS] test_updateFeeReceiver_WithdrawFromOldSpoke() (gas: 972958)
[PASS] test_updateFeeReceiver_correctAccruals() (gas: 1000568)
[PASS] test_updateFeeReceiver_fuzz(address) (runs: 5000, μ: 170901, ~: 170901)
[PASS] test_updateFeeReceiver_fuzz_revertsWith_OwnableUnauthorizedAccount(address) (runs: 5000, μ: 17269, ~: 17269)
[PASS] test_updateFeeReceiver_revertsWith_InvalidAddress_spoke() (gas: 52675)
[PASS] test_updateFeeReceiver_revertsWith_SpokeAlreadyListed() (gas: 74330)
[PASS] test_updateInterestRateData() (gas: 71575)
[PASS] test_updateInterestRateData_revertsWith_OwnableUnauthorizedAccount() (gas: 19152)
[PASS] test_updateInterestRateStrategy() (gas: 91080)
[PASS] test_updateInterestRateStrategy_fuzz_revertsWith_OwnableUnauthorizedAccount(address) (runs: 5000, μ: 28659, ~: 28659)
[PASS] test_updateInterestRateStrategy_revertsWith_InterestRateStrategyReverts() (gas: 74619)
[PASS] test_updateInterestRateStrategy_revertsWith_InvalidAddress_irStrategy() (gas: 64366)
[PASS] test_updateInterestRateStrategy_revertsWith_InvalidInterestRateStrategy() (gas: 64861)
[PASS] test_updateLiquidityFee_fuzz(uint256,uint16) (runs: 5000, μ: 84310, ~: 84169)
[PASS] test_updateLiquidityFee_revertsWith_InvalidLiquidityFee() (gas: 52600)
[PASS] test_updateLiquidityFee_revertsWith_OwnableUnauthorizedAccount() (gas: 16633)
[PASS] test_updateReinvestmentController() (gas: 99106)
[PASS] test_updateReinvestmentController_fuzz_revertsWith_OwnableUnauthorizedAccount(address) (runs: 5000, μ: 17271, ~: 17271)
[PASS] test_updateSpokeActive() (gas: 81157)
[PASS] test_updateSpokeActive_revertsWith_OwnableUnauthorizedAccount() (gas: 20241)
[PASS] test_updateSpokeCaps() (gas: 62767)
[PASS] test_updateSpokeCaps_revertsWith_OwnableUnauthorizedAccount() (gas: 20172)
[PASS] test_updateSpokeDrawCap() (gas: 62574)
[PASS] test_updateSpokeDrawCap_revertsWith_OwnableUnauthorizedAccount() (gas: 20245)
[PASS] test_updateSpokePaused() (gas: 84139)
[PASS] test_updateSpokePaused_revertsWith_OwnableUnauthorizedAccount() (gas: 20352)
[PASS] test_updateSpokeSupplyCap() (gas: 62561)
[PASS] test_updateSpokeSupplyCap_revertsWith_OwnableUnauthorizedAccount() (gas: 20193)
Suite result: ok. 57 passed; 0 failed; 0 skipped; finished in 9.47s (9.45s CPU time)

Ran 2 tests for tests/invariant/HubInvariant.t.sol:HubInvariant
[SKIP] invariant_exchangeRateMonotonicallyIncreasing() (runs: 1, calls: 1, reverts: 1)
[SKIP] invariant_reserveTotalAssets() (runs: 1, calls: 1, reverts: 1)
Suite result: ok. 0 passed; 0 failed; 2 skipped; finished in 7.11ms (702.69µs CPU time)

Ran 6 tests for tests/unit/Spoke/Spoke.Borrow.Scenario.t.sol:SpokeBorrowScenarioTest
[PASS] test_borrow_fuzz_multi_spoke_multi_reserves(uint256,uint256,uint256,uint256,uint256) (runs: 5000, μ: 2196774, ~: 2206953)
[PASS] test_borrow_fuzz_single_spoke_multi_reserves(uint256,uint256,uint256,uint256) (runs: 5000, μ: 2362065, ~: 2371079)
[PASS] test_borrow_fuzz_single_spoke_multi_reserves_multi_user(uint256,uint256,uint256,uint256) (runs: 5000, μ: 2749626, ~: 2757959)
[PASS] test_borrow_fuzz_skip_borrow(uint256,uint256,uint256) (runs: 5000, μ: 1078869, ~: 1081178)
[PASS] test_borrow_skip_borrow() (gas: 1080363)
Logs:
  Bound result 10000000000000000000
  Bound result 20000000000000000000
  Bound result 31536000

[PASS] test_userAccountData_does_not_include_zero_cf_collateral() (gas: 1158002)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 182.72s (182.70s CPU time)

Ran 14 tests for tests/unit/Spoke/Spoke.Borrow.Validation.t.sol:SpokeBorrowValidationTest
[PASS] test_borrow_fuzz_revertsWith_DrawCapExceeded(uint256,uint56) (runs: 5000, μ: 106329, ~: 106238)
[PASS] test_borrow_fuzz_revertsWith_DrawCapExceeded_due_to_interest(uint256) (runs: 5000, μ: 697136, ~: 697424)
[PASS] test_borrow_fuzz_revertsWith_InsufficientLiquidity(uint256,uint256,uint256) (runs: 5000, μ: 280726, ~: 280532)
[PASS] test_borrow_fuzz_revertsWith_InvalidAmount(uint256) (runs: 5000, μ: 32651, ~: 32709)
[PASS] test_borrow_fuzz_revertsWith_ReserveFrozen(uint256,uint256) (runs: 5000, μ: 69423, ~: 69222)
[PASS] test_borrow_fuzz_revertsWith_ReserveNotBorrowable(uint256,uint256) (runs: 5000, μ: 69658, ~: 69457)
[PASS] test_borrow_fuzz_revertsWith_ReserveNotListed(uint256,uint256) (runs: 5000, μ: 26050, ~: 25796)
[PASS] test_borrow_fuzz_revertsWith_ReservePaused(uint256,uint256) (runs: 5000, μ: 69280, ~: 69079)
[PASS] test_borrow_revertsWith_InsufficientLiquidity() (gas: 280446)
Logs:
  Bound result 10000000000000000000

[PASS] test_borrow_revertsWith_InvalidAmount() (gas: 34320)
Logs:
  Bound result 2

[PASS] test_borrow_revertsWith_ReserveFrozen() (gas: 70828)
Logs:
  Bound result 2
  Bound result 1

[PASS] test_borrow_revertsWith_ReserveNotBorrowable() (gas: 71017)
Logs:
  Bound result 2
  Bound result 1

[PASS] test_borrow_revertsWith_ReserveNotListed() (gas: 27058)
Logs:
  Bound result 1

[PASS] test_borrow_revertsWith_ReservePaused() (gas: 70705)
Logs:
  Bound result 2
  Bound result 1

Suite result: ok. 14 passed; 0 failed; 0 skipped; finished in 15.65s (15.63s CPU time)

Ran 2 tests for tests/unit/Spoke/Spoke.Borrow.t.sol:SpokeBorrowTest
[PASS] test_borrow() (gas: 1074859)
[PASS] test_borrow_fuzz_amounts(uint256,uint256) (runs: 5000, μ: 1066924, ~: 1066974)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 26.79s (26.78s CPU time)

Ran 24 tests for tests/unit/Spoke/Spoke.Config.t.sol:SpokeConfigTest
[PASS] test_addReserve() (gas: 390215)
[PASS] test_addReserve_fuzz_revertsWith_AssetNotListed() (gas: 245632)
[PASS] test_addReserve_revertsWith_InvalidAddress_hub() (gas: 5969542)
[PASS] test_addReserve_revertsWith_InvalidAddress_oracle() (gas: 6006667)
[PASS] test_addReserve_revertsWith_InvalidAssetId() (gas: 33171)
[PASS] test_addReserve_revertsWith_ReserveExists() (gas: 374768)
[PASS] test_spoke_deploy() (gas: 4903727)
[PASS] test_spoke_deploy_revertsWith_InvalidOracleDecimals() (gas: 46386)
[PASS] test_spoke_deploy_reverts_on_InvalidConstructorInput() (gas: 43781)
[PASS] test_updateLiquidationConfig_fuzz_liqBonusConfig((uint128,uint64,uint16)) (runs: 5000, μ: 52152, ~: 52143)
[PASS] test_updateLiquidationConfig_fuzz_revertsWith_InvalidLiquidationConfig_healthFactorForMaxBonus((uint128,uint64,uint16)) (runs: 5000, μ: 37808, ~: 37949)
[PASS] test_updateLiquidationConfig_fuzz_revertsWith_InvalidLiquidationConfig_liquidationBonusFactor((uint128,uint64,uint16)) (runs: 5000, μ: 37379, ~: 37159)
[PASS] test_updateLiquidationConfig_fuzz_targetHealthFactor(uint128) (runs: 5000, μ: 46863, ~: 47159)
[PASS] test_updateLiquidationConfig_liqBonusConfig() (gas: 51102)
Logs:
  Bound result 900000000000000000
  Bound result 1000
  Bound result 1000000000000000000

[PASS] test_updateLiquidationConfig_revertsWith_InvalidLiquidationConfig_healthFactorForMaxBonus() (gas: 36462)
Logs:
  Bound result 1000000000000000000
  Bound result 1000
  Bound result 1000000000000000000

[PASS] test_updateLiquidationConfig_revertsWith_InvalidLiquidationConfig_liquidationBonusFactor() (gas: 36256)
Logs:
  Bound result 900000000000000000
  Bound result 10001
  Bound result 1000000000000000000

[PASS] test_updateLiquidationConfig_targetHealthFactor() (gas: 46442)
Logs:
  Bound result 1000000000000000001

[PASS] test_updateReserveConfig() (gas: 53882)
[PASS] test_updateReserveConfig_fuzz((bool,bool,bool,uint24)) (runs: 5000, μ: 55295, ~: 55127)
[PASS] test_updateReserveConfig_revertsWith_InvalidCollateralRisk() (gas: 39603)
[PASS] test_updateReserveConfig_revertsWith_ReserveNotListed() (gas: 36252)
[PASS] test_updateReservePriceSource() (gas: 240092)
[PASS] test_updateReservePriceSource_revertsWith_AccessManagedUnauthorized(address) (runs: 5000, μ: 31103, ~: 31103)
[PASS] test_updateReservePriceSource_revertsWith_ReserveNotListed() (gas: 34277)
Suite result: ok. 24 passed; 0 failed; 0 skipped; finished in 3.84s (3.82s CPU time)

Ran 9 tests for tests/unit/KeyValueList.t.sol:KeyValueListTest
[PASS] test_add_unique() (gas: 325391)
[PASS] test_fuzz_add(uint256,uint256) (runs: 5000, μ: 200012, ~: 201361)
[PASS] test_fuzz_add_unique(uint256,uint256) (runs: 5000, μ: 234208, ~: 230861)
[PASS] test_fuzz_get(uint256[]) (runs: 5000, μ: 413030, ~: 411058)
[PASS] test_fuzz_get_uninitialized(uint256[]) (runs: 5000, μ: 263153, ~: 252829)
[PASS] test_fuzz_get_uninitialized_sorted(uint256[]) (runs: 5000, μ: 204958, ~: 185400)
[PASS] test_fuzz_sortByKey(uint256[]) (runs: 5000, μ: 463709, ~: 454152)
[PASS] test_fuzz_sortByKey_length(uint256) (runs: 5000, μ: 201044, ~: 195846)
[PASS] test_fuzz_sortByKey_with_collision(uint256[]) (runs: 5000, μ: 547951, ~: 537198)
Suite result: ok. 9 passed; 0 failed; 0 skipped; finished in 72.31s (72.31s CPU time)

Ran 3 tests for tests/unit/libraries/LiquidationLogic/LiquidationLogic.DebtToLiquidate.t.sol:LiquidationLogicDebtToLiquidateTest
[PASS] test_calculateDebtToLiquidate_fuzz((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 30506, ~: 30445)
[PASS] test_calculateDebtToLiquidate_fuzz_AmountAdjustedDueToDust((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 32245, ~: 32352)
[PASS] test_calculateDebtToLiquidate_fuzz_ImpossibleToAdjustForDust((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 34398, ~: 34372)
Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 3.45s (3.44s CPU time)

Ran 7 tests for tests/unit/libraries/LiquidationLogic/LiquidationLogic.DebtToTargetHealthFactor.t.sol:LiquidationLogicDebtToTargetHealthFactorTest
[PASS] test_calculateDebtToTargetHealthFactor_HealthFactorEqualsTargetHealthFactor((uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 22971, ~: 23027)
[PASS] test_calculateDebtToTargetHealthFactor_NoPrecisionLoss() (gas: 25301)
[PASS] test_calculateDebtToTargetHealthFactor_PrecisionLoss() (gas: 15275)
[PASS] test_calculateDebtToTargetHealthFactor_UnitPrice() (gas: 25234)
[PASS] test_calculateDebtToTargetHealthFactor_fuzz_NoRevert((uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 20029, ~: 20085)
[PASS] test_calculateDebtToTargetHealthFactor_fuzz_revertsWith_DivisionByZero_ZeroAssetPrice((uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 22728, ~: 22784)
[PASS] test_calculateDebtToTargetHealthFactor_revertsWith_ArithmeticError_TargetHealthFactorLessThanHealthFactor((uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 22811, ~: 22867)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 2.82s (2.80s CPU time)

Ran 16 tests for tests/unit/libraries/LiquidationLogic/LiquidationLogic.EvaluateDeficit.t.sol:LiquidationLogicEvaluateDeficitTest
[PASS] test_evaluateDeficit_CRE_SCCM_DRE_BRCM() (gas: 8970)
[PASS] test_evaluateDeficit_CRE_SCCM_DRE_BRCO() (gas: 8938)
[PASS] test_evaluateDeficit_CRE_SCCM_DRN_BRCM() (gas: 8959)
[PASS] test_evaluateDeficit_CRE_SCCM_DRN_BRCO() (gas: 8926)
[PASS] test_evaluateDeficit_CRE_SCCO_DRE_BRCM() (gas: 8952)
[PASS] test_evaluateDeficit_CRE_SCCO_DRE_BRCO() (gas: 9019)
[PASS] test_evaluateDeficit_CRE_SCCO_DRN_BRCM() (gas: 8984)
[PASS] test_evaluateDeficit_CRE_SCCO_DRN_BRCO() (gas: 8972)
[PASS] test_evaluateDeficit_CRN_SCCM_DRE_BRCM() (gas: 8972)
[PASS] test_evaluateDeficit_CRN_SCCM_DRE_BRCO() (gas: 8961)
[PASS] test_evaluateDeficit_CRN_SCCM_DRN_BRCM() (gas: 8895)
[PASS] test_evaluateDeficit_CRN_SCCM_DRN_BRCO() (gas: 8928)
[PASS] test_evaluateDeficit_CRN_SCCO_DRE_BRCM() (gas: 8905)
[PASS] test_evaluateDeficit_CRN_SCCO_DRE_BRCO() (gas: 8962)
[PASS] test_evaluateDeficit_CRN_SCCO_DRN_BRCM() (gas: 8913)
[PASS] test_evaluateDeficit_CRN_SCCO_DRN_BRCO() (gas: 8991)
Suite result: ok. 16 passed; 0 failed; 0 skipped; finished in 18.40ms (1.07ms CPU time)

Ran 3 tests for tests/unit/libraries/LiquidationLogic/LiquidationLogic.LiquidateCollateral.t.sol:LiquidationLogicLiquidateCollateralTest
[PASS] test_liquidateCollateral_fuzz(uint256,uint256) (runs: 5000, μ: 272677, ~: 273153)
[PASS] test_liquidateCollateral_fuzz_revertsWith_ArithmeticUnderflow(uint256,uint256) (runs: 5000, μ: 99325, ~: 99126)
[PASS] test_liquidateCollateral_fuzz_revertsWith_InvalidAmount(uint256) (runs: 5000, μ: 103933, ~: 103850)
Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 4.14s (4.12s CPU time)

Ran 4 tests for tests/unit/libraries/LiquidationLogic/LiquidationLogic.LiquidateDebt.t.sol:LiquidationLogicLiquidateDebtTest
[PASS] test_liquidateDebt_fuzz(uint256) (runs: 5000, μ: 186574, ~: 186574)
[PASS] test_liquidateDebt_revertsWith_ArithmeticUnderflow() (gas: 151269)
[PASS] test_liquidateDebt_revertsWith_InsufficientAllowance() (gas: 155169)
[PASS] test_liquidateDebt_revertsWith_InsufficientBalance() (gas: 202279)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 2.40s (2.38s CPU time)

Ran 4 tests for tests/unit/libraries/LiquidationLogic/LiquidationLogic.LiquidateUser.t.sol:LiquidationLogicLiquidateUserTest
[PASS] test_liquidateUser() (gas: 359730)
[PASS] test_liquidateUser_revertsWith_InvalidDebtToCover() (gas: 75568)
[PASS] test_liquidateUser_revertsWith_MustNotLeaveDust_Collateral() (gas: 109326)
[PASS] test_liquidateUser_revertsWith_MustNotLeaveDust_Debt() (gas: 118740)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 24.19ms (1.52ms CPU time)

Ran 10 tests for tests/unit/Spoke/Spoke.DynamicConfig.Triggers.t.sol:SpokeDynamicConfigTriggersTest
[PASS] test_borrow_triggers_dynamicConfigUpdate() (gas: 1329769)
[PASS] test_liquidate_does_not_trigger_dynamicConfigUpdate() (gas: 1619505)
[PASS] test_repay_does_not_trigger_dynamicConfigUpdate() (gas: 912235)
[PASS] test_supply_does_not_trigger_dynamicConfigUpdate() (gas: 1070358)
[PASS] test_updateUserDynamicConfig_doesHFCheck() (gas: 801793)
[PASS] test_updateUserDynamicConfig_reverts_when_not_authorized(address) (runs: 5000, μ: 1196979, ~: 1196982)
[PASS] test_updateUserDynamicConfig_triggers_dynamicConfigUpdate() (gas: 677724)
[PASS] test_updateUserDynamicConfig_updatesRP() (gas: 1298195)
[PASS] test_usingAsCollateral_triggers_dynamicConfigUpdate() (gas: 1344582)
[PASS] test_withdraw_triggers_dynamicConfigUpdate() (gas: 1366758)
Suite result: ok. 10 passed; 0 failed; 0 skipped; finished in 27.71s (27.69s CPU time)

Ran 20 tests for tests/unit/Spoke/Spoke.DynamicConfig.t.sol:SpokeDynamicConfigTest
[PASS] test_addDynamicReserveConfig() (gas: 84923)
[PASS] test_addDynamicReserveConfig_fuzz_revertsWith_InvalidCollateralFactorAndMaxLiquidationBonus_incompatible(uint16,uint32) (runs: 5000, μ: 47681, ~: 47846)
[PASS] test_addDynamicReserveConfig_once() (gas: 540623)
[PASS] test_addDynamicReserveConfig_revertsWith_AccessManagedUnauthorized(address) (runs: 5000, μ: 52295, ~: 52295)
[PASS] test_addDynamicReserveConfig_revertsWith_InvalidCollateralFactorAndMaxLiquidationBonus_collateralFactor() (gas: 59362)
[PASS] test_addDynamicReserveConfig_revertsWith_InvalidCollateralFactorAndMaxLiquidationBonus_liquidationBonus() (gas: 41797)
[PASS] test_addDynamicReserveConfig_revertsWith_InvalidLiquidationFee() (gas: 42271)
[PASS] test_addDynamicReserveConfig_revertsWith_ReserveNotListed() (gas: 34262)
[PASS] test_fuzz_addDynamicReserveConfig_spaced_dup_updates(bytes32) (runs: 5000, μ: 153773, ~: 153773)
[PASS] test_fuzz_addDynamicReserveConfig_trailing_order(bytes32) (runs: 5000, μ: 150460, ~: 150460)
[PASS] test_offboardReserve_existing_borrows_remain_unaffected() (gas: 1160843)
[PASS] test_updateDynamicReserveConfig() (gas: 1715564)
[PASS] test_updateDynamicReserveConfig_fuzz_revertsWith_InvalidCollateralFactorAndMaxLiquidationBonus(uint16,uint32) (runs: 5000, μ: 63208, ~: 63373)
[PASS] test_updateDynamicReserveConfig_revertsWith_AccessManagedUnauthorized(address) (runs: 5000, μ: 52274, ~: 52274)
[PASS] test_updateDynamicReserveConfig_revertsWith_ConfigKeyUninitialized() (gas: 54155)
[PASS] test_updateDynamicReserveConfig_revertsWith_InvalidCollateralFactor() (gas: 56323)
[PASS] test_updateDynamicReserveConfig_revertsWith_InvalidCollateralFactorAndMaxLiquidationBonus_collateralFactor() (gas: 57109)
[PASS] test_updateDynamicReserveConfig_revertsWith_InvalidCollateralFactorAndMaxLiquidationBonus_liquidationBonus() (gas: 57257)
[PASS] test_updateDynamicReserveConfig_revertsWith_InvalidLiquidationFee() (gas: 57795)
[PASS] test_updateDynamicReserveConfig_revertsWith_ReserveNotListed() (gas: 34592)
Suite result: ok. 20 passed; 0 failed; 0 skipped; finished in 10.09s (10.07s CPU time)

Ran 5 tests for tests/gas/Spoke.Getters.gas.t.sol:SpokeGetters_Gas_Tests
[PASS] test_getUserAccountData() (gas: 22776)
[PASS] test_getUserAccountData_oneSupplies() (gas: 274198)
[PASS] test_getUserAccountData_twoSupplies() (gas: 499979)
[PASS] test_getUserAccountData_twoSupplies_oneBorrows() (gas: 1029589)
[PASS] test_getUserAccountData_twoSupplies_twoBorrows() (gas: 1595672)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 29.93ms (4.71ms CPU time)

Ran 5 tests for tests/unit/Spoke/Spoke.Getters.t.sol:SpokeGettersTest
[PASS] test_getLiquidationBonus_configured() (gas: 89437)
Logs:
  Bound result 2
  Bound result 1000000000000000000
  Bound result 4000
  Bound result 900000000000000000

[PASS] test_getLiquidationBonus_fuzz_configured(uint256,uint256,uint16,uint64) (runs: 5000, μ: 88130, ~: 88548)
[PASS] test_getLiquidationBonus_fuzz_notConfigured(uint256,uint256) (runs: 5000, μ: 65780, ~: 65534)
[PASS] test_getLiquidationBonus_notConfigured() (gas: 67041)
Logs:
  Bound result 2
  Bound result 1000000000000000000

[PASS] test_protocol_getters() (gas: 278487)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 1.92s (1.91s CPU time)

Ran 4 tests for tests/unit/Spoke/Liquidations/Spoke.LiquidationCall.Dust.t.sol:SpokeLiquidationCallDustTest
[PASS] test_collateralDust_min_debtToTarget() (gas: 7403494)
[PASS] test_debtToCover_exceeds_collateralValue() (gas: 7397000)
[PASS] test_dustColl_allowed() (gas: 7244781)
[PASS] test_dustDebt_allowed() (gas: 7391941)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 46.83ms (22.34ms CPU time)

Ran 8 tests for tests/unit/libraries/LiquidationLogic/LiquidationLogic.LiquidationAmounts.t.sol:LiquidationLogicLiquidationAmountsTest
[PASS] test_calculateLiquidationAmounts_EnoughCollateral() (gas: 15278)
[PASS] test_calculateLiquidationAmounts_InsufficientCollateral() (gas: 15516)
[PASS] test_calculateLiquidationAmounts_fuzz_EnoughCollateral_CollateralDust((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 59726, ~: 59227)
[PASS] test_calculateLiquidationAmounts_fuzz_EnoughCollateral_NoCollateralDust((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 57279, ~: 57312)
[PASS] test_calculateLiquidationAmounts_fuzz_EnoughCollateral_NoDebtLeft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 75996, ~: 75910)
[PASS] test_calculateLiquidationAmounts_fuzz_InsufficientCollateral((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 61232, ~: 61038)
[PASS] test_calculateLiquidationAmounts_fuzz_revertsWith_MustNotLeaveDust_Collateral((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 57701, ~: 57636)
[PASS] test_calculateLiquidationAmounts_fuzz_revertsWith_MustNotLeaveDust_Debt((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 71399, ~: 71344)
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 19.79s (19.77s CPU time)

Ran 4 tests for tests/unit/libraries/LiquidationLogic/LiquidationLogic.LiquidationBonus.t.sol:LiquidationLogicLiquidationBonusTest
[PASS] test_calculateLiquidationBonus_MinBonusDueToRounding() (gas: 9360)
[PASS] test_calculateLiquidationBonus_PartialBonus() (gas: 9381)
[PASS] test_calculateLiquidationBonus_fuzz_ConstantBonus(uint256,uint256,uint256,uint256) (runs: 5000, μ: 17242, ~: 17178)
[PASS] test_calculateLiquidationBonus_fuzz_MaxBonus(uint256,uint256,uint256,uint256) (runs: 5000, μ: 19580, ~: 19506)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 980.52ms (957.56ms CPU time)

Ran 13 tests for tests/unit/libraries/LiquidationLogic/LiquidationLogic.ValidateLiquidationCall.t.sol:LiquidationLogicValidateLiquidationCallTest
[PASS] test_validateLiquidationCall() (gas: 31018)
[PASS] test_validateLiquidationCall_revertsWith_CannotReceiveShares_CollateralFrozen() (gas: 63008)
[PASS] test_validateLiquidationCall_revertsWith_CollateralCannotBeLiquidated_NotUsingAsCollateral() (gas: 32027)
[PASS] test_validateLiquidationCall_revertsWith_CollateralCannotBeLiquidated_ZeroCollateralFactor() (gas: 32054)
[PASS] test_validateLiquidationCall_revertsWith_HealthFactorNotBelowThreshold() (gas: 36791)
[PASS] test_validateLiquidationCall_revertsWith_InvalidDebtToCover() (gas: 31762)
[PASS] test_validateLiquidationCall_revertsWith_ReserveNotBorrowed() (gas: 32074)
[PASS] test_validateLiquidationCall_revertsWith_ReserveNotListed_ZeroCollateralHub() (gas: 31837)
[PASS] test_validateLiquidationCall_revertsWith_ReserveNotListed_ZeroDebtHub() (gas: 31894)
[PASS] test_validateLiquidationCall_revertsWith_ReserveNotSupplied() (gas: 32041)
[PASS] test_validateLiquidationCall_revertsWith_ReservePaused_CollateralPaused() (gas: 36728)
[PASS] test_validateLiquidationCall_revertsWith_ReservePaused_DebtPaused() (gas: 36811)
[PASS] test_validateLiquidationCall_revertsWith_SelfLiquidation() (gas: 38718)
Suite result: ok. 13 passed; 0 failed; 0 skipped; finished in 18.88ms (1.07ms CPU time)

Ran 26 tests for tests/unit/MathUtils.t.sol:MathUtilsTest
[PASS] test_add_edge_cases() (gas: 4788)
[PASS] test_add_negative_operand(uint256,int256) (runs: 5000, μ: 9323, ~: 9561)
[PASS] test_add_positive_operand(uint256,int256) (runs: 5000, μ: 4013, ~: 4010)
[PASS] test_calculateLinearInterest() (gas: 4511)
[PASS] test_calculateLinearInterest_add_edge() (gas: 5087)
[PASS] test_calculateLinearInterest_edge_cases() (gas: 16870)
Logs:
  Bound result 0
  Bound result 1
  Bound result 864000000
  Bound result 864000000

[PASS] test_calculateLinearInterest_reverts_on_past_timestamp(uint32) (runs: 5000, μ: 7588, ~: 7508)
[PASS] test_constants() (gas: 3211)
[PASS] test_fuzz_calculateLinearInterest(uint96,uint32,uint256) (runs: 5000, μ: 8696, ~: 8997)
[PASS] test_fuzz_mulDivDown(uint256,uint256,uint256) (runs: 5000, μ: 3491, ~: 3545)
[PASS] test_fuzz_mulDivUp(uint256,uint256,uint256) (runs: 5000, μ: 3666, ~: 3781)
[PASS] test_min(uint256,uint256) (runs: 5000, μ: 3338, ~: 3338)
[PASS] test_mulDivDown_NoRemainder() (gas: 3324)
[PASS] test_mulDivDown_RevertOnDivByZero() (gas: 3191)
[PASS] test_mulDivDown_RevertOnOverflow() (gas: 3203)
[PASS] test_mulDivDown_WithRemainder() (gas: 3236)
[PASS] test_mulDivDown_ZeroAOrB() (gas: 3768)
[PASS] test_mulDivUp_NoRemainder() (gas: 3350)
[PASS] test_mulDivUp_RevertOnDivByZero() (gas: 3146)
[PASS] test_mulDivUp_RevertOnOverflow() (gas: 3204)
[PASS] test_mulDivUp_WithRemainder() (gas: 3349)
[PASS] test_mulDivUp_ZeroAOrB() (gas: 3818)
[PASS] test_signedSub(uint256,uint256) (runs: 5000, μ: 8639, ~: 8594)
[PASS] test_uncheckedAdd(uint256,uint256) (runs: 5000, μ: 3460, ~: 3452)
[PASS] test_uncheckedExp(uint256,uint256) (runs: 5000, μ: 11474, ~: 7279)
[PASS] test_uncheckedSub(uint256,uint256) (runs: 5000, μ: 3456, ~: 3374)
Suite result: ok. 26 passed; 0 failed; 0 skipped; finished in 1.46s (1.45s CPU time)

Ran 34 tests for tests/unit/NativeTokenGateway.t.sol:NativeTokenGatewayTest
[PASS] test_borrowNative() (gas: 622400)
Logs:
  Bound result 5000000000000000000

[PASS] test_borrowNative_fuzz(uint256) (runs: 5000, μ: 622633, ~: 622429)
[PASS] test_borrowNative_fuzz_otherReceiver(uint256) (runs: 5000, μ: 648590, ~: 648386)
[PASS] test_borrowNative_otherReceiver() (gas: 648251)
Logs:
  Bound result 5000000000000000000

[PASS] test_borrowNative_revertsWith_InvalidAddress() (gas: 30607)
[PASS] test_borrowNative_revertsWith_InvalidAmount() (gas: 30649)
[PASS] test_borrowNative_revertsWith_NotNativeWrappedAsset() (gas: 30732)
[PASS] test_constructor() (gas: 1050731)
[PASS] test_constructor_revertsWith_InvalidAddress() (gas: 130011)
[PASS] test_fallback_revertsWith_UnsupportedAction() (gas: 17453)
[PASS] test_receive_revertsWith_UnsupportedAction() (gas: 17216)
[PASS] test_renouncePositionManagerRole() (gas: 44795)
[PASS] test_renouncePositionManagerRole_revertsWith_OwnableUnauthorizedAccount() (gas: 50939)
[PASS] test_repayNative() (gas: 747667)
Logs:
  Bound result 5000000000000000000

[PASS] test_repayNative_excessAmount() (gas: 639394)
[PASS] test_repayNative_fuzz(uint256) (runs: 5000, μ: 747271, ~: 748324)
[PASS] test_repayNative_fuzz_withInterest(uint256,uint256) (runs: 5000, μ: 649681, ~: 644078)
[PASS] test_repayNative_revertsWith_InvalidAmount() (gas: 30623)
[PASS] test_repayNative_revertsWith_NativeAmountMismatch() (gas: 54820)
[PASS] test_repayNative_revertsWith_NotNativeWrappedAsset() (gas: 37428)
[PASS] test_supplyNative() (gas: 234409)
Logs:
  Bound result 100000000000000000000

[PASS] test_supplyNative_fuzz(uint256) (runs: 5000, μ: 234750, ~: 234481)
[PASS] test_supplyNative_revertsWith_InvalidAmount() (gas: 30625)
[PASS] test_supplyNative_revertsWith_NativeAmountMismatch() (gas: 54653)
[PASS] test_supplyNative_revertsWith_NotNativeWrappedAsset() (gas: 37341)
[PASS] test_withdrawNative() (gas: 280581)
Logs:
  Bound result 100000000000000000000

[PASS] test_withdrawNative_fuzz(uint256) (runs: 5000, μ: 280557, ~: 280631)
[PASS] test_withdrawNative_fuzz_allBalance(uint256) (runs: 5000, μ: 234729, ~: 234537)
[PASS] test_withdrawNative_fuzz_allBalanceWithInterest(uint256,uint256) (runs: 5000, μ: 614953, ~: 616048)
[PASS] test_withdrawNative_fuzz_otherReceiver(uint256) (runs: 5000, μ: 264349, ~: 264157)
[PASS] test_withdrawNative_otherReceiver() (gas: 264164)
Logs:
  Bound result 100000000000000000000

[PASS] test_withdrawNative_revertsWith_InvalidAddress() (gas: 30518)
[PASS] test_withdrawNative_revertsWith_InvalidAmount() (gas: 30569)
[PASS] test_withdrawNative_revertsWith_NotNativeWrappedAsset() (gas: 30601)
Suite result: ok. 34 passed; 0 failed; 0 skipped; finished in 74.53s (74.51s CPU time)

Ran 4 tests for tests/unit/NoncesKeyed.t.sol:NoncesKeyedTest
[PASS] test_useCheckedNonce_monotonic(bytes32) (runs: 5000, μ: 16229, ~: 16229)
[PASS] test_useCheckedNonce_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 107533, ~: 107533)
[PASS] test_useNonce_monotonic(bytes32) (runs: 5000, μ: 17035, ~: 17035)
[PASS] test_useNonce_zeroKey_monotonic(bytes32) (runs: 5000, μ: 16983, ~: 16983)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 4.70s (4.70s CPU time)

Ran 10 tests for tests/unit/PercentageMath.t.sol:PercentageMathTests
[PASS] test_constants() (gas: 8664)
[PASS] test_fromBpsDown() (gas: 9678)
[PASS] test_percentDiv() (gas: 15222)
[PASS] test_percentDivUp_ge_value(uint256,uint256) (runs: 5000, μ: 15285, ~: 15509)
[PASS] test_percentDivUp_le_value(uint256,uint256) (runs: 5000, μ: 15668, ~: 15662)
[PASS] test_percentDiv_fuzz(uint256,uint256) (runs: 5000, μ: 12884, ~: 13012)
[PASS] test_percentMul() (gas: 15116)
[PASS] test_percentMulUp_ge_value(uint256,uint256) (runs: 5000, μ: 15651, ~: 15645)
[PASS] test_percentMulUp_le_value(uint256,uint256) (runs: 5000, μ: 15288, ~: 15512)
[PASS] test_percentMul_fuzz(uint256,uint256) (runs: 5000, μ: 11766, ~: 12247)
Suite result: ok. 10 passed; 0 failed; 0 skipped; finished in 1.46s (1.46s CPU time)

Ran 29 tests for tests/unit/libraries/PositionStatusMap.t.sol:PositionStatusMapTest
[PASS] test_bucketId() (gas: 8971)
[PASS] test_collateralCount() (gas: 110158)
[PASS] test_collateralCount(uint256) (runs: 5000, μ: 2084397, ~: 1899913)
[PASS] test_collateralCount_ignoresInvalidBits() (gas: 124482)
[PASS] test_constants() (gas: 44966)
[PASS] test_fls() (gas: 545261)
[PASS] test_fromBitId(uint256,uint256) (runs: 5000, μ: 14108, ~: 14336)
[PASS] test_fuzz_setBorrowing(uint256,bool) (runs: 5000, μ: 22353, ~: 32140)
[PASS] test_fuzz_setUseAsCollateral(uint256,bool) (runs: 5000, μ: 22449, ~: 32236)
[PASS] test_getBucketWord(uint256) (runs: 5000, μ: 14489, ~: 14489)
[PASS] test_isUsingAsCollateralOrBorrowing_slot0() (gas: 108801)
[PASS] test_isUsingAsCollateralOrBorrowing_slot1() (gas: 44065)
[PASS] test_isolateBorrowing(uint256) (runs: 5000, μ: 162282, ~: 162282)
[PASS] test_isolateBorrowingUntil(uint256,uint256) (runs: 5000, μ: 154774, ~: 154662)
[PASS] test_isolateCollateral(uint256) (runs: 5000, μ: 162044, ~: 162044)
[PASS] test_isolateCollateralUntil(uint256,uint256) (runs: 5000, μ: 154753, ~: 154641)
[PASS] test_isolateUntil(uint256,uint256) (runs: 5000, μ: 143621, ~: 143619)
[PASS] test_next(uint256) (runs: 5000, μ: 20429, ~: 20328)
[PASS] test_nextBorrowing(uint256) (runs: 5000, μ: 18206, ~: 18289)
[PASS] test_nextBorrowing_continuous() (gas: 63845326)
[PASS] test_nextCollateral(uint256) (runs: 5000, μ: 18124, ~: 17716)
[PASS] test_nextCollateral_continuous() (gas: 64381718)
[PASS] test_next_continuous() (gas: 91795620)
[PASS] test_popCount(bytes32) (runs: 5000, μ: 38133, ~: 38133)
[PASS] test_setBorrowing_slot0() (gas: 44129)
[PASS] test_setBorrowing_slot1() (gas: 44166)
[PASS] test_setUseAsCollateral_slot0() (gas: 44203)
[PASS] test_setUseAsCollateral_slot1() (gas: 44185)
[PASS] test_setters_use_correct_slot(uint256) (runs: 5000, μ: 22195, ~: 22195)
Suite result: ok. 29 passed; 0 failed; 0 skipped; finished in 102.21s (102.20s CPU time)

Ran 5 tests for tests/unit/Rescuable.t.sol:RescuableTest
[PASS] test_constructor() (gas: 12654)
[PASS] test_rescueNative_fuzz(uint256) (runs: 5000, μ: 33695, ~: 33370)
[PASS] test_rescueNative_revertsWith_OnlyRescueGuardian() (gas: 11400)
[PASS] test_rescueToken_fuzz(uint256) (runs: 5000, μ: 209620, ~: 209387)
[PASS] test_rescueToken_revertsWith_OnlyRescueGuardian() (gas: 183212)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 3.40s (3.38s CPU time)

Ran 10 tests for tests/unit/misc/SignatureGateway/SignatureGateway.Constants.t.sol:SignatureGatewayConstantsTest
[PASS] test_DOMAIN_SEPARATOR() (gas: 2038827)
[PASS] test_borrow_typeHash() (gas: 9902)
[PASS] test_constructor() (gas: 2186349)
[PASS] test_eip712Domain() (gas: 2044411)
[PASS] test_repay_typeHash() (gas: 9959)
[PASS] test_setUsingAsCollateral_typeHash() (gas: 9971)
[PASS] test_supply_typeHash() (gas: 9907)
[PASS] test_updateUserDynamicConfig_typeHash() (gas: 9941)
[PASS] test_updateUserRiskPremium_typeHash() (gas: 9904)
[PASS] test_withdraw_typeHash() (gas: 10037)
Suite result: ok. 10 passed; 0 failed; 0 skipped; finished in 19.23ms (2.05ms CPU time)

Ran 4 tests for tests/unit/misc/SignatureGateway/SignatureGateway.PermitReserve.t.sol:SignatureGatewayPermitReserveTest
[PASS] test_permitReserve() (gas: 102415)
[PASS] test_permitReserve_forwards_correct_call() (gas: 49518)
[PASS] test_permitReserve_ignores_permit_reverts() (gas: 38413)
[PASS] test_permitReserve_revertsWith_ReserveNotListed() (gas: 28359)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 19.31ms (1.87ms CPU time)

Ran 2 tests for tests/unit/misc/SignatureGateway/SignatureGateway.Reverts.InsufficientAllowance.t.sol:SignatureGateway_InsufficientAllowance_Test
[PASS] test_repayWithSig_revertsWith_ERC20InsufficientAllowance() (gas: 467163)
[PASS] test_supplyWithSig_revertsWith_ERC20InsufficientAllowance() (gas: 84224)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 19.81ms (2.60ms CPU time)

Ran 21 tests for tests/unit/misc/SignatureGateway/SignatureGateway.Reverts.InvalidSignature.t.sol:SignatureGatewayInvalidSignatureTest
[PASS] test_borrowWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 186128, ~: 186128)
[PASS] test_borrowWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 36111)
[PASS] test_borrowWithSig_revertsWith_InvalidSignature_dueTo_InvalidSigner() (gas: 34553)
[PASS] test_repayWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 186107, ~: 186107)
[PASS] test_repayWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 36067)
[PASS] test_repayWithSig_revertsWith_InvalidSignature_dueTo_InvalidSigner() (gas: 34642)
[PASS] test_setUsingAsCollateralWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 229395, ~: 229395)
[PASS] test_setUsingAsCollateralWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 36124)
[PASS] test_setUsingAsCollateralWithSig_revertsWith_InvalidSignature_dueTo_InvalidSigner() (gas: 34720)
[PASS] test_supplyWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 186192, ~: 186192)
[PASS] test_supplyWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 36134)
[PASS] test_supplyWithSig_revertsWith_InvalidSignature_dueTo_InvalidSigner() (gas: 34629)
[PASS] test_updateUserDynamicConfigWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 64831, ~: 64831)
[PASS] test_updateUserDynamicConfigWithSig_revertsWith_InvalidSignatureDueTo_InvalidSigner() (gas: 23288)
[PASS] test_updateUserDynamicConfigWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 24720)
[PASS] test_updateUserRiskPremiumWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 64842, ~: 64842)
[PASS] test_updateUserRiskPremiumWithSig_revertsWith_InvalidSignatureDueTo_InvalidSigner() (gas: 23272)
[PASS] test_updateUserRiskPremiumWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 24787)
[PASS] test_withdrawWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 186060, ~: 186060)
[PASS] test_withdrawWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 36110)
[PASS] test_withdrawWithSig_revertsWith_InvalidSignature_dueTo_InvalidSigner() (gas: 34596)
Suite result: ok. 21 passed; 0 failed; 0 skipped; finished in 43.64s (43.62s CPU time)

Ran 7 tests for tests/unit/misc/SignatureGateway/SignatureGateway.Reverts.Unauthorized.t.sol:SignatureGateway_Unauthorized_PositionManagerActive_Test
[PASS] test_borrowWithSig_revertsWith_Unauthorized() (gas: 77338)
[PASS] test_repayWithSig_revertsWith_Unauthorized() (gas: 113915)
[PASS] test_setUsingAsCollateralWithSig_revertsWith_Unauthorized() (gas: 69653)
[PASS] test_supplyWithSig_revertsWith_Unauthorized() (gas: 138300)
[PASS] test_updateUserDynamicConfigWithSig_revertsWith_Unauthorized() (gas: 79298)
[PASS] test_updateUserRiskPremiumWithSig_revertsWith_Unauthorized() (gas: 79130)
[PASS] test_withdrawWithSig_revertsWith_Unauthorized() (gas: 98982)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 21.46ms (4.21ms CPU time)

Ran 7 tests for tests/unit/misc/SignatureGateway/SignatureGateway.Reverts.Unauthorized.t.sol:SignatureGateway_Unauthorized_PositionManagerNotActive_Test
[PASS] test_borrowWithSig_revertsWith_Unauthorized() (gas: 75137)
[PASS] test_repayWithSig_revertsWith_Unauthorized() (gas: 111714)
[PASS] test_setUsingAsCollateralWithSig_revertsWith_Unauthorized() (gas: 67452)
[PASS] test_supplyWithSig_revertsWith_Unauthorized() (gas: 136099)
[PASS] test_updateUserDynamicConfigWithSig_revertsWith_Unauthorized() (gas: 77097)
[PASS] test_updateUserRiskPremiumWithSig_revertsWith_Unauthorized() (gas: 76929)
[PASS] test_withdrawWithSig_revertsWith_Unauthorized() (gas: 96781)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 21.41ms (4.21ms CPU time)

Ran 11 tests for tests/unit/misc/SignatureGateway/SignatureGateway.t.sol:SignatureGatewayTest
[PASS] test_borrowWithSig() (gas: 814886)
[PASS] test_renouncePositionManagerRole() (gas: 26616)
[PASS] test_renouncePositionManagerRole_revertsWith_OnlyOwner() (gas: 16173)
[PASS] test_repayWithSig() (gas: 793523)
[PASS] test_setSelfAsUserPositionManagerWithSig() (gas: 308720)
[PASS] test_setUsingAsCollateralWithSig() (gas: 617732)
[PASS] test_supplyWithSig() (gas: 590824)
[PASS] test_updateUserDynamicConfigWithSig() (gas: 320991)
[PASS] test_updateUserRiskPremiumWithSig() (gas: 907792)
[PASS] test_useNonce_monotonic(bytes32) (runs: 5000, μ: 16888, ~: 16888)
[PASS] test_withdrawWithSig() (gas: 599561)
Suite result: ok. 11 passed; 0 failed; 0 skipped; finished in 447.72ms (430.65ms CPU time)

Ran 3 tests for tests/unit/Spoke/Spoke.Access.t.sol:SpokeAccessTest
[PASS] testAccess_change_authority() (gas: 2612679)
[PASS] testAccess_hub_functions_callable_by_spokes() (gas: 603472)
[PASS] testAccess_spoke_admin_config_access() (gas: 490383)
Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 25.38ms (3.21ms CPU time)

Ran 1 test for tests/unit/Spoke/Spoke.AccrueInterest.Scenario.t.sol:SpokeAccrueInterestScenarioTest
[SKIP: pending rft] test_accrueInterest_fuzz_RPBorrowAndSkipTime_twoActions((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256),uint32) (runs: 0, μ: 0, ~: 0)
Suite result: ok. 0 passed; 0 failed; 1 skipped; finished in 21.79ms (4.25ms CPU time)

Ran 7 tests for tests/unit/Spoke/Spoke.AccrueInterest.t.sol:SpokeAccrueInterestTest
[PASS] test_accrueInterest_NoActionTaken() (gas: 138269)
[PASS] test_accrueInterest_NoInterest_NoDebt(uint32) (runs: 5000, μ: 662018, ~: 661933)
[PASS] test_accrueInterest_NoInterest_OnlySupply(uint32) (runs: 5000, μ: 258127, ~: 258434)
[PASS] test_accrueInterest_TenPercentRp(uint256,uint32) (runs: 5000, μ: 596245, ~: 597258)
[PASS] test_accrueInterest_fuzz_BorrowAmountAndSkipTime(uint256,uint32) (runs: 5000, μ: 556558, ~: 557147)
[PASS] test_accrueInterest_fuzz_RPBorrowAndSkipTime((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256),uint32) (runs: 5000, μ: 3938144, ~: 3953480)
[PASS] test_accrueInterest_fuzz_RatesRPBorrowAndSkipTime((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256),(uint96,uint96,uint96,uint96),uint32) (runs: 5000, μ: 3999725, ~: 4012176)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 214.49s (214.48s CPU time)

Ran 5 tests for tests/unit/Spoke/Spoke.AccrueLiquidityFee.EdgeCases.t.sol:SpokeAccrueLiquidityFeeEdgeCasesTest
[PASS] test_accrueLiquidityFee_fuzz_maxLiquidityFee_with_premium(uint256,uint256,uint256,uint256) (runs: 5000, μ: 558754, ~: 558914)
[PASS] test_accrueLiquidityFee_fuzz_maxLiquidityFee_with_premium_multiple_users(uint256,uint256,uint256,uint256,uint256) (runs: 5000, μ: 801590, ~: 801583)
[PASS] test_accrueLiquidityFee_maxLiquidityFee_multi_spoke() (gas: 588442864)
[PASS] test_accrueLiquidityFee_maxLiquidityFee_multi_user() (gas: 249886089)
[PASS] test_accrueLiquidityFee_maxLiquidityFee_with_premium() (gas: 559233)
Logs:
  Bound result 500000000000000000000
  Bound result 5000
  Bound result 34560000
  Bound result 2

Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 20.89s (20.88s CPU time)

Ran 7 tests for tests/unit/Spoke/Spoke.AccrueLiquidityFee.t.sol:SpokeAccrueLiquidityFeeTest
[PASS] test_accrueLiquidityFee() (gas: 849252)
[PASS] test_accrueLiquidityFee_NoActionTaken() (gas: 97975)
[PASS] test_accrueLiquidityFee_NoInterest_OnlySupply(uint32) (runs: 5000, μ: 235977, ~: 236131)
[PASS] test_accrueLiquidityFee_exact() (gas: 838144)
[PASS] test_accrueLiquidityFee_fuzz_BorrowAmountAndSkipTime(uint256,uint32) (runs: 5000, μ: 833445, ~: 862602)
[PASS] test_accrueLiquidityFee_maxLiquidityFee() (gas: 553850)
[PASS] test_accrueLiquidityFee_setUsingAsCollateral() (gas: 883831)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 19.37s (19.36s CPU time)

Ran 11 tests for tests/gas/Spoke.Operations.gas.t.sol:SpokeOperations_Gas_Tests
[PASS] test_borrow() (gas: 1166384)
[PASS] test_liquidation() (gas: 8344376)
[PASS] test_liquidation_receiveShares() (gas: 8306397)
[PASS] test_multicall_ops() (gas: 1601378)
[PASS] test_repay() (gas: 960318)
[PASS] test_setUserPositionManagerWithSig() (gas: 294086)
[PASS] test_supply() (gas: 948510)
[PASS] test_updateRiskPremium() (gas: 14324...*[Comment body truncated]*
@github-actions
Copy link

github-actions bot commented Oct 10, 2025

♻️ Forge Gas Snapshots

Path Value
snapshots/Spoke.Getters.json
getUserAccountData: supplies: 0, borrows: 0 ↓0% (-22) 12,142
getUserAccountData: supplies: 1, borrows: 0 ↓0% (-22) 47,232
getUserAccountData: supplies: 2, borrows: 0 ↓0% (-22) 77,437
getUserAccountData: supplies: 2, borrows: 1 ↓0% (-22) 98,178
getUserAccountData: supplies: 2, borrows: 2 ↓0% (-22) 117,573
snapshots/Spoke.Operations.ZeroRiskPremium.json
liquidationCall: full ↑0% (+739) 291,754
liquidationCall: partial ↑0% (+739) 315,848
permitReserve + repay (multicall) ↑0% (+61) 235,861
permitReserve + supply (multicall) ↓0% (-43) 141,007
permitReserve + supply + enable collateral (multicall) ↑0% (+23) 176,310
repay: full ↑0% (+82) 151,846
repay: partial ↑0% (+82) 176,309
setUserPositionManagerWithSig: disable ↓0% (-22) 44,896
setUserPositionManagerWithSig: enable ↓0% (-22) 68,925
supply + enable collateral (multicall) ↑0% (+22) 154,251
supply: 0 borrows, collateral disabled ↓0% (-22) 115,762
supply: 0 borrows, collateral enabled ↓0% (-22) 120,159
supply: 1 borrow ↓0% (-22) 120,151
supply: second action, same reserve ↓0% (-22) 103,059
updateUserDynamicConfig: 1 collateral ↑0% (+66) 73,827
updateUserDynamicConfig: 2 collaterals ↑0% (+66) 88,687
updateUserRiskPremium: 1 borrow ↓0% (-22) 95,254
updateUserRiskPremium: 2 borrows ↓0% (-22) 111,346
usingAsCollateral: 0 borrows, enable ↑0% (+66) 59,042
usingAsCollateral: 1 borrow, disable ↑0% (+66) 105,589
usingAsCollateral: 1 borrow, enable ↑0% (+66) 32,364
usingAsCollateral: 2 borrows, disable ↑0% (+66) 128,054
usingAsCollateral: 2 borrows, enable ↑0% (+66) 41,942
liquidationCall (receiveShares): full 263815
liquidationCall (receiveShares): partial 305858
snapshots/Spoke.Operations.json
liquidationCall: full ↑0% (+739) 325,140
liquidationCall: partial ↑0% (+739) 349,234
permitReserve + repay (multicall) ↑0% (+61) 269,240
permitReserve + supply (multicall) ↓0% (-43) 141,007
permitReserve + supply + enable collateral (multicall) ↑0% (+23) 176,310
repay: full ↑0% (+82) 146,487
repay: partial ↑0% (+82) 209,688
setUserPositionManagerWithSig: disable ↓0% (-22) 44,896
setUserPositionManagerWithSig: enable ↓0% (-22) 68,925
supply + enable collateral (multicall) ↑0% (+22) 154,251
supply: 0 borrows, collateral disabled ↓0% (-22) 115,762
supply: 0 borrows, collateral enabled ↓0% (-22) 120,159
supply: 1 borrow ↓0% (-22) 120,151
supply: second action, same reserve ↓0% (-22) 103,059
updateUserDynamicConfig: 1 collateral ↑0% (+66) 73,827
updateUserDynamicConfig: 2 collaterals ↑0% (+66) 88,687
updateUserRiskPremium: 1 borrow ↓0% (-22) 177,341
updateUserRiskPremium: 2 borrows ↓0% (-22) 262,706
usingAsCollateral: 0 borrows, enable ↑0% (+66) 59,042
usingAsCollateral: 1 borrow, disable ↑0% (+66) 187,676
usingAsCollateral: 1 borrow, enable ↑0% (+66) 32,364
usingAsCollateral: 2 borrows, disable ↑0% (+66) 287,413
usingAsCollateral: 2 borrows, enable ↑0% (+66) 41,942
liquidationCall (receiveShares): full 297201
liquidationCall (receiveShares): partial 339244
🔕 Unchanged
Path Value
snapshots/Hub.Operations.json
add 113,832
draw 122,026
eliminateDeficit: full 57,818
eliminateDeficit: partial 67,394
payFee 73,744
refreshPremium 96,823
remove: full 75,059
remove: partial 80,306
reportDeficit 118,722
restore: full 97,460
restore: partial 110,890
transferShares 79,425
snapshots/Spoke.Operations.ZeroRiskPremium.json
borrow: first 199,032
borrow: second action, same reserve 179,553
withdraw: 0 borrows, full 127,742
withdraw: 0 borrows, partial 132,783
withdraw: 1 borrow, partial 161,765
withdraw: 2 borrows, partial 184,218
withdraw: non collateral 126,851
snapshots/Spoke.Operations.json
borrow: first 269,201
borrow: second action, same reserve 212,722
withdraw: 0 borrows, full 127,742
withdraw: 0 borrows, partial 132,783
withdraw: 1 borrow, partial 241,352
withdraw: 2 borrows, partial 341,078
withdraw: non collateral 126,851

bool isUserInDeficit = LiquidationLogic.liquidateUser(
_reserves[collateralReserveId],
_reserves[debtReserveId],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does passing _reserves save anything? i d make sense to do it for consistency also

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would declare storage pointers for both pos & reserves like before but at the top of this fn in the library, such that we don't do repeated lookups for storage slots -> hopefully stack too deep is feeling kind

Copy link
Contributor Author

@yan-man yan-man Oct 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hopefully stack too deep is feeling kind

it was not feeling kind...I passed in reserves for consistency anyway. It costs ~2k more, basically i think bc we do the repeated lookups

ca5722e

) internal returns (bool) {
IHubBase hub = reserve.hub;
uint256 assetId = reserve.assetId;
IHubBase hub = collateralReserve.hub;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could just pass the hub address here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to clarify, you mean include it in LiquidateCollateralParams right? (and we should pass it as IHub instead of address I think)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trying to pass hub as a param caused stack issues

}

/// @dev Validates applied premium delta for given premium data and returns updated premium data.
function _validateApplyPremiumDelta(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was much better where it was, right below _applyPremiumDelta
why was this moved down?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's pure and based on solidity style guideline must be at the end

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's very awkwardly placed now, was much better before; let's make an exception instead of being sticklers pls

sharesToLiquidator = hub.remove(assetId, params.collateralToLiquidator, params.liquidator);
}

if (sharesToLiquidate > sharesToLiquidator) {
Copy link
Member

@miguelmtzinf miguelmtzinf Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

per @DhairyaSethi, if receiveShares = true and sharesToLiquidate <= sharesToLiquidator (no fees), collateral reserve does not accrue.

Copy link
Contributor

@avniculae avniculae Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a very good point, are there any concerns? (apart from the current issue with the supply share price)

ISpoke.Reserve storage debtReserve,
ISpoke.UserPosition storage collateralPosition,
ISpoke.UserPosition storage debtPosition,
mapping(address user => mapping(uint256 reserveId => ISpoke.UserPosition)) storage positions,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

personally I'd prefer to pass the 3 positions that we are interested in (coll, debt and liq), but nbd

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I tried that initially and ran into some stack issues. Lots of stack issues I encountered trying to tweak things

@yan-man yan-man requested a review from DhairyaSethi October 16, 2025 14:17
@miguelmtzinf miguelmtzinf merged commit 2659b7d into main Oct 16, 2025
7 checks passed
@miguelmtzinf miguelmtzinf deleted the feat/liquidate-receive-shares branch October 16, 2025 17:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6 participants