組み込み関数

ポリシーで利用可能なすべての組み込み関数の完全なリファレンス

ポリシーでは、以下の組み込み関数のみが有効です。ここに記載されていない関数は、セキュリティ上の理由で無効になっています。無効化された関数の詳細については、制限を参照してください。

文字列関数

文字列値を操作および検査するための関数。アドレス、メソッド名、その他のテキストフィールドを扱う際に不可欠です。

contains

文字列に部分文字列が含まれているかどうかを確認します。見つかった場合は true を返し、そうでない場合は false を返します。

# Block any method containing "sign"
deny if {
    contains(input.rpc_method, "sign")
}

startswith

文字列が接頭辞で始まるかどうかを確認します。メソッドカテゴリまたはアドレスパターンの一致に便利です。

# Block debug methods
deny if {
    startswith(input.rpc_method, "debug_")
}
 
# Block addresses starting with many zeros
deny if {
    startswith(input.to_address, "0x00000000")
}

endswith

文字列が接尾辞で終わるかどうかを確認します。

# Block addresses ending with specific pattern
deny if {
    endswith(lower(input.to_address), "dead")
}

lower

文字列を小文字に変換します。アドレスには大文字と小文字が混在する可能性があるため、大文字と小文字を区別しないアドレス比較に不可欠です。

# Case-insensitive address check
blocked_addresses := {
    "0x000000000000000000000000000000000000dead"
}
 
deny if {
    lower(input.to_address) in blocked_addresses
}

upper

文字列を大文字に変換します。

# Normalize method names that might have inconsistent casing
deny if {
    upper(input.rpc_method) == "ETH_SENDTRANSACTION"
    input.usd_value > 10000
}

concat

区切り文字を使用して文字列の配列を結合します。

# Join values for logging or comparison
message := concat(", ", ["chain:", input.chain, "method:", input.rpc_method])

split

区切り文字を使用して文字列を配列に分割します。

# Parse a method name
parts := split(input.rpc_method, "_")
 
deny if {
    parts[0] == "debug"
}

replace

部分文字列のすべての出現を別の文字列に置き換えます。

# Normalize address format
normalized := replace(input.to_address, "0X", "0x")

substring

開始位置と長さで文字列の一部を抽出します。

# Get method prefix (first 4 characters after "eth_")
deny if {
    startswith(input.rpc_method, "eth_")
    method_action := substring(input.rpc_method, 4, 4)
    method_action == "send"
}

sprintf

プレースホルダーを使用して文字列をフォーマットします。動的な値を作成するのに便利です。

PlaceholderType
%sString
%dInteger
%fFloat
%vAny value

# Create formatted message
threshold := 10000
message := sprintf("Value %d exceeds limit of %d", [input.usd_value, threshold])

trim

文字列の両端から指定された文字を削除します。

# Remove specific characters from both ends
cleaned := trim(input.rpc_method, "_")

trim_space

文字列の両端から空白を削除します。

# Clean up input with extra spaces
clean_method := trim_space(input.rpc_method)

trim_prefix

存在する場合、文字列から接頭辞を削除します。

# Remove common prefix to get the action name
method_name := trim_prefix(input.rpc_method, "eth_")
 
deny if {
    method_name == "sendTransaction"
}

trim_suffix

存在する場合、文字列から接尾辞を削除します。

# Remove suffix for comparison
base_method := trim_suffix(input.rpc_method, "_v2")

indexof

部分文字列の最初の出現のインデックスを検索します。見つからない場合は -1 を返します。

# Check if underscore exists
deny if {
    indexof(input.rpc_method, "_") == -1
}

正規表現関数

正規表現を使用したパターンマッチングのための関数。複雑なパターンには文字列関数よりも強力です。

regex.match

文字列が正規表現パターンに一致するかどうかを確認します。true または false を返します。

# Block methods starting with debug_, admin_, or personal_
deny if {
    regex.match("^(debug_|admin_|personal_)", input.rpc_method)
}
 
# Block addresses with many leading zeros
deny if {
    regex.match("^0x0{10,}", input.to_address)
}

regex.replace

パターンのすべての一致を置換文字列に置き換えます。

# Remove all non-alphanumeric characters
cleaned := regex.replace(input.rpc_method, "[^a-zA-Z0-9]", "")

regex.split

正規表現パターンで文字列を分割します。

# Split by multiple delimiters
parts := regex.split("[_.]", input.rpc_method)

regex.find_n

文字列内でパターンの最大 n 個の一致を検索します。

# Find all hex sequences
hex_matches := regex.find_n("0x[a-fA-F0-9]+", input.raw_params[0].data, 10)
 
deny if {
    count(hex_matches) > 5
}

時間関数

時間を扱うための関数。すべての時間値は Unix エポックからのナノ秒です。

time.now_ns

現在時刻をナノ秒で取得します。時間ベースのポリシーの基礎としてこれを使用します。

# Block high-value transactions during volatile market hours
deny if {
    current := time.now_ns()
    [hour, _, _] := time.clock(current)
    hour >= 14  # After 2 PM UTC (US market open)
    hour < 21   # Before 9 PM UTC (US market close)
    input.usd_value > 50000
}

time.clock

タイムスタンプから時、分、秒を抽出します。[hour, minute, second] を返します。

# Block outside business hours (9 AM - 5 PM UTC)
deny if {
    [hour, _, _] := time.clock(time.now_ns())
    hour < 9
}
 
deny if {
    [hour, _, _] := time.clock(time.now_ns())
    hour >= 17
}

time.weekday

タイムスタンプから曜日を取得します。0(日曜日)から 6(土曜日)を返します。

# Block on weekends
deny if {
    day := time.weekday(time.now_ns())
    day == 0  # Sunday
}
 
deny if {
    day := time.weekday(time.now_ns())
    day == 6  # Saturday
}

time.date

タイムスタンプから年、月、日を抽出します。[year, month, day] を返します。

# Block on specific dates
deny if {
    [year, month, day] := time.date(time.now_ns())
    month == 12
    day == 25  # Christmas
}

time.parse_rfc3339_ns

RFC3339 形式のタイムスタンプ文字列をナノ秒に解析します。

# Compare against a specific date
cutoff := time.parse_rfc3339_ns("2024-12-31T23:59:59Z")
 
deny if {
    time.now_ns() > cutoff
}

time.add_date

タイムスタンプに年、月、日を追加します。

# Block transactions if we're within 7 days of year end
deny if {
    year_end := time.parse_rfc3339_ns("2024-12-31T23:59:59Z")
    week_before := time.add_date(year_end, 0, 0, -7)
    time.now_ns() > week_before
    input.usd_value > 10000
}

time.diff

2 つのタイムスタンプ間の差を計算します。[years, months, days, hours, minutes, seconds] を返します。

# Check if more than 1 hour has passed
start := time.parse_rfc3339_ns("2024-01-01T00:00:00Z")
[_, _, _, hours, _, _] := time.diff(time.now_ns(), start)
 
deny if {
    hours > 1
}

集約関数

値のコレクションを扱うための関数。

count

配列、セット、またはオブジェクト内の要素の数をカウントします。

# Limit number of contracts in a request
deny if {
    count(input.contract_addresses) > 5
}
 
# Ensure at least one address
deny if {
    count(input.contract_addresses) == 0
}

sum

配列内の数値の合計を計算します。

# Block if total gas across params exceeds limit
deny if {
    gas_values := [to_number(p.gas) | some p in input.raw_params; p.gas != null]
    sum(gas_values) > 5000000
}

max

配列内の最大値を検索します。

# Check against maximum in a set of thresholds
thresholds := [1000, 5000, 10000]
 
deny if {
    input.usd_value > max(thresholds)
}

min

配列内の最小値を検索します。

# Ensure value meets minimum threshold
thresholds := [100, 500, 1000]
 
deny if {
    input.usd_value < min(thresholds)
}

sort

配列を昇順にソートします。

# Check if smallest contract address looks suspicious (many leading zeros)
deny if {
    count(input.contract_addresses) > 0
    sorted_addrs := sort(input.contract_addresses)
    startswith(sorted_addrs[0], "0x00000000")
}

product

配列内の数値の積を計算します。

# Calculate combined risk score from multiple factors
deny if {
    risk_factors := [2, 3]  # High-value = 2x, Unknown sender = 3x
    combined_risk := product(risk_factors)
    combined_risk > 5
}

型関数

データ型をチェックして扱うための関数。null 許容フィールドを安全に処理するのに便利です。

is_null

値が null かどうかを確認します。オプションの入力フィールドを処理するために不可欠です。

# Safely check nullable field
deny if {
    not is_null(input.usd_value)
    input.usd_value > 10000
}

is_number

値が数値かどうかを確認します。

# Validate before numeric comparison
deny if {
    is_number(input.usd_value)
    input.usd_value > 10000
}

is_string

値が文字列かどうかを確認します。

# Validate input type
deny if {
    is_string(input.to_address)
    startswith(input.to_address, "0x0000")
}

is_array

値が配列かどうかを確認します。

# Check before iterating
deny if {
    is_array(input.contract_addresses)
    count(input.contract_addresses) > 10
}

is_boolean

値がブール値(true または false)かどうかを確認します。

# Verify a flag is actually a boolean before using it
deny if {
    is_boolean(input.raw_params[0].enabled)
    input.raw_params[0].enabled == false
}

is_set

値がセットかどうかを確認します。

# Validate collection type
deny if {
    is_set(input.raw_params[0].addresses)
    count(input.raw_params[0].addresses) > 100
}

is_object

値がオブジェクト(キー値マップ)かどうかを確認します。

# Ensure params is an object before accessing fields
deny if {
    is_object(input.raw_params[0])
    object.get(input.raw_params[0], "dangerous", false) == true
}

type_name

値の型名を文字列として取得します。

# Block if usd_value is not a number (unexpected type)
deny if {
    input.usd_value != null
    type_name(input.usd_value) != "number"
}

数値関数

数値演算のための関数。

abs

数値の絶対値を取得します。

# Check magnitude regardless of sign
deny if {
    abs(input.usd_value) > 10000
}

round

数値を最も近い整数に丸めます。

# Round for comparison
deny if {
    round(input.usd_value) > 10000
}

ceil

数値を次の整数に切り上げます。

# Round up for conservative limit checking
deny if {
    ceil(input.usd_value) > 10000
}

floor

数値を前の整数に切り捨てます。

# Block transactions over $10,000 (ignoring cents)
deny if {
    floor(input.usd_value) >= 10000
}

to_number

文字列を数値に変換します。16 進文字列値に便利です。

# Convert hex gas values
deny if {
    input.gas_limit != null
    to_number(input.gas_limit) > 1000000
}

numbers.range

開始から終了まで(両端を含む)の数値の配列を生成します。

# Allow transactions only during business hours (9 AM - 5 PM)
deny if {
    [hour, _, _] := time.clock(time.now_ns())
    business_hours := numbers.range(9, 17)
    not hour in business_hours
}

オブジェクト関数

オブジェクト(キー値マップ)を扱うための関数。

object.get

キーが存在しない場合はデフォルト値を使用してオブジェクトから安全に値を取得します。

# Safely access nested data
deny if {
    params := input.raw_params[0]
    data := object.get(params, "data", "0x")
    startswith(data, "0xa9059cbb")  # ERC-20 transfer
}

object.keys

オブジェクトからすべてのキーを配列として取得します。

# Check which fields are present
params := input.raw_params[0]
keys := object.keys(params)
 
deny if {
    "data" in keys
    "value" in keys
}

object.remove

指定されたキーを削除した新しいオブジェクトを作成します。

# Block if params contain unexpected fields after removing known safe ones
deny if {
    safe_fields := ["to", "from", "value", "gas", "data"]
    remaining := object.remove(input.raw_params[0], safe_fields)
    count(object.keys(remaining)) > 0
}

object.union

2 つのオブジェクトをマージします。2 番目のオブジェクトの値が最初のオブジェクトを上書きします。

# Apply safe defaults and check resulting gas limit
deny if {
    defaults := {"gas": "0x5208"}
    params := object.union(defaults, input.raw_params[0])
    to_number(params.gas) > 1000000
}

配列関数

配列操作のための関数。

array.concat

2 つの配列を 1 つに連結します。

# Combine address lists
all_addresses := array.concat(
    input.contract_addresses,
    [input.to_address]
)

array.slice

開始インデックスと終了インデックスで配列の一部を抽出します。

# Only check first 5 contract addresses for blocked list
deny if {
    first_five := array.slice(input.contract_addresses, 0, 5)
    some addr in first_five
    addr in {"0xbanned1...", "0xbanned2..."}
}

array.reverse

配列内の要素の順序を反転します。

# Check last contract address (most recent) for suspicious patterns
deny if {
    count(input.contract_addresses) > 0
    reversed := array.reverse(input.contract_addresses)
    startswith(reversed[0], "0x00000000")
}

セット関数

セット演算のための関数。

intersection

両方のセットに存在する要素を取得します。

# Check for any blocked address
blocked := {"0xdead...", "0xbad..."}
request_addrs := {lower(input.to_address)}
 
deny if {
    count(intersection(blocked, request_addrs)) > 0
}

union

すべての一意の要素を持つ 2 つのセットを 1 つに結合します。

# Combine multiple blocklists
blocked_countries := union(
    {"KP", "IR", "CU"},
    {"SY", "RU"}
)
 
deny if {
    input.source_country in blocked_countries
}

エンコーディング関数

データをエンコードおよびデコードするための関数。

base64.encode

文字列を Base64 形式にエンコードします。

# Check if method matches an encoded pattern
deny if {
    encoded_method := base64.encode(input.rpc_method)
    encoded_method == "ZXRoX3NlbmRUcmFuc2FjdGlvbg=="  # eth_sendTransaction
}

base64.decode

Base64 文字列をプレーンテキストにデコードします。

# Decode base64 data from request
decoded := base64.decode("aGVsbG8=")  # "hello"
 
deny if {
    contains(decoded, "dangerous")
}

base64url.encode

文字列を URL セーフな Base64 形式にエンコードします。+/ の代わりに -_ を使用します。

# Create URL-safe identifier from address for comparison
deny if {
    encoded_addr := base64url.encode(input.to_address)
    encoded_addr in {"MHhkZWFk...", "MHhiYWQ..."}
}

base64url.decode

URL セーフな Base64 文字列をプレーンテキストにデコードします。

# Decode and check URL-safe encoded data in params
deny if {
    encoded_data := object.get(input.raw_params[0], "encoded", "")
    decoded := base64url.decode(encoded_data)
    contains(decoded, "malicious")
}

hex.encode

文字列を 16 進形式にエンコードします。

# Encode method name to hex for pattern matching
deny if {
    method_hex := hex.encode(input.rpc_method)
    startswith(method_hex, "657468")  # "eth" in hex
}

hex.decode

16 進文字列をプレーンテキストにデコードします。

# Decode hex-encoded data field and check contents
deny if {
    data := object.get(input.raw_params[0], "data", "")
    startswith(data, "0x")
    decoded := hex.decode(substring(data, 2, 8))
    contains(decoded, "admin")
}
組み込み関数 | 256 Blocks