Skip to content

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#

  1. Stake. Stake $BZL to become eligible to place prongs.
  2. Consent. The holder signs the prong's terms.
  3. Place. Call placeProng with the consent. You are ranked below existing prongs on that asset.
  4. Monitor. Read prongsOf(holder) to track your rank and the vault's state.
  5. Execute or release. Call proveTrigger when your trigger occurs during market hours, or release when 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 prongsOf before asking for consent.
  • Handle freezes. proveTrigger reverts while the asset is frozen and your expiry keeps running.
  • Seniority is not negotiable after placement. If you need rank 1, place first.