Skip to content

feat: add etherfi spoke contract to restrict borrows to only etherfi safes#209

Open
shivam-ef wants to merge 3 commits into
feat/lendfrom
feat/aave-spoke-update
Open

feat: add etherfi spoke contract to restrict borrows to only etherfi safes#209
shivam-ef wants to merge 3 commits into
feat/lendfrom
feat/aave-spoke-update

Conversation

@shivam-ef

@shivam-ef shivam-ef commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Note

High Risk
Borrow gating and treasury-owned fee routing are core to whitelabel economics and who can take debt; misconfiguration or a flawed isEtherFiSafe check could block legitimate users or allow unauthorized borrows.

Overview
Introduces the whitelabel Aave v4 spoke and fee-splitting plumbing for the planned ether.fi instance, plus lend-profile tests that deploy the gated spoke instead of stock SpokeInstance.

EtherFiSpokeInstance overrides borrow so onBehalfOf must pass IEtherFiDataProvider.isEtherFiSafe; supply, withdraw, repay, and liquidation stay unchanged. The data provider is an immutable constructor arg so borrow policy is enforced for gateway and direct self-service paths alike.

AaveV4RevenueSplitter is meant to own the instance TreasurySpoke, expose permissionless claimAndSplit (withdraw from treasury then split by fixed BPS), and give the splitter owner a two-step escape hatch to transfer treasury ownership.

Build / tests: default Foundry profile now also skips src/aave-v4/**. AaveV4Fixture._deployAaveV4 takes an etherFiDataProvider and deploys EtherFiSpokeInstance. Gateway setup uses the real dataProvider; lens tests mock all addresses as safes; withdrawal accrual tests mock a second borrower as a safe. New GatedBorrow and RevenueSplitter fork tests cover gating invariants and 80/20 fee flow.

Reviewed by Cursor Bugbot for commit d20f00b. Bugbot is set up for automated code reviews on this repo. Configure here.

shivam-ef and others added 3 commits July 20, 2026 16:58
….fi safes

Requires the one-line aave-v4 patch (Spoke.borrow -> public virtual) carried on
the local submodule branch etherfi/v0.5.11-gated-borrow; the submodule pin
lands once the etherfi-protocol/aave-v4 fork is published.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
AaveV4Fixture now deploys the gated spoke (matching the planned whitelabel
instance) and takes the data provider feeding its isEtherFiSafe check. The two
tests simulating third-party borrow pressure mark those actors as safes.
GatedBorrow.t.sol proves the gating invariant: non-safes cannot borrow directly
or via a position manager, while supply/withdraw/liquidation stay permissionless.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…he whitelabel treasury

Owns the TreasurySpoke (2-step handshake), claims accrued fees via withdraw and
splits them between two immutable recipients; claim/split are permissionless.
Owner-gated escape hatch can hand the TreasurySpoke to a new owner (flagged to
Aave to keep or strike).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

}

/// @notice Borrows `amount` of reserve `reserveId` for `onBehalfOf`, which must be an ether.fi safe
function borrow(uint256 reserveId, uint256 amount, address onBehalfOf) public override returns (uint256, uint256) {

@nikkaroraa nikkaroraa Jul 20, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

borrow cannot override the Aave version pinned in this repo because the parent function is not virtual. the lend test job fails to compile here, so none of the new lend tests run. we'll need to include the required Aave change in this PR and update the pinned Aave version.


/// @notice Borrows `amount` of reserve `reserveId` for `onBehalfOf`, which must be an ether.fi safe
function borrow(uint256 reserveId, uint256 amount, address onBehalfOf) public override returns (uint256, uint256) {
if (!etherFiDataProvider.isEtherFiSafe(onBehalfOf)) revert OnlyEtherFiSafe(onBehalfOf);

@nikkaroraa nikkaroraa Jul 20, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

How about we also check that msg.sender is the LendGateway? The check would make sure all borrows go through the gateway rules.

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 safe is fine, so if we have new contracts in the future trying to do something similar to gateway, it would still work

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.

2 participants