operator/precompiles/datahaven-native-transfer/README.md
This precompile exposes the pallet-datahaven-native-transfer functionality to the EVM layer, allowing smart contracts to transfer DataHaven native tokens to Ethereum via Snowbridge.
The DataHaven Native Transfer precompile provides an EVM-compatible interface for:
Precompile Address: 0x0000000000000000000000000000000000000819 (2073 decimal)
transferToEthereum(address recipient, uint256 amount, uint256 fee)Transfers DataHaven native tokens to an Ethereum address via Snowbridge.
Parameters:
recipient: Ethereum address to receive the tokensamount: Amount of tokens to transfer (in smallest unit)fee: Fee to incentivize relayers (in smallest unit)Requirements:
recipient cannot be the zero addressamount and fee must be greater than zeroExample (Solidity):
import "./DataHavenNativeTransfer.sol";
contract MyContract {
function sendToEthereum(address ethRecipient, uint256 amount) external {
DATAHAVEN_NATIVE_TRANSFER_CONTRACT.transferToEthereum(
ethRecipient,
amount,
100000000000000000 // 0.1 token fee
);
}
}
isPaused() view returns (bool)Checks if the pallet is currently paused.
Returns:
true if paused (transfers disabled)false if operational (transfers enabled)Example (Solidity):
bool paused = DATAHAVEN_NATIVE_TRANSFER_CONTRACT.isPaused();
if (paused) {
revert("Transfers are currently disabled");
}
totalLockedBalance() view returns (uint256)Returns the total amount of tokens currently locked in the Ethereum sovereign account.
Returns:
Example (Solidity):
uint256 locked = DATAHAVEN_NATIVE_TRANSFER_CONTRACT.totalLockedBalance();
ethereumSovereignAccount() view returns (address)Returns the address of the Ethereum sovereign account that holds locked tokens.
Returns:
Example (Solidity):
address sovereign = DATAHAVEN_NATIVE_TRANSFER_CONTRACT.ethereumSovereignAccount();
TokensLocked(address indexed account, uint256 amount)Emitted when tokens are locked for transfer to Ethereum.
TokensUnlocked(address indexed account, uint256 amount)Emitted when tokens are unlocked from Ethereum (handled by pallet, not directly through precompile).
TokensTransferredToEthereum(address indexed from, address indexed to, uint256 amount)Emitted when a transfer to Ethereum is initiated.
Paused()Emitted when the pallet is paused.
Unpaused()Emitted when the pallet is unpaused.
The precompile provides detailed error messages for common failure cases:
Approximate gas costs for each operation:
| Operation | Estimated Gas | Notes |
|---|---|---|
transferToEthereum | ~100,000-150,000 | Includes dispatch + storage writes |
pause | ~30,000-50,000 | Simple dispatch |
unpause | ~30,000-50,000 | Simple dispatch |
isPaused (view) | ~2,000-5,000 | Single storage read |
totalLockedBalance (view) | ~2,000-5,000 | Single storage read |
ethereumSovereignAccount (view) | ~1,000-3,000 | Config read |
Note: Actual gas costs may vary depending on runtime configuration and network conditions.
Complete example of integrating the precompile into a smart contract:
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.0;
import "./DataHavenNativeTransfer.sol";
contract CrossChainBridge {
event TransferInitiated(address indexed from, address indexed to, uint256 amount);
function bridgeToEthereum(
address ethRecipient,
uint256 amount,
uint256 fee
) external {
require(!DATAHAVEN_NATIVE_TRANSFER_CONTRACT.isPaused(), "Transfers paused");
require(ethRecipient != address(0), "Invalid recipient");
require(amount > 0, "Invalid amount");
DATAHAVEN_NATIVE_TRANSFER_CONTRACT.transferToEthereum(
ethRecipient,
amount,
fee
);
emit TransferInitiated(msg.sender, ethRecipient, amount);
}
function getLockedBalance() external view returns (uint256) {
return DATAHAVEN_NATIVE_TRANSFER_CONTRACT.totalLockedBalance();
}
}
The precompile includes a comprehensive test suite covering:
Run tests with:
cd operator/precompiles/datahaven-native-transfer
cargo test
Existential Deposit: Transfers respect the chain's existential deposit requirement. Ensure callers retain sufficient balance to keep their account alive.
Fee Payment: The fee is paid to the configured fee recipient separately from the amount being bridged. Ensure you have sufficient balance for both.
Token Registration: The native token must be registered on Ethereum before transfers can occur. Check this before initiating transfers.
Pause Mechanism: Only governance can pause the pallet. This is a safety mechanism for emergency situations.
Snowbridge Dependency: Transfers depend on the Snowbridge infrastructure. Monitor Snowbridge health before large transfers.
No Reentrancy: The precompile uses Frontier's reentrancy protection (forbid-evm-reentrancy feature).
┌─────────────────┐
│ EVM Contract │
└────────┬────────┘
│ calls precompile at 0x...07F5
↓
┌─────────────────────────────┐
│ DataHavenNativeTransfer │
│ Precompile │
│ ┌──────────────────────┐ │
│ │ Address Mapping │ │
│ │ Type Conversions │ │
│ │ Gas Accounting │ │
│ │ Error Handling │ │
│ └──────────┬───────────┘ │
└─────────────┼───────────────┘
│ dispatches call
↓
┌─────────────────────────────┐
│ pallet-datahaven-native- │
│ transfer │
│ ┌──────────────────────┐ │
│ │ Lock tokens │ │
│ │ Build message │ │
│ │ Send via Snowbridge │ │
│ └──────────┬───────────┘ │
└─────────────┼───────────────┘
│
↓
[ Snowbridge ]
│
↓
[ Ethereum ]
This precompile is part of DataHaven and is licensed under GPL-3.0.
For issues or questions: