mars-protocol / cw-asset

A unified representation of various types of Cosmos fungible assets, and helper functions for interacting with them
Apache License 2.0
27 stars 13 forks source link

Validate native denoms #17

Open 0xekez opened 2 years ago

0xekez commented 2 years ago

I was recently looking into native denom validation, and it turns out there are actually some reasonably strict rules in the SDK as to what strings may be denominations. We should be able to perform that validation in a contract reasonably enough. From dao-contracts:

/// Follows cosmos SDK validation logic. Specifically, the regex
/// string `[a-zA-Z][a-zA-Z0-9/:._-]{2,127}`.
///
/// <https://github.com/cosmos/cosmos-sdk/blob/7728516abfab950dc7a9120caad4870f1f962df5/types/coin.go#L865-L867>
pub fn validate_native_denom(denom: String) -> Result<String, DenomError> {
    if denom.len() < 3 || denom.len() > 128 {
        return Err(DenomError::NativeDenomLength { len: denom.len() });
    }
    let mut chars = denom.chars();
    // Really this means that a non utf-8 character is in here, but
    // non-ascii is also correct.
    let first = chars.next().ok_or(DenomError::NonAlphabeticAscii)?;
    if !first.is_ascii_alphabetic() {
        return Err(DenomError::NonAlphabeticAscii);
    }

    for c in chars {
        if !(c.is_ascii_alphanumeric() || c == '/' || c == ':' || c == '.' || c == '_' || c == '-')
        {
            return Err(DenomError::InvalidCharacter { c });
        }
    }

    Ok(denom)
}
larry0x commented 2 years ago

this looks nice! actually i once tried using the regex for verification, but the regex library makes the contract binary too big to be put on-chain.

0xekez commented 2 years ago

@larry0x: this looks nice!

Happy to put up a PR to add this. Are we early enough with versioning here that we can make a change that isn't backwards compatible?

Agree about regex. :) There are some ways to generate valid strings from a regex so I was thinking of trying to write some fuzzing code for this using that. There are some weird corners with go regex vs rust strings that I worry about: https://github.com/DA0-DA0/dao-contracts/blob/zeke/deposit-modules/packages/voting/src/denom.rs#L215-L223