Token Bridge System
The token bridge is a system for enabling token transfers between different blockchain networks. This tutorial will explain how to implement a secure and reliable cross-chain bridge system.
Features
- Cross-chain Transfer
- Asset Locking
- Verification Mechanism
- Security Protection
- Emergency Handling
Contract Implementation
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
/**
* @title TokenBridge
* @dev Token bridge contract implementation
*/
contract TokenBridge is Ownable, ReentrancyGuard, Pausable {
using ECDSA for bytes32;
// Bridge request
struct BridgeRequest {
uint256 nonce; // Request number
address token; // Token address
address sender; // Sender
address receiver; // Receiver
uint256 amount; // Amount
uint256 sourceChainId; // Source chain ID
uint256 targetChainId; // Target chain ID
uint256 timestamp; // Timestamp
bool processed; // Whether processed
}
// Validator information
struct Validator {
bool isActive; // Whether active
uint256 threshold; // Threshold
uint256 weight; // Weight
}
// Configuration information
struct BridgeConfig {
uint256 minAmount; // Minimum amount
uint256 maxAmount; // Maximum amount
uint256 dailyLimit; // Daily limit
uint256 validatorThreshold; // Validator threshold
bool requiresValidation; // Whether validation is required
bool isActive; // Whether active
}
// State variables
mapping(address => bool) public supportedTokens; // Supported tokens
mapping(address => Validator) public validators; // Validators
mapping(bytes32 => BridgeRequest) public requests; // Request records
mapping(address => uint256) public dailyAmounts; // Daily amounts
mapping(address => uint256) public lastResetTime; // Last reset time
BridgeConfig public config; // Configuration information
uint256 public chainId; // Current chain ID
// Events
event TokenLocked(bytes32 indexed requestId, address indexed token, address indexed sender, uint256 amount);
event TokenReleased(bytes32 indexed requestId, address indexed token, address indexed receiver, uint256 amount);
event ValidatorUpdated(address indexed validator, bool status, uint256 weight);
event TokenUpdated(address indexed token, bool status);
event ConfigUpdated(uint256 minAmount, uint256 maxAmount, uint256 dailyLimit);
/**
* @dev Constructor
*/
constructor(
uint256 _chainId,
uint256 _minAmount,
uint256 _maxAmount,
uint256 _dailyLimit,
uint256 _validatorThreshold
) {
chainId = _chainId;
config = BridgeConfig({
minAmount: _minAmount,
maxAmount: _maxAmount,
dailyLimit: _dailyLimit,
validatorThreshold: _validatorThreshold,
requiresValidation: true,
isActive: true
});
}
/**
* @dev Lock tokens
*/
function lockTokens(
address _token,
address _receiver,
uint256 _amount,
uint256 _targetChainId
) external nonReentrant whenNotPaused returns (bytes32) {
require(supportedTokens[_token], "Token not supported");
require(_amount >= config.minAmount && _amount <= config.maxAmount, "Invalid amount");
require(_updateDailyAmount(_token, _amount), "Exceeds daily limit");
bytes32 requestId = keccak256(abi.encodePacked(
block.timestamp,
_token,
msg.sender,
_receiver,
_amount,
chainId,
_targetChainId
));
requests[requestId] = BridgeRequest({
nonce: block.number,
token: _token,
sender: msg.sender,
receiver: _receiver,
amount: _amount,
sourceChainId: chainId,
targetChainId: _targetChainId,
timestamp: block.timestamp,
processed: false
});
require(
IERC20(_token).transferFrom(msg.sender, address(this), _amount),
"Transfer failed"
);
emit TokenLocked(requestId, _token, msg.sender, _amount);
return requestId;
}
/**
* @dev Release tokens
*/
function releaseTokens(
bytes32 _requestId,
bytes[] calldata _signatures
) external nonReentrant whenNotPaused {
BridgeRequest storage request = requests[_requestId];
require(!request.processed, "Request already processed");
require(request.targetChainId == chainId, "Invalid chain");
require(_validateSignatures(_requestId, _signatures), "Invalid signatures");
request.processed = true;
require(
IERC20(request.token).transfer(request.receiver, request.amount),
"Transfer failed"
);
emit TokenReleased(_requestId, request.token, request.receiver, request.amount);
}
/**
* @dev Validate signatures
*/
function _validateSignatures(
bytes32 _requestId,
bytes[] calldata _signatures
) internal view returns (bool) {
require(_signatures.length > 0, "No signatures");
bytes32 message = keccak256(abi.encodePacked(_requestId));
uint256 validWeight = 0;
for (uint256 i = 0; i < _signatures.length; i++) {
address signer = message.toEthSignedMessageHash().recover(_signatures[i]);
Validator storage validator = validators[signer];
if (validator.isActive) {
validWeight += validator.weight;
if (validWeight >= config.validatorThreshold) {
return true;
}
}
}
return false;
}
/**
* @dev Update daily amount
*/
function _updateDailyAmount(
address _token,
uint256 _amount
) internal returns (bool) {
uint256 currentTime = block.timestamp;
uint256 lastReset = lastResetTime[_token];
if (currentTime - lastReset >= 1 days) {
dailyAmounts[_token] = _amount;
lastResetTime[_token] = currentTime;
return true;
}
uint256 newAmount = dailyAmounts[_token] + _amount;
if (newAmount > config.dailyLimit) {
return false;
}
dailyAmounts[_token] = newAmount;
return true;
}
/**
* @dev Update validator
*/
function updateValidator(
address _validator,
bool _isActive,
uint256 _weight
) external onlyOwner {
validators[_validator] = Validator({
isActive: _isActive,
threshold: config.validatorThreshold,
weight: _weight
});
emit ValidatorUpdated(_validator, _isActive, _weight);
}
/**
* @dev Update supported token
*/
function updateSupportedToken(
address _token,
bool _status
) external onlyOwner {
supportedTokens[_token] = _status;
emit TokenUpdated(_token, _status);
}
/**
* @dev Update configuration
*/
function updateConfig(
uint256 _minAmount,
uint256 _maxAmount,
uint256 _dailyLimit,
uint256 _validatorThreshold
) external onlyOwner {
config.minAmount = _minAmount;
config.maxAmount = _maxAmount;
config.dailyLimit = _dailyLimit;
config.validatorThreshold = _validatorThreshold;
emit ConfigUpdated(_minAmount, _maxAmount, _dailyLimit);
}
/**
* @dev Emergency withdrawal
*/
function emergencyWithdraw(
address _token,
address _to,
uint256 _amount
) external onlyOwner whenPaused {
require(_to != address(0), "Invalid address");
require(
IERC20(_token).transfer(_to, _amount),
"Transfer failed"
);
}
/**
* @dev Get request information
*/
function getRequest(
bytes32 _requestId
) external view returns (
uint256 nonce,
address token,
address sender,
address receiver,
uint256 amount,
uint256 sourceChainId,
uint256 targetChainId,
uint256 timestamp,
bool processed
) {
BridgeRequest storage request = requests[_requestId];
return (
request.nonce,
request.token,
request.sender,
request.receiver,
request.amount,
request.sourceChainId,
request.targetChainId,
request.timestamp,
request.processed
);
}
/**
* @dev Get validator information
*/
function getValidator(
address _validator
) external view returns (
bool isActive,
uint256 threshold,
uint256 weight
) {
Validator storage validator = validators[_validator];
return (
validator.isActive,
validator.threshold,
validator.weight
);
}
}
System Architecture
1. Core Components
- Bridge Contract: Manages token locking and releasing
- Validator Network: Verifies cross-chain transactions
- Oracle System: Monitors cross-chain events
- Security Module: Handles emergency situations
2. Process Flow
- User initiates cross-chain transfer
- Source chain locks tokens
- Validators verify the transaction
- Target chain releases tokens
- Event monitoring and confirmation
Security Measures
1. Transaction Security
- Multi-signature verification
- Amount limits
- Daily transfer limits
- Emergency pause mechanism
2. Validator Security
- Validator threshold
- Weight-based voting
- Active status management
- Signature verification
Best Practices
1. Implementation Guidelines
- Use secure random number generation
- Implement proper access control
- Handle edge cases carefully
- Maintain comprehensive event logs
2. Operation Guidelines
- Regular security audits
- Validator network maintenance
- Emergency response plan
- Regular configuration updates
FAQ
1. Basic Concepts
Q: What is a token bridge? A: A token bridge is a system that enables the transfer of tokens between different blockchain networks while maintaining the tokens' value and properties.
Q: How does cross-chain verification work? A: Cross-chain verification involves:
- Transaction validation
- Multi-signature consensus
- Event verification
- State synchronization
2. Security
Q: How to ensure bridge security? A: Security measures include:
- Multi-signature validation
- Amount limits
- Validator network
- Emergency mechanisms
- Regular audits
Q: How to handle bridge attacks? A: Protection measures include:
- Transaction monitoring
- Amount verification
- Signature validation
- Emergency pause
- Quick response plan
3. Performance
Q: How to optimize bridge performance? A: Optimization methods include:
- Batch processing
- Efficient validation
- State caching
- Event optimization
- Gas optimization
Q: How to handle high traffic? A: Traffic management includes:
- Load balancing
- Queue management
- Rate limiting
- Parallel processing
- Resource optimization
4. Maintenance
Q: How to upgrade the bridge? A: Upgrade process includes:
- Version control
- Backward compatibility
- State migration
- Testing verification
- Gradual rollout
Q: How to monitor bridge status? A: Monitoring includes:
- Transaction tracking
- Validator status
- System metrics
- Error logging
- Performance analysis