function distribute(uint256 vaultId) external override virtual nonReentrant {
  require(nftxVaultFactory != address(0));
  address _vault = INFTXVaultFactory(nftxVaultFactory).vault(vaultId);

  uint256 tokenBalance = IERC20Upgradeable(_vault).balanceOf(address(this));

  if (distributionPaused || allocTotal == 0) {
    IERC20Upgradeable(_vault).safeTransfer(treasury, tokenBalance);
    return;
  }

  uint256 length = feeReceivers.length;
  uint256 leftover;
  for (uint256 i = 0; i <length; i++) {
    FeeReceiver memory _feeReceiver = feeReceivers[i];
    uint256 amountToSend = leftover + ((tokenBalance * _feeReceiver.allocPoint) / allocTotal);
    uint256 currentTokenBalance = IERC20Upgradeable(_vault).balanceOf(address(this));
    amountToSend = amountToSend> currentTokenBalance? currentTokenBalance: amountToSend;
    bool complete = _sendForReceiver(_feeReceiver, vaultId, _vault, amountToSend);
    if (!complete) {
      leftover = amountToSend;
    } else {
      leftover = 0;
    }
  }
function _sendForReceiver(FeeReceiver memory _receiver, uint256 _vaultId, address _vault, uint256 amountToSend) internal virtual returns (bool) {
  if (_receiver.isContract) {
    IERC20Upgradeable(_vault).approve(_receiver.receiver, amountToSend);
    // If the receive is not properly processed, send it to the treasury instead.
      
    bytes memory payload = abi.encodeWithSelector(INFTXLPStaking.receiveRewards.selector, _vaultId, amountToSend);
    (bool success,) = address(_receiver.receiver).call(payload);

    // If the allowance has not been spent, it means we can pass it forward to next.
    return success && IERC20Upgradeable(_vault).allowance(address(this), _receiver.receiver) == 0;
  } else {
    IERC20Upgradeable(_vault).safeTransfer(_receiver.receiver, amountToSend);
  }
}
