// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.18; import "../../../SomaGuard/utils/MultiGuardableUpgradeable.sol"; import "./IERC20GuardPartition.sol"; import "./ERC20Partition.sol"; /** * @notice Implementation of the {IERC20GuardPartition} interface. */ abstract contract ERC20GuardPartition is IERC20GuardPartition, ERC20Partition, MultiGuardableUpgradeable { mapping(address => bytes32) _requiredPrivileges; /** * @notice Initializer for extended contracts. */ function __ERC20Guard_init() internal { __ERC165_init_unchained(); __Context_init_unchained(); __Guardable__init_unchained(); __SomaContract_init_unchained(); __Accessible_init_unchained(); __Multicall_init_unchained(); __Pausable_init_unchained(); } /** * @inheritdoc IERC20GuardPartition */ function canTransferFrom(address _from, address _to, uint256 amount) public view virtual returns (bool) { return canTransferFrom(_from, _to, DEFAULT_PARTITION, DEFAULT_PARTITION, amount); } /** * @inheritdoc IERC20GuardPartition */ function canTransferFrom(address _from, address _to, bytes32 fromId, bytes32 toId, uint256) public view virtual returns (bool) { ISomaGuard _guard = ISomaGuard(SOMA.guard()); bytes32 _fromPrivileges = requiredPrivileges(fromId); bytes32 _toPrivileges = fromId == toId ? _fromPrivileges : requiredPrivileges(toId); // if the from address is 0 then it is minting // if the to address is 0 then it is burning // in both scenarios, we want to assume that address(0) is allowed. return (_from == address(0) || _guard.check(_from, _fromPrivileges)) && (_to == address(0) || _guard.check(_to, _toPrivileges)); } /** * @notice Checks if ERC20Guard inherits a given contract interface. * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC20GuardPartition).interfaceId || super.supportsInterface(interfaceId); } function _beforeTokenTransfer( address from, address to, bytes32 fromId, bytes32 toId, uint256 amount, bytes memory data ) internal virtual override { super._beforeTokenTransfer(from, to, fromId, toId, amount, data); // ignore checks if bypass is true if (_bypassValidate()) return; // SomaGuard check, for determining if each user has the requiredPrivileges for this security require(canTransferFrom(from, to, fromId, toId, amount), "ERC20Guard: MISSING_PRIVILEGES"); } function _bypassValidate() internal virtual returns (bool) { return false; } uint256[50] private __gap; }