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. |