BridgeChef
Creates and manages farms for the cross-chain bridge. Liquidity providers can stake their LP tokens in a farm (if available) to earn BRIDGE tokens which are required to participate in reward pools.

Functions

add

Adds a new farm
1
function add(
2
uint256 _farmMultiplier,
3
IERC20 _lpToken,
4
bool _withUpdate
5
) external whenNotPaused nonReentrant {
6
// check permission and input parameter
7
if (!hasRole(FARM_ADMIN_ROLE, _msgSender())) revert Unauthorized();
8
if (address(_lpToken) == address(0)) revert InvalidAddress();
9
if (usedLpTokens[address(_lpToken)]) revert AlreadyUsed();
10
11
// run mass farm update if flag was set to true
12
if (_withUpdate) {
13
massUpdateFarms();
14
}
15
16
// Add multiplier to sumOfFarmMultiplier so bridge distribution ratio can be correctly calculated
17
sumOfFarmMultiplier = sumOfFarmMultiplier + _farmMultiplier;
18
19
// add LP token to list of LP tokens
20
lpToken.push(_lpToken);
21
22
// add LP token to list of used LP tokens
23
usedLpTokens[address(_lpToken)] = true;
24
25
// create a new LP farm and save it in the list of farms (farmInfo)
26
farmInfo.push(
27
FarmInfo({
28
farmMultiplier: _farmMultiplier,
29
lastRewardBlock: block.number,
30
accBridgePerShare: 0,
31
lpToken: address(_lpToken)
32
})
33
);
34
35
// LP farm successfully created, emit event
36
emit FarmAdded(farmInfo.length - 1, _farmMultiplier, _lpToken);
37
}
38
Copied!

Parameters:

Name
Type
Description
_farmMultiplier
uint256
the multiplier that this farm gets (value 100 = multiplier 1, value 300 = multiplier 3, value 0 will deactivate the farm entirely)
_lpToken
IERC20
the LP token for this farm
_withupdate
bool
update all other farms? Always a good idea...

bridgeTokensReadyToHarvest

Returns the amount of BRIDGE tokens that are ready for harvesting for the given user and farm
1
function bridgeTokensReadyToHarvest(uint256 farmId, address user) external view returns (uint256) {
2
//check input parameters
3
if (farmId >= farmInfo.length) revert OutOfRange(farmId, 0, farmInfo.length - 1);
4
5
// get farm info
6
FarmInfo memory farm = farmInfo[farmId];
7
8
// get user deposit info
9
DepositInfo memory userDeposit = depositInfo[farmId][user];
10
11
if (userDeposit.amount == 0) {
12
return 0;
13
}
14
15
// get the farm's accumulated reward per share
16
uint256 accBridgePerShare = farm.accBridgePerShare;
17
18
uint256 lpSupply = IERC20(farm.lpToken).balanceOf(address(this));
19
20
// check if farm has funds and if new rewards have been accumulated since last reward
21
if (block.number > farm.lastRewardBlock && lpSupply != 0) {
22
// calculate how many blocks have passed since last reward
23
uint256 blocks = block.number - farm.lastRewardBlock;
24
25
// calculate how many bridge tokens are pending for this farm
26
// (=>> blocks * bridgePerBlock * farm multiplier / sumOfFarmMultipliers)
27
uint256 bridgeReward = (blocks * bridgePerBlock * farm.farmMultiplier) / sumOfFarmMultiplier;
28
29
// calculate how many bridge tokens will be assigned to each share in the farm
30
accBridgePerShare = accBridgePerShare + (bridgeReward * _ROUNDING_PRECISION) / lpSupply;
31
}
32
33
// return the calculated amount of bridge tokens that are pending for the shareholder
34
return uint256(int256((userDeposit.amount * accBridgePerShare) / _ROUNDING_PRECISION) - userDeposit.rewardDebt);
35
}
Copied!

Parameters:

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

Return value:

Name
Type
Description
uint256
the unharvested reward amount in BRIDGE tokens

deposit

Deposits liquidity provider (LP) tokens in the given farm for the user to start earning BRIDGE tokens
1
function deposit(uint256 farmId, uint256 amount) external whenNotPaused nonReentrant {
2
// run some input parameter and data checks
3
if (amount == 0) revert InvalidParameter();
4
if (farmId >= farmInfo.length) revert OutOfRange(farmId, 0, farmInfo.length - 1);
5
6
// get farm info
7
FarmInfo storage farm = farmInfo[farmId];
8
9
// update the farm to have a clean start for the new deposit
10
updateFarm(farmId);
11
12
// create or update a deposit and persist it
13
DepositInfo storage userDeposit = depositInfo[farmId][_msgSender()];
14
userDeposit.amount = userDeposit.amount + amount;
15
userDeposit.rewardDebt = userDeposit.rewardDebt + int256((amount * farm.accBridgePerShare) / _ROUNDING_PRECISION);
16
17
// Interactions - transfer LP tokens from user to this smart contract
18
lpToken[farmId].safeTransferFrom(_msgSender(), address(this), amount);
19
20
// deposit successfully processed, emit event
21
emit DepositAdded(_msgSender(), farmId, amount);
22
}
Copied!

Parameters:

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

harvest

Harvests BRIDGE rewards from the given farm and sends them to the caller of this function
1
function harvest(uint256 farmId) external whenNotPaused nonReentrant {
2
// check if farm exists
3
if (farmId >= farmInfo.length) revert OutOfRange(farmId, 0, farmInfo.length - 1);
4
5
// update farm calculations
6
FarmInfo memory farm = updateFarm(farmId);
7
8
// get deposit information
9
DepositInfo storage userDeposit = depositInfo[farmId][_msgSender()];
10
11
// check if user/deposit exists
12
if (userDeposit.amount == 0) revert InvalidTarget();
13
14
// calculate the accumulated reward amount
15
int256 accumulatedBridgeTokens = int256((userDeposit.amount * farm.accBridgePerShare) / _ROUNDING_PRECISION);
16
uint256 _pendingBridgeToken = uint256(accumulatedBridgeTokens - userDeposit.rewardDebt);
17
18
// check if any bridge tokens are ready for harvesting
19
if (_pendingBridgeToken == 0) revert InvalidBalance();
20
21
// Effects - update rewardDebt with current harvest amount
22
userDeposit.rewardDebt = accumulatedBridgeTokens;
23
24
// Interactions - transfer bridge tokens to _msgSender()
25
safeBridgeTransfer(_msgSender(), _pendingBridgeToken);
26
27
// harvest successful, emit event
28
emit RewardsHarvested(_msgSender(), farmId, _pendingBridgeToken);
29
}
Copied!

Parameters:

Name
Type
Description
farmId
uint256
the ID of the farm

updateFarm

Update reward calculations for the given farm
1
function updateFarm(uint256 farmId) public whenNotPaused returns (FarmInfo memory) {
2
if (farmId >= farmInfo.length) revert OutOfRange(farmId, 0, farmInfo.length - 1);
3
FarmInfo storage farm = farmInfo[farmId];
4
5
//check if rewards have been accrued since last reward calculation
6
if (block.number <= farm.lastRewardBlock) {
7
return farm;
8
}
9
10
uint256 lpSupply = IERC20(farm.lpToken).balanceOf(address(this));
11
12
// check if farm is funded with LP tokens
13
if (lpSupply <= 0) {
14
// update lastRewardblock with current block number
15
farm.lastRewardBlock = block.number;
16
emit FarmUpdated(farmId, farm.lastRewardBlock, lpSupply, farm.accBridgePerShare);
17
return farm;
18
}
19
20
// calculate how many blocks have passed since last reward calculation
21
uint256 blocks = block.number - farm.lastRewardBlock;
22
23
// calculate the amount of bridge tokens this farm has accrued since last reward calculation
24
// (=>> blocks * bridgePerBlock * farm multiplier / sumOfFarmMultipliers)
25
uint256 bridgeReward = (blocks * bridgePerBlock * farm.farmMultiplier) / sumOfFarmMultiplier;
26
27
// mint bridge tokens to developer account (if set), staking pool (if set) and to this contract
28
bridgeToken.mint(address(this), bridgeReward);
29
bridgeToken.mint(devAddr, (bridgeReward * devRewardPercentage) / 100);
30
bridgeToken.mint(stakingAddr, (bridgeReward * stakingPercentage) / 100);
31
32
// update accumulatedBridgePerShare calculation in farm
33
farm.accBridgePerShare = farm.accBridgePerShare + (bridgeReward * _ROUNDING_PRECISION) / lpSupply;
34
35
// set lastRewardBlock to current block number
36
farm.lastRewardBlock = block.number;
37
38
// farm updated, emit event
39
emit FarmUpdated(farmId, farm.lastRewardBlock, lpSupply, farm.accBridgePerShare);
40
41
return farm;
42
}
Copied!

Parameters:

Name
Type
Description
farmId
uint256
The index of the farm

Return value:

Name
Type
Description
farmInfo
FarmInfo
returns the updated farm information
Updates the given farm's multiplier (that determines how many bridge token will be assigned to this farm on each block)

massUpdateFarms

Update reward variables for all available reward farms
1
function massUpdateFarms() public whenNotPaused {
2
massUpdateFarms(0, farmInfo.length - 1);
3
}
Copied!

massUpdateFarms(from, to)

Update reward variables for the given reward farms
1
function massUpdateFarms(uint256 from, uint256 to) public whenNotPaused {
2
if (from > to) revert InvalidParameter();
3
if (to >= farmInfo.length) revert OutOfRange(to, 0, farmInfo.length - 1);
4
for (uint256 farmId = from; farmId <= to; ++farmId) {
5
updateFarm(farmId);
6
}
7
}
Copied!

Parameters:

Name
Type
Description
from
uint256
the starting index for the mass update (first element: 0)
to
uint256
the ending index for the mass update (if you want to update the first 5 reward farms, the 'to' value should be 4)

withdraw

Withdraws liquidity provider (LP) tokens from the given farm
1
function withdraw(uint256 farmId, uint256 amount) external whenNotPaused nonReentrant {
2
// get deposit info
3
DepositInfo storage userDeposit = depositInfo[farmId][_msgSender()];
4
5
// check input parameters
6
if (farmId >= farmInfo.length) revert OutOfRange(farmId, 0, farmInfo.length - 1);
7
if (amount == 0) revert InvalidParameter();
8
if (userDeposit.amount == 0) revert InvalidTarget();
9
10
// update farm reward calculations
11
FarmInfo memory farm = updateFarm(farmId);
12
13
// calculate the accumulated reward amount
14
int256 accumulatedBridgeTokens = int256((userDeposit.amount * farm.accBridgePerShare) / _ROUNDING_PRECISION);
15
uint256 _pendingBridgeToken = uint256(accumulatedBridgeTokens - userDeposit.rewardDebt);
16
17
// update reward debt to reflect that funds have been withdrawn
18
userDeposit.rewardDebt = accumulatedBridgeTokens - int256((amount * farm.accBridgePerShare) / _ROUNDING_PRECISION);
19
20
// subtract the withdrawal amount from the deposit
21
userDeposit.amount = userDeposit.amount - amount;
22
23
// Interactions - transfer bridge tokens to _msgSender()
24
safeBridgeTransfer(_msgSender(), _pendingBridgeToken);
25
26
// Interactions
27
// transfer LP token back to user
28
lpToken[farmId].safeTransfer(_msgSender(), amount);
29
30
// harvest successful, emit event
31
emit RewardsHarvested(_msgSender(), farmId, _pendingBridgeToken);
32
// withdrawal successful, emit event
33
emit FundsWithdrawn(_msgSender(), farmId, amount);
34
}
Copied!

Parameters:

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