Dutch Auctions
Settle Expired Auction
Route unsold collateral from an expired auction to the liquidation router
POST
/
lending-external-securities-v2
/
api
/
liquidations
/
{marketId}
/
settle-expired-auction
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/liquidations/{marketId}/settle-expired-auction" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"auctionId": 3}'
const res = await fetch(
`https://api.trusset.org/lending-external-securities-v2/api/liquidations/${marketId}/settle-expired-auction`,
{
method: 'POST',
headers: {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify({ auctionId: 3 })
}
);
const { success, data, error } = await res.json();
{
"success": true,
"data": {
"success": true,
"auctionId": 3,
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0x5c3e8a91d2f04b7e6a1c9d38f0b2e47a6d15c8e3",
"data": "0x081528910000000000000000000000000000000000000000000000000000000000000003",
"value": "0",
"chainId": 11155111
},
"functionName": "settleExpiredAuction",
"venueAddress": "0x5c3e8a91d2f04b7e6a1c9d38f0b2e47a6d15c8e3"
}
}
{
"success": true,
"data": {
"txHash": "0x2d81c4f6a9e03b75d1c8e46f0a29b7d53e61f8c04a7b92d5e3f16c08a4d9b271",
"auctionId": 3,
"liquidationId": "9",
"marketLiquidationId": "12"
}
}
{
"success": false,
"error": {
"code": "AUCTION_NOT_EXPIRED",
"message": "An auction can only be settled after it expires. Auction 3 runs until 2024-06-15T11:00:00.000Z, in 42 minutes. Bid on it to clear it sooner, or retry after that time.",
"eligibleAt": "2024-06-15T11:00:00.000Z"
}
}
{
"success": false,
"error": {
"code": "LIQUIDATOR_ROLE_MISSING",
"message": "Wallet 0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52 does not hold LIQUIDATOR_ROLE on market 0x70a0e25c7b768b87e658348b3b577678a173e038. Grant it via the roles flow.",
"calldata": {
"to": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"data": "0x...",
"description": "Grant LIQUIDATOR_ROLE to 0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52 (requires market DEFAULT_ADMIN_ROLE)",
"chainId": 11155111,
"value": "0"
},
"eligibleAt": null
}
}
Closes a Dutch auction that reached its end time without selling out, and moves the unsold collateral from the market’s auction venue to the market’s liquidation router. The router opens a record for the remainder, linked to the market’s own liquidation record, and the position enters the manual settlement workflow. The transaction targets the venue, not the market.
Until this is called, an expired auction leaves the collateral in limbo: no longer purchasable, and not yet available for an off-platform sale. The loan stays locked too, because the market treats the auction as open until it is settled.
Refusals from the auction and role checks carry
The venue must be authorized on the market’s liquidation router, otherwise the settlement reverts and the collateral stays in the venue. The API does not check this before building the calldata. Read
routerAuthorized on Get Auction Module, and sign the authorizeModuleOnRouter leg from Wire Auction Module if it is not true. The collateral token must also admit the router, as it must for every liquidation.Any wallet may settle an expired auction while the market is unpaused. Under a pause, the venue accepts the call only from a wallet holding
LIQUIDATOR_ROLE on the market. The optional signerAddress check is stricter than the contract: it demands LIQUIDATOR_ROLE whether or not the market is paused.Path Parameters
string
required
Body Parameters
integer
required
Auction ID on the market’s venue. Must be a positive integer sent as a JSON number. Required on the confirm call too.
string
Wallet you intend to settle with. Supplying it turns on a
LIQUIDATOR_ROLE check against that address, so the call is refused with LIQUIDATOR_ROLE_MISSING rather than handing back calldata that a paused market would revert. Omit it and no role check runs, which is the right choice when an unpaused market is settled from a wallet without the role.string
Hash of the
settleExpiredAuction transaction you broadcast. Send it with the same auctionId to confirm the settlement and record the result. Omit it to receive the calldata.Response Fields
object
Show child attributes
Show child attributes
integer
Auction ID, echoed back.
boolean
Nested inside
data on the calldata response.string
SIGN_TRANSACTION when txHash is omitted.object
Unsigned transaction,
{ to, data, value, chainId }, calling settleExpiredAuction on the auction venue. Returned when txHash is omitted.string
settleExpiredAuction. Returned when txHash is omitted.string
The market’s auction venue, lowercased. Returned when
txHash is omitted.string
Transaction hash. Returned when confirming with
txHash.string
The router’s liquidation ID for the routed remainder. Pass it to the router-side endpoints such as Withdraw Collateral for Sale. Returned when confirming,
null when the receipt shows nothing routed.string
The market’s own liquidation record the remainder belongs to, the one Handle Liquidation Timeout writes off. Returned when confirming,
null when the receipt shows nothing routed.What Happens Next
After settlement the unsold collateral sits at the liquidation router as aPENDING liquidation, visible through Get Pending Liquidations. The remainder always arrives two-step, whatever the router’s atomic mode. From there the standard manual workflow applies: withdraw for sale, report proceeds, settle. Where the atomic sale is offered, Sell Pending Liquidation can sell the whole remainder to the sale recipient instead. The 7 day write-off clock does not restart at this point. It runs from the original liquidation, when the market opened its record and the auction began, so the router-side sale has whatever remains of those 7 days.
Use the returned liquidationId on those router-side endpoints. Until this call confirms, they refuse the record with LIQUIDATION_ON_VENUE, because the router holds none of its collateral yet. Cash that earlier bids paid stays on the market’s record, and it settles together with whatever the router later forwards.
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/liquidations/{marketId}/settle-expired-auction" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"auctionId": 3}'
const res = await fetch(
`https://api.trusset.org/lending-external-securities-v2/api/liquidations/${marketId}/settle-expired-auction`,
{
method: 'POST',
headers: {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify({ auctionId: 3 })
}
);
const { success, data, error } = await res.json();
{
"success": true,
"data": {
"success": true,
"auctionId": 3,
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0x5c3e8a91d2f04b7e6a1c9d38f0b2e47a6d15c8e3",
"data": "0x081528910000000000000000000000000000000000000000000000000000000000000003",
"value": "0",
"chainId": 11155111
},
"functionName": "settleExpiredAuction",
"venueAddress": "0x5c3e8a91d2f04b7e6a1c9d38f0b2e47a6d15c8e3"
}
}
{
"success": true,
"data": {
"txHash": "0x2d81c4f6a9e03b75d1c8e46f0a29b7d53e61f8c04a7b92d5e3f16c08a4d9b271",
"auctionId": 3,
"liquidationId": "9",
"marketLiquidationId": "12"
}
}
{
"success": false,
"error": {
"code": "AUCTION_NOT_EXPIRED",
"message": "An auction can only be settled after it expires. Auction 3 runs until 2024-06-15T11:00:00.000Z, in 42 minutes. Bid on it to clear it sooner, or retry after that time.",
"eligibleAt": "2024-06-15T11:00:00.000Z"
}
}
{
"success": false,
"error": {
"code": "LIQUIDATOR_ROLE_MISSING",
"message": "Wallet 0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52 does not hold LIQUIDATOR_ROLE on market 0x70a0e25c7b768b87e658348b3b577678a173e038. Grant it via the roles flow.",
"calldata": {
"to": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"data": "0x...",
"description": "Grant LIQUIDATOR_ROLE to 0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52 (requires market DEFAULT_ADMIN_ROLE)",
"chainId": 11155111,
"value": "0"
},
"eligibleAt": null
}
}
Error Codes
| Code | HTTP | Cause |
|---|---|---|
MISSING_MARKET_ID | 400 | The market ID is longer than 100 characters |
NO_MARKET_ADDRESS | 400 | The market has no on-chain address recorded |
VALIDATION_ERROR | 400 | auctionId is not a positive integer, signerAddress is not a valid address, or txHash is malformed |
AUCTION_NOT_ACTIVE | 400 | The auction was already fully bought or settled, so settling it again reverts |
AUCTION_NOT_EXPIRED | 400 | The auction is still running. The error carries eligibleAt |
LIQUIDATOR_ROLE_MISSING | 400 | signerAddress was supplied and lacks LIQUIDATOR_ROLE on the market. The error carries grant calldata |
ROLE_UNVERIFIABLE | 400 | signerAddress was supplied and its role could not be read on-chain. Retry shortly |
TX_NOT_VERIFIED | 400 | The confirmed transaction settles a different auction |
SETTLE_FAILED | 400 | The settlement could not be prepared or confirmed and no more specific code applied |
AUCTION_NOT_FOUND | 404 | The venue has not created an auction with this ID |
MARKET_NOT_FOUND | 404 | No market with this ID on your instance |
AUCTION_MODULE_NOT_SET | 409 | The market has no auction venue wired, so there is no auction to settle |
AUCTION_STATE_UNAVAILABLE | 503 | The auction could not be read on-chain, so whether it has expired is unknown. Retry shortly |
eligibleAt, which is null except on AUCTION_NOT_EXPIRED. Confirming with txHash can also return any transaction verification error.⌘I
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/liquidations/{marketId}/settle-expired-auction" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"auctionId": 3}'
const res = await fetch(
`https://api.trusset.org/lending-external-securities-v2/api/liquidations/${marketId}/settle-expired-auction`,
{
method: 'POST',
headers: {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify({ auctionId: 3 })
}
);
const { success, data, error } = await res.json();
{
"success": true,
"data": {
"success": true,
"auctionId": 3,
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0x5c3e8a91d2f04b7e6a1c9d38f0b2e47a6d15c8e3",
"data": "0x081528910000000000000000000000000000000000000000000000000000000000000003",
"value": "0",
"chainId": 11155111
},
"functionName": "settleExpiredAuction",
"venueAddress": "0x5c3e8a91d2f04b7e6a1c9d38f0b2e47a6d15c8e3"
}
}
{
"success": true,
"data": {
"txHash": "0x2d81c4f6a9e03b75d1c8e46f0a29b7d53e61f8c04a7b92d5e3f16c08a4d9b271",
"auctionId": 3,
"liquidationId": "9",
"marketLiquidationId": "12"
}
}
{
"success": false,
"error": {
"code": "AUCTION_NOT_EXPIRED",
"message": "An auction can only be settled after it expires. Auction 3 runs until 2024-06-15T11:00:00.000Z, in 42 minutes. Bid on it to clear it sooner, or retry after that time.",
"eligibleAt": "2024-06-15T11:00:00.000Z"
}
}
{
"success": false,
"error": {
"code": "LIQUIDATOR_ROLE_MISSING",
"message": "Wallet 0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52 does not hold LIQUIDATOR_ROLE on market 0x70a0e25c7b768b87e658348b3b577678a173e038. Grant it via the roles flow.",
"calldata": {
"to": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"data": "0x...",
"description": "Grant LIQUIDATOR_ROLE to 0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52 (requires market DEFAULT_ADMIN_ROLE)",
"chainId": 11155111,
"value": "0"
},
"eligibleAt": null
}
}
