0

I called

/**
 *Submitted for verification at Etherscan.io on 2021-02-21
*/

contract m_quiz
{
    function Try(string memory _response) public payable
    {
        require(msg.sender == tx.origin);

        if(responseHash == keccak256(abi.encode(_response)) && msg.value > 1 ether)
        {
            payable(msg.sender).transfer(address(this).balance);
        }
    }

    string public question;

    bytes32 responseHash;

    mapping (bytes32=>bool) admin;

    function Start(string calldata _question, string calldata _response) public payable isAdmin{
        if(responseHash==0x0){
            responseHash = keccak256(abi.encode(_response));
            question = _question;
        }
    }

    function Stop() public payable isAdmin {
        payable(msg.sender).transfer(address(this).balance);
    }

    function New(string calldata _question, bytes32 _responseHash) public payable isAdmin {
        question = _question;
        responseHash = _responseHash;
    }

    constructor(bytes32[] memory admins) {
        for(uint256 i=0; i< admins.length; i++){
            admin[admins[i]] = true;
        }
    }

    modifier isAdmin(){
        require(admin[keccak256(abi.encodePacked(msg.sender))]);
        _;
    }

    fallback() external {}
}

contract's Try function by passing the same string which was passed in Start function. I checked hex. Can someone help me why Try function call https://etherscan.io/tx/0x096a060d64d833c55fd83b2ea4ec209578dc3316d863de3a3de63692e8476628 did not initiate balance transfer. Although txn got executed, still balance transfer didn't happen

3
  • 1
    Warning to anyone who looks at this: this is a typical honeypot/phishing contract. As with previous similar posts on this site, the author is a new poster whose affiliation is unknown and potentially dubious. (Apologies, Dark Lord.) – Richard Horrocks Feb 24 at 15:10
  • This is not my contract, I lost 1 ether in this, that is why I wanted to understand what was I doing wrong. – Dark Lord Feb 24 at 15:12
  • Do you know if responseHash was 0x0 at the time? – The Renaissance Feb 24 at 16:35
2

For people to follow along...

I called contract's Try function by passing the same string which was passed in Start function.

The Start function was called in this transaction, and passed the following arguments, together with the 20 ETH seed:

0   _question   string  What two things you can never eat for breakfast?
1   _response   string  lunch and Dinner

That's a lot of money that someone was seemingly giving away for very little effort...

Looking through the contract code, and the other transactions listed in Etherscan, there seems no reason why sending the same response wouldn't work.

However...

Looking at the list of transactions coming into the contract in Etherchain (not Etherscan), this contract -> contract transaction was initiated shortly after the contract was created.

This transaction, which isn't presented in Etherscan's view, actually set the responseHash variable to a non-0x0 value before Start was called. This means that when Start was called, the if (responseHash==0x0) check returned false, and responseHash wouldn't be set to the value everyone thinks it would be set to.

The honeypot basically takes advantage of a limitation in the way Etherscan presents data (and the fact that most people only use Etherscan).

It appears that the owner has drained all funds from the contract.

2

For all those who would fall for Dark Lord's honey pot or future similar ones.

I remember asking Etherscan to also list internal transactions that do not transfer Ether. They have now implemented this feature, that you can activate here by toggling "advanced".

This honey pot relies on:

  1. The Start function being called in the clear with question and solution. The newbie cannot believe his luck because the answer is right there.
  2. An admin calling the New function but from another contract so that the call appears only in internal transactions advanced mode.
  3. This New function replacing the hash without changing the response. So now the link is broken between the response and "its hash".
  4. The responseHash being internal so that you cannot easily get it from Etherscan. If you had access to it, you would see that it no longer matches that of Start. Actually, you can get it, but with web3.eth.getStorageAt(address, 1) or something like that.
  5. The list of admins being known only by their hash, so that you cannot look around the list of admins to see if they sent this New call. Unless you use Etherscan for that.
  6. require(msg.sender == tx.origin) in Try preventing you from calling it from another contract, which could check that it got the money and revert otherwise.

I wrote a blog post almost 3 years ago for this same thing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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