Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More ERC20 token Incentive in gauge #10

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
34 changes: 2 additions & 32 deletions contracts/Voter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ contract Voter is IVoter, ERC2771Context, ReentrancyGuard {
/// @inheritdoc IVoter
mapping(address => address) public gauges;
/// @inheritdoc IVoter
mapping(address => address) public gaugeToIncentives;
/// @inheritdoc IVoter
mapping(address => address) public poolForGauge;
/// @inheritdoc IVoter
mapping(address => uint256) public weights;
Expand Down Expand Up @@ -276,10 +274,10 @@ contract Voter is IVoter, ERC2771Context, ReentrancyGuard {
}

address gaugeFactory = IFactoryRegistry(factoryRegistry).factoriesToPoolFactory(_poolFactory);
address _gauge = IGaugeFactory(gaugeFactory).createGauge(forwarder, _pool);
address _incentiveReward = IIncentivesFactory(incentiveFactory).createRewards(forwarder, _pool);
address _gauge = IGaugeFactory(gaugeFactory).createGauge(forwarder, _pool, _incentiveReward);
IReward(_incentiveReward).setGauge(_gauge);

gaugeToIncentives[_gauge] = _incentiveReward;
gauges[_pool] = _gauge;
poolForGauge[_gauge] = _pool;
isGauge[_gauge] = true;
Expand Down Expand Up @@ -379,15 +377,6 @@ contract Voter is IVoter, ERC2771Context, ReentrancyGuard {
}
}

/// @inheritdoc IVoter
function claimIncentive(address[] memory _incentives, address[][] memory _tokens) external {
address _sender = msg.sender;
uint256 _length = _incentives.length;
for (uint256 i = 0; i < _length; i++) {
IReward(_incentives[i]).getReward(_sender, _tokens[i]);
}
}

function _distribute(address _gauge) internal {
_updateFor(_gauge); // should set claimable to 0 if killed
uint256 _claimable = claimable[_gauge];
Expand All @@ -414,23 +403,4 @@ contract Voter is IVoter, ERC2771Context, ReentrancyGuard {
_distribute(_gauges[x]);
}
}

function depositLP(address _pool, uint256 _amount) external hasValidGauge(_pool) nonReentrant {
if (_amount == 0) revert ZeroAmount();
address _sender = msg.sender;
address _gauge = gauges[_pool];
IERC20(_pool).safeTransferFrom(_sender, address(this), _amount);
IERC20(_pool).approve(_gauge, _amount);
IGauge(_gauge).deposit(_amount, _sender);
IReward(gaugeToIncentives[_gauge])._deposit(_amount, _sender);
}

function withdrawLP(address _pool, uint256 _amount) external nonReentrant {
if (_amount == 0) revert ZeroAmount();
address _gauge = gauges[_pool];
if (_gauge == address(0)) revert GaugeDoesNotExist(_pool);
address _sender = msg.sender;
IGauge(_gauge).withdraw(_sender, _amount);
IReward(gaugeToIncentives[_gauge])._withdraw(_amount, _sender);
}
}
4 changes: 2 additions & 2 deletions contracts/factories/GaugeFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {IGaugeFactory} from "../interfaces/factories/IGaugeFactory.sol";
import {Gauge} from "../gauges/Gauge.sol";

contract GaugeFactory is IGaugeFactory {
function createGauge(address _forwarder, address _pool) external returns (address gauge) {
gauge = address(new Gauge(_forwarder, _pool, msg.sender));
function createGauge(address _forwarder, address _pool, address _moreIncentives) external returns (address gauge) {
gauge = address(new Gauge(_forwarder, _pool, msg.sender, _moreIncentives));
}
}
8 changes: 7 additions & 1 deletion contracts/gauges/Gauge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.0;
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
import {IGauge} from "../interfaces/IGauge.sol";
import {IVoter} from "../interfaces/IVoter.sol";
import {IReward} from "../interfaces/IReward.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {ERC2771Context} from "@openzeppelin/contracts/metatx/ERC2771Context.sol";
Expand Down Expand Up @@ -41,10 +42,13 @@ contract Gauge is IGauge, ERC2771Context, ReentrancyGuard {
mapping(address => uint256) public rewards;
/// @inheritdoc IGauge
mapping(uint256 => uint256) public rewardRateByEpoch;
/// @inheritdoc IGauge
address public incentives;

constructor(address _forwarder, address _stakingToken, address _voter) ERC2771Context(_forwarder) {
constructor(address _forwarder, address _stakingToken, address _voter, address _moreIncentives) ERC2771Context(_forwarder) {
stakingToken = _stakingToken;
voter = _voter;
incentives = _moreIncentives;
}

/// @inheritdoc IGauge
Expand Down Expand Up @@ -103,6 +107,7 @@ contract Gauge is IGauge, ERC2771Context, ReentrancyGuard {
IERC20(stakingToken).safeTransferFrom(sender, address(this), _amount);
totalSupply += _amount;
balanceOf[_recipient] += _amount;
IReward(incentives)._deposit(_amount, _recipient);

emit Deposit(sender, _recipient, _amount);
}
Expand All @@ -125,6 +130,7 @@ contract Gauge is IGauge, ERC2771Context, ReentrancyGuard {
totalSupply -= _amount;
balanceOf[receipt] -= _amount;
IERC20(stakingToken).safeTransfer(receipt, _amount);
IReward(incentives)._withdraw(_amount, receipt);

emit Withdraw(receipt, _amount);
}
Expand Down
26 changes: 14 additions & 12 deletions contracts/interfaces/IReward.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,8 @@
pragma solidity ^0.8.0;

interface IReward {
error InvalidReward();
error NotAuthorized();
error NotGauge();
error NotEscrowToken();
error NotSingleToken();
error NotVotingEscrow();
error NotWhitelisted();
error ZeroAmount();

Expand Down Expand Up @@ -64,9 +60,13 @@ interface IReward {
/// @notice The total number of checkpoints
function supplyNumCheckpoints() external view returns (uint256);

/// @notice Deposit an amount into the rewards contract to earn future rewards associated to a veNFT
/// @notice set gauge when create incentive in Voter.
/// @param Address of the _gauge that will be associated with incentive.
function setGauge(address _gauge) external;

/// @notice Deposit an amount into the rewards contract to earn future rewards associated to the address.
/// @dev Internal notation used as only callable internally by `authorized`.
/// @param amount Amount deposited for the veNFT
/// @param amount Amount deposited for the user
/// @param user Which deposit LP
function _deposit(uint256 amount, address user) external;
ludete marked this conversation as resolved.
Show resolved Hide resolved

Expand All @@ -78,12 +78,7 @@ interface IReward {

/// @notice Claim the rewards earned by Lp
/// @param tokens Array of tokens to claim rewards of
function getReward(address[] memory tokens) external;

/// @notice Claim the rewards earned by Lp
/// @param user which get rewards from incentive
/// @param tokens Array of tokens to claim rewards of
function getReward(address user, address[] memory tokens) external;
function claimReward(address[] memory tokens) external;

/// @notice Add rewards for stakers to earn
/// @param token Address of token to reward
Expand All @@ -106,9 +101,16 @@ interface IReward {
/// @notice Get number of rewards tokens
function rewardsListLength() external view returns (uint256);
ludete marked this conversation as resolved.
Show resolved Hide resolved

/// @notice Get the reward tokens
function rewardTokens() external view returns (address[] memory);

/// @notice Calculate how much in rewards are earned for a specific token and veNFT
/// @param token Address of token to fetch rewards of
/// @param _user will receive reward
/// @return Amount of token earned in rewards
function earned(address token, address _user) external view returns (uint256);

/// @notice add new reward token to incentive.
/// @param address of the new reward token
function addRewardToken(address token) external;
}
8 changes: 0 additions & 8 deletions contracts/interfaces/IVoter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,6 @@ interface IVoter {
/// @dev Token => Whitelisted status
function isWhitelistedToken(address token) external view returns (bool);

/// @dev gauge ==> incentive
function gaugeToIncentives(address gauge) external view returns (address);

/// @dev Gauge => Liveness status
function isAlive(address gauge) external view returns (bool);

Expand Down Expand Up @@ -155,11 +152,6 @@ interface IVoter {
/// @param _gauges Array of gauges to collect emissions from.
function claimRewards(address[] memory _gauges) external;

/// @notice Claim incentives with another reward for LP in gauge
/// @param _incentives which store reward
/// @param _tokens Array of reward token for LP in gauge
function claimIncentive(address[] memory _incentives, address[][] memory _tokens) external;

/// @notice Set new governor.
/// @dev Throws if not called by governor.
/// @param _governor .
Expand Down
2 changes: 1 addition & 1 deletion contracts/interfaces/factories/IGaugeFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
pragma solidity ^0.8.0;

interface IGaugeFactory {
function createGauge(address _forwarder, address _pool) external returns (address);
function createGauge(address _forwarder, address _pool, address _moreIncentives) external returns (address);
}
12 changes: 2 additions & 10 deletions contracts/rewards/CustomReward.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,9 @@ abstract contract CustomReward is Reward {
}

/// @inheritdoc Reward
function getReward(address[] memory tokens) external override nonReentrant {
function claimReward(address[] memory tokens) external override nonReentrant {
address sender = _msgSender();
_getReward(sender, tokens);
}

/// @inheritdoc Reward
function getReward(address receiver, address[] memory tokens) external override nonReentrant {
address sender = _msgSender();
if (sender != voter) revert NotAuthorized();

_getReward(receiver, tokens);
_claimReward(sender, tokens);
}

/// @inheritdoc Reward
Expand Down
7 changes: 0 additions & 7 deletions contracts/rewards/Incentive.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,6 @@ contract Incentive is CustomReward {
/// @inheritdoc CustomReward
function notifyRewardAmount(address token, uint256 amount) external override nonReentrant {
address sender = _msgSender();

if (!isReward[token]) {
if (!IVoter(voter).isWhitelistedToken(token)) revert NotWhitelisted();
isReward[token] = true;
rewards.push(token);
}
ludete marked this conversation as resolved.
Show resolved Hide resolved

_notifyRewardAmount(sender, token, amount);
}
}
34 changes: 27 additions & 7 deletions contracts/rewards/Reward.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,20 @@ abstract contract Reward is IReward, ERC2771Context, ReentrancyGuard {
/// @inheritdoc IReward
uint256 public supplyNumCheckpoints;

/// @inheritdoc IReward
address public gauge;

constructor(address _forwarder, address _voter) ERC2771Context(_forwarder) {
voter = _voter;
}

function setGauge(address _gauge) external {
require(gauge == address (0), "gauge has been set");
if (msg.sender != authorized) revert NotAuthorized();
ludete marked this conversation as resolved.
Show resolved Hide resolved

gauge = _gauge;
}

/// @inheritdoc IReward
function getPriorBalanceIndex(address receiver, uint256 timestamp) public view returns (uint256) {
uint256 nCheckpoints = numCheckpoints[receiver];
Expand Down Expand Up @@ -153,6 +163,10 @@ abstract contract Reward is IReward, ERC2771Context, ReentrancyGuard {
return rewards.length;
}

function rewardTokens() external view returns (address[] memory) {
return rewards;
Copy link
Contributor

Choose a reason for hiding this comment

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

rewards may be too long to be returned

}

/// @inheritdoc IReward
function earned(address token, address receiver) public view returns (uint256) {
if (numCheckpoints[receiver] == 0) {
Expand Down Expand Up @@ -190,7 +204,7 @@ abstract contract Reward is IReward, ERC2771Context, ReentrancyGuard {
/// @inheritdoc IReward
function _deposit(uint256 amount, address receiver) external {
address sender = _msgSender();
if (sender != authorized) revert NotAuthorized();
if (sender != gauge) revert NotGauge();

totalSupply += amount;
balanceOf[receiver] += amount;
Expand All @@ -204,7 +218,7 @@ abstract contract Reward is IReward, ERC2771Context, ReentrancyGuard {
/// @inheritdoc IReward
function _withdraw(uint256 amount, address receiver) external {
address sender = _msgSender();
if (sender != authorized) revert NotAuthorized();
if (sender != gauge) revert NotGauge();

totalSupply -= amount;
balanceOf[receiver] -= amount;
Expand All @@ -216,13 +230,10 @@ abstract contract Reward is IReward, ERC2771Context, ReentrancyGuard {
}

/// @inheritdoc IReward
function getReward(address[] memory tokens) external virtual nonReentrant {}

/// @inheritdoc IReward
function getReward(address user, address[] memory tokens) external virtual nonReentrant {}
function claimReward(address[] memory tokens) external virtual nonReentrant {}

/// @dev used with all getReward implementations
function _getReward(address recipient, address[] memory tokens) internal {
function _claimReward(address recipient, address[] memory tokens) internal {
uint256 _length = tokens.length;
for (uint256 i = 0; i < _length; i++) {
uint256 _reward = earned(tokens[i], recipient);
Expand All @@ -246,4 +257,13 @@ abstract contract Reward is IReward, ERC2771Context, ReentrancyGuard {

emit NotifyReward(sender, token, epochStart, amount);
}

/// @dev add new reward token to incentive.
function addRewardToken(address token) external {
ludete marked this conversation as resolved.
Show resolved Hide resolved
if (!isReward[token]) {
if (!IVoter(voter).isWhitelistedToken(token)) revert NotWhitelisted();
isReward[token] = true;
rewards.push(token);
}
}
}
Loading