Skip to content

feat: Add V4 Addresses Provider - #1310

Open
avniculae wants to merge 14 commits into
mainfrom
feat/addresses-provider
Open

feat: Add V4 Addresses Provider#1310
avniculae wants to merge 14 commits into
mainfrom
feat/addresses-provider

Conversation

@avniculae

Copy link
Copy Markdown
Contributor

No description provided.

vm.stopPrank();
}

function test_setAddress_idCollision_revertsWith_AddressAlreadySet() public {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added this test to highlight that id collision is possible, but it will revert if already set (that's why I decided to not allow updating an existing id, but rather owner needs to remove --by setting addr(0) and add). Owner could use the general setAddress fn to set "MAIN_TOKENIZATION" as name, and SPOKE as tag, which would result in a different tag tracking for that address, but to me this is acceptable since it's owner-controlled fn. Mistakes should be prevented by the fact that we revert on collision, hence I decided to concatenate name and tag in the same string, rather than using abi.encode() to distinguish between these collisions. thoughts/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Agree with the chosen method to prevent overriding address on same id.
I don't think in normal usage we'll have too much couple tag + name that would create issues there, so this logic should be sufficient, and then up to Owner to respect a coherent tag and naming convention.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

whats the benefit here over abi.encode i am not following - if we accept over being stupid then we should allow this and use abi.encode

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm thinking if you want to replicate the id yourself it might be easier to do it with the current impl, but I'm good with abi.encode as well. it's also about how you think it conceptually I guess

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

can you share a usecase? im not following, would prefer to go w abi encode

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

vm.stopPrank();
}

function test_setAddress_sameAddressUnderMultipleIds() public {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

this is currently possible, in case owner wants to track same address under multiple ids, eg babylon spoke can be in babylon tag and in third party tag. thoughts?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

yes, this was my 1st thought here, how much would it be an issue if the same address leaves under multiple tags/names, but since there is no tracking address -> id or address -> tag & name, I don't think it should be an issue actually, and just up to owner to correctly clean each id when removing an address from the Provider

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

although I think address -> tag & name would be useful imo, wdyt? also I'm thinking whether for an id, we should track the name as well, not just tag and address. wdyt?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

(in which case maybe one address shouldn't be registered under multiple ids / name&tag)?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

if we add the other side of the tracking, then yes deciding if we allow address registered multiple times would need to be considered. But it might be useful to easy verify an address identity, or if it is a legit V4 approved address.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i think its fine to be registered across multiple tags, the reverse map can be address to an array of (name, tag)s

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

you want the revert map if multiple tags are supported as well?

@DhairyaSethi DhairyaSethi Jun 15, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

sure why not, unless youre concerned about bloat

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

xnvx123

This comment was marked as spam.

@@ -0,0 +1,166 @@
// SPDX-License-Identifier: LicenseRef-BUSL

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can we add it to the Deploy procedures, and the Config Engine (tho it might be managed by a different admin than Gov, can be useful to have support if Gov ends up controling the Provider)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yes, I'll add a commit to have procedures as well, although I was thinking to not be part of the config engine. can be separate and can be configured in an AIP, wdyt?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yeah, the Config Engine part can be done later on when needed.
Keeping this open as a reminder.

@avniculae avniculae Jun 12, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I don't think it needs to be part of config engine, I'm thinking it can be configured in an AIP, wdyt?

@avniculae avniculae Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

hmm I see, you mean when you add a new hub/spoke. I thought on the initialisation at the moment, since we already deployed and we need to do it retroactively. I will add in config engine for future listings

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

we also have the option to do this in the configurator instead

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

its more fool proof if we do it in the configurator @avniculae

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

settled offline with Dhairya: the engine now reverts if a hub/spoke it targets is not registered in the provider, and registering/unregistering is a dedicated engine action (executeAddressesProviderEntryUpdates, runs before hub/spoke actions in the payload). 5650778

@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown
🌈 Test Results
No files changed, compilation skipped

Ran 10 tests for tests/contracts/position-manager/SignatureGateway/SignatureGateway.Constants.t.sol:SignatureGatewayConstantsTest
[PASS] test_DOMAIN_SEPARATOR() (gas: 5637)
[PASS] test_borrow_typeHash() (gas: 9778)
[PASS] test_constructor() (gas: 3716)
[PASS] test_eip712Domain() (gas: 10904)
[PASS] test_repay_typeHash() (gas: 9880)
[PASS] test_setUsingAsCollateral_typeHash() (gas: 9847)
[PASS] test_supply_typeHash() (gas: 9849)
[PASS] test_updateUserDynamicConfig_typeHash() (gas: 9803)
[PASS] test_updateUserRiskPremium_typeHash() (gas: 9801)
[PASS] test_withdraw_typeHash() (gas: 9757)
Suite result: ok. 10 passed; 0 failed; 0 skipped; finished in 31.40ms (2.53ms CPU time)

Ran 5 tests for tests/contracts/position-manager/SignatureGateway/SignatureGateway.PermitReserve.t.sol:SignatureGatewayPermitReserveTest
[PASS] test_permitReserve() (gas: 101530)
[PASS] test_permitReserve_forwards_correct_call() (gas: 51018)
[PASS] test_permitReserve_ignores_permit_reverts() (gas: 40088)
[PASS] test_permitReserve_revertsWith_ReserveNotListed() (gas: 31030)
[PASS] test_permitReserve_revertsWith_SpokeNotRegistered() (gas: 29373)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 30.54ms (1.79ms CPU time)

Ran 2 tests for tests/contracts/position-manager/SignatureGateway/SignatureGateway.Reverts.InsufficientAllowance.t.sol:SignatureGateway_InsufficientAllowance_Test
[PASS] test_repayWithSig_revertsWith_ERC20InsufficientAllowance() (gas: 463594)
[PASS] test_supplyWithSig_revertsWith_ERC20InsufficientAllowance() (gas: 87496)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 32.34ms (3.69ms CPU time)

Ran 19 tests for tests/contracts/spoke/AaveOracle.t.sol:AaveOracleTest
[PASS] test_constructor() (gas: 15250)
[PASS] test_decimals() (gas: 8358)
[PASS] test_fuzz_constructor(uint8) (runs: 5000, μ: 16685, ~: 17009)
Logs:
  Bound result 1

[PASS] test_getReservePrice() (gas: 46794)
[PASS] test_getReservePrice_revertsWith_InvalidPrice() (gas: 44558)
[PASS] test_getReservePrice_revertsWith_InvalidSource() (gas: 10899)
[PASS] test_getReservePrices() (gas: 76746)
[PASS] test_getReservePrices_revertsWith_InvalidSource() (gas: 48933)
[PASS] test_getReserveSource() (gas: 47184)
[PASS] test_setReserveSource() (gas: 44204)
[PASS] test_setReserveSource_revertsWith_InvalidPrice() (gas: 97493)
[PASS] test_setReserveSource_revertsWith_InvalidSource() (gas: 17205)
[PASS] test_setReserveSource_revertsWith_InvalidSourceDecimals() (gas: 16954)
[PASS] test_setReserveSource_revertsWith_OnlySpoke() (gas: 12996)
[PASS] test_setReserveSource_revertsWith_OracleMismatch() (gas: 5010870)
[PASS] test_setSpoke() (gas: 5039232)
[PASS] test_setSpoke_revertsWith_InvalidAddress() (gas: 10892)
[PASS] test_setSpoke_revertsWith_OnlyDeployer(address) (runs: 5000, μ: 13465, ~: 13465)
[PASS] test_setSpoke_revertsWith_SpokeAlreadySet() (gas: 15102)
Suite result: ok. 19 passed; 0 failed; 0 skipped; finished in 1.47s (1.42s CPU time)

Ran 2 tests for tests/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.t.sol:AaveV4AaveOracleDeployProcedureTest
[PASS] test_deployAaveOracle() (gas: 524367)
[PASS] test_deployAaveOracle_reverts_inputValidation() (gas: 8466)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 5.22ms (104.84µs CPU time)

Ran 2 tests for tests/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.t.sol:AaveV4AccessManagerEnumerableDeployProcedureTest
[PASS] test_deployAccessManagerEnumerable() (gas: 4403059)
[PASS] test_deployAccessManagerEnumerable_reverts() (gas: 10562)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 5.82ms (573.48µs CPU time)

Ran 6 tests for tests/deployments/procedures/deploy/roles/AaveV4AccessManagerRolesProcedure.t.sol:AaveV4AccessManagerRolesProcedureTest
[PASS] test_grantAccessManagerAdminRole() (gas: 177653)
[PASS] test_grantAccessManagerAdminRole_reverts() (gas: 14087)
[PASS] test_labelAllRoles() (gas: 1713955)
[PASS] test_labelAllRoles_reverts_zeroAddress() (gas: 8466)
[PASS] test_replaceDefaultAdminRole() (gas: 144664)
[PASS] test_replaceDefaultAdminRole_reverts() (gas: 178594)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 6.86ms (1.95ms CPU time)

Ran 5 tests for tests/deployments/batches/AaveV4AuthorityBatch.t.sol:AaveV4AuthorityBatchTest
[PASS] test_adminRoleMemberTracking() (gas: 21955)
[PASS] test_differentSaltProducesDifferentAddress() (gas: 14349)
[PASS] test_getReport() (gas: 19926)
[PASS] test_noOtherRolesInitialized() (gas: 15847)
[PASS] test_revert_zeroAdmin() (gas: 3765)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 6.33ms (1.02ms CPU time)

Ran 16 tests for tests/contracts/hub/draw-restore/Hub.Draw.t.sol:HubDrawTest
[PASS] test_draw_DifferentSpokes() (gas: 364699)
[PASS] test_draw_fuzz_IncreasedDrawnRate(uint256,uint256) (runs: 5000, μ: 708539, ~: 708778)
Logs:
  Bound result 3
  Bound result 100

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

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

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

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

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

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

[PASS] test_draw_fuzz_revertsWith_InvalidAddress(uint256) (runs: 5000, μ: 21086, ~: 21086)
[PASS] test_draw_revertsWith_DrawCapExceeded_due_to_deficit() (gas: 276476)
[PASS] test_draw_revertsWith_InsufficientLiquidity() (gas: 33650)
[PASS] test_draw_revertsWith_InsufficientLiquidity_due_to_draw() (gas: 173401)
[PASS] test_draw_revertsWith_InsufficientLiquidity_due_to_remove() (gas: 135088)
[PASS] test_draw_revertsWith_InvalidAmount() (gas: 21150)
[PASS] test_draw_revertsWith_SpokeHalted() (gas: 67970)
[PASS] test_draw_revertsWith_SpokeNotActive() (gas: 67909)
Suite result: ok. 16 passed; 0 failed; 0 skipped; finished in 25.70s (25.65s CPU time)

Ran 21 tests for tests/contracts/position-manager/SignatureGateway/SignatureGateway.Reverts.InvalidSignature.t.sol:SignatureGatewayInvalidSignatureTest
[PASS] test_borrowWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 155226, ~: 154787)
[PASS] test_borrowWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 39263)
[PASS] test_borrowWithSig_revertsWith_InvalidSignature_dueTo_InvalidSigner() (gas: 37609)
[PASS] test_repayWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 155182, ~: 154743)
[PASS] test_repayWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 39284)
[PASS] test_repayWithSig_revertsWith_InvalidSignature_dueTo_InvalidSigner() (gas: 37588)
[PASS] test_setUsingAsCollateralWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 154539, ~: 155631)
[PASS] test_setUsingAsCollateralWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 39358)
[PASS] test_setUsingAsCollateralWithSig_revertsWith_InvalidSignature_dueTo_InvalidSigner() (gas: 37680)
[PASS] test_supplyWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 155244, ~: 154805)
[PASS] test_supplyWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 39329)
[PASS] test_supplyWithSig_revertsWith_InvalidSignature_dueTo_InvalidSigner() (gas: 37620)
[PASS] test_updateUserDynamicConfigWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 141570, ~: 140298)
[PASS] test_updateUserDynamicConfigWithSig_revertsWith_InvalidSignatureDueTo_InvalidSigner() (gas: 25576)
[PASS] test_updateUserDynamicConfigWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 27259)
[PASS] test_updateUserRiskPremiumWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 141563, ~: 140291)
[PASS] test_updateUserRiskPremiumWithSig_revertsWith_InvalidSignatureDueTo_InvalidSigner() (gas: 25486)
[PASS] test_updateUserRiskPremiumWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 27230)
[PASS] test_withdrawWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 155223, ~: 154784)
[PASS] test_withdrawWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 39370)
[PASS] test_withdrawWithSig_revertsWith_InvalidSignature_dueTo_InvalidSigner() (gas: 37609)
Suite result: ok. 21 passed; 0 failed; 0 skipped; finished in 42.77s (42.74s CPU time)

Ran 8 tests for tests/contracts/hub/deficit/Hub.EliminateDeficit.t.sol:HubEliminateDeficitTest
[PASS] test_eliminateDeficit(uint256) (runs: 5000, μ: 679523, ~: 679523)
[PASS] test_eliminateDeficit_fuzz_revertsWith_AccessManagedUnauthorized(address) (runs: 5000, μ: 36483, ~: 36483)
[PASS] test_eliminateDeficit_fuzz_revertsWith_ArithmeticUnderflow_CallerSpokeNoFunds(uint256) (runs: 5000, μ: 360072, ~: 360072)
[PASS] test_eliminateDeficit_revertsWith_InvalidAmount_ZeroAmountNoDeficit() (gas: 41078)
[PASS] test_eliminateDeficit_revertsWith_InvalidAmount_ZeroAmountWithDeficit() (gas: 356183)
[PASS] test_eliminateDeficit_revertsWith_InvalidAmount_on_UnregisteredCoveredSpoke() (gas: 41399)
[PASS] test_eliminateDeficit_revertsWith_SpokeNotActive_on_UnregisteredAsset() (gas: 392824)
[PASS] test_eliminateDeficit_revertsWith_callerSpokeNotActive() (gas: 166549)
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 18.42s (18.39s CPU time)

Ran 6 tests for tests/contracts/hub/fees/Hub.MintFeeShares.t.sol:HubMintFeeSharesTest
[PASS] test_mintFeeShares() (gas: 325652)
[PASS] test_mintFeeShares_noFees() (gas: 384713)
[PASS] test_mintFeeShares_noShares() (gas: 301749)
[PASS] test_mintFeeShares_revertsWith_AccessManagedUnauthorized() (gas: 29096)
[PASS] test_mintFeeShares_revertsWith_AssetNotListed() (gas: 32893)
[PASS] test_mintFeeShares_revertsWith_SpokeNotActive() (gas: 248741)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 33.96ms (4.22ms CPU time)

Ran 9 tests for tests/gas/Hub.Operations.gas.t.sol:HubOperations_Gas_Tests
[PASS] test_add() (gas: 280037)
[PASS] test_deficit() (gas: 1392118)
[PASS] test_draw() (gas: 433406)
[PASS] test_mintFeeShares() (gas: 519703)
[PASS] test_payFee_transferShares() (gas: 971259)
[PASS] test_refreshPremium() (gas: 672333)
[PASS] test_remove() (gas: 325619)
[PASS] test_restore() (gas: 946959)
[PASS] test_restore_with_transfer() (gas: 947622)
Suite result: ok. 9 passed; 0 failed; 0 skipped; finished in 53.07ms (7.46ms CPU time)

Ran 7 tests for tests/contracts/position-manager/SignatureGateway/SignatureGateway.Reverts.SpokeNotRegistered.t.sol:SignatureGateway_SpokeNotRegistered_Test
[PASS] test_borrowWithSig_revertsWith_SpokeNotRegistered((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 13433, ~: 13433)
[PASS] test_repayWithSig_revertsWith_SpokeNotRegistered((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 13411, ~: 13411)
[PASS] test_setUsingAsCollateralWithSig_revertsWith_SpokeNotRegistered((address,uint256,bool,address,uint256,uint256)) (runs: 5000, μ: 13446, ~: 13446)
[PASS] test_supplyWithSig_revertsWith_SpokeNotRegistered((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 13476, ~: 13476)
[PASS] test_updateUserDynamicConfigWithSig_revertsWith_SpokeNotRegistered((address,address,uint256,uint256)) (runs: 5000, μ: 13709, ~: 13709)
[PASS] test_updateUserRiskPremiumWithSig_revertsWith_SpokeNotRegistered((address,address,uint256,uint256)) (runs: 5000, μ: 13665, ~: 13665)
[PASS] test_withdrawWithSig_revertsWith_SpokeNotRegistered((address,uint256,uint256,address,uint256,uint256)) (runs: 5000, μ: 13476, ~: 13476)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 17.28s (17.25s CPU time)

Ran 7 tests for tests/contracts/position-manager/SignatureGateway/SignatureGateway.Reverts.Unauthorized.t.sol:SignatureGateway_Unauthorized_PositionManagerActive_Test
[PASS] test_borrowWithSig_revertsWith_Unauthorized() (gas: 80669)
[PASS] test_repayWithSig_revertsWith_Unauthorized() (gas: 118700)
[PASS] test_setUsingAsCollateralWithSig_revertsWith_Unauthorized() (gas: 73255)
[PASS] test_supplyWithSig_revertsWith_Unauthorized() (gas: 140299)
[PASS] test_updateUserDynamicConfigWithSig_revertsWith_Unauthorized() (gas: 81545)
[PASS] test_updateUserRiskPremiumWithSig_revertsWith_Unauthorized() (gas: 81655)
[PASS] test_withdrawWithSig_revertsWith_Unauthorized() (gas: 79681)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 33.90ms (4.49ms CPU time)

Ran 7 tests for tests/contracts/position-manager/SignatureGateway/SignatureGateway.Reverts.Unauthorized.t.sol:SignatureGateway_Unauthorized_PositionManagerNotActive_Test
[PASS] test_borrowWithSig_revertsWith_Unauthorized() (gas: 78461)
[PASS] test_repayWithSig_revertsWith_Unauthorized() (gas: 116492)
[PASS] test_setUsingAsCollateralWithSig_revertsWith_Unauthorized() (gas: 71047)
[PASS] test_supplyWithSig_revertsWith_Unauthorized() (gas: 138091)
[PASS] test_updateUserDynamicConfigWithSig_revertsWith_Unauthorized() (gas: 79337)
[PASS] test_updateUserRiskPremiumWithSig_revertsWith_Unauthorized() (gas: 79447)
[PASS] test_withdrawWithSig_revertsWith_Unauthorized() (gas: 77473)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 33.99ms (4.60ms CPU time)

Ran 4 tests for tests/contracts/position-manager/SignatureGateway/SignatureGateway.SetSelfAsUserPositionManagerWithSig.t.sol:SignatureGatewaySetSelfAsUserPositionManagerTest
[PASS] test_setSelfAsUserPositionManagerWithSig() (gas: 140247)
[PASS] test_setSelfAsUserPositionManagerWithSig_forwards_correct_call() (gas: 32698)
[PASS] test_setSelfAsUserPositionManagerWithSig_ignores_underlying_spoke_reverts() (gas: 29754)
[PASS] test_setSelfAsUserPositionManagerWithSig_revertsWith_SpokeNotRegistered() (gas: 16553)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 30.31ms (1.13ms CPU time)

Ran 14 tests for tests/contracts/position-manager/SignatureGateway/SignatureGateway.t.sol:SignatureGatewayTest
[PASS] test_borrowWithSig() (gas: 843431)
[PASS] test_multicall() (gas: 681960)
[PASS] test_multicall_atomicity_on_revert() (gas: 551378)
[PASS] test_multicall_no_atomicity_with_trycatch() (gas: 653662)
[PASS] test_renouncePositionManagerRole() (gas: 29776)
[PASS] test_renouncePositionManagerRole_revertsWith_OnlyOwner() (gas: 18135)
[PASS] test_repayWithSig() (gas: 856488)
[PASS] test_setSelfAsUserPositionManagerWithSig() (gas: 336990)
[PASS] test_setUsingAsCollateralWithSig() (gas: 543151)
[PASS] test_supplyWithSig() (gas: 629653)
[PASS] test_updateUserDynamicConfigWithSig() (gas: 361979)
[PASS] test_updateUserRiskPremiumWithSig() (gas: 1068979)
[PASS] test_useNonce_monotonic(bytes32) (runs: 5000, μ: 13346, ~: 13346)
[PASS] test_withdrawWithSig() (gas: 633591)
Suite result: ok. 14 passed; 0 failed; 0 skipped; finished in 537.29ms (507.77ms CPU time)

Ran 3 tests for tests/contracts/spoke/misc/Spoke.Access.t.sol:SpokeAccessTest
[PASS] testAccess_change_authority() (gas: 519305)
[PASS] testAccess_hub_functions_callable_by_spokes() (gas: 603850)
[PASS] testAccess_spoke_admin_config_access() (gas: 496807)
Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 31.38ms (2.94ms CPU time)

Ran 6 tests for tests/contracts/hub/fees/Hub.PayFee.t.sol:HubPayFeeTest
[PASS] test_payFee_fuzz(uint256,uint256) (runs: 5000, μ: 712224, ~: 712380)
Logs:
  Bound result 68691281934999
  Bound result 0
  Bound result 100

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

[PASS] test_payFee_revertsWith_InvalidShares() (gas: 25298)
[PASS] test_payFee_revertsWith_SpokeNotActive() (gas: 67924)
[PASS] test_payFee_revertsWith_underflow_added_shares_exceeded() (gas: 142707)
[PASS] test_payFee_revertsWith_underflow_added_shares_exceeded_with_interest() (gas: 646910)
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 28.37s (28.34s CPU time)

Ran 11 tests for tests/contracts/hub/add-remove/Hub.Reclaim.t.sol:HubReclaimTest
[PASS] test_reclaim() (gas: 642334)
Logs:
  Bound result 1000000000000000000000
  Bound result 500000000000000000000
  Bound result 200000000000000000000

[PASS] test_reclaim_fullAmount() (gas: 623453)
[PASS] test_reclaim_fuzz(uint256,uint256,uint256) (runs: 5000, μ: 644042, ~: 643312)
Logs:
  Bound result 615514462186775432459
  Bound result 571193127101173104469
  Bound result 564283877115702805413

[PASS] test_reclaim_multipleSweepsAndReclaims() (gas: 734012)
[PASS] test_reclaim_revertsWith_AssetNotListed() (gas: 18447)
[PASS] test_reclaim_revertsWith_InsufficientTransferred() (gas: 442924)
[PASS] test_reclaim_revertsWith_InsufficientTransferred_noSwept() (gas: 109383)
[PASS] test_reclaim_revertsWith_InvalidAmount_zero() (gas: 99136)
[PASS] test_reclaim_revertsWith_OnlyReinvestmentController(address) (runs: 5000, μ: 98357, ~: 98357)
[PASS] test_reclaim_revertsWith_OnlyReinvestmentController_init() (gas: 46036)
[PASS] test_reclaim_revertsWith_underflow_exceedsSwept_afterSweep() (gas: 606671)
Suite result: ok. 11 passed; 0 failed; 0 skipped; finished in 16.62s (16.59s CPU time)

Ran 12 tests for tests/contracts/hub/draw-restore/Hub.RefreshPremium.t.sol:HubRefreshPremiumTest
[PASS] test_refreshPremium_emitsEvent() (gas: 264186)
[PASS] test_refreshPremium_fuzz_positiveDeltas(uint256,int256,int256) (runs: 5000, μ: 503686, ~: 509051)
Logs:
  Bound result 999999999910000000000000000001
  Bound result 1
  Bound result 2804

[PASS] test_refreshPremium_fuzz_withAccrual(uint256,uint256,uint256,uint256) (runs: 5000, μ: 480506, ~: 490442)
Logs:
  Bound result 3699
  Bound result 314
  Bound result 1777777777777777777777777777
  Bound result 19117

[PASS] test_refreshPremium_haltedSpokesAllowed() (gas: 129404)
[PASS] test_refreshPremium_maxRiskPremiumThreshold() (gas: 910790)
[PASS] test_refreshPremium_negativeDeltas(uint256) (runs: 5000, μ: 472503, ~: 472498)
Logs:
  Bound result 3124043968137

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

[PASS] test_refreshPremium_revertsWith_InvalidPremiumChange_NonZeroRestoredPremiumRay() (gas: 867378)
[PASS] test_refreshPremium_revertsWith_InvalidPremiumChange_RiskPremiumThresholdExceeded_DecreasingPremium() (gas: 886242)
[PASS] test_refreshPremium_revertsWith_SpokeNotActive() (gas: 65397)
[PASS] test_refreshPremium_riskPremiumThreshold() (gas: 933880)
[PASS] test_refreshPremium_spokePremiumUpdateIsContained() (gas: 723261)
Suite result: ok. 12 passed; 0 failed; 0 skipped; finished in 20.84s (20.81s CPU time)

Ran 4 tests for tests/contracts/spoke/risk-premium/Spoke.RiskPremium.Scenario.t.sol:SpokeRiskPremiumScenarioTest
[PASS] test_getUserRiskPremium_applyInterest_two_users_two_reserves_borrowed() (gas: 3356158)
[PASS] test_getUserRiskPremium_fuzz_inflight_calcs((uint256,uint256),(uint256,uint256),(uint256,uint256),(uint256,uint256),uint40) (runs: 5000, μ: 2513693, ~: 2569162)
Logs:
  Bound result 6
  Bound result 416966230219621053938274952927
  Bound result 796581240052418918521216347353
  Bound result 939822379796025780
  Bound result 42049413792536014079
  Bound result 0
  Bound result 151038352776559397490183429611
  Bound result 33522909571553656
  Bound result 12412

[PASS] test_getUserRiskPremium_fuzz_two_users_two_reserves_borrowed((uint256,uint256),(uint256,uint256),(uint256,uint256),(uint256,uint256),uint16,uint16,uint40[3]) (runs: 5000, μ: 2992337, ~: 2925618)
Logs:
  Bound result 2289
  Bound result 1136
  Bound result 80
  Bound result 40
  Bound result 24024024024024024024024024025
  Bound result 999000000000000000
  Bound result 5962
  Bound result 982
  Bound result 7949
  Bound result 7992
  Bound result 14592
  Bound result 12318
  Bound result 696

[PASS] test_riskPremiumPropagatesCorrectly_singleBorrow() (gas: 2028196)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 113.70s (113.66s CPU time)

Ran 15 tests for tests/contracts/hub/add-remove/Hub.Remove.t.sol:HubRemoveTest
[PASS] test_remove() (gas: 221433)
Logs:
  Bound result 2
  Bound result 100000000000000000000

[PASS] test_remove_all_with_interest() (gas: 387732)
[PASS] test_remove_fuzz(uint256,uint256) (runs: 5000, μ: 220247, ~: 220306)
Logs:
  Bound result 4
  Bound result 100

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

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

[PASS] test_remove_fuzz_multi_spoke_with_interest(uint256,uint256,uint256,uint256) (runs: 5000, μ: 439441, ~: 439978)
Logs:
  Bound result 11935
  Bound result 22369
  Bound result 25713
  Bound result 19722

[PASS] test_remove_revertsWith_InsufficientLiquidity() (gas: 162043)
[PASS] test_remove_revertsWith_InsufficientLiquidity_exceeding_added_amount() (gas: 151233)
[PASS] test_remove_revertsWith_InsufficientLiquidity_zero_added() (gas: 26348)
[PASS] test_remove_revertsWith_InvalidAddress() (gas: 21463)
[PASS] test_remove_revertsWith_InvalidAmount() (gas: 23620)
[PASS] test_remove_revertsWith_SpokeHalted() (gas: 68400)
[PASS] test_remove_revertsWith_SpokeNotActive() (gas: 68398)
[PASS] test_remove_revertsWith_underflow_exceeding_added_amount() (gas: 186917)
[PASS] test_remove_revertsWtih_underflow_one_extra_wei() (gas: 367420)
Suite result: ok. 15 passed; 0 failed; 0 skipped; finished in 32.82s (32.79s CPU time)

Ran 7 tests for tests/contracts/hub/deficit/Hub.ReportDeficit.t.sol:HubReportDeficitTest
[PASS] test_reportDeficit_fuzz_revertsWith_SurplusDrawnDeficitReported(uint256) (runs: 5000, μ: 229175, ~: 229606)
Logs:
  Bound result 3124043968137

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

[PASS] test_reportDeficit_fuzz_with_premium(uint256,uint256,uint256,uint256) (runs: 5000, μ: 381702, ~: 382431)
Logs:
  Bound result 11994
  Bound result 18109
  Bound result 2273
  Bound result 55941257610327129762177782

[PASS] test_reportDeficit_halted() (gas: 274045)
[PASS] test_reportDeficit_revertsWith_InvalidAmount() (gas: 27786)
[PASS] test_reportDeficit_revertsWith_SpokeNotActive(address) (runs: 5000, μ: 40042, ~: 40042)
[PASS] test_reportDeficit_with_premium() (gas: 381054)
Logs:
  Bound result 10000000000
  Bound result 31536000
  Bound result 5000000000
  Bound result 0

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

Ran 3 tests for tests/contracts/hub/misc/Hub.Rescue.t.sol:HubRescueTest
[PASS] test_cannot_rescue_liquidity_fee_reverts_with_InsufficientTransferred() (gas: 277182)
[PASS] test_rescue_fuzz_with_interest(uint256,uint256) (runs: 5000, μ: 520749, ~: 520712)
Logs:
  Bound result 351500639
  Bound result 1256746

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

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

Ran 23 tests for tests/contracts/hub/draw-restore/Hub.Restore.t.sol:HubRestoreTest
[PASS] test_restore_full_amount_with_interest() (gas: 379923)
Logs:
  Bound result 1000000000000000000000
  Bound result 500000000000000000000
  Bound result 31536000

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

[PASS] test_restore_fuzz_full_amount_with_interest_and_premium(uint256,uint256,uint256,uint256) (runs: 5000, μ: 685838, ~: 697386)
Logs:
  Bound result 1060
  Bound result 370
  Bound result 337777777
  Bound result 21

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

[PASS] test_restore_fuzz_revertsWith_SurplusDrawnRestored_with_interest_and_premium(uint256,uint256,uint256,uint256) (runs: 5000, μ: 655143, ~: 655404)
Logs:
  Bound result 1060
  Bound result 370
  Bound result 337777777
  Bound result 21

[PASS] test_restore_one_share_delta_increase_revertsWith_InvalidPremiumChange() (gas: 246388)
[PASS] test_restore_partial_drawn() (gas: 341434)
[PASS] test_restore_partial_same_block() (gas: 340516)
[PASS] test_restore_premiumDeltas_twoWeiIncrease_realizedDelta() (gas: 244814)
[PASS] test_restore_revertsWith_InsufficientTransferred() (gas: 264148)
[PASS] test_restore_revertsWith_InvalidAmount_zero() (gas: 67795)
[PASS] test_restore_revertsWith_InvalidPremiumChange_premiumIncrease() (gas: 253321)
[PASS] test_restore_revertsWith_InvalidPremiumChange_premiumSharesIncrease() (gas: 253365)
[PASS] test_restore_revertsWith_SpokeHalted() (gas: 110434)
[PASS] test_restore_revertsWith_SpokeNotActive_whenPaused() (gas: 196951)
[PASS] test_restore_revertsWith_SurplusDrawnRestored() (gas: 371756)
[PASS] test_restore_revertsWith_SurplusDrawnRestored_with_interest() (gas: 255279)
Logs:
  Bound result 100000000000000000000
  Bound result 50000000000000000000
  Bound result 15768000

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

[PASS] test_restore_revertsWith_SurplusPremiumRayRestored() (gas: 517967)
[PASS] test_restore_revertsWith_underflow_offsetIncrease() (gas: 262202)
[PASS] test_restore_tooMuchDrawn_revertsWith_SurplusDrawnRestored() (gas: 222111)
[PASS] test_restore_when_asset_caps_reset() (gas: 459000)
Suite result: ok. 23 passed; 0 failed; 0 skipped; finished in 19.61s (19.58s CPU time)

Ran 1 test for tests/contracts/hub/misc/Hub.Rounding.t.sol:HubRoundingTest
[PASS] test_sharePriceWithMultipleDonations() (gas: 681921221)
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.99s (2.96s CPU time)

Ran 1 test for tests/contracts/spoke/accrual/Spoke.AccrueInterest.Scenario.t.sol:SpokeAccrueInterestScenarioTest
[PASS] test_accrueInterest_fuzz_RPBorrowAndSkipTime_twoActions((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256),uint40) (runs: 5000, μ: 6656866, ~: 6506700)
Logs:
  Bound result 416966230219621053938274952927
  Bound result 0
  Bound result 255831241153786906
  Bound result 41191294854201435881
  Bound result 124281697546210950467266407747
  Bound result 33522909571553656
  Bound result 481970306954558904
  Bound result 12412
  Bound result 6
  Bound result 124281697546210950467266407747
  Bound result 33522909571553656
  Bound result 481970306954558904
  Bound result 12412

Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 158.49s (158.46s CPU time)

Ran 4 tests for tests/contracts/hub/misc/Hub.Skim.t.sol:HubSkimTest
[PASS] test_skimAdd_fuzz_donationAfterAdd(uint256,uint256,uint256) (runs: 5000, μ: 241473, ~: 241547)
Logs:
  Bound result 3
  Bound result 18470873395738003579119570309
  Bound result 446067553769140138733721804

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

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

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

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

Ran 10 tests for tests/contracts/hub/configuration/Hub.SpokeConfig.t.sol:HubSpokeConfigTest
[PASS] test_add_active_halted_scenarios() (gas: 320777)
[PASS] test_draw_active_halted_scenarios() (gas: 323360)
[PASS] test_eliminateDeficit_active_halted_scenarios() (gas: 859545)
[PASS] test_mintFeeShares_active_halted_scenarios() (gas: 854206)
[PASS] test_payFeeShares_active_halted_scenarios() (gas: 390412)
[PASS] test_refreshPremium_active_halted_scenarios() (gas: 286040)
[PASS] test_remove_active_halted_scenarios() (gas: 337215)
[PASS] test_reportDeficit_active_halted_scenarios() (gas: 466692)
[PASS] test_restore_active_halted_scenarios() (gas: 372855)
[PASS] test_transferShares_fuzz_active_halted_scenarios(bool,bool,bool,bool) (runs: 5000, μ: 223438, ~: 223453)
Suite result: ok. 10 passed; 0 failed; 0 skipped; finished in 4.23s (4.20s CPU time)

Ran 8 tests for tests/contracts/hub/misc/Hub.Sweep.t.sol:HubSweepTest
[PASS] test_sweep() (gas: 471853)
Logs:
  Bound result 1000000000000000000000
  Bound result 1000000000000000000000

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

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

[PASS] test_sweep_revertsWith_AssetNotListed() (gas: 17956)
[PASS] test_sweep_revertsWith_InsufficientLiquidity() (gas: 227157)
[PASS] test_sweep_revertsWith_InvalidAmount() (gas: 110855)
[PASS] test_sweep_revertsWith_OnlyReinvestmentController(address) (runs: 5000, μ: 98425, ~: 98425)
[PASS] test_sweep_revertsWith_OnlyReinvestmentController_init() (gas: 45573)
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 20.96s (20.93s CPU time)

Ran 7 tests for tests/contracts/hub/add-remove/Hub.TransferShares.t.sol:HubTransferSharesTest
[PASS] test_transferShares() (gas: 199716)
Logs:
  Bound result 1000000000000000000000
  Bound result 1000000000000000000000

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

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

[PASS] test_transferShares_revertsWith_AddCapExceeded() (gas: 211348)
[PASS] test_transferShares_revertsWith_SpokeHalted() (gas: 190902)
[PASS] test_transferShares_revertsWith_SpokeNotActive() (gas: 184103)
[PASS] test_transferShares_zeroShares_revertsWith_InvalidShares() (gas: 27543)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 9.40s (9.37s CPU time)

Ran 10 tests for tests/contracts/hub/misc/Hub.Upgradeable.t.sol:HubUpgradeableTest
[PASS] test_hub_revision_accessible() (gas: 5003152)
[PASS] test_implementation_constructor_fuzz(uint64) (runs: 5000, μ: 6332111, ~: 6332111)
[PASS] test_proxy_constructor_fuzz(uint64) (runs: 5000, μ: 6350277, ~: 6350269)
Logs:
  Bound result 649

[PASS] test_proxy_constructor_fuzz_revertsWith_InvalidInitialization(uint64) (runs: 5000, μ: 12660276, ~: 12660268)
Logs:
  Bound result 649

[PASS] test_proxy_constructor_revertsWith_InvalidAddress() (gas: 4998882)
[PASS] test_proxy_constructor_revertsWith_InvalidInitialization_ZeroRevision() (gas: 6329422)
[PASS] test_proxy_reinitialization_fuzz(uint64) (runs: 5000, μ: 14073222, ~: 14073206)
Logs:
  Bound result 649

[PASS] test_proxy_reinitialization_revertsWith_CallerNotProxyAdmin() (gas: 12650654)
[PASS] test_proxy_reinitialization_revertsWith_InvalidAddress() (gas: 12651077)
[PASS] test_proxy_storage_persists_across_upgrade() (gas: 14073302)
Suite result: ok. 10 passed; 0 failed; 0 skipped; finished in 20.56s (20.53s CPU time)

Ran 8 tests for tests/contracts/hub/misc/HubAccrueInterest.t.sol:HubAccrueInterestTest
[PASS] test_accrueInterest_NoActionTaken() (gas: 48710)
[PASS] test_accrueInterest_NoInterest_NoDebt(uint40) (runs: 5000, μ: 406994, ~: 406870)
Logs:
  Bound result 9

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

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

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

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

[PASS] test_getAssetDrawnRate_MatchesStoredAfterAction() (gas: 195004)
[PASS] test_getAssetDrawnRate_fuzz_DiffersAfterTimePasses(uint40) (runs: 5000, μ: 219588, ~: 219462)
Logs:
  Bound result 9

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

Ran 13 tests for tests/contracts/hub/configurator/HubConfigurator.GranularAccessControl.t.sol:HubConfiguratorGranularAccessControlTest
[PASS] test_assetManager_canCall_deactivateAsset() (gas: 149209)
[PASS] test_assetManager_canCall_haltAsset() (gas: 149223)
[PASS] test_assetManager_canCall_resetAssetCaps() (gas: 149707)
[PASS] test_assetManager_canCall_updateLiquidityFee() (gas: 90157)
[PASS] test_assetManager_cannotCall_anySpokeManagerMethod() (gas: 354221)
[PASS] test_fuzz_unauthorized_cannotCall_assetManagerMethods(address) (runs: 5000, μ: 279962, ~: 279962)
[PASS] test_fuzz_unauthorized_cannotCall_spokeManagerMethods(address) (runs: 5000, μ: 354590, ~: 354590)
[PASS] test_spokeManager_canCall_addSpoke() (gas: 132156)
[PASS] test_spokeManager_canCall_resetSpokeCaps() (gas: 205666)
[PASS] test_spokeManager_canCall_updateSpokeActive() (gas: 71977)
[PASS] test_spokeManager_canCall_updateSpokeCaps() (gas: 72523)
[PASS] test_spokeManager_canCall_updateSpokeHalted() (gas: 71946)
[PASS] test_spokeManager_cannotCall_anyAssetManagerMethod() (gas: 279027)
Suite result: ok. 13 passed; 0 failed; 0 skipped; finished in 5.77s (5.73s CPU time)

Ran 60 tests for tests/contracts/hub/configurator/HubConfigurator.t.sol:HubConfiguratorTest
[PASS] test_addAsset_fuzz(bool,address,uint8,address,uint256,uint16,uint32,uint32,uint32) (runs: 5000, μ: 457973, ~: 458540)
Logs:
  Bound result 6
  Bound result 7221
  Bound result 7991
  Bound result 12462
  Bound result 1003
  Bound result 19707

[PASS] test_addAsset_fuzz_revertsWith_AccessManagedUnauthorized(address) (runs: 5000, μ: 48852, ~: 49221)
[PASS] test_addAsset_fuzz_revertsWith_InvalidAssetDecimals(bool,address,uint8,address,uint256,address) (runs: 5000, μ: 70235, ~: 70214)
Logs:
  Bound result 254
  Bound result 10000

[PASS] test_addAsset_revertsWith_InvalidAddress_irStrategy() (gas: 63250)
[PASS] test_addAsset_revertsWith_InvalidAddress_underlying() (gas: 63187)
[PASS] test_addAsset_revertsWith_InvalidLiquidityFee() (gas: 356185)
[PASS] test_addAsset_reverts_invalidIrData() (gas: 81471)
[PASS] test_addSpoke() (gas: 140965)
[PASS] test_addSpokeToAssets() (gas: 239204)
[PASS] test_addSpokeToAssets_revertsWith_AccessManagedUnauthorized() (gas: 28169)
[PASS] test_addSpokeToAssets_revertsWith_MismatchedConfigs() (gas: 35971)
[PASS] test_addSpoke_revertsWith_AccessManagedUnauthorized() (gas: 27836)
[PASS] test_deactivateAsset() (gas: 191176)
[PASS] test_deactivateAsset_revertsWith_AccessManagedUnauthorized() (gas: 29021)
[PASS] test_deactivateSpoke() (gas: 192554)
[PASS] test_deactivateSpoke_revertsWith_AccessManagedUnauthorized() (gas: 29035)
[PASS] test_haltAsset() (gas: 191232)
[PASS] test_haltAsset_revertsWith_AccessManagedUnauthorized() (gas: 28977)
[PASS] test_haltSpoke() (gas: 192574)
[PASS] test_haltSpoke_revertsWith_AccessManagedUnauthorized() (gas: 29023)
[PASS] test_resetAssetCaps() (gas: 265416)
[PASS] test_resetAssetCaps_revertsWith_AccessManagedUnauthorized() (gas: 28952)
[PASS] test_resetSpokeCaps() (gas: 285587)
[PASS] test_resetSpokeCaps_revertsWith_AccessManagedUnauthorized() (gas: 29087)
[PASS] test_updateFeeConfig_Scenario() (gas: 366884)
Logs:
  Bound result 0
  Bound result 1800
  Bound result 0
  Bound result 400
  Bound result 0
  Bound result 0

[PASS] test_updateFeeConfig_fuzz(uint256,uint16,address) (runs: 5000, μ: 202951, ~: 203255)
Logs:
  Bound result 4
  Bound result 2614

[PASS] test_updateFeeConfig_fuzz_revertsWith_AccessManagedUnauthorized(address) (runs: 5000, μ: 35062, ~: 35062)
[PASS] test_updateFeeConfig_revertsWith_InvalidAddress_spoke() (gas: 65284)
[PASS] test_updateFeeConfig_revertsWith_InvalidLiquidityFee() (gas: 68932)
[PASS] test_updateFeeReceiver_Scenario() (gas: 237399)
[PASS] test_updateFeeReceiver_WithdrawFromOldSpoke() (gas: 2132208)
[PASS] test_updateFeeReceiver_correctAccruals() (gas: 2170340)
[PASS] test_updateFeeReceiver_fuzz(address) (runs: 5000, μ: 196127, ~: 196127)
[PASS] test_updateFeeReceiver_fuzz_revertsWith_AccessManagedUnauthorized(address) (runs: 5000, μ: 34746, ~: 34746)
[PASS] test_updateFeeReceiver_revertsWith_InvalidAddress_spoke() (gas: 69939)
[PASS] test_updateFeeReceiver_revertsWith_SpokeAlreadyListed() (gas: 95268)
[PASS] test_updateInterestRateData() (gas: 86852)
[PASS] test_updateInterestRateData_revertsWith_AccessManagedUnauthorized() (gas: 30180)
[PASS] test_updateInterestRateStrategy() (gas: 109286)
[PASS] test_updateInterestRateStrategy_fuzz_revertsWith_AccessManagedUnauthorized(address) (runs: 5000, μ: 46099, ~: 46099)
[PASS] test_updateInterestRateStrategy_revertsWith_DrawnRateStrategyReverts() (gas: 91881)
[PASS] test_updateInterestRateStrategy_revertsWith_InvalidAddress_irStrategy() (gas: 81455)
[PASS] test_updateInterestRateStrategy_revertsWith_InvalidInterestRateStrategy() (gas: 81656)
[PASS] test_updateLiquidityFee_fuzz(uint256,uint16) (runs: 5000, μ: 107233, ~: 108851)
Logs:
  Bound result 3
  Bound result 0

[PASS] test_updateLiquidityFee_revertsWith_AccessManagedUnauthorized() (gas: 27622)
[PASS] test_updateLiquidityFee_revertsWith_InvalidLiquidityFee() (gas: 70079)
[PASS] test_updateReinvestmentController() (gas: 117309)
[PASS] test_updateReinvestmentController_fuzz_revertsWith_AccessManagedUnauthorized(address) (runs: 5000, μ: 34703, ~: 34703)
[PASS] test_updateSpokeActive() (gas: 107347)
[PASS] test_updateSpokeActive_revertsWith_AccessManagedUnauthorized() (gas: 31321)
[PASS] test_updateSpokeAddCap() (gas: 81852)
[PASS] test_updateSpokeAddCap_revertsWith_AccessManagedUnauthorized() (gas: 31290)
[PASS] test_updateSpokeCaps() (gas: 81965)
[PASS] test_updateSpokeCaps_revertsWith_AccessManagedUnauthorized() (gas: 31300)
[PASS] test_updateSpokeDrawCap() (gas: 81770)
[PASS] test_updateSpokeDrawCap_revertsWith_AccessManagedUnauthorized() (gas: 31289)
[PASS] test_updateSpokeHalted() (gas: 110103)
[PASS] test_updateSpokeHalted_revertsWith_AccessManagedUnauthorized() (gas: 31276)
[PASS] test_updateSpokeRiskPremiumThreshold() (gas: 81837)
[PASS] test_updateSpokeRiskPremiumThreshold_revertsWith_AccessManagedUnauthorized() (gas: 31301)
Suite result: ok. 60 passed; 0 failed; 0 skipped; finished in 13.10s (13.07s CPU time)

Ran 51 tests for tests/config-engine/HubEngine.t.sol:HubEngineTest
[PASS] test_computeImplementationAddress() (gas: 23607)
[PASS] test_executeHubAssetCapsResets() (gas: 181431)
[PASS] test_executeHubAssetConfigUpdates_allFields() (gas: 334425)
[PASS] test_executeHubAssetConfigUpdates_crossHub() (gas: 247688)
[PASS] test_executeHubAssetConfigUpdates_feeBoth() (gas: 240740)
[PASS] test_executeHubAssetConfigUpdates_feeNeither() (gas: 66948)
[PASS] test_executeHubAssetConfigUpdates_feeOnly() (gas: 143480)
[PASS] test_executeHubAssetConfigUpdates_irDataOnly() (gas: 128413)
[PASS] test_executeHubAssetConfigUpdates_irNoOp() (gas: 58110)
[PASS] test_executeHubAssetConfigUpdates_multipleAssets() (gas: 221260)
[PASS] test_executeHubAssetConfigUpdates_receiverOnly() (gas: 219961)
[PASS] test_executeHubAssetConfigUpdates_reinvestmentController() (gas: 139697)
[PASS] test_executeHubAssetConfigUpdates_revertsWith_partialSentinelIrDataOnStrategyChange() (gas: 46860)
[PASS] test_executeHubAssetConfigUpdates_revertsWith_sentinelIrDataOnStrategyChange() (gas: 46736)
[PASS] test_executeHubAssetConfigUpdates_strategyChange() (gas: 146597)
[PASS] test_executeHubAssetDeactivations() (gas: 239768)
[PASS] test_executeHubAssetHalts() (gas: 166724)
[PASS] test_executeHubAssetHalts_multipleAssets() (gas: 285432)
[PASS] test_executeHubAssetListings() (gas: 415611)
[PASS] test_executeHubAssetListings_multipleHubs() (gas: 780785)
[PASS] test_executeHubAssetListings_noTokenization() (gas: 444309)
[PASS] test_executeHubAssetListings_revert() (gas: 427695)
[PASS] test_executeHubAssetListings_tokenization_deterministicAddress() (gas: 4125588)
[PASS] test_executeHubAssetListings_tokenization_revertsOnAddCapOnly() (gas: 406687)
[PASS] test_executeHubAssetListings_tokenization_revertsOnEmptyName() (gas: 408848)
[PASS] test_executeHubAssetListings_tokenization_revertsOnEmptySymbol() (gas: 408801)
[PASS] test_executeHubAssetListings_tokenization_revertsOnProxyAdminOwnerOnly() (gas: 408816)
[PASS] test_executeHubAssetListings_tokenization_revertsOnZeroProxyAdminOwner() (gas: 406780)
[PASS] test_executeHubAssetListings_tokenization_zeroAddCap_deploysInactiveCapped() (gas: 4127581)
[PASS] test_executeHubAssetListings_withTokenization() (gas: 4132175)
[PASS] test_executeHubAssetListings_withTokenization_duplicateUnderlying_revertsBeforeCreate2() (gas: 4120421)
[PASS] test_executeHubSpokeCapsResets() (gas: 169862)
[PASS] test_executeHubSpokeConfigUpdates_addCapOnly() (gas: 97371)
[PASS] test_executeHubSpokeConfigUpdates_allFields() (gas: 152601)
[PASS] test_executeHubSpokeConfigUpdates_capsBoth() (gas: 102548)
[PASS] test_executeHubSpokeConfigUpdates_capsNeither() (gas: 52361)
[PASS] test_executeHubSpokeConfigUpdates_drawCapOnly() (gas: 97337)
[PASS] test_executeHubSpokeConfigUpdates_haltedOnly() (gas: 93137)
[PASS] test_executeHubSpokeConfigUpdates_multipleHubs() (gas: 149826)
[PASS] test_executeHubSpokeConfigUpdates_multipleUpdates() (gas: 136494)
[PASS] test_executeHubSpokeConfigUpdates_riskPremiumThreshold() (gas: 93058)
[PASS] test_executeHubSpokeConfigUpdates_statusBoth() (gas: 109357)
[PASS] test_executeHubSpokeDeactivations() (gas: 162343)
[PASS] test_executeHubSpokeToAssetsAdditions() (gas: 7766075)
[PASS] test_executeHubSpokeToAssetsAdditions_revert_spokeAlreadyListed() (gas: 77413)
[PASS] test_fuzz_executeHubAssetConfigUpdates_feeOnly(uint256) (runs: 5000, μ: 147002, ~: 147413)
Logs:
  Bound result 4978

[PASS] test_fuzz_executeHubSpokeConfigUpdates_addCap(uint256) (runs: 5000, μ: 101220, ~: 101528)
Logs:
  Bound result 925020712585

[PASS] test_fuzz_executeHubSpokeConfigUpdates_capsBoth(uint256,uint256) (runs: 5000, μ: 102484, ~: 102356)
Logs:
  Bound result 521561012887
  Bound result 100

[PASS] test_fuzz_executeHubSpokeConfigUpdates_drawCap(uint256) (runs: 5000, μ: 101143, ~: 101451)
Logs:
  Bound result 925020712585

[PASS] test_fuzz_executeHubSpokeConfigUpdates_riskPremiumThreshold(uint256) (runs: 5000, μ: 101521, ~: 101739)
Logs:
  Bound result 8908425

[PASS] test_tokenizationSpokeDeployer_deploy_revertsOnZeroProxyAdminOwner() (gas: 11506)
Suite result: ok. 51 passed; 0 failed; 0 skipped; finished in 6.80s (6.78s CPU time)

Ran 7 tests for tests/contracts/spoke/accrual/Spoke.AccrueInterest.t.sol:SpokeAccrueInterestTest
[PASS] test_accrueInterest_NoActionTaken() (gas: 155586)
[PASS] test_accrueInterest_NoInterest_NoDebt(uint40) (runs: 5000, μ: 711052, ~: 710886)
Logs:
  Bound result 9

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

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

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

[SKIP: pending rft] test_accrueInterest_fuzz_RPBorrowAndSkipTime((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256),uint40) (runs: 0, μ: 0, ~: 0)
[PASS] test_accrueInterest_fuzz_RatesRPBorrowAndSkipTime((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256),(uint96,uint96,uint96,uint96),uint40) (runs: 5000, μ: 4873150, ~: 4892338)
Logs:
  Bound result 1216503444
  Bound result 7600
  Bound result 1363
  Bound result 16114
  Bound result 4711
  Bound result 636063623153014607566485136742
  Bound result 45000000
  Bound result 24038
  Bound result 4182
  Bound result 15581
  Bound result 23643
  Bound result 67372
  Bound result 992
  Bound result 4711
  Bound result 551025821073470
  Bound result 1093050
  Bound result 2024

Suite result: ok. 6 passed; 0 failed; 1 skipped; finished in 140.56s (140.53s CPU time)

Ran 20 tests for tests/contracts/spoke/risk-premium/Spoke.RiskPremium.t.sol:SpokeRiskPremiumTest
[PASS] test_getUserRiskPremium_fuzz_applyInterest_two_reserves_borrowed(uint256,uint256,uint256,uint256,uint256) (runs: 5000, μ: 2360021, ~: 2410922)
Logs:
  Bound result 999999999999999999999998
  Bound result 12136
  Bound result 2901
  Bound result 45000000000000000000
  Bound result 12932

[PASS] test_getUserRiskPremium_fuzz_applyingInterest(uint256,uint256,uint256,uint256) (runs: 5000, μ: 1674117, ~: 1730549)
Logs:
  Bound result 1076
  Bound result 1131
  Bound result 277777774222222222
  Bound result 18146

[PASS] test_getUserRiskPremium_fuzz_four_reserves_change_cr(uint256,uint256,uint256,uint256,uint256,uint24) (runs: 5000, μ: 2091525, ~: 2072980)
Logs:
  Bound result 6369
  Bound result 748111466082993287060025057983
  Bound result 1
  Bound result 163154532952117007
  Bound result 6304403909286328381
  Bound result 60380874664557845373500555178

[PASS] test_getUserRiskPremium_fuzz_four_reserves_change_one_price(uint256,uint256,uint256,uint256,uint256,uint256) (runs: 5000, μ: 2269590, ~: 2252681)
Logs:
  Bound result 8218757779814625
  Bound result 748111466082993287060025057983
  Bound result 1
  Bound result 163154532952117007
  Bound result 6304403909286328381
  Bound result 60380874664557845373500555178

[PASS] test_getUserRiskPremium_fuzz_four_reserves_prices_supply_debt((uint256,uint256,uint256,uint256,uint24,uint256),(uint256,uint256,uint256,uint256,uint24,uint256),(uint256,uint256,uint256,uint256,uint24,uint256),(uint256,uint256,uint256,uint256,uint24,uint256)) (runs: 5000, μ: 1988112, ~: 1996286)
Logs:
  Bound result 870723947635714054037546585955
  Bound result 473671367
  Bound result 278874279231035951
  Bound result 26430314854020610888
  Bound result 193525900071632913369146180766
  Bound result 44288117
  Bound result 123989919386587648
  Bound result 2401623631710939574
  Bound result 78106
  Bound result 2608617192926279
  Bound result 3437864049167507
  Bound result 9167441769694072
  Bound result 1602
  Bound result 43
  Bound result 49298
  Bound result 73194

[PASS] test_getUserRiskPremium_fuzz_four_reserves_supply_and_borrow(uint256,uint256,uint256,uint256,uint256) (runs: 5000, μ: 1584929, ~: 1579543)
Logs:
  Bound result 999999999999999999999998
  Bound result 2901
  Bound result 12136
  Bound result 45000000000000000000
  Bound result 12932

[PASS] test_getUserRiskPremium_fuzz_single_reserve_collateral_borrowed_amount(uint256) (runs: 5000, μ: 427677, ~: 427177)
Logs:
  Bound result 3124043968137

[PASS] test_getUserRiskPremium_fuzz_supply_does_not_impact(uint256,uint256) (runs: 5000, μ: 607023, ~: 606905)
Logs:
  Bound result 68691281934999
  Bound result 100

[PASS] test_getUserRiskPremium_fuzz_three_reserves_supply_and_borrow(uint256,uint256,uint256,uint256) (runs: 5000, μ: 1255530, ~: 1295105)
Logs:
  Bound result 1076
  Bound result 1777777777777777777777777777
  Bound result 1131
  Bound result 18146

[PASS] test_getUserRiskPremium_fuzz_two_reserves_supply_and_borrow(uint256,uint256,uint256) (runs: 5000, μ: 1049072, ~: 1082497)
Logs:
  Bound result 615514462186775432459
  Bound result 573251106969745917
  Bound result 446067553769140138733721804

[PASS] test_getUserRiskPremium_multi_reserve_collateral() (gas: 969150)
[PASS] test_getUserRiskPremium_multi_reserve_collateral_lower_rp_than_highest_cr() (gas: 1735618)
[PASS] test_getUserRiskPremium_multi_reserve_collateral_weth_partial_cover() (gas: 1309006)
[PASS] test_getUserRiskPremium_no_collateral() (gas: 98052)
[PASS] test_getUserRiskPremium_no_collateral_set() (gas: 200717)
[PASS] test_getUserRiskPremium_single_reserve_collateral() (gas: 211079)
[PASS] test_getUserRiskPremium_single_reserve_collateral_borrowed() (gas: 421913)
[PASS] test_getUserRiskPremium_two_reserves_equal_parts() (gas: 1122489)
[PASS] test_riskPremium_collateral_insufficient_to_cover_debt() (gas: 2469247)
[PASS] test_riskPremium_postActions() (gas: 1342164)
Suite result: ok. 20 passed; 0 failed; 0 skipped; finished in 247.07s (247.04s CPU time)

Ran 5 tests for tests/contracts/spoke/accrual/Spoke.AccrueLiquidityFee.EdgeCases.t.sol:SpokeAccrueLiquidityFeeEdgeCasesTest
[PASS] test_accrueLiquidityFee_fuzz_maxLiquidityFee_with_premium(uint256,uint256,uint256,uint256) (runs: 5000, μ: 558034, ~: 558106)
Logs:
  Bound result 18230
  Bound result 337777777
  Bound result 0
  Bound result 1432

[PASS] test_accrueLiquidityFee_fuzz_maxLiquidityFee_with_premium_multiple_users(uint256,uint256,uint256,uint256,uint256) (runs: 5000, μ: 818995, ~: 819111)
Logs:
  Bound result 12663
  Bound result 288000000
  Bound result 0
  Bound result 2759
  Bound result 9982

[PASS] test_accrueLiquidityFee_maxLiquidityFee_multi_spoke() (gas: 281470908)
[PASS] test_accrueLiquidityFee_maxLiquidityFee_multi_user() (gas: 197683658)
[PASS] test_accrueLiquidityFee_maxLiquidityFee_with_premium() (gas: 558123)
Logs:
  Bound result 5000
  Bound result 34560000
  Bound result 2
  Bound result 500000000000000000000

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

Ran 7 tests for tests/contracts/spoke/accrual/Spoke.AccrueLiquidityFee.t.sol:SpokeAccrueLiquidityFeeTest
[PASS] test_accrueLiquidityFee() (gas: 923020)
[PASS] test_accrueLiquidityFee_NoActionTaken() (gas: 138320)
[PASS] test_accrueLiquidityFee_NoInterest_OnlySupply(uint40) (runs: 5000, μ: 261784, ~: 261744)
Logs:
  Bound result 9

[PASS] test_accrueLiquidityFee_exact() (gas: 929328)
[PASS] test_accrueLiquidityFee_fuzz_BorrowAmountAndSkipTime(uint256,uint40) (runs: 5000, μ: 1006635, ~: 1031646)
Logs:
  Bound result 68691281934999
  Bound result 0

[PASS] test_accrueLiquidityFee_maxLiquidityFee() (gas: 563962)
[PASS] test_accrueLiquidityFee_setUsingAsCollateral() (gas: 922952)
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 21.05s (21.02s CPU time)

Ran 11 tests for tests/contracts/spoke/libraries/KeyValueList.t.sol:KeyValueListTest
[PASS] test_add_unique() (gas: 352075)
[PASS] test_fuzz_add(uint256,uint256) (runs: 5000, μ: 231254, ~: 232296)
[PASS] test_fuzz_add_unique(uint256,uint256) (runs: 5000, μ: 240456, ~: 241124)
Logs:
  Bound result 100

[PASS] test_fuzz_get(uint256[]) (runs: 5000, μ: 377309, ~: 378109)
[PASS] test_fuzz_get_uninitialized(uint256[]) (runs: 5000, μ: 264434, ~: 249976)
[PASS] test_fuzz_get_uninitialized_sorted(uint256[]) (runs: 5000, μ: 180094, ~: 153157)
[PASS] test_fuzz_pack_unpack_roundtrip(uint256,uint256) (runs: 5000, μ: 9180, ~: 9363)
Logs:
  Bound result 1869986064
  Bound result 100

[PASS] test_fuzz_sortByKey(uint256[]) (runs: 5000, μ: 434638, ~: 429176)
[PASS] test_fuzz_sortByKey_length(uint256) (runs: 5000, μ: 200131, ~: 196305)
Logs:
  Bound result 37

[PASS] test_fuzz_sortByKey_with_collision(uint256[]) (runs: 5000, μ: 512924, ~: 511631)
[PASS] test_fuzz_uncheckedAt(uint256[]) (runs: 5000, μ: 150000, ~: 150694)
Suite result: ok. 11 passed; 0 failed; 0 skipped; finished in 70.68s (70.67s CPU time)

Ran 2 tests for tests/contracts/spoke/libraries/liquidation-logic/LiquidationLogic.CollateralToLiquidate.t.sol:LiquidationLogicCollateralToLiquidateTest
[PASS] test_calculateCollateralAmountToLiquidate() (gas: 174095)
[PASS] test_calculateCollateralToLiquidate_fuzz((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 197938, ~: 186709)
Logs:
  Bound result 2
  Bound result 16
  Bound result 9010
  Bound result 99000000000000000000000012757
  Bound result 5
  Bound result 32
  Bound result 15
  Bound result 61
  Bound result 14202

Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 3.40s (3.37s CPU time)

Ran 15 tests for tests/contracts/spoke/position-manager/Spoke.SetUserPositionManagerWithSig.t.sol:SpokeSetUserPositionManagersWithSigTest
[PASS] test_DOMAIN_SEPARATOR() (gas: 5039341)
[PASS] test_eip712Domain() (gas: 5044742)
[PASS] test_positionManagerUpdate_typeHash() (gas: 3903)
[PASS] test_setUserPositionManager_typeHash() (gas: 15642)
[PASS] test_setUserPositionManagersWithSig() (gas: 287767)
[PASS] test_setUserPositionManagersWithSig_ERC1271() (gas: 374521)
[PASS] test_setUserPositionManagersWithSig_ERC1271_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 458227, ~: 455925)
[PASS] test_setUserPositionManagersWithSig_ERC1271_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 277122)
[PASS] test_setUserPositionManagersWithSig_ERC1271_revertsWith_InvalidSignature_dueTo_InvalidHash() (gas: 328428)
[PASS] test_setUserPositionManagersWithSig_multiple_updates((address,bool)[]) (runs: 5000, μ: 2443520, ~: 2409416)
[PASS] test_setUserPositionManagersWithSig_revertsWith_InvalidAccountNonce(bytes32) (runs: 5000, μ: 259907, ~: 263400)
[PASS] test_setUserPositionManagersWithSig_revertsWith_InvalidSignature_dueTo_ExpiredDeadline() (gas: 33302)
[PASS] test_setUserPositionManagersWithSig_revertsWith_InvalidSignature_dueTo_InvalidSigner() (gas: 33695)
[PASS] test_setUserPositionManagersWithSig_zero_updates() (gas: 256432)
[PASS] test_useNonce_monotonic(bytes32) (runs: 5000, μ: 19474, ~: 19474)
Suite result: ok. 15 passed; 0 failed; 0 skipped; finished in 60.01s (59.98s CPU time)

Ran 9 tests for tests/contracts/spoke/misc/Spoke.SetUsingAsCollateral.t.sol:SpokeSetUsingAsCollateralTest
[PASS] test_setUsingAsCollateral() (gas: 314916)
[PASS] test_setUsingAsCollateral_collateralStatusUnchanged() (gas: 474354)
[PASS] test_setUsingAsCollateral_revertsWith_MaximumUserReservesExceeded() (gas: 5706493)
[PASS] test_setUsingAsCollateral_revertsWith_ReentrancyGuardReentrantCall() (gas: 777432)
[PASS] test_setUsingAsCollateral_revertsWith_ReserveFrozen() (gas: 106635)
[PASS] test_setUsingAsCollateral_revertsWith_ReserveNotListed() (gas: 28527)
[PASS] test_setUsingAsCollateral_revertsWith_ReservePaused() (gas: 65885)
[PASS] test_setUsingAsCollateral_to_limit_disable_enable_again() (gas: 5963016)
[PASS] test_setUsingAsCollateral_unlimited_whenLimitIsMax() (gas: 826611)
Suite result: ok. 9 passed; 0 failed; 0 skipped; finished in 47.80ms (13.95ms CPU time)

Ran 3 tests for tests/contracts/spoke/libraries/liquidation-logic/LiquidationLogic.DebtToLiquidate.t.sol:LiquidationLogicDebtToLiquidateTest
[PASS] test_calculateDebtToLiquidate_fuzz((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 39391, ~: 39511)
Logs:
  Bound result 1631194238
  Bound result 10585
  Bound result 3436
  Bound result 1187448874948792728
  Bound result 232473893725761368
  Bound result 7575125999959706
  Bound result 15
  Bound result 306286583169637935431906209884
  Bound result 75679658657443156232320694161
  Bound result 101634016077
  Bound result 57926430471

[PASS] test_calculateDebtToLiquidate_fuzz_AmountAdjustedDueToDust((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 41798, ~: 42015)
Logs:
  Bound result 31337
  Bound result 13151
  Bound result 2126
  Bound result 1000000000000011941
  Bound result 5840439118120325
  Bound result 10000000000000000
  Bound result 18
  Bound result 1252
  Bound result 99000000013052238805970149254
  Bound result 129
  Bound result 21080468969905
  Bound result 10000000000000000
  Bound result 129

[PASS] test_calculateDebtToLiquidate_fuzz_ImpossibleToAdjustForDust((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 41687, ~: 41668)
Logs:
  Bound result 1631194238
  Bound result 10585
  Bound result 3436
  Bound result 1187448874948792728
  Bound result 232473893725761368
  Bound result 7575125999959706
  Bound result 15
  Bound result 306286583169637935431906209884
  Bound result 75679658657443156232320694161
  Bound result 101634016077
  Bound result 57926430471
  Bound result 5
  Bound result 10000000000000000
  Bound result 101634016077

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

Ran 7 tests for tests/contracts/spoke/libraries/liquidation-logic/LiquidationLogic.DebtToTargetHealthFactor.t.sol:LiquidationLogicDebtToTargetHealthFactorTest
[PASS] test_calculateDebtToTargetHealthFactor_HealthFactorEqualsTargetHealthFactor((uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 23368, ~: 23420)
Logs:
  Bound result 3116123919
  Bound result 10725
  Bound result 2977
  Bound result 1486249897798496545
  Bound result 555054242782847130
  Bound result 6199474701275945
  Bound result 9

[PASS] test_calculateDebtToTargetHealthFactor_NoPrecisionLoss() (gas: 28007)
[PASS] test_calculateDebtToTargetHealthFactor_PrecisionLoss() (gas: 17498)
[PASS] test_calculateDebtToTargetHealthFactor_UnitPrice() (gas: 28029)
[PASS] test_calculateDebtToTargetHealthFactor_fuzz_NoRevert((uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 20597, ~: 20569)
Logs:
  Bound result 3116123919
  Bound result 10725
  Bound result 2977
  Bound result 1486249897798496545
  Bound result 555054242782847130
  Bound result 6199474701275945
  Bound result 9

[PASS] test_calculateDebtToTargetHealthFactor_fuzz_revertsWith_DivisionByZero_ZeroAssetPrice((uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 22877, ~: 22929)
Logs:
  Bound result 3116123919
  Bound result 10725
  Bound result 2977
  Bound result 1486249897798496545
  Bound result 555054242782847130
  Bound result 6199474701275945
  Bound result 9

[PASS] test_calculateDebtToTargetHealthFactor_revertsWith_ArithmeticError_TargetHealthFactorLessThanHealthFactor((uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 22673, ~: 22725)
Logs:
  Bound result 3116123919
  Bound result 10725
  Bound result 2977
  Bound result 1486249897798496545
  Bound result 555054242782847130
  Bound result 6199474701275945
  Bound result 9

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

Ran 16 tests for tests/contracts/spoke/libraries/liquidation-logic/LiquidationLogic.EvaluateDeficit.t.sol:LiquidationLogicEvaluateDeficitTest
[PASS] test_evaluateDeficit_CRE_SCCM_DRE_BRCM() (gas: 8919)
[PASS] test_evaluateDeficit_CRE_SCCM_DRE_BRCO() (gas: 8932)
[PASS] test_evaluateDeficit_CRE_SCCM_DRN_BRCM() (gas: 8930)
[PASS] test_evaluateDeficit_CRE_SCCM_DRN_BRCO() (gas: 8942)
[PASS] test_evaluateDeficit_CRE_SCCO_DRE_BRCM() (gas: 8968)
[PASS] test_evaluateDeficit_CRE_SCCO_DRE_BRCO() (gas: 8991)
[PASS] test_evaluateDeficit_CRE_SCCO_DRN_BRCM() (gas: 8911)
[PASS] test_evaluateDeficit_CRE_SCCO_DRN_BRCO() (gas: 8944)
[PASS] test_evaluateDeficit_CRN_SCCM_DRE_BRCM() (gas: 8899)
[PASS] test_evaluateDeficit_CRN_SCCM_DRE_BRCO() (gas: 8955)
[PASS] test_evaluateDeficit_CRN_SCCM_DRN_BRCM() (gas: 8889)
[PASS] test_evaluateDeficit_CRN_SCCM_DRN_BRCO() (gas: 8922)
[PASS] test_evaluateDeficit_CRN_SCCO_DRE_BRCM() (gas: 8921)
[PASS] test_evaluateDeficit_CRN_SCCO_DRE_BRCO() (gas: 8956)
[PASS] test_evaluateDeficit_CRN_SCCO_DRN_BRCM() (gas: 8907)
[PASS] test_evaluateDeficit_CRN_SCCO_DRN_BRCO() (gas: 8962)
Suite result: ok. 16 passed; 0 failed; 0 skipped; finished in 30.75ms (1.06ms CPU time)

Ran 4 tests for tests/contracts/spoke/libraries/liquidation-logic/LiquidationLogic.ExecuteLiquidation.t.sol:LiquidationLogicExecuteLiquidationTest
[PASS] test_executeLiquidation() (gas: 385499)
[PASS] test_executeLiquidation_revertsWith_InvalidDebtToCover() (gas: 86003)
[PASS] test_executeLiquidation_revertsWith_MustNotLeaveDust_Collateral() (gas: 155559)
[PASS] test_executeLiquidation_revertsWith_MustNotLeaveDust_Debt() (gas: 155684)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 36.08ms (1.55ms CPU time)

Ran 3 tests for tests/contracts/spoke/libraries/liquidation-logic/LiquidationLogic.LiquidateCollateral.t.sol:LiquidationLogicLiquidateCollateralTest
[PASS] test_liquidateCollateral_fuzz(uint256,uint256,bool) (runs: 5000, μ: 211546, ~: 195795)
Logs:
  Bound result 1333
  Bound result 910

[PASS] test_liquidateCollateral_revertsWith_ArithmeticUnderflow() (gas: 28110)
[PASS] test_liquidateCollateral_revertsWith_ArithmeticUnderflow_FeeShares() (gas: 123764)
Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 2.85s (2.82s CPU time)

Ran 4 tests for tests/contracts/spoke/libraries/liquidation-logic/LiquidationLogic.LiquidateDebt.t.sol:LiquidationLogicLiquidateDebtTest
[PASS] test_liquidateDebt_fuzz(uint256) (runs: 5000, μ: 236616, ~: 226818)
[PASS] test_liquidateDebt_revertsWith_ArithmeticUnderflow() (gas: 111952)
[PASS] test_liquidateDebt_revertsWith_InsufficientAllowance() (gas: 121410)
[PASS] test_liquidateDebt_revertsWith_InsufficientBalance() (gas: 181814)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 2.82s (2.79s CPU time)

Ran 4 tests for tests/contracts/spoke/libraries/liquidation-logic/LiquidationLogic.LiquidateUser.t.sol:LiquidationLogicLiquidateUserTest
[PASS] test_liquidateUser() (gas: 386562)
[PASS] test_liquidateUser_revertsWith_InvalidDebtToCover() (gas: 78781)
[PASS] test_liquidateUser_revertsWith_MustNotLeaveDust_Collateral() (gas: 152355)
[PASS] test_liquidateUser_revertsWith_MustNotLeaveDust_Debt() (gas: 156499)
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 36.12ms (1.70ms CPU time)

Ran 8 tests for tests/contracts/spoke/libraries/liquidation-logic/LiquidationLogic.LiquidationAmounts.t.sol:LiquidationLogicLiquidationAmountsTest
[PASS] test_calculateLiquidationAmounts_EnoughCollateral() (gas: 176648)
[PASS] test_calculateLiquidationAmounts_InsufficientCollateral() (gas: 177287)
[PASS] test_calculateLiquidationAmounts_fuzz_EnoughCollateral_CollateralDust((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 298199, ~: 287496)
Logs:
  Bound result 3
  Bound result 2767
  Bound result 443124196721905572
  Bound result 14843
  Bound result 8
  Bound result 18
  Bound result 13290
  Bound result 5661
  Bound result 1999999999999999997
  Bound result 443124196721905572
  Bound result 9304570613870847
  Bound result 9
  Bound result 999999999999999999999999999997
  Bound result 1000000000000000000000000000
  Bound result 28591
  Bound result 54527
  Bound result 6504484831365108
  Bound result 7
  Bound result 1109
  Bound result 18850239771387979476210927906
  Bound result 0
  Bound result 6504484831365108
  Bound result 26
  Bound result 115792089237316195423570985008687907853269984665640564039457584007913129639935

[PASS] test_calculateLiquidationAmounts_fuzz_EnoughCollateral_NoCollateralDust((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 251226, ~: 239741)
Logs:
  Bound result 3
  Bound result 2767
  Bound result 443124196721905572
  Bound result 14843
  Bound result 8
  Bound result 18
  Bound result 13290
  Bound result 5661
  Bound result 1999999999999999997
  Bound result 443124196721905572
  Bound result 9304570613870847
  Bound result 9
  Bound result 999999999999999999999999999997
  Bound result 1000000000000000000000000000
  Bound result 28591
  Bound result 54527
  Bound result 6504484831365108
  Bound result 7
  Bound result 1109
  Bound result 18850239771387979476210927906
  Bound result 0
  Bound result 18850239771387979476210927906
  Bound result 999999999999999999999999999997

[PASS] test_calculateLiquidationAmounts_fuzz_EnoughCollateral_NoDebtLeft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 5000, μ: 269912, ~: 258378)
Logs:
  Bound result 449773931704024038
  Bound result 3335
  Bound result 0
  Bound result 10007
  Bound result 7
  Bound result 103
  Bound result 10007
  Bound result 8800
  Bound result 1000000000500000001
  Bound result 0
  Bound result 7344928932233215
  Bound result 10
  Bound result 7577
  Bound result 99000000000000000000000011295
  Bound result 534491
  Bound result 494196
  Bound result 1242436743107328
  Bound result 13
  Bound result 369
  Bound result 1280000000000000000
  Bound result 4
  Bound result 103
  Bound res...*[Comment body truncated]*

@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown

♻️ Forge Gas Snapshots

🔕 Unchanged
Path Value
snapshots/ConfigPositionManager.Operations.json
renounceCanUpdateUserDynamicConfigPermission 28,037
renounceCanUpdateUserRiskPremiumPermission 27,971
renounceCanUpdateUsingAsCollateralPermission 27,994
renounceGlobalPermission 27,952
setCanSetUsingAsCollateralPermission 50,136
setCanUpdateUserDynamicConfigPermission 50,158
setCanUpdateUserRiskPremiumPermission 50,158
setGlobalPermission 50,110
setUsingAsCollateralOnBehalfOf 77,828
updateUserDynamicConfigOnBehalfOf 52,342
updateUserRiskPremiumOnBehalfOf 140,135
snapshots/GiverPositionManager.Operations.json
repayOnBehalfOf 176,497
supplyOnBehalfOf 143,072
snapshots/Hub.Operations.json
add 91,610
add: with transfer 112,942
draw 109,072
eliminateDeficit: full 77,541
eliminateDeficit: partial 87,146
mintFeeShares 87,668
payFee 75,720
refreshPremium 75,289
remove: full 80,564
remove: partial 85,702
reportDeficit 116,908
restore: full 81,488
restore: full - with transfer 188,919
restore: partial 90,198
restore: partial - with transfer 148,213
transferShares 74,540
snapshots/NativeTokenGateway.Operations.json
borrowNative 238,707
repayNative 172,321
supplyAsCollateralNative 165,113
supplyNative 139,728
withdrawNative: full 129,898
withdrawNative: partial 142,172
snapshots/PositionManagerBase.Operations.json
setSelfAsUserPositionManagerWithSig 75,041
snapshots/SignatureGateway.Operations.json
borrowWithSig 222,144
repayWithSig 192,513
setSelfAsUserPositionManagerWithSig 75,138
setUsingAsCollateralWithSig 85,380
supplyWithSig 155,914
updateUserDynamicConfigWithSig 63,113
updateUserRiskPremiumWithSig 61,995
withdrawWithSig 135,124
snapshots/Spoke.Getters.json
getUserAccountData: supplies: 0, borrows: 0 13,014
getUserAccountData: supplies: 1, borrows: 0 56,072
getUserAccountData: supplies: 2, borrows: 0 89,894
getUserAccountData: supplies: 2, borrows: 1 112,389
getUserAccountData: supplies: 2, borrows: 2 133,792
snapshots/Spoke.Operations.ZeroRiskPremium.json
borrow: first 199,509
borrow: second action, same reserve 179,375
liquidationCall (receiveShares): full 314,227
liquidationCall (receiveShares): partial 313,645
liquidationCall (reportDeficit): full 380,307
liquidationCall: full 332,763
liquidationCall: partial 332,181
permitReserve + repay (multicall) 169,938
permitReserve + supply (multicall) 151,663
permitReserve + supply + enable collateral (multicall) 166,114
repay: full 129,276
repay: partial 134,234
setUserPositionManagersWithSig: disable 46,772
setUserPositionManagersWithSig: enable 68,684
supply + enable collateral (multicall) 146,316
supply: 0 borrows, collateral disabled 127,753
supply: 0 borrows, collateral enabled 110,724
supply: second action, same reserve 110,653
updateUserDynamicConfig: 1 collateral 76,251
updateUserDynamicConfig: 2 collaterals 92,825
updateUserRiskPremium: 1 borrow 104,446
updateUserRiskPremium: 2 borrows 114,563
usingAsCollateral: 0 borrows, enable 59,616
usingAsCollateral: 1 borrow, disable 114,490
usingAsCollateral: 1 borrow, enable 42,504
usingAsCollateral: 2 borrows, disable 138,182
usingAsCollateral: 2 borrows, enable 42,516
withdraw: 0 borrows, full 135,058
withdraw: 0 borrows, partial 140,394
withdraw: 1 borrow, partial 169,591
withdraw: 2 borrows, partial 186,292
withdraw: non collateral 111,299
snapshots/Spoke.Operations.json
borrow: first 269,297
borrow: second action, same reserve 212,163
liquidationCall (receiveShares): full 347,124
liquidationCall (receiveShares): partial 346,542
liquidationCall (reportDeficit): full 372,507
liquidationCall: full 365,660
liquidationCall: partial 365,078
permitReserve + repay (multicall) 166,334
permitReserve + supply (multicall) 151,663
permitReserve + supply + enable collateral (multicall) 166,114
repay: full 123,355
repay: partial 142,713
setUserPositionManagersWithSig: disable 46,772
setUserPositionManagersWithSig: enable 68,684
supply + enable collateral (multicall) 146,316
supply: 0 borrows, collateral disabled 127,753
supply: 0 borrows, collateral enabled 110,724
supply: second action, same reserve 110,653
updateUserDynamicConfig: 1 collateral 76,251
updateUserDynamicConfig: 2 collaterals 92,825
updateUserRiskPremium: 1 borrow 158,658
updateUserRiskPremium: 2 borrows 210,210
usingAsCollateral: 0 borrows, enable 59,616
usingAsCollateral: 1 borrow, disable 168,699
usingAsCollateral: 1 borrow, enable 42,504
usingAsCollateral: 2 borrows, disable 241,825
usingAsCollateral: 2 borrows, enable 42,516
withdraw: 0 borrows, full 135,058
withdraw: 0 borrows, partial 140,394
withdraw: 1 borrow, partial 221,298
withdraw: 2 borrows, partial 270,470
withdraw: non collateral 111,299
snapshots/TakerPositionManager.Operations.json
approveBorrow 49,807
approveBorrowWithSig 65,689
approveWithdraw 49,816
approveWithdrawWithSig 65,643
borrowOnBehalfOf 332,512
renounceBorrowAllowance 27,929
renounceWithdrawAllowance 27,983
withdrawOnBehalfOf: full 127,209
withdrawOnBehalfOf: partial 138,811
snapshots/TokenizationSpoke.Operations.json
deposit 118,614
depositWithSig 129,518
mint 118,251
mintWithSig 129,130
permit 62,766
redeem: on behalf, full 95,212
redeem: on behalf, partial 119,015
redeem: self, full 94,282
redeem: self, partial 113,482
redeemWithSig 128,864
withdraw: on behalf, full 95,646
withdraw: on behalf, partial 119,557
withdraw: self, full 94,824
withdraw: self, partial 114,024
withdrawWithSig 129,405

@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown

Forge Build Sizes

🔕 Unchanged
Contract Runtime Size (B) Initcode Size (B) Runtime Margin (B) Initcode Margin (B)
AaveOracle 2,396 2,529 22,180 46,623
AaveV4AaveOracleDeployProcedure 21 47 24,555 49,105
AaveV4AccessManagerEnumerableDeployProcedure 21 47 24,555 49,105
AaveV4AccessManagerRolesProcedure 44 94 24,532 49,058
AaveV4AuthorityBatch 145 24,028 24,431 25,124
AaveV4ConfigEngine 9,322 9,350 15,254 39,802
AaveV4ConfigPositionManagerDeployProcedure 21 47 24,555 49,105
AaveV4ConfiguratorBatch 150 27,491 24,426 21,661
AaveV4DeployBase 44 94 24,532 49,058
AaveV4DeployOrchestration 123 173 24,453 48,979
AaveV4DeployProcedureBase 21 47 24,555 49,105
AaveV4GatewayBatch 150 23,513 24,426 25,639
AaveV4GiverPositionManagerDeployProcedure 21 47 24,555 49,105
AaveV4HubConfiguratorDeployProcedure 21 47 24,555 49,105
AaveV4HubConfiguratorRolesProcedure 44 94 24,532 49,058
AaveV4HubDeployProcedure 21 47 24,555 49,105
AaveV4HubInstanceBatch 215 8,845 24,361 40,307
AaveV4HubRolesProcedure 44 94 24,532 49,058
AaveV4InterestRateStrategyDeployProcedure 21 47 24,555 49,105
AaveV4NativeTokenGatewayDeployProcedure 21 47 24,555 49,105
AaveV4PayloadSize 11,604 11,777 12,972 37,375
AaveV4PositionManagerBatch 215 35,572 24,361 13,580
AaveV4SignatureGatewayDeployProcedure 21 47 24,555 49,105
AaveV4SpokeConfiguratorDeployProcedure 21 47 24,555 49,105
AaveV4SpokeConfiguratorRolesProcedure 44 94 24,532 49,058
AaveV4SpokeDeployProcedure 21 47 24,555 49,105
AaveV4SpokeInstanceBatch 215 9,395 24,361 39,757
AaveV4SpokeRolesProcedure 44 94 24,532 49,058
AaveV4TakerPositionManagerDeployProcedure 21 47 24,555 49,105
AaveV4TestOrchestrationWrapper 2,990 3,018 21,586 46,134
AaveV4TokenizationSpokeBatch 150 21,572 24,426 27,580
AaveV4TokenizationSpokeDeployProcedure 21 47 24,555 49,105
AaveV4TreasurySpokeBatch 145 9,715 24,431 39,437
AaveV4TreasurySpokeDeployProcedure 21 47 24,555 49,105
AccessManager 12,985 14,210 11,591 34,942
AccessManagerEngine 4,426 4,478 20,150 44,674
AccessManagerEnumerable 21,008 22,847 3,568 26,305
Address 44 94 24,532 49,058
AddressesProviderBatch 150 17,700 24,426 31,452
AddressesProviderDeployProcedure 21 47 24,555 49,105
AddressesProviderInstance 11,951 12,165 12,625 36,987
Arrays 44 94 24,532 49,058
Arrays.hub 16 44 24,560 49,108
Arrays.spoke 16 44 24,560 49,108
AssetInterestRateStrategy 2,626 2,811 21,950 46,341
AssetLogic 44 94 24,532 49,058
AssetLogic.hub 16 44 24,560 49,108
AuthorityUtils 44 94 24,532 49,058
AuthorityUtils.hub 16 44 24,560 49,108
AuthorityUtils.spoke 16 44 24,560 49,108
BatchReports 44 94 24,532 49,058
BytecodeHelper 44 94 24,532 49,058
Bytes 44 94 24,532 49,058
Bytes.spoke 16 44 24,560 49,108
Comparators 44 94 24,532 49,058
Comparators.hub 16 44 24,560 49,108
Comparators.spoke 16 44 24,560 49,108
ConfigData 44 94 24,532 49,058
ConfigPermissionsMap 44 94 24,532 49,058
ConfigPermissionsMapWrapper 1,001 1,029 23,575 48,123
ConfigPositionManager 13,555 14,109 11,021 35,043
Create2Utils 134 184 24,442 48,968
Create2UtilsWrapper 6,162 6,190 18,414 42,962
DeployConstants 133 183 24,443 48,969
Dummy 21 47 24,555 49,105
ECDSA 44 94 24,532 49,058
ECDSA.spoke 16 44 24,560 49,108
EIP712Hash (src/position-manager/libraries/EIP712Hash.sol) 771 823 23,805 48,329
EIP712Hash (src/spoke/libraries/EIP712Hash.sol) 441 493 24,135 48,659
EIP712Hash.spoke 491 521 24,085 48,631
EIP712Types 44 94 24,532 49,058
ERC1967Proxy 135 891 24,441 48,261
ERC1967Utils 44 94 24,532 49,058
EngineFlags 44 94 24,532 49,058
EngineFlagsHarness 339 367 24,237 48,785
EngineUtils 44 94 24,532 49,058
EngineUtilsHarness 516 544 24,060 48,608
EnumerableSet 44 94 24,532 49,058
EnumerableSet.hub 16 44 24,560 49,108
Errors 44 94 24,532 49,058
ExtSloadWrapper 394 422 24,182 48,730
GiverPositionManager 6,924 7,199 17,652 41,953
Hashes 44 94 24,532 49,058
HubActions 44 94 24,532 49,058
HubConfigurator 13,833 14,067 10,743 35,085
HubEngine 14,468 14,520 10,108 34,632
HubInstance 24,353 24,560 223 24,592
InputUtils 44 94 24,532 49,058
KeyValueList 44 94 24,532 49,058
KeyValueList.spoke 16 44 24,560 49,108
KeyValueListWrapper 957 985 23,619 48,167
LibBit 44 94 24,532 49,058
LibBit.spoke 16 44 24,560 49,108
LiquidationLogic 12,519 12,571 12,057 36,581
LiquidationLogic.spoke 9,835 9,867 14,741 39,285
Logger 7,000 7,853 17,576 41,299
LowLevelCall 44 94 24,532 49,058
Math 44 94 24,532 49,058
Math.hub 16 44 24,560 49,108
Math.spoke 16 44 24,560 49,108
MathUtils 44 94 24,532 49,058
MathUtils.hub 16 44 24,560 49,108
MathUtils.spoke 16 44 24,560 49,108
MetadataLogger 10,599 11,457 13,977 37,695
MinimalAaveV4Payload 11,704 11,877 12,872 37,275
MockERC1271Wallet 828 962 23,748 48,190
MockERC20 2,540 3,006 22,036 46,146
MockGovernanceExecutor 896 1,027 23,680 48,125
MockNoncesKeyed 858 886 23,718 48,266
MockPriceFeed 538 1,187 24,038 47,965
MockReentrantCaller 882 1,083 23,694 48,069
MockSkimSpoke 1,116 1,275 23,460 47,877
MockTokenizationListingPayload 12,232 12,636 12,344 36,516
NativeTokenGateway 8,787 9,204 15,789 39,948
NoncesKeyed 644 672 23,932 48,480
NoncesKeyed.spoke 387 413 24,189 48,739
OrchestrationReports 44 94 24,532 49,058
Panic 44 94 24,532 49,058
Panic.hub 16 44 24,560 49,108
Panic.spoke 16 44 24,560 49,108
PercentageMath 44 94 24,532 49,058
PercentageMath.hub 16 44 24,560 49,108
PercentageMath.spoke 16 44 24,560 49,108
PercentageMathWrapper 632 660 23,944 48,492
PositionManagerBaseWrapper 5,100 5,375 19,476 43,777
PositionManagerEngine 1,021 1,073 23,555 48,079
PositionManagerNoMulticall 5,036 5,311 19,540 43,841
PositionStatusMap 44 94 24,532 49,058
PositionStatusMap.spoke 16 44 24,560 49,108
PositionStatusMapWrapper 3,341 3,369 21,235 45,783
Premium 44 94 24,532 49,058
Premium.hub 16 44 24,560 49,108
Premium.spoke 16 44 24,560 49,108
ProxyAdmin 1,320 1,556 23,256 47,596
ProxyHelper 44 94 24,532 49,058
RescuableWrapper 973 1,107 23,603 48,045
ReserveFlagsMap 44 94 24,532 49,058
ReserveFlagsMap.spoke 16 44 24,560 49,108
ReserveFlagsMapWrapper 928 956 23,648 48,196
Roles 325 377 24,251 48,775
SafeCast 44 94 24,532 49,058
SafeCast.hub 16 44 24,560 49,108
SafeCast.spoke 16 44 24,560 49,108
SafeERC20 44 94 24,532 49,058
SafeERC20.hub 16 44 24,560 49,108
SafeERC20.spoke 16 44 24,560 49,108
SharesMath 44 94 24,532 49,058
SharesMath.hub 16 44 24,560 49,108
SignatureChecker 44 94 24,532 49,058
SignatureChecker.spoke 16 44 24,560 49,108
SignatureGateway 12,208 12,749 12,368 36,403
SlotDerivation 44 94 24,532 49,058
SlotDerivation.hub 16 44 24,560 49,108
SlotDerivation.spoke 16 44 24,560 49,108
SpokeActions 44 94 24,532 49,058
SpokeConfigurator 11,825 12,059 12,751 37,093
SpokeEngine 9,797 9,849 14,779 39,303
SpokeInstance 24,291 25,098 285 24,054
SpokeUtils 96 146 24,480 49,006
SpokeUtils.spoke 71 99 24,505 49,053
SpokeUtilsWrapper 1,827 1,855 22,749 47,297
StorageSlot 44 94 24,532 49,058
StorageSlot.hub 16 44 24,560 49,108
StorageSlot.spoke 16 44 24,560 49,108
TakerPositionManager 12,153 12,707 12,423 36,445
TestTokensBatch 388 6,337 24,188 42,815
TestTypes 44 94 24,532 49,058
TestnetERC20 3,649 4,525 20,927 44,627
TestnetERC20DeployProcedure 21 47 24,555 49,105
Time 44 94 24,532 49,058
TokenizationSpokeDeployer 23,031 23,083 1,545 26,069
TokenizationSpokeInstance 13,627 14,953 10,949 34,199
TransientSlot 44 94 24,532 49,058
TransientSlot.spoke 16 44 24,560 49,108
TransparentUpgradeableProxy 1,419 4,078 23,157 45,074
TreasurySpokeInstance 4,004 4,218 20,572 44,934
UserPositionUtils 44 94 24,532 49,058
UserPositionUtils.spoke 16 44 24,560 49,108
UserPositionUtilsWrapper 3,263 3,291 21,313 45,861
WETH9 2,148 2,614 22,428 46,538
WETHDeployProcedure 21 47 24,555 49,105
WadRayMath 44 94 24,532 49,058
WadRayMath.hub 16 44 24,560 49,108
WadRayMath.spoke 16 44 24,560 49,108
WadRayMathWrapper 1,514 1,542 23,062 47,610

Comment on lines +69 to +71
function getIds(string memory tag) external view returns (bytes32[] memory) {
return _taggedIds[tag].values();
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

annoyingly we might need to overload with index and length methods instead of this bc we'll get a finding says array size can make inflate over gas limit (unlikely), we've done this way already elsewhere with array getters in the codebase

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yes true, we should do this

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Comment thread src/addresses-provider/V4AddressesProvider.sol Outdated
Kogaroshi
Kogaroshi previously approved these changes Jun 17, 2026

@Kogaroshi Kogaroshi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I still think we should add specific logic in the Config Engine, but impl lgtm

Comment thread src/config-engine/interfaces/IAaveV4ConfigEngine.sol Outdated
Comment thread src/config-engine/interfaces/IAaveV4ConfigEngine.sol Outdated
@avniculae
avniculae force-pushed the feat/addresses-provider branch from cfed17a to 8e0bf2a Compare June 24, 2026 16:26
Kogaroshi
Kogaroshi previously approved these changes Jun 30, 2026
/// @notice Returns the identifiers of all entries registered for an address.
/// @param addr The registered address.
/// @return The list of identifiers.
function getAddressIds(address addr) external view returns (bytes32[] memory);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

we do not need this if we have the one below

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

this is meant for convenience

Comment on lines +108 to +114
/// @notice Returns the number of tags with at least one registered entry.
/// @return The number of tags.
function getTagCount() external view returns (uint256);

/// @notice Returns all tags with at least one registered entry.
/// @return The list of tags.
function getTags() external view returns (string[] memory);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
/// @notice Returns the number of tags with at least one registered entry.
/// @return The number of tags.
function getTagCount() external view returns (uint256);
/// @notice Returns all tags with at least one registered entry.
/// @return The list of tags.
function getTags() external view returns (string[] memory);
/// @notice Returns the number of tags with at least one registered entry.
function getTagCount() external view returns (uint256);
/// @notice Returns all tags with at least one registered entry.
function getTags() external view returns (string[] memory);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

idk if this should be in a separate folder, perhaps misc? nbd either way

/// @title V4AddressesProvider
/// @author Aave Labs
/// @notice Main registry of Aave V4 contract addresses.
abstract contract V4AddressesProvider is

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

thinking more its a registry

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I followed the v3 naming convention here (also with the plural in "addresses" which I don't like). I'm fine changing the name, thoughts @Kogaroshi @miguelmtzinf ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it's better to keep v3 name convention, so we don't have more difference of naming in the tooling.

}

/// @inheritdoc IV4AddressesProvider
function getTokenizationSpokes() external view returns (address[] memory) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

these dont have pointer getters, i would just keep those and not have full arr return one's for all

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

we can add range getters, but would keep these for convenience as well, wdyt?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i would kill these, unnecessary take space

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

we NEED range getters bc of potential out of gas, these arent needed

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I am not aligned here. What's the concern if we have both range-based and full getters?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

overpopulation

return _addressEntries[_getId({name: name, tag: tag})].addr;
}

function _getId(string memory name, string memory tag) internal pure returns (bytes32) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

could be useful as a public fn

@avniculae avniculae Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

we have one already

IAaveV4ConfigEngine.AssetListing calldata listing,
uint256 assetId
) private {
if (!listing.hubRegistration.register) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

if input is false i believe we should assert non zero len label

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I agree, we should check these for sanity, in all of the structs used as "optional" params

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

listing.tokenization.symbol
);

uint256 assetId = IHubBase(listing.hub).getAssetId(listing.underlying);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this was dead code?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

the assetId is retrieved at listing in _registerHub() now, and passed, instead of fetching after. Less gas intensive, same result

string tag;
}

/// @notice Emitted when the address associated with a name and tag is updated.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

when the address of an entry is updated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

event name can be changed to UpdateEntry or SetEntry
(if keeping, it d be SetAddress ig, for style consistency)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

/// @param addr The registered address.
/// @param name The name of the entry.
/// @param tag The tag grouping the entry.
struct AddressEntry {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this can be just Entry

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

// SPDX-License-Identifier: LicenseRef-BUSL
pragma solidity ^0.8.0;

/// @title IV4AddressesProvider

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

the V4 preffix may not be needed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

address indexed newAddress
);

/// @notice Thrown when an empty tag is supplied.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
/// @notice Thrown when an empty tag is supplied.
/// @notice Thrown when the specified tag is invalid.

same for InvalidName

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Comment on lines +44 to +54
/// @notice Returns the tag grouping all canonical Hubs.
function CANONICAL_HUB_TAG() external view returns (string memory);

/// @notice Returns the tag grouping all canonical Spokes.
function CANONICAL_SPOKE_TAG() external view returns (string memory);

/// @notice Returns the tag grouping all tokenization Spokes.
function TOKENIZATION_SPOKE_TAG() external view returns (string memory);

/// @notice Returns the tag grouping all treasury Spokes.
function TREASURY_SPOKE_TAG() external view returns (string memory);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

view functions of constants at the bottom

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

/// @dev This contract defines all storage variables used by the V4AddressesProvider.
abstract contract V4AddressesProviderStorage {
/// @dev Map of entry identifiers to address entries.
mapping(bytes32 id => IV4AddressesProvider.AddressEntry) internal _addressEntries;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i d follow the same conventions we used as for AccessManagerEnumerable.
It's a bit unclear what each var is for (without looking at the definition/docs)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Comment on lines +29 to +30
/// @dev Left unset (the default), `register` is false and the registration is skipped.
/// @dev All fields must be set when `register` is true, and left unset when false; reverts otherwise.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

different behavior than for TokenizationSpoke.. do we want to make them both consistent?
we derive the need for doing the action (registering/deploying) by checking all params are set.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think this changed in the latest config engine, we revert if fields are partially set for tokenization spokes. to me this is better since we avoid footguns, wdyr

);

_deployAndRegisterTokenizationSpoke(listings[i]);
_registerHub(listings[i], assetId);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why is this coupled with listing an asset? Is the intention to do this automatically, and allow registering the hub separately even with no assets via direct call?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yes, idea is to have it both automatic and manual if needed

/// already-configured Hub; reverts otherwise.
function _registerHub(
IAaveV4ConfigEngine.AssetListing calldata listing,
uint256 assetId

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this is input param is a bit weird, and I d manage this condition outside (better reusability)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I agree it's weird, but I don't like that it would split the validation into 2 parts. Another option is to fetch the asset/reserve count and assess in this way, wdyt about this?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

more in favor of fetching the count instead of passing the parameter here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@Kogaroshi I agree, the question is: are you in fabor of fetching the count instead of splitting the validation into 2 parts (Miguel's suggestion)?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

since we only need it for the require here, I would fetch it locally here only

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

/// registering an already-configured Spoke; reverts otherwise.
function _registerSpoke(
IAaveV4ConfigEngine.ReserveListing calldata listing,
uint256 reserveId

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

same, i d move this condition out

- rename V4AddressesProvider/IV4AddressesProvider and the deploy
  procedure and batch to drop the V4/AaveV4 prefix
- rename the AddressEntry struct to Entry and follow through on the
  API: setAddress -> setEntry, AddressSet -> SetEntry,
  getAddressEntry -> getEntry, getAddressEntries -> getEntries
- name storage vars after the AccessManagerEnumerable convention and
  set __gap to 50, matching HubStorage and SpokeStorage
- document that the range getters clamp out-of-range bounds
Move getId() after the tag constant getters in the interface, and
_getId() after _toAddresses()/_toEntries() in the implementation, so
each visibility group runs non-mutating -> view -> pure per the
Solidity style guide order of layout.
Combine the AddressesProvider registration hooks with the config engine
fixes from #1321:

- HubEngine keeps both new errors (InvalidAddressesProviderRegistration,
  InvalidTokenizationSpokeConfig)
- _deployAndRegisterTokenizationSpoke takes main's proxyAdminOwner
  handling and revert-on-partial-config, and keeps the AddressesProvider
  registration and the passed-in assetId
- test listings and MockTokenizationListingPayload gain proxyAdminOwner
  and the unset registration fields
- AddressesProviderRegistration tests predict the proxy address from the
  declared proxyAdminOwner instead of the caller, since the owner is no
  longer derived from msg.sender
Comment thread src/addresses-provider/interfaces/IAddressesProvider.sol Outdated
Comment thread src/addresses-provider/interfaces/IAddressesProvider.sol
- _registerHub and _registerSpoke no longer take the listed id; they read
  getAssetCount()/getReserveCount() directly, so the guard stays beside
  the action it protects and the helpers take only the listing
- reorder the Entry struct to name, tag, addr, matching the (name, tag)
  ordering the rest of the interface uses
- describe IAddressesProvider as an interface, in line with the other
  interface natspec
Kogaroshi
Kogaroshi previously approved these changes Aug 5, 2026
/// @notice Library containing shared helpers for the AaveV4ConfigEngine libraries.
library EngineUtils {
/// @dev Returns whether an optional AddressesProvider registration is consistent: all fields must
/// be set when registering, and left unset otherwise.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

it should be left unset only when it's already populated no? i would not keep it optional, i thought we settled on this

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

5650778 — registration is no longer optional, engine actions require the target to be registered upfront

/// KEEP_CURRENT sentinel. All fields must be explicitly set when the strategy changes.
error InvalidIrDataWithNewStrategy();

/// @dev Thrown when an addresses provider registration is requested for a listing that does not

@DhairyaSethi DhairyaSethi Aug 5, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i would keep it strict by default, optional only when its already set

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

if (!listing.hubRegistration.register) {
return;
}
require(IHub(listing.hub).getAssetCount() == 1, InvalidAddressesProviderRegistration());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this is too strict, we cannot retrofix

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i would also check if its present in the address provider here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

5650778 — the count guard is gone, listings now require the hub to already be registered in the provider, so existing hubs can be registered retroactively via the entry updates action

- Hub and Spoke actions revert unless the target is registered on the
  AddressesProvider: Hubs as canonical Hubs, SpokeEngine targets as
  canonical Spokes, and Spokes referenced by hub-side actions under any
  spoke tag
- add executeAddressesProviderEntryUpdates as a dedicated engine action
  to register or unregister entries, executed before Hub and Spoke
  actions in AaveV4Payload
- bind the AddressesProvider to the engine as a constructor immutable
- drop the optional per-listing registration structs and the
  first-asset/first-reserve guards; TokenizationSpoke deployment always
  registers the proxy under a required registrationName
- add IAddressesProvider.isRegistered(addr, tag)
}

/// @inheritdoc IAddressesProvider
function isRegistered(address addr, string calldata tag) external view returns (bool) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

flagging: this walks every id of the address and hashes each tag, so it degrades if one address is registered under many names/tags. The engine can also check the same address several times in one payload (requireRegisteredSpoke does up to 3 isRegistered calls per item). Probably fine to leave for now since it is owner-driven and the sets stay small, but if AIP gas becomes a concern we may want to optimise (e.g. a tag-keyed lookup).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

config engine can just check if its registered on any tag, if so it passes no?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

in the optional tag input case

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'd rather keep strongly checking the type — an entry under an unrelated tag shouldn't authorize hub/spoke actions. Made the typed check O(1) instead by tracking a per-address tag count in setEntry: e7c9097

Comment on lines +37 to +39
addressesProvider.isRegistered(spoke, addressesProvider.CANONICAL_SPOKE_TAG()) ||
addressesProvider.isRegistered(spoke, addressesProvider.TOKENIZATION_SPOKE_TAG()) ||
addressesProvider.isRegistered(spoke, addressesProvider.TREASURY_SPOKE_TAG()),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

maybe we should instead maintain a reverse map as well such that we can just do isRegistered(spoke)? i reckon safer that we validate type as well so not sure

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

e7c9097 — kept the typed checks and made isRegistered a single mapping read (per-address tag count maintained in setEntry), so we don't have to trade type validation for gas

Maintain a per-address tag entry count in _setEntry so isRegistered
reads a single mapping slot instead of walking the address's entries,
keeping the engine's typed registration checks cheap regardless of how
many entries an address has.
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.

5 participants