Skip to content

Commit e157b6d

Browse files
committed
fix dockerfile issue
1 parent c1f9791 commit e157b6d

7 files changed

Lines changed: 71 additions & 85 deletions

File tree

Dockerfile

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,34 @@
11
ARG ETHEREUM_VERSION=alltools-v1.10.21
22
ARG SOLC_VERSION=0.8.16
33

4-
FROM ethereum/client-go:${ETHEREUM_VERSION} as geth
5-
FROM ethereum/solc:${SOLC_VERSION} as solc
6-
7-
FROM ubuntu:bionic as CLI
8-
9-
ARG NODEREPO=node_8.x
10-
11-
LABEL maintainer "Shuo Yang <https://github.com/shuo-young>"
12-
13-
SHELL ["/bin/bash", "-c", "-l"]
14-
RUN apt-get update && apt-get -y upgrade
15-
RUN apt-get install -y wget unzip python-virtualenv git build-essential software-properties-common curl
16-
RUN curl -s 'https://deb.nodesource.com/gpgkey/nodesource.gpg.key' | apt-key add -
17-
RUN apt-add-repository "deb https://deb.nodesource.com/${NODEREPO} $(lsb_release -c -s) main"
18-
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
19-
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
20-
RUN apt-get update
21-
RUN apt-get install -y musl-dev golang-go python3 python3-pip python-pip \
22-
bison zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libreadline-dev \
23-
zlib1g-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 \
24-
libxml2-dev libxslt1-dev libcurl4-openssl-dev libffi-dev nodejs yarn && \
25-
apt-get clean
26-
27-
# Instsall geth from official geth image
28-
COPY --from=geth /usr/local/bin/evm /usr/local/bin/evm
4+
FROM ethereum/client-go:${ETHEREUM_VERSION} AS geth
5+
FROM ethereum/solc:${SOLC_VERSION} AS solc
296

30-
# Install solc from official solc image
31-
COPY --from=solc /usr/bin/solc /usr/bin/solc
7+
FROM python:3.10-slim AS cli
8+
9+
LABEL maintainer="Shuo Yang <https://github.com/shuo-young>"
3210

33-
ENV PYTHONIOENCODING=utf-8
11+
ENV PYTHONIOENCODING=utf-8
3412

35-
COPY . /NFTGuard
36-
RUN cd /NFTGuard && pip3 install -r requirements.txt
13+
# Install build dependencies and runtime tools
14+
RUN apt-get update && apt-get install -y --no-install-recommends \
15+
gcc \
16+
libc6-dev \
17+
ca-certificates \
18+
&& rm -rf /var/lib/apt/lists/*
19+
20+
# Install geth evm and solc from official images
21+
COPY --from=geth /usr/local/bin/evm /usr/local/bin/evm
22+
COPY --from=solc /usr/bin/solc /usr/bin/solc
3723

3824
WORKDIR /NFTGuard
39-
ENTRYPOINT ["python3", "/NFTGuard/tool.py"]
25+
26+
# Leverage Docker layer caching for deps
27+
COPY requirements.txt ./
28+
RUN pip install --upgrade pip setuptools wheel && \
29+
pip install -r requirements.txt
30+
31+
# Copy source
32+
COPY . .
33+
34+
ENTRYPOINT ["python3", "/NFTGuard/tool.py"]

config/config.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ class AnalysisConfig:
3737

3838
# Paths and files
3939
source: Optional[str] = None
40-
crawl_dir: str = \"./test/\"
40+
crawl_dir: str = "./test/"
4141

4242
# Contract metadata
43-
contract_address: str = \"\"
43+
contract_address: str = ""
4444
contract_count: int = 0
4545
storage_var_count: int = 0
4646
pub_fun_count: int = 0
@@ -51,7 +51,7 @@ class AnalysisConfig:
5151

5252
@classmethod
5353
def from_args(cls, args) -> 'AnalysisConfig':
54-
\"\"\"Create configuration from command line arguments.\"\"\"
54+
"""Create configuration from command line arguments."""
5555
config = cls()
5656

5757
# Update from args if provided
@@ -95,7 +95,7 @@ def from_args(cls, args) -> 'AnalysisConfig':
9595
return config
9696

9797
def to_dict(self) -> dict:
98-
\"\"\"Convert configuration to dictionary.\"\"\"
98+
"""Convert configuration to dictionary."""
9999
return {
100100
'timeout': self.timeout,
101101
'global_timeout': self.global_timeout,
@@ -122,20 +122,20 @@ def to_dict(self) -> dict:
122122

123123

124124
def get_config() -> AnalysisConfig:
125-
\"\"\"Get the global configuration instance.\"\"\"
125+
"""Get the global configuration instance."""
126126
global _global_config
127127
if _global_config is None:
128128
_global_config = AnalysisConfig()
129129
return _global_config
130130

131131

132132
def set_config(config: AnalysisConfig) -> None:
133-
\"\"\"Set the global configuration instance.\"\"\"
133+
"""Set the global configuration instance."""
134134
global _global_config
135135
_global_config = config
136136

137137

138138
def reset_config() -> None:
139-
\"\"\"Reset the global configuration to defaults.\"\"\"
139+
"""Reset the global configuration to defaults."""
140140
global _global_config
141141
_global_config = AnalysisConfig()

crawler/crawl.py

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,13 @@
22
import json
33
import os
44
from time import sleep
5+
import logging
56

67
import requests as rq
78

89

910
def make_dir(path):
10-
folders = []
11-
while not os.path.isdir(path):
12-
path, suffix = os.path.split(path)
13-
folders.append(suffix)
14-
for folder in folders[::-1]:
15-
path = os.path.join(path, folder)
16-
os.mkdir(path)
11+
os.makedirs(path, exist_ok=True)
1712

1813

1914
def is_json(myjson):
@@ -36,14 +31,13 @@ def crawl_contract(rootdir, c_address):
3631
root = rootdir
3732
contract_address = c_address
3833
# contract_name = row[2]
39-
curl_link = (
40-
"https://api.etherscan.io/api?module=contract&action=getsourcecode&address="
41-
+ c_address
42-
+ "&apikey=HPB1MEZ5YEJ7GZJF7ASQDJ4MPU7YEUTIUT"
43-
)
44-
print(curl_link)
45-
46-
output = rq.get(curl_link, headers=send_headers)
34+
api_key = os.getenv("ETHERSCAN_API_KEY")
35+
params = {"module": "contract", "action": "getsourcecode", "address": c_address}
36+
if api_key:
37+
params["apikey"] = api_key
38+
else:
39+
logging.warning("ETHERSCAN_API_KEY not set; proceeding without API key")
40+
output = rq.get("https://api.etherscan.io/api", headers=send_headers, params=params)
4741

4842
# sleep to avoid ban
4943
sleep(2)
@@ -54,34 +48,27 @@ def crawl_contract(rootdir, c_address):
5448
if is_json(source_code):
5549
res = json.loads(source_code)
5650
for key in res:
57-
print(key)
58-
sol_file = open(
59-
root + contract_address + "/" + key, "w", encoding="UTF-8"
60-
)
61-
sol_file.write(res[key]["content"])
62-
sol_file.close()
51+
logging.debug(key)
52+
with open(root + contract_address + "/" + key, "w", encoding="UTF-8") as sol_file:
53+
sol_file.write(res[key]["content"])
6354
elif source_code[0] == source_code[1] == "{":
6455
new_code = source_code[1:-1]
6556
res = json.loads(new_code)
6657
sources = res["sources"]
6758
for name in sources:
68-
print(name)
59+
logging.debug(name)
6960
_dir, _file = os.path.split(root + contract_address + "/" + name)
70-
print(_dir)
61+
logging.debug(_dir)
7162
make_dir(_dir)
72-
sol_file = open(
73-
root + contract_address + "/" + name, "w", encoding="UTF-8"
74-
)
75-
sol_file.write(sources[name]["content"])
76-
sol_file.close()
63+
with open(root + contract_address + "/" + name, "w", encoding="UTF-8") as sol_file:
64+
sol_file.write(sources[name]["content"])
7765
else:
78-
sol_file = open(
66+
with open(
7967
root + contract_address + "/" + contract_address + ".sol",
8068
"w",
8169
encoding="UTF-8",
82-
)
83-
sol_file.write(source_code)
84-
sol_file.close()
70+
) as sol_file:
71+
sol_file.write(source_code)
8572

8673

8774
if __name__ == "__main__":

feature_detector/semantic_analysis.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
import math
23

34
import global_params
45
from cfg_builder.opcodes import *
@@ -152,7 +153,7 @@ def semantic_analysis(
152153
global_state["approve"]["MSTORE_1"] = True
153154
elif value in g_slot_map.owner_index:
154155
global_state["approve"]["MSTORE_owner"] = True
155-
elif value in g_slot_map.owner_index:
156+
elif value in g_slot_map.approval_index:
156157
global_state["approve"]["MSTORE_2"] = True
157158

158159
if global_state["burn"]["trigger"] is True:
@@ -176,10 +177,11 @@ def semantic_analysis(
176177
# *Risky Mutable Proxy DEFECT
177178
if g_src_map:
178179
if stored_address in g_slot_map.proxy_index and current_func_name:
180+
name_upper = current_func_name.upper()
179181
if (
180-
"ACTIVE" not in current_func_name.upper()
181-
and "START" not in current_func_name.upper()
182-
and "SETPROXY" in current_func_name.upper()
182+
"ACTIVE" not in name_upper
183+
and "START" not in name_upper
184+
and "SETPROXY" in name_upper
183185
):
184186
solver = Solver()
185187
solver.set("timeout", global_params.TIMEOUT)
@@ -348,10 +350,9 @@ def semantic_analysis(
348350
for var in list_vars:
349351
if str(var) == str(global_state["sender_address"]):
350352
check = True
351-
if check == False:
353+
if not check:
352354
global_problematic_pcs["burn_defect"].append(global_state["burn"]["pc"])
353355
elif opcode.startswith("PUSH", 0):
354-
position = int(opcode[4:], 10)
355356
source_code = g_src_map.get_source_code(global_state["pc"])
356357
if source_code.strip().startswith("_safeMint"):
357358
# find 4 pc count before to find the exit of the for loop to judge the end of the function (for _safeMint)
@@ -473,7 +474,7 @@ def check_reentrancy_bug(g_src_map, global_state, stack, mem):
473474
# *Read memory from 160 to 224/mem_64 => 160, 164 + mem_mem_64 => 224
474475
# *The values should be the shift-lefted value of OnERC721Received selector
475476
start_data_input = stack[3]
476-
size_data_input = stack[4]
477+
_ = stack[4]
477478
if (
478479
str(start_data_input) == "mem_64"
479480
or mem[start_data_input] == global_params.ONERC721RECEIVED_SELECTOR_SHL

inputter/slot_map.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import re
2+
import logging
23

34
from inputter.ast.ast_helper import AstHelper
45

@@ -110,7 +111,7 @@ def calculate_extracted_slot(self):
110111
simpler_slot_map[slots[id]].append({key: type})
111112
else:
112113
simpler_slot_map[slots[id]] = [key]
113-
print(simpler_slot_map)
114+
logging.debug(simpler_slot_map)
114115
return id_to_state_vars, simpler_slot_map, name_to_type
115116

116117
def calculate_slot(self):

inputter/solc_version_switcher.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import re
22
import subprocess
3+
import logging
34

45

56
def install_and_use_solc_version(version_info):
@@ -8,16 +9,16 @@ def install_and_use_solc_version(version_info):
89
).decode()
910

1011
if version_info in installed_versions_output:
11-
print(f"Version {version_info} is already installed.")
12+
logging.info(f"Version {version_info} is already installed.")
1213
else:
13-
print(f"Installing version {version_info}...")
14+
logging.info(f"Installing version {version_info}...")
1415
subprocess.run(["solc-select", "install", version_info], check=True)
15-
print(f"Version {version_info} installed successfully.")
16+
logging.info(f"Version {version_info} installed successfully.")
1617
# else:
1718
# raise ValueError(f"Version {version_info} is not available for installation.")
1819

1920
subprocess.run(["solc-select", "use", version_info], check=True)
20-
print(f"Switched to version {version_info}.")
21+
logging.info(f"Switched to version {version_info}.")
2122

2223

2324
class SolidityVersionSwitcher:
@@ -41,9 +42,9 @@ def extract_solidity_version(self, solidity_code):
4142
def switch_solc_version(self, version_info):
4243
try:
4344
subprocess.run(["solc-select", "use", version_info], check=True)
44-
print(f"Successfully switched to Solidity version {version_info}.")
45+
logging.info(f"Successfully switched to Solidity version {version_info}.")
4546
except subprocess.CalledProcessError as e:
46-
print(f"Failed to switch to Solidity version {version_info}. Error: {e}")
47+
logging.error(f"Failed to switch to Solidity version {version_info}. Error: {e}")
4748

4849
def run(self):
4950
solidity_code = self.load_solidity_code()

inputter/source_map.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import ast
22
import json
3+
import logging
34

45
import six
56

@@ -197,7 +198,7 @@ def _load_position_groups(cls, remap):
197198
cls.parent_filename,
198199
" ".join(remap),
199200
)
200-
print(cmd)
201+
logging.debug(cmd)
201202
out = run_command(cmd)
202203
out = json.loads(out)
203204
return out["contracts"]

0 commit comments

Comments
 (0)