Skip to content

Smar 62 tron ensure all scripts work#1617

Open
purriza wants to merge 36 commits intomainfrom
SMAR-62-Tron-ensure-all-scripts-work
Open

Smar 62 tron ensure all scripts work#1617
purriza wants to merge 36 commits intomainfrom
SMAR-62-Tron-ensure-all-scripts-work

Conversation

@purriza
Copy link
Contributor

@purriza purriza commented Feb 4, 2026

Which Jira task belongs to this PR?

https://lifi.atlassian.net/browse/SMAR-62

Why did I implement it this way?

Because Tron needed a delay in order to correctly check the deployed contracts

Checklist before requesting a review

Checklist for reviewer (DO NOT DEPLOY and contracts BEFORE CHECKING THIS!!!)

  • I have checked that any arbitrary calls to external contracts are validated and or restricted
  • I have checked that any privileged calls (i.e. storage modifications) are validated and or restricted
  • I have ensured that any new contracts have had AT A MINIMUM 1 preliminary audit conducted on by <company/auditor>

@lifi-action-bot lifi-action-bot marked this pull request as draft February 4, 2026 15:29
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 4, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Populates the Tron production deployment state and adds rate-limit retry utilities plus Tron-aware health-check logic (RPC wrappers, ownership and whitelist checks, and command retry helpers).

Changes

Cohort / File(s) Summary
Tron Deployment Configuration
script/deploy/_targetState.json
Replaces empty tron.production with a populated LiFiDiamond configuration listing facets, periphery contracts, and version pins (+27/-1).
Health Check — Tron & Retry Integration
script/deploy/healthCheck.ts
Adds execWithRateLimitRetry, Tron-specific contract call helpers (callTronContract, callTronContractBoolean, etc.), integrates retry/delay behavior into facet, periphery, ownership, and whitelist checks, and refactors flows for Tron vs EVM (+1033/-212).
Tron Retry Utilities
script/deploy/tron/utils.ts
Introduces retryWithRateLimit and isRateLimitError, default retry delays/retries, and wraps checkIsDeployedTron with retry logic (+89/-4).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is vague and uses unclear phrasing ('ensure all scripts work') that doesn't clearly convey the specific technical change being made. Revise the title to be more specific about the main change, such as: 'Add rate-limit retry logic for Tron RPC calls' or 'Add Tron network deployment configuration and rate-limit handling'
✅ Passed checks (2 passed)
Check name Status Explanation
Description check ✅ Passed The pull request description includes the Jira task reference, rationale for implementation, and completes the required template sections with appropriate self-review checkboxes marked.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch SMAR-62-Tron-ensure-all-scripts-work

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • JIRA integration encountered authorization issues. Please disconnect and reconnect the integration in the CodeRabbit UI.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@purriza purriza marked this pull request as ready for review February 4, 2026 15:29
@purriza purriza requested review from 0xDEnYO and mirooon February 4, 2026 15:40
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@script/deploy/healthCheck.ts`:
- Around line 36-84: Add a colocated Bun test file for the new helper
execWithRateLimitRetry that provides 100% coverage: create e.g.
healthCheck.test.ts using Bun's describe/it/expect and stub/mock
child_process.execSync (the symbol used inside execWithRateLimitRetry) to
simulate (1) immediate success returning a string, (2) initial 429/rate-limit
errors then success to verify retry delay/attempts, and (3) persistent
429/errors to hit max-retries and throw; assert returned output or thrown error
and verify retry count/ordering where applicable. Ensure tests import
execWithRateLimitRetry from healthCheck.ts and clean up/restore the execSync
mock between tests.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@script/deploy/healthCheck.ts`:
- Around line 81-84: The throw new Error('Max retries reached') statement is
dead/unreachable because the retry loop always either returns result or
re-throws the last error when retries reach maxRetries; remove the unreachable
throw to clean up the code. Locate the retry loop that uses retries and
maxRetries (the block that returns result on success and re-throws error when
retries >= maxRetries) and delete the final throw new Error('Max retries
reached') line so control flow is clear and no dead code remains.
🧹 Nitpick comments (3)
script/deploy/healthCheck.test.ts (2)

12-19: Fix import order violations flagged by ESLint.

The imports should be reordered: external libs first (sorted alphabetically), then local imports. The process.env.BUN_TEST = 'true' assignment before the execWithRateLimitRetry import is intentional to set the test environment flag, but the other imports should be reorganized.

♻️ Proposed fix for import order
-import { describe, it, expect, beforeEach, afterEach, spyOn } from 'bun:test'
-import { consola } from 'consola'
 import * as childProcess from 'child_process'
 
+import { describe, it, expect, beforeEach, afterEach, spyOn } from 'bun:test'
+import { consola } from 'consola'
+
 // Set test environment before importing
 process.env.BUN_TEST = 'true'
 
 import { execWithRateLimitRetry } from './healthCheck'

247-258: Consider wrapping the string in an Error to satisfy ESLint.

The test correctly verifies behavior when non-Error objects are thrown, which is a valid edge case. However, ESLint flags throw 'string error' as a violation of no-throw-literal. You could test the same scenario by catching and re-throwing or using a custom approach.

🔧 Optional fix to satisfy ESLint
     it('should throw immediately on non-Error object thrown', async () => {
+      // eslint-disable-next-line no-throw-literal
       execSyncSpy.mockImplementationOnce(() => {
         throw 'string error'
       })
script/deploy/healthCheck.ts (1)

85-90: Move import to the top of the file with other local imports.

The import statement for Tron utilities is placed after the execWithRateLimitRetry function definition. While ES modules hoist imports, this unconventional placement can confuse maintainers. Per coding guidelines, imports should be grouped at the top: external libs → config files → internal utils/helpers.

♻️ Suggested organization

Move the import block at lines 85-90 to after line 34 (before the new function), keeping it with other local imports:

import targetState from './_targetState.json'
import {
  checkIsDeployedTron,
  getCoreFacets as getTronCoreFacets,
  getTronCorePeriphery,
  parseTroncastFacetsOutput,
} from './tron/utils'

/**
 * Execute a command with retry logic for rate limit errors (429)
 * ...
 */
export async function execWithRateLimitRetry(

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
script/deploy/healthCheck.ts (2)

2-37: ⚠️ Potential issue | 🟡 Minor

Fix duplicate/late imports to satisfy ESLint import order.

Line 35 and Line 108 import retryWithRateLimit twice, and there’s an import block after executable code. ESLint also flags empty lines within the import group.

Suggested cleanup
-import { hexToTronAddress, retryWithRateLimit } from './tron/utils'
+import {
+  checkIsDeployedTron,
+  getCoreFacets as getTronCoreFacets,
+  getTronCorePeriphery,
+  hexToTronAddress,
+  parseTroncastFacetsOutput,
+  retryWithRateLimit,
+} from './tron/utils'
 import targetState from './_targetState.json'
 ...
-import {
-  checkIsDeployedTron,
-  getCoreFacets as getTronCoreFacets,
-  getTronCorePeriphery,
-  parseTroncastFacetsOutput,
-  retryWithRateLimit,
-} from './tron/utils'

Also applies to: 108-114


1136-1286: ⚠️ Potential issue | 🟠 Major

Add Bun tests for the newly introduced Tron helper functions.

Lines 1139–1285 introduce multiple new helpers (wallet selection, selector normalization, Tron ownership checks, ABI decoding). Please extend the colocated Bun tests to cover success and error paths.

As per coding guidelines, “New TypeScript helpers must be covered by a colocated *.test.ts file using Bun (describe / it / expect) with 100% coverage.”

🤖 Fix all issues with AI agents
In `@script/deploy/healthCheck.ts`:
- Around line 997-1003: The variable rpcUrl assigned in the isTron block is
unused and causing a lint error; remove the assignment "const rpcUrl =
networksConfig[networkLower].rpcUrl" from the block (keep the surrounding logic
that reads deployedContracts['LiFiDiamond'], calls
ensureTronAddress(refundWallet, tronWeb), and uses isTron/tronWeb) so no other
behavior changes occur.
- Around line 1375-1612: The inner function parseArray declared inside
checkWhitelistIntegrityTron triggers ESLint no-inner-declarations; move
parseArray to module scope (e.g., alongside other helpers) and update
checkWhitelistIntegrityTron to call the top-level parseArray; ensure the
signature stays parseArray(str: string, start: number): [unknown[], number] and
any references to it (in the JSON.parse fallback within
checkWhitelistIntegrityTron) are adjusted to use the extracted helper.

In `@script/deploy/tron/utils.ts`:
- Around line 33-106: Replace the loose any types and add Bun tests: change the
error parameter types in isRateLimitError and retryWithRateLimit from any to
unknown and add proper narrowing (e.g., derive errorMessage via typeof checks
and optional chaining when accessing message/property) so both functions safely
handle non-Error inputs; then add a colocated Bun test file
script/deploy/tron/utils.test.ts that covers: successful operation (no retries),
rate-limit retries (simulate errors matching '429'/'rate limit' and verify retry
delays/onRetry calls and eventual success), exhausted retries throwing the last
error, non-rate-limit errors propagating immediately, connection error detection
(ECONNREFUSED/ETIMEDOUT when includeConnectionErrors true/false), and edge cases
(error as string/null/unknown), ensuring 100% coverage for both isRateLimitError
and retryWithRateLimit.
🧹 Nitpick comments (1)
script/deploy/healthCheck.ts (1)

116-197: Consider reusing execWithRateLimitRetry to avoid duplicate spawn/retry logic.

callTronContract reimplements the same spawn+retry flow. Reusing the helper keeps the retry policy consistent and reduces duplication.

Refactor sketch
-  const result = await retryWithRateLimit(
-    () => { /* spawn logic */ },
-    3,
-    [1000, 2000, 3000],
-    (attempt, delay) => { ... },
-    false
-  )
+  const result = await execWithRateLimitRetry(
+    ['bun', ...args],
+    2000,
+    3,
+    [1000, 2000, 3000]
+  )

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@script/deploy/healthCheck.ts`:
- Around line 35-37: The file currently imports retryWithRateLimit twice (once
at the top with hexToTronAddress and again later inside the module), causing a
redeclaration and import-in-body ESLint error; fix by consolidating all imports
from './tron/utils' into the existing top-level import (include
retryWithRateLimit, hexToTronAddress and any other symbols used) and remove the
later duplicate import statement so no imports appear inside the module body and
the top import is the sole source of those symbols.
🧹 Nitpick comments (2)
script/deploy/healthCheck.ts (2)

81-85: Redundant error message assignment.

Line 84 creates an Error with a message, then immediately overwrites the message property. This is redundant and uses a type assertion to any.

Suggested fix
         child.on('close', (code) => {
           if (code !== 0) {
-            const error = new Error(
-              `Command failed with exit code ${code}: ${stderr || stdout}`
-            )
-            ;(error as any).message = stderr || stdout || `Exit code ${code}`
-            reject(error)
+            reject(new Error(stderr || stdout || `Exit code ${code}`))
           } else {
             resolve(stdout)
           }
         })

125-197: Code duplication with execWithRateLimitRetry.

The spawn execution logic inside callTronContract (lines 150-182) duplicates the pattern from execWithRateLimitRetry (lines 61-95). Consider reusing execWithRateLimitRetry instead:

Suggested refactor
 async function callTronContract(
   contractAddress: string,
   functionSignature: string,
   params: string[],
   returnType: string,
   rpcUrl: string
 ): Promise<string> {
   const args = [
     'bun',
     'run',
     'script/troncast/index.ts',
     'call',
     contractAddress,
     `${functionSignature} returns (${returnType})`,
     ...(params.length > 0 ? [params.join(',')] : []),
     '--rpc-url',
     rpcUrl,
   ]

-  // Add initial delay for Tron to avoid rate limits
-  await new Promise((resolve) => setTimeout(resolve, 2000))
-
-  // Execute with retry logic for rate limits using spawn to avoid shell issues
-  const result = await retryWithRateLimit(
-    () => {
-      return new Promise<string>((resolve, reject) => {
-        const child = spawn('bun', args.slice(1), {
-          stdio: ['ignore', 'pipe', 'pipe'],
-        })
-        // ... duplicate spawn logic
-      })
-    },
-    // ...
-  )
+  const result = await execWithRateLimitRetry(args, 2000, 3, [1000, 2000, 3000])

   return result.trim()
 }

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
script/deploy/healthCheck.ts (1)

1063-1116: ⚠️ Potential issue | 🟡 Minor

SAFE configuration check silently fails for Tron.

When isTron is true, publicClient is undefined. The SAFE check block (lines 1063-1116) gates on environment === 'production' but does not gate on isTron. If Tron has a safeAddress in its network config, getSafeInfoFromContract(publicClient, safeAddress) will throw because publicClient is undefined, producing a misleading error: "Failed to get SAFE information: ...". Consider adding an explicit Tron skip message:

   if (environment === 'production') {
+    if (isTron) {
+      consola.info('Skipping SAFE checks for Tron network (not supported yet)')
+    } else {
       consola.box('Checking SAFE configuration...')
       // ... existing EVM logic
+    }
   }
🤖 Fix all issues with AI agents
In `@script/deploy/healthCheck.ts`:
- Line 44: Swap the import order so the JSON import is before the utils import:
move the "import targetState from './_targetState.json'" statement above the
"import ... from './tron/utils'" import to satisfy the ESLint import/order rule
(ensure the import of targetState appears in the earlier group than imports from
'./tron/utils').
🧹 Nitpick comments (3)
script/deploy/healthCheck.ts (3)

125-197: Duplicated spawn-and-retry logic — extract to reuse execWithRateLimitRetry.

callTronContract (lines 125-197) manually spawns bun with retry logic nearly identical to execWithRateLimitRetry (lines 56-114). The only differences are the hardcoded 2s delay and the command construction. Since execWithRateLimitRetry already accepts initialDelay, callTronContract can delegate to it:

Refactor sketch
 async function callTronContract(
   contractAddress: string,
   functionSignature: string,
   params: string[],
   returnType: string,
   rpcUrl: string
 ): Promise<string> {
   const args = [
     'bun', 'run', 'script/troncast/index.ts', 'call',
     contractAddress,
     `${functionSignature} returns (${returnType})`,
     ...(params.length > 0 ? [params.join(',')] : []),
     '--rpc-url', rpcUrl,
   ]

-  await new Promise((resolve) => setTimeout(resolve, 2000))
-
-  const result = await retryWithRateLimit(
-    () => {
-      return new Promise<string>((resolve, reject) => {
-        // ... 30+ lines duplicated from execWithRateLimitRetry
-      })
-    },
-    3, [1000, 2000, 3000],
-    ...
-  )
+  const result = await execWithRateLimitRetry(
+    args,
+    2000, // initial delay for Tron
+    3,
+    [1000, 2000, 3000]
+  )

   return result.trim()
 }

This removes ~50 lines of duplication.


86-92: Error .message is overwritten immediately after construction.

On lines 88-91 (and identically 169-172), an Error is constructed with a descriptive message, then .message is immediately overwritten to just the raw stderr/stdout. This discards the "Command failed with exit code …" prefix. If this is intentional (for rate-limit string matching in retryWithRateLimit), a comment would clarify intent. If not, the overwrite is a bug.

             const error = new Error(
               `Command failed with exit code ${code}: ${stderr || stdout}`
             )
-            ;(error as any).message = stderr || stdout || `Exit code ${code}`
+            // Raw message preserved for rate-limit detection in retryWithRateLimit
             reject(error)

If both the prefix and the raw message are needed, consider a custom property (e.g., (error as any).rawOutput = stderr || stdout) rather than silently mutating .message.

Also applies to: 167-173


1508-1539: Whitelist granular check: each pair incurs a 500ms delay + RPC round-trip — can be very slow.

For large whitelists, checkWhitelistIntegrityTron issues one callTronContractBoolean call per expected pair (line 1515), each preceded by a 500ms delayTron(). With, say, 200 pairs this loop alone takes >100 seconds of sleeping plus RPC time.

The getter-array check (Step 2/2, lines 1547-1610) already validates the same data offline via set comparison. Consider making the per-pair granular check optional (or batching with a single getAllContractSelectorPairs comparison), and only falling back to per-pair calls if discrepancies are found.

…dularity

- Consolidate delay constants in script/deploy/tron/constants.ts
- Extract Tron health check functions to healthCheckTronUtils.ts
- Replace setTimeout with centralized sleep() utility across 9 files
- Improve RPC URL handling to prioritize environment variables
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants