We tried to steal from a fund five ways. The contract refused every one.

This is not an audit badge. It is a record of attempts, run against a fork of Robinhood Chain mainnet with the real NVDA and USDG pool and the real Chainlink NVDA feed, because a guard that only holds against a mock is not a guard.

6 of 6
attempts against real liquidity
8 of 8
with a price the test can move

What was tried, and what happened

Each row is one test in test/ForkManagedFund.t.sol, written from the manager's side, trying to get paid.

1

The manager takes the money out.

There is no door. The only path that moves value out of a fund is withdraw, and withdraw pays the caller a proportional slice of the shares the caller holds. The manager holds none of the depositor's, so the call dies on NoShares and their balance at the end of it is still zero.

Refused
2

The manager buys a worthless token they minted themselves.

Both sides of every trade have to be on a list fixed when the fund was built. The fresh token is not on that list, so the trade is refused with NotAllowed before any money moves. This is also why a fund here can only hold stock: the moment any token can be bought, any token can be used to steal, and no guard can tell the two apart.

Refused
3

The manager makes the fund call another contract.

The test knocks on the five doors an escape hatch usually hides behind: execute, call, multicall, sweep, rescue. None of them are there. No function anywhere in the fund takes a target address or calldata, so this attempt cannot even be written down.

Refused
4

Somebody who is not the manager trades the fund.

The depositor, whose money it actually is, tries to move it herself. NotManager. Permission to trade and ownership of the money are two separate things in this contract, and neither one can reach across into the other.

Refused
5

The manager promises nothing and takes a terrible fill.

This is how trading vaults are really drained. The manager sets the slippage limit to zero, accepts a dreadful price, and collects the difference as the other side of the trade. A fund that only honours the manager's own promise waves this through, so this one measures the price the trade actually got and checks it against Chainlink afterwards. The fill was refused, and the fund is holding no NVDA at the end of it.

Refused
6

An honest trade, and then the investor leaves.

The five refusals are worth nothing if the fund no longer works. So the last one is the ordinary day: money in, NVDA bought at the real pool price, and the investor withdrawing her exact proportional slice of what the fund is holding.

10,000 USDG
deposited
23.355 NVDA
traded into
9,997.05 USDG
fund worth after
0.03%
cost of the round trip
Passed

Eight more, with a price the test can move

A fork gives real liquidity, but the price on a fork only does what the market did that day. To ask what a manager earns when a fund doubles, and what they earn when it halves, the feed has to be one the test can push around. All eight of these are in test/ManagedFund.t.sol.

Can anyone open a fund?
Yes. One call to the factory, and the fund exists.
Can a manager set any fee they like?
No. The factory caps the performance fee at 30% of the profit.
Can a manager trade before putting their own money in?
No. They have to be invested in their own fund first.
Is a fill above the feed refused?
Yes. And the fund is holding nothing afterwards, so none of it leaked through.
Is the manager paid a tenth of the gain?
Yes. Out of the shares being redeemed, which is why it is a claim on the fund and never a transfer out of it.
Is the manager paid on a loss?
No. Below your own high-water mark they work for free.
Does a late depositor pay for profit earned before they arrived?
No. Your mark is the share price on the day you put money in.
Can somebody leave while the feed is frozen?
Yes. In kind, with their exact slice, and the manager is not paid.

The days a fund cannot be priced

A stock feed updates 24 hours a day, 5 days a week, and stops outright while a corporate action is being processed. The pools never stop. So for most of any given week there is no honest price for a fund that holds stock, and the contract splits that problem in two.

Deposits refuse.

Handing out new shares needs a price, and a guessed one hands the difference to whoever deposits at exactly the right moment. So the fund says no until the feed is warm again.

Exits always work.

Your payout is a proportional slice of every holding, which needs no price at all. A closed market can never trap you in somebody else's fund.

The manager is not paid.

The only thing in the whole fund that needs a price is the fee. When the fund cannot be priced you still leave with your exact slice, and the manager simply gets nothing.

Go and run them

Nothing here needs anything from us. The fork test dials Robinhood Chain's public RPC itself.

forge test --match-path test/ForkManagedFund.t.sol -vv
test/ForkManagedFund.t.solThe five attacks, against real liquidity.
test/ManagedFund.t.solThe fee, the manager's own stake, and the frozen feed.
src/ManagedFund.solThe fund, and the three walls around the manager.
src/FundFactory.solOpening one, and the list the board reads.