Встроенные Функции
Полный справочник всех доступных встроенных функций в политиках
В политиках доступны только следующие встроенные функции. Функции, не указанные здесь, отключены по соображениям безопасности. Подробную информацию об отключенных функциях см. в разделе Ограничения.
Строковые Функции
Функции для манипулирования и проверки строковых значений. Необходимы для работы с адресами, именами методов и другими текстовыми полями.
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
Форматирует строку с заполнителями. Полезно для создания динамических значений.
| Placeholder | Type |
|---|---|
%s | String |
%d | Integer |
%f | Float |
%v | Any 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
Вычисляет разницу между двумя временными метками. Возвращает [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
Преобразует строку в число. Полезно для шестнадцатеричных строковых значений.
Пример
# 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
Объединяет два объекта. Значения из второго объекта переопределяют первый.
Пример
# 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
Объединяет два массива в один.
Пример
# 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
Объединяет два множества в одно со всеми уникальными элементами.
Пример
# 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
Кодирует строку в формат Base64, безопасный для URL. Использует - и _ вместо + и /.
Пример
# Create URL-safe identifier from address for comparison
deny if {
encoded_addr := base64url.encode(input.to_address)
encoded_addr in {"MHhkZWFk...", "MHhiYWQ..."}
}base64url.decode
Декодирует строку Base64, безопасную для URL, обратно в обычный текст.
Пример
# 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
Кодирует строку в шестнадцатеричный формат.
Пример
# 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
Декодирует шестнадцатеричную строку обратно в обычный текст.
Пример
# 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")
}