datahaven/operator/pallets/datahaven-native-transfer
Ahmad Kaouk 41788d56bb
test: refactor e2e tests (#365)
This PR significantly refactors and improves the end-to-end testing
framework and infrastructure. The primary focus was on simplifying the
test suites, improving reliability through better resource management,
and hardening the relayer infrastructure.

All E2E tests are now passing on the CI and demonstrate consistent
reliability when run locally.

### Key Changes

#### 1. E2E Test Suite Refactor & Cleanup
* **Simplified Test Logic**: Heavily refactored the core test suites
(`native-token-transfer.test.ts`, `rewards-message.test.ts`, and
`validator-set-update.test.ts`). The new implementation is much cleaner,
utilizing shared helpers to reduce boilerplate.
* **Utility Consolidation**: Removed redundant utility files
(`storage.ts`, `rewards-helpers.ts`) and simplified `events.ts`. Event
waiting now uses `rxjs` for Substrate and native `viem` watchers for
Ethereum, which is more robust and easier to maintain.
* **Better Connector Management**: Unified the creation and cleanup of
test clients in `ConnectorFactory`. It now handles the lifecycle of
WebSocket connections more gracefully, including clearing the
`socketClientCache` to prevent reconnection noise during teardown.

#### 2. Infrastructure & Stability
* **Relayer Relaunch Policy**: Added a restart policy for Snowbridge
relayer containers. They are now configured with `--restart
on-failure:5`, ensuring that relayers automatically relaunch if they
crash during the sensitive initialization phase.
*   **WebSocket Integration**: 
* Updated the `ConnectorFactory` to prefer **WebSockets** for the
Ethereum public client, which is essential for efficient, event-heavy
E2E testing.
* Enhanced `launchKurtosisNetwork` to correctly identify and register
the Execution Layer's WebSocket endpoint from Kurtosis.
* **Disabled Contract Injection**: This PR temporarily disables the
automatic injection of contracts into the genesis state by default.
* *Reason*: I encountered issues generating a valid `state-diff.json`
for the latest contract versions. Even after applying several
workarounds, the injected state remained unstable. As a result, I've
reverted to manual contract deployment during the launch sequence for
better reliability for now.

#### 3. Documentation & Maintenance
* Removed obsolete documentation (`event-utilities-guide.md`) that no
longer reflects the simplified event-handling API.
* Cleaned up `test/launcher/validators.ts` and moved logic into more
appropriate helpers.

---------

Co-authored-by: Steve Degosserie <723552+stiiifff@users.noreply.github.com>
2025-12-24 13:31:40 +01:00
..
src test: refactor e2e tests (#365) 2025-12-24 13:31:40 +01:00
Cargo.toml chore: ♻️ Add missing license header in operator & AVS contracts source code (#285) 2025-11-10 12:56:41 +01:00
README.md feat: Native Token Transfer to Ethereum (#88) 2025-06-12 00:07:36 +02:00

DataHaven Native Transfer Pallet

A Substrate pallet that enables cross-chain transfers of DataHaven native tokens to and from Ethereum using the Snowbridge infrastructure.

Overview

This pallet facilitates the transfer of DataHaven (DH) native tokens to Ethereum, where they are represented as wrapped ERC20 tokens. It implements a lock-and-mint mechanism: tokens are locked on DataHaven when transferred to Ethereum, and unlocked when transferred back.

Features

  • Cross-chain Transfers: Transfer DH tokens to Ethereum addresses
  • Token Locking: Secure token locking in a sovereign account during transfers
  • Fee Management: Mandatory fee collection for bridge relayers
  • Pause Mechanism: Emergency pause functionality for security

Fee Structure

Fees are mandatory for all transfers and serve to:

  1. Compensate relayers for Ethereum gas costs
  2. Provide incentive for timely message delivery
  3. Prevent spam transactions

The fee is:

  • Collected in DataHaven native tokens
  • Transferred to a designated fee recipient account
  • Separate from the transfer amount

Fee Calculation Guidelines

When calculating fees, consider:

  1. Ethereum Gas Costs: Estimate gas required for the Ethereum transaction
  2. Gas Price: Current Ethereum gas prices (use oracles or fixed estimates)
  3. Exchange Rate: DH to ETH conversion rate
  4. Relayer Margin: Additional incentive

Example calculation:

Ethereum gas required: 100,000 gas
Gas price: 30 gwei
ETH cost: 0.003 ETH
DH/ETH rate: 1000 DH per ETH
Base fee: 3 DH
With 20% margin: 3.6 DH

Extrinsics

transfer_to_ethereum

Transfer DataHaven native tokens to an Ethereum address.

Parameters:

  • origin: The account initiating the transfer
  • recipient: The Ethereum address (H160) to receive the tokens
  • amount: The amount of tokens to transfer
  • fee: The fee to cover Ethereum gas costs and incentivize relayers (must be non-zero)

pause

Pause all transfers. Only callable by PauseOrigin (typically governance).

unpause

Resume transfers after pause. Only callable by PauseOrigin.

Public Functions

total_locked_balance

Get the total balance of tokens locked in the Ethereum sovereign account.

ethereum_sovereign_account

Get the account ID of the Ethereum sovereign account for monitoring purposes.

Events

  • TokensLocked: Emitted when tokens are locked for transfer
  • TokensUnlocked: Emitted when tokens are unlocked from Ethereum
  • TokensTransferredToEthereum: Emitted on successful transfer to Ethereum
  • Paused: Emitted when the pallet is paused
  • Unpaused: Emitted when the pallet is unpaused

Errors

  • InsufficientBalance: Account has insufficient balance for transfer
  • Overflow: Arithmetic overflow in calculations
  • SendMessageFailed: Failed to send message through Snowbridge
  • InvalidEthereumAddress: Provided Ethereum address is zero
  • InvalidAmount: Transfer amount is zero
  • TransfersDisabled: Transfers are paused
  • ZeroFee: Fee cannot be zero

Security Considerations

  1. Pause Mechanism: The pallet can be paused by governance in case of emergencies
  2. Fee Validation: All transfers require non-zero fees to prevent spam
  3. Balance Preservation: The pallet uses Preservation::Preserve to maintain existential deposits
  4. Address Validation: Zero Ethereum addresses are rejected