contract1.sol:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
abstract contract Contract1 {
    error Error1(address account);
}
contract2.sol:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {Contract1} from "./contract1.sol";
contract Contract2 is Contract1 {    
    error Error2(address account);
    function customError1() public view {
        revert Error1(msg.sender);
    }
    function customError2() public view {
        revert Error2(msg.sender);
    }
}
test script:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {Test, console} from "forge-std/Test.sol";
import {Contract2} from "../src/contract2.sol";
contract ErrorTest is Test {
    Contract2 public contract2;
    function setUp() public {
        contract2 = new Contract2();
    }
    function test_customError1() public {                vm.expectRevert(abi.encodeWithSelector(Contract2.Error1.selector, msg.sender));
        vm.prank(address(123));
        contract2.customError1();
    }
    function test_customError2() public {       vm.expectRevert(abi.encodeWithSelector(Contract2.Error2.selector, msg.sender));
        vm.prank(address(123));
        contract2.customError2();
    }
}
报错信息:
Error: 
Compiler run failed:
Error (9582): Member "Error1" not found or not visible after argument-dependent lookup in type(contract Contract2).
  --> test/test.t.sol:15:48:
   |
15 |         vm.expectRevert(abi.encodeWithSelector(Contract2.Error1.selector, msg.sender));
   |                                           
测试 Error2 没有问题,但是 Error1 就不行。。。
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {Test, console} from "forge-std/Test.sol";
import {Contract1,Contract2} from "../src/Counter.sol";
contract ErrorTest is Test {
    Contract2 public contract2;
    function setUp() public {
        contract2 = new Contract2();
    }
   function test_customError1() public {                
        vm.expectRevert(abi.encodeWithSelector(Contract1.Error1.selector, msg.sender));
        vm.prank(msg.sender);
        contract2.customError1();
    }
    function test_customError2() public {       
        vm.expectRevert(abi.encodeWithSelector(Contract2.Error2.selector, msg.sender));
        vm.prank(msg.sender);
        contract2.customError2();
    }
}
从抽象合约里引入就好了