Security
What has been tested, what the site checks, and what still rests on trust.
Audit status
The contracts have not been audited by a third party. The tests described below are the project's own. They show that the contracts and the site behave as intended in the cases they test, and an independent review could still find problems they miss.
Contract tests
The contract suite has 44 tests, and all 44 pass. It runs on a local Hardhat network against a mock USDG with 6 decimals:
cd contracts
npm install
npm test
| Area | What the tests check |
|---|---|
| ERC-4626 conformance and rounding | 18 decimals, USDG as the asset, name, symbol, cap and owner. The first deposit mints 10^12 share units per USDG base unit. A deposit and redeem round trip returns the deposit with no fee, and after added capital returns it minus at most one base unit. mint and withdraw follow their preview functions. |
| Added capital | addCapital and a plain USDG transfer both raise convertToAssets(1e18), and addCapital emits CapitalAdded. A zero amount and an empty vault are rejected. A later depositor buys at the current price and does not dilute earlier holders. |
| Cap and pause | maxDeposit is the cap minus totalAssets, deposits above it revert, and an exact fill works. Pause blocks deposit and mint, and never blocks redeem, withdraw, share transfers or addCapital. Only the owner can pause, unpause and set the cap. |
| Inflation and donation attack | A victim who deposits after an attacker's donation gets fair shares, and the attacker loses money. |
| Owner limits | The vault has no path for the owner to withdraw USDG or move holders' vRENT. renounceOwnership reverts on both contracts. Ownership transfer takes two steps. |
| RollRegistry | Only the owner can publish. Numbering is strict: publishing 2 before 1, publishing 0 and republishing 1 all revert. A zero hash is rejected. No function can change or delete a published Roll. rolls(n) returns the word layout the site decodes. |
| Accounting invariant | A seeded random test runs 160 operations by default across four holders: deposits, mints, redeems, withdrawals, addCapital calls and plain donations. After every step it checks that the vault could pay every holder at once and that the share price has not gone down. The default seed is 20260923; FUZZ_SEED and FUZZ_STEPS change it. |
| Operator scripts | The scripts in contracts/scripts run end to end on a local node. |
Site tests
The site suite has 19 tests, run with npm test from the project root. They cover the close engine and the Roll format, and check the site's ABI encoding against the compiled selectors.
End-to-end runs
Two end-to-end runs pass. tools/e2e-local.mjs drives the site's own wallet layer against the real contracts on a local chain. tools/e2e-operator.mjs drives the operator console in a real browser: deploy, deposit, settle, publish and pause.
Deployed bytecode
The runtime bytecode of the live RentdayVault and RollRegistry was compared with the compiled artifacts, and both match, with immutables masked for the comparison. Addresses are on Chain and addresses.
Checks the site makes
- Identity check. Before it shows vault figures, the site confirms that the configured vault's
asset()is USDG and itsdecimals()is 18. - Exact-amount approvals. A deposit asks for approval of the amount being deposited, never for an unlimited allowance.
- Chain and account re-checked. Before every transaction the site asks the wallet again for its chain ID and account, and stops if the chain is not 4663 or the account has changed.
- Quotes from the chain. Deposit and cash-out amounts come from
previewDepositandpreviewRedeemon the vault. - Reads through the public RPC. Balances, price and cap come from Robinhood Chain's public RPC, so the figures do not depend on what a wallet reports.
- Roll hashes checked in the browser. /roll#verify hashes the file in your browser and reads the registry itself.
- No keys in the page. The operator console signs every transaction in the owner's wallet, and it is excluded from the deployed site.
Known limitations
- USDG is an upgradeable, pausable token controlled by its issuer. A pause would stop cash-outs along with every other USDG transfer. The tests use a mock USDG, so they do not cover the real token's behaviour.
- The operator is trusted to claim, convert and settle the fees honestly and on time. Every step is a public transaction named in the Roll, and a hash proves a file is unchanged without proving its figures are true.
- Income depends on $RENT trading volume and can be zero.
- The creator fee's mechanics belong to Pons, outside anything these tests cover.
- Whoever holds the owner key can pause deposits, change the cap and publish a false Roll under the next number. The key cannot move USDG out of the vault.
- There has been no third-party audit.
Reporting a problem
Reach the project through @rentdayxyz on X.