Ironbank: Extension Authorization in v2
Iron Bank is a lending protocol. In its v2
eth
code branch, protected calls accept the account itself or, for a non-credit account, an extension the account has allowed. Each operation keeps its own market, balance, and liquidity restrictions.
Page sections
Permission registration and caller checks
setUserExtension(extension, allowed)
changes the caller’s own extension permissions, keyed to
msg.sender
. Setting
allowed
to
true
adds an address if it isn’t already allowed; setting it to
false
removes an existing permission. Those changes emit
ExtensionAdded
or
ExtensionRemoved
.
The authorization check for protected functions evaluates this expression:
from == operator ||
(!isCreditAccount(from) && isAllowedExtension(from, operator))
from
is the account the modifier protects, and
operator
is the address calling Iron Bank. A direct call from that account passes the first condition. An extension needs both an allowed entry and a non-credit account to pass the second.
getUserAllowedExtensions(user)
returns the recorded extension list;
isAllowedExtension(user, extension)
returns the stored permission for one address. The core stores permission for an account-extension pair, with no market or amount parameter in that permission.
Credit-account restrictions
isCreditAccount(user)
returns true when the account’s credit-market list isn’t empty. The credit-limit manager adds a market to that list when assigning a previously zero limit a nonzero value. An unused nonzero limit therefore also makes the account a credit account. Resetting that limit to zero removes its entry; any remaining credit-market entry keeps the account classified as a credit account.
Credit limits belong to individual account-market pairs, while the extension restriction covers the account across markets in that Iron Bank instance. A credit account can pass authorization by calling directly. Its borrow must send funds to itself, and its resulting debt in the requested market can’t exceed its assigned credit limit. Repayment to a credit account also requires the payer and debt account to be the same address. Supply rejects a credit account as the recipient of the supply balance.
Hypothetical approval after a credit assignment
In this hypothetical example, Account A has allowed Extension E and initially has no credit-market entries. E calls
borrow
with A as both
from
and
to
. The extension branch passes because E is allowed and A isn’t a credit account.
Now suppose the credit-limit manager gives A a nonzero limit in one listed market, leaving E’s stored permission unchanged. E’s next call for A fails with
!authorized
, including an attempted borrow in a different market in that instance. A’s own direct call still passes the caller check, but borrowing remains subject to the requested market’s credit limit, available cash, and other operation checks.
Protected accounts and token recipients
borrow
protects
from
, the account taking on debt, while
to
receives the borrowed tokens. For
redeem
,
from
owns the supply claim, and
to
receives the underlying asset. For non-credit accounts, these recipients can differ from the protected account. An allowed extension can therefore pass authorization for a borrow or redemption with a separate recipient.
supply
and
repay
authorize the token-paying
from
account. Their
to
parameter identifies the account receiving the supply balance or having its debt reduced, respectively. For a supply made on an account’s behalf, the core’s
safeTransferFrom
still needs the payer’s tokens and applicable token spending allowance. The
liquidate
function applies its authorization check to the named liquidator.
Authorization alone doesn’t complete an operation. A borrow still requires a listed market with borrowing unpaused, enough market cash, and compliance with any configured borrow cap. It then applies the credit-limit or account-liquidity condition appropriate to the borrower. Redemption checks the supply claim and market cash, then calls the account-liquidity check. The deferral mechanism changes the timing of that last check under its own conditions.
Batch operations and deferred liquidity checks
The
v2 extension contracts
include
TxBuilderExtension.sol
for combining operations in one transaction and
UniswapExtension.sol
for leverage, debt swaps, and collateral swaps. Calls these extensions make to protected pool functions remain subject to the affected account’s authorization.
deferLiquidityCheck(user, data)
requires authorization for
user
and excludes credit accounts. It starts only from the normal liquidity-check state and invokes
onDeferredLiquidityCheck(data)
on the caller, which must implement
DeferLiquidityCheckInterface
.
The core restores the normal state after the callback returns. If the account’s deferred state was marked dirty, it then checks account liquidity. The deferral stays within that transaction; market pauses, caps, cash requirements, and other operation rules remain in force.