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": {
"src/contracts/facilitators/gsm/swapFreezer/OracleSwapFreezer.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import {IPoolAddressesProvider} from 'aave-v3-origin/contracts/interfaces/IPoolAddressesProvider.sol';
import {IPriceOracle} from 'aave-v3-origin/contracts/interfaces/IPriceOracle.sol';
import {AutomationCompatibleInterface} from 'src/contracts/dependencies/chainlink/AutomationCompatibleInterface.sol';
import {IGsm} from 'src/contracts/facilitators/gsm/interfaces/IGsm.sol';
/**
* @title OracleSwapFreezer
* @author Aave
* @notice Swap freezer that enacts the freeze action based on underlying oracle price, GSM's state and predefined price boundaries
* @dev Chainlink Automation-compatible contract using Aave V3 Price Oracle, where prices are USD denominated with 8-decimal precision
* @dev Freeze action is executable if GSM is not seized, not frozen and price is outside of the freeze bounds
* @dev Unfreeze action is executable if GSM is not seized, frozen, unfreezing is allowed and price is inside the unfreeze bounds
*/
contract OracleSwapFreezer is AutomationCompatibleInterface {
enum Action {
NONE,
FREEZE,
UNFREEZE
}
IGsm public immutable GSM;
address public immutable UNDERLYING_ASSET;
IPoolAddressesProvider public immutable ADDRESS_PROVIDER;
uint128 internal immutable _freezeLowerBound;
uint128 internal immutable _freezeUpperBound;
uint128 internal immutable _unfreezeLowerBound;
uint128 internal immutable _unfreezeUpperBound;
bool internal immutable _allowUnfreeze;
/**
* @dev Constructor
* @dev Freeze/unfreeze bounds are specified in USD with 8-decimal precision, like Aave v3 Price Oracles
* @dev Unfreeze boundaries are "contained" in freeze boundaries, where freezeLowerBound < unfreezeLowerBound and unfreezeUpperBound < freezeUpperBound
* @dev All bound ranges are inclusive
* @param gsm The GSM that this contract will trigger freezes/unfreezes on
* @param underlyingAsset The address of the collateral asset
* @param addressProvider The Aave Addresses Provider for looking up the Price Oracle
* @param freezeLowerBound The lower price bound for freeze operations
* @param freezeUpperBound The upper price bound for freeze operations
* @param unfreezeLowerBound The lower price bound for unfreeze operations, must be 0 if unfreezing not allowed
* @param unfreezeUpperBound The upper price bound for unfreeze operations, must be 0 if unfreezing not allowed
* @param allowUnfreeze True if bounds verification should factor in the unfreeze boundary, false otherwise
*/
constructor(
IGsm gsm,
address underlyingAsset,
IPoolAddressesProvider addressProvider,
uint128 freezeLowerBound,
uint128 freezeUpperBound,
uint128 unfreezeLowerBound,
uint128 unfreezeUpperBound,
bool allowUnfreeze
) {
require(underlyingAsset != address(0), 'ZERO_ADDRESS_NOT_VALID');
require(
_validateBounds(
freezeLowerBound,
freezeUpperBound,
unfreezeLowerBound,
unfreezeUpperBound,
allowUnfreeze
),
'BOUNDS_NOT_VALID'
);
GSM = gsm;
UNDERLYING_ASSET = underlyingAsset;
ADDRESS_PROVIDER = addressProvider;
_freezeLowerBound = freezeLowerBound;
_freezeUpperBound = freezeUpperBound;
_unfreezeLowerBound = unfreezeLowerBound;
_unfreezeUpperBound = unfreezeUpperBound;
_allowUnfreeze = allowUnfreeze;
}
/// @inheritdoc AutomationCompatibleInterface
function performUpkeep(bytes calldata) external {
Action action = _getAction();
if (action == Action.FREEZE) {
GSM.setSwapFreeze(true);
} else if (action == Action.UNFREEZE) {
GSM.setSwapFreeze(false);
}
}
/// @inheritdoc AutomationCompatibleInterface
function checkUpkeep(bytes calldata) external view returns (bool, bytes memory) {
return (_getAction() == Action.NONE ? false : true, '');
}
/**
* @notice Returns whether or not the swap freezer can unfreeze a GSM
* @return True if the freezer can unfreeze, false otherwise
*/
function getCanUnfreeze() external view returns (bool) {
return _allowUnfreeze;
}
/**
* @notice Returns the bound used for freeze operations
* @return The freeze lower bound (inclusive)
* @return The freeze upper bound (inclusive)
*/
function getFreezeBound() external view returns (uint128, uint128) {
return (_freezeLowerBound, _freezeUpperBound);
}
/**
* @notice Returns the bound used for unfreeze operations, or (0, 0) if unfreezing not allowed
* @return The unfreeze lower bound (inclusive), or 0 if unfreezing not allowed
* @return The unfreeze upper bound (inclusive), or 0 if unfreezing not allowed
*/
function getUnfreezeBound() external view returns (uint128, uint128) {
return (_unfreezeLowerBound, _unfreezeUpperBound);
}
/**
* @notice Fetches price oracle data and checks whether a swap freeze or unfreeze action is required
* @return The action to take (none, freeze, or unfreeze)
*/
function _getAction() internal view returns (Action) {
if (GSM.hasRole(GSM.SWAP_FREEZER_ROLE(), address(this))) {
if (GSM.getIsSeized()) {
return Action.NONE;
} else if (!GSM.getIsFrozen()) {
if (_isActionAllowed(Action.FREEZE)) {
return Action.FREEZE;
}
} else if (_allowUnfreeze) {
if (_isActionAllowed(Action.UNFREEZE)) {
return Action.UNFREEZE;
}
}
}
return Action.NONE;
}
/**
* @notice Checks whether the action is allowed, based on the action, oracle price and freeze/unfreeze bounds
* @dev Freeze action is allowed if price is outside of the freeze bounds
* @dev Unfreeze action is allowed if price is inside the unfreeze bounds
* @param actionToExecute The requested action type to validate
* @return True if conditions to execute the action passed are met, false otherwise
*/
function _isActionAllowed(Action actionToExecute) internal view returns (bool) {
uint256 oraclePrice = IPriceOracle(ADDRESS_PROVIDER.getPriceOracle()).getAssetPrice(
UNDERLYING_ASSET
);
// Assume a 0 oracle price is invalid and no action should be taken based on that data
if (oraclePrice == 0) {
return false;
} else if (actionToExecute == Action.FREEZE) {
if (oraclePrice <= _freezeLowerBound || oraclePrice >= _freezeUpperBound) {
return true;
}
} else if (actionToExecute == Action.UNFREEZE) {
if (oraclePrice >= _unfreezeLowerBound && oraclePrice <= _unfreezeUpperBound) {
return true;
}
}
return false;
}
/**
* @notice Verifies that the unfreeze bound and freeze bounds do not conflict, causing unexpected behaviour
* @param freezeLowerBound The lower bound for freeze operations
* @param freezeUpperBound The upper bound for freeze operations
* @param unfreezeLowerBound The lower bound for unfreeze operations, must be 0 if unfreezing not allowed
* @param unfreezeUpperBound The upper bound for unfreeze operations, must be 0 if unfreezing not allowed
* @param allowUnfreeze True if bounds verification should factor in the unfreeze boundary, false otherwise
* @return True if the bounds are valid and conflict-free, false otherwise
*/
function _validateBounds(
uint128 freezeLowerBound,
uint128 freezeUpperBound,
uint128 unfreezeLowerBound,
uint128 unfreezeUpperBound,
bool allowUnfreeze
) internal pure returns (bool) {
if (freezeLowerBound >= freezeUpperBound) {
return false;
} else if (allowUnfreeze) {
if (
unfreezeLowerBound >= unfreezeUpperBound ||
freezeLowerBound >= unfreezeLowerBound ||
freezeUpperBound <= unfreezeUpperBound
) {
return false;
}
} else {
if (unfreezeLowerBound != 0 || unfreezeUpperBound != 0) {
return false;
}
}
return true;
}
}
"
},
"lib/aave-v3-origin/src/contracts/interfaces/IPoolAddressesProvider.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title IPoolAddressesProvider
* @author Aave
* @notice Defines the basic interface for a Pool Addresses Provider.
*/
interface IPoolAddressesProvider {
/**
* @dev Emitted when the market identifier is updated.
* @param oldMarketId The old id of the market
* @param newMarketId The new id of the market
*/
event MarketIdSet(string indexed oldMarketId, string indexed newMarketId);
/**
* @dev Emitted when the pool is updated.
* @param oldAddress The old address of the Pool
* @param newAddress The new address of the Pool
*/
event PoolUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the pool configurator is updated.
* @param oldAddress The old address of the PoolConfigurator
* @param newAddress The new address of the PoolConfigurator
*/
event PoolConfiguratorUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the price oracle is updated.
* @param oldAddress The old address of the PriceOracle
* @param newAddress The new address of the PriceOracle
*/
event PriceOracleUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the ACL manager is updated.
* @param oldAddress The old address of the ACLManager
* @param newAddress The new address of the ACLManager
*/
event ACLManagerUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the ACL admin is updated.
* @param oldAddress The old address of the ACLAdmin
* @param newAddress The new address of the ACLAdmin
*/
event ACLAdminUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the price oracle sentinel is updated.
* @param oldAddress The old address of the PriceOracleSentinel
* @param newAddress The new address of the PriceOracleSentinel
*/
event PriceOracleSentinelUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the pool data provider is updated.
* @param oldAddress The old address of the PoolDataProvider
* @param newAddress The new address of the PoolDataProvider
*/
event PoolDataProviderUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when a new proxy is created.
* @param id The identifier of the proxy
* @param proxyAddress The address of the created proxy contract
* @param implementationAddress The address of the implementation contract
*/
event ProxyCreated(
bytes32 indexed id,
address indexed proxyAddress,
address indexed implementationAddress
);
/**
* @dev Emitted when a new non-proxied contract address is registered.
* @param id The identifier of the contract
* @param oldAddress The address of the old contract
* @param newAddress The address of the new contract
*/
event AddressSet(bytes32 indexed id, address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the implementation of the proxy registered with id is updated
* @param id The identifier of the contract
* @param proxyAddress The address of the proxy contract
* @param oldImplementationAddress The address of the old implementation contract
* @param newImplementationAddress The address of the new implementation contract
*/
event AddressSetAsProxy(
bytes32 indexed id,
address indexed proxyAddress,
address oldImplementationAddress,
address indexed newImplementationAddress
);
/**
* @notice Returns the id of the Aave market to which this contract points to.
* @return The market id
*/
function getMarketId() external view returns (string memory);
/**
* @notice Associates an id with a specific PoolAddressesProvider.
* @dev This can be used to create an onchain registry of PoolAddressesProviders to
* identify and validate multiple Aave markets.
* @param newMarketId The market id
*/
function setMarketId(string calldata newMarketId) external;
/**
* @notice Returns an address by its identifier.
* @dev The returned address might be an EOA or a contract, potentially proxied
* @dev It returns ZERO if there is no registered address with the given id
* @param id The id
* @return The address of the registered for the specified id
*/
function getAddress(bytes32 id) external view returns (address);
/**
* @notice General function to update the implementation of a proxy registered with
* certain `id`. If there is no proxy registered, it will instantiate one and
* set as implementation the `newImplementationAddress`.
* @dev IMPORTANT Use this function carefully, only for ids that don't have an explicit
* setter function, in order to avoid unexpected consequences
* @param id The id
* @param newImplementationAddress The address of the new implementation
*/
function setAddressAsProxy(bytes32 id, address newImplementationAddress) external;
/**
* @notice Sets an address for an id replacing the address saved in the addresses map.
* @dev IMPORTANT Use this function carefully, as it will do a hard replacement
* @param id The id
* @param newAddress The address to set
*/
function setAddress(bytes32 id, address newAddress) external;
/**
* @notice Returns the address of the Pool proxy.
* @return The Pool proxy address
*/
function getPool() external view returns (address);
/**
* @notice Updates the implementation of the Pool, or creates a proxy
* setting the new `pool` implementation when the function is called for the first time.
* @param newPoolImpl The new Pool implementation
*/
function setPoolImpl(address newPoolImpl) external;
/**
* @notice Returns the address of the PoolConfigurator proxy.
* @return The PoolConfigurator proxy address
*/
function getPoolConfigurator() external view returns (address);
/**
* @notice Updates the implementation of the PoolConfigurator, or creates a proxy
* setting the new `PoolConfigurator` implementation when the function is called for the first time.
* @param newPoolConfiguratorImpl The new PoolConfigurator implementation
*/
function setPoolConfiguratorImpl(address newPoolConfiguratorImpl) external;
/**
* @notice Returns the address of the price oracle.
* @return The address of the PriceOracle
*/
function getPriceOracle() external view returns (address);
/**
* @notice Updates the address of the price oracle.
* @param newPriceOracle The address of the new PriceOracle
*/
function setPriceOracle(address newPriceOracle) external;
/**
* @notice Returns the address of the ACL manager.
* @return The address of the ACLManager
*/
function getACLManager() external view returns (address);
/**
* @notice Updates the address of the ACL manager.
* @param newAclManager The address of the new ACLManager
*/
function setACLManager(address newAclManager) external;
/**
* @notice Returns the address of the ACL admin.
* @return The address of the ACL admin
*/
function getACLAdmin() external view returns (address);
/**
* @notice Updates the address of the ACL admin.
* @param newAclAdmin The address of the new ACL admin
*/
function setACLAdmin(address newAclAdmin) external;
/**
* @notice Returns the address of the price oracle sentinel.
* @return The address of the PriceOracleSentinel
*/
function getPriceOracleSentinel() external view returns (address);
/**
* @notice Updates the address of the price oracle sentinel.
* @param newPriceOracleSentinel The address of the new PriceOracleSentinel
*/
function setPriceOracleSentinel(address newPriceOracleSentinel) external;
/**
* @notice Returns the address of the data provider.
* @return The address of the DataProvider
*/
function getPoolDataProvider() external view returns (address);
/**
* @notice Updates the address of the data provider.
* @param newDataProvider The address of the new DataProvider
*/
function setPoolDataProvider(address newDataProvider) external;
}
"
},
"lib/aave-v3-origin/src/contracts/interfaces/IPriceOracle.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title IPriceOracle
* @author Aave
* @notice Defines the basic interface for a Price oracle.
*/
interface IPriceOracle {
/**
* @notice Returns the asset price in the base currency
* @param asset The address of the asset
* @return The price of the asset
*/
function getAssetPrice(address asset) external view returns (uint256);
/**
* @notice Set the price of the asset
* @param asset The address of the asset
* @param price The price of the asset
*/
function setAssetPrice(address asset, uint256 price) external;
}
"
},
"src/contracts/dependencies/chainlink/AutomationCompatibleInterface.sol": {
"content": "// SPDX-License-Identifier: MIT
// Chainlink Contracts v0.8
pragma solidity ^0.8.0;
interface AutomationCompatibleInterface {
/**
* @notice method that is simulated by the keepers to see if any work actually
* needs to be performed. This method does does not actually need to be
* executable, and since it is only ever simulated it can consume lots of gas.
* @dev To ensure that it is never called, you may want to add the
* cannotExecute modifier from KeeperBase to your implementation of this
* method.
* @param checkData specified in the upkeep registration so it is always the
* same for a registered upkeep. This can easily be broken down into specific
* arguments using `abi.decode`, so multiple upkeeps can be registered on the
* same contract and easily differentiated by the contract.
* @return upkeepNeeded boolean to indicate whether the keeper should call
* performUpkeep or not.
* @return performData bytes that the keeper should call performUpkeep with, if
* upkeep is needed. If you would like to encode data to decode later, try
* `abi.encode`.
*/
function checkUpkeep(
bytes calldata checkData
) external returns (bool upkeepNeeded, bytes memory performData);
/**
* @notice method that is actually executed by the keepers, via the registry.
* The data returned by the checkUpkeep simulation will be passed into
* this method to actually be executed.
* @dev The input to this method should not be trusted, and the caller of the
* method should not even be restricted to any single registry. Anyone should
* be able call it, and the input should be validated, there is no guarantee
* that the data passed in is the performData returned from checkUpkeep. This
* could happen due to malicious keepers, racing keepers, or simply a state
* change while the performUpkeep transaction is waiting for confirmation.
* Always validate the data passed in.
* @param performData is the data which was passed back from the checkData
* simulation. If it is encoded, it can easily be decoded into other types by
* calling `abi.decode`. This data should not be trusted, and should be
* validated against the contract's current state.
*/
function performUpkeep(bytes calldata performData) external;
}
"
},
"src/contracts/facilitators/gsm/interfaces/IGsm.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IAccessControl} from 'src/contracts/dependencies/openzeppelin-contracts/contracts/access/IAccessControl.sol';
import {IGhoFacilitator} from 'src/contracts/gho/interfaces/IGhoFacilitator.sol';
/**
* @title IGsm
* @author Aave
* @notice Defines the behaviour of a GHO Stability Module
*/
interface IGsm is IAccessControl, IGhoFacilitator {
/**
* @dev Emitted when a user buys an asset (selling GHO) in the GSM
* @param originator The address of the buyer originating the request
* @param receiver The address of the receiver of the underlying asset
* @param underlyingAmount The amount of the underlying asset bought
* @param ghoAmount The amount of GHO sold, inclusive of fee
* @param fee The fee paid by the buyer, in GHO
*/
event BuyAsset(
address indexed originator,
address indexed receiver,
uint256 underlyingAmount,
uint256 ghoAmount,
uint256 fee
);
/**
* @dev Emitted when the GHO reserve is updated
* @param oldReserve The address of the old reserve
* @param newReserve The address of the new reserve
*/
event GhoReserveUpdated(address oldReserve, address newReserve);
/**
* @dev Emitted when a user sells an asset (buying GHO) in the GSM
* @param originator The address of the seller originating the request
* @param receiver The address of the receiver of GHO
* @param underlyingAmount The amount of the underlying asset sold
* @param ghoAmount The amount of GHO bought, inclusive of fee
* @param fee The fee paid by the buyer, in GHO
*/
event SellAsset(
address indexed originator,
address indexed receiver,
uint256 underlyingAmount,
uint256 ghoAmount,
uint256 fee
);
/**
* @dev Emitted when the Swap Freezer freezes buys/sells
* @param freezer The address of the Swap Freezer
* @param enabled True if swap functions are frozen, False otherwise
*/
event SwapFreeze(address indexed freezer, bool enabled);
/**
* @dev Emitted when a Liquidator seizes GSM funds
* @param seizer The address originating the seizure request
* @param recipient The address of the recipient of seized funds
* @param underlyingAmount The amount of the underlying asset seized
* @param ghoOutstanding The amount of remaining GHO that the GSM had minted
*/
event Seized(
address indexed seizer,
address indexed recipient,
uint256 underlyingAmount,
uint256 ghoOutstanding
);
/**
* @dev Emitted when burning GHO after a seizure of GSM funds
* @param burner The address of the burner
* @param amount The amount of GHO burned
* @param ghoOutstanding The amount of remaining GHO that the GSM had minted
*/
event BurnAfterSeize(address indexed burner, uint256 amount, uint256 ghoOutstanding);
/**
* @dev Emitted when the Fee Strategy is updated
* @param oldFeeStrategy The address of the old Fee Strategy
* @param newFeeStrategy The address of the new Fee Strategy
*/
event FeeStrategyUpdated(address indexed oldFeeStrategy, address indexed newFeeStrategy);
/**
* @dev Emitted when the GSM underlying asset Exposure Cap is updated
* @param oldExposureCap The amount of the old Exposure Cap
* @param newExposureCap The amount of the new Exposure Cap
*/
event ExposureCapUpdated(uint256 oldExposureCap, uint256 newExposureCap);
/**
* @dev Emitted when tokens are rescued from the GSM
* @param tokenRescued The address of the rescued token
* @param recipient The address that received the rescued tokens
* @param amountRescued The amount of token rescued
*/
event TokensRescued(
address indexed tokenRescued,
address indexed recipient,
uint256 amountRescued
);
/**
* @notice Buys the GSM underlying asset in exchange for selling GHO
* @dev Use `getAssetAmountForBuyAsset` function to calculate the amount based on the GHO amount to sell
* @param minAmount The minimum amount of the underlying asset to buy
* @param receiver Recipient address of the underlying asset being purchased
* @return The amount of underlying asset bought
* @return The amount of GHO sold by the user
*/
function buyAsset(uint256 minAmount, address receiver) external returns (uint256, uint256);
/**
* @notice Buys the GSM underlying asset in exchange for selling GHO, using an EIP-712 signature
* @dev Use `getAssetAmountForBuyAsset` function to calculate the amount based on the GHO amount to sell
* @param originator The signer of the request
* @param minAmount The minimum amount of the underlying asset to buy
* @param receiver Recipient address of the underlying asset being purchased
* @param deadline Signature expiration deadline
* @param signature Signature data
* @return The amount of underlying asset bought
* @return The amount of GHO sold by the user
*/
function buyAssetWithSig(
address originator,
uint256 minAmount,
address receiver,
uint256 deadline,
bytes calldata signature
) external returns (uint256, uint256);
/**
* @notice Sells the GSM underlying asset in exchange for buying GHO
* @dev Use `getAssetAmountForSellAsset` function to calculate the amount based on the GHO amount to buy
* @param maxAmount The maximum amount of the underlying asset to sell
* @param receiver Recipient address of the GHO being purchased
* @return The amount of underlying asset sold
* @return The amount of GHO bought by the user
*/
function sellAsset(uint256 maxAmount, address receiver) external returns (uint256, uint256);
/**
* @notice Sells the GSM underlying asset in exchange for buying GHO, using an EIP-712 signature
* @dev Use `getAssetAmountForSellAsset` function to calculate the amount based on the GHO amount to buy
* @param originator The signer of the request
* @param maxAmount The maximum amount of the underlying asset to sell
* @param receiver Recipient address of the GHO being purchased
* @param deadline Signature expiration deadline
* @param signature Signature data
* @return The amount of underlying asset sold
* @return The amount of GHO bought by the user
*/
function sellAssetWithSig(
address originator,
uint256 maxAmount,
address receiver,
uint256 deadline,
bytes calldata signature
) external returns (uint256, uint256);
/**
* @notice Rescue and transfer tokens locked in this contract
* @dev In a Gsm4626 instance, distributeFeesToTreasury() must be called first to ensure the accounting of
* accrued fees is up-to-date.
* @param token The address of the token
* @param to The address of the recipient
* @param amount The amount of token to transfer
*/
function rescueTokens(address token, address to, uint256 amount) external;
/**
* @notice Enable or disable the swap freeze
* @param enable True to freeze swap functions, false otherwise
*/
function setSwapFreeze(bool enable) external;
/**
* @notice Seizes all of the underlying asset from the GSM, sending to the Treasury
* @dev Seizing is a last resort mechanism to provide the Treasury with the entire amount of underlying asset
* so it can be used to backstop any potential event impacting the functionality of the Gsm.
* @dev Seizing disables the swap feature
* @return The amount of underlying asset seized and transferred to Treasury
*/
function seize() external returns (uint256);
/**
* @notice Burns an amount of GHO after seizure reducing the facilitator bucket level effectively
* @dev Passing an amount higher than the facilitator bucket level will result in burning all minted GHO
* @dev Only callable if the GSM has assets seized, helpful to wind down the facilitator
* @param amount The amount of GHO to burn
* @return The amount of GHO burned
*/
function burnAfterSeize(uint256 amount) external returns (uint256);
/**
* @notice Updates the address of the Fee Strategy
* @param feeStrategy The address of the new FeeStrategy
*/
function updateFeeStrategy(address feeStrategy) external;
/**
* @notice Updates the exposure cap of the underlying asset
* @param exposureCap The new value for the exposure cap (in underlying asset terms)
*/
function updateExposureCap(uint128 exposureCap) external;
/**
* @notice Updates the GHO reserve address
* @dev It revokes the allowance to the old reserve and grants maximum allowance to the new one.
* @param newGhoReserve The new address of the GHO reserve
*/
function updateGhoReserve(address newGhoReserve) external;
/**
* @notice Returns the EIP712 domain separator
* @return The EIP712 domain separator
*/
function DOMAIN_SEPARATOR() external view returns (bytes32);
/**
* @notice Returns the total amount of GHO, gross amount and fee result of buying assets
* @param minAssetAmount The minimum amount of underlying asset to buy
* @return The exact amount of underlying asset to be bought
* @return The total amount of GHO the user sells (gross amount in GHO plus fee)
* @return The gross amount of GHO
* @return The fee amount in GHO, applied on top of gross amount of GHO
*/
function getGhoAmountForBuyAsset(
uint256 minAssetAmount
) external view returns (uint256, uint256, uint256, uint256);
/**
* @notice Returns the total amount of GHO, gross amount and fee result of selling assets
* @param maxAssetAmount The maximum amount of underlying asset to sell
* @return The exact amount of underlying asset to sell
* @return The total amount of GHO the user buys (gross amount in GHO minus fee)
* @return The gross amount of GHO
* @return The fee amount in GHO, applied to the gross amount of GHO
*/
function getGhoAmountForSellAsset(
uint256 maxAssetAmount
) external view returns (uint256, uint256, uint256, uint256);
/**
* @notice Returns the amount of underlying asset, gross amount of GHO and fee result of buying assets
* @param maxGhoAmount The maximum amount of GHO the user provides for buying underlying asset
* @return The amount of underlying asset the user buys
* @return The exact amount of GHO the user provides
* @return The gross amount of GHO corresponding to the given total amount of GHO
* @return The fee amount in GHO, charged for buying assets
*/
function getAssetAmountForBuyAsset(
uint256 maxGhoAmount
) external view returns (uint256, uint256, uint256, uint256);
/**
* @notice Returns the amount of underlying asset, gross amount of GHO and fee result of selling assets
* @param minGhoAmount The minimum amount of GHO the user must receive for selling underlying asset
* @return The amount of underlying asset the user sells
* @return The exact amount of GHO the user receives in exchange
* @return The gross amount of GHO corresponding to the given total amount of GHO
* @return The fee amount in GHO, charged for selling assets
*/
function getAssetAmountForSellAsset(
uint256 minGhoAmount
) external view returns (uint256, uint256, uint256, uint256);
/**
* @notice Returns the remaining GSM exposure capacity
* @return The amount of underlying asset that can be sold to the GSM
*/
function getAvailableUnderlyingExposure() external view returns (uint256);
/**
* @notice Returns the exposure limit to the underlying asset
* @return The maximum amount of underlying asset that can be sold to the GSM
*/
function getExposureCap() external view returns (uint128);
/**
* @notice Returns the actual underlying asset balance immediately available in the GSM
* @return The amount of underlying asset that can be bought from the GSM
*/
function getAvailableLiquidity() external view returns (uint256);
/**
* @notice Returns the Fee Strategy for the GSM
* @dev It returns 0x0 in case of no fee strategy
* @return The address of the FeeStrategy
*/
function getFeeStrategy() external view returns (address);
/**
* @notice Returns the amount of current accrued fees
* @dev It does not factor in potential fees that can be accrued upon distribution of fees
* @return The amount of accrued fees
*/
function getAccruedFees() external view returns (uint256);
/**
* @notice Returns the freeze status of the GSM
* @return True if frozen, false if not
*/
function getIsFrozen() external view returns (bool);
/**
* @notice Returns the current seizure status of the GSM
* @return True if the GSM has been seized, false if not
*/
function getIsSeized() external view returns (bool);
/**
* @notice Returns the address of the GHO reserve
* @return The address of the GHO reserve
*/
function getGhoReserve() external view returns (address);
/**
* @notice Returns the amount of GHO used by the GSM
* @return The amount of GHO used
*/
function getUsed() external view returns (uint256);
/**
* @notice Returns the maximum amount of GHO that can be used
* @return The maximum amount of GHO that can be used
*/
function getLimit() external view returns (uint256);
/**
* @notice Returns whether or not swaps via buyAsset/sellAsset are currently possible
* @return True if the GSM has swapping enabled, false otherwise
*/
function canSwap() external view returns (bool);
/**
* @notice Returns the GSM revision number
* @return The revision number
*/
function GSM_REVISION() external pure returns (uint256);
/**
* @notice Returns the address of the GHO token
* @return The address of GHO token contract
*/
function GHO_TOKEN() external view returns (address);
/**
* @notice Returns the underlying asset of the GSM
* @return The address of the underlying asset
*/
function UNDERLYING_ASSET() external view returns (address);
/**
* @notice Returns the price strategy of the GSM
* @return The address of the price strategy
*/
function PRICE_STRATEGY() external view returns (address);
/**
* @notice Returns the current nonce (for EIP-712 signature methods) of an address
* @param user The address of the user
* @return The current nonce of the user
*/
function nonces(address user) external view returns (uint256);
/**
* @notice Returns the identifier of the Configurator Role
* @return The bytes32 id hash of the Configurator role
*/
function CONFIGURATOR_ROLE() external pure returns (bytes32);
/**
* @notice Returns the identifier of the Token Rescuer Role
* @return The bytes32 id hash of the TokenRescuer role
*/
function TOKEN_RESCUER_ROLE() external pure returns (bytes32);
/**
* @notice Returns the identifier of the Swap Freezer Role
* @return The bytes32 id hash of the SwapFreezer role
*/
function SWAP_FREEZER_ROLE() external pure returns (bytes32);
/**
* @notice Returns the identifier of the Liquidator Role
* @return The bytes32 id hash of the Liquidator role
*/
function LIQUIDATOR_ROLE() external pure returns (bytes32);
/**
* @notice Returns the EIP-712 signature typehash for buyAssetWithSig
* @return The bytes32 signature typehash for buyAssetWithSig
*/
function BUY_ASSET_WITH_SIG_TYPEHASH() external pure returns (bytes32);
/**
* @notice Returns the EIP-712 signature typehash for sellAssetWithSig
* @return The bytes32 signature typehash for sellAssetWithSig
*/
function SELL_ASSET_WITH_SIG_TYPEHASH() external pure returns (bytes32);
}
"
},
"src/contracts/dependencies/openzeppelin-contracts/contracts/access/IAccessControl.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @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.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @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 granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}
"
},
"src/contracts/gho/interfaces/IGhoFacilitator.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title IGhoFacilitator
* @author Aave
* @notice Defines the behavior of a Gho Facilitator
*/
interface IGhoFacilitator {
/**
* @dev Emitted when fees are distributed to the GhoTreasury
* @param ghoTreasury The address of the ghoTreasury
* @param asset The address of the asset transferred to the ghoTreasury
* @param amount The amount of the asset transferred to the ghoTreasury
*/
event FeesDistributedToTreasury(
address indexed ghoTreasury,
address indexed asset,
uint256 amount
);
/**
* @dev Emitted when Gho Treasury address is updated
* @param oldGhoTreasury The address of the old GhoTreasury contract
* @param newGhoTreasury The address of the new GhoTreasury contract
*/
event GhoTreasuryUpdated(address indexed oldGhoTreasury, address indexed newGhoTreasury);
/**
* @notice Distribute fees to the GhoTreasury
*/
function distributeFeesToTreasury() external;
/**
* @notice Updates the address of the Gho Treasury
* @dev WARNING: The GhoTreasury is where revenue fees are sent to. Update carefully
* @param newGhoTreasury The address of the GhoTreasury
*/
function updateGhoTreasury(address newGhoTreasury) external;
/**
* @notice Returns the address of the Gho Treasury
* @return The address of the GhoTreasury contract
*/
function getGhoTreasury() external view returns (address);
}
"
}
},
"settings": {
"remappings": [
"forge-std/=lib/forge-std/src/",
"aave-v3-origin/=lib/aave-v3-origin/src/",
"aave-v3-origin-tests/=lib/aave-v3-origin/tests/",
"solidity-utils/=lib/aave-v3-origin/lib/solidity-utils/src/",
"@openzeppelin/contracts-upgradeable/=lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/contracts/",
"@openzeppelin/contracts/=lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/",
"ds-test/=lib/aave-v3-origin/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
"halmos-cheatcodes/=lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
"openzeppelin-contracts-upgradeable/=lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false
}
}}
Submitted on: 2025-10-23 16:19:42
Comments
Log in to comment.
No comments yet.