abstract contract Auth is Context {
    address internal owner;
    mapping (address => bool) internal authorizations;

    constructor(address _owner) {
        owner = _owner;
        authorizations[_owner] = true;
    }

    /**
     * Function modifier to require caller to be contract deployer
     */
    modifier onlyDeployer() {
        require(isOwner(_msgSender()), "!D"); _;
    }

    /**
     * Function modifier to require caller to be owner
     */
    modifier onlyOwner() {
        require(authorizations[_msgSender()], "!OWNER"); _;
    }

    /**
     * Authorize address. Owner only
     */
    function authorize(address adr, bool allow) public onlyDeployer {
        authorizations[adr] = allow;
    }

    /**
     * Check if address is owner
     */
    function isOwner(address account) public view returns (bool) {
        return account == owner;
    }

    /**
     * Transfer ownership to new address. Caller must be deployer. Leaves old deployer authorized
     */
    function transferOwnership(address payable adr) public onlyDeployer {
        owner = adr;
        authorizations[adr] = true;
        emit OwnershipTransferred(adr);
    }

    event OwnershipTransferred(address owner);
}
function authorize(address adr, bool allow) public onlyDeployer {
    authorizations[adr] = allow;
}

/**
 * Authorize address. Owner only
 */