2

I'm creating an app where users submit a request via a button, and then the app requires (for security reasons) that they not be able to return to that page for a fairly short while (say, ten to twenty seconds). The app is not intended for a purpose such that a wait like this should be a major issue (it's intended as a frontend for a kind of Ethereum voting app, ergo a person should use it fairly infrequently.

The contract has built-in protections to prevent the same account from voting multiple times, but these don't work if the user can return to the voting screen before their vote is mined, which takes about 10-15 seconds). Simply putting a lengthy delay each time the page is loaded seems feasible, but might irritate users.

I had an idea to locally store a user's details after they cast a vote, and to disallow anyone from interacting with the voting page if their details were in the list of people who've voted already (which would be updated such that a name should be removed from it a short time after). However, while this might work, it seems like it'd be a pain to scale up, since the whole array would need to be iterated constantly.

Does anyone have a better way that I could ensure that people aren't able to return to (or at least, interact with) the first page for 10-20 seconds after leaving it? Thanks.

tadman
  • 208,517
  • 23
  • 234
  • 262
  • Breaking up that enormous wall of text into paragraphs really helps us understand what you're getting at more quickly. Take a little time to make your question clear, it goes a long way in the end. – tadman Aug 15 '18 at 17:06
  • Well the best solution is a serverside one. Clientside can be sidestepped pretty easily. – epascarello Aug 15 '18 at 17:06
  • 1
    How are you identifying users? Why can't you just test if they've already voted recently and render a "come back later" message? – tadman Aug 15 '18 at 17:07
  • "The contract has built-in protections to prevent the same account from voting multiple times, but these don't work if the user can return to the voting screen before their vote is mined," Could you explain this? If the contract can prevent double voting, then there's nothing else you need to do. (The second transaction will fail.) – user94559 Aug 15 '18 at 18:54
  • @tadman and smarx: I'm identifying them via MetaMask IDs. The problem is that the contract's built-in checkers don't work properly until the "vote" transaction is mined, which takes several seconds, and if they are able to access the voting interface before that is complete, then the system (at least as presently designed) won't know that they've already voted (because that information is meant to be stored in the Contract). – Eoin Moloney Aug 15 '18 at 19:41
  • @EoinMoloney It sounds like your contract already forbids double voting. You claim that somehow submitting multiple transactions defeats it, but I don't see how that's possible. Perhaps you have a mistaken mental model about concurrency? (There is none in a smart contract.) – user94559 Aug 16 '18 at 02:05

1 Answers1

3

Don't approach it from the front end. Even if you use some kind of local rate limiting, someone could clear cookies/cache, or just move to a different machine. Lastly, they could remove the limitation by just interacting with the contract directly over the ethereum network, instead of going through your frontend.

Your contract should maintain a mapping of address->lastBlockVoted. If a new vote from an address arrives within n blocks of the last block, the transaction should fail.

This way, even if someone broadcasts 20 transactions before the first one is mined, the latter 19 will all fail.

Raghav Sood
  • 81,899
  • 22
  • 187
  • 195
  • Thanks, that's a great idea. I'm relatively new to this, so, could I ask you how exactly I would go about detecting whether or not a certain transaction occurs on a certain block or not? Thanks. – Eoin Moloney Aug 16 '18 at 16:56
  • Solidity exposes a `block` variable that can give details such as the block number. Use that to compare against the block number in your mapping – Raghav Sood Aug 16 '18 at 16:57