ETH Price: $2,152.08 (+5.34%)

Transaction Decoder

Block:
18406490 at Oct-22-2023 02:40:11 PM +UTC
Transaction Fee:
0.00044026345104054 ETH $0.95
Gas Used:
48,362 Gas / 9.10349967 Gwei

Emitted Events:

233 OperatorStore.SetOperator( operator=0x4554CC10...54c687Fb2, account=[Sender] 0xa31fa3a404e79b24f865d1281b546bc3028b404b, domain=1, permissionIndexes=[12], packed=4096 )

Account State Difference:

  Address   Before After State Difference Code
(beaverbuild)
10.235379537515398281 Eth10.235384373715398281 Eth0.0000048362
0xa31Fa3a4...3028B404b
0.00942824807777319 Eth
Nonce: 130
0.00898798462673265 Eth
Nonce: 131
0.00044026345104054
0xab47304D...3A98B0db2
(Juicebox: Operator Store)

Execution Trace

OperatorStore.setOperator( _operator=0x4554CC10898f92D45378b98D6D6c2dD54c687Fb2, _domain=1, _permissionIndexes=[12] )
// 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;
        }
    }
}
// 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;
}