Incorrect interface detector
Name: incorrect-interface
Reports multiple different issues when implementing ERC-20/ERC-721/ERC-1155 interfaces.
Missing functions & events
One or more functions or events are missing from the contract. The recognition is based on the function/event selectors.
Example
| pragma solidity ^0.8;
contract MyToken { // (1)!
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
event Transfer(address indexed from, address indexed to, uint256 value);
function approve(address spender, uint256 value) external returns (bool) {
// ...
}
function transfer(address to, uint256 value) external returns (bool) {
// ...
}
}
|
- The contract does not implement the
transferFrom function and the Approval event defined in the ERC20 standard.
Incorrect state mutability
Some functions are marked as view in the token standards as they are not supposed to modify the state.
The detector reports functions that should be marked as view but are not.
Example
| pragma solidity ^0.8;
contract MyToken {
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(
address indexed owner, address indexed spender, uint256 value
);
function totalSupply() external returns (uint256) { // (1)!
// ...
}
function approve(address spender, uint256 value) external returns (bool) {
// ...
}
function transfer(address to, uint256 value) external returns (bool) {
// ...
}
function transferFrom(
address from, address to, uint256 value
) external returns (bool) {
// ...
}
}
|
- The
totalSupply function should be marked as pure or view, but it is not.
Incorrect return type
Return types do not affect the function selectors. Still, tokens implemented according to the standard should return values as specified in the standard.
Example
| pragma solidity ^0.8;
contract MyToken {
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(
address indexed owner, address indexed spender, uint256 value
);
function approve(address spender, uint256 value) external { // (1)!
// ...
}
function transfer(address to, uint256 value) external { // (2)!
// ...
}
function transferFrom(
address from, address to, uint256 value
) external { // (3)!
// ...
}
}
|
- The
approve function should return a bool value, but it does not.
- The
transfer function should return a bool value, but it does not.
- The
transferFrom function should return a bool value, but it does not.
Indexed event parameters
Indexed event parameters do not affect the event selectors, but they still should be used according to the standard.
Example
| pragma solidity ^0.8;
contract MyToken {
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
event Transfer(address indexed from, address to, uint256 value); // (1)!
event Approval(
address indexed owner,
address indexed spender,
uint256 indexed value // (2)!
);
function approve(address spender, uint256 value) external returns (bool) {
// ...
}
function transfer(address to, uint256 value) external returns (bool) {
// ...
}
function transferFrom(
address from, address to, uint256 value
) external returns (bool) {
// ...
}
}
|
- The
to parameter of the Transfer event should be indexed, but it is not.
- The
value parameter of the Approval event should not be indexed, but it is.
Anonymous events
Events defined in the token standards should not be anonymous.
Example
| pragma solidity ^0.8;
contract MyToken {
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
event Transfer(
address indexed from, address indexed to, uint256 value
) anonymous; // (1)!
event Approval(
address indexed owner, address indexed spender, uint256 value
);
function approve(address spender, uint256 value) external returns (bool) {
// ...
}
function transfer(address to, uint256 value) external returns (bool) {
// ...
}
function transferFrom(
address from, address to, uint256 value
) external returns (bool) {
// ...
}
}
|
- The
Transfer event should not be anonymous, but it is.
Parameters
| Command-line name |
TOML name |
Type |
Default value |
Description |
--erc20-threshold |
erc20_threshold |
int |
4 |
Number of ERC-20 functions/events required to consider a contract an ERC-20 token. |
--erc721-threshold |
erc721_threshold |
int |
6 |
Number of ERC-721 functions/events required to consider a contract an ERC-721 token. |
--erc1155-threshold |
erc1155_threshold |
int |
4 |
Number of ERC-1155 functions/events required to consider a contract an ERC-1155 token. |