# Protocol Updates
Source: https://docs.train.tech/changelog/overview
Protocol updates and improvements
* Introduced [Wallet HTLC](/protocol/atomic-swaps-secret_gen), secret generation from the wallet mechanism.
* Added [HKDF specification](/protocol-spec/HKDF) describing HKDF usage in TRAIN.
* Updated the [Auction Mechanism](/protocol-spec/auction) to enable solver competition and ensure users receive the best possible swap price.
* Added research about [cross-chain trading dynamics](/research/cross-chain-trading) with TRAIN protocol.
* Released TRAIN to mainnet. Live [here](https://app.train.tech).
* Mainnet contracts are available [here](/protocol/contracts).
* Added [Bridge Deployment API](/bridge-deployment-api/deploy-quickstart) documentation.
* Updated the [Edge Cases](/protocol-spec/edge-cases) specification with more detailed explanations.
* Rebranded to TRAIN from Layerswap V8. All repositories have been migrated to the new [TrainProtocol](https://github.com/trainProtocol) organization.
* Removed the Atomic Pool concept.
* Introduced the new [Reward & Slash mechanism](/protocol/slashing) embedded in Atomic Swaps themselves, eliminating the need for Atomic Pools.
* Added introduction to the [Auction system](/protocol/auction) and the [technical details](/protocol-spec/auction).
* Released TRAIN [Bridge dApp](https://app.train.tech) to use [Signature flow](/protocol-spec/core) instead of requiring two transactions; users now complete one transaction and one signature.
* Updated [dApp Implementation](/protocol-spec/implementation-dApp) and [dApp](/protocol/dApp) pages to include details for verifying the state of destination chains via Light Clients and/or multiple providers.
* Replaced 'LP' terminology with 'Solver' to avoid confusion with passive liquidity providing and to better explain the concept.
* Prepared branch for EVM security audit
* EVM Gas Optimization
| Function | Optimization | Gas (new) | Gas (old) |
| -------------- | ------------ | --------- | --------- |
| `commit()` | 52.7% | 146,300 | 309,608 |
| `addLock()` | 56.6% | 34,250 | 78,961 |
| `addLockSig()` | 48.9% | 42,103 | 82,447 |
| `refund()` | 35.5% | 39,460 | 61,262 |
| `redeem()` | 45.5% | 45,835 | 84,110 |
* Released the first version of the TRAIN protocol. Live [here](https://app.train.tech) on EVM, Fuel, Starknet, Solana, and TON testnets.
* Released the first version of the [Bridge Deployment API](/api-reference).
* Released the documentation page.
# HKDF
Source: https://docs.train.tech/protocol-spec/HKDF
Describes HMAC-based Key Derivation Function(HKDF) usage in TRAIN
Train uses HKDF (HMAC-based Key Derivation Function) to generate deterministic and secure secrets for atomic swaps.
HKDF is a standardized key-derivation algorithm, which lets us turn one signature into any number of unique, swap-specific secrets.
If you are not familiar with HKDF you can consider it as just hashing.
The users signs the message `I am using Train`.
`initial_key = HKDF-Extract(signature)`
This key is cached locally by the dApp, as long as the cache persists, more signatures are not needed.
`secret = HKDF-Expand(initial_key, salt = (source_chain, destination_chain, timelock))`
For each swap, dapp derives a new secret using initial\_key, and the salt.
### Advanatges of HKDF derived secrets.
* **Deterministic**: The dApp can always recompute the secret as salt is not random, but is based on public data from the blockchain.
* **Unique**: Even if two swaps involve the same user, they will have different secrets because the salts differ.
* **No user Friction**: The user signs only once, and the dapp produces unlimited secrets from that one signature.
* **Recoverable**: If the cached initial\_key is lost, the user can simply sign the same message again and regenerate the identical initial key.
# Core
Source: https://docs.train.tech/protocol-spec/core
Start deploying a trustless bridge on any rollup/chain in under 5 minutes
The core of the protocol relies on the HTLC contract. This contract is responsible for locking and unlocking funds based on specific conditions.
### Core Functions
User creates an HTLC on the source chain with a hashlock derived from the recoverable secret generation mechanism. This locks the user's funds for the specified Solver.
Solver reveals the secret on the destination chain to claim the user's funds. Alternatively, user reveals the secret on destination to claim their funds if needed.
Solver reveals the secret (transmitted by the user via off-chain channels) on both source and destination chains to claim their reward and unlock the user's funds.
Allows the original sender to reclaim their locked funds after the timelock expires if the exchange wasn't completed.
Implementation of the HTLC core contracts can be found at the [TRAIN repo](https://github.com/trainprotocol/contracts/tree/dev) for any VM blockchain, such as [EVM](https://github.com/trainprotocol/contracts/tree/dev/chains/evm), [TON](https://github.com/trainprotocol/contracts/tree/dev/chains/ton), [Solana](https://github.com/trainprotocol/contracts/tree/dev/chains/solana), [Sui](https://github.com/trainprotocol/contracts/tree/dev/chains/sui), [Fuel](https://github.com/trainprotocol/contracts/tree/dev/chains/fuel), [Aztec](https://github.com/trainprotocol/contracts/tree/dev/chains/aztec), and more.
```solidity theme={null}
contract TRAINERC20 {
/// @dev Emitted when an HTLC is created and ERC20 tokens are committed.
/// @param Id The unique identifier of the HTLC.
/// @param hopChains The sequence of chains forming the path from the source to the destination chain.
/// @param hopAssets The sequence of assets being swapped along the path.
/// @param hopAddresses The sequence of addresses involved along the path.
/// @param dstChain The destination blockchain.
/// @param dstAddress The recipient address on the destination chain.
/// @param dstAsset The asset on the destination chain.
/// @param sender The creator of the HTLC.
/// @param srcReceiver The recipient of the funds if conditions are met.
/// @param srcAsset The asset being locked.
/// @param amount The amount of ERC20 tokens locked in the HTLC.
/// @param timelock The timestamp after which the funds can be refunded.
/// @param tokenContract The address of the ERC20 token contract.
event TokenCommitted(
bytes32 indexed Id,
string[] hopChains,
string[] hopAssets,
string[] hopAddresses,
string dstChain,
string dstAddress,
string dstAsset,
address indexed sender,
address indexed srcReceiver,
string srcAsset,
uint256 amount,
uint48 timelock,
address tokenContract
);
/// @dev Emitted when an HTLC is locked with a hashlock and timelock.
/// @param reward The reward amount (in ERC20 token) associated with the HTLC.
/// @param rewardTimelock The timelock (timestamp) after which the reward can be claimed.
event TokenLocked(
bytes32 indexed Id,
bytes32 hashlock,
string dstChain,
string dstAddress,
string dstAsset,
address indexed sender,
address indexed srcReceiver,
string srcAsset,
uint256 amount,
uint256 reward,
uint48 rewardTimelock,
uint48 timelock,
address tokenContract
);
/// @dev Emitted when a hashlock and timelock are added to an existing HTLC.
event TokenLockAdded(bytes32 indexed Id, bytes32 hashlock, uint48 timelock);
/// @dev Emitted when funds are redeemed from an HTLC using the correct secret.
event TokenRedeemed(
bytes32 indexed Id,
address redeemAddress,
uint256 secret,
bytes32 hashlock
);
/// @dev Emitted when funds are redeemed from an HTLC using the correct secret.
event TokenRefunded(bytes32 indexed Id);
/// @notice Creates and commits a new hashed time-locked contract (HTLC) for ERC20 tokens.
/// @dev Transfers the specified amount of ERC20 tokens to the contract and emits a `TokenCommitted` event.
/// @param hopChains The sequence of chains forming the path from the source to the destination chain.
/// @param hopAssets The sequence of assets being swapped along the path.
/// @param hopAddresses The sequence of addresses involved along the path.
/// @param dstChain The destination blockchain.
/// @param dstAsset The asset on the destination chain.
/// @param dstAddress The recipient address on the destination chain.
/// @param srcAsset The asset being locked.
/// @param srcReceiver The recipient of the funds if conditions are met.
/// @param timelock The timestamp after which the funds can be refunded.
/// @param amount The amount of ERC20 tokens to lock in the HTLC.
/// @param tokenContract The address of the ERC20 token contract.
/// @return Id The unique identifier of the created HTLC.
function commit(
string[] calldata hopChains,
string[] calldata hopAssets,
string[] calldata hopAddresses,
string calldata dstChain,
string calldata dstAsset,
string calldata dstAddress,
string calldata srcAsset,
address srcReceiver,
uint48 timelock,
uint256 amount,
address tokenContract
) external _validTimelock(timelock) nonReentrant returns (bytes32 Id) { ... }
/// @notice Adds a hashlock and updates the timelock for an existing HTLC.
/// @dev Can only be called by the HTLC's creator if the HTLC exists and has not been claimed. Emits a `TokenLockAdded` event.
/// @param Id The unique identifier of the HTLC to update.
/// @param hashlock The hashlock to be added.
/// @param timelock The new timelock to be set.
/// @return bytes32 The updated HTLC identifier.
function addLock(
bytes32 Id,
bytes32 hashlock,
uint48 timelock
) external _exists(Id) _validTimelock(timelock) nonReentrant returns (bytes32) { ... }
/// @notice Adds a hashlock and updates the timelock for an existing HTLC using a signed message.
/// @dev Verifies the provided signature and updates the HTLC if valid. Emits a `TokenLockAdded` event.
/// @param message The details of the lock to be added, including the HTLC ID, hashlock, and timelock.
/// @param r The `r` value of the ECDSA signature.
/// @param s The `s` value of the ECDSA signature.
/// @param v The `v` value of the ECDSA signature.
/// @return bytes32 The updated HTLC identifier.
function addLockSig(
addLockMsg calldata message,
uint8 v,
bytes32 r,
bytes32 s
) external _exists(message.Id) _validTimelock(message.timelock) nonReentrant returns (bytes32) { ... }
/// @notice Locks ERC20 tokens in a new hashed time-locked contract (HTLC).
/// @dev Transfers the specified amount of ERC20 tokens to the contract and emits a `TokenLocked` event.
/// @param Id The unique identifier of the HTLC.
/// @param hashlock The hash of the secret required for redemption.
/// @param reward The reward amount in ERC20 token granted to the caller of redeem.
/// @param rewardTimelock The timelock (timestamp) after which the reward can be claimed.
/// @param timelock The timestamp after which the funds can be refunded if not claimed.
/// @param srcReceiver The recipient of the funds if the HTLC is successfully redeemed.
/// @param srcAsset The asset being locked.
/// @param dstChain The destination blockchain for the swap.
/// @param dstAddress The recipient address on the destination chain.
/// @param dstAsset The asset on the destination chain.
/// @param amount The amount of ERC20 tokens to lock in the HTLC.
/// @param tokenContract The address of the ERC20 token contract.
/// @return bytes32 The unique identifier of the created HTLC.
function lock(
bytes32 Id,
bytes32 hashlock,
uint256 reward,
uint48 rewardTimelock,
uint48 timelock,
address srcReceiver,
string calldata srcAsset,
string calldata dstChain,
string calldata dstAddress,
string calldata dstAsset,
uint256 amount,
address tokenContract
) external _validTimelock(timelock) nonReentrant returns (bytes32) { ... }
/// @notice Redeems funds from an HTLC using the correct secret.
/// @dev Verifies the provided secret against the hashlock and transfers the funds to the recipient. Emits a `TokenRedeemed` event.
/// @param Id The unique identifier of the HTLC to be redeemed.
/// @param secret The secret value used to unlock the HTLC.
/// @return bool Returns `true` if the redemption is successful.
function redeem(bytes32 Id, uint256 secret) external _exists(Id) nonReentrant returns (bool) { ... }
/// @notice Refunds the locked funds from an HTLC after the timelock expires.
/// @dev Can only be called if the HTLC exists and the timelock has passed. Emits a `TokenRefunded` event.
/// @param Id The unique identifier of the HTLC to be refunded.
/// @return bool Returns `true` if the refund is successful.
function refund(bytes32 Id) external _exists(Id) nonReentrant returns (bool) { ...}
}
```
# Edge Cases
Source: https://docs.train.tech/protocol-spec/edge-cases
Describes potential failure scenarios and how the protocol handles them to ensure fund safety and transaction integrity
### Solver Fails to Act on the User's Lock
In a rare scenario where the selected Solver fails to act on the User's lock, the User only needs to wait for the timelock period (usually \~15 minutes) to receive their funds back.
```mermaid theme={null}
sequenceDiagram
participant User
participant SC as Source Chain
participant Solver
participant DC as Destination Chain
User->>SC: lock() with hashlock
SC-->>Solver: TokenLocked
Note over User,SC: Timelock passes
User->>SC: refund()
SC-->>User: TokenRefunded
```
### User Fails to Transmit Secret to Solver
If the User does not transmit the derived secret to the Solver in time, both parties can refund their funds after the timelock period expires.
```mermaid theme={null}
sequenceDiagram
participant User
participant SC as Source Chain
participant Solver
participant DC as Destination Chain
User->>SC: lock() with hashlock
SC-->>Solver: TokenLocked
Solver->>DC: lock() with same hashlock
DC-->>User: TokenLocked
Note over User,SC: Timelock passes
User->>SC: refund()
SC-->>User: TokenRefunded
Note over Solver,DC: Timelock passes
Solver->>DC: refund()
DC-->>Solver: TokenRefunded
```
### Solver Fails to Release the User's Funds
In scenarios where the Solver releases their own funds but fails to release the User's funds, the protocol provides two mechanisms:
1. **Manual Redemption**: The User already possesses the secret (they transmitted it to the Solver). If the Solver fails to redeem on the destination chain, the User can directly use the secret to manually redeem their own funds on the destination chain, bypassing the Solver's failure.
2. **Reward Mechanism**: Other actors can redeem on behalf of the user and earn a reward for completing the swap. The original Solver loses their reward by failing to act in time.
```mermaid theme={null}
sequenceDiagram
participant User
participant SC as Source Chain
participant Solver
participant DC as Destination Chain
User->>SC: lock() with hashlock
SC-->>Solver: TokenLocked
Solver->>DC: lock() with same hashlock
DC-->>User: TokenLocked
User->>Solver: sign(secret)
Solver->>SC: redeem(secret)
SC-->>Solver: TokenRedeemed
User->>DC: redeem(secret)
DC-->>User: TokenRedeemed
```
### Solver Fails to Release Any Funds
If the Solver fails to release any funds, both the User and Solver can wait for the timelock period to expire and then refund their funds.
```mermaid theme={null}
sequenceDiagram
participant User
participant SC as Source Chain
participant Solver
participant DC as Destination Chain
User->>SC: lock() with hashlock
SC-->>Solver: TokenLocked
Solver->>DC: lock() with same hashlock
DC-->>User: TokenLocked
User->>Solver: sign(secret)
Note over Solver,DC: Timelock passes
Solver->>DC: refund()
DC-->>Solver: TokenRefunded
Note over User,SC: Timelock passes
User->>SC: refund()
SC-->>User: TokenRefunded
```
# dApp Implementation
Source: https://docs.train.tech/protocol-spec/implementation-dApp
Describes the protocol implementation for the User/dApp
Using the [recoverable secret generation mechanism](/protocol/atomic-swaps-secret_gen), derive a secret from the user's wallet signature, source chain, destination chain, and timelock parameters. Hash the secret to create the hashlock.
Call the `lock()` function to lock funds with the derived hashlock and a timelock of [$T + \Delta$](/protocol-spec/model/#standard-flow).
* Watch for the `TokenLocked` event or use the `Id` on the destination chain by calling `getDetails()`.
* Verify that the `hashlock` of the `HTLC` on the destination chain matches your derived hashlock and provides sufficient time, ensuring it is at least [$T + 2\Delta$](/protocol-spec/model/#standard-flow).
The state of the destination chain should be read from a Light Client if one exists; if not, it should be read from multiple RPC providers.
Sign a message containing the derived secret and transmit this signed message to the Solver or any available actor. This allows them to use the secret to unlock funds on both chains without requiring further user interaction.
This signature transmission can happen via off-chain channels (WebSocket, API, etc.). The signature includes the actual secret, which the Solver can now use.
The Solver reveals the secret on the destination chain to unlock the user's funds and on the source chain to claim their own funds. Both the user and Solver can now complete their side of the transaction.
[Edge Case: Solver Fails to Act on the User’s Commitment/Intent](/protocol-spec/edge-cases#solver-fails-to-act-on-the-users-commitment-intent)
* Wait for the `timelock` to expire.
* Call `refund()` on the source chain to reclaim your funds.
[Edge Case: Solver Fails to Release Any Funds](/protocol-spec/edge-cases#solver-fails-to-release-any-funds)
* Wait for the `timelock` to expire.
* Call `refund()` on the source chain to reclaim your funds.
[Edge Case: Solver Fails to Release the User’s Funds](/protocol-spec/edge-cases#solver-fails-to-release-the-users-funds)
* If funds are not released on the destination chain, watch the source chain for the `TokenRedeemed` event (or `getDetails()` function).
* Once detected, capture the `secret` and call `redeem()` on the destination chain.
# Solver Implementation
Source: https://docs.train.tech/protocol-spec/implementation-solver
Describes the protocol implementation for the Solcer
Subscribe to `TokenLocked` events to detect any locks made to your address with a hashlock.
* When a lock is detected, call `lock()` on the destination chain and pass the same `hashlock` with `timelock` of [$T + 2\Delta$](/protocol-spec/model/#standard-flow).
* Monitor the source chain for the `TokenLocked` event details (or use the `getDetails()` function) on the detected lock.
* Verify that the `hashlock` matches what the user used.
* Verify that the `timelock` provides sufficient time to act, ensuring it is at least [$T + \Delta$](/protocol-spec/model/#standard-flow).
* Verify that the `Id` is consistent and valid.
The user will sign and transmit the derived secret to you via off-chain channels. Verify that when hashed, this secret matches the hashlock on both chains.
* Once you receive the secret, call `redeem()` on the destination chain to unlock the user's funds. You are incentivized to do this quickly because a reward is reserved for whoever completes this transaction. If you delay, another actor can call redeem and claim the reward instead.
* Call `redeem()` on the source chain to claim your primary fee/reward.
* Pass in the secret value received from the user.
[Edge Case: User Fails to Act on the Solver’s Lock](/protocol-spec/edge-cases#user-fails-to-act-on-the-solvers-lock)
* If the commitment is not locked, wait for the `timelock` to expire.
* Call `refund()` on the destination chain to reclaim your funds.
# Model
Source: https://docs.train.tech/protocol-spec/model
Outlines the main protocol model for performing atomic swaps between parties
The protocol model relies on atomic swaps with recoverable secret generation for parties exchanging assets across different chains. The model outlines the core flow of assets and actions that should be taken by each party for a successful asset exchange. The protocol uses the [Standard flow](#standard-flow) for asset exchange between parties.
### Standard flow
When a party (Solver) directly supports both the source and destination chains and is willing to perform the swap, the standard flow applies. The user derives a secret using the [recoverable secret generation mechanism](/protocol/atomic-swaps-secret_gen) and locks funds on the source chain with the hashlock of that secret, setting the timelock to $T + \Delta$, where $T$ is the current timestamp and $\Delta$ is a reasonable duration (e.g., 15 minutes). The Solver observes this lock and creates a matching lock on the destination chain with the same hashlock and timelock of $T + 2\Delta$. The user then signs and transmits the derived secret to the Solver. The Solver reveals the secret on both chains to complete the swap.
Here are the steps:
The user derives a secret using [HKDF](/protocol-spec/HKDF) and creates a lock object on the source chain with the hashlock and a timelock of $T + \Delta$.
The Solver observes the lock on the source chain and creates a matching lock object on the destination chain with the same hashlock and a timelock of $T + 2\Delta$.
The user signs and transmits the derived secret to the Solver via off-chain channels.
The Solver reveals the secret on the destination chain to unlock the user's funds (earning a reward for this action), then reveals it on the source chain to claim their primary fee. The Solver is economically incentivized to complete the destination redemption promptly—if they delay, any other actor can step in and claim the reward instead.
```mermaid theme={null}
sequenceDiagram
participant User
participant SC as Source Chain
participant Solver
participant DC as Destination Chain
User->>SC: lock() with hashlock
SC-->>Solver: TokenLocked
Solver->>DC: lock() with same hashlock
DC-->>User: TokenLocked
User->>Solver: sign(secret)
Solver->>DC: redeem(secret)
DC-->>User: TokenRedeemed
Solver->>SC: redeem(secret)
SC-->>Solver: TokenRedeemed
```
# Reward-Slash
Source: https://docs.train.tech/protocol-spec/reward-slashing
Explains how the system penalizes Solver misbehavior and rewards others for acting to release user funds.
While users can always manually claim their funds, this protocol aims to prevent delays and inconvenience through economic incentives.
Solvers can exhibit unpredictable behavior that leads to various edge cases, such as refusing to release user funds. While users always retain the ability to manually claim their funds, preventing any permanent loss, this situation creates significant inconvenience.
## Core Mechanism
The **Reward-Slashing Mechanism** incentivizes proper Solver behavior. The process begins when a Solver locks funds for a user. At this point, they must also lock an additional reward amount secured by a timelock. This reward serves as an incentive - if the Solver successfully transfers the user's assets before the timelock expires, they receive their reward back. However, if they fail to act within the specified timeframe, the reward transfers to whoever executes the function to release the user's assets.
## Implementation Details
When a Solver locks funds for a user, the **lock** function requires additional **reward amount** along with a **rewardTimelock** parameter. This timelock must be set to a future timestamp and cannot exceed the timelock duration of the associated HTLC. The system records these reward details both through event emission in the **TokenLocked** event and storage in a rewards mapping, which links to the unique ID of the corresponding HTLC. Users can access reward information for any HTLC by calling the **getReward** function with the appropriate ID.
The `rewardTimelock` must always be set to a future timestamp and cannot exceed the HTLC timelock duration.
## Redemption Process
The redeem function handles rewards differently based on timing and who initiates the redemption. The logic is illustrated below using pseudocode:
```solidity theme={null}
if (!rewardTimelock.expired) {
transfer(reward, solver);
transfer(funds, user);
} else {
if (msg.sender == user) {
transfer(reward + funds, user);
} else {
transfer(funds, user);
transfer(reward, msg.sender);
}
}
```
## Security Considerations
The `rewardTimelock` serves as a crucial protection against MEV attacks. It provides Solvers adequate time to assess whether they can execute the **redeem** function within the specified timeframe. Even if Solvers miss their initial window, they can still call the function later to retrieve their reward, provided no one else has already executed it.
# Original HTLC
Source: https://docs.train.tech/protocol/atomic-swaps-overview
Introduction to original Atomic Swaps and their challenges
Atomic Swaps (HTLC - Hashed Time Lock Contract) enable peer-to-peer asset exchange without requiring one Network to know the state of the other. The User generates a secret and locks funds on the Source Network. Then, the Solver locks funds on the Destination Network. They exchange the secret to unlock their respective funds, with a time limit ensuring fund retrieval if the exchange fails.
### The Standard HTLC Flow
The User generates a *Secret* S and computes *Hashlock* HASH(S). Then, they create an HTLC, locking funds for the selected Solver in the Source Network.
The Solver detects this HTLC and creates a counterparty HTLC with the same Hashlock. This locks funds for the User (initial amount minus the *Solver Fee*) in the Destination Network.
The User detects the HTLC in the Destination Network and reveals S to claim the funds.
The Solver detects the revealed S and reveals it in the Source Network to claim their funds.
### Challenges with HTLCs
Despite their potential, HTLCs have proven impractical for real-world bridging due to three main issues:
* **Secret Management**: Users must generate and securely manage a Secret until the counterparty completes their transaction.
* **Liveness**: Users must maintain the state of the bridging process locally and actively monitor and respond to counterparty transactions.
These challenges significantly impact the User experience and create barriers to adoption. The requirement for Users to manage the Secret creates a dependency issue. If the User closes the browser, clears the cache, or loses access to the Secret, the transaction flow cannot be recovered from the chain data.
# Wallet HTLC
Source: https://docs.train.tech/protocol/atomic-swaps-secret_gen
TRAIN Protocol atomic swaps with recoverable secret generation from the wallet
The **Wallet HTLC** approach is TRAIN's solution for practical atomic swaps with recoverable secret generation. Instead of requiring users to manually manage secrets or complete multiple transactions per swap, secrets are derived from the user's wallet signature. This enables **N+1 interactions for N swaps** — after an initial sign-in, users can perform unlimited swaps without additional signing steps.
## The Challenge
Traditional HTLC implementations face a key tradeoff: **User-generated secrets**. Private key/secret management burden on users; if the browser clears cache or the user loses access, the transaction cannot be recovered
Wallet HTLC solves this by making secret derivation **reproducible and recoverable from on-chain data**, while delegating the management entirely to the dApp.
### Sign In
The users signs the message `I am using Train`.
The dapp calls a [HKDF](/protocol-spec/HKDF) to derive an initial key from the signature, and keeps the key in the cache.
### Wallet HTLC Flow
The dApp derives a secret from the user's cached initial key, source chain, destination chain, and the timelock of the swap using [HKDF](/protocol-spec/HKDF).
User locks funds on the source chain using the hash of the derived secret as the hashlock.
Solver observes the source lock and creates a matching HTLC on the destination chain with the same hashlock.
The dApp signs a message containing the actual derived secret and transmits this signed secret to the Solver (or broadcasts it to any available actor).
The Solver reveals the secret on the destination chain to unlock the user's funds (earning a designated reward for this action) and on the source chain to claim their primary fee. The Solver is economically incentivized to execute the destination redemption promptly—if they delay, any other actor can step in and claim the reward instead. Both user and Solver complete the swap.
This way we keep all the advantages of HTLC, but delegate the secret management to the dapp.
As long as the user does not clear the cache the dapp can crete newer and newer secrets.
And if the cache is cleared than the user can sign the message again and get the initial key,
after that the secret can be recovered as the other parameters used to derive the key are publicly stored in the blockchain.
## Passkey-Based Implementation
For enhanced security and UX, the secret generation can also be derived from passkeys (WebAuthn credentials) instead of wallet signatures. This allows for fully passwordless authentication while maintaining the same recoverable secret generation properties.
**Implementation details:** See the [auth package](https://github.com/TrainProtocol/app/tree/dev/packages/auth) in the TRAIN app repository for the passkey-based implementation using HKDF key derivation.
# Contracts
Source: https://docs.train.tech/protocol/contracts
List of deployed protocol contracts
### Atomic Swap (HTLC) Contracts
* Native Contract: [0x67d3E9cb8d3200444349D2a7794960EeB969631c](https://sepolia.etherscan.io/address/0x67d3E9cb8d3200444349D2a7794960EeB969631c#code)
* Token Contract: [0x5305aC8c135c650b145Fb59356695E12155107ee](https://sepolia.etherscan.io/address/0x5305aC8c135c650b145Fb59356695E12155107ee#code)
* Native Contract: --
* Token Contract: [0x00aff0da8f9df8d7ec3fd8e2c3d1f5ff178df21aa11414b0fce689a54ee1f452](https://sepolia.voyager.online/contract/0x00aff0da8f9df8d7ec3fd8e2c3d1f5ff178df21aa11414b0fce689a54ee1f452)
* Native Contract: [EQDyQE9HXfUu6KmiH70OkqnegMBBhr2X\_-2ymJ4kL1ecfJMM](https://verifier.ton.org/EQDyQE9HXfUu6KmiH70OkqnegMBBhr2X_-2ymJ4kL1ecfJMM?testnet)
* Token Contract: [EQA37e2ZOCwppPnZjgnIYAEqrmJmLvkmP14FTMw1D-xRN\_hp](https://verifier.ton.org/EQA37e2ZOCwppPnZjgnIYAEqrmJmLvkmP14FTMw1D-xRN_hp?testnet)
* Native Contract: [2XfmTmnhz8kDnryZSJKKV53tLN7DKZbrN9Q1sZbJo5bc](https://explorer.solana.com/address/2XfmTmnhz8kDnryZSJKKV53tLN7DKZbrN9Q1sZbJo5bc?cluster=devnet)
* Token Contract: [3TTb3BF3H273DS8hCJT9w8wuhtchN7fi7tX2sZDZ3p3Q](https://explorer.solana.com/address/3TTb3BF3H273DS8hCJT9w8wuhtchN7fi7tX2sZDZ3p3Q?cluster=devnet)
* Native Contract: [0x0c7f392943dd6609af92ecd071c1841bc4fe823b79b033ede8c027213dc8caf8](https://app-testnet.fuel.network/contract/0x0c7f392943dd6609af92ecd071c1841bc4fe823b79b033ede8c027213dc8caf8/code)
* Native Contract: [0xb0284d80fa0ecd8c59a92d67649ebd28f85946f327271a238d62eb5c708cd507](https://explorer.hiro.so/txid/0xb0284d80fa0ecd8c59a92d67649ebd28f85946f327271a238d62eb5c708cd507?chain=testnet)
* Token Contract: --
* Native Contract: [0x2fDf0Cbe7bF2f27E8aDeCD6CaF33d9b2647EDE8d](https://sepolia.arbiscan.io/address/0x2fdf0cbe7bf2f27e8adecd6caf33d9b2647ede8d#code)
* Token Contract: [0x01B0421DbEd7322cBb9c5796E0202bC6d37a9beE](https://sepolia.arbiscan.io/address/0x01B0421DbEd7322cBb9c5796E0202bC6d37a9beE#code)
* Native Contract: [0xC41F8341199D27a00557Be9Be72de41b3652706a](https://sepolia-optimism.etherscan.io/address/0xC41F8341199D27a00557Be9Be72de41b3652706a#code)
* Token Contract: [0x2B8A230Cf3e72262c694B19807a861A9e273c979](https://sepolia-optimism.etherscan.io/address/0x2B8A230Cf3e72262c694B19807a861A9e273c979#code)
* Native Contract: [0x2d190F4b4899f4D05B763B801b248A5d322E29c9](https://sepolia.lineascan.build/address/0x2d190F4b4899f4D05B763B801b248A5d322E29c9#code)
* Token Contract: [0x7B5b32B5096f6Ad691118306BD1123c7cED6F403](https://sepolia.lineascan.build/address/0x7B5b32B5096f6Ad691118306BD1123c7cED6F403#code)
* Native Contract: [0xF3CFa3964Ffdce47f78e7ffFA5E56f88dB27286b](https://explorer.hekla.taiko.xyz/address/0xF3CFa3964Ffdce47f78e7ffFA5E56f88dB27286b?tab=contract)
* Token Contract: [0x210a3a6F364787C65e206C1001925986bf68253D](https://explorer.hekla.taiko.xyz/address/0x210a3a6F364787C65e206C1001925986bf68253D?tab=contract)
* Native Contract: [0x01B0421DbEd7322cBb9c5796E0202bC6d37a9beE](https://explorer.testnet.immutable.com/address/0x01B0421DbEd7322cBb9c5796E0202bC6d37a9beE?tab=contract)
* Token Contract: [0x2fDf0Cbe7bF2f27E8aDeCD6CaF33d9b2647EDE8d](https://explorer.testnet.immutable.com/address/0x2fDf0Cbe7bF2f27E8aDeCD6CaF33d9b2647EDE8d?tab=contract)
* Native Contract: [0xE886692f8b3FaC25B88CB3507F3F000969415350](https://soneium-minato.blockscout.com/address/0xE886692f8b3FaC25B88CB3507F3F000969415350?tab=contract)
* Token Contract: [0xD41981B117a6fb9bF01139e01d82aeDC0741a97f](https://soneium-minato.blockscout.com/address/0xD41981B117a6fb9bF01139e01d82aeDC0741a97f?tab=contract)
* Native Contract: [0xD41981B117a6fb9bF01139e01d82aeDC0741a97f](https://unichain-sepolia.blockscout.com/address/0xD41981B117a6fb9bF01139e01d82aeDC0741a97f)
* Token Contract: [0x582D5807290Cad35111A325d4B201dDB85eba0f5](https://unichain-sepolia.blockscout.com/address/0x582D5807290Cad35111A325d4B201dDB85eba0f5)
* Native Contract: [0xa4777590626006374a75d2ae04A567A1612e6C76](https://bartio.beratrail.io/address/0xa4777590626006374a75d2ae04A567A1612e6C76/contract/80084/code)
* Token Contract: [0x2FEE8a563d1c3901EBfe2F86B5723CCc1d55F7A4](https://bartio.beratrail.io/address/0x2FEE8a563d1c3901EBfe2F86B5723CCc1d55F7A4/contract/80084/code)
* Native Contract: [0x2FEE8a563d1c3901EBfe2F86B5723CCc1d55F7A4](https://sepolia.kakarotscan.org/address/0x2FEE8a563d1c3901EBfe2F86B5723CCc1d55F7A4/contract/920637907288165/code)
* Token Contract: [0x8419ad96e064d963eDd39d47c1178197cc344637](https://sepolia.kakarotscan.org/address/0x8419ad96e064d963eDd39d47c1178197cc344637/contract/920637907288165/code)
* Native Contract: [0xa4777590626006374a75d2ae04A567A1612e6C76](https://sepolia.mantlescan.xyz/address/0xa4777590626006374a75d2ae04A567A1612e6C76#code)
* Token Contract: [0x2FEE8a563d1c3901EBfe2F86B5723CCc1d55F7A4](https://sepolia.mantlescan.xyz/address/0x2FEE8a563d1c3901EBfe2F86B5723CCc1d55F7A4#code)
* Native Contract: [0x07fbdc90f60f474514ab79c99b50ef27b91ce594c168a38cb1dcadae3244f859](https://devnet.aztecscan.xyz/contracts/instances/0x07fbdc90f60f474514ab79c99b50ef27b91ce594c168a38cb1dcadae3244f859)
* Token Contract: --
* Native Contract: [0x7E6f983f93fd12114DaFE0C69d1e55023EE0abCB](https://etherscan.io/address/0x7E6f983f93fd12114DaFE0C69d1e55023EE0abCB#code)
* Token Contract: [0x11E0Da85724F1B2CA8BEd308c349372e2Fc7dAc8](https://etherscan.io/address/0x11E0Da85724F1B2CA8BEd308c349372e2Fc7dAc8#code)
* Native Contract: [0x126Fc543AA75D1D8511390aEb0a5E49Ad8a245BC](https://arbiscan.io/address/0x126Fc543AA75D1D8511390aEb0a5E49Ad8a245BC#code)
* Native Contract: [0x126Fc543AA75D1D8511390aEb0a5E49Ad8a245BC](https://optimistic.etherscan.io/address/0x126Fc543AA75D1D8511390aEb0a5E49Ad8a245BC#code)
* Native Contract: [0xAE90b87324DA77113075E149455C53a88F6a01fb](https://basescan.org/address/0xAE90b87324DA77113075E149455C53a88F6a01fb#code)
* Token Contract: [0x232d3A1c68e63898E2679467ed02CcAc2593CD40](https://basescan.org/address/0x232d3A1c68e63898E2679467ed02CcAc2593CD40#code)
* Native Contract: [0xB4863f53332C89078575320C01E270032f71e486](https://explorer.zksync.io/address/0xB4863f53332C89078575320C01E270032f71e486#contract)
* Token Contract: [0x06dcbd1c97d73f205298f098e95f44bf3e52d049ea610206c06997943d147818](https://starkscan.co/contract/0x06dcbd1c97d73f205298f098e95f44bf3e52d049ea610206c06997943d147818)
* Native Contract: [0x320818EEFCF46ED1ec722f3bbC5B463EA1F5B619](https://lineascan.build/address/0x320818EEFCF46ED1ec722f3bbC5B463EA1F5B619#code)
* Native Contract: [0xb0e6e598739780b7c5d212514c8d8d6b4a40950b729e4d918590ef0426badaa0](https://app.fuel.network/contract/0xb0e6e598739780b7c5d212514c8d8d6b4a40950b729e4d918590ef0426badaa0/code)
* Native Contract: [0x320818EEFCF46ED1ec722f3bbC5B463EA1F5B619](https://bscscan.com/address/0x320818EEFCF46ED1ec722f3bbC5B463EA1F5B619)
* Token Contract: [0xAE90b87324DA77113075E149455C53a88F6a01fb](https://bscscan.com/address/0xAE90b87324DA77113075E149455C53a88F6a01fb)
* Native Contract: [TdkzKRrvbXPcQF3J3mL99JYuHtgbePpcRgiq3F7qMnB](https://explorer.solana.com/address/TdkzKRrvbXPcQF3J3mL99JYuHtgbePpcRgiq3F7qMnB)
* Token Contract: [4khpoidv4ympbnwh9mKwKro3quTFTULD7utZJ8MHSVHn](https://explorer.solana.com/address/4khpoidv4ympbnwh9mKwKro3quTFTULD7utZJ8MHSVHn)
# dApp
Source: https://docs.train.tech/protocol/dApp
Explains the details of the dApp using the protocol
### Overview
The [TRAIN Bridge dApp](https://testnet.train.tech/) serves as the central interface for seamless cross-chain transactions. It submits user intents for Solver matching, receives the selected Solver quote, and orchestrates the [HTLC flow with recoverable secret generation](/protocol/atomic-swaps-secret_gen).
The dApp has **four** main responsibilities:
1. Accept user swap intent and obtain a Solver quote
2. Display the winning Solver quote and allow the user to initiate the swap (specifying the winning Solver)
3. Execute the [HTLC flow](/protocol/atomic-swaps-secret_gen):
* Derive a secret from the user's wallet signature
* Lock funds on the source chain with the derived hashlock
* Observe the Solver's lock on the destination chain
* Sign and transmit the derived secret to the Solver so they can unlock funds on both chains
4. Optionally monitor and verify that funds are unlocked on both chains. The Solver is economically incentivized to redeem on the destination chain quickly because a reward is reserved for whoever completes that transaction—if they delay, any other actor can step in and claim it.
### Observing the Destination Network
The dApp must observe the destination lock created by the Solver to verify the swap is proceeding correctly. The dApp can observe this transaction through the following methods, listed in order of priority:
1. Bootstrap a Light Client (e.g., [Helios](https://github.com/a16z/helios)) for the destination chain and read the lock state from it
2. If no Light Client is available, read and verify the lock state from multiple RPC providers
# Introduction
Source: https://docs.train.tech/protocol/introduction
A trustless, permissionless cross-chain bridging (swapping) solution.
The **TRAIN** Protocol (**TR**ustless **A**tomic **IN**tents) is a peer-to-peer system for bridging and swapping crypto assets between blockchain networks. The protocol is implemented as a set of persistent, non-upgradable smart contracts deployed to all [supported networks](/protocol/contracts).
* TRAIN is built on top of [HTLC with recoverable secret generation](/protocol/atomic-swaps-secret_gen). This allows two parties—the **User** and the **Solver**—to exchange assets trustlessly across different chains. Users send their **Intents** to Solvers, who fulfill these Intents using Atomic Swaps.
* There are **no third parties or gatekeepers**. The security of the exchange is fully ensured by:
* The cryptographic protocol (Atomic Swaps)
* Local verification through a [Light Client](/protocol/dApp) running in the User's browser
Experience TRAIN on all major network testnets, including EVM-compatible chains, Starknet, TON, Solana, and Aptos.
Explore the core protocol concepts: Users, Solvers, Auctions, and Atomic Swaps.
Dive deeper into the protocol specification and detailed protocol design.
# Security
Source: https://docs.train.tech/protocol/security
Key security details of the TRAIN protocol
* **Homogeneous Security**: The protocol establishes consistent cryptographic security for all permissionless participants. Security attributes remain unchanged when adding new networks or Solvers.
* **Battle-Tested**: The core technology of Atomic Swaps (HTLC) has been successfully used in production for the Lightning Network.
* **No Pools**: No single contract holds large amounts of funds. This design choice significantly reduces the risk of being targeted by attackers.
* **Immutability**: The contracts are immutable. This eliminates the risks associated with upgrades.
* **Simplicity**: HTLC contracts are straightforward locking mechanisms. Each contract typically consists of about [300 lines of code](https://github.com/TrainProtocol/contracts/blob/main/chains/evm/solidity/contracts/Train.sol) in any smart contract language.
# Reward-Slash
Source: https://docs.train.tech/protocol/slashing
Incentivizing Solvers to act honestly without creating inconveniences for users
Solvers can sometimes misbehave, leading to various edge cases. For example, a Solver might refuse to release a user’s funds. While users can always manually claim their funds, ensuring no loss, this process creates significant inconvenience.
To address this, we introduce a [Reward-Slashing Mechanism](/protocol-spec/reward-slashing) to incentivize Solvers to act correctly. When locking funds for a user, the Solver also locks an additional reward amount with a timelock. If the Solver successfully transfers the user’s assets before the timelock expires, the reward is released to the Solver. However, if the Solver fails to act in time, the reward is transferred to the party that executes the function to release the user’s assets.
This mechanism serves as both an incentive for the Solver and a penalty (or "slash") for failing to fulfill their responsibility.
# The Protocol
Source: https://docs.train.tech/protocol/the-protocol
Overview of the TRAIN protocol with all main components
The TRAIN protocol consists of **two** main components:
The Bridge UI/dApp or integration in a wallet, connected to the Auction Manager. This dApp submits user intents, receives the selected Solver, and executes the atomic swap.
These are the contracts responsible for ensuring secure asset exchange between the User and Solver on different chains using HTLC with recoverable secret generation.
# Adding a New Network
Source: https://docs.train.tech/protocol/usage-add-new-network
Explains how networks can be added to the protocol
Implement [HTLC with recoverable secret generation](/protocol/atomic-swaps-secret_gen) standards in the network.
If there is no existing implementation (e.g., EVM), implement the Solver Agent Chain Library for the new network (functions for interacting with deployed HTLC contracts on specific chains).
Run an Solver for two networks—one well connected to others (already active Solvers) and the new network.
If there is no existing implementation (e.g., EVM), implement the Client Chain Library for the new network (functions for interacting with wallets on specific chains, subscribing to contract events, and composing user transactions).
Create a pull request for a [popular bridge UI](https://testnet.train.tech/) or fork and deploy a separate UI.
These steps can be performed independently without needing permission or interaction with any party or entity. At this stage, anyone can transfer assets to the new network. The network-adding process in the TRAIN protocol is **similar to adding an ERC20 token to the Uniswap protocol**, making bridging trustless and permissionless. The detailed implementation steps can be found in the [Solver Implementation](/protocol-spec/implementation-solver) spec.
# Cross-Chain Swap
Source: https://docs.train.tech/protocol/usage-swap
Explains how the protocol can be used for cross-chain swaps
Send an intent to find the best Solver/price for the given source and destination.
Perform an atomic swap using [HTLC with recoverable secret generation](/protocol/atomic-swaps-secret_gen).
The TRAIN Protocol makes bridging **completely transparent and fully controllable** by the client. The integrator has complete control over every aspect, from selecting and ranking Solvers independently to performing final verification, ensuring the entire process is **trustless, transparent, and under their control**. The detailed implementation steps can be found in the [dApp Implementation](/protocol-spec/implementation-dApp) spec.