Description:
Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"external/evk-periphery/src/Governor/GovernorAccessControlEmergency.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import {GovernorAccessControl} from "./GovernorAccessControl.sol";
import {AmountCap, AmountCapLib} from "evk/EVault/shared/types/AmountCap.sol";
import {IGovernance} from "evk/EVault/IEVault.sol";
import "evk/EVault/shared/Constants.sol";
/// @title GovernorAccessControlEmergency
/// @custom:security-contact security@euler.xyz
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice A limited governor contract that allows whitelisted callers to call specific functions on target contracts.
/// It special cases setting LTVs, setting hook config and setting caps to enable custom emergency flows.
contract GovernorAccessControlEmergency is GovernorAccessControl {
using AmountCapLib for AmountCap;
/// @notice Role identifier for emergency borrow LTV adjustments
bytes32 public constant LTV_EMERGENCY_ROLE = keccak256("LTV_EMERGENCY_ROLE");
/// @notice Role identifier for emergency vault operations disabling
bytes32 public constant HOOK_EMERGENCY_ROLE = keccak256("HOOK_EMERGENCY_ROLE");
/// @notice Role identifier for emergency supply and borrow caps adjustments
bytes32 public constant CAPS_EMERGENCY_ROLE = keccak256("CAPS_EMERGENCY_ROLE");
/// @notice Constructor
/// @param evc The address of the EVC.
/// @param admin The address to be granted the DEFAULT_ADMIN_ROLE.
constructor(address evc, address admin) GovernorAccessControl(evc, admin) {}
/// @dev Emergency process allows authorized users to lower borrow LTV without changing liquidation LTV. As with all
/// changes to borrow LTV, this takes effect immediately. The current ramp state for liquidation LTV (if any) is
/// preserved, overriding passed rampDuration parameter if necessary.
function setLTV(address collateral, uint16 borrowLTV, uint16 liquidationLTV, uint32 rampDuration)
external
virtual
onlyEVCAccountOwner
{
IGovernance vault = IGovernance(_targetContract());
(uint16 currentBorrowLTV, uint16 currentLiquidationLTV,, uint48 currentTargetTimestamp,) =
vault.LTVFull(collateral);
bool isEmergency = borrowLTV < currentBorrowLTV && liquidationLTV == currentLiquidationLTV;
if (isEmergency && hasRole(LTV_EMERGENCY_ROLE, _msgSender())) {
rampDuration =
currentTargetTimestamp <= block.timestamp ? 0 : uint32(currentTargetTimestamp - block.timestamp);
} else {
_authenticateCaller();
}
vault.setLTV(collateral, borrowLTV, liquidationLTV, rampDuration);
}
/// @dev Emergency process allows authorized users to disable all operations on the vault.
function setHookConfig(address newHookTarget, uint32 newHookedOps) external virtual onlyEVCAccountOwner {
IGovernance vault = IGovernance(_targetContract());
bool isEmergency = newHookTarget == address(0) && newHookedOps == OP_MAX_VALUE - 1;
if (!isEmergency || !hasRole(HOOK_EMERGENCY_ROLE, _msgSender())) {
_authenticateCaller();
}
vault.setHookConfig(newHookTarget, newHookedOps);
}
/// @dev Emergency process allows authorized users to lower the caps.
function setCaps(uint16 supplyCap, uint16 borrowCap) external virtual onlyEVCAccountOwner {
IGovernance vault = IGovernance(_targetContract());
uint256 supplyCapResolved = AmountCap.wrap(supplyCap).resolve();
uint256 borrowCapResolved = AmountCap.wrap(borrowCap).resolve();
(uint256 currentSupplyCapResolved, uint256 currentBorrowCapResolved) = vault.caps();
currentSupplyCapResolved = AmountCap.wrap(uint16(currentSupplyCapResolved)).resolve();
currentBorrowCapResolved = AmountCap.wrap(uint16(currentBorrowCapResolved)).resolve();
bool isEmergency = (
supplyCapResolved < currentSupplyCapResolved || borrowCapResolved < currentBorrowCapResolved
) && (supplyCapResolved <= currentSupplyCapResolved && borrowCapResolved <= currentBorrowCapResolved);
if (!isEmergency || !hasRole(CAPS_EMERGENCY_ROLE, _msgSender())) {
_authenticateCaller();
}
vault.setCaps(supplyCap, borrowCap);
}
}
"
},
"external/evk-periphery/src/Governor/GovernorAccessControl.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import {SelectorAccessControl} from "../AccessControl/SelectorAccessControl.sol";
import {RevertBytes} from "evk/EVault/shared/lib/RevertBytes.sol";
/// @title GovernorAccessControl
/// @custom:security-contact security@euler.xyz
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice A limited governor contract that allows whitelisted callers to call specific functions on target contracts.
contract GovernorAccessControl is SelectorAccessControl {
/// @notice Error thrown when the message data is invalid.
error MsgDataInvalid();
/// @notice Constructor
/// @param evc The address of the EVC.
/// @param admin The address to be granted the DEFAULT_ADMIN_ROLE.
constructor(address evc, address admin) SelectorAccessControl(evc, admin) {}
/// @notice Fallback function to forward calls to target contracts.
/// @dev This function authenticates the caller, extracts the target contract address from the calldata, and
/// forwards the call to the target contract.
fallback() external {
_authenticateCaller();
address targetContract = _targetContract();
assembly {
let forwardDataSize := sub(calldatasize(), 20)
calldatacopy(0, 0, forwardDataSize)
let result := call(gas(), targetContract, 0, 0, forwardDataSize, 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}
}
/// @notice Returns the selector of this function to identify this contract as a GovernorAccessControl contract
/// instance
function isGovernorAccessControl() external pure returns (bytes4) {
return this.isGovernorAccessControl.selector;
}
/// @notice Authenticates the caller based on their role and the function selector. In case of authentication
/// through the EVC, it ensures that the caller is the EVC account owner.
/// @inheritdoc SelectorAccessControl
function _authenticateCaller() internal view virtual override onlyEVCAccountOwner {
super._authenticateCaller();
}
/// @notice Extracts the target contract address from the calldata.
/// @return targetContract The address of the target contract
function _targetContract() internal view virtual returns (address targetContract) {
if (msg.data.length <= 20) revert MsgDataInvalid();
assembly {
targetContract := shr(96, calldataload(sub(calldatasize(), 20)))
}
}
}
"
},
"external/evk-periphery/lib/euler-vault-kit/src/EVault/shared/types/AmountCap.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import {AmountCap} from "./Types.sol";
/// @title AmountCapLib
/// @custom:security-contact security@euler.xyz
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice Library for `AmountCap` custom type
/// @dev AmountCaps are 16-bit decimal floating point values:
/// * The least significant 6 bits are the exponent
/// * The most significant 10 bits are the mantissa, scaled by 100
/// * The special value of 0 means limit is not set
/// * This is so that uninitialized storage implies no limit
/// * For an actual cap value of 0, use a zero mantissa and non-zero exponent
library AmountCapLib {
function resolve(AmountCap self) internal pure returns (uint256) {
uint256 amountCap = AmountCap.unwrap(self);
if (amountCap == 0) return type(uint256).max;
unchecked {
// Cannot overflow because this is less than 2**256:
// 10**(2**6 - 1) * (2**10 - 1) = 1.023e+66
return 10 ** (amountCap & 63) * (amountCap >> 6) / 100;
}
}
function toRawUint16(AmountCap self) internal pure returns (uint16) {
return AmountCap.unwrap(self);
}
}
"
},
"external/evk-periphery/lib/euler-vault-kit/src/EVault/IEVault.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;
import {IVault as IEVCVault} from "ethereum-vault-connector/interfaces/IVault.sol";
// Full interface of EVault and all it's modules
/// @title IInitialize
/// @notice Interface of the initialization module of EVault
interface IInitialize {
/// @notice Initialization of the newly deployed proxy contract
/// @param proxyCreator Account which created the proxy or should be the initial governor
function initialize(address proxyCreator) external;
}
/// @title IERC20
/// @notice Interface of the EVault's Initialize module
interface IERC20 {
/// @notice Vault share token (eToken) name, ie "Euler Vault: DAI"
/// @return The name of the eToken
function name() external view returns (string memory);
/// @notice Vault share token (eToken) symbol, ie "eDAI"
/// @return The symbol of the eToken
function symbol() external view returns (string memory);
/// @notice Decimals, the same as the asset's or 18 if the asset doesn't implement `decimals()`
/// @return The decimals of the eToken
function decimals() external view returns (uint8);
/// @notice Sum of all eToken balances
/// @return The total supply of the eToken
function totalSupply() external view returns (uint256);
/// @notice Balance of a particular account, in eTokens
/// @param account Address to query
/// @return The balance of the account
function balanceOf(address account) external view returns (uint256);
/// @notice Retrieve the current allowance
/// @param holder The account holding the eTokens
/// @param spender Trusted address
/// @return The allowance from holder for spender
function allowance(address holder, address spender) external view returns (uint256);
/// @notice Transfer eTokens to another address
/// @param to Recipient account
/// @param amount In shares.
/// @return True if transfer succeeded
function transfer(address to, uint256 amount) external returns (bool);
/// @notice Transfer eTokens from one address to another
/// @param from This address must've approved the to address
/// @param to Recipient account
/// @param amount In shares
/// @return True if transfer succeeded
function transferFrom(address from, address to, uint256 amount) external returns (bool);
/// @notice Allow spender to access an amount of your eTokens
/// @param spender Trusted address
/// @param amount Use max uint for "infinite" allowance
/// @return True if approval succeeded
function approve(address spender, uint256 amount) external returns (bool);
}
/// @title IToken
/// @notice Interface of the EVault's Token module
interface IToken is IERC20 {
/// @notice Transfer the full eToken balance of an address to another
/// @param from This address must've approved the to address
/// @param to Recipient account
/// @return True if transfer succeeded
function transferFromMax(address from, address to) external returns (bool);
}
/// @title IERC4626
/// @notice Interface of an ERC4626 vault
interface IERC4626 {
/// @notice Vault's underlying asset
/// @return The vault's underlying asset
function asset() external view returns (address);
/// @notice Total amount of managed assets, cash and borrows
/// @return The total amount of assets
function totalAssets() external view returns (uint256);
/// @notice Calculate amount of assets corresponding to the requested shares amount
/// @param shares Amount of shares to convert
/// @return The amount of assets
function convertToAssets(uint256 shares) external view returns (uint256);
/// @notice Calculate amount of shares corresponding to the requested assets amount
/// @param assets Amount of assets to convert
/// @return The amount of shares
function convertToShares(uint256 assets) external view returns (uint256);
/// @notice Fetch the maximum amount of assets a user can deposit
/// @param account Address to query
/// @return The max amount of assets the account can deposit
function maxDeposit(address account) external view returns (uint256);
/// @notice Calculate an amount of shares that would be created by depositing assets
/// @param assets Amount of assets deposited
/// @return Amount of shares received
function previewDeposit(uint256 assets) external view returns (uint256);
/// @notice Fetch the maximum amount of shares a user can mint
/// @param account Address to query
/// @return The max amount of shares the account can mint
function maxMint(address account) external view returns (uint256);
/// @notice Calculate an amount of assets that would be required to mint requested amount of shares
/// @param shares Amount of shares to be minted
/// @return Required amount of assets
function previewMint(uint256 shares) external view returns (uint256);
/// @notice Fetch the maximum amount of assets a user is allowed to withdraw
/// @param owner Account holding the shares
/// @return The maximum amount of assets the owner is allowed to withdraw
function maxWithdraw(address owner) external view returns (uint256);
/// @notice Calculate the amount of shares that will be burned when withdrawing requested amount of assets
/// @param assets Amount of assets withdrawn
/// @return Amount of shares burned
function previewWithdraw(uint256 assets) external view returns (uint256);
/// @notice Fetch the maximum amount of shares a user is allowed to redeem for assets
/// @param owner Account holding the shares
/// @return The maximum amount of shares the owner is allowed to redeem
function maxRedeem(address owner) external view returns (uint256);
/// @notice Calculate the amount of assets that will be transferred when redeeming requested amount of shares
/// @param shares Amount of shares redeemed
/// @return Amount of assets transferred
function previewRedeem(uint256 shares) external view returns (uint256);
/// @notice Transfer requested amount of underlying tokens from sender to the vault pool in return for shares
/// @param amount Amount of assets to deposit (use max uint256 for full underlying token balance)
/// @param receiver An account to receive the shares
/// @return Amount of shares minted
/// @dev Deposit will round down the amount of assets that are converted to shares. To prevent losses consider using
/// mint instead.
function deposit(uint256 amount, address receiver) external returns (uint256);
/// @notice Transfer underlying tokens from sender to the vault pool in return for requested amount of shares
/// @param amount Amount of shares to be minted
/// @param receiver An account to receive the shares
/// @return Amount of assets deposited
function mint(uint256 amount, address receiver) external returns (uint256);
/// @notice Transfer requested amount of underlying tokens from the vault and decrease account's shares balance
/// @param amount Amount of assets to withdraw
/// @param receiver Account to receive the withdrawn assets
/// @param owner Account holding the shares to burn
/// @return Amount of shares burned
function withdraw(uint256 amount, address receiver, address owner) external returns (uint256);
/// @notice Burn requested shares and transfer corresponding underlying tokens from the vault to the receiver
/// @param amount Amount of shares to burn (use max uint256 to burn full owner balance)
/// @param receiver Account to receive the withdrawn assets
/// @param owner Account holding the shares to burn.
/// @return Amount of assets transferred
function redeem(uint256 amount, address receiver, address owner) external returns (uint256);
}
/// @title IVault
/// @notice Interface of the EVault's Vault module
interface IVault is IERC4626 {
/// @notice Balance of the fees accumulator, in shares
/// @return The accumulated fees in shares
function accumulatedFees() external view returns (uint256);
/// @notice Balance of the fees accumulator, in underlying units
/// @return The accumulated fees in asset units
function accumulatedFeesAssets() external view returns (uint256);
/// @notice Address of the original vault creator
/// @return The address of the creator
function creator() external view returns (address);
/// @notice Creates shares for the receiver, from excess asset balances of the vault (not accounted for in `cash`)
/// @param amount Amount of assets to claim (use max uint256 to claim all available assets)
/// @param receiver An account to receive the shares
/// @return Amount of shares minted
/// @dev Could be used as an alternative deposit flow in certain scenarios. E.g. swap directly to the vault, call
/// `skim` to claim deposit.
function skim(uint256 amount, address receiver) external returns (uint256);
}
/// @title IBorrowing
/// @notice Interface of the EVault's Borrowing module
interface IBorrowing {
/// @notice Sum of all outstanding debts, in underlying units (increases as interest is accrued)
/// @return The total borrows in asset units
function totalBorrows() external view returns (uint256);
/// @notice Sum of all outstanding debts, in underlying units scaled up by shifting
/// INTERNAL_DEBT_PRECISION_SHIFT bits
/// @return The total borrows in internal debt precision
function totalBorrowsExact() external view returns (uint256);
/// @notice Balance of vault assets as tracked by deposits/withdrawals and borrows/repays
/// @return The amount of assets the vault tracks as current direct holdings
function cash() external view returns (uint256);
/// @notice Debt owed by a particular account, in underlying units
/// @param account Address to query
/// @return The debt of the account in asset units
function debtOf(address account) external view returns (uint256);
/// @notice Debt owed by a particular account, in underlying units scaled up by shifting
/// INTERNAL_DEBT_PRECISION_SHIFT bits
/// @param account Address to query
/// @return The debt of the account in internal precision
function debtOfExact(address account) external view returns (uint256);
/// @notice Retrieves the current interest rate for an asset
/// @return The interest rate in yield-per-second, scaled by 10**27
function interestRate() external view returns (uint256);
/// @notice Retrieves the current interest rate accumulator for an asset
/// @return An opaque accumulator that increases as interest is accrued
function interestAccumulator() external view returns (uint256);
/// @notice Returns an address of the sidecar DToken
/// @return The address of the DToken
function dToken() external view returns (address);
/// @notice Transfer underlying tokens from the vault to the sender, and increase sender's debt
/// @param amount Amount of assets to borrow (use max uint256 for all available tokens)
/// @param receiver Account receiving the borrowed tokens
/// @return Amount of assets borrowed
function borrow(uint256 amount, address receiver) external returns (uint256);
/// @notice Transfer underlying tokens from the sender to the vault, and decrease receiver's debt
/// @param amount Amount of debt to repay in assets (use max uint256 for full debt)
/// @param receiver Account holding the debt to be repaid
/// @return Amount of assets repaid
function repay(uint256 amount, address receiver) external returns (uint256);
/// @notice Pay off liability with shares ("self-repay")
/// @param amount In asset units (use max uint256 to repay the debt in full or up to the available deposit)
/// @param receiver Account to remove debt from by burning sender's shares
/// @return shares Amount of shares burned
/// @return debt Amount of debt removed in assets
/// @dev Equivalent to withdrawing and repaying, but no assets are needed to be present in the vault
/// @dev Contrary to a regular `repay`, if account is unhealthy, the repay amount must bring the account back to
/// health, or the operation will revert during account status check
function repayWithShares(uint256 amount, address receiver) external returns (uint256 shares, uint256 debt);
/// @notice Take over debt from another account
/// @param amount Amount of debt in asset units (use max uint256 for all the account's debt)
/// @param from Account to pull the debt from
/// @dev Due to internal debt precision accounting, the liability reported on either or both accounts after
/// calling `pullDebt` may not match the `amount` requested precisely
function pullDebt(uint256 amount, address from) external;
/// @notice Request a flash-loan. A onFlashLoan() callback in msg.sender will be invoked, which must repay the loan
/// to the main Euler address prior to returning.
/// @param amount In asset units
/// @param data Passed through to the onFlashLoan() callback, so contracts don't need to store transient data in
/// storage
function flashLoan(uint256 amount, bytes calldata data) external;
/// @notice Updates interest accumulator and totalBorrows, credits reserves, re-targets interest rate, and logs
/// vault status
function touch() external;
}
/// @title ILiquidation
/// @notice Interface of the EVault's Liquidation module
interface ILiquidation {
/// @notice Checks to see if a liquidation would be profitable, without actually doing anything
/// @param liquidator Address that will initiate the liquidation
/// @param violator Address that may be in collateral violation
/// @param collateral Collateral which is to be seized
/// @return maxRepay Max amount of debt that can be repaid, in asset units
/// @return maxYield Yield in collateral corresponding to max allowed amount of debt to be repaid, in collateral
/// balance (shares for vaults)
function checkLiquidation(address liquidator, address violator, address collateral)
external
view
returns (uint256 maxRepay, uint256 maxYield);
/// @notice Attempts to perform a liquidation
/// @param violator Address that may be in collateral violation
/// @param collateral Collateral which is to be seized
/// @param repayAssets The amount of underlying debt to be transferred from violator to sender, in asset units (use
/// max uint256 to repay the maximum possible amount). Meant as slippage check together with `minYieldBalance`
/// @param minYieldBalance The minimum acceptable amount of collateral to be transferred from violator to sender, in
/// collateral balance units (shares for vaults). Meant as slippage check together with `repayAssets`
/// @dev If `repayAssets` is set to max uint256 it is assumed the caller will perform their own slippage checks to
/// make sure they are not taking on too much debt. This option is mainly meant for smart contract liquidators
function liquidate(address violator, address collateral, uint256 repayAssets, uint256 minYieldBalance) external;
}
/// @title IRiskManager
/// @notice Interface of the EVault's RiskManager module
interface IRiskManager is IEVCVault {
/// @notice Retrieve account's total liquidity
/// @param account Account holding debt in this vault
/// @param liquidation Flag to indicate if the calculation should be performed in liquidation vs account status
/// check mode, where different LTV values might apply.
/// @return collateralValue Total risk adjusted value of all collaterals in unit of account
/// @return liabilityValue Value of debt in unit of account
function accountLiquidity(address account, bool liquidation)
external
view
returns (uint256 collateralValue, uint256 liabilityValue);
/// @notice Retrieve account's liquidity per collateral
/// @param account Account holding debt in this vault
/// @param liquidation Flag to indicate if the calculation should be performed in liquidation vs account status
/// check mode, where different LTV values might apply.
/// @return collaterals Array of collaterals enabled
/// @return collateralValues Array of risk adjusted collateral values corresponding to items in collaterals array.
/// In unit of account
/// @return liabilityValue Value of debt in unit of account
function accountLiquidityFull(address account, bool liquidation)
external
view
returns (address[] memory collaterals, uint256[] memory collateralValues, uint256 liabilityValue);
/// @notice Release control of the account on EVC if no outstanding debt is present
function disableController() external;
/// @notice Checks the status of an account and reverts if account is not healthy
/// @param account The address of the account to be checked
/// @return magicValue Must return the bytes4 magic value 0xb168c58f (which is a selector of this function) when
/// account status is valid, or revert otherwise.
/// @dev Only callable by EVC during status checks
function checkAccountStatus(address account, address[] calldata collaterals) external view returns (bytes4);
/// @notice Checks the status of the vault and reverts if caps are exceeded
/// @return magicValue Must return the bytes4 magic value 0x4b3d1223 (which is a selector of this function) when
/// account status is valid, or revert otherwise.
/// @dev Only callable by EVC during status checks
function checkVaultStatus() external returns (bytes4);
}
/// @title IBalanceForwarder
/// @notice Interface of the EVault's BalanceForwarder module
interface IBalanceForwarder {
/// @notice Retrieve the address of rewards contract, tracking changes in account's balances
/// @return The balance tracker address
function balanceTrackerAddress() external view returns (address);
/// @notice Retrieves boolean indicating if the account opted in to forward balance changes to the rewards contract
/// @param account Address to query
/// @return True if balance forwarder is enabled
function balanceForwarderEnabled(address account) external view returns (bool);
/// @notice Enables balance forwarding for the authenticated account
/// @dev Only the authenticated account can enable balance forwarding for itself
/// @dev Should call the IBalanceTracker hook with the current account's balance
function enableBalanceForwarder() external;
/// @notice Disables balance forwarding for the authenticated account
/// @dev Only the authenticated account can disable balance forwarding for itself
/// @dev Should call the IBalanceTracker hook with the account's balance of 0
function disableBalanceForwarder() external;
}
/// @title IGovernance
/// @notice Interface of the EVault's Governance module
interface IGovernance {
/// @notice Retrieves the address of the governor
/// @return The governor address
function governorAdmin() external view returns (address);
/// @notice Retrieves address of the governance fee receiver
/// @return The fee receiver address
function feeReceiver() external view returns (address);
/// @notice Retrieves the interest fee in effect for the vault
/// @return Amount of interest that is redirected as a fee, as a fraction scaled by 1e4
function interestFee() external view returns (uint16);
/// @notice Looks up an asset's currently configured interest rate model
/// @return Address of the interest rate contract or address zero to indicate 0% interest
function interestRateModel() external view returns (address);
/// @notice Retrieves the ProtocolConfig address
/// @return The protocol config address
function protocolConfigAddress() external view returns (address);
/// @notice Retrieves the protocol fee share
/// @return A percentage share of fees accrued belonging to the protocol, in 1e4 scale
function protocolFeeShare() external view returns (uint256);
/// @notice Retrieves the address which will receive protocol's fees
/// @notice The protocol fee receiver address
function protocolFeeReceiver() external view returns (address);
/// @notice Retrieves supply and borrow caps in AmountCap format
/// @return supplyCap The supply cap in AmountCap format
/// @return borrowCap The borrow cap in AmountCap format
function caps() external view returns (uint16 supplyCap, uint16 borrowCap);
/// @notice Retrieves the borrow LTV of the collateral, which is used to determine if the account is healthy during
/// account status checks.
/// @param collateral The address of the collateral to query
/// @return Borrowing LTV in 1e4 scale
function LTVBorrow(address collateral) external view returns (uint16);
/// @notice Retrieves the current liquidation LTV, which is used to determine if the account is eligible for
/// liquidation
/// @param collateral The address of the collateral to query
/// @return Liquidation LTV in 1e4 scale
function LTVLiquidation(address collateral) external view returns (uint16);
/// @notice Retrieves LTV configuration for the collateral
/// @param collateral Collateral asset
/// @return borrowLTV The current value of borrow LTV for originating positions
/// @return liquidationLTV The value of fully converged liquidation LTV
/// @return initialLiquidationLTV The initial value of the liquidation LTV, when the ramp began
/// @return targetTimestamp The timestamp when the liquidation LTV is considered fully converged
/// @return rampDuration The time it takes for the liquidation LTV to converge from the initial value to the fully
/// converged value
function LTVFull(address collateral)
external
view
returns (
uint16 borrowLTV,
uint16 liquidationLTV,
uint16 initialLiquidationLTV,
uint48 targetTimestamp,
uint32 rampDuration
);
/// @notice Retrieves a list of collaterals with configured LTVs
/// @return List of asset collaterals
/// @dev Returned assets could have the ltv disabled (set to zero)
function LTVList() external view returns (address[] memory);
/// @notice Retrieves the maximum liquidation discount
/// @return The maximum liquidation discount in 1e4 scale
/// @dev The default value, which is zero, is deliberately bad, as it means there would be no incentive to liquidate
/// unhealthy users. The vault creator must take care to properly select the limit, given the underlying and
/// collaterals used.
function maxLiquidationDiscount() external view returns (uint16);
/// @notice Retrieves liquidation cool-off time, which must elapse after successful account status check before
/// account can be liquidated
/// @return The liquidation cool off time in seconds
function liquidationCoolOffTime() external view returns (uint16);
/// @notice Retrieves a hook target and a bitmask indicating which operations call the hook target
/// @return hookTarget Address of the hook target contract
/// @return hookedOps Bitmask with operations that should call the hooks. See Constants.sol for a list of operations
function hookConfig() external view returns (address hookTarget, uint32 hookedOps);
/// @notice Retrieves a bitmask indicating enabled config flags
/// @return Bitmask with config flags enabled
function configFlags() external view returns (uint32);
/// @notice Address of EthereumVaultConnector contract
/// @return The EVC address
function EVC() external view returns (address);
/// @notice Retrieves a reference asset used for liquidity calculations
/// @return The address of the reference asset
function unitOfAccount() external view returns (address);
/// @notice Retrieves the address of the oracle contract
/// @return The address of the oracle
function oracle() external view returns (address);
/// @notice Retrieves the Permit2 contract address
/// @return The address of the Permit2 contract
function permit2Address() external view returns (address);
/// @notice Splits accrued fees balance according to protocol fee share and transfers shares to the governor fee
/// receiver and protocol fee receiver
function convertFees() external;
/// @notice Set a new governor address
/// @param newGovernorAdmin The new governor address
/// @dev Set to zero address to renounce privileges and make the vault non-governed
function setGovernorAdmin(address newGovernorAdmin) external;
/// @notice Set a new governor fee receiver address
/// @param newFeeReceiver The new fee receiver address
function setFeeReceiver(address newFeeReceiver) external;
/// @notice Set a new LTV config
/// @param collateral Address of collateral to set LTV for
/// @param borrowLTV New borrow LTV, for assessing account's health during account status checks, in 1e4 scale
/// @param liquidationLTV New liquidation LTV after ramp ends in 1e4 scale
/// @param rampDuration Ramp duration in seconds
function setLTV(address collateral, uint16 borrowLTV, uint16 liquidationLTV, uint32 rampDuration) external;
/// @notice Set a new maximum liquidation discount
/// @param newDiscount New maximum liquidation discount in 1e4 scale
/// @dev If the discount is zero (the default), the liquidators will not be incentivized to liquidate unhealthy
/// accounts
function setMaxLiquidationDiscount(uint16 newDiscount) external;
/// @notice Set a new liquidation cool off time, which must elapse after successful account status check before
/// account can be liquidated
/// @param newCoolOffTime The new liquidation cool off time in seconds
/// @dev Setting cool off time to zero allows liquidating the account in the same block as the last successful
/// account status check
function setLiquidationCoolOffTime(uint16 newCoolOffTime) external;
/// @notice Set a new interest rate model contract
/// @param newModel The new IRM address
/// @dev If the new model reverts, perhaps due to governor error, the vault will silently use a zero interest
/// rate. Governor should make sure the new interest rates are computed as expected.
function setInterestRateModel(address newModel) external;
/// @notice Set a new hook target and a new bitmap indicating which operations should call the hook target.
/// Operations are defined in Constants.sol.
/// @param newHookTarget The new hook target address. Use address(0) to simply disable hooked operations
/// @param newHookedOps Bitmask with the new hooked operations
/// @dev All operations are initially disabled in a newly created vault. The vault creator must set their
/// own configuration to make the vault usable
function setHookConfig(address newHookTarget, uint32 newHookedOps) external;
/// @notice Set new bitmap indicating which config flags should be enabled. Flags are defined in Constants.sol
/// @param newConfigFlags Bitmask with the new config flags
function setConfigFlags(uint32 newConfigFlags) external;
/// @notice Set new supply and borrow caps in AmountCap format
/// @param supplyCap The new supply cap in AmountCap fromat
/// @param borrowCap The new borrow cap in AmountCap fromat
function setCaps(uint16 supplyCap, uint16 borrowCap) external;
/// @notice Set a new interest fee
/// @param newFee The new interest fee
function setInterestFee(uint16 newFee) external;
}
/// @title IEVault
/// @custom:security-contact security@euler.xyz
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice Interface of the EVault, an EVC enabled lending vault
interface IEVault is
IInitialize,
IToken,
IVault,
IBorrowing,
ILiquidation,
IRiskManager,
IBalanceForwarder,
IGovernance
{
/// @notice Fetch address of the `Initialize` module
function MODULE_INITIALIZE() external view returns (address);
/// @notice Fetch address of the `Token` module
function MODULE_TOKEN() external view returns (address);
/// @notice Fetch address of the `Vault` module
function MODULE_VAULT() external view returns (address);
/// @notice Fetch address of the `Borrowing` module
function MODULE_BORROWING() external view returns (address);
/// @notice Fetch address of the `Liquidation` module
function MODULE_LIQUIDATION() external view returns (address);
/// @notice Fetch address of the `RiskManager` module
function MODULE_RISKMANAGER() external view returns (address);
/// @notice Fetch address of the `BalanceForwarder` module
function MODULE_BALANCE_FORWARDER() external view returns (address);
/// @notice Fetch address of the `Governance` module
function MODULE_GOVERNANCE() external view returns (address);
}
"
},
"external/evk-periphery/lib/euler-vault-kit/src/EVault/shared/Constants.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
// Implementation internals
// asset amounts are shifted left by this number of bits for increased precision of debt tracking.
uint256 constant INTERNAL_DEBT_PRECISION_SHIFT = 31;
// max amount for Assets and Shares custom types based on a uint112.
uint256 constant MAX_SANE_AMOUNT = type(uint112).max;
// max debt amount fits in uint144 (112 + 31 bits).
// Last 31 bits are zeros to ensure max debt rounded up equals max sane amount.
uint256 constant MAX_SANE_DEBT_AMOUNT = uint256(MAX_SANE_AMOUNT) << INTERNAL_DEBT_PRECISION_SHIFT;
// proxy trailing calldata length in bytes.
// Three addresses, 20 bytes each: vault underlying asset, oracle and unit of account + 4 empty bytes.
uint256 constant PROXY_METADATA_LENGTH = 64;
// gregorian calendar
uint256 constant SECONDS_PER_YEAR = 365.2425 * 86400;
// max interest rate accepted from IRM. 1,000,000% APY: floor(((1000000 / 100 + 1)**(1/(86400*365.2425)) - 1) * 1e27)
uint256 constant MAX_ALLOWED_INTEREST_RATE = 291867278914945094175;
// max valid value of the ConfigAmount custom type, signifying 100%
uint16 constant CONFIG_SCALE = 1e4;
// Account status checks special values
// no account status checks should be scheduled
address constant CHECKACCOUNT_NONE = address(0);
// account status check should be scheduled for the authenticated account
address constant CHECKACCOUNT_CALLER = address(1);
// Operations
uint32 constant OP_DEPOSIT = 1 << 0;
uint32 constant OP_MINT = 1 << 1;
uint32 constant OP_WITHDRAW = 1 << 2;
uint32 constant OP_REDEEM = 1 << 3;
uint32 constant OP_TRANSFER = 1 << 4;
uint32 constant OP_SKIM = 1 << 5;
uint32 constant OP_BORROW = 1 << 6;
uint32 constant OP_REPAY = 1 << 7;
uint32 constant OP_REPAY_WITH_SHARES = 1 << 8;
uint32 constant OP_PULL_DEBT = 1 << 9;
uint32 constant OP_CONVERT_FEES = 1 << 10;
uint32 constant OP_LIQUIDATE = 1 << 11;
uint32 constant OP_FLASHLOAN = 1 << 12;
uint32 constant OP_TOUCH = 1 << 13;
uint32 constant OP_VAULT_STATUS_CHECK = 1 << 14;
// Delimiter of possible operations
uint32 constant OP_MAX_VALUE = 1 << 15;
// Config Flags
// When flag is set, debt socialization during liquidation is disabled
uint32 constant CFG_DONT_SOCIALIZE_DEBT = 1 << 0;
// When flag is set, asset is considered to be compatible with EVC sub-accounts and protections
// against sending assets to sub-accounts are disabled
uint32 constant CFG_EVC_COMPATIBLE_ASSET = 1 << 1;
// Delimiter of possible config flags
uint32 constant CFG_MAX_VALUE = 1 << 2;
// EVC authentication
// in order to perform these operations, the account doesn't need to have the vault installed as a controller
uint32 constant CONTROLLER_NEUTRAL_OPS = OP_DEPOSIT | OP_MINT | OP_WITHDRAW | OP_REDEEM | OP_TRANSFER | OP_SKIM
| OP_REPAY | OP_REPAY_WITH_SHARES | OP_CONVERT_FEES | OP_FLASHLOAN | OP_TOUCH | OP_VAULT_STATUS_CHECK;
"
},
"external/evk-periphery/src/AccessControl/SelectorAccessControl.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import {ContextUpgradeable} from "openzeppelin-contracts-upgradeable/utils/ContextUpgradeable.sol";
import {AccessControlEnumerableUpgradeable} from
"openzeppelin-contracts-upgradeable/access/extensions/AccessControlEnumerableUpgradeable.sol";
import {
AccessControlUpgradeable,
IAccessControl
} from "openzeppelin-contracts-upgradeable/access/AccessControlUpgradeable.sol";
import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol";
/// @title SelectorAccessControl
/// @custom:security-contact security@euler.xyz
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice A utility contract with the EVC support that allows for access control based on specific selectors.
abstract contract SelectorAccessControl is EVCUtil, AccessControlEnumerableUpgradeable {
/// @notice The wildcard for all selectors. A caller with this role can call any function selector.
bytes32 public constant WILD_CARD = bytes32(type(uint256).max);
/// @notice Constructor for SelectorAccessControl
/// @param evc The address of the Ethereum Vault Connector (EVC)
/// @param admin The address to be granted the DEFAULT_ADMIN_ROLE
constructor(address evc, address admin) EVCUtil(evc) {
_grantRole(DEFAULT_ADMIN_ROLE, admin);
_disableInitializers();
}
/// @notice Initializes the contract, setting up the admin role
/// @param admin The address to be granted the DEFAULT_ADMIN_ROLE
function initialize(address admin) public initializer {
_grantRole(DEFAULT_ADMIN_ROLE, admin);
}
/// @dev Grants `role` to `account`.
function grantRole(bytes32 role, address account)
public
virtual
override (AccessControlUpgradeable, IAccessControl)
onlyEVCAccountOwner
{
super.grantRole(role, account);
}
/// @dev Revokes `role` from `account`.
function revokeRole(bytes32 role, address account)
public
virtual
override (AccessControlUpgradeable, IAccessControl)
onlyEVCAccountOwner
{
super.revokeRole(role, account);
}
/// @dev Revokes `role` from the calling account.
function renounceRole(bytes32 role, address callerConfirmation)
public
virtual
override (AccessControlUpgradeable, IAccessControl)
onlyEVCAccountOwner
{
super.renounceRole(role, callerConfirmation);
}
/// @notice Authenticates the caller based on their role and the function selector called
/// @dev Checks if the caller has either the wildcard role or the specific role for the current function selector
/// @dev If the caller doesn't have the required role, it reverts with a NotAuthorized error
function _authenticateCaller() internal view virtual {
address msgSender = _msgSender();
// Don't revert if whitelisted for wildcard or specific selector
if (!hasRole(WILD_CARD, msgSender) && !hasRole(msg.sig, msgSender)) revert NotAuthorized();
}
/// @notice Retrieves the message sender in the context of the EVC.
/// @dev This function returns the account on behalf of which the current operation is being performed, which is
/// either msg.sender or the account authenticated by the EVC.
/// @return The address of the message sender.
function _msgSender() internal view virtual override (EVCUtil, ContextUpgradeable) returns (address) {
return EVCUtil._msgSender();
}
}
"
},
"external/evk-periphery/lib/euler-vault-kit/src/EVault/shared/lib/RevertBytes.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import "../Errors.sol";
/// @title RevertBytes Library
/// @custom:security-contact security@euler.xyz
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice The library provides a helper function for bubbling up errors
library RevertBytes {
function revertBytes(bytes memory errMsg) internal pure {
if (errMsg.length > 0) {
assembly {
revert(add(32, errMsg), mload(errMsg))
}
}
revert Errors.E_EmptyError();
}
}
"
},
"external/evk-periphery/lib/euler-vault-kit/src/EVault/shared/types/Types.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import "../../IEVault.sol";
import "./VaultStorage.sol";
import "./Snapshot.sol";
import "./UserStorage.sol";
import "./Shares.sol";
import "./Assets.sol";
import "./Owed.sol";
import "./ConfigAmount.sol";
import "./Flags.sol";
import "./AmountCap.sol";
/// @notice In this file, custom types are defined and linked globally with their libraries and operators
type Shares is uint112;
type Assets is uint112;
type Owed is uint144;
type AmountCap is uint16;
type ConfigAmount is uint16;
type Flags is uint32;
using SharesLib for Shares global;
using {
addShares as +, subShares as -, eqShares as ==, neqShares as !=, gtShares as >, ltShares as <
} for Shares global;
using AssetsLib for Assets global;
using {
addAssets as +,
subAssets as -,
eqAssets as ==,
neqAssets as !=,
gtAssets as >,
gteAssets as >=,
ltAssets as <,
lteAssets as <=
} for Assets global;
using OwedLib for Owed global;
using {addOwed as +, subOwed as -, eqOwed as ==, neqOwed as !=, gtOwed as >, ltOwed as <} for Owed global;
using ConfigAmountLib for ConfigAmount global;
using {
gtConfigAmount as >, gteConfigAmount as >=, ltConfigAmount as <, lteConfigAmount as <=
} for ConfigAmount global;
using AmountCapLib for AmountCap global;
using FlagsLib for Flags global;
/// @title TypesLib
/// @notice Library for casting basic types' amounts into custom types
library TypesLib {
function toShares(uint256 amount) internal pure returns (Shares) {
if (amount > MAX_SANE_AMOUNT) revert Errors.E_AmountTooLargeToEncode();
return Shares.wrap(uint112(amount));
}
function toAssets(uint256 amount) internal pure returns (Assets) {
if (amount > MAX_SANE_AMOUNT) revert Errors.E_AmountTooLargeToEncode();
return Assets.wrap(uint112(amount));
}
function toOwed(uint256 amount) internal pure returns (Owed) {
if (amount > MAX_SANE_DEBT_AMOUNT) revert Errors.E_DebtAmountTooLargeToEncode();
return Owed.wrap(uint144(amount));
}
function toConfigAmount(uint16 amount) internal pure returns (ConfigAmount) {
if (amount > CONFIG_SCALE) revert Errors.E_ConfigAmountTooLargeToEncode();
return ConfigAmount.wrap(amount);
}
}
"
},
"external/ethereum-vault-connector/src/interfaces/IVault.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;
/// @title IVault
/// @custom:security-contact security@euler.xyz
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice This interface defines the methods for the Vault for the purpose of integration with the Ethereum Vault
/// Connector.
interface IVault {
/// @notice Disables a controller (this vault) for the authenticated account.
/// @dev A controller is a vault that has been chosen for an account to have special control over account’s
/// balances in the enabled collaterals vaults. User calls this function in order for the vault to disable itself
/// for the account if the conditions are met (i.e. user has repaid debt in full). If the conditions are not met,
/// the function reverts.
function disableController() external;
/// @notice Checks the status of an account.
/// @dev This function must only deliberately revert if the account status is invalid. If this function reverts due
/// to any other reason, it may render the account unusable with possibly no way to recover funds.
/// @param account The address of the account to be checked.
/// @param collaterals The array of enabled collateral addresses to be considered for the account status check.
/// @return magicValue Must return the bytes4 magic value 0xb168c58f (which is a selector of this function) when
/// account status is valid, or revert otherwise.
function checkAccountStatus(
address account,
address[] calldata collaterals
) external view returns (bytes4 magicValue);
/// @notice Checks the status of the vault.
/// @dev This function must only deliberately revert if the vault status is invalid. If this function reverts due to
/// any other reason, it may render some accounts unusable with possibly no way to recover funds.
/// @return magicValue Must return the bytes4 magic value 0x4b3d1223 (which is a selector of this function) when
/// account status is valid, or revert otherwise.
function checkVaultStatus() external returns (bytes4 magicValue);
}
"
},
"external/evk-periphery/lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
"
},
"external/evk-periphery/lib/openzeppelin-contracts-upgradeable/contracts/access/extensions/AccessControlEnumerableUpgradeable.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (access/extensions/AccessControlEnumerable.sol)
pragma solidity ^0.8.20;
import {IAccessControlEnumerable} from "@openzeppelin/contracts/access/extensions/IAccessControlEnumerable.sol";
import {AccessControlUpgradeable} from "../AccessControlUpgradeable.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {Initializable} from "../../proxy/utils/Initializable.sol";
/**
* @dev Extension of {AccessControl} that allows enumerating the members of each role.
*/
abstract contract AccessControlEnumerableUpgradeable is Initializable, IAccessControlEnumerable, AccessControlUpgradeable {
using EnumerableSet for EnumerableSet.AddressSet;
/// @custom:storage-location erc7201:openzeppelin.storage.AccessControlEnumerable
struct AccessControlEnumerableStorage {
mapping(bytes32 role => EnumerableSet.AddressSet) _roleMembers;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.AccessControlEnumerable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant AccessControlEnumerableStorageLocation = 0xc1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e82371705932000;
function _getAccessControlEnumerableStorage() private pure returns (AccessControlEnumerableStorage storage $) {
assembly {
$.slot := AccessControlEnumerableStorageLocation
}
}
function __AccessControlEnumerable_init() internal onlyInitializing {
}
function __AccessControlEnumerable_init_unchained() internal onlyInitializing {
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns one of the accounts that have `role`. `index` must be a
* value between 0 and {getRoleMemberCount}, non-inclusive.
*
* Role bearers are not sorted in any particular way, and their ordering may
* change at any point.
*
* WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
* you perform all queries on the same block. See the following
* https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
* for more information.
*/
function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {
AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage();
return $._roleMembers[role].at(index);
}
/**
* @dev Returns the number of accounts that have `role`. Can be used
* together with {getRoleMember} to enumerate all bearers of a role.
*/
function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {
AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage();
return $._roleMembers[role].length();
}
/**
* @dev Return all accounts that have `role`
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function getRoleMembers(bytes32 role) public view virtual returns (address[] memory) {
AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage();
return $._roleMembers[role].values();
}
/**
* @dev Overload {AccessControl-_grantRole} to track enumerable memberships
*/
function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {
AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage();
bool granted = super._grantRole(role, account);
if (granted) {
$._roleMembers[role].add(account);
}
return granted;
}
/**
* @dev Overload {AccessControl-_revokeRole} to track enumerable memberships
*/
function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {
AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage();
bool revoked = super._revokeRole(role, account);
if (revoked) {
$._roleMembers[role].remove(account);
}
return revoked;
}
}
"
},
"external/evk-periphery/lib/openzeppelin-contracts-upgradeable/contracts/access/AccessControlUpgradeable.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)
pragma solidity ^0.8.20;
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {ERC165Upgradeable} from "../utils/introspection/ERC165Upgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControl, ERC165Upgradeable {
struct RoleData {
mapping(address account => bool) hasRole;
bytes32 adminRole;
}
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/// @custom:storage-location erc7201:openzeppelin.storage.AccessControl
struct AccessControlStorage {
mapping(bytes32 role => RoleData) _roles;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.AccessControl")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant AccessControlStorageLocation = 0x02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800;
function _getAccessControlStorage() private pure returns (AccessControlStorage storage $) {
assembly {
$.slot := AccessControlStorageLocation
}
}
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with an {AccessControlUnauthorizedAccount} error including the required role.
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
function __AccessControl_init() internal onlyInitializing {
}
function __AccessControl_init_unchained() internal onlyInitializing {
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
AccessControlStorage storage $ = _getAccessControlStorage();
return $._roles[role].hasRole[account];
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
* is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
* is missing `role`.
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
AccessControlStorage storage $ = _getAccessControlStorage();
return $._roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address callerConfirmation) public virtual {
if (callerConfirmation != _msgSender()) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, callerConfirmation);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
AccessControlStorage storage $ = _getAccessControlStorage();
bytes32 previousAdminRole = getRoleAdmin(role);
$._roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
AccessControlStorage storage $ = _getAccessControlStorage();
if (!hasRole(role, account)) {
$._roles[role].hasRole[account] = true;
emit RoleGranted(role, account, _msgSender());
return true;
} else {
return false;
}
}
/**
* @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
*
* Internal function without acce
Submitted on: 2025-10-28 11:57:45
Comments
Log in to comment.
No comments yet.