Token Integration Checklist

This checklist offers recommendations for interacting with arbitrary tokens. Ensure that every unchecked item is justified and that its risks are understood.

For convenience, all Slither utilities can be run directly on a token address, as shown below:

slither-check-erc 0xdac17f958d2ee523a2206206994597c13d831ec7 TetherToken --erc erc20
slither-check-erc 0x06012c8cf97BEaD5deAe237070F9587f8E7A266d KittyCore --erc erc721

Use the following Slither output for the token to follow this checklist:

- slither-check-erc [target] [contractName] [optional: --erc ERC_NUMBER]
- slither [target] --print human-summary
- slither [target] --print contract-summary
- slither-prop . --contract ContractName # requires configuration, and use of Echidna and Manticore

General Considerations

  • The contract has a security review. Avoid interacting with contracts that lack a security review. Assess the review's duration (i.e., the level of effort), the reputation of the security firm, and the number and severity of findings.
  • You have contacted the developers. If necessary, alert their team to incidents. Locate appropriate contacts on blockchain-security-contacts.
  • They have a security mailing list for critical announcements. Their team should advise users (like you!) on critical issues or when upgrades occur.

Contract Composition

  • The contract avoids unnecessary complexity. The token should be a simple contract; tokens with complex code require a higher standard of review. Use Slither’s human-summary printer to identify complex code.
  • The contract uses SafeMath. Contracts that do not use SafeMath require a higher standard of review. Inspect the contract manually for SafeMath usage.
  • The contract has only a few non-token-related functions. Non-token-related functions increase the likelihood of issues in the contract. Use Slither’s contract-summary printer to broadly review the code used in the contract.
  • The token has only one address. Tokens with multiple entry points for balance updates can break internal bookkeeping based on the address (e.g., balances[token_address][msg.sender] might not reflect the actual balance).

Owner Privileges

  • The token is not upgradeable. Upgradeable contracts may change their rules over time. Use Slither’s human-summary printer to determine if the contract is upgradeable.
  • The owner has limited minting capabilities. Malicious or compromised owners can abuse minting capabilities. Use Slither’s human-summary printer to review minting capabilities and consider manually reviewing the code.
  • The token is not pausable. Malicious or compromised owners can trap contracts relying on pausable tokens. Identify pausable code manually.
  • The owner cannot blacklist the contract. Malicious or compromised owners can trap contracts relying on tokens with a blacklist. Identify blacklisting features manually.
  • The team behind the token is known and can be held responsible for abuse. Contracts with anonymous development teams or teams situated in legal shelters require a higher standard of review.

ERC20 Tokens

ERC20 Conformity Checks

Slither includes the slither-check-erc utility that checks a token's conformance to various ERC standards. Use slither-check-erc to review the following:

  • Transfer and transferFrom return a boolean. Some tokens do not return a boolean for these functions, which may cause their calls in the contract to fail.
  • The name, decimals, and symbol functions are present if used. These functions are optional in the ERC20 standard and may not be present.
  • Decimals returns a uint8. Some tokens incorrectly return a uint256. In these cases, ensure the returned value is below 255.
  • The token mitigates the known ERC20 race condition. The ERC20 standard has a known race condition that must be mitigated to prevent attackers from stealing tokens.

Slither includes the slither-prop utility, which generates unit tests and security properties to find many common ERC flaws. Use slither-prop to review the following:

  • The contract passes all unit tests and security properties from slither-prop. Run the generated unit tests, then check the properties with Echidna and Manticore.

Risks of ERC20 Extensions

The behavior of certain contracts may differ from the original ERC specification. Review the following conditions manually:

  • The token is not an ERC777 token and has no external function call in transfer or transferFrom. External calls in the transfer functions can lead to reentrancies.
  • Transfer and transferFrom should not take a fee. Deflationary tokens can lead to unexpected behavior.
  • Consider any interest earned from the token. Some tokens distribute interest to token holders. If not taken into account, this interest may become trapped in the contract.

Token Scarcity

Token scarcity issues must be reviewed manually. Check for the following conditions:

  • The supply is owned by more than a few users. If a few users own most of the tokens, they can influence operations based on the tokens' distribution.
  • The total supply is sufficient. Tokens with a low total supply can be easily manipulated.
  • The tokens are located in more than a few exchanges. If all tokens are in one exchange, compromising the exchange could compromise the contract relying on the token.
  • Users understand the risks associated with large funds or flash loans. Contracts relying on the token balance must account for attackers with large funds or attacks executed through flash loans.
  • The token does not allow flash minting. Flash minting can lead to drastic changes in balance and total supply, requiring strict and comprehensive overflow checks in the token operation.

Known non-standard ERC20 tokens

Protocols that allow integration with arbitrary tokens must take care to properly handle certain well-known non-standard ERC20 tokens. Refer to the non-standard-tokens list for a list of well-known tokens that contain additional risks.

ERC721 Tokens

ERC721 Conformity Checks

The behavior of certain contracts may differ from the original ERC specification. Review the following conditions manually:

  • Transfers of tokens to the 0x0 address revert. Some tokens allow transfers to 0x0 and consider tokens sent to that address to have been burned; however, the ERC721 standard requires that such transfers revert.
  • safeTransferFrom functions are implemented with the correct signature. Some token contracts do not implement these functions. Transferring NFTs to one of those contracts can result in a loss of assets.
  • The name, decimals, and symbol functions are present if used. These functions are optional in the ERC721 standard and may not be present.
  • If used, decimals returns a uint8(0). Other values are invalid.
  • The name and symbol functions can return an empty string. This behavior is allowed by the standard.
  • The ownerOf function reverts if the tokenId is invalid or refers to a token that has already been burned. The function cannot return 0x0. This behavior is required by the standard but may not always be implemented correctly.
  • A transfer of an NFT clears its approvals. This is required by the standard.
  • The token ID of an NFT cannot be changed during its lifetime. This is required by the standard.

Common Risks of the ERC721 Standard

Mitigate the risks associated with ERC721 contracts by conducting a manual review of the following conditions:

  • The onERC721Received callback is taken into account. External calls in the transfer functions can lead to reentrancies, especially when the callback is not explicit (e.g., in safeMint calls).
  • When an NFT is minted, it is safely transferred to a smart contract. If a minting function exists, it should behave similarly to safeTransferFrom and handle the minting of new tokens to a smart contract properly, preventing asset loss.
  • Burning a token clears its approvals. If a burning function exists, it should clear the token’s previous approvals.