Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- Authorizer
- Optimization enabled
- false
- Compiler version
- v0.7.6+commit.7338295f
- EVM Version
- default
- Verified at
- 2025-08-08T21:13:47.381222Z
Constructor Arguments
0x0000000000000000000000004677143c96bccb614aa08097ddd1348e7384efcc
Arg [0] (address) : 0x4677143c96bccb614aa08097ddd1348e7384efcc
contracts/Authorizer.sol
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity ^0.7.0;
/**
* @dev This is an empty interface used to represent either ERC20-conforming token contracts or ETH (using the zero
* address sentinel value). We're just relying on the fact that `interface` can be used to declare new address-like
* types.
*
* This concept is unrelated to a Pool's Asset Managers.
*/
interface IAsset {
// solhint-disable-previous-line no-empty-blocks
}
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
// Based on the EnumerableSet library from OpenZeppelin contracts, altered to remove the base private functions that
// work on bytes32, replacing them with a native implementation for address values, to reduce bytecode size and runtime
// costs.
// The `unchecked_at` function was also added, which allows for more gas efficient data reads in some scenarios.
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*/
library EnumerableSet {
// The original OpenZeppelin implementation uses a generic Set type with bytes32 values: this was replaced with
// AddressSet, which uses address keys natively, resulting in more dense bytecode.
struct AddressSet {
// Storage of set values
address[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(address => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
if (!contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
// When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.
address lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = toDeleteIndex + 1; // All indexes are 1-based
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
_require(set._values.length > index, Errors.OUT_OF_BOUNDS);
return unchecked_at(set, index);
}
/**
* @dev Same as {at}, except this doesn't revert if `index` it outside of the set (i.e. if it is equal or larger
* than {length}). O(1).
*
* This function performs one less storage read than {at}, but should only be used when `index` is known to be
* within bounds.
*/
function unchecked_at(AddressSet storage set, uint256 index) internal view returns (address) {
return set._values[index];
}
}
// solhint-disable
/**
* @dev Reverts if `condition` is false, with a revert reason containing `errorCode`. Only codes up to 999 are
* supported.
*/
function _require(bool condition, uint256 errorCode) pure {
if (!condition) _revert(errorCode);
}
/**
* @dev Reverts with a revert reason containing `errorCode`. Only codes up to 999 are supported.
*/
function _revert(uint256 errorCode) pure {
// We're going to dynamically create a revert string based on the error code, with the following format:
// 'BAL#{errorCode}'
// where the code is left-padded with zeroes to three digits (so they range from 000 to 999).
//
// We don't have revert strings embedded in the contract to save bytecode size: it takes much less space to store a
// number (8 to 16 bits) than the individual string characters.
//
// The dynamic string creation algorithm that follows could be implemented in Solidity, but assembly allows for a
// much denser implementation, again saving bytecode size. Given this function unconditionally reverts, this is a
// safe place to rely on it without worrying about how its usage might affect e.g. memory contents.
assembly {
// First, we need to compute the ASCII representation of the error code. We assume that it is in the 0-999
// range, so we only need to convert three digits. To convert the digits to ASCII, we add 0x30, the value for
// the '0' character.
let units := add(mod(errorCode, 10), 0x30)
errorCode := div(errorCode, 10)
let tenths := add(mod(errorCode, 10), 0x30)
errorCode := div(errorCode, 10)
let hundreds := add(mod(errorCode, 10), 0x30)
// With the individual characters, we can now construct the full string. The "BAL#" part is a known constant
// (0x42414c23): we simply shift this by 24 (to provide space for the 3 bytes of the error code), and add the
// characters to it, each shifted by a multiple of 8.
// The revert reason is then shifted left by 200 bits (256 minus the length of the string, 7 characters * 8 bits
// per character = 56) to locate it in the most significant part of the 256 slot (the beginning of a byte
// array).
let revertReason := shl(200, add(0x42414c23000000, add(add(units, shl(8, tenths)), shl(16, hundreds))))
// We can now encode the reason in memory, which can be safely overwritten as we're about to revert. The encoded
// message will have the following layout:
// [ revert reason identifier ] [ string location offset ] [ string length ] [ string contents ]
// The Solidity revert reason identifier is 0x08c739a0, the function selector of the Error(string) function. We
// also write zeroes to the next 28 bytes of memory, but those are about to be overwritten.
mstore(0x0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
// Next is the offset to the location of the string, which will be placed immediately after (20 bytes away).
mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)
// The string length is fixed: 7 characters.
mstore(0x24, 7)
// Finally, the string itself is stored.
mstore(0x44, revertReason)
// Even if the string is only 7 bytes long, we need to return a full 32 byte slot containing it. The length of
// the encoded message is therefore 4 + 32 + 32 + 32 = 100.
revert(0, 100)
}
}
library Errors {
// Math
uint256 internal constant ADD_OVERFLOW = 0;
uint256 internal constant SUB_OVERFLOW = 1;
uint256 internal constant SUB_UNDERFLOW = 2;
uint256 internal constant MUL_OVERFLOW = 3;
uint256 internal constant ZERO_DIVISION = 4;
uint256 internal constant DIV_INTERNAL = 5;
uint256 internal constant X_OUT_OF_BOUNDS = 6;
uint256 internal constant Y_OUT_OF_BOUNDS = 7;
uint256 internal constant PRODUCT_OUT_OF_BOUNDS = 8;
uint256 internal constant INVALID_EXPONENT = 9;
// Input
uint256 internal constant OUT_OF_BOUNDS = 100;
uint256 internal constant UNSORTED_ARRAY = 101;
uint256 internal constant UNSORTED_TOKENS = 102;
uint256 internal constant INPUT_LENGTH_MISMATCH = 103;
uint256 internal constant ZERO_TOKEN = 104;
// Shared pools
uint256 internal constant MIN_TOKENS = 200;
uint256 internal constant MAX_TOKENS = 201;
uint256 internal constant MAX_SWAP_FEE_PERCENTAGE = 202;
uint256 internal constant MIN_SWAP_FEE_PERCENTAGE = 203;
uint256 internal constant MINIMUM_BPT = 204;
uint256 internal constant CALLER_NOT_VAULT = 205;
uint256 internal constant UNINITIALIZED = 206;
uint256 internal constant BPT_IN_MAX_AMOUNT = 207;
uint256 internal constant BPT_OUT_MIN_AMOUNT = 208;
uint256 internal constant EXPIRED_PERMIT = 209;
// Pools
uint256 internal constant MIN_AMP = 300;
uint256 internal constant MAX_AMP = 301;
uint256 internal constant MIN_WEIGHT = 302;
uint256 internal constant MAX_STABLE_TOKENS = 303;
uint256 internal constant MAX_IN_RATIO = 304;
uint256 internal constant MAX_OUT_RATIO = 305;
uint256 internal constant MIN_BPT_IN_FOR_TOKEN_OUT = 306;
uint256 internal constant MAX_OUT_BPT_FOR_TOKEN_IN = 307;
uint256 internal constant NORMALIZED_WEIGHT_INVARIANT = 308;
uint256 internal constant INVALID_TOKEN = 309;
uint256 internal constant UNHANDLED_JOIN_KIND = 310;
uint256 internal constant ZERO_INVARIANT = 311;
// Lib
uint256 internal constant REENTRANCY = 400;
uint256 internal constant SENDER_NOT_ALLOWED = 401;
uint256 internal constant PAUSED = 402;
uint256 internal constant PAUSE_WINDOW_EXPIRED = 403;
uint256 internal constant MAX_PAUSE_WINDOW_DURATION = 404;
uint256 internal constant MAX_BUFFER_PERIOD_DURATION = 405;
uint256 internal constant INSUFFICIENT_BALANCE = 406;
uint256 internal constant INSUFFICIENT_ALLOWANCE = 407;
uint256 internal constant ERC20_TRANSFER_FROM_ZERO_ADDRESS = 408;
uint256 internal constant ERC20_TRANSFER_TO_ZERO_ADDRESS = 409;
uint256 internal constant ERC20_MINT_TO_ZERO_ADDRESS = 410;
uint256 internal constant ERC20_BURN_FROM_ZERO_ADDRESS = 411;
uint256 internal constant ERC20_APPROVE_FROM_ZERO_ADDRESS = 412;
uint256 internal constant ERC20_APPROVE_TO_ZERO_ADDRESS = 413;
uint256 internal constant ERC20_TRANSFER_EXCEEDS_ALLOWANCE = 414;
uint256 internal constant ERC20_DECREASED_ALLOWANCE_BELOW_ZERO = 415;
uint256 internal constant ERC20_TRANSFER_EXCEEDS_BALANCE = 416;
uint256 internal constant ERC20_BURN_EXCEEDS_ALLOWANCE = 417;
uint256 internal constant SAFE_ERC20_CALL_FAILED = 418;
uint256 internal constant ADDRESS_INSUFFICIENT_BALANCE = 419;
uint256 internal constant ADDRESS_CANNOT_SEND_VALUE = 420;
uint256 internal constant SAFE_CAST_VALUE_CANT_FIT_INT256 = 421;
uint256 internal constant GRANT_SENDER_NOT_ADMIN = 422;
uint256 internal constant REVOKE_SENDER_NOT_ADMIN = 423;
uint256 internal constant RENOUNCE_SENDER_NOT_ALLOWED = 424;
uint256 internal constant BUFFER_PERIOD_EXPIRED = 425;
// Vault
uint256 internal constant INVALID_POOL_ID = 500;
uint256 internal constant CALLER_NOT_POOL = 501;
uint256 internal constant SENDER_NOT_ASSET_MANAGER = 502;
uint256 internal constant USER_DOESNT_ALLOW_RELAYER = 503;
uint256 internal constant INVALID_SIGNATURE = 504;
uint256 internal constant EXIT_BELOW_MIN = 505;
uint256 internal constant JOIN_ABOVE_MAX = 506;
uint256 internal constant SWAP_LIMIT = 507;
uint256 internal constant SWAP_DEADLINE = 508;
uint256 internal constant CANNOT_SWAP_SAME_TOKEN = 509;
uint256 internal constant UNKNOWN_AMOUNT_IN_FIRST_SWAP = 510;
uint256 internal constant MALCONSTRUCTED_MULTIHOP_SWAP = 511;
uint256 internal constant INTERNAL_BALANCE_OVERFLOW = 512;
uint256 internal constant INSUFFICIENT_INTERNAL_BALANCE = 513;
uint256 internal constant INVALID_ETH_INTERNAL_BALANCE = 514;
uint256 internal constant INVALID_POST_LOAN_BALANCE = 515;
uint256 internal constant INSUFFICIENT_ETH = 516;
uint256 internal constant UNALLOCATED_ETH = 517;
uint256 internal constant ETH_TRANSFER = 518;
uint256 internal constant CANNOT_USE_ETH_SENTINEL = 519;
uint256 internal constant TOKENS_MISMATCH = 520;
uint256 internal constant TOKEN_NOT_REGISTERED = 521;
uint256 internal constant TOKEN_ALREADY_REGISTERED = 522;
uint256 internal constant TOKENS_ALREADY_SET = 523;
uint256 internal constant TOKENS_LENGTH_MUST_BE_2 = 524;
uint256 internal constant NONZERO_TOKEN_BALANCE = 525;
uint256 internal constant BALANCE_TOTAL_OVERFLOW = 526;
uint256 internal constant POOL_NO_TOKENS = 527;
uint256 internal constant INSUFFICIENT_FLASH_LOAN_BALANCE = 528;
// Fees
uint256 internal constant SWAP_FEE_PERCENTAGE_TOO_HIGH = 600;
uint256 internal constant FLASH_LOAN_FEE_PERCENTAGE_TOO_HIGH = 601;
uint256 internal constant INSUFFICIENT_FLASH_LOAN_FEE_AMOUNT = 602;
}
library InputHelpers {
function ensureInputLengthMatch(uint256 a, uint256 b) internal pure {
_require(a == b, Errors.INPUT_LENGTH_MISMATCH);
}
function ensureInputLengthMatch(
uint256 a,
uint256 b,
uint256 c
) internal pure {
_require(a == b && b == c, Errors.INPUT_LENGTH_MISMATCH);
}
function ensureArrayIsSorted(IAsset[] memory array) internal pure {
address[] memory addressArray;
// solhint-disable-next-line no-inline-assembly
assembly {
addressArray := array
}
ensureArrayIsSorted(addressArray);
}
function ensureArrayIsSorted(IERC20[] memory array) internal pure {
address[] memory addressArray;
// solhint-disable-next-line no-inline-assembly
assembly {
addressArray := array
}
ensureArrayIsSorted(addressArray);
}
function ensureArrayIsSorted(address[] memory array) internal pure {
if (array.length < 2) {
return;
}
address previous = array[0];
for (uint256 i = 1; i < array.length; ++i) {
address current = array[i];
_require(previous < current, Errors.UNSORTED_ARRAY);
previous = current;
}
}
}
abstract contract AccessControl {
using EnumerableSet for EnumerableSet.AddressSet;
struct RoleData {
EnumerableSet.AddressSet members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
return _roles[role].members.contains(account);
}
/**
* @dev Returns the number of accounts that have `role`. Can be used
* together with {getRoleMember} to enumerate all bearers of a role.
*/
function getRoleMemberCount(bytes32 role) public view returns (uint256) {
return _roles[role].members.length();
}
/**
* @dev Returns one of the accounts that have `role`. `index` must be a
* value between 0 and {getRoleMemberCount}, non-inclusive.
*
* Role bearers are not sorted in any particular way, and their ordering may
* change at any point.
*
* WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
* you perform all queries on the same block. See the following
* https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
* for more information.
*/
function getRoleMember(bytes32 role, uint256 index) public view returns (address) {
return _roles[role].members.at(index);
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) public virtual {
_require(hasRole(_roles[role].adminRole, msg.sender), Errors.GRANT_SENDER_NOT_ADMIN);
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had already been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) public virtual {
_require(hasRole(_roles[role].adminRole, msg.sender), Errors.REVOKE_SENDER_NOT_ADMIN);
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) public virtual {
_require(account == msg.sender, Errors.RENOUNCE_SENDER_NOT_ALLOWED);
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);
_roles[role].adminRole = adminRole;
}
function _grantRole(bytes32 role, address account) private {
if (_roles[role].members.add(account)) {
emit RoleGranted(role, account, msg.sender);
}
}
function _revokeRole(bytes32 role, address account) private {
if (_roles[role].members.remove(account)) {
emit RoleRevoked(role, account, msg.sender);
}
}
}
interface IAuthorizer {
/**
* @dev Returns true if `account` can perform the action described by `actionId` in the contract `where`.
*/
function canPerform(
bytes32 actionId,
address account,
address where
) external view returns (bool);
}
/**
* @dev Basic Authorizer implementation, based on OpenZeppelin's Access Control.
*
* Users are allowed to perform actions if they have the role with the same identifier. In this sense, roles are not
* being truly used as such, since they each map to a single action identifier.
*
* This temporary implementation is expected to be replaced soon after launch by a more sophisticated one, able to
* manage permissions across multiple contracts and to natively handle timelocks.
*/
contract Authorizer is AccessControl, IAuthorizer {
constructor(address admin) {
_setupRole(DEFAULT_ADMIN_ROLE, admin);
}
function canPerform(
bytes32 actionId,
address account,
address
) public view override returns (bool) {
// This Authorizer ignores the 'where' field completely.
return AccessControl.hasRole(actionId, account);
}
/**
* @dev Grants multiple roles to a single account.
*/
function grantRoles(bytes32[] memory roles, address account) external {
for (uint256 i = 0; i < roles.length; i++) {
grantRole(roles[i], account);
}
}
/**
* @dev Grants roles to a list of accounts.
*/
function grantRolesToMany(bytes32[] memory roles, address[] memory accounts) external {
InputHelpers.ensureInputLengthMatch(roles.length, accounts.length);
for (uint256 i = 0; i < roles.length; i++) {
grantRole(roles[i], accounts[i]);
}
}
/**
* @dev Revokes multiple roles from a single account.
*/
function revokeRoles(bytes32[] memory roles, address account) external {
for (uint256 i = 0; i < roles.length; i++) {
revokeRole(roles[i], account);
}
}
/**
* @dev Revokes roles from a list of accounts.
*/
function revokeRolesFromMany(bytes32[] memory roles, address[] memory accounts) external {
InputHelpers.ensureInputLengthMatch(roles.length, accounts.length);
for (uint256 i = 0; i < roles.length; i++) {
revokeRole(roles[i], accounts[i]);
}
}
}
Compiler Settings
{"outputSelection":{"*":{"*":["abi","metadata","devdoc","userdoc","storageLayout","evm.legacyAssembly","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","evm.gasEstimates","evm.assembly"],"":["ast"]}},"optimizer":{"runs":200,"enabled":false},"libraries":{}}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"admin","internalType":"address"}]},{"type":"event","name":"RoleAdminChanged","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"previousAdminRole","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"newAdminRole","internalType":"bytes32","indexed":true}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address","name":"sender","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address","name":"sender","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"DEFAULT_ADMIN_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"canPerform","inputs":[{"type":"bytes32","name":"actionId","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"getRoleAdmin","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getRoleMember","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"uint256","name":"index","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getRoleMemberCount","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"grantRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"grantRoles","inputs":[{"type":"bytes32[]","name":"roles","internalType":"bytes32[]"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"grantRolesToMany","inputs":[{"type":"bytes32[]","name":"roles","internalType":"bytes32[]"},{"type":"address[]","name":"accounts","internalType":"address[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"hasRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"revokeRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"revokeRoles","inputs":[{"type":"bytes32[]","name":"roles","internalType":"bytes32[]"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"revokeRolesFromMany","inputs":[{"type":"bytes32[]","name":"roles","internalType":"bytes32[]"},{"type":"address[]","name":"accounts","internalType":"address[]"}]}]
Contract Creation Code
0x608060405234801561001057600080fd5b506040516200123e3803806200123e8339818101604052602081101561003557600080fd5b81019080805190602001909291905050506100596000801b8261005f60201b60201c565b5061022e565b61006f828261007360201b60201c565b5050565b61009e8160008085815260200190815260200160002060000161010360201b610a971790919060201c565b156100ff573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b600061011583836101df60201b60201c565b6101d45782600001829080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600001805490508360010160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600190506101d9565b600090505b92915050565b6000808360010160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541415905092915050565b611000806200023e6000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c8063988360a31161008c578063a73cb2ab11610066578063a73cb2ab1461053e578063ca15c8731461068a578063d547741f146106cc578063fcd7627e1461071a576100cf565b8063988360a3146103c45780639be2a8841461049c578063a217fddf14610520576100cf565b806318b2cde9146100d4578063248a9ca3146102205780632f2ff15d1461026257806336568abe146102b05780639010d07c146102fe57806391d1485414610360575b600080fd5b61021e600480360360408110156100ea57600080fd5b810190808035906020019064010000000081111561010757600080fd5b82018360208201111561011957600080fd5b8035906020019184602083028401116401000000008311171561013b57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561019b57600080fd5b8201836020820111156101ad57600080fd5b803590602001918460208302840111640100000000831117156101cf57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505091929192905050506107f2565b005b61024c6004803603602081101561023657600080fd5b810190808035906020019092919050505061084c565b6040518082815260200191505060405180910390f35b6102ae6004803603604081101561027857600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061086b565b005b6102fc600480360360408110156102c657600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506108a3565b005b6103346004803603604081101561031457600080fd5b8101908080359060200190929190803590602001909291905050506108eb565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103ac6004803603604081101561037657600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061091c565b60405180821515815260200191505060405180910390f35b61049a600480360360408110156103da57600080fd5b81019080803590602001906401000000008111156103f757600080fd5b82018360208201111561040957600080fd5b8035906020019184602083028401116401000000008311171561042b57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050509192919290803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061094d565b005b610508600480360360608110156104b257600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610988565b60405180821515815260200191505060405180910390f35b61052861099d565b6040518082815260200191505060405180910390f35b6106886004803603604081101561055457600080fd5b810190808035906020019064010000000081111561057157600080fd5b82018360208201111561058357600080fd5b803590602001918460208302840111640100000000831117156105a557600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561060557600080fd5b82018360208201111561061757600080fd5b8035906020019184602083028401116401000000008311171561063957600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505091929192905050506109a4565b005b6106b6600480360360208110156106a057600080fd5b81019080803590602001909291905050506109fe565b6040518082815260200191505060405180910390f35b610718600480360360408110156106e257600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610a24565b005b6107f06004803603604081101561073057600080fd5b810190808035906020019064010000000081111561074d57600080fd5b82018360208201111561075f57600080fd5b8035906020019184602083028401116401000000008311171561078157600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050509192919290803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610a5c565b005b6107fe82518251610b6d565b60005b82518110156108475761083a83828151811061081957fe5b602002602001015183838151811061082d57fe5b6020026020010151610a24565b8080600101915050610801565b505050565b6000806000838152602001908152602001600020600201549050919050565b61089561088d600080858152602001908152602001600020600201543361091c565b6101a6610b7e565b61089f8282610b91565b5050565b6108dd3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146101a8610b7e565b6108e78282610c1d565b5050565b600061091482600080868152602001908152602001600020600001610ca990919063ffffffff16565b905092915050565b600061094582600080868152602001908152602001600020600001610cd190919063ffffffff16565b905092915050565b60005b82518110156109835761097683828151811061096857fe5b602002602001015183610a24565b8080600101915050610950565b505050565b6000610994848461091c565b90509392505050565b6000801b81565b6109b082518251610b6d565b60005b82518110156109f9576109ec8382815181106109cb57fe5b60200260200101518383815181106109df57fe5b602002602001015161086b565b80806001019150506109b3565b505050565b6000610a1d600080848152602001908152602001600020600001610d20565b9050919050565b610a4e610a46600080858152602001908152602001600020600201543361091c565b6101a7610b7e565b610a588282610c1d565b5050565b60005b8251811015610a9257610a85838281518110610a7757fe5b60200260200101518361086b565b8080600101915050610a5f565b505050565b6000610aa38383610cd1565b610b625782600001829080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600001805490508360010160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555060019050610b67565b600090505b92915050565b610b7a8183146067610b7e565b5050565b81610b8d57610b8c81610d31565b5b5050565b610bb881600080858152602001908152602001600020600001610a9790919063ffffffff16565b15610c19573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b610c4481600080858152602001908152602001600020600001610da190919063ffffffff16565b15610ca5573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b6000610cbf828460000180549050116064610b7e565b610cc98383610f86565b905092915050565b6000808360010160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541415905092915050565b600081600001805490509050919050565b6030600a820601600a820491506030600a830601600a830492506030600a8406018060101b8260081b8401016642414c230000000160c81b7f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260076024528060445260646000fd5b6000808360010160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060008114610f7a5760006001820390506000600186600001805490500390506000866000018281548110610e1857fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905080876000018481548110610e5557fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600183018760010160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555086600001805480610ef357fe5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905590558660010160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090556001945050505050610f80565b60009150505b92915050565b6000826000018281548110610f9757fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690509291505056fea2646970667358221220fce9e53c578c88773c7bdc41686cd953553d6e4e6c3b9c0214407dd46ff48d8564736f6c634300070600330000000000000000000000004677143c96bccb614aa08097ddd1348e7384efcc
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c8063988360a31161008c578063a73cb2ab11610066578063a73cb2ab1461053e578063ca15c8731461068a578063d547741f146106cc578063fcd7627e1461071a576100cf565b8063988360a3146103c45780639be2a8841461049c578063a217fddf14610520576100cf565b806318b2cde9146100d4578063248a9ca3146102205780632f2ff15d1461026257806336568abe146102b05780639010d07c146102fe57806391d1485414610360575b600080fd5b61021e600480360360408110156100ea57600080fd5b810190808035906020019064010000000081111561010757600080fd5b82018360208201111561011957600080fd5b8035906020019184602083028401116401000000008311171561013b57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561019b57600080fd5b8201836020820111156101ad57600080fd5b803590602001918460208302840111640100000000831117156101cf57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505091929192905050506107f2565b005b61024c6004803603602081101561023657600080fd5b810190808035906020019092919050505061084c565b6040518082815260200191505060405180910390f35b6102ae6004803603604081101561027857600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061086b565b005b6102fc600480360360408110156102c657600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506108a3565b005b6103346004803603604081101561031457600080fd5b8101908080359060200190929190803590602001909291905050506108eb565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103ac6004803603604081101561037657600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061091c565b60405180821515815260200191505060405180910390f35b61049a600480360360408110156103da57600080fd5b81019080803590602001906401000000008111156103f757600080fd5b82018360208201111561040957600080fd5b8035906020019184602083028401116401000000008311171561042b57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050509192919290803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061094d565b005b610508600480360360608110156104b257600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610988565b60405180821515815260200191505060405180910390f35b61052861099d565b6040518082815260200191505060405180910390f35b6106886004803603604081101561055457600080fd5b810190808035906020019064010000000081111561057157600080fd5b82018360208201111561058357600080fd5b803590602001918460208302840111640100000000831117156105a557600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561060557600080fd5b82018360208201111561061757600080fd5b8035906020019184602083028401116401000000008311171561063957600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505091929192905050506109a4565b005b6106b6600480360360208110156106a057600080fd5b81019080803590602001909291905050506109fe565b6040518082815260200191505060405180910390f35b610718600480360360408110156106e257600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610a24565b005b6107f06004803603604081101561073057600080fd5b810190808035906020019064010000000081111561074d57600080fd5b82018360208201111561075f57600080fd5b8035906020019184602083028401116401000000008311171561078157600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050509192919290803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610a5c565b005b6107fe82518251610b6d565b60005b82518110156108475761083a83828151811061081957fe5b602002602001015183838151811061082d57fe5b6020026020010151610a24565b8080600101915050610801565b505050565b6000806000838152602001908152602001600020600201549050919050565b61089561088d600080858152602001908152602001600020600201543361091c565b6101a6610b7e565b61089f8282610b91565b5050565b6108dd3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146101a8610b7e565b6108e78282610c1d565b5050565b600061091482600080868152602001908152602001600020600001610ca990919063ffffffff16565b905092915050565b600061094582600080868152602001908152602001600020600001610cd190919063ffffffff16565b905092915050565b60005b82518110156109835761097683828151811061096857fe5b602002602001015183610a24565b8080600101915050610950565b505050565b6000610994848461091c565b90509392505050565b6000801b81565b6109b082518251610b6d565b60005b82518110156109f9576109ec8382815181106109cb57fe5b60200260200101518383815181106109df57fe5b602002602001015161086b565b80806001019150506109b3565b505050565b6000610a1d600080848152602001908152602001600020600001610d20565b9050919050565b610a4e610a46600080858152602001908152602001600020600201543361091c565b6101a7610b7e565b610a588282610c1d565b5050565b60005b8251811015610a9257610a85838281518110610a7757fe5b60200260200101518361086b565b8080600101915050610a5f565b505050565b6000610aa38383610cd1565b610b625782600001829080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600001805490508360010160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555060019050610b67565b600090505b92915050565b610b7a8183146067610b7e565b5050565b81610b8d57610b8c81610d31565b5b5050565b610bb881600080858152602001908152602001600020600001610a9790919063ffffffff16565b15610c19573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b610c4481600080858152602001908152602001600020600001610da190919063ffffffff16565b15610ca5573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b6000610cbf828460000180549050116064610b7e565b610cc98383610f86565b905092915050565b6000808360010160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541415905092915050565b600081600001805490509050919050565b6030600a820601600a820491506030600a830601600a830492506030600a8406018060101b8260081b8401016642414c230000000160c81b7f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260076024528060445260646000fd5b6000808360010160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060008114610f7a5760006001820390506000600186600001805490500390506000866000018281548110610e1857fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905080876000018481548110610e5557fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600183018760010160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555086600001805480610ef357fe5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905590558660010160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090556001945050505050610f80565b60009150505b92915050565b6000826000018281548110610f9757fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690509291505056fea2646970667358221220fce9e53c578c88773c7bdc41686cd953553d6e4e6c3b9c0214407dd46ff48d8564736f6c63430007060033