Skip to main content
All indexed parameters can be used as filter topics in eth_getLogs calls, enabling efficient server-side filtering without downloading and scanning every event. For high-volume deployments, combine multiple indexed filters to narrow queries to the exact offer, series, or participant you care about.

OfferCreated

Emitted when a seller successfully deposits collateral and registers a new offer. An unlockTime of 0 indicates a spot offer; any non-zero value indicates a deferred forward offer.
event OfferCreated(
    uint256 indexed offerId,
    address indexed seller,
    address indexed asset,
    address quote,
    uint256 requestedAssetAmount,
    uint256 escrowedAssetAmount,
    uint256 pricePerUnit,
    uint64 expiry,
    uint64 unlockTime,
    address allowedBuyer
);
offerId
uint256
required
Sequential identifier for the newly created offer. Indexed — use as a topic filter to track a specific offer across all subsequent events.
seller
address
required
The address that created the offer and deposited the collateral. Indexed — filter by seller to retrieve all offers from a specific wallet.
asset
address
required
The ERC-20 token address of the collateral asset being sold. Indexed — filter by asset to retrieve all offers for a specific token.
quote
address
The ERC-20 token accepted as payment. Not indexed.
requestedAssetAmount
uint256
The amount the seller requested to deposit. For standard tokens this equals escrowedAssetAmount; for fee-on-transfer tokens it may be higher.
escrowedAssetAmount
uint256
The actual amount of collateral received and escrowed by the venue, measured by balance delta. This is the true starting assetRemaining for the offer.
pricePerUnit
uint256
The quote-token cost per one whole unit (10^assetDecimals) of the asset token.
expiry
uint64
Unix timestamp after which the offer can no longer be filled.
unlockTime
uint64
Unix timestamp at which claim tokens become redeemable. A value of 0 identifies this as a spot offer.
allowedBuyer
address
The address permitted to fill the offer, or address(0) for a public offer with no fill restriction.

OfferFilled

Emitted on every fill, whether partial or complete. A single offer may emit multiple OfferFilled events as it is filled incrementally by one or more buyers.
event OfferFilled(
    uint256 indexed offerId,
    address indexed buyer,
    uint256 assetUnits,
    uint256 assetReceived,
    uint256 quoteCost,
    uint256 sellerQuoteReceived,
    uint256 feeCharged,
    uint256 feeReceived,
    uint256 buyerQuoteDebited
);
offerId
uint256
required
Identifier of the offer that was filled. Indexed — join with OfferCreated on this field to associate fills with their originating offer.
buyer
address
required
The address that executed the fill and paid the quote tokens. For deferred offers, this is also the address that receives the minted claim tokens. Indexed.
assetUnits
uint256
The number of asset units requested in this fill, in base units.
assetReceived
uint256
The net asset tokens actually received by the buyer (spot) or credited as claim tokens (deferred). May differ from assetUnits for fee-on-transfer asset tokens in spot fills.
quoteCost
uint256
The base quote cost for this fill before fees, computed via the cumulative mulDiv formula.
sellerQuoteReceived
uint256
The net quote tokens actually received by the seller after any transfer fees.
feeCharged
uint256
The nominal protocol fee computed as quoteCost * feeBps / 10000.
feeReceived
uint256
The net fee amount actually received by the fee recipient after any transfer fees.
buyerQuoteDebited
uint256
The total amount of quote tokens debited from the buyer’s balance (cost + fee + any transfer taxes). This is the buyer’s true total outlay.

OfferCancelled

Emitted when the seller cancels the remaining unfilled portion of an offer. After this event, the offer accepts no further fills, and the escrowed remainder is returned to the seller.
event OfferCancelled(
    uint256 indexed offerId,
    uint256 assetDebited,
    uint256 assetReceived
);
offerId
uint256
required
Identifier of the cancelled offer. Indexed.
assetDebited
uint256
The amount of asset collateral debited from the venue’s escrow (the full unfilled remainder).
assetReceived
uint256
The net amount of asset tokens actually received by the seller. For fee-on-transfer tokens, this may be less than assetDebited.

SeriesCreated

Emitted the first time a deferred offer is filled for a unique (asset, unlockTime) pair. This event signals that a new claim token contract has been deployed and that the series is now active. Subsequent deferred fills sharing the same pair do not re-emit this event — they silently join the existing series.
event SeriesCreated(
    bytes32 indexed seriesId,
    address indexed asset,
    uint64 unlockTime,
    address claimToken
);
seriesId
bytes32
required
The deterministic series identifier, derived as keccak256(abi.encode(asset, unlockTime)). Indexed.
asset
address
required
The ERC-20 asset token address for this series. Indexed.
unlockTime
uint64
The Unix timestamp at which claim tokens for this series become redeemable.
claimToken
address
The address of the newly deployed ERC-20 claim token contract for this series. Store this address in your indexer — it is the token that buyers receive when filling deferred offers in this series.

Redeemed

Emitted when a claim token holder burns their tokens after the unlock time and receives the underlying collateral. Redemption is permissionless — any holder can redeem any amount of their claim tokens once block.timestamp >= unlockTime.
event Redeemed(
    bytes32 indexed seriesId,
    address indexed holder,
    uint256 amount,
    uint256 assetReceived
);
seriesId
bytes32
required
The series identifier from which collateral was redeemed. Indexed.
holder
address
required
The address that burned claim tokens and received the collateral. Indexed.
amount
uint256
The number of claim tokens burned in this redemption.
assetReceived
uint256
The net amount of asset collateral received by the redeemer. For standard tokens this equals amount (1:1 backing). For fee-on-transfer asset tokens, this may be less than amount due to the transfer fee on the outbound transfer.

FeeUpdated

Emitted when the admin changes the protocol fee rate or fee recipient.
event FeeUpdated(uint16 feeBps, address feeRecipient);
feeBps
uint16
The new fee rate in basis points. Capped at MAX_FEE_BPS (100 bps = 1%).
feeRecipient
address
The new address that will receive protocol fees on future offers.

EntryPauseUpdated

Emitted when the admin toggles the entry pause state.
event EntryPauseUpdated(bool paused);
paused
bool
true when new offer creation and fills are paused; false when they are resumed.

Querying Events with ethers.js

Use typed event filters to query events efficiently. The following example retrieves all OfferCreated events for a specific asset address across a block range:
const filter = canopy.filters.OfferCreated(null, null, ASSET_ADDRESS);
const events = await canopy.queryFilter(filter, fromBlock, toBlock);

events.forEach((event) => {
  const { offerId, seller, escrowedAssetAmount, unlockTime } = event.args;
  const isDeferred = unlockTime > 0n;
  console.log(`Offer ${offerId} by ${seller}${isDeferred ? "deferred" : "spot"}`);
});
Pass null for any indexed parameter you do not want to filter on. The three indexed fields of OfferCreated correspond to topic positions [1], [2], and [3] in the raw log, so you can also compose raw eth_getLogs filters directly if you are working outside of an ethers.js context.