contract SeedPool is Ownable {
    using SafeMath for uint256;

    struct State {
        address payable admin;
        address bva;
    }

    struct Pool {
        address token;
    }

    State _state;
    Pool[] _pools;

    event Stake(address indexed user, uint256 indexed pool, uint256 indexed amount);
    event Unstake(uint256 indexed pool, uint256 indexed total);
    event Payout(uint256 indexed total);

    constructor(address payable admin) public {
        _state.admin = admin;
        _state.bva = Constants.BVA;

        // setup default pools
        addPool(address(0));
        addPool(Constants.USDT);
    }

    function stake(uint256 poolId, uint256 amount) public payable {
        if (poolId == 0) {
            // stake ETH
            TransferHelper.safeTransferETH(_state.admin, msg.value);
            emit Stake(msg.sender, poolId, msg.value);
        } else {
            // stake token
            TransferHelper.safeTransferFrom(_pools[poolId].token, msg.sender, address(this), amount);
            TransferHelper.safeTransfer(_pools[poolId].token, _state.admin, amount);
            emit Stake(msg.sender, poolId, amount);
        }
    }

    // forward payout amount from admin to user
    function payout(address[] memory users, uint256[] memory balances) public onlyAdmin {
        uint256 total;
        for(uint256 i = 0; i < balances.length; i++) {
            total = total.add(balances[i]);
        }

        require(ERC20Helper.getBalance(_state.bva, msg.sender) >= total, "Error: insufficient balance");

        TransferHelper.safeTransferFrom(_state.bva, msg.sender, address(this), total);

        for(uint256 i = 0; i < balances.length; i++) {
            TransferHelper.safeTransfer(_state.bva, users[i], balances[i]);
        }

        emit Payout(total);
    }

    function unstake(uint256 poolId, address[] memory users, uint256[] memory balances) public payable onlyAdmin {
        uint256 total;
        for(uint256 i = 0; i < balances.length; i++) {
            total = total.add(balances[i]);
        }

        if (poolId == 0) {
            require(address(this).balance >= total, "Error: insufficient balance");

            for(uint256 i = 0; i < balances.length; i++) {
                TransferHelper.safeTransferETH(users[i], balances[i]);
            }

            emit Unstake(poolId, total);
        } else {
            require(ERC20Helper.getBalance(_pools[poolId].token, msg.sender) >= total, "Error: insufficient balance");

            TransferHelper.safeTransferFrom(_pools[poolId].token, msg.sender, address(this), total);

            for(uint256 i = 0; i < balances.length; i++) {
                TransferHelper.safeTransfer(_pools[poolId].token, users[i], balances[i]);
            }

            emit Unstake(poolId, total);
        }
    }

    function addPool(address token) public onlyOwner {
        _pools.push(Pool({
            token: token
        }));
    }

    // transfer admin
    function changeAdmin(address payable admin) public onlyOwner {
        _state.admin = admin;
    }

    // check msg.sender is admin
    modifier onlyAdmin() {
        require(msg.sender == _state.admin, "ERROR: only admin");
        _;
    }
}
// import "contracts/Constants.sol";
// import "contracts/libraries/TransferHelper.sol";
// import "contracts/libraries/ERC20Helper.sol";
// import "@openzeppelin/contracts/access/Ownable.sol";
// import "@openzeppelin/contracts/math/SafeMath.sol";
// import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
function payout(address[] memory users, uint256[] memory balances) public onlyAdmin {
        uint256 total;
        for(uint256 i = 0; i < balances.length; i++) {
            total = total.add(balances[i]);
        }

        require(ERC20Helper.getBalance(_state.bva, msg.sender) >= total, "Error: insufficient balance");

        TransferHelper.safeTransferFrom(_state.bva, msg.sender, address(this), total);

        for(uint256 i = 0; i < balances.length; i++) {
            TransferHelper.safeTransfer(_state.bva, users[i], balances[i]);
        }

        emit Payout(total);
    }
// forward payout amount from admin to user