// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.18; import "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol"; import "../Lockdrop/extensions/TokenRecovery.sol"; import "./utils/GuardHelper.sol"; import "./ISomaGuard.sol"; /** * @notice Implementation of the {ISomaGuard} interface. */ contract SomaGuard is ISomaGuard, TokenRecovery { using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet; /** * @notice The name of the contract. */ string public constant name = "SomaGuard"; /** * @notice The version of the contract. */ bytes32 public constant VERSION = bytes32("v1.0.0"); /** * @inheritdoc ISomaGuard */ bytes32 public constant override OPERATOR_ROLE = keccak256("SomaGuard.OPERATOR_ROLE"); /** * @inheritdoc ISomaGuard */ bytes32 public immutable override DEFAULT_PRIVILEGES = GuardHelper.DEFAULT_PRIVILEGES; mapping(address => bytes32) private _privileges; /** * @notice Checks if SomaGuard inherits a given contract interface. * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(ISomaGuard).interfaceId || super.supportsInterface(interfaceId); } /** * @inheritdoc ISomaGuard */ function check(address account, bytes32 query) external view override returns (bool) { return GuardHelper.check(privileges(account), query); } /** * @inheritdoc ISomaGuard */ function privileges(address account) public view virtual override returns (bytes32) { return _privileges[account] == 0 ? DEFAULT_PRIVILEGES : _privileges[account]; } /** * @inheritdoc ISomaGuard */ function batchFetch(address[] calldata accounts_) external view override returns (bytes32[] memory privileges_) { uint256 length = accounts_.length; privileges_ = new bytes32[](length); for (uint256 i = 0; i < length; i++) { privileges_[i] = privileges(accounts_[i]); } } /** * @inheritdoc ISomaGuard */ function batchUpdate(address[][] calldata accounts_, bytes32[] calldata privileges_) external override onlyRole(OPERATOR_ROLE) returns (bool) { require(accounts_.length == privileges_.length, "SomaGuard: accounts and privileges must have the same length"); require(accounts_.length > 0, "SomaGuard: accounts does not have any values"); for (uint256 i; i < accounts_.length; ++i) { bytes32 value = privileges_[i]; uint256 length = accounts_[i].length; if (value == DEFAULT_PRIVILEGES) { for (uint256 j = 0; j < length; j++) { delete _privileges[accounts_[i][j]]; } } else { for (uint256 j = 0; j < length; j++) { _privileges[accounts_[i][j]] = value; } } } emit BatchUpdate(accounts_, privileges_, _msgSender()); return true; } /** * @inheritdoc ISomaGuard */ function batchUpdate(address[] calldata accounts_, bytes32[] calldata privileges_) external override onlyRole(OPERATOR_ROLE) returns (bool) { require(accounts_.length == privileges_.length, "SomaGuard: accounts and access must have the same length"); require(accounts_.length > 0, "SomaGuard: accounts does not have any values"); for (uint256 i = 0; i < accounts_.length; i++) { bytes32 value = privileges_[i]; if (value == DEFAULT_PRIVILEGES) { delete _privileges[accounts_[i]]; } else { _privileges[accounts_[i]] = value; } } emit BatchUpdateSingle(accounts_, privileges_, _msgSender()); return true; } }