214 lines
7.0 KiB
Markdown
214 lines
7.0 KiB
Markdown
|
|
# Fraud Proof Documentation
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
The trustless bridge system uses cryptographic fraud proofs to verify claims against the source chain (ChainID 138) state. This document describes the fraud proof types, formats, and verification process.
|
||
|
|
|
||
|
|
## Fraud Proof Types
|
||
|
|
|
||
|
|
### 1. NonExistentDeposit
|
||
|
|
|
||
|
|
**Purpose**: Prove that a claimed deposit does not exist on the source chain.
|
||
|
|
|
||
|
|
**Proof Structure**:
|
||
|
|
```solidity
|
||
|
|
struct NonExistentDepositProof {
|
||
|
|
bytes32 stateRoot; // State root from source chain block
|
||
|
|
bytes32 depositHash; // Hash of deposit data that should exist
|
||
|
|
bytes32[] merkleProof; // Merkle proof path
|
||
|
|
bytes32 leftSibling; // Left sibling for non-existence proof
|
||
|
|
bytes32 rightSibling; // Right sibling for non-existence proof
|
||
|
|
bytes blockHeader; // Block header from source chain
|
||
|
|
uint256 blockNumber; // Block number
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Verification Process**:
|
||
|
|
1. Verify state root against block header
|
||
|
|
2. Hash the claimed deposit data
|
||
|
|
3. Verify that the deposit hash matches the proof
|
||
|
|
4. Verify non-existence proof using Merkle proof with left/right siblings
|
||
|
|
|
||
|
|
**Use Case**: Relayer claims a deposit that was never made on ChainID 138.
|
||
|
|
|
||
|
|
### 2. IncorrectAmount
|
||
|
|
|
||
|
|
**Purpose**: Prove that the claimed deposit amount differs from the actual deposit amount.
|
||
|
|
|
||
|
|
**Proof Structure**:
|
||
|
|
```solidity
|
||
|
|
struct IncorrectAmountProof {
|
||
|
|
bytes32 stateRoot; // State root from source chain block
|
||
|
|
bytes32 depositHash; // Hash of actual deposit data
|
||
|
|
bytes32[] merkleProof; // Merkle proof for actual deposit
|
||
|
|
uint256 actualAmount; // Actual deposit amount from source chain
|
||
|
|
bytes blockHeader; // Block header from source chain
|
||
|
|
uint256 blockNumber; // Block number
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Verification Process**:
|
||
|
|
1. Verify state root against block header
|
||
|
|
2. Verify that actual amount differs from claimed amount
|
||
|
|
3. Hash the actual deposit data with correct amount
|
||
|
|
4. Verify Merkle proof for actual deposit
|
||
|
|
|
||
|
|
**Use Case**: Relayer claims 2 ETH but actual deposit was 1 ETH.
|
||
|
|
|
||
|
|
### 3. IncorrectRecipient
|
||
|
|
|
||
|
|
**Purpose**: Prove that the claimed recipient differs from the actual deposit recipient.
|
||
|
|
|
||
|
|
**Proof Structure**:
|
||
|
|
```solidity
|
||
|
|
struct IncorrectRecipientProof {
|
||
|
|
bytes32 stateRoot; // State root from source chain block
|
||
|
|
bytes32 depositHash; // Hash of actual deposit data
|
||
|
|
bytes32[] merkleProof; // Merkle proof for actual deposit
|
||
|
|
address actualRecipient; // Actual recipient from source chain
|
||
|
|
bytes blockHeader; // Block header from source chain
|
||
|
|
uint256 blockNumber; // Block number
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Verification Process**:
|
||
|
|
1. Verify state root against block header
|
||
|
|
2. Verify that actual recipient differs from claimed recipient
|
||
|
|
3. Hash the actual deposit data with correct recipient
|
||
|
|
4. Verify Merkle proof for actual deposit
|
||
|
|
|
||
|
|
**Use Case**: Relayer claims recipient A but actual deposit was to recipient B.
|
||
|
|
|
||
|
|
### 4. DoubleSpend
|
||
|
|
|
||
|
|
**Purpose**: Prove that a deposit was already claimed in a previous claim.
|
||
|
|
|
||
|
|
**Proof Structure**:
|
||
|
|
```solidity
|
||
|
|
struct DoubleSpendProof {
|
||
|
|
uint256 previousClaimId; // Deposit ID of previous claim
|
||
|
|
bytes32 previousClaimHash; // Hash of previous claim
|
||
|
|
bytes32[] merkleProof; // Merkle proof for previous claim
|
||
|
|
bytes blockHeader; // Block header from source chain
|
||
|
|
uint256 blockNumber; // Block number
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Verification Process**:
|
||
|
|
1. Verify that previous claim ID matches current deposit ID
|
||
|
|
2. Verify that previous claim exists and is finalized
|
||
|
|
3. Verify that deposit data matches (same deposit, different claim)
|
||
|
|
|
||
|
|
**Use Case**: Same deposit is claimed twice by different relayers.
|
||
|
|
|
||
|
|
## Deposit Data Hashing
|
||
|
|
|
||
|
|
Deposit data is hashed using the following format:
|
||
|
|
|
||
|
|
```solidity
|
||
|
|
keccak256(abi.encodePacked(
|
||
|
|
depositId,
|
||
|
|
asset,
|
||
|
|
amount,
|
||
|
|
recipient,
|
||
|
|
timestamp
|
||
|
|
))
|
||
|
|
```
|
||
|
|
|
||
|
|
This hash is used as the leaf in the Merkle tree.
|
||
|
|
|
||
|
|
## Merkle Proof Verification
|
||
|
|
|
||
|
|
The system uses standard Merkle tree verification:
|
||
|
|
|
||
|
|
1. Start with the leaf hash (deposit data hash)
|
||
|
|
2. For each proof element:
|
||
|
|
- If current hash < proof element: hash(current, proof)
|
||
|
|
- Else: hash(proof, current)
|
||
|
|
3. Final hash should equal the state root
|
||
|
|
|
||
|
|
## Non-Existence Proofs
|
||
|
|
|
||
|
|
For non-existence proofs, the system verifies that:
|
||
|
|
1. The deposit hash would be between leftSibling and rightSibling in the tree
|
||
|
|
2. The Merkle proof path shows the deposit doesn't exist
|
||
|
|
|
||
|
|
## Block Header Verification
|
||
|
|
|
||
|
|
Block headers from ChainID 138 are verified to extract the state root. The current implementation includes a placeholder for RLP decoding and state root extraction.
|
||
|
|
|
||
|
|
**Future Enhancement**: Implement full RLP decoding and state root extraction from block headers.
|
||
|
|
|
||
|
|
## Light Client Integration (Future)
|
||
|
|
|
||
|
|
Future implementations will integrate light clients for trustless state verification without relying on RPC nodes. This will:
|
||
|
|
- Remove RPC dependency for verification
|
||
|
|
- Enable fully trustless operation
|
||
|
|
- Improve security and decentralization
|
||
|
|
|
||
|
|
## Proof Generation (Off-Chain)
|
||
|
|
|
||
|
|
Fraud proofs are generated off-chain by challengers who:
|
||
|
|
1. Monitor source chain (ChainID 138) for deposits
|
||
|
|
2. Monitor destination chain (Ethereum) for claims
|
||
|
|
3. Compare claims against source chain state
|
||
|
|
4. Generate appropriate fraud proof when fraud is detected
|
||
|
|
5. Submit challenge with fraud proof
|
||
|
|
|
||
|
|
## Example: Generating a Non-Existence Proof
|
||
|
|
|
||
|
|
```python
|
||
|
|
# Pseudocode for generating non-existence proof
|
||
|
|
def generate_non_existence_proof(deposit_id, claimed_deposit_data, source_chain_state):
|
||
|
|
# Hash the claimed deposit data
|
||
|
|
deposit_hash = keccak256(encode(deposit_id, claimed_deposit_data))
|
||
|
|
|
||
|
|
# Get state root from source chain block
|
||
|
|
state_root = source_chain_state.get_state_root()
|
||
|
|
|
||
|
|
# Generate Merkle proof showing deposit doesn't exist
|
||
|
|
merkle_proof, left_sibling, right_sibling = generate_non_existence_merkle_proof(
|
||
|
|
state_root,
|
||
|
|
deposit_hash
|
||
|
|
)
|
||
|
|
|
||
|
|
# Get block header
|
||
|
|
block_header = source_chain_state.get_block_header()
|
||
|
|
block_number = source_chain_state.get_block_number()
|
||
|
|
|
||
|
|
# Construct proof
|
||
|
|
proof = NonExistentDepositProof({
|
||
|
|
stateRoot: state_root,
|
||
|
|
depositHash: deposit_hash,
|
||
|
|
merkleProof: merkle_proof,
|
||
|
|
leftSibling: left_sibling,
|
||
|
|
rightSibling: right_sibling,
|
||
|
|
blockHeader: block_header,
|
||
|
|
blockNumber: block_number
|
||
|
|
})
|
||
|
|
|
||
|
|
return encode(proof)
|
||
|
|
```
|
||
|
|
|
||
|
|
## Security Considerations
|
||
|
|
|
||
|
|
1. **State Root Verification**: Always verify state root against block header
|
||
|
|
2. **Block Finality**: Use finalized blocks from source chain
|
||
|
|
3. **Proof Validity**: Verify all proof elements are valid
|
||
|
|
4. **Replay Protection**: Ensure proofs are for the correct deposit and claim
|
||
|
|
|
||
|
|
## Testing
|
||
|
|
|
||
|
|
Comprehensive test suite available in `test/bridge/trustless/FraudProof.t.sol` covering:
|
||
|
|
- All fraud proof types
|
||
|
|
- Encoding/decoding
|
||
|
|
- Merkle proof verification
|
||
|
|
- Edge cases
|
||
|
|
|
||
|
|
## References
|
||
|
|
|
||
|
|
- Merkle Proof Verifier: `contracts/bridge/trustless/libraries/MerkleProofVerifier.sol`
|
||
|
|
- Fraud Proof Types: `contracts/bridge/trustless/libraries/FraudProofTypes.sol`
|
||
|
|
- Challenge Manager: `contracts/bridge/trustless/ChallengeManager.sol`
|
||
|
|
|