Skip to main content

Token Safety API (beta)

The Token Safety API offers an array of features that can help determine on whether a token is malicious or not. From storage checks, to simulation and static analsysis features. In its current form the Token Safety API supports all ERC20 contracts on Ethereum, with more chains coming soon. The features are across all Uniswap V2/V3 pools with V4 support coming soon.

Feature set support

Static Analysis Features

We leverage the Gigahorse decompiler to analyze contracts whose source code is unavailable. The decompiled bytecode is checked for patterns commonly associated with undesirable behaviors in ERC20 tokens.

mint_or_burn_function:

There is a public function that changes the token’s total supply

can_selfdestruct:

The contract contains a selfdestruct call. (Note: The EVM no longer supports the SELFDESTRUCT opcode, so this is now a no-op.)

transfer_guarded_by_storage:

A storage variable determines whether balance updates in the transfer function will succeed.

transfer_from_guarded_by_storage:

A storage variable determines whether balance updates in the transferFrom function will succeed.

trading_cooldown:

An address must wait for a certain period after its last transfer before it can transfer tokens again.

view_function_modifies_state:

A function with the signature of one of the view functions defined by EIP-20 updates a storage variable.

trading_cap:

The amount of tokens transferred by a single call to transfer cannot exceed a value, either constant or held in storage.

trading_cap_can_be_modified:

The transfer amount cap is held in storage and there is function that can update it.

position_cap:

The amount of tokens an address can hold cannot exceed a value, either constant or held in storage.

trading_cap_can_be_modified:

The position cap is held in storage and there is function that can update it.

has_owner:

There is one or more addresses that have access to functionality of the token that the rest do not.

can_be_paused:

The token’s trading can be paused.

has_blacklist_or_whitelist:

Addresses can be restricted from trading the token.

external_call:

There is a call to another contract, whose target is not statically known and/or returns arbitrary data that are used by the token.

timebomb:

Certain functionality is only enabled after a specific timestamp.

has_tax:

A percentage of the transfer amount is sent to an address that is not the transfer recipient.

tax_can_be_modified:

The tax rate is held in a storage variable, whose value can be updated.

has_source:

This indicates whether the contract's source code is available. The readme mentions leveraging a decompiler "to analyze contracts whose source code is unavailable," implying this check, but it doesn't list has_source as a feature.

is_liquid:

This boolean indicates if the token is liquid, i.e. if at least one pool has more than $100 (in weth/usdc/usdt) value in it.

is_proxy:

Indicates if the contract is a proxy contract.

ownership_renounced:

This indicates if the ownership of the contract has been renounced.

ownership_retrieval_function:

This indicates if there is a function to retrieve the owner's address.

privileged_entity_can_change_balances:

This likely indicates if a privileged entity (e.g., owner) has the ability to change token balances outside of normal transfers.

can_steal_via_approval:

This feature suggests a check for a vulnerability where tokens can be stolen through an approval mechanism.

Simulation Features

transfer_tax

Returns the send/receive tax applied on a typical token transfer.

"transfer_tax": {
"errorMessage": null,
"errorCode": null,
"send_tax": 0.0,
"receive_tax": 0.0
}
  • send_tax (%): Calculated as the percentage loss from the sender's balance — e.g., if the sender sent 100 tokens and 110 were deducted, the send tax is 10%.
  • receive_tax (%): Calculated as the percentage the recipient received — e.g., if the sender sent 100 tokens and the recipient only received 90, the receive tax is 10%.
  • All values are expressed as percentages (e.g., 0.0 means 0%).
  • errorMessage / errorCode: Populated when the tax check fails.

pools

An array of liquidity pools (Uniswap V2/V3 forks) where the token is paired with WETH, USDC, or USDT, along with details on liquidity and trading behavior.

{
"pair_address": "0x...",
"type": "v2" | "v3",
"usd_liquidity": 2455608.22,
"buy_success": true,
"buy_tax": 0.0,
"sell_success": true,
"sell_tax": 0.0,
"errorMessage": null,
"errorCode": null
}
  • pair_address: Address of the liquidity pair.

  • type: Type of the pool. v2 = Uniswap V2 or compatible fork; v3 = Uniswap V3 or compatible fork.

  • usd_liquidity: USD value of the pool's known-token reserves:

    • For V2 pools: Calculated using the USD value of the known side of the pair (WETH, USDC or USDT).
    • For V3 pools: Estimated using balanceOf() on the known token — while not exact, it is a practical approximation that serves as a useful indicator of pool health and liquidity status.
  • buy_success: Whether buying the token (e.g., WETH -> token) succeeded during simulation.

  • buy_tax (%): Tax incurred on a buy.

  • sell_success: Whether selling the token succeeded.

  • sell_tax (%): Tax incurred on a sell.

  • errorMessage / errorCode: Populated for failed queries (e.g., low liquidity, failed swaps).

Notes on usd_liquidity

  • For V2 pools, using the known token side (e.g., WETH in WETH/XYZ) is reliable since the reserves are fixed.
  • For V3 pools, the balanceOf() method on the known token offers a fast heuristic to assess pool liquidity. While it has some limitations — such as including uncollected fees or dust and not reflecting active price ranges — it still provides a strong signal of pool activity and health. In most cases, very low balances are a reliable indicator of illiquidity or abandoned pools.

Other features

supply_percentage_held_by_owner:

This provides details on the token amount and percentage of total supply held by the owner. While has_owner is listed, the specific details about the owner's holdings are not.