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
2 changes: 1 addition & 1 deletion protocols/timelock/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The script runs hourly via the [monitoring runner](../automation/jobs.yaml).

Only `TimelockController` timelocks are checked. Compound-style queues expire after a grace period, and governor proposals have their own lifecycle.

Alerts show the timelock, schedule transaction link, readiness date, and call details. Operation IDs are omitted from the alert text.
Alerts show the timelock, full operation ID in inline code for copying into `getTimestamp(id)` or other state queries, schedule transaction link, readiness date, and call details.

## GraphQL Schema

Expand Down
1 change: 1 addition & 0 deletions protocols/timelock/stale_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ def format_operation(operation: Operation, ready_at: int, now: int) -> str:
)
prefix = (
f"*{operation.timelock.label}* (chain {chain_id}): {timelock}\n"
f"Operation ID: `{operation.operation_id}`\n"
f"Scheduled {_date(operation.scheduled_at)} in {tx}\n"
f"Ready since {_date(ready_at)} ({(now - ready_at) // DAY} days)\n"
"Calls:\n"
Expand Down
5 changes: 3 additions & 2 deletions tests/test_timelock_stale_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ def test_links_full_addresses_and_counts_days(self, decode: MagicMock) -> None:
text,
)
self.assertIn("(39 days)", text)
self.assertIn(f"Operation ID: `{_operation().operation_id}`\n", text)
self.assertIn(f"[{RATE_MANAGER}](https://etherscan.io/address/{RATE_MANAGER}) `setRate(address,uint256)`", text)

@patch("utils.calldata.decoder._resolve_signature_via_abi")
Expand All @@ -109,7 +110,7 @@ def test_long_signatures_fit_with_an_explicit_omission_notice(self, resolve: Mag
self.assertGreater(shown, 0)
self.assertLess(shown, len(operation.calls))
self.assertIn(f"… and {len(operation.calls) - shown} more calls (see the schedule tx)", text)
self.assertNotIn(operation.operation_id, text)
self.assertIn(f"Operation ID: `{operation.operation_id}`\n", text)
self.assertIn(operation.transaction_hash, text)

@patch("utils.calldata.decoder._resolve_signature_via_abi")
Expand All @@ -123,7 +124,7 @@ def test_a_single_oversized_call_is_omitted_without_breaking_markdown(self, reso
self.assertLessEqual(len(message), stale_operations.MAX_MESSAGE_LENGTH)
self.assertNotIn(signature, text)
self.assertIn("… and 1 more calls (see the schedule tx)", text)
self.assertNotIn(operation.operation_id, text)
self.assertIn(f"Operation ID: `{operation.operation_id}`\n", text)
self.assertIn(operation.transaction_hash, text)
self.assertEqual(text.count("`") % 2, 0)

Expand Down
Loading