-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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"); | ||
_; | ||
} | ||
|
||
// =================================== 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
MerklFraxIncentivizationHandler.setOperator(address)._operatorAddress lacks a zero-check on :
- operatorAddress = _operatorAddress Check warning Code scanning / Slither Conformance to Solidity naming conventions Warning
Parameter MerklFraxIncentivizationHandler.setOperator(address)._operatorAddress is not in mixedCase
|
||
operatorAddress = _operatorAddress; | ||
} | ||
Check notice Code scanning / Slither Missing events access control Low
MerklFraxIncentivizationHandler.setOperator(address) should emit an event for:
- operatorAddress = _operatorAddress |
||
|
||
/// @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, | ||
|
@@ -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 | ||
|
@@ -94,4 +108,10 @@ contract MerklFraxIncentivizationHandler is Ownable { | |
} | ||
} | ||
} | ||
Check failure Code scanning / Slither Reentrancy vulnerabilities High
Reentrancy in MerklFraxIncentivizationHandler.incentivizePool(address,address,address,address,uint256,uint256):
External calls: - IERC20(incentiveTokenAddress).safeTransferFrom(msg.sender,address(this),amount) - _handleIncentiveTokenAllowance(IERC20(incentiveTokenAddress),address(creator),amount) - returndata = address(token).functionCall(data,SafeERC20: low-level call failed) - incentiveTokenAddress.safeIncreaseAllowance(spender,amount - currentAllowance) - (success,returndata) = target.call{value: value}(data) - merklDistributionCreator().createDistribution(params) External calls sending eth: - _handleIncentiveTokenAllowance(IERC20(incentiveTokenAddress),address(creator),amount) - (success,returndata) = target.call{value: value}(data) State variables written after the call(s): - leftovers[incentiveTokenAddress][poolAddress] = 0 MerklFraxIncentivizationHandler.leftovers can be used in cross function reentrancies: - MerklFraxIncentivizationHandler.incentivizePool(address,address,address,address,uint256,uint256) - MerklFraxIncentivizationHandler.leftovers Check warning Code scanning / Slither Unused return Medium Check notice Code scanning / Slither Reentrancy vulnerabilities Low
Reentrancy in MerklFraxIncentivizationHandler.incentivizePool(address,address,address,address,uint256,uint256):
External calls: - IERC20(incentiveTokenAddress).safeTransferFrom(msg.sender,address(this),amount) State variables written after the call(s): - leftovers[incentiveTokenAddress][poolAddress] = 0 - leftovers[incentiveTokenAddress][poolAddress] = amount |
||
|
||
/// @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); | ||
} | ||
} |
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
Parameter MockMerklFraxIncentivizationHandler.setAddresses(DistributionCreator)._manager is not in mixedCase
|
||
manager = _manager; | ||
} | ||
} |