3

I asked this question before but I worded it ambiguosly.

I have a function in a smartcontract that should only be accessible by users who have a signature, issued by the contract owner. The goal is, to allow a user to use this signature only once and get rejected every try thereafter. This signature will be issued off-chain and is unique to each user.

The issue with this approach however, is that, since the signatures would be issued off-chain, nothing would stop a user from saving their signature and to just use it to perform the transaction a second time.

The reason I am not just creating a mapping or an array of users who are allowed to access this function, or who have already accessed it, is that operations on those data structures can quickly become very expensive at scale. So I would like to avoid those.

Do you see any way to achieve this without resorting to on chain lists or mappings?

Thanks!

2 Answers 2

3

You pretty much need a mapping, but mappings don't have to be that expensive. It would just be a mapping(uint256 => bool) showing whether the address has used that signature yet, and would cost I believe 20k gas to update per user.

Is there something I'm missing here that would make this too expensive?

2
  • Wow thank you it looks like I was missing something big. I was stuck thinking that I'd need to pre seed the mapping with addresses allowed.
    – HappyHippo
    Commented Feb 16, 2022 at 16:34
  • Just reread the question, I think a merkle tree will solve your problem better than just a mapping.
    – Meriadoc
    Commented Jun 17, 2022 at 0:02
1

There are two possible ways, one is to keep track of a nonce in the smart contract, and increment each time a transaction has been submitted. The nonce is used to prevent replay attacks and as such results in a signature being valid only once.

You can then generate the hash by including the nonce before recovering the signer.

bytes32 txHash = keccak256(abi.encode(TXTYPE_HASH, value, keccak256(data), nonce));

Another way is to keep a mapping of signatures and check if it has been used.

mapping(bytes => bool) public signaturesUsed

You can then add to the mapping the signature once used.

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.