Skip to content

Conversation

@avniculae
Copy link
Contributor

@avniculae avniculae commented Dec 12, 2025

  • Implements temporary approvals in AllowancePositionManager by using transient storage (following draft ERC7674)

@avniculae avniculae changed the base branch from main to feat/new-position-managers December 12, 2025 12:32
@avniculae avniculae changed the title Feat/posm temporary approvals feat: Temporary approvals in AllowancePositionManager Dec 12, 2025
@github-actions
Copy link

github-actions bot commented Dec 12, 2025

♻️ Forge Gas Snapshots

Path Value
snapshots/AllowancePositionManager.Operations.json
borrowOnBehalfOf ↑0% (+657) 310,092
withdrawOnBehalfOf: full ↑0% (+508) 121,837
withdrawOnBehalfOf: partial ↑0% (+635) 132,096
borrowOnBehalfOf (with temporary allowance) 247979
temporaryApproveWithdraw 25552
temporaryDelegateCredit 25528
withdrawOnBehalfOf: full (with temporary allowance) 56154
withdrawOnBehalfOf: partial (with temporary allowance) 66954
🔕 Unchanged
Path Value
snapshots/AllowancePositionManager.Operations.json
approveWithdraw 49,895
approveWithdrawWithSig 66,560
delegateCredit 49,864
delegateCreditWithSig 66,505
renounceCreditDelegation 28,020
renounceWithdrawAllowance 28,007
snapshots/Hub.Operations.json
add 88,006
add: with transfer 109,613
draw 105,931
eliminateDeficit: full 59,781
eliminateDeficit: partial 69,429
mintFeeShares 84,007
payFee 72,302
refreshPremium 71,999
remove: full 76,993
remove: partial 81,640
reportDeficit 115,225
restore: full 80,471
restore: full - with transfer 173,377
restore: partial 89,137
restore: partial - with transfer 147,400
transferShares 71,192
snapshots/NativeTokenGateway.Operations.json
borrowNative 229,396
repayNative 168,082
supplyAsCollateralNative 160,453
supplyNative 136,523
withdrawNative: full 125,667
withdrawNative: partial 136,883
snapshots/PositionConfigPositionManager.Operations.json
renounceGlobalPermission 27,699
renounceUserDynamicConfigPermission 27,763
renounceUserRiskPremiumPermission 27,720
renounceUsingAsCollateralPermission 27,698
setGlobalPermission 49,868
setUserDynamicConfigPermission 49,845
setUserRiskPremiumPermission 49,891
setUsingAsCollateralOnBehalfOf 71,916
setUsingAsCollateralPermission 49,847
updateUserDynamicConfigOnBehalfOf 49,577
updateUserRiskPremiumOnBehalfOf 130,652
snapshots/PositionManagerBase.Operations.json
setSelfAsUserPositionManagerWithSig 74,809
snapshots/SignatureGateway.Operations.json
borrowWithSig 215,605
repayWithSig 188,872
setSelfAsUserPositionManagerWithSig 74,880
setUsingAsCollateralWithSig 85,075
supplyWithSig 153,223
updateUserDynamicConfigWithSig 62,791
updateUserRiskPremiumWithSig 61,513
withdrawWithSig 131,731
snapshots/Spoke.Getters.json
getUserAccountData: supplies: 0, borrows: 0 11,937
getUserAccountData: supplies: 1, borrows: 0 48,600
getUserAccountData: supplies: 2, borrows: 0 80,378
getUserAccountData: supplies: 2, borrows: 1 100,166
getUserAccountData: supplies: 2, borrows: 2 118,596
snapshots/Spoke.Operations.ZeroRiskPremium.json
borrow: first 191,325
borrow: second action, same reserve 171,297
liquidationCall (receiveShares): full 300,103
liquidationCall (receiveShares): partial 299,821
liquidationCall: full 310,468
liquidationCall: partial 310,186
permitReserve + repay (multicall) 166,029
permitReserve + supply (multicall) 146,862
permitReserve + supply + enable collateral (multicall) 160,573
repay: full 126,094
repay: partial 130,983
setUserPositionManagerWithSig: disable 44,846
setUserPositionManagerWithSig: enable 68,875
supply + enable collateral (multicall) 140,624
supply: 0 borrows, collateral disabled 123,679
supply: 0 borrows, collateral enabled 106,601
supply: second action, same reserve 106,579
updateUserDynamicConfig: 1 collateral 73,694
updateUserDynamicConfig: 2 collaterals 88,551
updateUserRiskPremium: 1 borrow 94,804
updateUserRiskPremium: 2 borrows 104,619
usingAsCollateral: 0 borrows, enable 58,915
usingAsCollateral: 1 borrow, disable 105,072
usingAsCollateral: 1 borrow, enable 41,803
usingAsCollateral: 2 borrows, disable 126,055
usingAsCollateral: 2 borrows, enable 41,815
withdraw: 0 borrows, full 128,910
withdraw: 0 borrows, partial 133,473
withdraw: 1 borrow, partial 161,036
withdraw: 2 borrows, partial 174,214
withdraw: non collateral 106,544
snapshots/Spoke.Operations.json
borrow: first 261,721
borrow: second action, same reserve 204,693
liquidationCall (receiveShares): full 333,666
liquidationCall (receiveShares): partial 333,384
liquidationCall: full 344,031
liquidationCall: partial 343,749
permitReserve + repay (multicall) 163,273
permitReserve + supply (multicall) 146,862
permitReserve + supply + enable collateral (multicall) 160,573
repay: full 120,256
repay: partial 139,545
setUserPositionManagerWithSig: disable 44,846
setUserPositionManagerWithSig: enable 68,875
supply + enable collateral (multicall) 140,624
supply: 0 borrows, collateral disabled 123,679
supply: 0 borrows, collateral enabled 106,601
supply: second action, same reserve 106,579
updateUserDynamicConfig: 1 collateral 73,694
updateUserDynamicConfig: 2 collaterals 88,551
updateUserRiskPremium: 1 borrow 151,080
updateUserRiskPremium: 2 borrows 204,276
usingAsCollateral: 0 borrows, enable 58,915
usingAsCollateral: 1 borrow, disable 161,348
usingAsCollateral: 1 borrow, enable 41,803
usingAsCollateral: 2 borrows, disable 233,712
usingAsCollateral: 2 borrows, enable 41,815
withdraw: 0 borrows, full 128,910
withdraw: 0 borrows, partial 133,473
withdraw: 1 borrow, partial 214,810
withdraw: 2 borrows, partial 259,272
withdraw: non collateral 106,544
snapshots/SupplyRepayPositionManager.Operations.json
repayOnBehalfOf 169,863
supplyOnBehalfOf 138,004

@github-actions
Copy link

github-actions bot commented Dec 12, 2025

Forge Build Sizes

Contract Runtime Size (B) Initcode Size (B) Runtime Margin (B) Initcode Margin (B)
AllowancePositionManager ↑6% (+533) 8,924 ↑6% (+533) 9,448 ↓3% (-533) 15,652 ↓1% (-533) 39,704
AllowancePositionManagerWrapper 9,016 9,542 15,560 39,610
🔕 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
AccessManagerEnumerable 12,137 13,534 12,439 35,618
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
ConfigPermissionsMap 44 94 24,532 49,058
ConfigPermissionsWrapper 723 751 23,853 48,401
Constants 447 499 24,129 48,653
ECDSA 44 94 24,532 49,058
EIP712Hash 541 593 24,035 48,559
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 21,598 21,832 2,978 27,320
HubConfigurator 9,981 10,254 14,595 38,898
JsonBindings 11,158 11,210 13,418 37,942
KeyValueList 44 94 24,532 49,058
KeyValueListWrapper 802 830 23,774 48,322
LibBit 44 94 24,532 49,058
LiquidationLogic 6,542 6,594 18,034 42,558
LiquidationLogicWrapper 10,943 11,117 13,633 38,035
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
MockNoncesKeyed 601 629 23,975 48,523
MockPriceFeed 642 1,300 23,934 47,852
MockSkimSpoke 923 1,082 23,653 48,070
NativeTokenGateway 6,002 6,419 18,574 42,733
NoncesKeyed 425 453 24,151 48,699
Panic 44 94 24,532 49,058
PercentageMath 44 94 24,532 49,058
PercentageMathWrapper 592 620 23,984 48,532
PositionConfigPositionManager 6,026 6,301 18,550 42,851
PositionManagerBaseWrapper 3,754 4,029 20,822 45,123
PositionStatusMap 44 94 24,532 49,058
PositionStatusMapWrapper 2,389 2,417 22,187 46,735
Premium 44 94 24,532 49,058
ProxyAdmin 977 1,213 23,599 47,939
RescuableWrapper 770 904 23,806 48,248
ReserveFlagsMap 44 94 24,532 49,058
ReserveFlagsMapWrapper 1,075 1,103 23,501 48,049
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,892 10,403 14,684 38,749
SlotDerivation 44 94 24,532 49,058
SpokeConfigurator 8,659 8,932 15,917 40,220
SpokeInstance 24,523 25,266 53 23,886
StorageSlot 44 94 24,532 49,058
SupplyRepayPositionManager 4,742 5,017 19,834 44,135
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
TreasurySpoke 2,764 3,179 21,812 45,973
UnitPriceFeed 700 1,635 23,876 47,517
UserPositionDebt 44 94 24,532 49,058
UserPositionDebtWrapper 2,677 2,705 21,899 46,447
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,371 1,399 23,205 47,753

@github-actions
Copy link

github-actions bot commented Dec 12, 2025

🌈 Test Results
No files changed, compilation skipped

Ran 7 tests for tests/unit/position-managers/SignatureGateway/SignatureGateway.Reverts.Unauthorized.t.sol:SignatureGateway_Unauthorized_PositionManagerNotActive_Test
[PASS] test_borrowWithSig_revertsWith_Unauthorized() (gas: 77610)
[PASS] test_repayWithSig_revertsWith_Unauthorized() (gas: 110918)
[PASS] test_setUsingAsCollateralWithSig_revertsWith_Unauthorized() (gas: 70732)
[PASS] test_supplyWithSig_revertsWith_Unauthorized() (gas: 138527)
[PASS] test_updateUserDynamicConfigWithSig_revertsWith_Unauthorized() (gas: 80289)
[PASS] test_updateUserRiskPremiumWithSig_revertsWith_Unauthorized() (gas: 80141)
[PASS] test_withdrawWithSig_revertsWith_Unauthorized() (gas: 77732)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 23.51ms (4.56ms CPU time)

Ran 4 tests for tests/unit/position-managers/SignatureGateway/SignatureGateway.SetSelfAsUserPositionManagerWithSig.t.sol:SignatureGatewaySetSelfAsUserPositionManagerTest
[PASS] test_setSelfAsUserPositionManagerWithSig() (gas: 136283)
[PASS] test_setSelfAsUserPositionManagerWithSig_forwards_correct_call() (gas: 30879)
[PASS] test_setSelfAsUserPositionManagerWithSig_ignores_underlying_spoke_reverts() (gas: 29894)
[PASS] test_setSelfAsUserPositionManagerWithSig_revertsWith_SpokeNotRegistered() (gas: 16971)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 19.22ms (1.07ms CPU time)

Ran 9 tests for tests/gas/Hub.Operations.gas.t.sol:HubOperations_Gas_Tests
[PASS] test_add() (gas: 273543)
[PASS] test_deficit() (gas: 1181116)
[PASS] test_draw() (gas: 423925)
[PASS] test_mintFeeShares() (gas: 506169)
[PASS] test_payFee_transferShares() (gas: 975173)
[PASS] test_refreshPremium() (gas: 636225)
[PASS] test_remove() (gas: 314977)
[PASS] test_restore() (gas: 891658)
[PASS] test_restore_with_transfer() (gas: 892326)
Suite result: ok. 9 passed; 0 failed; 0 skipped; finished in 54.64ms (7.39ms CPU time)

Ran 3 tests for tests/unit/Spoke/Spoke.Access.t.sol:SpokeAccessTest
[PASS] testAccess_change_authority() (gas: 2616614)
[PASS] testAccess_hub_functions_callable_by_spokes() (gas: 579019)
[PASS] testAccess_spoke_admin_config_access() (gas: 494131)
Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 22.08ms (3.18ms 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),uint40) (runs: 0, μ: 0, ~: 0)
Suite result: ok. 0 passed; 0 failed; 1 skipped; finished in 25.06ms (4.86ms 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, μ: 24544, ~: 24690)
[PASS] test_calculateInterestRate_RightToKinkPoint(uint256) (runs: 5000, μ: 25643, ~: 25690)
[PASS] test_calculateInterestRate_ZeroDebtZeroLiquidity() (gas: 18944)
Logs:
  Bound result 0

[PASS] test_calculateInterestRate_fuzz_ZeroDebt(uint256) (runs: 5000, μ: 19190, ~: 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 1.08s (1.07s CPU time)

Ran 5 tests for tests/unit/position-managers/libraries/ConfigPermissions.t.sol:ConfigPermissionsTests
[PASS] test_constants() (gas: 12214)
[PASS] test_setCanSetUsingAsCollateral_fuzz(uint8,bool) (runs: 5000, μ: 10617, ~: 10605)
[PASS] test_setCanUpdateUserDynamicConfig_fuzz(uint8,bool) (runs: 5000, μ: 10641, ~: 10629)
[PASS] test_setCanUpdateUserRiskPremium_fuzz(uint8,bool) (runs: 5000, μ: 10584, ~: 10572)
[PASS] test_setFullPermissions_fuzz(uint8,bool) (runs: 5000, μ: 13546, ~: 13536)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 786.99ms (786.75ms CPU time)

Ran 10 tests for tests/unit/position-managers/libraries/EIP712Hash.t.sol:EIP712HashTest
[PASS] test_constants() (gas: 6214)
[PASS] test_hash_borrow_fuzz((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 4637, ~: 4637)
[PASS] test_hash_creditDelegation_fuzz((address,uint256,address,address,uint256,uint256,uint256)) (runs: 5000, μ: 5010, ~: 5010)
[PASS] test_hash_repay_fuzz((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 4615, ~: 4615)
[PASS] test_hash_setUsingAsCollateral_fuzz((address,uint256,bool,address,uint256,uint256)) (runs: 5000, μ: 4880, ~: 4880)
[PASS] test_hash_supply_fuzz((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 4703, ~: 4703)
[PASS] test_hash_updateUserDynamicConfig_fuzz((address,address,uint256,uint256)) (runs: 5000, μ: 4441, ~: 4441)
[PASS] test_hash_updateUserRiskPremium_fuzz((address,address,uint256,uint256)) (runs: 5000, μ: 4462, ~: 4462)
[PASS] test_hash_withdrawPermit_fuzz((address,uint256,address,address,uint256,uint256,uint256)) (runs: 5000, μ: 5032, ~: 5032)
[PASS] test_hash_withdraw_fuzz((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 4681, ~: 4681)
Suite result: ok. 10 passed; 0 failed; 0 skipped; finished in 1.31s (1.31s CPU time)

Ran 5 tests for tests/gas/Gateways.Operations.gas.t.sol:NativeTokenGateway_Gas_Tests
[PASS] test_borrowNative() (gas: 921631)
[PASS] test_repayNative() (gas: 996126)
[PASS] test_supplyAndCollateralNative() (gas: 306628)
[PASS] test_supplyNative() (gas: 288375)
[PASS] test_withdrawNative() (gas: 511108)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 37.25ms (4.51ms CPU time)

Ran 17 tests for tests/unit/AaveOracle.t.sol:AaveOracleTest
[PASS] testDECIMALS() (gas: 8379)
[PASS] test_constructor() (gas: 440478)
[PASS] test_deploy_revertsWith_InvalidAddress() (gas: 38111)
[PASS] test_description() (gas: 12049)
[PASS] test_fuzz_constructor(uint8) (runs: 5000, μ: 444403, ~: 444725)
[PASS] test_getReservePrice() (gas: 47398)
[PASS] test_getReservePrice_revertsWith_InvalidPrice() (gas: 46691)
[PASS] test_getReservePrice_revertsWith_InvalidSource() (gas: 10998)
[PASS] test_getReservePrices() (gas: 79462)
[PASS] test_getReservePrices_revertsWith_InvalidSource() (gas: 49374)
[PASS] test_getReserveSource() (gas: 47628)
[PASS] test_setReserveSource() (gas: 44488)
[PASS] test_setReserveSource_revertsWith_InvalidPrice() (gas: 97705)
[PASS] test_setReserveSource_revertsWith_InvalidSource() (gas: 15349)
[PASS] test_setReserveSource_revertsWith_InvalidSourceDecimals() (gas: 15171)
[PASS] test_setReserveSource_revertsWith_OnlySpoke() (gas: 10984)
[PASS] test_spoke() (gas: 10559)
Suite result: ok. 17 passed; 0 failed; 0 skipped; finished in 3.71s (3.70s CPU time)

Ran 8 tests for tests/gas/Gateways.Operations.gas.t.sol:SignatureGateway_Gas_Tests
[PASS] test_borrowWithSig() (gas: 754995)
[PASS] test_repayWithSig() (gas: 991682)
[PASS] test_setSelfAsUserPositionManagerWithSig() (gas: 208311)
[PASS] test_setUsingAsCollateralWithSig() (gas: 296278)
[PASS] test_supplyWithSig() (gas: 468533)
[PASS] test_updateUserDynamicConfigWithSig() (gas: 145441)
[PASS] test_updateUserRiskPremiumWithSig() (gas: 143002)
[PASS] test_withdrawWithSig() (gas: 418536)
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 43.21ms (8.49ms CPU time)

Ran 6 tests for tests/unit/Hub/Hub.Access.t.sol:HubAccessTest
[PASS] test_change_authority() (gas: 2312388)
[PASS] test_change_role_responsibility() (gas: 122065)
[PASS] test_hub_access_manager_exposure() (gas: 12684)
[PASS] test_hub_admin_access() (gas: 1205062)
[PASS] test_migrate_role_responsibility() (gas: 682280)
[PASS] test_setInterestRateData_access() (gas: 103546)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 23.14ms (3.91ms CPU time)

Ran 6 tests for tests/unit/Hub/Hub.PayFee.t.sol:HubPayFeeTest
[PASS] test_payFee_fuzz(uint256,uint256) (runs: 5000, μ: 707703, ~: 707842)
[PASS] test_payFee_fuzz_with_interest(uint256,uint256,uint256) (runs: 5000, μ: 708169, ~: 708441)
[PASS] test_payFee_revertsWith_InvalidShares() (gas: 20137)
[PASS] test_payFee_revertsWith_SpokeNotActive() (gas: 59678)
[PASS] test_payFee_revertsWith_underflow_added_shares_exceeded() (gas: 138907)
[PASS] test_payFee_revertsWith_underflow_added_shares_exceeded_with_interest() (gas: 652789)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 26.37s (39.93s CPU time)

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

[PASS] test_reclaim_fullAmount() (gas: 661472)
[PASS] test_reclaim_fuzz(uint256,uint256,uint256) (runs: 5000, μ: 682550, ~: 681689)
[PASS] test_reclaim_multipleSweepsAndReclaims() (gas: 789768)
[PASS] test_reclaim_revertsWith_AssetNotListed() (gas: 12439)
[PASS] test_reclaim_revertsWith_InvalidAmount_zero() (gas: 93115)
[PASS] test_reclaim_revertsWith_OnlyReinvestmentController(address) (runs: 5000, μ: 93980, ~: 93980)
[PASS] test_reclaim_revertsWith_OnlyReinvestmentController_init() (gas: 40003)
[PASS] test_reclaim_revertsWith_underflow_exceedsSwept() (gas: 98578)
[PASS] test_reclaim_revertsWith_underflow_exceedsSwept_afterSweep() (gas: 461593)
Suite result: ok. 10 passed; 0 failed; 0 skipped; finished in 15.23s (16.88s CPU time)

Ran 19 tests for tests/unit/Hub/Hub.Add.t.sol:HubAddTest
[PASS] test_add_AddCapReachedButNotExceeded_rounding() (gas: 674997)
[PASS] test_add_fuzz_AddCapReachedButNotExceeded(uint40) (runs: 5000, μ: 160181, ~: 160147)
[PASS] test_add_fuzz_multi_asset_multi_spoke(uint256,uint256,uint256) (runs: 5000, μ: 330227, ~: 330441)
[PASS] test_add_fuzz_revertsWith_AddCapExceeded(uint40) (runs: 5000, μ: 112996, ~: 112962)
[PASS] test_add_fuzz_revertsWith_AddCapExceeded_due_to_interest(uint40,uint256,uint256) (runs: 5000, μ: 274499, ~: 274376)
[PASS] test_add_fuzz_revertsWith_InvalidShares_due_to_index(uint256,uint256,uint256) (runs: 5000, μ: 229996, ~: 230208)
[PASS] test_add_fuzz_single_asset(uint256,address,uint256) (runs: 5000, μ: 345559, ~: 345452)
[PASS] test_add_fuzz_single_spoke_multi_add(uint256,uint256) (runs: 5000, μ: 822164, ~: 822213)
[PASS] test_add_multi_add_minimal_shares() (gas: 328544)
[PASS] test_add_revertsWith_AmountDowncastOverflow() (gas: 368149)
[PASS] test_add_revertsWith_InsufficientTransferred() (gas: 64867)
[PASS] test_add_revertsWith_InvalidAmount() (gas: 13475)
[PASS] test_add_revertsWith_InvalidShares() (gas: 230124)
[PASS] test_add_revertsWith_SharesDowncastOverflow() (gas: 228043)
[PASS] test_add_revertsWith_SpokeNotActive() (gas: 98590)
[PASS] test_add_revertsWith_SpokePaused() (gas: 98707)
[PASS] test_add_single_asset() (gas: 333479)
Logs:
  Bound result 2
  Bound result 100000000000000000000

[PASS] test_add_with_increased_index() (gas: 308110)
[PASS] test_add_with_increased_index_with_premium() (gas: 688370)
Suite result: ok. 19 passed; 0 failed; 0 skipped; finished in 47.01s (46.99s CPU time)

Ran 9 tests for tests/unit/libraries/KeyValueList.t.sol:KeyValueListTest
[PASS] test_add_unique() (gas: 325391)
[PASS] test_fuzz_add(uint256,uint256) (runs: 5000, μ: 200299, ~: 201361)
[PASS] test_fuzz_add_unique(uint256,uint256) (runs: 5000, μ: 266098, ~: 271836)
[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, μ: 204892, ~: 185054)
[PASS] test_fuzz_sortByKey(uint256[]) (runs: 5000, μ: 464445, ~: 454508)
[PASS] test_fuzz_sortByKey_length(uint256) (runs: 5000, μ: 231328, ~: 241359)
[PASS] test_fuzz_sortByKey_with_collision(uint256[]) (runs: 5000, μ: 547910, ~: 538598)
Suite result: ok. 9 passed; 0 failed; 0 skipped; finished in 71.43s (121.63s 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, μ: 30637, ~: 30638)
[PASS] test_calculateDebtToLiquidate_fuzz_AmountAdjustedDueToDust((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 32368, ~: 32474)
[PASS] test_calculateDebtToLiquidate_fuzz_ImpossibleToAdjustForDust((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 34482, ~: 34400)
Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 3.28s (5.52s 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, μ: 23064, ~: 23016)
[PASS] test_calculateDebtToTargetHealthFactor_NoPrecisionLoss() (gas: 25208)
[PASS] test_calculateDebtToTargetHealthFactor_PrecisionLoss() (gas: 15209)
[PASS] test_calculateDebtToTargetHealthFactor_UnitPrice() (gas: 25141)
[PASS] test_calculateDebtToTargetHealthFactor_fuzz_NoRevert((uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 20125, ~: 20077)
[PASS] test_calculateDebtToTargetHealthFactor_fuzz_revertsWith_DivisionByZero_ZeroAssetPrice((uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 22824, ~: 22776)
[PASS] test_calculateDebtToTargetHealthFactor_revertsWith_ArithmeticError_TargetHealthFactorLessThanHealthFactor((uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 22907, ~: 22859)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 2.74s (4.76s CPU time)

Ran 16 tests for tests/unit/libraries/LiquidationLogic/LiquidationLogic.EvaluateDeficit.t.sol:LiquidationLogicEvaluateDeficitTest
[PASS] test_evaluateDeficit_CRE_SCCM_DRE_BRCM() (gas: 9012)
[PASS] test_evaluateDeficit_CRE_SCCM_DRE_BRCO() (gas: 8980)
[PASS] test_evaluateDeficit_CRE_SCCM_DRN_BRCM() (gas: 9001)
[PASS] test_evaluateDeficit_CRE_SCCM_DRN_BRCO() (gas: 8968)
[PASS] test_evaluateDeficit_CRE_SCCO_DRE_BRCM() (gas: 8994)
[PASS] test_evaluateDeficit_CRE_SCCO_DRE_BRCO() (gas: 9061)
[PASS] test_evaluateDeficit_CRE_SCCO_DRN_BRCM() (gas: 9026)
[PASS] test_evaluateDeficit_CRE_SCCO_DRN_BRCO() (gas: 9014)
[PASS] test_evaluateDeficit_CRN_SCCM_DRE_BRCM() (gas: 9014)
[PASS] test_evaluateDeficit_CRN_SCCM_DRE_BRCO() (gas: 9003)
[PASS] test_evaluateDeficit_CRN_SCCM_DRN_BRCM() (gas: 8937)
[PASS] test_evaluateDeficit_CRN_SCCM_DRN_BRCO() (gas: 8970)
[PASS] test_evaluateDeficit_CRN_SCCO_DRE_BRCM() (gas: 8947)
[PASS] test_evaluateDeficit_CRN_SCCO_DRE_BRCO() (gas: 9004)
[PASS] test_evaluateDeficit_CRN_SCCO_DRN_BRCM() (gas: 8955)
[PASS] test_evaluateDeficit_CRN_SCCO_DRN_BRCO() (gas: 9033)
Suite result: ok. 16 passed; 0 failed; 0 skipped; finished in 21.01ms (1.20ms CPU time)

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

[PASS] test_remove_all_with_interest() (gas: 377919)
[PASS] test_remove_fuzz(uint256,uint256) (runs: 5000, μ: 209217, ~: 209034)
[PASS] test_remove_fuzz_all_liquidity_with_interest(uint256,uint256) (runs: 5000, μ: 429875, ~: 430159)
[PASS] test_remove_fuzz_multi_spoke(uint256,uint256) (runs: 5000, μ: 293878, ~: 294021)
[PASS] test_remove_fuzz_multi_spoke_with_interest(uint256,uint256,uint256,uint256) (runs: 5000, μ: 433383, ~: 433926)
[PASS] test_remove_revertsWith_InsufficientLiquidity() (gas: 160467)
[PASS] test_remove_revertsWith_InsufficientLiquidity_exceeding_added_amount() (gas: 148158)
[PASS] test_remove_revertsWith_InsufficientLiquidity_zero_added() (gas: 20745)
[PASS] test_remove_revertsWith_InvalidAddress() (gas: 15718)
[PASS] test_remove_revertsWith_InvalidAmount() (gas: 17819)
[PASS] test_remove_revertsWith_SpokeNotActive() (gas: 59802)
[PASS] test_remove_revertsWith_SpokePaused() (gas: 59908)
[PASS] test_remove_revertsWith_underflow_exceeding_added_amount() (gas: 188116)
[PASS] test_remove_revertsWtih_underflow_one_extra_wei() (gas: 372890)
Suite result: ok. 15 passed; 0 failed; 0 skipped; finished in 32.67s (32.65s CPU time)

Ran 5 tests for tests/unit/libraries/LiquidationLogic/LiquidationLogic.LiquidateCollateral.t.sol:LiquidationLogicLiquidateCollateralTest
[PASS] test_liquidateCollateral_fuzz(uint256,uint256) (runs: 5000, μ: 268296, ~: 269280)
[PASS] test_liquidateCollateral_fuzz_CollateralToLiquidatorIsZero(uint256) (runs: 5000, μ: 110216, ~: 110942)
[PASS] test_liquidateCollateral_fuzz_receiveShares_sharesToLiquidator(uint256,uint256) (runs: 5000, μ: 754676, ~: 755973)
[PASS] test_liquidateCollateral_fuzz_revertsWith_ArithmeticUnderflow(uint256,uint256) (runs: 5000, μ: 100458, ~: 100270)
[PASS] test_liquidateCollateral_receiveShares_sharesToLiquidatorIsZero() (gas: 741483)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 13.16s (14.50s CPU time)

Ran 12 tests for tests/unit/Hub/Hub.RefreshPremium.t.sol:HubRefreshPremiumTest
[PASS] test_refreshPremium_emitsEvent() (gas: 259376)
[PASS] test_refreshPremium_fuzz_positiveDeltas(uint256,int256,int256) (runs: 5000, μ: 467692, ~: 472069)
[PASS] test_refreshPremium_fuzz_withAccrual(uint256,uint256,uint256,uint256) (runs: 5000, μ: 535279, ~: 542236)
[PASS] test_refreshPremium_maxRiskPremiumThreshold() (gas: 896046)
[PASS] test_refreshPremium_negativeDeltas(uint256) (runs: 5000, μ: 461071, ~: 461095)
[PASS] test_refreshPremium_negativeDeltas_withAccrual(uint256) (runs: 5000, μ: 533769, ~: 533995)
[PASS] test_refreshPremium_pausedSpokesAllowed() (gas: 120453)
[PASS] test_refreshPremium_revertsWith_InvalidPremiumChange_NonZeroRestoredPremiumRay() (gas: 856323)
[PASS] test_refreshPremium_revertsWith_InvalidPremiumChange_RiskPremiumThresholdExceeded_DecreasingPremium() (gas: 874204)
[PASS] test_refreshPremium_revertsWith_SpokeNotActive() (gas: 57758)
[PASS] test_refreshPremium_riskPremiumThreshold() (gas: 921454)
[PASS] test_refreshPremium_spokePremiumUpdateIsContained() (gas: 710313)
Suite result: ok. 12 passed; 0 failed; 0 skipped; finished in 55.21s (66.36s CPU time)

Ran 8 tests for tests/unit/libraries/LiquidationLogic/LiquidationLogic.LiquidationAmounts.t.sol:LiquidationLogicLiquidationAmountsTest
[PASS] test_calculateLiquidationAmounts_EnoughCollateral() (gas: 15487)
[PASS] test_calculateLiquidationAmounts_InsufficientCollateral() (gas: 15739)
[PASS] test_calculateLiquidationAmounts_fuzz_EnoughCollateral_CollateralDust((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 57004, ~: 56825)
[PASS] test_calculateLiquidationAmounts_fuzz_EnoughCollateral_NoCollateralDust((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 56012, ~: 55957)
[PASS] test_calculateLiquidationAmounts_fuzz_EnoughCollateral_NoDebtLeft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 72618, ~: 72482)
[PASS] test_calculateLiquidationAmounts_fuzz_InsufficientCollateral((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 59623, ~: 59508)
[PASS] test_calculateLiquidationAmounts_fuzz_revertsWith_MustNotLeaveDust_Collateral((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 56334, ~: 56155)
[PASS] test_calculateLiquidationAmounts_fuzz_revertsWith_MustNotLeaveDust_Debt((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 69155, ~: 69096)
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 17.40s (17.38s CPU time)

Ran 4 tests for tests/unit/libraries/LiquidationLogic/LiquidationLogic.LiquidationBonus.t.sol:LiquidationLogicLiquidationBonusTest
[PASS] test_calculateLiquidationBonus_MinBonusDueToRounding() (gas: 9317)
[PASS] test_calculateLiquidationBonus_PartialBonus() (gas: 9338)
[PASS] test_calculateLiquidationBonus_fuzz_ConstantBonus(uint256,uint256,uint256,uint256) (runs: 5000, μ: 17337, ~: 17135)
[PASS] test_calculateLiquidationBonus_fuzz_MaxBonus(uint256,uint256,uint256,uint256) (runs: 5000, μ: 19624, ~: 19420)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 965.40ms (942.94ms CPU time)

Ran 12 tests for tests/unit/libraries/LiquidationLogic/LiquidationLogic.ValidateLiquidationCall.t.sol:LiquidationLogicValidateLiquidationCallTest
[PASS] test_validateLiquidationCall() (gas: 26157)
[PASS] test_validateLiquidationCall_revertsWith_CannotReceiveShares() (gas: 262562)
[PASS] test_validateLiquidationCall_revertsWith_CollateralCannotBeLiquidated() (gas: 46049)
[PASS] test_validateLiquidationCall_revertsWith_HealthFactorNotBelowThreshold() (gas: 32053)
[PASS] test_validateLiquidationCall_revertsWith_InvalidDebtToCover() (gas: 27026)
[PASS] test_validateLiquidationCall_revertsWith_ReserveNotBorrowed() (gas: 27145)
[PASS] test_validateLiquidationCall_revertsWith_ReserveNotEnabledAsCollateral_NotUsingAsCollateral() (gas: 27266)
[PASS] test_validateLiquidationCall_revertsWith_ReserveNotEnabledAsCollateral_ZeroCollateralFactor() (gas: 27282)
[PASS] test_validateLiquidationCall_revertsWith_ReserveNotSupplied() (gas: 27112)
[PASS] test_validateLiquidationCall_revertsWith_ReservePaused_CollateralPaused() (gas: 32175)
[PASS] test_validateLiquidationCall_revertsWith_ReservePaused_DebtPaused() (gas: 32175)
[PASS] test_validateLiquidationCall_revertsWith_SelfLiquidation() (gas: 33938)
Suite result: ok. 12 passed; 0 failed; 0 skipped; finished in 20.98ms (1.50ms CPU time)

Ran 26 tests for tests/unit/MathUtils.t.sol:MathUtilsTest
[PASS] test_add_edge_cases() (gas: 4854)
[PASS] test_add_negative_operand(uint256,int256) (runs: 5000, μ: 9257, ~: 9012)
[PASS] test_add_positive_operand(uint256,int256) (runs: 5000, μ: 4015, ~: 4010)
[PASS] test_calculateLinearInterest() (gas: 4467)
[PASS] test_calculateLinearInterest_add_edge() (gas: 5043)
[PASS] test_calculateLinearInterest_edge_cases() (gas: 16815)
Logs:
  Bound result 0
  Bound result 1
  Bound result 864000000
  Bound result 864000000

[PASS] test_calculateLinearInterest_reverts_on_past_timestamp(uint40) (runs: 5000, μ: 7700, ~: 7550)
[PASS] test_constants() (gas: 3167)
[PASS] test_fuzz_calculateLinearInterest(uint96,uint40,uint256) (runs: 5000, μ: 8752, ~: 8996)
[PASS] test_fuzz_mulDivDown(uint256,uint256,uint256) (runs: 5000, μ: 3577, ~: 3634)
[PASS] test_fuzz_mulDivUp(uint256,uint256,uint256) (runs: 5000, μ: 3659, ~: 3781)
[PASS] test_min(uint256,uint256) (runs: 5000, μ: 3338, ~: 3339)
[PASS] test_mulDivDown_NoRemainder() (gas: 3302)
[PASS] test_mulDivDown_RevertOnDivByZero() (gas: 3147)
[PASS] test_mulDivDown_RevertOnOverflow() (gas: 3181)
[PASS] test_mulDivDown_WithRemainder() (gas: 3236)
[PASS] test_mulDivDown_ZeroAOrB() (gas: 3768)
[PASS] test_mulDivUp_NoRemainder() (gas: 3306)
[PASS] test_mulDivUp_RevertOnDivByZero() (gas: 3102)
[PASS] test_mulDivUp_RevertOnOverflow() (gas: 3160)
[PASS] test_mulDivUp_WithRemainder() (gas: 3305)
[PASS] test_mulDivUp_ZeroAOrB() (gas: 3884)
[PASS] test_signedSub(uint256,uint256) (runs: 5000, μ: 8714, ~: 8661)
[PASS] test_uncheckedAdd(uint256,uint256) (runs: 5000, μ: 3416, ~: 3408)
[PASS] test_uncheckedExp(uint256,uint256) (runs: 5000, μ: 12049, ~: 9396)
[PASS] test_uncheckedSub(uint256,uint256) (runs: 5000, μ: 3435, ~: 3518)
Suite result: ok. 26 passed; 0 failed; 0 skipped; finished in 1.68s (1.67s CPU time)

Ran 3 tests for tests/unit/Hub/Hub.Rescue.t.sol:HubRescueTest
[PASS] test_cannot_rescue_liquidity_fee_reverts_with_InsufficientTransferred() (gas: 279900)
[PASS] test_rescue_fuzz_with_interest(uint256,uint256) (runs: 5000, μ: 526157, ~: 526144)
[PASS] test_rescue_scenario_fuzz(uint256) (runs: 5000, μ: 462922, ~: 462720)
Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 19.13s (19.10s CPU time)

Ran 6 tests for tests/unit/Hub/Hub.ReportDeficit.t.sol:HubReportDeficitTest
[PASS] test_reportDeficit_fuzz_revertsWith_SurplusDrawnDeficitReported(uint256) (runs: 5000, μ: 221513, ~: 221238)
[PASS] test_reportDeficit_fuzz_revertsWith_SurplusPremiumRayDeficitReported(uint256) (runs: 5000, μ: 223207, ~: 222932)
[PASS] test_reportDeficit_fuzz_with_premium(uint256,uint256,uint256,uint256) (runs: 5000, μ: 676426, ~: 677378)
[PASS] test_reportDeficit_revertsWith_InvalidAmount() (gas: 24282)
[PASS] test_reportDeficit_revertsWith_SpokeNotActive(address) (runs: 5000, μ: 32428, ~: 32428)
[PASS] test_reportDeficit_with_premium() (gas: 675953)
Logs:
  Bound result 10000000000
  Bound result 31536000
  Bound result 5000000000
  Bound result 0

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

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

Ran 36 tests for tests/unit/Hub/Hub.Config.t.sol:HubConfigTest
[PASS] test_addAsset_fuzz(address,uint8,address) (runs: 5000, μ: 916150, ~: 916184)
[PASS] test_addAsset_fuzz_revertsWith_InvalidAddress_feeReceiver(address,uint8,address) (runs: 5000, μ: 46606, ~: 46787)
[PASS] test_addAsset_fuzz_revertsWith_InvalidAddress_irStrategy(address,uint8,address) (runs: 5000, μ: 46637, ~: 46818)
[PASS] test_addAsset_fuzz_revertsWith_InvalidAddress_underlying(uint8,address,address) (runs: 5000, μ: 37590, ~: 37590)
[PASS] test_addAsset_fuzz_revertsWith_InvalidAssetDecimals(address,uint8,address,address) (runs: 5000, μ: 47157, ~: 46949)
[PASS] test_addAsset_fuzz_revertsWith_InvalidAssetDecimals_tooLow(address,uint8,address,address) (runs: 5000, μ: 47408, ~: 47648)
[PASS] test_addAsset_fuzz_reverts_InvalidIrData(address,uint8,address,address) (runs: 5000, μ: 40970, ~: 36219)
[PASS] test_addAsset_revertsWith_BlockTimestampDowncastOverflow() (gas: 767690)
[PASS] test_addAsset_revertsWith_DrawnRateDowncastOverflow() (gas: 764636)
[PASS] test_addAsset_reverts_UnderlyingAlreadyListed() (gas: 47752)
[PASS] test_addSpoke_fuzz(uint256,(uint40,uint40,uint24,bool,bool)) (runs: 5000, μ: 125864, ~: 125918)
[PASS] test_addSpoke_fuzz_revertsWith_AssetNotListed(uint256,(uint40,uint40,uint24,bool,bool)) (runs: 5000, μ: 34744, ~: 34731)
[PASS] test_addSpoke_fuzz_revertsWith_InvalidAddress_spoke(uint256,(uint40,uint40,uint24,bool,bool)) (runs: 5000, μ: 33333, ~: 33387)
[PASS] test_addSpoke_revertsWith_SpokeAlreadyListed() (gas: 38876)
[PASS] test_hub_deploy_revertsWith_InvalidAddress() (gas: 47579)
[PASS] test_hub_max_riskPremium() (gas: 8570)
[PASS] test_updateAssetConfig_NewFeeReceiver_noFees() (gas: 731780)
[PASS] test_updateAssetConfig_NewFeeReceiver_revertsWith_SpokeNotActive_noFees() (gas: 625973)
[PASS] test_updateAssetConfig_UseExistingSpokeAndListedAsFeeReceiver_revertsWith_SpokeAlreadyListed() (gas: 72068)
[PASS] test_updateAssetConfig_fuzz(uint256,(address,uint16,address,address)) (runs: 5000, μ: 269283, ~: 269552)
[PASS] test_updateAssetConfig_fuzz_FromZeroLiquidityFee(uint256,uint16) (runs: 5000, μ: 823119, ~: 823071)
[PASS] test_updateAssetConfig_fuzz_LiquidityFee(uint256,uint16) (runs: 5000, μ: 725274, ~: 725226)
[PASS] test_updateAssetConfig_fuzz_NewFeeReceiver(uint256) (runs: 5000, μ: 831446, ~: 831564)
[PASS] test_updateAssetConfig_fuzz_NewInterestRateStrategy(uint256) (runs: 5000, μ: 1208199, ~: 1208317)
[PASS] test_updateAssetConfig_fuzz_ReuseFeeReceiver_revertsWith_SpokeAlreadyListed(uint256) (runs: 5000, μ: 883692, ~: 883810)
[PASS] test_updateAssetConfig_fuzz_Scenario(uint256) (runs: 5000, μ: 682862, ~: 682913)
[PASS] test_updateAssetConfig_fuzz_UseExistingSpokeAsFeeReceiver_revertsWith_SpokeAlreadyListed(uint256) (runs: 5000, μ: 71740, ~: 71740)
[PASS] test_updateAssetConfig_fuzz_revertsWith_InvalidInterestRateStrategy(uint256) (runs: 5000, μ: 59944, ~: 59995)
[PASS] test_updateAssetConfig_fuzz_revertsWith_InvalidLiquidityFee(uint256,(address,uint16,address,address)) (runs: 5000, μ: 41406, ~: 41307)
[PASS] test_updateAssetConfig_fuzz_revertsWith_InvalidReinvestmentController() (gas: 490561)
[PASS] test_updateAssetConfig_fuzz_revertsWith_calculateInterestRateReverts(uint256,(address,uint16,address,address)) (runs: 5000, μ: 202680, ~: 202951)
[PASS] test_updateAssetConfig_fuzz_revertsWith_setInterestRateDataReverts(uint256,(address,uint16,address,address)) (runs: 5000, μ: 65521, ~: 65421)
[PASS] test_updateAssetConfig_oldFeeReceiver_flags() (gas: 844758)
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, μ: 58475, ~: 58537)
[PASS] test_updateSpokeConfig_fuzz_revertsWith_SpokeNotListed(uint256,address,(uint40,uint40,uint24,bool,bool)) (runs: 5000, μ: 40444, ~: 40504)
[PASS] test_updateSpokeConfig_revertsWith_AssetNotListed() (gas: 29356)
Suite result: ok. 36 passed; 0 failed; 0 skipped; finished in 97.59s (97.57s CPU time)

Ran 33 tests for tests/unit/position-managers/NativeTokenGateway.t.sol:NativeTokenGatewayTest
[PASS] test_borrowNative() (gas: 666032)
Logs:
  Bound result 5000000000000000000

[PASS] test_borrowNative_fuzz(uint256) (runs: 5000, μ: 665217, ~: 666038)
[PASS] test_borrowNative_revertsWith_InvalidAmount() (gas: 32287)
[PASS] test_borrowNative_revertsWith_NotNativeWrappedAsset() (gas: 32370)
[PASS] test_borrowNative_revertsWith_SpokeNotRegistered() (gas: 25342)
[PASS] test_constructor() (gas: 1274233)
[PASS] test_constructor_revertsWith_InvalidAddress() (gas: 65710)
[PASS] test_fallback_revertsWith_UnsupportedAction() (gas: 17874)
[PASS] test_multicall_revertsWith_UnsupportedAction() (gas: 11501)
[PASS] test_receive_revertsWith_UnsupportedAction() (gas: 17647)
[PASS] test_repayNative() (gas: 753359)
Logs:
  Bound result 5000000000000000000

[PASS] test_repayNative_excessAmount() (gas: 665347)
[PASS] test_repayNative_fuzz(uint256) (runs: 5000, μ: 748037, ~: 753701)
[PASS] test_repayNative_fuzz_withInterest(uint256,uint256) (runs: 5000, μ: 676166, ~: 671501)
[PASS] test_repayNative_revertsWith_InvalidAmount() (gas: 32601)
[PASS] test_repayNative_revertsWith_NativeAmountMismatch() (gas: 30659)
[PASS] test_repayNative_revertsWith_NotNativeWrappedAsset() (gas: 39407)
[PASS] test_repayNative_revertsWith_SpokeNotRegistered() (gas: 39286)
[PASS] test_supplyAndCollateralNative() (gas: 332046)
Logs:
  Bound result 100000000000000000000

[PASS] test_supplyAndCollateralNative_fuzz(uint256) (runs: 5000, μ: 332332, ~: 332052)
[PASS] test_supplyNative() (gas: 304370)
Logs:
  Bound result 100000000000000000000

[PASS] test_supplyNative_fuzz(uint256) (runs: 5000, μ: 304766, ~: 304486)
[PASS] test_supplyNative_revertsWith_InvalidAmount() (gas: 32588)
[PASS] test_supplyNative_revertsWith_NativeAmountMismatch() (gas: 30413)
[PASS] test_supplyNative_revertsWith_NotNativeWrappedAsset() (gas: 39283)
[PASS] test_supplyNative_revertsWith_SpokeNotRegistered() (gas: 39197)
[PASS] test_withdrawNative() (gas: 330567)
Logs:
  Bound result 100000000000000000000

[PASS] test_withdrawNative_fuzz(uint256) (runs: 5000, μ: 330086, ~: 330639)
[PASS] test_withdrawNative_fuzz_allBalance(uint256) (runs: 5000, μ: 268743, ~: 268544)
[PASS] test_withdrawNative_fuzz_allBalanceWithInterest(uint256,uint256) (runs: 5000, μ: 620363, ~: 620360)
[PASS] test_withdrawNative_revertsWith_InvalidAmount() (gas: 32329)
[PASS] test_withdrawNative_revertsWith_NotNativeWrappedAsset() (gas: 32414)
[PASS] test_withdrawNative_revertsWith_SpokeNotRegistered() (gas: 25408)
Suite result: ok. 33 passed; 0 failed; 0 skipped; finished in 65.52s (65.50s CPU time)

Ran 3 tests for tests/unit/NoncesKeyed.t.sol:NoncesKeyedTest
[PASS] test_useCheckedNonce_monotonic(bytes32) (runs: 5000, μ: 13319, ~: 13319)
[PASS] test_useCheckedNonce_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 102401, ~: 102401)
[PASS] test_useNonce_monotonic(bytes32) (runs: 5000, μ: 14081, ~: 14081)
Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 4.34s (4.33s CPU time)

Ran 16 tests for tests/unit/Hub/Hub.Draw.t.sol:HubDrawTest
[PASS] test_draw_DifferentSpokes() (gas: 362336)
[PASS] test_draw_fuzz_IncreasedBorrowRate(uint256,uint256) (runs: 5000, μ: 704773, ~: 704809)
[PASS] test_draw_fuzz_amounts_same_block(uint256,uint256) (runs: 5000, μ: 288999, ~: 288910)
[PASS] test_draw_fuzz_revertsWith_DrawCapExceeded(uint40) (runs: 5000, μ: 81416, ~: 81382)
[PASS] test_draw_fuzz_revertsWith_DrawCapExceeded_due_to_interest(uint40,uint256,uint256) (runs: 5000, μ: 293870, ~: 294131)
[PASS] test_draw_fuzz_revertsWith_InsufficientLiquidity(uint256,uint256) (runs: 5000, μ: 34071, ~: 33863)
[PASS] test_draw_fuzz_revertsWith_InsufficientLiquidity_due_to_draw(uint256) (runs: 5000, μ: 175327, ~: 175045)
[PASS] test_draw_fuzz_revertsWith_InsufficientLiquidity_due_to_remove(uint256) (runs: 5000, μ: 136214, ~: 136016)
[PASS] test_draw_fuzz_revertsWith_InvalidAddress(uint256) (runs: 5000, μ: 15757, ~: 15757)
[PASS] test_draw_revertsWith_DrawCapExceeded_due_to_deficit() (gas: 274491)
[PASS] test_draw_revertsWith_InsufficientLiquidity() (gas: 28097)
[PASS] test_draw_revertsWith_InsufficientLiquidity_due_to_draw() (gas: 171620)
[PASS] test_draw_revertsWith_InsufficientLiquidity_due_to_remove() (gas: 133323)
[PASS] test_draw_revertsWith_InvalidAmount() (gas: 15877)
[PASS] test_draw_revertsWith_SpokeNotActive() (gas: 59712)
[PASS] test_draw_revertsWith_SpokePaused() (gas: 59785)
Suite result: ok. 16 passed; 0 failed; 0 skipped; finished in 24.61s (24.59s 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, μ: 15348, ~: 15509)
[PASS] test_percentDivUp_le_value(uint256,uint256) (runs: 5000, μ: 15672, ~: 15662)
[PASS] test_percentDiv_fuzz(uint256,uint256) (runs: 5000, μ: 12867, ~: 13012)
[PASS] test_percentMul() (gas: 15116)
[PASS] test_percentMulUp_ge_value(uint256,uint256) (runs: 5000, μ: 15655, ~: 15645)
[PASS] test_percentMulUp_le_value(uint256,uint256) (runs: 5000, μ: 15351, ~: 15512)
[PASS] test_percentMul_fuzz(uint256,uint256) (runs: 5000, μ: 11728, ~: 12247)
Suite result: ok. 10 passed; 0 failed; 0 skipped; finished in 1.53s (1.53s CPU time)

Ran 4 tests for tests/unit/Hub/Hub.Skim.t.sol:HubSkimTest
[PASS] test_skimAdd_fuzz_donationAfterAdd(uint256,uint256,uint256) (runs: 5000, μ: 228308, ~: 228333)
[PASS] test_skimAdd_fuzz_donationBeforeAdd(uint256,uint256,uint256) (runs: 5000, μ: 228362, ~: 228387)
[PASS] test_skimAdd_fuzz_wrongSpokeTransfer(uint256,uint256,uint256) (runs: 5000, μ: 217212, ~: 217154)
[PASS] test_skimRestore_fuzz_liquidityDonation(uint256,uint256,uint256) (runs: 5000, μ: 276325, ~: 277893)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 28.25s (28.23s CPU time)

Ran 4 tests for tests/unit/libraries/LiquidationLogic/LiquidationLogic.LiquidateDebt.t.sol:LiquidationLogicLiquidateDebtTest
[PASS] test_liquidateDebt_fuzz(uint256) (runs: 5000, μ: 232952, ~: 232952)
[PASS] test_liquidateDebt_revertsWith_ArithmeticUnderflow() (gas: 97214)
[PASS] test_liquidateDebt_revertsWith_InsufficientAllowance() (gas: 124353)
[PASS] test_liquidateDebt_revertsWith_InsufficientBalance() (gas: 182249)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 94.55s (94.53s CPU time)

Ran 4 tests for tests/unit/libraries/LiquidationLogic/LiquidationLogic.LiquidateUser.t.sol:LiquidationLogicLiquidateUserTest
[PASS] test_liquidateUser() (gas: 368104)
[PASS] test_liquidateUser_revertsWith_InvalidDebtToCover() (gas: 76753)
[PASS] test_liquidateUser_revertsWith_MustNotLeaveDust_Collateral() (gas: 110465)
[PASS] test_liquidateUser_revertsWith_MustNotLeaveDust_Debt() (gas: 119743)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 26.38ms (1.46ms CPU time)

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

[PASS] test_restore_full_amount_with_interest_and_premium() (gas: 677110)
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, μ: 368058, ~: 368161)
[PASS] test_restore_fuzz_full_amount_with_interest_and_premium(uint256,uint256,uint256,uint256) (runs: 5000, μ: 666984, ~: 679061)
[PASS] test_restore_fuzz_revertsWith_SurplusDrawnRestored_with_interest(uint256,uint256,uint256) (runs: 5000, μ: 247875, ~: 249163)
[PASS] test_restore_fuzz_revertsWith_SurplusDrawnRestored_with_interest_and_premium(uint256,uint256,uint256,uint256) (runs: 5000, μ: 639384, ~: 639598)
[PASS] test_restore_one_share_delta_increase_revertsWith_InvalidPremiumChange() (gas: 214389)
[PASS] test_restore_partial_drawn() (gas: 330394)
[PASS] test_restore_partial_same_block() (gas: 326180)
[PASS] test_restore_premiumDeltas_twoWeiIncrease_realizedDelta() (gas: 236094)
[PASS] test_restore_revertsWith_InsufficientTransferred() (gas: 258359)
[PASS] test_restore_revertsWith_InvalidAmount_zero() (gas: 53333)
[PASS] test_restore_revertsWith_InvalidPremiumChange_premiumIncrease() (gas: 221541)
[PASS] test_restore_revertsWith_InvalidPremiumChange_premiumSharesIncrease() (gas: 221585)
[PASS] test_restore_revertsWith_SpokeNotActive_whenPaused() (gas: 165841)
[PASS] test_restore_revertsWith_SpokePaused() (gas: 93304)
[PASS] test_restore_revertsWith_SurplusDrawnRestored() (gas: 364671)
[PASS] test_restore_revertsWith_SurplusDrawnRestored_with_interest() (gas: 247739)
Logs:
  Bound result 100000000000000000000
  Bound result 50000000000000000000
  Bound result 15768000

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

[PASS] test_restore_revertsWith_SurplusPremiumRayRestored() (gas: 534140)
[PASS] test_restore_revertsWith_underflow_offsetIncrease() (gas: 232781)
[PASS] test_restore_tooMuchDrawn_revertsWith_SurplusDrawnRestored() (gas: 221898)
[PASS] test_restore_when_asset_frozen() (gas: 428118)
Suite result: ok. 23 passed; 0 failed; 0 skipped; finished in 51.65s (56.82s CPU time)

Ran 15 tests for tests/unit/position-managers/PositionManagerBase.t.sol:PositionManagerBaseTest
[PASS] test_constructor() (gas: 17626)
[PASS] test_getReserveUnderlying_fuzz(uint256) (runs: 5000, μ: 36272, ~: 36326)
[PASS] test_getReserveUnderlying_revertsWith_ReserveNotListed() (gas: 25378)
[PASS] test_permitReserveUnderlying() (gas: 131453)
[PASS] test_permitReserveUnderlying_forwards_correct_call() (gas: 78385)
[PASS] test_permitReserveUnderlying_ignores_permit_reverts() (gas: 67318)
[PASS] test_permitReserveUnderlying_revertsWith_ReserveNotListed() (gas: 58331)
[PASS] test_registerSpoke_fuzz(address) (runs: 5000, μ: 42113, ~: 42113)
[PASS] test_registerSpoke_revertsWith_InvalidAddress() (gas: 13260)
[PASS] test_registerSpoke_revertsWith_OwnableUnauthorizedAccount() (gas: 14080)
[PASS] test_registerSpoke_unregister() (gas: 36696)
[PASS] test_renouncePositionManagerRole() (gas: 65254)
[PASS] test_renouncePositionManagerRole_revertsWith_InvalidAddress() (gas: 76602)
[PASS] test_renouncePositionManagerRole_revertsWith_OwnableUnauthorizedAccount() (gas: 76896)
[PASS] test_setSelfAsUserPositionManagerWithSig() (gas: 128641)
Suite result: ok. 15 passed; 0 failed; 0 skipped; finished in 886.00ms (866.71ms CPU time)

Ran 12 tests for tests/gas/PositionManagers.Operations.gas.t.sol:AllowancePositionManager_Gas_Tests
[PASS] test_approveWithdraw() (gas: 73912)
[PASS] test_approveWithdrawWithSig() (gas: 239391)
[PASS] test_borrowOnBehalfOf() (gas: 767362)
[PASS] test_borrowOnBehalfOf_WithTemporaryDelegateCredit() (gas: 510352)
[PASS] test_creditDelegation() (gas: 73879)
[PASS] test_creditDelegationWithSig() (gas: 239272)
[PASS] test_renounceCreditDelegation() (gas: 98594)
[PASS] test_renounceWithdrawAllowance() (gas: 98612)
[PASS] test_temporaryApproveWithdraw() (gas: 49540)
[PASS] test_temporaryDelegateCredit() (gas: 49539)
[PASS] test_withdrawOnBehalfOf() (gas: 594048)
[PASS] test_withdrawOnBehalfOf_WithTemporaryWithdrawAllowance() (gas: 259849)
Suite result: ok. 12 passed; 0 failed; 0 skipped; finished in 42.05ms (7.10ms CPU time)

Ran 11 tests for tests/gas/PositionManagers.Operations.gas.t.sol:PositionConfigPositionManager_Gas_Tests
[PASS] test_renounceGlobalPermission() (gas: 95825)
[PASS] test_renounceUserDynamicConfigPermission() (gas: 95846)
[PASS] test_renounceUserRiskPremiumPermission() (gas: 95848)
[PASS] test_renounceUsingAsCollateralPermission() (gas: 95781)
[PASS] test_setGlobalPermission() (gas: 71610)
[PASS] test_setUserDynamicConfigPermission() (gas: 71557)
[PASS] test_setUserRiskPremiumPermission() (gas: 71604)
[PASS] test_setUsingAsCollateralOnBehalfOf_fuzz_withGlobalPermission() (gas: 146946)
[PASS] test_setUsingAsCollateralPermission() (gas: 71561)
[PASS] test_updateUserDynamicConfigOnBehalfOf_withGlobalPermission() (gas: 122460)
[PASS] test_updateUserRiskPremiumOnBehalfOf_withGlobalPermission() (gas: 715126)
Suite result: ok. 11 passed; 0 failed; 0 skipped; finished in 35.32ms (2.58ms CPU time)

Ran 1 test for tests/gas/PositionManagers.Operations.gas.t.sol:PositionManager_Gas_Tests
[PASS] test_setSelfAsUserPositionManagerWithSig() (gas: 214823)
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 34.86ms (712.45µs CPU time)

Ran 2 tests for tests/gas/PositionManagers.Operations.gas.t.sol:SupplyRepayPositionManager_Gas_Tests
[PASS] test_repayOnBehalfOf() (gas: 929659)
[PASS] test_supplyOnBehalfOf() (gas: 289260)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 35.19ms (1.89ms CPU time)

Ran 6 tests for tests/unit/Hub/Hub.EliminateDeficit.t.sol:HubEliminateDeficitTest
[PASS] test_eliminateDeficit(uint256) (runs: 5000, μ: 656628, ~: 656628)
[PASS] test_eliminateDeficit_allowSpokePaused() (gas: 429180)
[PASS] test_eliminateDeficit_fuzz_revertsWith_ArithmeticUnderflow_CallerSpokeNoFunds(uint256) (runs: 5000, μ: 343306, ~: 343306)
[PASS] test_eliminateDeficit_fuzz_revertsWith_callerSpokeNotActive(address) (runs: 5000, μ: 28908, ~: 28908)
[PASS] test_eliminateDeficit_revertsWith_InvalidAmount_ZeroAmountNoDeficit() (gas: 20068)
[PASS] test_eliminateDeficit_revertsWith_InvalidAmount_ZeroAmountWithDeficit() (gas: 340316)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 17.03s (17.01s CPU time)

Ran 5 tests for tests/unit/Hub/Hub.MintFeeShares.t.sol:HubMintFeeSharesTest
[PASS] test_mintFeeShares() (gas: 312892)
[PASS] test_mintFeeShares_noFees() (gas: 370166)
[PASS] test_mintFeeShares_noShares() (gas: 301138)
[PASS] test_mintFeeShares_revertsWith_AccessManagedUnauthorized() (gas: 25025)
[PASS] test_mintFeeShares_revertsWith_SpokeNotActive() (gas: 245875)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 23.27ms (4.18ms CPU time)

Ran 7 tests for tests/unit/Spoke/Spoke.AccrueInterest.t.sol:SpokeAccrueInterestTest
[PASS] test_accrueInterest_NoActionTaken() (gas: 132063)
[PASS] test_accrueInterest_NoInterest_NoDebt(uint40) (runs: 5000, μ: 638506, ~: 638347)
[PASS] test_accrueInterest_NoInterest_OnlySupply(uint40) (runs: 5000, μ: 252251, ~: 252281)
[PASS] test_accrueInterest_TenPercentRp(uint256,uint40) (runs: 5000, μ: 584318, ~: 584803)
[PASS] test_accrueInterest_fuzz_BorrowAmountAndSkipTime(uint256,uint40) (runs: 5000, μ: 541912, ~: 542197)
[PASS] test_accrueInterest_fuzz_RPBorrowAndSkipTime((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256),uint40) (runs: 5000, μ: 3862080, ~: 3879702)
[PASS] test_accrueInterest_fuzz_RatesRPBorrowAndSkipTime((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256),(uint96,uint96,uint96,uint96),uint40) (runs: 5000, μ: 3930324, ~: 3946698)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 200.06s (200.04s CPU time)

Ran 8 tests for tests/unit/AccessManagerEnumerable.t.sol:AccessManagerEnumerableTest
[PASS] test_getRoleMembers_fuzz(uint256,uint256) (runs: 5000, μ: 1921322, ~: 1920052)
[PASS] test_getRoleTargetFunctions_fuzz(uint256,uint256) (runs: 5000, μ: 1118570, ~: 1117552)
[PASS] test_grantRole() (gas: 239205)
[PASS] test_grantRole_fuzz(uint64,uint256) (runs: 5000, μ: 857743, ~: 851108)
[PASS] test_revokeRole() (gas: 259646)
[PASS] test_setTargetFunctionRole() (gas: 274815)
[PASS] test_setTargetFunctionRole_skipAddToAdminRole() (gas: 29820)
[PASS] test_setTargetFunctionRole_withReplace() (gas: 336391)
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 198.58s (201.46s CPU time)

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

[PASS] test_transferShares_fuzz(uint256,uint256) (runs: 5000, μ: 192235, ~: 192464)
[PASS] test_transferShares_fuzz_revertsWith_underflow_spoke_added_shares_exceeded(uint256) (runs: 5000, μ: 151665, ~: 151383)
[PASS] test_transferShares_revertsWith_AddCapExceeded() (gas: 194958)
[PASS] test_transferShares_revertsWith_SpokeNotActive() (gas: 176511)
[PASS] test_transferShares_revertsWith_SpokePaused() (gas: 178870)
[PASS] test_transferShares_zeroShares_revertsWith_InvalidShares() (gas: 22457)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 7.68s (7.65s CPU time)

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

[PASS] test_sweep_does_not_impact_utilization(uint256,uint256) (runs: 5000, μ: 635287, ~: 636683)
[PASS] test_sweep_fuzz(uint256,uint256) (runs: 5000, μ: 486886, ~: 486892)
[PASS] test_sweep_revertsWith_AssetNotListed() (gas: 12406)
[PASS] test_sweep_revertsWith_InsufficientLiquidity() (gas: 222313)
[PASS] test_sweep_revertsWith_InvalidAmount() (gas: 104209)
[PASS] test_sweep_revertsWith_OnlyReinvestmentController(address) (runs: 5000, μ: 94702, ~: 94702)
[PASS] test_sweep_revertsWith_OnlyReinvestmentController_init() (gas: 40016)
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 26.73s (36.58s 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, μ: 540242, ~: 540423)
[PASS] test_accrueLiquidityFee_fuzz_maxLiquidityFee_with_premium_multiple_users(uint256,uint256,uint256,uint256,uint256) (runs: 5000, μ: 791586, ~: 791636)
[PASS] test_accrueLiquidityFee_maxLiquidityFee_multi_spoke() (gas: 647619185)
[PASS] test_accrueLiquidityFee_maxLiquidityFee_multi_user() (gas: 260580011)
[PASS] test_accrueLiquidityFee_maxLiquidityFee_with_premium() (gas: 540591)
Logs:
  Bound result 500000000000000000000
  Bound result 5000
  Bound result 34560000
  Bound result 2

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

Ran 11 tests for tests/unit/position-managers/SignatureGateway/SignatureGateway.t.sol:SignatureGatewayTest
[PASS] test_borrowWithSig() (gas: 792728)
[PASS] test_renouncePositionManagerRole() (gas: 26851)
[PASS] test_renouncePositionManagerRole_revertsWith_OnlyOwner() (gas: 18352)
[PASS] test_repayWithSig() (gas: 794049)
[PASS] test_setSelfAsUserPositionManagerWithSig() (gas: 298104)
[PASS] test_setUsingAsCollateralWithSig() (gas: 613309)
[PASS] test_supplyWithSig() (gas: 584522)
[PASS] test_updateUserDynamicConfigWithSig() (gas: 310881)
[PASS] test_updateUserRiskPremiumWithSig() (gas: 880672)
[PASS] test_useNonce_monotonic(bytes32) (runs: 5000, μ: 13899, ~: 13899)
[PASS] test_withdrawWithSig() (gas: 585126)
Suite result: ok. 11 passed; 0 failed; 0 skipped; finished in 219.98s (219.96s CPU time)

Ran 6 tests for tests/unit/Hub/HubAccrueInterest.t.sol:HubAccrueInterestTest
[PASS] test_accrueInterest_NoActionTaken() (gas: 43656)
[PASS] test_accrueInterest_NoInterest_NoDebt(uint40) (runs: 5000, μ: 401944, ~: 401854)
[PASS] test_accrueInterest_NoInterest_OnlyAdd(uint40) (runs: 5000, μ: 210912, ~: 210858)
[PASS] test_accrueInterest_fuzz_BorrowAmountAndElapsed(uint256,uint40) (runs: 5000, μ: 276624, ~: 276266)
[PASS] test_accrueInterest_fuzz_BorrowAmountRateAndElapsed(uint256,uint256,uint40) (runs: 5000, μ: 402350, ~: 402132)
[PASS] test_accrueInterest_fuzz_BorrowAndWait(uint40) (runs: 5000, μ: 275373, ~: 275283)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 27.04s (41.53s CPU time)

Ran 7 tests for tests/unit/Spoke/Spoke.AccrueLiquidityFee.t.sol:SpokeAccrueLiquidityFeeTest
[PASS] test_accrueLiquidityFee() (gas: 880876)
[PASS] test_accrueLiquidityFee_NoActionTaken() (gas: 120065)
[PASS] test_accrueLiquidityFee_NoInterest_OnlySupply(uint40) (runs: 5000, μ: 247276, ~: 247256)
[PASS] test_accrueLiquidityFee_exact() (gas: 887419)
[PASS] test_accrueLiquidityFee_fuzz_BorrowAmountAndSkipTime(uint256,uint40) (runs: 5000, μ: 957904, ~: 980335)
[PASS] test_accrueLiquidityFee_maxLiquidityFee() (gas: 546465)
[PASS] test_accrueLiquidityFee_setUsingAsCollateral() (gas: 900263)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 20.92s (38.31s CPU time)

Ran 1 test for tests/unit/Spoke/Spoke.MultipleHub.IsolationMode.t.sol:SpokeMultipleHubIsolationModeTest
[PASS] test_isolation_mode() (gas: 1443256)
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 9.81ms (2.50ms CPU time)

Ran 1 test for tests/unit/Spoke/Spoke.MultipleHub.SiloedBorrowing.t.sol:SpokeMultipleHubSiloedBorrowingTest
[PASS] test_siloed_borrowing() (gas: 667131)
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 8.23ms (1.15ms CPU time)

Ran 2 tests for tests/unit/Spoke/Spoke.MultipleHub.t.sol:SpokeMultipleHubTest
[PASS] test_borrow_secondHub() (gas: 895549)
[PASS] test_borrow_thirdHub() (gas: 737841)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 27.69ms (3.74ms CPU time)

Ran 13 tests for tests/gas/Spoke.Operations.gas.t.sol:SpokeOperations_Gas_Tests
[PASS] test_borrow() (gas: 1335928)
[PASS] test_liquidation_full() (gas: 1891814)
[PASS] test_liquidation_partial() (gas: 1891523)
[PASS] test_liquidation_receiveShares_full() (gas: 1881508)
[PASS] test_liquidation_receiveShares_partial() (gas: 1881225)
[PASS] test_multicall_ops() (gas: 1410878)
[PASS] test_repay() (gas: 875638)
[PASS] test_setUserPositionManagerWithSig() (gas: 303733)
[PASS] test_supply() (gas: 542220)
[PASS] test_updateRiskPremium() (gas: 1327300)
[PASS] test_updateUserDynamicConfig() (gas: 581796)
[PASS] test_usingAsCollateral() (gas: 1481373)
[PASS] test_withdraw() (gas: 1962523)
Suite result: ok. 13 passed; 0 failed; 0 skipped; finished in 65.18ms (30.93ms CPU time)

Ran 13 tests for tests/gas/Spoke.Operations.gas.t.sol:SpokeOperations_ZeroRiskPremium_Gas_Tests
[PASS] test_borrow() (gas: 1096592)
[PASS] test_liquidation_full() (gas: 1754099)
[PASS] test_liquidation_partial() (gas: 1753808)
[PASS] test_liquidation_receiveShares_full() (gas: 1743793)
[PASS] test_liquidation_receiveShares_partial() (gas: 1743510)
[PASS] test_multicall_ops() (gas: 1327357)
[PASS] test_repay() (gas: 783166)
[PASS] test_setUserPositionManagerWithSig() (gas: 308181)
[PASS] test_supply() (gas: 544892)
[PASS] test_updateRiskPremium() (gas: 942460)
[PASS] test_updateUserDynamicConfig() (gas: 586244)
[PASS] test_usingAsCollateral() (gas: 1087205)
[PASS] test_withdraw() (gas: 1593456)
Suite result: ok. 13 passed; 0 failed; 0 skipped; finished in 62.17ms (26.88ms CPU time)

Ran 4 tests for tests/unit/Spoke/Spoke.PermitReserve.t.sol:SpokePermitReserveTest
[PASS] test_permitReserve() (gas: 89200)
[PASS] test_permitReserve_forwards_correct_call() (gas: 36410)
[PASS] test_permitReserve_ignores_permit_reverts() (gas: 25167)
[PASS] test_permitReserve_revertsWith_ReserveNotListedIn() (gas: 23207)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 20.01ms (1.11ms CPU time)

Ran 12 tests for tests/unit/Spoke/Spoke.PositionManager.t.sol:SpokePositionManagerTest
[PASS] test_disableApproval_on_InactivePositionManager() (gas: 99880)
[PASS] test_onlyPositionManager_on_borrow() (gas: 536818)
[PASS] test_onlyPositionManager_on_repay() (gas: 561679)
[PASS] test_onlyPositionManager_on_supply() (gas: 290708)
[PASS] test_onlyPositionManager_on_updateUserDynamicConfig() (gas: 1279605)
[PASS] test_onlyPositionManager_on_updateUserRiskPremium() (gas: 1409880)
[PASS] test_onlyPositionManager_on_usingAsCollateral() (gas: 143048)
[PASS] test_onlyPositionManager_on_withdraw() (gas: 320913)
[PASS] test_renouncePositionManagerRole() (gas: 20039)
[PASS] test_renouncePositionManagerRole_noop_from_disabled() (gas: 21345)
[PASS] test_setApprovalForPositionManager(bytes32) (runs: 5000, μ: 19880, ~: 19880)
[PASS] test_setApproval_revertsWith_InactivePositionManager() (gas: 20176)
Suite result: ok. 12 passed; 0 failed; 0 skipped; finished in 448.94ms (427.33ms 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, μ: 695309, ~: 695153)
[PASS] test_repay_less_than_share() (gas: 584163)
[PASS] test_repay_only_base_debt_interest() (gas: 757312)
[PASS] test_repay_only_base_debt_no_premium() (gas: 641179)
[PASS] test_repay_supply_ex_rate_decr() (gas: 1483810)
[PASS] test_repay_supply_ex_rate_decr_skip_time() (gas: 1481138)
[PASS] test_repay_zero_shares_nonzero_premium_debt() (gas: 761319)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 15.58s (15.56s CPU time)

Ran 21 tests for tests/unit/Spoke/Spoke.DynamicConfig.t.sol:SpokeDynamicConfigTest
[PASS] test_addDynamicReserveConfig() (gas: 80458)
[PASS] test_addDynamicReserveConfig_fuzz_revertsWith_InvalidCollateralFactorAndMaxLiquidationBonus_incompatible(uint16,uint32) (runs: 5000, μ: 47202, ~: 47371)
[PASS] test_addDynamicReserveConfig_once() (gas: 521068)
[PASS] test_addDynamicReserveConfig_revertsWith_AccessManagedUnauthorized(address) (runs: 5000, μ: 44502, ~: 44504)
[PASS] test_addDynamicReserveConfig_revertsWith_InvalidCollateralFactorAndMaxLiquidationBonus_collateralFactor() (gas: 58724)
[PASS] test_addDynamicReserveConfig_revertsWith_InvalidCollateralFactorAndMaxLiquidationBonus_liquidationBonus() (gas: 41321)
[PASS] test_addDynamicReserveConfig_revertsWith_InvalidLiquidationFee() (gas: 41784)
[PASS] test_addDynamicReserveConfig_revertsWith_MaximumDynamicConfigKeyReached() (gas: 44375)
[PASS] test_addDynamicReserveConfig_revertsWith_ReserveNotListed() (gas: 28943)
[PASS] test_fuzz_addDynamicReserveConfig_spaced_dup_updates(bytes32) (runs: 5000, μ: 141885, ~: 141885)
[PASS] test_fuzz_addDynamicReserveConfig_trailing_order(bytes32) (runs: 5000, μ: 135957, ~: 135957)
[PASS] test_offboardReserve_existing_borrows_remain_unaffected() (gas: 1137597)
[PASS] test_updateDynamicReserveConfig() (gas: 1739770)
[PASS] test_updateDynamicReserveConfig_fuzz_revertsWith_InvalidCollateralFactorAndMaxLiquidationBonus(uint16,uint32) (runs: 5000, μ: 58036, ~: 58205)
[PASS] test_updateDynamicReserveConfig_revertsWith_AccessManagedUnauthorized(address) (runs: 5000, μ: 44481, ~: 44483)
[PASS] test_updateDynamicReserveConfig_revertsWith_ConfigKeyUninitialized() (gas: 50000)
[PASS] test_updateDynamicReserveConfig_revertsWith_InvalidCollateralFactor() (gas: 51154)
[PASS] test_updateDynamicReserveConfig_revertsWith_InvalidCollateralFactorAndMaxLiquidationBonus_collateralFactor() (gas: 51929)
[PASS] test_updateDynamicReserveConfig_revertsWith_InvalidCollateralFactorAndMaxLiquidationBonus_liquidationBonus() (gas: 52088)
[PASS] test_updateDynamicReserveConfig_revertsWith_InvalidLiquidationFee() (gas: 52615)
[PASS] test_updateDynamicReserveConfig_revertsWith_ReserveNotListed() (gas: 29255)
Suite result: ok. 21 passed; 0 failed; 0 skipped; finished in 8.89s (8.87s CPU time)

Ran 5 tests for tests/gas/Spoke.Getters.gas.t.sol:SpokeGetters_Gas_Tests
[PASS] test_getUserAccountData() (gas: 22583)
[PASS] test_getUserAccountData_oneSupplies() (gas: 283401)
[PASS] test_getUserAccountData_twoSupplies() (gas: 518556)
[PASS] test_getUserAccountData_twoSupplies_oneBorrows() (gas: 1042914)
[PASS] test_getUserAccountData_twoSupplies_twoBorrows() (gas: 1604916)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 38.92ms (4.75ms 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, μ: 2036672, ~: 1836861)
[PASS] test_collateralCount_ignoresInvalidBits() (gas: 124482)
[PASS] test_constants() (gas: 44966)
[PASS] test_fls() (gas: 545261)
[PASS] test_fromBitId(uint256,uint256) (runs: 5000, μ: 14161, ~: 14452)
[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: 109180)
[PASS] test_isUsingAsCollateralOrBorrowing_slot1() (gas: 44203)
[PASS] test_isolateBorrowing(uint256) (runs: 5000, μ: 162282, ~: 162282)
[PASS] test_isolateBorrowingUntil(uint256,uint256) (runs: 5000, μ: 153507, ~: 153033)
[PASS] test_isolateCollateral(uint256) (runs: 5000, μ: 162044, ~: 162044)
[PASS] test_isolateCollateralUntil(uint256,uint256) (runs: 5000, μ: 153486, ~: 153012)
[PASS] test_isolateUntil(uint256,uint256) (runs: 5000, μ: 143593, ~: 143583)
[PASS] test_next(uint256) (runs: 5000, μ: 20224, ~: 19157)
[PASS] test_nextBorrowing(uint256) (runs: 5000, μ: 18201, ~: 18289)
[PASS] test_nextBorrowing_continuous() (gas: 63845326)
[PASS] test_nextCollateral(uint256) (runs: 5000, μ: 17934, ~: 17116)
[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 99.47s (99.46s CPU time)

Ran 34 tests for tests/unit/position-managers/PositionConfigPositionManager.t.sol:PositionConfigPositionManagerTest
[PASS] test_renounceGlobalPermission() (gas: 42892)
[PASS] test_renounceGlobalPermission_revertsWith_SpokeNotRegistered() (gas: 17627)
[PASS] test_renounceUserDynamicConfigPermission() (gas: 41532)
[PASS] test_renounceUserDynamicConfigPermission_revertsWith_SpokeNotRegistered() (gas: 17757)
[PASS] test_renounceUserRiskPremiumPermission() (gas: 41568)
[PASS] test_renounceUserRiskPremiumPermission_revertsWith_SpokeNotRegistered() (gas: 17628)
[PASS] test_renounceUsingAsCollateralPermission() (gas: 41505)
[PASS] test_renounceUsingAsCollateralPermission_revertsWith_SpokeNotRegistered() (gas: 17693)
[PASS] test_setGlobalPermission() (gas: 56206)
[PASS] test_setGlobalPermission_fuzz(bool) (runs: 5000, μ: 38309, ~: 24641)
[PASS] test_setGlobalPermission_removeAllPermissions() (gas: 43048)
[PASS] test_setGlobalPermission_removePreviousPermissions() (gas: 47222)
[PASS] test_setGlobalPermission_revertsWith_SpokeNotRegistered() (gas: 17829)
[PASS] test_setUserDynamicConfigPermission() (gas: 54323)
[PASS] test_setUserDynamicConfigPermission_remove() (gas: 41689)
[PASS] test_setUserDynamicConfigPermission_revertsWith_SpokeNotRegistered() (gas: 17784)
[PASS] test_setUserRiskPremiumPermission() (gas: 54304)
[PASS] test_setUserRiskPremiumPermission_remove() (gas: 41710)
[PASS] test_setUserRiskPremiumPermission_revertsWith_SpokeNotRegistered() (gas: 17828)
[PASS] test_setUsingAsCollateralOnBehalfOf_fuzz_withGlobalPermission(uint256,bool) (runs: 5000, μ: 103913, ~: 108894)
[PASS] test_setUsingAsCollateralOnBehalfOf_fuzz_withPermission(uint256,bool) (runs: 5000, μ: 103870, ~: 108851)
[PASS] test_setUsingAsCollateralOnBehalfOf_revertsWith_CallerNotAllowed() (gas: 22561)
[PASS] test_setUsingAsCollateralOnBehalfOf_revertsWith_SpokeNotRegistered() (gas: 17877)
[PASS] test_setUsingAsCollateralPermission() (gas: 54271)
[PASS] test_setUsingAsCollateralPermission_remove() (gas: 41648)
[PASS] test_setUsingAsCollateralPermission_revertsWith_SpokeNotRegistered() (gas: 17786)
[PASS] test_updateUserDynamicConfigOnBehalfOf_revertsWith_CallerNotAllowed() (gas: 20113)
[PASS] test_updateUserDynamicConfigOnBehalfOf_revertsWith_SpokeNotRegistered() (gas: 17715)
[PASS] test_updateUserDynamicConfigOnBehalfOf_withGlobalPermission() (gas: 69242)
[PASS] test_updateUserDynamicConfigOnBehalfOf_withPermission() (gas: 69240)
[PASS] test_updateUserRiskPremiumOnBehalfOf_revertsWith_CallerNotAllowed() (gas: 20180)
[PASS] test_updateUserRiskPremiumOnBehalfOf_revertsWith_SpokeNotRegistered() (gas: 17738)
[PASS] test_updateUserRiskPremiumOnBehalfOf_withGlobalPermission() (gas: 682814)
[PASS] test_updateUserRiskPremiumOnBehalfOf_withPermission() (gas: 682836)
Suite result: ok. 34 passed; 0 failed; 0 skipped; finished in 109.59s (109.57s CPU time)

Ran 5 tests for tests/unit/Rescuable.t.sol:RescuableTest
[PASS] test_constructor() (gas: 12654)
[PASS] test_rescueNative_fuzz(uint256) (runs: 5000, μ: 33716, ~: 33899)
[PASS] test_rescueNative_revertsWith_OnlyRescueGuardian() (gas: 11400)
[PASS] test_rescueToken_fuzz(uint256) (runs: 5000, μ: 209646, ~: 209774)
[PASS] test_rescueToken_revertsWith_OnlyRescueGuardian() (gas: 183215)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 3.33s (6.28s CPU time)

Ran 10 tests for tests/unit/position-managers/SignatureGateway/SignatureGateway.Constants.t.sol:SignatureGatewayConstantsTest
[PASS] test_DOMAIN_SEPARATOR() (gas: 2049139)
[PASS] test_borrow_typeHash() (gas: 9874)
[PASS] test_constructor() (gas: 53326)
[PASS] test_eip712Domain() (gas: 2054726)
[PASS] test_repay_typeHash() (gas: 9975)
[PASS] test_setUsingAsCollateral_typeHash() (gas: 9943)
[PASS] test_supply_typeHash() (gas: 9945)
[PASS] test_updateUserDynamicConfig_typeHash() (gas: 9915)
[PASS] test_updateUserRiskPremium_typeHash() (gas: 9876)
[PASS] test_withdraw_typeHash() (gas: 9919)
Suite result: ok. 10 passed; 0 failed; 0 skipped; finished in 21.82ms (2.05ms CPU time)

Ran 5 tests for tests/unit/position-managers/SignatureGateway/SignatureGateway.PermitReserve.t.sol:SignatureGatewayPermitReserveTest
[PASS] test_permitReserve() (gas: 103953)
[PASS] test_permitReserve_forwards_correct_call() (gas: 51093)
[PASS] test_permitReserve_ignores_permit_reverts() (gas: 39973)
[PASS] test_permitReserve_revertsWith_ReserveNotListed() (gas: 30938)
[PASS] test_permitReserve_revertsWith_SpokeNotRegistered() (gas: 29497)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 21.09ms (1.41ms CPU time)

Ran 8 tests for tests/unit/ReserveFlags.t.sol:ReserveFlagsTests
[PASS] test_constants() (gas: 13620)
[PASS] test_create_fuzz(bool,bool,bool,bool,bool) (runs: 5000, μ: 16485, ~: 16492)
[PASS] test_setBorrowable_fuzz(uint8) (runs: 5000, μ: 13414, ~: 13414)
[PASS] test_setFrozen_fuzz(uint8) (runs: 5000, μ: 13422, ~: 13422)
[PASS] test_setLiquidatable_fuzz(uint8) (runs: 5000, μ: 13422, ~: 13422)
[PASS] test_setPaused_fuzz(uint8) (runs: 5000, μ: 13297, ~: 13297)
[PASS] test_setReceiveSharesEnabled_fuzz(uint8) (runs: 5000, μ: 13405, ~: 13405)
[PASS] test_set_flags() (gas: 95757)
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 1.66s (2.18s CPU time)

Ran 2 tests for tests/unit/position-managers/SignatureGateway/SignatureGateway.Reverts.InsufficientAllowance.t.sol:SignatureGateway_InsufficientAllowance_Test
[PASS] test_repayWithSig_revertsWith_ERC20InsufficientAllowance() (gas: 455775)
[PASS] test_supplyWithSig_revertsWith_ERC20InsufficientAllowance() (gas: 84051)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 23.80ms (3.63ms CPU time)

Ran 10 tests for tests/unit/Spoke/Spoke.DynamicConfig.Triggers.t.sol:SpokeDynamicConfigTriggersTest
[PASS] test_borrow_triggers_dynamicConfigUpdate() (gas: 1317147)
[PASS] test_liqui...*[Comment body truncated]*

Comment on lines 37 to 39
/// @dev keccak256('temporary.withdrawAllowances')
bytes32 private constant _TEMPORARY_WITHDRAW_ALLOWANCES_SLOT =
0x1c6a61279a13a86a789311ddf30aee38e2f4a9f6c4aad1ff4a2e75a4018e68c3;
Copy link
Member

Choose a reason for hiding this comment

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

-1 & ~0ff for collision resistance :gigachad:

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As discussed, I'm not convinced what values these bring. Curious to understand other's thoughts as well

Copy link
Member

Choose a reason for hiding this comment

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

they bring collision resistance from potentially using this slot (which we clearly don't here) & are generally considered best practice

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we do -1 & ~0xff everywhere, these measures do not bring any value: we will still have a collision if same string is used.

Copy link
Member

Choose a reason for hiding this comment

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

why would we do it everywhere? we just it exceptionally here

Copy link
Member

Choose a reason for hiding this comment

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

the idea of this was not a best practice to use strings + mappings, its just to bring additional randomness on slot derivation

Copy link
Contributor Author

Choose a reason for hiding this comment

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

why would we do it everywhere?

if we follow this pattern (-1 & ~0xff) everywhere, then collisions are still guaranteed when the same underlying string is used.

its just to bring additional randomness on slot derivation

additional randomness relative to what?

Copy link
Member

Choose a reason for hiding this comment

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

to potentially using a string for slot derivation, we dont know but its just good practice.
'if we follow this pattern (-1 & ~0xff) everywhere' ==> see we wouldn't use it everywhere, just here
oz also does

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@avniculae avniculae force-pushed the feat/posm-temporary-approvals branch from 29fda38 to 6ee2b26 Compare December 15, 2025 12:59
"AllowancePositionManager: renounceWithdrawAllowance": "24989",
"AllowancePositionManager: withdrawOnBehalfOf: full": "123488",
"AllowancePositionManager: withdrawOnBehalfOf: partial": "134160",
"AllowancePositionManager: approveWithdraw": "46858",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can easily add gas snapshots for temporary approvals, but how to properly test gas usage of borrowOnBehalfOf and withdrawOnBehalfOf, while temporary approvals are in place. Challenge is that we are in isolate mode, there are not cheatcodes for transient storage manipulation, and we don't want the temporary approval to count towards the gas consumed by consumer functions. Only solution I see is: create a bundle function in the wrapper, measure bundle fn gas, measure approve fn gas, and then subtract the two. Any suggestions?

Copy link
Member

Choose a reason for hiding this comment

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

wrapper can call vm.snapshotGasLastCall, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm not sure it works. if vm.snapshotGasLastCall works correctly for this purpose, it must not consider the temporaryApprove call. If it does not consider it, borrow/withdraw will fail (since transient storage is cleared).

Copy link
Member

@DhairyaSethi DhairyaSethi Dec 15, 2025

Choose a reason for hiding this comment

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

for the wrapper tempApprove & consumeAllowance are 2 ext calls, if snapshotGasLastCall considers what's inside its context this would work but could be wrong here

Copy link
Member

Choose a reason for hiding this comment

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

if not then we could do run this test w isolate=false and manually vm.cold() targets but this is more error prone; thinking more but probably subtract from cumulative usage is a good enough estimate

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah ended up doing the last suggestion as well 26743fa. Not sure if cooling is necessary

Copy link
Member

Choose a reason for hiding this comment

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

cooling is very necessary otherwise loading the target for eth_call (of consumeAllowance) is warm

Copy link
Contributor Author

Choose a reason for hiding this comment

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

if temporary approval is active, then it must have happened in the same tx, so not cooling might make sense here

@avniculae avniculae marked this pull request as ready for review December 15, 2025 13:17
Comment on lines 185 to 191
/// forge-config: default.isolate = true
function test_temporaryApproveWithdraw_TransientStorage() public {
// make sure transient storage is used for temporary withdraw allowances
vm.prank(alice);
positionManager.temporaryApproveWithdraw(bob, _daiReserveId(spoke), 100e18);
assertEq(positionManager.temporaryWithdrawAllowance(alice, bob, _daiReserveId(spoke)), 0);
}
Copy link
Member

@DhairyaSethi DhairyaSethi Dec 15, 2025

Choose a reason for hiding this comment

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

another way to test this would be using vm.accesses() - assertEq(writes.length, 0);

@avniculae avniculae force-pushed the feat/posm-temporary-approvals branch from 68b4195 to 6e766f6 Compare December 18, 2025 11:38
@avniculae avniculae requested a review from Kogaroshi December 19, 2025 18:09
Copy link
Contributor

Choose a reason for hiding this comment

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

nice addition

Copy link
Contributor

@Kogaroshi Kogaroshi left a comment

Choose a reason for hiding this comment

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

lgtm

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