createOffer to escrow collateral and register the offer atomically.
Prerequisites
Before callingcreateOffer, you must grant the OTCVenue contract an ERC-20 allowance for at least assetAmount of the token you intend to sell. Without this approval the contract’s transferFrom call will revert.
For fee-on-transfer tokens, approve the nominal amount you want to deposit. The venue measures the actual balance change after the transfer and escrows only what it receives. The
assetAmount you pass sets the ceiling, not the guaranteed escrow balance.Function Signature
Parameters
The ERC-20 token you are selling. This token must be approved for transfer to the venue contract before calling
createOffer. Cannot be address(0) and cannot be the same as quote.The ERC-20 token you will accept as payment. Buyers must hold and approve this token to fill your offer. Cannot be
address(0).The total amount of collateral to deposit, in the asset token’s native decimals. Must be greater than zero. For standard ERC-20 tokens this equals the amount escrowed. For fee-on-transfer tokens, the actual escrowed amount may be less because the contract records the net balance received.
The quote-token cost per one whole unit of the asset token. One “whole unit” equals
10^assetDecimals base units. Must be greater than zero.For example, to sell a token with 18 decimals at a price of 0.43 USDC (6 decimals) per token:- One whole unit =
10^18base units of the asset pricePerUnit=430000(0.43 × 10^6 USDC base units)
Unix timestamp after which the offer can no longer be filled. Must be in the future (
expiry > block.timestamp). For deferred offers, expiry must also be less than or equal to unlockTime.Controls the settlement mode of the offer:
0— Spot offer. Assets transfer directly to the buyer at fill time.- Non-zero Unix timestamp — Deferred forward offer. Assets remain in escrow until the unlock time; buyers receive ERC-20 claim tokens at fill time and redeem them for the underlying collateral after the unlock timestamp. Must be in the future and must satisfy
expiry <= unlockTime.
Controls who can fill the offer:
address(0)— Public offer; any address may fill.- Specific address — Private bilateral offer; only that address may fill.
Return Value
A sequential identifier for the newly created offer, assigned from the venue’s
nextOfferId counter. Store this value — you will need it to fill, query, or cancel the offer.Events
The venue emits the following event upon successful offer creation:Validation Rules
createOffer will revert with InvalidParams() if any of the following are true:
assetisaddress(0)quoteisaddress(0)asset == quoteassetAmount == 0pricePerUnit == 0expiry <= block.timestamp(expired or current block)unlockTime != 0andunlockTime <= block.timestamp(deferred but already past)unlockTime != 0andexpiry > unlockTime(fills accepted after unlock)- Asset token’s
decimals() > 77
ZeroReceived() if the actual amount received by the venue after the transfer is zero.
Example: Creating a Public Spot Offer
The following TypeScript snippet uses ethers.js v6 to approve collateral and create a public spot offer selling 500,000 TECH tokens at 0.43 USDC each.The fee rate and fee recipient are snapshotted into the offer at creation time. Even if the admin changes the venue’s fee rate later, your offer’s fills will always use the rate that was active when you created the offer.