Skip to content

[contracts] fork test profit assertion validates hot-wallet sweep, cementing bug #120 #265

@obchain

Description

@obchain

Refs #53

File: contracts/test/CharonLiquidatorFork.t.sol, _assertHappyPath(), ~line 122

Code:
uint256 ownerBalBefore = IERC20(m.debtToken).balanceOf(owner);
// ...
uint256 ownerBalAfter = IERC20(m.debtToken).balanceOf(owner);
assertGt(ownerBalAfter, ownerBalBefore, string.concat(m.name, ": owner should have received profit"));

Problem:
owner in the test is address(this) — the test contract, which acted as msg.sender for the CharonLiquidator constructor. In CharonLiquidator.sol, profit is swept to owner (the hot wallet). CLAUDE.md safety invariant: 'Profit is swept to the cold wallet inside every flash-loan callback. Do not introduce code that parks profit in the hot wallet.'

The fork test asserts profit lands at the hot wallet and treats this as correct. This cements and validates issue #120 (profit to hot wallet) rather than guarding against it. Any future PR that correctly fixes #120 by adding a coldWallet constructor arg will cause all 5 market assertions in this suite to fail, forcing a test rewrite at fix time.

PRD clause: CLAUDE.md safety invariant: profit must go to cold wallet, not hot wallet.

Impact:

  • The fork test suite provides a false green signal on the most critical financial safety invariant in the protocol.
  • CI will continue to 'pass' while funds are being swept to the wrong wallet on every production liquidation.
  • The test must be rewritten to deploy CharonLiquidator with a separate coldWallet address and assert profit lands there.

Fix:
Add a coldWallet address to the test state:
address internal coldWallet = makeAddr("coldWallet");

Construct liquidator with coldWallet:
liquidator = new CharonLiquidator(AAVE_V3_POOL, PCS_V3_ROUTER, coldWallet);

Assert:
uint256 coldBalAfter = IERC20(m.debtToken).balanceOf(coldWallet);
assertGt(coldBalAfter, coldBalBefore, ...);

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions