Integrating as a protocol
This page is for lenders, options desks, clubs and other protocols that want to take a claim on Stock Tokens without taking custody.
Interface sketch. Not a deployed contract. Names and signatures can change before launch. No address exists yet.
Requirements#
- Stake $BZL before placing prongs. Your stake is slashed if a prong executes without valid proof.
- Pay the prong fee: 0.05% of pledged notional per 30 days, for as long as the prong is active.
- Provide a trigger verifier that can check your proofs on-chain.
- Obtain the holder's EIP-712 consent for each prong.
Interface#
// SPDX-License-Identifier: UNLICENSED
// Interface sketch. Subject to change.
pragma solidity ^0.8.24;
interface IBezel {
enum ProngClass { Collateral, Sale }
enum ProngStatus { Active, Executed, Released, Expired }
struct Prong {
uint256 id;
address protocol; // placing protocol, must have $BZL staked
address asset; // Stock Token
uint256 claim; // number of tokens, capped
ProngClass class_;
address verifier; // trigger verifier
bytes32 triggerId; // trigger parameters, interpreted by the verifier
uint64 expiry; // unix seconds
uint16 seniority; // 1 settles first
ProngStatus status;
}
/// Holder deposits Stock Tokens into their own vault. Creates the vault on first call.
function mount(address asset, uint256 amount) external;
/// Protocol places a prong on a holder's vault.
/// Reverts on over-pledge, incompatible class, frozen asset,
/// insufficient stake, or invalid consent.
function placeProng(
address holder,
address asset,
uint256 claim,
ProngClass class_,
address verifier,
bytes32 triggerId,
uint64 expiry,
bytes calldata holderConsent
) external returns (uint256 prongId);
/// Executes a prong. Moves exactly `claim` tokens to the protocol.
/// Reverts outside market hours, when the asset is frozen,
/// when the prong is not active, or when the verifier rejects the proof.
function proveTrigger(address holder, uint256 prongId, bytes calldata proof) external;
/// Protocol releases a prong it placed. The claim returns to the free balance.
function release(address holder, uint256 prongId) external;
/// All active prongs on a holder's vault, in seniority order.
function prongsOf(address holder) external view returns (Prong[] memory);
}
interface ITriggerVerifier {
/// True if `proof` shows the trigger identified by `triggerId` has occurred for this prong.
function verify(address holder, uint256 prongId, bytes32 triggerId, bytes calldata proof)
external view returns (bool);
}
Flow#
- Stake. Stake $BZL to become eligible to place prongs.
- Consent. The holder signs the prong's terms.
- Place. Call
placeProngwith the consent. You are ranked below existing prongs on that asset. - Monitor. Read
prongsOf(holder)to track your rank and the vault's state. - Execute or release. Call
proveTriggerwhen your trigger occurs during market hours, orreleasewhen the position closes.
Design notes#
- Size claims to what you need. Claims are in tokens, not value. Price risk between placement and execution is yours.
- A sale prong fails if the vault already carries one on that asset. Check
prongsOfbefore asking for consent. - Handle freezes.
proveTriggerreverts while the asset is frozen and your expiry keeps running. - Seniority is not negotiable after placement. If you need rank 1, place first.