0

I have my own smart contract. Users on my webpage needs to first approve (increaseAllowance) and then they call "donate" function and part of the assets are sent to my vault and the other part goes to the address of another user.

Strange thing is that everything worked fine, after couple of months I think my app was hacked somehow. Now when user call increaseAllowance, assets are sent immediately to another smart contract I know nothing about. This happens before user call my true "donate" function and ofcourse call to my "donate" function fails, because assets are already drained.

tx = await tokenContract.increaseAllowance(smartContractAddress, amount, {
    gasLimit: gasLimit,
    gasPrice: gasPrice
});

After this call, assets are immediately sent to this contract: 0xa847991e081c2dcabc960839c8c2b92047fbc435

If you look to contract creator, there is warning: enter image description here

This is malicious transaction: https://polygonscan.com/tx/0x2b6694c82f5ab8159111b15bc5fb2440a3d8d034927b4dfdab5d38f9a47d413f

Real transaction should look like this: https://polygonscan.com/tx/0x5a527c8fd1ca8bffc7f9393c5a97940ef10b71c64461c4caed928ddcab06a1cb

Can someone tell me how is this possible? User is giving permision for token transfer to my smart contract address and yet assets are sent out by malicious user to a contract I never interacted with.

** Noone lost any funds (except me, rly small amount) and I really wanna learn how to avoid such things. Thank you.

4
  • Seems like your front-end code is wrong. Those two transactions are not even calling the same method. Can you share the part you initiate tokenContract? Mar 22, 2023 at 7:47
  • I don't think my front end is the problem, because I redeployed completely same smart contract and it works as it should. If I call old smart contract address (which is the same, only address is different) funds are stolen. i.imgur.com/ECBoamm.png Mar 22, 2023 at 12:00
  • Right, the first transaction is calling 0x210ff46c, which I think is the increaseAllowance function, the second transaction is calling 0x9328264d, which is the donate function. Yeah I guess the issue can be with your smart contract. Are you using a reliable library? Can't provide much help without your solidity code here. Mar 23, 2023 at 3:40
  • @Wuzhong-ChainstackDevEx polygonscan.com/address/… Mar 24, 2023 at 12:05

1 Answer 1

2

From what I see the malicious contract attacked the old MetaOchtapas contract

That contract didn't have any verification regarding the sender, so anyone could have withdraw the funds once the proxy was approved by the user.

function donate(IERC20Upgradeable token, address from, address to, uint256 amount) public {
    // SEND FEE TO METAOCHTAPAS WALLET
    metaOchtapasWalletAddress = 0xA0F0E2a0b72A823535A2A203b3e51a34F8228F76;
    donationFee = (amount * 5) / 100;
    SafeERC20Upgradeable.safeTransferFrom(token, from, metaOchtapasWalletAddress, donationFee);
    emit FeeSent(token, from, metaOchtapasWalletAddress, donationFee);

    // SEND ASSETS TO CREATOR WALLET
    donationAmount = amount - donationFee;
    SafeERC20Upgradeable.safeTransferFrom(token, from, to, donationAmount);
    emit DonationSent(token, from, to, amount);
}

The new MetaOchtapas implementation added signature verification

    // VERIFY SIGNATURE
    require(
        verify(from, to, amount, message, nonce, signature),
        "Invalid signature"
    );

It has a few problems by itself:

  • allows signature reuse
  • message and nonce are user controlled

I really suggest to hire an auditing firm, or hire better developers.

3
  • This is exactly what I am trying to understand. So when user called increaseAllowance, attacker changed "address to" in a donate function and execute it before user really called donate function himself, right? So I guess, implementing signature will solve this? Mar 24, 2023 at 10:18
  • @PoorMillionaire When you call increaseAllowance(X,amount) you authorize X to withdraw amount+previous_amount. The problem with MetaOchtapas contract is that it allows anyone to call donate(). After a user calls increaseAllowance(MetaOchtapas,amount) then anyone can call donate and withdraw funds to themselves.
    – Ismael
    Mar 24, 2023 at 18:12
  • I understand. Thank you. Mar 25, 2023 at 10:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.