Skip to content

feat: migrate to Tangle evm#3090

Merged
drewstone merged 153 commits intodevelopfrom
v2
Mar 3, 2026
Merged

feat: migrate to Tangle evm#3090
drewstone merged 153 commits intodevelopfrom
v2

Conversation

@drewstone
Copy link
Copy Markdown
Contributor

@drewstone drewstone commented Dec 23, 2025

No description provided.

drewstone and others added 30 commits December 10, 2025 01:32
- Add --disable-code-size-limit flag to Anvil for oversized contracts
- Add --private-key and --non-interactive flags to forge deploy
- Clear forge broadcast cache before deployment
- Verify deployment by checking deployer nonce and contract code
- Update GraphQL queries to use Envio/Hasura syntax (PascalCase entities,
  limit/offset, order_by, where with operators)
- Update indexing progress to use chain_metadata table
- Rename block-based queries to timestamp-based

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Update useOperatorBlueprints to accept EVM Address type instead of SubstrateAddress
- Fix SelectBlueprintsModal to use viem Address type
- Update operator page to use isAddress from viem for validation
- Convert deprecated tx hook stubs to return no-op functions instead of null
  to avoid TypeScript "never" type narrowing issues
- Add proper return type annotations to prevent type narrowing
- Fix DepositForm setValue type to match react-hook-form type

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Create stub implementations for service approve/reject/terminate/register
hooks until proper Tangle contract ABI integration is implemented.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add comments to empty reset functions to satisfy eslint no-empty-function rule.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Update OperatorSelectionStep to use GraphQL hooks (useOperatorMap, useRestakeAssets)
- Fix operator mapping to use EVM types (Address instead of SubstrateAddress)
- Update AssetConfigurationStep to use useRestakeAssets with proper typing
- Fix instance tables to use correct Blueprint type and property names
- Update confirmation modals for EVM Blueprint type compatibility
- Fix TotalValueLocked to use assetPositions instead of deposits
- Add useOperatorBatchRegisterTx stub hook for batch registration
- Change BigInt literals from 0n to BigInt(0) for ES2019 compatibility
- Fix property name mismatches (logo -> imgUrl, serviceCount -> instancesCount)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add wagmi connectors (injected, coinbaseWallet, safe, walletConnect)
- Enable EIP-6963 multi-injected provider discovery
- Add new wallets: Coinbase, Safe, Talisman, Trust Wallet, Keplr
- Create wallet icons for new wallets
- Improve connector matching logic with multiple fallback strategies
- Update local RPC endpoint to anvil port (8545)
- Fix VaultsHightlightCard React key warning
- Add debug logging for available connectors

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Update wallet connection system to use RainbowKit while preserving
existing UI components. This provides:
- Better wallet detection via EIP-6963
- Automatic support for MetaMask, Coinbase, WalletConnect, etc.
- Simplified provider setup with RainbowKitProvider

Changes:
- Update wagmi config to use RainbowKit's getDefaultConfig
- Add RainbowKitProvider to tangle-dapp and tangle-cloud providers
- Update ConnectWalletButton to use wagmi hooks (useAccount, useDisconnect)
- Update WalletDropdown to use wagmi for disconnect
- Remove unused ConnectWalletModal (replaced by RainbowKit modal)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Update WalletDropdown to match original UI design with wallet icons
- Add walletIcons helper to map wagmi connectors to wallet icons
- Update NetworkSelectorDropdown to use wagmi hooks (useChainId, useSwitchChain)
- Remove dependency on deprecated useWebContext for network switching
- Simplify TopNavigationPanel by removing unused props

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…in switcher

- Remove Tangle Mainnet/Testnet from wagmiChains (they use Substrate)
- Add Anvil Local, Base, and Base Sepolia as primary chains
- Create ChainSelectorButton using RainbowKit's useChainModal
- Replace custom NetworkSelectorDropdown with RainbowKit chain modal

This aligns with the pure EVM architecture using RainbowKit for
wallet and chain management.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Remove custom bridge components (BridgeContainer, BridgeConfirmationModal, etc.)
- Remove bridge contexts (BridgeHyperlaneContext, BridgeTxQueueContext)
- Remove bridge hooks (useHyperlaneQuote, useHyperlaneTransfer, etc.)
- Remove bridge utilities
- Add Li.Fi widget for cross-chain bridging
- Update dependencies: wagmi@2.19.5, viem@2.37.0, @tanstack/react-query@5.90.12
- Simplify providers by removing bridge-specific providers
- Remove BridgeTxQueueDropdown from Layout

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add NetworkGuard component to show wrong network message on Dashboard,
  Restake, and Liquid Staking pages when not on Base/Base Sepolia/Local
- Fix LiFi widget styling: apply Satoshi font family to all MUI variants,
  add component overrides, and force font via CSS
- Fix dropdown z-index (z-50) to appear above LiFi widget
- Fix ClaimRewardsDropdown button height to match adjacent buttons
- Fix NativeRestakeContainer to hide page title when showing wrong network
- Fix Switcher import in create-vault form

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Scripts were moved to scripts/local-env/ for shared use across apps.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Native Restaking:
- Add ValidatorPod and ValidatorPodManager ABIs
- Create native restaking UI components (CreatePodCard, DelegationCard, etc.)
- Add hooks for validator pod management
- Add wrong network alert for unsupported chains

Migration Claims:
- Add TangleMigration contract integration
- Create claim eligibility and proof generation hooks
- Add SubstrateKeyInput component for SS58 address entry
- Include merkle tree utilities and snapshot data
- Add deploy-migration.sh script for local testing

Data Layer Improvements:
- Add on-chain fallback for restake assets when indexer unavailable
- Add Envio health check utility
- Add LOCAL_MOCK_TOKENS config for local development
- Add unified restake assets hook with automatic fallback

EVM Support:
- Add Ethereum mainnet and Holesky testnet chains
- Add contract addresses for new chains

Liquid Staking:
- Add vault tables and user positions components
- Add liquid delegation hooks and data fetching

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add comprehensive README with deployment and proof generation guide
- Fix curve25519-dalek patch branch name (patch-curve25519-v4.1.3)
- Pin serde to <1.0.218 to avoid alloy-consensus compatibility issue
- Add HashableKey import for vkey.bytes32() method
- Fix test assertions to use PublicValues.pubkey field

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add claim-relayer service for gasless claims via gas sponsorship
- Add deployment scripts (deploy.sh, setup-local-test.sh)
- Add extractEvmClaims.ts for EVM snapshot processing
- Update generateMerkleTree.ts with improved structure
- Add SubstrateWalletSelector component for Polkadot.js integration
- Add gitignore entries for large generated files (migration-proofs.json)
- Add gitignore for Foundry and Rust build artifacts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Remove Substrate-specific staking components (ValidatorTable,
  NominationsTable, NominationValidatorTables)
- Remove Substrate balance hooks and contexts (BalancesContext,
  useTransferTx, usePendingEvmBalance, etc.)
- Remove legacy restaking containers (JoinOperatorsModal,
  SelectOperatorModal, WithdrawModal, etc.)
- Update types from BN/SubstrateAddress to bigint/Address (viem)
- Migrate data hooks to use GraphQL/Envio indexer instead of
  Substrate RxJS hooks
- Rename Evm-suffixed components to remove suffix:
  - UserRestakingOverviewEvm → UserRestakingOverview
  - ProtocolStatisticCardEvm → ProtocolStatisticCard
  - OperatorsTableEvm → OperatorsTable
- Update imports across tangle-dapp and tangle-cloud apps
- Remove unused Substrate utility functions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The activity generator was hardcoded to use chain ID 84532 (Base Sepolia)
while Anvil runs on 31337 (default). This caused the script to hang as
viem would reject transactions with mismatched chain IDs.

Now uses a configurable CHAIN_ID that defaults to 31337 to match the
Anvil configuration in start-local-env.sh and config.local.yaml.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Removed `forge clean` which was forcing full recompilation on every run.
Now only the broadcast cache is cleared (needed for deterministic contract
addresses), while compiled artifacts in `out/` are reused.

This significantly speeds up subsequent runs of the local environment.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
… and blueprint features

- Add operator management page with registration/unregister/slashing UI
- Add job submission form and job history table for service details
- Add rewards claiming page for operators
- Add developer earnings dashboard for blueprint owners
- Add blueprint creation wizard and management page
- Add advanced deployment options (approval model config)
- Create GraphQL hooks for jobs, rewards, operator management, slashing,
  blueprint management, and developer earnings

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add Anvil state caching to speed up local environment startup
- Add Hasura health check before db-setup to fix race condition
- Fix dynamic env var syntax for Envio RPC URL
- Add cache CLI commands (cache clear/save/status, reset)
- Fix lint errors in tangle-cloud and tangle-dapp (unused imports/vars)
- Update migration deployment scripts with improved logging
- Various code quality improvements

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Fix operators query enum type (String -> restakingoperatorstatus)
- Add useDelegatorCount hook for accurate restaker count
- Update ProtocolStatisticCard to use unique restaker count
- Improve claim page error display with user-friendly messages
- Fix UserRestakingOverview to show "0" instead of "--" for zero values
- Change suffix from "ETH" to "TNT" in restaking overview

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add chain check in useProtocolConfig to skip contract calls on chains
  where restaking contracts aren't deployed
- Return sensible default values for protocol config on non-restaking chains
- Fix icon import in migration claim page (AlertLine -> Alert)
- Add asset list display on dashboard with token icons
- Improve useDynamicSVGImport to always fall back to default icons
- Remove debug console.log statements from restake asset hooks

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Fix empty object type in useDelegatorCount to use Record<string, never>
- Prefix unused hasBalance variable with underscore in Actions.tsx
- Remove unused RestakeAsset import and chainId in TransferModal.tsx
- Move handleClose before handleTransfer to fix hook dependency
- Reorder imports in migration claim page to fix import/first rule

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Use useOptionalRestakeContext instead of useRestakeContext to prevent
errors during hot module reload when the context may temporarily be
unavailable. Shows a loading skeleton instead of throwing an error.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Replace skeleton loader with an animated spinner component matching
the Claim Migration page design. Features a gradient background,
spinning border animation, and descriptive text.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add token icons to RestakingAssetsTable with symbol lookup
- Add token icons to DepositForm asset selector and list modal
- Add token icons to DelegateForm asset selector and list modal
- Add token icons to UnstakeForm delegation selector and list modal
- Add token icons to WithdrawForm asset selector and list modal
- Use local token config to resolve symbol from token address

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Include native token (zero address) in potential tokens list
- Fetch native balance using wagmi useBalance hook
- Add native ETH to asset map with hardcoded metadata
- Handle case where only native token is enabled (no ERC20 tokens)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
vutuanlinh2k2 and others added 2 commits February 23, 2026 22:04
@drewstone drewstone marked this pull request as ready for review March 2, 2026 20:10
@drewstone drewstone requested a review from AtelyPham as a code owner March 2, 2026 20:10
@claude
Copy link
Copy Markdown

claude Bot commented Mar 2, 2026

Claude finished @drewstone's task —— View job


PR Review: Tangle EVM Migration

Conducting comprehensive review of this major migration PR (813k+ additions, 34k deletions across 725+ files).

Review Checklist

  • Analyze migration scope and architecture
  • Review security implications and address reported security alert
  • Examine EVM contract implementations
  • Check migration claim system
  • Assess code quality and best practices
  • Review performance considerations
  • Evaluate documentation updates
  • Provide overall assessment and recommendations

🔍 Overall Assessment: 6/10 - Good Design, Execution Concerns

This PR shows excellent architectural planning but has significant execution and scope management issues that prevent it from being merge-ready.


🚨 Critical Security Issues

1. Insecure Randomness (High Priority)

Location: scripts/local-env/activity-generator.mjs:670, 682

let random = Math.random() * totalWeight;         // Line 670
const accountIndex = 1 + Math.floor(Math.random() * (ANVIL_ACCOUNTS.length - 1)); // Line 682

Issue: Using Math.random() for weighted activity selection and account selection in a local development environment.

Risk: While this is only for local testing, using cryptographically insecure randomness is flagged by security scanners and sets a bad precedent.

Recommendation:

// Use crypto.randomBytes instead
import { randomBytes } from 'crypto';

const randomFloat = () => randomBytes(4).readUInt32LE(0) / 0x100000000;
let random = randomFloat() * totalWeight;
const accountIndex = 1 + Math.floor(randomFloat() * (ANVIL_ACCOUNTS.length - 1));

✅ Strong Architecture Highlights

1. Well-Designed Migration System

  • ZK-based Claims: Excellent use of SP1 for SR25519 signature verification
  • Merkle Tree Distribution: Proper implementation with OpenZeppelin standards
  • Documentation: Outstanding migration plan (MIGRATION_CLAIM_PLAN.md - 571 lines)

2. Clean Contract Structure

  • Separation of Concerns: Contracts properly separated by functionality
  • Auto-generated ABIs: Good practice sourcing from tnt-core
  • Type Safety: Strong TypeScript integration throughout

3. Resilient Infrastructure

  • Error Handling: useResilientReadContract shows good error handling patterns
  • Network Agnostic: Proper multi-chain support (Base, Arbitrum)

⚠️ Major Concerns

1. PR Size (Critical)

  • 725+ files changed - This is unmanageable for review
  • 813k additions - Includes large generated files (merkle proofs, ABIs)
  • Should be split: ABI updates → Provider removal → Migration UI → Generated artifacts

2. Missing Contract Addresses (High)

Location: libs/dapp-config/src/contracts.ts:54, 58, 64-96

masterBlueprintServiceManager: '0x0000000000000000000000000000000000000000', // Not deployed
credits: '0x0000000000000000000000000000000000000000', // Missing
// All mainnet addresses are zero addresses

Issues:

  • Base Sepolia missing critical addresses
  • All mainnet addresses unset
  • Will cause runtime failures

3. Incomplete Implementation (High)

Based on previous audit comments, many hooks are stubs blocking core user flows.


🏗️ Code Quality Assessment

Strengths

  • Consistent Architecture: Clean separation between apps/libs
  • Type Safety: Strong TypeScript usage throughout
  • Error Handling: Good patterns in useContractWrite and resilient reads
  • Documentation: Excellent inline documentation for complex logic

Issues

  • Generated Files in PR: Large merkle proof files should be excluded
  • No Test Coverage: As noted in previous comments, practically no tests
  • Code Comments: Following repo guidelines correctly (minimal comments)

🔐 Security Analysis

Migration Claim System (✅ Well-Designed)

// Proper validation in MigrationClaim.sol concept
require(provenPublicKey == substratePublicKey, "Public key mismatch");
require(provenEvmAddress == msg.sender, "EVM address mismatch");
require(provenChallenge == expectedChallenge, "Invalid challenge");

Security Features:

  • ✅ Double-claim prevention via mapping
  • ✅ Replay protection with challenge including contract + chain ID
  • ✅ Front-running protection (only msg.sender can claim)
  • ✅ Time-bound claims (1-year expiry)
  • ✅ ZK proofs provide 128-bit security

Contract Integration

  • ✅ Proper use of OpenZeppelin libraries
  • ✅ Immutable parameters where appropriate
  • ✅ Event emissions for transparency

🚀 Performance Considerations

Strengths

  • Viem Integration: Efficient blockchain interactions
  • React Query: Good caching patterns in useResilientReadContract
  • Batch Operations: optimizeTxBatch utility shows good batching

Concerns

  • Large Bundle Size: 813k additions will significantly increase bundle
  • Network Calls: Many new contract reads may impact loading

📚 Documentation Quality: Excellent

Outstanding Documentation

  • MIGRATION_CLAIM_PLAN.md: Comprehensive 571-line implementation plan
  • V2_MIGRATION_PARITY.md: Detailed feature parity tracking
  • TANGLE_CLOUD_CONTRACT_PARITY.md: Clear implementation status
  • Inline code documentation follows repo standards

🎯 Actionable Recommendations

Immediate (Before Merge)

  1. Fix Security Alert: Replace Math.random() with crypto.randomBytes
  2. Split PR: Break into 4-5 smaller PRs for reviewability
  3. Complete Contract Addresses: Deploy and update all missing addresses
  4. Fix CI: Address build/deployment failures
  5. Add Tests: At minimum, critical path unit tests

Short-term (Next Sprint)

  1. Complete Stub Implementations: Finish hooks blocking user flows
  2. Performance Audit: Bundle size and network call optimization
  3. Error Handling: Standardize error patterns across hooks
  4. Migration Testing: End-to-end claim flow verification

Long-term (Post-Migration)

  1. Remove Legacy Code: Clean up remaining Substrate references
  2. Documentation Updates: Update READMEs for v2 architecture
  3. Monitoring: Add metrics for migration claim success rates

📋 Merge Blockers

❌ Security alert unresolved
❌ PR too large for review (725+ files)
❌ Missing critical contract addresses  
❌ CI failures (build/deploy)
❌ No test coverage
❌ Incomplete implementations (per audit comments)

🏁 Conclusion

This represents excellent architectural work with a well-designed migration strategy. The ZK-based claim system is particularly impressive, and the documentation is outstanding.

However, the execution approach needs refinement. The PR is too large, has missing infrastructure, and lacks testing.

Recommendation: Do not merge in current state. Split into smaller PRs, complete missing pieces, and add tests before review.

The migration design is solid - the implementation just needs proper staging and completion.


@drewstone
Copy link
Copy Markdown
Contributor Author

Cross-repo dependency: tnt-core canonicalization and local-dev resilience PR is open at https://github.com/tangle-network/tnt-core/pull/96.\n\nRecommended merge order: merge tnt-core #96 first, then finalize this v2 dApp PR once CI is green.

@drewstone drewstone merged commit 54ca966 into develop Mar 3, 2026
20 checks passed
@drewstone drewstone deleted the v2 branch March 3, 2026 20:12
drewstone added a commit that referenced this pull request Mar 3, 2026
Co-authored-by: vutuanlinh2k2 <69841784+vutuanlinh2k2@users.noreply.github.com>
Co-authored-by: vutuanlinh2k2 <vutuanlinh2002@gmail.com>
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.

3 participants