Let's say I have the following in my smart contract:

string passwordHash;
uint money;
function checkPassword(string cleanPassword, string newPasswordHash)[...]

When running the function checkPassword, I run it with the clean password. The clean password is then checked as sha256 with the passwordHash and if it's correct, the sender (normally me) gets the funds. But now following problem:

What if someone spectates my address, runs a transaction with more gas and gets "selected" before me: Is there a way to prevent someone "stealing the password from my transaction"? Is the only way to me run with more than enough gas?


No, there is nothing you can do in order to be mined before someone if not paying more gas than he pays...

This is called the problem of the Man in the Middle (MIM) and exist for mining as well.

What you can truly do is to find a way to use the msg.sender as part of the valid hash. When he shall try to reuse your “password, he simply do not succeed because his address is different from your.

I.e. the password must be related to the address of the user.

| improve this answer | |
  • Thank you! What if the address can't be used and everyone should be able to call? I want to develop a retreive function where I can access the funds when for example my private key gets hacked or lost but I for example have stored the password in another safe space (as I do not need the password generally but for the private key there are more attacking points). The password is then similar to a private key in terms of length and randomness. But it shouldn't be able to be called before me. – dkb Feb 8 '19 at 21:14
  • This problem is unsolved without a zero knowledge approach or something similar. Try to read about zsnark and similar zero knowledge algorithms. There is a lot of articles on this argument. At the moment does not exist something very simple able to do what you want, not in Ethereum using solidity, but a lot of work is on going on the matter. – Rick Park Feb 8 '19 at 22:36

If I'm reading the question right, you're concerned with the clear password getting grabbed before it's mined, then used by an attacker with more gas. If so, this is a rephrasing of the frontrunning problem (here's a link to how it's described on Ethereum's wiki). Zero-Knowledge proofs are an option, but may be overkill. Let's explore some other options.

Modifiers if you know all addresses that will need to access this function, you can use a modifier to whitelist them.

addresses_with_access = [0x...,0x...,0x...];
modifier onlyPrivileged {
    privileged = false;
    for (uint i=0; i < addresses_with_access.length; i++) {
        if(msg.sender === addresses_with_access[i]){
            privileged = true;
    require privileged;

function checkPassword(string cleanPassword, string newPasswordHash) onlyPrivileged {

(That is, in Solidity. Vyper doesn't have modifiers. Your code above is in Solidity, though, and if you'd like Vyper, you can have a list of addresses and assert that msg.sender is a member of the list at the beginning of the function with.)

def checkPassword(string cleanPassword, string newPasswordHash):
    assert msg.sender is in addresses_with_access

Precommit if you can implement a pre-commit, that should be enough. Here is another EthStackExchange Q&A about that. I'm not sure this will help all they way. It may be able to stop frontrunning, but not griefing. Griefing is where the attacker can't steal your information and perform the tx themselves, but can still stop you from doing what you want to do.

Submarines there is a library dedicated to submarine transactions to defeat frontrunning. Their website is here, repo, HackerNoon article.

Update: Just found an OpenZeppelin article here that talks at length about solutions to mitigate frontrunning, and contains solutions not discussed here (in addition to submarines and commit/reveal).

| improve this answer | |

Thank you both for your answers and sorry for my late answer. What I have done are two security measurements.

1. Double Password
The first measurement/change I have added is not relying on one single cleartext password function. When I or a bad actor enter the password for phase 1, the entering of the cleartext password will be blocked for 2 hours and the sender of the password is marked as the current unlocker. He can then send an other transaction with the second password. If he sends the second password within that two hours, he is the new contract owner. If someone else send the second password, they won't be the new owner.

2. Fee to the current contract owner The second measurement I have implemented is a fee of 1 ethereum to enable the first phase. That means, if someone sends the password transaction for phase 1 before me, he is paying 1 ether to me but still has not the second password. Also I have implemented a function to increase or decrease that price. The worst case could be that the contract is locked for a long time and I get 1 ether or more every 2 hours :)

| improve this answer | |

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.