forge coverage does not work for specific contract

Component
Forge
Have you ensured that all of these are up to date?

[X] Foundry
[X] Foundryup

What version of Foundry are you on?
forge 0.2.0 (9e3ab9b 2024-01-04T00:18:01.892563000Z)
What command(s) is the bug in?
forge coverage
Operating System
macOS (Apple Silicon)
Describe the bug
Hi there, I've upgraded Uniswap V2 contracts to solidity v0.8.21 & I added unit tests for each contract such as Router, Pair, Factory etc. So, my issue is even my test suites totally covers the contracts that i mentioned, Router contract's coverage does not increment. I tried to remove override tags, IRouter interface inheritance, and converted internal functions to public functions. Consequently, I did not get any solution by doing these methods.

Here's the Router.t.sol;
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.21;

import { Test } from "forge-std/Test.sol";
import "forge-std/console.sol";

import { WETH } from "vectorized/solady/tokens/WETH.sol";
import "openzeppelin-contracts/contracts/utils/math/Math.sol";

import { Pair } from "../../src/core/Pair.sol";
import { Router } from "../../src/helpers/Router.sol";
import { PairFactory } from "../../src/core/PairFactory.sol";
import { RouterLib } from "../../src/libraries/RouterLib.sol";

import { MockERC20 } from "../mocks/MockERC20.sol";

contract RouterTest is Test {
    uint256 public constant TOKEN_A_TOTAL_SUPPLY = 115_792_089_237_316_195_423_570_985e18;
    uint256 public constant TOKEN_B_TOTAL_SUPPLY = 115_792_089_237_316_195_423_570_985e18;
    bytes32 constant PERMIT_TYPEHASH =
        keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

    address public feeTo;
    address public sender;
    uint256 public deadline;
    address public feeToSetter;

    Pair pair;
    WETH weth;
    Router router;
    MockERC20 tokenA;
    MockERC20 tokenB;
    PairFactory pairFactory;

    //Ordered pair adress
    MockERC20 public token0;
    MockERC20 public token1;

    receive() external payable { }

    constructor() { }

    function setUp() public {
        sender = vm.addr(1);
        feeTo = makeAddr("feeTo");
        deadline = block.timestamp + 1;
        feeToSetter = makeAddr("feeToSetter");

        tokenA = new MockERC20("tokenA", "TA");
        tokenB = new MockERC20("tokenB", "TB");
        weth = new WETH();

        weth.deposit{ value: 20e18 }();

        pairFactory = new PairFactory(feeToSetter);
        router = new Router(address(pairFactory), address(weth));

        address createdPairAddress = pairFactory.createPair(address(tokenA), address(tokenB));
        pair = Pair(createdPairAddress);

        (address _token0, address _token1) = RouterLib.sortTokens(address(tokenA), address(tokenB));
        token0 = MockERC20(_token0);
        token1 = MockERC20(_token1);

        assertEq(pair.token0(), _token0);
        assertEq(pair.token1(), _token1);
        assertEq(pairFactory.getPair(_token0, _token1), createdPairAddress);
    }

    function test_ShouldBeSuccess_initialize() public {
        pairFactory = new PairFactory(feeToSetter);
        router = new Router(address(pairFactory), address(weth));

        assertEq(router.factory(), address(pairFactory));
        assertEq(router.WETH(), address(weth));
    }

    function test_ShouldBeSuccess_createsPair_addLiquidity() public {
        MockERC20 tokenC = new MockERC20("tokenC", "TC");
        MockERC20 tokenD = new MockERC20("tokenD", "TD");

        uint256 token0approveAmount = 1e18;
        uint256 token1approveAmount = 1e18;

        tokenC.approve(address(router), token0approveAmount);
        tokenD.approve(address(router), token1approveAmount);

        (uint256 amountA, uint256 amountB, uint256 liquidity) = router.addLiquidity(
            address(tokenC),
            address(tokenD),
            token0approveAmount,
            token1approveAmount,
            token0approveAmount,
            token1approveAmount,
            address(this),
            deadline
        );

        address pairAddress = pairFactory.getPair(address(tokenC), address(tokenD));
        address createdPairAddress = RouterLib.pairFor(address(pairFactory), address(tokenC), address(tokenD));

        assertEq(pairAddress, createdPairAddress);
        assertEq(tokenC.balanceOf(address(pairAddress)), amountA);
        assertEq(tokenD.balanceOf(address(pairAddress)), amountB);
        assertEq(Pair(pairAddress).balanceOf(address(this)), liquidity);
        assertEq(Pair(pairAddress).balanceOf(address(0)), Pair(pairAddress).MINIMUM_LIQUIDITY());
        assertEq(Pair(pairAddress).totalSupply(), liquidity + Pair(pairAddress).MINIMUM_LIQUIDITY());
    }

    function test_ShouldBeSuccess_amountBOptimalIsOk_addLiquidity() public {
        uint256 token0transferAmount = 1e18;
        uint256 token1transferAmount = 1e18;
        (,, uint256 firstLiquidity) = _addLiquidity(token0transferAmount, token1transferAmount);

        uint256 token0approveAmount = 1e18;
        uint256 token1approveAmount = 2e18;

        token0.approve(address(router), token0approveAmount);
        token1.approve(address(router), token1approveAmount);

        (uint256 amountA, uint256 amountB, uint256 secondLiquidity) = router.addLiquidity(
            address(token0),
            address(token1),
            token0approveAmount,
            token1approveAmount,
            1e18,
            1e17,
            address(this),
            deadline
        );

        (uint112 _reserve0, uint112 _reserve1,) = pair.getReserves();
        uint256 amountBOptimal = RouterLib.quote(token0approveAmount, _reserve0, _reserve1);

        assertEq(amountA, token0approveAmount);
        assertEq(amountB, amountBOptimal);
        assertEq(pair.balanceOf(address(this)), firstLiquidity + secondLiquidity);
    }

    function test_ShouldBeSuccess_amountBOptimalIsTooHigh_addLiquidity() public {
        uint256 token0transferAmount = 10e18;
        uint256 token1transferAmount = 5e18;
        (,, uint256 firstLiquidity) = _addLiquidity(token0transferAmount, token1transferAmount);

        uint256 token0approveAmount = 2e18;
        uint256 token1approveAmount = 1e18;

        token0.approve(address(router), token0approveAmount);
        token1.approve(address(router), token1approveAmount);

        (uint112 _reserve0, uint112 _reserve1,) = pair.getReserves();
        uint256 amountBOptimal = RouterLib.quote(token0approveAmount, _reserve0, _reserve1);

        uint256 nonOptimal = amountBOptimal - 1e17;

        uint256 amountAOptimal = RouterLib.quote(nonOptimal, _reserve1, _reserve0);

        (uint256 amountA, uint256 amountB, uint256 secondLiquidity) = router.addLiquidity(
            address(token0),
            address(token1),
            token0approveAmount,
            nonOptimal,
            amountAOptimal,
            token1approveAmount,
            address(this),
            deadline
        );

        assertEq(amountA, amountAOptimal);
        assertEq(amountB, nonOptimal);
        assertEq(pair.balanceOf(address(this)), firstLiquidity + secondLiquidity);
    }

    function test_ShouldBeSuccess_noPair_addLiquidityETH() public {
        uint256 token0approveAmount = 1e18;
        uint256 WETHapproveAmount = 2e18;

        token0.approve(address(router), token0approveAmount);
        weth.approve(address(router), WETHapproveAmount);

        (uint256 amountA, uint256 amountB, uint256 secondLiquidity) = router.addLiquidityETH{ value: 2e18 }(
            address(token0), token0approveAmount, 1e18, 1e17, address(this), deadline
        );

        address pairAddress = pairFactory.getPair(address(token0), address(weth));

        (uint112 _reserve0, uint112 _reserve1,) = Pair(pairAddress).getReserves();
        uint256 amountBOptimal = RouterLib.quote(token0approveAmount, _reserve0, _reserve1);

        assertEq(amountA, token0approveAmount);
        assertEq(amountB, amountBOptimal);
        assertEq(Pair(pairAddress).balanceOf(address(this)), secondLiquidity);
    }

    function test_ShouldBeSuccess_removeLiquidity() public {
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        (uint256 amountA, uint256 amountB, uint256 liquidity) =
            _addLiquidity(token0TransferAmount, token1TransferAmount);

        pair.approve(address(router), liquidity);

        (uint256 _amountA, uint256 _amountB) = router.removeLiquidity(
            address(token0),
            address(token1),
            liquidity,
            token0TransferAmount - pair.MINIMUM_LIQUIDITY(),
            token1TransferAmount - pair.MINIMUM_LIQUIDITY(),
            address(this),
            deadline
        );

        (uint256 reserve0, uint256 reserve1,) = pair.getReserves();
        assertEq(uint112(token0.balanceOf(address(pair))), reserve0);
        assertEq(uint112(token1.balanceOf(address(pair))), reserve1);

        assertEq(pair.balanceOf(address(this)), 0);
        assertEq(pair.totalSupply(), pair.MINIMUM_LIQUIDITY());
        assertEq(token0.balanceOf(address(this)), TOKEN_A_TOTAL_SUPPLY - amountA + _amountA);
        assertEq(token1.balanceOf(address(this)), TOKEN_B_TOTAL_SUPPLY - amountB + _amountB);
    }

    function test_ShouldBeSuccess_removeLiquidityETH() public {
        uint256 token0approveAmount = 1e18;
        uint256 WETHapproveAmount = 1e18;

        token0.approve(address(router), token0approveAmount);
        weth.approve(address(router), WETHapproveAmount);

        (uint256 amountA,, uint256 liquidity) = router.addLiquidityETH{ value: 1e18 }(
            address(token0), token0approveAmount, 1e18, 1e18, address(this), deadline
        );

        address pairAddress = pairFactory.getPair(address(token0), address(weth));

        Pair(pairAddress).approve(address(router), liquidity);

        (uint256 _amountA, uint256 _amountB) = router.removeLiquidity(
            address(token0),
            address(weth),
            liquidity,
            token0approveAmount - pair.MINIMUM_LIQUIDITY(),
            WETHapproveAmount - pair.MINIMUM_LIQUIDITY(),
            address(this),
            deadline
        );

        (uint256 reserve0, uint256 reserve1,) = Pair(pairAddress).getReserves();
        assertEq(uint112(token0.balanceOf(address(pairAddress))), reserve0);
        assertEq(uint112(weth.balanceOf(address(pairAddress))), reserve1);

        assertEq(Pair(pairAddress).balanceOf(address(this)), 0);
        assertEq(Pair(pairAddress).totalSupply(), pair.MINIMUM_LIQUIDITY());
        assertEq(token0.balanceOf(address(this)), TOKEN_A_TOTAL_SUPPLY - amountA + _amountA);
        assertEq(weth.balanceOf(address(this)), 20e18 + _amountB);
    }

    function test_ShouldBeSuccess_partially_removeLiquidity() public {
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        (uint256 amountA, uint256 amountB, uint256 liquidity) =
            _addLiquidity(token0TransferAmount, token1TransferAmount);

        uint256 calculateLiquidity = (liquidity * 3) / 10;
        pair.approve(address(router), calculateLiquidity);

        (uint256 _amountA, uint256 _amountB) = router.removeLiquidity(
            address(tokenA),
            address(tokenB),
            calculateLiquidity,
            0.3 ether - 3e16,
            0.3 ether - 3e16,
            address(this),
            deadline
        );

        (uint256 reserve0, uint256 reserve1,) = pair.getReserves();
        assertEq(uint112(token0.balanceOf(address(pair))), reserve0);
        assertEq(uint112(token1.balanceOf(address(pair))), reserve1);

        assertEq(pair.balanceOf(address(this)), liquidity - calculateLiquidity);
        assertEq(token0.balanceOf(address(this)), TOKEN_A_TOTAL_SUPPLY - amountA + _amountA);
        assertEq(token1.balanceOf(address(this)), TOKEN_B_TOTAL_SUPPLY - amountB + _amountB);
        assertEq(pair.totalSupply(), (liquidity + pair.MINIMUM_LIQUIDITY()) - calculateLiquidity);
    }

    function test_ShouldBeSuccess_removeLiquidityWithPermit() public {
        token0.transfer(sender, 5e18);
        token1.transfer(sender, 5e18);

        vm.startPrank(sender);

        token0.approve(address(router), 1e18);
        token1.approve(address(router), 1e18);

        (uint256 amountA, uint256 amountB, uint256 liquidity) =
            router.addLiquidity(address(token0), address(token1), 1e18, 1e18, 1e18, 1e18, sender, deadline);

        bytes32 permitMeesageHash =
            _getPermitHash(pair, sender, address(router), liquidity, pair.nonces(sender), deadline);

        (uint8 v, bytes32 r, bytes32 s) = vm.sign(1, permitMeesageHash);

        (uint256 _amountA, uint256 _amountB) = router.removeLiquidityWithPermit(
            address(token0),
            address(token1),
            liquidity,
            1e18 - pair.MINIMUM_LIQUIDITY(),
            1e18 - pair.MINIMUM_LIQUIDITY(),
            sender,
            deadline,
            false,
            v,
            r,
            s
        );

        (uint256 reserve0, uint256 reserve1,) = pair.getReserves();
        assertEq(uint112(token0.balanceOf(address(pair))), reserve0);
        assertEq(uint112(token1.balanceOf(address(pair))), reserve1);

        assertEq(pair.balanceOf(sender), 0);
        assertEq(pair.totalSupply(), pair.MINIMUM_LIQUIDITY());
        assertEq(token0.balanceOf(sender), 5e18 - amountA + _amountA);
        assertEq(token1.balanceOf(sender), 5e18 - amountB + _amountB);
    }

    function test_ShouldBeSuccess_removeLiquidityETHWithPermit() public {
        vm.deal(sender, 1e18);
        token0.transfer(sender, 5e18);
        weth.transfer(sender, 5e18);

        vm.startPrank(sender);

        token0.approve(address(router), 1e18);
        weth.approve(address(router), 1e18);

        (uint256 amountA,, uint256 liquidity) =
            router.addLiquidityETH{ value: 1e18 }(address(token0), 1e18, 1e18, 1e18, sender, deadline);

        address pairAddress = pairFactory.getPair(address(token0), address(weth));

        bytes32 permitMeesageHash = _getPermitHash(
            Pair(pairAddress), sender, address(router), liquidity, Pair(pairAddress).nonces(sender), deadline
        );

        (uint8 v, bytes32 r, bytes32 s) = vm.sign(1, permitMeesageHash);

        (uint256 _amountA,) = router.removeLiquidityETHWithPermit(
            address(token0),
            liquidity,
            1e18 - Pair(pairAddress).MINIMUM_LIQUIDITY(),
            1e18 - Pair(pairAddress).MINIMUM_LIQUIDITY(),
            sender,
            deadline,
            false,
            v,
            r,
            s
        );

        (uint256 reserve0, uint256 reserve1,) = Pair(pairAddress).getReserves();
        assertEq(uint112(token0.balanceOf(address(pairAddress))), reserve0);
        assertEq(uint112(weth.balanceOf(address(pairAddress))), reserve1);

        assertEq(Pair(pairAddress).balanceOf(sender), 0);
        assertEq(Pair(pairAddress).totalSupply(), pair.MINIMUM_LIQUIDITY());
        assertEq(token0.balanceOf(sender), 5e18 - amountA + _amountA);
        assertEq(weth.balanceOf(sender), 5e18);
    }

    function test_ShouldBeSuccess_removeLiquidityETHSupportingFeeOnTransferTokens() public {
        uint256 token0approveAmount = 1e18;
        uint256 WETHapproveAmount = 1e18;

        token0.approve(address(router), token0approveAmount);
        weth.approve(address(router), WETHapproveAmount);

        (,, uint256 liquidity) = router.addLiquidityETH{ value: 1e18 }(
            address(token0), token0approveAmount, 1e18, 1e18, address(this), deadline
        );

        address pairAddress = pairFactory.getPair(address(token0), address(weth));

        Pair(pairAddress).approve(address(router), liquidity);

        (uint256 _amountEth) = router.removeLiquidityETHSupportingFeeOnTransferTokens(
            address(token0),
            liquidity,
            token0approveAmount - pair.MINIMUM_LIQUIDITY(),
            WETHapproveAmount - pair.MINIMUM_LIQUIDITY(),
            address(this),
            deadline
        );

        (uint256 reserve0, uint256 reserve1,) = Pair(pairAddress).getReserves();
        assertEq(uint112(token0.balanceOf(address(pairAddress))), reserve0);
        assertEq(uint112(weth.balanceOf(address(pairAddress))), reserve1);

        assertEq(Pair(pairAddress).balanceOf(address(this)), 0);
        assertEq(Pair(pairAddress).totalSupply(), pair.MINIMUM_LIQUIDITY());
        assertEq(token0.balanceOf(address(this)), TOKEN_A_TOTAL_SUPPLY - 1e18 + _amountEth);
        assertEq(weth.balanceOf(address(this)), 20e18);
    }

    function test_ShouldBeSuccess_removeLiquidityETHWithPermitSupportingFeeOnTransferTokens() public {
        vm.deal(sender, 1e18);
        token0.transfer(sender, 5e18);
        weth.transfer(sender, 5e18);

        vm.startPrank(sender);

        token0.approve(address(router), 1e18);
        weth.approve(address(router), 1e18);

        (uint256 amountA,, uint256 liquidity) =
            router.addLiquidityETH{ value: 1e18 }(address(token0), 1e18, 1e18, 1e18, sender, deadline);

        address pairAddress = pairFactory.getPair(address(token0), address(weth));

        bytes32 permitMeesageHash = _getPermitHash(
            Pair(pairAddress), sender, address(router), liquidity, Pair(pairAddress).nonces(sender), deadline
        );

        (uint8 v, bytes32 r, bytes32 s) = vm.sign(1, permitMeesageHash);

        (uint256 _amountETH) = router.removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
            address(token0),
            liquidity,
            1e18 - Pair(pairAddress).MINIMUM_LIQUIDITY(),
            1e18 - Pair(pairAddress).MINIMUM_LIQUIDITY(),
            sender,
            deadline,
            false,
            v,
            r,
            s
        );

        (uint256 reserve0, uint256 reserve1,) = Pair(pairAddress).getReserves();
        assertEq(uint112(token0.balanceOf(address(pairAddress))), reserve0);
        assertEq(uint112(weth.balanceOf(address(pairAddress))), reserve1);

        assertEq(Pair(pairAddress).balanceOf(sender), 0);
        assertEq(Pair(pairAddress).totalSupply(), pair.MINIMUM_LIQUIDITY());
        assertEq(token0.balanceOf(sender), 5e18 - amountA + _amountETH);
        assertEq(weth.balanceOf(sender), 5e18);
    }

    function test_ShouldBeSuccess_swapExactTokensForTokens() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(token0);
        path[1] = address(token1);
        path[2] = address(weth);

        uint256 amount1Out = RouterLib.getAmountOut(3e17, 1e18, 1e18);
        uint256 amount2Out = RouterLib.getAmountOut(amount1Out, 1e18, 1e18);

        token0.approve(address(router), 3e17);
        router.swapExactTokensForTokens(3e17, 1e17, path, address(this), deadline);

        assertEq(token0.balanceOf(address(this)), TOKEN_A_TOTAL_SUPPLY - 1e18 - 3e17);
        assertEq(token1.balanceOf(address(this)), TOKEN_B_TOTAL_SUPPLY - 2e18);
        assertEq(weth.balanceOf(address(this)), 20e18 + amount2Out);
    }

    function test_ShouldBeSuccess_swapTokensForExactTokens() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(token0);
        path[1] = address(token1);
        path[2] = address(weth);

        uint256 amount1Out = RouterLib.getAmountOut(3e17, 1e18, 1e18);
        uint256 amount2Out = RouterLib.getAmountOut(amount1Out, 1e18, 1e18);

        token0.approve(address(router), 3e17);
        router.swapTokensForExactTokens(amount2Out, 3e17, path, address(this), deadline);

        assertEq(token0.balanceOf(address(this)), TOKEN_A_TOTAL_SUPPLY - 1e18 - 3e17);
        assertEq(token1.balanceOf(address(this)), TOKEN_B_TOTAL_SUPPLY - 2e18);
        assertEq(weth.balanceOf(address(this)), 20e18 + amount2Out);
    }

    function test_ShouldBeSuccess_swapExactETHForTokens() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(weth);
        path[1] = address(token1);
        path[2] = address(token0);

        uint256 amount1Out = RouterLib.getAmountOut(3e17, 1e18, 1e18);
        uint256 amount2Out = RouterLib.getAmountOut(amount1Out, 1e18, 1e18);

        weth.approve(address(router), 3e17);
        router.swapExactETHForTokens{ value: 3e17 }(1e17, path, address(this), deadline);

        assertEq(token0.balanceOf(address(this)), TOKEN_A_TOTAL_SUPPLY - 1e18 + amount2Out);
        assertEq(token1.balanceOf(address(this)), TOKEN_B_TOTAL_SUPPLY - 2e18);
        assertEq(weth.balanceOf(address(this)), 20e18);
    }

    function test_ShouldBeSuccess_swapTokensForExactETH() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(token0);
        path[1] = address(token1);
        path[2] = address(weth);

        uint256 amount1Out = RouterLib.getAmountOut(3e17, 1e18, 1e18);
        uint256 amount2Out = RouterLib.getAmountOut(amount1Out, 1e18, 1e18);

        token0.approve(address(router), 3e17);
        router.swapTokensForExactETH(amount2Out, 3e17, path, address(this), deadline);

        assertEq(token0.balanceOf(address(this)), TOKEN_A_TOTAL_SUPPLY - 1e18 - 3e17);
        assertEq(token1.balanceOf(address(this)), TOKEN_B_TOTAL_SUPPLY - 2e18);
        assertEq(weth.balanceOf(address(this)), 20e18);
    }

    function test_ShouldBeSuccess_swapExactTokensForETH() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(token0);
        path[1] = address(token1);
        path[2] = address(weth);

        token0.approve(address(router), 3e17);
        router.swapExactTokensForETH(3e17, 1e17, path, address(this), deadline);

        assertEq(token0.balanceOf(address(this)), TOKEN_A_TOTAL_SUPPLY - 1e18 - 3e17);
        assertEq(token1.balanceOf(address(this)), TOKEN_B_TOTAL_SUPPLY - 2e18);
        assertEq(weth.balanceOf(address(this)), 20e18);
    }

    function test_ShouldBeSuccess_swapETHForExactTokens() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(weth);
        path[1] = address(token1);
        path[2] = address(token0);

        uint256 amount1Out = RouterLib.getAmountOut(3e17, 1e18, 1e18);
        uint256 amount2Out = RouterLib.getAmountOut(amount1Out, 1e18, 1e18);

        weth.approve(address(router), 3e17);
        router.swapETHForExactTokens{ value: 3e17 }(amount2Out, path, address(this), deadline);

        assertEq(token0.balanceOf(address(this)), TOKEN_A_TOTAL_SUPPLY - 1e18 + amount2Out);
        assertEq(token1.balanceOf(address(this)), TOKEN_B_TOTAL_SUPPLY - 2e18);
        assertEq(weth.balanceOf(address(this)), 20e18);
    }

    function test_ShouldBeSuccess_swapExactTokensForTokensSupportingFeeOnTransferTokens() public {
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        address[] memory path = new address[](2);
        path[0] = address(token0);
        path[1] = address(token1);

        uint256 amount1Out = RouterLib.getAmountOut(3e17, 1e18, 1e18);

        token0.approve(address(router), 3e17);
        router.swapExactTokensForTokensSupportingFeeOnTransferTokens(3e17, amount1Out, path, address(this), deadline);

        assertEq(token0.balanceOf(address(this)), TOKEN_A_TOTAL_SUPPLY - 1e18 - 3e17);
        assertEq(token1.balanceOf(address(this)), TOKEN_B_TOTAL_SUPPLY - 1e18 + amount1Out);
    }

    function test_ShouldBeSuccess_swapExactETHForTokensSupportingFeeOnTransferTokens() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(weth);
        path[1] = address(token1);
        path[2] = address(token0);

        uint256 amount1Out = RouterLib.getAmountOut(3e17, 1e18, 1e18);
        uint256 amount2Out = RouterLib.getAmountOut(amount1Out, 1e18, 1e18);

        weth.approve(address(router), 3e17);
        router.swapExactETHForTokensSupportingFeeOnTransferTokens{ value: 3e17 }(1e17, path, address(this), deadline);

        assertEq(token0.balanceOf(address(this)), TOKEN_A_TOTAL_SUPPLY - 1e18 + amount2Out);
        assertEq(token1.balanceOf(address(this)), TOKEN_B_TOTAL_SUPPLY - 2e18);
        assertEq(weth.balanceOf(address(this)), 20e18);
    }

    function test_ShouldBeSuccess_swapExactTokensForETHSupportingFeeOnTransferTokens() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(token0);
        path[1] = address(token1);
        path[2] = address(weth);

        token0.approve(address(router), 3e17);
        router.swapExactTokensForETHSupportingFeeOnTransferTokens(3e17, 1e17, path, address(this), deadline);

        assertEq(token0.balanceOf(address(this)), TOKEN_A_TOTAL_SUPPLY - 1e18 - 3e17);
        assertEq(token1.balanceOf(address(this)), TOKEN_B_TOTAL_SUPPLY - 2e18);
        assertEq(weth.balanceOf(address(this)), 20e18);
    }

    /*//////////////////////////////////////////////////////////////////////////
                                      REVERTS
    //////////////////////////////////////////////////////////////////////////*/

    function test_Revert_insufficientBAmount_addLiquidity() public {
        uint256 token0transferAmount = 1e18;
        uint256 token1transferAmount = 1e18;
        _addLiquidity(token0transferAmount, token1transferAmount);

        uint256 token0approveAmount = 1e18;
        uint256 token1approveAmount = 2e18;

        token0.approve(address(router), token0approveAmount);
        token1.approve(address(router), token1approveAmount);

        vm.expectRevert(Router.InsufficientBAmount.selector);
        router.addLiquidity(
            address(token0),
            address(token1),
            token0approveAmount,
            token1approveAmount,
            token0approveAmount,
            token1approveAmount,
            address(this),
            deadline
        );
    }

    function test_Revert_insufficientAAmount_addLiquidity() public {
        uint256 token0transferAmount = 1e18;
        uint256 token1transferAmount = 1e18;
        _addLiquidity(token0transferAmount, token1transferAmount);

        uint256 token0approveAmount = 1e18;
        uint256 token1approveAmount = 2e18;

        token0.approve(address(router), token0approveAmount);
        token1.approve(address(router), token1approveAmount);

        vm.expectRevert(Router.InsufficientAAmount.selector);
        router.addLiquidity(
            address(token0),
            address(token1),
            token1approveAmount,
            token0approveAmount,
            token1approveAmount,
            token0approveAmount,
            address(this),
            deadline
        );
    }

    //function test_Revert_UnableToTransferWETH_addLiquidityETH() public { }

    function test_Revert_UnableToSendEther_addLiquidityETH() public {
        address erc20Contarct = makeAddr("erc20Contarct");
        vm.etch(erc20Contarct, "1");

        vm.deal(erc20Contarct, 5e18);
        token0.transfer(erc20Contarct, 5e18);
        weth.transfer(erc20Contarct, 5e18);

        vm.startPrank(erc20Contarct);

        uint256 token0approveAmount = 1e18;
        uint256 WETHapproveAmount = 1e18;

        token0.approve(address(router), token0approveAmount);
        weth.approve(address(router), WETHapproveAmount);

        router.addLiquidityETH{ value: 1e18 }(address(token0), token0approveAmount, 1e18, 1e18, erc20Contarct, deadline);

        token0.approve(address(router), 1e18);
        weth.approve(address(router), 2e18);

        vm.expectRevert(Router.UnableToSendEther.selector);
        router.addLiquidityETH{ value: 1e18 }(address(token0), 1e17, 1e18, 1e17, erc20Contarct, deadline);
    }

    function test_Revert_insufficientAAmount_removeLiquidity() public {
        uint256 token0transferAmount = 1e18;
        uint256 token1transferAmount = 1e18;
        (,, uint256 liquidity) = _addLiquidity(token0transferAmount, token1transferAmount);

        pair.approve(address(router), liquidity);

        vm.expectRevert(Router.InsufficientAAmount.selector);
        router.removeLiquidity(
            address(token0),
            address(token1),
            liquidity,
            token0transferAmount,
            token1transferAmount,
            address(this),
            deadline
        );
    }

    function test_Revert_insufficientBAmount_removeLiquidity() public {
        uint256 token0transferAmount = 1e18;
        uint256 token1transferAmount = 1e18;
        (,, uint256 liquidity) = _addLiquidity(token0transferAmount, token1transferAmount);

        pair.approve(address(router), liquidity);

        vm.expectRevert(Router.InsufficientBAmount.selector);
        router.removeLiquidity(
            address(token0),
            address(token1),
            liquidity,
            token0transferAmount - 10 ** 3,
            token1transferAmount,
            address(this),
            deadline
        );
    }

    function test_Revert_unableToSendEther_removeLiquidityETHSupportingFeeOnTransferTokens() public {
        address erc20Contarct = makeAddr("erc20Contarct");
        vm.etch(erc20Contarct, "1");

        vm.deal(erc20Contarct, 1e18);
        token0.transfer(erc20Contarct, 5e18);
        weth.transfer(erc20Contarct, 5e18);

        vm.startPrank(erc20Contarct);

        uint256 token0approveAmount = 1e18;
        uint256 WETHapproveAmount = 1e18;

        token0.approve(address(router), token0approveAmount);
        weth.approve(address(router), WETHapproveAmount);

        (,, uint256 liquidity) = router.addLiquidityETH{ value: 1e18 }(
            address(token0), token0approveAmount, 1e18, 1e18, erc20Contarct, deadline
        );

        address pairAddress = pairFactory.getPair(address(token0), address(weth));

        Pair(pairAddress).approve(address(router), liquidity);

        vm.expectRevert(Router.UnableToSendEther.selector);
        router.removeLiquidityETHSupportingFeeOnTransferTokens(
            address(token0),
            liquidity,
            token0approveAmount - 10 ** 3,
            WETHapproveAmount - 10 ** 3,
            erc20Contarct,
            deadline
        );
    }

    function test_Revert_insufficientOutputAmount_swapExactTokensForTokens() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(token0);
        path[1] = address(token1);
        path[2] = address(weth);

        token0.approve(address(router), 3e17);

        vm.expectRevert(Router.InsufficientOutputAmount.selector);
        router.swapExactTokensForTokens(3e17, 1e18, path, address(this), deadline);
    }

    function test_Revert_excessiveInputAmount_swapTokensForExactTokens() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(token0);
        path[1] = address(token1);
        path[2] = address(weth);

        uint256 amount1Out = RouterLib.getAmountOut(3e17, 1e18, 1e18);
        uint256 amount2Out = RouterLib.getAmountOut(amount1Out, 1e18, 1e18);

        token0.approve(address(router), 3e17);

        vm.expectRevert(Router.ExcessiveInputAmount.selector);
        router.swapTokensForExactTokens(amount2Out, 1e16, path, address(this), deadline);
    }

    function test_Revert_invalidPath_swapExactETHForTokens() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(token0);
        path[1] = address(token1);
        path[2] = address(weth);

        weth.approve(address(router), 3e17);

        vm.expectRevert(Router.InvalidPath.selector);
        router.swapExactETHForTokens{ value: 3e17 }(1e18, path, address(this), deadline);
    }

    function test_Revert_insufficientOutputAmount_swapExactETHForTokens() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(weth);
        path[1] = address(token1);
        path[2] = address(token0);

        weth.approve(address(router), 3e17);

        vm.expectRevert(Router.InsufficientOutputAmount.selector);
        router.swapExactETHForTokens{ value: 3e17 }(1e18, path, address(this), deadline);
    }

    //function test_Revert_unableToTransferWETH_swapExactETHForTokens() public { }

    function test_Revert_invalidPath_swapTokensForExactETH() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[1] = address(weth);
        path[0] = address(token0);
        path[2] = address(token1);

        uint256 amount1Out = RouterLib.getAmountOut(3e17, 1e18, 1e18);
        uint256 amount2Out = RouterLib.getAmountOut(amount1Out, 1e18, 1e18);

        token0.approve(address(router), 3e17);

        vm.expectRevert(Router.InvalidPath.selector);
        router.swapTokensForExactETH(amount2Out, 3e17, path, address(this), deadline);
    }

    function test_Revert_excessiveInputAmount_swapTokensForExactETH() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(token0);
        path[1] = address(token1);
        path[2] = address(weth);

        uint256 amount1Out = RouterLib.getAmountOut(3e17, 1e18, 1e18);
        uint256 amount2Out = RouterLib.getAmountOut(amount1Out, 1e18, 1e18);

        token0.approve(address(router), 3e17);

        vm.expectRevert(Router.ExcessiveInputAmount.selector);
        router.swapTokensForExactETH(amount2Out, 3e16, path, address(this), deadline);
    }

    function test_Revert_unableToSendEther_swapTokensForExactETH() public {
        address erc20Contarct = makeAddr("erc20Contarct");
        vm.etch(erc20Contarct, "1");

        vm.deal(erc20Contarct, 1e18);
        token0.transfer(erc20Contarct, 5e18);
        token1.transfer(erc20Contarct, 5e18);
        weth.transfer(erc20Contarct, 5e18);

        vm.startPrank(erc20Contarct);

        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, erc20Contarct, deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(token0);
        path[1] = address(token1);
        path[2] = address(weth);

        uint256 amount1Out = RouterLib.getAmountOut(3e17, 1e18, 1e18);
        uint256 amount2Out = RouterLib.getAmountOut(amount1Out, 1e18, 1e18);

        token0.approve(address(router), 3e17);

        vm.expectRevert(Router.UnableToSendEther.selector);
        router.swapTokensForExactETH(amount2Out, 3e17, path, erc20Contarct, deadline);
    }

    function test_Revert_invalidPath_swapExactTokensForETH() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(weth);
        path[1] = address(token1);
        path[2] = address(token0);

        token0.approve(address(router), 3e17);

        vm.expectRevert(Router.InvalidPath.selector);
        router.swapExactTokensForETH(3e17, 1e17, path, address(this), deadline);
    }

    function test_Revert_insufficientOutputAmount_swapExactTokensForETH() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(token0);
        path[1] = address(token1);
        path[2] = address(weth);

        token0.approve(address(router), 3e17);

        vm.expectRevert(Router.InsufficientOutputAmount.selector);
        router.swapExactTokensForETH(3e17, 1e18, path, address(this), deadline);
    }

    function test_Revert_unableToSendEther_swapExactTokensForETH() public {
        address erc20Contarct = makeAddr("erc20Contarct");
        vm.etch(erc20Contarct, "1");

        vm.deal(erc20Contarct, 1e18);
        token0.transfer(erc20Contarct, 5e18);
        token1.transfer(erc20Contarct, 5e18);
        weth.transfer(erc20Contarct, 5e18);

        vm.startPrank(erc20Contarct);

        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, erc20Contarct, deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(token0);
        path[1] = address(token1);
        path[2] = address(weth);

        token0.approve(address(router), 3e17);

        vm.expectRevert(Router.UnableToSendEther.selector);
        router.swapExactTokensForETH(3e17, 1e17, path, erc20Contarct, deadline);
    }

    function test_Revert_invalidPath_swapETHForExactTokens() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(token0);
        path[1] = address(token1);
        path[2] = address(weth);

        uint256 amount1Out = RouterLib.getAmountOut(3e17, 1e18, 1e18);
        uint256 amount2Out = RouterLib.getAmountOut(amount1Out, 1e18, 1e18);

        weth.approve(address(router), 3e17);

        vm.expectRevert(Router.InvalidPath.selector);
        router.swapETHForExactTokens{ value: 3e17 }(amount2Out, path, address(this), deadline);
    }

    function test_Revert_excessiveInputAmount_swapETHForExactTokens() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(weth);
        path[1] = address(token1);
        path[2] = address(token0);

        uint256 amount1Out = RouterLib.getAmountOut(3e17, 1e18, 1e18);
        uint256 amount2Out = RouterLib.getAmountOut(amount1Out, 1e18, 1e18);

        weth.approve(address(router), 3e17);

        vm.expectRevert(Router.ExcessiveInputAmount.selector);
        router.swapETHForExactTokens{ value: 3e16 }(amount2Out, path, address(this), deadline);
    }

    //function test_Revert_unableToTransferWETH_swapETHForExactTokens() public { }

    //function test_Revert_unableToSendEther_swapETHForExactTokens() public { }

    function test_Revert_insufficientOutputAmount_swapExactTokensForTokensSupportingFeeOnTransferTokens() public {
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        address[] memory path = new address[](2);
        path[0] = address(token0);
        path[1] = address(token1);

        token0.approve(address(router), 3e17);

        vm.expectRevert(Router.InsufficientOutputAmount.selector);
        router.swapExactTokensForTokensSupportingFeeOnTransferTokens(3e17, 1e18, path, address(this), deadline);
    }

    function test_Revert_invalidPath_swapExactETHForTokensSupportingFeeOnTransferTokens() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(token0);
        path[1] = address(token1);
        path[2] = address(weth);

        weth.approve(address(router), 3e17);

        vm.expectRevert(Router.InvalidPath.selector);
        router.swapExactETHForTokensSupportingFeeOnTransferTokens{ value: 3e17 }(1e18, path, address(this), deadline);
    }

    //function test_Revert_unableToTransferWETH_swapExactETHForTokensSupportingFeeOnTransferTokens() public { }

    function test_Revert_insufficientOutputAmount_swapExactETHForTokensSupportingFeeOnTransferTokens() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(weth);
        path[1] = address(token1);
        path[2] = address(token0);

        weth.approve(address(router), 3e17);

        vm.expectRevert(Router.InsufficientOutputAmount.selector);
        router.swapExactETHForTokensSupportingFeeOnTransferTokens{ value: 3e17 }(1e18, path, address(this), deadline);
    }

    //function test_Revert_unableToTransferWETH_swapExactTokensForETHSupportingFeeOnTransferTokens() public { }

    function test_Revert_invalidPath_swapExactTokensForETHSupportingFeeOnTransferTokens() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(weth);
        path[1] = address(token1);
        path[2] = address(token0);

        token0.approve(address(router), 3e17);

        vm.expectRevert(Router.InvalidPath.selector);
        router.swapExactTokensForETHSupportingFeeOnTransferTokens(3e17, 1e17, path, address(this), deadline);
    }

    function test_Revert_insufficientOutputAmount_swapExactTokensForETHSupportingFeeOnTransferTokens() public {
        uint256 WETHTransferAmount = 1e18;
        uint256 token0TransferAmount = 1e18;
        uint256 token1TransferAmount = 1e18;

        _addLiquidity(token0TransferAmount, token1TransferAmount);

        token1.approve(address(router), token1TransferAmount);
        weth.approve(address(router), WETHTransferAmount);

        router.addLiquidityETH{ value: 1e18 }(
            address(token1), token1TransferAmount, 1e18, 1e18, address(this), deadline
        );

        address[] memory path = new address[](3);
        path[0] = address(token0);
        path[1] = address(token1);
        path[2] = address(weth);

        token0.approve(address(router), 3e17);

        vm.expectRevert(Router.InsufficientOutputAmount.selector);
        router.swapExactTokensForETHSupportingFeeOnTransferTokens(3e17, 1e18, path, address(this), deadline);
    }

    /*//////////////////////////////////////////////////////////////////////////
                                      HELPERS
    //////////////////////////////////////////////////////////////////////////*/

    function _addLiquidity(
        uint256 _token0Amount,
        uint256 _token1Amount
    )
        private
        returns (uint256 amountA, uint256 amountB, uint256 liquidity)
    {
        token0.approve(address(router), _token0Amount);
        token1.approve(address(router), _token1Amount);
        (amountA, amountB, liquidity) = router.addLiquidity(
            address(token0),
            address(token1),
            _token0Amount,
            _token1Amount,
            _token0Amount,
            _token1Amount,
            address(this),
            deadline
        );
    }

    function _getPermitHash(
        Pair _pair,
        address _owner,
        address _spender,
        uint256 _value,
        uint256 _nonce,
        uint256 _deadline
    )
        private
        view
        returns (bytes32)
    {
        return keccak256(
            abi.encodePacked(
                "\x19\x01",
                _pair.DOMAIN_SEPARATOR(),
                keccak256(abi.encode(PERMIT_TYPEHASH, _owner, _spender, _value, _nonce, _deadline))
            )
        );
    }
}

Here's the coverage result:
I used forge coverage command.

cc: @PaulRBerg @gakonst

could anyone please help me with this issue? i am not able to solve this issue.

@ismailcanvardar One thing that I always do is disable optimizations for coverage runs. The optimizations inline a lot of code, so there's no way to attribute the runs back to the source code.
Example foundry.toml:
# Default "production" profile.
[profile.default]
solc-version = "0.8.19"
optimizer = true
optimizer-runs = 20000

# Use FOUNDRY_PROFILE=lite for quicker compilation, coverage
[profile.lite]
optimizer = false

Then run like:
FOUNDRY_PROFILE=lite forge coverage

Thanks for your response @KholdStare.

My foundry.toml file
[profile.default]
  fs_permissions = [{ access = "read-write", path = "./"}]
  auto_detect_solc = false
  block_timestamp = 1_680_220_800 # March 31, 2023 at 00:00 GMT
  bytecode_hash = "none"
  evm_version = "paris"
  fuzz = { runs = 1_000 }
  gas_reports = ["*"]
  libs = ["lib"]
  optimizer = true
  optimizer_runs = 10_000
  out = "out"
  script = "script"
  solc = "0.8.21"
  src = "src"
  test = "test"

[profile.lite]
  optimizer = false

[profile.ci]
  fuzz = { runs = 10_000 }
  verbosity = 4

# [etherscan]
#   arbitrum_one = { key = "${API_KEY_ARBISCAN}" }
#   avalanche = { key = "${API_KEY_SNOWTRACE}" }
#   bnb_smart_chain = { key = "${API_KEY_BSCSCAN}" }
#   gnosis_chain = { key = "${API_KEY_GNOSISSCAN}" }
#   goerli = { key = "${API_KEY_ETHERSCAN}" }
#   mainnet = { key = "${API_KEY_ETHERSCAN}" }
#   optimism = { key = "${API_KEY_OPTIMISTIC_ETHERSCAN}" }
#   polygon = { key = "${API_KEY_POLYGONSCAN}" }
#   sepolia = { key = "${API_KEY_ETHERSCAN}" }

[fmt]
  bracket_spacing = true
  int_types = "long"
  line_length = 120
  multiline_func_header = "all"
  number_underscore = "thousands"
  quote_style = "double"
  tab_width = 4
  wrap_comments = true

[rpc_endpoints]
  arbitrum_one = "https://arbitrum-mainnet.infura.io/v3/${API_KEY_INFURA}"
  avalanche = "https://avalanche-mainnet.infura.io/v3/${API_KEY_INFURA}"
  bnb_smart_chain = "https://bsc-dataseed.binance.org"
  gnosis_chain = "https://rpc.gnosischain.com"
  goerli = "https://goerli.infura.io/v3/${API_KEY_INFURA}"
  localhost = "http://localhost:8545"
  mainnet = "https://eth-mainnet.g.alchemy.com/v2/${API_KEY_ALCHEMY}"
  optimism = "https://optimism-mainnet.infura.io/v3/${API_KEY_INFURA}"
  polygon = "https://polygon-mainnet.infura.io/v3/${API_KEY_INFURA}"
  sepolia = "https://sepolia.infura.io/v3/${API_KEY_INFURA}"

So, I've added lite profile section after your comment. After that I'd ran forge clean and FOUNDRY_PROFILE=lite forge coverage commands. Unfortunately, nothing changed.
Here's the coverage scores.

Do you want me to add more details to solve this problem?

Experiencing a similar problem with oracles

After some reading I think #2567 might explain our problem

Project: Uniswap v2 contracts (UniswapV2Router02.sol, UniswapV2Library.sol)
I wanted to bring up a recurring challenge we've been facing in our project regarding code quality and test coverage. We've noticed that when we aim for higher test coverage, the quality of our code seems to deteriorate, and vice versa.
I've attached some screenshots below to illustrate the issue. As you can see, when we prioritize increasing test coverage, the codebase becomes messier and harder to maintain. On the other hand, when we focus on improving code quality, test coverage tends to suffer.
We've been grappling with this problem for weeks now, and despite various attempts, we haven't been able to find a satisfactory solution. It's becoming increasingly frustrating as it's impeding our progress.

When we set the reserve part to (0,0) in the getReserves function of RouterLib, it provides coverage. However, in the Router->addLiquidity function, the line liquidity = IPair(pair).mint(to); needs to be commented out. When I uncomment it, we still don't get coverage.

When I correct the implementation of the getReserves function in RouterLib and keep the line liquidity = IPair(pair).mint(to); commented out in the Router->addLiquidity function, we still do not achieve coverage.

Lastly, I showed you the common IPair interface in both examples above.
I'm reaching out to gather insights and suggestions from all of you. Have any of you encountered similar challenges in your projects? If so, how did you approach them?
@onbjerg @Austinhs @mattsse

@whisskey , look into lcov reports they are interactive and provide line by line results of what was covered and what was not covered...
Here is a script I keep in our repo to run lcov reports:
#!/bin/bash
rm -rf coverage_report
rm lcov.info
forge coverage --report lcov
lcov --remove lcov.info  -o lcov.info 'tests/*' 'script/*' '**/libraries/external/*' '**/testnet/*' '**/mocks/*' '**/indexing/*'
genhtml lcov.info -o coverage_report
google-chrome --headless --window-size=1200,800 --screenshot="coverage_report/coverage.png" "coverage_report/index.html"
printf "<img src=\"coverage.png\"/>" > coverage_report/README.md
open coverage_report/index.html

Bump on this. Getting the same issue. Running forge coverage on this repo: https://github.com/marsfoundation/sparklend-advanced
Ran 13 test suites in 19.32s (59.57s CPU time): 69 tests passed, 1 failed, 0 skipped (70 total tests)
| File                                       | % Lines          | % Statements     | % Branches     | % Funcs         |
|--------------------------------------------|------------------|------------------|----------------|-----------------|
| src/CappedFallbackRateSource.sol           | 100.00% (8/8)    | 100.00% (9/9)    | 100.00% (4/4)  | 100.00% (3/3)   |
| src/CappedOracle.sol                       | 100.00% (7/7)    | 100.00% (9/9)    | 100.00% (4/4)  | 100.00% (3/3)   |
| src/FixedPriceOracle.sol                   | 100.00% (4/4)    | 100.00% (4/4)    | 100.00% (2/2)  | 100.00% (3/3)   |
| src/MorphoUpgradableOracle.sol             | 100.00% (6/6)    | 100.00% (7/7)    | 100.00% (0/0)  | 100.00% (4/4)   |
| src/PotRateSource.sol                      | 100.00% (3/3)    | 100.00% (4/4)    | 100.00% (0/0)  | 100.00% (3/3)   |
| src/RETHExchangeRateOracle.sol             | 100.00% (9/9)    | 100.00% (15/15)  | 100.00% (4/4)  | 100.00% (3/3)   |
| src/RateTargetBaseInterestRateStrategy.sol | 100.00% (6/6)    | 100.00% (10/10)  | 100.00% (2/2)  | 100.00% (3/3)   |
| src/RateTargetKinkInterestRateStrategy.sol | 100.00% (6/6)    | 100.00% (11/11)  | 100.00% (2/2)  | 100.00% (3/3)   |
| src/VariableBorrowInterestRateStrategy.sol | 91.18% (31/34)   | 93.02% (40/43)   | 87.50% (7/8)   | 100.00% (13/13) |
| src/WEETHExchangeRateOracle.sol            | 0.00% (0/9)      | 0.00% (0/15)     | 0.00% (0/4)    | 0.00% (0/3)     |
| src/WSTETHExchangeRateOracle.sol           | 100.00% (9/9)    | 100.00% (15/15)  | 100.00% (4/4)  | 100.00% (3/3)   |
| test/CappedFallbackRateSource.t.sol        | 83.33% (5/6)     | 87.50% (7/8)     | 100.00% (0/0)  | 100.00% (3/3)   |
| test/PotRateSource.t.sol                   | 100.00% (2/2)    | 100.00% (2/2)    | 100.00% (0/0)  | 100.00% (2/2)   |
| test/RETHExchangeRateOracle.t.sol          | 100.00% (3/3)    | 100.00% (3/3)    | 100.00% (0/0)  | 100.00% (3/3)   |
| test/WEETHExchangeRateOracle.t.sol         | 100.00% (3/3)    | 100.00% (3/3)    | 100.00% (0/0)  | 100.00% (3/3)   |
| test/WSTETHExchangeRateOracle.t.sol        | 100.00% (3/3)    | 100.00% (5/5)    | 100.00% (0/0)  | 100.00% (3/3)   |
| test/mocks/PriceSourceMock.sol             | 100.00% (5/5)    | 100.00% (5/5)    | 100.00% (0/0)  | 100.00% (4/4)   |
| test/mocks/RateSourceMock.sol              | 100.00% (5/5)    | 100.00% (5/5)    | 100.00% (0/0)  | 100.00% (4/4)   |
| Total                                      | 89.84% (115/128) | 89.02% (154/173) | 85.29% (29/34) | 95.45% (63/66)  |

WEETHExchangeRateOracle is very clearly being tested in the WEETHExchangeRateOracle.t.sol file. Similar to the comment above if I modify the code and add an event emission in the latestAnswer() function (and remove view modifier) it will pass with 100% coverage. Something odd is going on.

was doing some more tests and there's RETHExchangeRateOracle which is similar to WEETHExchangeRateOracle but comes before it, what I suspect is they're somehow matched by deployed bytecode because if changing require msg in RETHExchangeRateOracle from  "RETHExchangeRateOracle/invalid-decimals" to "RETHExchangeRateOracle/invalid-d" then coverage for WEETHExchangeRateOracle appears. @klkvr wdyt, should this somehow explain the issue? thank you!

same reported in
https://github.com/foundry-rs/foundry/issues/5729
https://github.com/foundry-rs/foundry/issues/5342
https://github.com/foundry-rs/foundry/issues/4780
https://github.com/foundry-rs/foundry/issues/4316
https://github.com/foundry-rs/foundry/issues/4142

going to close this one for now as the latest problem signaled was solved with https://github.com/foundry-rs/foundry/pull/8214 and don't have original repro to test, feel free to reopen if hit again. thank you


Helm chart for gitea?

Gitea version (or commit ref): v1.10
Operating system: Kubernetes (OpenShift) + Helm 3.0

Description
Is there a runnable helm chart for gitea?
I've seen this PR in helm/charts and this "issue" on here but they are both more than one year old and seem dead
Is there somewhere a working helm chart for gitea? or at least a work in progress where I could help/contribute?
If not, should it be maintained on here (go-gitea/gitea) or in the helm/charts repo?

I know of https://github.com/jfelten/gitea-helm-chart

@techknowlogick thanks. It is a nice effort and a good work from @jfelten but IMHO the chart is strangely structured, variables are grouped by type (persistence, resources, images etc) instead of componernt (gitea, postgres..)
Q: Is there a will to get an "official" helm chart for gitea  that will be updated with each version of gitea?
If so, should it be maintained side by side the gitea code? in another gitea repository or in the helm/charts repo?
I could find the time to contribute to this as we are about to deploy gitea in OpenShift v4.x

Gitea ❤'s k8s (we run gitea.com on-top of k8s), and while we don't use Helm, I would be supportive of creating a repo in our org for the helm chart.

Or maybe we should implement a gitea operator?

@lunny Sure ! or both. Who will design this operator?

@titou10titou10 Contributors or maintainers of gitea!

@techknowlogick would you mind sharing (in private?) your k8s objects (Deployments, STS, PV/PVC, etc) in order to have a base from a running gitea

@titou10titou10 @techknowlogick I think not currently. It needs more work as a public project.

I found 2 operators, one for k8s and one for OpenShift (because of a "route" object being created, easily replaced by an "ingress" I guess). The latter one is from the OpenShift team lead Wolfgang Kulhanek
Also a gitea docker image runnable in OpenShift (ie running with non-root user and other high privileges processes..) with an OpenShift "template" with persistent and ephemeral deployment
Could be a great  source of inspiration
https://github.com/wkulhanek/gitea-operator
https://github.com/integr8ly/gitea-operator
https://github.com/wkulhanek/docker-openshift-gitea

^ One more Rancher-style k8s config

Hey all @loleg @titou10titou10 @techknowlogick @jfelten
I've actually been working on a Gitea Helm chart for the past week and I'd be more than welcome to contribute / donate it to the Gitea project in it's own separate repo.
It was originally based upon https://github.com/jfelten/gitea-helm-chart but I ran into a few issues with regards to its structure. My following chart does the following different:

Database is de-coupled and the chart uses the official mariadb database from: https://github.com/helm/charts/blob/master/stable/mariadb this helps in terms of stability rather than having the databased coupled within the same Pod (as @jfelten 's helm chart did)
Upgrade functionality
Uses ingress by default and LoadBalancer for the SSH port on port 8022
Persistency has been enabled / integrated
Let's Encrypt has been enabled / integrated into the Helm chart

It is located here:
https://github.com/cdrage/charts/tree/master/gitea
To try:
helm repo add cdrage http://charts.charliedrage.com
helm install gitea cdrage/gitea

For production / persistency:
helm show values cdrage/gitea > values.yaml
vim values.yaml # Edit to enable persistent storage
helm install gitea cdrage/gitea -f values.yaml

@bclermont , for inspiration, I found 2 other operatora for gitea and OpenShift, but I'm not sure of the maturity of both:
https://github.com/integr8ly/gitea-operator
https://github.com/wkulhanek/gitea-operator

@titou10titou10 I looked at them already, they install gitea, not manage it once deployed.
for the installation of gitea I just use helm

Hi all, anybody having an issue described here: https://github.com/go-gitea/gitea/issues/11408?
Basically using this helm chart, any push (via git client or gitea ui) results in the following error message:
The change was rejected by the server with the following message:
Gitea: Internal Server Error
Unable to contact gitea: Post http://<IP_ADDRESS>:3000/api/internal/hook/pre-receive/dynatrace/test: net/http: invalid header field value "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE1ODk0NTQxOTJ9.iWBvmOHvMVDnPNwVtNaAZ91gMBPljH-3lDVvM0_0HEE\n" for key Authorization
Please check githooks.

The helm chart is listed in the linked issue.
Thanks in advance!

Hello,
Just to know: is anyone still working on an official Helm chart for Gitea ?
If it is the case, I would love to help write and maintain it !

https://github.com/k8s-land/gitea-chart
Is a actively maintained.
I've proposed to have this chart as the official one for Gitea but I've got no response yet.

@cdrage Sorry for the slow response. And thanks for your significant work on gitea chart. Once we accept your repository as an official one, we should update the chart with every gitea release. I think currently we have no enough maintainers and test environments to do it well. We should have at least another two maintainers (except you if you want to become one) to follow gitea's review policy - Every PR should be reviewed by at least two maintainers before it could be merged.

Hello we've also created a gitea helm chart. It is fairly new and currently only used in our own kubernetes clusters. But we've decided to make it public.
https://github.com/novumrgi/helm/tree/master/charts/gitea
current support for:

built in support for memcached, postgresql, mysql via dependencies.
support via values for nearly all settings from https://docs.gitea.io/en-us/config-cheat-sheet/
and we're working on a more flexible way to provide all the settings.
statefulset so your repository settings only getting lost if you really want them to
ldap and admin user settings via values (currently via init container, it would be nice to have this supported by app.ini or api)

Since we're actively using gitea in our company cluster we're going to maintain the chart for a long time.
However I don't want to start a "which chart is better" war. So if someone is interested let me know, or just use it :).
If you want to use our chart as official helm chart for gitea, let me know.

@luhahn that's awesome! feel free to send a PR to https://gitea.com/gitea/awesome-gitea/ to list it there as an option :)
I'm going to close this now, as we have many different options for helm charts now, and so the goal of this ticket is now complete.

We have an official helm chart https://gitea.com/gitea/helm-chart based on @cdrage 's recently. It's welcome to send PRs to that repository.

Sorry, but since our helm chart already supports admin user, ldap and much more we won't start working on another one. We're already using ours in our company and it supports all our needs, so it is highly unlikely that we're allowed to develop another one, which doesn't support the features we need.
However we're happy to help if you have questions, or if you decide to use ours and need support.

Let's discuss on discord. An official helm-chart with more features could help more people.

This is great news that this has been done.


feat: Remove progressbar when --no-color flag is set

Pull request

What this PR does / why we need it
Hide progress bar when --no-color is set
Which issue(s) this PR fixes

Fixes #440
Describe testing done for PR

Additional information or special notes for your reviewer

Signed-off-by: Wendy Arango<EMAIL_ADDRESS>


Add www.web3isgoinggreat.com

https://www.web3isgoinggreat.com returns a Cloudflare errror, but https://web3isgoinggreat.com works. May need a new www entry

By the looks of the error it seems like www is trying to serve a certificate that is only valid for the root domain. Only Molly can check though because Cloudflare was recently added (it was a Google certificate before, and I didn't save it)

Thanks, should be fixed now.


Marginfigure OR embedded latex breaking rmarkdown

If I put the following into a document it stops parsing syntax below the block.
 ```{marginfigure}
![](/Users/jtth/Dropbox/Proposal/text/draft1/gabor.png)
A Gabor patch. These Gabor patches are described by $g(x,y;\lambda,\theta,\psi,\sigma,\gamma) = \exp\left(-\frac{x'^2+\gamma^2y'^2}{2\sigma^2}\right)\sin\left(2\pi\frac{x'}{\lambda}+\psi\right)$, where $\lambda$ ranges from .01 to .1, $\theta$ ranges from 0 to 90, $\psi = 0, \sigma = 50, \gamma = 1$. Degrees of rotation corresponds with the value of $\theta$ and the spacing between the stripes corresponds with $\lambda$.

It ends with three '`' too.

Thanks for reporting, I'll have a look at it!

@jtth I've taken a quick look, and I've found two things.

The syntax you used {marginfigure} isn't supported (by this package at least), so I've assumed {r engine='marginfigure'}. That at least starts parsing the fenced-code-block, which leads me to:
There's a lot of tokens on that single line, and due to performance issues, the amount of tokens is limited by Atom to a hundred. I've tried increasing this via the grammar, but it appears to be immutable. This may be the cause that it sort of stops parsing that line, and for some reason doesn't exit the scope it's in at that moment, etc, etc.

What additional, relevant packages do you have installed?

Linter, language-r, r-exec, and tidy-markdown.
Interestingly, replacing marginfigure (used with the tufte-template in Rmarkdown) with your version and replacing the quotes with \prime seems to work. And that is probably better. Thanks for the heads-up; I was taking pandoc's ability to interpret quote characters and transferring that to the text editor. Some day, maybe.

Quotes are bitches. [@burodepeper2016]

May we consider this issue closed then?

Indeed. Thanks!


Fall 2024 Meeting

Adding a meeting page to point people to for the Fall 2024 meeting

@sapols did I miss anything?

@jibarnum Nope it looks great to me! Thanks for making this, I'll merge 👍


Catch paste event on image

Hi,
The paste event of an image is stopped by _processBlobItems. (tui-editor-Editor.js 2239)
What is the correct way to catch this event and handle the data ?

What I've done so far is inserting my custom listener in the first position of the map in the eventManager.
Something like that:

var pasteListener = (event) => {
  var cbData = event.data.clipboardData;
  var types = cbData && cbData.types;

  if (types.includes("Files")) {
    event.preventDefault();
    event.stopPropagation();
   }
  };

tuiEditor.eventManager.events.set('paste', [pasteListener, ...tuiEditor.eventManager.events.get('paste')]);

In case pasting image, we need to emit addImageBlobHook hook and load image using FileReader.
Why you need paste event for image? If you give me for more detail information, I will check it.

I think it's following use case:
The user has image data in his clipboard and simply wants to insert an image in editor by pressing ctrl+v without using buttons of editor. This would result in a huge usability improvement.


Download video or audio error

Please follow the guide below

You will be asked some questions and requested to provide some information, please read them carefully and answer honestly
Put an x into all the boxes [ ] relevant to your issue (like this: [x])
Use the Preview tab to see what your issue will actually look like

Make sure you are using the latest version: run youtube-dl --version and ensure your version is 2019.04.24. If it's not, read this FAQ entry and update. Issues with outdated version will be rejected.

[ ] I've verified and I assure that I'm running youtube-dl 2019.04.24

Before submitting an issue make sure you have:

[ ] At least skimmed through the README, most notably the FAQ and BUGS sections
[ ] Searched the bugtracker for similar issues including closed ones
[ ] Checked that provided video/audio/playlist URLs (if any) are alive and playable in a browser

What is the purpose of your issue?

[ ] Bug report (encountered problems with youtube-dl)
[ ] Site support request (request for adding support for a new site)
[ ] Feature request (request for a new functionality)
[ ] Question
[ ] Other

The following sections concretize particular purposed issues, you can erase any section (the contents between triple ---) not applicable to your issue

If the purpose of this issue is a bug report, site support request or you are not completely sure provide the full verbose output as follows:
Add the -v flag to your command line you run youtube-dl with (youtube-dl -v <your command line>), copy the whole output and insert it here. It should look similar to one below (replace it with your log inserted between triple ```):
[debug] System config: []
[debug] User config: []
[debug] Command-line args: [u'-v', u'http://www.youtube.com/watch?v=BaW_jenozKcj']
[debug] Encodings: locale cp1251, fs mbcs, out cp866, pref cp1251
[debug] youtube-dl version 2019.04.24
[debug] Python version 2.7.11 - Windows-2003Server-5.2.3790-SP2
[debug] exe versions: ffmpeg N-75573-g1d0487f, ffprobe N-75573-g1d0487f, rtmpdump 2.4
[debug] Proxy map: {}
...
<end of log>

If the purpose of this issue is a site support request please provide all kinds of example URLs support for which should be included (replace following example URLs by yours):

Single video: https://www.youtube.com/watch?v=BaW_jenozKc
Single video: https://youtu.be/BaW_jenozKc
Playlist: https://www.youtube.com/playlist?list=PL4lCao7KL_QFVb7Iudeipvc2BCavECqzc

Note that youtube-dl does not support sites dedicated to copyright infringement. In order for site support request to be accepted all provided example URLs should not violate any copyrights.

Description of your issue, suggested solution and other information
Explanation of your issue in arbitrary form goes here. Please make sure the description is worded well enough to be understood. Provide as much context and examples as possible.
If work on your issue requires account credentials please provide them or explain how one can obtain them.
localhost:wei chenlong$ youtube-dl --proxy socks5://<IP_ADDRESS>:1086/ https://www.youtube.com/watch?v=x6ficfIqUaM
[youtube] x6ficfIqUaM: Downloading webpage
[youtube] x6ficfIqUaM: Downloading video info webpage
ERROR: x6ficfIqUaM: "token" parameter not in video info for unknown reason; please report this issue on https://yt-dl.org/bug . Make sure you are using the latest version; type  youtube-dl -U  to update. Be sure to call youtube-dl with the --verbose flag and include its complete output.
localhost:wei chenlong$ youtube-dl --proxy socks5://<IP_ADDRESS>:1086/ https://www.youtube.com/watch?v=x6ficfIqUaM -i -x --audio-format mp3
[youtube] x6ficfIqUaM: Downloading webpage
[youtube] x6ficfIqUaM: Downloading video info webpage
ERROR: x6ficfIqUaM: "token" parameter not in video info for unknown reason; please report this issue on https://yt-dl.org/bug . Make sure you are using the latest version; type  youtube-dl -U  to update. Be sure to call youtube-dl with the --verbose flag and include its complete output.

Maybe because I used Homebrew
There is no latest version of 2010.04.24 over there.


Integrity column is broken between v3.0.6121.1594 Git-da65c8d3 and v3.0.6127.1600 Git-b8e0f890

Regression (?) between v3.0.6121.1594 Git-da65c8d3 and v3.0.6127.1600 Git-b8e0f890. In v3.0.6121.1594 the Git-da65c8d3 column Integrity works, in v3.0.6127.1600 Git-b8e0f890 is broken.
Please, see screenshots:

This phenomena exists on Win7 SP1 x64 and Win 10 LTSB x64 (reported by KLASS).

Thanks! Fixed:


Signature not working on Samsung.

Signature pad is not working on Samsung device if the user needs to scroll.  Everything appears to work correctly if the signature pad is at the very top of the page.  If i need to scroll down the page to use the pad the drawing in not accurate.  Works on chrome but not stock browser.

Samsung phone's native browser fires Mouse events along with touch events. I faced same bug and was shocked after I removed mouse handling code, everything worked well.

I have the same issue on OnePlus 6T, Xiaomi Mi 5, Samsung galaxy A5 2018, Huawei P20 with Chrome only.
That work on all other browser like FireFox,...

@ryosaebasg1 Can you debug it somehow and check what happens there exactly? Also, which version of the library are you using?

If i scroll to bottom, when i try to sign, i have only some dot and the move not write, it scroll. If i stell on bottom and i refresh using the arrow turning in menu, that's work.
I have try to add signature on top of page and i have the same issue if need to scroll before it don't work, if i refresh at the rigth place it work.
I use this<EMAIL_ADDRESS>

Could you try out this version<EMAIL_ADDRESS>It supports pointer events, so maybe it will work.

I still have the same issue

I have create codepen :
https://codepen.io/anon/pen/eoMBPa
Use it on android chrome to see the issue and remove the div with heigth 5000px to see that's work

@ryosaebasg1 Thanks! I can replicate this issue, but I have no idea when I'll have time to look into it.

I have search and the only way to use it is to create the div with a button ;-)
Hope you find a direct way or Chrome accept it.


Fixed empty space bug in CollectionView

Fixed situation when cells with small height don't intersect with the Rect and stop the enumeration that cause empty spaces in collectionView.
Changes in this pull request
Issue fixed: # 680
Checklist

[x] All tests pass. Demo project builds and runs.
[x] I added tests, an experiment, or detailed why my change isn't tested.
[x] I added an entry to the CHANGELOG.md for any breaking changes, enhancements, or bug fixes.
[x] I have reviewed the contributing guide

@rnystrom All done. Sorry for awkward merge...


I need help with chapter three

I've done everything the book told me to do but the enemies don't shoot. I just dont know what to do. I've done everything. if you can help me it would me wonderful.

Well, "done everything" is pretty vague, can you be more specific? And not just "everything in chapter three" because, well duh, but rather list what specific things have you done so I can point out "aha you forgot X".

And the enemies aren't shooting the fireballs
On Thu, Jun 2, 2022, 18:31 AnimeGamer #101 @.***> wrote:

Well,
The error says "Prefab not found" but I put the fire ball in the prefab
section and in the script
On Thu, Jun 2, 2022, 18:29 Joseph Hocking @.***>
wrote:

Well, "done everything" is pretty vague, can you be more specific? And
not just "everything in chapter three" because, well duh, but rather list
what specific things have you done so I can point out "aha you forgot X".
—
Reply to this email directly, view it on GitHub
https://github.com/jhocking/uia-2e/issues/1#issuecomment-1145067296,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AWPDNRMHW623KCVMVGEM6XTVNDONXANCNFSM5V7DXE2A
.
You are receiving this because you authored the thread.Message ID:
@.***>


Will GreyMass expose my Karma tokens for conversion?

I want to convert my Karma (an EOS-based coin) to either EOS or an ERC-20 token, or really anything, heh.
Will GreyMass help with this? Scatter says it can but then bugs out at last step.
Thanks!

If you can find an exchange or swapping service that supports Anchor, it might.
I'm not knowledgable about Karma or where it's traded though so I can't be of much help there.


Try different JDK 10

CI tests with JDK have been flaky for some time, so I'm trying a different distribution to see if it's a distribution-specific bug. I'll have to rerun the build several times to see whether it flakes.

Didn't work, same failure on a different JDK.


Document what is "blocking and tackling"?

I have found an unfamiliar word - "blocking and tackling" from ADVANCED - Angular Module chapter
(https://angular.io/docs/ts/latest/guide/ngmodule.html).
...
"Most of this is familiar blocking and tackling."
...
What is the exact meaning of "blocking and tackling"?
Is that some kind of sports idioms? Then what's that mean for this context??
Please, anyone who knows the meaning help me!

We recently made an update to the ngmodule page and this verbage no longer exists; yes, it was a sports analogy; please see the new version which should clarify for you the original intention.


[Eventing - Control Plane] Channel Lifecycle Manual Test Plan

Description
This issue describes the creation of a "Manual Testing Plan" for a portion of the Eventing Spec.
Below is a link to the Spec Sub-heading which this issue is referencing, alongside a template upon which you should base your PR.
Link to Spec: https://github.com/knative/specs/blob/main/specs/eventing/control-plane.md#channel-lifecycle
Template: https://hackmd.io/D1S9NPaRTG2dcyFtdURSww?view
If you have any questions, please reach out in the #conformance channel on Slack
Acceptance Criteria

[ ]  Contributing to the right place

GIVEN I am accepting the PR that closes this issue
WHEN I inspect the .md file
THEN I see it is being committed to the /test/test-plan/ folder in the specs repo

[ ]  Conformance to Template

GIVEN I am reviewing the submitted .md file
WHEN I compare it to the template linked above
THEN I see that the submitted .md conforms to the template

[ ]  Coverage of Spec

GIVEN I am reviewing the submitted .md file
WHEN I compare the .md file to the Channel Lifecycle subheading in the spec
THEN all of the  "MUST" "MUST NOT" and "REQUIRED" sentences under the Channel Lifecycle sub-heading are covered within the submitted .md file

[ ]  Coverage of Tests

GIVEN I am running each of the tests in the submitted .md file
AND each test has a expected output
WHEN I am finished running the tests
THEN all of my tests pass (when compared to the expected output)
AND at least 2 reviewers feel it is properly covering all portions of the spec outlined at the top .md file

/assign

@gabo1208 is there a PR coming right?

Yup! here it is @salaboy https://github.com/knative/specs/pull/67


mongoose challenges: check for db connection

Pre-Submission Checklist

[x] Your pull request targets the staging branch of freeCodeCamp.
[x] Branch starts with either fix/, feature/, or translate/ (e.g. fix/signin-issue)
[x] You have only one commit (if not, squash them into one commit).
[ ] All new and existing tests pass the command npm test. Use git commit --amend to amend any fixes.

Type of Change

[ ] Small bug fix (non-breaking change which fixes an issue)
[x] New feature (non-breaking change which adds new functionality)
[ ] Breaking change (fix or feature that would change existing functionality)
[ ] Add new translation (feature adding new translations)

Checklist:

[ ] Tested changes locally.
[x] Addressed currently open issue (replace XXXXX with an issue no in next line)

Closes #16761
Description

@Em-Ant Can you let me know when you are online in gitter, I am having issues with connecting to the database, your assistance would be greatly appreciated.

I had left a note here but apparently not.
The boilerplate had been approved in the appropriate repo. Waiting for the changes to be merged on the main boilerplate before testing again.

@mstellaluna ping.


EgressDeny for a port dropping all egress traffic

I have been attempting to block the unauthenticated kubernetes port 10255 from all pod access bar prometheus through the use of an egressDeny rule that matches the port above and any pod with labels not in app=prometheus and this is applied to all pods as a whole via a CiliumClusterwideNetworkPolicy. I can see that this policy is selecting the pods correctly as the prometheus pod is still able to connect to the port on each node but for all other pods, no matter the port, all egress traffic is dropped. Changing the port 10255 to any arbitrary port also causes the same issue.
The basic version of the network policy looks like so:
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
  name: "block-10255-egress"
spec:
  description: ""
  endpointSelector:
    matchExpressions:
      - key: k8s:app
        operator: NotIn
        values:
        - "prometheus"
  egressDeny:
  - toPorts:
    - ports:
      - port: "10255"
        protocol: TCP

Cilium is installed using the following values:
USER-SUPPLIED VALUES:
cni:
  binPath: /home/kubernetes/bin
endpointRoutes:
  enabled: false
gke:
  enabled: false
hostFirewall: true
hubble:
  listenAddress: :4244
  relay:
    enabled: true
  ui:
    enabled: true
ipam:
  mode: kubernetes
nativeRoutingCIDR: <IP_ADDRESS>/14
nodeinit:
  enabled: true
  reconfigureKubelet: true
  removeCbrBridge: true
tunnel: disabled

Cilium has been setup to enable host filtering as suggested in the documentation.
Versions:
Cilium version: 1.9.4
Kubernetes version: v1.19.7-gke.800
Kubernetes provider: GKE
Node OS: Ubuntu + CoS (some nodes are running gvisor but cilium is not deployed with gvisor as its runtime class)
CoS kernel version: 5.4.49+
Ubuntu kernel version: 5.4.0-1033-gke

I believe this is expected behavior. As per the documentation, pods selected by a deny policy enter a default-deny mode. You will need another allow rule on egress to switch to default-allow.

Cilium has been setup to enable host filtering as suggested in the documentation.

Do you have a link to the documentation page that recommend that?

Okay I must have misunderstood that in the documentation, my fault. The link to the documentation entry is here I shall close this issue as you have pointed out it is an issue on my end and I can confirm that adding an egress rule now allows all traffic bar port 10255 like so:

Ok :+1:
You only need to enable the host firewall if you are using host policies, that is, policies that select nodes with nodeSelector.

Yes I was initially attempting to use that to block ingress on that port on the node, but it was not a favourable approach.
Many thanks again for your help


V1.2.19 Has Introduced New, Undocumented Color Modes and can no longer use color picker to switch modes

Version of the integration

V1.2.19
Configuration

L530 H/W V 2.0 F/W V1.0.9 Build 220526 Rel 203202
Add your logs here.

Describe the bug
A clear and concise description of what the bug is.
It is easy to put the L530 into a mode which does not conform to the
Light Entity specifications, which documentation says that:
the color_mode property must Return the color mode of the light. The returned color mode must be present in the supported_color_modes property.
In the case of the L530, these are:
supported_color_modes:
  - color_temp
  - hs

After updating the integration the developer states tool shows the following supported modes:
supported_color_modes: brightness, color_temp, hs, onoff
But "brightness" and "onoff" are not part of the aforementioned documentation.
This patch has apparently replaced the prior color_mode state of "unknown", which was what was returned when using the color picker at the centre, or programmatically with RGB=[255,255,255] with "brightness" rather than "color_temp".  I'm not sure what the purpose of "onoff" is.
An additional problem, which I don't think was present with the previous version, is that, once "color_temp" mode is achieved, (either with the HA color picker, or programmatically) to move back to "hs" mode.   That can only be achieved, so far,  with the TAPO application on my smartphone.  This seems to be a bug.
Debug log

Please let me know what logs are useful.

An additional problem, which I don't think was present with the previous version, is that, once "color_temp" mode is achieved, (either with the HA color picker, or programmatically) to move back to "hs" mode. That can only be achieved, so far, with the TAPO application on my smartphone. This seems to be a bug.

  Apologies for that.  However, the problem with getting stuck in color_temp which needs the Tapo app to fix is still a problem.  I guess that's why you put the Bug label on it?
Thanks!

Update to v1.3.4. I can change color in the right way

Updated to 1.3.4
Still not able to change color on my L530s :(

Can you send a photo or video which describe the issue better?

When I want to change the color of a L530 nothing happing. The color on the icon changes to the color i picked. The bulb stays in temperature mode.
Changing temperature works very well.
btw; on my L900s every thing works just fine.

I have the exact same problem!

btw; on my L900s every thing works just fine.

Can you provide hw version and sw version of L900?

L900:
Hardware Version
1.0
Firmware Version
1.0.16 Build 220902 Rel. 151030
L530:
Hardware Version
2.0
Firmware Version
1.0.9 Build 220526 Rel. 203202
Hope this helps

It's an issue related to HW Version like here #133. I will investigate on it

Chris, all my L530s are the same as yours. I also have 2 x L900s and one L930.
After updating, one of my L900`s and the L930 still work with the colour wheel.
They were both unplugged at the mains at the time of the update but the none working L900 was turned on. Is that the case with you?

It's an issue related to HW Version like here #133. I will investigate on it

Thanks buddy. I really do appreciate that! (y)

Chris, all my L530s are the same as yours. I also have 2 x L900s and one L930.
After updating, one of my L900`s and the L930 still work with the colour wheel.
They were both unplugged at the mains at the time of the update but the none working L900 was turned on. Is that the case with you?

To be honest, I can't remember. I ran the update and on the next day my daughter came to me telling she can't change colors on here lamp. So I tried mine and recognized it also won't work :(

Maybe the following is related.
Scenes I created in HomeKit don't work properly either. The icons show the lights as "on", but in reality they stay off.
When I go to the lights directly in HomeKit, I can turn them on perfectly.

Now it gets weird.
I have started a scene from HomeKit. All four lights in the scene are also lit in reality. However, two of the four are displayed as "off" in Home Assistant. In HomeKit as "on".
We are talking about two L530 and two L900. The L530s are displayed as "off" in Home Assistant, but as I said, they actually light up and are also displayed as "on" in HomeKit.

Sorry to be dumb, but how do I get HACS to upgrade ?
This shows that it knows there is a new version

============================
However the system doesn't act like it
============================

Am I missing something?
Thanks!

oops!  Never mind.

Maybe this helps

I have now upgraded to 1.3.4 and the problem remains, for which I have appended an MP4 video.
Before the video starts, I use the Tapo phone app to establish color mode.
Although the quality is not high, you can see the color of the bulb change as the palette is clicked.
You then see the mode change to Temperature and see the color of the bulb change with the slider
Lastly, you see the failure of the attempt to change into color mode, whereby the pallette has no effect, and requires another use of the Tapo phone app to get back to that mode.
Thanks!
Update:  The video was too big to include.  Here is a shareable link to google photos.  Apologies for the 4 second glitch at 4 seconds in, but there is still enough detail to show the problem
https://photos.app.goo.gl/ERoGePkz4WAfpKCG6

Thanks for video. I've a fix ready to be published. https://user-images.githubusercontent.com/25798293/210650391-e535cb92-9ab5-497a-abd6-e2f5f314f134.mp4 Its right?

Thank you @petretiandrea 🙏
I really appreciate your work 👍

Release v1.3.5 should resolve this issue


O.S. Systems pending fixes

@schnitzeltony Please merge this as it includes some important fixes.

I've merged all except 'plasma-workspace: Fix kdeinit path'. That is wrong with current oe-core's libexec interpretation. See
commit e7270e331560546d3805cd66ed14afcbc96b6d89
Author:     Ross Burton<EMAIL_ADDRESS>AuthorDate: Tue Apr 30 20:35:54 2013 +0100
Commit:     Richard Purdie<EMAIL_ADDRESS>CommitDate: Fri Jan 22 23:42:38 2016 +0000
Thanks


Upgrade rbe-toolchain to Python3.7

Ah how I missed fiddling with Python versions /s
We dropped Python stuff from this image when we dropped the Bazel build
of the Python bindings, but now we have some trace stuff using Python
for generation and it needs dataclasses (plus we use Python3.7 everhwere
else).
Needed for https://github.com/google/iree/pull/7499

Merging past already-failing cmake asan build, which this docker image cannot affect.


[Bugfix] Fix CustomAllreduce pcie nvlink topology detection (#3974)

CustomAllreduce requires nvidia GPUs to be fully connected via NVlink, and attempts to disable itself when run on incompatible hardware (e.g. >2 PCIE GPU where only specific pairs of cards are linked).
Current code calls nvmlDeviceGetNvLinkState(), but that method does not actually assess peer connectivity, instead it queries status of individual NVlink lanes on the current-rank GPU (equivalent to "nvidia-smi nvlink -s -i ").  As a result, CustomAllReduce is intermittently incorrectly enabled for >2 PCIE configurations, leading to hangs at model loading as discussed in #3974.
New code calls nvmlDeviceGetP2PStatus() to determine topology.
FIX #3974

Can you give some pointers to explain the behavior of nvmlDeviceGetNvLinkState and nvmlDeviceGetP2PStatus ? Since nvmlDeviceGetNvLinkState has two arguments, it looks surprising to me if it only checks nvlink status on one device.

This should be a release blocker. cc @simon-mo

Also cc @hanzhi713 FYI

ok what's the merge plan?

I can confirm this pr fix is correct. I tested it in a V100 DGX-1 machine, with 6 nvlinks for each device. The topo is

test code:
import pynvml
from contextlib import contextmanager

@contextmanager
def _nvml():
    try:
        pynvml.nvmlInit()
        yield
    finally:
        pynvml.nvmlShutdown()

@_nvml()
def check_link_state(device: int, link_lane: int):
    device = pynvml.nvmlDeviceGetHandleByIndex(device)
    return pynvml.nvmlDeviceGetNvLinkState(device, link_lane)

@_nvml()
def check_p2p_nvlink(device: int, target: int):
    device = pynvml.nvmlDeviceGetHandleByIndex(device)
    target = pynvml.nvmlDeviceGetHandleByIndex(target)
    return pynvml.nvmlDeviceGetP2PStatus(device, target, pynvml.NVML_P2P_CAPS_INDEX_NVLINK) == pynvml.NVML_P2P_STATUS_OK

check_p2p_nvlink(6, 7) # returns True
check_link_state(6, 6) # errors , because device 6 only has 6 nvlink lanes
check_link_state(6, 5) # returns True

ok what's the merge plan?

I will merge it after the test is good.


What are the oldest browsers and mobile browsers that this fetch polyfill (w/promise polyfill) will work on?

I see in the readme that it mentions latest chrome, ff, IE9, Safari and there is another comment at top about having some older browser support if you add a promise polyfill.
I guess my question is more about what browsers won't it work on if we include the promise polyfill. Or said differently what are the oldest browsers and mobile browsers that this will work with?
I would like to use fetch as my new http client, but I just need to know what limitations that is placing on that use, especially mobile browsers.

Can I use is a good reference for browser Promise support, including mobile browsers.

@dgraham are you saying that this fetch API will polyfill and work on all browsers that I can polyfill Promises? or did you not really understand my question?

I'm asking about where this fetch polyfill will work. If I include a promise polyfill, then how old of browsers can I use with fetch?
Are promises really the only limitation here?

The readme lists the browsers that we test on and support in production. We don't use fetch on mobile because the Promise polyfill is so large (we use XMLHttpRequest instead). But, if you want to try it out and report back, we can update the supported browser list.

ok. I'll have to leave that to someone else since I don't have nearly enough hardware to test with. I guess I'll stick with XMLHttpRequest libs until promise support is popular enough.

@dgraham I have enough page views from a static site and where I did insert a stats script for the resolution. What should I test to make sure:

native OK for fetch and promise
or OK after the es6-promise polyfill

Safari in iOS 8.4 and the browser in Android 4.4.4 are the first to support the Promise API. Previous mobile operating system versions will require the es6-promise polyfill in order to use fetch.
The percentage of your visitors using versions older than that will determine when fetch is viable.

Do you have deps other than Promise?

No deps other than Promise and XMLHttpRequest 2.


"--free-libraries" aggressor script option parsing errors

Recent changes introduced problem with aggressor script arguments parsing. Running simple example cause following error:

Tested current version of No-Consolation (commit 44784d6578c61e65f43cf2f2e0bf52dc22b8e963) on Cobalt Strike 4.10.

The issue here is $free_libs is initially declared as $free_libs = 0; and then evaluated by strlen($free_libs); to determine if it's set or not. However, strlen($free_libs); never equals 0 because it's treated as a string: $free_libs = "0" with a length of 1.
A solution could be to declare as empty string $free_libs = ""; or use proper comparison operators if($free_libs == 0 || $free_libs != 0)


Reverted 8b29739

I mistakenly changed the directory that should be included -- the change in  8b29739 means you have to use #include <doctest/doctest.h>, while it should be #include <doctest.h>. This reverts to the correct behaviour.

I'm a bit confused by this PR - it's against master instead of dev and "Files Changed" shows 0..?!

My bad -- it looks like I targeted master. It should naturally have been dev, where I previously made a wrong change. That change isn't in master yet (luckily), and this just reverts it.

I just committed and pushed that change in dev so I'm closing this PR.