1

Lets say that I have a smart contract C witch has a function setf(uint256). Also let's assume that there are many users(with different accounts) that want to call that function with argument 5 for example. As i understand each of them will make a logically same transaction to the same contract function with the same argument and each of them will pay the same gas. Is there any way to reject the rest of the pending transactions when the first one of them is mined and avoid the gas? If every user use the same account I could use the same nonce in all the transactions and only one would be mined. In the case of different accounts is there any way?

3 Answers 3

2

I think of 2 ways but it’s not for general case.

I’m gonna use set(uint256) function as an example, it take an input an set a variable let say x that input value. Here is the code:

function set(uint256 y) public {
    revert(y == x);
    x = y;
}

it’s goona revert if the value you pass it equal to the value of x. Let just say when the first transaction got mined then all other pending transaction got revert.

Second example i gonna take it from the erc20 allowance / transferFrom possible attack vector solution. You can read the code from here: https://gist.github.com/flygoing/836666010f0a5bf91abac211df938611.

The idea is that once you set a value to a variable then to set it again you need to reset to value 0 then you can set a new value. So when many people send the same value, after the first transaction get mined, the rest is going to get revert because that variable has already been set

1

Just to add to @haxerl's good answer: you could use a proxy contract which does the logic for you. So the idea is the same but the proxy account would act as an intermediare which is only used for checking for duplicate transactions.

The benefit of this is that you can code the actual contract normally and then afterwards just include the proxy contract in-between to do the actual checking. The downside is that your "context" changes - for example msg.sender would be the proxy account instead of the actual sender (unless you do some ugly delegatecall magic).

2
  • So as I understand, with these solutions they just pay the gas for the smart contract call and the function execution up to revert(). Right ?
    – Mike T
    Commented Mar 7, 2019 at 19:13
  • Yes, that is correct Commented Mar 7, 2019 at 19:18
0

A very simple solution: you can have a nonce in your contract storage.

uint256 contractNonce;
uint256 f;

function setF(uint256 newF, uint256 providedNonce) public {
  revert(providedNonce <= contractNonce);
  f = newF;
  contractNonce++;
}

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.