function getEpochStart(uint timestamp) public view returns (uint) {
	uint bribeStart = timestamp - (timestamp % (7 days)) + BRIBE_LAG;
	uint bribeEnd = bribeStart + DURATION - COOLDOWN;
	return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;
}
function notifyRewardAmount(address token, uint amount) external lock {
  require(amount > 0);
  if (!isReward[token]) {
	require(rewards.length < MAX_REWARD_TOKENS, "too many rewards tokens");
  }
  // bribes kick in at the start of next bribe period
  uint adjustedTstamp = getEpochStart(block.timestamp);
  uint epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];

  _safeTransferFrom(token, msg.sender, address(this), amount);
  tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;

  if (!isReward[token]) {
	  isReward[token] = true;
	  rewards.push(token);
	  IGauge(gauge).addBribeRewardToken(token);
  }

  emit NotifyReward(msg.sender, token, adjustedTstamp, amount);
}
function distribute(address _gauge) public lock {
	require(isAlive[_gauge]); // killed gauges cannot distribute
	uint dayCalc = block.timestamp % (7 days);
	require((dayCalc < BRIBE_LAG) || (dayCalc > (DURATION + BRIBE_LAG)), "cannot claim during votes period");
	IMinter(minter).update_period();
	_updateFor(_gauge);
	uint _claimable = claimable[_gauge];
	if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {
		claimable[_gauge] = 0;
		IGauge(_gauge).notifyRewardAmount(base, _claimable);
		emit DistributeReward(msg.sender, _gauge, _claimable);
		// distribute bribes & fees too
		IGauge(_gauge).deliverBribes();
	}
}
function deliverBribes() external lock {
	require(msg.sender == voter);
	IBribe sb = IBribe(bribe);
	uint bribeStart = block.timestamp - (block.timestamp % (7 days)) + BRIBE_LAG;
	uint numRewards = sb.rewardsListLength();

	for (uint i = 0; i < numRewards; i++) {
		address token = sb.rewards(i);
		uint epochRewards = sb.deliverReward(token, bribeStart);
		if (epochRewards > 0) {
			_notifyBribeAmount(token, epochRewards, bribeStart);
		}
	}
}
function deliverReward(address token, uint epochStart) external lock returns (uint) {
	require(msg.sender == gauge);
	uint rewardPerEpoch = tokenRewardsPerEpoch[token][epochStart];
	if (rewardPerEpoch > 0) {
	  _safeTransfer(token, address(gauge), rewardPerEpoch);
	}
	return rewardPerEpoch;
}
