I'll help you understand token wrapping and bridging! Here are the main approaches:
1. Token Wrapping (Creating Wrapped Tokens)
Basic ERC-20 Wrapper Contract:

// Simple Wrapped Token Contract
contract WrappedToken {
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
event Wrap(address indexed user, uint256 amount);
event Unwrap(address indexed user, uint256 amount);
IERC20 public originalToken;
constructor(address _originalToken) {
originalToken = IERC20(_originalToken);
name = string(abi.encodePacked("Wrapped ", IERC20(_originalToken).name()));
symbol = string(abi.encodePacked("W", IERC20(_originalToken).symbol()));
decimals = IERC20(_originalToken).decimals();
}
// Wrap original tokens to get wrapped tokens
function wrap(uint256 amount) external {
require(originalToken.transferFrom(msg.sender, address(this), amount), "Transfer failed");
balanceOf[msg.sender] += amount;
totalSupply += amount;
emit Wrap(msg.sender, amount);
emit Transfer(address(0), msg.sender, amount);
}
// Unwrap to get original tokens back
function unwrap(uint256 amount) external {
require(balanceOf[msg.sender] >= amount, "Insufficient balance");
balanceOf[msg.sender] -= amount;
totalSupply -= amount;
require(originalToken.transfer(msg.sender, amount), "Transfer failed");
emit Unwrap(msg.sender, amount);
emit Transfer(msg.sender, address(0), amount);
}
// Standard ERC-20 functions
function transfer(address to, uint256 amount) external returns (bool) {
// ... standard transfer logic
}
function approve(address spender, uint256 amount) external returns (bool) {
// ... standard approval logic
}
}
2. Cross-Chain Bridges
Common Bridge Architectures:
A. Lock-and-Mint Bridge
// Simple lock-and-mint bridge
contract Bridge {
mapping(address => uint256) public lockedAmounts;
mapping(bytes32 => bool) public processedTransactions;
address public remoteBridge;
IERC20 public token;
WrappedToken public wrappedToken;
event TokensLocked(address indexed user, uint256 amount, uint256 chainId);
event TokensMinted(address indexed user, uint256 amount);
function lockTokens(uint256 amount, uint256 destinationChainId) external {
require(token.transferFrom(msg.sender, address(this), amount), "Transfer failed");
lockedAmounts[msg.sender] += amount;
emit TokensLocked(msg.sender, amount, destinationChainId);
}
function mintTokens(address user, uint256 amount, bytes32 transactionId) external {
require(msg.sender == remoteBridge, "Unauthorized");
require(!processedTransactions[transactionId], "Already processed");
processedTransactions[transactionId] = true;
wrappedToken.mint(user, amount);
emit TokensMinted(user, amount);
}
}
B. Liquidity Pool Bridge (like Stargate/LayerZero)
// Simplified liquidity pool bridge
contract PoolBridge {
struct ChainPath {
uint16 dstChainId;
uint256 poolId;
uint256 liquidity;
}
mapping(uint16 => ChainPath) public chainPaths;
mapping(address => uint256) public liquidityProvided;
function sendTokens(
uint16 dstChainId,
address to,
uint256 amount,
address payable refundAddress
) external payable {
// Lock tokens locally
token.transferFrom(msg.sender, address(this), amount);
// Emit event for off-chain relayer/oracle
emit CrossChainTransfer(
dstChainId,
msg.sender,
to,
amount,
block.timestamp
);
}
function receiveTokens(
uint16 srcChainId,
address to,
uint256 amount,
bytes32 transactionId
) external onlyRelayer {
// Mint wrapped tokens on destination
wrappedToken.mint(to, amount);
}
}
3. Popular Bridge Solutions
Using Existing Bridge Protocols:
1.LayerZero Implementation:
import "@layerzerolabs/solidity-examples/contracts/token/oft/IOFT.sol";
import "@layerzerolabs/solidity-examples/contracts/token/oft/OFTCore.sol";
contract MyOFT is OFTCore, ERC20 {
constructor(address _layerZeroEndpoint)
ERC20("MyToken", "MTK")
OFTCore(_layerZeroEndpoint)
{}
function sendFrom(
address _from,
uint16 _dstChainId,
bytes calldata _toAddress,
uint _amount,
address payable _refundAddress,
address _zroPaymentAddress,
bytes calldata _adapterParams
) public payable override {
_send(_from, _dstChainId, _toAddress, _amount, _refundAddress, _zroPaymentAddress, _adapterParams);
}
}
2.Wormhole Implementation:
import "@wormhole-foundation/wormhole-solidity-sdk/contracts/token/TokenBridge.sol";
contract WormholeWrapper {
IWormholeBridge public bridge;
function transferTokens(
address token,
uint256 amount,
uint16 recipientChain,
bytes32 recipient,
uint256 arbiterFee,
uint32 nonce
) external returns (uint64 sequence) {
// Lock/burn tokens
// Emit wormhole message
}
}
4. Executable Bridge Commands
Using CLI Tools:
# 1. Using Axelar
axelard tx token-link [source-chain] [destination-chain] [token-amount] [recipient]
# 2. Using Wormhole CLI
wormhole bridge transfer --chain ethereum --target-chain polygon \
--token USDC --amount 100 --recipient 0x...
# 3. Using LayerZero Scan API
curl -X POST https://api.layerzero-scan.com/bridge \
-H "Content-Type: application/json" \
-d '{
"srcChainId": 1,
"dstChainId": 137,
"token": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"amount": "100000000",
"to": "0x..."
}'
5. Security Considerations
// Important security patterns
contract SecureBridge {
// 1. Use nonces/replay protection
mapping(uint256 => bool) public nonceUsed;
// 2. Implement timelocks for large withdrawals
mapping(address => WithdrawalRequest) public withdrawalRequests;
// 3. Use multisig for admin functions
address[] public signers;
uint256 public requiredSignatures;
// 4. Implement pause functionality
bool public paused;
modifier whenNotPaused() {
require(!paused, "Contract paused");
_;
}
// 5. Rate limiting
mapping(address => uint256) public lastTransferTime;
uint256 public constant COOLDOWN_PERIOD = 1 hours;
}
Quick Start Recommendations:
-
For simple wrapping: Use OpenZeppelin's ERC-20 with a mint/burn wrapper
-
For cross-chain: Start with LayerZero or Axelar for easier implementation
-
For production: Consider using existing bridge protocols rather than building from scratch
-
Always: Audit your contracts and implement proper security measures
