Skip to content

Repository files navigation

Презентация: SheikhFiDApp.pdf

Видео: 20250720 Алексей Цветков Шейх-fi Singularity x БАШНЯ

Демо: Шейх-Fi DApp в сети Base Sepolia

SheikhFi - Исламская DeFi платформа

SheikhFi реализует принципы исламского финансирования (Islamic Finance) в децентрализованной среде. Основные принципы исламского финансирования воплощены в следующих механизмах:

Партнёрство инвесторов (Musharaka)

  • Инвесторы объединяют свои средства в общий фонд
  • Каждый инвестор имеет право голоса при принятии решений об использовании общих средств
  • Прибыль и убытки распределяются пропорционально вложенным средствам

Доверительное управление (Mudaraba)

  • Управляющие (менеджеры) получают средства от инвесторов для реализации инвестиционных проектов
  • Управляющие несут ответственность за эффективное использование средств
  • Прибыль от проектов распределяется между инвесторами и управляющими по заранее установленным ставкам

Реальные активы как обеспечение

  • Все инвестиционные сделки должны быть обеспечены реальными активами
  • Управляющие должны предоставить описание проекта и требуемую сумму финансирования
  • Проекты проходят процедуру одобрения инвесторами перед финансированием

Механизм одобрения проектов

  • Предложение (submitProposal) несёт описание, IPFS-хэш документов реального актива и число траншей
  • Голосование открывается только после сертификации шариатским советом (certifyProposal); совет назначается владельцем (setBoard)
  • Для финансирования проекта необходимо получить одобрение от инвесторов, владеющих определённой долей от общего фонда
  • Порог одобрения (approval threshold) устанавливается при создании контракта и может быть изменён владельцем (setApproveShareThreshold)
  • Вес голоса фиксируется в момент голосования — последующие депозиты или выходы не меняют уже поданные голоса
  • Голосование ограничено дедлайном (votingPeriod, по умолчанию 30 дней); незасекьюренное предложение может отменить его автор или владелец (cancelProposal)
  • При достижении порога резервируется вся сумма, но управляющему зачисляется только первый транш; следующие транши совет открывает по вехам (releaseTranche)
  • Управляющий может добровольно внести залог (postCollateral); изъять его может только совет вердиктом с фиксацией основания (slashCollateral) — за нарушение, не за коммерческий убыток

Полный цикл капитала (v2)

  • Тело инвестиции управляющий возвращает отдельно (returnPrincipal) — без комиссий, средства сразу пополняют свободный пул
  • Прибыль (receiveRevenuedistributeRevenue) признаётся только после полного возврата тела — до этого распределение ревертится (Principal outstanding)
  • Прибыль распределяется между:
    • Управляющим (по установленной ставке — теперь строго из прибыли, не из оборота)
    • Инвесторами (по их доле в общем фонде)
    • Владельцем контракта (операционные расходы)
  • Невозвращённое тело провалившегося проекта владелец списывает (writeOffProposal) — убыток ложится на всех инвесторов строго пропорционально долям
  • Инвестор может выйти из пула (exit) в пределах свободных средств; доля к выходу уже амортизирована списанными убытками
  • Средства не отправляются автоматически — каждый участник вызывает withdraw() для получения своей доли. Доля инвестора фиксируется в момент вызова withdraw() или явного вызова settle()
  • Владелец передаётся в два шага (transferOwnershipacceptOwnership); новый владелец обязан заранее быть инвестором
  • Доля инвестора — это ERC-20 токен SHFI («SheikhFi Musharaka Share»): balanceOf = вклад, переводы разрешены только между онборженными инвесторами, прибыль обеих сторон кристаллизуется до перевода
  • Пул может вестись не в ETH, а в ERC-20 (например, USDC): адрес токена передаётся в конструктор; демо работает в нативном ETH

Трассировка этих механизмов на пункты стандартов AAOIFI — в STANDARDS.md.

Соответствие принципам Шариата

Каждый механизм контракта трассирован на пункты стандартов AAOIFI с дословными цитатами, ссылками на реализацию и тесты — STANDARDS.md. Несущие функции цитируют свой пункт в NatSpec; шариатские инварианты (I1–I6) непрерывно проверяются на случайных последовательностях операций (test/Invariants.test.js).

Архитектура веб-приложения

Консольный многоэкранный интерфейс (sidebar + main column), пять экранов:

Экран Содержимое
Overview KPI-полоса (Total / Free / Revenue / Threshold), топ-3 предложения, панель принципов Musharaka/Mudaraba
Desk (роль-зависимый) Council — онбординг партнёров и операторов · Operator — подача предложения и доставка выручки · Partner — депозит, моя позиция, предложения на голосование · Guest — приглашение подключить кошелёк
Proposals Карточки предложений с фильтрами (All / Pending / Secured / Settled), прогресс-бар с отметкой порога одобрения, кнопка Approve
Treasury Deployed / Free / Settled KPI, ссылка на контракт в обозревателе сети, история выручки, панель «Distribute revenue» (только для Council)
Members Партнёры (Musharaka) и операторы (Mudaraba) с аватарами и статистикой
Activity Хронологический фид всех событий контракта (InvestorAdded, ManagerAdded, FundsDeposited, ProposalSubmitted, ProposalApproved, ProposalFunded, RevenueReceived, RevenueDistributed, Withdrawn) с ссылками на транзакции в обозревателе

Роль (Council / Operator / Partner / Guest) определяется по адресу подключённого MetaMask через isManager, isInvestor и сравнение с owner(). Адресу owner соответствует Council-роль; одобрение проектов доступно Council и Partner.

Метаданные сети (имя, обозреватель, RPC, native-токен) описаны в webapp/src/networks.js. При подключении кошелька веб-приложение автоматически переключает MetaMask на нужный chainId (или добавляет сеть, если её нет).

Поле deployBlock в webapp/src/abi/deployment.json — номер блока, в котором был размещён контракт. Экран Activity опирается на него, чтобы не сканировать всю историю сети: он перебирает блоки от deployBlock до latest чанками по 800 (лимит публичного RPC eth_getLogs) и декодирует все события контракта одним фильтром по адресу. deploy.js записывает это поле автоматически.

Тестовая сеть

Контракт развёрнут в Base Sepolia (chainId 84532, RPC https://sepolia.base.org, обозреватель https://sepolia.basescan.org): на 2026 год это единственный публичный testnet с программным faucet без mainnet-gate — через Coinbase Developer Platform.

Текущий деплой (v7: тайм-лок вердиктов совета с заморозкой залога и конфигурируемой задержкой; плюс весь v6/v5):

Поле Значение
Адрес контракта 0xD9aB8c35E46753264f1BC02b3937792EA7705D74
Владелец 0xC7120b785Fc0877bb370E3EDe2dAE15F07d12A73 (Ali)
Шариатский совет 0xf6eb5bbBAb196242Afcda8fe6bF6A37EfC1f26b4 (отдельный ключ — v5 §5)
Approval threshold 60%
Участники Bob (инвестор, 95%), Charlie (управляющий, 20%), AliLegacy (инвестор)

Бутстрап совета (до первого разделения) и пополнение его газа: node scripts/set-board.mjs 0xAddr [gasEth]; дальнейшая смена — только избранием партнёрами (v6: nominateBoardapproveBoardacceptBoardSeat).

Архивные деплои: v6 в Base Sepolia (0x9811c5b8c466F127B0CCf27Ee303f1E8e6670681), v5 в Base Sepolia (0x7F4d6b3abCE0D03cB75432B719326DBD9540C76b), v3 в Base Sepolia (0xE0b29B49Af548a7cBAf7CaAc999197D895d8D0E0), первая версия в Base Sepolia (0x3743aCa3d2ED36744703C36c6AfB27B8E3A444Db, владелец 0xb853…c807) и Polygon Amoy (0x408f311ff021e4bba7a3088b6a1c4af1a9c23994). Веб-приложение определяет возможности контракта по ABI (feature-detect), поэтому одинаково работает и со старыми деплоями, и с v7.

Архивный деплой в Polygon Amoy (0x408f311ff021e4bba7a3088b6a1c4af1a9c23994) больше не используется веб-приложением, но сохранён в webapp/src/networks.js как известная сеть для обратной совместимости.

Как запустить (локально)

Тулчейн не ставится на хост — все команды идут через compose-тулбокс (docker-compose.yml, node 20.19.0, репозиторий примонтирован):

# всё сразу: доказательства + тесты + coverage + lint + build + контейнерный e2e
./scripts/verify.sh

# формальная верификация: доказывает шариатские инварианты для всех входов
# (Halmos, ~4 с) — подробности и границы в STANDARDS.md
docker compose run --rm halmos

docker compose run --rm node 'npm ci && npx hardhat test'
docker compose run --rm node 'npx hardhat coverage'
docker compose run --rm node 'cd webapp && npm ci && npm run lint && npm run build'

# локальный демо-режим: hardhat node + посев Bob+Charlie
docker compose run --rm node 'npx hardhat node'   # в другом терминале
docker compose run --rm node 'npx hardhat run deploy.js --network localhost'
docker compose run --rm node 'cd webapp && npm run dev'

# сквозной e2e: chain → deploy → webapp → playwright-смок, всё в контейнерах
docker compose --profile e2e up --abort-on-container-exit e2e
# локальный деплой переключает активную конфигурацию на 31337 — вернуть демо:
docker compose run --rm node 'node scripts/use-deployment.mjs 84532'

В режиме localhost deploy.js использует второй и третий signer hardhat-а как Bob (инвестор) и Charlie (управляющий) — демо-поток готов сразу.

Как опубликовать в Base Sepolia

# 1. Создать кошелёк-деплойер (один раз) и положить ключ в .env
cp .env.example .env
# заполнить DEPLOYER_PRIVATE_KEY и DEPLOYER_ADDRESS
# (можно сгенерировать: node -e 'const {ethers}=require("ethers"); const w=ethers.Wallet.createRandom(); console.log(w.address, w.privateKey)')

# 2. Получить API-ключ CDP (Coinbase Developer Platform) и положить
#    CDP_API_KEY_ID / CDP_API_KEY_SECRET / CDP_WALLET_SECRET в .env
#    https://portal.cdp.coinbase.com/

# 3. Пополнить деплойер 0.0001 ETH через программный faucet
node scripts/faucet.mjs
# тот же скрипт принимает произвольные адреса и пополняет каждый:
# node scripts/faucet.mjs 0xPartner... 0xOperator...

# 4. Скомпилировать и развернуть контракт
npx hardhat compile
npx hardhat run deploy.js --network baseSepolia
# запишутся webapp/src/abi/deployments/<chainId>.json (пер-чейн снапшот)
# и webapp/src/abi/deployment.json (активная копия, её импортирует webapp);
# переключение активного деплоя: node scripts/use-deployment.mjs <chainId>

# 5. (опционально) верифицировать исходники на BaseScan
#    нужен ETHERSCAN_API_KEY (V2) в .env
npx hardhat verify --network baseSepolia <адрес> "Ali" 60

Публикация на GitHub Pages — автоматическая: workflow pages.yml на каждый push в main гоняет тесты контракта и lint webapp, собирает webapp/dist и force-пушит его orphan-коммитом в ветку gh-pages (или вручную через workflow_dispatch). Руками ветку gh-pages трогать не нужно.

deploy.js понимает обе ситуации:

  • если у сети несколько signer-ов (hardhat/localhost) — посев Bob + Charlie выполняется автоматически;
  • если signer один (любой реальный testnet, включая baseSepolia) — посев пропускается, и онбординг участников делается отдельно через UI (Council desk) или через скрипт ниже.

Добавление участников

В реальной сети развёрнутый контракт не знает ни про Bob-а, ни про Charlie-я. Council (владелец) добавляет адреса MetaMask пользователей через метод addInvestor или addManager. Два способа:

Через UI. Импортировать DEPLOYER_PRIVATE_KEY в MetaMask (или подключить уже существующий кошелёк, который является owner-ом контракта), открыть демо, переключиться на Base Sepolia — сайдбар покажет «Council desk», в нём поля «Onboard partner / operator».

Через скрипт. Деплойер остаётся серверным (ключ не уходит в MetaMask). Council вызывает контракт из CLI:

# партнёр (инвестор) с долей в прибыли 50%
node scripts/onboard.mjs investor 0xYour... "Имя" 50

# оператор (управляющий) с долей в выручке 20%
node scripts/onboard.mjs manager  0xYour... "Имя" 20

После подтверждения транзакции пользователь открывает демо, подключает свой MetaMask — роль определяется автоматически.

profitRate — это процент:

  • для инвестора: доля валовой прибыли, которую он сохраняет до отчисления владельцу;
  • для управляющего: доля выручки проекта, которую он удерживает до распределения между инвесторами.

Мониторинг и отладка

scripts/monitor.mjs — фоновый «tail» состояния контракта. Опрашивает Base Sepolia каждые 5 секунд и пишет дифф к предыдущему снимку: новые предложения, новые голоса, флип secured, revenueReceived / revenuePayed, изменения балансов и withdrawable всех зарегистрированных участников.

node scripts/monitor.mjs                       # отслеживать всех инвесторов + менеджеров + владельца
node scripts/monitor.mjs 0xExtra...            # плюс произвольные адреса по CLI

Список отслеживаемых читается из контракта на старте (getInvestorCount / getManagerCount), так что после онбординга нового участника достаточно перезапустить скрипт — никаких правок кода.

scripts/members.mjs — одноразовый срез состава и балансов деплоя: owner/board/asset, инвесторы (ставка, вклад, прибыль, withdrawable, баланс газа) и управляющие (+ залог). Без аргумента читает активный деплой; с адресом — любой контракт той же формы (так переносится состав участников на новый деплой):

docker compose run --rm node 'node scripts/members.mjs'
docker compose run --rm node 'node scripts/members.mjs 0x3743aCa3d2ED36744703C36c6AfB27B8E3A444Db'

Обе утилиты ходят через публичный RPC с пейсингом и ретраями на rate-limit.

Структура репозитория

contracts/
  SheikhFi.sol            смарт-контракт пула + предложений + распределения
  BadReceiver.sol         тестовый «злой получатель»: контракт-инвестор, который реверт-ит при получении ETH
test/
  *.js                    hardhat-тесты (101 passing)
e2e/
  tests/smoke.spec.js     playwright-смок против контейнерного стека (read-only, без MetaMask)
deploy.js                 скрипт деплоя (поддерживает localhost и baseSepolia)
hardhat.config.js         сети: hardhat / localhost / baseSepolia / amoy; оптимизатор; ключи из .env
docker-compose.yml        compose-тулбокс: docker compose run --rm node '<cmd>' (node 20.19.0)
AGENTS.md                 метод репозитория: рабочий цикл, чек-лист аудита, как повторить с другим бизнес-процессом
STANDARDS.md              трассировка: требование → пункт AAOIFI (цитата) → реализация → тесты
PLAN.md                   спецификации волн для исполнителя; выполненное схлопнуто до записей
scripts/
  faucet.mjs              CDP-faucet → деплойер или указанные адреса на Base Sepolia (0.0001 ETH каждому)
  onboard.mjs             addInvestor / addManager от имени Council
  monitor.mjs             фоновый tail контракта: предложения, голоса, ревенью, балансы (5-секундный опрос)
  members.mjs             одноразовый срез участников и балансов активного или указанного деплоя
  use-deployment.mjs      переключение активного деплоя на deployments/<chainId>.json
  verify.sh               полный прогон: тесты + coverage + lint + build + e2e, всё в контейнерах
webapp/
  src/
    ui.jsx                примитивы интерфейса + formatEther/parseEther/shortAddr
    state.jsx             StoreProvider: подключение через ethers, чтение статуса контракта, обёртки мутаций
    networks.js           метаданные сетей (имя, обозреватель, RPC, native-токен)
    main.jsx              ReactDOM.createRoot + StoreProvider + App
    App.jsx               маршрутизатор экранов
    components/Sidebar.jsx
    screens/
      PageHead.jsx        заголовок страницы + WithdrawPill
      Overview.jsx        обзор
      Desk.jsx            Council / Operator / Partner / Guest
      Proposals.jsx       список + карточка предложения
      Treasury.jsx        состояние казны + Distribute (Council)
      Members.jsx         партнёры + операторы
      Activity.jsx        фид всех on-chain событий с timestamp и ссылками на tx
    hooks/
      useWallet.js        подключение MetaMask + auto-switch chain
      useContractStatus.js
      useDetails.js
      useRole.js
      useEvents.js        чтение и декодирование всех событий контракта от deployBlock (чанками по 800)
    abi/deployment.json   активный деплой: адрес, ABI, owner, chainId, network (пишется deploy.js)
    abi/deployments/      пер-чейн снапшоты деплоев (<chainId>.json)
    bg.webp               фон, бандлируется vite-ом как хешированный asset
assets/, index.html       артефакты сборки, опубликованные на gh-pages
.env.example              шаблон переменных окружения

Безопасность ключей

  • .env находится в .gitignore. Содержит приватный ключ деплойера и секреты CDP.
  • Веб-приложение не имеет доступа к DEPLOYER_PRIVATE_KEY — оно подписывает транзакции через MetaMask пользователя.
  • Серверные операции (faucet, onboarding) выполняются Node-скриптами в scripts/, которые читают ключ только из .env.
  • Для продакшна рекомендуется заменить plaintext-ключ в .env на encrypted keystore (например, cast wallet import) или KMS.

Дальнейшее развитие

Крупные изменения расписаны как исполняемые спецификации в PLAN.md. Выполнены: экономика v2 (возврат тела, списание убытков, выход партнёра), жизненный цикл предложения, двухшаговый ownership, кэш Activity-скана, контейнерный E2E — и расширения v3: токенизация долей (ERC-20 SHFI), опциональная деноминация в стейблкоине, шариатский совет с сертификацией и IPFS-документами, milestone-транши, залог менеджера со слэшингом по вердикту, multi-chain селектор в UI. Ожидает секретов: деплой v3 в Base Sepolia и обновление демо (PLAN.md §7). Бэкенд-очередь (PLAN.md §8): индексер, seed.mjs.

Соответствие механизмов контракта шариатским стандартам — с номерами пунктов AAOIFI и дословными цитатами — в STANDARDS.md; все найденные аудитом разрывы закрыты (сводная таблица в конце файла).

About

SheikhFi islamic DeFi platform demo for a hackathon

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Contributors

Languages