HODL Hotel Token Logo

HODL [HODL Hotel] Token

About HODL

Listings

Not Found
Token 20 months

Website

Not Found

Description

Not Found

Social

Not Found

Laser Scorebeta Last Audit: 10 August 2022

report
Token seems to be anonymous. As long as we are unable to find website score is limited.

HODLHotel.sendBNBToFee(uint256) (#809-811) sends eth to arbitrary user
Dangerous calls:
- _treasuryWallet.transfer(amount) (#810)
Ensure that an arbitrary user cannot withdraw unauthorized funds.

Additional information: link

Reentrancy in HODLHotel._transfer(address,address,uint256) (#702-748):
External calls:
- swapBack() (#743)
- uniswapV2Router.addLiquidityETH{value: ethAmount}(address(this),tokenAmount,0,0,_liquidityWallet,block.timestamp) (#799-806)
- uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(tokenAmount,0,path,address(this),block.timestamp) (#788-794)
- (success,None) = address(_treasuryWallet).call{value: address(this).balance}() (#780)
External calls sending eth:
- swapBack() (#743)
- uniswapV2Router.addLiquidityETH{value: ethAmount}(address(this),tokenAmount,0,0,_liquidityWallet,block.timestamp) (#799-806)
- (success,None) = address(_treasuryWallet).call{value: address(this).balance}() (#780)
State variables written after the call(s):
- _tokenTransfer(from,to,amount,takeFee,shouldSwap) (#747)
- _rOwned[sender] = _rOwned[sender].sub(tAmount) (#949)
- _rOwned[recipient] = _rOwned[recipient].add(tAmount) (#950)
- swapping = false (#744)
- _tokenTransfer(from,to,amount,takeFee,shouldSwap) (#747)
- tokensForLiquidity += fees * liqFee / _totalFees (#974)
- _tokenTransfer(from,to,amount,takeFee,shouldSwap) (#747)
- tokensForTreasury += fees * trsryFee / _totalFees (#975)
Reentrancy in HODLHotel.launch() (#813-828):
External calls:
- uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory()).createPair(address(this),_uniswapV2Router.WETH()) (#818)
- uniswapV2Router.addLiquidityETH{value: address(this).balance}(address(this),balanceOf(address(this)),0,0,owner(),block.timestamp) (#819)
External calls sending eth:
- uniswapV2Router.addLiquidityETH{value: address(this).balance}(address(this),balanceOf(address(this)),0,0,owner(),block.timestamp) (#819)
State variables written after the call(s):
- launched = true (#826)
Apply the check-effects-interactions pattern.

Additional information: link

HODLHotel.withdrawStuckTokens(address) (#1009-1013) ignores return value by IERC20(tkn).transfer(msg.sender,amount) (#1012)
Use SafeERC20, or ensure that the transfer/transferFrom return value is checked.

Additional information: link


Unable to find manual contract audit (e.g. Certik, PeckShield, Solidity...)


Combination 1: Reentrancy vulnerabilities + Functions that send Ether to arbitraty destination. Usual for scams. May be justified by some complex mechanics (e.g. rebase, reflections). DYOR & manual audit are advised.


Combination 2: Unchecked transfer + Functions that send Ether to arbitraty destination. Usual for scams. May be justified by some complex mechanics (e.g. rebase, reflections). DYOR & manual audit are advised.


Combination 3: Reentrancy vulnerabilities + Unchecked transfer vulnerability. Usual for scams. May be justified by some complex mechanics (e.g. rebase, reflections). DYOR & manual audit are advised.


Contract ownership is not renounced (belongs to a wallet)

HODLHotel._takeFees(address,uint256,bool) (#954-982) performs a multiplication on the result of a division:
-fees = amount.mul(_totalFees).div(feeDivisor) (#973)
-tokensForLiquidity += fees * liqFee / _totalFees (#974)
HODLHotel._takeFees(address,uint256,bool) (#954-982) performs a multiplication on the result of a division:
-fees = amount.mul(_totalFees).div(feeDivisor) (#973)
-tokensForTreasury += fees * trsryFee / _totalFees (#975)
Consider ordering multiplication before division.

Additional information: link

Reentrancy in HODLHotel.swapBack() (#750-781):
External calls:
- swapTokensForBNB(amountToSwapForBNB) (#766)
- uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(tokenAmount,0,path,address(this),block.timestamp) (#788-794)
State variables written after the call(s):
- tokensForLiquidity = 0 (#772)
- tokensForTreasury = 0 (#773)
Apply the check-effects-interactions pattern.

Additional information: link

HODLHotel._transfer(address,address,uint256) (#702-748) uses tx.origin for authorization: require(bool,string)(cooldown[tx.origin] < block.number - cooldownBlocks && cooldown[to] < block.number - cooldownBlocks,Transfer delay enabled. Try again later.) (#717)
Do not use tx.origin for authorization.

Additional information: link

HODLHotel.addLiquidity(uint256,uint256) (#797-807) ignores return value by uniswapV2Router.addLiquidityETH{value: ethAmount}(address(this),tokenAmount,0,0,_liquidityWallet,block.timestamp) (#799-806)
HODLHotel.launch() (#813-828) ignores return value by uniswapV2Router.addLiquidityETH{value: address(this).balance}(address(this),balanceOf(address(this)),0,0,owner(),block.timestamp) (#819)
HODLHotel.launch() (#813-828) ignores return value by IERC20(uniswapV2Pair).approve(address(uniswapV2Router),type()(uint256).max) (#827)
Ensure that all the return values of the function calls are used.

Additional information: link

HODLHotel.allowance(address,address).owner (#672) shadows:
- Ownable.owner() (#68-70) (function)
HODLHotel._approve(address,address,uint256).owner (#695) shadows:
- Ownable.owner() (#68-70) (function)
Rename the local variables that shadow another component.

Additional information: link

HODLHotel.setMaxBuyAmount(uint256) (#836-839) should emit an event for:
- _maxBuyAmount = maxBuy (#838)
HODLHotel.setMaxSellAmount(uint256) (#841-844) should emit an event for:
- _maxSellAmount = maxSell (#843)
HODLHotel.setMaxWalletAmount(uint256) (#846-849) should emit an event for:
- _maxWalletAmount = maxToken (#848)
HODLHotel.setSwapTokensAtAmount(uint256) (#851-855) should emit an event for:
- swapTokensAtAmount = newAmount (#854)
HODLHotel.setBuyFee(uint256,uint256) (#893-897) should emit an event for:
- _buyLiquidityFee = buyLiquidityFee (#895)
- _buyTreasuryFee = buyTreasuryFee (#896)
HODLHotel.setSellFee(uint256,uint256) (#899-903) should emit an event for:
- _sellLiquidityFee = sellLiquidityFee (#901)
- _sellTreasuryFee = sellTreasuryFee (#902)
HODLHotel.setBlocksToBlacklist(uint256) (#905-907) should emit an event for:
- blocksToBlacklist = blocks (#906)
HODLHotel.setCooldownBlocks(uint256) (#909-911) should emit an event for:
- cooldownBlocks = blocks (#910)
Emit an event for critical parameter changes.

Additional information: link

HODLHotel.constructor(address,address).liquidityWallet (#630) lacks a zero-check on :
- _liquidityWallet = address(liquidityWallet) (#631)
HODLHotel.constructor(address,address).treasuryWallet (#630) lacks a zero-check on :
- _treasuryWallet = address(treasuryWallet) (#632)
Check that the address is not zero.

Additional information: link

Reentrancy in HODLHotel._transfer(address,address,uint256) (#702-748):
External calls:
- swapBack() (#743)
- uniswapV2Router.addLiquidityETH{value: ethAmount}(address(this),tokenAmount,0,0,_liquidityWallet,block.timestamp) (#799-806)
- uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(tokenAmount,0,path,address(this),block.timestamp) (#788-794)
- (success,None) = address(_treasuryWallet).call{value: address(this).balance}() (#780)
External calls sending eth:
- swapBack() (#743)
- uniswapV2Router.addLiquidityETH{value: ethAmount}(address(this),tokenAmount,0,0,_liquidityWallet,block.timestamp) (#799-806)
- (success,None) = address(_treasuryWallet).call{value: address(this).balance}() (#780)
State variables written after the call(s):
- _tokenTransfer(from,to,amount,takeFee,shouldSwap) (#747)
- _buyLiquidityFee = _previousBuyLiquidityFee (#928)
- _buyLiquidityFee = 0 (#921)
- _tokenTransfer(from,to,amount,takeFee,shouldSwap) (#747)
- _buyTreasuryFee = _previousBuyTreasuryFee (#929)
- _buyTreasuryFee = 0 (#922)
- _tokenTransfer(from,to,amount,takeFee,shouldSwap) (#747)
- _previousBuyLiquidityFee = _buyLiquidityFee (#916)
- _tokenTransfer(from,to,amount,takeFee,shouldSwap) (#747)
- _previousBuyTreasuryFee = _buyTreasuryFee (#917)
- _tokenTransfer(from,to,amount,takeFee,shouldSwap) (#747)
- _previousSellLiquidityFee = _sellLiquidityFee (#918)
- _tokenTransfer(from,to,amount,takeFee,shouldSwap) (#747)
- _previousSellTreasuryFee = _sellTreasuryFee (#919)
- _tokenTransfer(from,to,amount,takeFee,shouldSwap) (#747)
- _sellLiquidityFee = _previousSellLiquidityFee (#930)
- _sellLiquidityFee = 0 (#923)
- _tokenTransfer(from,to,amount,takeFee,shouldSwap) (#747)
- _sellTreasuryFee = _previousSellTreasuryFee (#931)
- _sellTreasuryFee = 0 (#924)
Reentrancy in HODLHotel.launch() (#813-828):
External calls:
- uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory()).createPair(address(this),_uniswapV2Router.WETH()) (#818)
- uniswapV2Router.addLiquidityETH{value: address(this).balance}(address(this),balanceOf(address(this)),0,0,owner(),block.timestamp) (#819)
External calls sending eth:
- uniswapV2Router.addLiquidityETH{value: address(this).balance}(address(this),balanceOf(address(this)),0,0,owner(),block.timestamp) (#819)
State variables written after the call(s):
- _maxBuyAmount = 1e7 * (10 ** _decimals) (#822)
- _maxSellAmount = 1e7 * (10 ** _decimals) (#823)
- _maxWalletAmount = 2e8 * (10 ** _decimals) (#824)
- cooldownEnabled = true (#821)
- swapEnabled = true (#820)
- swapTokensAtAmount = 5e5 * (10 ** _decimals) (#825)
Reentrancy in HODLHotel.swapBack() (#750-781):
External calls:
- swapTokensForBNB(amountToSwapForBNB) (#766)
- uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(tokenAmount,0,path,address(this),block.timestamp) (#788-794)
- addLiquidity(liquidityTokens,ethForLiquidity) (#776)
- uniswapV2Router.addLiquidityETH{value: ethAmount}(address(this),tokenAmount,0,0,_liquidityWallet,block.timestamp) (#799-806)
External calls sending eth:
- addLiquidity(liquidityTokens,ethForLiquidity) (#776)
- uniswapV2Router.addLiquidityETH{value: ethAmount}(address(this),tokenAmount,0,0,_liquidityWallet,block.timestamp) (#799-806)
State variables written after the call(s):
- addLiquidity(liquidityTokens,ethForLiquidity) (#776)
- _allowances[owner][spender] = amount (#698)
Reentrancy in HODLHotel.transferFrom(address,address,uint256) (#681-685):
External calls:
- _transfer(sender,recipient,amount) (#682)
- uniswapV2Router.addLiquidityETH{value: ethAmount}(address(this),tokenAmount,0,0,_liquidityWallet,block.timestamp) (#799-806)
- uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(tokenAmount,0,path,address(this),block.timestamp) (#788-794)
- (success,None) = address(_treasuryWallet).call{value: address(this).balance}() (#780)
External calls sending eth:
- _transfer(sender,recipient,amount) (#682)
- uniswapV2Router.addLiquidityETH{value: ethAmount}(address(this),tokenAmount,0,0,_liquidityWallet,block.timestamp) (#799-806)
- (success,None) = address(_treasuryWallet).call{value: address(this).balance}() (#780)
State variables written after the call(s):
- _approve(sender,_msgSender(),_allowances[sender][_msgSender()].sub(amount,ERC20: transfer amount exceeds allowance)) (#683)
- _allowances[owner][spender] = amount (#698)
Apply the check-effects-interactions pattern.

Additional information: link

Reentrancy in HODLHotel._transfer(address,address,uint256) (#702-748):
External calls:
- swapBack() (#743)
- uniswapV2Router.addLiquidityETH{value: ethAmount}(address(this),tokenAmount,0,0,_liquidityWallet,block.timestamp) (#799-806)
- uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(tokenAmount,0,path,address(this),block.timestamp) (#788-794)
- (success,None) = address(_treasuryWallet).call{value: address(this).balance}() (#780)
External calls sending eth:
- swapBack() (#743)
- uniswapV2Router.addLiquidityETH{value: ethAmount}(address(this),tokenAmount,0,0,_liquidityWallet,block.timestamp) (#799-806)
- (success,None) = address(_treasuryWallet).call{value: address(this).balance}() (#780)
Event emitted after the call(s):
- Transfer(sender,recipient,tAmount) (#951)
- _tokenTransfer(from,to,amount,takeFee,shouldSwap) (#747)
Reentrancy in HODLHotel.swapBack() (#750-781):
External calls:
- swapTokensForBNB(amountToSwapForBNB) (#766)
- uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(tokenAmount,0,path,address(this),block.timestamp) (#788-794)
- addLiquidity(liquidityTokens,ethForLiquidity) (#776)
- uniswapV2Router.addLiquidityETH{value: ethAmount}(address(this),tokenAmount,0,0,_liquidityWallet,block.timestamp) (#799-806)
External calls sending eth:
- addLiquidity(liquidityTokens,ethForLiquidity) (#776)
- uniswapV2Router.addLiquidityETH{value: ethAmount}(address(this),tokenAmount,0,0,_liquidityWallet,block.timestamp) (#799-806)
Event emitted after the call(s):
- Approval(owner,spender,amount) (#699)
- addLiquidity(liquidityTokens,ethForLiquidity) (#776)
- SwapAndLiquify(amountToSwapForBNB,ethForLiquidity,tokensForLiquidity) (#777)
Reentrancy in HODLHotel.transferFrom(address,address,uint256) (#681-685):
External calls:
- _transfer(sender,recipient,amount) (#682)
- uniswapV2Router.addLiquidityETH{value: ethAmount}(address(this),tokenAmount,0,0,_liquidityWallet,block.timestamp) (#799-806)
- uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(tokenAmount,0,path,address(this),block.timestamp) (#788-794)
- (success,None) = address(_treasuryWallet).call{value: address(this).balance}() (#780)
External calls sending eth:
- _transfer(sender,recipient,amount) (#682)
- uniswapV2Router.addLiquidityETH{value: ethAmount}(address(this),tokenAmount,0,0,_liquidityWallet,block.timestamp) (#799-806)
- (success,None) = address(_treasuryWallet).call{value: address(this).balance}() (#780)
Event emitted after the call(s):
- Approval(owner,spender,amount) (#699)
- _approve(sender,_msgSender(),_allowances[sender][_msgSender()].sub(amount,ERC20: transfer amount exceeds allowance)) (#683)
Apply the check-effects-interactions pattern.

Additional information: link

Different versions of Solidity is used:
- Version used: ['>=0.5.0', '>=0.6.2', '^0.8.0', '^0.8.15']
- ^0.8.15 (#3)
- ^0.8.0 (#7)
- ^0.8.0 (#31)
- ^0.8.0 (#112)
- ^0.8.0 (#194)
- >=0.5.0 (#419)
- >=0.6.2 (#437)
- >=0.6.2 (#533)
Use one Solidity version.

Additional information: link

Context._msgData() (#24-26) is never used and should be removed
SafeMath.div(uint256,uint256,string) (#381-390) is never used and should be removed
SafeMath.mod(uint256,uint256) (#341-343) is never used and should be removed
SafeMath.mod(uint256,uint256,string) (#407-416) is never used and should be removed
SafeMath.tryAdd(uint256,uint256) (#212-218) is never used and should be removed
SafeMath.tryDiv(uint256,uint256) (#254-259) is never used and should be removed
SafeMath.tryMod(uint256,uint256) (#266-271) is never used and should be removed
SafeMath.tryMul(uint256,uint256) (#237-247) is never used and should be removed
SafeMath.trySub(uint256,uint256) (#225-230) is never used and should be removed
Remove unused functions.

Additional information: link

HODLHotel._previousBuyLiquidityFee (#611) is set pre-construction with a non-constant function or state variable:
- _buyLiquidityFee
HODLHotel._previousBuyTreasuryFee (#613) is set pre-construction with a non-constant function or state variable:
- _buyTreasuryFee
HODLHotel._previousSellLiquidityFee (#615) is set pre-construction with a non-constant function or state variable:
- _sellLiquidityFee
HODLHotel._previousSellTreasuryFee (#617) is set pre-construction with a non-constant function or state variable:
- _sellTreasuryFee
Remove any initialization of state variables via non-constant state variables or function calls. If variables must be set upon contract deployment, locate initialization in the constructor instead.

Additional information: link

Pragma version^0.8.15 (#3) necessitates a version too recent to be trusted. Consider deploying with 0.6.12/0.7.6/0.8.7
Pragma version^0.8.0 (#7) allows old versions
Pragma version^0.8.0 (#31) allows old versions
Pragma version^0.8.0 (#112) allows old versions
Pragma version^0.8.0 (#194) allows old versions
Pragma version>=0.5.0 (#419) allows old versions
Pragma version>=0.6.2 (#437) allows old versions
Pragma version>=0.6.2 (#533) allows old versions
solc-0.8.15 is not recommended for deployment
Deploy with any of the following Solidity versions: 0.5.16 - 0.5.17, 0.6.11 - 0.6.12, 0.7.5 - 0.7.6 Use a simple pragma version that allows any of these versions. Consider using the latest version of Solidity for testing.

Additional information: link

Low level call in HODLHotel.swapBack() (#750-781):
- (success,None) = address(_treasuryWallet).call{value: address(this).balance}() (#780)
Low level call in HODLHotel.withdrawStuckBNB() (#1004-1007):
- (success,None) = address(msg.sender).call{value: address(this).balance}() (#1006)
Avoid low-level calls. Check the call success. If the call is meant for a contract, check for code existence

Additional information: link

Function IUniswapV2Router01.WETH() (#441) is not in mixedCase
Constant HODLHotel._name (#597) is not in UPPER_CASE_WITH_UNDERSCORES
Constant HODLHotel._symbol (#598) is not in UPPER_CASE_WITH_UNDERSCORES
Constant HODLHotel._decimals (#600) is not in UPPER_CASE_WITH_UNDERSCORES
Constant HODLHotel._tTotal (#602) is not in UPPER_CASE_WITH_UNDERSCORES
Variable HODLHotel._maxBuyAmount (#603) is not in mixedCase
Variable HODLHotel._maxSellAmount (#604) is not in mixedCase
Variable HODLHotel._maxWalletAmount (#605) is not in mixedCase
Constant HODLHotel.feeDivisor (#609) is not in UPPER_CASE_WITH_UNDERSCORES
Variable HODLHotel.DEAD (#625) is not in mixedCase
Variable HODLHotel.ZERO (#626) is not in mixedCase
Follow the Solidity naming convention.

Additional information: link

Variable IUniswapV2Router01.addLiquidity(address,address,uint256,uint256,uint256,uint256,address,uint256).amountADesired (#446) is too similar to IUniswapV2Router01.addLiquidity(address,address,uint256,uint256,uint256,uint256,address,uint256).amountBDesired (#447)
Prevent variables from having similar names.

Additional information: link

HODLHotel.slitherConstructorVariables() (#576-1023) uses literals with too many digits:
- DEAD = 0x000000000000000000000000000000000000dEaD (#625)
HODLHotel.slitherConstructorVariables() (#576-1023) uses literals with too many digits:
- ZERO = 0x0000000000000000000000000000000000000000 (#626)
Use: Ether suffix, Time suffix, or The scientific notation

Additional information: link

HODLHotel.DEAD (#625) should be constant
HODLHotel.ZERO (#626) should be constant
Add the constant attributes to state variables that never change.

Additional information: link

renounceOwnership() should be declared external:
- Ownable.renounceOwnership() (#86-88)
transferOwnership(address) should be declared external:
- Ownable.transferOwnership(address) (#94-97)
name() should be declared external:
- HODLHotel.name() (#647-649)
symbol() should be declared external:
- HODLHotel.symbol() (#651-653)
decimals() should be declared external:
- HODLHotel.decimals() (#655-657)
totalSupply() should be declared external:
- HODLHotel.totalSupply() (#659-661)
transfer(address,uint256) should be declared external:
- HODLHotel.transfer(address,uint256) (#667-670)
allowance(address,address) should be declared external:
- HODLHotel.allowance(address,address) (#672-674)
approve(address,uint256) should be declared external:
- HODLHotel.approve(address,uint256) (#676-679)
transferFrom(address,address,uint256) should be declared external:
- HODLHotel.transferFrom(address,address,uint256) (#681-685)
setCooldownEnabled(bool) should be declared external:
- HODLHotel.setCooldownEnabled(bool) (#687-689)
setSwapEnabled(bool) should be declared external:
- HODLHotel.setSwapEnabled(bool) (#691-693)
launch() should be declared external:
- HODLHotel.launch() (#813-828)
openTrading() should be declared external:
- HODLHotel.openTrading() (#830-834)
setMaxBuyAmount(uint256) should be declared external:
- HODLHotel.setMaxBuyAmount(uint256) (#836-839)
setMaxSellAmount(uint256) should be declared external:
- HODLHotel.setMaxSellAmount(uint256) (#841-844)
setMaxWalletAmount(uint256) should be declared external:
- HODLHotel.setMaxWalletAmount(uint256) (#846-849)
setSwapTokensAtAmount(uint256) should be declared external:
- HODLHotel.setSwapTokensAtAmount(uint256) (#851-855)
setLiquidityWallet(address) should be declared external:
- HODLHotel.setLiquidityWallet(address) (#857-864)
setTreasuryWallet(address) should be declared external:
- HODLHotel.setTreasuryWallet(address) (#866-873)
setExcludedFromFees(address[],bool) should be declared external:
- HODLHotel.setExcludedFromFees(address[],bool) (#875-879)
setExcludeFromMaxTransaction(address[],bool) should be declared external:
- HODLHotel.setExcludeFromMaxTransaction(address[],bool) (#881-885)
setBots(address[],bool) should be declared external:
- HODLHotel.setBots(address[],bool) (#887-891)
setBuyFee(uint256,uint256) should be declared external:
- HODLHotel.setBuyFee(uint256,uint256) (#893-897)
setSellFee(uint256,uint256) should be declared external:
- HODLHotel.setSellFee(uint256,uint256) (#899-903)
setBlocksToBlacklist(uint256) should be declared external:
- HODLHotel.setBlocksToBlacklist(uint256) (#905-907)
setCooldownBlocks(uint256) should be declared external:
- HODLHotel.setCooldownBlocks(uint256) (#909-911)
unclog() should be declared external:
- HODLHotel.unclog() (#994-997)
distributeFees() should be declared external:
- HODLHotel.distributeFees() (#999-1002)
withdrawStuckBNB() should be declared external:
- HODLHotel.withdrawStuckBNB() (#1004-1007)
withdrawStuckTokens(address) should be declared external:
- HODLHotel.withdrawStuckTokens(address) (#1009-1013)
removeLimits() should be declared external:
- HODLHotel.removeLimits() (#1015-1020)
Use the external attribute for functions never called from the contract.

Additional information: link

Holders:

Contract has 12% buy tax and 20% sell tax.
Taxes are suspiciously high (over 10%) and contract ownership is not renounced. Token has a high risk of becoming a honeypot.


Token is deployed only at one blockchain


Token has only one trading pair


Unable to find Telegram and Twitter accounts


Unable to find website, listings and other project-related information


Young tokens have high risks of scam / price dump / death


Token has no active CoinGecko listing / rank


Token has no active CoinMarketCap listing / rank

Price for HODL