Roles
Set Liquidator Role
Grant or revoke LIQUIDATOR_ROLE on a market
POST
/
lending-external-securities-v2
/
api
/
markets
/
{marketId}
/
liquidator-role
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/markets/{marketId}/liquidator-role" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"address": "0x5b7e2d91c04a38f6e1d9a72b3c8f40e6d15a9c27", "action": "grant"}'
const url = `https://api.trusset.org/lending-external-securities-v2/api/markets/${marketId}/liquidator-role`;
const headers = {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
};
const body = { address: botAddress, action: 'grant' };
const res = await fetch(url, { method: 'POST', headers, body: JSON.stringify(body) });
const { data } = await res.json();
if (data.requiresUserAction) {
const { to, data: calldata, value, chainId } = data.configurationCalldata.liquidatorRole;
const tx = await adminWallet.sendTransaction({ to, data: calldata, value, chainId });
await tx.wait();
await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ ...body, txHash: tx.hash })
});
}
{
"success": true,
"data": {
"requiresUserAction": true,
"action": "grant",
"address": "0x5b7e2d91c04a38f6e1d9a72b3c8f40e6d15a9c27",
"configurationCalldata": {
"liquidatorRole": {
"to": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"data": "0x...",
"description": "Grant LIQUIDATOR_ROLE to 0x5b7e2d...5a9c27 (requires market DEFAULT_ADMIN_ROLE)",
"chainId": 11155111,
"value": "0"
}
}
}
}
{
"success": true,
"data": {
"action": "grant",
"address": "0x5b7e2d91c04a38f6e1d9a72b3c8f40e6d15a9c27",
"txHash": "0x9f2c41d8b7e05a3164c2870fbd935e1a4c7802db6135ea9048f7c21b5d3ea41b",
"unchanged": false
}
}
{
"success": true,
"data": {
"action": "grant",
"address": "0x5b7e2d91c04a38f6e1d9a72b3c8f40e6d15a9c27",
"txHash": null,
"unchanged": true
}
}
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request parameters",
"details": [
{ "field": "address", "message": "Invalid" }
]
}
}
{
"success": false,
"error": {
"code": "MARKET_PENDING_CURATOR",
"message": "This market has no lender of record yet, so changing who may liquidate on it is not possible. A nominated candidate must take the role before the market has an admin that can sign this."
}
}
Grants or revokes
The wallet holding
Confirming with
LIQUIDATOR_ROLE for an address on the market contract. The contract refuses Liquidate Loan from any caller without the role. Settle Expired Auction is open to any caller once the auction has expired, and needs the role only while the market is paused.
Revoking the role from every holder leaves the market with no liquidator. Loans still become liquidatable, but no liquidation can start until an address holds the role again.
DEFAULT_ADMIN_ROLE on the market signs the change. The endpoint returns the unsigned grantRole or revokeRole call for that wallet, and the same POST with txHash verifies the mined transaction against the change you asked for. The confirm call records nothing; it checks the receipt and echoes the hash.
A lender of record can also name a liquidator in its adoption terms on Accept Lender Role, and that address receives the role in the adoption transaction. The same change is available as MARKET_LIQUIDATOR on Set Access Role.
When the address is already in the requested state, the response returns
unchanged: true and no calldata. Nothing needs to be signed. A role the chain read cannot answer counts as a change, so the calldata comes back.Path Parameters
string
required
Body Parameters
string
required
Address to grant or revoke. Must be a 0x-prefixed 40-character hex address other than the zero address.
string
required
grant or revoke.string
Hash of the mined transaction, as a 0x-prefixed 64-character hex string. Send it with the same
address and action to verify the change. Omit it to receive the calldata.Response Fields
object
Show child attributes
Show child attributes
boolean
true when the role needs changing and the market admin has to sign. Absent otherwise.string
The action requested, echoed back.
string
The address affected, echoed back.
object
Present only alongside
requiresUserAction. Carries liquidatorRole, the unsigned transaction { to, data, description, chainId, value } targeting the market.string
The verified transaction hash when confirming, or
null when the address was already in the requested state. Absent on the calldata response.boolean
true when no transaction was needed, false on a confirmed change. Absent on the calldata response.curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/markets/{marketId}/liquidator-role" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"address": "0x5b7e2d91c04a38f6e1d9a72b3c8f40e6d15a9c27", "action": "grant"}'
const url = `https://api.trusset.org/lending-external-securities-v2/api/markets/${marketId}/liquidator-role`;
const headers = {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
};
const body = { address: botAddress, action: 'grant' };
const res = await fetch(url, { method: 'POST', headers, body: JSON.stringify(body) });
const { data } = await res.json();
if (data.requiresUserAction) {
const { to, data: calldata, value, chainId } = data.configurationCalldata.liquidatorRole;
const tx = await adminWallet.sendTransaction({ to, data: calldata, value, chainId });
await tx.wait();
await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ ...body, txHash: tx.hash })
});
}
{
"success": true,
"data": {
"requiresUserAction": true,
"action": "grant",
"address": "0x5b7e2d91c04a38f6e1d9a72b3c8f40e6d15a9c27",
"configurationCalldata": {
"liquidatorRole": {
"to": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"data": "0x...",
"description": "Grant LIQUIDATOR_ROLE to 0x5b7e2d...5a9c27 (requires market DEFAULT_ADMIN_ROLE)",
"chainId": 11155111,
"value": "0"
}
}
}
}
{
"success": true,
"data": {
"action": "grant",
"address": "0x5b7e2d91c04a38f6e1d9a72b3c8f40e6d15a9c27",
"txHash": "0x9f2c41d8b7e05a3164c2870fbd935e1a4c7802db6135ea9048f7c21b5d3ea41b",
"unchanged": false
}
}
{
"success": true,
"data": {
"action": "grant",
"address": "0x5b7e2d91c04a38f6e1d9a72b3c8f40e6d15a9c27",
"txHash": null,
"unchanged": true
}
}
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request parameters",
"details": [
{ "field": "address", "message": "Invalid" }
]
}
}
{
"success": false,
"error": {
"code": "MARKET_PENDING_CURATOR",
"message": "This market has no lender of record yet, so changing who may liquidate on it is not possible. A nominated candidate must take the role before the market has an admin that can sign this."
}
}
Error Codes
| Code | HTTP | Cause |
|---|---|---|
VALIDATION_ERROR | 400 | address is not a 0x-prefixed 40-character hex address, action is not grant or revoke, or txHash is malformed |
NO_MARKET_ADDRESS | 400 | The market has no on-chain address recorded |
INVALID_ADDRESS | 400 | address is the zero address |
TX_NOT_VERIFIED | 400 | The confirmed transaction changes a different role or names a different address |
LIQUIDATOR_ROLE_UPDATE_FAILED | 400 | The role change could not be prepared or confirmed and no more specific code applied |
MISSING_MARKET_ID | 400 | marketId is longer than 100 characters |
MARKET_NOT_FOUND | 404 | No market with this ID on your instance |
MARKET_PENDING_CURATOR | 409 | The market has no lender of record yet, so nobody holds the admin role this change requires. Skipped when confirming with txHash |
txHash can also return any transaction verification error. On this endpoint every one of them answers 400, including TX_NOT_FOUND.⌘I
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/markets/{marketId}/liquidator-role" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"address": "0x5b7e2d91c04a38f6e1d9a72b3c8f40e6d15a9c27", "action": "grant"}'
const url = `https://api.trusset.org/lending-external-securities-v2/api/markets/${marketId}/liquidator-role`;
const headers = {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
};
const body = { address: botAddress, action: 'grant' };
const res = await fetch(url, { method: 'POST', headers, body: JSON.stringify(body) });
const { data } = await res.json();
if (data.requiresUserAction) {
const { to, data: calldata, value, chainId } = data.configurationCalldata.liquidatorRole;
const tx = await adminWallet.sendTransaction({ to, data: calldata, value, chainId });
await tx.wait();
await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ ...body, txHash: tx.hash })
});
}
{
"success": true,
"data": {
"requiresUserAction": true,
"action": "grant",
"address": "0x5b7e2d91c04a38f6e1d9a72b3c8f40e6d15a9c27",
"configurationCalldata": {
"liquidatorRole": {
"to": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"data": "0x...",
"description": "Grant LIQUIDATOR_ROLE to 0x5b7e2d...5a9c27 (requires market DEFAULT_ADMIN_ROLE)",
"chainId": 11155111,
"value": "0"
}
}
}
}
{
"success": true,
"data": {
"action": "grant",
"address": "0x5b7e2d91c04a38f6e1d9a72b3c8f40e6d15a9c27",
"txHash": "0x9f2c41d8b7e05a3164c2870fbd935e1a4c7802db6135ea9048f7c21b5d3ea41b",
"unchanged": false
}
}
{
"success": true,
"data": {
"action": "grant",
"address": "0x5b7e2d91c04a38f6e1d9a72b3c8f40e6d15a9c27",
"txHash": null,
"unchanged": true
}
}
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request parameters",
"details": [
{ "field": "address", "message": "Invalid" }
]
}
}
{
"success": false,
"error": {
"code": "MARKET_PENDING_CURATOR",
"message": "This market has no lender of record yet, so changing who may liquidate on it is not possible. A nominated candidate must take the role before the market has an admin that can sign this."
}
}
