Skip to content

tests, debug, deploy#848

Open
n0umen0n wants to merge 3 commits intomainfrom
debug1v1v
Open

tests, debug, deploy#848
n0umen0n wants to merge 3 commits intomainfrom
debug1v1v

Conversation

@n0umen0n
Copy link
Contributor

@n0umen0n n0umen0n commented May 29, 2025

Summary by CodeRabbit

  • New Features

    • Introduced scripts to debug, list, and verify decaying and ownership token factory contracts on mainnet.
    • Added scripts to set proposals and decay voting power contract addresses in factories.
    • Added a comprehensive test script for the full decaying token proposal and deployment flow.
    • Added scripts to configure ownership token contracts and deploy ownership token voting power proxy.
    • Enhanced storage layout to include new implementation entries for decaying and ownership token factories.
  • Bug Fixes

    • Improved error handling and verification steps in upgrade scripts for token factories.
  • Documentation

    • Updated documentation to include instructions for upgrading the decaying token factory.
  • Tests

    • Added thorough test coverage for the getSpaceToken function and decaying token deployment scenarios.

@vercel
Copy link

vercel bot commented May 29, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
www-hypha-earth-v3 ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 30, 2025 6:44am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 29, 2025

"""

Walkthrough

This update introduces several new scripts for interacting with and testing DecayingTokenFactory and OwnershipTokenFactory contracts on Ethereum mainnet. It adds their storage layouts to the OpenZeppelin manifest, enhances upgrade scripts with improved validation and error handling, and extends test coverage for the getSpaceToken function. Documentation is updated accordingly.

Changes

File(s) Change Summary
packages/storage-evm/.openzeppelin/base.json Added storage layouts for DecayingTokenFactoryStorage, OwnershipTokenFactoryStorage, and TokenVotingPowerStorage; updated proxies and addresses.
packages/storage-evm/scripts/README.md Added documentation for upgrading the Decaying Token Factory.
packages/storage-evm/scripts/base-mainnet-contracts-scripts/debug-decaying-factory.ts New script to debug DecayingTokenFactory contract interface and functions.
packages/storage-evm/scripts/base-mainnet-contracts-scripts/list-decaying-space-tokens.ts New script to list decaying tokens for DAO spaces on mainnet.
packages/storage-evm/scripts/base-mainnet-contracts-scripts/list-ownership-space-tokens.ts New script to list ownership tokens for DAO spaces on mainnet.
packages/storage-evm/scripts/base-mainnet-contracts-scripts/set-decay-token-factory-in-votedecaytokenvotingpower.ts New script to set the decay token factory in VoteDecayTokenVotingPower contract.
packages/storage-evm/scripts/base-mainnet-contracts-scripts/set-decay-voting-power-contract-in-decayingtokenfactory.ts Extended interface and ABI; added verification after setting decay voting power contract.
packages/storage-evm/scripts/base-mainnet-contracts-scripts/set-proposals-contract-in-decayingtokenfactory.ts New script to set proposals contract in DecayingTokenFactory.
packages/storage-evm/scripts/base-mainnet-contracts-scripts/test-decaying-token-proposal.ts New comprehensive script to test decaying token deployment and governance proposal flow.
packages/storage-evm/scripts/base-mainnet-contracts-scripts/configure-ownership-token-contracts.ts New script to configure ownership token contracts by setting voting power and factory addresses.
packages/storage-evm/scripts/decaying-token-factory.upgrade.ts Enhanced upgrade script with validation, force import, and improved logging.
packages/storage-evm/scripts/ownership-token-factory.upgrade.ts Enhanced upgrade script with ownership checks and improved diagnostics.
packages/storage-evm/scripts/ownership-token-voting-power-proxy.deploy.ts New deployment script for OwnershipTokenVotingPowerImplementation proxy contract.
packages/storage-evm/scripts/test-upgraded-getspacetoken.ts New script to test getSpaceToken on upgraded DecayingTokenFactory contract.
packages/storage-evm/scripts/verify-decaying-token-factory.ts New script to verify DecayingTokenFactory contract and test function presence.
packages/storage-evm/scripts/set-decay-token-factory-in-votedecaytokenvotingpower.ts New script to set decay token factory address in VoteDecayTokenVotingPower contract.
packages/storage-evm/scripts/set-decay-voting-power-contract-in-decayingtokenfactory.ts Added decayVotingPowerContract view function to interface and ABI; added verification after setting.
packages/storage-evm/scripts/set-proposals-contract-in-decayingtokenfactory.ts New script to set proposals contract address in DecayingTokenFactory contract.
packages/storage-evm/test/DAOSpaceFactoryImplementation.test.ts Added test case for getSpaceToken in DecayingTokenFactory across multiple scenarios.
packages/storage-evm/contracts/addresses.txt Extended deployment log with OwnershipTokenVotingPower deployment sequence.
path/to/file Added empty file (no functional code).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Script
    participant Provider
    participant DecayingTokenFactory
    participant DAOProposals
    participant DAOSpaceFactory
    participant VoteDecayTokenVotingPower

    User->>Script: Run test-decaying-token-proposal.ts
    Script->>Provider: Connect to Ethereum mainnet
    Script->>DAOSpaceFactory: Create new space
    DAOSpaceFactory-->>Script: Return new space ID
    Script->>DecayingTokenFactory: Check getSpaceToken(spaceId)
    DecayingTokenFactory-->>Script: Return zero address (no token yet)
    Script->>DAOProposals: Submit proposal to deploy decaying token
    DAOProposals-->>Script: Return proposal ID
    Script->>DAOProposals: Vote on proposal
    DAOProposals-->>Script: Confirm vote
    Script->>DAOProposals: Execute proposal
    DAOProposals-->>DecayingTokenFactory: Call deploy function
    DecayingTokenFactory-->>DAOProposals: Emit TokenDeployed event
    Script->>DecayingTokenFactory: Check getSpaceToken(spaceId)
    DecayingTokenFactory-->>Script: Return deployed token address
    Script->>DeployedToken: Query token parameters
    DeployedToken-->>Script: Return name, symbol, decay params
    Script-->>User: Log results
Loading

Possibly related PRs

  • hypha-dao/hypha-web#746: Adds storage layout entries for OwnershipTokenFactoryStorage and DecayingTokenFactoryStorage, directly matching the new manifest entries here.
  • hypha-dao/hypha-web#739: Updates storage layouts for DecayingTokenFactoryStorage, overlapping with the manifest changes in this update.
  • hypha-dao/hypha-web#613: Adds new proxy and implementation entries with storage layouts for DAOSpaceFactoryStorage, related to proxy and implementation manifest updates.

Suggested reviewers

  • evgenibir
  • plitzenberger

Poem

In the warren of code, new scripts do appear,
Factories for tokens—both ownership and decay—are here!
Upgrades and tests, with addresses aligned,
Storage layouts updated, all neatly combined.
With every hop forward, our contracts grow strong—
🐇 On mainnet adventures, we code right along!
"""

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 5

🧹 Nitpick comments (13)
packages/storage-evm/scripts/base-mainnet-contracts-scripts/set-decay-token-factory-in-votedecaytokenvotingpower.ts (1)

157-195: Enhance transaction error handling.

The transaction handling is functional but could provide more detailed error information for debugging mainnet issues.

Consider enhancing error handling with more specific error types:

  } catch (error: any) {
-   console.error('Error setting decay token factory:', error.message);
+   console.error('Error setting decay token factory:', error.message);
+   if (error.code) {
+     console.error('Error code:', error.code);
+   }
+   if (error.reason) {
+     console.error('Error reason:', error.reason);
+   }
    throw error;
  }
packages/storage-evm/scripts/base-mainnet-contracts-scripts/list-ownership-space-tokens.ts (3)

215-235: Consider batch processing for improved performance.

The current implementation queries tokens sequentially, which could be slow for large numbers of spaces. Consider implementing batch processing or parallel requests to improve performance.

-      // Iterate through all spaces
-      for (let spaceId = 1; spaceId <= Number(spaceCounter); spaceId++) {
-        try {
-          const tokenAddress = await ownershipTokenFactory.getSpaceToken(
-            spaceId,
-          );
+      // Iterate through all spaces with batching
+      const batchSize = 10;
+      for (let i = 1; i <= Number(spaceCounter); i += batchSize) {
+        const batch = [];
+        for (let j = i; j < Math.min(i + batchSize, Number(spaceCounter) + 1); j++) {
+          batch.push(ownershipTokenFactory.getSpaceToken(j));
+        }
+        
+        try {
+          const results = await Promise.allSettled(batch);
+          results.forEach((result, index) => {
+            const spaceId = i + index;
+            if (result.status === 'fulfilled') {
+              const tokenAddress = result.value;

7-10: Document contract addresses for better maintainability.

The contract addresses should include comments indicating the network, deployment details, and purpose for easier verification and maintenance.

-// Base Mainnet contract addresses
+// Base Mainnet contract addresses - deployed [date]
 const CONTRACTS = {
+  // OwnershipTokenFactory proxy contract
   OWNERSHIP_TOKEN_FACTORY: '0xA1eDf096B72226ae2f7BDEb12E9c9C82152BccB6',
+  // DAOSpaceFactory contract for space enumeration
   DAO_SPACE_FACTORY: '0xc8B8454D2F9192FeCAbc2C6F5d88F6434A2a9cd9',
 };
🧰 Tools
🪛 Gitleaks (8.26.0)

8-8: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


216-235: Consider extracting magic number to a constant.

The loop starting from spaceId = 1 uses a magic number. Consider making this configurable or documented.

+      const FIRST_SPACE_ID = 1; // Space IDs start from 1, not 0
       // Iterate through all spaces
-      for (let spaceId = 1; spaceId <= Number(spaceCounter); spaceId++) {
+      for (let spaceId = FIRST_SPACE_ID; spaceId <= Number(spaceCounter); spaceId++) {
packages/storage-evm/scripts/ownership-token-factory.upgrade.ts (1)

44-54: Good pre-upgrade validation approach.

Testing the existence of getSpaceToken before upgrade helps validate whether the upgrade is needed. However, consider making this test more robust by testing with a known space ID that has a token deployed.

-    // Test if getSpaceToken function exists (should fail before upgrade if missing)
-    console.log('\n🧪 Testing current getSpaceToken function...');
-    try {
-      await currentProxy.getSpaceToken(1);
-      console.log(
-        '⚠️ getSpaceToken already exists - upgrade may not be needed',
-      );
-    } catch (error) {
-      console.log('✅ getSpaceToken missing as expected');
-    }
+    // Test if getSpaceToken function exists (should fail before upgrade if missing)
+    console.log('\n🧪 Testing current getSpaceToken function...');
+    try {
+      // Test with a low-level call to distinguish between missing function vs revert
+      const result = await currentProxy.getSpaceToken.staticCall(1);
+      console.log(
+        '⚠️ getSpaceToken already exists - upgrade may not be needed',
+      );
+    } catch (error: any) {
+      if (error.code === 'CALL_EXCEPTION' && error.reason?.includes('function selector was not recognized')) {
+        console.log('✅ getSpaceToken missing as expected');
+      } else {
+        console.log('✅ getSpaceToken exists but reverted (expected behavior)');
+      }
+    }
packages/storage-evm/scripts/verify-decaying-token-factory.ts (3)

40-54: Intelligent fallback mechanism for function testing.

The low-level call approach is excellent for distinguishing between missing functions and functions that revert. Consider deriving the function selector programmatically for better maintainability.

-    // Try low-level call
-    const functionSelector = '0x1080fa43';
+    // Try low-level call
+    const functionSelector = ethers.id('getSpaceToken(uint256)').slice(0, 10);

This makes the code more maintainable and self-documenting.


3-3: Document the proxy address for better maintainability.

The hardcoded proxy address should include a comment indicating the network and purpose.

-const PROXY_ADDRESS = '0x299f4D2327933c1f363301dbd2a28379ccD5539b';
+// DecayingTokenFactory proxy address on Base Mainnet
+const PROXY_ADDRESS = '0x299f4D2327933c1f363301dbd2a28379ccD5539b';

41-53: Consider making function selector more maintainable.

The hardcoded function selector could be more maintainable by computing it from the function signature.

-    // Try low-level call
-    const functionSelector = '0x1080fa43';
+    // Try low-level call - getSpaceToken(uint256)
+    const functionSelector = ethers.id('getSpaceToken(uint256)').slice(0, 10);
packages/storage-evm/test/DAOSpaceFactoryImplementation.test.ts (1)

1072-1315: Well-structured test with comprehensive coverage, but consider reducing console output.

This new test case provides excellent coverage of the getSpaceToken function across multiple scenarios:

Strengths:

  • Tests both before and after token deployment states
  • Covers multiple spaces to ensure proper isolation
  • Handles edge cases (non-existent space IDs)
  • Thorough property verification of deployed tokens
  • Proper async/await usage and event parsing
  • Good test organization with clear sections

⚠️ Areas for improvement:

  • Excessive console logging: While useful for debugging, the extensive console.log statements (lines 1077, 1096, 1102, 1117-1135, etc.) may clutter test output in CI/CD environments
  • Test performance: The detailed logging could slow down test execution

Recommendation: Consider using a test-specific logger or reducing console output to essential information only.

- console.log('\n=== TESTING DECAYING TOKEN FACTORY getSpaceToken ===');
- console.log(`✅ Created space with ID: ${spaceId}`);
- console.log(`✅ Space executor: ${executorAddress}`);
+ // Consider using a test logger or removing verbose console output
+ // console.log('\n=== TESTING DECAYING TOKEN FACTORY getSpaceToken ===');
packages/storage-evm/scripts/base-mainnet-contracts-scripts/set-proposals-contract-in-decayingtokenfactory.ts (1)

48-54: Apply optional chaining for cleaner code.

The static analysis tool correctly suggests using optional chaining for a more concise implementation.

Apply this diff to use optional chaining:

   for (const [key, pattern] of Object.entries(patterns)) {
     const match = fileContent.match(pattern);
-    if (match && match[1]) {
+    if (match?.[1]) {
       addresses[key] = match[1];
     }
   }
🧰 Tools
🪛 Biome (1.9.4)

[error] 50-50: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/storage-evm/scripts/base-mainnet-contracts-scripts/test-decaying-token-proposal.ts (1)

33-38: Consider making contract addresses configurable.

While hardcoding addresses works for test scripts, consider loading them from environment variables or a configuration file for better flexibility across different networks.

Example approach:

const CONTRACTS = {
  DAO_SPACE_FACTORY: process.env.DAO_SPACE_FACTORY_ADDRESS || '0xc8B8454D2F9192FeCAbc2C6F5d88F6434A2a9cd9',
  DAO_PROPOSALS: process.env.DAO_PROPOSALS_ADDRESS || '0x001bA7a00a259Fb12d7936455e292a60FC2bef14',
  // ... other contracts
};
🧰 Tools
🪛 Gitleaks (8.26.0)

36-36: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


37-37: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

packages/storage-evm/scripts/base-mainnet-contracts-scripts/debug-decaying-factory.ts (2)

6-6: Contract address should be documented and verified.

The hardcoded contract address should include a comment indicating what this address represents (network, deployment date, etc.) to aid in verification and maintenance.

-const DECAYING_TOKEN_FACTORY = '0x299f4D2327933c1f363301dbd2a28379ccD5539b';
+// DecayingTokenFactory proxy address on Base Mainnet
+const DECAYING_TOKEN_FACTORY = '0x299f4D2327933c1f363301dbd2a28379ccD5539b';
🧰 Tools
🪛 Gitleaks (8.26.0)

6-6: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


40-48: Improve error handling specificity.

The error handling truncates the error message which might remove important debugging information. Consider preserving more context while still keeping output readable.

-      console.log(`Failed: ${error.message.split('(')[0]}`);
+      console.log(`Failed: ${error.code || 'UNKNOWN_ERROR'} - ${error.message.substring(0, 100)}${error.message.length > 100 ? '...' : ''}`);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8b9638b and a97b4d1.

📒 Files selected for processing (15)
  • packages/storage-evm/.openzeppelin/base.json (1 hunks)
  • packages/storage-evm/scripts/README.md (1 hunks)
  • packages/storage-evm/scripts/base-mainnet-contracts-scripts/debug-decaying-factory.ts (1 hunks)
  • packages/storage-evm/scripts/base-mainnet-contracts-scripts/list-decaying-space-tokens.ts (1 hunks)
  • packages/storage-evm/scripts/base-mainnet-contracts-scripts/list-ownership-space-tokens.ts (1 hunks)
  • packages/storage-evm/scripts/base-mainnet-contracts-scripts/set-decay-token-factory-in-votedecaytokenvotingpower.ts (1 hunks)
  • packages/storage-evm/scripts/base-mainnet-contracts-scripts/set-decay-voting-power-contract-in-decayingtokenfactory.ts (3 hunks)
  • packages/storage-evm/scripts/base-mainnet-contracts-scripts/set-proposals-contract-in-decayingtokenfactory.ts (1 hunks)
  • packages/storage-evm/scripts/base-mainnet-contracts-scripts/test-decaying-token-proposal.ts (1 hunks)
  • packages/storage-evm/scripts/decaying-token-factory.upgrade.ts (1 hunks)
  • packages/storage-evm/scripts/ownership-token-factory.upgrade.ts (1 hunks)
  • packages/storage-evm/scripts/test-upgraded-getspacetoken.ts (1 hunks)
  • packages/storage-evm/scripts/verify-decaying-token-factory.ts (1 hunks)
  • packages/storage-evm/test/DAOSpaceFactoryImplementation.test.ts (1 hunks)
  • path/to/file (1 hunks)
🧰 Additional context used
🪛 Gitleaks (8.26.0)
packages/storage-evm/scripts/base-mainnet-contracts-scripts/debug-decaying-factory.ts

6-6: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

packages/storage-evm/scripts/base-mainnet-contracts-scripts/list-decaying-space-tokens.ts

6-6: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

packages/storage-evm/scripts/base-mainnet-contracts-scripts/list-ownership-space-tokens.ts

8-8: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

packages/storage-evm/scripts/base-mainnet-contracts-scripts/test-decaying-token-proposal.ts

36-36: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


37-37: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


834-834: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🪛 Biome (1.9.4)
packages/storage-evm/scripts/base-mainnet-contracts-scripts/set-decay-token-factory-in-votedecaytokenvotingpower.ts

[error] 51-51: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/storage-evm/scripts/base-mainnet-contracts-scripts/set-proposals-contract-in-decayingtokenfactory.ts

[error] 50-50: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 ESLint
packages/storage-evm/scripts/base-mainnet-contracts-scripts/test-decaying-token-proposal.ts

[error] 784-784: 'proposalData' is never reassigned. Use 'const' instead.

(prefer-const)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: main
  • GitHub Check: deploy-preview
🔇 Additional comments (39)
packages/storage-evm/.openzeppelin/base.json (3)

7457-7461: Storage layout entry correctly defines DecayingTokenFactory allAddresses.

The addition of the allAddresses array properly documents the contract deployment at the specified address, following OpenZeppelin manifest conventions.


7462-7595: DecayingTokenFactory storage layout properly extends with proposalsContract field.

The updated storage layout correctly adds the proposalsContract field at slot 4, which is safe for upgradeable contracts as it extends the existing storage without modifying previous slots. This follows the append-only pattern required for safe contract upgrades.


7596-7721: OwnershipTokenFactory storage layout properly defined.

The storage layout correctly defines the expected fields for the OwnershipTokenFactory contract:

  • spacesContract at slot 0
  • votingPowerContract at slot 1
  • isTokenDeployedByFactory mapping at slot 2
  • spaceTokens mapping at slot 3

The layout follows OpenZeppelin patterns and is consistent with similar factory contracts in the codebase.

packages/storage-evm/scripts/base-mainnet-contracts-scripts/set-decay-token-factory-in-votedecaytokenvotingpower.ts (1)

140-150: Good ownership verification implementation.

The ownership check is well-implemented with proper error handling and clear messaging. This prevents unauthorized transactions and provides helpful debugging information.

path/to/file (1)

1-1: Clarify the purpose of this empty file.

This file contains only a blank line. If this is intentionally empty (e.g., a placeholder or required for build processes), consider adding a comment explaining its purpose.

If this file was added unintentionally, it should be removed from the PR.

packages/storage-evm/scripts/README.md (1)

148-152: Documentation update follows established patterns.

The addition of upgrade instructions for the Decaying Token Factory is well-formatted and consistent with the existing documentation structure. The command follows the same pattern as other upgrade scripts.

packages/storage-evm/scripts/test-upgraded-getspacetoken.ts (2)

32-34: Good diagnostic messaging for interface issues.

The comment about potential interface or override issues provides helpful debugging context for developers investigating failures.


16-16:

Details

✅ Verification successful

Verify ethers.ZeroAddress compatibility.

The usage of ethers.ZeroAddress may not be available in all versions of ethers.js.

Ensure that the version of ethers.js being used supports ethers.ZeroAddress. If using an older version, use ethers.constants.AddressZero instead:


🏁 Script executed:

#!/bin/bash
# Check the ethers version in package.json
cat package.json | jq '.dependencies.ethers // .devDependencies.ethers'

Length of output: 83


🌐 Web query:

ethers.ZeroAddress ethers.js v6 documentation

💡 Result:

Ethers.js v6 includes the ZeroAddress constant as part of its standard constants library. This constant represents the Ethereum "zero address" (0x0000000000000000000000000000000000000000), which is commonly used in Ethereum development for various purposes.

Accessing ZeroAddress in Ethers.js v6

In Ethers.js v6, you can access the ZeroAddress constant directly from the ethers object:

import { ethers } from "ethers";

// Use the ZeroAddress constant
const zeroAddr = ethers.ZeroAddress;
console.log(zeroAddr); // Outputs: 0x0000000000000000000000000000000000000000

The ZeroAddress constant is defined as a string that represents 20 bytes (40 nibbles) of zeros prefixed with "0x"[2]. This is equivalent to the v5 ethers.constants.AddressZero that was previously used[5].

Other Related Constants

Ethers.js v6 provides several other useful constants along with ZeroAddress:

  • ZeroHash: Represents 32 bytes (64 nibbles) of zeros[2]
  • MaxUint256: The maximum value for a uint256[2]
  • MaxInt256: The maximum value for an int256[2]
  • MinInt256: The minimum value for an int256[2]
  • WeiPerEther: The BigInt value representing 10^18 (number of Wei per Ether)[2]
  • EtherSymbol: The Ether symbol (Ξ)[2]
  • MessagePrefix: A constant for the EIP-191 personal message prefix[2]

Migration from v5

If you're migrating from v5 to v6, note that the constants structure has changed. In v5, constants were accessed through ethers.constants.AddressZero, but in v6, they're available directly from the root ethers object as ethers.ZeroAddress[5][8].

This is part of the broader changes in v6 where most functionality has been moved to the root package for easier access, along with the shift to modern ES6 features including the use of native BigInt instead of the BigNumber class[4][6].

Citations:


No action needed: ethers.ZeroAddress is supported in ethers.js v6.13.5
Verified against the official ethers.js v6 documentation that ethers.ZeroAddress is available and equivalent to the v5 ethers.constants.AddressZero.

packages/storage-evm/scripts/base-mainnet-contracts-scripts/debug-decaying-factory.ts (2)

1-51: LGTM! Well-structured debugging script with good interface discovery approach.

The script effectively tests multiple potential function signatures to determine the correct contract interface. The error handling and logging are appropriate for a debugging utility.

Note: The static analysis warning about line 6 being a "Generic API Key" is a false positive - this is clearly an Ethereum contract address (0x299f4D2327933c1f363301dbd2a28379ccD5539b).

🧰 Tools
🪛 Gitleaks (8.26.0)

6-6: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


9-11: Environment variable validation is appropriate.

Good practice to validate required environment variables early and provide clear error messages.

packages/storage-evm/scripts/base-mainnet-contracts-scripts/list-ownership-space-tokens.ts (3)

80-156: Excellent interface discovery implementation with comprehensive validation.

The checkContractInterface function is well-designed with thorough testing of multiple function signatures and proper error categorization. The distinction between non-existent functions and functions that revert is particularly valuable for debugging.


12-18: TypeScript interfaces are well-designed.

The interfaces properly define the expected contract methods with correct types. Good practice for type safety.


80-156: Contract interface checking is thorough and well-implemented.

The function properly validates contract deployment and tests multiple function signatures with appropriate error handling. The logic correctly distinguishes between missing functions and functions that revert.

packages/storage-evm/scripts/ownership-token-factory.upgrade.ts (8)

19-43: Excellent security validation with proper ownership verification.

The ownership check before proceeding with the upgrade is a critical security measure. The error messages are clear and provide actionable information for troubleshooting.


58-99: Robust upgrade logic with intelligent retry mechanism.

The try-catch structure that handles missing proxy manifests with force import is well-implemented. This gracefully handles edge cases where the proxy isn't properly tracked in the upgrades manifest.


2-4: Good addition of environment configuration.

Adding dotenv configuration allows for better environment management and follows best practices for handling environment variables.


14-18: Excellent logging for upgrade visibility.

The detailed logging provides good visibility into the upgrade process, including network information and addresses involved.


30-42: Proper ownership verification enhances security.

The ownership check is crucial for upgrade security and prevents unauthorized upgrades. Good error handling with clear messages.


44-53: Smart pre-upgrade function testing.

Testing the getSpaceToken function before upgrade helps determine if the upgrade is actually needed. This prevents unnecessary upgrades.


80-99: Robust retry logic with force import.

The fallback mechanism using forceImport when the proxy is not found in the manifest is a good practice for handling edge cases in proxy upgrades.


104-112: Helpful diagnostic information for common issues.

The additional debugging hints for ownership and proxy admin issues provide valuable guidance for troubleshooting upgrade failures.

packages/storage-evm/scripts/verify-decaying-token-factory.ts (3)

18-32: Good basic function verification with proper error handling.

The verification of core contract functions (owner() and spacesContract()) provides essential validation that the contract is properly deployed and accessible.


8-10: Clear verification logging provides good visibility.

The logging clearly indicates what is being verified and provides useful context about the network and address being used.


19-31: Proper error handling for basic contract functions.

The verification of basic contract functions with appropriate error handling follows good practices for contract verification.

packages/storage-evm/scripts/base-mainnet-contracts-scripts/set-decay-voting-power-contract-in-decayingtokenfactory.ts (1)

170-193: Excellent verification pattern for state changes!

The addition of retrieving and verifying the set contract address is a best practice that ensures the transaction succeeded and the state was updated correctly.

packages/storage-evm/scripts/decaying-token-factory.upgrade.ts (2)

19-99: Well-structured upgrade script with excellent error handling!

The improvements provide:

  • Early ownership validation to prevent failed transactions
  • Pre/post upgrade testing of the new getSpaceToken function
  • Automatic force import handling when proxy isn't in the manifest
  • Clear progress indicators and error messages

This is a robust pattern for proxy upgrades.


100-115: Helpful debugging hints in error handling!

The specific error messages for ownership and proxy admin issues will help developers quickly diagnose and resolve common upgrade problems.

packages/storage-evm/scripts/base-mainnet-contracts-scripts/list-decaying-space-tokens.ts (3)

86-165: Robust contract interface detection!

The checkContractInterface function handles uncertainty about the actual function name by testing multiple possibilities. This defensive approach ensures the script works even if the deployed contract uses a different function name than expected.


199-264: Well-designed command-line interface with comprehensive output!

The script provides flexibility to query specific space IDs or enumerate all spaces, with a helpful summary that distinguishes between spaces with and without decaying tokens.


272-313: Useful test function for development!

Having the testDecayingTokens function available but commented out is a good practice - it allows quick testing during development without affecting normal script execution.

packages/storage-evm/scripts/base-mainnet-contracts-scripts/set-proposals-contract-in-decayingtokenfactory.ts (4)

9-30: LGTM! Well-structured type definitions.

The interfaces provide good type safety for ethers.js interactions and the contract methods.


58-98: LGTM! Minimal ABI with required functions.

The ABI includes only the necessary functions for this script, which is a good practice for maintainability.


100-191: Excellent implementation with comprehensive verification.

The function includes:

  • Proper error handling for missing addresses
  • Ownership verification to prevent unauthorized operations
  • Post-update validation to confirm success
  • Clear user feedback throughout the process

193-198: LGTM! Standard script execution pattern.

Proper handling of async execution with appropriate exit codes.

packages/storage-evm/scripts/base-mainnet-contracts-scripts/test-decaying-token-proposal.ts (5)

1-31: LGTM! Well-defined interfaces and imports.

The interfaces provide good type safety for space creation, proposals, and account data.


40-241: LGTM! Comprehensive ABI definitions.

All required contract functions are properly defined in the ABIs.


243-366: Excellent event parsing implementation.

The functions provide comprehensive event parsing with:

  • Detailed logging for debugging
  • Proper error handling for decoding failures
  • Support for multiple event types

830-836: Hardcoded fallback address needs explanation.

The fallback address 0xc8995514f8c76b9d9a509b4fdba0d06eb732907e is hardcoded without explanation. This could cause issues if the test is run in different environments.

Consider:

  1. Adding a comment explaining why this specific address is used as a fallback
  2. Making it configurable via environment variables
  3. Or removing it entirely if it's test-specific
       } catch (error: any) {
         console.log(`❌ getSpaceToken failed: ${error.message}`);
-        // Fall back to the known address from events
-        tokenAddressAfter = '0xc8995514f8c76b9d9a509b4fdba0d06eb732907e';
-        console.log(`Using token address from event: ${tokenAddressAfter}`);
+        // If getSpaceToken fails, we should use the address from the deployment event
+        // or fail the test gracefully
+        console.log('Unable to retrieve token address - proposal may not have executed');
       }
🧰 Tools
🪛 Gitleaks (8.26.0)

834-834: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


367-915: Comprehensive test implementation with excellent coverage.

The test script thoroughly covers:

  • Space creation and membership verification
  • Contract configuration validation
  • Proposal creation with proper encoding
  • Voting and execution flow
  • Token deployment verification
  • Detailed error handling and debugging output

Great work on the comprehensive test coverage!

🧰 Tools
🪛 Gitleaks (8.26.0)

834-834: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🪛 ESLint

[error] 784-784: 'proposalData' is never reassigned. Use 'const' instead.

(prefer-const)

Comment on lines +101 to +123
async function main(): Promise<void> {
// Parse addresses from file
const addresses = parseAddressesFile();

// Verify all required addresses are available
const requiredContracts = [
'DecayingTokenFactory',
'VoteDecayTokenVotingPower',
];
const missingContracts = requiredContracts.filter(
(contract) => !addresses[contract],
);

if (missingContracts.length > 0) {
throw new Error(`Missing addresses for: ${missingContracts.join(', ')}`);
}

// Connect to the network
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);

// Create a wallet instance
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '', provider);

Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add environment variable validation.

The script relies on critical environment variables but doesn't validate their presence, which could lead to runtime failures.

Add this validation at the beginning of the main function:

async function main(): Promise<void> {
+ // Validate required environment variables
+ if (!process.env.RPC_URL) {
+   throw new Error('RPC_URL environment variable is required');
+ }
+ if (!process.env.PRIVATE_KEY) {
+   throw new Error('PRIVATE_KEY environment variable is required');
+ }
+
  // Parse addresses from file
  const addresses = parseAddressesFile();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async function main(): Promise<void> {
// Parse addresses from file
const addresses = parseAddressesFile();
// Verify all required addresses are available
const requiredContracts = [
'DecayingTokenFactory',
'VoteDecayTokenVotingPower',
];
const missingContracts = requiredContracts.filter(
(contract) => !addresses[contract],
);
if (missingContracts.length > 0) {
throw new Error(`Missing addresses for: ${missingContracts.join(', ')}`);
}
// Connect to the network
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
// Create a wallet instance
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '', provider);
async function main(): Promise<void> {
// Validate required environment variables
if (!process.env.RPC_URL) {
throw new Error('RPC_URL environment variable is required');
}
if (!process.env.PRIVATE_KEY) {
throw new Error('PRIVATE_KEY environment variable is required');
}
// Parse addresses from file
const addresses = parseAddressesFile();
// Verify all required addresses are available
const requiredContracts = [
'DecayingTokenFactory',
'VoteDecayTokenVotingPower',
];
const missingContracts = requiredContracts.filter(
(contract) => !addresses[contract],
);
if (missingContracts.length > 0) {
throw new Error(`Missing addresses for: ${missingContracts.join(', ')}`);
}
// Connect to the network
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
// Create a wallet instance
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '', provider);
...
}
🤖 Prompt for AI Agents
In
packages/storage-evm/scripts/base-mainnet-contracts-scripts/set-decay-token-factory-in-votedecaytokenvotingpower.ts
around lines 101 to 123, the script uses environment variables RPC_URL and
PRIVATE_KEY without validating their presence, risking runtime errors. Add
validation at the start of the main function to check if process.env.RPC_URL and
process.env.PRIVATE_KEY are defined; if either is missing, throw an error with a
clear message indicating the missing environment variable(s). This ensures the
script fails early with a helpful error instead of failing unpredictably later.


// Step 5: Check proposal status and wait for execution
console.log('\n📍 Step 5: Checking proposal status...');
let proposalData = await daoProposals.getProposalCore(proposalId);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Use const instead of let for proposalData.

The variable is never reassigned, so it should be declared as const.

Apply this diff:

-      let proposalData = await daoProposals.getProposalCore(proposalId);
+      const proposalData = await daoProposals.getProposalCore(proposalId);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let proposalData = await daoProposals.getProposalCore(proposalId);
const proposalData = await daoProposals.getProposalCore(proposalId);
🧰 Tools
🪛 ESLint

[error] 784-784: 'proposalData' is never reassigned. Use 'const' instead.

(prefer-const)

🤖 Prompt for AI Agents
In
packages/storage-evm/scripts/base-mainnet-contracts-scripts/test-decaying-token-proposal.ts
at line 784, change the declaration of proposalData from let to const since the
variable is never reassigned. This improves code clarity and prevents accidental
reassignment.

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: 4

🧹 Nitpick comments (4)
packages/storage-evm/scripts/ownership-token-voting-power-proxy.deploy.ts (2)

14-21: Consider adding deployment parameter validation

The deployment uses adminAddress as the initializer parameter, but there's no validation that this address is valid or intentional.

Consider adding validation before deployment:

+ // Validate admin address
+ if (!adminAddress || adminAddress === ethers.ZeroAddress) {
+   throw new Error('Invalid admin address');
+ }
+
  const ownershipTokenVotingPower = await upgrades.deployProxy(
    OwnershipTokenVotingPower,
    [adminAddress],
    {
      initializer: 'initialize',
      kind: 'uups',
    },
  );

30-35: Enhance error handling with deployment context

The error handling could be more informative by including deployment context information.

Consider enhancing the error output:

main()
  .then(() => process.exit(0))
  .catch((error: Error) => {
-   console.error(error);
+   console.error('Deployment failed:', error.message);
+   console.error('Stack trace:', error.stack);
    process.exit(1);
  });
packages/storage-evm/scripts/base-mainnet-contracts-scripts/configure-ownership-token-contracts.ts (1)

148-153: Secure environment variable handling

The RPC URL and private key handling is appropriate with fallback for missing private key, though consider additional validation.

Consider adding validation for required environment variables:

+ if (!process.env.RPC_URL) {
+   throw new Error('RPC_URL environment variable is required');
+ }
+ if (!process.env.PRIVATE_KEY) {
+   throw new Error('PRIVATE_KEY environment variable is required');
+ }
+
  // Connect to the network
  const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
  
  // Create a wallet instance
- const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '', provider);
+ const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
packages/storage-evm/scripts/base-mainnet-contracts-scripts/set-proposals-contract-in-decayingtokenfactory.ts (1)

117-118: Consider environment variable validation

Similar to the previous script, consider validating required environment variables exist before proceeding.

Add validation for required environment variables:

+ if (!process.env.RPC_URL) {
+   throw new Error('RPC_URL environment variable is required');
+ }
+ if (!process.env.PRIVATE_KEY) {
+   throw new Error('PRIVATE_KEY environment variable is required');
+ }
+
  // Connect to the network
  const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
  
  // Create a wallet instance
- const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '', provider);
+ const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a97b4d1 and be87b01.

📒 Files selected for processing (7)
  • packages/storage-evm/.openzeppelin/base.json (2 hunks)
  • packages/storage-evm/contracts/addresses.txt (1 hunks)
  • packages/storage-evm/scripts/README.md (1 hunks)
  • packages/storage-evm/scripts/base-mainnet-contracts-scripts/configure-ownership-token-contracts.ts (1 hunks)
  • packages/storage-evm/scripts/base-mainnet-contracts-scripts/set-proposals-contract-in-decayingtokenfactory.ts (1 hunks)
  • packages/storage-evm/scripts/ownership-token-voting-power-proxy.deploy.ts (1 hunks)
  • packages/storage-evm/scripts/test-upgraded-getspacetoken.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/storage-evm/contracts/addresses.txt
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/storage-evm/scripts/test-upgraded-getspacetoken.ts
  • packages/storage-evm/scripts/README.md
🧰 Additional context used
🪛 Biome (1.9.4)
packages/storage-evm/scripts/base-mainnet-contracts-scripts/set-proposals-contract-in-decayingtokenfactory.ts

[error] 50-50: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/storage-evm/scripts/base-mainnet-contracts-scripts/configure-ownership-token-contracts.ts

[error] 57-57: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: deploy-preview
  • GitHub Check: main
🔇 Additional comments (9)
packages/storage-evm/scripts/ownership-token-voting-power-proxy.deploy.ts (1)

1-11: LGTM - Standard deployment setup

The imports and contract factory setup follow standard patterns for OpenZeppelin UUPS proxy deployment.

packages/storage-evm/scripts/base-mainnet-contracts-scripts/configure-ownership-token-contracts.ts (3)

8-21: Well-structured TypeScript interfaces

The interface definitions provide good type safety for ethers.js interactions and clearly define the expected contract methods.


178-203: Excellent ownership verification implementation

The ownership checks for both contracts are comprehensive and provide clear error messages. This is a critical security measure that prevents unauthorized configuration.


205-237: Robust transaction handling with proper error management

The sequential transaction execution with confirmation waiting and comprehensive error handling is well implemented. The try-catch structure ensures proper error reporting.

packages/storage-evm/scripts/base-mainnet-contracts-scripts/set-proposals-contract-in-decayingtokenfactory.ts (4)

8-29: Good interface definitions for type safety

The TypeScript interfaces provide proper typing for the contract interactions and ethers.js objects.


104-112: Excellent validation of required contracts

The validation logic to check for all required contract addresses before proceeding is robust and provides clear error messaging.


135-145: Strong ownership verification security

The ownership check prevents unauthorized access and provides clear error messages about permission requirements.


152-189: Comprehensive transaction execution with verification

The implementation includes proper transaction handling, confirmation waiting, and a verification step to ensure the setting was successful. The address comparison and detailed logging provide excellent transparency.

packages/storage-evm/.openzeppelin/base.json (1)

106-111: New DecayingTokenFactory proxy entry looks correct
The proxy array now includes the address and transaction hash for the DecayingTokenFactory (0xf44ABfc7606cC97794A8E036823d1edd6d34786c), and the kind is set to uups as expected.

Comment on lines +48 to +53
for (const [key, pattern] of Object.entries(patterns)) {
const match = fileContent.match(pattern);
if (match && match[1]) {
addresses[key] = match[1];
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Apply optional chaining as suggested by static analysis

Same issue as in the previous file - static analysis correctly identifies the need for optional chaining.

Apply the suggested fix to use optional chaining:

  for (const [key, pattern] of Object.entries(patterns)) {
    const match = fileContent.match(pattern);
-   if (match && match[1]) {
+   if (match?.[1]) {
      addresses[key] = match[1];
    }
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for (const [key, pattern] of Object.entries(patterns)) {
const match = fileContent.match(pattern);
if (match && match[1]) {
addresses[key] = match[1];
}
}
for (const [key, pattern] of Object.entries(patterns)) {
const match = fileContent.match(pattern);
if (match?.[1]) {
addresses[key] = match[1];
}
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 50-50: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🤖 Prompt for AI Agents
In
packages/storage-evm/scripts/base-mainnet-contracts-scripts/set-proposals-contract-in-decayingtokenfactory.ts
around lines 48 to 53, the code accesses match[1] without confirming match is
defined, which can cause runtime errors. Update the condition to use optional
chaining by replacing match && match[1] with match?.[1] to safely access the
capture group only if match is not null or undefined.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant