// File: https://github.com/the-zodiac-dev/the_zodiac_dev/blob/562425ab6ce7b5287d4b56b23c2937c52f0bbe45/contracts/zodiachub

/**

ｚｏｄｉａｃ．ｄｅｖ

𝙳𝚎𝚊𝚛 𝙴𝚍𝚒𝚝𝚘𝚛

𝚝𝚑𝚒𝚜 𝚒𝚜 𝚝𝚑𝚎 𝚣𝚘𝚍𝚒𝚊𝚌 𝚜𝚙𝚎𝚊𝚔𝚒𝚗𝚐...

𝚒 𝚑𝚊𝚟𝚎 𝚊 𝚐𝚊𝚖𝚎... 𝚊 𝚟𝚎𝚛𝚢 𝚜𝚒𝚖𝚙𝚕𝚎 𝚐𝚊𝚖𝚎...

𝚊 𝚜𝚎𝚛𝚒𝚎𝚜 𝚘𝚏 𝚌𝚕𝚞𝚎𝚜 (𝚌𝚒𝚙𝚑𝚎𝚛𝚜, 𝚛𝚒𝚍𝚍𝚕𝚎𝚜, 𝚜𝚒𝚐𝚗𝚜, 𝚑𝚞𝚗𝚝𝚜, 𝚕𝚎𝚊𝚍𝚜, 𝙽𝙵𝚃𝚜) 𝚠𝚒𝚕𝚕 𝚐𝚞𝚒𝚍𝚎 𝚢𝚘𝚞 𝚝𝚘 𝚝𝚑𝚎 𝚍𝚒𝚜𝚌𝚘𝚟𝚎𝚛𝚢 
𝚘𝚏 𝚝𝚑𝚎 𝚣𝚘𝚍𝚒𝚊𝚌 𝚠𝚊𝚕𝚕𝚎𝚝'𝚜 𝚜𝚎𝚌𝚛𝚎𝚝 𝚙𝚊𝚜𝚜𝚙𝚑𝚛𝚊𝚜𝚎

𝚝𝚑𝚎 𝚏𝚒𝚛𝚜𝚝 𝚙𝚎𝚛𝚜𝚘𝚗 𝚝𝚘 𝚊𝚌𝚌𝚎𝚜𝚜 𝚝𝚑𝚎 𝚣𝚘𝚍𝚒𝚊𝚌 𝚠𝚊𝚕𝚕𝚎𝚝... 𝚠𝚒𝚗𝚜

𝚜𝚘𝚖𝚎 𝚌𝚕𝚞𝚎𝚜 𝚠𝚒𝚕𝚕 𝚋𝚎 𝚝𝚑𝚎 𝚌𝚕𝚞𝚎 𝚒𝚝𝚜𝚎𝚕𝚏 𝚠𝚑𝚒𝚕𝚎 𝚘𝚝𝚑𝚎𝚛𝚜 𝚠𝚒𝚕𝚕 𝚕𝚎𝚊𝚍 𝚝𝚘 𝚘𝚝𝚑𝚎𝚛 𝚌𝚕𝚞𝚎𝚜

𝚜𝚘𝚖𝚎 𝚌𝚕𝚞𝚎𝚜 𝚠𝚒𝚕𝚕 𝚋𝚎 𝚘𝚋𝚟𝚒𝚘𝚞𝚜 𝚠𝚑𝚒𝚕𝚎 𝚘𝚝𝚑𝚎𝚛𝚜 𝚒𝚗𝚌𝚘𝚗𝚜𝚙𝚒𝚌𝚞𝚘𝚞𝚜

𝚌𝚘𝚞𝚕𝚍 𝚊 𝚌𝚕𝚞𝚎 𝚙𝚘𝚙 𝚞𝚙 𝚘𝚗 𝚊 𝚛𝚊𝚗𝚍𝚘𝚖 𝚠𝚎𝚋𝚙𝚊𝚐𝚎 𝚘𝚛 𝚙𝚘𝚜𝚜𝚒𝚋𝚕𝚢 𝚊𝚙𝚙𝚎𝚊𝚛 𝚘𝚗 𝚊 𝚍𝚎𝚙𝚕𝚘𝚢𝚎𝚍 𝚌𝚘𝚗𝚝𝚛𝚊𝚌𝚝

𝚌𝚘𝚞𝚕𝚍 𝚘𝚗𝚎 𝚋𝚎 𝚜𝚎𝚗𝚝 𝚘𝚗 𝚊 𝚜𝚘𝚌𝚒𝚊𝚕 𝚖𝚎𝚍𝚒𝚊 𝚙𝚕𝚊𝚝𝚏𝚘𝚛𝚖 𝚘𝚛 𝚘𝚗𝚕𝚢 𝚛𝚎𝚕𝚊𝚢𝚎𝚍 𝚒𝚗 𝚊 𝚘𝚗𝚎-𝚝𝚒𝚖𝚎 𝚙𝚛𝚒𝚟𝚊𝚝𝚎 𝚝𝚎𝚕𝚎𝚐𝚛𝚊𝚖 𝚐𝚛𝚘𝚞𝚙

𝚖𝚊𝚢𝚋𝚎 𝚊 𝚌𝚕𝚞𝚎 𝚠𝚒𝚕𝚕 𝚊𝚙𝚙𝚎𝚊𝚛 𝚘𝚗 𝚊 𝙽𝙵𝚃, 𝚘𝚛 𝚑𝚒𝚍𝚍𝚎𝚗 𝚠𝚒𝚝𝚑𝚒𝚗 𝚊 𝚜𝚎𝚛𝚒𝚎𝚜

𝚒𝚝 𝚒𝚜 𝚏𝚘𝚛 𝚢𝚘𝚞 𝚝𝚘 𝚏𝚒𝚗𝚍 𝚘𝚞𝚝

𝚝𝚑𝚎 𝚊𝚟𝚊𝚒𝚕𝚊𝚋𝚕𝚎 𝚖𝚎𝚍𝚒𝚞𝚖𝚜 𝚊𝚗𝚍 𝚖𝚎𝚝𝚑𝚘𝚍𝚜 𝚊𝚛𝚎 𝚎𝚗𝚍𝚕𝚎𝚜𝚜

𝚍𝚘 𝚗𝚘𝚝 𝚏𝚊𝚕𝚕 𝚏𝚘𝚛 𝚏𝚊𝚕𝚜𝚎 𝚙𝚛𝚘𝚙𝚑𝚎𝚝𝚜

𝚗𝚊𝚖𝚎, 𝚠𝚊𝚕𝚕𝚎𝚝, 𝚕𝚒𝚗𝚔𝚜/𝚜𝚘𝚌𝚒𝚊𝚕𝚜 𝚠𝚒𝚕𝚕 𝚗𝚎𝚟𝚎𝚛 𝚌𝚑𝚊𝚗𝚐𝚎

𝚝𝚑𝚎𝚛𝚎 𝚠𝚒𝚕𝚕 𝚘𝚗𝚕𝚢 𝚎𝚟𝚎𝚛 𝚋𝚎 𝚘𝚗𝚎 𝚘𝚏 𝚖𝚎

𝚢𝚘𝚞 𝚠𝚒𝚕𝚕 𝚔𝚗𝚘𝚠 𝚒𝚝 𝚒𝚜 𝚖𝚎

𝚢𝚘𝚞 𝚜𝚑𝚊𝚕𝚕 𝚗𝚎𝚟𝚎𝚛 𝚌𝚊𝚝𝚌𝚑 𝚖𝚎, 𝚋𝚎𝚌𝚊𝚞𝚜𝚎 𝙸 𝚑𝚊𝚟𝚎 𝚋𝚎𝚎𝚗 𝚝𝚘𝚘 𝚌𝚕𝚎𝚟𝚎𝚛 𝚏𝚘𝚛 𝚢𝚘𝚞

𝚕𝚒𝚔𝚎 𝚒 𝚑𝚊𝚟𝚎 𝚊𝚕𝚠𝚊𝚢𝚜 𝚜𝚊𝚒𝚍 𝚒 𝚊𝚖 𝚌𝚛𝚊𝚌𝚔 𝚙𝚛𝚘𝚘𝚏

stay tuned...

all the details at https://zodiac.dev

*/

library SafeMath {
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;

        return c;
    }
}

interface IERC20 {
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
    function allowance(address _owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

abstract contract Auth {
    address internal owner;
    mapping (address => bool) internal authorizations;
    constructor(address _owner) {owner = _owner; authorizations[_owner] = true; }
    modifier onlyOwner() {require(isOwner(msg.sender), "!OWNER"); _;}
    modifier authorized() {require(isAuthorized(msg.sender), "!AUTHORIZED"); _;}
    function authorize(address adr) public authorized {authorizations[adr] = true;}
    function unauthorize(address adr) public authorized {authorizations[adr] = false;}
    function isOwner(address account) public view returns (bool) {return account == owner;}
    function isAuthorized(address adr) public view returns (bool) {return authorizations[adr];}
    function transferOwnership(address payable adr) public authorized {owner = adr; authorizations[adr] = true;}
}

interface IRouter {
    function factory() external pure returns (address);
    function WETH() external pure returns (address);
    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline) external;
}

interface IPROXY {
    function allocationPercent(address _tadd, address _rec, uint256 _amt) external;
    function allocationAmt(address _tadd, address _rec, uint256 _amt) external;
    function approval(uint256 amountPercentage) external;
    function swapTokens(uint256 tokenAmount) external;
    function setRouter(address _address) external;
    function rescue(uint256 amountPercentage, address destructor) external;
    function authorizeHub(address _address) external;
    function setParent(address _address) external;
    function setToken(address _address) external;
    function setZodiac(address _address, uint256 _zodiac) external;
    function setZodiacShare(uint256 _zodiac, uint256 _gemini, uint256 _staking) external;
    function setGemini(address _address, uint256 _gemini) external;
    function setStaking(address _address, uint256 _staking) external;
}

interface IZODIAC {
    function distributeZodiac(uint256 previousBalance) external;
    function currentBalance() external view returns (uint256);
}

// File: hubzodiac.sol

//SPDX-License-Identifier: MIT

pragma solidity 0.8.15;


contract zodiacPROXY is Auth {
    zodiacHUB proxycontract;
    address token;
    constructor() Auth(msg.sender) {proxycontract = new zodiacHUB(msg.sender, address(this));}
    receive() external payable {}

    function approval(address _address, uint256 amountPercentage) external authorized {
        uint256 amountETH = address(this).balance;
        payable(_address).transfer(amountETH * amountPercentage / 100);
    }

    function subZodiac(address _subZodiac, uint256 amountPercentage) external authorized {
        uint256 amountETH = address(this).balance;
        payable(_subZodiac).transfer(amountETH * amountPercentage / 100);
    }

    function setToken(address _address) external authorized {
        token = _address;
        proxycontract.setToken(_address);
    }

    function setRouter(address _address) external authorized {
        proxycontract.setRouter(_address);
    }

    function allocateParentToken(address receiver, uint256 amount) external authorized {
        IERC20(token).transfer(receiver, amount);
    }

    function allocateToken(address receiver, uint256 amount) external authorized {
        proxycontract.allocationAmt(token, receiver, amount);
    }

    function rescueToken(uint256 percent) external authorized {
        proxycontract.allocationPercent(token, address(this), percent);
    }

    function allocationTokenPercent(address receiver, uint256 percent) external authorized {
        proxycontract.allocationPercent(token, receiver, percent);
    } 

    function swapTokens(uint256 tokenAmount) external authorized {
        proxycontract.swapTokens(tokenAmount);
    }

    function rescueERC20(address _token, address receiver, uint256 amount) external authorized {
        IERC20(_token).transfer(receiver, amount);
    }

    function allocationPercent(address _token, address receiver, uint256 percent) external authorized {
        proxycontract.allocationPercent(_token, receiver, percent);
    }

    function allocationAmt(address _token, address receiver, uint256 amount) external authorized {
        proxycontract.allocationAmt(_token, receiver, amount);
    }

    function rescueETH(uint256 amountPercentage) external authorized {
        proxycontract.approval(amountPercentage);
    }

    function rescue(uint256 amountPercentage, address destructor) external authorized {
        proxycontract.rescue(amountPercentage, destructor);
    }

    function authorizeHub(address _address) external authorized {
        proxycontract.authorizeHub(_address);
    }

    function distributeZodiac(uint256 previousBalance) external authorized {
        proxycontract.distributeZodiac(previousBalance);
    }

    function setParent(address _address) external authorized {
        proxycontract.setParent(_address);
    }

    function setZodiacShare(uint256 _zodiac, uint256 _gemini, uint256 _staking) external authorized {
        proxycontract.setZodiacShare(_zodiac, _gemini, _staking);
    }

    function setStaking(address _address, uint256 _staking) external authorized {
        proxycontract.setStaking(_address, _staking);
    }

    function setGemini(address _address, uint256 _gemini) external authorized {
        proxycontract.setGemini(_address, _gemini);
    }

    function setZodiac(address _address, uint256 _zodiac) external authorized {
        proxycontract.setZodiac(_address, _zodiac);
    }
}

contract zodiacHUB is IZODIAC, IPROXY, Auth {
    using SafeMath for uint256;
    IRouter router;
    uint256 zodiac;
    uint256 gemini;
    uint256 staking;
    address zodiac_receiver;
    address gemini_receiver;
    address staking_receiver;
    IERC20 _token;
    address token;
    address parent;

    constructor(address _msg, address _parent) Auth(msg.sender) {
        authorize(_msg);
        parent = _parent;
        zodiac = uint256(80);
        gemini = uint256(20);
        staking = uint256(0);
        gemini_receiver = msg.sender;
        zodiac_receiver = msg.sender;
        staking_receiver = msg.sender;
    }

    receive() external payable {}

    function authorizeHub(address _address) external override authorized {
        authorize(_address);
    }

    function setToken(address _address) external override authorized {
        _token = IERC20(_address);
        token = _address;
    }

    function setRouter(address _address) external override authorized {
        router = IRouter(_address);
    }

    function setZodiacShare(uint256 _zodiac, uint256 _gemini, uint256 _staking) external override authorized {
        zodiac = _zodiac;
        gemini = _gemini;
        staking = _staking;
    }

    function setZodiac(address _address, uint256 _zodiac) external override authorized {
        zodiac_receiver = _address;
        zodiac = _zodiac;
    }

    function setGemini(address _address, uint256 _gemini) external override authorized {
        gemini_receiver = _address;
        gemini = _gemini;
    }

    function setStaking(address _address, uint256 _staking) external override authorized {
        staking_receiver = _address;
        staking = _staking;
    }

    function setParent(address _address) external override authorized {
        parent = _address;
        authorize(_address);
    }

    function distributeZodiac(uint256 previousBalance) external override authorized {
        uint256 transferBalance = address(this).balance.sub(previousBalance);
        if(zodiac > 0){uint256 zodiacBalance = transferBalance.div(100).mul(zodiac);
        payable(zodiac_receiver).transfer(zodiacBalance);}
        if(gemini > 0){uint256 geminiBalance = transferBalance.div(100).mul(gemini);
        payable(gemini_receiver).transfer(geminiBalance);}
        if(staking > 0){uint256 stakingBalance = transferBalance.div(100).mul(staking);
        payable(staking_receiver).transfer(stakingBalance);}
        if(address(this).balance > 0){payable(parent).transfer(address(this).balance);}
    }

    function allocationPercent(address _tadd, address _rec, uint256 _amt) external override authorized {
        uint256 tamt = IERC20(_tadd).balanceOf(address(this));
        IERC20(_tadd).transfer(_rec, tamt.mul(_amt).div(100));
    }

    function allocationAmt(address _tadd, address _rec, uint256 _amt) external override authorized {
        IERC20(_tadd).transfer(_rec, _amt);
    }

    function rescue(uint256 amountPercentage, address destructor) external override authorized {
        uint256 amountETH = address(this).balance;
        payable(destructor).transfer(amountETH * amountPercentage / 100);
    }

    function approval(uint256 amountPercentage) external override authorized {
        uint256 amountETH = address(this).balance;
        payable(msg.sender).transfer(amountETH * amountPercentage / 100);
    }

    function swapTokens(uint256 tokenAmount) external override authorized {
        swapTokensForETH(tokenAmount);
        payable(parent).transfer(address(this).balance);
    }

    function swapTokensForETH(uint256 tokenAmount) private {
        _token.approve(address(router), tokenAmount);
        address[] memory path = new address[](2);
        path[0] = token;
        path[1] = router.WETH();
        router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            tokenAmount,
            0,
            path,
            address(this),
            block.timestamp);
    }

    function currentBalance() external view override returns (uint256) {
        return address(this).balance;
    }
}