Skip to content

chore: reorder rp update on deficit#1078

Merged
yan-man merged 22 commits intodevfrom
chore/deficit-reorder
Feb 7, 2026
Merged

chore: reorder rp update on deficit#1078
yan-man merged 22 commits intodevfrom
chore/deficit-reorder

Conversation

@DhairyaSethi
Copy link
Member

@DhairyaSethi DhairyaSethi commented Dec 23, 2025

revert changes done on _reportDeficit reorder done in #1010

motivation:

Someone who reads the code, given the changes, would assume that the _notifyRiskPremiumUpdate would actually perform the main reason for which the function is executed: call hub.refreshPremium and notify the hubs, instead this action is never performed.

The only reason to execute it when we are in the deficit scenario is to only update the positionStatus.hasPositiveRiskPremium state variable and emit the event.

Note: there's one "edge" case for which _notifyRiskPremiumUpdate will early return and will not emit the UpdateUserRiskPremium event: when the liquidated borrower had provided only collaterals with zero collateralRisk. In that case the riskPremium of the user, tracked by positionStatus.riskPremium, would have been already equal to zero.

@yan-man
Copy link
Contributor

yan-man commented Dec 23, 2025

smh code size

@Kogaroshi
Copy link
Contributor

14B over the size limit, not that big of a change tho. We can see if bundled with other changes the code size impact is reduced.

@DhairyaSethi DhairyaSethi changed the base branch from main to dev January 6, 2026 11:04
@github-actions
Copy link

github-actions bot commented Jan 14, 2026

Forge Build Sizes

Contract Runtime Size (B) Initcode Size (B) Runtime Margin (B) Initcode Margin (B)
LiquidationLogic ↑1% (+122) 12,440 ↑1% (+122) 12,492 ↓1% (-122) 12,136 ↓0% (-122) 36,660
LiquidationLogic.spoke ↑1% (+57) 9,829 ↑1% (+57) 9,861 ↓0% (-57) 14,747 ↓0% (-57) 39,291
SpokeInstance ↓0% (-10) 24,342 ↓0% (-10) 25,149 ↑4% (+10) 234 ↑0% (+10) 24,003
🔕 Unchanged
Contract Runtime Size (B) Initcode Size (B) Runtime Margin (B) Initcode Margin (B)
AaveOracle 2,834 3,488 21,742 45,664
AccessManager 12,985 14,210 11,591 34,942
AccessManagerEnumerable 16,881 18,699 7,695 30,453
Address 44 94 24,532 49,058
Arrays 44 94 24,532 49,058
Arrays.hub 16 44 24,560 49,108
Arrays.spoke 16 44 24,560 49,108
AssetInterestRateStrategy 2,704 2,889 21,872 46,263
AssetLogic 44 94 24,532 49,058
AssetLogic.hub 16 44 24,560 49,108
AuthorityUtils 44 94 24,532 49,058
AuthorityUtils.hub 16 44 24,560 49,108
AuthorityUtils.spoke 16 44 24,560 49,108
Bytes 44 94 24,532 49,058
Bytes.spoke 16 44 24,560 49,108
Comparators 44 94 24,532 49,058
Comparators.hub 16 44 24,560 49,108
Comparators.spoke 16 44 24,560 49,108
Constants 499 551 24,077 48,601
Create2Utils 134 184 24,442 48,968
DeployUtils 44 94 24,532 49,058
DeployWrapper 3,330 3,358 21,246 45,794
ECDSA 44 94 24,532 49,058
ECDSA.spoke 16 44 24,560 49,108
EIP712Hash (src/position-manager/libraries/EIP712Hash.sol) 441 493 24,135 48,659
EIP712Hash (src/spoke/libraries/EIP712Hash.sol) 171 221 24,405 48,931
EIP712Hash.spoke 166 194 24,410 48,958
EIP712Types 44 94 24,532 49,058
ERC1967Proxy 135 891 24,441 48,261
ERC1967Utils 44 94 24,532 49,058
EnumerableSet 44 94 24,532 49,058
EnumerableSet.hub 16 44 24,560 49,108
Errors 44 94 24,532 49,058
ExtSloadWrapper 394 422 24,182 48,730
GatewayBaseWrapper 2,400 2,675 22,176 46,477
Hashes 44 94 24,532 49,058
Hub 23,547 23,744 1,029 25,408
HubConfigurator 13,833 14,029 10,743 35,123
JsonBindings 12,853 12,905 11,723 36,247
KeyValueList 44 94 24,532 49,058
KeyValueList.spoke 16 44 24,560 49,108
KeyValueListWrapper 957 985 23,619 48,167
LibBit 44 94 24,532 49,058
LibBit.spoke 16 44 24,560 49,108
LiquidationLogicWrapper 18,567 18,741 6,009 30,411
LowLevelCall 44 94 24,532 49,058
Math 44 94 24,532 49,058
Math.hub 16 44 24,560 49,108
Math.spoke 16 44 24,560 49,108
MathUtils 44 94 24,532 49,058
MathUtils.hub 16 44 24,560 49,108
MathUtils.spoke 16 44 24,560 49,108
MockERC1271Wallet 828 962 23,748 48,190
MockERC20 2,540 3,006 22,036 46,146
MockNoncesKeyed 858 886 23,718 48,266
MockPriceFeed 737 1,395 23,839 47,757
MockReentrantCaller 882 1,083 23,694 48,069
MockSkimSpoke 1,116 1,275 23,460 47,877
NativeTokenGateway 6,187 6,604 18,389 42,548
NoncesKeyed 644 672 23,932 48,480
NoncesKeyed.spoke 387 413 24,189 48,739
Panic 44 94 24,532 49,058
Panic.hub 16 44 24,560 49,108
Panic.spoke 16 44 24,560 49,108
PercentageMath 44 94 24,532 49,058
PercentageMath.hub 16 44 24,560 49,108
PercentageMath.spoke 16 44 24,560 49,108
PercentageMathWrapper 632 660 23,944 48,492
PositionStatusMap 44 94 24,532 49,058
PositionStatusMap.spoke 16 44 24,560 49,108
PositionStatusMapWrapper 3,341 3,369 21,235 45,783
Premium 44 94 24,532 49,058
Premium.hub 16 44 24,560 49,108
Premium.spoke 16 44 24,560 49,108
ProxyAdmin 1,320 1,556 23,256 47,596
RescuableWrapper 908 1,042 23,668 48,110
ReserveFlagsMap 44 94 24,532 49,058
ReserveFlagsMap.spoke 16 44 24,560 49,108
ReserveFlagsMapWrapper 928 956 23,648 48,196
Roles 218 269 24,358 48,883
SafeCast 44 94 24,532 49,058
SafeCast.hub 16 44 24,560 49,108
SafeCast.spoke 16 44 24,560 49,108
SafeERC20 44 94 24,532 49,058
SafeERC20.hub 16 44 24,560 49,108
SafeERC20.spoke 16 44 24,560 49,108
SharesMath 44 94 24,532 49,058
SharesMath.hub 16 44 24,560 49,108
SignatureChecker 44 94 24,532 49,058
SignatureChecker.spoke 16 44 24,560 49,108
SignatureGateway 11,485 12,024 13,091 37,128
SlotDerivation 44 94 24,532 49,058
SlotDerivation.hub 16 44 24,560 49,108
SlotDerivation.spoke 16 44 24,560 49,108
SpokeConfigurator 12,328 12,524 12,248 36,628
SpokeUtils 96 146 24,480 49,006
SpokeUtils.spoke 71 99 24,505 49,053
SpokeUtilsWrapper 1,827 1,855 22,749 47,297
StorageSlot 44 94 24,532 49,058
StorageSlot.hub 16 44 24,560 49,108
StorageSlot.spoke 16 44 24,560 49,108
TestnetERC20 3,649 4,525 20,927 44,627
Time 44 94 24,532 49,058
TransientSlot 44 94 24,532 49,058
TransientSlot.spoke 16 44 24,560 49,108
TransparentUpgradeableProxy 1,419 4,078 23,157 45,074
TreasurySpoke 3,599 4,014 20,977 45,138
UnitPriceFeed 777 1,771 23,799 47,381
UserPositionUtils (src/spoke/libraries/UserPositionDebt.sol) 44 94 24,532 49,058
UserPositionUtils (src/spoke/libraries/UserPositionUtils.sol) 44 94 24,532 49,058
UserPositionUtils.spoke 16 44 24,560 49,108
UserPositionUtilsWrapper (tests/mocks/UserPositionDebtWrapper.sol) 3,263 3,291 21,313 45,861
UserPositionUtilsWrapper (tests/mocks/UserPositionUtilsWrapper.sol) 3,263 3,291 21,313 45,861
Utils 44 94 24,532 49,058
WETH9 2,148 2,614 22,428 46,538
WadRayMath 44 94 24,532 49,058
WadRayMath.hub 16 44 24,560 49,108
WadRayMath.spoke 16 44 24,560 49,108
WadRayMathWrapper 1,514 1,542 23,062 47,610

@github-actions
Copy link

github-actions bot commented Jan 14, 2026

🌈 Test Results
No files changed, compilation skipped

Ran 14 tests for tests/gas/Spoke.Operations.gas.t.sol:SpokeOperations_Gas_Tests
[PASS] test_borrow() (gas: 1325506)
[PASS] test_liquidation_full() (gas: 10890053)
[PASS] test_liquidation_partial() (gas: 10889470)
[PASS] test_liquidation_receiveShares_full() (gas: 10872476)
[PASS] test_liquidation_receiveShares_partial() (gas: 10871895)
[PASS] test_liquidation_reportDeficit_full() (gas: 10868236)
[PASS] test_multicall_ops() (gas: 1404316)
[PASS] test_repay() (gas: 868406)
[PASS] test_setUserPositionManagersWithSig() (gas: 307152)
[PASS] test_supply() (gas: 539086)
[PASS] test_updateRiskPremium() (gas: 1315335)
[PASS] test_updateUserDynamicConfig() (gas: 587622)
[PASS] test_usingAsCollateral() (gas: 1470441)
[PASS] test_withdraw() (gas: 1947067)
Suite result: ok. 14 passed; 0 failed; 0 skipped; finished in 97.00ms (35.39ms CPU time)

Ran 14 tests for tests/gas/Spoke.Operations.gas.t.sol:SpokeOperations_ZeroRiskPremium_Gas_Tests
[PASS] test_borrow() (gas: 1092020)
[PASS] test_liquidation_full() (gas: 10755347)
[PASS] test_liquidation_partial() (gas: 10754764)
[PASS] test_liquidation_receiveShares_full() (gas: 10737770)
[PASS] test_liquidation_receiveShares_partial() (gas: 10737189)
[PASS] test_liquidation_reportDeficit_full() (gas: 10792574)
[PASS] test_multicall_ops() (gas: 1321737)
[PASS] test_repay() (gas: 777567)
[PASS] test_setUserPositionManagersWithSig() (gas: 311606)
[PASS] test_supply() (gas: 541767)
[PASS] test_updateRiskPremium() (gas: 943183)
[PASS] test_updateUserDynamicConfig() (gas: 592076)
[PASS] test_usingAsCollateral() (gas: 1088976)
[PASS] test_withdraw() (gas: 1587569)
Suite result: ok. 14 passed; 0 failed; 0 skipped; finished in 98.75ms (30.92ms CPU time)

Ran 4 tests for tests/unit/Spoke/Spoke.PermitReserve.t.sol:SpokePermitReserveTest
[PASS] test_permitReserve() (gas: 88227)
[PASS] test_permitReserve_forwards_correct_call() (gas: 35554)
[PASS] test_permitReserve_ignores_permit_reverts() (gas: 24390)
[PASS] test_permitReserve_revertsWith_ReserveNotListedIn() (gas: 22949)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 25.21ms (1.02ms CPU time)

Ran 10 tests for tests/unit/Spoke/Spoke.PositionManager.t.sol:SpokePositionManagerTest
[PASS] test_onlyPositionManager_on_borrow() (gas: 538533)
[PASS] test_onlyPositionManager_on_repay() (gas: 563800)
[PASS] test_onlyPositionManager_on_supply() (gas: 291778)
[PASS] test_onlyPositionManager_on_updateUserDynamicConfig() (gas: 1287955)
[PASS] test_onlyPositionManager_on_updateUserRiskPremium() (gas: 1525690)
[PASS] test_onlyPositionManager_on_usingAsCollateral() (gas: 144395)
[PASS] test_onlyPositionManager_on_withdraw() (gas: 320770)
[PASS] test_renouncePositionManagerRole() (gas: 20268)
[PASS] test_renouncePositionManagerRole_noop_from_disabled() (gas: 21904)
[PASS] test_setApprovalForPositionManager(bytes32) (runs: 5000, μ: 18111, ~: 18111)
Suite result: ok. 10 passed; 0 failed; 0 skipped; finished in 408.06ms (384.41ms CPU time)

Ran 20 tests for tests/unit/AaveOracle.t.sol:AaveOracleTest
[PASS] test_DECIMALS() (gas: 8326)
[PASS] test_constructor() (gas: 18428)
[PASS] test_description() (gas: 12039)
[PASS] test_fuzz_constructor(uint8) (runs: 5000, μ: 19888, ~: 20214)
Logs:
  Bound result 1

[PASS] test_getReservePrice() (gas: 48776)
[PASS] test_getReservePrice_revertsWith_InvalidPrice() (gas: 48047)
[PASS] test_getReservePrice_revertsWith_InvalidSource() (gas: 10898)
[PASS] test_getReservePrices() (gas: 80715)
[PASS] test_getReservePrices_revertsWith_InvalidSource() (gas: 50930)
[PASS] test_getReserveSource() (gas: 48946)
[PASS] test_setReserveSource() (gas: 45988)
[PASS] test_setReserveSource_revertsWith_InvalidPrice() (gas: 102779)
[PASS] test_setReserveSource_revertsWith_InvalidSource() (gas: 17228)
[PASS] test_setReserveSource_revertsWith_InvalidSourceDecimals() (gas: 17065)
[PASS] test_setReserveSource_revertsWith_OnlySpoke() (gas: 13021)
[PASS] test_setReserveSource_revertsWith_OracleMismatch() (gas: 5040654)
[PASS] test_setSpoke() (gas: 5068555)
[PASS] test_setSpoke_revertsWith_InvalidAddress() (gas: 10870)
[PASS] test_setSpoke_revertsWith_OnlyDeployer(address) (runs: 5000, μ: 13397, ~: 13397)
[PASS] test_setSpoke_revertsWith_SpokeAlreadySet() (gas: 15080)
Suite result: ok. 20 passed; 0 failed; 0 skipped; finished in 1.10s (1.07s CPU time)

Ran 7 tests for tests/unit/Spoke/Spoke.Repay.EdgeCases.t.sol:SpokeRepayEdgeCaseTest
[PASS] test_fuzz_repay_effect_on_ex_rates(uint256,uint256) (runs: 5000, μ: 701177, ~: 701098)
Logs:
  Bound result 78992632040425094409860859598
  Bound result 1338
  Bound result 58007991318047724297336281658

[PASS] test_repay_less_than_share() (gas: 600094)
[PASS] test_repay_only_base_debt_interest() (gas: 766292)
[PASS] test_repay_only_base_debt_no_premium() (gas: 644360)
[PASS] test_repay_supply_ex_rate_decr() (gas: 1466871)
[PASS] test_repay_supply_ex_rate_decr_skip_time() (gas: 1463487)
[PASS] test_repay_zero_shares_nonzero_premium_debt() (gas: 764204)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 16.01s (15.99s CPU time)

Ran 17 tests for tests/unit/AccessManagerEnumerable.t.sol:AccessManagerEnumerableTest
[PASS] test_getRoleMembers_fuzz(uint256,uint256) (runs: 5000, μ: 1981460, ~: 1980367)
Logs:
  Bound result 9
  Bound result 10

[PASS] test_getRoleTargetSelectors_fuzz(uint256,uint256) (runs: 5000, μ: 1528820, ~: 1527966)
Logs:
  Bound result 9
  Bound result 10

[PASS] test_grantRole() (gas: 315886)
[PASS] test_grantRole_fuzz(uint64,uint256) (runs: 5000, μ: 916110, ~: 919753)
Logs:
  Bound result 8

[PASS] test_revokeRole() (gas: 323138)
[PASS] test_setRoleAdmin_fuzz_trackAdminRoles_multipleRoles_multipleAdmins(uint256) (runs: 5000, μ: 2159661, ~: 2257477)
Logs:
  Bound result 12

[PASS] test_setRoleAdmin_fuzz_trackRolesAndTrackAdminRoles_multipleRoles(uint256) (runs: 5000, μ: 1974061, ~: 2114661)
Logs:
  Bound result 12

[PASS] test_setRoleAdmin_trackAdminOfRoles() (gas: 606131)
[PASS] test_setRoleAdmin_trackAdminOfRoles_changeAdminRole() (gas: 577217)
[PASS] test_setRoleAdmin_trackAdminRoles() (gas: 602311)
[PASS] test_setRoleAdmin_trackRolesAndTrackAdminRoles() (gas: 378311)
[PASS] test_setRoleGuardian_trackRoles() (gas: 263932)
[PASS] test_setTargetFunctionRole() (gas: 414440)
[PASS] test_setTargetFunctionRole_multipleTargets() (gas: 1103911)
[PASS] test_setTargetFunctionRole_removeTarget() (gas: 894967)
[PASS] test_setTargetFunctionRole_skipAddToAdminRole() (gas: 30940)
[PASS] test_setTargetFunctionRole_withReplace() (gas: 549104)
Suite result: ok. 17 passed; 0 failed; 0 skipped; finished in 22.47s (22.47s CPU time)

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

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

[PASS] test_calculateInterestRate_LeftToKinkPoint(uint256) (runs: 5000, μ: 24187, ~: 24330)
Logs:
  Bound result 137
  Bound result 252173843969976304268974536488

[PASS] test_calculateInterestRate_RightToKinkPoint(uint256) (runs: 5000, μ: 25304, ~: 25351)
Logs:
  Bound result 8137
  Bound result 252173843969976304268974536488

[PASS] test_calculateInterestRate_ZeroDebtZeroLiquidity() (gas: 18771)
Logs:
  Bound result 0

[PASS] test_calculateInterestRate_fuzz_ZeroDebt(uint256) (runs: 5000, μ: 19069, ~: 18822)
Logs:
  Bound result 3124043968137

[PASS] test_calculateInterestRate_revertsWith_InterestRateDataNotSet() (gas: 11225)
[PASS] test_deploy_revertsWith_InvalidAddress() (gas: 3746)
[PASS] test_getBaseVariableBorrowRate() (gas: 14812)
[PASS] test_getInterestRateData() (gas: 19290)
[PASS] test_getMaxVariableBorrowRate() (gas: 15258)
[PASS] test_getOptimalUsageRatio() (gas: 14705)
[PASS] test_getVariableRateSlope1() (gas: 14791)
[PASS] test_getVariableRateSlope2() (gas: 14746)
[PASS] test_maxBorrowRate() (gas: 8312)
[PASS] test_maxOptimalRatio() (gas: 8312)
[PASS] test_minOptimalRatio() (gas: 8321)
[PASS] test_setInterestRateData() (gas: 68999)
[PASS] test_setInterestRateData_revertsWith_InvalidMaxRate() (gas: 41819)
[PASS] test_setInterestRateData_revertsWith_InvalidOptimalUsageRatio() (gas: 42380)
[PASS] test_setInterestRateData_revertsWith_InvalidRateData() (gas: 35269)
[PASS] test_setInterestRateData_revertsWith_OnlyHub() (gas: 23502)
[PASS] test_setInterestRateData_revertsWith_Slope2MustBeGteSlope1() (gas: 37658)
Suite result: ok. 23 passed; 0 failed; 0 skipped; finished in 1.15s (1.13s CPU time)

Ran 10 tests for tests/unit/misc/EIP712Hash.t.sol:EIP712HashTest
[PASS] test_constants() (gas: 13531)
[PASS] test_hash_borrow_fuzz((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 6805, ~: 6805)
[PASS] test_hash_positionManagerUpdate_fuzz((address,bool)) (runs: 5000, μ: 6193, ~: 6193)
[PASS] test_hash_repay_fuzz((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 6806, ~: 6806)
[PASS] test_hash_setUserPositionManagers_fuzz((address,(address,bool)[],uint256,uint256)) (runs: 5000, μ: 453554, ~: 449260)
[PASS] test_hash_setUsingAsCollateral_fuzz((address,uint256,bool,address,uint256,uint256)) (runs: 5000, μ: 7305, ~: 7305)
[PASS] test_hash_supply_fuzz((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 6849, ~: 6849)
[PASS] test_hash_updateUserDynamicConfig_fuzz((address,address,uint256,uint256)) (runs: 5000, μ: 6450, ~: 6450)
[PASS] test_hash_updateUserRiskPremium_fuzz((address,address,uint256,uint256)) (runs: 5000, μ: 6471, ~: 6471)
[PASS] test_hash_withdraw_fuzz((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 6805, ~: 6805)
Suite result: ok. 10 passed; 0 failed; 0 skipped; finished in 21.78s (21.78s CPU time)

Ran 3 tests for tests/unit/misc/ExtSload.t.sol:ExtSloadTest
[PASS] test_extSload(bytes32) (runs: 5000, μ: 9767, ~: 9767)
[PASS] test_extSloads(uint256) (runs: 5000, μ: 950474, ~: 926350)
Logs:
  Bound result 812

[PASS] test_extSloads(uint256,bytes) (runs: 5000, μ: 1008291, ~: 970986)
Logs:
  Bound result 362

Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 59.85s (59.85s CPU time)

Ran 8 tests for tests/unit/misc/GatewayBase.t.sol:GatewayBaseTest
[PASS] test_constructor() (gas: 17151)
[PASS] test_registerSpoke_fuzz(address) (runs: 5000, μ: 41629, ~: 41629)
[PASS] test_registerSpoke_revertsWith_InvalidAddress() (gas: 13119)
[PASS] test_registerSpoke_revertsWith_OwnableUnauthorizedAccount() (gas: 13791)
[PASS] test_registerSpoke_unregister() (gas: 36076)
[PASS] test_renouncePositionManagerRole() (gas: 65293)
[PASS] test_renouncePositionManagerRole_revertsWith_InvalidAddress() (gas: 74220)
[PASS] test_renouncePositionManagerRole_revertsWith_OwnableUnauthorizedAccount() (gas: 74439)
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 397.81ms (374.14ms CPU time)

Ran 5 tests for tests/gas/Gateways.Operations.gas.t.sol:NativeTokenGateway_Gas_Tests
[PASS] test_borrowNative() (gas: 918117)
[PASS] test_repayNative() (gas: 989465)
[PASS] test_supplyAndCollateralNative() (gas: 305199)
[PASS] test_supplyNative() (gas: 286678)
[PASS] test_withdrawNative() (gas: 508784)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 47.22ms (4.14ms CPU time)

Ran 8 tests for tests/gas/Gateways.Operations.gas.t.sol:SignatureGateway_Gas_Tests
[PASS] test_borrowWithSig() (gas: 745390)
[PASS] test_repayWithSig() (gas: 980244)
[PASS] test_setSelfAsUserPositionManagerWithSig() (gas: 209574)
[PASS] test_setUsingAsCollateralWithSig() (gas: 289371)
[PASS] test_supplyWithSig() (gas: 460957)
[PASS] test_updateUserDynamicConfigWithSig() (gas: 145257)
[PASS] test_updateUserRiskPremiumWithSig() (gas: 143188)
[PASS] test_withdrawWithSig() (gas: 409938)
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 50.41ms (7.71ms CPU time)

Ran 6 tests for tests/unit/Hub/Hub.Access.t.sol:HubAccessTest
[PASS] test_change_authority() (gas: 206690)
[PASS] test_change_role_responsibility() (gas: 121258)
[PASS] test_hub_access_manager_exposure() (gas: 13439)
[PASS] test_hub_admin_access() (gas: 1350388)
[PASS] test_migrate_role_responsibility() (gas: 708988)
[PASS] test_setInterestRateData_access() (gas: 102667)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 27.47ms (3.79ms CPU time)

Ran 7 tests for tests/unit/Spoke/Spoke.AccrueInterest.t.sol:SpokeAccrueInterestTest
[PASS] test_accrueInterest_NoActionTaken() (gas: 133168)
[PASS] test_accrueInterest_NoInterest_NoDebt(uint40) (runs: 5000, μ: 632522, ~: 632351)
Logs:
  Bound result 9

[PASS] test_accrueInterest_NoInterest_OnlySupply(uint40) (runs: 5000, μ: 250256, ~: 250261)
Logs:
  Bound result 9

[PASS] test_accrueInterest_TenPercentRp(uint256,uint40) (runs: 5000, μ: 579296, ~: 579757)
Logs:
  Bound result 68691281934999
  Bound result 0

[PASS] test_accrueInterest_fuzz_BorrowAmountAndSkipTime(uint256,uint40) (runs: 5000, μ: 538656, ~: 539050)
Logs:
  Bound result 68691281934999
  Bound result 0

[SKIP: pending rft] test_accrueInterest_fuzz_RPBorrowAndSkipTime((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256),uint40) (runs: 0, μ: 0, ~: 0)
[PASS] test_accrueInterest_fuzz_RatesRPBorrowAndSkipTime((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256),(uint96,uint96,uint96,uint96),uint40) (runs: 5000, μ: 4051544, ~: 4067798)
Logs:
  Bound result 262803947816958635071541867761
  Bound result 300000000000000000000000000
  Bound result 239
  Bound result 33562733834177737067
  Bound result 10536
  Bound result 1712
  Bound result 13000
  Bound result 965875254
  Bound result 6234
  Bound result 14243
  Bound result 16127
  Bound result 81433
  Bound result 12742
  Bound result 10536
  Bound result 1712
  Bound result 13000
  Bound result 965875254

Suite result: ok. 6 passed; 0 failed; 1 skipped; finished in 116.90s (116.88s 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, μ: 544655, ~: 544712)
Logs:
  Bound result 13048
  Bound result 480000000
  Bound result 2
  Bound result 1873

[PASS] test_accrueLiquidityFee_fuzz_maxLiquidityFee_with_premium_multiple_users(uint256,uint256,uint256,uint256,uint256) (runs: 5000, μ: 803281, ~: 803386)
Logs:
  Bound result 4946
  Bound result 480000000
  Bound result 0
  Bound result 2226133357
  Bound result 12642

[PASS] test_accrueLiquidityFee_maxLiquidityFee_multi_spoke() (gas: 645542074)
[PASS] test_accrueLiquidityFee_maxLiquidityFee_multi_user() (gas: 263716026)
[PASS] test_accrueLiquidityFee_maxLiquidityFee_with_premium() (gas: 544774)
Logs:
  Bound result 5000
  Bound result 34560000
  Bound result 2
  Bound result 500000000000000000000

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

Ran 19 tests for tests/unit/Hub/Hub.Add.t.sol:HubAddTest
[PASS] test_add_AddCapReachedButNotExceeded_rounding() (gas: 667246)
[PASS] test_add_fuzz_AddCapReachedButNotExceeded(uint40) (runs: 5000, μ: 157893, ~: 157848)
Logs:
  Bound result 9

[PASS] test_add_fuzz_multi_asset_multi_spoke(uint256,uint256,uint256) (runs: 5000, μ: 332481, ~: 332613)
Logs:
  Bound result 3
  Bound result 218470873395738003579119570309
  Bound result 446067553769140138733721804

[PASS] test_add_fuzz_revertsWith_AddCapExceeded(uint40) (runs: 5000, μ: 112438, ~: 112393)
Logs:
  Bound result 9

[PASS] test_add_fuzz_revertsWith_AddCapExceeded_due_to_interest(uint40,uint256,uint256) (runs: 5000, μ: 267084, ~: 266951)
Logs:
  Bound result 1291
  Bound result 1071208440522043736492
  Bound result 173721804

[PASS] test_add_fuzz_revertsWith_InvalidShares_due_to_index(uint256,uint256,uint256) (runs: 5000, μ: 223922, ~: 224119)
Logs:
  Bound result 999999999900000000000045000001
  Bound result 3122066865
  Bound result 5

[PASS] test_add_fuzz_single_asset(uint256,address,uint256) (runs: 5000, μ: 342386, ~: 342406)
Logs:
  Bound result 0
  Bound result 714477922937634359008573850498

[PASS] test_add_fuzz_single_spoke_multi_add(uint256,uint256) (runs: 5000, μ: 805223, ~: 805253)
Logs:
  Bound result 68691281934999
  Bound result 100

[PASS] test_add_multi_add_minimal_shares() (gas: 322520)
[PASS] test_add_revertsWith_AmountDowncastOverflow() (gas: 360306)
[PASS] test_add_revertsWith_InsufficientTransferred() (gas: 64504)
[PASS] test_add_revertsWith_InvalidAmount() (gas: 13631)
[PASS] test_add_revertsWith_InvalidShares() (gas: 223458)
[PASS] test_add_revertsWith_SharesDowncastOverflow() (gas: 224358)
[PASS] test_add_revertsWith_SpokeHalted() (gas: 99705)
[PASS] test_add_revertsWith_SpokeNotActive() (gas: 99741)
[PASS] test_add_single_asset() (gas: 330255)
Logs:
  Bound result 2
  Bound result 100000000000000000000

[PASS] test_add_with_increased_index() (gas: 301312)
[PASS] test_add_with_increased_index_with_premium() (gas: 680739)
Suite result: ok. 19 passed; 0 failed; 0 skipped; finished in 44.57s (44.54s CPU time)

Ran 7 tests for tests/unit/Spoke/Spoke.AccrueLiquidityFee.t.sol:SpokeAccrueLiquidityFeeTest
[PASS] test_accrueLiquidityFee() (gas: 862391)
[PASS] test_accrueLiquidityFee_NoActionTaken() (gas: 122186)
[PASS] test_accrueLiquidityFee_NoInterest_OnlySupply(uint40) (runs: 5000, μ: 245276, ~: 245236)
Logs:
  Bound result 9

[PASS] test_accrueLiquidityFee_exact() (gas: 868299)
[PASS] test_accrueLiquidityFee_fuzz_BorrowAmountAndSkipTime(uint256,uint40) (runs: 5000, μ: 939237, ~: 961050)
Logs:
  Bound result 68691281934999
  Bound result 0

[PASS] test_accrueLiquidityFee_maxLiquidityFee() (gas: 545943)
[PASS] test_accrueLiquidityFee_setUsingAsCollateral() (gas: 894583)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 19.52s (19.50s 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, μ: 1043388, ~: 1043492)
Logs:
  Bound result 68691281934999
  Bound result 100

[PASS] test_borrow_fuzz_rounding_effect_inflated_ex_rate(uint256,uint256,uint256) (runs: 5000, μ: 1416529, ~: 1416610)
Logs:
  Bound result 803957830884488240088146
  Bound result 92661078480051493823004
  Bound result 217892126

[PASS] test_borrow_fuzz_rounding_effect_shares(uint256,uint256) (runs: 5000, μ: 1085767, ~: 1085516)
Logs:
  Bound result 68691281934999
  Bound result 832464101

[PASS] test_borrow_rounding_effect_multiple_actions() (gas: 1146119)
[PASS] test_borrow_rounding_effect_shares() (gas: 1084778)
Logs:
  Bound result 5000000000000000000
  Bound result 94608000

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

Ran 38 tests for tests/unit/Hub/Hub.Config.t.sol:HubConfigTest
[PASS] test_addAsset_fuzz(address,uint8,address) (runs: 5000, μ: 390345, ~: 390384)
Logs:
  Bound result 18

[PASS] test_addAsset_fuzz_revertsWith_InvalidAddress_feeReceiver(address,uint8,address) (runs: 5000, μ: 45289, ~: 44992)
Logs:
  Bound result 4

[PASS] test_addAsset_fuzz_revertsWith_InvalidAddress_irStrategy(address,uint8,address) (runs: 5000, μ: 45332, ~: 45035)
Logs:
  Bound result 4

[PASS] test_addAsset_fuzz_revertsWith_InvalidAddress_underlying(uint8,address,address) (runs: 5000, μ: 36719, ~: 36719)
[PASS] test_addAsset_fuzz_revertsWith_InvalidAssetDecimals(address,uint8,address,address) (runs: 5000, μ: 45945, ~: 45986)
Logs:
  Bound result 241

[PASS] test_addAsset_fuzz_revertsWith_InvalidAssetDecimals_tooLow(address,uint8,address,address) (runs: 5000, μ: 46020, ~: 46308)
Logs:
  Bound result 4

[PASS] test_addAsset_fuzz_reverts_InvalidIrData(address,uint8,address,address) (runs: 5000, μ: 79906566881, ~: 34963)
Logs:
  Bound result 4

[PASS] test_addAsset_revertsWith_BlockTimestampDowncastOverflow() (gas: 956634)
[PASS] test_addAsset_revertsWith_DrawnRateDowncastOverflow() (gas: 953770)
[PASS] test_addAsset_reverts_UnderlyingAlreadyListed() (gas: 48980)
[PASS] test_addSpoke_fuzz(uint256,(uint40,uint40,uint24,bool,bool)) (runs: 5000, μ: 126677, ~: 126726)
Logs:
  Bound result 4

[PASS] test_addSpoke_fuzz_revertsWith_AssetNotListed(uint256,(uint40,uint40,uint24,bool,bool)) (runs: 5000, μ: 35246, ~: 35235)
Logs:
  Bound result 18376

[PASS] test_addSpoke_fuzz_revertsWith_InvalidAddress_spoke(uint256,(uint40,uint40,uint24,bool,bool)) (runs: 5000, μ: 33930, ~: 33979)
Logs:
  Bound result 4

[PASS] test_addSpoke_revertsWith_SpokeAlreadyListed() (gas: 39773)
[PASS] test_getAssetId() (gas: 73160)
[PASS] test_getAssetId_fuzz_revertsWith_AssetNotListed(address) (runs: 5000, μ: 18561, ~: 18561)
[PASS] test_hub_deploy_reverts_on_InvalidConstructorInput() (gas: 828595)
[PASS] test_hub_max_riskPremium() (gas: 8610)
[PASS] test_isUnderlyingListed() (gas: 1178402)
[PASS] test_updateAssetConfig_NewFeeReceiver_noFees() (gas: 719381)
[PASS] test_updateAssetConfig_NewFeeReceiver_revertsWith_SpokeNotActive_noFees() (gas: 618740)
[PASS] test_updateAssetConfig_UseExistingSpokeAndListedAsFeeReceiver_revertsWith_SpokeAlreadyListed() (gas: 70708)
[PASS] test_updateAssetConfig_fuzz(uint256,(address,uint16,address,address)) (runs: 5000, μ: 269239, ~: 269609)
Logs:
  Bound result 4
  Bound result 6906

[PASS] test_updateAssetConfig_fuzz_FromZeroLiquidityFee(uint256,uint16) (runs: 5000, μ: 822255, ~: 822117)
Logs:
  Bound result 3
  Bound result 1
  Bound result 3
  Bound result 0
  Bound result 3
  Bound result 1

[PASS] test_updateAssetConfig_fuzz_LiquidityFee(uint256,uint16) (runs: 5000, μ: 724648, ~: 724510)
Logs:
  Bound result 3
  Bound result 1
  Bound result 3
  Bound result 1

[PASS] test_updateAssetConfig_fuzz_NewFeeReceiver(uint256) (runs: 5000, μ: 823646, ~: 823680)
Logs:
  Bound result 3
  Bound result 3
  Bound result 1000

[PASS] test_updateAssetConfig_fuzz_NewInterestRateStrategy(uint256) (runs: 5000, μ: 698246, ~: 698280)
Logs:
  Bound result 3

[PASS] test_updateAssetConfig_fuzz_ReuseFeeReceiver_revertsWith_SpokeAlreadyListed(uint256) (runs: 5000, μ: 875247, ~: 875281)
Logs:
  Bound result 3
  Bound result 3
  Bound result 3
  Bound result 1000

[PASS] test_updateAssetConfig_fuzz_Scenario(uint256) (runs: 5000, μ: 700552, ~: 700605)
Logs:
  Bound result 3
  Bound result 3
  Bound result 1000
  Bound result 3
  Bound result 1000
  Bound result 3
  Bound result 0
  Bound result 3
  Bound result 0
  Bound result 3
  Bound result 0
  Bound result 3
  Bound result 0

[PASS] test_updateAssetConfig_fuzz_revertsWith_InvalidInterestRateStrategy(uint256) (runs: 5000, μ: 61083, ~: 61136)
Logs:
  Bound result 3

[PASS] test_updateAssetConfig_fuzz_revertsWith_InvalidLiquidityFee(uint256,(address,uint16,address,address)) (runs: 5000, μ: 40146, ~: 40042)
Logs:
  Bound result 4
  Bound result 6906

[PASS] test_updateAssetConfig_fuzz_revertsWith_InvalidReinvestmentController() (gas: 485646)
[PASS] test_updateAssetConfig_fuzz_revertsWith_calculateInterestRateReverts(uint256,(address,uint16,address,address)) (runs: 5000, μ: 198826, ~: 199256)
Logs:
  Bound result 0
  Bound result 1270

[PASS] test_updateAssetConfig_fuzz_revertsWith_setInterestRateDataReverts(uint256,(address,uint16,address,address)) (runs: 5000, μ: 95913, ~: 96293)
Logs:
  Bound result 3
  Bound result 350

[PASS] test_updateAssetConfig_oldFeeReceiver_flags() (gas: 880156)
Logs:
  Bound result 1
  Bound result 500
  Bound result 3
  Bound result 1000
  Bound result 5
  Bound result 500
  Bound result 3
  Bound result 1000

[PASS] test_updateSpokeConfig_fuzz(uint256,(uint40,uint40,uint24,bool,bool)) (runs: 5000, μ: 59224, ~: 59284)
Logs:
  Bound result 0

[PASS] test_updateSpokeConfig_fuzz_revertsWith_SpokeNotListed(uint256,address,(uint40,uint40,uint24,bool,bool)) (runs: 5000, μ: 40524, ~: 40592)
Logs:
  Bound result 3

[PASS] test_updateSpokeConfig_revertsWith_AssetNotListed() (gas: 29639)
Suite result: ok. 38 passed; 0 failed; 0 skipped; finished in 96.68s (96.65s CPU time)

Ran 16 tests for tests/unit/Hub/Hub.Draw.t.sol:HubDrawTest
[PASS] test_draw_DifferentSpokes() (gas: 355531)
[PASS] test_draw_fuzz_IncreasedBorrowRate(uint256,uint256) (runs: 5000, μ: 696687, ~: 696813)
Logs:
  Bound result 3
  Bound result 100

[PASS] test_draw_fuzz_amounts_same_block(uint256,uint256) (runs: 5000, μ: 289106, ~: 289127)
Logs:
  Bound result 3
  Bound result 100

[PASS] test_draw_fuzz_revertsWith_DrawCapExceeded(uint40) (runs: 5000, μ: 82328, ~: 82284)
Logs:
  Bound result 9

[PASS] test_draw_fuzz_revertsWith_DrawCapExceeded_due_to_interest(uint40,uint256,uint256) (runs: 5000, μ: 287069, ~: 287313)
Logs:
  Bound result 1291
  Bound result 70309
  Bound result 173721804

[PASS] test_draw_fuzz_revertsWith_InsufficientLiquidity(uint256,uint256) (runs: 5000, μ: 34737, ~: 34512)
Logs:
  Bound result 3
  Bound result 100

[PASS] test_draw_fuzz_revertsWith_InsufficientLiquidity_due_to_draw(uint256) (runs: 5000, μ: 172782, ~: 172492)
Logs:
  Bound result 3124043968137

[PASS] test_draw_fuzz_revertsWith_InsufficientLiquidity_due_to_remove(uint256) (runs: 5000, μ: 134500, ~: 134296)
Logs:
  Bound result 3124043968137

[PASS] test_draw_fuzz_revertsWith_InvalidAddress(uint256) (runs: 5000, μ: 16138, ~: 16138)
[PASS] test_draw_revertsWith_DrawCapExceeded_due_to_deficit() (gas: 270488)
[PASS] test_draw_revertsWith_InsufficientLiquidity() (gas: 28289)
[PASS] test_draw_revertsWith_InsufficientLiquidity_due_to_draw() (gas: 169103)
[PASS] test_draw_revertsWith_InsufficientLiquidity_due_to_remove() (gas: 131632)
[PASS] test_draw_revertsWith_InvalidAmount() (gas: 16269)
[PASS] test_draw_revertsWith_SpokeHalted() (gas: 61452)
[PASS] test_draw_revertsWith_SpokeNotActive() (gas: 61391)
Suite result: ok. 16 passed; 0 failed; 0 skipped; finished in 23.70s (23.68s CPU time)

Ran 8 tests for tests/unit/Hub/Hub.EliminateDeficit.t.sol:HubEliminateDeficitTest
[PASS] test_eliminateDeficit(uint256) (runs: 5000, μ: 663609, ~: 663609)
[PASS] test_eliminateDeficit_fuzz_revertsWith_AccessManagedUnauthorized(address) (runs: 5000, μ: 32580, ~: 32580)
[PASS] test_eliminateDeficit_fuzz_revertsWith_ArithmeticUnderflow_CallerSpokeNoFunds(uint256) (runs: 5000, μ: 352008, ~: 352008)
[PASS] test_eliminateDeficit_revertsWith_InvalidAmount_ZeroAmountNoDeficit() (gas: 36025)
[PASS] test_eliminateDeficit_revertsWith_InvalidAmount_ZeroAmountWithDeficit() (gas: 348183)
[PASS] test_eliminateDeficit_revertsWith_InvalidAmount_on_UnregisteredCoveredSpoke() (gas: 36412)
[PASS] test_eliminateDeficit_revertsWith_SpokeNotActive_on_UnregisteredAsset() (gas: 384005)
[PASS] test_eliminateDeficit_revertsWith_callerSpokeNotActive() (gas: 159412)
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 16.51s (16.48s CPU time)

Ran 6 tests for tests/unit/Hub/Hub.MintFeeShares.t.sol:HubMintFeeSharesTest
[PASS] test_mintFeeShares() (gas: 311928)
[PASS] test_mintFeeShares_noFees() (gas: 367828)
[PASS] test_mintFeeShares_noShares() (gas: 293092)
[PASS] test_mintFeeShares_revertsWith_AccessManagedUnauthorized() (gas: 24139)
[PASS] test_mintFeeShares_revertsWith_AssetNotListed() (gas: 27553)
[PASS] test_mintFeeShares_revertsWith_SpokeNotActive() (gas: 242774)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 28.44ms (4.10ms CPU time)

Ran 9 tests for tests/gas/Hub.Operations.gas.t.sol:HubOperations_Gas_Tests
[PASS] test_add() (gas: 270130)
[PASS] test_deficit() (gas: 1342104)
[PASS] test_draw() (gas: 418586)
[PASS] test_mintFeeShares() (gas: 499967)
[PASS] test_payFee_transferShares() (gas: 968646)
[PASS] test_refreshPremium() (gas: 634510)
[PASS] test_remove() (gas: 310697)
[PASS] test_restore() (gas: 877878)
[PASS] test_restore_with_transfer() (gas: 878543)
Suite result: ok. 9 passed; 0 failed; 0 skipped; finished in 50.11ms (7.01ms CPU time)

Ran 6 tests for tests/unit/Hub/Hub.PayFee.t.sol:HubPayFeeTest
[PASS] test_payFee_fuzz(uint256,uint256) (runs: 5000, μ: 703890, ~: 704052)
Logs:
  Bound result 68691281934999
  Bound result 0
  Bound result 100

[PASS] test_payFee_fuzz_with_interest(uint256,uint256,uint256) (runs: 5000, μ: 704336, ~: 704600)
Logs:
  Bound result 615514462186775432459
  Bound result 10765498
  Bound result 571193127101173104469

[PASS] test_payFee_revertsWith_InvalidShares() (gas: 20356)
[PASS] test_payFee_revertsWith_SpokeNotActive() (gas: 61390)
[PASS] test_payFee_revertsWith_underflow_added_shares_exceeded() (gas: 138740)
[PASS] test_payFee_revertsWith_underflow_added_shares_exceeded_with_interest() (gas: 643431)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 25.24s (25.22s CPU time)

Ran 8 tests for tests/unit/Spoke/Spoke.Repay.Scenario.t.sol:SpokeRepayScenarioTest
[PASS] test_fuzz_repay_borrow_twice_repay_twice((uint256,uint256,uint256,uint40),(uint256,uint256,uint256,uint40)) (runs: 5000, μ: 1255556, ~: 1260362)
Logs:
  Bound result 7092
  Bound result 8868
  Bound result 650000000000000000
  Bound result 7166
  Bound result 3207
  Bound result 941

[PASS] test_fuzz_repay_multiple_users_repay_same_reserve((uint256,uint256,uint256,uint256,uint256,uint256,address),(uint256,uint256,uint256,uint256,uint256,uint256,address),(uint256,uint256,uint256,uint256,uint256,uint256,address),uint256) (runs: 5000, μ: 2026530, ~: 1998488)
Logs:
  Bound result 16072
  Bound result 750000000000000000000
  Bound result 300000000
  Bound result 3292
  Bound result 12
  Bound result 1650000000000000000
  Bound result 10731

[PASS] test_repay_fuzz_multiple_users_multiple_assets(((uint256,uint256,uint256,uint256,uint256),(uint256,uint256,uint256,uint256,uint256),(uint256,uint256,uint256,uint256,uint256),(uint256,uint256,uint256,uint256,uint256),address),((uint256,uint256,uint256,uint256,uint256),(uint256,uint256,uint256,uint256,uint256),(uint256,uint256,uint256,uint256,uint256),(uint256,uint256,uint256,uint256,uint256),address),((uint256,uint256,uint256,uint256,uint256),(uint256,uint256,uint256,uint256,uint256),(uint256,uint256,uint256,uint256,uint256),(uint256,uint256,uint256,uint256,uint256),address),uint40) (runs: 5000, μ: 6054596, ~: 6054991)
Logs:
  Bound result 3601589825
  Bound result 1000000000000000000000000
  Bound result 482
  Bound result 20758
  Bound result 2500000000000000000000000000
  Bound result 216
  Bound result 6736
  Bound result 184
  Bound result 15700
  Bound result 5000000000000000000000
  Bound result 11702
  Bound result 7095
  Bound result 7900
  Bound result 9500000000000000000000
  Bound result 10193
  Bound result 686
  Bound result 25
  Bound result 78340066645871065499466465281
  Bound result 20620
  Bound result 20000
  Bound result 31536000
  Bound result 36
  Bound result 72804214737418362637539853836006058574737022617871426945351382859961153355777
  Bound result 18314
  Bound result 8646

[PASS] test_repay_fuzz_two_users_multiple_assets(((uint256,uint256,uint256,uint256,uint256),(uint256,uint256,uint256,uint256,uint256),(uint256,uint256,uint256,uint256,uint256),(uint256,uint256,uint256,uint256,uint256),address),((uint256,uint256,uint256,uint256,uint256),(uint256,uint256,uint256,uint256,uint256),(uint256,uint256,uint256,uint256,uint256),(uint256,uint256,uint256,uint256,uint256),address),uint40) (runs: 5000, μ: 4288200, ~: 4288424)
Logs:
  Bound result 2082
  Bound result 18665
  Bound result 125000000000000000
  Bound result 559
  Bound result 75000000000000000000000
  Bound result 10600
  Bound result 865400000000000000
  Bound result 3562
  Bound result 13052238805970149254
  Bound result 255
  Bound result 14418
  Bound result 6698189629259549513
  Bound result 411369862228566123857978459849914418579267864052950501802639359
  Bound result 1500000000000000000000000000
  Bound result 7162
  Bound result 1000000000000
  Bound result 303532249

[PASS] test_repay_partial_then_max() (gas: 690413)
[PASS] test_repay_round_trip_borrow_repay(uint256,uint256,uint40,address,uint256) (runs: 5000, μ: 872256, ~: 875831)
Logs:
  Bound result 2
  Bound result 40156480554970129807
  Bound result 470178205
  Bound result 17274227773553515385346548028

[PASS] test_repay_round_trip_repay_borrow(uint256,uint256,uint256,uint40,address,uint256) (runs: 5000, μ: 953506, ~: 962812)
Logs:
  Bound result 2
  Bound result 300000000000000000
  Bound result 587655666
  Bound result 10500000000000000000000
  Bound result 15401

[PASS] test_repay_two_users_repay_same_reserve((uint256,uint256,uint256,uint256,uint256,uint256,address),(uint256,uint256,uint256,uint256,uint256,uint256,address),uint256) (runs: 5000, μ: 1464588, ~: 1494048)
Logs:
  Bound result 5401549876140600956580819487
  Bound result 65251468040295843421393
  Bound result 11263328023241632836759
  Bound result 7707153379656042561281651440489383780992440
  Bound result 681445185

Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 309.71s (309.68s CPU time)

Ran 2 tests for tests/unit/Spoke/Spoke.Repay.Validation.t.sol:SpokeRepayValidationTest
[PASS] test_repay_revertsWith_ReserveNotListed() (gas: 23228)
[PASS] test_repay_revertsWith_ReservePaused() (gas: 63748)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 24.88ms (406.82µs CPU time)

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

[PASS] test_reclaim_fullAmount() (gas: 635224)
[PASS] test_reclaim_fuzz(uint256,uint256,uint256) (runs: 5000, μ: 654452, ~: 653715)
Logs:
  Bound result 615514462186775432459
  Bound result 571193127101173104469
  Bound result 564283877115702805413

[PASS] test_reclaim_multipleSweepsAndReclaims() (gas: 743828)
[PASS] test_reclaim_revertsWith_AssetNotListed() (gas: 13093)
[PASS] test_reclaim_revertsWith_InsufficientTransferred() (gas: 456516)
[PASS] test_reclaim_revertsWith_InsufficientTransferred_noSwept() (gas: 102551)
[PASS] test_reclaim_revertsWith_InvalidAmount_zero() (gas: 92721)
[PASS] test_reclaim_revertsWith_OnlyReinvestmentController(address) (runs: 5000, μ: 93604, ~: 93604)
[PASS] test_reclaim_revertsWith_OnlyReinvestmentController_init() (gas: 40516)
[PASS] test_reclaim_revertsWith_underflow_exceedsSwept_afterSweep() (gas: 619868)
Suite result: ok. 11 passed; 0 failed; 0 skipped; finished in 15.03s (15.00s 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, μ: 910794, ~: 910770)
Logs:
  Bound result 100
  Bound result 68691281934999

[PASS] test_borrow_fuzz_revertsWith_HealthFactorBelowThreshold_multiple_colls(uint256,uint256) (runs: 5000, μ: 857337, ~: 857784)
Logs:
  Bound result 2655
  Bound result 6528

[PASS] test_borrow_fuzz_revertsWith_HealthFactorBelowThreshold_multiple_colls_with_interest(uint256,uint256,uint256) (runs: 5000, μ: 893935, ~: 894018)
Logs:
  Bound result 23330
  Bound result 1000000000000
  Bound result 1800

[PASS] test_borrow_fuzz_revertsWith_HealthFactorBelowThreshold_multiple_debts(uint256,uint256) (runs: 5000, μ: 1097908, ~: 1098141)
Logs:
  Bound result 99999999999068691281935000
  Bound result 99999999999000000000000101

[PASS] test_borrow_fuzz_revertsWith_HealthFactorBelowThreshold_multiple_debts_with_interest(uint256,uint256,uint256) (runs: 5000, μ: 1137193, ~: 1137306)
Logs:
  Bound result 157997812150141603783604
  Bound result 44433414873489694395086073102
  Bound result 725

[PASS] test_borrow_fuzz_revertsWith_HealthFactorBelowThreshold_with_interest(uint256,uint256) (runs: 5000, μ: 673550, ~: 673725)
Logs:
  Bound result 5407
  Bound result 192000000

[PASS] test_borrow_revertsWith_HealthFactorBelowThreshold() (gas: 641080)
[PASS] test_borrow_revertsWith_HealthFactorBelowThreshold_collateral_price_drop_weth() (gas: 905020)
[PASS] test_borrow_revertsWith_HealthFactorBelowThreshold_multiple_colls() (gas: 851565)
[PASS] test_borrow_revertsWith_HealthFactorBelowThreshold_multiple_colls_collateral_price_drop_dai() (gas: 1125254)
[PASS] test_borrow_revertsWith_HealthFactorBelowThreshold_multiple_colls_collateral_price_drop_weth() (gas: 1125298)
[PASS] test_borrow_revertsWith_HealthFactorBelowThreshold_multiple_colls_with_interest() (gas: 889027)
[PASS] test_borrow_revertsWith_HealthFactorBelowThreshold_multiple_debts() (gas: 1090381)
[PASS] test_borrow_revertsWith_HealthFactorBelowThreshold_multiple_debts_with_interest() (gas: 1128971)
[PASS] test_borrow_revertsWith_HealthFactorBelowThreshold_with_interest() (gas: 668431)
[PASS] test_fuzz_borrow_revertsWith_HealthFactorBelowThreshold_multiple_colls_collateral_price_drop_dai(uint256,uint256,uint256) (runs: 5000, μ: 1129425, ~: 1129779)
Logs:
  Bound result 10000000
  Bound result 283
  Bound result 8800

[PASS] test_fuzz_borrow_revertsWith_HealthFactorBelowThreshold_multiple_colls_collateral_price_drop_weth(uint256,uint256,uint256) (runs: 5000, μ: 1129886, ~: 1129801)
Logs:
  Bound result 10000000
  Bound result 283
  Bound result 8800

Suite result: ok. 17 passed; 0 failed; 0 skipped; finished in 125.46s (125.43s CPU time)

Ran 12 tests for tests/unit/Hub/Hub.RefreshPremium.t.sol:HubRefreshPremiumTest
[PASS] test_refreshPremium_emitsEvent() (gas: 254760)
[PASS] test_refreshPremium_fuzz_positiveDeltas(uint256,int256,int256) (runs: 5000, μ: 488513, ~: 493803)
Logs:
  Bound result 999999999910000000000000000001
  Bound result 1
  Bound result 22056

[PASS] test_refreshPremium_fuzz_withAccrual(uint256,uint256,uint256,uint256) (runs: 5000, μ: 465980, ~: 475279)
Logs:
  Bound result 925
  Bound result 81
  Bound result 7500000000000000000000000000
  Bound result 12811

[PASS] test_refreshPremium_haltedSpokesAllowed() (gas: 121441)
[PASS] test_refreshPremium_maxRiskPremiumThreshold() (gas: 898527)
[PASS] test_refreshPremium_negativeDeltas(uint256) (runs: 5000, μ: 458598, ~: 459144)
Logs:
  Bound result 3124043968137

[PASS] test_refreshPremium_negativeDeltas_withAccrual(uint256) (runs: 5000, μ: 528560, ~: 528779)
Logs:
  Bound result 3124043968137

[PASS] test_refreshPremium_revertsWith_InvalidPremiumChange_NonZeroRestoredPremiumRay() (gas: 853935)
[PASS] test_refreshPremium_revertsWith_InvalidPremiumChange_RiskPremiumThresholdExceeded_DecreasingPremium() (gas: 875237)
[PASS] test_refreshPremium_revertsWith_SpokeNotActive() (gas: 58921)
[PASS] test_refreshPremium_riskPremiumThreshold() (gas: 920705)
[PASS] test_refreshPremium_spokePremiumUpdateIsContained() (gas: 707752)
Suite result: ok. 12 passed; 0 failed; 0 skipped; finished in 20.51s (20.49s CPU time)

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

[PASS] test_remove_all_with_interest() (gas: 368376)
[PASS] test_remove_fuzz(uint256,uint256) (runs: 5000, μ: 207745, ~: 207681)
Logs:
  Bound result 4
  Bound result 100

[PASS] test_remove_fuzz_all_liquidity_with_interest(uint256,uint256) (runs: 5000, μ: 419589, ~: 419810)
Logs:
  Bound result 68691281934999
  Bound result 100

[PASS] test_remove_fuzz_multi_spoke(uint256,uint256) (runs: 5000, μ: 289015, ~: 289118)
Logs:
  Bound result 68691281934999
  Bound result 100

[PASS] test_remove_fuzz_multi_spoke_with_interest(uint256,uint256,uint256,uint256) (runs: 5000, μ: 422362, ~: 422842)
Logs:
  Bound result 45962924587436021823203788457
  Bound result 23679
  Bound result 7500000000000000000000000000
  Bound result 15822

[PASS] test_remove_revertsWith_InsufficientLiquidity() (gas: 158411)
[PASS] test_remove_revertsWith_InsufficientLiquidity_exceeding_added_amount() (gas: 147500)
[PASS] test_remove_revertsWith_InsufficientLiquidity_zero_added() (gas: 21376)
[PASS] test_remove_revertsWith_InvalidAddress() (gas: 16471)
[PASS] test_remove_revertsWith_InvalidAmount() (gas: 18628)
[PASS] test_remove_revertsWith_SpokeHalted() (gas: 61971)
[PASS] test_remove_revertsWith_SpokeNotActive() (gas: 61880)
[PASS] test_remove_revertsWith_underflow_exceeding_added_amount() (gas: 185386)
[PASS] test_remove_revertsWtih_underflow_one_extra_wei() (gas: 364720)
Suite result: ok. 15 passed; 0 failed; 0 skipped; finished in 30.79s (30.77s CPU time)

Ran 7 tests for tests/unit/Hub/Hub.ReportDeficit.t.sol:HubReportDeficitTest
[PASS] test_reportDeficit_fuzz_revertsWith_SurplusDrawnDeficitReported(uint256) (runs: 5000, μ: 220026, ~: 220468)
Logs:
  Bound result 3124043968137

[PASS] test_reportDeficit_fuzz_revertsWith_SurplusPremiumRayDeficitReported(uint256) (runs: 5000, μ: 221051, ~: 221493)
Logs:
  Bound result 3124043968137

[PASS] test_reportDeficit_fuzz_with_premium(uint256,uint256,uint256,uint256) (runs: 5000, μ: 674639, ~: 675385)
Logs:
  Bound result 907
  Bound result 748619775
  Bound result 349
  Bound result 7500000000000000000000000000

[PASS] test_reportDeficit_halted() (gas: 265152)
[PASS] test_reportDeficit_revertsWith_InvalidAmount() (gas: 24893)
[PASS] test_reportDeficit_revertsWith_SpokeNotActive(address) (runs: 5000, μ: 33865, ~: 33865)
[PASS] test_reportDeficit_with_premium() (gas: 673745)
Logs:
  Bound result 10000000000
  Bound result 31536000
  Bound result 5000000000
  Bound result 0

Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 17.76s (17.73s CPU time)

Ran 3 tests for tests/unit/Hub/Hub.Rescue.t.sol:HubRescueTest
[PASS] test_cannot_rescue_liquidity_fee_reverts_with_InsufficientTransferred() (gas: 274449)
[PASS] test_rescue_fuzz_with_interest(uint256,uint256) (runs: 5000, μ: 514689, ~: 514649)
Logs:
  Bound result 351500639
  Bound result 1256746

[PASS] test_rescue_scenario_fuzz(uint256) (runs: 5000, μ: 454220, ~: 454013)
Logs:
  Bound result 3124043968137

Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 17.94s (17.91s CPU time)

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

[PASS] test_restore_full_amount_with_interest_and_premium() (gas: 674124)
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, μ: 365390, ~: 365484)
Logs:
  Bound result 615514462186775432459
  Bound result 571193127101173104469
  Bound result 173721804

[PASS] test_restore_fuzz_full_amount_with_interest_and_premium(uint256,uint256,uint256,uint256) (runs: 5000, μ: 665060, ~: 676185)
Logs:
  Bound result 8964
  Bound result 537
  Bound result 480000000
  Bound result 30

[PASS] test_restore_fuzz_revertsWith_SurplusDrawnRestored_with_interest(uint256,uint256,uint256) (runs: 5000, μ: 246730, ~: 247883)
Logs:
  Bound result 615514462186775432459
  Bound result 571193127101173104469
  Bound result 173721804

[PASS] test_restore_fuzz_revertsWith_SurplusDrawnRestored_with_interest_and_premium(uint256,uint256,uint256,uint256) (runs: 5000, μ: 638764, ~: 639011)
Logs:
  Bound result 8964
  Bound result 537
  Bound result 480000000
  Bound result 30

[PASS] test_restore_one_share_delta_increase_revertsWith_InvalidPremiumChange() (gas: 214877)
[PASS] test_restore_partial_drawn() (gas: 325676)
[PASS] test_restore_partial_same_block() (gas: 325802)
[PASS] test_restore_premiumDeltas_twoWeiIncrease_realizedDelta() (gas: 235598)
[PASS] test_restore_revertsWith_InsufficientTransferred() (gas: 255389)
[PASS] test_restore_revertsWith_InvalidAmount_zero() (gas: 58090)
[PASS] test_restore_revertsWith_InvalidPremiumChange_premiumIncrease() (gas: 221842)
[PASS] test_restore_revertsWith_InvalidPremiumChange_premiumSharesIncrease() (gas: 221842)
[PASS] test_restore_revertsWith_SpokeHalted() (gas: 99279)
[PASS] test_restore_revertsWith_SpokeNotActive_whenPaused() (gas: 181407)
[PASS] test_restore_revertsWith_SurplusDrawnRestored() (gas: 364517)
[PASS] test_restore_revertsWith_SurplusDrawnRestored_with_interest() (gas: 246508)
Logs:
  Bound result 100000000000000000000
  Bound result 50000000000000000000
  Bound result 15768000

[PASS] test_restore_revertsWith_SurplusDrawnRestored_with_interest_and_premium() (gas: 636973)
Logs:
  Bound result 100000000000000000000
  Bound result 50000000000000000000
  Bound result 31536000
  Bound result 1

[PASS] test_restore_revertsWith_SurplusPremiumRayRestored() (gas: 527044)
[PASS] test_restore_revertsWith_underflow_offsetIncrease() (gas: 230699)
[PASS] test_restore_tooMuchDrawn_revertsWith_SurplusDrawnRestored() (gas: 217195)
[PASS] test_restore_when_asset_caps_reset() (gas: 438601)
Suite result: ok. 23 passed; 0 failed; 0 skipped; finished in 19.02s (18.99s CPU time)

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

Ran 4 tests for tests/unit/Hub/Hub.Skim.t.sol:HubSkimTest
[PASS] test_skimAdd_fuzz_donationAfterAdd(uint256,uint256,uint256) (runs: 5000, μ: 228241, ~: 228304)
Logs:
  Bound result 3
  Bound result 18470873395738003579119570309
  Bound result 446067553769140138733721804

[PASS] test_skimAdd_fuzz_donationBeforeAdd(uint256,uint256,uint256) (runs: 5000, μ: 228273, ~: 228336)
Logs:
  Bound result 3
  Bound result 18470873395738003579119570309
  Bound result 446067553769140138733721804

[PASS] test_skimAdd_fuzz_wrongSpokeTransfer(uint256,uint256,uint256) (runs: 5000, μ: 217360, ~: 217300)
Logs:
  Bound result 3
  Bound result 18132171100462486213502917929
  Bound result 446067553769140138733721804

[PASS] test_skimRestore_fuzz_liquidityDonation(uint256,uint256,uint256) (runs: 5000, μ: 272670, ~: 274039)
Logs:
  Bound result 3
  Bound result 18470873395738003579119570309
  Bound result 446067553769140138733721804

Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 27.85s (27.83s CPU time)

Ran 10 tests for tests/unit/Hub/Hub.SpokeConfig.t.sol:HubSpokeConfigTest
[PASS] test_add_active_halted_scenarios() (gas: 303691)
[PASS] test_draw_active_halted_scenarios() (gas: 304383)
[PASS] test_eliminateDeficit_active_halted_scenarios() (gas: 838931)
[PASS] test_mintFeeShares_active_halted_scenarios() (gas: 839923)
[PASS] test_payFeeShares_active_halted_scenarios() (gas: 369275)
[PASS] test_refreshPremium_active_halted_scenarios() (gas: 267102)
[PASS] test_remove_active_halted_scenarios() (gas: 319521)
[PASS] test_reportDeficit_active_halted_scenarios() (gas: 444886)
[PASS] test_restore_active_halted_scenarios() (gas: 355284)
[PASS] test_transferShares_fuzz_active_halted_scenarios(bool,bool,bool,bool) (runs: 5000, μ: 213528, ~: 213542)
Suite result: ok. 10 passed; 0 failed; 0 skipped; finished in 4.09s (4.06s CPU time)

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

[PASS] test_sweep_does_not_impact_utilization(uint256,uint256) (runs: 5000, μ: 630343, ~: 631460)
Logs:
  Bound result 68691281934999
  Bound result 100

[PASS] test_sweep_fuzz(uint256,uint256) (runs: 5000, μ: 483822, ~: 483814)
Logs:
  Bound result 68691281934999
  Bound result 100

[PASS] test_sweep_revertsWith_AssetNotListed() (gas: 12581)
[PASS] test_sweep_revertsWith_InsufficientLiquidity() (gas: 219888)
[PASS] test_sweep_revertsWith_InvalidAmount() (gas: 103885)
[PASS] test_sweep_revertsWith_OnlyReinvestmentController(address) (runs: 5000, μ: 93946, ~: 93946)
[PASS] test_sweep_revertsWith_OnlyReinvestmentController_init() (gas: 40055)
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 18.42s (18.39s CPU time)

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

[PASS] test_transferShares_fuzz(uint256,uint256) (runs: 5000, μ: 194818, ~: 195023)
Logs:
  Bound result 68691281934999
  Bound result 100

[PASS] test_transferShares_fuzz_revertsWith_underflow_spoke_added_shares_exceeded(uint256) (runs: 5000, μ: 151436, ~: 151149)
Logs:
  Bound result 3124043968137

[PASS] test_transferShares_revertsWith_AddCapExceeded() (gas: 195766)
[PASS] test_transferShares_revertsWith_SpokeHalted() (gas: 184920)
[PASS] test_transferShares_revertsWith_SpokeNotActive() (gas: 178184)
[PASS] test_transferShares_zeroShares_revertsWith_InvalidShares() (gas: 22595)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 7.64s (7.62s 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, μ: 2167311, ~: 2176713)
Logs:
  Bound result 100000000000000
  Bound result 2057199178
  Bound result 1949
  Bound result 75000000000000000000000
  Bound result 4514

[PASS] test_borrow_fuzz_single_spoke_multi_reserves(uint256,uint256,uint256,uint256) (runs: 5000, μ: 2319103, ~: 2329281)
Logs:
  Bound result 640744106
  Bound result 531
  Bound result 249999970000000001
  Bound result 13008

[PASS] test_borrow_fuzz_single_spoke_multi_reserves_multi_user(uint256,uint256,uint256,uint256) (runs: 5000, μ: 2725135, ~: 2735340)
Logs:
  Bound result 640744106
  Bound result 531
  Bound result 7500000000000000000000000000
  Bound result 13008

[PASS] test_borrow_fuzz_skip_borrow(uint256,uint256,uint256) (runs: 5000, μ: 1057675, ~: 1057925)
Logs:
  Bound result 615514462186775432459
  Bound result 218470873395738003579119570309
  Bound result 10765498

[PASS] test_borrow_skip_borrow() (gas: 1056626)
Logs:
  Bound result 10000000000000000000
  Bound result 20000000000000000000
  Bound result 31536000

[PASS] test_userAccountData_does_not_include_zero_cf_collateral() (gas: 1290006)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 165.26s (165.24s CPU time)

Ran 17 tests for tests/unit/Spoke/Spoke.Borrow.Validation.t.sol:SpokeBorrowValidationTest
[PASS] test_borrow_fuzz_revertsWith_DrawCapExceeded(uint256,uint40) (runs: 5000, μ: 110733, ~: 110742)
Logs:
  Bound result 4
  Bound result 1

[PASS] test_borrow_fuzz_revertsWith_DrawCapExceeded_due_to_interest(uint256) (runs: 5000, μ: 683882, ~: 684107)
Logs:
  Bound result 683968137

[PASS] test_borrow_fuzz_revertsWith_InsufficientLiquidity(uint256,uint256) (runs: 5000, μ: 295420, ~: 295171)
Logs:
  Bound result 100

[PASS] test_borrow_fuzz_revertsWith_InvalidAmount(uint256) (runs: 5000, μ: 34422, ~: 34478)
Logs:
  Bound result 2

[PASS] test_borrow_fuzz_revertsWith_ReserveFrozen(uint256,uint256) (runs: 5000, μ: 70977, ~: 70746)
Logs:
  Bound result 4
  Bound result 100

[PASS] test_borrow_fuzz_revertsWith_ReserveNotBorrowable(uint256,uint256) (runs: 5000, μ: 71075, ~: 70844)
Logs:
  Bound result 4
  Bound result 100

[PASS] test_borrow_fuzz_revertsWith_ReserveNotListed(uint256,uint256) (runs: 5000, μ: 27422, ~: 27138)
Logs:
  Bound result 670000000000000000

[PASS] test_borrow_fuzz_revertsWith_ReservePaused(uint256,uint256) (runs: 5000, μ: 70893, ~: 70662)
Logs:
  Bound result 4
  Bound result 100

[PASS] test_borrow_revertsWith_InsufficientLiquidity() (gas: 295104)
Logs:
  Bound result 10000000000000000000

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

[PASS] test_borrow_revertsWith_MaximumUserReservesExceeded() (gas: 6873012)
[PASS] test_borrow_revertsWith_ReserveFrozen() (gas: 72284)
Logs:
  Bound result 2
  Bound result 1

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

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

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

[PASS] test_borrow_to_limit_repay_borrow_again() (gas: 7136579)
[PASS] test_borrow_unlimited_whenLimitIsMax() (gas: 2088101)
Suite result: ok. 17 passed; 0 failed; 0 skipped; finished in 14.65s (14.63s CPU time)

Ran 17 tests for tests/unit/Spoke/Spoke.Repay.t.sol:SpokeRepayTest
[PASS] test_fuzz_amounts_repay_only_premium(uint256,uint256,uint40) (runs: 5000, μ: 887604, ~: 890959)
Logs:
  Bound result 615514462186775432459
  Bound result 6348
  Bound result 363243867333215

[PASS] test_fuzz_repay_amounts_only_interest(uint256,uint256,uint40) (runs: 5000, μ: 889231, ~: 894739)
Logs:
  Bound result 615514462186775432459
  Bound result 6348
  Bound result 6773030186390597

[PASS] test_fuzz_repay_only_premium(uint256,uint40) (runs: 5000, μ: 759420, ~: 759619)
Logs:
  Bound result 68691281934999
  Bound result 1
  Bound result 1

[PASS] test_fuzz_repay_same_block_fuzz_amounts(uint256,uint256) (runs: 5000, μ: 900085, ~: 910585)
Logs:
  Bound result 68691281934999
  Bound result 100

[PASS] test_fuzz_repay_x_y_shares(uint256,uint40) (runs: 5000, μ: 622185, ~: 622314)
Logs:
  Bound result 68691281934999
  Bound result 1

[PASS] test_repay() (gas: 704543)
[PASS] test_repay_all_with_accruals() (gas: 417294)
[PASS] test_repay_fuzz_amountsAndWait(uint256,uint256,uint40) (runs: 5000, μ: 936148, ~: 938121)
Logs:
  Bound result 615514462186775432459
  Bound result 571193127101173104469
  Bound result 6348

[PASS] test_repay_fuzz_amounts_base_debt(uint256,uint256,uint40) (runs: 5000, μ: 948762, ~: 962122)
Logs:
  Bound result 615514462186775432459
  Bound result 6348
  Bound result 12587671819954927

[PASS] test_repay_fuzz_amounts_base_debt_no_premium(uint256,uint256,uint40) (runs: 5000, μ: 823786, ~: 832799)
Logs:
  Bound result 615514462186775432459
  Bound result 6348
  Bound result 12587671819954927

[PASS] test_repay_fuzz_revertsWith_ERC20InsufficientBalance(uint256) (runs: 5000, μ: 553694, ~: 553826)
Logs:
  Bound result 3124043968137

[PASS] test_repay_max() (gas: 600436)
[PASS] test_repay_multiple_reserves_fuzz_amountsAndWait(uint256,uint256,uint256,uint256,uint256,uint40) (runs: 5000, μ: 3350669, ~: 3356993)
Logs:
  Bound result 248111466093868109584737499669
  Bound result 1
  Bound result 273983824922877658
  Bound result 28090053839266215334
  Bound result 5861
  Bound result 2947297

[PASS] test_repay_only_interest() (gas: 728336)
[PASS] test_repay_revertsWith_ERC20InsufficientAllowance() (gas: 556060)
[PASS] test_repay_revertsWith_ReentrancyGuardReentrantCall() (gas: 651005)
[PASS] test_repay_same_block() (gas: 681333)
Suite result: ok. 17 passed; 0 failed; 0 skipped; finished in 194.02s (194.00s CPU time)

Ran 6 tests for tests/unit/Hub/HubAccrueInterest.t.sol:HubAccrueInterestTest
[PASS] test_accrueInterest_NoActionTaken() (gas: 42658)
[PASS] test_accrueInterest_NoInterest_NoDebt(uint40) (runs: 5000, μ: 391609, ~: 391510)
Logs:
  Bound result 9

[PASS] test_accrueInterest_NoInterest_OnlyAdd(uint40) (runs: 5000, μ: 206802, ~: 206740)
Logs:
  Bound result 9

[PASS] test_accrueInterest_fuzz_BorrowAmountAndElapsed(uint256,uint40) (runs: 5000, μ: 271307, ~: 271199)
Logs:
  Bound result 68691281934999
  Bound result 1

[PASS] test_accrueInterest_fuzz_BorrowAmountRateAndElapsed(uint256,uint256,uint40) (runs: 5000, μ: 392397, ~: 392137)
Logs:
  Bound result 615514462186775432459
  Bound result 27544
  Bound result 6348

[PASS] test_accrueInterest_fuzz_BorrowAndWait(uint40) (runs: 5000, μ: 270026, ~: 269927)
Logs:
  Bound result 9

Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 24.92s (24.90s CPU time)

Ran 13 tests for tests/unit/HubConfigurator.GranularAccessControl.t.sol:HubConfiguratorGranularAccessControlTest
[PASS] test_assetManager_canCall_deactivateAsset() (gas: 138311)
[PASS] test_assetManager_canCall_haltAsset() (gas: 138325)
[PASS] test_assetManager_canCall_resetAssetCaps() (gas: 138743)
[PASS] test_assetManager_canCall_updateLiquidityFee() (gas: 84268)
[PASS] test_assetManager_cannotCall_anySpokeManagerMethod() (gas: 353934)
[PASS] test_fuzz_unauthorized_cannotCall_assetManagerMethods(address) (runs: 5000, μ: 277895, ~: 277895)
[PASS] test_fuzz_unauthorized_cannotCall_spokeManagerMethods(address) (runs: 5000, μ: 352478, ~: 352478)
[PASS] test_spokeManager_canCall_addSpoke() (gas: 126721)
[PASS] test_spokeManager_canCall_resetSpokeCaps() (gas: 185463)
[PASS] test_spokeManager_canCall_updateSpokeActive() (gas: 66003)
[PASS] test_spokeManager_canCall_updateSpokeCaps() (gas: 66504)
[PASS] test_spokeManager_canCall_updateSpokeHalted() (gas: 65972)
[PASS] test_spokeManager_cannotCall_anyAssetManagerMethod() (gas: 278850)
Suite result: ok. 13 passed; 0 failed; 0 skipped; finished in 5.87s (5.84s CPU time)

Ran 5 tests for tests/unit/Spoke/Spoke.ReserveConfig.t.sol:SpokeReserveConfigTest
[PASS] test_borrow_fuzz_borrowable_paused_frozen_scenarios(bool,bool,bool) (runs: 5000, μ: 280687, ~: 255167)
[PASS] test_repay_fuzz_paused_scenarios(bool) (runs: 5000, μ: 552831, ~: 551471)
[PASS] test_setUsingAsCollateral_fuzz_paused_frozen_scenarios(bool) (runs: 5000, μ: 184299, ~: 184311)
[PASS] test_supply_paused_frozen_scenarios() (gas: 322027)
[PASS] test_withdraw_paused_scenarios() (gas: 294262)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 16.08s (16.05s CPU time)

Ran 60 tests for tests/unit/HubConfigurator.t.sol:HubConfiguratorTest
[PASS] test_addAsset_fuzz(bool,address,uint8,address,uint256,uint16,uint32,uint32,uint32) (runs: 5000, μ: 448773, ~: 449342)
Logs:
  Bound result 9
  Bound result 5810
  Bound result 2365
  Bound result 20870
  Bound result 3
  Bound result 877

[PASS] test_addAsset_fuzz_revertsWith_AccessManagedUnauthorized(address) (runs: 5000, μ: 42331, ~: 42700)
[PASS] test_addAsset_fuzz_revertsWith_InvalidAssetDecimals(bool,address,uint8,address,uint256,address) (runs: 5000, μ: 65216, ~: 65188)
Logs:
  Bound result 252
  Bound result 9997

[PASS] test_addAsset_revertsWith_InvalidAddress_irStrategy() (gas: 58255)
[PASS] test_addAsset_revertsWith_InvalidAddress_underlying() (gas: 58171)
[PASS] test_addAsset_revertsWith_InvalidLiquidityFee() (gas: 350377)
[PASS] test_addAsset_reverts_invalidIrData() (gas: 76503)
[PASS] test_addSpoke() (gas: 135409)
[PASS] test_addSpokeToAssets() (gas: 232696)
[PASS] test_addSpokeToAssets_revertsWith_AccessManagedUnauthorized() (gas: 28151)
[PASS] test_addSpokeToAssets_revertsWith_MismatchedConfigs() (gas: 35971)
[PASS] test_addSpoke_revertsWith_AccessManagedUnauthorized() (gas: 27817)
[PASS] test_deactivateAsset() (gas: 176526)
[PASS] test_deactivateAsset_revertsWith_AccessManagedUnauthorized() (gas: 29002)
[PASS] test_deactivateSpoke() (gas: 175401)
[PASS] test_deactivateSpoke_revertsWith_AccessManagedUnauthorized() (gas: 28996)
[PASS] test_haltAsset() (gas: 176560)
[PASS] test_haltAsset_revertsWith_AccessManagedUnauthorized() (gas: 28981)
[PASS] test_haltSpoke() (gas: 175422)
[PASS] test_haltSpoke_revertsWith_AccessManagedUnauthorized() (gas: 29004)
[PASS] test_resetAssetCaps() (gas: 250744)
[PASS] test_resetAssetCaps_revertsWith_AccessManagedUnauthorized() (gas: 28956)
[PASS] test_resetSpokeCaps() (gas: 268435)
[PASS] test_resetSpokeCaps_revertsWith_AccessManagedUnauthorized() (gas: 29046)
[PASS] test_updateFeeConfig_Scenario() (gas: 353206)
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, μ: 195274, ~: 195561)
Logs:
  Bound result 2
  Bound result 9814

[PASS] test_updateFeeConfig_fuzz_revertsWith_AccessManagedUnauthorized(address) (runs: 5000, μ: 28519, ~: 28519)
[PASS] test_updateFeeConfig_revertsWith_InvalidAddress_spoke() (gas: 59417)
[PASS] test_updateFeeConfig_revertsWith_InvalidLiquidityFee() (gas: 62593)
[PASS] test_updateFeeReceiver_Scenario() (gas: 227692)
[PASS] test_updateFeeReceiver_WithdrawFromOldSpoke() (gas: 429602)
[PASS] test_updateFeeReceiver_correctAccruals() (gas: 466574)
[PASS] test_updateFeeReceiver_fuzz(address) (runs: 5000, μ: 188869, ~: 188889)
[PASS] test_updateFeeReceiver_fuzz_revertsWith_AccessManagedUnauthorized(address) (runs: 5000, μ: 28203, ~: 28203)
[PASS] test_updateFeeReceiver_revertsWith_InvalidAddress_spoke() (gas: 64072)
[PASS] test_updateFeeReceiver_revertsWith_SpokeAlreadyListed() (gas: 89372)
[PASS] test_updateInterestRateData() (gas: 81916)
[PASS] test_updateInterestRateData_revertsWith_AccessManagedUnauthorized() (gas: 30162)
[PASS] test_updateInterestRateStrategy() (gas: 102777)
[PASS] test_updateInterestRateStrategy_fuzz_revertsWith_AccessManagedUnauthorized(address) (runs: 5000, μ: 39577, ~: 39577)
[PASS] test_updateInterestRateStrategy_revertsWith_InterestRateStrategyReverts() (gas: 85998)
[PASS] test_updateInterestRateStrategy_revertsWith_InvalidAddress_irStrategy() (gas: 75586)
[PASS] test_updateInterestRateStrategy_revertsWith_InvalidInterestRateStrategy() (gas: 76221)
[PASS] test_updateLiquidityFee_fuzz(uint256,uint16) (runs: 5000, μ: 100500, ~: 102101)
Logs:
  Bound result 3
  Bound result 0

[PASS] test_updateLiquidityFee_revertsWith_AccessManagedUnauthorized() (gas: 27626)
[PASS] test_updateLiquidityFee_revertsWith_InvalidLiquidityFee() (gas: 64212)
[PASS] test_updateReinvestmentController() (gas: 110930)
[PASS] test_updateReinvestmentController_fuzz_revertsWith_AccessManagedUnauthorized(address) (runs: 5000, μ: 28204, ~: 28204)
[PASS] test_updateSpokeActive() (gas: 99297)
[PASS] test_updateSpokeActive_revertsWith_AccessManagedUnauthorized() (gas: 31303)
[PASS] test_updateSpokeCaps() (gas: 75433)
[PASS] test_updateSpokeCaps_revertsWith_AccessManagedUnauthorized() (gas: 31260)
[PASS] test_updateSpokeDrawCap() (gas: 75238)
[PASS] test_updateSpokeDrawCap_revertsWith_AccessManagedUnauthorized() (gas: 31227)
[PASS] test_updateSpokeHalted() (gas: 102054)
[PASS] test_updateSpokeHalted_revertsWith_AccessManagedUnauthorized() (gas: 31259)
[PASS] test_updateSpokeRiskPremiumThreshold() (gas: 75305)
[PASS] test_updateSpokeRiskPremiumThreshold_revertsWith_AccessManagedUnauthorized() (gas: 31261)
[PASS] test_updateSpokeSupplyCap() (gas: 75277)
[PASS] test_updateSpokeSupplyCap_revertsWith_AccessManagedUnauthorized() (gas: 31271)
Suite result: ok. 60 passed; 0 failed; 0 skipped; finished in 12.50s (12.47s CPU time)

Ran 4 tests for tests/unit/Spoke/Spoke.Borrow.t.sol:SpokeBorrowTest
[PASS] test_borrow() (gas: 1126246)
[PASS] test_borrow_fuzz_amounts(uint256,uint256) (runs: 5000, μ: 1135803, ~: 1135426)
Logs:
  Bound result 68691281934999
  Bound result 100

[PASS] test_borrow_revertsWith_ReentrancyGuardReentrantCall_hubDraw() (gas: 400261)
[PASS] test_borrow_revertsWith_ReentrancyGuardReentrantCall_hubRefreshPremium() (gas: 526688)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 27.82s (27.80s CPU time)

Ran 29 tests for tests/unit/Spoke/Spoke.Config.t.sol:SpokeConfigTest
[PASS] test_addReserve() (gas: 423674)
[PASS] test_addReserve_fuzz_revertsWith_AssetNotListed() (gas: 287886)
[PASS] test_addReserve_revertsWith_InvalidAddress_hub() (gas: 5085448)
[PASS] test_addReserve_revertsWith_InvalidAddress_oracle() (gas: 5126093)
[PASS] test_addReserve_revertsWith_InvalidAssetId() (gas: 32875)
[PASS] test_addReserve_revertsWith_InvalidUnderlyingDecimals() (gas: 281220)
[PASS] test_addReserve_revertsWith_ReserveExists() (gas: 399624)
[PASS] test_getReserveId_fuzz(uint256) (runs: 5000, μ: 55352, ~: 58043)
Logs:
  Bound result 2

[PASS] test_getReserveId_fuzz_multipleHubs(uint256) (runs: 5000, μ: 31037761, ~: 31040583)
Logs:
  Bound result 1

[PASS] test_getReserveId_fuzz_revertsWith_ReserveNotListed(uint256) (runs: 5000, μ: 29595, ~: 29583)
Logs:
  Bound result 3124043968137

[PASS] test_spoke_deploy() (gas: 5038298)
[PASS] test_spoke_deploy_reverts_on_InvalidConstructorInput() (gas: 833980)
[PASS] test_spoke_deploy_reverts_on_InvalidMaxUserReservesLimit() (gas: 836268)
[PASS] test_spoke_deploy_reverts_on_InvalidOracleDecimals() (gas: 836240)
[PASS] test_updateLiquidationConfig_fuzz_liqBonusConfig((uint128,uint64,uint16)) (runs: 5000, μ: 53023, ~: 53101)
Logs:
  Bound result 1708126567894405
  Bound result 12
  Bound result 340282366920938463462374607436975099147

[PASS] test_updateLiquidationConfig_fuzz_revertsWith_InvalidLiquidationConfig_healthFactorForMaxBonus((uint128,uint64,uint16)) (runs: 5000, μ: 36880, ~: 37137)
Logs:
  Bound result 17448452200277446021
  Bound result 12
  Bound result 340282366920938463462374607436975099147

[PASS] test_updateLiquidationConfig_fuzz_revertsWith_InvalidLiquidationConfig_liquidationBonusFactor((uint128,uint64,uint16)) (runs: 5000, μ: 36697, ~: 36462)
Logs:
  Bound result 1708126567894405
  Bound result 55547
  Bound result 340282366920938463462374607436975099147

[PASS] test_updateLiquidationConfig_fuzz_targetHealthFactor(uint128) (runs: 5000, μ: 46971, ~: 47279)
Logs:
  Bound result 340282366920938463462374607431768731273

[PASS] test_updateLiquidationConfig_liqBonusConfig() (gas: 52164)
Logs:
  Bound result 900000000000000000
  Bound result 1000
  Bound result 1000000000000000000

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

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

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

[PASS] test_updateReserveConfig() (gas: 54681)
[PASS] test_updateReserveConfig_fuzz((uint24,bool,bool,bool,bool)) (runs: 5000, μ: 55879, ~: 55709)
Logs:
  Bound result 818

[PASS] test_updateReserveConfig_revertsWith_InvalidCollateralRisk() (gas: 40147)
[PASS] test_upda...*[Comment body truncated]*

@github-actions
Copy link

github-actions bot commented Jan 14, 2026

♻️ Forge Gas Snapshots

Path Value
snapshots/Spoke.Operations.ZeroRiskPremium.json
liquidationCall (receiveShares): full ↓0% (-4) 303,257
liquidationCall (receiveShares): partial ↓0% (-4) 302,675
liquidationCall (reportDeficit): full ↑0% (+1303) 367,686
liquidationCall: full ↓0% (-4) 320,893
liquidationCall: partial ↓0% (-4) 320,311
snapshots/Spoke.Operations.json
liquidationCall (receiveShares): full ↓0% (-4) 335,301
liquidationCall (receiveShares): partial ↓0% (-4) 334,719
liquidationCall (reportDeficit): full ↓0% (-1114) 359,886
liquidationCall: full ↓0% (-4) 352,937
liquidationCall: partial ↓0% (-4) 352,355
🔕 Unchanged
Path Value
snapshots/Hub.Operations.json
add 86,703
add: with transfer 108,000
draw 104,159
eliminateDeficit: full 72,578
eliminateDeficit: partial 82,183
mintFeeShares 82,752
payFee 70,816
refreshPremium 70,373
remove: full 75,607
remove: partial 80,745
reportDeficit 111,893
restore: full 76,563
restore: full - with transfer 169,172
restore: partial 85,273
restore: partial - with transfer 143,253
transferShares 69,630
snapshots/NativeTokenGateway.Operations.json
borrowNative 228,656
repayNative 166,471
supplyAsCollateralNative 160,133
supplyNative 135,762
withdrawNative: full 125,557
withdrawNative: partial 136,746
snapshots/SignatureGateway.Operations.json
borrowWithSig 213,889
repayWithSig 186,743
setSelfAsUserPositionManagerWithSig 75,385
setUsingAsCollateralWithSig 85,387
supplyWithSig 151,994
updateUserDynamicConfigWithSig 63,120
updateUserRiskPremiumWithSig 62,090
withdrawWithSig 130,812
snapshots/Spoke.Getters.json
getUserAccountData: supplies: 0, borrows: 0 13,014
getUserAccountData: supplies: 1, borrows: 0 49,426
getUserAccountData: supplies: 2, borrows: 0 81,102
getUserAccountData: supplies: 2, borrows: 1 101,531
getUserAccountData: supplies: 2, borrows: 2 120,791
snapshots/Spoke.Operations.ZeroRiskPremium.json
borrow: first 190,384
borrow: second action, same reserve 170,250
permitReserve + repay (multicall) 164,576
permitReserve + supply (multicall) 146,756
permitReserve + supply + enable collateral (multicall) 161,207
repay: full 123,914
repay: partial 128,872
setUserPositionManagersWithSig: disable 47,039
setUserPositionManagersWithSig: enable 68,951
supply + enable collateral (multicall) 141,409
supply: 0 borrows, collateral disabled 122,846
supply: 0 borrows, collateral enabled 105,817
supply: second action, same reserve 105,746
updateUserDynamicConfig: 1 collateral 74,545
updateUserDynamicConfig: 2 collaterals 89,413
updateUserRiskPremium: 1 borrow 95,734
updateUserRiskPremium: 2 borrows 105,414
usingAsCollateral: 0 borrows, enable 59,616
usingAsCollateral: 1 borrow, disable 105,778
usingAsCollateral: 1 borrow, enable 42,504
usingAsCollateral: 2 borrows, disable 127,327
usingAsCollateral: 2 borrows, enable 42,516
withdraw: 0 borrows, full 127,955
withdraw: 0 borrows, partial 132,851
withdraw: 1 borrow, partial 159,982
withdraw: 2 borrows, partial 174,540
withdraw: non collateral 105,902
snapshots/Spoke.Operations.json
borrow: first 259,319
borrow: second action, same reserve 202,185
permitReserve + repay (multicall) 162,044
permitReserve + supply (multicall) 146,756
permitReserve + supply + enable collateral (multicall) 161,207
repay: full 117,993
repay: partial 137,351
setUserPositionManagersWithSig: disable 47,039
setUserPositionManagersWithSig: enable 68,951
supply + enable collateral (multicall) 141,409
supply: 0 borrows, collateral disabled 122,846
supply: 0 borrows, collateral enabled 105,817
supply: second action, same reserve 105,746
updateUserDynamicConfig: 1 collateral 74,545
updateUserDynamicConfig: 2 collaterals 89,413
updateUserRiskPremium: 1 borrow 149,093
updateUserRiskPremium: 2 borrows 199,355
usingAsCollateral: 0 borrows, enable 59,616
usingAsCollateral: 1 borrow, disable 159,134
usingAsCollateral: 1 borrow, enable 42,504
usingAsCollateral: 2 borrows, disable 229,264
usingAsCollateral: 2 borrows, enable 42,516
withdraw: 0 borrows, full 127,955
withdraw: 0 borrows, partial 132,851
withdraw: 1 borrow, partial 210,836
withdraw: 2 borrows, partial 257,012
withdraw: non collateral 105,902

@@ -863,6 +862,7 @@ abstract contract Spoke is
/// @dev It clears the user position, setting drawn debt, premium debt, and risk premium to zero.
function _reportDeficit(address user) internal {
Copy link
Member

Choose a reason for hiding this comment

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

independently from applying this PR:

  • It may make sense to rename this fn to _notifyReportDeficit or smt similar, given it's analogous to _notifyRiskPremiumUpdate imo.
  • The natspec docs above is now corrent, but not in head dev atm (this fn does not set user rp to zero)

uint256 newRiskPremium = _calculateUserAccountData(user).riskPremium;
_notifyRiskPremiumUpdate(user, newRiskPremium);
}
_notifyRiskPremiumUpdate(user, newRiskPremium);
Copy link
Member

Choose a reason for hiding this comment

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

here the question, when reading this fn you can assume either
i. _reportDeficit only clears user debt and notify so we must _notifyRiskPremiumUpdate at the end no matter what (dev)
ii. _reportDeficit also clears risk premium so we don't need to notify later. (PR)

imo:
i. option follow single responsability principle, and makes liq fn more readable
ii. option is more self-contained and favors reusability. It's only used once and worsen liq fn readabiltiy

Copy link
Member Author

Choose a reason for hiding this comment

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

single responsibility is readable but more error prone imo, since the true action is contained in two methods

i think renaming to notifyReportDefict or reportAndNotifyDeficit is a great suggestion to improve the lost readability

Copy link
Contributor

@yan-man yan-man left a comment

Choose a reason for hiding this comment

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

I submit

emit ISpoke.ReportDeficit(reserveId, user, deficitShares, premiumDelta);
}

emit ISpoke.UpdateUserRiskPremium(user, 0);
Copy link
Member

Choose a reason for hiding this comment

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

this is being emitted even if the risk premium was already 0. We d need to do smt like to avoid emitting false events...

    if (newRiskPremium == 0 && positionStatus.riskPremium == 0) {
      return;
    }

I d keep the code as is OR create an internal helper for updating user risk premium that i) returns early if not needed, ii) update storage and iii) emit event.

Copy link
Member Author

@DhairyaSethi DhairyaSethi Feb 5, 2026

Choose a reason for hiding this comment

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

its just a redundant event, idt it's 'false'. to me its fine as is

internal helper will make the logic of _notifyRiskPremium more expensive

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

why are you fine with the redudant event in this case? it d make the logic of _reportDeficit more expensive no? the _notifyRiskPremium wouldn't be much affected.
the suggestion does not work for the same reason that calling _notifyRiskPremiumUpdate but not actually calling hub.refresh is misleading (one of the motivations for this PR).

Copy link
Member Author

@DhairyaSethi DhairyaSethi Feb 6, 2026

Choose a reason for hiding this comment

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

it adds additional comparator which is more expensive in the general case, the redundant event is only redundant in one case when prev rp is 0; im fine here because next rp bc of report deficit is always 0
(unlike notify risk premium)

the logic is simpler w/o suggestion but i'm happy to apply

Copy link
Member

Choose a reason for hiding this comment

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

We agreed to accept the redundancy, as it makes deficit scenarios more explicit when the system fully clears a user position, without impacting gas efficiency in the average case.

@yan-man yan-man merged commit 5c2b8fa into dev Feb 7, 2026
3 checks passed
@miguelmtzinf miguelmtzinf deleted the chore/deficit-reorder branch February 7, 2026 08:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants