// Solidity 0.7.4
/**
 * @dev this function allows a user to add a liquidity Staking
 * position.  The user will need to choose one of the three
 * configured lock Periods. Users may add to the position 
 * only once per lock period.
 */
function addPosition(uint256 _lpTokenAmount, uint256 _lockPeriod, uint256 _pid) public addPositionNotDisabled unpaused{
        LiquidityProviders storage p = provider[_pid][msg.sender];
        PoolInfo storage pool = poolInfo[_pid];
        address ca = address(this);
        require(p.LockedAmount == 0, "LiquidityMining: This account already has a position");
        if(_lockPeriod == lockPeriod0) {
            pool.ContractAddress.safeTransferFrom(msg.sender, ca, _lpTokenAmount);
            uint _preYield = _lpTokenAmount.mul(lockPeriod0BasisPoint.add(pool.PoolBonus)).div(lockPeriodBPScale).mul(_lockPeriod);
            provider[_pid][msg.sender] = LiquidityProviders (
                msg.sender, 
                block.number.add(periodCalc.mul(lockPeriod0)), 
                _lpTokenAmount, 
                lockPeriod0, 
                lockPeriod0BasisPoint,
                p.TotalRewardsPaid.add(_preYield.div(preYieldDivisor))
            );
            fundamenta.mintTo(msg.sender, _preYield.div(preYieldDivisor));
            pool.TotalLPTokensLocked = pool.TotalLPTokensLocked.add(_lpTokenAmount);
            pool.TotalRewardsPaidByPool = pool.TotalRewardsPaidByPool.add(_preYield.div(preYieldDivisor));
        } else if (_lockPeriod == lockPeriod1) {
            pool.ContractAddress.safeTransferFrom(msg.sender, ca, _lpTokenAmount);
            uint _preYield = _lpTokenAmount.mul(lockPeriod1BasisPoint.add(pool.PoolBonus)).div(lockPeriodBPScale).mul(_lockPeriod);
            provider[_pid][msg.sender] = LiquidityProviders (
                msg.sender, 
                block.number.add(periodCalc.mul(lockPeriod1)), 
                _lpTokenAmount, 
                lockPeriod1, 
                lockPeriod1BasisPoint,
                p.TotalRewardsPaid.add(_preYield.div(preYieldDivisor))
            );
            fundamenta.mintTo(msg.sender, _preYield.div(preYieldDivisor));
            pool.TotalLPTokensLocked = pool.TotalLPTokensLocked.add(_lpTokenAmount);
            pool.TotalRewardsPaidByPool = pool.TotalRewardsPaidByPool.add(_preYield.div(preYieldDivisor));
        } else if (_lockPeriod == lockPeriod2) {
            pool.ContractAddress.safeTransferFrom(msg.sender, ca, _lpTokenAmount);
            uint _preYield = _lpTokenAmount.mul(lockPeriod2BasisPoint.add(pool.PoolBonus)).div(lockPeriodBPScale).mul(_lockPeriod);
            provider[_pid][msg.sender] = LiquidityProviders (
                msg.sender, 
                block.number.add(periodCalc.mul(lockPeriod2)), 
                _lpTokenAmount, 
                lockPeriod2, 
                lockPeriod2BasisPoint,
                p.TotalRewardsPaid.add(_preYield.div(preYieldDivisor))
            );
            fundamenta.mintTo(msg.sender, _preYield.div(preYieldDivisor));
            pool.TotalLPTokensLocked = pool.TotalLPTokensLocked.add(_lpTokenAmount);
            pool.TotalRewardsPaidByPool = pool.TotalRewardsPaidByPool.add(_preYield.div(preYieldDivisor));
        }else revert("LiquidityMining: Incompatible Lock Period");
    }