Comparing msg.value with 'require' can be really confusing

First of all, I am using BSC, the solidity is ^0.8.0. The contract is simple enough, there are only 2 functions here, one is using require, another is not. The mission of this contract is to test msg.value in require behavior. I have deployed and verifited it on BSC, the address is :0x971Fe0eD151f5F083382b7848648891E1b716f82, if you want to take a look.

pragma solidity ^0.8.0;

contract Demo {
    uint256 public minAmount; // minimum amount (denominated in wei)

    event LogMsgValueIsLarger(uint256 msgValue, uint256 minAmount);
    event LogMinAmountIsLarger(uint256 msgValue, uint256 minAmount);

        uint256 _minAmount
    ) {
        minAmount = _minAmount;

    function func1() external payable {
        require(msg.value >= minAmount, "Msg value must be greater than minAmount");

        // Do something...

    function func2() external payable {
        if (msg.value >= minAmount) {
            emit LogMsgValueIsLarger(msg.value, minAmount);
        } else {
            emit LogMinAmountIsLarger(msg.value, minAmount);

        // Do something...

Then, I write some javascript with web3.js, to test it out.

const Web3 = require('web3');
const web3 = new Web3(new Web3.providers.HttpProvider(''));
const fs = require('fs');
const CONTRACT_ABI = JSON.parse(fs.readFileSync('./abis/Demo.json'))['abi'];
const CONTRACT_ADDRRESS = '0x971Fe0eD151f5F083382b7848648891E1b716f82';

async function send(user, transaction, amount) {
    const gasPrice = await web3.eth.getGasPrice();
    const options  = {
        to: transaction._parent._address,
        data: transaction.encodeABI(),
        gas: await transaction.estimateGas({from: user.address}),
        gasPrice: gasPrice,
        value: web3.utils.toWei(amount, 'ether')
    const signed  = await web3.eth.accounts.signTransaction(options, user.privateKey);
    const receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction);
    return receipt;

(async () => {
    const contract = new web3.eth.Contract(CONTRACT_ABI, CONTRACT_ADDRRESS);
    const user = web3.eth.accounts.privateKeyToAccount(MY_USER_PRIVATE_KEY); // input yours
    const tx1 = contract.methods.func1();
    const receipt1 = await send(user, tx1, '0.001');

    const tx2 = contract.methods.func2();
    const receipt2 = await send(user, tx2, '0.001');


The default minAmount is 0.001, so if everything is OK, you should pass the require of (msg.value >= minAmount), but somehow, func1 is not pass, func2 is pass. This is where I fell confused

NOTICE If you run this js file, you have change to lose 0.001 BNB, but in func1 you will get revert msg by Msg value must be greater than minAmount"