文件 1 的 28:AccessControlUpgradeable.sol
pragma solidity ^0.8.7;
import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "../interfaces/IAccessControl.sol";
abstract contract AccessControlUpgradeable is Initializable, IAccessControl {
function __AccessControl_init() internal initializer {
__AccessControl_init_unchained();
}
function __AccessControl_init_unchained() internal initializer {}
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
modifier onlyRole(bytes32 role) {
_checkRole(role, msg.sender);
_;
}
function hasRole(bytes32 role, address account) public view override returns (bool) {
return _roles[role].members[account];
}
function _checkRole(bytes32 role, address account) internal view {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
StringsUpgradeable.toHexString(uint160(account), 20),
" is missing role ",
StringsUpgradeable.toHexString(uint256(role), 32)
)
)
);
}
}
function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
return _roles[role].adminRole;
}
function grantRole(bytes32 role, address account) external override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
function revokeRole(bytes32 role, address account) external override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
function renounceRole(bytes32 role, address account) external override {
require(account == msg.sender, "71");
_revokeRole(role, account);
}
function _setupRole(bytes32 role, address account) internal {
_grantRole(role, account);
}
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal {
emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);
_roles[role].adminRole = adminRole;
}
function _grantRole(bytes32 role, address account) internal {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, msg.sender);
}
}
function _revokeRole(bytes32 role, address account) internal {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, msg.sender);
}
}
uint256[49] private __gap;
}
文件 2 的 28:Address.sol
pragma solidity ^0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 3 的 28:AddressUpgradeable.sol
pragma solidity ^0.8.0;
library AddressUpgradeable {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 4 的 28:BaseAccumulator.sol
pragma solidity 0.8.7;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../interfaces/ILocker.sol";
import "../interfaces/ILiquidityGauge.sol";
import { ISDTDistributor } from "../interfaces/ISDTDistributor.sol";
contract BaseAccumulator {
using SafeERC20 for IERC20;
address public governance;
address public locker;
address public tokenReward;
address public gauge;
address public sdtDistributor;
uint256 public claimerFee;
event SdtDistributorUpdated(address oldDistributor, address newDistributor);
event GaugeSet(address oldGauge, address newGauge);
event RewardNotified(address gauge, address tokenReward, uint256 amount);
event LockerSet(address oldLocker, address newLocker);
event GovernanceSet(address oldGov, address newGov);
event TokenRewardSet(address oldTr, address newTr);
event TokenDeposited(address token, uint256 amount);
event ERC20Rescued(address token, uint256 amount);
constructor(address _tokenReward) {
tokenReward = _tokenReward;
governance = msg.sender;
}
function notifyExtraReward(address _tokenReward, uint256 _amount) external {
require(msg.sender == governance, "!gov");
_notifyReward(_tokenReward, _amount, true);
}
function notifyAllExtraReward(address _tokenReward) external {
require(msg.sender == governance, "!gov");
uint256 amount = IERC20(_tokenReward).balanceOf(address(this));
_notifyReward(_tokenReward, amount, true);
}
function _notifyReward(
address _tokenReward,
uint256 _amount,
bool _distributeSDT
) internal {
require(gauge != address(0), "gauge not set");
require(_amount > 0, "set an amount > 0");
uint256 balanceBefore = IERC20(_tokenReward).balanceOf(address(this));
require(balanceBefore >= _amount, "amount not enough");
if (ILiquidityGauge(gauge).reward_data(_tokenReward).distributor != address(0)) {
if (_distributeSDT) {
ISDTDistributor(sdtDistributor).distribute(gauge);
}
uint256 claimerReward = (_amount * claimerFee) / 10000;
IERC20(_tokenReward).transfer(msg.sender, claimerReward);
_amount -= claimerReward;
IERC20(_tokenReward).approve(gauge, _amount);
ILiquidityGauge(gauge).deposit_reward_token(_tokenReward, _amount);
uint256 balanceAfter = IERC20(_tokenReward).balanceOf(address(this));
require(balanceBefore - balanceAfter == _amount, "wrong amount notified");
emit RewardNotified(gauge, _tokenReward, _amount);
}
}
function depositToken(address _token, uint256 _amount) external {
require(_amount > 0, "set an amount > 0");
IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);
emit TokenDeposited(_token, _amount);
}
function setGauge(address _gauge) external {
require(msg.sender == governance, "!gov");
require(_gauge != address(0), "can't be zero address");
emit GaugeSet(gauge, _gauge);
gauge = _gauge;
}
function setSdtDistributor(address _sdtDistributor) external {
require(msg.sender == governance, "!gov");
require(_sdtDistributor != address(0), "can't be zero address");
emit SdtDistributorUpdated(sdtDistributor, _sdtDistributor);
sdtDistributor = _sdtDistributor;
}
function setGovernance(address _governance) external {
require(msg.sender == governance, "!gov");
require(_governance != address(0), "can't be zero address");
emit GovernanceSet(governance, _governance);
governance = _governance;
}
function setLocker(address _locker) external {
require(msg.sender == governance, "!gov");
require(_locker != address(0), "can't be zero address");
emit LockerSet(locker, _locker);
locker = _locker;
}
function setTokenReward(address _tokenReward) external {
require(msg.sender == governance, "!gov");
require(_tokenReward != address(0), "can't be zero address");
emit TokenRewardSet(tokenReward, _tokenReward);
tokenReward = _tokenReward;
}
function setClaimerFee(uint256 _claimerFee) external {
require(msg.sender == governance, "!gov");
claimerFee = _claimerFee;
}
function rescueERC20(
address _token,
uint256 _amount,
address _recipient
) external {
require(msg.sender == governance, "!gov");
require(_amount > 0, "set an amount > 0");
require(_recipient != address(0), "can't be zero address");
IERC20(_token).safeTransfer(_recipient, _amount);
emit ERC20Rescued(_token, _amount);
}
}
文件 5 的 28:BaseStrategy.sol
pragma solidity 0.8.7;
import "../interfaces/ILocker.sol";
contract BaseStrategy {
ILocker public locker;
address public governance;
address public rewardsReceiver;
address public veSDTFeeProxy;
address public vaultGaugeFactory;
uint256 public constant BASE_FEE = 10_000;
mapping(address => address) public gauges;
mapping(address => bool) public vaults;
mapping(address => uint256) public perfFee;
mapping(address => address) public multiGauges;
mapping(address => uint256) public accumulatorFee;
mapping(address => uint256) public claimerRewardFee;
mapping(address => uint256) public veSDTFee;
event Deposited(address _gauge, address _token, uint256 _amount);
event Withdrawn(address _gauge, address _token, uint256 _amount);
event Claimed(address _gauge, address _token, uint256 _amount);
event RewardReceiverSet(address _gauge, address _receiver);
event VaultToggled(address _vault, bool _newState);
event GaugeSet(address _gauge, address _token);
modifier onlyGovernance() {
require(msg.sender == governance, "!governance");
_;
}
modifier onlyApprovedVault() {
require(vaults[msg.sender], "!approved vault");
_;
}
modifier onlyGovernanceOrFactory() {
require(msg.sender == governance || msg.sender == vaultGaugeFactory, "!governance && !factory");
_;
}
constructor(
ILocker _locker,
address _governance,
address _receiver
) {
locker = _locker;
governance = _governance;
rewardsReceiver = _receiver;
}
function deposit(address _token, uint256 _amount) external virtual onlyApprovedVault {}
function withdraw(address _token, uint256 _amount) external virtual onlyApprovedVault {}
function claim(address _gauge) external virtual {}
function toggleVault(address _vault) external virtual onlyGovernanceOrFactory {}
function setGauge(address _token, address _gauge) external virtual onlyGovernanceOrFactory {}
function setMultiGauge(address _gauge, address _multiGauge) external virtual onlyGovernanceOrFactory {}
}
文件 6 的 28:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 7 的 28:CurveAccumulator.sol
pragma solidity 0.8.7;
import "./BaseAccumulator.sol";
contract CurveAccumulator is BaseAccumulator {
address public constant CRV3 = 0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490;
constructor(address _tokenReward) BaseAccumulator(_tokenReward) {}
function notify(uint256 _amount) external {
_notifyReward(tokenReward, _amount, true);
}
function notifyAll() external {
uint256 crv3Amount = IERC20(CRV3).balanceOf(address(this));
_notifyReward(tokenReward, crv3Amount, true);
}
}
文件 8 的 28:CurveStrategy.sol
pragma solidity 0.8.7;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "./BaseStrategy.sol";
import "../accumulator/CurveAccumulator.sol";
import "../interfaces/ILiquidityGauge.sol";
import "../interfaces/IMultiRewards.sol";
import "../staking/SdtDistributorV2.sol";
contract CurveStrategy is BaseStrategy {
using SafeERC20 for IERC20;
CurveAccumulator public accumulator;
address public sdtDistributor;
address public constant CRV_FEE_D = 0xA464e6DCda8AC41e03616F95f4BC98a13b8922Dc;
address public constant CRV3 = 0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490;
address public constant CRV_MINTER = 0xd061D61a4d941c39E5453435B6345Dc261C2fcE0;
address public constant CRV = 0xD533a949740bb3306d119CC777fa900bA034cd52;
mapping (address => uint256) public lGaugeType;
struct ClaimerReward {
address rewardToken;
uint256 amount;
}
enum MANAGEFEE {
PERFFEE,
VESDTFEE,
ACCUMULATORFEE,
CLAIMERREWARD
}
event Crv3Claimed(uint256 amount, bool notified);
constructor(
ILocker _locker,
address _governance,
address _receiver,
CurveAccumulator _accumulator,
address _veSDTFeeProxy,
address _sdtDistributor
) BaseStrategy(_locker, _governance, _receiver) {
accumulator = _accumulator;
veSDTFeeProxy = _veSDTFeeProxy;
sdtDistributor = _sdtDistributor;
}
function deposit(address _token, uint256 _amount) external override onlyApprovedVault {
IERC20(_token).transferFrom(msg.sender, address(locker), _amount);
address gauge = gauges[_token];
require(gauge != address(0), "!gauge");
locker.execute(_token, 0, abi.encodeWithSignature("approve(address,uint256)", gauge, 0));
locker.execute(_token, 0, abi.encodeWithSignature("approve(address,uint256)", gauge, _amount));
(bool success, ) = locker.execute(gauge, 0, abi.encodeWithSignature("deposit(uint256)", _amount));
require(success, "Deposit failed!");
emit Deposited(gauge, _token, _amount);
}
function withdraw(address _token, uint256 _amount) external override onlyApprovedVault {
uint256 _before = IERC20(_token).balanceOf(address(locker));
address gauge = gauges[_token];
require(gauge != address(0), "!gauge");
(bool success, ) = locker.execute(gauge, 0, abi.encodeWithSignature("withdraw(uint256)", _amount));
require(success, "Transfer failed!");
uint256 _after = IERC20(_token).balanceOf(address(locker));
uint256 _net = _after - _before;
(success, ) = locker.execute(_token, 0, abi.encodeWithSignature("transfer(address,uint256)", msg.sender, _net));
require(success, "Transfer failed!");
emit Withdrawn(gauge, _token, _amount);
}
function sendToAccumulator(address _token, uint256 _amount) external onlyGovernance {
IERC20(_token).approve(address(accumulator), _amount);
accumulator.depositToken(_token, _amount);
}
function claim(address _token) external override {
address gauge = gauges[_token];
require(gauge != address(0), "!gauge");
uint256 crvBeforeClaim = IERC20(CRV).balanceOf(address(locker));
(bool success, ) = locker.execute(
CRV_MINTER,
0,
abi.encodeWithSignature("mint(address)", gauge)
);
require(success, "CRV mint failed!");
uint256 crvMinted = IERC20(CRV).balanceOf(address(locker)) - crvBeforeClaim;
(success, ) = locker.execute(
CRV,
0,
abi.encodeWithSignature("transfer(address,uint256)", address(this), crvMinted)
);
require(success, "CRV transfer failed!");
uint256 crvNetRewards = sendFee(gauge, CRV, crvMinted);
IERC20(CRV).approve(multiGauges[gauge], crvNetRewards);
ILiquidityGauge(multiGauges[gauge]).deposit_reward_token(CRV, crvNetRewards);
emit Claimed(gauge, CRV, crvMinted);
SdtDistributorV2(sdtDistributor).distribute(multiGauges[gauge]);
if(lGaugeType[gauge] == 0 && ILiquidityGauge(gauge).reward_tokens(0) != address(0)) {
(success, ) = locker.execute(
gauge, 0, abi.encodeWithSignature("claim_rewards(address,address)", address(locker), address(this))
);
if (!success) {
ILiquidityGauge(gauge).claim_rewards(address(locker));
}
address rewardToken;
uint256 rewardsBalance;
for (uint8 i = 0; i < 8; i++) {
rewardToken = ILiquidityGauge(gauge).reward_tokens(i);
if (rewardToken == address(0)) {
break;
}
if (success) {
rewardsBalance = IERC20(rewardToken).balanceOf(address(this));
} else {
rewardsBalance = IERC20(rewardToken).balanceOf(address(locker));
(success, ) = locker.execute(
rewardToken, 0, abi.encodeWithSignature("transfer(address,uint256)", address(this), rewardsBalance)
);
require(success, "Transfer failed");
}
IERC20(rewardToken).approve(multiGauges[gauge], rewardsBalance);
ILiquidityGauge(multiGauges[gauge]).deposit_reward_token(rewardToken, rewardsBalance);
emit Claimed(gauge, rewardToken, rewardsBalance);
}
}
}
function sendFee(address _gauge, address _rewardToken, uint256 _rewardsBalance) internal returns(uint256) {
uint256 multisigFee = (_rewardsBalance * perfFee[_gauge]) / BASE_FEE;
uint256 accumulatorPart = (_rewardsBalance * accumulatorFee[_gauge]) / BASE_FEE;
uint256 veSDTPart = (_rewardsBalance * veSDTFee[_gauge]) / BASE_FEE;
uint256 claimerPart = (_rewardsBalance * claimerRewardFee[_gauge]) / BASE_FEE;
IERC20(_rewardToken).approve(address(accumulator), accumulatorPart);
accumulator.depositToken(_rewardToken, accumulatorPart);
IERC20(_rewardToken).transfer(rewardsReceiver, multisigFee);
IERC20(_rewardToken).transfer(veSDTFeeProxy, veSDTPart);
IERC20(_rewardToken).transfer(msg.sender, claimerPart);
return _rewardsBalance - multisigFee - accumulatorPart - veSDTPart - claimerPart;
}
function claim3Crv(bool _notify) external {
bool success;
(success, ) = locker.execute(CRV_FEE_D, 0, abi.encodeWithSignature("claim()"));
require(success, "3crv claim failed");
uint256 amountToSend = IERC20(CRV3).balanceOf(address(locker));
require(amountToSend > 0, "nothing claimed");
(success, ) = locker.execute(
CRV3,
0,
abi.encodeWithSignature("transfer(address,uint256)", address(accumulator), amountToSend)
);
require(success, "3crv transfer failed");
if (_notify) {
accumulator.notifyAll();
}
emit Crv3Claimed(amountToSend, _notify);
}
function toggleVault(address _vault) external override onlyGovernanceOrFactory {
require(_vault != address(0), "zero address");
vaults[_vault] = !vaults[_vault];
emit VaultToggled(_vault, vaults[_vault]);
}
function setLGtype(address _gauge, uint256 _gaugeType) external onlyGovernanceOrFactory {
lGaugeType[_gauge] = _gaugeType;
}
function setGauge(address _token, address _gauge) external override onlyGovernanceOrFactory {
require(_token != address(0), "zero address");
gauges[_token] = _gauge;
emit GaugeSet(_gauge, _token);
}
function migrateLP(address _token) external onlyApprovedVault {
require(gauges[_token] != address(0), "not existent gauge");
migrate(_token);
}
function migrate(address _token) internal {
address gauge = gauges[_token];
uint256 amount = IERC20(gauge).balanceOf(address(locker));
(bool success, ) = locker.execute(gauge, 0, abi.encodeWithSignature("withdraw(uint256)", amount));
require(success, "Withdraw failed!");
(success, ) = locker.execute(_token, 0, abi.encodeWithSignature("transfer(address,uint256)", msg.sender, amount));
require(success, "Transfer failed!");
}
function setMultiGauge(address _gauge, address _multiGauge) external override onlyGovernanceOrFactory {
require(_gauge != address(0), "zero address");
require(_multiGauge != address(0), "zero address");
multiGauges[_gauge] = _multiGauge;
}
function setVeSDTProxy(address _newVeSDTProxy) external onlyGovernance {
require(_newVeSDTProxy != address(0), "zero address");
veSDTFeeProxy = _newVeSDTProxy;
}
function setAccumulator(address _newAccumulator) external onlyGovernance {
require(_newAccumulator != address(0), "zero address");
accumulator = CurveAccumulator(_newAccumulator);
}
function setRewardsReceiver(address _newRewardsReceiver) external onlyGovernance {
require(_newRewardsReceiver != address(0), "zero address");
rewardsReceiver = _newRewardsReceiver;
}
function setGovernance(address _newGovernance) external onlyGovernance {
require(_newGovernance != address(0), "zero address");
governance = _newGovernance;
}
function setVaultGaugeFactory(address _newVaultGaugeFactory) external onlyGovernance {
require(_newVaultGaugeFactory != address(0), "zero address");
vaultGaugeFactory = _newVaultGaugeFactory;
}
function manageFee(
MANAGEFEE _manageFee,
address _gauge,
uint256 _newFee
) external onlyGovernanceOrFactory {
require(_gauge != address(0), "zero address");
if (_manageFee == MANAGEFEE.PERFFEE) {
perfFee[_gauge] = _newFee;
} else if (_manageFee == MANAGEFEE.VESDTFEE) {
veSDTFee[_gauge] = _newFee;
} else if (_manageFee == MANAGEFEE.ACCUMULATORFEE) {
accumulatorFee[_gauge] = _newFee;
} else if (_manageFee == MANAGEFEE.CLAIMERREWARD) {
claimerRewardFee[_gauge] = _newFee;
}
require(
perfFee[_gauge] +
veSDTFee[_gauge] +
accumulatorFee[_gauge] +
claimerRewardFee[_gauge]
<= BASE_FEE, "fee to high"
);
}
function execute(
address _to,
uint256 _value,
bytes calldata _data
) external onlyGovernance returns (bool, bytes memory) {
(bool success, bytes memory result) = _to.call{ value: _value }(_data);
return (success, result);
}
}
文件 9 的 28:ERC20.sol
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
unchecked {
_approve(sender, _msgSender(), currentAllowance - amount);
}
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
uint256 currentAllowance = _allowances[_msgSender()][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(_msgSender(), spender, currentAllowance - subtractedValue);
}
return true;
}
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[sender] = senderBalance - amount;
}
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
_afterTokenTransfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
文件 10 的 28:IAccessControl.sol
pragma solidity 0.8.7;
interface IAccessControl {
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address account) external;
}
文件 11 的 28:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 12 的 28:IERC20Metadata.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 13 的 28:IGaugeController.sol
pragma solidity 0.8.7;
interface IGaugeController {
function gauge_types(address addr) external view returns (int128);
function gauge_relative_weight_write(address addr, uint256 timestamp) external returns (uint256);
function gauge_relative_weight(address addr) external view returns (uint256);
function gauge_relative_weight(address addr, uint256 timestamp) external view returns (uint256);
function get_total_weight() external view returns (uint256);
function get_gauge_weight(address addr) external view returns (uint256);
}
文件 14 的 28:ILiquidityGauge.sol
pragma solidity 0.8.7;
interface ILiquidityGauge {
struct Reward {
address token;
address distributor;
uint256 period_finish;
uint256 rate;
uint256 last_update;
uint256 integral;
}
function deposit_reward_token(address _rewardToken, uint256 _amount) external;
function claim_rewards_for(address _user, address _recipient) external;
function deposit(uint256 _value, address _addr) external;
function reward_tokens(uint256 _i) external view returns (address);
function reward_data(address _tokenReward) external view returns (Reward memory);
function balanceOf(address) external returns (uint256);
function claimable_reward(address _user, address _reward_token) external view returns (uint256);
function claimable_tokens(address _user) external returns (uint256);
function user_checkpoint(address _user) external returns (bool);
function commit_transfer_ownership(address) external;
function claim_rewards(address) external;
}
文件 15 的 28:ILocker.sol
pragma solidity 0.8.7;
interface ILocker {
function createLock(uint256, uint256) external;
function increaseAmount(uint256) external;
function increaseUnlockTime(uint256) external;
function release() external;
function claimRewards(address,address) external;
function claimFXSRewards(address) external;
function execute(
address,
uint256,
bytes calldata
) external returns (bool, bytes memory);
function setGovernance(address) external;
function voteGaugeWeight(address, uint256) external;
function setAngleDepositor(address) external;
function setFxsDepositor(address) external;
}
文件 16 的 28:IMasterchef.sol
pragma solidity 0.8.7;
interface IMasterchef {
function deposit(uint256, uint256) external;
function withdraw(uint256, uint256) external;
function userInfo(uint256, address) external view returns (uint256, uint256);
function poolInfo(uint256)
external
returns (
address,
uint256,
uint256,
uint256
);
function totalAllocPoint() external view returns (uint256);
function sdtPerBlock() external view returns (uint256);
function pendingSdt(uint256, address) external view returns (uint256);
}
文件 17 的 28:IMultiRewards.sol
pragma solidity 0.8.7;
interface IMultiRewards {
function balanceOf(address) external returns (uint256);
function stakeFor(address, uint256) external;
function withdrawFor(address, uint256) external;
function notifyRewardAmount(address, uint256) external;
function mintFor(address recipient, uint256 amount) external;
function burnFrom(address _from, uint256 _amount) external;
function stakeOf(address account) external view returns (uint256);
}
文件 18 的 28:ISDTDistributor.sol
pragma solidity ^0.8.7;
interface ISDTDistributor {
function distribute(address gaugeAddr) external;
}
文件 19 的 28:ISdtMiddlemanGauge.sol
pragma solidity ^0.8.7;
interface ISdtMiddlemanGauge {
function notifyReward(address gauge, uint256 amount) external;
}
文件 20 的 28:IStakingRewards.sol
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IStakingRewardsFunctions {
function notifyRewardAmount(uint256 reward) external;
function recoverERC20(
address tokenAddress,
address to,
uint256 tokenAmount
) external;
function setNewRewardsDistribution(address newRewardsDistribution) external;
}
interface IStakingRewards is IStakingRewardsFunctions {
function rewardToken() external view returns (IERC20);
}
文件 21 的 28:Initializable.sol
pragma solidity ^0.8.0;
import "../../utils/AddressUpgradeable.sol";
abstract contract Initializable {
bool private _initialized;
bool private _initializing;
modifier initializer() {
require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
function _isConstructor() private view returns (bool) {
return !AddressUpgradeable.isContract(address(this));
}
}
文件 22 的 28:MasterchefMasterToken.sol
pragma solidity 0.8.7;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MasterchefMasterToken is ERC20, Ownable {
constructor() ERC20("Masterchef Master Token", "MMT") {
_mint(msg.sender, 1e18);
}
}
文件 23 的 28:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 24 的 28:ReentrancyGuardUpgradeable.sol
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
abstract contract ReentrancyGuardUpgradeable is Initializable {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal onlyInitializing {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
uint256[49] private __gap;
}
文件 25 的 28:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 26 的 28:SdtDistributorEvents.sol
pragma solidity 0.8.7;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "../interfaces/IGaugeController.sol";
import "../interfaces/ILiquidityGauge.sol";
import "../interfaces/ISdtMiddlemanGauge.sol";
import "../interfaces/IStakingRewards.sol";
import "../interfaces/IMasterchef.sol";
import "./MasterchefMasterToken.sol";
import "../external/AccessControlUpgradeable.sol";
abstract contract SdtDistributorEvents {
event DelegateGaugeUpdated(address indexed _gaugeAddr, address indexed _delegateGauge);
event DistributionsToggled(bool _distributionsOn);
event GaugeControllerUpdated(address indexed _controller);
event GaugeToggled(address indexed gaugeAddr, bool newStatus);
event InterfaceKnownToggled(address indexed _delegateGauge, bool _isInterfaceKnown);
event RateUpdated(uint256 _newRate);
event Recovered(address indexed tokenAddress, address indexed to, uint256 amount);
event RewardDistributed(address indexed gaugeAddr, uint256 sdtDistributed, uint256 lastMasterchefPull);
event UpdateMiningParameters(uint256 time, uint256 rate, uint256 supply);
}
文件 27 的 28:SdtDistributorV2.sol
pragma solidity 0.8.7;
import "./SdtDistributorEvents.sol";
contract SdtDistributorV2 is ReentrancyGuardUpgradeable, AccessControlUpgradeable, SdtDistributorEvents {
using SafeERC20 for IERC20;
uint256 public constant BASE_UNIT = 10_000;
IERC20 public constant rewardToken = IERC20(0x73968b9a57c6E53d41345FD57a6E6ae27d6CDB2F);
IMasterchef public constant masterchef = IMasterchef(0xfEA5E213bbD81A8a94D0E1eDB09dBD7CEab61e1c);
bytes32 public constant GOVERNOR_ROLE = keccak256("GOVERNOR_ROLE");
bytes32 public constant GUARDIAN_ROLE = keccak256("GUARDIAN_ROLE");
uint256 public timePeriod;
IERC20 public masterchefToken;
IGaugeController public controller;
address public delegateGauge;
bool public distributionsOn;
mapping(address => address) public delegateGauges;
mapping(address => bool) public killedGauges;
mapping(address => bool) public isInterfaceKnown;
uint256 public masterchefPID;
uint256 public lastMasterchefPull;
mapping(uint256 => uint256) public pulls;
mapping(uint256 => mapping(address => bool)) public isGaugePaid;
uint256 public claimerFee;
uint256 public lookPastDays;
function initialize(
address _controller,
address _governor,
address _guardian,
address _delegateGauge
) external initializer {
require(_controller != address(0) && _guardian != address(0) && _governor != address(0), "0");
controller = IGaugeController(_controller);
delegateGauge = _delegateGauge;
masterchefToken = IERC20(address(new MasterchefMasterToken()));
distributionsOn = false;
timePeriod = 3600 * 24;
lookPastDays = 45;
_setRoleAdmin(GOVERNOR_ROLE, GOVERNOR_ROLE);
_setRoleAdmin(GUARDIAN_ROLE, GOVERNOR_ROLE);
_setupRole(GUARDIAN_ROLE, _guardian);
_setupRole(GOVERNOR_ROLE, _governor);
_setupRole(GUARDIAN_ROLE, _governor);
}
constructor() initializer {}
function initializeMasterchef(uint256 _pid) external onlyRole(GOVERNOR_ROLE) {
masterchefPID = _pid;
masterchefToken.approve(address(masterchef), 1e18);
masterchef.deposit(_pid, 1e18);
}
function distribute(address gaugeAddr) external nonReentrant {
_distribute(gaugeAddr);
}
function distributeMulti(address[] calldata gaugeAddr) public nonReentrant {
uint256 length = gaugeAddr.length;
for (uint256 i; i < length; i++) {
_distribute(gaugeAddr[i]);
}
}
function _distribute(address gaugeAddr) internal {
require(distributionsOn, "not allowed");
(bool success, bytes memory result) = address(controller).call(
abi.encodeWithSignature("gauge_types(address)", gaugeAddr)
);
if (!success || killedGauges[gaugeAddr]) {
return;
}
int128 gaugeType = abi.decode(result, (int128));
uint256 roundedTimestamp = (block.timestamp / 1 days) * 1 days;
uint256 totalDistribute;
if (block.timestamp > lastMasterchefPull + timePeriod) {
uint256 sdtBefore = rewardToken.balanceOf(address(this));
_pullSDT();
pulls[roundedTimestamp] = rewardToken.balanceOf(address(this)) - sdtBefore;
lastMasterchefPull = roundedTimestamp;
}
for (uint256 i; i < lookPastDays; i++) {
uint256 currentTimestamp = roundedTimestamp - (i * 86_400);
if (pulls[currentTimestamp] > 0) {
bool isPaid = isGaugePaid[currentTimestamp][gaugeAddr];
if (isPaid) {
break;
}
uint256 sdtBalance = pulls[currentTimestamp];
uint256 gaugeRelativeWeight;
if (i == 0) {
gaugeRelativeWeight = controller.gauge_relative_weight_write(gaugeAddr, currentTimestamp);
} else {
gaugeRelativeWeight = controller.gauge_relative_weight(gaugeAddr, currentTimestamp);
}
uint256 sdtDistributed = (sdtBalance * gaugeRelativeWeight) / 1e18;
totalDistribute += sdtDistributed;
isGaugePaid[currentTimestamp][gaugeAddr] = true;
}
}
if (totalDistribute > 0) {
if (gaugeType == 1) {
rewardToken.safeTransfer(gaugeAddr, totalDistribute);
IStakingRewards(gaugeAddr).notifyRewardAmount(totalDistribute);
} else if (gaugeType >= 2) {
address delegate = delegateGauges[gaugeAddr];
if (delegate == address(0)) {
delegate = delegateGauge;
}
if (delegate != address(0)) {
rewardToken.safeTransfer(delegate, totalDistribute);
if (isInterfaceKnown[delegate]) {
ISdtMiddlemanGauge(delegate).notifyReward(gaugeAddr, totalDistribute);
}
} else {
rewardToken.safeTransfer(gaugeAddr, totalDistribute);
}
} else {
ILiquidityGauge(gaugeAddr).deposit_reward_token(address(rewardToken), totalDistribute);
}
emit RewardDistributed(gaugeAddr, totalDistribute, lastMasterchefPull);
}
}
function _pullSDT() internal {
masterchef.withdraw(masterchefPID, 0);
}
function setDistribution(bool _state) external onlyRole(GOVERNOR_ROLE) {
distributionsOn = _state;
}
function setGaugeController(address _controller) external onlyRole(GOVERNOR_ROLE) {
require(_controller != address(0), "0");
controller = IGaugeController(_controller);
emit GaugeControllerUpdated(_controller);
}
function setDelegateGauge(
address gaugeAddr,
address _delegateGauge,
bool toggleInterface
) external onlyRole(GOVERNOR_ROLE) {
if (gaugeAddr != address(0)) {
delegateGauges[gaugeAddr] = _delegateGauge;
} else {
delegateGauge = _delegateGauge;
}
emit DelegateGaugeUpdated(gaugeAddr, _delegateGauge);
if (toggleInterface) {
_toggleInterfaceKnown(_delegateGauge);
}
}
function toggleGauge(address gaugeAddr) external onlyRole(GOVERNOR_ROLE) {
bool gaugeKilledMem = killedGauges[gaugeAddr];
if (!gaugeKilledMem) {
rewardToken.safeApprove(gaugeAddr, 0);
}
killedGauges[gaugeAddr] = !gaugeKilledMem;
emit GaugeToggled(gaugeAddr, !gaugeKilledMem);
}
function toggleInterfaceKnown(address _delegateGauge) external onlyRole(GUARDIAN_ROLE) {
_toggleInterfaceKnown(_delegateGauge);
}
function _toggleInterfaceKnown(address _delegateGauge) internal {
bool isInterfaceKnownMem = isInterfaceKnown[_delegateGauge];
isInterfaceKnown[_delegateGauge] = !isInterfaceKnownMem;
emit InterfaceKnownToggled(_delegateGauge, !isInterfaceKnownMem);
}
function approveGauge(address gaugeAddr) external onlyRole(GOVERNOR_ROLE) {
rewardToken.safeApprove(gaugeAddr, type(uint256).max);
}
function setTimePeriod(uint256 _timePeriod) external onlyRole(GOVERNOR_ROLE) {
require(_timePeriod >= 1 days, "TOO_LOW");
timePeriod = _timePeriod;
}
function setClaimerFee(uint256 _newFee) external onlyRole(GOVERNOR_ROLE) {
require(_newFee <= BASE_UNIT, "TOO_HIGH");
claimerFee = _newFee;
}
function setLookPastDays(uint256 _newLookPastDays) external onlyRole(GOVERNOR_ROLE) {
lookPastDays = _newLookPastDays;
}
function recoverERC20(
address tokenAddress,
address to,
uint256 amount
) external onlyRole(GOVERNOR_ROLE) {
IERC20(tokenAddress).safeTransfer(to, amount);
emit Recovered(tokenAddress, to, amount);
}
}
文件 28 的 28:StringsUpgradeable.sol
pragma solidity ^0.8.0;
library StringsUpgradeable {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
{
"compilationTarget": {
"contracts/strategy/CurveStrategy.sol": "CurveStrategy"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract ILocker","name":"_locker","type":"address"},{"internalType":"address","name":"_governance","type":"address"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"contract CurveAccumulator","name":"_accumulator","type":"address"},{"internalType":"address","name":"_veSDTFeeProxy","type":"address"},{"internalType":"address","name":"_sdtDistributor","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_gauge","type":"address"},{"indexed":false,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"notified","type":"bool"}],"name":"Crv3Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_gauge","type":"address"},{"indexed":false,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_gauge","type":"address"},{"indexed":false,"internalType":"address","name":"_token","type":"address"}],"name":"GaugeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_gauge","type":"address"},{"indexed":false,"internalType":"address","name":"_receiver","type":"address"}],"name":"RewardReceiverSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_vault","type":"address"},{"indexed":false,"internalType":"bool","name":"_newState","type":"bool"}],"name":"VaultToggled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_gauge","type":"address"},{"indexed":false,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"BASE_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CRV","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CRV3","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CRV_FEE_D","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CRV_MINTER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accumulator","outputs":[{"internalType":"contract CurveAccumulator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"accumulatorFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_notify","type":"bool"}],"name":"claim3Crv","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"claimerRewardFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"execute","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gauges","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lGaugeType","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"locker","outputs":[{"internalType":"contract ILocker","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum CurveStrategy.MANAGEFEE","name":"_manageFee","type":"uint8"},{"internalType":"address","name":"_gauge","type":"address"},{"internalType":"uint256","name":"_newFee","type":"uint256"}],"name":"manageFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"migrateLP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"multiGauges","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"perfFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sdtDistributor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"sendToAccumulator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newAccumulator","type":"address"}],"name":"setAccumulator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_gauge","type":"address"}],"name":"setGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newGovernance","type":"address"}],"name":"setGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"},{"internalType":"uint256","name":"_gaugeType","type":"uint256"}],"name":"setLGtype","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"},{"internalType":"address","name":"_multiGauge","type":"address"}],"name":"setMultiGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newRewardsReceiver","type":"address"}],"name":"setRewardsReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newVaultGaugeFactory","type":"address"}],"name":"setVaultGaugeFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newVeSDTProxy","type":"address"}],"name":"setVeSDTProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"}],"name":"toggleVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vaultGaugeFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"vaults","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"veSDTFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"veSDTFeeProxy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]