Run a secondary trade
Post, accept, and finalize a secondary offer under an elected exemption pathway
Secondary trades settle through a cyberCORP's DealManager, which since the deal-manager secondary-trading upgrade has a dedicated offer flow: post an offer → accept it → finalize the settlement. Each acceptance creates a fully-signed settlement agreement in the CyberAgreementRegistry (a bytes32 id), and the DealManager holds the escrow internally.
Offers have two sides (OfferSide.SELL / OfferSide.BUY), support partial fills, and every settlement is pinned to a securities-law exemption pathway (ExemptionPathway: RULE_144, SECTION_4A7, SECTION_4A1HALF, RULE_144A, REGULATION_S) elected by the buyer. Structs are in ISecondaryTradeStorage.sol.
0. One-time configuration (owner/admin)
Before any offer can settle, the cyberCORP configures its trading policy on the DealManager:
// enable a pathway and set its exemption-specific conditions
dealManager.setPathwayThresholdConditions(ExemptionPathway.RULE_144, conds, true);
dealManager.setSpvThresholdConditions(fundConds); // apply to every offer
dealManager.setClosingConditions(closingConds); // checked at finalize only
dealManager.setMinTradeThreshold(minUnits, minConsideration);
dealManager.setSettlementWindow(window); // seconds from acceptance
dealManager.setDefaultIntegrator(integrator); // optional fee-split partnerA pathway that is not enabled can be neither pinned nor elected.
1. Post the offer
units is 18-decimal fixed point (one share = 1e18), while consideration is denominated in the payment token's own decimals (USDC = 6). Mixing these up misprices the offer by orders of magnitude.
SELL offers require the caller to be the cert's registered owner; the offered units are reserved on the cert (they cannot be scripified or reassigned while reserved).
BUY offers pull the full
considerationinto DealManager custody up front, and must pin an exemption pathway.
2. Accept the offer
Any counterparty (fully or partially) accepts:
Acceptance creates the settlement agreement in the registry (signed by both sides), funds the escrow (the buyer pays here on a sell offer), and re-runs the SPV and elected-pathway conditions against the concrete buyer. A failed condition reverts the whole acceptance.
3. Finalize
After acceptance — and within the settlement window — anyone can finalize:
Finalization re-checks the pathway, threshold, and closing conditions (eligibility must hold at settlement, not just at acceptance), pays the seller net of the platform/integrator fee, releases the unit reservation, and executes the ownership change through IssuanceManager.secondaryTransfer — decrementing the seller's cert and minting the buyer's cert with the seller's endorsement attached.
Cancelling and voiding
cancelOffer(offerId)— offeror cancels a live offer; only the uncommitted units/consideration are released, in-flight settlements resolve on their own.voidSecondaryTradeAgreement(agreementId, signer, signature)— records a party's void request; the settlement voids once both parties request it (or it expires).voidExpiredSecondaryTradeAgreement(agreementId, signer, signature)— unwinds a settlement past its expiry.syncVoidedSecondaryTradeAgreement(agreementId)— syncs a settlement that was voided directly in the registry.
Relayer support
postOffer, cancelOffer, and acceptOffer each have a relayed overload (…, address forAddr, uint256 nonce, bytes sig) where sig is forAddr's EIP-712 authorization over the call parameters and nonce — so end users can trade gaslessly. voidSecondaryTradeAgreement's relayed overload is different: (agreementId, signer, voidSignature, nonce, authSig) — the registry void signature plus a separate relayer-authorization signature, with signer as the authorized party.
Bespoke deals
The generic deal flow still exists alongside the offer flow, for primary issuances and negotiated bilateral deals: proposeDeal(...) / proposeAndSignDeal(...) (both return (bytes32 agreementId, uint256[] certIds)), then signDealAndPay(signer, agreementId, signature, partyValues, fillUnallocated, name, secret), then finalizeDeal(agreementId) — with voidExpiredDeal / revokeDeal / signToVoid for unwinding.
Note on escrow
Escrow of payment and certs is internal to the DealManager in both flows — there is no separate escrow contract to call. See LeXscroWLite.
Related
Last updated
Was this helpful?
