{"file_path":"src/contracts/misc/GhoBucketSteward.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport {Ownable} from '@openzeppelin/contracts/access/Ownable.sol';\nimport {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol';\nimport {IGhoToken} from '../gho/interfaces/IGhoToken.sol';\nimport {RiskCouncilControlled} from './RiskCouncilControlled.sol';\nimport {IGhoBucketSteward} from './interfaces/IGhoBucketSteward.sol';\n\n/**\n * @title GhoBucketSteward\n * @author Aave Labs\n * @notice Helper contract for managing bucket capacities of controlled facilitators\n * @dev Only the Risk Council is able to action contract's functions, based on specific conditions that have been agreed upon with the community.\n * @dev Requires role GHO_TOKEN_BUCKET_MANAGER_ROLE on GhoToken\n */\ncontract GhoBucketSteward is Ownable, RiskCouncilControlled, IGhoBucketSteward {\n  using EnumerableSet for EnumerableSet.AddressSet;\n\n  /// @inheritdoc IGhoBucketSteward\n  uint256 public constant MINIMUM_DELAY = 1 days;\n\n  /// @inheritdoc IGhoBucketSteward\n  address public immutable GHO_TOKEN;\n\n  mapping(address => uint40) internal _facilitatorsBucketCapacityTimelocks;\n\n  mapping(address => bool) internal _controlledFacilitatorsByAddress;\n  EnumerableSet.AddressSet internal _controlledFacilitators;\n\n  /**\n   * @dev Only methods that are not timelocked can be called if marked by this modifier.\n   */\n  modifier notTimelocked(uint40 timelock) {\n    require(block.timestamp - timelock > MINIMUM_DELAY, 'DEBOUNCE_NOT_RESPECTED');\n    _;\n  }\n\n  /**\n   * @dev Constructor\n   * @param owner The address of the contract's owner\n   * @param ghoToken The address of the GhoToken\n   * @param riskCouncil The address of the risk council\n   */\n  constructor(\n    address owner,\n    address ghoToken,\n    address riskCouncil\n  ) RiskCouncilControlled(riskCouncil) {\n    require(owner != address(0), 'INVALID_OWNER');\n    require(ghoToken != address(0), 'INVALID_GHO_TOKEN');\n\n    GHO_TOKEN = ghoToken;\n\n    _transferOwnership(owner);\n  }\n\n  /// @inheritdoc IGhoBucketSteward\n  function updateFacilitatorBucketCapacity(\n    address facilitator,\n    uint128 newBucketCapacity\n  ) external onlyRiskCouncil notTimelocked(_facilitatorsBucketCapacityTimelocks[facilitator]) {\n    require(_controlledFacilitatorsByAddress[facilitator], 'FACILITATOR_NOT_CONTROLLED');\n    (uint256 currentBucketCapacity, ) = IGhoToken(GHO_TOKEN).getFacilitatorBucket(facilitator);\n    require(newBucketCapacity != currentBucketCapacity, 'NO_CHANGE_IN_BUCKET_CAPACITY');\n    require(\n      _isIncreaseLowerThanMax(currentBucketCapacity, newBucketCapacity, currentBucketCapacity),\n      'INVALID_BUCKET_CAPACITY_UPDATE'\n    );\n\n    _facilitatorsBucketCapacityTimelocks[facilitator] = uint40(block.timestamp);\n\n    IGhoToken(GHO_TOKEN).setFacilitatorBucketCapacity(facilitator, newBucketCapacity);\n  }\n\n  /// @inheritdoc IGhoBucketSteward\n  function setControlledFacilitator(\n    address[] memory facilitatorList,\n    bool approve\n  ) external onlyOwner {\n    for (uint256 i = 0; i < facilitatorList.length; i++) {\n      _controlledFacilitatorsByAddress[facilitatorList[i]] = approve;\n      if (approve) {\n        _controlledFacilitators.add(facilitatorList[i]);\n      } else {\n        _controlledFacilitators.remove(facilitatorList[i]);\n      }\n    }\n  }\n\n  /// @inheritdoc IGhoBucketSteward\n  function getControlledFacilitators() external view returns (address[] memory) {\n    return _controlledFacilitators.values();\n  }\n\n  /// @inheritdoc IGhoBucketSteward\n  function isControlledFacilitator(address facilitator) external view returns (bool) {\n    return _controlledFacilitatorsByAddress[facilitator];\n  }\n\n  /// @inheritdoc IGhoBucketSteward\n  function getFacilitatorBucketCapacityTimelock(\n    address facilitator\n  ) external view returns (uint40) {\n    return _facilitatorsBucketCapacityTimelocks[facilitator];\n  }\n\n  /// @inheritdoc IGhoBucketSteward\n  function RISK_COUNCIL() public view override returns (address) {\n    return _riskCouncil;\n  }\n\n  /**\n   * @dev Ensures that the change is positive and the difference is lower than max.\n   * @param from current value\n   * @param to new value\n   * @param max maximum difference between from and to\n   * @return bool true if difference between values is positive and lower than max, false otherwise\n   */\n  function _isIncreaseLowerThanMax(\n    uint256 from,\n    uint256 to,\n    uint256 max\n  ) internal pure returns (bool) {\n    return to >= from && to - from <= max;\n  }\n}\n","deployed_bytecode":"0x608060405234801561001057600080fd5b50600436106100a95760003560e01c8063715018a611610071578063715018a6146101705780638da5cb5b14610178578063b1b43ae514610189578063b1c660f7146101a1578063ce5030b9146101c8578063f2fde38b1461020457600080fd5b806311aa1670146100ae578063153d9212146100ed57806337a0fdcb146101025780635ae6fb3a146101485780635e107b9c1461015d575b600080fd5b7f0000000000000000000000008513e6f37dbc52de87b166980fa3f50639694b605b6040516001600160a01b0390911681526020015b60405180910390f35b6100f5610217565b6040516100e4919061099c565b610132610110366004610a05565b6001600160a01b031660009081526001602052604090205464ffffffffff1690565b60405164ffffffffff90911681526020016100e4565b61015b610156366004610a46565b610228565b005b61015b61016b366004610b1d565b610311565b61015b61065d565b6000546001600160a01b03166100d0565b6101936201518081565b6040519081526020016100e4565b6100d07f00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f81565b6101f46101d6366004610a05565b6001600160a01b031660009081526002602052604090205460ff1690565b60405190151581526020016100e4565b61015b610212366004610a05565b610671565b606061022360036106ea565b905090565b6102306106fe565b60005b825181101561030c57816002600085848151811061025357610253610b60565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555081156102cb576102c58382815181106102ad576102ad610b60565b6020026020010151600361075890919063ffffffff16565b506102fa565b6102f88382815181106102e0576102e0610b60565b6020026020010151600361077690919063ffffffff16565b505b8061030481610b8c565b915050610233565b505050565b7f0000000000000000000000008513e6f37dbc52de87b166980fa3f50639694b606001600160a01b0316331461037f5760405162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa1a0a62622a960911b60448201526064015b60405180910390fd5b6001600160a01b03821660009081526001602052604090205464ffffffffff16620151806103ad8242610ba7565b116103f35760405162461bcd60e51b815260206004820152601660248201527511115093d55390d157d393d517d49154d41150d5115160521b6044820152606401610376565b6001600160a01b03831660009081526002602052604090205460ff1661045b5760405162461bcd60e51b815260206004820152601a60248201527f464143494c495441544f525f4e4f545f434f4e54524f4c4c45440000000000006044820152606401610376565b6040516355017ca560e11b81526001600160a01b0384811660048301526000917f00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f9091169063aa02f94a906024016040805180830381865afa1580156104c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e99190610bbe565b50905080836001600160801b031614156105455760405162461bcd60e51b815260206004820152601c60248201527f4e4f5f4348414e47455f494e5f4255434b45545f4341504143495459000000006044820152606401610376565b61055981846001600160801b03168361078b565b6105a55760405162461bcd60e51b815260206004820152601e60248201527f494e56414c49445f4255434b45545f43415041434954595f55504441544500006044820152606401610376565b6001600160a01b0384811660008181526001602052604090819020805464ffffffffff19164264ffffffffff161790555163af93df5760e01b815260048101919091526001600160801b03851660248201527f00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f9091169063af93df5790604401600060405180830381600087803b15801561063f57600080fd5b505af1158015610653573d6000803e3d6000fd5b5050505050505050565b6106656106fe565b61066f60006107ae565b565b6106796106fe565b6001600160a01b0381166106de5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610376565b6106e7816107ae565b50565b606060006106f7836107fe565b9392505050565b6000546001600160a01b0316331461066f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610376565b600061076d836001600160a01b03841661085a565b90505b92915050565b600061076d836001600160a01b0384166108a9565b60008383101580156107a65750816107a38585610ba7565b11155b949350505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561084e57602002820191906000526020600020905b81548152602001906001019080831161083a575b50505050509050919050565b60008181526001830160205260408120546108a157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610770565b506000610770565b600081815260018301602052604081205480156109925760006108cd600183610ba7565b85549091506000906108e190600190610ba7565b905081811461094657600086600001828154811061090157610901610b60565b906000526020600020015490508087600001848154811061092457610924610b60565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061095757610957610be2565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610770565b6000915050610770565b6020808252825182820181905260009190848201906040850190845b818110156109dd5783516001600160a01b0316835292840192918401916001016109b8565b50909695505050505050565b80356001600160a01b0381168114610a0057600080fd5b919050565b600060208284031215610a1757600080fd5b61076d826109e9565b634e487b7160e01b600052604160045260246000fd5b80358015158114610a0057600080fd5b60008060408385031215610a5957600080fd5b823567ffffffffffffffff80821115610a7157600080fd5b818501915085601f830112610a8557600080fd5b8135602082821115610a9957610a99610a20565b8160051b604051601f19603f83011681018181108682111715610abe57610abe610a20565b604052928352818301935084810182019289841115610adc57600080fd5b948201945b83861015610b0157610af2866109e9565b85529482019493820193610ae1565b9650610b109050878201610a36565b9450505050509250929050565b60008060408385031215610b3057600080fd5b610b39836109e9565b915060208301356001600160801b0381168114610b5557600080fd5b809150509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415610ba057610ba0610b76565b5060010190565b600082821015610bb957610bb9610b76565b500390565b60008060408385031215610bd157600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220d1fdf34f1a2c1e412c206302e78664c2e806cdddafdc9efc52656803c90b28d864736f6c634300080a0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"london","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":true,"runs":200},"remappings":[":@aave/=lib/aave-token/",":@aave/core-v3/=lib/aave-v3-core/",":@aave/periphery-v3/=lib/aave-v3-periphery/",":@openzeppelin/=lib/openzeppelin-contracts/",":aave-address-book/=lib/aave-address-book/src/",":aave-helpers/=lib/aave-stk-v1-5/lib/aave-helpers/",":aave-stk-v1-5/=lib/aave-stk-v1-5/",":aave-token/=lib/aave-token/contracts/",":aave-v3-core/=lib/aave-address-book/lib/aave-v3-core/",":aave-v3-periphery/=lib/aave-address-book/lib/aave-v3-periphery/",":ds-test/=lib/forge-std/lib/ds-test/src/",":erc4626-tests/=lib/aave-stk-v1-5/lib/openzeppelin-contracts/lib/erc4626-tests/",":eth-gas-reporter/=node_modules/eth-gas-reporter/",":forge-std/=lib/forge-std/src/",":hardhat-deploy/=node_modules/hardhat-deploy/",":hardhat/=node_modules/hardhat/",":openzeppelin-contracts/=lib/aave-stk-v1-5/lib/openzeppelin-contracts/",":safety-module/=lib/safety-module/contracts/",":solidity-utils/=lib/solidity-utils/src/"]},"optimization_runs":200,"sourcify_repo_url":"https://repo.sourcify.dev/contracts/partial_match/1/0x46Aa1063e5265b43663E81329333B47c517A5409/","decoded_constructor_args":[["0x5300A1a15135EA4dc7aD5a167152C01EFc9b192A",{"internalType":"address","name":"owner","type":"address"}],["0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f",{"internalType":"address","name":"ghoToken","type":"address"}],["0x8513e6F37dBc52De87b166980Fa3F50639694B60",{"internalType":"address","name":"riskCouncil","type":"address"}]],"compiler_version":"0.8.10+commit.fc410830","is_verified_via_verifier_alliance":false,"verified_at":"2024-10-15T02:07:37.246881Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x60c06040523480156200001157600080fd5b5060405162000e7638038062000e768339810160408190526200003491620001c4565b80620000403362000157565b6001600160a01b0381166200009c5760405162461bcd60e51b815260206004820152601460248201527f494e56414c49445f5249534b5f434f554e43494c00000000000000000000000060448201526064015b60405180910390fd5b6001600160a01b039081166080528316620000ea5760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22fa7aba722a960991b604482015260640162000093565b6001600160a01b038216620001365760405162461bcd60e51b815260206004820152601160248201527024a72b20a624a22fa3a427afaa27a5a2a760791b604482015260640162000093565b6001600160a01b03821660a0526200014e8362000157565b5050506200020e565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b0381168114620001bf57600080fd5b919050565b600080600060608486031215620001da57600080fd5b620001e584620001a7565b9250620001f560208501620001a7565b91506200020560408501620001a7565b90509250925092565b60805160a051610c2e62000248600039600081816101a60152818161047d01526105f901526000818160b001526103130152610c2e6000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c8063715018a611610071578063715018a6146101705780638da5cb5b14610178578063b1b43ae514610189578063b1c660f7146101a1578063ce5030b9146101c8578063f2fde38b1461020457600080fd5b806311aa1670146100ae578063153d9212146100ed57806337a0fdcb146101025780635ae6fb3a146101485780635e107b9c1461015d575b600080fd5b7f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b0390911681526020015b60405180910390f35b6100f5610217565b6040516100e4919061099c565b610132610110366004610a05565b6001600160a01b031660009081526001602052604090205464ffffffffff1690565b60405164ffffffffff90911681526020016100e4565b61015b610156366004610a46565b610228565b005b61015b61016b366004610b1d565b610311565b61015b61065d565b6000546001600160a01b03166100d0565b6101936201518081565b6040519081526020016100e4565b6100d07f000000000000000000000000000000000000000000000000000000000000000081565b6101f46101d6366004610a05565b6001600160a01b031660009081526002602052604090205460ff1690565b60405190151581526020016100e4565b61015b610212366004610a05565b610671565b606061022360036106ea565b905090565b6102306106fe565b60005b825181101561030c57816002600085848151811061025357610253610b60565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555081156102cb576102c58382815181106102ad576102ad610b60565b6020026020010151600361075890919063ffffffff16565b506102fa565b6102f88382815181106102e0576102e0610b60565b6020026020010151600361077690919063ffffffff16565b505b8061030481610b8c565b915050610233565b505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316331461037f5760405162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa1a0a62622a960911b60448201526064015b60405180910390fd5b6001600160a01b03821660009081526001602052604090205464ffffffffff16620151806103ad8242610ba7565b116103f35760405162461bcd60e51b815260206004820152601660248201527511115093d55390d157d393d517d49154d41150d5115160521b6044820152606401610376565b6001600160a01b03831660009081526002602052604090205460ff1661045b5760405162461bcd60e51b815260206004820152601a60248201527f464143494c495441544f525f4e4f545f434f4e54524f4c4c45440000000000006044820152606401610376565b6040516355017ca560e11b81526001600160a01b0384811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063aa02f94a906024016040805180830381865afa1580156104c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e99190610bbe565b50905080836001600160801b031614156105455760405162461bcd60e51b815260206004820152601c60248201527f4e4f5f4348414e47455f494e5f4255434b45545f4341504143495459000000006044820152606401610376565b61055981846001600160801b03168361078b565b6105a55760405162461bcd60e51b815260206004820152601e60248201527f494e56414c49445f4255434b45545f43415041434954595f55504441544500006044820152606401610376565b6001600160a01b0384811660008181526001602052604090819020805464ffffffffff19164264ffffffffff161790555163af93df5760e01b815260048101919091526001600160801b03851660248201527f00000000000000000000000000000000000000000000000000000000000000009091169063af93df5790604401600060405180830381600087803b15801561063f57600080fd5b505af1158015610653573d6000803e3d6000fd5b5050505050505050565b6106656106fe565b61066f60006107ae565b565b6106796106fe565b6001600160a01b0381166106de5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610376565b6106e7816107ae565b50565b606060006106f7836107fe565b9392505050565b6000546001600160a01b0316331461066f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610376565b600061076d836001600160a01b03841661085a565b90505b92915050565b600061076d836001600160a01b0384166108a9565b60008383101580156107a65750816107a38585610ba7565b11155b949350505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561084e57602002820191906000526020600020905b81548152602001906001019080831161083a575b50505050509050919050565b60008181526001830160205260408120546108a157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610770565b506000610770565b600081815260018301602052604081205480156109925760006108cd600183610ba7565b85549091506000906108e190600190610ba7565b905081811461094657600086600001828154811061090157610901610b60565b906000526020600020015490508087600001848154811061092457610924610b60565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061095757610957610be2565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610770565b6000915050610770565b6020808252825182820181905260009190848201906040850190845b818110156109dd5783516001600160a01b0316835292840192918401916001016109b8565b50909695505050505050565b80356001600160a01b0381168114610a0057600080fd5b919050565b600060208284031215610a1757600080fd5b61076d826109e9565b634e487b7160e01b600052604160045260246000fd5b80358015158114610a0057600080fd5b60008060408385031215610a5957600080fd5b823567ffffffffffffffff80821115610a7157600080fd5b818501915085601f830112610a8557600080fd5b8135602082821115610a9957610a99610a20565b8160051b604051601f19603f83011681018181108682111715610abe57610abe610a20565b604052928352818301935084810182019289841115610adc57600080fd5b948201945b83861015610b0157610af2866109e9565b85529482019493820193610ae1565b9650610b109050878201610a36565b9450505050509250929050565b60008060408385031215610b3057600080fd5b610b39836109e9565b915060208301356001600160801b0381168114610b5557600080fd5b809150509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415610ba057610ba0610b76565b5060010190565b600082821015610bb957610bb9610b76565b500390565b60008060408385031215610bd157600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220d1fdf34f1a2c1e412c206302e78664c2e806cdddafdc9efc52656803c90b28d864736f6c634300080a00330000000000000000000000005300a1a15135ea4dc7ad5a167152c01efc9b192a00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f0000000000000000000000008513e6f37dbc52de87b166980fa3f50639694b60","name":"GhoBucketSteward","is_blueprint":false,"license_type":"none","is_fully_verified":false,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"london","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":true,"additional_sources":[{"file_path":"lib/openzeppelin-contracts/contracts/access/IAccessControl.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n    /**\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n     *\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n     * {RoleAdminChanged} not being emitted signaling this.\n     *\n     * _Available since v3.1._\n     */\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n    /**\n     * @dev Emitted when `account` is granted `role`.\n     *\n     * `sender` is the account that originated the contract call, an admin role\n     * bearer except when using {AccessControl-_setupRole}.\n     */\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Emitted when `account` is revoked `role`.\n     *\n     * `sender` is the account that originated the contract call:\n     *   - if using `revokeRole`, it is the admin role bearer\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\n     */\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) external view returns (bool);\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     */\n    function renounceRole(bytes32 role, address account) external;\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/access/Ownable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    constructor() {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 amount\n    ) external returns (bool);\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/utils/Context.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n *     // Add the library methods\n *     using EnumerableSet for EnumerableSet.AddressSet;\n *\n *     // Declare a set state variable\n *     EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n    // To implement this library for multiple types with as little code\n    // repetition as possible, we write it in terms of a generic Set type with\n    // bytes32 values.\n    // The Set implementation uses private functions, and user-facing\n    // implementations (such as AddressSet) are just wrappers around the\n    // underlying Set.\n    // This means that we can only create new EnumerableSets for types that fit\n    // in bytes32.\n\n    struct Set {\n        // Storage of set values\n        bytes32[] _values;\n        // Position of the value in the `values` array, plus 1 because index 0\n        // means a value is not in the set.\n        mapping(bytes32 => uint256) _indexes;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function _add(Set storage set, bytes32 value) private returns (bool) {\n        if (!_contains(set, value)) {\n            set._values.push(value);\n            // The value is stored at length-1, but we add 1 to all indexes\n            // and use 0 as a sentinel value\n            set._indexes[value] = set._values.length;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function _remove(Set storage set, bytes32 value) private returns (bool) {\n        // We read and store the value's index to prevent multiple reads from the same storage slot\n        uint256 valueIndex = set._indexes[value];\n\n        if (valueIndex != 0) {\n            // Equivalent to contains(set, value)\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\n            // This modifies the order of the array, as noted in {at}.\n\n            uint256 toDeleteIndex = valueIndex - 1;\n            uint256 lastIndex = set._values.length - 1;\n\n            if (lastIndex != toDeleteIndex) {\n                bytes32 lastValue = set._values[lastIndex];\n\n                // Move the last value to the index where the value to delete is\n                set._values[toDeleteIndex] = lastValue;\n                // Update the index for the moved value\n                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n            }\n\n            // Delete the slot where the moved value was stored\n            set._values.pop();\n\n            // Delete the index for the deleted slot\n            delete set._indexes[value];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function _contains(Set storage set, bytes32 value) private view returns (bool) {\n        return set._indexes[value] != 0;\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function _length(Set storage set) private view returns (uint256) {\n        return set._values.length;\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function _at(Set storage set, uint256 index) private view returns (bytes32) {\n        return set._values[index];\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function _values(Set storage set) private view returns (bytes32[] memory) {\n        return set._values;\n    }\n\n    // Bytes32Set\n\n    struct Bytes32Set {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _add(set._inner, value);\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _remove(set._inner, value);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n        return _contains(set._inner, value);\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(Bytes32Set storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n        return _at(set._inner, index);\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        bytes32[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n\n    // AddressSet\n\n    struct AddressSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(AddressSet storage set, address value) internal returns (bool) {\n        return _add(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(AddressSet storage set, address value) internal returns (bool) {\n        return _remove(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(AddressSet storage set, address value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(AddressSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(AddressSet storage set, uint256 index) internal view returns (address) {\n        return address(uint160(uint256(_at(set._inner, index))));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(AddressSet storage set) internal view returns (address[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        address[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n\n    // UintSet\n\n    struct UintSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(UintSet storage set, uint256 value) internal returns (bool) {\n        return _add(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(UintSet storage set, uint256 value) internal returns (bool) {\n        return _remove(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(UintSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n        return uint256(_at(set._inner, index));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(UintSet storage set) internal view returns (uint256[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        uint256[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n}\n"},{"file_path":"src/contracts/gho/interfaces/IGhoToken.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport {IAccessControl} from '@openzeppelin/contracts/access/IAccessControl.sol';\n\n/**\n * @title IGhoToken\n * @author Aave\n */\ninterface IGhoToken is IERC20, IAccessControl {\n  struct Facilitator {\n    uint128 bucketCapacity;\n    uint128 bucketLevel;\n    string label;\n  }\n\n  /**\n   * @dev Emitted when a new facilitator is added\n   * @param facilitatorAddress The address of the new facilitator\n   * @param label A hashed human readable identifier for the facilitator\n   * @param bucketCapacity The initial capacity of the facilitator's bucket\n   */\n  event FacilitatorAdded(\n    address indexed facilitatorAddress,\n    bytes32 indexed label,\n    uint256 bucketCapacity\n  );\n\n  /**\n   * @dev Emitted when a facilitator is removed\n   * @param facilitatorAddress The address of the removed facilitator\n   */\n  event FacilitatorRemoved(address indexed facilitatorAddress);\n\n  /**\n   * @dev Emitted when the bucket capacity of a facilitator is updated\n   * @param facilitatorAddress The address of the facilitator whose bucket capacity is being changed\n   * @param oldCapacity The old capacity of the bucket\n   * @param newCapacity The new capacity of the bucket\n   */\n  event FacilitatorBucketCapacityUpdated(\n    address indexed facilitatorAddress,\n    uint256 oldCapacity,\n    uint256 newCapacity\n  );\n\n  /**\n   * @dev Emitted when the bucket level changed\n   * @param facilitatorAddress The address of the facilitator whose bucket level is being changed\n   * @param oldLevel The old level of the bucket\n   * @param newLevel The new level of the bucket\n   */\n  event FacilitatorBucketLevelUpdated(\n    address indexed facilitatorAddress,\n    uint256 oldLevel,\n    uint256 newLevel\n  );\n\n  /**\n   * @notice Returns the identifier of the Facilitator Manager Role\n   * @return The bytes32 id hash of the FacilitatorManager role\n   */\n  function FACILITATOR_MANAGER_ROLE() external pure returns (bytes32);\n\n  /**\n   * @notice Returns the identifier of the Bucket Manager Role\n   * @return The bytes32 id hash of the BucketManager role\n   */\n  function BUCKET_MANAGER_ROLE() external pure returns (bytes32);\n\n  /**\n   * @notice Mints the requested amount of tokens to the account address.\n   * @dev Only facilitators with enough bucket capacity available can mint.\n   * @dev The bucket level is increased upon minting.\n   * @param account The address receiving the GHO tokens\n   * @param amount The amount to mint\n   */\n  function mint(address account, uint256 amount) external;\n\n  /**\n   * @notice Burns the requested amount of tokens from the account address.\n   * @dev Only active facilitators (bucket level > 0) can burn.\n   * @dev The bucket level is decreased upon burning.\n   * @param amount The amount to burn\n   */\n  function burn(uint256 amount) external;\n\n  /**\n   * @notice Add the facilitator passed with the parameters to the facilitators list.\n   * @dev Only accounts with `FACILITATOR_MANAGER_ROLE` role can call this function\n   * @param facilitatorAddress The address of the facilitator to add\n   * @param facilitatorLabel A human readable identifier for the facilitator\n   * @param bucketCapacity The upward limit of GHO can be minted by the facilitator\n   */\n  function addFacilitator(\n    address facilitatorAddress,\n    string calldata facilitatorLabel,\n    uint128 bucketCapacity\n  ) external;\n\n  /**\n   * @notice Remove the facilitator from the facilitators list.\n   * @dev Only accounts with `FACILITATOR_MANAGER_ROLE` role can call this function\n   * @param facilitatorAddress The address of the facilitator to remove\n   */\n  function removeFacilitator(address facilitatorAddress) external;\n\n  /**\n   * @notice Set the bucket capacity of the facilitator.\n   * @dev Only accounts with `BUCKET_MANAGER_ROLE` role can call this function\n   * @param facilitator The address of the facilitator\n   * @param newCapacity The new capacity of the bucket\n   */\n  function setFacilitatorBucketCapacity(address facilitator, uint128 newCapacity) external;\n\n  /**\n   * @notice Returns the facilitator data\n   * @param facilitator The address of the facilitator\n   * @return The facilitator configuration\n   */\n  function getFacilitator(address facilitator) external view returns (Facilitator memory);\n\n  /**\n   * @notice Returns the bucket configuration of the facilitator\n   * @param facilitator The address of the facilitator\n   * @return The capacity of the facilitator's bucket\n   * @return The level of the facilitator's bucket\n   */\n  function getFacilitatorBucket(address facilitator) external view returns (uint256, uint256);\n\n  /**\n   * @notice Returns the list of the addresses of the active facilitator\n   * @return The list of the facilitators addresses\n   */\n  function getFacilitatorsList() external view returns (address[] memory);\n}\n"},{"file_path":"src/contracts/misc/RiskCouncilControlled.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\n/**\n * @title RiskCouncilControlled\n * @author Aave Labs\n * @notice Helper contract for controlling access to Steward and other functions restricted to Risk Council\n */\nabstract contract RiskCouncilControlled {\n  address internal immutable _riskCouncil;\n\n  /**\n   * @dev Constructor\n   * @param riskCouncil The address of the risk council\n   */\n  constructor(address riskCouncil) {\n    require(riskCouncil != address(0), 'INVALID_RISK_COUNCIL');\n    _riskCouncil = riskCouncil;\n  }\n\n  /**\n   * @dev Only Risk Council can call functions marked by this modifier.\n   */\n  modifier onlyRiskCouncil() {\n    require(_riskCouncil == msg.sender, 'INVALID_CALLER');\n    _;\n  }\n}\n"},{"file_path":"src/contracts/misc/interfaces/IGhoBucketSteward.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\n/**\n * @title IGhoBucketSteward\n * @author Aave Labs\n * @notice Defines the basic interface of the GhoBucketSteward\n */\ninterface IGhoBucketSteward {\n  /**\n   * @notice Updates the bucket capacity of facilitator, only if:\n   * - respects `MINIMUM_DELAY`, the minimum time delay between updates\n   * - the update changes up to 100% upwards\n   * - the facilitator is controlled\n   * @dev Only callable by Risk Council\n   * @param facilitator The facilitator address\n   * @param newBucketCapacity The new facilitator bucket capacity\n   */\n  function updateFacilitatorBucketCapacity(address facilitator, uint128 newBucketCapacity) external;\n\n  /**\n   * @notice Adds/Removes controlled facilitators\n   * @dev Only callable by owner\n   * @param facilitatorList A list of facilitators addresses to add to control\n   * @param approve True to add as controlled facilitators, false to remove\n   */\n  function setControlledFacilitator(address[] memory facilitatorList, bool approve) external;\n\n  /**\n   * @notice Returns the list of controlled facilitators by this steward.\n   * @return An array of facilitator addresses\n   */\n  function getControlledFacilitators() external view returns (address[] memory);\n\n  /**\n   * @notice Checks if a facilitator is controlled by this steward\n   * @param facilitator The facilitator address to check\n   * @return True if the facilitator is controlled by this steward\n   */\n  function isControlledFacilitator(address facilitator) external view returns (bool);\n\n  /**\n   * @notice Returns timestamp of the facilitators last bucket capacity update\n   * @param facilitator The facilitator address\n   * @return The unix time of the last bucket capacity (in seconds).\n   */\n  function getFacilitatorBucketCapacityTimelock(address facilitator) external view returns (uint40);\n\n  /**\n   * @notice Returns the minimum delay that must be respected between parameters update.\n   * @return The minimum delay between parameter updates (in seconds)\n   */\n  function MINIMUM_DELAY() external view returns (uint256);\n\n  /**\n   * @notice Returns the address of the Gho Token\n   * @return The address of the GhoToken\n   */\n  function GHO_TOKEN() external view returns (address);\n\n  /**\n   * @notice Returns the address of the risk council\n   * @return The address of the RiskCouncil\n   */\n  function RISK_COUNCIL() external view returns (address);\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"ghoToken","type":"address"},{"internalType":"address","name":"riskCouncil","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"GHO_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINIMUM_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RISK_COUNCIL","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getControlledFacilitators","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"facilitator","type":"address"}],"name":"getFacilitatorBucketCapacityTimelock","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"facilitator","type":"address"}],"name":"isControlledFacilitator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"facilitatorList","type":"address[]"},{"internalType":"bool","name":"approve","type":"bool"}],"name":"setControlledFacilitator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"facilitator","type":"address"},{"internalType":"uint128","name":"newBucketCapacity","type":"uint128"}],"name":"updateFacilitatorBucketCapacity","outputs":[],"stateMutability":"nonpayable","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":true,"constructor_args":"0x0000000000000000000000005300a1a15135ea4dc7ad5a167152c01efc9b192a00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f0000000000000000000000008513e6f37dbc52de87b166980fa3f50639694b60"}