Skip to content

Commit

Permalink
feat: add FeeDistributorBALClaimer contract
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench committed Mar 31, 2022
1 parent 4fc4db5 commit 4228761
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,12 @@ contract FeeDistributor is IFeeDistributor, ReentrancyGuard {
* @param tokens - An array of ERC20 token addresses to be claimed.
* @return An array of the amounts of each token in `tokens` sent to `user` as a result of claiming.
*/
function claimTokens(address user, IERC20[] calldata tokens) external override nonReentrant returns (uint256[] memory) {
function claimTokens(address user, IERC20[] calldata tokens)
external
override
nonReentrant
returns (uint256[] memory)
{
// Prevent someone from assigning tokens to an inaccessible week.
require(block.timestamp > _startTime, "Fee distribution has not started yet");
_checkpointTotalSupply();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;

import "@balancer-labs/v2-standalone-utils/contracts/interfaces/IBALTokenHolder.sol";

import "../interfaces/IFeeDistributor.sol";
import "../interfaces/ISingleRecipientGauge.sol";

/**
* @title FeeDistributorBALClaimer
* @notice Atomically mints any outstanding BAL from a SingleRecipientGauge and transfers it to the FeeDistributor
* in order for it to be distributed among veBAL holders.
*/
contract FeeDistributorBALClaimer {
IERC20 private immutable _balToken;
IFeeDistributor private immutable _feeDistributor;
ISingleRecipientGauge private immutable _gauge;
IBALTokenHolder private immutable _balTokenHolder;

constructor(IFeeDistributor feeDistributor, ISingleRecipientGauge gauge) {
IBALTokenHolder balTokenHolder = IBALTokenHolder(gauge.getRecipient());

_balToken = balTokenHolder.getBalancerToken();
_feeDistributor = feeDistributor;
_gauge = gauge;
_balTokenHolder = balTokenHolder;
}

/**
* @notice Mint any outstanding BAL emissions and send them to the FeeDistributor
*/
function distributeBAL() external {
_gauge.checkpoint();
_balTokenHolder.withdrawFunds(address(_feeDistributor), _balToken.balanceOf(address(_balTokenHolder)));
_feeDistributor.checkpointToken(_balToken);
}
}
6 changes: 3 additions & 3 deletions pkg/liquidity-mining/contracts/gauges/StakelessGauge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import "@balancer-labs/v2-solidity-utils/contracts/openzeppelin/ReentrancyGuard.
import "../interfaces/IBalancerMinter.sol";
import "../interfaces/IBalancerTokenAdmin.sol";
import "../interfaces/IGaugeController.sol";
import "../interfaces/ILiquidityGauge.sol";
import "../interfaces/IStakelessGauge.sol";

abstract contract StakelessGauge is ILiquidityGauge, ReentrancyGuard {
abstract contract StakelessGauge is IStakelessGauge, ReentrancyGuard {
IERC20 internal immutable _balToken;
IBalancerTokenAdmin private immutable _tokenAdmin;
IBalancerMinter private immutable _minter;
Expand Down Expand Up @@ -78,7 +78,7 @@ abstract contract StakelessGauge is ILiquidityGauge, ReentrancyGuard {
_startEpochTime = _tokenAdmin.startEpochTimeWrite();
}

function checkpoint() external payable nonReentrant returns (bool) {
function checkpoint() external payable override nonReentrant returns (bool) {
require(msg.sender == address(_authorizerAdaptor), "SENDER_NOT_ALLOWED");
uint256 lastPeriod = _period;
uint256 currentPeriod = _currentPeriod();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import "./IVotingEscrow.sol";
* holders simply transfer the tokens to the `FeeDistributor` contract and then call `checkpointToken`.
*/
interface IFeeDistributor {

event TokenCheckpointed(IERC20 token, uint256 amount, uint256 lastCheckpointTimestamp);
event TokensClaimed(address user, IERC20 token, uint256 amount, uint256 userTokenTimeCursor);

Expand All @@ -38,11 +37,13 @@ interface IFeeDistributor {
* @notice Returns the global time cursor representing the most earliest uncheckpointed week.
*/
function getTimeCursor() external view returns (uint256);

/**
* @notice Returns the user-level time cursor representing the most earliest uncheckpointed week.
* @param user - The address of the user to query.
*/
function getUserTimeCursor(address user) external view returns (uint256);

/**
* @notice Returns the token-level time cursor storing the timestamp at up to which tokens have been distributed.
* @param token - The ERC20 token address to query.
Expand Down Expand Up @@ -77,6 +78,7 @@ interface IFeeDistributor {
* @notice Returns the FeeDistributor's cached balance of `token`.
*/
function getTokenLastBalance(IERC20 token) external view returns (uint256);

// Checkpointing

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@

pragma solidity ^0.7.0;

import "./ILiquidityGauge.sol";
import "./IStakelessGauge.sol";

interface ISingleRecipientGauge is ILiquidityGauge {
interface ISingleRecipientGauge is IStakelessGauge {
function initialize(address recipient) external;

function getRecipient() external view returns (address);
Expand Down
21 changes: 21 additions & 0 deletions pkg/liquidity-mining/contracts/interfaces/IStakelessGauge.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

pragma solidity ^0.7.0;

import "./ILiquidityGauge.sol";

interface IStakelessGauge is ILiquidityGauge {
function checkpoint() external payable returns (bool);
}
3 changes: 1 addition & 2 deletions pkg/standalone-utils/contracts/BALTokenHolder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import "@balancer-labs/v2-solidity-utils/contracts/helpers/Authentication.sol";
import "@balancer-labs/v2-solidity-utils/contracts/openzeppelin/SafeERC20.sol";

import "@balancer-labs/v2-vault/contracts/interfaces/IVault.sol";
import "@balancer-labs/v2-liquidity-mining/contracts/interfaces/IBalancerToken.sol";

import "./interfaces/IBALTokenHolder.sol";

Expand Down Expand Up @@ -51,7 +50,7 @@ contract BALTokenHolder is IBALTokenHolder, Authentication {
_name = name;
}

function getBalancerToken() external view returns (IBalancerToken) {
function getBalancerToken() external view override returns (IBalancerToken) {
return _balancerToken;
}

Expand Down
4 changes: 4 additions & 0 deletions pkg/standalone-utils/contracts/interfaces/IBALTokenHolder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@ pragma solidity ^0.7.0;

import "@balancer-labs/v2-solidity-utils/contracts/helpers/IAuthentication.sol";
import "@balancer-labs/v2-solidity-utils/contracts/openzeppelin/IERC20.sol";
import "@balancer-labs/v2-liquidity-mining/contracts/interfaces/IBalancerToken.sol";


interface IBALTokenHolder is IAuthentication {
function getBalancerToken() external view returns (IBalancerToken);

function withdrawFunds(address recipient, uint256 amount) external;

function sweepTokens(
Expand Down

0 comments on commit 4228761

Please sign in to comment.