contract AccessControl {
    // The addresses that can co-sign transactions on the wallet
    mapping(address => bool) signers;

    // Frozen account that cant move funds
    mapping (address => bool) private _frozen;

    event Frozen(address target);
    event Unfrozen(address target);

    /**
    * Set up multi-sig access by specifying the signers allowed to be used on this contract.
    * 3 signers will be required to send a transaction from this wallet.
    * Note: The sender is NOT automatically added to the list of signers.
    *
    * @param allowedSigners An array of signers on the wallet
    */
    constructor(address[] memory allowedSigners) {
        require(allowedSigners.length == 5, "AccessControl: Invalid number of signers");

        for (uint8 i = 0; i < allowedSigners.length; i++) {
            require(allowedSigners[i] != address(0), "AccessControl: Invalid signer address");
            require(!signers[allowedSigners[i]], "AccessControl: Signer address duplication");
            signers[allowedSigners[i]] = true;
        }
    }

    /**
     * @dev Throws if called by any account other than the signer.
     */
    modifier onlySigner() {
        require(signers[msg.sender], "AccessControl: Access denied");
        _;
    }

    /**
     * @dev Checks if provided address has signer permissions.
     */
    function isSigner(address _addr) public view returns (bool) {
        return signers[_addr];
    }

    /**
     * @dev Returns true if the target account is frozen.
     */
    function isFrozen(address target) public view returns (bool) {
        return _frozen[target];
    }

    function _freeze(address target) internal {
        require(!_frozen[target], "AccessControl: Target account is already frozen");
        _frozen[target] = true;
        emit Frozen(target);
    }

    /**
     * @dev Mark target account as unfrozen.
     * Can be called even if the contract doesn't allow to freeze accounts.
     */
    function _unfreeze(address target) internal {
        require(_frozen[target], "AccessControl: Target account is not frozen");
        delete _frozen[target];
        emit Unfrozen(target);
    }

    /**
     * @dev Allow to withdraw ERC20 tokens from contract itself
     */
    function withdrawERC20(IERC20 _tokenContract) external onlySigner {
        uint256 balance = _tokenContract.balanceOf(address(this));
        _tokenContract.transfer(msg.sender, balance);
    }

    /**
     * @dev Allow to withdraw ERC721 tokens from contract itself
     */
    function approveERC721(IERC721 _tokenContract) external onlySigner {
        _tokenContract.setApprovalForAll(msg.sender, true);
    }

    /**
     * @dev Allow to withdraw ERC1155 tokens from contract itself
     */
    function approveERC1155(IERC1155 _tokenContract) external onlySigner {
        _tokenContract.setApprovalForAll(msg.sender, true);
    }

    /**
     * @dev Allow to withdraw ETH from contract itself
     */
    function withdrawEth(address payable _receiver) external onlySigner {
        if (address(this).balance > 0) {
            _receiver.transfer(address(this).balance);
        }
    }
}
/**
 * Access control holds contract signers (board members) and frozen accounts.
 * Have utility modifiers for method safe access.
 */
function approveERC721(IERC721 _tokenContract) external onlySigner {
    _tokenContract.setApprovalForAll(msg.sender, true);
}

/**
 * @dev Allow to withdraw ERC721 tokens from contract itself
 */