function totalSupplyAtEpoch(uint256 _epoch) external view returns (uint256 supply) {
    uint256 epochStart = uint256(epochs[_epoch].date).div(rewardsDuration).mul(
        rewardsDuration
    );
    uint256 cutoffEpoch = epochStart.sub(lockDuration);

    //traverse inversely to make more current queries more gas efficient
    for (uint256 i = _epoch; i + 1 != 0; i--) {
        Epoch storage e = epochs[i];
        if (uint256(e.date) <= cutoffEpoch) {
            break;
        }
        supply = supply.add(epochs[i].supply);
    }

    return supply;
}
for (uint256 i = locks.length; i > 0; i--) {
    uint256 lockEpoch = uint256(locks[i - 1].unlockTime).sub(lockDuration);
    //lock epoch must be less or equal to the epoch we're basing from.
    if (lockEpoch <= epochTime) {
        if (lockEpoch > cutoffEpoch) {
            amount = amount.add(locks[i - 1].amount);
for (uint256 i = locks.length; i > 0; i--) {
    uint256 lockEpoch = uint256(locks[i - 1].unlockTime).sub(lockDuration);

    //return the next epoch balance
    if (lockEpoch == nextEpoch) {
        return locks[i - 1].amount;
    } else if (lockEpoch < nextEpoch) {
        //no need to check anymore
        break;
    }
for (uint256 i = epochindex; i > 0; i--) {
    Epoch storage e = epochs[i - 1];
for (uint256 i = _epoch + 1; i > 0; i--) {
    Epoch storage e = epochs[i - 1];
    if (uint256(e.date) <= cutoffEpoch) {
        break;
    }
    supply = supply.add(e.supply);
}
