Here is the contract, function being called is voteForCharacter:

pragma solidity ^0.4.19;

contract CharacterEveryDay {

event CharacterSelected(uint8 _character, uint64[256] characterVotes, uint64 day);

uint64[256] public characterVotes;

uint8 public winningCharacter;
uint64 public day; 
uint256 public winningCharacterVotes;
uint256 public timeOfLastVote;

mapping (uint256 => bool) addressVotedToday;

constructor (uint8 _character) public {
    day = 0;
    winningCharacterVotes = 0;
    timeOfLastVote = now;

modifier onlyCharacter(uint256 _character) {
    require(_character < 256);

function voteForCharacter(uint256 _character) public onlyCharacter(_character) {
    if ((now - timeOfLastVote) > 1 days) {

    uint256 todaysAddressHash = uint(keccak256(abi.encodePacked(day, msg.sender)));
    require(addressVotedToday[todaysAddressHash] == false);

    if (characterVotes[_character] > winningCharacterVotes) {
        winningCharacter = uint8(_character);
        winningCharacterVotes = characterVotes[_character];
    addressVotedToday[todaysAddressHash] = true;
    timeOfLastVote = now;

function getCharacterVotes() external view returns (uint64[256]) {
    return characterVotes;

function selectCharacter (uint8 _winningCharacter) private {
    day += uint64((now - timeOfLastVote) / 1 days);
    emit CharacterSelected(_winningCharacter, characterVotes, day);
    delete characterVotes;
    delete winningCharacter;
    delete winningCharacterVotes;


When I run it for the first time in a day, when the require passes:

require(addressVotedToday[todaysAddressHash] == false);

the gas estimate on MetaMask is reasonable and the functions succeeds: 0.000294 eth ($.05)

If I run it again in the same day with the same address, which means the require will fail, the gas cost becomes unreasonable: 2850000 eth ($500 millionish)

If I use a different address on the same day, the gas estimate becomes reasonable.


The gas estimate stays reasonable, but after the first vote the function will fail not because the require fails, but because it runs out of gas.

  • The very high cost is likely a limitation/bug of MetaMask. There wasn't an standard way to determine the exact cause of failure of a transaction, so most interfaces will show "out of gas" as a wildcard. Now there's the possibility of passing a message when require will fail, but it is not widely implemented yet. – Ismael Sep 11 '18 at 15:16

Your Answer

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

Browse other questions tagged or ask your own question.