Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Code coverage #4142

Closed
1 of 2 tasks
0xAurelou opened this issue Jan 20, 2023 · 7 comments
Closed
1 of 2 tasks

[BUG] Code coverage #4142

0xAurelou opened this issue Jan 20, 2023 · 7 comments
Labels
T-bug Type: bug

Comments

@0xAurelou
Copy link

0xAurelou commented Jan 20, 2023

Component

Forge

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

  • Foundry
  • Foundryup

What version of Foundry are you on?

forge 0.2.0 (d8f2434 2023-01-20T00:09:17.907613959Z)

What command(s) is the bug in?

forge coverage

Operating System

Linux

Describe the bug

When I am doing some code coverage the same code can get me a 0% code coverage while it should be 100% (Both compile)

Source Code

mock/USDC.sol

//  SPDX-License-Identifier: MIT

pragma solidity ^0.8.16;

import "openzeppelin-contracts/token/ERC20/IERC20.sol";
import "openzeppelin-contracts/token/ERC20/ERC20.sol";
import "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";

// @notice: Really basic USDC token just an ERC20 token mocked
// @dev: Need to define
contract USDC is ERC20 {
    using SafeERC20 for IERC20;

    constructor() ERC20("Circle Token", "USDC") {}

    function mint(address account, uint256 amount) public {
        _mint(account, amount);
    }

    function burn(address account, uint256 amount) public {
        _burn(account, amount);
    }
}

mock/USDT.sol

//  SPDX-License-Identifier: MIT

pragma solidity ^0.8.16;

import "openzeppelin-contracts/token/ERC20/IERC20.sol";
import "openzeppelin-contracts/token/ERC20/ERC20.sol";
import "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";

// @notice: Really basic USDT token just an ERC20 token mocked
contract USDT is ERC20 {
    using SafeERC20 for IERC20;

    constructor() ERC20("Tether Token", "USDT") {}

    function mint(address account, uint256 amount) public {
        _mint(account, amount);
    }

    function burn(address account, uint256 amount) public {
        _burn(account, amount);
    }
}

test/USDC.t.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.16;

import "forge-std/Test.sol";
import "../mock/USDC.sol";

contract USDCTest is Test {
    USDC public usdc;

    // hardhat getSigner() -> vm.addr()
    address public alice = vm.addr(0x1);
    address public bob = vm.addr(0x2);

    function setUp() public {
        usdc = new USDC();
    }

    function testName() external {
        assertEq("Circle Token", usdc.name());
    }

    function testSymbol() external {
        assertEq("USDC", usdc.symbol());
    }

    function testMint() public {
        usdc.mint(alice, 2e18);
        assertEq(usdc.totalSupply(), usdc.balanceOf(alice));
    }

    function testBurn() public {
        usdc.mint(alice, 10e18);
        assertEq(usdc.balanceOf(alice), 10e18);

        usdc.burn(alice, 8e18);

        assertEq(usdc.totalSupply(), 2e18);
        assertEq(usdc.balanceOf(alice), 2e18);
    }

    function testApprove() public {
        assertTrue(usdc.approve(alice, 1e18));
        assertEq(usdc.allowance(address(this), alice), 1e18);
    }

    function testIncreaseAllowance() external {
        assertEq(usdc.allowance(address(this), alice), 0);
        assertTrue(usdc.increaseAllowance(alice, 2e18));
        assertEq(usdc.allowance(address(this), alice), 2e18);
    }

    function testDescreaseAllowance() external {
        testApprove();
        assertTrue(usdc.decreaseAllowance(alice, 0.5e18));
        assertEq(usdc.allowance(address(this), alice), 0.5e18);
    }

    function testTransfer() external {
        testMint();
        vm.startPrank(alice);
        usdc.transfer(bob, 0.5e18);
        assertEq(usdc.balanceOf(bob), 0.5e18);
        assertEq(usdc.balanceOf(alice), 1.5e18);
        vm.stopPrank();
    }

    function testTransferFrom() external {
        testMint();
        vm.prank(alice);
        usdc.approve(address(this), 1e18);
        assertTrue(usdc.transferFrom(alice, bob, 0.7e18));
        assertEq(usdc.allowance(alice, address(this)), 1e18 - 0.7e18);
        assertEq(usdc.balanceOf(alice), 2e18 - 0.7e18);
        assertEq(usdc.balanceOf(bob), 0.7e18);
    }

    function testMintZero() public {
        vm.expectRevert("ERC20: mint to the zero address");
        usdc.mint(address(0), 2e18);
    }

    function testFailMintToZero() external {
        usdc.mint(address(0), 1e18);
    }

    function testFailBurnFromZero() external {
        usdc.burn(address(0), 1e18);
    }

    function testFailBurnInsufficientBalance() external {
        testMint();
        vm.prank(alice);
        usdc.burn(alice, 3e18);
    }

    function testFailApproveToZeroAddress() external {
        usdc.approve(address(0), 1e18);
    }

    function testFailApproveFromZeroAddress() external {
        vm.prank(address(0));
        usdc.approve(alice, 1e18);
    }

    function testFailTransferToZeroAddress() external {
        testMint();
        vm.prank(alice);
        usdc.transfer(address(0), 1e18);
    }

    function testFailTransferFromZeroAddress() external {
        testBurn();
        vm.prank(address(0));
        usdc.transfer(alice, 1e18);
    }

    function testFailTransferInsufficientBalance() external {
        testMint();
        vm.prank(alice);
        usdc.transfer(bob, 3e18);
    }

    function testFailTransferFromInsufficientApprove() external {
        testMint();
        vm.prank(alice);
        usdc.approve(address(this), 1e18);
        usdc.transferFrom(alice, bob, 2e18);
    }

    function testFailTransferFromInsufficientBalance() external {
        testMint();
        vm.prank(alice);
        usdc.approve(address(this), type(uint256).max);

        usdc.transferFrom(alice, bob, 3e18);
    }

    function testMint(uint256 amount) public {
        usdc.mint(alice, amount);
        assertEq(usdc.totalSupply(), usdc.balanceOf(alice));
    }

    function testBurn(uint256 amount) public {
        usdc.mint(alice, 10e18);
        if (amount > usdc.balanceOf(alice)) {
            vm.expectRevert("ERC20: burn amount exceeds balance");
            usdc.burn(alice, amount);
            return;
        } else {
            usdc.burn(alice, amount);
        }
        assertEq(usdc.balanceOf(alice), 10e18 - amount);
        assertEq(usdc.totalSupply(), 10e18 - amount);
    }

    function testApprove(uint256 amount) public {
        assertTrue(usdc.approve(alice, amount));
        assertEq(usdc.allowance(address(this), alice), amount);
    }

    function testIncreaseAllowance(uint256 amount) external {
        assertEq(usdc.allowance(address(this), alice), 0);
        assertTrue(usdc.increaseAllowance(alice, amount));
        assertEq(usdc.allowance(address(this), alice), amount);
    }

    function testDecreaseAllowance(uint256 amount) external {
        testApprove(0.5e18);
        if (amount > 0.5e18) {
            vm.expectRevert("ERC20: decreased allowance below zero");
            usdc.decreaseAllowance(alice, amount);
            return ();
        }
        assertTrue(usdc.decreaseAllowance(alice, amount));
        assertEq(usdc.allowance(address(this), alice), 0.5e18 - amount);
    }

    function testTransfer(uint256 amount) external {
        testMint(10e18);
        if (amount > 10e18) {
            vm.startPrank(alice);
            vm.expectRevert("ERC20: transfer amount exceeds balance");
            usdc.transfer(bob, amount);
            return;
        } else {
            vm.prank(alice);
            usdc.transfer(bob, amount);
        }
        assertEq(usdc.balanceOf(bob), amount);
        vm.stopPrank();
    }
}
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.16;

import "forge-std/Test.sol";
import "../mock/USDT.sol";

contract USDTTest is Test {
    USDT public usdt;

    // hardhat getSigner() -> vm.addr()
    address public alice = vm.addr(0x1);
    address public bob = vm.addr(0x2);

    function setUp() public {
        usdt = new USDT();
    }

    function testName() external {
        assertEq("Tether Token", usdt.name());
    }

    function testSymbol() external {
        assertEq("USDT", usdt.symbol());
    }

    function testMint() public {
        usdt.mint(alice, 2e18);
        assertEq(usdt.totalSupply(), usdt.balanceOf(alice));
    }

    function testMint2() public {
        usdt.mint(bob, 2e18);
        assertEq(2e18, usdt.balanceOf(bob));
    }

    function testBurn() public {
        usdt.mint(alice, 10e18);
        assertEq(usdt.balanceOf(alice), 10e18);

        usdt.burn(alice, 8e18);

        assertEq(usdt.totalSupply(), 2e18);
        assertEq(usdt.balanceOf(alice), 2e18);
    }

    function testBurn2() public {
        usdt.mint(bob, 10e18);
        assertEq(usdt.balanceOf(bob), 10e18);

        usdt.burn(bob, 8e18);

        assertEq(usdt.totalSupply(), 2e18);
        assertEq(usdt.balanceOf(bob), 2e18);
    }

    function testApprove() public {
        assertTrue(usdt.approve(alice, 1e18));
        assertEq(usdt.allowance(address(this), alice), 1e18);
    }

    function testIncreaseAllowance() external {
        assertEq(usdt.allowance(address(this), alice), 0);
        assertTrue(usdt.increaseAllowance(alice, 2e18));
        assertEq(usdt.allowance(address(this), alice), 2e18);
    }

    function testDescreaseAllowance() external {
        testApprove();
        assertTrue(usdt.decreaseAllowance(alice, 0.5e18));
        assertEq(usdt.allowance(address(this), alice), 0.5e18);
    }

    function testTransfer() external {
        testMint();
        vm.startPrank(alice);
        usdt.transfer(bob, 0.5e18);
        assertEq(usdt.balanceOf(bob), 0.5e18);
        assertEq(usdt.balanceOf(alice), 1.5e18);
        vm.stopPrank();
    }

    function testTransferFrom() external {
        testMint();
        vm.prank(alice);
        usdt.approve(address(this), 1e18);
        assertTrue(usdt.transferFrom(alice, bob, 0.7e18));
        assertEq(usdt.allowance(alice, address(this)), 1e18 - 0.7e18);
        assertEq(usdt.balanceOf(alice), 2e18 - 0.7e18);
        assertEq(usdt.balanceOf(bob), 0.7e18);
    }

    function testMintZero() public {
        vm.expectRevert("ERC20: mint to the zero address");
        usdt.mint(address(0), 2e18);
    }

    function testFailMintToZero() external {
        usdt.mint(address(0), 1e18);
    }

    function testFailBurnFromZero() external {
        usdt.burn(address(0), 1e18);
    }

    function testFailBurnInsufficientBalance() external {
        testMint();
        vm.prank(alice);
        usdt.burn(alice, 3e18);
    }

    function testFailApproveToZeroAddress() external {
        usdt.approve(address(0), 1e18);
    }

    function testFailApproveFromZeroAddress() external {
        vm.prank(address(0));
        usdt.approve(alice, 1e18);
    }

    function testFailTransferToZeroAddress() external {
        testMint();
        vm.prank(alice);
        usdt.transfer(address(0), 1e18);
    }

    function testFailTransferFromZeroAddress() external {
        testBurn();
        vm.prank(address(0));
        usdt.transfer(alice, 1e18);
    }

    function testFailTransferInsufficientBalance() external {
        testMint();
        vm.prank(alice);
        usdt.transfer(bob, 3e18);
    }

    function testFailTransferFromInsufficientApprove() external {
        testMint();
        vm.prank(alice);
        usdt.approve(address(this), 1e18);
        usdt.transferFrom(alice, bob, 2e18);
    }

    function testFailTransferFromInsufficientBalance() external {
        testMint();
        vm.prank(alice);
        usdt.approve(address(this), type(uint256).max);

        usdt.transferFrom(alice, bob, 3e18);
    }

    function testMint(uint256 amount) public {
        usdt.mint(alice, amount);
        assertEq(usdt.totalSupply(), usdt.balanceOf(alice));
    }

    function testBurn(uint256 amount) public {
        usdt.mint(alice, 10e18);
        if (amount > usdt.balanceOf(alice)) {
            vm.expectRevert("ERC20: burn amount exceeds balance");
            usdt.burn(alice, amount);
            return;
        } else {
            usdt.burn(alice, amount);
        }
        assertEq(usdt.balanceOf(alice), 10e18 - amount);
        assertEq(usdt.totalSupply(), 10e18 - amount);
    }

    function testApprove(uint256 amount) public {
        assertTrue(usdt.approve(alice, amount));
        assertEq(usdt.allowance(address(this), alice), amount);
    }

    function testIncreaseAllowance(uint256 amount) external {
        assertEq(usdt.allowance(address(this), alice), 0);
        assertTrue(usdt.increaseAllowance(alice, amount));
        assertEq(usdt.allowance(address(this), alice), amount);
    }

    function testDecreaseAllowance(uint256 amount) external {
        testApprove(0.5e18);
        if (amount > 0.5e18) {
            vm.expectRevert("ERC20: decreased allowance below zero");
            usdt.decreaseAllowance(alice, amount);
            return ();
        }
        assertTrue(usdt.decreaseAllowance(alice, amount));
        assertEq(usdt.allowance(address(this), alice), 0.5e18 - amount);
    }

    function testTransfer(uint256 amount) external {
        testMint(10e18);
        if (amount > 10e18) {
            vm.startPrank(alice);
            vm.expectRevert("ERC20: transfer amount exceeds balance");
            usdt.transfer(bob, amount);
            return;
        } else {
            vm.prank(alice);
            usdt.transfer(bob, amount);
        }
        assertEq(usdt.balanceOf(bob), amount);
        vm.stopPrank();
    }
}

Output

image

image

image

@0xAurelou 0xAurelou added the T-bug Type: bug label Jan 20, 2023
@0xAurelou 0xAurelou changed the title [BUG] [BUG] Code coverage Jan 20, 2023
@PaulRBerg
Copy link
Contributor

PaulRBerg commented Jan 21, 2023

Hey @0xAurelou, a friendly suggestion - your issue would be more readable if you put the code in a collapsible Markdown section.

@0xAurelou
Copy link
Author

Hello @PaulRBerg,
My issue have been updated hope it's better in this way 👍

@0xAurelou
Copy link
Author

@PaulRBerg No Update or ETA on this issue ?

@PaulRBerg
Copy link
Contributor

@0xAurelou I am not an active Foundry maintainer.

@0xAurelou
Copy link
Author

Sorry my Bad I thought you were.
Cheers

@KholdStare
Copy link
Contributor

@onbjerg Seems like a few code coverage bugs are related to more than one contract having a similar interface. I think code coverage gets attributed to the wrong function/contract if they share bytecode or naming? Not sure what it is, but I've seen several issues with very similar symptoms. Any insight?

Thank you

@grandizzy
Copy link
Collaborator

looks similar with #6875 which was solved in #8214 please reopen if you still see the issue with latest

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-bug Type: bug
Projects
None yet
Development

No branches or pull requests

4 participants