Links

CrossChainBridgeRouter

This contract is our one-stop-shop for accessing all functionality of the cross-chain bridge. It can be used to integrate our bridging and investing functionality into your smart contract or dApp.
We are currently testing this contract. At the moment it is only deployed to BSC testnet. Once we have concluded our testing phase, we will roll out the router contract to all other connected networks.

Functions

addLiquidityERC20

Adds liquidity to the ERC20 bridge
function addLiquidityERC20(IERC20 token, uint256 amount) external payable override whenNotPaused {
// check bridgeERC20 token balance before deposit
uint256 balanceBefore = token.balanceOf(address(bridgeERC20));
// Transfer token amount from sender to bridgeERC20
token.safeTransferFrom(_msgSender(), address(bridgeERC20), amount);
// check if bridgeERC20 token balance has increased by amount (>> effectively preventing deflationary tokens to be added for now)
if (token.balanceOf(address(bridgeERC20)) != balanceBefore + amount) revert OperationFailed();
// call liquidityManager contract to emit event
ICrossChainBridgeERC20LiquidityManager(liquidityManager).addLiquidityERC20(_msgSender(), token, amount);
}

Parameters:

Name
Type
Description
token
IERC20
the address of the token for which liquidity should be added
amount
uint256
the amount of tokens to be added

addLiquidityNative

Adds native liquidity to the ERC20 bridge
function addLiquidityNative(uint256 amount) external payable override whenNotPaused {
ICrossChainBridgeERC20LiquidityManager(liquidityManager).addLiquidityNative{value: msg.value}(_msgSender(), amount);
}

Parameters:

Name
Type
Description
amount
uint256
the amount of native tokens to be added

depositERC20TokensToBridge

Accepts ERC20 token deposits that should be bridged into another network (effectively starting a new bridge transaction)
function depositERC20TokensToBridge(
IERC20 token,
uint256 amount,
address receiverAddress,
uint256 targetChainId
) external payable override whenNotPaused {
// check token balance before deposit
uint256 balanceBefore = token.balanceOf(bridgeERC20);
// Transfer to-be-deposited tokens from sender to this smart contract
token.safeTransferFrom(_msgSender(), bridgeERC20, amount);
// check if token balance has increased by amount (>> effectively preventing deflationary tokens to be added for now)
if (token.balanceOf(bridgeERC20) != balanceBefore + amount) revert OperationFailed();
// call deposit function in bridgeERC20 contract
ICrossChainBridgeERC20(bridgeERC20).depositERC20(token, amount, receiverAddress, targetChainId);
}

Parameters:

Name
Type
Description
token
IERC20
the ERC20 token that should be deposited
amount
uint256
the amount to be deposited
receiverAddress
address
the address which should receive the bridged funds in the target network
targetChainId
uint256
chain ID of the target network

depositERC721TokenToBridge

Accepts ERC721 deposits that should be bridged into another network (effectively starting a bridge transaction). The collection must be whitelisted in order to be accepted for a deposit.
function depositERC721TokenToBridge(
address collectionAddress,
uint256 tokenId,
address receiverAddress,
uint256 targetChainId
) external payable override whenNotPaused {
// check if token was minted from an original collection or minted by this bridge
if (ICrossChainBridgeERC721(bridgeERC721).mintedDeposits(collectionAddress, tokenId)) {
// no whitelist check necessary since token was minted by this bridge
//TODO: to check > will it be a problem that the router will have mint/burn permission instead of the bridges?
//TODO: @CHRIS: pls comment
MintableERC721(collectionAddress).burn(tokenId);
} else {
if (!ICrossChainBridgeERC721(bridgeERC721).officialCollectionWhitelist(collectionAddress)) revert Unauthorized();
// transfer the token into the bridge
IERC721Upgradeable(collectionAddress).safeTransferFrom(_msgSender(), address(bridgeERC721), tokenId);
}
// call bridgeERC721 contract to emit event
ICrossChainBridgeERC721(bridgeERC721).depositERC721(collectionAddress, tokenId, receiverAddress, targetChainId);
}

Parameters:

Name
Type
Description
collectionAddress
address
the address of the ERC721 contract the collection was issued with
tokenId
uint256
the (native) ID of the ERC721 token that should be bridged
receiverAddress
address
the address which should receive the bridged token in the target network
targetChainId
uint256
chain ID of the target network

depositNativeTokensToBridge

Accepts native token deposits that should be bridged into another network (effectively starting a new bridge transaction)
function depositNativeTokensToBridge(
uint256 amount,
address receiverAddress,
uint256 targetChainId
) external payable override whenNotPaused {
ICrossChainBridgeERC20(bridgeERC20).depositNative{value: msg.value}(amount, receiverAddress, targetChainId);
}

Parameters:

Name
Type
Description
amount
uint256
the amount to be deposited
receiverAddress
address
the address which should receive the bridged funds in the target network
targetChainId
uint256
chain ID of the target network

getChainID

Returns the ID of the network this contract is deployed in
function getChainID() external view override returns (uint256) {
uint256 id;
assembly {
id := chainid()
}
return id;
}

Return value:

Type
Description
uint256
chainId of the current network

getERC20BridgeFeeQuote

Returns the estimated bridging fee for a specific ERC20 token and amount
function getERC20BridgeFeeQuote(address tokenAddress, uint256 amountToBeBridged)
external
view
override
returns (uint256 bridgeFee)
{
uint256 customBridgeFee = ICrossChainBridgeERC20(bridgeERC20).bridgeFees(tokenAddress);
uint256 relativeBridgeFee = customBridgeFee > 0
? customBridgeFee
: ICrossChainBridgeERC20(bridgeERC20).defaultBridgeFee();
return (amountToBeBridged * relativeBridgeFee) / PPM_DIVISOR;
}

Parameters:

Name
Type
Description
tokenAddress
address
the address of the token that should be bridged
amountToBeBridged
uint256
the amount to be bridged

Return value:

Name
Type
Description
bridgeFee
uint256
the estimated bridging fee (in ERC20 tokens)

getERC721BridgeFeeQuote

Returns the estimated bridge fee in native currency (e.g. ETH, BSC, MATIC, AVAX, FTM) for bridging one token of a specific ERC721 collection
function getERC721BridgeFeeQuote(address collectionAddress) external view override returns (uint256 bridgeFee) {
uint256 customBridgeFee = ICrossChainBridgeERC721(bridgeERC721).bridgeFees(collectionAddress);
return customBridgeFee > 0 ? customBridgeFee : ICrossChainBridgeERC721(bridgeERC721).defaultBridgeFee();
}

Parameters:

Name
Type
Description
collectionAddress
address
the address of the collection

Return value:

Name
Type
Description
bridgeFee
uint256
the estimated bridging fee (in native tokens)

getLiquidityWithdrawalFeeAmount

Returns the liquidity withdrawal fee amount for the given ERC20 token and amount
function getLiquidityWithdrawalFeeAmount(IERC20 token, uint256 withdrawalAmount)
public
view
override
returns (uint256)
{
return
ICrossChainBridgeERC20LiquidityManager(liquidityManager).getLiquidityWithdrawalFeeAmount(
address(token),
withdrawalAmount
);
}

Parameters:

Name
Type
Description
token
IERC20
the address of the ERC20 token in which liquidity was provided
withdrawalAmount
uint256
the amount of tokens to be withdrawn

getLPToken

Returns the address of the LP token for a given ERC20 token address
function getLPToken(address tokenAddress) public view override returns (address) {
(bool exists, IERC20 lpToken) = ICrossChainBridgeERC20LiquidityManager(liquidityManager).lpTokens(tokenAddress);
return exists ? address(lpToken) : address(0);
}

Parameters:

Name
Type
Description
tokenAddress
address
the address of token for which the LP token should be returned

Return value:

Type
Description
address
the address of the LP token contract

harvestFromMiningPool

Harvests BRIDGE rewards from the given LiquidityMiningPool and sends them to the staker address
function harvestFromMiningPool(address tokenAddress, address stakerAddress) external payable override whenNotPaused {
IPools(liquidityMiningPools).harvest(tokenAddress, stakerAddress);
}

Parameters:

Name
Type
Description
token
address
the address of the underlying token of the pool
stakerAddress
address
the address of the staker for which rewards should be harvested

harvestFromRewardPool

Harvests staking rewards from the given RewardPool and sends them to the staker address
function harvestFromRewardPool(address tokenAddress, address stakerAddress) external payable override whenNotPaused {
IRewardPools(rewardPools).harvest(tokenAddress, stakerAddress);
}

Parameters:

Name
Type
Description
tokenAddress
address
the address of the underlying token of the pool
stakerAddress
address
the address of the staker for which rewards should be harvested

Parameters:

Name
Type
Descriptions
farmId
uint256
The ID of the farm
user
address
the address of the user

Return value:

Type
Description
uint256
the unharvested reward amount in BRIDGE tokens

pendingMiningPoolRewards

Returns the amount of tokens that are ready for harvesting for the given user and LiquidityMiningPool
function pendingMiningPoolRewards(address tokenAddress, address stakerAddress)
external
view
override
returns (uint256)
{
return IPools(liquidityMiningPools).pendingReward(tokenAddress, stakerAddress);
}

Parameters:

Name
Type
Description
tokenAddress
address
the address of the underlying token of the pool
stakerAddress
address
the address of the staker for which rewards should be harvested

Return value:

Type
Description
uint256
the unharvested reward amount in ERC20 tokens

pendingRewardPoolRewards

Returns the amount of tokens that are ready for harvesting for the given user and RewardPool
function pendingRewardPoolRewards(address tokenAddress, address stakerAddress)
external
view
override
returns (uint256)
{
return IRewardPools(rewardPools).pendingReward(tokenAddress, stakerAddress);
}

Parameters:

Name
Type
Description
tokenAddress
address
the address of the underlying token of the reward pool
stakerAddress
address
the address of the staker for which pending rewards should be returned

Return value:

Type
Description
uint256
the unharvested reward amount

releaseERC20TokenBridgeDeposit

Releases ERC20 tokens in this network if a valid deposit was made in another network (effectively completing a bridge transaction)
function releaseERC20TokenBridgeDeposit(
uint8[] memory sigV,
bytes32[] memory sigR,
bytes32[] memory sigS,
address receiverAddress,
address sourceNetworkTokenAddress,
uint256 amount,
uint256 depositChainId,
uint256 depositNumber
) external payable override whenNotPaused {
ICrossChainBridgeERC20(bridgeERC20).releaseERC20(
sigV,
sigR,
sigS,
receiverAddress,
sourceNetworkTokenAddress,
amount,
depositChainId,
depositNumber
);
}

Parameters:

Name
Type
Description
sigV
uint8
Array of recovery Ids for the signature
sigR
bytes32
Array of R values of the signatures
sigS
bytes32
Array of S values of the signatures
receiverAddress
address
the address which should receive the bridged funds in this network
sourceNetworkTokenAddress
address
the address of the ERC20 contract in the network the deposit was made
amount
uint256
The amount of tokens to be released
depositChainId
uint256
chain ID of the network in which the deposit was made
depositNumber
uint256
The deposit ID of the corresponding deposit

releaseERC721TokenDeposit

Releases an ERC721 token in this network after a deposit was made in the source network (effectively completing a bridge transaction)
function releaseERC721TokenDeposit(
uint8[] memory sigV,
bytes32[] memory sigR,
bytes32[] memory sigS,
address receiverAddress,
address sourceNetworkCollectionAddress,
uint256 tokenId,
uint256 depositChainId,
uint256 depositNumber
) external payable override whenNotPaused {
ICrossChainBridgeERC721(bridgeERC721).releaseERC721{value: msg.value}(
sigV,
sigR,
sigS,
receiverAddress,
sourceNetworkCollectionAddress,
tokenId,
depositChainId,
depositNumber
);
}

Parameters:

Name
Type
Description
sigV
uint8
Array of recovery Ids for the signature
sigR
bytes32
Array of R values of the signatures
sigS
bytes32
Array of S values of the signatures
receiverAddress
address
the address to which the bridged token should be released to
sourceNetworkAddress
address
the address of the ERC721 collection in the network the deposit was made
tokenId
uint256
The token id to be sent
depositChainId
uint256
chain ID of the network in which the deposit was made
depositNumber
uint256
The deposit ID of the corresponding deposit

releaseNativeTokenBridgeDeposit

Releases native tokens in this network that were deposited in another network (effectively completing a bridge transaction)
function releaseNativeTokenBridgeDeposit(
uint8[] memory sigV,
bytes32[] memory sigR,
bytes32[] memory sigS,
address receiverAddress,
address sourceNetworkTokenAddress,
uint256 amount,
uint256 depositChainId,
uint256 depositNumber
) external payable override whenNotPaused {
ICrossChainBridgeERC20(bridgeERC20).releaseNative(
sigV,
sigR,
sigS,
receiverAddress,
sourceNetworkTokenAddress,
amount,
depositChainId,
depositNumber
);
}

Parameters:

Name
Type
Description
sigV
uint8
Array of recovery Ids for the signature
sigR
bytes32
Array of R values of the signatures
sigS
bytes32
Array of S values of the signatures
receiverAddress
address
the address to which the bridged token should be released to
sourceNetworkTokenAddress
address
the address of the ERC20 contract in the network the deposit was made
amount
uint256
The amount of tokens to be released
depositChainId
uint256
chain ID of the network in which the deposit was made
depositNumber
uint256
The deposit ID of the corresponding deposit

rewardPoolWithdrawalFee

Returns the token-specific RewardPool withdrawal fee in parts per million (ppm)
function rewardPoolWithdrawalFee(address tokenAddress) external view override returns (uint256) {
uint256 customFee = IRewardPools(rewardPools).rewardPoolWithdrawalFees(tokenAddress);
return customFee > 0 ? customFee : IRewardPools(rewardPools).defaultRewardPoolWithdrawalFee();
}

Parameters:

Name
Type
Description
tokenAddress
address
the address of the underlying token of the reward pool

Return value:

Type
Description
uint256
the withdrawal fee in ppm

stakeBRIDGEInRewardPool

Stakes BRIDGE tokens in the given RewardPool
function stakeBRIDGEInRewardPool(address tokenAddress, uint256 amount) external payable override whenNotPaused {
// call rewardPools contract to update stake info and emit event
IRewardPools(rewardPools).stake(_msgSender(), tokenAddress, amount);
// transfer to-be-staked funds from user to this smart contract (must be done after rewardPools call)
IBridgeChef(bridgeChef).bridgeToken().safeTransferFrom(_msgSender(), address(rewardPools), amount);
}

Parameters:

Name
Type
Description
tokenAddress
address
the address of the underlying token of the reward pool
amount
uint256
the amount of bridge tokens that should be staked

stakeLpTokensInMiningPool

Stakes liquidity provider (LP) tokens in the given LiquidityMiningPool for the user to start earning from bridge fees of the given ERC20 token
function stakeLpTokensInMiningPool(address tokenAddress, uint256 amount) external payable override whenNotPaused {
// call liquidityMiningPools contract and update stake information (must be done before token transfer)
IPools(liquidityMiningPools).stake(_msgSender(), tokenAddress, amount);
// transfer to-be-staked funds from user to this smart contract
IERC20(getLPToken(tokenAddress)).safeTransferFrom(_msgSender(), address(liquidityMiningPools), amount);
}

Parameters:

Name
Type
Description
tokenAddress
address
the address of the underlying token of the pool
amount
uint256
the amount of LP tokens that should be staked

unstakeBRIDGEFromRewardPool

Unstakes BRIDGE tokens from the given RewardPool
function unstakeBRIDGEFromRewardPool(address tokenAddress, uint256 amount) external payable override whenNotPaused {
// no approval required for unstaking BRIDGE tokens
IRewardPools(rewardPools).unstake(_msgSender(), tokenAddress, amount);
}

Parameters:

Name
Type
Description
tokenAddress
address
the address of the underlying token of the reward pool
amount
uint256
the amount of bridge tokens that should be unstaked

unstakeLpTokensFromMiningPool

Unstakes LP tokens from the given LiquidityMiningPool after harvesting pending rewards
function unstakeLpTokensFromMiningPool(address tokenAddress, uint256 amount) external payable override whenNotPaused {
// no approval needed to burn poolsInterestBearingToken, thus transfer happens in liquidityMiningPools contract
IPools(liquidityMiningPools).unstake(_msgSender(), tokenAddress, amount);
}

Parameters:

Name
Type
Description
tokenAddress
address
the address of the underlying token of the liquidity mining pool
amount
uint256
the amount of LP tokens that should be unstaked

withdrawLiquidityERC20

Burns LP tokens and removes previously provided liquidity from the ERC20 bridge
function withdrawLiquidityERC20(IERC20 token, uint256 amount) external payable override whenNotPaused {
// burn LP token in the amount of liquidity that should be removed
ERC20Burnable(getLPToken(address(token))).burnFrom(_msgSender(), amount);
// call liquidityManager contract to emit event and transfer liquidity
ICrossChainBridgeERC20LiquidityManager(liquidityManager).withdrawLiquidityERC20(_msgSender(), token, amount);
}

Parameters:

Name
Type
Description
token
IERC20
the token for which liquidity should be removed from this pool
amount
uint256
the amount of tokens to be withdrawn

withdrawLiquidityInAnotherNetwork

Burns LP tokens and creates a bridge deposit in the amount of "burnedLPtokens - liquidity withdrawal fee". This function was introduced to allow liquidity withdrawals even if a network's current liquidity is insufficient for a withdrawal.
function withdrawLiquidityInAnotherNetwork(
IERC20 token,
uint256 amount,
address receiverAddress,
uint256 targetChainId
) external payable override whenNotPaused {
// check if withdrawal fee applies and send LP tokens to devAddress
uint256 feeAmount = getLiquidityWithdrawalFeeAmount(token, amount);
uint256 depositAmount = amount;
if (feeAmount > 0) {
// get LP token and transfer amount of withdrawal fee to dev account
IERC20(getLPToken(address(token))).safeTransferFrom(
_msgSender(),
ICrossChainBridgeERC20LiquidityManager(liquidityManager).devAddr(),
getLiquidityWithdrawalFeeAmount(token, amount)
);
depositAmount = amount - feeAmount;
}
// burn LP tokens from user in full amount
ERC20Burnable(getLPToken(address(token))).burnFrom(_msgSender(), depositAmount);
// call bridgeERC20 to make deposit and create event
ICrossChainBridgeERC20(bridgeERC20).createDepositAndLiquidityRemovedEvent(
token,
depositAmount,
amount,
receiverAddress,
targetChainId
);
}

Parameters:

Name
Type
Description
token
IERC20
the ERC20 token in which liquidity was provided
amount
uint256
the amount to be withdrawn
receiverAddress
address
the address which should receive the bridged funds in the target network
targetChainId
uint256
chain ID of the target network

withdrawLiquidityNative

Removes native liquidity from a liquidity pool
function withdrawLiquidityNative(uint256 amount) external payable override whenNotPaused {
// burn LP token in the amount of liquidity that should be removed
ERC20Burnable(getLPToken(wrappedNative())).burnFrom(_msgSender(), amount);
// call liquidityManager contract to emit event and transfer liquidity
ICrossChainBridgeERC20LiquidityManager(liquidityManager).withdrawLiquidityNative(_msgSender(), amount);
}

Parameters:

Name
Type
Description
amount
uint256
the amount of native tokens to be removed

wrappedNative

Returns the wrapped native token contract address that is used in the deployed network. Example: in Ethereum the native currency is ETH and the wrapped native token is WETH.
function wrappedNative() public view override returns (address) {
return address(ICrossChainBridgeERC20(bridgeERC20).wrappedNative());
}

Return value:

Type
Description
address
the address of the wrapped native ERC20 token contract in this network