Contract Source Code:
File 1 of 1 : Timelock
// Sources flattened with hardhat v2.9.3 https://hardhat.org
// File contracts/peripherals/interfaces/ITimelockTarget.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
interface ITimelockTarget {
function setGov(address _gov) external;
function withdrawToken(
address _token,
address _account,
uint256 _amount
) external;
}
// File contracts/peripherals/interfaces/ITimelock.sol
pragma solidity 0.6.12;
interface ITimelock {
function setAdmin(address _admin) external;
function enableLeverage(address _vault) external;
function disableLeverage(address _vault) external;
function setIsLeverageEnabled(address _vault, bool _isLeverageEnabled) external;
function signalSetGov(address _target, address _gov) external;
function managedSetHandler(
address _target,
address _handler,
bool _isActive
) external;
function managedSetMinter(
address _target,
address _minter,
bool _isActive
) external;
}
// File contracts/peripherals/interfaces/IHandlerTarget.sol
pragma solidity 0.6.12;
interface IHandlerTarget {
function isHandler(address _account) external returns (bool);
function setHandler(address _handler, bool _isActive) external;
}
// File contracts/access/interfaces/IAdmin.sol
pragma solidity 0.6.12;
interface IAdmin {
function setAdmin(address _admin) external;
}
// File contracts/core/interfaces/IVaultUtils.sol
pragma solidity 0.6.12;
interface IVaultUtils {
function updateCumulativeFundingRate(address _collateralToken, address _indexToken) external returns (bool);
function validateIncreasePosition(
address _account,
address _collateralToken,
address _indexToken,
uint256 _sizeDelta,
bool _isLong
) external view;
function validateDecreasePosition(
address _account,
address _collateralToken,
address _indexToken,
uint256 _collateralDelta,
uint256 _sizeDelta,
bool _isLong,
address _receiver
) external view;
function validateLiquidation(
address _account,
address _collateralToken,
address _indexToken,
bool _isLong,
bool _raise
) external view returns (uint256, uint256);
function getEntryFundingRate(
address _collateralToken,
address _indexToken,
bool _isLong
) external view returns (uint256);
function getPositionFee(
address _account,
address _collateralToken,
address _indexToken,
bool _isLong,
uint256 _sizeDelta
) external view returns (uint256);
function getFundingFee(
address _account,
address _collateralToken,
address _indexToken,
bool _isLong,
uint256 _size,
uint256 _entryFundingRate
) external view returns (uint256);
function getBuyUsdgFeeBasisPoints(address _token, uint256 _usdgAmount) external view returns (uint256);
function getSellUsdgFeeBasisPoints(address _token, uint256 _usdgAmount) external view returns (uint256);
function getSwapFeeBasisPoints(
address _tokenIn,
address _tokenOut,
uint256 _usdgAmount
) external view returns (uint256);
function getFeeBasisPoints(
address _token,
uint256 _usdgDelta,
uint256 _feeBasisPoints,
uint256 _taxBasisPoints,
bool _increment
) external view returns (uint256);
}
// File contracts/core/interfaces/IVault.sol
pragma solidity 0.6.12;
interface IVault {
function isInitialized() external view returns (bool);
function isSwapEnabled() external view returns (bool);
function isLeverageEnabled() external view returns (bool);
function setVaultUtils(IVaultUtils _vaultUtils) external;
function setError(uint256 _errorCode, string calldata _error) external;
function router() external view returns (address);
function usdg() external view returns (address);
function gov() external view returns (address);
function whitelistedTokenCount() external view returns (uint256);
function maxLeverage() external view returns (uint256);
function minProfitTime() external view returns (uint256);
function hasDynamicFees() external view returns (bool);
function fundingInterval() external view returns (uint256);
function totalTokenWeights() external view returns (uint256);
function getTargetUsdgAmount(address _token) external view returns (uint256);
function inManagerMode() external view returns (bool);
function inPrivateLiquidationMode() external view returns (bool);
function maxGasPrice() external view returns (uint256);
function approvedRouters(address _account, address _router) external view returns (bool);
function isLiquidator(address _account) external view returns (bool);
function isManager(address _account) external view returns (bool);
function minProfitBasisPoints(address _token) external view returns (uint256);
function tokenBalances(address _token) external view returns (uint256);
function lastFundingTimes(address _token) external view returns (uint256);
function setMaxLeverage(uint256 _maxLeverage) external;
function setInManagerMode(bool _inManagerMode) external;
function setManager(address _manager, bool _isManager) external;
function setIsSwapEnabled(bool _isSwapEnabled) external;
function setIsLeverageEnabled(bool _isLeverageEnabled) external;
function setMaxGasPrice(uint256 _maxGasPrice) external;
function setUsdgAmount(address _token, uint256 _amount) external;
function setBufferAmount(address _token, uint256 _amount) external;
function setMaxGlobalShortSize(address _token, uint256 _amount) external;
function setInPrivateLiquidationMode(bool _inPrivateLiquidationMode) external;
function setLiquidator(address _liquidator, bool _isActive) external;
function setFundingRate(
uint256 _fundingInterval,
uint256 _fundingRateFactor,
uint256 _stableFundingRateFactor
) external;
function setFees(
uint256 _taxBasisPoints,
uint256 _stableTaxBasisPoints,
uint256 _mintBurnFeeBasisPoints,
uint256 _swapFeeBasisPoints,
uint256 _stableSwapFeeBasisPoints,
uint256 _marginFeeBasisPoints,
uint256 _liquidationFeeUsd,
uint256 _minProfitTime,
bool _hasDynamicFees
) external;
function setTokenConfig(
address _token,
uint256 _tokenDecimals,
uint256 _redemptionBps,
uint256 _minProfitBps,
uint256 _maxUsdgAmount,
bool _isStable,
bool _isShortable
) external;
function setPriceFeed(address _priceFeed) external;
function withdrawFees(address _token, address _receiver) external returns (uint256);
function directPoolDeposit(address _token) external;
function buyUSDG(address _token, address _receiver) external returns (uint256);
function sellUSDG(address _token, address _receiver) external returns (uint256);
function swap(
address _tokenIn,
address _tokenOut,
address _receiver
) external returns (uint256);
function increasePosition(
address _account,
address _collateralToken,
address _indexToken,
uint256 _sizeDelta,
bool _isLong
) external;
function decreasePosition(
address _account,
address _collateralToken,
address _indexToken,
uint256 _collateralDelta,
uint256 _sizeDelta,
bool _isLong,
address _receiver
) external returns (uint256);
function liquidatePosition(
address _account,
address _collateralToken,
address _indexToken,
bool _isLong,
address _feeReceiver
) external;
function tokenToUsdMin(address _token, uint256 _tokenAmount) external view returns (uint256);
function priceFeed() external view returns (address);
function fundingRateFactor() external view returns (uint256);
function stableFundingRateFactor() external view returns (uint256);
function cumulativeFundingRates(address _token) external view returns (uint256);
function getNextFundingRate(address _token) external view returns (uint256);
function getFeeBasisPoints(
address _token,
uint256 _usdgDelta,
uint256 _feeBasisPoints,
uint256 _taxBasisPoints,
bool _increment
) external view returns (uint256);
function liquidationFeeUsd() external view returns (uint256);
function taxBasisPoints() external view returns (uint256);
function stableTaxBasisPoints() external view returns (uint256);
function mintBurnFeeBasisPoints() external view returns (uint256);
function swapFeeBasisPoints() external view returns (uint256);
function stableSwapFeeBasisPoints() external view returns (uint256);
function marginFeeBasisPoints() external view returns (uint256);
function allWhitelistedTokensLength() external view returns (uint256);
function allWhitelistedTokens(uint256) external view returns (address);
function whitelistedTokens(address _token) external view returns (bool);
function stableTokens(address _token) external view returns (bool);
function shortableTokens(address _token) external view returns (bool);
function feeReserves(address _token) external view returns (uint256);
function globalShortSizes(address _token) external view returns (uint256);
function globalShortAveragePrices(address _token) external view returns (uint256);
function maxGlobalShortSizes(address _token) external view returns (uint256);
function tokenDecimals(address _token) external view returns (uint256);
function tokenWeights(address _token) external view returns (uint256);
function guaranteedUsd(address _token) external view returns (uint256);
function poolAmounts(address _token) external view returns (uint256);
function bufferAmounts(address _token) external view returns (uint256);
function reservedAmounts(address _token) external view returns (uint256);
function usdgAmounts(address _token) external view returns (uint256);
function maxUsdgAmounts(address _token) external view returns (uint256);
function getRedemptionAmount(address _token, uint256 _usdgAmount) external view returns (uint256);
function getMaxPrice(address _token) external view returns (uint256);
function getMinPrice(address _token) external view returns (uint256);
function getDelta(
address _indexToken,
uint256 _size,
uint256 _averagePrice,
bool _isLong,
uint256 _lastIncreasedTime
) external view returns (bool, uint256);
function getPosition(
address _account,
address _collateralToken,
address _indexToken,
bool _isLong
)
external
view
returns (
uint256,
uint256,
uint256,
uint256,
uint256,
uint256,
bool,
uint256
);
}
// File contracts/core/interfaces/IVaultPriceFeed.sol
pragma solidity 0.6.12;
interface IVaultPriceFeed {
function adjustmentBasisPoints(address _token) external view returns (uint256);
function isAdjustmentAdditive(address _token) external view returns (bool);
function setAdjustment(
address _token,
bool _isAdditive,
uint256 _adjustmentBps
) external;
function setUseV2Pricing(bool _useV2Pricing) external;
function setIsAmmEnabled(bool _isEnabled) external;
function setIsSecondaryPriceEnabled(bool _isEnabled) external;
function setSpreadBasisPoints(address _token, uint256 _spreadBasisPoints) external;
function setSpreadThresholdBasisPoints(uint256 _spreadThresholdBasisPoints) external;
function setFavorPrimaryPrice(bool _favorPrimaryPrice) external;
function setPriceSampleSpace(uint256 _priceSampleSpace) external;
function setMaxStrictPriceDeviation(uint256 _maxStrictPriceDeviation) external;
function getPrice(
address _token,
bool _maximise,
bool _includeAmmPrice,
bool _useSwapPricing
) external view returns (uint256);
function getAmmPrice(address _token) external view returns (uint256);
function getPrimaryPrice(address _token, bool _maximise) external view returns (uint256);
function setTokenConfig(
address _token,
address _priceFeed,
uint256 _priceDecimals,
bool _isStrictStable
) external;
}
// File contracts/core/interfaces/IRouter.sol
pragma solidity 0.6.12;
interface IRouter {
function addPlugin(address _plugin) external;
function pluginTransfer(
address _token,
address _account,
address _receiver,
uint256 _amount
) external;
function pluginIncreasePosition(
address _account,
address _collateralToken,
address _indexToken,
uint256 _sizeDelta,
bool _isLong
) external;
function pluginDecreasePosition(
address _account,
address _collateralToken,
address _indexToken,
uint256 _collateralDelta,
uint256 _sizeDelta,
bool _isLong,
address _receiver
) external returns (uint256);
function swap(
address[] memory _path,
uint256 _amountIn,
uint256 _minOut,
address _receiver
) external;
}
// File contracts/tokens/interfaces/IYieldToken.sol
pragma solidity 0.6.12;
interface IYieldToken {
function totalStaked() external view returns (uint256);
function stakedBalance(address _account) external view returns (uint256);
function removeAdmin(address _account) external;
}
// File contracts/tokens/interfaces/IBaseToken.sol
pragma solidity 0.6.12;
interface IBaseToken {
function totalStaked() external view returns (uint256);
function stakedBalance(address _account) external view returns (uint256);
function removeAdmin(address _account) external;
function setInPrivateTransferMode(bool _inPrivateTransferMode) external;
function withdrawToken(
address _token,
address _account,
uint256 _amount
) external;
}
// File contracts/tokens/interfaces/IMintable.sol
pragma solidity 0.6.12;
interface IMintable {
function isMinter(address _account) external returns (bool);
function setMinter(address _minter, bool _isActive) external;
function mint(address _account, uint256 _amount) external;
function burn(address _account, uint256 _amount) external;
}
// File contracts/tokens/interfaces/IUSDG.sol
pragma solidity 0.6.12;
interface IUSDG {
function addVault(address _vault) external;
function removeVault(address _vault) external;
function mint(address _account, uint256 _amount) external;
function burn(address _account, uint256 _amount) external;
}
// File contracts/staking/interfaces/IVester.sol
pragma solidity 0.6.12;
interface IVester {
function rewardTracker() external view returns (address);
function claimForAccount(address _account, address _receiver) external returns (uint256);
function claimable(address _account) external view returns (uint256);
function cumulativeClaimAmounts(address _account) external view returns (uint256);
function claimedAmounts(address _account) external view returns (uint256);
function pairAmounts(address _account) external view returns (uint256);
function getVestedAmount(address _account) external view returns (uint256);
function transferredAverageStakedAmounts(address _account) external view returns (uint256);
function transferredCumulativeRewards(address _account) external view returns (uint256);
function cumulativeRewardDeductions(address _account) external view returns (uint256);
function bonusRewards(address _account) external view returns (uint256);
function transferStakeValues(address _sender, address _receiver) external;
function setTransferredAverageStakedAmounts(address _account, uint256 _amount) external;
function setTransferredCumulativeRewards(address _account, uint256 _amount) external;
function setCumulativeRewardDeductions(address _account, uint256 _amount) external;
function setBonusRewards(address _account, uint256 _amount) external;
function getMaxVestableAmount(address _account) external view returns (uint256);
function getCombinedAverageStakedAmount(address _account) external view returns (uint256);
}
// File contracts/libraries/math/SafeMath.sol
pragma solidity 0.6.12;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
// File contracts/libraries/token/IERC20.sol
pragma solidity 0.6.12;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
// File contracts/peripherals/Timelock.sol
pragma solidity 0.6.12;
contract Timelock is ITimelock {
using SafeMath for uint256;
uint256 public constant PRICE_PRECISION = 10**30;
uint256 public constant MAX_BUFFER = 5 days;
uint256 public constant MAX_FUNDING_RATE_FACTOR = 200; // 0.02%
uint256 public constant MAX_LEVERAGE_VALIDATION = 500000; // 50x
uint256 public buffer;
address public admin;
address public tokenManager;
address public rewardManager;
address public mintReceiver;
uint256 public maxTokenSupply;
uint256 public marginFeeBasisPoints;
uint256 public maxMarginFeeBasisPoints;
bool public shouldToggleIsLeverageEnabled;
mapping(bytes32 => uint256) public pendingActions;
mapping(address => bool) public excludedTokens;
mapping(address => bool) public isHandler;
event SignalPendingAction(bytes32 action);
event SignalApprove(address token, address spender, uint256 amount, bytes32 action);
event SignalWithdrawToken(address target, address token, address receiver, uint256 amount, bytes32 action);
event SignalMint(address token, address receiver, uint256 amount, bytes32 action);
event SignalSetGov(address target, address gov, bytes32 action);
event SignalSetHandler(address target, address handler, bool isActive, bytes32 action);
event SignalSetPriceFeed(address vault, address priceFeed, bytes32 action);
event SignalAddPlugin(address router, address plugin, bytes32 action);
event SignalRedeemUsdg(address vault, address token, uint256 amount);
event SignalVaultSetTokenConfig(
address vault,
address token,
uint256 tokenDecimals,
uint256 tokenWeight,
uint256 minProfitBps,
uint256 maxUsdgAmount,
bool isStable,
bool isShortable
);
event SignalPriceFeedSetTokenConfig(
address vaultPriceFeed,
address token,
address priceFeed,
uint256 priceDecimals,
bool isStrictStable
);
event ClearAction(bytes32 action);
modifier onlyAdmin() {
require(msg.sender == admin, "Timelock: forbidden");
_;
}
modifier onlyAdminOrHandler() {
require(msg.sender == admin || isHandler[msg.sender], "Timelock: forbidden");
_;
}
modifier onlyTokenManager() {
require(msg.sender == tokenManager, "Timelock: forbidden");
_;
}
modifier onlyRewardManager() {
require(msg.sender == rewardManager, "Timelock: forbidden");
_;
}
constructor(
address _admin,
uint256 _buffer,
address _rewardManager,
address _tokenManager,
address _mintReceiver,
uint256 _maxTokenSupply,
uint256 _marginFeeBasisPoints,
uint256 _maxMarginFeeBasisPoints
) public {
require(_buffer <= MAX_BUFFER, "Timelock: invalid _buffer");
admin = _admin;
buffer = _buffer;
rewardManager = _rewardManager;
tokenManager = _tokenManager;
mintReceiver = _mintReceiver;
maxTokenSupply = _maxTokenSupply;
marginFeeBasisPoints = _marginFeeBasisPoints;
maxMarginFeeBasisPoints = _maxMarginFeeBasisPoints;
}
function setAdmin(address _admin) external override onlyTokenManager {
admin = _admin;
}
function setExternalAdmin(address _target, address _admin) external onlyAdmin {
require(_target != address(this), "Timelock: invalid _target");
IAdmin(_target).setAdmin(_admin);
}
function setContractHandler(address _handler, bool _isActive) external onlyAdmin {
isHandler[_handler] = _isActive;
}
function setBuffer(uint256 _buffer) external onlyAdmin {
require(_buffer <= MAX_BUFFER, "Timelock: invalid _buffer");
require(_buffer > buffer, "Timelock: buffer cannot be decreased");
buffer = _buffer;
}
function mint(address _token, uint256 _amount) external onlyAdmin {
_mint(_token, mintReceiver, _amount);
}
function setMaxLeverage(address _vault, uint256 _maxLeverage) external onlyAdmin {
require(_maxLeverage > MAX_LEVERAGE_VALIDATION, "Timelock: invalid _maxLeverage");
IVault(_vault).setMaxLeverage(_maxLeverage);
}
function setFundingRate(
address _vault,
uint256 _fundingInterval,
uint256 _fundingRateFactor,
uint256 _stableFundingRateFactor
) external onlyAdmin {
require(_fundingRateFactor < MAX_FUNDING_RATE_FACTOR, "Timelock: invalid _fundingRateFactor");
require(_stableFundingRateFactor < MAX_FUNDING_RATE_FACTOR, "Timelock: invalid _stableFundingRateFactor");
IVault(_vault).setFundingRate(_fundingInterval, _fundingRateFactor, _stableFundingRateFactor);
}
function setShouldToggleIsLeverageEnabled(bool _shouldToggleIsLeverageEnabled) external onlyAdmin {
shouldToggleIsLeverageEnabled = _shouldToggleIsLeverageEnabled;
}
function setMarginFeeBasisPoints(uint256 _marginFeeBasisPoints, uint256 _maxMarginFeeBasisPoints)
external
onlyAdmin
{
marginFeeBasisPoints = _marginFeeBasisPoints;
maxMarginFeeBasisPoints = _maxMarginFeeBasisPoints;
}
// assign _marginFeeBasisPoints to this.marginFeeBasisPoints
// because enableLeverage would update Vault.marginFeeBasisPoints to this.marginFeeBasisPoints
// and disableLeverage would reset the Vault.marginFeeBasisPoints to this.maxMarginFeeBasisPoints
function setFees(
address _vault,
uint256 _taxBasisPoints,
uint256 _stableTaxBasisPoints,
uint256 _mintBurnFeeBasisPoints,
uint256 _swapFeeBasisPoints,
uint256 _stableSwapFeeBasisPoints,
uint256 _marginFeeBasisPoints,
uint256 _liquidationFeeUsd,
uint256 _minProfitTime,
bool _hasDynamicFees
) external onlyAdmin {
marginFeeBasisPoints = _marginFeeBasisPoints;
IVault(_vault).setFees(
_taxBasisPoints,
_stableTaxBasisPoints,
_mintBurnFeeBasisPoints,
_swapFeeBasisPoints,
_stableSwapFeeBasisPoints,
maxMarginFeeBasisPoints,
_liquidationFeeUsd,
_minProfitTime,
_hasDynamicFees
);
}
function enableLeverage(address _vault) external override onlyAdminOrHandler {
IVault vault = IVault(_vault);
if (shouldToggleIsLeverageEnabled) {
vault.setIsLeverageEnabled(true);
}
vault.setFees(
vault.taxBasisPoints(),
vault.stableTaxBasisPoints(),
vault.mintBurnFeeBasisPoints(),
vault.swapFeeBasisPoints(),
vault.stableSwapFeeBasisPoints(),
marginFeeBasisPoints,
vault.liquidationFeeUsd(),
vault.minProfitTime(),
vault.hasDynamicFees()
);
}
function disableLeverage(address _vault) external override onlyAdminOrHandler {
IVault vault = IVault(_vault);
if (shouldToggleIsLeverageEnabled) {
vault.setIsLeverageEnabled(false);
}
vault.setFees(
vault.taxBasisPoints(),
vault.stableTaxBasisPoints(),
vault.mintBurnFeeBasisPoints(),
vault.swapFeeBasisPoints(),
vault.stableSwapFeeBasisPoints(),
maxMarginFeeBasisPoints, // marginFeeBasisPoints
vault.liquidationFeeUsd(),
vault.minProfitTime(),
vault.hasDynamicFees()
);
}
function setIsLeverageEnabled(address _vault, bool _isLeverageEnabled) external override onlyAdminOrHandler {
IVault(_vault).setIsLeverageEnabled(_isLeverageEnabled);
}
function setTokenConfig(
address _vault,
address _token,
uint256 _tokenWeight,
uint256 _minProfitBps,
uint256 _maxUsdgAmount,
uint256 _bufferAmount,
uint256 _usdgAmount
) external onlyAdmin {
require(_minProfitBps <= 500, "Timelock: invalid _minProfitBps");
IVault vault = IVault(_vault);
require(vault.whitelistedTokens(_token), "Timelock: token not yet whitelisted");
uint256 tokenDecimals = vault.tokenDecimals(_token);
bool isStable = vault.stableTokens(_token);
bool isShortable = vault.shortableTokens(_token);
IVault(_vault).setTokenConfig(
_token,
tokenDecimals,
_tokenWeight,
_minProfitBps,
_maxUsdgAmount,
isStable,
isShortable
);
IVault(_vault).setBufferAmount(_token, _bufferAmount);
IVault(_vault).setUsdgAmount(_token, _usdgAmount);
}
function setMaxGlobalShortSize(
address _vault,
address _token,
uint256 _amount
) external onlyAdmin {
IVault(_vault).setMaxGlobalShortSize(_token, _amount);
}
function removeAdmin(address _token, address _account) external onlyAdmin {
IYieldToken(_token).removeAdmin(_account);
}
function setIsAmmEnabled(address _priceFeed, bool _isEnabled) external onlyAdmin {
IVaultPriceFeed(_priceFeed).setIsAmmEnabled(_isEnabled);
}
function setIsSecondaryPriceEnabled(address _priceFeed, bool _isEnabled) external onlyAdmin {
IVaultPriceFeed(_priceFeed).setIsSecondaryPriceEnabled(_isEnabled);
}
function setMaxStrictPriceDeviation(address _priceFeed, uint256 _maxStrictPriceDeviation) external onlyAdmin {
IVaultPriceFeed(_priceFeed).setMaxStrictPriceDeviation(_maxStrictPriceDeviation);
}
function setUseV2Pricing(address _priceFeed, bool _useV2Pricing) external onlyAdmin {
IVaultPriceFeed(_priceFeed).setUseV2Pricing(_useV2Pricing);
}
function setAdjustment(
address _priceFeed,
address _token,
bool _isAdditive,
uint256 _adjustmentBps
) external onlyAdmin {
IVaultPriceFeed(_priceFeed).setAdjustment(_token, _isAdditive, _adjustmentBps);
}
function setSpreadBasisPoints(
address _priceFeed,
address _token,
uint256 _spreadBasisPoints
) external onlyAdmin {
IVaultPriceFeed(_priceFeed).setSpreadBasisPoints(_token, _spreadBasisPoints);
}
function setSpreadThresholdBasisPoints(address _priceFeed, uint256 _spreadThresholdBasisPoints) external onlyAdmin {
IVaultPriceFeed(_priceFeed).setSpreadThresholdBasisPoints(_spreadThresholdBasisPoints);
}
function setFavorPrimaryPrice(address _priceFeed, bool _favorPrimaryPrice) external onlyAdmin {
IVaultPriceFeed(_priceFeed).setFavorPrimaryPrice(_favorPrimaryPrice);
}
function setPriceSampleSpace(address _priceFeed, uint256 _priceSampleSpace) external onlyAdmin {
require(_priceSampleSpace <= 5, "Invalid _priceSampleSpace");
IVaultPriceFeed(_priceFeed).setPriceSampleSpace(_priceSampleSpace);
}
function setIsSwapEnabled(address _vault, bool _isSwapEnabled) external onlyAdmin {
IVault(_vault).setIsSwapEnabled(_isSwapEnabled);
}
function setVaultUtils(address _vault, IVaultUtils _vaultUtils) external onlyAdmin {
IVault(_vault).setVaultUtils(_vaultUtils);
}
function setMaxGasPrice(address _vault, uint256 _maxGasPrice) external onlyAdmin {
require(_maxGasPrice > 5000000000, "Invalid _maxGasPrice");
IVault(_vault).setMaxGasPrice(_maxGasPrice);
}
function withdrawFees(
address _vault,
address _token,
address _receiver
) external onlyAdmin {
IVault(_vault).withdrawFees(_token, _receiver);
}
function setInPrivateLiquidationMode(address _vault, bool _inPrivateLiquidationMode) external onlyAdmin {
IVault(_vault).setInPrivateLiquidationMode(_inPrivateLiquidationMode);
}
function setLiquidator(
address _vault,
address _liquidator,
bool _isActive
) external onlyAdmin {
IVault(_vault).setLiquidator(_liquidator, _isActive);
}
function addExcludedToken(address _token) external onlyAdmin {
excludedTokens[_token] = true;
}
function setInPrivateTransferMode(address _token, bool _inPrivateTransferMode) external onlyAdmin {
if (excludedTokens[_token]) {
// excludedTokens can only have their transfers enabled
require(_inPrivateTransferMode == false, "Timelock: invalid _inPrivateTransferMode");
}
IBaseToken(_token).setInPrivateTransferMode(_inPrivateTransferMode);
}
function managedSetHandler(
address _target,
address _handler,
bool _isActive
) external override onlyRewardManager {
IHandlerTarget(_target).setHandler(_handler, _isActive);
}
function managedSetMinter(
address _target,
address _minter,
bool _isActive
) external override onlyRewardManager {
IMintable(_target).setMinter(_minter, _isActive);
}
function batchSetBonusRewards(
address _vester,
address[] memory _accounts,
uint256[] memory _amounts
) external onlyAdmin {
require(_accounts.length == _amounts.length, "Timelock: invalid lengths");
if (!IHandlerTarget(_vester).isHandler(address(this))) {
IHandlerTarget(_vester).setHandler(address(this), true);
}
for (uint256 i = 0; i < _accounts.length; i++) {
address account = _accounts[i];
uint256 amount = _amounts[i];
IVester(_vester).setBonusRewards(account, amount);
}
}
function transferIn(
address _sender,
address _token,
uint256 _amount
) external onlyAdmin {
IERC20(_token).transferFrom(_sender, address(this), _amount);
}
function signalApprove(
address _token,
address _spender,
uint256 _amount
) external onlyAdmin {
bytes32 action = keccak256(abi.encodePacked("approve", _token, _spender, _amount));
_setPendingAction(action);
emit SignalApprove(_token, _spender, _amount, action);
}
function approve(
address _token,
address _spender,
uint256 _amount
) external onlyAdmin {
bytes32 action = keccak256(abi.encodePacked("approve", _token, _spender, _amount));
_validateAction(action);
_clearAction(action);
IERC20(_token).approve(_spender, _amount);
}
function signalWithdrawToken(
address _target,
address _token,
address _receiver,
uint256 _amount
) external onlyAdmin {
bytes32 action = keccak256(abi.encodePacked("withdrawToken", _target, _token, _receiver, _amount));
_setPendingAction(action);
emit SignalWithdrawToken(_target, _token, _receiver, _amount, action);
}
function withdrawToken(
address _target,
address _token,
address _receiver,
uint256 _amount
) external onlyAdmin {
bytes32 action = keccak256(abi.encodePacked("withdrawToken", _target, _token, _receiver, _amount));
_validateAction(action);
_clearAction(action);
IBaseToken(_target).withdrawToken(_token, _receiver, _amount);
}
function signalMint(
address _token,
address _receiver,
uint256 _amount
) external onlyAdmin {
bytes32 action = keccak256(abi.encodePacked("mint", _token, _receiver, _amount));
_setPendingAction(action);
emit SignalMint(_token, _receiver, _amount, action);
}
function processMint(
address _token,
address _receiver,
uint256 _amount
) external onlyAdmin {
bytes32 action = keccak256(abi.encodePacked("mint", _token, _receiver, _amount));
_validateAction(action);
_clearAction(action);
_mint(_token, _receiver, _amount);
}
function signalSetGov(address _target, address _gov) external override onlyAdmin {
bytes32 action = keccak256(abi.encodePacked("setGov", _target, _gov));
_setPendingAction(action);
emit SignalSetGov(_target, _gov, action);
}
function setGov(address _target, address _gov) external onlyAdmin {
bytes32 action = keccak256(abi.encodePacked("setGov", _target, _gov));
_validateAction(action);
_clearAction(action);
ITimelockTarget(_target).setGov(_gov);
}
function signalSetHandler(
address _target,
address _handler,
bool _isActive
) external onlyAdmin {
bytes32 action = keccak256(abi.encodePacked("setHandler", _target, _handler, _isActive));
_setPendingAction(action);
emit SignalSetHandler(_target, _handler, _isActive, action);
}
function setHandler(
address _target,
address _handler,
bool _isActive
) external onlyAdmin {
bytes32 action = keccak256(abi.encodePacked("setHandler", _target, _handler, _isActive));
_validateAction(action);
_clearAction(action);
IHandlerTarget(_target).setHandler(_handler, _isActive);
}
function signalSetPriceFeed(address _vault, address _priceFeed) external onlyAdmin {
bytes32 action = keccak256(abi.encodePacked("setPriceFeed", _vault, _priceFeed));
_setPendingAction(action);
emit SignalSetPriceFeed(_vault, _priceFeed, action);
}
function setPriceFeed(address _vault, address _priceFeed) external onlyAdmin {
bytes32 action = keccak256(abi.encodePacked("setPriceFeed", _vault, _priceFeed));
_validateAction(action);
_clearAction(action);
IVault(_vault).setPriceFeed(_priceFeed);
}
function signalAddPlugin(address _router, address _plugin) external onlyAdmin {
bytes32 action = keccak256(abi.encodePacked("addPlugin", _router, _plugin));
_setPendingAction(action);
emit SignalAddPlugin(_router, _plugin, action);
}
function addPlugin(address _router, address _plugin) external onlyAdmin {
bytes32 action = keccak256(abi.encodePacked("addPlugin", _router, _plugin));
_validateAction(action);
_clearAction(action);
IRouter(_router).addPlugin(_plugin);
}
function signalRedeemUsdg(
address _vault,
address _token,
uint256 _amount
) external onlyAdmin {
bytes32 action = keccak256(abi.encodePacked("redeemUsdg", _vault, _token, _amount));
_setPendingAction(action);
emit SignalRedeemUsdg(_vault, _token, _amount);
}
function redeemUsdg(
address _vault,
address _token,
uint256 _amount
) external onlyAdmin {
bytes32 action = keccak256(abi.encodePacked("redeemUsdg", _vault, _token, _amount));
_validateAction(action);
_clearAction(action);
address usdg = IVault(_vault).usdg();
IVault(_vault).setManager(address(this), true);
IUSDG(usdg).addVault(address(this));
IUSDG(usdg).mint(address(this), _amount);
IERC20(usdg).transfer(address(_vault), _amount);
IVault(_vault).sellUSDG(_token, mintReceiver);
IVault(_vault).setManager(address(this), false);
IUSDG(usdg).removeVault(address(this));
}
function signalVaultSetTokenConfig(
address _vault,
address _token,
uint256 _tokenDecimals,
uint256 _tokenWeight,
uint256 _minProfitBps,
uint256 _maxUsdgAmount,
bool _isStable,
bool _isShortable
) external onlyAdmin {
bytes32 action = keccak256(
abi.encodePacked(
"vaultSetTokenConfig",
_vault,
_token,
_tokenDecimals,
_tokenWeight,
_minProfitBps,
_maxUsdgAmount,
_isStable,
_isShortable
)
);
_setPendingAction(action);
emit SignalVaultSetTokenConfig(
_vault,
_token,
_tokenDecimals,
_tokenWeight,
_minProfitBps,
_maxUsdgAmount,
_isStable,
_isShortable
);
}
function vaultSetTokenConfig(
address _vault,
address _token,
uint256 _tokenDecimals,
uint256 _tokenWeight,
uint256 _minProfitBps,
uint256 _maxUsdgAmount,
bool _isStable,
bool _isShortable
) external onlyAdmin {
bytes32 action = keccak256(
abi.encodePacked(
"vaultSetTokenConfig",
_vault,
_token,
_tokenDecimals,
_tokenWeight,
_minProfitBps,
_maxUsdgAmount,
_isStable,
_isShortable
)
);
_validateAction(action);
_clearAction(action);
IVault(_vault).setTokenConfig(
_token,
_tokenDecimals,
_tokenWeight,
_minProfitBps,
_maxUsdgAmount,
_isStable,
_isShortable
);
}
function signalPriceFeedSetTokenConfig(
address _vaultPriceFeed,
address _token,
address _priceFeed,
uint256 _priceDecimals,
bool _isStrictStable
) external onlyAdmin {
bytes32 action = keccak256(
abi.encodePacked(
"priceFeedSetTokenConfig",
_vaultPriceFeed,
_token,
_priceFeed,
_priceDecimals,
_isStrictStable
)
);
_setPendingAction(action);
emit SignalPriceFeedSetTokenConfig(_vaultPriceFeed, _token, _priceFeed, _priceDecimals, _isStrictStable);
}
function priceFeedSetTokenConfig(
address _vaultPriceFeed,
address _token,
address _priceFeed,
uint256 _priceDecimals,
bool _isStrictStable
) external onlyAdmin {
bytes32 action = keccak256(
abi.encodePacked(
"priceFeedSetTokenConfig",
_vaultPriceFeed,
_token,
_priceFeed,
_priceDecimals,
_isStrictStable
)
);
_validateAction(action);
_clearAction(action);
IVaultPriceFeed(_vaultPriceFeed).setTokenConfig(_token, _priceFeed, _priceDecimals, _isStrictStable);
}
function cancelAction(bytes32 _action) external onlyAdmin {
_clearAction(_action);
}
function _mint(
address _token,
address _receiver,
uint256 _amount
) private {
IMintable mintable = IMintable(_token);
if (!mintable.isMinter(address(this))) {
mintable.setMinter(address(this), true);
}
mintable.mint(_receiver, _amount);
require(IERC20(_token).totalSupply() <= maxTokenSupply, "Timelock: maxTokenSupply exceeded");
}
function _setPendingAction(bytes32 _action) private {
pendingActions[_action] = block.timestamp.add(buffer);
emit SignalPendingAction(_action);
}
function _validateAction(bytes32 _action) private view {
require(pendingActions[_action] != 0, "Timelock: action not signalled");
require(pendingActions[_action] < block.timestamp, "Timelock: action time not yet passed");
}
function _clearAction(bytes32 _action) private {
require(pendingActions[_action] != 0, "Timelock: invalid _action");
delete pendingActions[_action];
emit ClearAction(_action);
}
}