Wrong sending to a mainet account

I have received a ticket with the following problem:

Someone sent a user the address of a pre-sale contract on testnet for testing.
But the user somehow sent a real BNB to the same address in the mainet.

This is the address of the pre-sale contract on testnet:

And this is the same address in mainet in which you see the balance of the shipment:

I have various doubts...

Was it a coincidence?
That is, since there is an account with the same hash, has an unknown user received the money?

If the address had not existed in the mainet, would the transaction have been reversed?

I just realized something that is curious to say the least. This transaction in theory by mistake, has called a token purchase function ... as the image can be seen ...

Now, if I look at the BEP-20 token transaction, with the same date, we verify that a token theft contract has interacted with that account.

Let's see if he interpreted what happened correctly.
Has the user mistakenly sent money to an account that was prepared to be stolen?

Is such bad luck possible?

In Ethereum every address exists. There's no possibility of an address not existing (as long as the address is a valid ethereum address with numbers, a-f etc.). Addresses don't get "activated". Unfortunately these funds are most likely lost forever.

The token transaction you mentioned is a scam token. Sometimes you receive random tokens that come out of nowhere because the projects want to get attention. But this token is a token named after an URL that will SCAM YOU. DO NOT DO ANYTHING ON THAT URL! If you happen to visit it, you will see that it looks like a swap page. But if you try to swap and it says "approve", you actually approve an address to spend an other token you own. In my case it would try to spend WETH. If I would have approved, because some users do not see the difference in time (they think they approve Zepe but actually approve an other token that has a lot of worth in their account), a bot of the scammers will see the approval and instantly after transfer funds out of your account.

Thank you very much for your reply and welcome to the community.

Then the user is blameless. That is to say, it was wrong to send and also that account was hacked. Since it strikes me that the two hashes are at the same time in that account. When it was wrong to send the transaction of that token was activated. It seems like too much of a coincidence.

Thank you :slight_smile:
Yes, this theoretically is not the users fault. Depending on where the user was told to do the test, I'd say a frontend mistake happened here (if it even exists). When users do tests on a dApp, the dApp is responsible for testing if the user is on the correct chain (in this case on the testnet instead of the mainnet). If it fails to do so, such things like here can happen where the user was in the mainnet instead of in the testnet. Of course, the user could also have been more cautious but things happen sometimes.

Yes, the failure has been through a dapp. But the type of network is controlled. Therefore I do not understand how the user has been able to interact with the contract from the mainet.

  async function changeNetwork() {
  
    if (typeof window.ethereum !== 'undefined') {
    // detect Network account change
    window.ethereum.on('networkChanged', async function(networkId) {
      console.log('cambio de red efectuado..',networkId);
      await isconnectedMetamask();
    });

    }
  }
async function addNetwork() {

    let networkData = [{

            chainId: "0x61",

            chainName: "BSCTESTNET",

            rpcUrls: ["https://data-seed-prebsc-2-s3.binance.org:8545"],

            nativeCurrency: {

              name: "BINANCE COIN",

              symbol: "BNB",

              decimals: 18,

            },

            blockExplorerUrls: ["https://testnet.bscscan.com/"],

          },

        ];

      // agregar red o cambiar red

      return window.ethereum.request({

        method: "wallet_addEthereumChain",

        params: networkData,

      });

  }

The only explanation I can think of is that the user entered the contract address directly in the metamask and transferred BNBs directly. Activating the fallback that activates the purchase of tokens ...

However, there is something that I do not understand ...

How can you activate a method that is in the testnet from the mainet? If the shipment was in the mainet in which the pre-sale contract is not, how is it possible for the method to appear in the mainet?
as you can check in the transaction capture


Can there be a crossing of chains? How has something like this been possible?

Methods get picked up by etherscan. It just looks at the function selector (the 1st 4 bytes of the transaction data) and goes "hey, i know that selector! Its used in other contracts for a "buy tokens" function, so im just going to assume its the exact same here". Now it is perfectly possible to call a function to a non contract account (its exactly what happened here). In this case, the transaction data gets completely ignored (since it doesnt correspond to any code to execute since this address on mainnet isnt used to store code) and only the value transfer is completed (i.e. BNB get sent)

Ok, thanks for the reply.
Although I still do not understand very well how etherscan captures a method that is not in its network.
Since the id method should only be available on his network, that is, on the testnet.
In essence it has been a transfer on mainet.
I do not understand how you can execute the method in the testnet but do the transfer by in mainet.
It still makes me dark.

What does the isconnectedMetamask() do? From what you posted, addNetwork() only adds a network, but does not actually check if the user is connected to that network (it basically asks "Do you want to add network X to MetaMask" and a few warnings). If isconnectedMetamask() only checks if the user has MetaMask (as the name suggest), but not if the user uses the testnet, then that's the fault. The transaction implies that the user was in fact on mainnet but calling a function provided by the dApp. Functions are converted to bytecode and an average user does not know neither the exact function parameters (the user would have to take the input, convert it to bytecode, create a custom function call), nor is there a contract on the mainnet and even the contract on testnet is not verified. Almost impossible that the user did all of that work manually. So the dApp definetly is responsible for this imo. If isconnectedMetamask() does check the testnet, then there can be an other issue too (like the check not working properly or so).

thanks for your answer

Does many things:

captures the user.

trims the account and introduces it to REACT status

Acquire the user's balance and enter it in the REACT status

check the metamask network, capture it, and if it is not the one you touch, the modal will skip to change the network. THIS IS THE POINT. We do not force the network change.

If you are in the right network, check if you have a balance of the tokens, capture them, and store them in the REACT state

async function isconnectedMetamask() {

      const accounts = await window.ethereum.request({ method: 'eth_accounts' });
      let cuentaUsuario = accounts[0];

      if (cuentaUsuario) {
        
        let subini = cuentaUsuario.substr(0,4);
        let subfinal = cuentaUsuario.substr(-4,4);
        //let cuentaRecortada = subini + '...' + subfinal;
        let cuentaRecortada = `${subini} ... ${subfinal}`;
        setUserAccount(cuentaUsuario);

        document.querySelector('#wallet').innerHTML = cuentaRecortada;

        const provider = new ethers.providers.Web3Provider(window.ethereum);
        const contractUserBalance = await provider.getBalance(cuentaUsuario);
        let amount = ethers.utils.formatEther(contractUserBalance).toString();
        let result = Number.parseFloat(amount).toFixed(2);
        let bnbButton = document.querySelector('#bnbs');
        bnbButton.classList.remove('d-none');
        bnbButton.innerHTML = `${result} BNB`;
        setUserBalance(`${result} BNB`);

        const network = await provider.getNetwork();
        console.log('network', network.name);
        setNetwork(network.name);

        const contract = new ethers.Contract(presaleaddress, Presale.abi, provider);
        try {
          const balanceOtiums = await contract.getBalanceOtium({ from: cuentaUsuario });
          let amountOtiums = ethers.utils.formatEther(balanceOtiums).toString();
          let otiums = Number.parseFloat(amountOtiums).toFixed(0);
          setUserBalanceOtiums(otiums);
          document.querySelector('#otiums').classList.remove('d-none');
        } catch (err) {
          console.log("Error: ", err)
        }
      
      }
  }

Best (and probably only) way to prove if that's the case or not is very simple, it's to visit the site in mainnet. If asked for a network change, do on purpose not change it. If you don't change it, stay in mainnet and still can run the functions or if there's not even an error message visible to the user stating that they're in mainnet, then it's proved that that was the reason. I as of now don't see any other way on how this happened other than a user staying on mainnet while browsing your dApp. If the funds would have went to a user's address or any other address, maybe the user could have tried to scam you. But this way there's absolutely no advantage for the user.

everything you say is totally logical and matches my way of thinking about the matter.

The daap will have to be ensured so that if the user does not change the network, all access to the contract is blocked.

We have learned something from all this. Confirm that what you think that something is impossible to happen, really is.

Thanks for your reply

Thanks alot, great to hear that I could help. And yes, a dApp holds a lot of responsibility - a lot of things can go wrong there, too. All the best!

Thanks for your good tips to me. The best for you too

1 Like