Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
This contract has been verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- OperatorStore
- Optimization enabled
- true
- Compiler version
- v0.8.6+commit.11564f7e
- Optimization runs
- 10000
- EVM Version
- berlin
- Verified at
- 2026-03-21T03:16:15.947134Z
contracts/OperatorStore.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.6;
import "./interfaces/IOperatorStore.sol";
/**
@notice
Addresses can give permissions to any other address to take specific actions
throughout the Juicebox ecosystem on their behalf. These addresses are called `operators`.
@dev
Permissions are stored as a uint256, with each boolean bit representing whether or not
an oporator has the permission identified by that bit's index in the 256 bit uint256.
Indexes must be between 0 and 255.
The directory of permissions, along with how they uniquely mapp to indexes, are managed externally.
This contract doesn't know or care about specific permissions and their indexes.
*/
contract OperatorStore is IOperatorStore {
// --- public stored properties --- //
/**
@notice
The permissions that an operator has to operate on a specific domain.
@dev
An account can give an operator permissions that only pertain to a specific domain.
There is no domain with an ID of 0 -- accounts can use the 0 domain to give an operator
permissions to operator on their personal behalf.
*/
mapping(address => mapping(address => mapping(uint256 => uint256)))
public
override permissionsOf;
// --- public views --- //
/**
@notice
Whether or not an operator has the permission to take a certain action pertaining to the specified domain.
@param _operator The operator to check.
@param _account The account that has given out permission to the operator.
@param _domain The domain that the operator has been given permissions to operate.
@param _permissionIndex the permission to check for.
@return Whether the operator has the specified permission.
*/
function hasPermission(
address _operator,
address _account,
uint256 _domain,
uint256 _permissionIndex
) external view override returns (bool) {
require(
_permissionIndex <= 255,
"OperatorStore::hasPermission: INDEX_OUT_OF_BOUNDS"
);
return
((permissionsOf[_operator][_account][_domain] >> _permissionIndex) &
1) == 1;
}
/**
@notice
Whether or not an operator has the permission to take certain actions pertaining to the specified domain.
@param _operator The operator to check.
@param _account The account that has given out permissions to the operator.
@param _domain The domain that the operator has been given permissions to operate.
@param _permissionIndexes An array of permission indexes to check for.
@return Whether the operator has all specified permissions.
*/
function hasPermissions(
address _operator,
address _account,
uint256 _domain,
uint256[] calldata _permissionIndexes
) external view override returns (bool) {
for (uint256 _i = 0; _i < _permissionIndexes.length; _i++) {
uint256 _permissionIndex = _permissionIndexes[_i];
require(
_permissionIndex <= 255,
"OperatorStore::hasPermissions: INDEX_OUT_OF_BOUNDS"
);
if (
((permissionsOf[_operator][_account][_domain] >>
_permissionIndex) & 1) == 0
) return false;
}
return true;
}
// --- external transactions --- //
/**
@notice
Sets permissions for an operator.
@param _operator The operator to give permission to.
@param _domain The domain that the operator is being given permissions to operate.
@param _permissionIndexes An array of indexes of permissions to set.
*/
function setOperator(
address _operator,
uint256 _domain,
uint256[] calldata _permissionIndexes
) external override {
// Pack the indexes into a uint256.
uint256 _packed = _packedPermissions(_permissionIndexes);
// Store the new value.
permissionsOf[_operator][msg.sender][_domain] = _packed;
emit SetOperator(
_operator,
msg.sender,
_domain,
_permissionIndexes,
_packed
);
}
/**
@notice
Sets permissions for many operators.
@param _operators The operators to give permission to.
@param _domains The domains that can be operated. Set to 0 to allow operation of account level actions.
@param _permissionIndexes The level of power each operator should have.
*/
function setOperators(
address[] calldata _operators,
uint256[] calldata _domains,
uint256[][] calldata _permissionIndexes
) external override {
// There should be a level for each operator provided.
require(
_operators.length == _permissionIndexes.length &&
_operators.length == _domains.length,
"OperatorStore::setOperators: BAD_ARGS"
);
for (uint256 _i = 0; _i < _operators.length; _i++) {
// Pack the indexes into a uint256.
uint256 _packed = _packedPermissions(_permissionIndexes[_i]);
// Store the new value.
permissionsOf[_operators[_i]][msg.sender][_domains[_i]] = _packed;
emit SetOperator(
_operators[_i],
msg.sender,
_domains[_i],
_permissionIndexes[_i],
_packed
);
}
}
// --- private helper functions --- //
/**
@notice
Converts an array of permission indexes to a packed int.
@param _indexes The indexes of the permissions to pack.
@return packed The packed result.
*/
function _packedPermissions(uint256[] calldata _indexes)
private
pure
returns (uint256 packed)
{
for (uint256 _i = 0; _i < _indexes.length; _i++) {
uint256 _permissionIndex = _indexes[_i];
require(
_permissionIndex <= 255,
"OperatorStore::_packedPermissions: INDEX_OUT_OF_BOUNDS"
);
// Turn the bit at the index on.
packed |= 1 << _permissionIndex;
}
}
}
/IOperatorStore.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.6;
interface IOperatorStore {
event SetOperator(
address indexed operator,
address indexed account,
uint256 indexed domain,
uint256[] permissionIndexes,
uint256 packed
);
function permissionsOf(
address _operator,
address _account,
uint256 _domain
) external view returns (uint256);
function hasPermission(
address _operator,
address _account,
uint256 _domain,
uint256 _permissionIndex
) external view returns (bool);
function hasPermissions(
address _operator,
address _account,
uint256 _domain,
uint256[] calldata _permissionIndexes
) external view returns (bool);
function setOperator(
address _operator,
uint256 _domain,
uint256[] calldata _permissionIndexes
) external;
function setOperators(
address[] calldata _operators,
uint256[] calldata _domains,
uint256[][] calldata _permissionIndexes
) external;
}
Compiler Settings
{"remappings":[],"optimizer":{"runs":10000,"enabled":true},"metadata":{"bytecodeHash":"ipfs"},"libraries":{},"evmVersion":"berlin","compilationTarget":{"contracts/OperatorStore.sol":"OperatorStore"}}
Contract ABI
[{"type":"event","name":"SetOperator","inputs":[{"type":"address","name":"operator","internalType":"address","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"uint256","name":"domain","internalType":"uint256","indexed":true},{"type":"uint256[]","name":"permissionIndexes","internalType":"uint256[]","indexed":false},{"type":"uint256","name":"packed","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"hasPermission","inputs":[{"type":"address","name":"_operator","internalType":"address"},{"type":"address","name":"_account","internalType":"address"},{"type":"uint256","name":"_domain","internalType":"uint256"},{"type":"uint256","name":"_permissionIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"hasPermissions","inputs":[{"type":"address","name":"_operator","internalType":"address"},{"type":"address","name":"_account","internalType":"address"},{"type":"uint256","name":"_domain","internalType":"uint256"},{"type":"uint256[]","name":"_permissionIndexes","internalType":"uint256[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"permissionsOf","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setOperator","inputs":[{"type":"address","name":"_operator","internalType":"address"},{"type":"uint256","name":"_domain","internalType":"uint256"},{"type":"uint256[]","name":"_permissionIndexes","internalType":"uint256[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setOperators","inputs":[{"type":"address[]","name":"_operators","internalType":"address[]"},{"type":"uint256[]","name":"_domains","internalType":"uint256[]"},{"type":"uint256[][]","name":"_permissionIndexes","internalType":"uint256[][]"}]}]
Contract Creation Code
0x608060405234801561001057600080fd5b50610ad0806100206000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c806380deb2301161005057806380deb230146100a957806393535be1146100e7578063c161c93f146100fa57600080fd5b80630f5932f01461006c5780635ea6cc8614610094575b600080fd5b61007f61007a36600461079f565b61010d565b60405190151581526020015b60405180910390f35b6100a76100a2366004610850565b61023b565b005b6100d96100b7366004610763565b6000602081815293815260408082208552928152828120909352825290205481565b60405190815260200161008b565b6100a76100f53660046108aa565b6102ce565b61007f61010836600461080e565b610513565b6000805b8281101561022c57600084848381811061012d5761012d610a6b565b90506020020135905060ff8111156101cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f70657261746f7253746f72653a3a6861735065726d697373696f6e733a204960448201527f4e4445585f4f55545f4f465f424f554e4453000000000000000000000000000060648201526084015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff888116600090815260208181526040808320938b16835292815282822089835290522054811c60011661021957600092505050610232565b508061022481610a0b565b915050610111565b50600190505b95945050505050565b600061024783836105f0565b73ffffffffffffffffffffffffffffffffffffffff8616600081815260208181526040808320338085529083528184208a855290925291829020849055905192935086929091907f9dee2ffb464e2d0198cd20321be1ae3f79ed49f7ed4abfaa7ee4fe982bbeb320906102bf90889088908890610944565b60405180910390a45050505050565b84811480156102dc57508483145b610368576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4f70657261746f7253746f72653a3a7365744f70657261746f72733a2042414460448201527f5f4152475300000000000000000000000000000000000000000000000000000060648201526084016101c3565b60005b8581101561050a5760006103a184848481811061038a5761038a610a6b565b905060200281019061039c91906109a3565b6105f0565b9050806000808a8a868181106103b9576103b9610a6b565b90506020020160208101906103ce9190610741565b73ffffffffffffffffffffffffffffffffffffffff1681526020808201929092526040908101600090812033825290925281209088888681811061041457610414610a6b565b9050602002013581526020019081526020016000208190555085858381811061043f5761043f610a6b565b905060200201353373ffffffffffffffffffffffffffffffffffffffff1689898581811061046f5761046f610a6b565b90506020020160208101906104849190610741565b73ffffffffffffffffffffffffffffffffffffffff167f9dee2ffb464e2d0198cd20321be1ae3f79ed49f7ed4abfaa7ee4fe982bbeb3208787878181106104cd576104cd610a6b565b90506020028101906104df91906109a3565b866040516104ef93929190610944565b60405180910390a4508061050281610a0b565b91505061036b565b50505050505050565b600060ff8211156105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4f70657261746f7253746f72653a3a6861735065726d697373696f6e3a20494e60448201527f4445585f4f55545f4f465f424f554e445300000000000000000000000000000060648201526084016101c3565b5073ffffffffffffffffffffffffffffffffffffffff808516600090815260208181526040808320938716835292815282822085835290522054600190821c811614949350505050565b6000805b828110156106c557600084848381811061061057610610610a6b565b90506020020135905060ff8111156106aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4f70657261746f7253746f72653a3a5f7061636b65645065726d697373696f6e60448201527f733a20494e4445585f4f55545f4f465f424f554e44530000000000000000000060648201526084016101c3565b6001901b9190911790806106bd81610a0b565b9150506105f4565b5092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106f057600080fd5b919050565b60008083601f84011261070757600080fd5b50813567ffffffffffffffff81111561071f57600080fd5b6020830191508360208260051b850101111561073a57600080fd5b9250929050565b60006020828403121561075357600080fd5b61075c826106cc565b9392505050565b60008060006060848603121561077857600080fd5b610781846106cc565b925061078f602085016106cc565b9150604084013590509250925092565b6000806000806000608086880312156107b757600080fd5b6107c0866106cc565b94506107ce602087016106cc565b935060408601359250606086013567ffffffffffffffff8111156107f157600080fd5b6107fd888289016106f5565b969995985093965092949392505050565b6000806000806080858703121561082457600080fd5b61082d856106cc565b935061083b602086016106cc565b93969395505050506040820135916060013590565b6000806000806060858703121561086657600080fd5b61086f856106cc565b935060208501359250604085013567ffffffffffffffff81111561089257600080fd5b61089e878288016106f5565b95989497509550505050565b600080600080600080606087890312156108c357600080fd5b863567ffffffffffffffff808211156108db57600080fd5b6108e78a838b016106f5565b9098509650602089013591508082111561090057600080fd5b61090c8a838b016106f5565b9096509450604089013591508082111561092557600080fd5b5061093289828a016106f5565b979a9699509497509295939492505050565b6040815282604082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84111561097d57600080fd5b8360051b8086606085013760009083016060019081526020909201929092529392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126109d857600080fd5b83018035915067ffffffffffffffff8211156109f357600080fd5b6020019150600581901b360382131561073a57600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415610a64577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea2646970667358221220fcf6ef5dd27163b088a1baab03bb18a417fb8934ef1fb97ffe3f84f57c6d47cd64736f6c63430008060033
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106100675760003560e01c806380deb2301161005057806380deb230146100a957806393535be1146100e7578063c161c93f146100fa57600080fd5b80630f5932f01461006c5780635ea6cc8614610094575b600080fd5b61007f61007a36600461079f565b61010d565b60405190151581526020015b60405180910390f35b6100a76100a2366004610850565b61023b565b005b6100d96100b7366004610763565b6000602081815293815260408082208552928152828120909352825290205481565b60405190815260200161008b565b6100a76100f53660046108aa565b6102ce565b61007f61010836600461080e565b610513565b6000805b8281101561022c57600084848381811061012d5761012d610a6b565b90506020020135905060ff8111156101cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f70657261746f7253746f72653a3a6861735065726d697373696f6e733a204960448201527f4e4445585f4f55545f4f465f424f554e4453000000000000000000000000000060648201526084015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff888116600090815260208181526040808320938b16835292815282822089835290522054811c60011661021957600092505050610232565b508061022481610a0b565b915050610111565b50600190505b95945050505050565b600061024783836105f0565b73ffffffffffffffffffffffffffffffffffffffff8616600081815260208181526040808320338085529083528184208a855290925291829020849055905192935086929091907f9dee2ffb464e2d0198cd20321be1ae3f79ed49f7ed4abfaa7ee4fe982bbeb320906102bf90889088908890610944565b60405180910390a45050505050565b84811480156102dc57508483145b610368576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4f70657261746f7253746f72653a3a7365744f70657261746f72733a2042414460448201527f5f4152475300000000000000000000000000000000000000000000000000000060648201526084016101c3565b60005b8581101561050a5760006103a184848481811061038a5761038a610a6b565b905060200281019061039c91906109a3565b6105f0565b9050806000808a8a868181106103b9576103b9610a6b565b90506020020160208101906103ce9190610741565b73ffffffffffffffffffffffffffffffffffffffff1681526020808201929092526040908101600090812033825290925281209088888681811061041457610414610a6b565b9050602002013581526020019081526020016000208190555085858381811061043f5761043f610a6b565b905060200201353373ffffffffffffffffffffffffffffffffffffffff1689898581811061046f5761046f610a6b565b90506020020160208101906104849190610741565b73ffffffffffffffffffffffffffffffffffffffff167f9dee2ffb464e2d0198cd20321be1ae3f79ed49f7ed4abfaa7ee4fe982bbeb3208787878181106104cd576104cd610a6b565b90506020028101906104df91906109a3565b866040516104ef93929190610944565b60405180910390a4508061050281610a0b565b91505061036b565b50505050505050565b600060ff8211156105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4f70657261746f7253746f72653a3a6861735065726d697373696f6e3a20494e60448201527f4445585f4f55545f4f465f424f554e445300000000000000000000000000000060648201526084016101c3565b5073ffffffffffffffffffffffffffffffffffffffff808516600090815260208181526040808320938716835292815282822085835290522054600190821c811614949350505050565b6000805b828110156106c557600084848381811061061057610610610a6b565b90506020020135905060ff8111156106aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4f70657261746f7253746f72653a3a5f7061636b65645065726d697373696f6e60448201527f733a20494e4445585f4f55545f4f465f424f554e44530000000000000000000060648201526084016101c3565b6001901b9190911790806106bd81610a0b565b9150506105f4565b5092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106f057600080fd5b919050565b60008083601f84011261070757600080fd5b50813567ffffffffffffffff81111561071f57600080fd5b6020830191508360208260051b850101111561073a57600080fd5b9250929050565b60006020828403121561075357600080fd5b61075c826106cc565b9392505050565b60008060006060848603121561077857600080fd5b610781846106cc565b925061078f602085016106cc565b9150604084013590509250925092565b6000806000806000608086880312156107b757600080fd5b6107c0866106cc565b94506107ce602087016106cc565b935060408601359250606086013567ffffffffffffffff8111156107f157600080fd5b6107fd888289016106f5565b969995985093965092949392505050565b6000806000806080858703121561082457600080fd5b61082d856106cc565b935061083b602086016106cc565b93969395505050506040820135916060013590565b6000806000806060858703121561086657600080fd5b61086f856106cc565b935060208501359250604085013567ffffffffffffffff81111561089257600080fd5b61089e878288016106f5565b95989497509550505050565b600080600080600080606087890312156108c357600080fd5b863567ffffffffffffffff808211156108db57600080fd5b6108e78a838b016106f5565b9098509650602089013591508082111561090057600080fd5b61090c8a838b016106f5565b9096509450604089013591508082111561092557600080fd5b5061093289828a016106f5565b979a9699509497509295939492505050565b6040815282604082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84111561097d57600080fd5b8360051b8086606085013760009083016060019081526020909201929092529392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126109d857600080fd5b83018035915067ffffffffffffffff8211156109f357600080fd5b6020019150600581901b360382131561073a57600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415610a64577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea2646970667358221220fcf6ef5dd27163b088a1baab03bb18a417fb8934ef1fb97ffe3f84f57c6d47cd64736f6c63430008060033