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
1
function addLiquidityERC20(IERC20 token, uint256 amount) external payable override whenNotPaused {
2
// check bridgeERC20 token balance before deposit
3
uint256 balanceBefore = token.balanceOf(address(bridgeERC20));
4
5
// Transfer token amount from sender to bridgeERC20
6
token.safeTransferFrom(_msgSender(), address(bridgeERC20), amount);
7
8
// check if bridgeERC20 token balance has increased by amount (>> effectively preventing deflationary tokens to be added for now)
9
if (token.balanceOf(address(bridgeERC20)) != balanceBefore + amount) revert OperationFailed();
10
11
// call liquidityManager contract to emit event
12
ICrossChainBridgeERC20LiquidityManager(liquidityManager).addLiquidityERC20(_msgSender(), token, amount);
13
}
Copied!

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
1
function addLiquidityNative(uint256 amount) external payable override whenNotPaused {
2
ICrossChainBridgeERC20LiquidityManager(liquidityManager).addLiquidityNative{value: msg.value}(_msgSender(), amount);
3
}
Copied!

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)
1
function depositERC20TokensToBridge(
2
IERC20 token,
3
uint256 amount,
4
address receiverAddress,
5
uint256 targetChainId
6
) external payable override whenNotPaused {
7
// check token balance before deposit
8
uint256 balanceBefore = token.balanceOf(bridgeERC20);
9
10
// Transfer to-be-deposited tokens from sender to this smart contract
11
token.safeTransferFrom(_msgSender(), bridgeERC20, amount);
12
13
// check if token balance has increased by amount (>> effectively preventing deflationary tokens to be added for now)
14
if (token.balanceOf(bridgeERC20) != balanceBefore + amount) revert OperationFailed();
15
16
// call deposit function in bridgeERC20 contract
17
ICrossChainBridgeERC20(bridgeERC20).depositERC20(token, amount, receiverAddress, targetChainId);
18
}
Copied!

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.
1
function depositERC721TokenToBridge(
2
address collectionAddress,
3
uint256 tokenId,
4
address receiverAddress,
5
uint256 targetChainId
6
) external payable override whenNotPaused {
7
// check if token was minted from an original collection or minted by this bridge
8
if (ICrossChainBridgeERC721(bridgeERC721).mintedDeposits(collectionAddress, tokenId)) {
9
// no whitelist check necessary since token was minted by this bridge
10
//TODO: to check > will it be a problem that the router will have mint/burn permission instead of the bridges?
11
//TODO: @CHRIS: pls comment
12
MintableERC721(collectionAddress).burn(tokenId);
13
} else {
14
if (!ICrossChainBridgeERC721(bridgeERC721).officialCollectionWhitelist(collectionAddress)) revert Unauthorized();
15
16
// transfer the token into the bridge
17
IERC721Upgradeable(collectionAddress).safeTransferFrom(_msgSender(), address(bridgeERC721), tokenId);
18
}
19
20
// call bridgeERC721 contract to emit event
21
ICrossChainBridgeERC721(bridgeERC721).depositERC721(collectionAddress, tokenId, receiverAddress, targetChainId);
22
}
Copied!

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)
1
function depositNativeTokensToBridge(
2
uint256 amount,
3
address receiverAddress,
4
uint256 targetChainId
5
) external payable override whenNotPaused {
6
ICrossChainBridgeERC20(bridgeERC20).depositNative{value: msg.value}(amount, receiverAddress, targetChainId);
7
}
Copied!

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
1
function getChainID() external view override returns (uint256) {
2
uint256 id;
3
assembly {
4
id := chainid()
5
}
6
return id;
7
}
Copied!

Return value:

Type
Description
uint256
chainId of the current network

getERC20BridgeFeeQuote

Returns the estimated bridging fee for a specific ERC20 token and amount
1
function getERC20BridgeFeeQuote(address tokenAddress, uint256 amountToBeBridged)
2
external
3
view
4
override
5
returns (uint256 bridgeFee)
6
{
7
uint256 customBridgeFee = ICrossChainBridgeERC20(bridgeERC20).bridgeFees(tokenAddress);
8
uint256 relativeBridgeFee = customBridgeFee > 0
9
? customBridgeFee
10
: ICrossChainBridgeERC20(bridgeERC20).defaultBridgeFee();
11
return (amountToBeBridged * relativeBridgeFee) / PPM_DIVISOR;
12
}
Copied!

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
1
function getERC721BridgeFeeQuote(address collectionAddress) external view override returns (uint256 bridgeFee) {
2
uint256 customBridgeFee = ICrossChainBridgeERC721(bridgeERC721).bridgeFees(collectionAddress);
3
return customBridgeFee > 0 ? customBridgeFee : ICrossChainBridgeERC721(bridgeERC721).defaultBridgeFee();
4
}
Copied!

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
1
function getLiquidityWithdrawalFeeAmount(IERC20 token, uint256 withdrawalAmount)
2
public
3
view
4
override
5
returns (uint256)
6
{
7
return
8
ICrossChainBridgeERC20LiquidityManager(liquidityManager).getLiquidityWithdrawalFeeAmount(
9
address(token),
10
withdrawalAmount
11
);
12
}
Copied!

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
1
function getLPToken(address tokenAddress) public view override returns (address) {
2
(bool exists, IERC20 lpToken) = ICrossChainBridgeERC20LiquidityManager(liquidityManager).lpTokens(tokenAddress);
3
return exists ? address(lpToken) : address(0);
4
}
Copied!

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

harvestFarmRewards

Harvests BRIDGE rewards from the given farm and sends them to the caller of this function
1
function harvestFarmRewards(uint256 farmId) external payable override whenNotPaused {
2
IBridgeChef(bridgeChef).harvest(_msgSender(), farmId);
3
}
Copied!

Parameters:

Name
Type
Description
farmId
uint256
the ID of the farm for which rewards should be harvested

harvestFromMiningPool

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

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
1
function harvestFromRewardPool(address tokenAddress, address stakerAddress) external payable override whenNotPaused {
2
IRewardPools(rewardPools).harvest(tokenAddress, stakerAddress);
3
}
Copied!

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

pendingFarmRewards

Returns the amount of BRIDGE tokens that are ready for harvesting for the given user and farm
1
function pendingFarmRewards(uint256 farmId, address user) external view override returns (uint256) {
2
return IBridgeChef(bridgeChef).bridgeTokensReadyToHarvest(farmId, user);
3
}
Copied!

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
1
function pendingMiningPoolRewards(address tokenAddress, address stakerAddress)
2
external
3
view
4
override
5
returns (uint256)
6
{
7
return IPools(liquidityMiningPools).pendingReward(tokenAddress, stakerAddress);
8
}
Copied!

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
1
function pendingRewardPoolRewards(address tokenAddress, address stakerAddress)
2
external
3
view
4
override
5
returns (uint256)
6
{
7
return IRewardPools(rewardPools).pendingReward(tokenAddress, stakerAddress);
8
}
Copied!

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)
1
function releaseERC20TokenBridgeDeposit(
2
uint8[] memory sigV,
3
bytes32[] memory sigR,
4
bytes32[] memory sigS,
5
address receiverAddress,
6
address sourceNetworkTokenAddress,
7
uint256 amount,
8
uint256 depositChainId,
9
uint256 depositNumber
10
) external payable override whenNotPaused {
11
ICrossChainBridgeERC20(bridgeERC20).releaseERC20(
12
sigV,
13
sigR,
14
sigS,
15
receiverAddress,
16
sourceNetworkTokenAddress,
17
amount,
18
depositChainId,
19
depositNumber
20
);
21
}
Copied!

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)
1
function releaseERC721TokenDeposit(
2
uint8[] memory sigV,
3
bytes32[] memory sigR,
4
bytes32[] memory sigS,
5
address receiverAddress,
6
address sourceNetworkCollectionAddress,
7
uint256 tokenId,
8
uint256 depositChainId,
9
uint256 depositNumber
10
) external payable override whenNotPaused {
11
ICrossChainBridgeERC721(bridgeERC721).releaseERC721{value: msg.value}(
12
sigV,
13
sigR,
14
sigS,
15
receiverAddress,
16
sourceNetworkCollectionAddress,
17
tokenId,
18
depositChainId,
19
depositNumber
20
);
21
}
Copied!

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)
1
function releaseNativeTokenBridgeDeposit(
2
uint8[] memory sigV,
3
bytes32[] memory sigR,
4
bytes32[] memory sigS,
5
address receiverAddress,
6
address sourceNetworkTokenAddress,
7
uint256 amount,
8
uint256 depositChainId,
9
uint256 depositNumber
10
) external payable override whenNotPaused {
11
ICrossChainBridgeERC20(bridgeERC20).releaseNative(
12
sigV,
13
sigR,
14
sigS,
15
receiverAddress,
16
sourceNetworkTokenAddress,
17
amount,
18
depositChainId,
19
depositNumber
20
);
21
}
Copied!

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)
1
function rewardPoolWithdrawalFee(address tokenAddress) external view override returns (uint256) {
2
uint256 customFee = IRewardPools(rewardPools).rewardPoolWithdrawalFees(tokenAddress);
3
return customFee > 0 ? customFee : IRewardPools(rewardPools).defaultRewardPoolWithdrawalFee();
4
}
Copied!

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
1
function stakeBRIDGEInRewardPool(address tokenAddress, uint256 amount) external payable override whenNotPaused {
2
// call rewardPools contract to update stake info and emit event
3
IRewardPools(rewardPools).stake(_msgSender(), tokenAddress, amount);
4
5
// transfer to-be-staked funds from user to this smart contract (must be done after rewardPools call)
6
IBridgeChef(bridgeChef).bridgeToken().safeTransferFrom(_msgSender(), address(rewardPools), amount);
7
}
8
Copied!

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

stakeLpTokensInFarm

Stakes liquidity provider (LP) tokens in the given farm for the user to start earning BRIDGE tokens
1
function stakeLpTokensInFarm(uint256 farmId, uint256 amount) external payable override whenNotPaused {
2
// call BridgeChef to update stake info and emit event
3
IBridgeChef(bridgeChef).deposit(_msgSender(), farmId, amount);
4
5
// transfer LP tokens from user to this smart contract (must be done after bridgeChef call
6
(, , , address lpToken) = IBridgeChef(bridgeChef).farmInfo(farmId);
7
IERC20(lpToken).safeTransferFrom(_msgSender(), address(bridgeChef), amount);
8
}
Copied!

Parameters:

Name
Type
Description
farmId
uint256
The ID of the farm
amount
uint256
the amount of LP tokens to be deposited

stakeLpTokensInMiningPool

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

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
1
function unstakeBRIDGEFromRewardPool(address tokenAddress, uint256 amount) external payable override whenNotPaused {
2
// no approval required for unstaking BRIDGE tokens
3
IRewardPools(rewardPools).unstake(_msgSender(), tokenAddress, amount);
4
}
Copied!

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

unstakeLpTokensFromFarm

Unstakes liquidity provider (LP) tokens from the given farm
1
function unstakeLpTokensFromFarm(uint256 farmId, uint256 amount) external payable override whenNotPaused {
2
// no approval required for unstaking LP tokens
3
IBridgeChef(bridgeChef).withdraw(_msgSender(), farmId, amount);
4
}
Copied!

Parameters:

Name
Type
Description
farmId
uint256
the ID of the farm
amount
uint256
the amount to be withdrawn

unstakeLpTokensFromMiningPool

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

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
1
function withdrawLiquidityERC20(IERC20 token, uint256 amount) external payable override whenNotPaused {
2
// burn LP token in the amount of liquidity that should be removed
3
ERC20Burnable(getLPToken(address(token))).burnFrom(_msgSender(), amount);
4
5
// call liquidityManager contract to emit event and transfer liquidity
6
ICrossChainBridgeERC20LiquidityManager(liquidityManager).withdrawLiquidityERC20(_msgSender(), token, amount);
7
}
8
Copied!

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.
1
function withdrawLiquidityInAnotherNetwork(
2
IERC20 token,
3
uint256 amount,
4
address receiverAddress,
5
uint256 targetChainId
6
) external payable override whenNotPaused {
7
// check if withdrawal fee applies and send LP tokens to devAddress
8
uint256 feeAmount = getLiquidityWithdrawalFeeAmount(token, amount);
9
uint256 depositAmount = amount;
10
if (feeAmount > 0) {
11
// get LP token and transfer amount of withdrawal fee to dev account
12
IERC20(getLPToken(address(token))).safeTransferFrom(
13
_msgSender(),
14
ICrossChainBridgeERC20LiquidityManager(liquidityManager).devAddr(),
15
getLiquidityWithdrawalFeeAmount(token, amount)
16
);
17
depositAmount = amount - feeAmount;
18
}
19
// burn LP tokens from user in full amount
20
ERC20Burnable(getLPToken(address(token))).burnFrom(_msgSender(), depositAmount);
21
22
// call bridgeERC20 to make deposit and create event
23
ICrossChainBridgeERC20(bridgeERC20).createDepositAndLiquidityRemovedEvent(
24
token,
25
depositAmount,
26
amount,
27
receiverAddress,
28
targetChainId
29
);
30
}
Copied!

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
1
function withdrawLiquidityNative(uint256 amount) external payable override whenNotPaused {
2
// burn LP token in the amount of liquidity that should be removed
3
ERC20Burnable(getLPToken(wrappedNative())).burnFrom(_msgSender(), amount);
4
5
// call liquidityManager contract to emit event and transfer liquidity
6
ICrossChainBridgeERC20LiquidityManager(liquidityManager).withdrawLiquidityNative(_msgSender(), amount);
7
}
Copied!

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.
1
function wrappedNative() public view override returns (address) {
2
return address(ICrossChainBridgeERC20(bridgeERC20).wrappedNative());
3
}
Copied!

Return value:

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