Skip to content

Conversation

@DhairyaSethi
Copy link
Member

@DhairyaSethi DhairyaSethi commented Nov 26, 2025

Implements ERC4626 vault to tokenise hub positions. Share price is maintained by the hub, fee-less accounting. Only acts as a proxy to tokenise supply-only positions.

@Kogaroshi
Copy link
Contributor

I'd say <action>WithSig to be consistent with V3 version.
As for Multicall + permitAsset, could be useful I think, we could have fully gas sponsored deposits for users with those 2.

Also maybe let's keep virtual on all methods of VaultSpoke.sol so we can use this base for variants ?

}

/// @inheritdoc IERC20Permit
function permit(
Copy link
Member Author

@DhairyaSethi DhairyaSethi Dec 1, 2025

Choose a reason for hiding this comment

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

reviewer note: this is permit for vault share token, depositWithPermit consumes permit for the underlying token
also // we re-reimplement permit & nonces(address) instead of inheriting https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v5.4.0/contracts/token/ERC20/extensions/ERC20PermitUpgradeable.sol directly to reuse NoncesKeyed & not have duplicate logic for EIP712


/// @title IVaultSpoke
/// @author Aave Labs
interface IVaultSpoke is IERC4626, IERC2612 {
Copy link
Member Author

Choose a reason for hiding this comment

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

reviewer-note: we do not inherit oz's 4626 impl bc we end up overriding every single fn except preview*'s

Comment on lines 209 to 211
function previewDeposit(uint256 assets) public view virtual returns (uint256) {
return hub().previewAddByAssets(assetId(), assets);
}
Copy link
Member Author

@DhairyaSethi DhairyaSethi Dec 1, 2025

Choose a reason for hiding this comment

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

review-note: ATokenVault min's this with maxDeposit but that is omitted here to more accurate with the spec

Image

Copy link
Member Author

Choose a reason for hiding this comment

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

@github-actions
Copy link

github-actions bot commented Dec 2, 2025

Forge Build Sizes

🔕 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
Constants 447 499 24,129 48,653
ECDSA 44 94 24,532 49,058
EIP712Hash 691 743 23,885 48,409
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
GatewayBaseWrapper 1,810 2,085 22,766 47,067
Hub 21,598 21,832 2,978 27,320
HubConfigurator 9,981 10,254 14,595 38,898
JsonBindings 12,035 12,087 12,541 37,065
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 4,889 5,306 19,687 43,846
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
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,913 10,424 14,663 38,728
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
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
VaultSpokeInstance 11,311 12,575 13,265 36,577
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 2, 2025

♻️ Forge Gas Snapshots

Path Value
snapshots/VaultSpoke.Operations.json
deposit 117356
depositWithSig 151404
mint 117438
mintWithSig 151540
permit 63205
redeem: on behalf, full 98149
redeem: on behalf, partial 122149
redeem: self, full 97291
redeem: self, partial 116491
redeemWithSig 149844
withdraw: on behalf, full 98259
withdraw: on behalf, partial 122259
withdraw: self, full 97401
withdraw: self, partial 116601
withdrawWithSig 149898
🔕 Unchanged
Path Value
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,316
repayNative 168,024
supplyAsCollateralNative 160,373
supplyNative 136,476
withdrawNative: full 125,620
withdrawNative: partial 136,825
snapshots/SignatureGateway.Operations.json
borrowWithSig 215,605
repayWithSig 188,872
setSelfAsUserPositionManagerWithSig 75,402
setUsingAsCollateralWithSig 85,053
supplyWithSig 153,205
updateUserDynamicConfigWithSig 62,769
updateUserRiskPremiumWithSig 61,579
withdrawWithSig 131,696
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

@github-actions
Copy link

github-actions bot commented Dec 2, 2025

🌈 Test Results
No files changed, compilation skipped

Ran 5 tests for tests/unit/Spoke/Spoke.SetUsingAsCollateral.t.sol:SpokeConfigTest
[PASS] test_setUsingAsCollateral() (gas: 313675)
[PASS] test_setUsingAsCollateral_collateralStatusUnchanged() (gas: 454124)
[PASS] test_setUsingAsCollateral_revertsWith_ReserveFrozen() (gas: 105264)
[PASS] test_setUsingAsCollateral_revertsWith_ReserveNotListed() (gas: 21986)
[PASS] test_setUsingAsCollateral_revertsWith_ReservePaused() (gas: 64656)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 47.27ms (4.64ms CPU time)

Ran 12 tests for tests/unit/misc/EIP712Hash.t.sol:EIP712HashTest
[PASS] test_constants() (gas: 7415)
[PASS] test_hash_borrow_fuzz((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 4645, ~: 4645)
[PASS] test_hash_repay_fuzz((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 4601, ~: 4601)
[PASS] test_hash_setUsingAsCollateral_fuzz((address,uint256,bool,address,uint256,uint256)) (runs: 5000, μ: 4859, ~: 4859)
[PASS] test_hash_supply_fuzz((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 4689, ~: 4689)
[PASS] test_hash_updateUserDynamicConfig_fuzz((address,address,uint256,uint256)) (runs: 5000, μ: 4409, ~: 4409)
[PASS] test_hash_updateUserRiskPremium_fuzz((address,address,uint256,uint256)) (runs: 5000, μ: 4452, ~: 4452)
[PASS] test_hash_vaultDeposit_fuzz((address,uint256,address,uint256,uint256)) (runs: 5000, μ: 4570, ~: 4570)
[PASS] test_hash_vaultMint_fuzz((address,uint256,address,uint256,uint256)) (runs: 5000, μ: 4503, ~: 4503)
[PASS] test_hash_vaultRedeem_fuzz((address,uint256,address,uint256,uint256)) (runs: 5000, μ: 4547, ~: 4547)
[PASS] test_hash_vaultWithdraw_fuzz((address,uint256,address,uint256,uint256)) (runs: 5000, μ: 4590, ~: 4590)
[PASS] test_hash_withdraw_fuzz((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 4667, ~: 4667)
Suite result: ok. 12 passed; 0 failed; 0 skipped; finished in 1.60s (1.60s CPU time)

Ran 8 tests for tests/unit/misc/GatewayBase.t.sol:GatewayBaseTest
[PASS] test_constructor() (gas: 17646)
[PASS] test_registerSpoke_fuzz(address) (runs: 5000, μ: 42033, ~: 42033)
[PASS] test_registerSpoke_revertsWith_InvalidAddress() (gas: 13345)
[PASS] test_registerSpoke_revertsWith_OwnableUnauthorizedAccount() (gas: 14077)
[PASS] test_registerSpoke_unregister() (gas: 36599)
[PASS] test_renouncePositionManagerRole() (gas: 65281)
[PASS] test_renouncePositionManagerRole_revertsWith_InvalidAddress() (gas: 76695)
[PASS] test_renouncePositionManagerRole_revertsWith_OwnableUnauthorizedAccount() (gas: 76856)
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 369.16ms (348.72ms CPU time)

Ran 5 tests for tests/gas/Gateways.Operations.gas.t.sol:NativeTokenGateway_Gas_Tests
[PASS] test_borrowNative() (gas: 921551)
[PASS] test_repayNative() (gas: 996068)
[PASS] test_supplyAndCollateralNative() (gas: 306548)
[PASS] test_supplyNative() (gas: 288339)
[PASS] test_withdrawNative() (gas: 511014)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 38.90ms (4.61ms 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: 965103)
[PASS] test_setSelfAsUserPositionManagerWithSig() (gas: 208929)
[PASS] test_setUsingAsCollateralWithSig() (gas: 296189)
[PASS] test_supplyWithSig() (gas: 441983)
[PASS] test_updateUserDynamicConfigWithSig() (gas: 145352)
[PASS] test_updateUserRiskPremiumWithSig() (gas: 143046)
[PASS] test_withdrawWithSig() (gas: 418488)
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 43.57ms (8.83ms 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, μ: 444406, ~: 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 2.57s (2.56s 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 37.55ms (4.68ms CPU time)

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

[PASS] test_getLiquidationBonus_fuzz_configured(uint256,uint256,uint16,uint64) (runs: 5000, μ: 93745, ~: 94119)
[PASS] test_getLiquidationBonus_fuzz_notConfigured(uint256,uint256) (runs: 5000, μ: 71394, ~: 71631)
[PASS] test_getLiquidationBonus_notConfigured() (gas: 72663)
Logs:
  Bound result 2
  Bound result 1000000000000000000

[PASS] test_premiumRayGetters() (gas: 1535906)
[PASS] test_protocol_getters() (gas: 284225)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 2.18s (2.16s CPU time)

Ran 4 tests for tests/unit/Spoke/Liquidations/Spoke.LiquidationCall.Dust.t.sol:SpokeLiquidationCallDustTest
[PASS] test_collateralDust_min_debtToTarget() (gas: 7480199)
[PASS] test_debtToCover_exceeds_collateralValue() (gas: 7472779)
[PASS] test_dustColl_allowed() (gas: 7338929)
[PASS] test_dustDebt_allowed() (gas: 7468615)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 46.53ms (20.35ms 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 29.35ms (4.06ms CPU time)

Ran 5 tests for tests/unit/libraries/LiquidationLogic/LiquidationLogic.LiquidateCollateral.t.sol:LiquidationLogicLiquidateCollateralTest
[PASS] test_liquidateCollateral_fuzz(uint256,uint256) (runs: 5000, μ: 268263, ~: 269268)
[PASS] test_liquidateCollateral_fuzz_CollateralToLiquidatorIsZero(uint256) (runs: 5000, μ: 110222, ~: 110942)
[PASS] test_liquidateCollateral_fuzz_receiveShares_sharesToLiquidator(uint256,uint256) (runs: 5000, μ: 754659, ~: 755961)
[PASS] test_liquidateCollateral_fuzz_revertsWith_ArithmeticUnderflow(uint256,uint256) (runs: 5000, μ: 100459, ~: 100270)
[PASS] test_liquidateCollateral_receiveShares_sharesToLiquidatorIsZero() (gas: 741471)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 14.14s (15.53s 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, μ: 57002, ~: 56823)
[PASS] test_calculateLiquidationAmounts_fuzz_EnoughCollateral_NoCollateralDust((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 56011, ~: 56048)
[PASS] test_calculateLiquidationAmounts_fuzz_EnoughCollateral_NoDebtLeft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 72619, ~: 72561)
[PASS] test_calculateLiquidationAmounts_fuzz_InsufficientCollateral((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 59633, ~: 59507)
[PASS] test_calculateLiquidationAmounts_fuzz_revertsWith_MustNotLeaveDust_Collateral((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 56350, ~: 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, μ: 69152, ~: 69098)
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, μ: 17335, ~: 17135)
[PASS] test_calculateLiquidationBonus_fuzz_MaxBonus(uint256,uint256,uint256,uint256) (runs: 5000, μ: 19622, ~: 19420)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 960.01ms (940.05ms 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 21.71ms (1.51ms CPU time)

Ran 27 tests for tests/unit/MathUtils.t.sol:MathUtilsTest
[PASS] test_add_edge_cases() (gas: 4854)
[PASS] test_add_negative_operand(uint256,int256) (runs: 5000, μ: 9236, ~: 8990)
[PASS] test_add_positive_operand(uint256,int256) (runs: 5000, μ: 4015, ~: 4010)
[PASS] test_calculateLinearInterest() (gas: 4445)
[PASS] test_calculateLinearInterest_add_edge() (gas: 5021)
[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, μ: 7703, ~: 7550)
[PASS] test_constants() (gas: 3145)
[PASS] test_fuzz_calculateLinearInterest(uint96,uint40,uint256) (runs: 5000, μ: 8756, ~: 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: 3280)
[PASS] test_mulDivDown_RevertOnDivByZero() (gas: 3125)
[PASS] test_mulDivDown_RevertOnOverflow() (gas: 3181)
[PASS] test_mulDivDown_WithRemainder() (gas: 3325)
[PASS] test_mulDivDown_ZeroAOrB() (gas: 3768)
[PASS] test_mulDivUp_NoRemainder() (gas: 3284)
[PASS] test_mulDivUp_RevertOnDivByZero() (gas: 3102)
[PASS] test_mulDivUp_RevertOnOverflow() (gas: 3249)
[PASS] test_mulDivUp_WithRemainder() (gas: 3283)
[PASS] test_mulDivUp_ZeroAOrB() (gas: 3884)
[PASS] test_signedSub(uint256,uint256) (runs: 5000, μ: 8694, ~: 8639)
[PASS] test_uncheckedAdd(uint256,uint256) (runs: 5000, μ: 3505, ~: 3497)
[PASS] test_uncheckedExp(uint256,uint256) (runs: 5000, μ: 12085, ~: 9422)
[PASS] test_uncheckedSub(uint256,uint256) (runs: 5000, μ: 3435, ~: 3518)
[PASS] test_zeroFloorSub(uint256,uint256) (runs: 5000, μ: 3346, ~: 3311)
Suite result: ok. 27 passed; 0 failed; 0 skipped; finished in 1.76s (1.75s 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: 121412)
[PASS] test_liquidateDebt_revertsWith_InsufficientBalance() (gas: 182249)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 23.26s (23.24s 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.29ms (1.46ms CPU time)

Ran 14 tests for tests/unit/Spoke/Spoke.Supply.t.sol:SpokeSupplyTest
[PASS] test_fuzz_supply_effect_on_ex_rates(uint256,uint256) (runs: 5000, μ: 706410, ~: 707495)
[PASS] test_supply() (gas: 302919)
[PASS] test_supply_does_not_update_risk_premium() (gas: 1651239)
[PASS] test_supply_fuzz_amounts(uint256) (runs: 5000, μ: 430557, ~: 430231)
[PASS] test_supply_fuzz_index_increase_no_premium(uint256,uint256,uint256,uint256) (runs: 5000, μ: 662745, ~: 663030)
[PASS] test_supply_fuzz_index_increase_with_premium(uint256,uint256,uint256,uint256) (runs: 5000, μ: 759261, ~: 759399)
[PASS] test_supply_fuzz_revertsWith_ERC20InsufficientBalance(uint256) (runs: 5000, μ: 62262, ~: 61983)
[PASS] test_supply_index_increase_no_premium() (gas: 864815)
[PASS] test_supply_index_increase_with_premium() (gas: 923445)
[PASS] test_supply_revertsWith_ERC20InsufficientAllowance() (gas: 39737)
[PASS] test_supply_revertsWith_InvalidSupplyAmount() (gas: 41953)
[PASS] test_supply_revertsWith_ReserveFrozen() (gas: 65102)
[PASS] test_supply_revertsWith_ReserveNotListed() (gas: 22091)
[PASS] test_supply_revertsWith_ReservePaused() (gas: 65022)
Suite result: ok. 14 passed; 0 failed; 0 skipped; finished in 50.24s (92.91s CPU time)

Ran 19 tests for tests/unit/Hub/Hub.Add.t.sol:HubAddTest
[PASS] test_add_AddCapReachedButNotExceeded_rounding() (gas: 668631)
[PASS] test_add_fuzz_AddCapReachedButNotExceeded(uint40) (runs: 5000, μ: 160154, ~: 160121)
[PASS] test_add_fuzz_multi_asset_multi_spoke(uint256,uint256,uint256) (runs: 5000, μ: 330235, ~: 330441)
[PASS] test_add_fuzz_revertsWith_AddCapExceeded(uint40) (runs: 5000, μ: 112969, ~: 112936)
[PASS] test_add_fuzz_revertsWith_AddCapExceeded_due_to_interest(uint40,uint256,uint256) (runs: 5000, μ: 271277, ~: 271151)
[PASS] test_add_fuzz_revertsWith_InvalidShares_due_to_index(uint256,uint256,uint256) (runs: 5000, μ: 226807, ~: 227023)
[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, μ: 803086, ~: 803141)
[PASS] test_add_multi_add_minimal_shares() (gas: 322178)
[PASS] test_add_revertsWith_AmountDowncastOverflow() (gas: 365600)
[PASS] test_add_revertsWith_InsufficientTransferred() (gas: 64864)
[PASS] test_add_revertsWith_InvalidAmount() (gas: 13475)
[PASS] test_add_revertsWith_InvalidShares() (gas: 226942)
[PASS] test_add_revertsWith_SharesDowncastOverflow() (gas: 228040)
[PASS] test_add_revertsWith_SpokeNotActive() (gas: 98587)
[PASS] test_add_revertsWith_SpokePaused() (gas: 98704)
[PASS] test_add_single_asset() (gas: 333479)
Logs:
  Bound result 2
  Bound result 100000000000000000000

[PASS] test_add_with_increased_index() (gas: 304921)
[PASS] test_add_with_increased_index_with_premium() (gas: 682005)
Suite result: ok. 19 passed; 0 failed; 0 skipped; finished in 46.88s (46.86s CPU time)

Ran 8 tests for tests/unit/Spoke/Spoke.Upgradeable.t.sol:SpokeUpgradeableTest
[PASS] test_implementation_constructor_fuzz(uint64) (runs: 5000, μ: 5010667, ~: 5010667)
[PASS] test_proxy_constructor_fuzz(uint64) (runs: 5000, μ: 5653678, ~: 5653672)
[PASS] test_proxy_constructor_fuzz_revertsWith_InvalidInitialization(uint64) (runs: 5000, μ: 10634925, ~: 10634919)
[PASS] test_proxy_constructor_revertsWith_InvalidAddress() (gas: 5066857)
[PASS] test_proxy_constructor_revertsWith_InvalidInitialization_ZeroRevision() (gas: 5067062)
[PASS] test_proxy_reinitialization_fuzz(uint64) (runs: 5000, μ: 11551857, ~: 11551844)
[PASS] test_proxy_reinitialization_revertsWith_CallerNotProxyAdmin() (gas: 10604905)
[PASS] test_proxy_reinitialization_revertsWith_InvalidAddress() (gas: 10606623)
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 18.67s (32.77s CPU time)

Ran 6 tests for tests/unit/Spoke/Spoke.UserAccountData.t.sol:SpokeUserAccountDataTest
[PASS] test_userAccountData_scenario1() (gas: 499849)
[PASS] test_userAccountData_scenario2() (gas: 561970)
[PASS] test_userAccountData_scenario3() (gas: 562260)
[PASS] test_userAccountData_scenario4() (gas: 838886)
[PASS] test_userAccountData_scenario5() (gas: 717637)
[PASS] test_userAccountData_scenario6() (gas: 690081)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 26.65ms (4.51ms 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, μ: 15344, ~: 15509)
[PASS] test_percentDivUp_le_value(uint256,uint256) (runs: 5000, μ: 15672, ~: 15662)
[PASS] test_percentDiv_fuzz(uint256,uint256) (runs: 5000, μ: 12865, ~: 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, μ: 15347, ~: 15512)
[PASS] test_percentMul_fuzz(uint256,uint256) (runs: 5000, μ: 11725, ~: 12247)
Suite result: ok. 10 passed; 0 failed; 0 skipped; finished in 1.54s (1.54s 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, μ: 46608, ~: 46938)
[PASS] test_addAsset_fuzz_revertsWith_InvalidAddress_irStrategy(address,uint8,address) (runs: 5000, μ: 46639, ~: 46969)
[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, μ: 47158, ~: 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, μ: 40943, ~: 36219)
[PASS] test_addAsset_revertsWith_BlockTimestampDowncastOverflow() (gas: 767690)
[PASS] test_addAsset_revertsWith_DrawnRateDowncastOverflow() (gas: 764636)
[PASS] test_addAsset_reverts_UnderlyingAlreadyListed() (gas: 47749)
[PASS] test_addSpoke_fuzz(uint256,(uint40,uint40,uint24,bool,bool)) (runs: 5000, μ: 125865, ~: 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, μ: 33334, ~: 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: 728609)
[PASS] test_updateAssetConfig_NewFeeReceiver_revertsWith_SpokeNotActive_noFees() (gas: 622561)
[PASS] test_updateAssetConfig_UseExistingSpokeAndListedAsFeeReceiver_revertsWith_SpokeAlreadyListed() (gas: 72068)
[PASS] test_updateAssetConfig_fuzz(uint256,(address,uint16,address,address)) (runs: 5000, μ: 268851, ~: 269125)
[PASS] test_updateAssetConfig_fuzz_FromZeroLiquidityFee(uint256,uint16) (runs: 5000, μ: 819140, ~: 819047)
[PASS] test_updateAssetConfig_fuzz_LiquidityFee(uint256,uint16) (runs: 5000, μ: 721723, ~: 721630)
[PASS] test_updateAssetConfig_fuzz_NewFeeReceiver(uint256) (runs: 5000, μ: 827893, ~: 827967)
[PASS] test_updateAssetConfig_fuzz_NewInterestRateStrategy(uint256) (runs: 5000, μ: 1205078, ~: 1205152)
[PASS] test_updateAssetConfig_fuzz_ReuseFeeReceiver_revertsWith_SpokeAlreadyListed(uint256) (runs: 5000, μ: 880140, ~: 880214)
[PASS] test_updateAssetConfig_fuzz_Scenario(uint256) (runs: 5000, μ: 680299, ~: 680351)
[PASS] test_updateAssetConfig_fuzz_UseExistingSpokeAsFeeReceiver_revertsWith_SpokeAlreadyListed(uint256) (runs: 5000, μ: 71740, ~: 71740)
[PASS] test_updateAssetConfig_fuzz_revertsWith_InvalidInterestRateStrategy(uint256) (runs: 5000, μ: 59943, ~: 59995)
[PASS] test_updateAssetConfig_fuzz_revertsWith_InvalidLiquidityFee(uint256,(address,uint16,address,address)) (runs: 5000, μ: 40978, ~: 40880)
[PASS] test_updateAssetConfig_fuzz_revertsWith_InvalidReinvestmentController() (gas: 475997)
[PASS] test_updateAssetConfig_fuzz_revertsWith_calculateInterestRateReverts(uint256,(address,uint16,address,address)) (runs: 5000, μ: 202250, ~: 202524)
[PASS] test_updateAssetConfig_fuzz_revertsWith_setInterestRateDataReverts(uint256,(address,uint16,address,address)) (runs: 5000, μ: 65092, ~: 64994)
[PASS] test_updateAssetConfig_oldFeeReceiver_flags() (gas: 843050)
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, μ: 58476, ~: 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 16 tests for tests/unit/Hub/Hub.Draw.t.sol:HubDrawTest
[PASS] test_draw_DifferentSpokes() (gas: 359152)
[PASS] test_draw_fuzz_IncreasedBorrowRate(uint256,uint256) (runs: 5000, μ: 701666, ~: 701658)
[PASS] test_draw_fuzz_amounts_same_block(uint256,uint256) (runs: 5000, μ: 285895, ~: 285848)
[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, μ: 290642, ~: 290903)
[PASS] test_draw_fuzz_revertsWith_InsufficientLiquidity(uint256,uint256) (runs: 5000, μ: 34069, ~: 33863)
[PASS] test_draw_fuzz_revertsWith_InsufficientLiquidity_due_to_draw(uint256) (runs: 5000, μ: 172137, ~: 171853)
[PASS] test_draw_fuzz_revertsWith_InsufficientLiquidity_due_to_remove(uint256) (runs: 5000, μ: 133662, ~: 133462)
[PASS] test_draw_fuzz_revertsWith_InvalidAddress(uint256) (runs: 5000, μ: 15757, ~: 15757)
[PASS] test_draw_revertsWith_DrawCapExceeded_due_to_deficit() (gas: 271293)
[PASS] test_draw_revertsWith_InsufficientLiquidity() (gas: 28097)
[PASS] test_draw_revertsWith_InsufficientLiquidity_due_to_draw() (gas: 168428)
[PASS] test_draw_revertsWith_InsufficientLiquidity_due_to_remove() (gas: 130769)
[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.49s (24.47s CPU time)

Ran 6 tests for tests/unit/Hub/Hub.EliminateDeficit.t.sol:HubEliminateDeficitTest
[PASS] test_eliminateDeficit(uint256) (runs: 5000, μ: 647081, ~: 647081)
[PASS] test_eliminateDeficit_allowSpokePaused() (gas: 422815)
[PASS] test_eliminateDeficit_fuzz_revertsWith_ArithmeticUnderflow_CallerSpokeNoFunds(uint256) (runs: 5000, μ: 340122, ~: 340122)
[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: 337132)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 16.86s (16.84s CPU time)

Ran 5 tests for tests/unit/Hub/Hub.MintFeeShares.t.sol:HubMintFeeSharesTest
[PASS] test_mintFeeShares() (gas: 309709)
[PASS] test_mintFeeShares_noFees() (gas: 366984)
[PASS] test_mintFeeShares_noShares() (gas: 297954)
[PASS] test_mintFeeShares_revertsWith_AccessManagedUnauthorized() (gas: 25025)
[PASS] test_mintFeeShares_revertsWith_SpokeNotActive() (gas: 242691)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 23.37ms (4.09ms 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: 1144043)
[PASS] test_draw() (gas: 423922)
[PASS] test_mintFeeShares() (gas: 506166)
[PASS] test_payFee_transferShares() (gas: 938100)
[PASS] test_refreshPremium() (gas: 636225)
[PASS] test_remove() (gas: 314977)
[PASS] test_restore() (gas: 891655)
[PASS] test_restore_with_transfer() (gas: 892323)
Suite result: ok. 9 passed; 0 failed; 0 skipped; finished in 40.48ms (7.70ms 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, μ: 2035257, ~: 1841697)
[PASS] test_collateralCount_ignoresInvalidBits() (gas: 124482)
[PASS] test_constants() (gas: 44966)
[PASS] test_fls() (gas: 545261)
[PASS] test_fromBitId(uint256,uint256) (runs: 5000, μ: 14153, ~: 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, μ: 153573, ~: 153214)
[PASS] test_isolateCollateral(uint256) (runs: 5000, μ: 162044, ~: 162044)
[PASS] test_isolateCollateralUntil(uint256,uint256) (runs: 5000, μ: 153552, ~: 153193)
[PASS] test_isolateUntil(uint256,uint256) (runs: 5000, μ: 143594, ~: 143587)
[PASS] test_next(uint256) (runs: 5000, μ: 20237, ~: 19157)
[PASS] test_nextBorrowing(uint256) (runs: 5000, μ: 18183, ~: 18289)
[PASS] test_nextBorrowing_continuous() (gas: 63845326)
[PASS] test_nextCollateral(uint256) (runs: 5000, μ: 17936, ~: 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.90s (99.90s CPU time)

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

[PASS] test_borrowNative_fuzz(uint256) (runs: 5000, μ: 665165, ~: 666238)
[PASS] test_borrowNative_revertsWith_InvalidAmount() (gas: 32207)
[PASS] test_borrowNative_revertsWith_NotNativeWrappedAsset() (gas: 32290)
[PASS] test_borrowNative_revertsWith_SpokeNotRegistered() (gas: 25298)
[PASS] test_constructor() (gas: 1051071)
[PASS] test_constructor_revertsWith_InvalidAddress() (gas: 65404)
[PASS] test_fallback_revertsWith_UnsupportedAction() (gas: 17852)
[PASS] test_receive_revertsWith_UnsupportedAction() (gas: 17647)
[PASS] test_repayNative() (gas: 753323)
Logs:
  Bound result 5000000000000000000

[PASS] test_repayNative_excessAmount() (gas: 665289)
[PASS] test_repayNative_fuzz(uint256) (runs: 5000, μ: 748106, ~: 753761)
[PASS] test_repayNative_fuzz_withInterest(uint256,uint256) (runs: 5000, μ: 676166, ~: 671443)
[PASS] test_repayNative_revertsWith_InvalidAmount() (gas: 32565)
[PASS] test_repayNative_revertsWith_NativeAmountMismatch() (gas: 30659)
[PASS] test_repayNative_revertsWith_NotNativeWrappedAsset() (gas: 39262)
[PASS] test_repayNative_revertsWith_SpokeNotRegistered() (gas: 39286)
[PASS] test_supplyAndCollateralNative() (gas: 331966)
Logs:
  Bound result 100000000000000000000

[PASS] test_supplyAndCollateralNative_fuzz(uint256) (runs: 5000, μ: 332252, ~: 331972)
[PASS] test_supplyNative() (gas: 304356)
Logs:
  Bound result 100000000000000000000

[PASS] test_supplyNative_fuzz(uint256) (runs: 5000, μ: 304708, ~: 304428)
[PASS] test_supplyNative_revertsWith_InvalidAmount() (gas: 32530)
[PASS] test_supplyNative_revertsWith_NativeAmountMismatch() (gas: 30390)
[PASS] test_supplyNative_revertsWith_NotNativeWrappedAsset() (gas: 39225)
[PASS] test_supplyNative_revertsWith_SpokeNotRegistered() (gas: 39197)
[PASS] test_withdrawNative() (gas: 330531)
Logs:
  Bound result 100000000000000000000

[PASS] test_withdrawNative_fuzz(uint256) (runs: 5000, μ: 330018, ~: 330581)
[PASS] test_withdrawNative_fuzz_allBalance(uint256) (runs: 5000, μ: 268732, ~: 268534)
[PASS] test_withdrawNative_fuzz_allBalanceWithInterest(uint256,uint256) (runs: 5000, μ: 620317, ~: 620313)
[PASS] test_withdrawNative_revertsWith_InvalidAmount() (gas: 32293)
[PASS] test_withdrawNative_revertsWith_NotNativeWrappedAsset() (gas: 32245)
[PASS] test_withdrawNative_revertsWith_SpokeNotRegistered() (gas: 25408)
Suite result: ok. 32 passed; 0 failed; 0 skipped; finished in 166.98s (205.26s 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.32s (8.34s CPU time)

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

Ran 10 tests for tests/unit/misc/SignatureGateway/SignatureGateway.Constants.t.sol:SignatureGatewayConstantsTest
[PASS] test_DOMAIN_SEPARATOR() (gas: 2053294)
[PASS] test_borrow_typeHash() (gas: 10008)
[PASS] test_constructor() (gas: 53238)
[PASS] test_eip712Domain() (gas: 2058991)
[PASS] test_repay_typeHash() (gas: 9931)
[PASS] test_setUsingAsCollateral_typeHash() (gas: 9965)
[PASS] test_supply_typeHash() (gas: 9967)
[PASS] test_updateUserDynamicConfig_typeHash() (gas: 10023)
[PASS] test_updateUserRiskPremium_typeHash() (gas: 10096)
[PASS] test_withdraw_typeHash() (gas: 10031)
Suite result: ok. 10 passed; 0 failed; 0 skipped; finished in 22.01ms (2.08ms CPU time)

Ran 5 tests for tests/unit/misc/SignatureGateway/SignatureGateway.PermitReserve.t.sol:SignatureGatewayPermitReserveTest
[PASS] test_permitReserve() (gas: 103964)
[PASS] test_permitReserve_forwards_correct_call() (gas: 51083)
[PASS] test_permitReserve_ignores_permit_reverts() (gas: 39985)
[PASS] test_permitReserve_revertsWith_ReserveNotListed() (gas: 30936)
[PASS] test_permitReserve_revertsWith_SpokeNotRegistered() (gas: 29473)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 21.29ms (1.46ms 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.64s (2.15s CPU time)

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

Ran 6 tests for tests/unit/Hub/Hub.PayFee.t.sol:HubPayFeeTest
[PASS] test_payFee_fuzz(uint256,uint256) (runs: 5000, μ: 701331, ~: 701477)
[PASS] test_payFee_fuzz_with_interest(uint256,uint256,uint256) (runs: 5000, μ: 701813, ~: 702192)
[PASS] test_payFee_revertsWith_InvalidShares() (gas: 20137)
[PASS] test_payFee_revertsWith_SpokeNotActive() (gas: 59678)
[PASS] test_payFee_revertsWith_underflow_added_shares_exceeded() (gas: 135724)
[PASS] test_payFee_revertsWith_underflow_added_shares_exceeded_with_interest() (gas: 646428)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 25.61s (25.59s CPU time)

Ran 8 tests for tests/unit/AccessManagerEnumerable.t.sol:AccessManagerEnumerableTest
[PASS] test_getRoleMembers_fuzz(uint256,uint256) (runs: 5000, μ: 1921342, ~: 1920052)
[PASS] test_getRoleTargetFunctions_fuzz(uint256,uint256) (runs: 5000, μ: 1118586, ~: 1117552)
[PASS] test_grantRole() (gas: 239205)
[PASS] test_grantRole_fuzz(uint64,uint256) (runs: 5000, μ: 856243, ~: 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 224.02s (226.91s CPU time)

Ran 21 tests for tests/unit/Spoke/Spoke.Withdraw.HealthFactor.t.sol:SpokeWithdrawHealthFactorTest
[PASS] test_unsetCollateral_fuzz_revertsWith_HealthFactorBelowThreshold(uint256) (runs: 5000, μ: 757672, ~: 757390)
[PASS] test_withdraw_fuzz_revertsWith_HealthFactorBelowThreshold_interest_increase(uint256,uint256) (runs: 5000, μ: 655935, ~: 656459)
[PASS] test_withdraw_fuzz_revertsWith_HealthFactorBelowThreshold_multiple_colls(uint256,uint256) (runs: 5000, μ: 883383, ~: 884163)
[PASS] test_withdraw_fuzz_revertsWith_HealthFactorBelowThreshold_multiple_colls_price_drop_dai(uint256,uint256,uint256) (runs: 5000, μ: 1146964, ~: 1148943)
[PASS] test_withdraw_fuzz_revertsWith_HealthFactorBelowThreshold_multiple_colls_price_drop_weth(uint256,uint256,uint256) (runs: 5000, μ: 1148206, ~: 1148937)
[PASS] test_withdraw_fuzz_revertsWith_HealthFactorBelowThreshold_multiple_colls_with_interest(uint256,uint256) (runs: 5000, μ: 939786, ~: 941859)
[PASS] test_withdraw_fuzz_revertsWith_HealthFactorBelowThreshold_multiple_debts(uint256,uint256) (runs: 5000, μ: 1003662, ~: 1003545)
[PASS] test_withdraw_fuzz_revertsWith_HealthFactorBelowThreshold_multiple_debts_price_drop(uint256,uint256,uint256) (runs: 5000, μ: 1252423, ~: 1252654)
[PASS] test_withdraw_fuzz_revertsWith_HealthFactorBelowThreshold_multiple_debts_with_interest(uint256,uint256,uint256) (runs: 5000, μ: 1040540, ~: 1040736)
[PASS] test_withdraw_fuzz_revertsWith_HealthFactorBelowThreshold_price_drop(uint256,uint256) (runs: 5000, μ: 869021, ~: 868880)
[PASS] test_withdraw_fuzz_revertsWith_HealthFactorBelowThreshold_singleBorrow(uint256) (runs: 5000, μ: 620333, ~: 620116)
[PASS] test_withdraw_revertsWith_HealthFactorBelowThreshold_interest_increase() (gas: 651094)
[PASS] test_withdraw_revertsWith_HealthFactorBelowThreshold_multiple_colls() (gas: 879582)
[PASS] test_withdraw_revertsWith_HealthFactorBelowThreshold_multiple_colls_price_drop_dai() (gas: 1142544)
[PASS] test_withdraw_revertsWith_HealthFactorBelowThreshold_multiple_colls_price_drop_weth() (gas: 1142524)
[PASS] test_withdraw_revertsWith_HealthFactorBelowThreshold_multiple_colls_with_interest() (gas: 936718)
[PASS] test_withdraw_revertsWith_HealthFactorBelowThreshold_multiple_debts() (gas: 998559)
[PASS] test_withdraw_revertsWith_HealthFactorBelowThreshold_multiple_debts_price_drop() (gas: 1245896)
[PASS] test_withdraw_revertsWith_HealthFactorBelowThreshold_multiple_debts_with_interest() (gas: 1034319)
[PASS] test_withdraw_revertsWith_HealthFactorBelowThreshold_price_drop() (gas: 863776)
[PASS] test_withdraw_revertsWith_HealthFactorBelowThreshold_singleBorrow() (gas: 622274)
Suite result: ok. 21 passed; 0 failed; 0 skipped; finished in 160.12s (295.23s CPU time)

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

[PASS] test_reclaim_fullAmount() (gas: 643059)
[PASS] test_reclaim_fuzz(uint256,uint256,uint256) (runs: 5000, μ: 664067, ~: 663275)
[PASS] test_reclaim_multipleSweepsAndReclaims() (gas: 771354)
[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: 443183)
Suite result: ok. 10 passed; 0 failed; 0 skipped; finished in 15.20s (15.17s CPU time)

Ran 21 tests for tests/unit/misc/SignatureGateway/SignatureGateway.Reverts.InvalidSignature.t.sol:SignatureGatewayInvalidSignatureTest
[PASS] test_borrowWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 190368, ~: 190368)
[PASS] test_borrowWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 38471)
[PASS] test_borrowWithSig_revertsWith_InvalidSignature_dueTo_InvalidSigner() (gas: 36913)
[PASS] test_repayWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 190324, ~: 190324)
[PASS] test_repayWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 38404)
[PASS] test_repayWithSig_revertsWith_InvalidSignature_dueTo_InvalidSigner() (gas: 36957)
[PASS] test_setUsingAsCollateralWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 234148, ~: 234148)
[PASS] test_setUsingAsCollateralWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 38365)
[PASS] test_setUsingAsCollateralWithSig_revertsWith_InvalidSignature_dueTo_InvalidSigner() (gas: 36961)
[PASS] test_supplyWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 190387, ~: 190387)
[PASS] test_supplyWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 38427)
[PASS] test_supplyWithSig_revertsWith_InvalidSignature_dueTo_InvalidSigner() (gas: 36922)
[PASS] test_updateUserDynamicConfigWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 67492, ~: 67492)
[PASS] test_updateUserDynamicConfigWithSig_revertsWith_InvalidSignatureDueTo_InvalidSigner() (gas: 25509)
[PASS] test_updateUserDynamicConfigWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 26941)
[PASS] test_updateUserRiskPremiumWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 67535, ~: 67535)
[PASS] test_updateUserRiskPremiumWithSig_revertsWith_InvalidSignatureDueTo_InvalidSigner() (gas: 25514)
[PASS] test_updateUserRiskPremiumWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 27029)
[PASS] test_withdrawWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 190321, ~: 190321)
[PASS] test_withdrawWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 38469)
[PASS] test_withdrawWithSig_revertsWith_InvalidSignature_dueTo_InvalidSigner() (gas: 36955)
Suite result: ok. 21 passed; 0 failed; 0 skipped; finished in 43.73s (68.36s CPU time)

Ran 12 tests for tests/unit/Hub/Hub.RefreshPremium.t.sol:HubRefreshPremiumTest
[PASS] test_refreshPremium_emitsEvent() (gas: 259385)
[PASS] test_refreshPremium_fuzz_positiveDeltas(uint256,int256,int256) (runs: 5000, μ: 467687, ~: 472069)
[PASS] test_refreshPremium_fuzz_withAccrual(uint256,uint256,uint256,uint256) (runs: 5000, μ: 535309, ~: 542271)
[PASS] test_refreshPremium_maxRiskPremiumThreshold() (gas: 892863)
[PASS] test_refreshPremium_negativeDeltas(uint256) (runs: 5000, μ: 461077, ~: 461095)
[PASS] test_refreshPremium_negativeDeltas_withAccrual(uint256) (runs: 5000, μ: 533767, ~: 533995)
[PASS] test_refreshPremium_pausedSpokesAllowed() (gas: 120453)
[PASS] test_refreshPremium_revertsWith_InvalidPremiumChange_NonZeroRestoredPremiumRay() (gas: 853140)
[PASS] test_refreshPremium_revertsWith_InvalidPremiumChange_RiskPremiumThresholdExceeded_DecreasingPremium() (gas: 871021)
[PASS] test_refreshPremium_revertsWith_SpokeNotActive() (gas: 57758)
[PASS] test_refreshPremium_riskPremiumThreshold() (gas: 918271)
[PASS] test_refreshPremium_spokePremiumUpdateIsContained() (gas: 710313)
Suite result: ok. 12 passed; 0 failed; 0 skipped; finished in 22.88s (22.86s CPU time)

Ran 7 tests for tests/unit/misc/SignatureGateway/SignatureGateway.Reverts.SpokeNotRegistered.t.sol:SignatureGateway_SpokeNotRegistered_Test
[PASS] test_borrowWithSig_revertsWith_SpokeNotRegistered((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 13878, ~: 13878)
[PASS] test_repayWithSig_revertsWith_SpokeNotRegistered((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 13878, ~: 13878)
[PASS] test_setUsingAsCollateralWithSig_revertsWith_SpokeNotRegistered((address,uint256,bool,address,uint256,uint256)) (runs: 5000, μ: 13857, ~: 13857)
[PASS] test_supplyWithSig_revertsWith_SpokeNotRegistered((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 13854, ~: 13854)
[PASS] test_updateUserDynamicConfigWithSig_revertsWith_SpokeNotRegistered((address,address,uint256,uint256)) (runs: 5000, μ: 14090, ~: 14090)
[PASS] test_updateUserRiskPremiumWithSig_revertsWith_SpokeNotRegistered((address,address,uint256,uint256)) (runs: 5000, μ: 14090, ~: 14090)
[PASS] test_withdrawWithSig_revertsWith_SpokeNotRegistered((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 13921, ~: 13921)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 9.98s (15.08s CPU time)

Ran 7 tests for tests/unit/misc/SignatureGateway/SignatureGateway.Reverts.Unauthorized.t.sol:SignatureGateway_Unauthorized_PositionManagerActive_Test
[PASS] test_borrowWithSig_revertsWith_Unauthorized() (gas: 79789)
[PASS] test_repayWithSig_revertsWith_Unauthorized() (gas: 113097)
[PASS] test_setUsingAsCollateralWithSig_revertsWith_Unauthorized() (gas: 72889)
[PASS] test_supplyWithSig_revertsWith_Unauthorized() (gas: 140684)
[PASS] test_updateUserDynamicConfigWithSig_revertsWith_Unauthorized() (gas: 82446)
[PASS] test_updateUserRiskPremiumWithSig_revertsWith_Unauthorized() (gas: 82386)
[PASS] test_withdrawWithSig_revertsWith_Unauthorized() (gas: 79867)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 24.35ms (4.30ms CPU time)

Ran 7 tests for tests/unit/misc/SignatureGateway/SignatureGateway.Reverts.Unauthorized.t.sol:SignatureGateway_Unauthorized_PositionManagerNotActive_Test
[PASS] test_borrowWithSig_revertsWith_Unauthorized() (gas: 77588)
[PASS] test_repayWithSig_revertsWith_Unauthorized() (gas: 110896)
[PASS] test_setUsingAsCollateralWithSig_revertsWith_Unauthorized() (gas: 70688)
[PASS] test_supplyWithSig_revertsWith_Unauthorized() (gas: 138483)
[PASS] test_updateUserDynamicConfigWithSig_revertsWith_Unauthorized() (gas: 80245)
[PASS] test_updateUserRiskPremiumWithSig_revertsWith_Unauthorized() (gas: 80185)
[PASS] test_withdrawWithSig_revertsWith_Unauthorized() (gas: 77666)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 24.09ms (4.23ms CPU time)

Ran 3 tests for tests/unit/Spoke/Spoke.Access.t.sol:SpokeAccessTest
[PASS] testAccess_change_authority() (gas: 2616612)
[PASS] testAccess_hub_functions_callable_by_spokes() (gas: 579012)
[PASS] testAccess_spoke_admin_config_access() (gas: 494129)
Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 29.42ms (3.06ms 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 24.57ms (4.45ms CPU time)

Ran 11 tests for tests/unit/misc/SignatureGateway/SignatureGateway.t.sol:SignatureGatewayTest
[PASS] test_borrowWithSig() (gas: 817858)
[PASS] test_renouncePositionManagerRole() (gas: 26880)
[PASS] test_renouncePositionManagerRole_revertsWith_OnlyOwner() (gas: 18398)
[PASS] test_repayWithSig() (gas: 815993)
[PASS] test_setSelfAsUserPositionManagerWithSig() (gas: 319299)
[PASS] test_setUsingAsCollateralWithSig() (gas: 640024)
[PASS] test_supplyWithSig() (gas: 606442)
[PASS] test_updateUserDynamicConfigWithSig() (gas: 331898)
[PASS] test_updateUserRiskPremiumWithSig() (gas: 901828)
[PASS] test_useNonce_monotonic(bytes32) (runs: 5000, μ: 13922, ~: 13922)
[PASS] test_withdrawWithSig() (gas: 610189)
Suite result: ok. 11 passed; 0 failed; 0 skipped; finished in 493.74ms (473.48ms CPU time)

Ran 5 tests for tests/unit/Spoke/Spoke.Withdraw.Scenario.t.sol:SpokeWithdrawScenarioTest
[PASS] test_withdraw_fuzz_all_liquidity_with_interest_multi_user((uint256,uint256,uint256,uint256,uint256[2],uint256)) (runs: 5000, μ: 869415, ~: 869492)
[PASS] test_withdraw_fuzz_partial_full_with_interest(uint256,uint256,uint256,uint40) (runs: 5000, μ: 716994, ~: 717051)
[PASS] test_withdraw_round_trip_deposit_withdraw(uint256,uint256,address,uint256) (runs: 5000, μ: 416942, ~: 416969)
[PASS] test_withdraw_round_trip_withdraw_deposit(uint256,uint256,uint256,address,uint256) (runs: 5000, μ: 438432, ~: 437794)
[PASS] test_withdraw_underwater_reserve_not_collateral() (gas: 818589)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 58.14s (82.50s CPU time)

Ran 6 tests for tests/unit/Spoke/Spoke.Withdraw.Validation.t.sol:SpokeWithdrawValidationTest
[PASS] test_withdraw_fuzz_revertsWith_InsufficientLiquidity_with_debt(uint256,uint256,uint256,uint256,uint256) (runs: 5000, μ: 432202, ~: 432430)
[PASS] test_withdraw_fuzz_revertsWith_InsufficientSupply_zero_supplied(uint256) (runs: 5000, μ: 52992, ~: 52708)
[PASS] test_withdraw_revertsWith_InsufficientLiquidity_with_debt() (gas: 428876)
[PASS] test_withdraw_revertsWith_InvalidAmount_zero_supplied() (gas: 49281)
[PASS] test_withdraw_revertsWith_ReserveNotListed() (gas: 22048)
[PASS] test_withdraw_revertsWith_ReservePaused() (gas: 64899)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 6.12s (6.81s CPU time)

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

[PASS] test_remove_all_with_interest() (gas: 371558)
[PASS] test_remove_fuzz(uint256,uint256) (runs: 5000, μ: 206113, ~: 206006)
[PASS] test_remove_fuzz_all_liquidity_with_interest(uint256,uint256) (runs: 5000, μ: 420311, ~: 420612)
[PASS] test_remove_fuzz_multi_spoke(uint256,uint256) (runs: 5000, μ: 287516, ~: 287657)
[PASS] test_remove_fuzz_multi_spoke_with_interest(uint256,uint256,uint256,uint256) (runs: 5000, μ: 423839, ~: 424381)
[PASS] test_remove_revertsWith_InsufficientLiquidity() (gas: 157284)
[PASS] test_remove_revertsWith_InsufficientLiquidity_exceeding_added_amount() (gas: 144975)
[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: 181750)
[PASS] test_remove_revertsWtih_underflow_one_extra_wei() (gas: 362635)
Suite result: ok. 15 passed; 0 failed; 0 skipped; finished in 31.83s (31.81s CPU time)

Ran 6 tests for tests/unit/Hub/Hub.ReportDeficit.t.sol:HubReportDeficitTest
[PASS] test_reportDeficit_fuzz_revertsWith_SurplusDrawnDeficitReported(uint256) (runs: 5000, μ: 221512, ~: 221238)
[PASS] test_reportDeficit_fuzz_revertsWith_SurplusPremiumRayDeficitReported(uint256) (runs: 5000, μ: 223206, ~: 222932)
[PASS] test_reportDeficit_fuzz_with_premium(uint256,uint256,uint256,uint256) (runs: 5000, μ: 676431, ~: 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 18.32s (18.30s CPU time)

Ran 3 tests for tests/unit/Hub/Hub.Rescue.t.sol:HubRescueTest
[PASS] test_cannot_rescue_liquidity_fee_reverts_with_InsufficientTransferred() (gas: 270569)
[PASS] test_rescue_fuzz_with_interest(uint256,uint256) (runs: 5000, μ: 518685, ~: 518672)
[PASS] test_rescue_scenario_fuzz(uint256) (runs: 5000, μ: 455453, ~: 455250)
Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 18.82s (18.80s 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, μ: 368065, ~: 368161)
[PASS] test_restore_fuzz_full_amount_with_interest_and_premium(uint256,uint256,uint256,uint256) (runs: 5000, μ: 667046, ~: 679061)
[PASS] test_restore_fuzz_revertsWith_SurplusDrawnRestored_with_interest(uint256,uint256,uint256) (runs: 5000, μ: 244753, ~: 245979)
[PASS] test_restore_fuzz_revertsWith_SurplusDrawnRestored_with_interest_and_premium(uint256,uint256,uint256,uint256) (runs: 5000, μ: 639390, ~: 639598)
[PASS] test_restore_one_share_delta_increase_revertsWith_InvalidPremiumChange() (gas: 211205)
[PASS] test_restore_partial_drawn() (gas: 327211)
[PASS] test_restore_partial_same_block() (gas: 322997)
[PASS] test_restore_premiumDeltas_twoWeiIncrease_realizedDelta() (gas: 232914)
[PASS] test_restore_revertsWith_InsufficientTransferred() (gas: 255176)
[PASS] test_restore_revertsWith_InvalidAmount_zero() (gas: 53333)
[PASS] test_restore_revertsWith_InvalidPremiumChange_premiumIncrease() (gas: 218363)
[PASS] test_restore_revertsWith_InvalidPremiumChange_premiumSharesIncrease() (gas: 218407)
[PASS] test_restore_revertsWith_SpokeNotActive_whenPaused() (gas: 165841)
[PASS] test_restore_revertsWith_SpokePaused() (gas: 93304)
[PASS] test_restore_revertsWith_SurplusDrawnRestored() (gas: 358544)
[PASS] test_restore_revertsWith_SurplusDrawnRestored_with_interest() (gas: 244555)
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: 515673)
[PASS] test_restore_revertsWith_underflow_offsetIncrease() (gas: 229598)
[PASS] test_restore_tooMuchDrawn_revertsWith_SurplusDrawnRestored() (gas: 218714)
[PASS] test_restore_when_asset_frozen() (gas: 424935)
Suite result: ok. 23 passed; 0 failed; 0 skipped; finished in 19.71s (19.69s CPU time)

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

Ran 49 tests for tests/unit/SpokeConfigurator.t.sol:SpokeConfiguratorTest
[PASS] test_addCollateralFactor() (gas: 113881)
[PASS] test_addCollateralFactor_revertsWith_OwnableUnauthorizedAccount() (gas: 17995)
[PASS] test_addDynamicReserveConfig() (gas: 96182)
[PASS] test_addDynamicReserveConfig_revertsWith_OwnableUnauthorizedAccount() (gas: 18267)
[PASS] test_addLiquidationBonus_revertsWith_OwnableUnauthorizedAccount() (gas: 18102)
[PASS] test_addLiquidationFee() (gas: 113859)
[PASS] test_addLiquidationFee_revertsWith_OwnableUnauthorizedAccount() (gas: 17995)
[PASS] test_addMaxLiquidationBonus() (gas: 113940)
[PASS] test_addReserve() (gas: 420029)
[PASS] test_addReserve_revertsWith_MaximumReservesReached() (gas: 253826)
[PASS] test_addReserve_revertsWith_OwnableUnauthorizedAccount() (gas: 19139)
[PASS] test_freezeAllReserves() (gas: 199042)
[PASS] test_freezeAllReserves_revertsWith_OwnableUnauthorizedAccount() (gas: 15774)
[PASS] test_pauseAllReserves() (gas: 198871)
[PASS] test_pauseAllReserves_revertsWith_OwnableUnauthorizedAccount() (gas: 15731)
[PASS] test_updateBorrowable() (gas: 96457)
[PASS] test_updateBorrowable_revertsWith_OwnableUnauthorizedAccount() (gas: 17993)
[PASS] test_updateCollateralFactor() (gas: 71501)
[PASS] test_updateCollateralFactor_revertsWith_OwnableUnauthorizedAccount() (gas: 18116)
[PASS] test_updateCollateralRisk() (gas: 70767)
[PASS] test_updateCollateralRisk_revertsWith_OwnableUnauthorizedAccount() (gas: 18027)
[PASS] test_updateDynamicReserveConfig() (gas: 183515)
[PASS] test_updateDynamicReserveConfig_revertsWith_OwnableUnauthorizedAccount() (gas: 18357)
[PASS] test_updateFrozen() (gas: 99371)
[PASS] test_updateFrozen_revertsWith_OwnableUnauthorizedAccount() (gas: 18058)
[PASS] test_updateHealthFactorForMaxBonus() (gas: 57251)
[PASS] test_updateHealthFactorForMaxBonus_revertsWith_OwnableUnauthorizedAccount() (gas: 15862)
[PASS] test_updateLiquidatable() (gas: 96570)
[PASS] test_updateLiquidatable_revertsWith_OwnableUnauthorizedAccount() (gas: 18059)
[PASS] test_updateLiquidationBonusFactor() (gas: 60269)
[PASS] test_updateLiquidationBonusFactor_revertsWith_OwnableUnauthorizedAccount() (gas: 15795)
[PASS] test_updateLiquidationConfig() (gas: 57065)
[PASS] test_updateLiquidationConfig_revertsWith_OwnableUnauthorizedAccount() (gas: 16125)
[PASS] test_updateLiquidationFee() (gas: 71508)
[PASS] test_updateLiquidationFee_revertsWith_OwnableUnauthorizedAccount() (gas: 18075)
[PASS] test_updateLiquidationTargetHealthFactor() (gas: 60270)
[PASS] test_updateLiquidationTargetHealthFactor_revertsWith_OwnableUnauthorizedAccount() (gas: 15886)
[PASS] test_updateMaxLiquidationBonus() (gas: 71462)
[PASS] test_updateMaxLiquidationBonus_revertsWith_OwnableUnauthorizedAccount() (gas: 18010)
[PASS] test_updateMaxReserves() (gas: 42648)
[PASS] test_updateMaxReserves_revertsWith_OwnableUnauthorizedAccount() (gas: 15821)
[PASS] test_updatePaused() (gas: 99246)
[PASS] test_updatePaused_revertsWith_OwnableUnauthorizedAccount() (gas: 18058)
[PASS] test_updatePositionManager() (gas: 62828)
[PASS] test_updatePositionManager_revertsWith_OwnableUnauthorizedAccount() (gas: 15917)
[PASS] test_updateReceiveSharesEnabled() (gas: 96500)
[PASS] test_updateReceiveSharesEnabled_revertsWith_OwnableUnauthorizedAccount() (gas: 18012)
[PASS] test_updateReservePriceSource() (gas: 250193)
[PASS] test_updateReservePriceSource_revertsWith_OwnableUnauthorizedAccount() (gas: 17987)
Suite result: ok. 49 passed; 0 failed; 0 skipped; finished in 38.71ms (13.30ms CPU time)

Ran 4 tests for tests/unit/Hub/Hub.Skim.t.sol:HubSkimTest
[PASS] test_skimAdd_fuzz_donationAfterAdd(uint256,uint256,uint256) (runs: 5000, μ: 228312, ~: 228333)
[PASS] test_skimAdd_fuzz_donationBeforeAdd(uint256,uint256,uint256) (runs: 5000, μ: 228366, ~: 228387)
[PASS] test_skimAdd_fuzz_wrongSpokeTransfer(uint256,uint256,uint256) (runs: 5000, μ: 217214, ~: 217154)
[PASS] test_skimRestore_fuzz_liquidityDonation(uint256,uint256,uint256) (runs: 5000, μ: 273215, ~: 274780)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 27.82s (27.80s CPU time)

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

[PASS] test_sweep_does_not_impact_utilization(uint256,uint256) (runs: 5000, μ: 632010, ~: 633570)
[PASS] test_sweep_fuzz(uint256,uint256) (runs: 5000, μ: 471425, ~: 471602)
[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 19.24s (19.22s CPU time)

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

[PASS] test_transferShares_fuzz(uint256,uint256) (runs: 5000, μ: 189049, ~: 189281)
[PASS] test_transferShares_fuzz_revertsWith_underflow_spoke_added_shares_exceeded(uint256) (runs: 5000, μ: 148482, ~: 148199)
[PASS] test_transferShares_revertsWith_AddCapExceeded() (gas: 191780)
[PASS] test_transferShares_revertsWith_SpokeNotActive() (gas: 173327)
[PASS] test_transferShares_revertsWith_SpokePaused() (gas: 175686)
[PASS] test_transferShares_zeroShares_revertsWith_InvalidShares() (gas: 22457)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 7.50s (7.48s CPU time)

Ran 17 tests for tests/unit/Spoke/TreasurySpoke.t.sol:TreasurySpokeTest
[PASS] test_borrow_revertsWith_UnsupportedAction() (gas: 9891)
[PASS] test_deploy_reverts_on_invalid_params() (gas: 97277)
[PASS] test_getters() (gas: 749074)
[PASS] test_initial_state() (gas: 161413)
[PASS] test_liquidationCall_revertsWith_UnsupportedAction() (gas: 10844)
[PASS] test_repay_revertsWith_UnsupportedAction() (gas: 9893)
[PASS] test_supply(uint256) (runs: 5000, μ: 126188, ~: 125988)
[PASS] test_supply_revertsWith_Unauthorized(address) (runs: 5000, μ: 16351, ~: 16351)
[PASS] test_transfer_fuzz(address,uint256,uint256) (runs: 5000, μ: 101178, ~: 102187)
[PASS] test_transfer_revertsWith_ERC20InsufficientBalance(uint256) (runs: 5000, μ: 478918, ~: 478918)
[PASS] test_transfer_revertsWith_Unauthorized(address) (runs: 5000, μ: 15243, ~: 15243)
[PASS] test_withdraw_fuzz_amount_feesOnly(uint256) (runs: 5000, μ: 791247, ~: 790967)
[PASS] test_withdraw_fuzz_amount_interestAndFees(uint256) (runs: 5000, μ: 782833, ~: 782658)
[PASS] test_withdraw_fuzz_amount_interestOnly(uint256) (runs: 5000, μ: 814456, ~: 814168)
[PASS] test_withdraw_fuzz_maxLiquidityFee(uint256,uint256,uint256) (runs: 5000, μ: 858726, ~: 858796)
[PASS] test_withdraw_maxLiquidityFee() (gas: 859684)
Logs:
  Bound result 1000000000000000000000
  Bound result 29376000
  Bound result 2

[PASS] test_withdraw_revertsWith_Unauthorized(address) (runs: 5000, μ: 16775, ~: 16775)
Suite result: ok. 17 passed; 0 failed; 0 skipped; finished in 56.28s (56.26s CPU time)

Ran 7 tests for tests/unit/UnitPriceFeed.t.sol:UnitPriceFeedTest
[PASS] testDECIMALS() (gas: 8333)
[PASS] test_description() (gas: 11937)
[PASS] test_fuzz_latestRoundData(uint80) (runs: 5000, μ: 11537, ~: 11537)
[PASS] test_fuzz_latestRoundData_DifferentDecimals(uint8) (runs: 5000, μ: 209805, ~: 210036)
[PASS] test_getRoundData() (gas: 12959)
[PASS] test_getRoundData_futureRound() (gas: 12900)
[PASS] test_version() (gas: 8268)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 534.91ms (527.89ms CPU time)

Ran 12 tests for tests/unit/libraries/UserPositionDebt.t.sol:UserPositionDebtTest
[PASS] test_applyPremiumDelta() (gas: 26494)
[PASS] test_calculatePremiumRay() (gas: 19772)
[PASS] test_calculateRestoreAmount() (gas: 24711)
[PASS] test_fuzz_applyPremiumDelta((int256,int256,uint256)) (runs: 5000, μ: 34586, ~: 34648)
[PASS] test_fuzz_calculatePremiumRay(uint256,int256,uint256) (runs: 5000, μ: 33754, ~: 33621)
[PASS] test_fuzz_calculateRestoreAmount(uint256,uint256,int256,uint256,uint256) (runs: 5000, μ: 43377, ~: 43318)
[PASS] test_fuzz_getPremiumDelta((uint256,uint256,int256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 49664, ~: 49849)
[PASS] test_fuzz_getUserDebt_DrawnIndex(uint256,uint256,int256,uint256) (runs: 5000, μ: 40370, ~: 40380)
[PASS] test_fuzz_getUserDebt_HubAndAssetId(uint256,uint256,int256,uint256) (runs: 5000, μ: 46459, ~: 46469)
[PASS] test_getPremiumDelta() (gas: 17411)
[PASS] test_getUserDebt_DrawnIndex() (gas: 23925)
[PASS] test_getUserDebt_HubAndAssetId() (gas: 30761)
Suite result: ok. 12 passed; 0 failed; 0 skipped; finished in 4.46s (4.46s CPU time)

Ran 4 tests for tests/unit/VaultSpoke/VaultSpoke.Base.t.sol:VaultSpokeInitTest
[PASS] test_configuration() (gas: 23734)
[PASS] test_constructor_asset_correctly_set() (gas: 2372286)
[PASS] test_constructor_reverts_when_invalid_setup() (gas: 84350)
[PASS] test_setUp() (gas: 71095)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 21.20ms (977.60µs CPU time)

Ran 7 tests for tests/unit/VaultSpoke/VaultSpoke.Constants.t.sol:VaultSpokeConstantsTest
[PASS] test_DOMAIN_SEPARATOR() (gas: 2970011)
[PASS] test_deposit_typeHash() (gas: 15437)
[PASS] test_eip712Domain() (gas: 2975491)
[PASS] test_mint_typeHash() (gas: 15509)
[PASS] test_permit_typeHash() (gas: 15336)
[PASS] test_redeem_typeHash() (gas: 15380)
[PASS] test_withdraw_typeHash() (gas: 15249)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 21.94ms (1.71ms CPU time)

Ran 4 tests for tests/unit/VaultSpoke/VaultSpoke.DepositWithPermit.t.sol:VaultSpokeDepositWithPermitTest
[PASS] test_depositWithPermit() (gas: 243562)
[PASS] test_depositWithPermit_forwards_correct_call() (gas: 198401)
[PASS] test_depositWithPermit_ignores_permit_reverts() (gas: 187517)
[PASS] test_depositWithPermit_works_with_existing_allowance() (gas: 208033)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 22.92ms (2.93ms 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, μ: 389499, ~: 389408)
[PASS] test_accrueInterest_NoInterest_OnlyAdd(uint40) (runs: 5000, μ: 204687, ~: 204632)
[PASS] test_accrueInterest_fuzz_BorrowAmountAndElapsed(uint256,uint40) (runs: 5000, μ: 270398, ~: 270040)
[PASS] test_accrueInterest_fuzz_BorrowAmountRateAndElapsed(uint256,uint256,uint40) (runs: 5000, μ: 389913, ~: 389693)
[PASS] test_accrueInterest_fuzz_BorrowAndWait(uint40) (runs: 5000, μ: 269148, ~: 269057)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 26.01s (25.99s 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, μ: 968775, ~: 969359)
[PASS] test_addAsset_fuzz_revertsWith_InvalidAssetDecimals(bool,address,uint8,address,uint256,address) (runs: 5000, μ: 57693, ~: 57625)
[PASS] test_addAsset_fuzz_revertsWith_OwnableUnauthorizedAccount(address) (runs: 5000, μ: 31174, ~: 31175)
[PASS] test_addAsset_revertsWith_InvalidAddress_irStrategy() (gas: 50891)
[PASS] test_addAsset_revertsWith_InvalidAddress_underlying() (gas: 50790)
[PASS] test_addAsset_revertsWith_InvalidLiquidityFee() (gas: 872500)
[PASS] test_addAsset_reverts_invalidIrData() (gas: 46921)
[PASS] test_addSpoke() (gas: 126299)
[PASS] test_addSpokeToAssets() (gas: 222721)
[PASS] test_addSpokeToAssets_revertsWith_MismatchedConfigs() (gas: 24780)
[PASS] test_addSpokeToAssets_revertsWith_OwnableUnauthorizedAccount() (gas: 17127)
[PASS]...*[Comment body truncated]*

/// @title EIP712Hash library
/// @author Aave Labs
/// @notice Helper methods to hash EIP712 typed data structs.
library EIP712Hash {
Copy link
Contributor

Choose a reason for hiding this comment

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

Happy to see this back in the common libraries :)

Copy link
Member

Choose a reason for hiding this comment

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

not a fan, i d prefer to keep it separate just because it does not make sense to have a library with eip712 hashes about vaults in a posm contract

contract VaultSpokeBaseTest is Base {
IVaultSpoke public daiVault;
string public constant SHARE_NAME = 'Core Hub DAI';
string public constant SHARE_SYMBOL = 'chDAI';
Copy link
Member

Choose a reason for hiding this comment

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

let's start thinking about this...

contract VaultSpokeERC4626ComplianceTest is VaultSpokeBaseTest, ERC4626Test {
function setUp() public override(VaultSpokeBaseTest, ERC4626Test) {
VaultSpokeBaseTest.setUp();
updateLiquidityFee(IHub(daiVault.hub()), daiVault.assetId(), 0);
Copy link
Member

Choose a reason for hiding this comment

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

why is this needed

Copy link
Member Author

@DhairyaSethi DhairyaSethi Dec 16, 2025

Choose a reason for hiding this comment

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

for my yield generating logic, to increase the share price by X i generate X amount of the debt interest, if non 0 fees part of that is lost & not contributing to share price

? vm.randomUint(1, MAX_SUPPLY_AMOUNT)
: vm.randomUint(1, maxAssets);

asset.mint(user, assets);
Copy link
Member

Choose a reason for hiding this comment

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

why this instead of prank?

Copy link
Member Author

Choose a reason for hiding this comment

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

no specific reason

Copy link
Member

Choose a reason for hiding this comment

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

it's just that i was looking for the prank when reading the test

/// @param r The r value of the permit.
/// @param s The s value of the permit.
/// @return The amount of shares minted.
function depositWithPermit(
Copy link
Member

Choose a reason for hiding this comment

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

no mintWithPermit, which is fine i guess

Copy link
Member Author

Choose a reason for hiding this comment

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

yes primarily bc it becomes very more complex to either:

  • also accept an assets param - at which point why are you even using mint, just use deposit
  • predict assets from shares but this value can be different than the one used in the signature bc of slippage on share price

updateAddCap(IHub(vault.hub()), vault.assetId(), address(vault), 0);
}

function isVaultActiveOrNotPaused() public view returns (bool) {
Copy link
Member

Choose a reason for hiding this comment

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

we can do internal/private right

Copy link
Member

Choose a reason for hiding this comment

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

also, should we rm to isVaultActiveAndNotPaused

Copy link
Member

Choose a reason for hiding this comment

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

why Or and not And @DhairyaSethi ?

1
);
} else {
vm.etch(vault.hub(), new bytes(0));
Copy link
Member

Choose a reason for hiding this comment

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

why, to do not impact the hub with the call?

Copy link
Member Author

Choose a reason for hiding this comment

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

to ensure we never hit the branches after the one the we're trying to isolate, the insight being we do hub calls in the max getters
first one to get config
and the second (if addCap is not infinite) to get spoke supplied balance (totalAssets())

return config.active && !config.paused;
}

modifier setUpPreconditions() {
Copy link
Member

Choose a reason for hiding this comment

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

a one-off throughout the test suite. We can use an internal method instead, for consistency.

function setUp() public virtual override {
super.setUp();
vault = daiVault;
updateAddCap(IHub(vault.hub()), vault.assetId(), address(vault), 0);
Copy link
Member

Choose a reason for hiding this comment

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

probably better to move this to the setUp of VaultSpokeMaxGettersTest_Active_NotPaused no?

Copy link
Member Author

Choose a reason for hiding this comment

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

ReturnsZero is the base for active/paused flag scenarios, will need to make VaultSpokeMaxGettersTest_Active_NotPaused the base for the subsequent contracts which feels weird


/// @notice Resets the allowance of an owner for the caller.
/// @param owner The owner of the allowance to renounce.
function renounceAllowance(address owner) external;
Copy link
Member

Choose a reason for hiding this comment

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

what's the use-case for this?

Copy link
Member Author

Choose a reason for hiding this comment

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

prevent dangling allowances from integrations

and works as a stopgap for transient allowance on the share tokens as integration can reset allowance themselves

/// @author Aave Labs
/// @notice Implementation contract for the VaultSpoke.
contract VaultSpokeInstance is VaultSpoke {
uint64 public constant SPOKE_REVISION = 1;
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd call this VAULT_SPOKE_REVISION, wdyt?

Copy link
Member Author

Choose a reason for hiding this comment

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

intentionally kept it as so to retain a common interface but not a strong opinion


/// @title VaultSpoke
/// @author Aave Labs
/// @notice ERC4626 compliant vault for hub's listed asset position management.
Copy link
Contributor

Choose a reason for hiding this comment

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

for hub's listed asset position management this is confusing imo

_spendAllowance({owner: owner, spender: caller, value: shares});
}
HUB.remove(ASSET_ID, assets, receiver);
_burn(owner, shares);
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd burn before hub.remove, wdyt?

Copy link
Contributor

Choose a reason for hiding this comment

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

for _deposit I think breaking checks effects interaction is actually better, so I wouldn;t change order there

bytes calldata signature
) external returns (uint256);

/// @notice Deposits assets into the vault with an underlying asset ERC2612 typed permit.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// @notice Deposits assets into the vault with an underlying asset ERC2612 typed permit.
/// @notice Deposits assets into the vault with an underlying asset EIP2612-typed permit.

emit Deposit({sender: caller, owner: receiver, assets: assets, shares: shares});
}

function _withdraw(
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
function _withdraw(
/// @dev Does not check `hub.remove(assets)` returns exactly `shares`; it must be the exact return value of `previewRemoveByAssets` or vice versa for `assets`.
function _withdraw(

not sure if this is clear enough tho. Apart from that, should we say smt about extensibility? These are the functions to be override if we want to create a new version of the vault with different logic on deposits/withdrawals

return assets;
}

/// @dev Does not check `hub.add(assets)` returns exactly `shares`; it must be the exact return value of `previewAddByShares` or vice versa for `assets`.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// @dev Does not check `hub.add(assets)` returns exactly `shares`; it must be the exact return value of `previewAddByShares` or vice versa for `assets`.
/// @dev Does not check `hub.add(assets)` returns exactly `shares`; it must be the exact return value of `previewAddByAssets` or vice versa for `assets`.

uint40 public immutable MAX_ALLOWED_SPOKE_CAP;

/// @inheritdoc IVaultSpoke
uint192 public constant PERMIT_NONCE_KEY = 0;
Copy link
Member

Choose a reason for hiding this comment

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

not sure this is the proper name / clear enough


/// @notice Returns the nonce key for the share token permit EIP-712 typed signatures.
/// @dev Share token permits nonces are always set at this specific key namespace.
/// Once the 2 ^ 64 - 1 nonces are used, the nonce at this namespace will overflow and reset to 0; unexpired permits can be replayed then.
Copy link
Member

Choose a reason for hiding this comment

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

too long, and
feels important to add this to the permit function itself, so thinking that we could have our own natspec docs there instead of inheriting

import {EIP712Hash, EIP712Types} from 'src/libraries/EIP712Hash.sol';
import {MathUtils} from 'src/libraries/math/MathUtils.sol';
import {GatewayBase} from 'src/position-manager/GatewayBase.sol';
import {EIP712} from 'src/dependencies/solady/EIP712.sol';
Copy link
Member

Choose a reason for hiding this comment

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

dependencies together pls, can you move it right after IERC20Permit?

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.

7 participants