Skip to content

Commit

Permalink
feat: tests on FRAX incentivization handler
Browse files Browse the repository at this point in the history
  • Loading branch information
sogipec committed Nov 13, 2023
1 parent e40c8ca commit 2b8db08
Show file tree
Hide file tree
Showing 5 changed files with 631 additions and 159 deletions.
58 changes: 39 additions & 19 deletions contracts/middleman/MerklFraxIncentivizationHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,54 +17,68 @@ import "../DistributionCreator.sol";
contract MerklFraxIncentivizationHandler is Ownable {
using SafeERC20 for IERC20;

// ================================= PARAMETERS ================================
/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
PARAMETERS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/

address public operatorAddress;

/// @notice Maps a gauge (same address as a pool here) to its reward parameters
mapping(address => DistributionParameters) public gaugeParams;
/// @notice Maps a gauge, incentive token pair to its reward parameters
mapping(address => mapping(address => DistributionParameters)) public gaugeParams;

/// @notice Maps an incentive token to a set of (pool, leftovers)
/// @dev Merkl imposes that each token distribution comes with a minimum amount per hour
/// We use this mapping to keep track of leftovers to be distributed during future distributions
mapping(address => mapping(address => uint256)) public leftovers;

/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MODIFIER / EVENT
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/

modifier onlyByOwnerOperator() {
require(msg.sender == operatorAddress || msg.sender == owner(), "Not owner or operator");

Check warning on line 39 in contracts/middleman/MerklFraxIncentivizationHandler.sol

View workflow job for this annotation

GitHub Actions / lint

Use Custom Errors instead of require statements
_;
}

// =================================== EVENT ===================================

event GaugeSet(address indexed gauge);
event GaugeSet(address indexed gauge, address indexed incentiveTokenAddress);

constructor(address _operatorAddress) {
constructor(address _operatorAddress) Ownable() {
operatorAddress = _operatorAddress;
}

// ================================= REFERENCES ================================
/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
REFERENCES
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/

/// @notice Address of the Merkl contract managing rewards to be distributed
/// @dev Address is the same across the different chains on which it is deployed
function merklDistributionCreator() public view virtual returns (DistributionCreator) {
return DistributionCreator(0x8BB4C975Ff3c250e0ceEA271728547f3802B36Fd);
}

// ============================= EXTERNAL FUNCTIONS ============================
/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
EXTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/

/// @notice Restores the allowance for the ANGLE token to the `DistributionCreator` contract
function _handleIncentiveTokenAllowance(IERC20 incentiveTokenAddress, address spender, uint256 amount) internal {
uint256 currentAllowance = incentiveTokenAddress.allowance(address(this), spender);
if (currentAllowance < amount) incentiveTokenAddress.safeIncreaseAllowance(spender, amount - currentAllowance);
/// @notice Specifies the reward distribution parameters for `poolAddress`
function setGauge(
address poolAddress,
address incentiveTokenAddress,
DistributionParameters memory params
) external onlyByOwnerOperator {
if (poolAddress == address(0) || incentiveTokenAddress == address(0)) revert InvalidParams();
gaugeParams[poolAddress][incentiveTokenAddress] = params;
emit GaugeSet(poolAddress, incentiveTokenAddress);
}

/// @notice Specifies the reward distribution parameters for `poolAddress`
function setGauge(address poolAddress, DistributionParameters memory params) external onlyByOwnerOperator {
if (poolAddress == address(0)) revert InvalidParams();
gaugeParams[poolAddress] = params;
emit GaugeSet(poolAddress);
/// @notice Sets the operator of the contract
function setOperator(address _operatorAddress) external onlyByOwnerOperator {

Check notice

Code scanning / Slither

Missing zero address validation Low

Check warning

Code scanning / Slither

Conformance to Solidity naming conventions Warning

operatorAddress = _operatorAddress;
}

Check notice

Code scanning / Slither

Missing events access control Low


/// @notice Function called by FRAX contract to stream rewards to `poolAddress`
/// @dev Params for the incentivization of the pool must have been set prior to any call for
/// a `(poolAddress,incentiveTokenAddress)` pair
function incentivizePool(
address poolAddress,
address,
Expand All @@ -74,7 +88,7 @@ contract MerklFraxIncentivizationHandler is Ownable {
uint256 amount
) external {
IERC20(incentiveTokenAddress).safeTransferFrom(msg.sender, address(this), amount);
DistributionParameters memory params = gaugeParams[poolAddress];
DistributionParameters memory params = gaugeParams[poolAddress][incentiveTokenAddress];
if (params.uniV3Pool == address(0)) revert InvalidParams();
DistributionCreator creator = merklDistributionCreator();
// Minimum amount of incentive tokens to be distributed per hour
Expand All @@ -94,4 +108,10 @@ contract MerklFraxIncentivizationHandler is Ownable {
}
}
}

/// @notice Restores the allowance for the ANGLE token to the `DistributionCreator` contract
function _handleIncentiveTokenAllowance(IERC20 incentiveTokenAddress, address spender, uint256 amount) internal {
uint256 currentAllowance = incentiveTokenAddress.allowance(address(this), spender);
if (currentAllowance < amount) incentiveTokenAddress.safeIncreaseAllowance(spender, amount - currentAllowance);
}
}
19 changes: 19 additions & 0 deletions contracts/mock/MockMerklFraxIncentivizationHandler.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.17;

Check warning

Code scanning / Slither

Incorrect versions of Solidity Warning

Pragma version^0.8.17 allows old versions

import "../middleman/MerklFraxIncentivizationHandler.sol";

contract MockMerklFraxIncentivizationHandler is MerklFraxIncentivizationHandler {
DistributionCreator public manager;

constructor(address _operator) MerklFraxIncentivizationHandler(_operator) {}

function merklDistributionCreator() public view override returns (DistributionCreator) {
return manager;
}

function setAddresses(DistributionCreator _manager) external {

Check warning

Code scanning / Slither

Conformance to Solidity naming conventions Warning

manager = _manager;
}
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-standard": "5.0.0",
"ethers": "^5.7.1",
"hardhat": "^2.12.6",
"hardhat": "^2.19.0",
"hardhat-abi-exporter": "2.2.1",
"hardhat-contract-sizer": "2.0.3",
"hardhat-deploy": "^0.11.23",
Expand Down Expand Up @@ -97,4 +97,4 @@
"solc": "0.8.12",
"yargs": "^17.5.1"
}
}
}
Loading

0 comments on commit 2b8db08

Please sign in to comment.