multiversx_chain_core/
token_identifier_util.rs

1const TICKER_MIN_LENGTH: usize = 3;
2const TICKER_MAX_LENGTH: usize = 10;
3const ADDITIONAL_RANDOM_CHARS_LENGTH: usize = 6;
4
5// +1 because of the '-' (dash) between ticker and the random chars
6pub const IDENTIFIER_MIN_LENGTH: usize = TICKER_MIN_LENGTH + ADDITIONAL_RANDOM_CHARS_LENGTH + 1;
7pub const IDENTIFIER_MAX_LENGTH: usize = TICKER_MAX_LENGTH + ADDITIONAL_RANDOM_CHARS_LENGTH + 1;
8
9const DASH_CHARACTER: u8 = b'-';
10
11/// There is a VM implementation of this very function.
12/// This implementation is used for debugging mode and backwards compatibility.
13/// Using the VM implementation instead of this one saves ~0.6 kB of contract code.
14pub fn validate_token_identifier(token_id_slice: &[u8]) -> bool {
15    let length = token_id_slice.len();
16
17    #[allow(clippy::manual_range_contains)]
18    if length < IDENTIFIER_MIN_LENGTH || length > IDENTIFIER_MAX_LENGTH {
19        return false;
20    }
21
22    let lowercase_letter_range = b'a'..=b'z';
23    let uppercase_letter_range = b'A'..=b'Z';
24    let number_range = b'0'..=b'9';
25
26    // ticker must be all uppercase alphanumeric
27    let ticker_len = get_token_ticker_len(length);
28    let ticker = &token_id_slice[..ticker_len];
29    for ticker_char in ticker {
30        let is_uppercase_letter = uppercase_letter_range.contains(ticker_char);
31        let is_number = number_range.contains(ticker_char);
32
33        if !is_uppercase_letter && !is_number {
34            return false;
35        }
36    }
37
38    let dash_position = ticker_len;
39    if token_id_slice[dash_position] != DASH_CHARACTER {
40        return false;
41    }
42
43    // random chars are alphanumeric lowercase
44    let random_chars = &token_id_slice[(length - ADDITIONAL_RANDOM_CHARS_LENGTH)..];
45    for rand_char in random_chars {
46        let is_lowercase_letter = lowercase_letter_range.contains(rand_char);
47        let is_number = number_range.contains(rand_char);
48
49        if !is_lowercase_letter && !is_number {
50            return false;
51        }
52    }
53
54    true
55}
56
57pub fn get_token_ticker_len(token_id_len: usize) -> usize {
58    token_id_len - ADDITIONAL_RANDOM_CHARS_LENGTH - 1
59}