[SECURITY] 2 High + 1 Medium — RevenueBondFactory.redeem non-pro-rata escrow & AgentCredit.liquidate no incentive (Base mainnet)
Summary (TL;DR)
I found three vulnerabilities in the Arcis Protocol smart contracts deployed on Base mainnet (chain 8453). Two are High severity (loss of user funds / broken lending-liquidation mechanism) and one is Medium (fee-share over-minting). All were validated against a pinned commit, reproduced with executable Foundry PoCs, and confirmed on the live Base fork.
Affected contracts (live)
| Contract |
Address (Base) |
Issue |
| RevenueBondFactory |
0xEb65d8BB08e0Ea4A6Bb9162D53d1B444f99681BA |
High — non-pro-rata escrow redemption |
| AgentCredit |
0xdF31800E620F728297340d66Acf5a306f07ce7a1 |
High — no incentive to liquidate |
| ArcisVault (raUSDC) |
0x00325D9Da832B38179Ed2f0dabd4062D93E325A7 |
Medium — fee-share over-mint |
Repo / commit: Arcis-Protocol/core @ 256825bab5dbfeec7d20a878a33047a6d8c1c4db (Solidity 0.8.24).
Finding #1 — HIGH: RevenueBondFactory.redeem distributes escrow NON-pro-rata (co-investor loss, front-runnable)
File/lines: src/core/RevenueBondFactory.sol redeem() — underfunded branch, lines 227-231.
In the underfunded branch, the entire escrow balance is paid to whichever holder calls redeem first, with no reservation for other holders. Subsequent redeemers receive zero.
Scenario: Two holders (A, B) each invested 100K. Escrow = 100K (underfunded). Fair pro-rata: 50K each. Instead, A redeems first and receives the full 100K; B receives 0. B loses 100% of what it was owed. This is deterministic and front-runnable.
Impact: User-fund loss exploitable by call ordering. Severity: High.
Finding #2 — HIGH: AgentCredit.liquidate has NO economic incentive — liquidation mechanism broken
File/lines: src/core/AgentCredit.sol liquidate() (lines 217-243). The constant LIQUIDATION_BONUS_BPS = 500 (line 29) is declared but never used in the liquidation logic.
liquidate requires healthFactor < 1.0 (collateralValue < owedAmount), yet the liquidator receives only the collateral shares — which are always worth LESS than the debt it pays. No rational actor will execute a liquidation at a guaranteed loss.
Impact: The liquidation mechanism is inoperative. Insolvent positions are never closed, permanently tying up lenders' liquidity and exposing the pool to growing, irreversible bad debt. Severity: High (incentive failure in the core lending function).
Finding #3 — MEDIUM: ArcisVault.harvest over-mints fee shares to the feeRecipient
File/lines: src/core/ArcisVault.sol harvest() (lines 489-522). Fee shares are computed using totalAssets() BEFORE deployedBalance is updated (line 520), resulting in a smaller denominator and more fee shares minted than correct. Same pattern in ArcisAgentVault. The over-mint per event is small (fraction of a basis point) but accumulates as compounding fee in favor of the feeRecipient.
Impact: ERC-4626 yield-inclusion violation; deterministic over-mint favoring feeRecipient. Severity: Medium.
Reproducibility
All three findings have executable Foundry PoCs that pass and reproduce the exact scenarios described above. PoC source code and detailed logs are available privately upon request — I am withholding them from this public issue per responsible disclosure practice.
forge build
forge test --match-contract ArcisFindings -vv # both High PoCs pass
False positives explicitly ruled out
- Reentrancy: all target functions use
nonReentrant + CEI pattern.
-
- ERC-4626 donation/inflation:
totalAssets() is internal accounting; external donation not counted.
-
-
withdraw underflow with early-withdrawal fee: floor rounding keeps amount < reserveBalance.
-
-
-
- Interest-rate divide-before-multiply: rates capped at 50% APR, no usable overflow.
Disclosure protocol
- Responsible disclosure to the Arcis team (this report + private PoCs on request).
-
- 90-day window before any public disclosure (standard whitehat practice).
-
- No formal bug bounty program found; disclosing directly to the team.
Please reach out so I can share the full PoC suite privately.
[SECURITY] 2 High + 1 Medium — RevenueBondFactory.redeem non-pro-rata escrow & AgentCredit.liquidate no incentive (Base mainnet)
Summary (TL;DR)
I found three vulnerabilities in the Arcis Protocol smart contracts deployed on Base mainnet (chain 8453). Two are High severity (loss of user funds / broken lending-liquidation mechanism) and one is Medium (fee-share over-minting). All were validated against a pinned commit, reproduced with executable Foundry PoCs, and confirmed on the live Base fork.
Affected contracts (live)
0xEb65d8BB08e0Ea4A6Bb9162D53d1B444f99681BA0xdF31800E620F728297340d66Acf5a306f07ce7a10x00325D9Da832B38179Ed2f0dabd4062D93E325A7Repo / commit:
Arcis-Protocol/core@256825bab5dbfeec7d20a878a33047a6d8c1c4db(Solidity 0.8.24).Finding #1 — HIGH:
RevenueBondFactory.redeemdistributes escrow NON-pro-rata (co-investor loss, front-runnable)File/lines:
src/core/RevenueBondFactory.solredeem()— underfunded branch, lines 227-231.In the underfunded branch, the entire escrow balance is paid to whichever holder calls
redeemfirst, with no reservation for other holders. Subsequent redeemers receive zero.Scenario: Two holders (A, B) each invested 100K. Escrow = 100K (underfunded). Fair pro-rata: 50K each. Instead, A redeems first and receives the full 100K; B receives 0. B loses 100% of what it was owed. This is deterministic and front-runnable.
Impact: User-fund loss exploitable by call ordering. Severity: High.
Finding #2 — HIGH:
AgentCredit.liquidatehas NO economic incentive — liquidation mechanism brokenFile/lines:
src/core/AgentCredit.solliquidate()(lines 217-243). The constantLIQUIDATION_BONUS_BPS = 500(line 29) is declared but never used in the liquidation logic.liquidaterequireshealthFactor < 1.0(collateralValue < owedAmount), yet the liquidator receives only the collateral shares — which are always worth LESS than the debt it pays. No rational actor will execute a liquidation at a guaranteed loss.Impact: The liquidation mechanism is inoperative. Insolvent positions are never closed, permanently tying up lenders' liquidity and exposing the pool to growing, irreversible bad debt. Severity: High (incentive failure in the core lending function).
Finding #3 — MEDIUM:
ArcisVault.harvestover-mints fee shares to the feeRecipientFile/lines:
src/core/ArcisVault.solharvest()(lines 489-522). Fee shares are computed usingtotalAssets()BEFOREdeployedBalanceis updated (line 520), resulting in a smaller denominator and more fee shares minted than correct. Same pattern inArcisAgentVault. The over-mint per event is small (fraction of a basis point) but accumulates as compounding fee in favor of the feeRecipient.Impact: ERC-4626 yield-inclusion violation; deterministic over-mint favoring feeRecipient. Severity: Medium.
Reproducibility
All three findings have executable Foundry PoCs that pass and reproduce the exact scenarios described above. PoC source code and detailed logs are available privately upon request — I am withholding them from this public issue per responsible disclosure practice.
False positives explicitly ruled out
nonReentrant+ CEI pattern.totalAssets()is internal accounting; external donation not counted.withdrawunderflow with early-withdrawal fee: floor rounding keeps amount < reserveBalance.Disclosure protocol
Please reach out so I can share the full PoC suite privately.