The WebGlideBridge only moves tokens from one wallet (which might be the user themself) to another wallet on a different chain. No target contract is required because there is no calldata involved.
In this example,Bridge has two functions:
WebGTransfer bridges any BEP20 token
Before the token can be spent on the Bridge contract, the user must authorise it.
RelayerFee is paid in native BNB, hence msg.value MUST be given in equal to the specified relayerFee when WebGTransfer is called. On the page titled "Estimating Fees," information is provided for computing relayer costs.
The flow is a little bit different while sending and receiving native BNB. Since WebGlide doesn't allow native BNB as the bridging asset, BNB must first be wrapped into WBNB on the origin domain before being unwrapped and converted back to BNB at the destination.
When sending BNB, msg.value = relayerFee + amount. See example below (note: in Bscscan, the payable field is in bnb while the other fields are specified in wei).
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.15;
import {IWebGlide} from "@WebGlide/interfaces/core/IWebGlide.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IWETH {
function deposit() external payable;
function approve(address guy, uint wad) external returns (bool);
}
/**
* @title WebGBridge
* @notice Example of a cross-domain token transfer.
*/
contract WebGBridge {
// The WebGlide contract on the origin domain
IWebglide public immutable webglide;
constructor(address _webglide) {
webglide = IWebglide(_webglide);
}
/**
* @notice Transfers non-native assets from one chain to another.
* @dev User should approve a spending allowance before calling this.
* @param token Address of the token on this domain.
* @param amount The amount to transfer.
* @param recipient The destination address (e.g. a wallet).
* @param destinationDomain The destination domain ID.
* @param slippage The maximum amount of slippage the user will accept in BPS.
* @param relayerFee The fee offered to relayers.
*/
function WebGTransfer(
address token,
uint256 amount,
address recipient,
uint32 destinationDomain,
uint256 slippage,
uint256 relayerFee
) external payable {
IERC20 _token = IERC20(token);
require(
_token.allowance(msg.sender, address(this)) >= amount,
"User must approve amount"
);
// User sends funds to this contract
_token.transferFrom(msg.sender, address(this), amount);
// This contract approves transfer to WebGlide
_token.approve(address(WebGlide), amount);
WebGlide.WebGcall{value: relayerFee}(
destinationDomain, // _destination: Domain ID of the destination chain
recipient, // _to: address receiving the funds on the destination
token, // _asset: address of the token contract
msg.sender, // _delegate: address that can revert or forceLocal on destination
amount, // _amount: amount of tokens to transfer
slippage, // _slippage: the maximum amount of slippage the user will accept in BPS (e.g. 30 = 0.3%)
bytes("") // _callData: empty bytes because we're only sending funds
);
}
/**
* @notice Transfers native assets from one chain to another.
* @param destinationUnwrapper Address of the Unwrapper contract on destination.
* @param weth Address of the WETH contract on this domain.
* @param amount The amount to transfer.
* @param recipient The destination address (e.g. a wallet).
* @param destinationDomain The destination domain ID.
* @param slippage The maximum amount of slippage the user will accept in BPS.
* @param relayerFee The fee offered to relayers.
*/
function WebGTransferEth(
address destinationUnwrapper,
address weth,
uint256 amount,
address recipient,
uint32 destinationDomain,
uint256 slippage,
uint256 relayerFee
) external payable {
// Wrap ETH into WETH to send with the WebGcall
IWETH(weth).deposit{value: amount}();
// This contract approves transfer to WebGlide
IWETH(weth).approve(address(WebGlide), amount);
// Encode the recipient address for calldata
bytes memory callData = abi.encode(recipient);
// WebGcall the Unwrapper contract to unwrap WETH into ETH on destination
WebGlide.WebGcall{value: relayerFee}(
destinationDomain, // _destination: Domain ID of the destination chain
destinationUnwrapper, // _to: Unwrapper contract
weth, // _asset: address of the WETH contract
msg.sender, // _delegate: address that can revert or forceLocal on destination
amount, // _amount: amount of tokens to transfer
slippage, // _slippage: the maximum amount of slippage the user will accept in BPS (e.g. 30 = 0.3%)
callData // _callData: calldata with encoded recipient address
);
}
}