Rota is an MVP running on Arc testnet only. It has not been audited. This file honestly lists the known limitations and design trade-offs.
RANDOM_ORDER derives its permutation from
keccak256(secret, blockhash(fullBlock), address(this), members), where secret
is committed by the organizer at creation (seedCommit = keccak256(secret)) and
revealed via activateWithSeed(). This splits control so neither side can steer it:
- The organizer fixes
secretbefore any member joins, so they cannot aim it at a particular ordering. blockhash(fullBlock)is fixed when the last member joins and is unknown at commit time. A validator can grind it, but withoutsecretthey cannot compute the permutation it produces — the grinding is blind.
On Arc, block.prevrandao always returns 0 (see docs/ARC_NOTES.md), so there is
no in-protocol randomness beyond blockhash, and no VRF is available.
Residual risk. At reveal time the organizer can compute the resulting order and
choose to withhold, letting the circle fall back to join order after REVEAL_WINDOW
(1 day). That is a one-bit choice between two orders, neither of which they picked —
inherent to any reveal scheme without a VRF. A real VRF would remove it.
Liveness. An organizer who loses or withholds the secret cannot hold the circle
hostage: once REVEAL_WINDOW has elapsed after the circle fills, anyone may call
activate() and the circle starts in join order.
Operational caveat. The secret must survive between two transactions, and the web
app keeps it in localStorage keyed by the circle address. Clearing site data, or
activating from a different browser or device, loses it — the circle still starts, but
in join order rather than shuffled.
Collateral is collateralBps of one contribution. A member who defaults in more
rounds than their collateral covers produces a shortfall: that round's recipient
receives a smaller pot. The shortfall is only made whole if the defaulter later calls
cureDefault(). Organizers should choose collateralBps (up to 100%) with this in
mind; multi-round collateral is future work.
Rounds are schedule-anchored. If nobody calls settleRound() long after a deadline,
the next round's contribution (and bid) window may be partially or fully elapsed when
it opens, potentially causing cascading defaults. Any member, keeper, or bot can
settle — the UI surfaces "settle available" prominently — but there is no protocol-run
keeper yet.
AutoPay is non-custodial and bounded: the contract can pull only the exact
contributionAmount, once per round, only while the member is opted in and the round
is open. However the ERC-20 allowance backing it is a standard approval: if the user
approves "unlimited" and the circle contract were somehow compromised, the allowance
is exposed. Rota defaults to exact-amount approvals and treats unlimited approval as
an advanced option. Opting out does not revoke the ERC-20 allowance — revoke it in
your wallet if desired.
The organizer controls the allowlist of invite-only circles/pots and may cancel any
not-yet-activated circle — including a full one racing against activate(). They have no access to escrowed funds. givingRecipient
is fixed at creation — verify it before joining a circle with a giving cut.
Bid-discount division dust goes to the round's recipient; fallback-distribution and final-round dust (micro-USDC scale) can remain in the contract permanently. GoalPot haircut shares round down against the unlock snapshot, so a few micro-USDC may remain there too.
Contracts assume a standard, non-fee-on-transfer, non-rebasing 6-decimal ERC-20 (USDC). Arc's USDC ERC-20 interface satisfies this. Do not deploy circles over exotic tokens.
USDC can blacklist addresses. Settlement and withdrawals are hardened against this:
if a round recipient or givingRecipient cannot receive tokens, settleRound()
credits the amount to their withdrawable dividend balance (event PayoutDeferred)
instead of reverting, and GoalPot defers the giving cut to pendingGiving
(retryable by anyone via flushGiving()). A frozen address can therefore never
freeze other members' funds; only its own.
The factory is permissionless and accepts any ERC-20, so an attacker can run circles/pots among their own wallets (even with a worthless token, or with USDC cycling between their own addresses and 1-second rounds) to inflate their Credit Passport at roughly gas cost. GoalPot credits at most one contribution per member per pot (dust-deposit spam is capped), but completions remain farmable. Treat the score as a within-community signal — verify the circles behind a score (token, members, amounts, durations are all on-chain) before extending real trust. Sybil resistance (token allowlist, stake- or time-weighted scoring) is future work.
emergencyWithdraw() is unavailable once a pot is unlockable (target reached or
deadline passed), so the giving cut cannot be dodged at the finish line. Before
that point, an exit pays the haircut instead of the giving cut; if an organizer
sets givingBps higher than earlyExitHaircutBps, exiting early remains cheaper
than staying. Choose earlyExitHaircutBps >= givingBps if that matters.
The haircut pool is paid out only by withdraw(), pro-rata against the deposit
total snapshotted at unlock. An exit that empties the pot therefore leaves nobody
to compensate, so it takes no haircut and sweeps the pool left by earlier
exits — the last member standing is exactly who the pool is for. Without this the
pool would be locked in the contract forever (the snapshot, and every remaining
claim, would be zero).
- FX rates are indicative. Local-currency figures come from a free client-side API, cached up to 12 h, and are never used in on-chain math. The exact USDC amount is always shown before signing.
- Invite links are not access control. Anyone with the link can join a non-invite-only circle; use invite-only + allowlist for closed groups.
- The "verify ownership" badge on the Credit Passport is a client-side signature check for in-person/screen-share verification, not a server-attested claim.
Rota has no KYC/AML layer and no licensing. Pooled-savings and rotating-credit products are regulated financial activity in many jurisdictions (e.g. chit funds are licensed in India; deposit-taking rules may apply in Bangladesh, the UK, and the US; money-transmission rules may apply to cross-border circles). This project must stay on testnet until reviewed per target market. Nothing here is an offer of financial services.
This is a demo codebase; open an issue in the repository for any vulnerability found.