Skip to content

Commit e523803

Browse files
committed
Add support of ERC1155 for slither-check-erc tool.
1 parent 9239269 commit e523803

File tree

4 files changed

+144
-1
lines changed

4 files changed

+144
-1
lines changed

slither/core/declarations/contract.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
ERC721_signatures,
2020
ERC1820_signatures,
2121
ERC777_signatures,
22+
ERC1155_signatures,
2223
)
2324
from slither.utils.tests_pattern import is_test_contract
2425

@@ -925,6 +926,16 @@ def is_erc777(self) -> bool:
925926
full_names = self.functions_signatures
926927
return all(s in full_names for s in ERC777_signatures)
927928

929+
def is_erc1155(self) -> bool:
930+
"""
931+
Check if the contract is an erc1155
932+
933+
Note: it does not check for correct return values
934+
:return: Returns a true if the contract is an erc1155
935+
"""
936+
full_names = self.functions_signatures
937+
return all(s in full_names for s in ERC1155_signatures)
938+
928939
@property
929940
def is_token(self) -> bool:
930941
"""
@@ -937,6 +948,7 @@ def is_token(self) -> bool:
937948
or self.is_erc165()
938949
or self.is_erc223()
939950
or self.is_erc777()
951+
or self.is_erc1155()
940952
)
941953

942954
def is_possible_erc20(self) -> bool:

slither/tools/erc_conformance/__main__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from slither.utils.output import output_to_json
99
from .erc.ercs import generic_erc_checks
1010
from .erc.erc20 import check_erc20
11+
from .erc.erc1155 import check_erc1155
1112

1213
logging.basicConfig()
1314
logging.getLogger("Slither").setLevel(logging.INFO)
@@ -22,7 +23,7 @@
2223
logger.handlers[0].setFormatter(formatter)
2324
logger.propagate = False
2425

25-
ADDITIONAL_CHECKS = {"ERC20": check_erc20}
26+
ADDITIONAL_CHECKS = {"ERC20": check_erc20, "ERC1155": check_erc1155}
2627

2728

2829
def parse_args():
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import logging
2+
3+
from slither.slithir.operations import EventCall
4+
from slither.utils import output
5+
6+
logger = logging.getLogger("Slither-conformance")
7+
8+
def events_safeBatchTransferFrom(contract, ret):
9+
function = contract.get_function_from_signature("safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)")
10+
events = [
11+
{"name": "TransferSingle", "parameters": ["address", "address", "address", "uint256", "uint256"]},
12+
{"name": "TransferBatch", "parameters": ["address", "address", "address", "uint256[]", "uint256[]"]}
13+
]
14+
15+
event_counter_name = 0
16+
event_counter_parameters = 0
17+
if function:
18+
for event in events:
19+
for ir in function.all_slithir_operations():
20+
if isinstance(ir, EventCall) and ir.name == event["name"]:
21+
event_counter_name += 1
22+
if event["parameters"] == [str(a.type) for a in ir.arguments]:
23+
event_counter_parameters += 1
24+
if event_counter_parameters == 1 and event_counter_name == 1:
25+
txt = "[✓] safeBatchTransferFrom emit TransferSingle or TransferBatch"
26+
logger.info(txt)
27+
else:
28+
txt = "[ ] safeBatchTransferFrom must emit TransferSingle or TransferBatch"
29+
logger.info(txt)
30+
31+
erroneous_erc1155_safeBatchTransferFrom_event = output.Output(txt)
32+
erroneous_erc1155_safeBatchTransferFrom_event.add(contract)
33+
ret["erroneous_erc1155_safeBatchTransferFrom_event"].append(
34+
erroneous_erc1155_safeBatchTransferFrom_event.data
35+
)
36+
37+
def check_erc1155(contract, ret, explored=None):
38+
if explored is None:
39+
explored = set()
40+
41+
explored.add(contract)
42+
43+
events_safeBatchTransferFrom(contract, ret)
44+
45+
for derived_contract in contract.derived_contracts:
46+
check_erc1155(derived_contract, ret, explored)
47+
48+
return ret

slither/utils/erc.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,11 +237,93 @@ def erc_to_signatures(erc: List[ERC]):
237237
]
238238
ERC777_signatures = erc_to_signatures(ERC777)
239239

240+
# Final
241+
# https://eips.ethereum.org/EIPS/eip-1155
242+
# Must have ERC165
243+
244+
ERC1155_transfersingle_event = ERC_EVENT(
245+
"TransferSingle",
246+
["address", "address", "address", "uint256", "uint256"],
247+
[True, True, True, False, False],
248+
)
249+
250+
ERC1155_transferbatch_event = ERC_EVENT(
251+
"TransferBatch",
252+
["address", "address", "address", "uint256[]", "uint256[]"],
253+
[True, True, True, False, False],
254+
)
255+
256+
ERC1155_approvalforall_event = ERC_EVENT(
257+
"ApprovalForAll",
258+
["address", "address", "bool"],
259+
[True, True, False],
260+
)
261+
262+
ERC1155_uri_event = ERC_EVENT(
263+
"URI",
264+
["string", "uint256"],
265+
[False, True],
266+
)
267+
268+
ERC1155_EVENTS = [
269+
ERC1155_transfersingle_event,
270+
ERC1155_transferbatch_event,
271+
ERC1155_approvalforall_event,
272+
ERC1155_uri_event,
273+
]
274+
275+
ERC1155 = [
276+
ERC("safeTransferFrom",
277+
["address", "address", "uint256", "uint256", "bytes"],
278+
"",
279+
False,
280+
True,
281+
[ERC1155_transfersingle_event]
282+
),
283+
ERC("safeBatchTransferFrom",
284+
["address", "address", "uint256[]", "uint256[]", "bytes"],
285+
"",
286+
False,
287+
True,
288+
[]
289+
),
290+
ERC("balanceOf", ["address", "uint256"], "uint256", True, True, []),
291+
ERC("balanceOfBatch", ["address[]", "uint256[]"], "uint256[]", True, True, []),
292+
ERC("setApprovalForAll", ["address", "bool"], "", False, True, [ERC1155_approvalforall_event]),
293+
ERC("isApprovedForAll", ["address", "address"], "bool", True, True, []),
294+
] + ERC165
295+
296+
ERC1155_TOKEN_RECEIVER = [
297+
ERC("onERC1155Received",
298+
["address", "address", "uint256", "uint256", "bytes"],
299+
"bytes4",
300+
False,
301+
False,
302+
[]
303+
),
304+
ERC("onERC1155BatchReceived",
305+
["address", "address", "uint256[]", "uint256[]", "bytes"],
306+
"bytes4",
307+
False,
308+
False,
309+
[]
310+
),
311+
]
312+
313+
ERC1155_METADATA = [
314+
ERC("uri", ["uint256"], "string", True, False, [])
315+
]
316+
317+
ERC1155 = ERC1155 + ERC1155_TOKEN_RECEIVER + ERC1155_METADATA
318+
319+
ERC1155_signatures = erc_to_signatures(ERC1155)
320+
240321
ERCS = {
241322
"ERC20": (ERC20, ERC20_EVENTS),
242323
"ERC223": (ERC223, ERC223_EVENTS),
243324
"ERC165": (ERC165, ERC165_EVENTS),
244325
"ERC721": (ERC721, ERC721_EVENTS),
245326
"ERC1820": (ERC1820, ERC1820_EVENTS),
246327
"ERC777": (ERC777, ERC777_EVENTS),
328+
"ERC1155": (ERC1155, ERC1155_EVENTS),
247329
}

0 commit comments

Comments
 (0)