Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x60e06040 | 22573075 | 252 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
UmbrellaConfigEngine
Compiler Version
v0.8.27+commit.40a35a09
Optimization Enabled:
Yes with 200 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;
import {IERC20} from 'openzeppelin-contracts/contracts/token/ERC20/IERC20.sol';
import {SafeERC20} from 'openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol';
import {IRescuableBase, RescuableBase} from 'solidity-utils/contracts/utils/RescuableBase.sol';
import {Rescuable} from 'solidity-utils/contracts/utils/Rescuable.sol';
import {IUmbrellaStkManager as ISMStructs, IUmbrellaConfiguration as ICStructs} from '../IUmbrellaEngineStructs.sol';
import {IUmbrellaEngineStructs as IStructs, IRewardsStructs as IRStructs} from '../IUmbrellaEngineStructs.sol';
import {IUmbrellaConfigEngine} from './IUmbrellaConfigEngine.sol';
import {EngineUtils} from '../utils/EngineUtils.sol';
import {IUmbrella} from '../../umbrella/interfaces/IUmbrella.sol';
import {IRewardsController} from '../../rewards/interfaces/IRewardsController.sol';
/**
* @dev Helper smart contract performing actions using internal libraries.
*
* ***IMPORTANT*** This engine MUST BE STATELESS always.
*
* Assumptions:
* - Only one `RewardsController` per network
* - Only one `Umbrella` per `Pool`
* - For each `Umbrella` separate `UmbrellaConfigEngine` will be deployed
*
* @author BGD Labs
*/
contract UmbrellaConfigEngine is Rescuable, IUmbrellaConfigEngine {
using SafeERC20 for IERC20;
address public immutable REWARDS_CONTROLLER;
address public immutable RESCUE_GUARDIAN;
address public immutable UMBRELLA;
constructor(address rewardsController, address umbrella, address guardian) {
require(
rewardsController != address(0) && umbrella != address(0) && guardian != address(0),
ZeroAddress()
);
REWARDS_CONTROLLER = rewardsController;
RESCUE_GUARDIAN = guardian;
UMBRELLA = umbrella;
}
/// Functions for basic and extended payloads
/////////////////////////////////////////////////////////////////////////////////////////
/// Umbrella
/////////////////////////////////////////////////////////////////////////////////////////
function executeCreateTokens(
ISMStructs.StakeTokenSetup[] memory configs
) public returns (address[] memory) {
return IUmbrella(UMBRELLA).createStakeTokens(configs);
}
function executeUpdateUnstakeConfigs(IStructs.UnstakeConfig[] memory configs) public {
(
ISMStructs.UnstakeWindowConfig[] memory unstakeWindowConfigs,
ISMStructs.CooldownConfig[] memory cooldownConfigs
) = EngineUtils.repackUnstakeStructs(configs);
executeChangeUnstakeWindows(unstakeWindowConfigs);
executeChangeCooldowns(cooldownConfigs);
}
function executeChangeCooldowns(ISMStructs.CooldownConfig[] memory configs) public {
IUmbrella(UMBRELLA).setCooldownStk(configs);
}
function executeChangeUnstakeWindows(ISMStructs.UnstakeWindowConfig[] memory configs) public {
IUmbrella(UMBRELLA).setUnstakeWindowStk(configs);
}
function executeRemoveSlashingConfigs(ICStructs.SlashingConfigRemoval[] memory configs) public {
IUmbrella(UMBRELLA).removeSlashingConfigs(configs);
}
function executeUpdateSlashingConfigs(ICStructs.SlashingConfigUpdate[] memory configs) public {
IUmbrella(UMBRELLA).updateSlashingConfigs(configs);
}
function executeSetDeficitOffsets(IStructs.SetDeficitOffset[] memory configs) public {
for (uint256 i; i < configs.length; ++i) {
IUmbrella(UMBRELLA).setDeficitOffset(configs[i].reserve, configs[i].newDeficitOffset);
}
}
function executeCoverPendingDeficits(IStructs.CoverDeficit[] memory configs) public {
for (uint256 i; i < configs.length; ++i) {
if (configs[i].approve) {
_approveBeforeCoverage(configs[i].reserve, configs[i].amount);
}
IUmbrella(UMBRELLA).coverPendingDeficit(configs[i].reserve, configs[i].amount);
}
}
function executeCoverDeficitOffsets(IStructs.CoverDeficit[] memory configs) public {
for (uint256 i; i < configs.length; ++i) {
if (configs[i].approve) {
_approveBeforeCoverage(configs[i].reserve, configs[i].amount);
}
IUmbrella(UMBRELLA).coverDeficitOffset(configs[i].reserve, configs[i].amount);
}
}
function executeCoverReserveDeficits(IStructs.CoverDeficit[] memory configs) public {
for (uint256 i; i < configs.length; ++i) {
if (configs[i].approve) {
_approveBeforeCoverage(configs[i].reserve, configs[i].amount);
}
IUmbrella(UMBRELLA).coverReserveDeficit(configs[i].reserve, configs[i].amount);
}
}
/// RewardsController
/////////////////////////////////////////////////////////////////////////////////////////
function executeConfigureStakesAndRewards(
IStructs.ConfigureStakeAndRewardsConfig[] memory configs
) public {
for (uint256 i; i < configs.length; ++i) {
configs[i].targetLiquidity = EngineUtils.getTargetLiquidity(
configs[i].umbrellaStake,
configs[i].targetLiquidity,
REWARDS_CONTROLLER
);
EngineUtils.repackRewardConfigs(
configs[i].rewardConfigs,
configs[i].umbrellaStake,
REWARDS_CONTROLLER
);
IRewardsController(REWARDS_CONTROLLER).configureAssetWithRewards(
configs[i].umbrellaStake,
configs[i].targetLiquidity,
configs[i].rewardConfigs
);
}
}
function executeConfigureRewards(IStructs.ConfigureRewardsConfig[] memory configs) public {
for (uint256 i; i < configs.length; ++i) {
EngineUtils.repackRewardConfigs(
configs[i].rewardConfigs,
configs[i].umbrellaStake,
REWARDS_CONTROLLER
);
IRewardsController(REWARDS_CONTROLLER).configureRewards(
configs[i].umbrellaStake,
configs[i].rewardConfigs
);
}
}
/// Functions for extended payloads
/////////////////////////////////////////////////////////////////////////////////////////
function executeComplexRemovals(IStructs.TokenRemoval[] memory configs) public {
(
ICStructs.SlashingConfigRemoval[] memory slashingConfigs,
IStructs.ConfigureRewardsConfig[] memory rewardsConfigs
) = EngineUtils.repackRemovalStructs(configs, REWARDS_CONTROLLER, UMBRELLA);
executeRemoveSlashingConfigs(slashingConfigs);
executeConfigureRewards(rewardsConfigs);
(
ISMStructs.UnstakeWindowConfig[] memory unstakeWindowConfigs,
ISMStructs.CooldownConfig[] memory cooldownConfigs
) = EngineUtils.repackInstantUnstakeStructs(configs);
executeChangeUnstakeWindows(unstakeWindowConfigs);
executeChangeCooldowns(cooldownConfigs);
}
function executeComplexCreations(IStructs.TokenSetup[] memory configs) public {
address[] memory createdTokens = executeCreateTokens(EngineUtils.repackCreateStructs(configs));
(
ICStructs.SlashingConfigUpdate[] memory slashingConfigs,
IStructs.ConfigureStakeAndRewardsConfig[] memory rewardConfigs
) = EngineUtils.repackInitStructs(configs, createdTokens);
executeUpdateSlashingConfigs(slashingConfigs);
executeConfigureStakesAndRewards(rewardConfigs);
executeSetDeficitOffsets(EngineUtils.repackDeficitIncreaseStructs(configs, UMBRELLA));
}
/////////////////////////////////////////////////////////////////////////////////////////
function whoCanRescue() public view override returns (address) {
return RESCUE_GUARDIAN;
}
function maxRescue(
address
) public pure override(IRescuableBase, RescuableBase) returns (uint256) {
return type(uint256).max;
}
/////////////////////////////////////////////////////////////////////////////////////////
function _approveBeforeCoverage(address reserve, uint256 amount) internal {
address tokenForCoverage = IUmbrella(UMBRELLA).tokenForDeficitCoverage(reserve);
IERC20(tokenForCoverage).forceApprove(UMBRELLA, amount);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
import {Address} from "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
// bubble errors
if iszero(success) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
returnSize := returndatasize()
returnValue := mload(0)
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
bool success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
returnSize := returndatasize()
returnValue := mload(0)
}
return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import {IERC20} from 'openzeppelin-contracts/contracts/token/ERC20/IERC20.sol';
import {SafeERC20} from 'openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol';
import {IRescuableBase} from './interfaces/IRescuableBase.sol';
abstract contract RescuableBase is IRescuableBase {
using SafeERC20 for IERC20;
/// @inheritdoc IRescuableBase
function maxRescue(address erc20Token) public view virtual returns (uint256);
function _emergencyTokenTransfer(address erc20Token, address to, uint256 amount) internal {
uint256 max = maxRescue(erc20Token);
amount = max > amount ? amount : max;
IERC20(erc20Token).safeTransfer(to, amount);
emit ERC20Rescued(msg.sender, erc20Token, to, amount);
}
function _emergencyEtherTransfer(address to, uint256 amount) internal {
(bool success, ) = to.call{value: amount}(new bytes(0));
if (!success) {
revert EthTransferFailed();
}
emit NativeTokensRescued(msg.sender, to, amount);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import {IERC20} from 'openzeppelin-contracts/contracts/token/ERC20/IERC20.sol';
import {RescuableBase} from './RescuableBase.sol';
import {IRescuable} from './interfaces/IRescuable.sol';
/**
* @title Rescuable
* @author BGD Labs
* @notice abstract contract with the methods to rescue tokens (ERC20 and native) from a contract
*/
abstract contract Rescuable is RescuableBase, IRescuable {
/// @notice modifier that checks that caller is allowed address
modifier onlyRescueGuardian() {
if (msg.sender != whoCanRescue()) {
revert OnlyRescueGuardian();
}
_;
}
/// @inheritdoc IRescuable
function emergencyTokenTransfer(
address erc20Token,
address to,
uint256 amount
) external virtual onlyRescueGuardian {
_emergencyTokenTransfer(erc20Token, to, amount);
}
/// @inheritdoc IRescuable
function emergencyEtherTransfer(address to, uint256 amount) external virtual onlyRescueGuardian {
_emergencyEtherTransfer(to, amount);
}
function whoCanRescue() public view virtual returns (address);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;
import {IUmbrellaStkManager} from '../umbrella/interfaces/IUmbrellaStkManager.sol';
import {IUmbrellaConfiguration} from '../umbrella/interfaces/IUmbrellaConfiguration.sol';
import {IRewardsStructs} from '../rewards/interfaces/IRewardsStructs.sol';
/**
* @title IUmbrellaEngineStructs interface
* @notice An interface containing structures that can be used externally.
* @author BGD labs
*/
interface IUmbrellaEngineStructs {
/// Umbrella
/////////////////////////////////////////////////////////////////////////////////////////
struct UnstakeConfig {
/// @notice Address of the `UmbrellaStakeToken` to be configured
address umbrellaStake;
/// @notice New duration of `cooldown` to be set (could be set as `KEEP_CURRENT`)
uint256 newCooldown;
/// @notice New duration of `unstakeWindow` to be set (could be set as `KEEP_CURRENT`)
uint256 newUnstakeWindow;
}
struct SetDeficitOffset {
/// @notice Reserve address
address reserve;
/// @notice New amount of `deficitOffset` to set for this reserve
uint256 newDeficitOffset;
}
struct CoverDeficit {
/// @notice Reserve address
address reserve;
/// @notice Amount of `aToken`s (or reserve) to be eliminated
uint256 amount;
/// @notice True - make `forceApprove` for required amount of tokens, false - skip
bool approve;
}
/// RewardsController
/////////////////////////////////////////////////////////////////////////////////////////
struct ConfigureStakeAndRewardsConfig {
/// @notice Address of the `asset` to be configured/initialized
address umbrellaStake;
/// @notice Amount of liquidity where will be the maximum emission of rewards per second applied (could be set as KEEP_CURRENT)
uint256 targetLiquidity;
/// @notice Optional array of reward configs, can be empty
IRewardsStructs.RewardSetupConfig[] rewardConfigs;
}
struct ConfigureRewardsConfig {
/// @notice Address of the `asset` whose reward should be configured
address umbrellaStake;
/// @notice Array of structs with params to set
IRewardsStructs.RewardSetupConfig[] rewardConfigs;
}
/// Structs for extended payloads
/////////////////////////////////////////////////////////////////////////////////////////
struct TokenRemoval {
/// @notice Address of the `UmbrellaStakeToken` which should be removed from the system
address umbrellaStake;
/// @notice Address that must transfer all rewards that have not been received by users
address residualRewardPayer;
}
struct TokenSetup {
/// @notice `UmbrellaStakeToken`s setup config
IUmbrellaStkManager.StakeTokenSetup stakeSetup;
/// @notice Amount of liquidity where will be the maximum emission of rewards per second applied
uint256 targetLiquidity;
/// @notice Optional array of reward configs, can be empty
IRewardsStructs.RewardSetupConfig[] rewardConfigs;
/// @notice Reserve address
address reserve;
/// @notice Percentage of funds slashed on top of the new deficit
uint256 liquidationFee;
/// @notice Oracle of `UmbrellaStakeToken`s underlying
address umbrellaStakeUnderlyingOracle;
/// @notice The value by which `deficitOffset` will be increased
uint256 deficitOffsetIncrease;
}
/////////////////////////////////////////////////////////////////////////////////////////
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;
import {IUmbrellaEngineStructs as IStructs} from '../IUmbrellaEngineStructs.sol';
import {IUmbrellaStkManager as ISMStructs, IUmbrellaConfiguration as ICStructs} from '../IUmbrellaEngineStructs.sol';
/**
* @title IUmbrellaConfigEngine interface
* @notice Interface to define functions that can be called from `UmbrellaBasePayload` and `UmbrellaExtendedPayload`.
* @author BGD labs
*/
interface IUmbrellaConfigEngine {
/// @dev Attempted to set zero address as parameter.
error ZeroAddress();
/// Umbrella
/////////////////////////////////////////////////////////////////////////////////////////
function executeCreateTokens(
ISMStructs.StakeTokenSetup[] memory configs
) external returns (address[] memory);
function executeUpdateUnstakeConfigs(IStructs.UnstakeConfig[] memory configs) external;
function executeChangeCooldowns(ISMStructs.CooldownConfig[] memory configs) external;
function executeChangeUnstakeWindows(ISMStructs.UnstakeWindowConfig[] memory configs) external;
function executeRemoveSlashingConfigs(ICStructs.SlashingConfigRemoval[] memory configs) external;
function executeUpdateSlashingConfigs(ICStructs.SlashingConfigUpdate[] memory configs) external;
function executeSetDeficitOffsets(IStructs.SetDeficitOffset[] memory configs) external;
function executeCoverPendingDeficits(IStructs.CoverDeficit[] memory configs) external;
function executeCoverDeficitOffsets(IStructs.CoverDeficit[] memory configs) external;
function executeCoverReserveDeficits(IStructs.CoverDeficit[] memory configs) external;
/// RewardsController
/////////////////////////////////////////////////////////////////////////////////////////
function executeConfigureStakesAndRewards(
IStructs.ConfigureStakeAndRewardsConfig[] memory configs
) external;
function executeConfigureRewards(IStructs.ConfigureRewardsConfig[] memory configs) external;
/// Functions for extended payloads
/////////////////////////////////////////////////////////////////////////////////////////
function executeComplexRemovals(IStructs.TokenRemoval[] memory configs) external;
function executeComplexCreations(IStructs.TokenSetup[] memory configs) external;
/////////////////////////////////////////////////////////////////////////////////////////
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;
import {IUmbrellaStkManager as ISMStructs, IUmbrellaConfiguration as ICStructs} from '../IUmbrellaEngineStructs.sol';
import {IUmbrellaEngineStructs as IStructs, IRewardsStructs as IRStructs} from '../IUmbrellaEngineStructs.sol';
import {EngineFlags} from '../EngineFlags.sol';
import {IUmbrella} from '../../umbrella/interfaces/IUmbrella.sol';
import {IRewardsController} from '../../rewards/interfaces/IRewardsController.sol';
library EngineUtils {
function getTargetLiquidity(
address umbrellaStake,
uint256 targetLiquidity,
address rewardsController
) internal view returns (uint256) {
if (targetLiquidity == EngineFlags.KEEP_CURRENT) {
targetLiquidity = IRewardsController(rewardsController)
.getAssetData(umbrellaStake)
.targetLiquidity;
}
return targetLiquidity;
}
function repackRewardConfigs(
IRStructs.RewardSetupConfig[] memory configs,
address umbrellaStake,
address rewardsController
) internal view {
for (uint256 i; i < configs.length; ++i) {
bool getEmission = configs[i].maxEmissionPerSecond == EngineFlags.KEEP_CURRENT;
bool getDistribution = configs[i].distributionEnd == EngineFlags.KEEP_CURRENT;
if (getEmission || getDistribution) {
IRStructs.RewardDataExternal memory rewardData = IRewardsController(rewardsController)
.getRewardData(umbrellaStake, configs[i].reward);
if (getEmission) {
configs[i].maxEmissionPerSecond = rewardData.maxEmissionPerSecond;
}
if (getDistribution) {
configs[i].distributionEnd = rewardData.distributionEnd;
}
}
}
}
function repackRemovalStructs(
IStructs.TokenRemoval[] memory configs,
address rewardsController,
address umbrella
)
internal
view
returns (ICStructs.SlashingConfigRemoval[] memory, IStructs.ConfigureRewardsConfig[] memory)
{
IStructs.ConfigureRewardsConfig[]
memory removeRewardsConfigs = new IStructs.ConfigureRewardsConfig[](configs.length);
ICStructs.SlashingConfigRemoval[]
memory removeSlashingConfigs = new ICStructs.SlashingConfigRemoval[](configs.length);
for (uint256 i; i < configs.length; ++i) {
removeRewardsConfigs[i] = repackRewardsRemovalStructs(configs[i], rewardsController);
removeSlashingConfigs[i] = repackSlashingConfigRemovalStructs(
configs[i].umbrellaStake,
umbrella
);
}
deleteStakesWithEmptyRewards(removeRewardsConfigs);
return (removeSlashingConfigs, removeRewardsConfigs);
}
function repackDeficitIncreaseStructs(
IStructs.TokenSetup[] memory configs,
address umbrella
) internal view returns (IStructs.SetDeficitOffset[] memory) {
IStructs.SetDeficitOffset[]
memory deficitOffsetIncreaseConfigs = new IStructs.SetDeficitOffset[](configs.length);
uint256 deficitOffsetIncreaseArrayLength;
for (uint256 i; i < configs.length; ++i) {
if (configs[i].deficitOffsetIncrease != 0) {
uint256 currentDeficitOffset = IUmbrella(umbrella).getDeficitOffset(configs[i].reserve);
deficitOffsetIncreaseConfigs[deficitOffsetIncreaseArrayLength++] = IStructs
.SetDeficitOffset({
reserve: configs[i].reserve,
newDeficitOffset: configs[i].deficitOffsetIncrease + currentDeficitOffset
});
}
}
assembly {
mstore(deficitOffsetIncreaseConfigs, deficitOffsetIncreaseArrayLength)
}
return deficitOffsetIncreaseConfigs;
}
function repackRewardsRemovalStructs(
IStructs.TokenRemoval memory tokenRemoval,
address rewardsController
) internal view returns (IStructs.ConfigureRewardsConfig memory) {
(, IRStructs.RewardDataExternal[] memory rewardsData) = IRewardsController(rewardsController)
.getAssetAndRewardsData(tokenRemoval.umbrellaStake);
IRStructs.RewardSetupConfig[] memory rewardsRemoval = new IRStructs.RewardSetupConfig[](
rewardsData.length
);
uint256 numberOfActiveRewards;
for (uint256 i; i < rewardsData.length; ++i) {
if (
rewardsData[i].maxEmissionPerSecond == 0 ||
rewardsData[i].distributionEnd <= block.timestamp
) {
continue;
}
rewardsRemoval[numberOfActiveRewards++] = IRStructs.RewardSetupConfig({
reward: rewardsData[i].addr,
rewardPayer: tokenRemoval.residualRewardPayer,
maxEmissionPerSecond: 0,
distributionEnd: block.timestamp
});
}
assembly {
mstore(rewardsRemoval, numberOfActiveRewards)
}
return
IStructs.ConfigureRewardsConfig({
umbrellaStake: tokenRemoval.umbrellaStake,
rewardConfigs: rewardsRemoval
});
}
function repackSlashingConfigRemovalStructs(
address umbrellaStake,
address umbrella
) internal view returns (ICStructs.SlashingConfigRemoval memory) {
ICStructs.StakeTokenData memory data = IUmbrella(umbrella).getStakeTokenData(umbrellaStake);
return ICStructs.SlashingConfigRemoval({reserve: data.reserve, umbrellaStake: umbrellaStake});
}
function repackUnstakeStructs(
IStructs.UnstakeConfig[] memory configs
)
internal
pure
returns (ISMStructs.UnstakeWindowConfig[] memory, ISMStructs.CooldownConfig[] memory)
{
ISMStructs.UnstakeWindowConfig[] memory unstakeConfigs = new ISMStructs.UnstakeWindowConfig[](
configs.length
);
ISMStructs.CooldownConfig[] memory cooldownConfigs = new ISMStructs.CooldownConfig[](
configs.length
);
uint256 unstakeConfigsToChange;
uint256 cooldownConfigsToChange;
for (uint256 i; i < configs.length; ++i) {
if (configs[i].newUnstakeWindow != EngineFlags.KEEP_CURRENT) {
unstakeConfigs[unstakeConfigsToChange++] = ISMStructs.UnstakeWindowConfig({
umbrellaStake: configs[i].umbrellaStake,
newUnstakeWindow: configs[i].newUnstakeWindow
});
}
if (configs[i].newCooldown != EngineFlags.KEEP_CURRENT) {
cooldownConfigs[cooldownConfigsToChange++] = ISMStructs.CooldownConfig({
umbrellaStake: configs[i].umbrellaStake,
newCooldown: configs[i].newCooldown
});
}
}
assembly {
mstore(unstakeConfigs, unstakeConfigsToChange)
mstore(cooldownConfigs, cooldownConfigsToChange)
}
return (unstakeConfigs, cooldownConfigs);
}
function repackInstantUnstakeStructs(
IStructs.TokenRemoval[] memory configs
)
internal
pure
returns (ISMStructs.UnstakeWindowConfig[] memory, ISMStructs.CooldownConfig[] memory)
{
ISMStructs.UnstakeWindowConfig[] memory unstakeConfigs = new ISMStructs.UnstakeWindowConfig[](
configs.length
);
ISMStructs.CooldownConfig[] memory cooldownConfigs = new ISMStructs.CooldownConfig[](
configs.length
);
for (uint256 i; i < configs.length; ++i) {
unstakeConfigs[i] = ISMStructs.UnstakeWindowConfig({
umbrellaStake: configs[i].umbrellaStake,
newUnstakeWindow: type(uint32).max
});
cooldownConfigs[i] = ISMStructs.CooldownConfig({
umbrellaStake: configs[i].umbrellaStake,
newCooldown: 0
});
}
return (unstakeConfigs, cooldownConfigs);
}
function repackCreateStructs(
IStructs.TokenSetup[] memory configs
) internal pure returns (ISMStructs.StakeTokenSetup[] memory) {
ISMStructs.StakeTokenSetup[] memory createStkConfigs = new ISMStructs.StakeTokenSetup[](
configs.length
);
for (uint256 i; i < configs.length; ++i) {
createStkConfigs[i] = configs[i].stakeSetup;
}
return createStkConfigs;
}
function repackInitStructs(
IStructs.TokenSetup[] memory configs,
address[] memory createdTokens
)
internal
pure
returns (
ICStructs.SlashingConfigUpdate[] memory,
IStructs.ConfigureStakeAndRewardsConfig[] memory
)
{
ICStructs.SlashingConfigUpdate[]
memory initSlashingConfigs = new ICStructs.SlashingConfigUpdate[](configs.length);
IStructs.ConfigureStakeAndRewardsConfig[]
memory configsForStakesAndRewards = new IStructs.ConfigureStakeAndRewardsConfig[](
configs.length
);
for (uint256 i; i < configs.length; ++i) {
initSlashingConfigs[i] = ICStructs.SlashingConfigUpdate({
reserve: configs[i].reserve,
umbrellaStake: createdTokens[i],
liquidationFee: configs[i].liquidationFee,
umbrellaStakeUnderlyingOracle: configs[i].umbrellaStakeUnderlyingOracle
});
configsForStakesAndRewards[i] = IStructs.ConfigureStakeAndRewardsConfig({
umbrellaStake: createdTokens[i],
targetLiquidity: configs[i].targetLiquidity,
rewardConfigs: configs[i].rewardConfigs
});
}
return (initSlashingConfigs, configsForStakesAndRewards);
}
function deleteStakesWithEmptyRewards(
IStructs.ConfigureRewardsConfig[] memory configs
) internal pure {
uint256 numberOfConfigs;
for (uint256 i; i < configs.length; ++i) {
if (configs[i].rewardConfigs.length == 0) {
continue;
}
configs[numberOfConfigs++] = configs[i];
}
assembly {
mstore(configs, numberOfConfigs)
}
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;
import {IUmbrellaStkManager} from './IUmbrellaStkManager.sol';
interface IUmbrella is IUmbrellaStkManager {
/**
* @notice Event is emitted whenever the `deficitOffset` is covered on some amount.
* @param reserve Reserve which `deficitOffset` is covered
* @param amount Amount of covered `deficitOffset`
*/
event DeficitOffsetCovered(address indexed reserve, uint256 amount);
/**
* @notice Event is emitted whenever the `pendingDeficit` is covered on some amount.
* @param reserve Reserve which `pendingDeficit` is covered
* @param amount Amount of covered `pendingDeficit`
*/
event PendingDeficitCovered(address indexed reserve, uint256 amount);
/**
* @notice Event is emitted whenever the deficit for untuned inside `Umbrella` reserve is covered on some amount.
* @param reserve Reserve which `reserve.deficit` is covered
* @param amount Amount of covered `reserve.deficit`
*/
event ReserveDeficitCovered(address indexed reserve, uint256 amount);
/**
* @notice Event is emitted when funds are slashed from a `umbrellaStake` to cover a reserve deficit.
* @param reserve Reserve address for which funds are slashed
* @param umbrellaStake Address of the `UmbrellaStakeToken` from which funds are transferred
* @param amount Amount of funds slashed for future deficit elimination
* @param fee Additional fee amount slashed on top of the amount
*/
event StakeTokenSlashed(
address indexed reserve,
address indexed umbrellaStake,
uint256 amount,
uint256 fee
);
/**
* @dev Attempted to change `deficitOffset` for a reserve that does not have a slashing configuration.
*/
error ReserveCoverageNotSetup();
/**
* @dev Attempted to set `deficitOffset` less than possible to avoid immediate slashing.
*/
error TooMuchDeficitOffsetReduction();
/**
* @dev Attempted to cover zero deficit.
*/
error ZeroDeficitToCover();
/**
* @dev Attempted to slash for reserve with zero new deficit or without `SlashingConfig` setup.
*/
error CannotSlash();
/**
* @dev Attempted to slash a basket of `StakeToken`s. Unreachable error in the current version.
*/
error NotImplemented();
/**
* @dev Attempted to call `coverReserveDeficit()` of reserve, which has some configuration.
* In this case functions `coverPendingDeficit` or `coverDeficitOffset` should be used instead.
*/
error ReserveIsConfigured();
// DEFAULT_ADMIN_ROLE
/////////////////////////////////////////////////////////////////////////////////////////
/**
* @notice Sets a new `deficitOffset` value for this `reserve`.
* @dev `deficitOffset` can be increased arbitrarily by a value exceeding `poolDeficit - pendingDeficit`.
* It can also be decreased, but not less than the same value `poolDeficit - pendingDeficit`.
* `deficitOffset` can only be changed for reserves that have at least 1 `SlashingConfig` setup.
* @param reserve Reserve address
* @param newDeficitOffset New amount of `deficitOffset` to set for this reserve
*/
function setDeficitOffset(address reserve, uint256 newDeficitOffset) external;
// COVERAGE_MANAGER_ROLE
/////////////////////////////////////////////////////////////////////////////////////////
/**
* @notice Pulls funds to resolve `pendingDeficit` **up to** specified amount.
* @dev If the amount exceeds the existing `pendingDeficit`, only the `pendingDeficit` will be eliminated.
* @param reserve Reserve address
* @param amount Amount of `aToken`s (or reserve) to be eliminated
* @return The amount of `pendingDeficit` eliminated
*/
function coverPendingDeficit(address reserve, uint256 amount) external returns (uint256);
/**
* @notice Pulls funds to resolve `deficitOffset` **up to** specified amount.
* @dev If the amount exceeds the existing `deficitOffset`, only the `deficitOffset` will be eliminated.
* @param reserve Reserve address
* @param amount Amount of `aToken`s (or reserve) to be eliminated
* @return The amount of `deficitOffset` eliminated
*/
function coverDeficitOffset(address reserve, uint256 amount) external returns (uint256);
/**
* @notice Pulls funds to resolve `reserve.deficit` **up to** specified amount.
* @dev If the amount exceeds the existing `reserve.deficit`, only the `reserve.deficit` will be eliminated.
* Can only be called if this reserve is not configured within `Umbrella`.
* (If the reserve has uncovered `deficitOffset`, `pendingDeficit` or at least one `SlashingConfig` is set, then the function will revert.
* In this case, to call this function you must first cover `pendingDeficit` and `deficitOffset`, along with removing all `SlashingConfig`s
* or use `coverPendingDeficit/coverDeficitOffset` instead.)
* @param reserve Reserve address
* @param amount Amount of `aToken`s (or reserve) to be eliminated
* @return The amount of `reserve.deficit` eliminated
*/
function coverReserveDeficit(address reserve, uint256 amount) external returns (uint256);
/////////////////////////////////////////////////////////////////////////////////////////
/**
* @notice Performs a slashing to cover **up to** the `Pool.getReserveDeficit(reserve) - (pendingDeficit + deficitOffset)`.
* @param reserve Reserve address
* @return New added and covered deficit
*/
function slash(address reserve) external returns (uint256);
/**
* @notice Returns an address of token, which should be used to cover reserve deficit.
* @param reserve Reserve address
* @return Address of token to use for deficit coverage
*/
function tokenForDeficitCoverage(address reserve) external view returns (address);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {IRewardsDistributor} from './IRewardsDistributor.sol';
interface IRewardsController is IRewardsDistributor {
/**
* @notice Event is emitted when an asset is initialized.
* @param asset Address of the new `asset` added
*/
event AssetInitialized(address indexed asset);
/**
* @notice Event is emitted when a `targetLiquidity` of the `asset` is changed.
* @param asset Address of the `asset`
* @param newTargetLiquidity New amount of `targetLiquidity` set for the `asset`
*/
event TargetLiquidityUpdated(address indexed asset, uint256 newTargetLiquidity);
/**
* @notice Event is emitted when a `lastUpdatedTimestamp` of the `asset` is updated.
* @param asset Address of the `asset`
* @param newTimestamp New value of `lastUpdatedTimestamp` updated for the `asset`
*/
event LastTimestampUpdated(address indexed asset, uint256 newTimestamp);
/**
* @notice Event is emitted when a reward is initialized for concrete `asset`.
* @param asset Address of the `asset`
* @param reward Address of the `reward`
*/
event RewardInitialized(address indexed asset, address indexed reward);
/**
* @notice Event is emitted when a reward config is updated.
* @param asset Address of the `asset`
* @param reward Address of the `reward`
* @param maxEmissionPerSecond Amount of maximum possible rewards emission per second
* @param distributionEnd Timestamp after which distribution ends
* @param rewardPayer Address from where rewards will be transferred
*/
event RewardConfigUpdated(
address indexed asset,
address indexed reward,
uint256 maxEmissionPerSecond,
uint256 distributionEnd,
address rewardPayer
);
/**
* @notice Event is emitted when a `reward` index is updated.
* @param asset Address of the `asset`
* @param reward Address of the `reward`
* @param newIndex New `reward` index updated for certain `asset`
*/
event RewardIndexUpdated(address indexed asset, address indexed reward, uint256 newIndex);
/**
* @notice Event is emitted when a user interacts with the asset (transfer, mint, burn) or manually updates the rewards data or claims them
* @param asset Address of the `asset`
* @param reward Address of the `reward`, which `user` data is updated
* @param user Address of the `user` whose `reward` data is updated
* @param newIndex Reward index set after update
* @param accruedFromLastUpdate Amount of accrued rewards from last update
*/
event UserDataUpdated(
address indexed asset,
address indexed reward,
address indexed user,
uint256 newIndex,
uint256 accruedFromLastUpdate
);
/**
* @notice Event is emitted when a `user` `reward` is claimed.
* @param asset Address of the `asset`, whose `reward` was claimed
* @param reward Address of the `reward`, which is claimed
* @param user Address of the `user` whose `reward` is claimed
* @param receiver Address of the funds receiver
* @param amount Amount of the received funds
*/
event RewardClaimed(
address indexed asset,
address indexed reward,
address indexed user,
address receiver,
uint256 amount
);
/**
* @dev Attempted to update data on the `asset` before it was initialized.
*/
error AssetNotInitialized(address asset);
/**
* @dev Attempted to change the configuration of the `reward` before it was initialized.
*/
error RewardNotInitialized(address reward);
/**
* @dev Attempted to set `distributionEnd` less than `block.timestamp` during `reward` initialization.
*/
error InvalidDistributionEnd();
/**
* @dev Attempted to initialize more rewards than limit.
*/
error MaxRewardsLengthReached();
// DEFAULT_ADMIN_ROLE
/////////////////////////////////////////////////////////////////////////////////////////
/**
* @notice Configures asset: sets `targetLiquidity` and updates `lastUpdatedTimestamp`.
* If the asset has already been initialized, then updates the rewards indexes and `lastUpdatedTimestamp`,
* also changes `targetLiquidity`, otherwise initializes asset and rewards.
* @dev `targetLiquidity` should be greater than 1 whole token.
* `maxEmissionPerSecond` inside `rewardConfig` should be less than 1000 tokens and greater than 2 wei.
* It must also be greater than `targetLiquidity * 1000 / 1e18`. Check EmissionMath.sol for more info.
* if `maxEmissionPerSecond` is zero or `distributionEnd` is less than current `block.timestamp`,
* then disable distribution for this `reward` if it was previously initialized.
* It can't initialize already disabled reward.
* @param asset Address of the `asset` to be configured/initialized
* @param targetLiquidity Amount of liquidity where will be the maximum emission of rewards per second applied
* @param rewardConfigs Optional array of reward configs, can be empty
*/
function configureAssetWithRewards(
address asset,
uint256 targetLiquidity,
RewardSetupConfig[] calldata rewardConfigs
) external;
// REWARDS_ADMIN_ROLE
/////////////////////////////////////////////////////////////////////////////////////////
/**
* @notice Configures already initialized rewards for certain `asset`: sets `distributionEnd` and `maxEmissionPerSecond`.
* If any reward hasn't initialized before then it reverts.
* Before setting new configuration updates all rewards indexes for `asset`.
* @dev `maxEmissionPerSecond` inside `rewardConfig` should be less than 1000 tokens and greater than 2 wei.
* It must also be greater than `targetLiquidity * 1000 / 1e18`. Check EmissionMath.sol for more info.
* If `maxEmissionPerSecond` is zero or `distributionEnd` is less than the current `block.timestamp`,
* then distribution for this `reward` will be disabled.
* @param asset Address of the `asset` whose reward should be configured
* @param rewardConfigs Array of structs with params to set
*/
function configureRewards(address asset, RewardSetupConfig[] calldata rewardConfigs) external;
/////////////////////////////////////////////////////////////////////////////////////////
/**
* @notice Special hook, which is called every time `StakeToken` makes `_update` or `slash`.
* Makes an update and calculates new `index` and `accrued`. Also updates `lastUpdateTimestamp`.
* @dev All variables are passed here before the actual update.
* @param totalSupply Total supply of `StakeToken`
* @param totalAssets Total assets of `StakeToken`
* @param user User, whose `index` and rewards accrued will be updated, if address is zero then skips user update
* @param userBalance Amount of `StakeToken` shares owned by user
*/
function handleAction(
uint256 totalSupply,
uint256 totalAssets,
address user,
uint256 userBalance
) external;
/**
* @notice Updates all `reward` indexes and `lastUpdateTimestamp` for the `asset`.
* @param asset Address of the `asset` whose rewards will be updated
*/
function updateAsset(address asset) external;
/**
* @notice Returns an array of all initialized assets (all `StakeTokens`, which are initialized here).
* @dev Return zero data if assets aren't set.
* @return assets Array of asset addresses
*/
function getAllAssets() external view returns (address[] memory assets);
/**
* @notice Returns an array of all initialized rewards for a certain `asset`.
* @dev Return zero data if asset or rewards aren't set.
* @param asset Address of the `asset` whose rewards should be returned
* @return rewards Array of reward addresses
*/
function getAllRewards(address asset) external view returns (address[] memory rewards);
/**
* @notice Returns all data about the asset and its rewards.
* @dev Return zero data if asset or rewards aren't set.
* Function made without some gas optimizations, so it's recommended to avoid calling it often from non-view method or inside batch.
* If the emission for a specific reward has ended at the time of the call (i.e., block.timestamp >= distributionEnd),
* the function will return a zero emission, even though there may still be remaining rewards.
* Note that the actual reward data will be updated the next time someone manually refreshes the data or interacts with the `StakeToken`.
* @param asset Address of the `asset` whose params should be returned
* @return assetData `targetLiquidity` and `lastUpdatedTimestamp` inside struct
* @return rewardsData All data about rewards including addresses and `RewardData`
*/
function getAssetAndRewardsData(
address asset
)
external
view
returns (AssetDataExternal memory assetData, RewardDataExternal[] memory rewardsData);
/**
* @notice Returns data about the asset.
* @dev Return zero data if asset isn't set.
* @param asset Address of the `asset` whose params should be returned
* @return assetData `targetLiquidity` and `lastUpdatedTimestamp` inside struct
*/
function getAssetData(address asset) external view returns (AssetDataExternal memory assetData);
/**
* @notice Returns data about the reward.
* @dev Return zero data if asset or rewards aren't set.
* If the emission has ended at the time of the call (i.e., block.timestamp >= distributionEnd), the function will return a zero emission,
* even though there may still be remaining rewards.
* Note that the actual reward data will be updated the next time someone manually refreshes the data or interacts with the `StakeToken`.
* @param asset Address of the `asset` whose `reward` params should be returned
* @param reward Address of the `reward` whose params should be returned
* @return rewardData `index`, `maxEmissionPerSecond` and `distributionEnd` and address inside struct, address is duplicated from external one
*/
function getRewardData(
address asset,
address reward
) external view returns (RewardDataExternal memory rewardData);
/**
* @notice Returns data about the reward emission.
* @dev Return zero data if asset or rewards aren't set.
* If `maxEmissionPerSecond` is equal to 1 wei, then `flatEmission` will be 0, although in fact it is not 0 and emission is taken into account correctly inside the code.
* Here this calculation is made specifically to simplify the function behaviour.
* If the emission has ended at the time of the call (i.e., block.timestamp >= distributionEnd), the function will return a zero max and flat emissions,
* even though there may still be remaining rewards.
* Note that the actual reward data will be updated the next time someone manually refreshes the data or interacts with the `StakeToken`.
* @param asset Address of the `asset` whose `reward` emission params should be returned
* @param reward Address of the `reward` whose emission params should be returned
* @return emissionData `targetLiquidity`, `targetLiquidityExcess`, `maxEmission` and `flatEmission` inside struct
*/
function getEmissionData(
address asset,
address reward
) external view returns (EmissionData memory emissionData);
/**
* @notice Returns `user` `index` and `accrued` for all rewards for certain `asset` at the time of the last user update.
* If you want to get current `accrued` of all rewards, see `calculateCurrentUserRewards`.
* @dev Return zero data if asset or rewards aren't set.
* @param asset Address of the `asset` for which the rewards are accumulated
* @param user Address of `user` accumulating rewards
* @return rewards Array of `reward` addresses
* @return userData `index` and `accrued` inside structs
*/
function getUserDataByAsset(
address asset,
address user
) external view returns (address[] memory rewards, UserDataExternal[] memory userData);
/**
* @notice Returns `user` `index` and `accrued` for certain `asset` and `reward` at the time of the last user update.
* If you want to calculate current `accrued` of the `reward`, see `calculateCurrentUserReward`.
* @dev Return zero data if asset or rewards aren't set.
* @param asset Address of the `asset` for which the `reward` is accumulated
* @param reward Address of the accumulating `reward`
* @param user Address of `user` accumulating rewards
* @return data `index` and `accrued` inside struct
*/
function getUserDataByReward(
address asset,
address reward,
address user
) external view returns (UserDataExternal memory data);
/**
* @notice Returns current `reward` indexes for `asset`.
* @dev Return zero if asset or rewards aren't set.
* Function made without some gas optimizations, so it's recommended to avoid calling it often from non-view method or inside batch.
* @param asset Address of the `asset` whose indexes of rewards should be calculated
* @return rewards Array of `reward` addresses
* @return indexes Current indexes
*/
function calculateRewardIndexes(
address asset
) external view returns (address[] memory rewards, uint256[] memory indexes);
/**
* @notice Returns current `index` for certain `asset` and `reward`.
* @dev Return zero if asset or rewards aren't set.
* @param asset Address of the `asset` whose `index` of `reward` should be calculated
* @param reward Address of the accumulating `reward`
* @return index Current `index`
*/
function calculateRewardIndex(
address asset,
address reward
) external view returns (uint256 index);
/**
* @notice Returns `emissionPerSecondScaled` for certain `asset` and `reward`. Returned value scaled to 18 decimals.
* @dev Return zero if asset or rewards aren't set.
* @param asset Address of the `asset` which current emission of `reward` should be returned
* @param reward Address of the `reward` which `emissionPerSecond` should be returned
* @return emissionPerSecondScaled Current amount of rewards distributed every second (scaled to 18 decimals)
*/
function calculateCurrentEmissionScaled(
address asset,
address reward
) external view returns (uint256 emissionPerSecondScaled);
/**
* @notice Returns `emissionPerSecond` for certain `asset` and `reward`.
* @dev Return zero if asset or rewards aren't set.
* An integer quantity is returned, although the accuracy of the calculations in reality is higher.
* @param asset Address of the `asset` which current emission of `reward` should be returned
* @param reward Address of the `reward` which `emissionPerSecond` should be returned
* @return emissionPerSecond Current amount of rewards distributed every second
*/
function calculateCurrentEmission(
address asset,
address reward
) external view returns (uint256 emissionPerSecond);
/**
* @notice Calculates and returns `user` `accrued` amounts for all rewards for certain `asset`.
* @dev Return zero data if asset or rewards aren't set.
* Function made without some gas optimizations, so it's recommended to avoid calling it often from non-view method or inside batch.
* @param asset Address of the `asset` whose rewards are accumulated
* @param user Address of `user` accumulating rewards
* @return rewards Array of `reward` addresses
* @return rewardsAccrued Array of current calculated `accrued` amounts
*/
function calculateCurrentUserRewards(
address asset,
address user
) external view returns (address[] memory rewards, uint256[] memory rewardsAccrued);
/**
* @notice Calculates and returns `user` `accrued` amount for certain `reward` and `asset`.
* @dev Return zero if asset or rewards aren't set.
* @param asset Address of the `asset` whose reward is accumulated
* @param reward Address of the `reward` that accumulates for the user
* @param user Address of `user` accumulating rewards
* @return rewardAccrued Amount of current calculated `accrued` amount
*/
function calculateCurrentUserReward(
address asset,
address reward,
address user
) external view returns (uint256 rewardAccrued);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol)
pragma solidity ^0.8.20;
import {Errors} from "./Errors.sol";
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert Errors.InsufficientBalance(address(this).balance, amount);
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert Errors.FailedCall();
}
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {Errors.FailedCall} error.
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert Errors.InsufficientBalance(address(this).balance, value);
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case
* of an unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {Errors.FailedCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.
*/
function _revert(bytes memory returndata) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly ("memory-safe") {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert Errors.FailedCall();
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
/**
* @title IRescuableBase
* @author BGD Labs
* @notice interface containing the objects, events and methods definitions of the RescuableBase contract
*/
interface IRescuableBase {
error EthTransferFailed();
/**
* @notice emitted when erc20 tokens get rescued
* @param caller address that triggers the rescue
* @param token address of the rescued token
* @param to address that will receive the rescued tokens
* @param amount quantity of tokens rescued
*/
event ERC20Rescued(
address indexed caller,
address indexed token,
address indexed to,
uint256 amount
);
/**
* @notice emitted when native tokens get rescued
* @param caller address that triggers the rescue
* @param to address that will receive the rescued tokens
* @param amount quantity of tokens rescued
*/
event NativeTokensRescued(address indexed caller, address indexed to, uint256 amount);
/**
* @notice method that defined the maximum amount rescuable for any given asset.
* @dev there's currently no way to limit the rescuable "native asset", as we assume erc20s as intended underlying.
* @return the maximum amount of
*/
function maxRescue(address erc20Token) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import {IRescuableBase} from './IRescuableBase.sol';
/**
* @title IRescuable
* @author BGD Labs
* @notice interface containing the objects, events and methods definitions of the Rescuable contract
*/
interface IRescuable is IRescuableBase {
error OnlyRescueGuardian();
/**
* @notice method called to rescue tokens sent erroneously to the contract. Only callable by owner
* @param erc20Token address of the token to rescue
* @param to address to send the tokens
* @param amount of tokens to rescue
*/
function emergencyTokenTransfer(address erc20Token, address to, uint256 amount) external;
/**
* @notice method called to rescue ether sent erroneously to the contract. Only callable by owner
* @param to address to send the eth
* @param amount of eth to rescue
*/
function emergencyEtherTransfer(address to, uint256 amount) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;
import {ITransparentProxyFactory} from 'solidity-utils/contracts/transparent-proxy/interfaces/ITransparentProxyFactory.sol';
import {IUmbrellaConfiguration} from './IUmbrellaConfiguration.sol';
interface IUmbrellaStkManager is IUmbrellaConfiguration {
struct StakeTokenSetup {
/// @notice Address of the underlying token for which the `UmbrellaStakeToken` will be created
address underlying;
/// @notice Cooldown duration of the `UmbrellaStakeToken`
uint256 cooldown;
/// @notice Time period during which funds can be withdrawn from the `UmbrellaStakeToken`
uint256 unstakeWindow;
/// @notice Suffix to be added in the end to name and symbol (optional, can be empty)
string suffix;
}
struct CooldownConfig {
/// @notice `UmbrellaStakeToken` address
address umbrellaStake;
/// @notice Amount of seconds users have to wait between triggering the `cooldown()` and being able to withdraw funds
uint256 newCooldown;
}
struct UnstakeWindowConfig {
/// @notice `UmbrellaStakeToken` address
address umbrellaStake;
/// @notice Amount of seconds users have to withdraw after `cooldown`
uint256 newUnstakeWindow;
}
/**
* @notice Event is emitted when a new `UmbrellaStakeToken` is created.
* @param umbrellaStake Address of the new `UmbrellaStakeToken`
* @param underlying Address of the underlying token it is created for
* @param name Name of the new `UmbrellaStakeToken`
* @param symbol Symbol of the new `UmbrellaStakeToken`
*/
event UmbrellaStakeTokenCreated(
address indexed umbrellaStake,
address indexed underlying,
string name,
string symbol
);
// DEFAULT_ADMIN_ROLE
/////////////////////////////////////////////////////////////////////////////////////////
/**
* @notice Creates new `UmbrellaStakeToken`s.
* @param stakeTokenSetups Array of `UmbrellaStakeToken`s setup configs
* @return stakeTokens Array of new `UmbrellaStakeToken`s addresses
*/
function createStakeTokens(
StakeTokenSetup[] calldata stakeTokenSetups
) external returns (address[] memory stakeTokens);
/**
* @notice Sets a new `cooldown`s (in seconds) for the specified `UmbrellaStakeToken`s.
* @param cooldownConfigs Array of new `cooldown` configs
*/
function setCooldownStk(CooldownConfig[] calldata cooldownConfigs) external;
/**
* @notice Sets a new `unstakeWindow`s (in seconds) for the specified `UmbrellaStakeToken`s.
* @param unstakeWindowConfigs Array of new `unstakeWindow` configs
*/
function setUnstakeWindowStk(UnstakeWindowConfig[] calldata unstakeWindowConfigs) external;
// RESCUE_GUARDIAN_ROLE
/////////////////////////////////////////////////////////////////////////////////////////
/**
* @notice Rescue tokens sent erroneously to the contract.
* @param stk Address of the `UmbrellaStakeToken` to rescue from
* @param erc20Token Address of the token to rescue
* @param to Address of the tokens receiver
* @param amount Amount of tokens to rescue
*/
function emergencyTokenTransferStk(
address stk,
address erc20Token,
address to,
uint256 amount
) external;
/**
* @notice Rescue native currency (e.g. Ethereum) sent erroneously to the contract.
* @param stk Address of the `UmbrellaStakeToken` to rescue from
* @param to Address of the tokens receiver
* @param amount Amount of tokens to rescue
*/
function emergencyEtherTransferStk(address stk, address to, uint256 amount) external;
// PAUSE_GUARDIAN_ROLE
/////////////////////////////////////////////////////////////////////////////////////////
/**
* @notice Pauses `UmbrellaStakeToken`.
* @param stk Address of the `UmbrellaStakeToken` to turn pause on
*/
function pauseStk(address stk) external;
/**
* @notice Unpauses `UmbrellaStakeToken`.
* @param stk Address of the `UmbrellaStakeToken` to turn pause off
*/
function unpauseStk(address stk) external;
/////////////////////////////////////////////////////////////////////////////////////////
/**
* @notice Predicts new `UmbrellaStakeToken`s addresses.
* @dev Should be used only to predict new `UmbrellaStakeToken` addresses and not to calculate already deployed ones.
* @param stakeSetups Array of `UmbrellaStakeToken`s setup configs
* @return stakeTokens Array of new `UmbrellaStakeToken`s predicted addresses
*/
function predictStakeTokensAddresses(
StakeTokenSetup[] calldata stakeSetups
) external view returns (address[] memory);
/**
* @notice Returns a list of all the `UmbrellaStakeToken`s created via this `Umbrella` instance.
* @return Array of addresses containing all the `UmbrellaStakeToken`s
*/
function getStkTokens() external view returns (address[] memory);
/**
* @notice Returns true if the provided address is a `UmbrellaStakeToken` belonging to this `Umbrella` instance.
* @return True if the token is part of this `Umbrella`, false otherwise
*/
function isUmbrellaStkToken(address stakeToken) external view returns (bool);
/**
* @notice Returns the `TransparentProxyFactory` contract used to create `UmbrellaStakeToken`s.
* @return `TransparentProxyFactory` address
*/
function TRANSPARENT_PROXY_FACTORY() external view returns (ITransparentProxyFactory);
/**
* @notice Returns the `UmbrellaStakeToken` implementation used to instantiate new umbrella stake tokens.
* @return `UmbrellaStakeToken` implementation address
*/
function UMBRELLA_STAKE_TOKEN_IMPL() external view returns (address);
/**
* @notice Returns the `SUPER_ADMIN` address, which has `DEFAULT_ADMIN_ROLE` and is used to manage `UmbrellaStakeToken`s upgradability.
* @return `SUPER_ADMIN` address
*/
function SUPER_ADMIN() external view returns (address);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;
import {IPool} from 'aave-v3-origin/contracts/interfaces/IPool.sol';
import {IPoolAddressesProvider} from 'aave-v3-origin/contracts/interfaces/IPoolAddressesProvider.sol';
interface IUmbrellaConfiguration {
struct SlashingConfigUpdate {
/// @notice Reserve which configuration should be updated
address reserve;
/// @notice Address of `UmbrellaStakeToken` that should be set for this reserve
address umbrellaStake;
/// @notice Percentage of funds slashed on top of the new deficit
uint256 liquidationFee;
/// @notice Oracle of `UmbrellaStakeToken`s underlying
address umbrellaStakeUnderlyingOracle;
}
struct SlashingConfigRemoval {
/// @notice Reserve which configuration is being removed
address reserve;
/// @notice Address of `UmbrellaStakeToken` that will be removed from this reserve
address umbrellaStake;
}
struct SlashingConfig {
/// @notice Address of `UmbrellaStakeToken`
address umbrellaStake;
/// @notice `UmbrellaStakeToken` underlying oracle address
address umbrellaStakeUnderlyingOracle;
/// @notice Percentage of funds slashed on top of the new deficit
uint256 liquidationFee;
}
struct StakeTokenData {
/// @notice Oracle for pricing an underlying assets of `UmbrellaStakeToken`
/// @dev Remains after removal of `SlashingConfig`
address underlyingOracle;
/// @notice Reserve address for which this `UmbrellaStakeToken` is configured
/// @dev Will be deleted after removal of `SlashingConfig`
address reserve;
}
/**
* @notice Event is emitted whenever a configuration is added or updated.
* @param reserve Reserve which configuration is changed
* @param umbrellaStake Address of `UmbrellaStakeToken`
* @param liquidationFee Percentage of funds slashed on top of the deficit
* @param umbrellaStakeUnderlyingOracle `UmbrellaStakeToken` underlying oracle address
*/
event SlashingConfigurationChanged(
address indexed reserve,
address indexed umbrellaStake,
uint256 liquidationFee,
address umbrellaStakeUnderlyingOracle
);
/**
* @notice Event is emitted whenever a configuration is removed.
* @param reserve Reserve which configuration is removed
* @param umbrellaStake Address of `UmbrellaStakeToken`
*/
event SlashingConfigurationRemoved(address indexed reserve, address indexed umbrellaStake);
/**
* @notice Event is emitted whenever the `deficitOffset` is changed.
* @param reserve Reserve which `deficitOffset` is changed
* @param newDeficitOffset New amount of `deficitOffset`
*/
event DeficitOffsetChanged(address indexed reserve, uint256 newDeficitOffset);
/**
* @notice Event is emitted whenever the `pendingDeficit` is changed.
* @param reserve Reserve which `pendingDeficit` is changed
* @param newPendingDeficit New amount of `pendingDeficit`
*/
event PendingDeficitChanged(address indexed reserve, uint256 newPendingDeficit);
/**
* @dev Attempted to set zero address.
*/
error ZeroAddress();
/**
* @dev Attempted to interact with a `UmbrellaStakeToken` that should be deployed by this `Umbrella` instance, but is not.
*/
error InvalidStakeToken();
/**
* @dev Attempted to set a `UmbrellaStakeToken` that has a different number of decimals than `reserve`.
*/
error InvalidNumberOfDecimals();
/**
* @dev Attempted to set `liquidationFee` greater than 100%.
*/
error InvalidLiquidationFee();
/**
* @dev Attempted to get `SlashingConfig` for this `reserve` and `StakeToken`, however config doesn't exist for this pair.
*/
error ConfigurationNotExist();
/**
* @dev Attempted to get price of `StakeToken` underlying, however the oracle has never been set.
*/
error ConfigurationHasNotBeenSet();
/**
* @dev Attempted to set `UmbrellaStakeToken`, which is already set for another reserve.
*/
error UmbrellaStakeAlreadySetForAnotherReserve();
/**
* @dev Attempted to add `reserve` to configuration, which isn't exist in the `Pool`.
*/
error InvalidReserve();
/**
* @dev Attempted to set `umbrellaStakeUnderlyingOracle` that returns invalid price.
*/
error InvalidOraclePrice();
// DEFAULT_ADMIN_ROLE
/////////////////////////////////////////////////////////////////////////////////////////
/**
* @notice Updates a set of slashing configurations.
* @dev If the configs contain an already existing configuration, the configuration will be overwritten.
* If install more than 1 configuration, then `slash` will not work in the current version.
* @param slashingConfigs An array of configurations
*/
function updateSlashingConfigs(SlashingConfigUpdate[] calldata slashingConfigs) external;
/**
* @notice Removes a set of slashing configurations.
* @dev If such a config did not exist, the function does not revert.
* @param removalPairs An array of coverage pairs (reserve:stk) to remove
*/
function removeSlashingConfigs(SlashingConfigRemoval[] calldata removalPairs) external;
/////////////////////////////////////////////////////////////////////////////////////////
/**
* @notice Returns all the slashing configurations, configured for a given `reserve`.
* @param reserve Address of the `reserve`
* @return An array of `SlashingConfig` structs
*/
function getReserveSlashingConfigs(
address reserve
) external view returns (SlashingConfig[] memory);
/**
* @notice Returns the slashing configuration for a given `UmbrellaStakeToken` in regards to a specific `reserve`.
* @dev Reverts if `SlashingConfig` doesn't exist.
* @param reserve Address of the `reserve`
* @param umbrellaStake Address of the `UmbrellaStakeToken`
* @return A `SlashingConfig` struct
*/
function getReserveSlashingConfig(
address reserve,
address umbrellaStake
) external view returns (SlashingConfig memory);
/**
* @notice Returns if a reserve is currently slashable or not.
* A reserve is slashable if:
* - there's only one stk configured for slashing
* - if there is a non zero new deficit
* @param reserve Address of the `reserve`
* @return flag If `Umbrella` could slash for a given `reserve`
* @return amount Amount of the new deficit, by which `UmbrellaStakeToken` potentially could be slashed
*/
function isReserveSlashable(address reserve) external view returns (bool flag, uint256 amount);
/**
* @notice Returns the amount of deficit that can't be slashed using `UmbrellaStakeToken` funds.
* @param reserve Address of the `reserve`
* @return The amount of the `deficitOffset`
*/
function getDeficitOffset(address reserve) external view returns (uint256);
/**
* @notice Returns the amount of already slashed funds that have not yet been used for the deficit elimination.
* @param reserve Address of the `reserve`
* @return The amount of funds pending for deficit elimination
*/
function getPendingDeficit(address reserve) external view returns (uint256);
/**
* @notice Returns the `StakeTokenData` of the `umbrellaStake`.
* @param umbrellaStake Address of the `UmbrellaStakeToken`
* @return stakeTokenData A `StakeTokenData` struct
*/
function getStakeTokenData(
address umbrellaStake
) external view returns (StakeTokenData memory stakeTokenData);
/**
* @notice Returns the price of the `UmbrellaStakeToken` underlying.
* @dev This price is used for calculations inside `Umbrella` and should not be used outside of this system.
*
* The underlying price is determined based on the current oracle, if the oracle has never been set, the function will revert.
* The system retains information about the last oracle installed for a given `StakeToken`.
*
* If the `SlashingConfig` associated with the `StakeToken` is removed, this function will still be operational.
* However, the results of its work are not guaranteed.
*
* @param umbrellaStake Address of the `UmbrellaStakeToken`
* @return latestAnswer Price of the underlying
*/
function latestUnderlyingAnswer(
address umbrellaStake
) external view returns (int256 latestAnswer);
/**
* @notice Returns the Pool addresses provider.
* @return Pool addresses provider address
*/
function POOL_ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider);
/**
* @notice Returns the address that is receiving the slashed funds.
* @return Slashed funds recipient
*/
function SLASHED_FUNDS_RECIPIENT() external view returns (address);
/**
* @notice Returns the Aave Pool for which this `Umbrella` instance is configured.
* @return Pool address
*/
function POOL() external view returns (IPool);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
/**
* @title IRewardsStructs interface
* @notice An interface containing structures that can be used externally.
* @author BGD labs
*/
interface IRewardsStructs {
struct RewardSetupConfig {
/// @notice Reward address
address reward;
/// @notice Address, from which this reward will be transferred (should give approval to this address)
address rewardPayer;
/// @notice Maximum possible emission rate of rewards per second
uint256 maxEmissionPerSecond;
/// @notice End of the rewards distribution
uint256 distributionEnd;
}
struct AssetDataExternal {
/// @notice Liquidity value at which there will be maximum emission per second (expected amount of asset to be deposited into `StakeToken`)
uint256 targetLiquidity;
/// @notice Timestamp of the last update
uint256 lastUpdateTimestamp;
}
struct RewardDataExternal {
/// @notice Reward address
address addr;
/// @notice Liquidity index of the reward set during the last update
uint256 index;
/// @notice Maximum possible emission rate of rewards per second
uint256 maxEmissionPerSecond;
/// @notice End of the reward distribution
uint256 distributionEnd;
}
struct EmissionData {
/// @notice Liquidity value at which there will be maximum emission per second applied
uint256 targetLiquidity;
/// @notice Liquidity value after which emission per second will be flat
uint256 targetLiquidityExcess;
/// @notice Maximum possible emission rate of rewards per second (can be with or without scaling to 18 decimals, depending on usage in code)
uint256 maxEmission;
/// @notice Flat emission value per second (can be with or without scaling, depending on usage in code)
uint256 flatEmission;
}
struct UserDataExternal {
/// @notice Liquidity index of the user reward set during the last update
uint256 index;
/// @notice Amount of accrued rewards that the user earned at the time of his last index update (pending to claim)
uint256 accrued;
}
struct SignatureParams {
uint8 v;
bytes32 r;
bytes32 s;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;
library EngineFlags {
/**
* @dev Magic value to be used as flag to keep unchanged any current configuration.
* Strongly assumes that the value `type(uint256).max - 42` will never be used, which seems reasonable
*
* For now could be used for:
* - `unstakeWindow (inside `UnstakeConfig`)
* - `cooldown` (inside `UnstakeConfig`)
* - `targetLiquidity` (inside `ConfigureStakeAndRewardsConfig`)
* - `rewardConfigs[i].maxEmissionPerSecond` (inside `ConfigureStakeAndRewardsConfig` and `ConfigureRewardsConfig`)
* - `rewardConfigs[i].distributionEnd` (inside `ConfigureStakeAndRewardsConfig` and `ConfigureRewardsConfig`)
*/
uint256 internal constant KEEP_CURRENT = type(uint256).max - 42;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {IRewardsStructs} from './IRewardsStructs.sol';
interface IRewardsDistributor is IRewardsStructs {
/**
* @notice Event is emitted when a `user` or admin installs/disables `claimer` for claiming user rewards.
* @param user Address of the `user`
* @param claimer Address of the `claimer` to install/disable
* @param caller Address of the `msg.sender` who changes claimer
* @param flag Flag responsible for setting/disabling `claimer`
*/
event ClaimerSet(
address indexed user,
address indexed claimer,
address indexed caller,
bool flag
);
/**
* @dev Attempted to use signature with expired deadline.
*/
error ExpiredSignature(uint256 deadline);
/**
* @dev Mismatched signature.
*/
error InvalidSigner(address signer, address owner);
/**
* @dev Attempted to claim `reward` without authorization.
*/
error ClaimerNotAuthorized(address claimer, address user);
/**
* @dev Attempted to claim rewards for assets while arrays lengths don't match.
*/
error LengthsDontMatch();
/**
* @dev Attempted to set zero address.
*/
error ZeroAddress();
// DEFAULT_ADMIN_ROLE
/////////////////////////////////////////////////////////////////////////////////////////
/**
* @notice Installs/disables `claimer` for claiming `user` rewards.
* @param user Address of the `user`
* @param claimer Address of the `claimer` to install/disable
* @param flag Flag responsible for setting/disabling `claimer`
*/
function setClaimer(address user, address claimer, bool flag) external;
/////////////////////////////////////////////////////////////////////////////////////////
/**
* @notice Installs/disables `claimer` for claiming `msg.sender` rewards.
* @param claimer Address of the `claimer` to install/disable
* @param flag Flag responsible for setting/disabling `claimer`
*/
function setClaimer(address claimer, bool flag) external;
/**
* @notice Claims all existing `rewards` for a certain `asset` on behalf of `msg.sender`.
* Makes an update and calculates new `index` and `accrued` `rewards` before claim.
* @dev Always claims all `rewards`.
* @param asset Address of the `asset` whose `rewards` should be claimed
* @param receiver Address of the funds receiver
* @return rewards Array containing the addresses of all `reward` tokens claimed
* @return amounts Array containing the corresponding `amounts` of each `reward` claimed
*/
function claimAllRewards(
address asset,
address receiver
) external returns (address[] memory rewards, uint256[] memory amounts);
/**
* @notice Claims all existing `rewards` on behalf of `user` for a certain `asset` by `msg.sender`.
* Makes an update and calculates new `index` and `accrued` `rewards` before claim.
* @dev Always claims all `rewards`.
* @param asset Address of the `asset` whose `rewards` should be claimed
* @param user Address of user, which accrued `rewards` should be claimed
* @param receiver Address of the funds receiver
* @return rewards Array containing the addresses of all `reward` tokens claimed
* @return amounts Array containing the corresponding `amounts` of each `reward` claimed
*/
function claimAllRewardsOnBehalf(
address asset,
address user,
address receiver
) external returns (address[] memory rewards, uint256[] memory amounts);
/**
* @notice Claims all existing `rewards` on behalf of `user` for a certain `asset` using signature.
* Makes an update and calculates new `index` and `accrued` `rewards` before claim.
* @dev Always claims all `rewards`.
* @param asset Address of the `asset` whose `rewards` should be claimed
* @param user Address of user, which accrued `rewards` should be claimed
* @param receiver Address of the funds receiver
* @param deadline Signature deadline for claiming
* @param sig Signature parameters
* @return rewards Array containing the addresses of all `reward` tokens claimed
* @return amounts Array containing the corresponding `amounts` of each `reward` claimed
*/
function claimAllRewardsPermit(
address asset,
address user,
address receiver,
uint256 deadline,
SignatureParams calldata sig
) external returns (address[] memory rewards, uint256[] memory amounts);
/**
* @notice Claims selected `rewards` of `msg.sender` for a certain `asset`.
* Makes an update and calculates new `index` and `accrued` `rewards` before claim.
* @param asset Address of the `asset` whose `rewards` should be claimed
* @param rewards Array of `reward` addresses, which should be claimed
* @param receiver Address of the funds receiver
* @return amounts Array containing the corresponding `amounts` of each `reward` claimed
*/
function claimSelectedRewards(
address asset,
address[] calldata rewards,
address receiver
) external returns (uint256[] memory amounts);
/**
* @notice Claims selected `rewards` on behalf of `user` for a certain `asset` by `msg.sender`.
* Makes an update and calculates new `index` and `accrued` `rewards` before claim.
* @param asset Address of the `asset` whose `rewards` should be claimed
* @param rewards Array of `reward` addresses, which should be claimed
* @param user Address of user, which accrued `rewards` should be claimed
* @param receiver Address of the funds receiver
* @return amounts Array containing the corresponding `amounts` of each `reward` claimed
*/
function claimSelectedRewardsOnBehalf(
address asset,
address[] calldata rewards,
address user,
address receiver
) external returns (uint256[] memory amounts);
/**
* @notice Claims selected `rewards` on behalf of `user` for a certain `asset` using signature.
* Makes an update and calculates new `index` and `accrued` `rewards` before claim.
* @param asset Address of the `asset` whose `rewards` should be claimed
* @param rewards Array of `reward` addresses, which should be claimed
* @param user Address of user, which accrued `rewards` should be claimed
* @param receiver Address of the funds receiver
* @param deadline Signature deadline for claiming
* @param sig Signature parameters
* @return amounts Array containing the corresponding `amounts` of each `reward` claimed
*/
function claimSelectedRewardsPermit(
address asset,
address[] calldata rewards,
address user,
address receiver,
uint256 deadline,
SignatureParams calldata sig
) external returns (uint256[] memory amounts);
/**
* @notice Claims all existing `rewards` of `msg.sender` across multiple `assets`.
* Makes an update and calculates new `index` and `accrued` `rewards` before claim.
* @dev Always claims all `rewards`.
* @param assets Array of addresses representing the `assets`, whose `rewards` should be claimed
* @param receiver Address of the funds receiver
* @return rewards Two-dimensional array where each inner array contains the addresses of `reward` tokens for a specific `asset`
* @return amounts Two-dimensional array where each inner array contains the amounts of each `reward` claimed for a specific `asset`
*/
function claimAllRewards(
address[] calldata assets,
address receiver
) external returns (address[][] memory rewards, uint256[][] memory amounts);
/**
* @notice Claims all existing `rewards` on behalf of `user` across multiple `assets` by `msg.sender`.
* Makes an update and calculates new `index` and `accrued` `rewards` before claim.
* @dev Always claims all `rewards`.
* @param assets Array of addresses representing the `assets`, whose `rewards` should be claimed
* @param user Address of user, which accrued `rewards` should be claimed
* @param receiver Address of the funds receiver
* @return rewards Two-dimensional array where each inner array contains the addresses of `reward` tokens for a specific `asset`
* @return amounts Two-dimensional array where each inner array contains the amounts of each `reward` claimed for a specific `asset`
*/
function claimAllRewardsOnBehalf(
address[] calldata assets,
address user,
address receiver
) external returns (address[][] memory rewards, uint256[][] memory amounts);
/**
* @notice Claims selected `rewards` of `msg.sender` across multiple `assets`.
* Makes an update and calculates new `index` and `accrued` `rewards` before claim.
* @param assets Array of addresses representing the `assets`, whose `rewards` should be claimed
* @param rewards Two-dimensional array where each inner array contains the addresses of `rewards` for a specific `asset`
* @param receiver Address of the funds receiver
* @return amounts Two-dimensional array where each inner array contains the amounts of each `reward` claimed for a specific `asset`
*/
function claimSelectedRewards(
address[] calldata assets,
address[][] calldata rewards,
address receiver
) external returns (uint256[][] memory);
/**
* @notice Claims selected `rewards` on behalf of `user` across multiple `assets` by `msg.sender`.
* Makes an update and calculates new `index` and `accrued` `rewards` before claim.
* @param assets Array of addresses representing the `assets`, whose `rewards` should be claimed
* @param rewards Two-dimensional array where each inner array contains the addresses of `rewards` for a specific `asset`
* @param user Address of user, which accrued `rewards` should be claimed
* @param receiver Address of the funds receiver
* @return amounts Two-dimensional array where each inner array contains the amounts of each `reward` claimed for a specific `asset`
*/
function claimSelectedRewardsOnBehalf(
address[] calldata assets,
address[][] calldata rewards,
address user,
address receiver
) external returns (uint256[][] memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of common custom errors used in multiple contracts
*
* IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
* It is recommended to avoid relying on the error API for critical functionality.
*
* _Available since v5.1._
*/
library Errors {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error InsufficientBalance(uint256 balance, uint256 needed);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedCall();
/**
* @dev The deployment failed.
*/
error FailedDeployment();
/**
* @dev A necessary precompile is missing.
*/
error MissingPrecompile(address);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface ITransparentProxyFactory {
event ProxyCreated(address proxy, address indexed logic, address indexed initialOwner);
event ProxyAdminCreated(address proxyAdmin, address indexed initialOwner);
event ProxyDeterministicCreated(
address proxy,
address indexed logic,
address indexed initialOwner,
bytes32 indexed salt
);
event ProxyAdminDeterministicCreated(
address proxyAdmin,
address indexed initialOwner,
bytes32 indexed salt
);
/**
* @notice Creates a transparent proxy instance, doing the first initialization in construction
* @dev Version using CREATE
* @param logic The address of the implementation contract
* @param initialOwner The initial owner of the admin of the proxy.
* @param data abi encoded call to the function with `initializer` (or `reinitializer`) modifier.
* E.g. `abi.encodeWithSelector(mockImpl.initialize.selector, 2)`
* for an `initialize` function being `function initialize(uint256 foo) external initializer;`
* @return address The address of the proxy deployed
**/
function create(
address logic,
address initialOwner,
bytes memory data
) external returns (address);
/**
* @notice Creates a proxyAdmin instance, and transfers ownership to provided owner
* @dev Version using CREATE
* @param initialOwner The initial owner of the proxyAdmin deployed.
* @return address The address of the proxyAdmin deployed
**/
function createProxyAdmin(address initialOwner) external returns (address);
/**
* @notice Creates a transparent proxy instance, doing the first initialization in construction
* @dev Version using CREATE2, so deterministic
* @param logic The address of the implementation contract
* @param initialOwner The initial owner of the admin of the proxy.
* @param data abi encoded call to the function with `initializer` (or `reinitializer`) modifier.
* E.g. `abi.encodeWithSelector(mockImpl.initialize.selector, 2)`
* for an `initialize` function being `function initialize(uint256 foo) external initializer;`
* @param salt Value to be used in the address calculation, to be chosen by the account calling this function
* @return address The address of the proxy deployed
**/
function createDeterministic(
address logic,
address initialOwner,
bytes memory data,
bytes32 salt
) external returns (address);
/**
* @notice Deterministically create a proxy admin instance and transfers ownership to provided owner.
* @dev Version using CREATE2, so deterministic
* @param adminOwner The owner of the ProxyAdmin deployed.
* @param salt Value to be used in the address calculation, to be chosen by the account calling this function
* @return address The address of the proxy admin deployed
**/
function createDeterministicProxyAdmin(
address adminOwner,
bytes32 salt
) external returns (address);
/**
* @notice Pre-calculates and return the address on which `createDeterministic` will deploy a proxy
* @param logic The address of the implementation contract
* @param initialOwner The initial owner of the admin of the proxy.
* @param data abi encoded call to the function with `initializer` (or `reinitializer`) modifier.
* E.g. `abi.encodeWithSelector(mockImpl.initialize.selector, 2)`
* for an `initialize` function being `function initialize(uint256 foo) external initializer;`
* @param salt Value to be used in the address calculation, to be chosen by the account calling this function
* @return address The pre-calculated address
**/
function predictCreateDeterministic(
address logic,
address initialOwner,
bytes calldata data,
bytes32 salt
) external view returns (address);
/**
* @notice Pre-calculates and return the address on which `createDeterministic` will deploy the proxyAdmin
* @param salt Value to be used in the address calculation, to be chosen by the account calling this function
* @return address The pre-calculated address
**/
function predictCreateDeterministicProxyAdmin(
bytes32 salt,
address initialOwner
) external view returns (address);
/**
* @notice Returns the address of the `ProxyAdmin` associated with a given transparent proxy.
* @param proxy Address of the transparent proxy
* @return address Address of the `ProxyAdmin` that was deployed when the proxy was created
*/
function getProxyAdmin(address proxy) external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IPoolAddressesProvider} from './IPoolAddressesProvider.sol';
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
/**
* @title IPool
* @author Aave
* @notice Defines the basic interface for an Aave Pool.
*/
interface IPool {
/**
* @dev Emitted on mintUnbacked()
* @param reserve The address of the underlying asset of the reserve
* @param user The address initiating the supply
* @param onBehalfOf The beneficiary of the supplied assets, receiving the aTokens
* @param amount The amount of supplied assets
* @param referralCode The referral code used
*/
event MintUnbacked(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
uint16 indexed referralCode
);
/**
* @dev Emitted on backUnbacked()
* @param reserve The address of the underlying asset of the reserve
* @param backer The address paying for the backing
* @param amount The amount added as backing
* @param fee The amount paid in fees
*/
event BackUnbacked(address indexed reserve, address indexed backer, uint256 amount, uint256 fee);
/**
* @dev Emitted on supply()
* @param reserve The address of the underlying asset of the reserve
* @param user The address initiating the supply
* @param onBehalfOf The beneficiary of the supply, receiving the aTokens
* @param amount The amount supplied
* @param referralCode The referral code used
*/
event Supply(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
uint16 indexed referralCode
);
/**
* @dev Emitted on withdraw()
* @param reserve The address of the underlying asset being withdrawn
* @param user The address initiating the withdrawal, owner of aTokens
* @param to The address that will receive the underlying
* @param amount The amount to be withdrawn
*/
event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount);
/**
* @dev Emitted on borrow() and flashLoan() when debt needs to be opened
* @param reserve The address of the underlying asset being borrowed
* @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just
* initiator of the transaction on flashLoan()
* @param onBehalfOf The address that will be getting the debt
* @param amount The amount borrowed out
* @param interestRateMode The rate mode: 2 for Variable, 1 is deprecated (changed on v3.2.0)
* @param borrowRate The numeric rate at which the user has borrowed, expressed in ray
* @param referralCode The referral code used
*/
event Borrow(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
DataTypes.InterestRateMode interestRateMode,
uint256 borrowRate,
uint16 indexed referralCode
);
/**
* @dev Emitted on repay()
* @param reserve The address of the underlying asset of the reserve
* @param user The beneficiary of the repayment, getting his debt reduced
* @param repayer The address of the user initiating the repay(), providing the funds
* @param amount The amount repaid
* @param useATokens True if the repayment is done using aTokens, `false` if done with underlying asset directly
*/
event Repay(
address indexed reserve,
address indexed user,
address indexed repayer,
uint256 amount,
bool useATokens
);
/**
* @dev Emitted on borrow(), repay() and liquidationCall() when using isolated assets
* @param asset The address of the underlying asset of the reserve
* @param totalDebt The total isolation mode debt for the reserve
*/
event IsolationModeTotalDebtUpdated(address indexed asset, uint256 totalDebt);
/**
* @dev Emitted when the user selects a certain asset category for eMode
* @param user The address of the user
* @param categoryId The category id
*/
event UserEModeSet(address indexed user, uint8 categoryId);
/**
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
*/
event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);
/**
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
*/
event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);
/**
* @dev Emitted on flashLoan()
* @param target The address of the flash loan receiver contract
* @param initiator The address initiating the flash loan
* @param asset The address of the asset being flash borrowed
* @param amount The amount flash borrowed
* @param interestRateMode The flashloan mode: 0 for regular flashloan,
* 1 for Stable (Deprecated on v3.2.0), 2 for Variable
* @param premium The fee flash borrowed
* @param referralCode The referral code used
*/
event FlashLoan(
address indexed target,
address initiator,
address indexed asset,
uint256 amount,
DataTypes.InterestRateMode interestRateMode,
uint256 premium,
uint16 indexed referralCode
);
/**
* @dev Emitted when a borrower is liquidated.
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param user The address of the borrower getting liquidated
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
* @param liquidatedCollateralAmount The amount of collateral received by the liquidator
* @param liquidator The address of the liquidator
* @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants
* to receive the underlying collateral asset directly
*/
event LiquidationCall(
address indexed collateralAsset,
address indexed debtAsset,
address indexed user,
uint256 debtToCover,
uint256 liquidatedCollateralAmount,
address liquidator,
bool receiveAToken
);
/**
* @dev Emitted when the state of a reserve is updated.
* @param reserve The address of the underlying asset of the reserve
* @param liquidityRate The next liquidity rate
* @param stableBorrowRate The next stable borrow rate @note deprecated on v3.2.0
* @param variableBorrowRate The next variable borrow rate
* @param liquidityIndex The next liquidity index
* @param variableBorrowIndex The next variable borrow index
*/
event ReserveDataUpdated(
address indexed reserve,
uint256 liquidityRate,
uint256 stableBorrowRate,
uint256 variableBorrowRate,
uint256 liquidityIndex,
uint256 variableBorrowIndex
);
/**
* @dev Emitted when the deficit of a reserve is covered.
* @param reserve The address of the underlying asset of the reserve
* @param caller The caller that triggered the DeficitCovered event
* @param amountCovered The amount of deficit covered
*/
event DeficitCovered(address indexed reserve, address caller, uint256 amountCovered);
/**
* @dev Emitted when the protocol treasury receives minted aTokens from the accrued interest.
* @param reserve The address of the reserve
* @param amountMinted The amount minted to the treasury
*/
event MintedToTreasury(address indexed reserve, uint256 amountMinted);
/**
* @dev Emitted when deficit is realized on a liquidation.
* @param user The user address where the bad debt will be burned
* @param debtAsset The address of the underlying borrowed asset to be burned
* @param amountCreated The amount of deficit created
*/
event DeficitCreated(address indexed user, address indexed debtAsset, uint256 amountCreated);
/**
* @notice Mints an `amount` of aTokens to the `onBehalfOf`
* @param asset The address of the underlying asset to mint
* @param amount The amount to mint
* @param onBehalfOf The address that will receive the aTokens
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
*/
function mintUnbacked(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) external;
/**
* @notice Back the current unbacked underlying with `amount` and pay `fee`.
* @param asset The address of the underlying asset to back
* @param amount The amount to back
* @param fee The amount paid in fees
* @return The backed amount
*/
function backUnbacked(address asset, uint256 amount, uint256 fee) external returns (uint256);
/**
* @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
* - E.g. User supplies 100 USDC and gets in return 100 aUSDC
* @param asset The address of the underlying asset to supply
* @param amount The amount to be supplied
* @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
* wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
* is a different wallet
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
*/
function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external;
/**
* @notice Supply with transfer approval of asset to be supplied done via permit function
* see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713
* @param asset The address of the underlying asset to supply
* @param amount The amount to be supplied
* @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
* wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
* is a different wallet
* @param deadline The deadline timestamp that the permit is valid
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
* @param permitV The V parameter of ERC712 permit sig
* @param permitR The R parameter of ERC712 permit sig
* @param permitS The S parameter of ERC712 permit sig
*/
function supplyWithPermit(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode,
uint256 deadline,
uint8 permitV,
bytes32 permitR,
bytes32 permitS
) external;
/**
* @notice Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned
* E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC
* @param asset The address of the underlying asset to withdraw
* @param amount The underlying amount to be withdrawn
* - Send the value type(uint256).max in order to withdraw the whole aToken balance
* @param to The address that will receive the underlying, same as msg.sender if the user
* wants to receive it on his own wallet, or a different address if the beneficiary is a
* different wallet
* @return The final amount withdrawn
*/
function withdraw(address asset, uint256 amount, address to) external returns (uint256);
/**
* @notice Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower
* already supplied enough collateral, or he was given enough allowance by a credit delegator on the VariableDebtToken
* - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet
* and 100 variable debt tokens
* @param asset The address of the underlying asset to borrow
* @param amount The amount to be borrowed
* @param interestRateMode 2 for Variable, 1 is deprecated on v3.2.0
* @param referralCode The code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
* @param onBehalfOf The address of the user who will receive the debt. Should be the address of the borrower itself
* calling the function if he wants to borrow against his own collateral, or the address of the credit delegator
* if he has been given credit delegation allowance
*/
function borrow(
address asset,
uint256 amount,
uint256 interestRateMode,
uint16 referralCode,
address onBehalfOf
) external;
/**
* @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned
* - E.g. User repays 100 USDC, burning 100 variable debt tokens of the `onBehalfOf` address
* @param asset The address of the borrowed underlying asset previously borrowed
* @param amount The amount to repay
* - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
* @param interestRateMode 2 for Variable, 1 is deprecated on v3.2.0
* @param onBehalfOf The address of the user who will get his debt reduced/removed. Should be the address of the
* user calling the function if he wants to reduce/remove his own debt, or the address of any other
* other borrower whose debt should be removed
* @return The final amount repaid
*/
function repay(
address asset,
uint256 amount,
uint256 interestRateMode,
address onBehalfOf
) external returns (uint256);
/**
* @notice Repay with transfer approval of asset to be repaid done via permit function
* see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713
* @param asset The address of the borrowed underlying asset previously borrowed
* @param amount The amount to repay
* - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
* @param interestRateMode 2 for Variable, 1 is deprecated on v3.2.0
* @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the
* user calling the function if he wants to reduce/remove his own debt, or the address of any other
* other borrower whose debt should be removed
* @param deadline The deadline timestamp that the permit is valid
* @param permitV The V parameter of ERC712 permit sig
* @param permitR The R parameter of ERC712 permit sig
* @param permitS The S parameter of ERC712 permit sig
* @return The final amount repaid
*/
function repayWithPermit(
address asset,
uint256 amount,
uint256 interestRateMode,
address onBehalfOf,
uint256 deadline,
uint8 permitV,
bytes32 permitR,
bytes32 permitS
) external returns (uint256);
/**
* @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the
* equivalent debt tokens
* - E.g. User repays 100 USDC using 100 aUSDC, burning 100 variable debt tokens
* @dev Passing uint256.max as amount will clean up any residual aToken dust balance, if the user aToken
* balance is not enough to cover the whole debt
* @param asset The address of the borrowed underlying asset previously borrowed
* @param amount The amount to repay
* - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
* @param interestRateMode DEPRECATED in v3.2.0
* @return The final amount repaid
*/
function repayWithATokens(
address asset,
uint256 amount,
uint256 interestRateMode
) external returns (uint256);
/**
* @notice Allows suppliers to enable/disable a specific supplied asset as collateral
* @param asset The address of the underlying asset supplied
* @param useAsCollateral True if the user wants to use the supply as collateral, false otherwise
*/
function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;
/**
* @notice Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1
* - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives
* a proportionally amount of the `collateralAsset` plus a bonus to cover market risk
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param user The address of the borrower getting liquidated
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
* @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants
* to receive the underlying collateral asset directly
*/
function liquidationCall(
address collateralAsset,
address debtAsset,
address user,
uint256 debtToCover,
bool receiveAToken
) external;
/**
* @notice Allows smartcontracts to access the liquidity of the pool within one transaction,
* as long as the amount taken plus a fee is returned.
* @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept
* into consideration. For further details please visit https://docs.aave.com/developers/
* @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanReceiver interface
* @param assets The addresses of the assets being flash-borrowed
* @param amounts The amounts of the assets being flash-borrowed
* @param interestRateModes Types of the debt to open if the flash loan is not returned:
* 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver
* 1 -> Deprecated on v3.2.0
* 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
* @param onBehalfOf The address that will receive the debt in the case of using 2 on `modes`
* @param params Variadic packed params to pass to the receiver as extra information
* @param referralCode The code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
*/
function flashLoan(
address receiverAddress,
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata interestRateModes,
address onBehalfOf,
bytes calldata params,
uint16 referralCode
) external;
/**
* @notice Allows smartcontracts to access the liquidity of the pool within one transaction,
* as long as the amount taken plus a fee is returned.
* @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept
* into consideration. For further details please visit https://docs.aave.com/developers/
* @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanSimpleReceiver interface
* @param asset The address of the asset being flash-borrowed
* @param amount The amount of the asset being flash-borrowed
* @param params Variadic packed params to pass to the receiver as extra information
* @param referralCode The code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
*/
function flashLoanSimple(
address receiverAddress,
address asset,
uint256 amount,
bytes calldata params,
uint16 referralCode
) external;
/**
* @notice Returns the user account data across all the reserves
* @param user The address of the user
* @return totalCollateralBase The total collateral of the user in the base currency used by the price feed
* @return totalDebtBase The total debt of the user in the base currency used by the price feed
* @return availableBorrowsBase The borrowing power left of the user in the base currency used by the price feed
* @return currentLiquidationThreshold The liquidation threshold of the user
* @return ltv The loan to value of The user
* @return healthFactor The current health factor of the user
*/
function getUserAccountData(
address user
)
external
view
returns (
uint256 totalCollateralBase,
uint256 totalDebtBase,
uint256 availableBorrowsBase,
uint256 currentLiquidationThreshold,
uint256 ltv,
uint256 healthFactor
);
/**
* @notice Initializes a reserve, activating it, assigning an aToken and debt tokens and an
* interest rate strategy
* @dev Only callable by the PoolConfigurator contract
* @param asset The address of the underlying asset of the reserve
* @param aTokenAddress The address of the aToken that will be assigned to the reserve
* @param variableDebtAddress The address of the VariableDebtToken that will be assigned to the reserve
* @param interestRateStrategyAddress The address of the interest rate strategy contract
*/
function initReserve(
address asset,
address aTokenAddress,
address variableDebtAddress,
address interestRateStrategyAddress
) external;
/**
* @notice Drop a reserve
* @dev Only callable by the PoolConfigurator contract
* @dev Does not reset eMode flags, which must be considered when reusing the same reserve id for a different reserve.
* @param asset The address of the underlying asset of the reserve
*/
function dropReserve(address asset) external;
/**
* @notice Updates the address of the interest rate strategy contract
* @dev Only callable by the PoolConfigurator contract
* @param asset The address of the underlying asset of the reserve
* @param rateStrategyAddress The address of the interest rate strategy contract
*/
function setReserveInterestRateStrategyAddress(
address asset,
address rateStrategyAddress
) external;
/**
* @notice Accumulates interest to all indexes of the reserve
* @dev Only callable by the PoolConfigurator contract
* @dev To be used when required by the configurator, for example when updating interest rates strategy data
* @param asset The address of the underlying asset of the reserve
*/
function syncIndexesState(address asset) external;
/**
* @notice Updates interest rates on the reserve data
* @dev Only callable by the PoolConfigurator contract
* @dev To be used when required by the configurator, for example when updating interest rates strategy data
* @param asset The address of the underlying asset of the reserve
*/
function syncRatesState(address asset) external;
/**
* @notice Sets the configuration bitmap of the reserve as a whole
* @dev Only callable by the PoolConfigurator contract
* @param asset The address of the underlying asset of the reserve
* @param configuration The new configuration bitmap
*/
function setConfiguration(
address asset,
DataTypes.ReserveConfigurationMap calldata configuration
) external;
/**
* @notice Returns the configuration of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The configuration of the reserve
*/
function getConfiguration(
address asset
) external view returns (DataTypes.ReserveConfigurationMap memory);
/**
* @notice Returns the configuration of the user across all the reserves
* @param user The user address
* @return The configuration of the user
*/
function getUserConfiguration(
address user
) external view returns (DataTypes.UserConfigurationMap memory);
/**
* @notice Returns the normalized income of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The reserve's normalized income
*/
function getReserveNormalizedIncome(address asset) external view returns (uint256);
/**
* @notice Returns the normalized variable debt per unit of asset
* @dev WARNING: This function is intended to be used primarily by the protocol itself to get a
* "dynamic" variable index based on time, current stored index and virtual rate at the current
* moment (approx. a borrower would get if opening a position). This means that is always used in
* combination with variable debt supply/balances.
* If using this function externally, consider that is possible to have an increasing normalized
* variable debt that is not equivalent to how the variable debt index would be updated in storage
* (e.g. only updates with non-zero variable debt supply)
* @param asset The address of the underlying asset of the reserve
* @return The reserve normalized variable debt
*/
function getReserveNormalizedVariableDebt(address asset) external view returns (uint256);
/**
* @notice Returns the state and configuration of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The state and configuration data of the reserve
*/
function getReserveData(address asset) external view returns (DataTypes.ReserveDataLegacy memory);
/**
* @notice Returns the virtual underlying balance of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The reserve virtual underlying balance
*/
function getVirtualUnderlyingBalance(address asset) external view returns (uint128);
/**
* @notice Validates and finalizes an aToken transfer
* @dev Only callable by the overlying aToken of the `asset`
* @param asset The address of the underlying asset of the aToken
* @param from The user from which the aTokens are transferred
* @param to The user receiving the aTokens
* @param amount The amount being transferred/withdrawn
* @param balanceFromBefore The aToken balance of the `from` user before the transfer
* @param balanceToBefore The aToken balance of the `to` user before the transfer
*/
function finalizeTransfer(
address asset,
address from,
address to,
uint256 amount,
uint256 balanceFromBefore,
uint256 balanceToBefore
) external;
/**
* @notice Returns the list of the underlying assets of all the initialized reserves
* @dev It does not include dropped reserves
* @return The addresses of the underlying assets of the initialized reserves
*/
function getReservesList() external view returns (address[] memory);
/**
* @notice Returns the number of initialized reserves
* @dev It includes dropped reserves
* @return The count
*/
function getReservesCount() external view returns (uint256);
/**
* @notice Returns the address of the underlying asset of a reserve by the reserve id as stored in the DataTypes.ReserveData struct
* @param id The id of the reserve as stored in the DataTypes.ReserveData struct
* @return The address of the reserve associated with id
*/
function getReserveAddressById(uint16 id) external view returns (address);
/**
* @notice Returns the PoolAddressesProvider connected to this contract
* @return The address of the PoolAddressesProvider
*/
function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider);
/**
* @notice Updates the protocol fee on the bridging
* @param bridgeProtocolFee The part of the premium sent to the protocol treasury
*/
function updateBridgeProtocolFee(uint256 bridgeProtocolFee) external;
/**
* @notice Updates flash loan premiums. Flash loan premium consists of two parts:
* - A part is sent to aToken holders as extra, one time accumulated interest
* - A part is collected by the protocol treasury
* @dev The total premium is calculated on the total borrowed amount
* @dev The premium to protocol is calculated on the total premium, being a percentage of `flashLoanPremiumTotal`
* @dev Only callable by the PoolConfigurator contract
* @param flashLoanPremiumTotal The total premium, expressed in bps
* @param flashLoanPremiumToProtocol The part of the premium sent to the protocol treasury, expressed in bps
*/
function updateFlashloanPremiums(
uint128 flashLoanPremiumTotal,
uint128 flashLoanPremiumToProtocol
) external;
/**
* @notice Configures a new or alters an existing collateral configuration of an eMode.
* @dev In eMode, the protocol allows very high borrowing power to borrow assets of the same category.
* The category 0 is reserved as it's the default for volatile assets
* @param id The id of the category
* @param config The configuration of the category
*/
function configureEModeCategory(
uint8 id,
DataTypes.EModeCategoryBaseConfiguration memory config
) external;
/**
* @notice Replaces the current eMode collateralBitmap.
* @param id The id of the category
* @param collateralBitmap The collateralBitmap of the category
*/
function configureEModeCategoryCollateralBitmap(uint8 id, uint128 collateralBitmap) external;
/**
* @notice Replaces the current eMode borrowableBitmap.
* @param id The id of the category
* @param borrowableBitmap The borrowableBitmap of the category
*/
function configureEModeCategoryBorrowableBitmap(uint8 id, uint128 borrowableBitmap) external;
/**
* @notice Returns the data of an eMode category
* @dev DEPRECATED use independent getters instead
* @param id The id of the category
* @return The configuration data of the category
*/
function getEModeCategoryData(
uint8 id
) external view returns (DataTypes.EModeCategoryLegacy memory);
/**
* @notice Returns the label of an eMode category
* @param id The id of the category
* @return The label of the category
*/
function getEModeCategoryLabel(uint8 id) external view returns (string memory);
/**
* @notice Returns the collateral config of an eMode category
* @param id The id of the category
* @return The ltv,lt,lb of the category
*/
function getEModeCategoryCollateralConfig(
uint8 id
) external view returns (DataTypes.CollateralConfig memory);
/**
* @notice Returns the collateralBitmap of an eMode category
* @param id The id of the category
* @return The collateralBitmap of the category
*/
function getEModeCategoryCollateralBitmap(uint8 id) external view returns (uint128);
/**
* @notice Returns the borrowableBitmap of an eMode category
* @param id The id of the category
* @return The borrowableBitmap of the category
*/
function getEModeCategoryBorrowableBitmap(uint8 id) external view returns (uint128);
/**
* @notice Allows a user to use the protocol in eMode
* @param categoryId The id of the category
*/
function setUserEMode(uint8 categoryId) external;
/**
* @notice Returns the eMode the user is using
* @param user The address of the user
* @return The eMode id
*/
function getUserEMode(address user) external view returns (uint256);
/**
* @notice Resets the isolation mode total debt of the given asset to zero
* @dev It requires the given asset has zero debt ceiling
* @param asset The address of the underlying asset to reset the isolationModeTotalDebt
*/
function resetIsolationModeTotalDebt(address asset) external;
/**
* @notice Sets the liquidation grace period of the given asset
* @dev To enable a liquidation grace period, a timestamp in the future should be set,
* To disable a liquidation grace period, any timestamp in the past works, like 0
* @param asset The address of the underlying asset to set the liquidationGracePeriod
* @param until Timestamp when the liquidation grace period will end
**/
function setLiquidationGracePeriod(address asset, uint40 until) external;
/**
* @notice Returns the liquidation grace period of the given asset
* @param asset The address of the underlying asset
* @return Timestamp when the liquidation grace period will end
**/
function getLiquidationGracePeriod(address asset) external view returns (uint40);
/**
* @notice Returns the total fee on flash loans
* @return The total fee on flashloans
*/
function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint128);
/**
* @notice Returns the part of the bridge fees sent to protocol
* @return The bridge fee sent to the protocol treasury
*/
function BRIDGE_PROTOCOL_FEE() external view returns (uint256);
/**
* @notice Returns the part of the flashloan fees sent to protocol
* @return The flashloan fee sent to the protocol treasury
*/
function FLASHLOAN_PREMIUM_TO_PROTOCOL() external view returns (uint128);
/**
* @notice Returns the maximum number of reserves supported to be listed in this Pool
* @return The maximum number of reserves supported
*/
function MAX_NUMBER_RESERVES() external view returns (uint16);
/**
* @notice Mints the assets accrued through the reserve factor to the treasury in the form of aTokens
* @param assets The list of reserves for which the minting needs to be executed
*/
function mintToTreasury(address[] calldata assets) external;
/**
* @notice Rescue and transfer tokens locked in this contract
* @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 Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
* - E.g. User supplies 100 USDC and gets in return 100 aUSDC
* @dev Deprecated: Use the `supply` function instead
* @param asset The address of the underlying asset to supply
* @param amount The amount to be supplied
* @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
* wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
* is a different wallet
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
*/
function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external;
/**
* @notice It covers the deficit of a specified reserve by burning:
* - the equivalent aToken `amount` for assets with virtual accounting enabled
* - the equivalent `amount` of underlying for assets with virtual accounting disabled (e.g. GHO)
* @dev The deficit of a reserve can occur due to situations where borrowed assets are not repaid, leading to bad debt.
* @param asset The address of the underlying asset to cover the deficit.
* @param amount The amount to be covered, in aToken or underlying on non-virtual accounted assets
*/
function eliminateReserveDeficit(address asset, uint256 amount) external;
/**
* @notice Returns the current deficit of a reserve.
* @param asset The address of the underlying asset of the reserve
* @return The current deficit of the reserve
*/
function getReserveDeficit(address asset) external view returns (uint256);
/**
* @notice Returns the aToken address of a reserve.
* @param asset The address of the underlying asset of the reserve
* @return The address of the aToken
*/
function getReserveAToken(address asset) external view returns (address);
/**
* @notice Returns the variableDebtToken address of a reserve.
* @param asset The address of the underlying asset of the reserve
* @return The address of the variableDebtToken
*/
function getReserveVariableDebtToken(address asset) external view returns (address);
/**
* @notice Gets the address of the external FlashLoanLogic
*/
function getFlashLoanLogic() external view returns (address);
/**
* @notice Gets the address of the external BorrowLogic
*/
function getBorrowLogic() external view returns (address);
/**
* @notice Gets the address of the external BridgeLogic
*/
function getBridgeLogic() external view returns (address);
/**
* @notice Gets the address of the external EModeLogic
*/
function getEModeLogic() external view returns (address);
/**
* @notice Gets the address of the external LiquidationLogic
*/
function getLiquidationLogic() external view returns (address);
/**
* @notice Gets the address of the external PoolLogic
*/
function getPoolLogic() external view returns (address);
/**
* @notice Gets the address of the external SupplyLogic
*/
function getSupplyLogic() external view returns (address);
}// 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;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library DataTypes {
/**
* This exists specifically to maintain the `getReserveData()` interface, since the new, internal
* `ReserveData` struct includes the reserve's `virtualUnderlyingBalance`.
*/
struct ReserveDataLegacy {
//stores the reserve configuration
ReserveConfigurationMap configuration;
//the liquidity index. Expressed in ray
uint128 liquidityIndex;
//the current supply rate. Expressed in ray
uint128 currentLiquidityRate;
//variable borrow index. Expressed in ray
uint128 variableBorrowIndex;
//the current variable borrow rate. Expressed in ray
uint128 currentVariableBorrowRate;
// DEPRECATED on v3.2.0
uint128 currentStableBorrowRate;
//timestamp of last update
uint40 lastUpdateTimestamp;
//the id of the reserve. Represents the position in the list of the active reserves
uint16 id;
//aToken address
address aTokenAddress;
// DEPRECATED on v3.2.0
address stableDebtTokenAddress;
//variableDebtToken address
address variableDebtTokenAddress;
//address of the interest rate strategy
address interestRateStrategyAddress;
//the current treasury balance, scaled
uint128 accruedToTreasury;
//the outstanding unbacked aTokens minted through the bridging feature
uint128 unbacked;
//the outstanding debt borrowed against this asset in isolation mode
uint128 isolationModeTotalDebt;
}
struct ReserveData {
//stores the reserve configuration
ReserveConfigurationMap configuration;
//the liquidity index. Expressed in ray
uint128 liquidityIndex;
//the current supply rate. Expressed in ray
uint128 currentLiquidityRate;
//variable borrow index. Expressed in ray
uint128 variableBorrowIndex;
//the current variable borrow rate. Expressed in ray
uint128 currentVariableBorrowRate;
/// @notice reused `__deprecatedStableBorrowRate` storage from pre 3.2
// the current accumulate deficit in underlying tokens
uint128 deficit;
//timestamp of last update
uint40 lastUpdateTimestamp;
//the id of the reserve. Represents the position in the list of the active reserves
uint16 id;
//timestamp until when liquidations are not allowed on the reserve, if set to past liquidations will be allowed
uint40 liquidationGracePeriodUntil;
//aToken address
address aTokenAddress;
// DEPRECATED on v3.2.0
address __deprecatedStableDebtTokenAddress;
//variableDebtToken address
address variableDebtTokenAddress;
//address of the interest rate strategy
address interestRateStrategyAddress;
//the current treasury balance, scaled
uint128 accruedToTreasury;
//the outstanding unbacked aTokens minted through the bridging feature
uint128 unbacked;
//the outstanding debt borrowed against this asset in isolation mode
uint128 isolationModeTotalDebt;
//the amount of underlying accounted for by the protocol
uint128 virtualUnderlyingBalance;
}
struct ReserveConfigurationMap {
//bit 0-15: LTV
//bit 16-31: Liq. threshold
//bit 32-47: Liq. bonus
//bit 48-55: Decimals
//bit 56: reserve is active
//bit 57: reserve is frozen
//bit 58: borrowing is enabled
//bit 59: DEPRECATED: stable rate borrowing enabled
//bit 60: asset is paused
//bit 61: borrowing in isolation mode is enabled
//bit 62: siloed borrowing enabled
//bit 63: flashloaning enabled
//bit 64-79: reserve factor
//bit 80-115: borrow cap in whole tokens, borrowCap == 0 => no cap
//bit 116-151: supply cap in whole tokens, supplyCap == 0 => no cap
//bit 152-167: liquidation protocol fee
//bit 168-175: DEPRECATED: eMode category
//bit 176-211: unbacked mint cap in whole tokens, unbackedMintCap == 0 => minting disabled
//bit 212-251: debt ceiling for isolation mode with (ReserveConfiguration::DEBT_CEILING_DECIMALS) decimals
//bit 252: virtual accounting is enabled for the reserve
//bit 253-255 unused
uint256 data;
}
struct UserConfigurationMap {
/**
* @dev Bitmap of the users collaterals and borrows. It is divided in pairs of bits, one pair per asset.
* The first bit indicates if an asset is used as collateral by the user, the second whether an
* asset is borrowed by the user.
*/
uint256 data;
}
// DEPRECATED: kept for backwards compatibility, might be removed in a future version
struct EModeCategoryLegacy {
// each eMode category has a custom ltv and liquidation threshold
uint16 ltv;
uint16 liquidationThreshold;
uint16 liquidationBonus;
// DEPRECATED
address priceSource;
string label;
}
struct CollateralConfig {
uint16 ltv;
uint16 liquidationThreshold;
uint16 liquidationBonus;
}
struct EModeCategoryBaseConfiguration {
uint16 ltv;
uint16 liquidationThreshold;
uint16 liquidationBonus;
string label;
}
struct EModeCategory {
// each eMode category has a custom ltv and liquidation threshold
uint16 ltv;
uint16 liquidationThreshold;
uint16 liquidationBonus;
uint128 collateralBitmap;
string label;
uint128 borrowableBitmap;
}
enum InterestRateMode {
NONE,
__DEPRECATED,
VARIABLE
}
struct ReserveCache {
uint256 currScaledVariableDebt;
uint256 nextScaledVariableDebt;
uint256 currLiquidityIndex;
uint256 nextLiquidityIndex;
uint256 currVariableBorrowIndex;
uint256 nextVariableBorrowIndex;
uint256 currLiquidityRate;
uint256 currVariableBorrowRate;
uint256 reserveFactor;
ReserveConfigurationMap reserveConfiguration;
address aTokenAddress;
address variableDebtTokenAddress;
uint40 reserveLastUpdateTimestamp;
}
struct ExecuteLiquidationCallParams {
uint256 reservesCount;
uint256 debtToCover;
address collateralAsset;
address debtAsset;
address user;
bool receiveAToken;
address priceOracle;
uint8 userEModeCategory;
address priceOracleSentinel;
}
struct ExecuteSupplyParams {
address asset;
uint256 amount;
address onBehalfOf;
uint16 referralCode;
}
struct ExecuteBorrowParams {
address asset;
address user;
address onBehalfOf;
uint256 amount;
InterestRateMode interestRateMode;
uint16 referralCode;
bool releaseUnderlying;
uint256 reservesCount;
address oracle;
uint8 userEModeCategory;
address priceOracleSentinel;
}
struct ExecuteRepayParams {
address asset;
uint256 amount;
InterestRateMode interestRateMode;
address onBehalfOf;
bool useATokens;
}
struct ExecuteWithdrawParams {
address asset;
uint256 amount;
address to;
uint256 reservesCount;
address oracle;
uint8 userEModeCategory;
}
struct ExecuteEliminateDeficitParams {
address asset;
uint256 amount;
}
struct ExecuteSetUserEModeParams {
uint256 reservesCount;
address oracle;
uint8 categoryId;
}
struct FinalizeTransferParams {
address asset;
address from;
address to;
uint256 amount;
uint256 balanceFromBefore;
uint256 balanceToBefore;
uint256 reservesCount;
address oracle;
uint8 fromEModeCategory;
}
struct FlashloanParams {
address receiverAddress;
address[] assets;
uint256[] amounts;
uint256[] interestRateModes;
address onBehalfOf;
bytes params;
uint16 referralCode;
uint256 flashLoanPremiumToProtocol;
uint256 flashLoanPremiumTotal;
uint256 reservesCount;
address addressesProvider;
address pool;
uint8 userEModeCategory;
bool isAuthorizedFlashBorrower;
}
struct FlashloanSimpleParams {
address receiverAddress;
address asset;
uint256 amount;
bytes params;
uint16 referralCode;
uint256 flashLoanPremiumToProtocol;
uint256 flashLoanPremiumTotal;
}
struct FlashLoanRepaymentParams {
uint256 amount;
uint256 totalPremium;
uint256 flashLoanPremiumToProtocol;
address asset;
address receiverAddress;
uint16 referralCode;
}
struct CalculateUserAccountDataParams {
UserConfigurationMap userConfig;
uint256 reservesCount;
address user;
address oracle;
uint8 userEModeCategory;
}
struct ValidateBorrowParams {
ReserveCache reserveCache;
UserConfigurationMap userConfig;
address asset;
address userAddress;
uint256 amount;
InterestRateMode interestRateMode;
uint256 reservesCount;
address oracle;
uint8 userEModeCategory;
address priceOracleSentinel;
bool isolationModeActive;
address isolationModeCollateralAddress;
uint256 isolationModeDebtCeiling;
}
struct ValidateLiquidationCallParams {
ReserveCache debtReserveCache;
uint256 totalDebt;
uint256 healthFactor;
address priceOracleSentinel;
}
struct CalculateInterestRatesParams {
uint256 unbacked;
uint256 liquidityAdded;
uint256 liquidityTaken;
uint256 totalDebt;
uint256 reserveFactor;
address reserve;
bool usingVirtualBalance;
uint256 virtualUnderlyingBalance;
}
struct InitReserveParams {
address asset;
address aTokenAddress;
address variableDebtAddress;
address interestRateStrategyAddress;
uint16 reservesCount;
uint16 maxNumberReserves;
}
}{
"remappings": [
"forge-std/=lib/aave-umbrella/lib/forge-std/src/",
"@openzeppelin/contracts-upgradeable/=lib/aave-umbrella/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/contracts/",
"@openzeppelin/contracts/=lib/aave-umbrella/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/",
"openzeppelin-contracts-upgradeable/=lib/aave-umbrella/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/aave-umbrella/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/",
"aave-v3-core/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/src/core/",
"aave-v3-origin-tests/=lib/aave-umbrella/lib/aave-v3-origin/tests/",
"aave-v3-origin/=lib/aave-umbrella/lib/aave-v3-origin/src/",
"aave-v3-periphery/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/src/periphery/",
"solidity-utils/=lib/aave-umbrella/lib/aave-v3-origin/lib/solidity-utils/src/",
"aave-address-book/=lib/aave-helpers/lib/aave-address-book/src/",
"aave-helpers/=lib/aave-helpers/src/",
"aave-umbrella/=lib/aave-umbrella/",
"ds-test/=lib/aave-umbrella/lib/aave-v3-origin/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/aave-umbrella/lib/erc4626-tests/",
"halmos-cheatcodes/=lib/aave-umbrella/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "shanghai",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"rewardsController","type":"address"},{"internalType":"address","name":"umbrella","type":"address"},{"internalType":"address","name":"guardian","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EthTransferFailed","type":"error"},{"inputs":[],"name":"OnlyRescueGuardian","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Rescued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"NativeTokensRescued","type":"event"},{"inputs":[],"name":"RESCUE_GUARDIAN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARDS_CONTROLLER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UMBRELLA","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emergencyEtherTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"erc20Token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emergencyTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"umbrellaStake","type":"address"},{"internalType":"uint256","name":"newCooldown","type":"uint256"}],"internalType":"struct IUmbrellaStkManager.CooldownConfig[]","name":"configs","type":"tuple[]"}],"name":"executeChangeCooldowns","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"umbrellaStake","type":"address"},{"internalType":"uint256","name":"newUnstakeWindow","type":"uint256"}],"internalType":"struct IUmbrellaStkManager.UnstakeWindowConfig[]","name":"configs","type":"tuple[]"}],"name":"executeChangeUnstakeWindows","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"underlying","type":"address"},{"internalType":"uint256","name":"cooldown","type":"uint256"},{"internalType":"uint256","name":"unstakeWindow","type":"uint256"},{"internalType":"string","name":"suffix","type":"string"}],"internalType":"struct IUmbrellaStkManager.StakeTokenSetup","name":"stakeSetup","type":"tuple"},{"internalType":"uint256","name":"targetLiquidity","type":"uint256"},{"components":[{"internalType":"address","name":"reward","type":"address"},{"internalType":"address","name":"rewardPayer","type":"address"},{"internalType":"uint256","name":"maxEmissionPerSecond","type":"uint256"},{"internalType":"uint256","name":"distributionEnd","type":"uint256"}],"internalType":"struct IRewardsStructs.RewardSetupConfig[]","name":"rewardConfigs","type":"tuple[]"},{"internalType":"address","name":"reserve","type":"address"},{"internalType":"uint256","name":"liquidationFee","type":"uint256"},{"internalType":"address","name":"umbrellaStakeUnderlyingOracle","type":"address"},{"internalType":"uint256","name":"deficitOffsetIncrease","type":"uint256"}],"internalType":"struct IUmbrellaEngineStructs.TokenSetup[]","name":"configs","type":"tuple[]"}],"name":"executeComplexCreations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"umbrellaStake","type":"address"},{"internalType":"address","name":"residualRewardPayer","type":"address"}],"internalType":"struct IUmbrellaEngineStructs.TokenRemoval[]","name":"configs","type":"tuple[]"}],"name":"executeComplexRemovals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"umbrellaStake","type":"address"},{"components":[{"internalType":"address","name":"reward","type":"address"},{"internalType":"address","name":"rewardPayer","type":"address"},{"internalType":"uint256","name":"maxEmissionPerSecond","type":"uint256"},{"internalType":"uint256","name":"distributionEnd","type":"uint256"}],"internalType":"struct IRewardsStructs.RewardSetupConfig[]","name":"rewardConfigs","type":"tuple[]"}],"internalType":"struct IUmbrellaEngineStructs.ConfigureRewardsConfig[]","name":"configs","type":"tuple[]"}],"name":"executeConfigureRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"umbrellaStake","type":"address"},{"internalType":"uint256","name":"targetLiquidity","type":"uint256"},{"components":[{"internalType":"address","name":"reward","type":"address"},{"internalType":"address","name":"rewardPayer","type":"address"},{"internalType":"uint256","name":"maxEmissionPerSecond","type":"uint256"},{"internalType":"uint256","name":"distributionEnd","type":"uint256"}],"internalType":"struct IRewardsStructs.RewardSetupConfig[]","name":"rewardConfigs","type":"tuple[]"}],"internalType":"struct IUmbrellaEngineStructs.ConfigureStakeAndRewardsConfig[]","name":"configs","type":"tuple[]"}],"name":"executeConfigureStakesAndRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"reserve","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"approve","type":"bool"}],"internalType":"struct IUmbrellaEngineStructs.CoverDeficit[]","name":"configs","type":"tuple[]"}],"name":"executeCoverDeficitOffsets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"reserve","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"approve","type":"bool"}],"internalType":"struct IUmbrellaEngineStructs.CoverDeficit[]","name":"configs","type":"tuple[]"}],"name":"executeCoverPendingDeficits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"reserve","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"approve","type":"bool"}],"internalType":"struct IUmbrellaEngineStructs.CoverDeficit[]","name":"configs","type":"tuple[]"}],"name":"executeCoverReserveDeficits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"underlying","type":"address"},{"internalType":"uint256","name":"cooldown","type":"uint256"},{"internalType":"uint256","name":"unstakeWindow","type":"uint256"},{"internalType":"string","name":"suffix","type":"string"}],"internalType":"struct IUmbrellaStkManager.StakeTokenSetup[]","name":"configs","type":"tuple[]"}],"name":"executeCreateTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"reserve","type":"address"},{"internalType":"address","name":"umbrellaStake","type":"address"}],"internalType":"struct IUmbrellaConfiguration.SlashingConfigRemoval[]","name":"configs","type":"tuple[]"}],"name":"executeRemoveSlashingConfigs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"reserve","type":"address"},{"internalType":"uint256","name":"newDeficitOffset","type":"uint256"}],"internalType":"struct IUmbrellaEngineStructs.SetDeficitOffset[]","name":"configs","type":"tuple[]"}],"name":"executeSetDeficitOffsets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"reserve","type":"address"},{"internalType":"address","name":"umbrellaStake","type":"address"},{"internalType":"uint256","name":"liquidationFee","type":"uint256"},{"internalType":"address","name":"umbrellaStakeUnderlyingOracle","type":"address"}],"internalType":"struct IUmbrellaConfiguration.SlashingConfigUpdate[]","name":"configs","type":"tuple[]"}],"name":"executeUpdateSlashingConfigs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"umbrellaStake","type":"address"},{"internalType":"uint256","name":"newCooldown","type":"uint256"},{"internalType":"uint256","name":"newUnstakeWindow","type":"uint256"}],"internalType":"struct IUmbrellaEngineStructs.UnstakeConfig[]","name":"configs","type":"tuple[]"}],"name":"executeUpdateUnstakeConfigs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxRescue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"whoCanRescue","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60e060405234801561000f575f5ffd5b5060405161348a38038061348a83398101604081905261002e916100b6565b6001600160a01b0383161580159061004e57506001600160a01b03821615155b801561006257506001600160a01b03811615155b61007f5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b03928316608052821660a0521660c0526100f6565b80516001600160a01b03811681146100b1575f5ffd5b919050565b5f5f5f606084860312156100c8575f5ffd5b6100d18461009b565b92506100df6020850161009b565b91506100ed6040850161009b565b90509250925092565b60805160a05160c0516132d76101b35f395f81816101c5015281816103ec0152818161050c0152818161054d015281816105cc01528181610672015281816106e401528181610726015281816109e101528181610a8101528181610afb01528181610d72015281816110bf015261113b01525f81816102600152818161028901528181610a210152610ce501525f81816102b00152818161065101528181610842015281816108c8015281816108ee0152610c1d01526132d75ff3fe608060405234801561000f575f5ffd5b5060043610610132575f3560e01c806392776de8116100b4578063d740871511610079578063d7408715146102d2578063e062987a146102f4578063e790b8e014610307578063eb2328f11461031a578063eed88b8d1461032d578063fc1b453f14610340575f5ffd5b806392776de814610238578063a3d5b2551461024b578063a4757b0f1461025e578063cb86c02514610284578063cd086d45146102ab575f5ffd5b80634d5b0d7a116100fa5780634d5b0d7a146101ad57806371459c15146101c057806384808a23146101ff57806389f8ed6c146102125780638f9ff96714610225575f5ffd5b8063023d6442146101365780630b75ef531461014b5780631d3dadda1461015e57806340e3f6b314610171578063444439f114610184575b5f5ffd5b6101496101443660046122a1565b610353565b005b610149610159366004612364565b610379565b61014961016c3660046125a8565b6104d2565b61014961017f3660046126fd565b610536565b6101976101923660046127d8565b6105b2565b6040516101a4919061287c565b60405180910390f35b6101496101bb366004612952565b610649565b6101e77f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a4565b61014961020d366004612952565b6106cd565b610149610220366004612a12565b610719565b610149610233366004612a56565b6107f7565b610149610246366004612a12565b6109ca565b610149610259366004612b4f565b610a16565b7f00000000000000000000000000000000000000000000000000000000000000006101e7565b6101e77f000000000000000000000000000000000000000000000000000000000000000081565b6101e77f000000000000000000000000000000000000000000000000000000000000000081565b6102e66102e0366004612b8d565b505f1990565b6040519081526020016101a4565b610149610302366004612a12565b610a6a565b610149610315366004612364565b610ab6565b610149610328366004612baf565b610bdd565b61014961033b366004612ca5565b610cda565b61014961034e366004612364565b610d2d565b5f5f61035e83610e54565b9150915061036b82610a6a565b610374816109ca565b505050565b5f5b81518110156104ce5781818151811061039657610396612ccf565b602002602001015160400151156103ea576103ea8282815181106103bc576103bc612ccf565b60200260200101515f01518383815181106103d9576103d9612ccf565b60200260200101516020015161109e565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631e5e18a783838151811061042b5761042b612ccf565b60200260200101515f015184848151811061044857610448612ccf565b6020026020010151602001516040518363ffffffff1660e01b81526004016104859291906001600160a01b03929092168252602082015260400190565b6020604051808303815f875af11580156104a1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104c59190612ce3565b5060010161037b565b5050565b5f6104df61019283611160565b90505f5f6104ed8484611235565b915091506104fa82610536565b610503816107f7565b610530610220857f000000000000000000000000000000000000000000000000000000000000000061148a565b50505050565b60405163284261a960e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635084c35290610582908490600401612cfa565b5f604051808303815f87803b158015610599575f5ffd5b505af11580156105ab573d5f5f3e3d5ffd5b5050505050565b60405163b1f396c560e01b81526060906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b1f396c590610601908590600401612d86565b5f604051808303815f875af115801561061c573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106439190810190612e35565b92915050565b5f5f610696837f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611655565b915091506106a3826106cd565b6106ac81610bdd565b5f5f6106b7856117c6565b915091506106c482610a6a565b6105ab816109ca565b6040516333b7985f60e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063676f30be90610582908490600401612ec4565b5f5b81518110156104ce577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a6307a0a83838151811061076557610765612ccf565b60200260200101515f015184848151811061078257610782612ccf565b6020026020010151602001516040518363ffffffff1660e01b81526004016107bf9291906001600160a01b03929092168252602082015260400190565b5f604051808303815f87803b1580156107d6575f5ffd5b505af11580156107e8573d5f5f3e3d5ffd5b5050505080600101905061071b565b5f5b81518110156104ce5761086682828151811061081757610817612ccf565b60200260200101515f015183838151811061083457610834612ccf565b6020026020010151602001517f000000000000000000000000000000000000000000000000000000000000000061195d565b82828151811061087857610878612ccf565b602002602001015160200181815250506108ec82828151811061089d5761089d612ccf565b6020026020010151604001518383815181106108bb576108bb612ccf565b60200260200101515f01517f00000000000000000000000000000000000000000000000000000000000000006119e3565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635129351c83838151811061092d5761092d612ccf565b60200260200101515f015184848151811061094a5761094a612ccf565b60200260200101516020015185858151811061096857610968612ccf565b6020026020010151604001516040518463ffffffff1660e01b815260040161099293929190612f7e565b5f604051808303815f87803b1580156109a9575f5ffd5b505af11580156109bb573d5f5f3e3d5ffd5b505050508060010190506107f9565b60405163f305644560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f305644590610582908490600401612fad565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a5f57604051633a02626960e01b815260040160405180910390fd5b610374838383611b60565b60405163c4e0c63960e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c4e0c63990610582908490600401613002565b5f5b81518110156104ce57818181518110610ad357610ad3612ccf565b60200260200101516040015115610af957610af98282815181106103bc576103bc612ccf565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663321b4539838381518110610b3a57610b3a612ccf565b60200260200101515f0151848481518110610b5757610b57612ccf565b6020026020010151602001516040518363ffffffff1660e01b8152600401610b949291906001600160a01b03929092168252602082015260400190565b6020604051808303815f875af1158015610bb0573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bd49190612ce3565b50600101610ab8565b5f5b81518110156104ce57610c1b828281518110610bfd57610bfd612ccf565b6020026020010151602001518383815181106108bb576108bb612ccf565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663745ff635838381518110610c5c57610c5c612ccf565b60200260200101515f0151848481518110610c7957610c79612ccf565b6020026020010151602001516040518363ffffffff1660e01b8152600401610ca2929190613057565b5f604051808303815f87803b158015610cb9575f5ffd5b505af1158015610ccb573d5f5f3e3d5ffd5b50505050806001019050610bdf565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610d2357604051633a02626960e01b815260040160405180910390fd5b6104ce8282611be4565b5f5b81518110156104ce57818181518110610d4a57610d4a612ccf565b60200260200101516040015115610d7057610d708282815181106103bc576103bc612ccf565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663423ce3c4838381518110610db157610db1612ccf565b60200260200101515f0151848481518110610dce57610dce612ccf565b6020026020010151602001516040518363ffffffff1660e01b8152600401610e0b9291906001600160a01b03929092168252602082015260400190565b6020604051808303815f875af1158015610e27573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e4b9190612ce3565b50600101610d2f565b6060805f83516001600160401b03811115610e7157610e71612186565b604051908082528060200260200182016040528015610eb557816020015b604080518082019091525f8082526020820152815260200190600190039081610e8f5790505b5090505f84516001600160401b03811115610ed257610ed2612186565b604051908082528060200260200182016040528015610f1657816020015b604080518082019091525f8082526020820152815260200190600190039081610ef05790505b5090505f5f5f5b875181101561108e57610f32602a5f1961308e565b888281518110610f4457610f44612ccf565b60200260200101516040015114610fd6576040518060400160405280898381518110610f7257610f72612ccf565b60200260200101515f01516001600160a01b03168152602001898381518110610f9d57610f9d612ccf565b602002602001015160400151815250858480610fb8906130a1565b955081518110610fca57610fca612ccf565b60200260200101819052505b610fe2602a5f1961308e565b888281518110610ff457610ff4612ccf565b6020026020010151602001511461108657604051806040016040528089838151811061102257611022612ccf565b60200260200101515f01516001600160a01b0316815260200189838151811061104d5761104d612ccf565b602002602001015160200151815250848380611068906130a1565b94508151811061107a5761107a612ccf565b60200260200101819052505b600101610f1d565b5090835281529094909350915050565b604051630393f2a760e61b81526001600160a01b0383811660048301525f917f00000000000000000000000000000000000000000000000000000000000000009091169063e4fca9c090602401602060405180830381865afa158015611106573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061112a91906130b9565b90506103746001600160a01b0382167f000000000000000000000000000000000000000000000000000000000000000084611cb3565b60605f82516001600160401b0381111561117c5761117c612186565b6040519080825280602002602001820160405280156111de57816020015b6111cb60405180608001604052805f6001600160a01b031681526020015f81526020015f8152602001606081525090565b81526020019060019003908161119a5790505b5090505f5b835181101561122e578381815181106111fe576111fe612ccf565b60200260200101515f015182828151811061121b5761121b612ccf565b60209081029190910101526001016111e3565b5092915050565b6060805f84516001600160401b0381111561125257611252612186565b6040519080825280602002602001820160405280156112a257816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f199092019101816112705790505b5090505f85516001600160401b038111156112bf576112bf612186565b60405190808252806020026020018201604052801561130b57816020015b60408051606080820183525f8083526020830152918101919091528152602001906001900390816112dd5790505b5090505f5b865181101561147e57604051806080016040528088838151811061133657611336612ccf565b6020026020010151606001516001600160a01b0316815260200187838151811061136257611362612ccf565b60200260200101516001600160a01b0316815260200188838151811061138a5761138a612ccf565b60200260200101516080015181526020018883815181106113ad576113ad612ccf565b602002602001015160a001516001600160a01b03168152508382815181106113d7576113d7612ccf565b602002602001018190525060405180606001604052808783815181106113ff576113ff612ccf565b60200260200101516001600160a01b0316815260200188838151811061142757611427612ccf565b602002602001015160200151815260200188838151811061144a5761144a612ccf565b60200260200101516040015181525082828151811061146b5761146b612ccf565b6020908102919091010152600101611310565b50909590945092505050565b60605f83516001600160401b038111156114a6576114a6612186565b6040519080825280602002602001820160405280156114ea57816020015b604080518082019091525f80825260208201528152602001906001900390816114c45790505b5090505f5f5b855181101561164b5785818151811061150b5761150b612ccf565b602002602001015160c001515f14611643575f856001600160a01b031663711e932288848151811061153f5761153f612ccf565b6020026020010151606001516040518263ffffffff1660e01b815260040161157691906001600160a01b0391909116815260200190565b602060405180830381865afa158015611591573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115b59190612ce3565b905060405180604001604052808884815181106115d4576115d4612ccf565b6020026020010151606001516001600160a01b031681526020018289858151811061160157611601612ccf565b602002602001015160c0015161161791906130d4565b90528484611624816130a1565b95508151811061163657611636612ccf565b6020026020010181905250505b6001016114f0565b5081529392505050565b6060805f85516001600160401b0381111561167257611672612186565b6040519080825280602002602001820160405280156116b757816020015b604080518082019091525f8152606060208201528152602001906001900390816116905790505b5090505f86516001600160401b038111156116d4576116d4612186565b60405190808252806020026020018201604052801561171857816020015b604080518082019091525f80825260208201528152602001906001900390816116f25790505b5090505f5b87518110156117b15761174988828151811061173b5761173b612ccf565b602002602001015188611d70565b83828151811061175b5761175b612ccf565b602002602001018190525061178c88828151811061177b5761177b612ccf565b60200260200101515f015187611f66565b82828151811061179e5761179e612ccf565b602090810291909101015260010161171d565b506117bb82612019565b969095509350505050565b6060805f83516001600160401b038111156117e3576117e3612186565b60405190808252806020026020018201604052801561182757816020015b604080518082019091525f80825260208201528152602001906001900390816118015790505b5090505f84516001600160401b0381111561184457611844612186565b60405190808252806020026020018201604052801561188857816020015b604080518082019091525f80825260208201528152602001906001900390816118625790505b5090505f5b85518110156119525760405180604001604052808783815181106118b3576118b3612ccf565b60200260200101515f01516001600160a01b0316815260200163ffffffff80168152508382815181106118e8576118e8612ccf565b6020026020010181905250604051806040016040528087838151811061191057611910612ccf565b60200260200101515f01516001600160a01b031681526020015f81525082828151811061193f5761193f612ccf565b602090810291909101015260010161188d565b509094909350915050565b5f61196a602a5f1961308e565b83036119db57604051631652e7b760e01b81526001600160a01b038581166004830152831690631652e7b7906024016040805180830381865afa1580156119b3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119d79190613116565b5192505b509092915050565b5f5b8351811015610530575f6119fb602a5f1961308e565b858381518110611a0d57611a0d612ccf565b6020026020010151604001511490505f602a5f19611a2b919061308e565b868481518110611a3d57611a3d612ccf565b6020026020010151606001511490508180611a555750805b15611b56575f846001600160a01b03166369f67d4287898781518110611a7d57611a7d612ccf565b6020908102919091010151516040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401608060405180830381865afa158015611ad2573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611af6919061317d565b90508215611b26578060400151878581518110611b1557611b15612ccf565b602002602001015160400181815250505b8115611b54578060600151878581518110611b4357611b43612ccf565b602002602001015160600181815250505b505b50506001016119e5565b5f19818111611b6f5780611b71565b815b9150611b876001600160a01b038516848461209c565b826001600160a01b0316846001600160a01b0316336001600160a01b03167fc7af665d489507e14ae25ac7ab0030fc7f570869610bdd32117ea56b60ae5c6185604051611bd691815260200190565b60405180910390a450505050565b604080515f808252602082019092526001600160a01b038416908390604051611c0d9190613197565b5f6040518083038185875af1925050503d805f8114611c47576040519150601f19603f3d011682016040523d82523d5f602084013e611c4c565b606091505b5050905080611c6e57604051630db2c7f160e31b815260040160405180910390fd5b6040518281526001600160a01b0384169033907fb7c602059992183c7b767c08204223afc99f1895fd175adf9ece23ce9f5bb8b79060200160405180910390a3505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052611d0484826120cd565b610530576040516001600160a01b0384811660248301525f6044830152611d6691869182169063095ea7b3906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050612116565b6105308482612116565b604080518082019091525f8152606060208201528251604051636808879d60e11b81526001600160a01b0391821660048201525f9184169063d0110f3a906024015f60405180830381865afa158015611dcb573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611df291908101906131b2565b9150505f81516001600160401b03811115611e0f57611e0f612186565b604051908082528060200260200182016040528015611e5f57816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f19909201910181611e2d5790505b5090505f5f5b8351811015611f3f57838181518110611e8057611e80612ccf565b6020026020010151604001515f1480611eb6575042848281518110611ea757611ea7612ccf565b60200260200101516060015111155b611f37576040518060800160405280858381518110611ed757611ed7612ccf565b60200260200101515f01516001600160a01b0316815260200188602001516001600160a01b031681526020015f815260200142815250838380611f19906130a1565b945081518110611f2b57611f2b612ccf565b60200260200101819052505b600101611e65565b5081526040805180820190915294516001600160a01b031685526020850152509192915050565b604080518082019091525f808252602082015260405163acc5876960e01b81526001600160a01b0384811660048301525f919084169063acc58769906024016040805180830381865afa158015611fbf573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fe39190613260565b9050604051806040016040528082602001516001600160a01b03168152602001856001600160a01b031681525091505092915050565b5f5f5b82518110156120975782818151811061203757612037612ccf565b602002602001015160200151515f031561208f5782818151811061205d5761205d612ccf565b6020026020010151838380612071906130a1565b94508151811061208357612083612ccf565b60200260200101819052505b60010161201c565b509052565b6040516001600160a01b0383811660248301526044820183905261037491859182169063a9059cbb90606401611d34565b5f5f5f5f60205f8651602088015f8a5af192503d91505f51905082801561210c575081156120fe578060011461210c565b5f866001600160a01b03163b115b9695505050505050565b5f5f60205f8451602086015f885af180612135576040513d5f823e3d81fd5b50505f513d9150811561214c578060011415612159565b6001600160a01b0384163b155b1561053057604051635274afe760e01b81526001600160a01b038516600482015260240160405180910390fd5b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b03811182821017156121bc576121bc612186565b60405290565b604051608081016001600160401b03811182821017156121bc576121bc612186565b60405160e081016001600160401b03811182821017156121bc576121bc612186565b604080519081016001600160401b03811182821017156121bc576121bc612186565b604051601f8201601f191681016001600160401b038111828210171561225057612250612186565b604052919050565b5f6001600160401b0382111561227057612270612186565b5060051b60200190565b6001600160a01b038116811461228e575f5ffd5b50565b803561229c8161227a565b919050565b5f602082840312156122b1575f5ffd5b81356001600160401b038111156122c6575f5ffd5b8201601f810184136122d6575f5ffd5b80356122e96122e482612258565b612228565b8082825260208201915060206060840285010192508683111561230a575f5ffd5b6020840193505b8284101561210c5760608488031215612328575f5ffd5b61233061219a565b843561233b8161227a565b815260208581013581830152604080870135908301529083526060909401939190910190612311565b5f60208284031215612374575f5ffd5b81356001600160401b03811115612389575f5ffd5b8201601f81018413612399575f5ffd5b80356123a76122e482612258565b808282526020820191506020606084028501019250868311156123c8575f5ffd5b6020840193505b8284101561210c57606084880312156123e6575f5ffd5b6123ee61219a565b84356123f98161227a565b81526020858101359082015260408501358015158114612417575f5ffd5b60408201528252606093909301926020909101906123cf565b5f60808284031215612440575f5ffd5b6124486121c2565b905081356124558161227a565b8152602082810135908201526040808301359082015260608201356001600160401b03811115612483575f5ffd5b8201601f81018413612493575f5ffd5b80356001600160401b038111156124ac576124ac612186565b6124bf601f8201601f1916602001612228565b8181528560208385010111156124d3575f5ffd5b816020840160208301375f6020838301015280606085015250505092915050565b5f82601f830112612503575f5ffd5b81356125116122e482612258565b8082825260208201915060208360071b860101925085831115612532575f5ffd5b602085015b8381101561259e576080818803121561254e575f5ffd5b6125566121c2565b81356125618161227a565b815260208201356125718161227a565b60208281019190915260408381013590830152606080840135908301529084529290920191608001612537565b5095945050505050565b5f602082840312156125b8575f5ffd5b81356001600160401b038111156125cd575f5ffd5b8201601f810184136125dd575f5ffd5b80356125eb6122e482612258565b8082825260208201915060208360051b85010192508683111561260c575f5ffd5b602084015b838110156126f25780356001600160401b0381111561262e575f5ffd5b850160e0818a03601f19011215612643575f5ffd5b61264b6121e4565b60208201356001600160401b03811115612663575f5ffd5b6126728b602083860101612430565b8252506040820135602082015260608201356001600160401b03811115612697575f5ffd5b6126a68b6020838601016124f4565b6040830152506126b860808301612291565b606082015260a082013560808201526126d360c08301612291565b60a082015260e0919091013560c0820152835260209283019201612611565b509695505050505050565b5f6020828403121561270d575f5ffd5b81356001600160401b03811115612722575f5ffd5b8201601f81018413612732575f5ffd5b80356127406122e482612258565b8082825260208201915060208360071b850101925086831115612761575f5ffd5b6020840193505b8284101561210c576080848803121561277f575f5ffd5b6127876121c2565b84356127928161227a565b815260208501356127a28161227a565b60208201526040858101359082015260608501356127bf8161227a565b6060820152825260809390930192602090910190612768565b5f602082840312156127e8575f5ffd5b81356001600160401b038111156127fd575f5ffd5b8201601f8101841361280d575f5ffd5b803561281b6122e482612258565b8082825260208201915060208360051b85010192508683111561283c575f5ffd5b602084015b838110156126f25780356001600160401b0381111561285e575f5ffd5b61286d89602083890101612430565b84525060209283019201612841565b602080825282518282018190525f918401906040840190835b818110156128bc5783516001600160a01b0316835260209384019390920191600101612895565b509095945050505050565b5f6128d46122e484612258565b838152905060208101600684901b8301858111156128f0575f5ffd5b835b81811015612948575f6040828903121561290a575f5ffd5b612912612206565b9050813561291f8161227a565b8152602082013561292f8161227a565b60208281019190915290845292909201916040016128f2565b5050509392505050565b5f60208284031215612962575f5ffd5b81356001600160401b03811115612977575f5ffd5b8201601f81018413612987575f5ffd5b612996848235602084016128c7565b949350505050565b5f6129ab6122e484612258565b838152905060208101600684901b8301858111156129c7575f5ffd5b835b81811015612948575f604082890312156129e1575f5ffd5b6129e9612206565b905081356129f68161227a565b81526020828101358183015290845292909201916040016129c9565b5f60208284031215612a22575f5ffd5b81356001600160401b03811115612a37575f5ffd5b8201601f81018413612a47575f5ffd5b6129968482356020840161299e565b5f60208284031215612a66575f5ffd5b81356001600160401b03811115612a7b575f5ffd5b8201601f81018413612a8b575f5ffd5b8035612a996122e482612258565b8082825260208201915060208360051b850101925086831115612aba575f5ffd5b602084015b838110156126f25780356001600160401b03811115612adc575f5ffd5b85016060818a03601f19011215612af1575f5ffd5b612af961219a565b6020820135612b078161227a565b81526040820135602082015260608201356001600160401b03811115612b2b575f5ffd5b612b3a8b6020838601016124f4565b60408301525084525060209283019201612abf565b5f5f5f60608486031215612b61575f5ffd5b8335612b6c8161227a565b92506020840135612b7c8161227a565b929592945050506040919091013590565b5f60208284031215612b9d575f5ffd5b8135612ba88161227a565b9392505050565b5f60208284031215612bbf575f5ffd5b81356001600160401b03811115612bd4575f5ffd5b8201601f81018413612be4575f5ffd5b8035612bf26122e482612258565b8082825260208201915060208360051b850101925086831115612c13575f5ffd5b602084015b838110156126f25780356001600160401b03811115612c35575f5ffd5b85016040818a03601f19011215612c4a575f5ffd5b612c52612206565b6020820135612c608161227a565b815260408201356001600160401b03811115612c7a575f5ffd5b612c898b6020838601016124f4565b6020830152508085525050602083019250602081019050612c18565b5f5f60408385031215612cb6575f5ffd5b8235612cc18161227a565b946020939093013593505050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215612cf3575f5ffd5b5051919050565b602080825282518282018190525f918401906040840190835b818110156128bc57835180516001600160a01b039081168552602080830151821681870152604080840151908701526060928301519091169185019190915290930192608090920191600101612d13565b5f5b83811015612d7e578181015183820152602001612d66565b50505f910152565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b82811015612e2957603f19878603018452815160018060a01b038151168652602081015160208701526040810151604087015260608101519050608060608701528051806080880152612e068160a0890160208501612d64565b601f01601f19169590950160a00194506020938401939190910190600101612dac565b50929695505050505050565b5f60208284031215612e45575f5ffd5b81516001600160401b03811115612e5a575f5ffd5b8201601f81018413612e6a575f5ffd5b8051612e786122e482612258565b8082825260208201915060208360051b850101925086831115612e99575f5ffd5b6020840193505b8284101561210c578351612eb38161227a565b825260209384019390910190612ea0565b602080825282518282018190525f918401906040840190835b818110156128bc57835180516001600160a01b039081168552602091820151168185015290930192604090920191600101612edd565b5f8151808452602084019350602083015f5b82811015612f7457815180516001600160a01b03908116885260208083015190911681890152604080830151908901526060918201519188019190915260809096019590910190600101612f25565b5093949350505050565b60018060a01b0384168152826020820152606060408201525f612fa46060830184612f13565b95945050505050565b602080825282518282018190525f918401906040840190835b818110156128bc57612fec83855180516001600160a01b03168252602090810151910152565b6020939093019260409290920191600101612fc6565b602080825282518282018190525f918401906040840190835b818110156128bc5761304183855180516001600160a01b03168252602090810151910152565b602093909301926040929092019160010161301b565b6001600160a01b03831681526040602082018190525f9061299690830184612f13565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106435761064361307a565b5f600182016130b2576130b261307a565b5060010190565b5f602082840312156130c9575f5ffd5b8151612ba88161227a565b808201808211156106435761064361307a565b5f604082840312156130f7575f5ffd5b6130ff612206565b825181526020928301519281019290925250919050565b5f60408284031215613126575f5ffd5b612ba883836130e7565b5f60808284031215613140575f5ffd5b6131486121c2565b905081516131558161227a565b8152602082810151908201526040808301519082015260609182015191810191909152919050565b5f6080828403121561318d575f5ffd5b612ba88383613130565b5f82516131a8818460208701612d64565b9190910192915050565b5f5f606083850312156131c3575f5ffd5b6131cd84846130e7565b915060408301516001600160401b038111156131e7575f5ffd5b8301601f810185136131f7575f5ffd5b80516132056122e482612258565b8082825260208201915060208360071b850101925087831115613226575f5ffd5b6020840193505b828410156132525761323f8885613130565b825260208201915060808401935061322d565b809450505050509250929050565b5f6040828403128015613271575f5ffd5b5061327a612206565b82516132858161227a565b815260208301516132958161227a565b6020820152939250505056fea264697066735822122030e84ad6ce792b80aff6da6a54795b3c123801cc9f364bad13528ec9d104c70c64736f6c634300081b00330000000000000000000000004655ce3d625a63d30ba704087e52b4c31e38188b000000000000000000000000d400fc38ed4732893174325693a63c30ee3881a80000000000000000000000005300a1a15135ea4dc7ad5a167152c01efc9b192a
Deployed Bytecode
0x608060405234801561000f575f5ffd5b5060043610610132575f3560e01c806392776de8116100b4578063d740871511610079578063d7408715146102d2578063e062987a146102f4578063e790b8e014610307578063eb2328f11461031a578063eed88b8d1461032d578063fc1b453f14610340575f5ffd5b806392776de814610238578063a3d5b2551461024b578063a4757b0f1461025e578063cb86c02514610284578063cd086d45146102ab575f5ffd5b80634d5b0d7a116100fa5780634d5b0d7a146101ad57806371459c15146101c057806384808a23146101ff57806389f8ed6c146102125780638f9ff96714610225575f5ffd5b8063023d6442146101365780630b75ef531461014b5780631d3dadda1461015e57806340e3f6b314610171578063444439f114610184575b5f5ffd5b6101496101443660046122a1565b610353565b005b610149610159366004612364565b610379565b61014961016c3660046125a8565b6104d2565b61014961017f3660046126fd565b610536565b6101976101923660046127d8565b6105b2565b6040516101a4919061287c565b60405180910390f35b6101496101bb366004612952565b610649565b6101e77f000000000000000000000000d400fc38ed4732893174325693a63c30ee3881a881565b6040516001600160a01b0390911681526020016101a4565b61014961020d366004612952565b6106cd565b610149610220366004612a12565b610719565b610149610233366004612a56565b6107f7565b610149610246366004612a12565b6109ca565b610149610259366004612b4f565b610a16565b7f0000000000000000000000005300a1a15135ea4dc7ad5a167152c01efc9b192a6101e7565b6101e77f0000000000000000000000005300a1a15135ea4dc7ad5a167152c01efc9b192a81565b6101e77f0000000000000000000000004655ce3d625a63d30ba704087e52b4c31e38188b81565b6102e66102e0366004612b8d565b505f1990565b6040519081526020016101a4565b610149610302366004612a12565b610a6a565b610149610315366004612364565b610ab6565b610149610328366004612baf565b610bdd565b61014961033b366004612ca5565b610cda565b61014961034e366004612364565b610d2d565b5f5f61035e83610e54565b9150915061036b82610a6a565b610374816109ca565b505050565b5f5b81518110156104ce5781818151811061039657610396612ccf565b602002602001015160400151156103ea576103ea8282815181106103bc576103bc612ccf565b60200260200101515f01518383815181106103d9576103d9612ccf565b60200260200101516020015161109e565b7f000000000000000000000000d400fc38ed4732893174325693a63c30ee3881a86001600160a01b0316631e5e18a783838151811061042b5761042b612ccf565b60200260200101515f015184848151811061044857610448612ccf565b6020026020010151602001516040518363ffffffff1660e01b81526004016104859291906001600160a01b03929092168252602082015260400190565b6020604051808303815f875af11580156104a1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104c59190612ce3565b5060010161037b565b5050565b5f6104df61019283611160565b90505f5f6104ed8484611235565b915091506104fa82610536565b610503816107f7565b610530610220857f000000000000000000000000d400fc38ed4732893174325693a63c30ee3881a861148a565b50505050565b60405163284261a960e11b81526001600160a01b037f000000000000000000000000d400fc38ed4732893174325693a63c30ee3881a81690635084c35290610582908490600401612cfa565b5f604051808303815f87803b158015610599575f5ffd5b505af11580156105ab573d5f5f3e3d5ffd5b5050505050565b60405163b1f396c560e01b81526060906001600160a01b037f000000000000000000000000d400fc38ed4732893174325693a63c30ee3881a8169063b1f396c590610601908590600401612d86565b5f604051808303815f875af115801561061c573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106439190810190612e35565b92915050565b5f5f610696837f0000000000000000000000004655ce3d625a63d30ba704087e52b4c31e38188b7f000000000000000000000000d400fc38ed4732893174325693a63c30ee3881a8611655565b915091506106a3826106cd565b6106ac81610bdd565b5f5f6106b7856117c6565b915091506106c482610a6a565b6105ab816109ca565b6040516333b7985f60e11b81526001600160a01b037f000000000000000000000000d400fc38ed4732893174325693a63c30ee3881a8169063676f30be90610582908490600401612ec4565b5f5b81518110156104ce577f000000000000000000000000d400fc38ed4732893174325693a63c30ee3881a86001600160a01b031663a6307a0a83838151811061076557610765612ccf565b60200260200101515f015184848151811061078257610782612ccf565b6020026020010151602001516040518363ffffffff1660e01b81526004016107bf9291906001600160a01b03929092168252602082015260400190565b5f604051808303815f87803b1580156107d6575f5ffd5b505af11580156107e8573d5f5f3e3d5ffd5b5050505080600101905061071b565b5f5b81518110156104ce5761086682828151811061081757610817612ccf565b60200260200101515f015183838151811061083457610834612ccf565b6020026020010151602001517f0000000000000000000000004655ce3d625a63d30ba704087e52b4c31e38188b61195d565b82828151811061087857610878612ccf565b602002602001015160200181815250506108ec82828151811061089d5761089d612ccf565b6020026020010151604001518383815181106108bb576108bb612ccf565b60200260200101515f01517f0000000000000000000000004655ce3d625a63d30ba704087e52b4c31e38188b6119e3565b7f0000000000000000000000004655ce3d625a63d30ba704087e52b4c31e38188b6001600160a01b0316635129351c83838151811061092d5761092d612ccf565b60200260200101515f015184848151811061094a5761094a612ccf565b60200260200101516020015185858151811061096857610968612ccf565b6020026020010151604001516040518463ffffffff1660e01b815260040161099293929190612f7e565b5f604051808303815f87803b1580156109a9575f5ffd5b505af11580156109bb573d5f5f3e3d5ffd5b505050508060010190506107f9565b60405163f305644560e01b81526001600160a01b037f000000000000000000000000d400fc38ed4732893174325693a63c30ee3881a8169063f305644590610582908490600401612fad565b336001600160a01b037f0000000000000000000000005300a1a15135ea4dc7ad5a167152c01efc9b192a1614610a5f57604051633a02626960e01b815260040160405180910390fd5b610374838383611b60565b60405163c4e0c63960e01b81526001600160a01b037f000000000000000000000000d400fc38ed4732893174325693a63c30ee3881a8169063c4e0c63990610582908490600401613002565b5f5b81518110156104ce57818181518110610ad357610ad3612ccf565b60200260200101516040015115610af957610af98282815181106103bc576103bc612ccf565b7f000000000000000000000000d400fc38ed4732893174325693a63c30ee3881a86001600160a01b031663321b4539838381518110610b3a57610b3a612ccf565b60200260200101515f0151848481518110610b5757610b57612ccf565b6020026020010151602001516040518363ffffffff1660e01b8152600401610b949291906001600160a01b03929092168252602082015260400190565b6020604051808303815f875af1158015610bb0573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bd49190612ce3565b50600101610ab8565b5f5b81518110156104ce57610c1b828281518110610bfd57610bfd612ccf565b6020026020010151602001518383815181106108bb576108bb612ccf565b7f0000000000000000000000004655ce3d625a63d30ba704087e52b4c31e38188b6001600160a01b031663745ff635838381518110610c5c57610c5c612ccf565b60200260200101515f0151848481518110610c7957610c79612ccf565b6020026020010151602001516040518363ffffffff1660e01b8152600401610ca2929190613057565b5f604051808303815f87803b158015610cb9575f5ffd5b505af1158015610ccb573d5f5f3e3d5ffd5b50505050806001019050610bdf565b336001600160a01b037f0000000000000000000000005300a1a15135ea4dc7ad5a167152c01efc9b192a1614610d2357604051633a02626960e01b815260040160405180910390fd5b6104ce8282611be4565b5f5b81518110156104ce57818181518110610d4a57610d4a612ccf565b60200260200101516040015115610d7057610d708282815181106103bc576103bc612ccf565b7f000000000000000000000000d400fc38ed4732893174325693a63c30ee3881a86001600160a01b031663423ce3c4838381518110610db157610db1612ccf565b60200260200101515f0151848481518110610dce57610dce612ccf565b6020026020010151602001516040518363ffffffff1660e01b8152600401610e0b9291906001600160a01b03929092168252602082015260400190565b6020604051808303815f875af1158015610e27573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e4b9190612ce3565b50600101610d2f565b6060805f83516001600160401b03811115610e7157610e71612186565b604051908082528060200260200182016040528015610eb557816020015b604080518082019091525f8082526020820152815260200190600190039081610e8f5790505b5090505f84516001600160401b03811115610ed257610ed2612186565b604051908082528060200260200182016040528015610f1657816020015b604080518082019091525f8082526020820152815260200190600190039081610ef05790505b5090505f5f5f5b875181101561108e57610f32602a5f1961308e565b888281518110610f4457610f44612ccf565b60200260200101516040015114610fd6576040518060400160405280898381518110610f7257610f72612ccf565b60200260200101515f01516001600160a01b03168152602001898381518110610f9d57610f9d612ccf565b602002602001015160400151815250858480610fb8906130a1565b955081518110610fca57610fca612ccf565b60200260200101819052505b610fe2602a5f1961308e565b888281518110610ff457610ff4612ccf565b6020026020010151602001511461108657604051806040016040528089838151811061102257611022612ccf565b60200260200101515f01516001600160a01b0316815260200189838151811061104d5761104d612ccf565b602002602001015160200151815250848380611068906130a1565b94508151811061107a5761107a612ccf565b60200260200101819052505b600101610f1d565b5090835281529094909350915050565b604051630393f2a760e61b81526001600160a01b0383811660048301525f917f000000000000000000000000d400fc38ed4732893174325693a63c30ee3881a89091169063e4fca9c090602401602060405180830381865afa158015611106573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061112a91906130b9565b90506103746001600160a01b0382167f000000000000000000000000d400fc38ed4732893174325693a63c30ee3881a884611cb3565b60605f82516001600160401b0381111561117c5761117c612186565b6040519080825280602002602001820160405280156111de57816020015b6111cb60405180608001604052805f6001600160a01b031681526020015f81526020015f8152602001606081525090565b81526020019060019003908161119a5790505b5090505f5b835181101561122e578381815181106111fe576111fe612ccf565b60200260200101515f015182828151811061121b5761121b612ccf565b60209081029190910101526001016111e3565b5092915050565b6060805f84516001600160401b0381111561125257611252612186565b6040519080825280602002602001820160405280156112a257816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f199092019101816112705790505b5090505f85516001600160401b038111156112bf576112bf612186565b60405190808252806020026020018201604052801561130b57816020015b60408051606080820183525f8083526020830152918101919091528152602001906001900390816112dd5790505b5090505f5b865181101561147e57604051806080016040528088838151811061133657611336612ccf565b6020026020010151606001516001600160a01b0316815260200187838151811061136257611362612ccf565b60200260200101516001600160a01b0316815260200188838151811061138a5761138a612ccf565b60200260200101516080015181526020018883815181106113ad576113ad612ccf565b602002602001015160a001516001600160a01b03168152508382815181106113d7576113d7612ccf565b602002602001018190525060405180606001604052808783815181106113ff576113ff612ccf565b60200260200101516001600160a01b0316815260200188838151811061142757611427612ccf565b602002602001015160200151815260200188838151811061144a5761144a612ccf565b60200260200101516040015181525082828151811061146b5761146b612ccf565b6020908102919091010152600101611310565b50909590945092505050565b60605f83516001600160401b038111156114a6576114a6612186565b6040519080825280602002602001820160405280156114ea57816020015b604080518082019091525f80825260208201528152602001906001900390816114c45790505b5090505f5f5b855181101561164b5785818151811061150b5761150b612ccf565b602002602001015160c001515f14611643575f856001600160a01b031663711e932288848151811061153f5761153f612ccf565b6020026020010151606001516040518263ffffffff1660e01b815260040161157691906001600160a01b0391909116815260200190565b602060405180830381865afa158015611591573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115b59190612ce3565b905060405180604001604052808884815181106115d4576115d4612ccf565b6020026020010151606001516001600160a01b031681526020018289858151811061160157611601612ccf565b602002602001015160c0015161161791906130d4565b90528484611624816130a1565b95508151811061163657611636612ccf565b6020026020010181905250505b6001016114f0565b5081529392505050565b6060805f85516001600160401b0381111561167257611672612186565b6040519080825280602002602001820160405280156116b757816020015b604080518082019091525f8152606060208201528152602001906001900390816116905790505b5090505f86516001600160401b038111156116d4576116d4612186565b60405190808252806020026020018201604052801561171857816020015b604080518082019091525f80825260208201528152602001906001900390816116f25790505b5090505f5b87518110156117b15761174988828151811061173b5761173b612ccf565b602002602001015188611d70565b83828151811061175b5761175b612ccf565b602002602001018190525061178c88828151811061177b5761177b612ccf565b60200260200101515f015187611f66565b82828151811061179e5761179e612ccf565b602090810291909101015260010161171d565b506117bb82612019565b969095509350505050565b6060805f83516001600160401b038111156117e3576117e3612186565b60405190808252806020026020018201604052801561182757816020015b604080518082019091525f80825260208201528152602001906001900390816118015790505b5090505f84516001600160401b0381111561184457611844612186565b60405190808252806020026020018201604052801561188857816020015b604080518082019091525f80825260208201528152602001906001900390816118625790505b5090505f5b85518110156119525760405180604001604052808783815181106118b3576118b3612ccf565b60200260200101515f01516001600160a01b0316815260200163ffffffff80168152508382815181106118e8576118e8612ccf565b6020026020010181905250604051806040016040528087838151811061191057611910612ccf565b60200260200101515f01516001600160a01b031681526020015f81525082828151811061193f5761193f612ccf565b602090810291909101015260010161188d565b509094909350915050565b5f61196a602a5f1961308e565b83036119db57604051631652e7b760e01b81526001600160a01b038581166004830152831690631652e7b7906024016040805180830381865afa1580156119b3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119d79190613116565b5192505b509092915050565b5f5b8351811015610530575f6119fb602a5f1961308e565b858381518110611a0d57611a0d612ccf565b6020026020010151604001511490505f602a5f19611a2b919061308e565b868481518110611a3d57611a3d612ccf565b6020026020010151606001511490508180611a555750805b15611b56575f846001600160a01b03166369f67d4287898781518110611a7d57611a7d612ccf565b6020908102919091010151516040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401608060405180830381865afa158015611ad2573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611af6919061317d565b90508215611b26578060400151878581518110611b1557611b15612ccf565b602002602001015160400181815250505b8115611b54578060600151878581518110611b4357611b43612ccf565b602002602001015160600181815250505b505b50506001016119e5565b5f19818111611b6f5780611b71565b815b9150611b876001600160a01b038516848461209c565b826001600160a01b0316846001600160a01b0316336001600160a01b03167fc7af665d489507e14ae25ac7ab0030fc7f570869610bdd32117ea56b60ae5c6185604051611bd691815260200190565b60405180910390a450505050565b604080515f808252602082019092526001600160a01b038416908390604051611c0d9190613197565b5f6040518083038185875af1925050503d805f8114611c47576040519150601f19603f3d011682016040523d82523d5f602084013e611c4c565b606091505b5050905080611c6e57604051630db2c7f160e31b815260040160405180910390fd5b6040518281526001600160a01b0384169033907fb7c602059992183c7b767c08204223afc99f1895fd175adf9ece23ce9f5bb8b79060200160405180910390a3505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052611d0484826120cd565b610530576040516001600160a01b0384811660248301525f6044830152611d6691869182169063095ea7b3906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050612116565b6105308482612116565b604080518082019091525f8152606060208201528251604051636808879d60e11b81526001600160a01b0391821660048201525f9184169063d0110f3a906024015f60405180830381865afa158015611dcb573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611df291908101906131b2565b9150505f81516001600160401b03811115611e0f57611e0f612186565b604051908082528060200260200182016040528015611e5f57816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f19909201910181611e2d5790505b5090505f5f5b8351811015611f3f57838181518110611e8057611e80612ccf565b6020026020010151604001515f1480611eb6575042848281518110611ea757611ea7612ccf565b60200260200101516060015111155b611f37576040518060800160405280858381518110611ed757611ed7612ccf565b60200260200101515f01516001600160a01b0316815260200188602001516001600160a01b031681526020015f815260200142815250838380611f19906130a1565b945081518110611f2b57611f2b612ccf565b60200260200101819052505b600101611e65565b5081526040805180820190915294516001600160a01b031685526020850152509192915050565b604080518082019091525f808252602082015260405163acc5876960e01b81526001600160a01b0384811660048301525f919084169063acc58769906024016040805180830381865afa158015611fbf573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fe39190613260565b9050604051806040016040528082602001516001600160a01b03168152602001856001600160a01b031681525091505092915050565b5f5f5b82518110156120975782818151811061203757612037612ccf565b602002602001015160200151515f031561208f5782818151811061205d5761205d612ccf565b6020026020010151838380612071906130a1565b94508151811061208357612083612ccf565b60200260200101819052505b60010161201c565b509052565b6040516001600160a01b0383811660248301526044820183905261037491859182169063a9059cbb90606401611d34565b5f5f5f5f60205f8651602088015f8a5af192503d91505f51905082801561210c575081156120fe578060011461210c565b5f866001600160a01b03163b115b9695505050505050565b5f5f60205f8451602086015f885af180612135576040513d5f823e3d81fd5b50505f513d9150811561214c578060011415612159565b6001600160a01b0384163b155b1561053057604051635274afe760e01b81526001600160a01b038516600482015260240160405180910390fd5b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b03811182821017156121bc576121bc612186565b60405290565b604051608081016001600160401b03811182821017156121bc576121bc612186565b60405160e081016001600160401b03811182821017156121bc576121bc612186565b604080519081016001600160401b03811182821017156121bc576121bc612186565b604051601f8201601f191681016001600160401b038111828210171561225057612250612186565b604052919050565b5f6001600160401b0382111561227057612270612186565b5060051b60200190565b6001600160a01b038116811461228e575f5ffd5b50565b803561229c8161227a565b919050565b5f602082840312156122b1575f5ffd5b81356001600160401b038111156122c6575f5ffd5b8201601f810184136122d6575f5ffd5b80356122e96122e482612258565b612228565b8082825260208201915060206060840285010192508683111561230a575f5ffd5b6020840193505b8284101561210c5760608488031215612328575f5ffd5b61233061219a565b843561233b8161227a565b815260208581013581830152604080870135908301529083526060909401939190910190612311565b5f60208284031215612374575f5ffd5b81356001600160401b03811115612389575f5ffd5b8201601f81018413612399575f5ffd5b80356123a76122e482612258565b808282526020820191506020606084028501019250868311156123c8575f5ffd5b6020840193505b8284101561210c57606084880312156123e6575f5ffd5b6123ee61219a565b84356123f98161227a565b81526020858101359082015260408501358015158114612417575f5ffd5b60408201528252606093909301926020909101906123cf565b5f60808284031215612440575f5ffd5b6124486121c2565b905081356124558161227a565b8152602082810135908201526040808301359082015260608201356001600160401b03811115612483575f5ffd5b8201601f81018413612493575f5ffd5b80356001600160401b038111156124ac576124ac612186565b6124bf601f8201601f1916602001612228565b8181528560208385010111156124d3575f5ffd5b816020840160208301375f6020838301015280606085015250505092915050565b5f82601f830112612503575f5ffd5b81356125116122e482612258565b8082825260208201915060208360071b860101925085831115612532575f5ffd5b602085015b8381101561259e576080818803121561254e575f5ffd5b6125566121c2565b81356125618161227a565b815260208201356125718161227a565b60208281019190915260408381013590830152606080840135908301529084529290920191608001612537565b5095945050505050565b5f602082840312156125b8575f5ffd5b81356001600160401b038111156125cd575f5ffd5b8201601f810184136125dd575f5ffd5b80356125eb6122e482612258565b8082825260208201915060208360051b85010192508683111561260c575f5ffd5b602084015b838110156126f25780356001600160401b0381111561262e575f5ffd5b850160e0818a03601f19011215612643575f5ffd5b61264b6121e4565b60208201356001600160401b03811115612663575f5ffd5b6126728b602083860101612430565b8252506040820135602082015260608201356001600160401b03811115612697575f5ffd5b6126a68b6020838601016124f4565b6040830152506126b860808301612291565b606082015260a082013560808201526126d360c08301612291565b60a082015260e0919091013560c0820152835260209283019201612611565b509695505050505050565b5f6020828403121561270d575f5ffd5b81356001600160401b03811115612722575f5ffd5b8201601f81018413612732575f5ffd5b80356127406122e482612258565b8082825260208201915060208360071b850101925086831115612761575f5ffd5b6020840193505b8284101561210c576080848803121561277f575f5ffd5b6127876121c2565b84356127928161227a565b815260208501356127a28161227a565b60208201526040858101359082015260608501356127bf8161227a565b6060820152825260809390930192602090910190612768565b5f602082840312156127e8575f5ffd5b81356001600160401b038111156127fd575f5ffd5b8201601f8101841361280d575f5ffd5b803561281b6122e482612258565b8082825260208201915060208360051b85010192508683111561283c575f5ffd5b602084015b838110156126f25780356001600160401b0381111561285e575f5ffd5b61286d89602083890101612430565b84525060209283019201612841565b602080825282518282018190525f918401906040840190835b818110156128bc5783516001600160a01b0316835260209384019390920191600101612895565b509095945050505050565b5f6128d46122e484612258565b838152905060208101600684901b8301858111156128f0575f5ffd5b835b81811015612948575f6040828903121561290a575f5ffd5b612912612206565b9050813561291f8161227a565b8152602082013561292f8161227a565b60208281019190915290845292909201916040016128f2565b5050509392505050565b5f60208284031215612962575f5ffd5b81356001600160401b03811115612977575f5ffd5b8201601f81018413612987575f5ffd5b612996848235602084016128c7565b949350505050565b5f6129ab6122e484612258565b838152905060208101600684901b8301858111156129c7575f5ffd5b835b81811015612948575f604082890312156129e1575f5ffd5b6129e9612206565b905081356129f68161227a565b81526020828101358183015290845292909201916040016129c9565b5f60208284031215612a22575f5ffd5b81356001600160401b03811115612a37575f5ffd5b8201601f81018413612a47575f5ffd5b6129968482356020840161299e565b5f60208284031215612a66575f5ffd5b81356001600160401b03811115612a7b575f5ffd5b8201601f81018413612a8b575f5ffd5b8035612a996122e482612258565b8082825260208201915060208360051b850101925086831115612aba575f5ffd5b602084015b838110156126f25780356001600160401b03811115612adc575f5ffd5b85016060818a03601f19011215612af1575f5ffd5b612af961219a565b6020820135612b078161227a565b81526040820135602082015260608201356001600160401b03811115612b2b575f5ffd5b612b3a8b6020838601016124f4565b60408301525084525060209283019201612abf565b5f5f5f60608486031215612b61575f5ffd5b8335612b6c8161227a565b92506020840135612b7c8161227a565b929592945050506040919091013590565b5f60208284031215612b9d575f5ffd5b8135612ba88161227a565b9392505050565b5f60208284031215612bbf575f5ffd5b81356001600160401b03811115612bd4575f5ffd5b8201601f81018413612be4575f5ffd5b8035612bf26122e482612258565b8082825260208201915060208360051b850101925086831115612c13575f5ffd5b602084015b838110156126f25780356001600160401b03811115612c35575f5ffd5b85016040818a03601f19011215612c4a575f5ffd5b612c52612206565b6020820135612c608161227a565b815260408201356001600160401b03811115612c7a575f5ffd5b612c898b6020838601016124f4565b6020830152508085525050602083019250602081019050612c18565b5f5f60408385031215612cb6575f5ffd5b8235612cc18161227a565b946020939093013593505050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215612cf3575f5ffd5b5051919050565b602080825282518282018190525f918401906040840190835b818110156128bc57835180516001600160a01b039081168552602080830151821681870152604080840151908701526060928301519091169185019190915290930192608090920191600101612d13565b5f5b83811015612d7e578181015183820152602001612d66565b50505f910152565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b82811015612e2957603f19878603018452815160018060a01b038151168652602081015160208701526040810151604087015260608101519050608060608701528051806080880152612e068160a0890160208501612d64565b601f01601f19169590950160a00194506020938401939190910190600101612dac565b50929695505050505050565b5f60208284031215612e45575f5ffd5b81516001600160401b03811115612e5a575f5ffd5b8201601f81018413612e6a575f5ffd5b8051612e786122e482612258565b8082825260208201915060208360051b850101925086831115612e99575f5ffd5b6020840193505b8284101561210c578351612eb38161227a565b825260209384019390910190612ea0565b602080825282518282018190525f918401906040840190835b818110156128bc57835180516001600160a01b039081168552602091820151168185015290930192604090920191600101612edd565b5f8151808452602084019350602083015f5b82811015612f7457815180516001600160a01b03908116885260208083015190911681890152604080830151908901526060918201519188019190915260809096019590910190600101612f25565b5093949350505050565b60018060a01b0384168152826020820152606060408201525f612fa46060830184612f13565b95945050505050565b602080825282518282018190525f918401906040840190835b818110156128bc57612fec83855180516001600160a01b03168252602090810151910152565b6020939093019260409290920191600101612fc6565b602080825282518282018190525f918401906040840190835b818110156128bc5761304183855180516001600160a01b03168252602090810151910152565b602093909301926040929092019160010161301b565b6001600160a01b03831681526040602082018190525f9061299690830184612f13565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106435761064361307a565b5f600182016130b2576130b261307a565b5060010190565b5f602082840312156130c9575f5ffd5b8151612ba88161227a565b808201808211156106435761064361307a565b5f604082840312156130f7575f5ffd5b6130ff612206565b825181526020928301519281019290925250919050565b5f60408284031215613126575f5ffd5b612ba883836130e7565b5f60808284031215613140575f5ffd5b6131486121c2565b905081516131558161227a565b8152602082810151908201526040808301519082015260609182015191810191909152919050565b5f6080828403121561318d575f5ffd5b612ba88383613130565b5f82516131a8818460208701612d64565b9190910192915050565b5f5f606083850312156131c3575f5ffd5b6131cd84846130e7565b915060408301516001600160401b038111156131e7575f5ffd5b8301601f810185136131f7575f5ffd5b80516132056122e482612258565b8082825260208201915060208360071b850101925087831115613226575f5ffd5b6020840193505b828410156132525761323f8885613130565b825260208201915060808401935061322d565b809450505050509250929050565b5f6040828403128015613271575f5ffd5b5061327a612206565b82516132858161227a565b815260208301516132958161227a565b6020820152939250505056fea264697066735822122030e84ad6ce792b80aff6da6a54795b3c123801cc9f364bad13528ec9d104c70c64736f6c634300081b0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000004655Ce3D625a63d30bA704087E52B4C31E38188B000000000000000000000000D400fc38ED4732893174325693a63C30ee3881a80000000000000000000000005300A1a15135EA4dc7aD5a167152C01EFc9b192A
-----Decoded View---------------
Arg [0] : rewardsController (address): 0x4655Ce3D625a63d30bA704087E52B4C31E38188B
Arg [1] : umbrella (address): 0xD400fc38ED4732893174325693a63C30ee3881a8
Arg [2] : guardian (address): 0x5300A1a15135EA4dc7aD5a167152C01EFc9b192A
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000004655Ce3D625a63d30bA704087E52B4C31E38188B
Arg [1] : 000000000000000000000000D400fc38ED4732893174325693a63C30ee3881a8
Arg [2] : 0000000000000000000000005300A1a15135EA4dc7aD5a167152C01EFc9b192A
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.