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
| Contract | What it does | LOC |
|---|---|---|
AssetToken | ERC-20 + ERC-2612 permit. The $GSEA token. | ~30 |
RepoVault | Per-repo treasury keyed by bytes32 repoId. Owner controls splits + withdrawals. | ~165 |
SplitsEngine | Atomic per-merge distribution by basis-point weights. | ~75 |
RoyaltyRouter | Continuous-time stream rates between repos, settled on-demand or in batches. | ~120 |
StakingHub | $GSEA staking with Light / Full / Validator tiers, slashing, voting-power. | ~165 |
CreditOracle | Soulbound credit scores per DID. Attester-gated attestMerge and attestRevert. | ~115 |
CreditLine | Per-repo and per-DID credit lines. Draw / repay / default. Flat interest. | ~165 |
InsurancePool | Three products (merge/dependency/refactor). Policies, claims, underwriting tranches. | ~205 |
GovernorAsset | Stake-weighted on-chain governance. 7-day vote → 48h timelock → execute. | ~165 |
MarketsRegistry | Parimutuel 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,TransferredSplitsEngine.MergePaidRoyaltyRouter.StreamSet,StreamSettledStakingHub.Staked,Unstaked,Withdrawn,SlashedCreditOracle.MergeAttested,RevertAttestedCreditLine.LineOpened,LineDrawn,LineRepaid,LineDefaultedInsurancePool.PolicyOpened,ClaimFiled,ClaimResolved,UnderwritingOpened,UnderwritingClosedGovernorAsset.ProposalCreated,VoteCast,ProposalQueued,ProposalExecutedMarketsRegistry.MarketOpened,PositionTaken,MarketResolved,Claimed
Related
- Architecture — how the contracts compose end-to-end.
- Tokenomics — fee schedule + staking economics.
- Security — audits, bounty, threat model.
- TypeScript SDK — call these contracts from the app.
