Skip to content

CodeWithShamim/Rota

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

43 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Rota β—Ž β€” Global Group Savings & Rotating Credit on Arc

rota (Latin): wheel. Your turn always comes.

The world has always saved in circles β€” somiti (Bangladesh), chit fund/kameti (India, Pakistan), tanda (Mexico), susu (Ghana, Caribbean), esusu/ajo (Nigeria), hui (China), paluwagan (Philippines), gam'eya (Egypt). Rota puts them all on one set of rails: smart-contract escrowed savings circles in USDC on Arc, Circle's stablecoin-native L1.

Beachhead market: Bangladesh β€” complete Bangla UI, taka amounts on every screen, somiti-native copy, and diaspora corridors (Dubai/KSA/Malaysia/UK/US β†’ Dhaka). New markets are configuration, not refactoring (see Adding a locale/currency).

Products

Product What it is
Rota Circle Classic ROSCA: N members pay a fixed USDC amount per round; each round one member takes the whole pot (fixed or random order).
Bid Circle Chit-fund mode: members who haven't won bid a discount to take the pot early; the discount is redistributed to everyone as a dividend β€” a market price for liquidity.
Goal Pot Non-rotating group saving toward a target (wedding, tuition, Eid, land). Locks until target/deadline; everyone withdraws exactly their own deposits.

Cross-cutting: contract escrow (no absconding organizer), deterministic payouts, collateral + default curing, non-custodial AutoPay, optional Giving round (labeled Zakat/Sadaqah in bn/ur), and an on-chain Credit Passport reputation score for thin-file users.

Repository layout

rota/
β”œβ”€β”€ contracts/            Foundry project (Solidity 0.8.24, OpenZeppelin 5)
β”‚   β”œβ”€β”€ src/              RotaFactory, RotaCircle, GoalPot, ReputationRegistry
β”‚   β”œβ”€β”€ test/             66 tests: happy paths, bids, autopay, defaults, fuzz, invariants, reentrancy
β”‚   └── script/           DeployLocal / DeployArc (+ script/config/ArcConfig.sol)
β”œβ”€β”€ app/                  Vite + React 18 + TS + Tailwind + wagmi v2/viem + i18next
β”‚   └── src/
β”‚       β”œβ”€β”€ config/       chain.ts (single source of chain truth), currencies.ts
β”‚       β”œβ”€β”€ abi/          AUTO-GENERATED by scripts/abi-sync.mjs
β”‚       └── i18n/         en + bn complete; es/hi/ur/tl scaffolds
β”œβ”€β”€ genlayer/             news_curator.py β€” GenLayer Intelligent Contract (AI news desk)
β”œβ”€β”€ scripts/              abi-sync.mjs, seed-local.mjs
β”œβ”€β”€ docs/                 ARC_NOTES.md (researched chain values), DECISIONS.md, ROADMAP.md
└── SECURITY.md           honest limitations β€” read it

Prerequisites

  • Foundry (forge, anvil)
  • Node β‰₯ 20, pnpm
  • A browser wallet (MetaMask) for the UI

Quickstart (local)

pnpm install

# terminal 1 β€” local chain
pnpm chain

# terminal 2 β€” deploy + wire the app + demo data
pnpm deploy:local     # MockUSDC + registry + implementations + factory,
                      # writes app/src/config/deployments.local.json, syncs ABIs
pnpm seed:local       # demo: ROSCA with 2 rounds played, bid circle mid-auction,
                      # goal pot at 60% β€” instantly demo-able
pnpm dev              # app at http://localhost:5173

In MetaMask: add network http://127.0.0.1:8545 (chain id 31337) and import anvil account #0 (0xac09…ff80 private key printed by anvil). Accounts #0–#3 are members of the seeded circles. The header has a Mint 1,000 test USDC button on anvil.

Run the contract suite:

pnpm test:contracts    # forge test β€” 74 tests, all green

Arc testnet β€” live deployment

Rota is deployed on Arc Testnet (chain id 5042002, redeployed 2026-07-12 with the audit fixes from SECURITY.md):

Contract Address
RotaFactory 0x1ba8Aabc9501d6C68A9eE1387b0d40d53EdCC325
ReputationRegistry 0xDE51D720ad3b93300e6f8A6F936f62F291c5CE80
RotaCircle implementation 0x5d5f658706acCB2B25B7f3FE22261C44DCA0DC2F
GoalPot implementation 0x0159536F931Ed1d1DdFEB4f1fc69F9f8429f0161
USDC (canonical ERC-20 interface) 0x3600000000000000000000000000000000000000

Run the app against it with VITE_CHAIN=arc pnpm dev (or set VITE_CHAIN=arc in .env / .env.local at the repo root β€” the app reads env from there). Get testnet USDC for your wallet at https://faucet.circle.com (Arc Testnet); on Arc, USDC is also the gas token.

News page β€” AI curation via GenLayer

The /news page shows the best Arc-ecosystem news and stories from Rota's domain (ROSCAs, group savings, stablecoin remittances), curated on-chain by a GenLayer Intelligent Contract (genlayer/news_curator.py) on the GenLayer Studio testnet: on each refresh_news() call, validators fetch live news feeds, run an LLM curation prompt, reach consensus, and store the result as JSON. The app reads it with genlayer-js β€” no backend, no API keys.

A curator instance is live on GenLayer studionet:

Contract Network Address
RotaNewsCurator (Intelligent Contract) GenLayer studionet 0xDFEE06117b8d91b5b3e17Bfb09C6C0592ea71690

To run your own instance, deploy news_curator.py at https://studio.genlayer.com and set VITE_GENLAYER_NEWS_CONTRACT=0x… in .env.local (see genlayer/README.md). When unset, /news shows setup instructions instead. Note: studionet resets occasionally β€” if reads fail, redeploy and update the address.

Redeploying

Chain values were researched from docs.arc.io and recorded in docs/ARC_NOTES.md: chain id 5042002, RPC https://rpc.testnet.arc.network, explorer https://testnet.arcscan.app, USDC = native gas token with an ERC-20 interface at 0x3600…0000 (6 decimals).

  1. Fund a deployer wallet with testnet USDC at https://faucet.circle.com (a full deploy costs β‰ˆ 0.12 USDC in gas).
  2. cp .env.example .env and set PRIVATE_KEY=0x… (the 0x prefix is required).
  3. pnpm deploy:arc   # sources .env/.env.local, deploys registry/implementations/factory,
                      # writes contracts/deployments/arc.json, syncs ABIs + addresses to the app

Architecture

RotaCircle state machine

stateDiagram-v2
    [*] --> OPEN: factory.createCircle (organizer auto-joins)
    OPEN --> OPEN: join() β€” collateral escrowed
    OPEN --> ACTIVE: activate() when full (payout order fixed/shuffled)
    OPEN --> CANCELLED: cancel() by organizer, or anyone after openDeadline
    ACTIVE --> ACTIVE: contribute()/pullContribution() β†’ placeBid() [BID] β†’ settleRound()
    ACTIVE --> COMPLETED: settleRound() of round N
    COMPLETED --> [*]: withdrawCollateral(), withdrawDividends()
    CANCELLED --> [*]: withdrawCollateral()
Loading

Per active round: members contribute before the schedule-anchored deadline (AutoPay lets anyone trigger an opted-in member's exact contribution); in BID mode an auction runs during the first bidWindowBps of the round; settleRound() slashes defaulter collateral, pays the optional giving cut, pays the recipient (order-based or winning bidder minus discount), credits bid dividends pull-withdrawably, and reports everything to the ReputationRegistry.

GoalPot state machine

stateDiagram-v2
    [*] --> LOCKED: factory.createGoalPot
    LOCKED --> LOCKED: deposit() (join on first deposit)
    LOCKED --> LOCKED: emergencyWithdraw() β€” haircut shared with stayers
    LOCKED --> UNLOCKED: unlock() when total β‰₯ target OR now > deadline
    UNLOCKED --> [*]: withdraw() β€” exact principal + haircut share βˆ’ giving cut
Loading

Reputation

Only factory-deployed clones can write. Transparent score: completionsΓ—100 + contributionsΓ—10 + curesΓ—20 βˆ’ defaultsΓ—50 βˆ’ earlyExitsΓ—15 (floored at 0). The frontend renders a shareable Credit Passport page per address with QR, history, and client-side signature verification β€” no backend.

Feature matrix

The phased plan behind the β€œFuture” column lives in docs/ROADMAP.md.

Feature MVP Future
ROSCA / bid / goal-pot products βœ…
Collateral, default slashing, curing βœ… multi-round collateral
Non-custodial AutoPay βœ… protocol keeper network
Giving round (Zakat/Sadaqah) βœ…
Reputation registry + passport page βœ… soul-bound token passport
en + bn locales, 7 display currencies βœ… es/hi/ur/tl translations
In-app + browser deadline reminders βœ… Telegram/WhatsApp bots
Random order via blockhash βœ… (documented) Chainlink VRF
Local anvil + Arc testnet βœ… mainnet (post-audit, post-legal)
Fiat ramps (bKash/Nagad, UPI, M-Pesa, GCash) β€” per-market integrations
Arc App Kit Unified Balance / Bridge deposits β€” chain-abstracted funding
Emergency micro-advances against reputation β€” research
AI organizer agent, mobile app β€” research

Adding a locale/currency

New markets are pure configuration:

  1. Locale: copy app/src/i18n/en.json to <code>.json, translate every key, register it in app/src/i18n/index.ts (SUPPORTED_LOCALES + resources). Missing keys automatically fall back to English, so partial translations ship safely. Scaffolds for es, hi, ur, tl already exist.
  2. Display currency: add one entry to CURRENCIES in app/src/config/currencies.ts (ISO code, symbol, Intl locale, name key) and, if the new locale should default to it, one line in LOCALE_DEFAULT_CURRENCY. Rates come from the swappable RATE_PROVIDER (free FX API, cached, display-only β€” on-chain money is always USDC).
  3. Localized product terminology (e.g. the giving label "Zakat/Sadaqah" vs "Giving") lives entirely in the locale file β€” contracts are locale-agnostic by design.

Security

Read SECURITY.md. Highlights: blockhash randomness is validator-influenceable (bounded impact), collateral can under-cover repeat defaults, AutoPay rests on standard ERC-20 allowances, FX rates are indicative, and there is no KYC/regulatory layer β€” pooled savings face financial regulation that varies by country, so Rota stays on testnet until reviewed per market.

License

MIT (contracts and app). Not audited. Not financial advice.

About

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors