Protocol

Smart Contracts

The ten contracts that implement every primitive named in the docs. Solidity 0.8.28, Cancun EVM, OpenZeppelin 5. Source in contracts/src, tests in contracts/test, deployed to Base via scripts/deploy.ts.

The registry

ContractWhat it doesLOC
AssetTokenERC-20 + ERC-2612 permit. The $GSEA token.~30
RepoVaultPer-repo treasury keyed by bytes32 repoId. Owner controls splits + withdrawals.~165
SplitsEngineAtomic per-merge distribution by basis-point weights.~75
RoyaltyRouterContinuous-time stream rates between repos, settled on-demand or in batches.~120
StakingHub$GSEA staking with Light / Full / Validator tiers, slashing, voting-power.~165
CreditOracleSoulbound credit scores per DID. Attester-gated attestMerge and attestRevert.~115
CreditLinePer-repo and per-DID credit lines. Draw / repay / default. Flat interest.~165
InsurancePoolThree products (merge/dependency/refactor). Policies, claims, underwriting tranches.~205
GovernorAssetStake-weighted on-chain governance. 7-day vote → 48h timelock → execute.~165
MarketsRegistryParimutuel prediction markets per (prId, question).~165

Where they live

contracts/
  src/
    AssetToken.sol
    RepoVault.sol
    SplitsEngine.sol
    RoyaltyRouter.sol
    StakingHub.sol
    CreditOracle.sol
    CreditLine.sol
    InsurancePool.sol
    GovernorAsset.sol
    MarketsRegistry.sol
  test/                # 9 test files, 186 tests
  scripts/
    deploy.ts          # deploys all 10 + wires authorization
    export-abis.ts     # → ../src/abis/*.json
  deployments/         # network manifests after deploy

Deployment addresses

Addresses live in contracts/deployments/<network>.json per network, exposed to the frontend via src/lib/contracts.ts:

import { addressOf, ABIS, repoId } from "@/lib/contracts";

const vault = addressOf("RepoVault", chainId); // null until deployed

Function reference (selected)

The full ABIs ship in src/abis/*.json. Below is a navigator of the most-used functions per contract.

AssetToken

function mint(address to, uint256 amount) external onlyOwner;
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
// + standard ERC-20: transfer, approve, transferFrom, balanceOf, allowance

RepoVault

function linkRepo(bytes32 repoId, bytes32 splitsRoot) external;
function setSplits(bytes32 repoId, bytes32 newSplitsRoot) external;   // owner only
function transferRepoOwner(bytes32 repoId, address newOwner) external; // owner only
function deposit(bytes32 repoId, address token, uint256 amount) external;
function withdraw(bytes32 repoId, address token, address to, uint256 amount) external; // owner only
function transferBetween(bytes32 from, bytes32 to, address token, uint256 amount) external; // authorized callers
function balanceOf(bytes32 repoId, address token) external view returns (uint256);
function repos(bytes32 repoId) external view returns (address owner, bytes32 splitsRoot, uint64 linkedAt, bool exists);

SplitsEngine

struct SplitItem { address recipient; uint16 weightBps; }

function distributeMerge(
  bytes32 repoId,
  bytes32 prHash,
  address token,
  uint256 amount,
  SplitItem[] calldata splits
) external;

RoyaltyRouter

function setStream(bytes32 from, bytes32 to, uint256 ratePerSec) external; // from-owner only
function settle(bytes32 from, bytes32 to) external;
function settleBatch(bytes32[] calldata fromArr, bytes32[] calldata toArr) external;
function accrued(bytes32 from, bytes32 to) external view returns (uint256);

StakingHub

enum Tier { Observer, Light, Full, Validator }

function stake(uint256 amount) external;
function unstake(uint256 amount) external;
function withdraw() external;                       // after unbond window
function slash(address who, uint256 amount, bytes32 reasonCid) external; // owner only
function tierOf(address who) external view returns (Tier);
function votingPower(address who) external view returns (uint256);
function totalStaked() external view returns (uint256);

CreditOracle

enum Grade { D, C, B, A, AA, APlus }

function attestMerge(
  bytes32 did, bytes32 repoId, bytes32 prHash,
  uint128 weight, bytes32 credentialCid,
  uint16 newScore, Grade newGrade
) external; // attester only
function attestRevert(
  bytes32 did, bytes32 repoId, bytes32 prHash,
  uint16 penalty, uint16 newScore, Grade newGrade
) external; // attester only
function scoreOf(bytes32 did) external view returns (uint16);
function gradeOf(bytes32 did) external view returns (Grade);

CreditLine

enum CollateralKind { Repo, DID }
enum State { Open, Drawn, Repaid, Defaulted, Closed }

function openLine(
  CollateralKind kind, bytes32 collateralId, address borrower,
  uint128 cap, uint16 interestBps, uint16 termDays
) external returns (uint256 lineId);     // underwriter only
function draw(uint256 lineId, uint128 amount) external;   // borrower only
function repay(uint256 lineId, uint128 amount) external;  // anyone
function markDefault(uint256 lineId) external;            // anyone, after dueBy
function statusOf(uint256 lineId) external view
  returns (uint128 drawn, uint128 owed, uint64 dueBy, State state);

InsurancePool

function openPolicy(bytes8 product, bytes32 subjectId, uint128 notional, uint128 premium, uint16 termDays)
  external returns (uint256 policyId);
function fileClaim(uint256 policyId, uint128 requested, bytes32 evidenceCid)
  external returns (uint256 claimId);
function resolveClaim(uint256 claimId, bool approve, uint128 amount, address payee) external; // owner
function underwrite(bytes8 product, bytes1 grade, uint128 principal, uint16 termDays)
  external returns (uint256 positionId);
function closeUnderwriting(uint256 positionId) external;       // after unlock
function creditPremium(uint256 positionId, uint128 amount) external; // owner

GovernorAsset

enum State { Pending, Active, Defeated, Succeeded, Queued, Executed, Canceled }

function propose(address target, bytes calldata callData, bytes32 descriptionHash)
  external returns (uint256 proposalId);
function castVote(uint256 proposalId, bool support) external;
function queue(uint256 proposalId) external;
function execute(uint256 proposalId) external returns (bytes memory);
function cancel(uint256 proposalId) external; // proposer or owner
function state(uint256 proposalId) public view returns (State);

MarketsRegistry

enum Outcome { Pending, Yes, No, Void }

function openMarket(bytes32 prId, bytes8 question, uint64 closesAt)
  external returns (bytes32 marketKey);
function takePosition(bytes32 marketKey, bool side, uint128 amount) external;
function resolve(bytes32 marketKey, Outcome outcome) external; // owner
function claim(bytes32 marketKey) external;
function impliedYesBps(bytes32 marketKey) external view returns (uint16);

Authorization wiring

After deploy, the script wires:

vault.setAuthorized(routerAddr, true)        // RoyaltyRouter can move funds between repos
oracle.setAttester(deployer, true)           // bootstrap attester (rotated to bot later)
creditLine.setUnderwriter(deployer, true)    // bootstrap underwriter (lender pool later)

Governance handoff (when ready): transfer ownership of every contract that has an owner() to the GovernorAsset Timelock so future parameter changes go through votes.

Events worth indexing

Subgraphs and indexers should watch:

  • RepoVault.RepoLinked, SplitsUpdated, Deposit, Withdraw, Transferred
  • SplitsEngine.MergePaid
  • RoyaltyRouter.StreamSet, StreamSettled
  • StakingHub.Staked, Unstaked, Withdrawn, Slashed
  • CreditOracle.MergeAttested, RevertAttested
  • CreditLine.LineOpened, LineDrawn, LineRepaid, LineDefaulted
  • InsurancePool.PolicyOpened, ClaimFiled, ClaimResolved, UnderwritingOpened, UnderwritingClosed
  • GovernorAsset.ProposalCreated, VoteCast, ProposalQueued, ProposalExecuted
  • MarketsRegistry.MarketOpened, PositionTaken, MarketResolved, Claimed