agentsclimarketplace

Evm decimal validation

Skill widnyana/eyay-toolkits/plugins/evm-decimal-validation/skills/evm-decimal-validation

Agents don’t behave, they swarm. Skills and plugins slot in mid flight, and somehow the whole thing is a mess

Install
npx -y skills add widnyana/eyay-toolkits --skill evm-decimal-validation

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Validate and configure token decimals for EVM-compatible blockchain deployments. Use when working with ERC20 tokens, multi-chain deployments, token amount conversions, or when decimals might vary across chains.

SKILL.md

4.8 KB, as published. Nobody here has run it

EVM Token Decimal Validation

Ensure token decimals are correctly configured for each blockchain deployment to prevent amount calculation errors.

Quick Start

  1. Check current configuration - Review network configs for decimal fields
  2. Validate against contracts - Query on-chain decimals() for each deployment
  3. Update configuration - Add per-chain decimals to network config
  4. Test conversions - Verify FromWei/ToWei work correctly

Token Decimal Standards

Common Decimal Values

DecimalsUse CaseExamples
18Standard ERC20 (most tokens)WETH, DAI, USDC (on some chains)
6StablecoinsUSDC, USDT (on Ethereum)
8Bitcoin-wrappedWBTC
2Fiat-backed (cents)IDRX, some CBDCs
0Raw integersSome wrapped tokens

Chain-Specific Variations

The same token contract deployed on different chains may use different decimals:

Token A on Ethereum:    18 decimals
Token A on Polygon:     0 decimals (different deployment)
Token A on BNB Chain:   0 decimals (different deployment)

Validation Checklist

Step 1: Audit Current Configuration

# Find hardcoded decimals
grep -rn "18)" --include="*.go" | grep -i "decimal\|wei\|amount"

# Check for decimals field in network config
grep -rn "Decimals" blockchain/networks.go

Step 2: Query On-Chain Values

// Get decimals from contract
decimals, err := contract.Decimals(nil)
if err != nil {
    return fmt.Errorf("failed to get decimals: %w", err)
}

Step 3: Update Network Config

type NetworkConfig struct {
    // ... existing fields ...
    Decimals uint8 // Token decimals for this deployment
}

// In SupportedNetworks
BaseMainnet: {
    // ...
    Decimals: 2, // From on-chain query
},

Step 4: Add Helper Function

// GetDecimals returns token decimals for a chain ID.
// Always provide a sensible fallback.
func GetDecimals(chainID uint64) uint8 {
    config, _, exists := GetNetworkConfigByChainID(chainID)
    if !exists {
        return 2 // Fallback to majority value
    }
    return config.Decimals
}

Step 5: Replace Hardcoded Values

// Before
return FromWei(balance, 18), nil

// After
return FromWei(balance, int32(GetDecimals(chainID))), nil

Common Pitfalls

Pitfall 1: Assuming All Chains Use Same Decimals

// WRONG: Hardcoded decimals
amount := FromWei(balance, 18)

// CORRECT: Per-chain decimals
amount := FromWei(balance, int32(GetDecimals(chainID)))

Pitfall 2: Missing Fallback Value

// WRONG: No fallback, potential nil pointer
return config.Decimals, nil

// CORRECT: Sensible fallback
if !exists {
    return 2 // Majority value or most common
}
return config.Decimals

Pitfall 3: Not Validating Config Against Chain

// Add startup validation
func ValidateDecimals() error {
    for name, config := range SupportedNetworks {
        onChainDecimals, err := queryOnChain(config)
        if err != nil {
            continue // Skip unreachable chains
        }
        if config.Decimals != onChainDecimals {
            return fmt.Errorf("%s: config=%d, on-chain=%d",
                name, config.Decimals, onChainDecimals)
        }
    }
    return nil
}

Test Patterns

func TestGetDecimals(t *testing.T) {
    testCases := map[uint64]uint8{
        8453: 2,  // Base
        137:  0,  // Polygon
        56:   0,  // BSC
    }

    for chainID, expected := range testCases {
        got := GetDecimals(chainID)
        if got != expected {
            t.Errorf("Chain %d: expected %d, got %d", chainID, expected, got)
        }
    }
}

func TestGetDecimalsFallback(t *testing.T) {
    got := GetDecimals(999999) // Unknown chain
    if got != 2 {
        t.Errorf("Unknown chain should return fallback, got %d", got)
    }
}

Integration Points

When adding decimal validation, check these areas:

AreaWhat to Check
Balance queriesBalanceOf() uses per-chain decimals
Total supplyTotalSupply() uses per-chain decimals
TransfersParseTokenAmount() receives correct decimals
Bridge operationsBoth source and dest chains considered
Fee calculationsPlatform fees use correct decimals
API responsesHuman-readable amounts properly converted

Token Decimals by Chain

See decimals-by-chain.md for a reference guide of common tokens and their decimals across different EVM chains.

Sources

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.