pragma solidity 0.7.6;

library SafeERC20 {
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {}
}

interface IERC20 {
    function transferFrom(address, address, uint256) external returns(bool);
}

contract ERC20 is IERC20 {
    function transferFrom(address from, address to, uint256 amount) external override returns(bool) {
        return true;
    }
}

contract C {
    using SafeERC20 for IERC20;

    IERC20 erc20;
    address notsend;
    address send;

    constructor() {
        erc20 = new ERC20();
        notsend = address(0x3);
        send = msg.sender;
    }

    function good1(address to, uint256 am) public {
        address from_msgsender = msg.sender;
        erc20.transferFrom(from_msgsender, to, am);
    }

    function bad1(address to, uint256 am) public {
        erc20.transferFrom(notsend, to, am);
    }

    function good2(address to, uint256 am) public {
        address from_msgsender = msg.sender;
        int_transferFrom(from_msgsender, to, am);
    }

    // This is not detected
    function bad2(address from, address to, uint256 am) public {
        int_transferFrom(from, to, am);
    }

    function int_transferFrom(address from, address to, uint256 amount) internal {
        erc20.transferFrom(from, to, amount);
    }

    function good3(address to, uint256 amount) external {
        erc20.safeTransferFrom(msg.sender, to, amount);
    }

    function bad3(address from, address to, uint256 amount) external {
        erc20.safeTransferFrom(from, to, amount);
    }    
    
    function good4(address to, uint256 amount) external {
        SafeERC20.safeTransferFrom(erc20, msg.sender, to, amount);
    }

    function bad4(address from, address to, uint256 amount) external {
        SafeERC20.safeTransferFrom(erc20, from, to, amount);
    }

    function good5(address to, uint256 amount) external {
        SafeERC20.safeTransferFrom(erc20, address(this), to, amount);
    }

    function good6(address from, address to, uint256 amount) external {
        erc20.safeTransferFrom(address(this), to, amount);
    }

}
