Crypto Training
Kiln DeFi: Architecture, User Flows, and Security Boundaries
A code-level breakdown of Kiln DeFi vault architecture, connector model, fund flows, user deposit and withdrawal journeys, role/governance controls, and practical risk analysis.
Kiln DeFi is a modular ERC-4626 vault system designed to route a single vault asset into external yield protocols through protocol-specific connectors. The core architecture is simple in interface and explicit in control boundaries: users interact with a single vault, while governance and operations control the connector registry, fees, sanctions controls, and emergency posture.
This post is a code-first architecture analysis based on:
- local source bundle snapshot of the Kiln DeFi contracts
- Kiln product page: kiln.fi/defi
- Cantina bounty scope: cantina.xyz/bounties/c9a4b51b-2e80-4713-a06f-13524c530fa6
- linked mainnet contracts from the deployment set
What Kiln DeFi is trying to optimize#
At a product level, Kiln DeFi is optimizing for:
- single-asset user UX: users hold one vault share token and do not manage protocol-specific actions
- connector modularity: Aave, Compound, Morpho/MetaMorpho, sDAI, sUSDS, Angle savings are accessed through swappable connector contracts
- operational controls: fine-grained roles, connector pause/freeze, vault deposit pause, sanctions/blocklist checks
- fee extraction without strategy-specific share classes: deposit fee and reward fee are handled by dedicated accounting paths
The architecture favors operational simplicity over maximal decentralization. The trust model is not "set and forget". It is "governed vault with explicit operator powers and emergency levers".
Contract architecture map#
Core modules#
Vault/src/Vault.sol: user-facing ERC-4626 + accounting + role-gated admin actionsVaultFactory/src/VaultFactory.sol: beacon-proxy deployment and upgrade orchestratorConnectorRegistry/src/ConnectorRegistry.sol: connector catalog with pause/freeze mechanicsFeeDispatcher/src/FeeDispatcher.sol: fee accrual splitting and dispatchExternalAccessControl/src/ExternalAccessControl.sol: external role authority used by vault transfer controlsBlockList/src/BlockList.sol: internal blocklist + underlying sanctions list adapter
Connector implementations#
AaveV3Connector/src/connectors/AaveV3Connector.solCompoundV3Connector/src/connectors/CompoundV3Connector.solMetamorphoConnector/src/connectors/MetamorphoConnector.solSDAIConnector/src/connectors/SDAIConnector.solSUSDSConnector/src/connectors/SUSDSConnector.solAngleSavingConnector/src/connectors/AngleSavingConnector.sol
Primary code references used in this analysis#
Vault/src/Vault.sol(deposit,mint,withdraw,redeem,claimAdditionalRewards,forceWithdraw, fee and pause controls)VaultFactory/src/VaultFactory.sol(createVault,upgradeVault)ConnectorRegistry/src/ConnectorRegistry.sol(getOrRevert,pause,pauseFor,freeze)FeeDispatcher/src/FeeDispatcher.sol(dispatchFees, pending fee accounting, recipient split validation)BlockList/src/BlockList.sol(isBlocked, internal and external sanctions list composition)ExternalAccessControl/src/ExternalAccessControl.sol(external role authority for transfer restrictions)- connector implementations under each
*/src/connectors/*.sol
Deployment surface and known addresses#
From the provided address set and Sourcify metadata resolution, the following contracts are directly identified:
| Address | Resolved contract |
|---|---|
0xdE63817c82e93499357aE198518f90Ac1bE93A72 | ConnectorRegistry |
0x4A1Ede66750e8e44a1569A4Af3F53fb31De3Dd32 | VaultFactory |
0x533DD3A719968Dba0cf454C2B2a692d196DF3605 | ExternalAccessControl |
0x637F9D0E032EFb98fe8Ae55C6D798FD54060Be04 | FeeDispatcher |
0x0d87F2834b4766CAf25aD5dBE193BEd70f5D9458 | BlockListFactory |
0xB58700939159Db7a47b64FF74cF98150AccBF904 | BlockListUpgradeableBeacon |
0x08c28e1c82C09487DCB15a3e0839e8C888EeE3CD | AaveV3Connector |
0xbeaa30DCB697CFFB64E319A3Fc4b0688Be5aE790 | CompoundV3Connector |
0x22Fc700401FABbB7de1872461E8733d74e02f88a | SDAIConnector |
0xDa5FfFCF097A95E0aE6e6eC9b966da5ba89844f2 | MetamorphoConnector |
0x3443Ea9BcC9E1E515e567a278bDae103e7324d1d | AngleSavingConnector |
0xe68c8E20C4E469800A13ABeBF0Dfd094CC2C4DE2 | SUSDSConnector |
Some addresses in the list are not fully resolved via Sourcify full/partial metadata and likely correspond to implementation variants, proxy instances, or additional deployment artifacts in the same system.
Why the connector model matters#
Vault.sol delegates actual protocol interaction via functionDelegateCall to connector code fetched from ConnectorRegistry.getOrRevert(connectorName). This gives Kiln a flexible strategy endpoint with one critical implication: connector trust is system trust.
If connector logic is wrong, the vault is wrong. If registry governance changes connector pointers, vault behavior can change without changing vault bytecode.
User stories and real usage modes#
Story 1: Retail user passively farming a selected strategy#
- User deposits a base asset into a specific Kiln vault.
- User receives ERC-4626 shares immediately.
- User can redeem later, subject to actual protocol liquidity available through the connector.
Story 2: Treasury using controlled transferability mode#
- Vault transferability can be disabled.
- Only entities with
SPENDER_ROLEinExternalAccessControlcan move shares between parties. - This turns shares into policy-managed claims rather than free-float tokens.
Story 3: Managed reward operations#
- Claim manager selects
AdditionalRewardsStrategy(None,Claim,Reinvest). - For claim/reinvest connectors that support incentive flows, rewards can be harvested and either sent out or reinvested.
Story 4: Sanctions and forced offboarding#
- Internal blocklist + sanctions source can block accounts.
- For internally blocked users,
forceWithdrawpath exists (with liquidity constraints and sanctions-specific checks).
Deposit flow from the user perspective#
From UX perspective, deposit is one transaction. Under the hood, several accounting steps occur.
Step-by-step#
- User calls
deposit(assets, receiver)ormint(shares, receiver). - Vault accrues reward fee first (
_accrueRewardFee) so share math uses updated total assets baseline. - Deposit fee is computed in asset terms.
- Shares are minted to receiver based on net assets after deposit fee.
- Vault delegatecalls connector deposit for net amount.
- Deposit fee is booked as pending in
FeeDispatcher.
Important detail#
Deposit success does not mean all protocol-side risk vanished. It only means assets are now exposed to the selected connector/protocol stack. User principal is now coupled to:
- connector correctness
- protocol solvency/liquidity behavior
- governance response if incidents occur
Withdrawal flow from the user perspective#
Withdrawal and redeem are synchronous calls, but they are bounded by connector-reported liquidity.
Step-by-step#
- User calls
withdraw(assets, receiver, owner)orredeem(shares, receiver, owner). - Vault checks max withdrawable amount based on owner position and connector liquidity.
- Shares are burned.
- Vault delegatecalls connector
withdraw(asset, amount). - Connector unwinds funds from protocol and returns assets to vault context.
- Vault transfers realized amount to receiver.
Where withdrawals can fail for users#
- connector paused/frozen via registry
- insufficient protocol liquidity
- external protocol paused/degraded
- blocklist/sanctions restrictions on caller/receiver
Fee model and economics#
Kiln vault has two core fee channels:
- deposit fee: charged on incoming assets
- reward fee: charged on accrued yield (implemented via fee shares logic then collected)
Both are capped (_MAX_FEE = 35, scaled against asset decimals and _MAX_PERCENT) and routed through FeeDispatcher.
FeeDispatcher keeps pending fee balances and then dispatchFees(asset, decimals) transfers fees according to configured split recipients, requiring split sum consistency.
Additional rewards: claim vs reinvest#
Vault.claimAdditionalRewards(rewardsAsset, payload) delegates to connector logic and applies strategy mode.
Claim: collect reward token amount and emitRewardsClaimedReinvest: perform connector-defined claim/swap/redeposit pathNone: no additional rewards operation
This path can introduce a separate operational risk because payload often includes external call data for swap routes.
Access control and governance model#
The system uses role-based access heavily. The practical question is not whether roles exist, but who controls them and under what delay/multisig policy.
Key role surfaces in Vault#
FEE_MANAGER_ROLE: set fee recipients, deposit fee, reward feeFEE_COLLECTOR_ROLE: collect reward feesSANCTIONS_MANAGER_ROLE: blocklist-related control pathsCLAIM_MANAGER_ROLE: additional rewards strategy operationsPAUSER_ROLE/UNPAUSER_ROLE: deposit pause toggles
SPENDER_ROLE is checked on the external ACL contract when transferability mode is restricted.
Sanctions and forced withdrawal controls#
BlockList combines:
- internal list management
- underlying sanctions list adapter (
ISanctionsList)
Vault.notBlocked modifiers gate user actions. forceWithdraw is designed for internal sanctions offboarding and checks full-liquidity constraints before execution.
Deployment and upgrade lifecycle#
VaultFactory deploys vault beacon proxies and can perform upgrade migration steps, including fee dispatcher compatibility handling from archived versions.
Security analysis: what can go wrong#
1) Connector trust and delegatecall blast radius#
Connector logic executes in vault context through delegatecall. Any connector bug is effectively a vault bug. Registry governance controls connector addresses, so registry compromise is equivalent to strategy logic compromise.
2) Reward payload misuse risk#
Connector claim flows can process externally supplied payloads. If payload validation assumptions fail, value extraction or bad route execution risks increase.
3) Liquidity illusion risk#
maxWithdraw depends on connector/protocol conditions that can degrade quickly. Synchronous withdraw UX can still be operationally constrained by protocol-side liquidity.
4) Governance centralization risk#
Pause, fee updates, sanctions toggles, and connector management are role-gated. Without robust multisig/timelock procedures, operator key compromise can cause severe user impact.
5) Sanctions path complexity#
Internal and external blocklist composition can create edge cases in forced exits and transfer restrictions, especially under rapid sanctions list changes.
6) Upgrade and migration risk#
Factory upgrade flows are powerful. Migration logic touching fee accounting and recipient splits must be treated as high-sensitivity changes with strict test and review coverage.
Connector-by-connector behavior and design tradeoffs#
The connector layer is where Kiln becomes opinionated about each external protocol. The vault interface stays constant, but each connector decides:
- what
maxDepositmeans for that protocol - what
maxWithdrawmeans under current liquidity - whether incentives can be claimed
- whether incentives can be reinvested
That means two vaults with the same ERC-4626 interface can have very different runtime behavior depending on connector choice.
Aave V3 connector#
AaveV3Connector routes deposits through Aave Pool supply and withdraws through Pool withdraw. It derives deposit limits from reserve cap/usage and derives withdraw limits from aToken liquidity constraints.
It also supports reward claiming and reinvest-style pathways with payload-driven logic, which is useful operationally but expands payload validation responsibility.
Compound V3 connector#
CompoundV3Connector integrates through Comet supply/withdraw and reward controller claim flow. Market selection relies on registry lookup for the asset-to-market mapping.
Operationally this is similar to Aave connector shape, but risk posture differs because Comet market and reward plumbing are distinct systems.
MetaMorpho connector#
MetamorphoConnector is effectively ERC-4626 passthrough behavior into a MetaMorpho vault for the configured asset. It intentionally does not implement extra reward claim/reinvest beyond core vault share value accrual.
This is cleaner from a call-surface perspective: fewer payload-heavy functions, but less flexibility for active rewards operations.
sDAI, sUSDS, Angle connectors#
These connectors mostly expose straightforward deposit/withdraw wrappers around ERC-4626-like savings constructs. Reward claim/reinvest is not the center of their model in this code path.
Angle connector includes paused-state awareness in max limits, which is a practical detail that prevents optimistic previews when protocol-level operations are paused.
Accounting invariants that should hold#
A robust user-facing vault is not only about successful calls. It is about preserving accounting invariants under stress.
Invariant family 1: share mint/burn coherence#
- shares minted on deposit should match net assets after deposit fee under current conversion assumptions
- shares burned on redeem should not exceed owner entitlement
- fee share minting should not silently dilute beyond configured fee logic
Invariant family 2: fee buckets are conservative#
- pending fee counters should only increase from authorized paths
- dispatch should never exceed pending balances
- recipient splits should sum correctly and avoid dust leakage from misconfigured scaling
Invariant family 3: total assets monotonicity assumptions are explicit#
During normal operation, total assets may increase with yield and decrease during withdrawals. But internally, fee accrual and conversion paths must not create accounting states where user-previewed conversions are structurally impossible to fulfill.
Invariant family 4: pause/freeze semantics are consistent#
- connector pause should block runtime connector retrieval for operations that need it
- vault deposit pause should reliably block deposit/mint paths
- pausing should not create hidden bypasses through alternate user entry points
A complete user journey with realistic edge conditions#
Journey A: successful lifecycle#
- User evaluates vault and connector choice.
- User deposits assets and receives shares.
- Over time, rewards accrue and may be harvested/reinvested by ops.
- User redeems shares and receives base asset.
This is the ideal path, and for most users this is what matters.
Journey B: stress lifecycle#
- User deposits successfully.
- External protocol enters partial liquidity crunch.
maxWithdrawfalls below user expectation.- User redeem reverts or can only redeem smaller chunks over time.
- Governance may pause deposits and adjust operations while liquidity normalizes.
The key takeaway: ERC-4626 UX can still be operationally constrained by external liquidity states.
Journey C: policy-enforced lifecycle#
- User shares are held in non-transferable mode environment.
- Transfer attempt fails unless sender or target has external
SPENDER_ROLE. - If internal sanctions logic flags account, normal interactions fail by design.
This is not a bug. It is policy posture.
Where Kiln DeFi differs from async queue vault designs#
Kiln DeFi here is primarily synchronous ERC-4626 interaction with protocol routing behind connectors. That is structurally different from async request/settlement queue systems.
Synchronous model strengths#
- simple user mental model
- immediate mint/redeem semantics when liquidity allows
- thinner state machine around requests
Synchronous model weaknesses#
- more direct dependence on real-time protocol liquidity
- less natural buffering for batched settlement under stress
- potential UX volatility during rapid market dislocations
Async model strengths (in general)#
- explicit request queueing during stress
- deterministic settlement windows
- reduced immediate liquidity pressure on each user call
Async model weaknesses (in general)#
- more moving parts and request accounting complexity
- delayed user finality by design
- more operator/reporting dependencies
Incident response design: what operators should predefine#
The contracts provide controls, but controls without runbooks are not enough. A production deployment should have explicit incident response runbooks.
Runbook 1: connector-level incident#
- trigger: connector bug or abnormal protocol behavior
- immediate action: pause connector in registry
- secondary action: pause deposits at vault level if needed
- communication action: publish user status and expected timeline
- recovery action: move to alternate connector only after code review + simulation
Runbook 2: protocol liquidity drought#
- trigger: withdraw slippage/revert patterns or liquidity metrics breach
- immediate action: monitor
maxWithdrawdrift and publish guidance - optional action: temporary deposit pause to prevent one-sided flow
- recovery action: staged operations once liquidity normalizes
Runbook 3: compromised operational key#
- trigger: suspicious role action or key compromise evidence
- immediate action: revoke role grants in admin flow
- secondary action: freeze sensitive connectors
- recovery action: rotate keys, perform postmortem, then re-enable operations
Deep dive on fee fairness from user perspective#
From a user perspective, fee fairness means:
- can I predict effective entry price after deposit fee?
- can I understand ongoing reward fee extraction impact?
- are recipients and splits transparent and stable?
The fee model is legible because deposit and reward fees are separated and tracked in dispatcher state. But governance still controls parameters. So transparency and announcement policy matters as much as raw code.
Practical fairness checklist#
- disclose fee values with decimals scaling interpretation
- disclose split recipients and rationale
- disclose admin delay and procedure for fee changes
- monitor pending fee growth against vault growth
Security test priorities for auditors and protocol engineers#
If auditing or extending this architecture, prioritize tests around the highest-blast-radius paths first.
Priority 1: delegatecall connector safety#
- malicious connector simulation
- connector upgrade/pointer swap abuse
- storage collision assumptions if connector code changes drastically
Priority 2: conversion edge-case fuzzing#
- low supply and low assets edge cases
- fee near cap behavior under tiny deposits
- rounding paths for preview vs execution parity
Priority 3: role bypass attempts#
- unauthorized caller paths for all admin functions
- transfer restrictions with and without external spender role
- sanctions-related bypass attempts across all user entry points
Priority 4: rewards payload abuse#
- malformed payloads
- payloads that target unintended call graphs
- gas griefing and reentrancy-adjacent scenarios in claim/reinvest flows
Operational metrics worth tracking in production#
A mature deployment should track runtime metrics continuously, not only after incidents.
Core metrics#
- vault TVL by connector and by protocol exposure
- deposit and redeem success rates
- average redeem gas and failure reasons
maxWithdrawtrend vs total user position- pending fee balances and dispatch cadence
- role grant/revoke events
- connector pause/freeze events
Risk metrics#
- concentration per external protocol
- liquidity-at-risk under stressed withdrawal assumptions
- claim/reinvest operation failure rates
- sanctions/blocklist event frequency and impact scope
Practical threat model by actor#
| Actor | Capability | What users trust them for |
|---|---|---|
| Vault governance/admin | role grants, fee config, pause/unpause | fair operation, non-abusive fee and policy changes |
| Connector manager | connector add/pause/freeze | safe connector bytecode and incident response |
| Claim manager | reward strategy and execution payloads | no value-destructive claim/reinvest behavior |
| Sanctions manager | blocklist and sanctions list updates | lawful and consistent offboarding behavior |
| External protocol governance | Aave/Compound/Morpho/etc behavior | solvency, liquidity, oracle safety |
User-facing deposit and withdrawal UX summary#
What users see#
- one vault token
deposit,mint,withdraw,redeemstandard ERC-4626 style methods- fees reflected in shares/assets conversion
What users should understand before using#
- this is not passive immutable logic
- connector and governance controls are active moving parts
- liquidity and reward behavior depend on external protocol conditions
- sanctions and transferability settings can alter account behavior materially
What is strong in this design#
- clear module boundaries
- explicit and auditable role gates
- broad connector portability for same ERC-4626 vault surface
- operational controls for pause/freeze/blocklist scenarios
What deserves extra caution in production#
- delegatecall connector architecture requires strict connector QA and governance hardening
- reward payload surfaces should be tightly constrained and monitored
- emergency and sanctions paths need runbooks and regression tests
- users should receive clear documentation of who controls each role on each deployed vault
Engineering checklist for integrators#
If you integrate Kiln DeFi vaults in wallet/UI/backend stacks:
- Verify connector name and connector contract for each vault before depositing.
- Track role holders and admin delay settings, not just vault TVL/APY.
- Monitor registry pause/freeze events and vault deposit pause state.
- Track pending fee dynamics and recipient changes over time.
- Simulate redeem under stressed liquidity conditions, not only happy-path previews.
- Alert on claim strategy changes and reward payload execution anomalies.
Final view#
Kiln DeFi is a strong example of an operationally managed ERC-4626 platform architecture. It is simple for end users at the interface level and complex where it matters: connector routing, governance controls, and risk operations.
That tradeoff can work well in production if governance discipline is high and connector quality is continuously audited. If governance discipline degrades, the same flexibility that enables protocol agility can become the dominant risk factor.
References#
- Product page: https://www.kiln.fi/defi
- Cantina scope: https://cantina.xyz/bounties/c9a4b51b-2e80-4713-a06f-13524c530fa6
- Audit list page: https://kilnfi.notion.site/EXTERNAL-AUDITS-479819dce90540d1a0800c0541d2352b
- Deployment links (examples from provided set):
- https://etherscan.io/address/0xdE63817c82e93499357aE198518f90Ac1bE93A72
- https://etherscan.io/address/0x4A1Ede66750e8e44a1569A4Af3F53fb31De3Dd32
- https://etherscan.io/address/0x637F9D0E032EFb98fe8Ae55C6D798FD54060Be04
- https://etherscan.io/address/0x08c28e1c82C09487DCB15a3e0839e8C888EeE3CD
- https://etherscan.io/address/0xbeaa30DCB697CFFB64E319A3Fc4b0688Be5aE790
- https://etherscan.io/address/0xDa5FfFCF097A95E0aE6e6eC9b966da5ba89844f2