#!/usr/bin/env bash # Verify that a GRU V2 token address exposes the expected standards and metadata surface. # # Usage: # bash scripts/verify/check-gru-v2-token-standard-surface.sh --token cUSDC_V2=0x... # bash scripts/verify/check-gru-v2-token-standard-surface.sh --token cEURC_V2=0x... --strict # # Exit: # 0 on successful execution # 1 with --strict when any checked token is missing a required surface set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" cd "$PROJECT_ROOT" STRICT=0 RPC_URL="${RPC_URL_138:-${CHAIN_138_RPC_URL:-http://192.168.11.211:8545}}" declare -A TOKENS=() TOKEN_ORDER=() add_token() { local spec="$1" local symbol="${spec%%=*}" local address="${spec#*=}" if [[ -z "$symbol" || -z "$address" || "$symbol" == "$address" ]]; then echo "ERROR: invalid token spec '$spec' (expected SYMBOL=ADDRESS)" >&2 exit 1 fi TOKENS["$symbol"]="$address" TOKEN_ORDER+=("$symbol") } while [[ $# -gt 0 ]]; do case "$1" in --strict) STRICT=1 shift ;; --rpc=*) RPC_URL="${1#--rpc=}" shift ;; --token) [[ $# -ge 2 ]] || { echo "ERROR: --token requires SYMBOL=ADDRESS" >&2; exit 1; } add_token "$2" shift 2 ;; --token=*) add_token "${1#--token=}" shift ;; *) echo "Unknown argument: $1" >&2 exit 2 ;; esac done if ! command -v cast >/dev/null 2>&1; then echo "cast is required" >&2 exit 1 fi if [[ ${#TOKEN_ORDER[@]} -eq 0 ]]; then echo "ERROR: provide at least one --token SYMBOL=ADDRESS" >&2 exit 1 fi HOLDER="0x0000000000000000000000000000000000000001" ZERO32="0x0000000000000000000000000000000000000000000000000000000000000000" call_ok() { local address="$1" local signature="$2" shift 2 cast call "$address" "$signature" "$@" --rpc-url "$RPC_URL" >/dev/null 2>&1 } overall_fail=0 for sym in "${TOKEN_ORDER[@]}"; do addr="${TOKENS[$sym]}" echo "=== ${sym} (${addr}) ===" missing=() call_ok "$addr" 'name()(string)' || missing+=("ERC-20 name") call_ok "$addr" 'symbol()(string)' || missing+=("ERC-20 symbol") call_ok "$addr" 'currencyCode()(string)' || missing+=("currencyCode") call_ok "$addr" 'versionTag()(string)' || missing+=("versionTag") call_ok "$addr" 'assetId()(bytes32)' || missing+=("assetId") call_ok "$addr" 'assetVersionId()(bytes32)' || missing+=("assetVersionId") call_ok "$addr" 'DOMAIN_SEPARATOR()(bytes32)' || missing+=("EIP-712 DOMAIN_SEPARATOR") call_ok "$addr" 'nonces(address)(uint256)' "$HOLDER" || missing+=("ERC-2612 nonces") call_ok "$addr" 'authorizationState(address,bytes32)(bool)' "$HOLDER" "$ZERO32" || missing+=("ERC-3009 authorizationState") call_ok "$addr" 'eip712Domain()(bytes1,string,string,uint256,address,bytes32,uint256[])' || missing+=("ERC-5267 eip712Domain") call_ok "$addr" 'governanceProfileId()(bytes32)' || missing+=("governanceProfileId") call_ok "$addr" 'supervisionProfileId()(bytes32)' || missing+=("supervisionProfileId") call_ok "$addr" 'storageNamespace()(bytes32)' || missing+=("storageNamespace") call_ok "$addr" 'primaryJurisdiction()(string)' || missing+=("primaryJurisdiction") call_ok "$addr" 'regulatoryDisclosureURI()(string)' || missing+=("regulatoryDisclosureURI") call_ok "$addr" 'reportingURI()(string)' || missing+=("reportingURI") call_ok "$addr" 'minimumUpgradeNoticePeriod()(uint256)' || missing+=("minimumUpgradeNoticePeriod") call_ok "$addr" 'wrappedTransport()(bool)' || missing+=("wrappedTransport") if [[ "${#missing[@]}" -gt 0 ]]; then overall_fail=1 echo "Missing:" for item in "${missing[@]}"; do echo "- $item" done else echo "[OK] Full GRU V2 standard surface detected." fi echo "" done if [[ "$STRICT" == "1" && "$overall_fail" == "1" ]]; then exit 1 fi