Integrators
For halal neobanks, fintechs, wallets, and protocols that want to offer compliant yield or credit without building it. Your users tap "Earn" or "Borrow" in your app; Rayyan is the settlement layer underneath.
Integration patterns
1. Yield (the common case for neobanks). Custody or smart-account architecture supplies user USDC to the pool; balances grow block-by-block. supply(usdc, amount) in, withdraw(usdc, amount) out: two calls. Show balanceOf(user); it's already yield-inclusive. LP share, utilization, and rates are on-chain reads for your UI.
2. Credit. Deposit user collateral (supply(weth, amount)), quote with getMaxBorrowable(user) and the guarded curve rate (below), open with borrowMurabaha(amount, maxRatePerSecond), where the second argument bounds the locked rate at the price you displayed, so the transaction reverts rather than locking a rate the user never saw. Your UX shows one number that never changes: the contract price. getAmountOwed(user) is the live payoff quote; repayMurabaha(user) closes with ibra' applied.
Quoting the rate: new positions price at max(getUtilization(), getUtilizationEma()) the EMA is the manipulation guard (spot utilization alone can be pushed within a block). Quote with getBorrowRate(max(spot, ema)) and pass that (plus a small buffer, e.g. +1%) as maxRatePerSecond.
3. Operators. Comet's native permission system (allow / allowBySig, EIP-712, gasless) lets your contract or backend act for users who authorize it once.
Integrator revenue share
Rayyan pays integrators for the volume they originate, from the protocol's own mudarabah share, never on top of the user's price. The contract price a borrower signs is untouched; your revenue comes out of our 15%, not their pocket.
The split: integrators earn one-third of the protocol's share of markup on positions they originate. On the launch market's 85/15 split that is 5% of the total markup stream; at band rates (~7.3% fixed) it is ≈ 0.36% per year on originated borrow volume. On a market with a different split the third scales with it (on a 95/5 market it is about 1.67% of markup). Either way it is paid continuously for as long as the positions run. Because murabaha positions are 360-day annuities, origination revenue compounds into a book, not a one-shot fee. Supply-side (Earn) integrations are negotiated separately, typically as bps/yr on average originated balances, also paid from the treasury share. Larger splits at scale are a conversation (contact@rayyan.finance).
How this compares (the two models we studied):
| Attribution | Who pays | Share | |
|---|---|---|---|
| Aave v3 | referralCode param, program inactive (designed as 20% of protocol fees by volume; never activated by governance) | — | 0 today |
| Hyperliquid builder codes | per-order builder code, user-approved fee cap | the user, fee added on top (≤10bps/order perps) | builder keeps their fee |
| Rayyan | operator address today; on-chain tag planned | the protocol, user price unchanged | 1/3 of protocol share (5% of markup) |
We take Aave's economics (paid from protocol revenue, no user surcharge, which also keeps the borrower's disclosed contract price exactly what they signed, as murabaha requires) and Hyperliquid's shipping discipline (real attribution, real payouts, their builders have earned $40M+; Aave's program never turned on).
Mechanics at launch: attribution by your operator/router address (the account that opens positions for your users, integration pattern 3 above), measured by the public subgraph, settled monthly in USDC on-chain. One agreement, no token lockups, no exclusivity. Planned (next ABI revision): an integrator tag emitted in MurabahaBorrow itself, giving trustless attribution and permissionless claiming in the Hyperliquid style, with the same paid-by-protocol economics.
Shariah note: the integrator is compensated as the protocol's distribution agent, a wakala/ujrah (agency/service fee) paid from the mudarib's own share, an established structure; nothing is added to the financed party's obligation.
Contract surface (the parts you'll use)
Core (Rayyan Comet)
// LP side
function supply(address asset, uint amount) external; // USDC or collateral
function withdraw(address asset, uint amount) external;
function balanceOf(address account) external view returns (uint256);
// Borrow side
function borrowMurabaha(uint requestedAmount, uint maxRatePerSecond) external;
function repayMurabaha(address borrower) external; // borrower or whitelisted closer
function getAmountOwed(address borrower) external view returns (uint256); // live payoff (ibra')
function getMaxBorrowable(address account) external view returns (uint256);
function getUtilizationEma() external view returns (uint256); // via CometExt fallback; quote at max(spot, ema)
// Position state (per borrower)
function borrowPrincipal(address) external view returns (uint256);
function contractPriceCap(address) external view returns (uint256);
function positionRate(address) external view returns (uint256); // per-second, 1e18
function borrowTimestamp(address) external view returns (uint40);
function borrowExpiration(address) external view returns (uint40);
// Pool state
function getUtilization() external view returns (uint256); // 1e18
function getBorrowRate(uint utilization) external view returns (uint64); // per-second, 1e18
function totalSupply() external view returns (uint256);
function totalBorrow() external view returns (uint256);
function lpShareBps() external view returns (uint256);
function totalMarkupPerSecond() external view returns (uint256); // 1e12-scaled
// Anyone may stream a voluntary donation to all suppliers
function donateToSupply(uint amount) external;Annualize per-second rates with ×31,536,000 (365d); markup terms use the 360-day murabaha convention internally, contract price = principal × (1 + rate/s × 31,104,000).
RayyanCloser
function closePosition(uint usdcContribution) external; // 0 → all-collateral … owed → all-USDC
function closePositionWith(uint usdcContribution, address asset) external; // pick which collateral funds it
function protocolClose(address borrower) external; // keeper-only, post-maturity, agency fee 0.25% of amount settled (min 1 USDC)
function setRoute(address asset, uint24 fee) external; // governor: route new collateral to a USDC poolAny routed collateral can fund a close (WETH and WBTC at launch; new listings get a route via setRoute). closePosition auto-picks the borrower's first routed asset with a balance; mixed-collateral positions choose explicitly with closePositionWith. Execution is bounded against the protocol's own oracle value (5% voluntary / 3.95% keeper settlement, so slippage plus the agency fee stays inside the absorb fallback's 4.2% cost; the live Sepolia deployment uses 6.5%), so a manipulated pool makes the close revert rather than overpay. Surplus collateral and USDC dust return to the borrower in the same transaction.
closePosition needs a USDC approval to the Closer when usdcContribution > 0 (approve the contract price, only the live owed amount is pulled). No collateral pre-auth is needed: the Closer holds a protocol-level, collateral-only operator grant.
Events (index these)
event MurabahaBorrow(address indexed borrower, uint principal, uint capPrice, uint ratePerSecond, uint40 expiration);
event MurabahaRepay(address indexed borrower, uint amountOwed, uint forgiven); // forgiven = ibra'
event PositionAbsorbed(address indexed account, uint capPrice, uint markupPerSecRemoved);
event SupplyDonation(address indexed donor, uint amount); // voluntary donations to suppliers
event LpShareUpdated(uint oldBps, uint newBps);
event IbraFactorUpdated(uint oldFactor, uint newFactor);Error surface worth mapping to UX
| Error | Show your user |
|---|---|
PositionExists | One murabaha position per address, close the current one first |
NotCollateralized | Add more collateral for this amount |
BorrowCapExceeded | Pool at capacity (80% utilization cap), try smaller or later |
UseBorrowMurabaha / UseRepayMurabaha | Wrong path, only the murabaha functions create/settle debt |
InsufficientCollateral (Closer) | Collateral can't cover the shortfall, add USDC to the mix |
Live testnet
Rayyan is deployed and running on Arbitrum Sepolia with all contracts source-verified, and has executed the full transaction matrix on the public chain: rate-locked borrows, live accrual, ibra' rebates on early settlement, LP supply and withdraw, and collateral-funded closes.
While the protocol is pre-audit, deployment addresses, ABIs, and testnet access are shared directly with integration partners rather than published. Get in touch at contact@rayyan.finance.
Addresses will be published with the audited mainnet deployment.