Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions contracts/PoolRewardDistributor.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import './uniswap/interfaces/IWETH.sol';
import './interfaces/IMasterChef.sol';
import "./boringcrypto/BoringOwnable.sol";

/**
* @title PoolRewardDistributor
* @notice Distribute rewards to pools
*/
contract PoolRewardDistributor is BoringOwnable {
using SafeMath for uint256;
using SafeERC20 for IERC20;


struct Pool {
uint256 pid; // id of pool
uint256 rewardAmount; // amount of rewards to distribue
}

address public immutable masterChef;
address public immutable WETH;

uint256 public totalRewardAmount;
Pool[] public pools;

constructor(address _masterChef, address _WETH) public {
masterChef = _masterChef;
WETH = _WETH;
}

function recoverFuse() public onlyOwner {
uint256 fuseBalance = address(this).balance;
(bool sent,) = payable(owner).call{value: fuseBalance}("");
require(sent);
}

function recoverToken(address token) public onlyOwner {
uint256 tokenBalance = IERC20(token).balanceOf(address(this));
IERC20(token).transfer(owner, tokenBalance);
}

function addPools(Pool[] memory _pools) external onlyOwner {
for (uint256 i = 0; i < _pools.length; i++) {
_addPool(_pools[i]);
}
}

function addPool(Pool memory _pool) external onlyOwner {
_addPool(_pool);
}

function removePool(uint256 _pid) external onlyOwner {
_removePool(_pid);
}

function distributeRewards() external payable onlyOwner {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it payable?

IWETH(WETH).deposit{value: msg.value}();

for (uint256 i = 0; i < pools.length; i++) {
Pool memory pool = pools[i];
IMasterChef.PoolInfo memory poolInfo = IMasterChef(masterChef).poolInfo(pool.pid);

if (address(poolInfo.rewarder) != address(0)) {
IWETH(WETH).transfer(address(poolInfo.rewarder), pool.rewardAmount);
}
}
}

function _addPool(Pool memory _pool) internal {
pools.push(_pool);
totalRewardAmount = totalRewardAmount.add(_pool.rewardAmount);
}

function _removePool(uint256 _pid) internal {
uint256 index = _poolIndex(_pid);

Pool memory pool = pools[index];
totalRewardAmount = totalRewardAmount.sub(pool.rewardAmount);

Pool[] storage poolsStorage = pools;

for (uint256 i = index; i < poolsStorage.length - 1; i++) {
poolsStorage[i] = poolsStorage[i + 1];
}

poolsStorage.pop();
}

function _poolIndex(uint256 _pid) internal view returns (uint256) {
for (uint256 i = 0; i < pools.length; i++) {
if (pools[i].pid == _pid) {
return i;
}
}

revert('pool not found');
}
}
12 changes: 12 additions & 0 deletions contracts/interfaces/IMasterChef.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

import "../libraries/BoringERC20.sol";

interface IRewarder {
function onVoltReward(address user, uint256 newLpAmount) external;

function pendingTokens(address user) external view returns (uint256 pending);

function rewardToken() external view returns (IERC20);
}

interface IMasterChef {
using BoringERC20 for IERC20;
struct UserInfo {
Expand All @@ -15,6 +24,7 @@ interface IMasterChef {
uint256 allocPoint; // How many allocation points assigned to this pool. JOE to distribute per block.
uint256 lastRewardTimestamp; // Last block number that JOE distribution occurs.
uint256 accJoePerShare; // Accumulated JOE per share, times 1e12. See below.
IRewarder rewarder;
}

function poolInfo(uint256 pid) external view returns (IMasterChef.PoolInfo memory);
Expand All @@ -28,4 +38,6 @@ interface IMasterChef {
function treasuryPercent() external view returns (uint256);

function investorPercent() external view returns (uint256);

function poolLength() external view returns (uint256);
}