Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions add_new_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
DeFi Hack Manager - A tool for documenting and managing DeFi hack POCs
"""

from datetime import datetime
from datetime import datetime, timezone
import argparse
import re
import os
Expand All @@ -15,6 +15,15 @@
import unittest
from unittest import mock

def utc_now() -> datetime:
"""Current UTC wall clock as a naive datetime.

Hack dates are recorded in UTC, so the fallback "current time" must not
depend on the timezone of the machine running this script.
"""
return datetime.now(timezone.utc).replace(tzinfo=None)


######################
# CONSTANTS
######################
Expand Down Expand Up @@ -443,13 +452,13 @@ def _run_cast_command(self, cast_args: List[str], rpc_url: str, command_descript
def get_timestamp_from_str(self, timestampstr: str) -> datetime:
"""Convert timestamp string to datetime object"""
if not timestampstr:
return datetime.now()
return utc_now()
try:
return datetime.strptime(timestampstr, "%b-%d-%Y %I:%M:%S %p")
except ValueError:
print("Invalid timestamp format. Please use 'Mon-DD-YYYY HH:MM:SS AM/PM' (e.g., Mar-21-2024 02:51:33 PM).")
print("Using current timestamp instead.")
return datetime.now()
return utc_now()

def get_timestamp_from_tx_hash(self, tx_hash: str, rpc_url: str, auto_confirm: bool = False) -> str:
"""Get timestamp from transaction hash.
Expand Down Expand Up @@ -485,7 +494,9 @@ def get_timestamp_from_tx_hash(self, tx_hash: str, rpc_url: str, auto_confirm: b
else:
unix_timestamp = int(unix_timestamp_any)

dt_object = datetime.fromtimestamp(unix_timestamp)
# Block timestamps are UTC; render them as UTC so the
# generated date does not depend on the runner's timezone.
dt_object = datetime.fromtimestamp(unix_timestamp, tz=timezone.utc)
suggested_timestamp_str = dt_object.strftime("%b-%d-%Y %I:%M:%S %p")
print(f"Suggested timestamp: {suggested_timestamp_str}")
if auto_confirm or input("Use suggested timestamp? (yes/no): ").lower() == 'yes':
Expand Down Expand Up @@ -655,7 +666,7 @@ def create_poc_solidity_file(self, file_name: str, lost_amount: str, attacker_ad
hacking_god_url: str, selected_network: str, timestamp_str: str):
"""Create a new Solidity POC file from template"""
# Parse timestamp and format date for path
timestamp = datetime.strptime(timestamp_str, "%b-%d-%Y %I:%M:%S %p") if timestamp_str else datetime.now()
timestamp = datetime.strptime(timestamp_str, "%b-%d-%Y %I:%M:%S %p") if timestamp_str else utc_now()
formatted_date_for_path = timestamp.strftime("%Y-%m")

# Ensure file name has proper extension
Expand Down
8 changes: 4 additions & 4 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -378,17 +378,17 @@ def test_get_timestamp_from_tx_hash_success(self, mock_input):

# Mock successful transaction data fetch
tx_data = {"blockNumber": 12345}
block_data = {"timestamp": 1647888693} # Tue Mar 22 2022 02:51:33 GMT+0000
block_data = {"timestamp": 1647888693} # Mon Mar 21 2022 18:51:33 GMT+0000

with mock.patch.object(self.tx_manager, "_run_cast_command") as mock_run_cast:
mock_run_cast.side_effect = [tx_data, block_data]
mock_input.return_value = "yes" # Accept suggested timestamp

result = self.tx_manager.get_timestamp_from_tx_hash(tx_hash, rpc_url)

# Assert the function returns formatted timestamp
# The exact format will depend on the locale, so we check for key parts
self.assertIn("Mar-22-2022", result)
# Block timestamps are UTC, so the result must not depend on the
# timezone of the machine running the tests.
self.assertEqual(result, "Mar-21-2022 06:51:33 PM")
mock_run_cast.assert_any_call(
["tx", tx_hash, "--json"],
rpc_url,
Expand Down