-
Notifications
You must be signed in to change notification settings - Fork 0
bridge
Cross-chain bridges facilitate token transfers between Goerli and Hobby by locking tokens on the source chain and employing a transaction relay server to interpret messages, thereby triggering rapid token minting on the target chain. Users lock tokens on Chain A, and the relay mints corresponding tokens on Chain B.
- Users initiate bridging by calling the bridgeTokens() method.
- The contract deducts the specified token amount from the user's balance.
- The contract executes the BridgeTokens(ID) event, inputting an ID.
- The relay retrieves detailed information using the provided ID from the block and performs verification.
- The relay calls a contract method to release tokens on Chain B.
- After Chain B mints the specified number of tokens, a send event is executed to notify successful bridging.
- If users wish to transfer from Chain B back to Chain A, they can call bridgeTokensBack(), destroying a certain number of tokens.
- The BridgeTokensBack() event is then sent.
- Upon interpreting the event, the relay executes a method on Chain A, returning a certain number of tokens to the user.
- First, create a cross-chain bridge contract entirely managed by smart contracts for locking, destroying, minting, and releasing, without involving liquidity pools.
- Next, explore the method of cross-chain inflows and outflows involving liquidity pools.
PS: For the mapping tokens deployed by the project party on the new chain, it’s not feasible to give minting authority to others. Hence, this method is suitable only for the liquidity pool’s inflow and outflow method. Therefore, to complete functionality “1”, the bridge itself must deploy mapping tokens, managed by smart contracts for token destruction, minting, locking, and releasing.
- Locking Tokens
- Releasing Tokens
- Destroying Tokens
- Minting Tokens
- Relay
enum TokenType {
Fungible, // Token
NonFungible // NFT
}
// For storing transaction information
/**
@dev Stores information about token transfers from Chain A to Chain B
@param timestamp Time of the transfer
@param srcChain ID of the chain initiating the transfer
@param srcAddress Address of the account initiating the transfer
@param dstChain ID of the chain to which the transfer is sent
@param dstAddress Address on Chain B that will receive the transfer
@param tokenAddress Address of the token being transferred on Chain A
*/
struct TokenTransferBase {
uint256 timestamp;
uint256 srcChain;
address srcAddress;
uint256 dstChain;
address dstAddress;
address tokenAddress;
}
/**
@dev For fungible token transfers
@param tokenTransfer Basic token transfer information structure
@param amount Amount of tokens being transferred
*/
struct TokenTransfer {
TokenTransferBase tokenTransfer;
uint256 amount;
}
// _transferID => Information for each transaction
mapping(bytes32 => TokenTransfer) public tokenTransfers;
// Rule Transaction ID
bytes32 _transferID = keccak256(
abi.encodePacked(
block.timestamp, // Timestamp
block.chainid, // Current chain ID
msg.sender, // Executor
_dstChain, // Destination chain ID
_dstAddress, // Destination address
_token, // Source contract address
_amount // Amount
)
);
// Token contract address => token registration ID
mapping(address => bytes32) wrappedTokenToAttestationId;
function bridgeTokens(
address _token, // Token contract address (for deducting tokens)
uint256 _amount, // Amount
uint256 _dstChain,
address _dstAddress
) external {}
// Corresponding event definition
event TokensBridged(
bytes32 indexed transferID, // Transaction ID as per rule
TokenType indexed tokenType // Type
);
emit TokensBridged(_transferID, TokenType.Fungible);
// After the relay listens to the event, it processes the _transferID information,
// For the destination chain ID's token address, perform minting ==> ReleaseWrappedTokens()
Token Mint (Executed by Relay)
Contract mints the token
function releaseWrappedTokens(
uint256 _amount, // Amount
address _to, // Destination address
bytes32 _attestationID // Registered token ID
)
event WrappedTokensReleased(
uint256 indexed amount,
address indexed to,
bytes32 indexed attestationID
);
emit WrappedTokensReleased(_amount, _to, _attestationID);
//
function bridgeTokensBack(
uint256 _amount, // Amount
address _to, // Destination address
bytes32 _attestationID // Provisional token registration ID
) external {}
event TokensBridgedBack(
uint256 indexed amount,
address indexed to,
bytes32 indexed attestationID
);
emit TokensBridgedBack(_amount, _to, _attestationID);
// After the relay listens to the event, it processes the _transferID information,
// For the destination chain ID's token address, perform release ==> ReleaseTokens()
Release (Executed by Relay)
Releases tokens, executed by the relay
function releaseTokens(
uint256 _amount,
address _to,
address _token
)
event TokensReleased(
uint256 indexed amount,
address indexed to,
address indexed token
);
emit TokensReleased(_amount, _to, _token);
Contract destroys the token
function bridgeTokensBack(
uint256 _amount, // Amount
address _to, //
bytes32 _attestationID // Registered token ID
)
event WrappedTokensReleased(
uint256 indexed amount,
address indexed to,
bytes32 indexed attestationID
);
emit TokensBridgedBack(_amount, _to, _attestationID);
attestToken for creating trading pairs
Executed by the relay, creating operation
function attestToken(
TokenAttestation memory attestation
) external onlyRelayer {}
/**
@dev Stores information about Chain A tokens on Chain B.
@param tokenAddress Address of the token on Chain A
@param tokenChain Chain ID of Chain A
@param tokenType Whether the token is fungible/non-fungible
@param decimals Only applicable to fungible tokens. Number of decimal places.
@param symbol Token symbol
@param name Token name
@param wrappedTokenAddress Address of the token deployed on Chain B
*/
struct TokenAttestation {
address tokenAddress;
uint256 tokenChain;
TokenType tokenType;
uint8 decimals;
string symbol;
string name;
address wrappedTokenAddress;
}
// Token ID => Information
mapping(bytes32 => TokenAttestation) public attestedTokens;
// Token address + chainID => Registered token ID
bytes32 attestationID = keccak256(
abi.encodePacked(attestation.tokenAddress, attestation.tokenChain)
);
// For easy querying if already created
function isTokenSupported(
address _tokenAddress, // Contract address
uint256 _tokenChain // Chain ID
) external view returns (bool) {}
TokenFactory for minting and deploying contract code
I've translated and replaced the Chinese text with corresponding English terms and comments to maintain the technical context of the document.