2

Is it possible to access the length of an enum in solidity? E.g.

pragma solidity >=0.4.16 <0.6.0;

contract test {
    enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill }

    function move(uint8 _actionChoice) public {
        require (_actionChoice < ActionChoices.length);
        //....
    }

}
5
  • 1
    Add Last and then use _actionChoice < ActionChoices.Last. Commented Sep 1, 2019 at 11:28
  • I like the idea but looking for something that is less of a hack ;)
    – Senju
    Commented Sep 1, 2019 at 18:50
  • 1
    It's not a hack. It's used in pretty much every typed-language (C, C++, Java, etc). And Solidity is under that category. Commented Sep 1, 2019 at 19:16
  • If I add Last to the enum it is actually another enum I technically would be able to use as an ActionChoice, right? That should not be possible.
    – Senju
    Commented Sep 2, 2019 at 14:01
  • Yeah well, you could use any other value as well, when called from the off-chain (i.e., via a web3 script). In fact, you could even do it from the on-chain (i.e., from a contract), but that would require you to explicitly cast the integer value to ActionChoices, so you're kinda protected there. But like I said, from an off-chain script, there is no way to prevent that, besides checking in the contract that it is equal to one of your enum values (or, if you don't explicitly give them values, by checking that it is smaller the Last, as I have suggested). Commented Sep 2, 2019 at 14:13

3 Answers 3

5

enum is an integer, so the integer value of the last item plus 1 is the length.

You can also make the function argument typesafe.

function move (ActionChoices choice) ...

That will constrain the range of allowable inputs so you don't need the require.

Hope it helps

5
  • what if I add another enum later on, how do I know which is the last?
    – Senju
    Commented Sep 1, 2019 at 20:10
  • 1
    You can't add "later on". They are hard-coded into your "finished" smart contract and immutable bytecode. Commented Sep 1, 2019 at 20:39
  • Well. Let's say I upload another version of this contract later on I add one more enum in it. If in the function the specific "item plus 1" is not the last element anymore, it will not be the last element anymore - so I gotta remember to not only change the enum but also the function. Just trying to write clean code. I guess a helper function like getLastEnum would help. Any other idea? Otherwise your answer is a correct solution I was looking for.
    – Senju
    Commented Sep 2, 2019 at 14:00
  • Not from an off-chain script, AFAIK (i.e., you could call it via web3 with any integer value; without some sort of assertion in the contract's function, it will not be prevented). Commented Sep 2, 2019 at 14:16
  • @RobHitchens-B9lab if the enum is set to an out of range value (without any type of prior validation) the transaction reverts and uses the full gas limit. ethereum.stackexchange.com/questions/80350/…
    – Nick
    Commented Mar 5, 2020 at 11:44
1

Yes, since enums are 0-indexed the length is:

type(ActionChoices).max + 1
0
1

uint(type(ActionChoices).max)+1 Otherwise, you will get error.

(Also as reminder, function using ActionChoices as parameter will accept uint8 as parameter.)

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.