Escribe reglas de política de transacciones

En esta página, se describen los atributos que puede verificar una política de transacciones y se muestran reglas de ejemplo para las transacciones de Ethereum (ETHEREUM_TX_V2 y EIP712_TYPED_DATA_V1), Bitcoin (BITCOIN_TX_V2) y Solana (SOLANA_TX_V1).

Para obtener información sobre cómo se combinan las políticas, qué políticas se aplican y por qué se rechaza una transacción, consulta Evaluación de políticas de transacciones.

Estructura de las reglas

Una política de transacción es una sola sentencia permit o forbid de Cedar sobre el principal, la acción, el recurso y el contexto:

permit (
  principal,
  action == Action::"buy_transaction",
  resource == Resource::"transaction_management"
)
when {
  context.principal_keyring == "institutional-treasury" &&
  context.schema == "ETHEREUM_TX_V2" &&
  context has amount_token_scaled && context.amount_token_scaled <= 1000000000
};

Ten en cuenta lo siguiente:

  • Los atributos se encuentran en el nivel superior del contexto. Escribe context.amount_token_scaled, no context.transaction.spend_amount_scaled, como en v1alpha1.
  • Algunos atributos son opcionales. Un atributo opcional que no está en el contexto hace que la política no se evalúe, y una política que no se evalúa no coincide. Verifica si hay un atributo opcional con has antes de leerlo o con unless { context has ... } en una regla forbid. Para obtener más información, consulta la situación 6 y la situación 8.
  • Las cadenas de Cedar distinguen mayúsculas de minúsculas. Compara las direcciones en el formato que describe la tabla de cada cadena.

Para el principal, consulta La solicitud de Cedar. Para conocer las acciones que acepta CreateTransaction (buy_transaction, sell_transaction y internal_transfer_transaction), consulta Acción y recurso.

Atributos de contexto

El contexto de cada transacción tiene los atributos decodificados de su carga útil, los IDs de la clave de firma y su KeyRing, y los atributos de metadatos (fiat_amount, validity, principal_value1 y principal_value2) que establece el iniciador.

Los atributos de la carga útil son los mismos para cada cadena de bloques. En la siguiente tabla, se describen todos los atributos de contexto, y las tablas de Ethereum, Bitcoin y Solana describen cómo la computación multipartita completa cada atributo para esa cadena de bloques:

Atributo Tipo de cedro ¿Siempre presente? Valor
schema String Sí El formato de la carga útil: "ETHEREUM_TX_V2", "BITCOIN_TX_V2", "SOLANA_TX_V1" o "EIP712_TYPED_DATA_V1". Para obtener más información, consulta Nombres de esquemas.
blockchain String Sí "ETH", "BTC" o "SOL".
principal_keyring String Sí Es el ID del llavero de claves que contiene la clave de firma, por ejemplo, "treasury".
principal_key String Sí Es el ID de la clave de firma, por ejemplo, "hot-wallet-1".
secondary_key String Sí La dirección de destino, el destinatario del token o NFT, el operador o gastador aprobado, o la contraparte de EIP-712 decodificada de la carga útil.
amount_token_scaled Long No Es el importe fungible transferido o aprobado, en unidades de 10-9 del activo. Se omite cuando no se transfiere un importe fungible, por ejemplo, una operación ERC-721 o una llamada de contrato que no envía ETH. Para obtener más información, consulta Importes.
token_symbol String No Es el símbolo del activo, por ejemplo, "ETH", "BTC", "SOL" o "USDC". Se omite cuando el activo no es uno que reconozca la computación multipartita y para las operaciones de ERC-721.
contract_address String No El contrato de token ERC-20 o ERC-721, o el contrato llamado (Ethereum), el contrato de verificación (EIP-712) o la acuñación (Solana). Se omite para las transferencias nativas.
token_standard String No "ERC721" para transferencias y aprobaciones de ERC-721 (ETHEREUM_TX_V2). Se omite para transferencias nativas y operaciones de tokens fungibles.
token_id String No El tokenId ERC-721 de 256 bits como una cadena de base 10 (ETHEREUM_TX_V2). Se omite para setApprovalForAll y para las transacciones que no son ERC-721.
from_address String No El propietario actual (from) en las llamadas transferFrom y safeTransferFrom de ERC-721, en formato de suma de comprobación EIP-55 con mayúsculas y minúsculas.
approve_all Bool No La marca approved en las llamadas setApprovalForAll(operator, approved) de ERC-721: true cuando se otorga la aprobación del operador, false cuando se revoca.
deadline Long No Es la hora de vencimiento de un mensaje de EIP712_TYPED_DATA_V1, en segundos desde el tiempo Unix, de su campo deadline, sigDeadline o validBefore.
eip712 Record No La carga útil estructurada de EIP-712: primary_type, domain y message, con números enteros de 256 bits como cadenas de base 10. Solo EIP712_TYPED_DATA_V1.
chain_id Long No Es el ID de la cadena de EVM, por ejemplo, 1 para la red principal de Ethereum o 11155111 para Sepolia. Solo Ethereum y EIP-712.
max_fee_atomic Long Sí Es el importe máximo que se puede pagar en tarifas de red por la transacción, en unidades de 10-9 de la moneda nativa de la cadena de bloques. 0 por EIP712_TYPED_DATA_V1.
payload String Sí Es el resumen con codificación hexadecimal de la carga útil, en minúsculas.
time_stamp Long Sí Es el createTime de la transacción, en segundos desde el tiempo Unix.
key_lists Record de Set<String> Sí Un registro que asigna cada ID de KeyList de la instancia al Set<String> de direcciones de cadena de bloques de esa KeyList, resuelto en createTime. Un registro vacío cuando la instancia no tiene KeyLists. Lee una KeyList con sintaxis de corchetes, por ejemplo, context.key_lists["trusted-destinations"]. Para obtener más información, consulta KeyLists en el contexto de Cedar.

principal_keyring y principal_key son IDs, no nombres de recursos completos. Un ID de clave es único solo dentro de su llavero de claves. Verifica principal_keyring para aplicar una regla a cada clave de un llavero de claves o ambos atributos para nombrar una clave:

context.principal_keyring == "treasury" && context.principal_key == "hot-wallet-1"

Si el analizador no puede decodificar la carga útil para Transaction.schema o no se puede proyectar en un contexto, no se evalúa ninguna política y se rechaza la transacción con UNRECOGNIZED_PAYLOAD. Para obtener más información, consulta Motivos de rechazo.

Nombres de esquemas

El atributo schema es el nombre del valor PayloadSchema en la API de v1beta: "ETHEREUM_TX_V2", "BITCOIN_TX_V2", "SOLANA_TX_V1" o "EIP712_TYPED_DATA_V1". Los nombres en minúscula que usan las reglas de v1alpha1, como "ethereum.transaction.v2", nunca coinciden en v1beta.

Una regla sin una verificación de schema o blockchain se aplica a todas las cadenas de bloques. Para limitar una regla a una cadena de bloques, marca schema.

Importes

amount_token_scaled y max_fee_atomic usan la misma escala para cada activo: 1 unidad es 10-9 del activo, por lo que 1.0 de cualquier activo es 1000000000. Para obtener el valor de una regla, multiplica el importe por 1,000,000,000 (109). En la siguiente tabla, encontrarás algunos ejemplos:

Importe amount_token_scaled
0.1 ETH 100000000
1.0 ETH, 1.0 BTC, 1.0 SOL o 1.0 USDC 1000000000
0.0025 BTC (250,000 satoshis) 2500000
1.5 SOL (1,500,000,000 lamports) 1500000000
5,000 USDC 5000000000000

En el caso de los activos con más de 9 decimales, como ETH, se descarta la parte del importe inferior a 10-9. Una regla no puede verificarlo.

Ethereum

En la siguiente tabla, se describen los atributos de contexto de las cargas útiles de ETHEREUM_TX_V2 (transacciones heredadas codificadas con RLP y EIP-2718, incluida la EIP-1559):

Atributo Valor
secondary_key Para las transferencias de ETH y las llamadas de contrato, la dirección to de la transacción. Para ERC-20 transfer y transferFrom, y ERC-721 transferFrom y safeTransferFrom, el destinatario del token o NFT. Para ERC-20 y ERC-721 approve, el gastador aprobado. Para ERC-721 setApprovalForAll, el operador. En formato de suma de comprobación EIP-55 con mayúsculas y minúsculas.
amount_token_scaled Para las transferencias de ETH y las transferencias y aprobaciones de ERC-20, el importe. Para las llamadas de contrato, el ETH enviado con la llamada; se omite si no se envía ETH. Siempre se omite para las transferencias y aprobaciones de ERC-721, de modo que los límites de inversión fungibles no coincidan con los IDs de tokens de NFT.
token_symbol "ETH" para las transferencias de ETH y para las llamadas de contratos que envían ETH. Para los tokens ERC-20 reconocidos en Ethereum Mainnet, "USDC", "USDT", "DAI" o "WBTC"; se omite para otros tokens y para las operaciones ERC-721.
contract_address Para las transferencias y aprobaciones de ERC-20 y ERC-721, el contrato de token o NFT. Para las llamadas de contrato, el contrato llamado. En formato de suma de comprobación EIP-55 con mayúsculas y minúsculas. Se omite para las transferencias de ETH.
token_standard "ERC721" para transferencias y aprobaciones de ERC-721. Se omite para las transferencias de ETH, las operaciones de ERC-20 y otras llamadas de contrato.
token_id Para los ERC-721 transferFrom, safeTransferFrom y approve, el tokenId de 256 bits como un String de base 10, de modo que los IDs de NFT nunca desborden el Long de 64 bits de Cedar. Como es un String, compáralo para verificar la igualdad con == o in [...]; < y > comparan cadenas, no números. Se omite para setApprovalForAll y para las transacciones que no son ERC-721.
from_address Para ERC-721 transferFrom y safeTransferFrom, el propietario actual (from), en formato de suma de comprobación EIP-55 con mayúsculas y minúsculas.
approve_all Para ERC-721 setApprovalForAll(operator, approved), la marca approved como Bool: true cuando se otorga la aprobación del operador sobre cada NFT de la colección, false cuando se revoca.
chain_id Es el ID de la cadena de la transacción. Se puede omitir en las transacciones heredadas, así que verifícalo con has.
max_fee_atomic Límite de gas × tarifa máxima por gas (o precio del gas para las transacciones heredadas), en gwei.

Para ERC-20 transfer(address, uint256) (0xa9059cbb), cuyo selector es único para ERC-20, un token que la computación multipartita no reconoce tiene su importe escalado como si el token tuviera 18 decimales. Haz coincidir los tokens reconocidos por contract_address y no establezcas límites de importe en los tokens no reconocidos cuyos decimales no sean 18. ERC-20 transferFrom y approve comparten sus selectores con ERC-721, por lo que necesitan un contrato reconocido; una llamada a un contrato no reconocido con uno de estos selectores se rechaza con UNRECOGNIZED_PAYLOAD. Para obtener más información, consulta Tokens no fungibles ERC-721.

En el contexto, no se indica qué tipo de transacción de Ethereum es, por lo que debes tener en cuenta lo siguiente:

  • Las llamadas de contrato que envían ETH se ven como transferencias de ETH. Ambos tienen token_symbol "ETH" y un amount_token_scaled. Solo una llamada de contrato tiene contract_address. Para permitir solo transferencias de ETH, agrega !(context has contract_address).
  • Las aprobaciones de ERC-20 se ven como transferencias de ERC-20. Un approve tiene los mismos contract_address, amount_token_scaled y secondary_key (el pagador) que una transferencia del mismo importe a la misma dirección. Una política que permite la transferencia también permite la aprobación.

Las transacciones de creación de contratos (con una dirección to vacía) no se pueden decodificar y se rechazan con UNRECOGNIZED_PAYLOAD.

Tokens no fungibles ERC-721

En ETHEREUM_TX_V2, Multi-party Compute decodifica los siguientes métodos de ERC-721:

  • safeTransferFrom(address from, address to, uint256 tokenId) (0x42842e0e)
  • safeTransferFrom(address from, address to, uint256 tokenId, bytes data) (0xb88d4fde)
  • transferFrom(address from, address to, uint256 tokenId) (0x23b872dd)
  • approve(address to, uint256 tokenId) (0x095ea7b3)
  • setApprovalForAll(address operator, bool approved) (0xa22cb465)

ERC-20 y ERC-721 comparten los mismos selectores de 4 bytes para transferFrom (0x23b872dd) y approve (0x095ea7b3). Para decidir si el argumento uint256 es un importe fungible o un ID de token, la computación multipartita busca la dirección del contrato to en su registro de contratos de tokens reconocidos. Para las llamadas de ERC-721, se omite amount_token_scaled, token_standard es "ERC721" y token_id es un String de base 10. Se rechaza una llamada a un contrato no reconocido con uno de estos selectores compartidos con UNRECOGNIZED_PAYLOAD.

Datos con tipo de EIP-712

Para las cargas útiles EIP712_TYPED_DATA_V1 (datos con tipo EIP-712 codificados en JSON UTF-8 con types, primaryType, domain y message), la computación multipartita valida la estructura JSON y calcula el resumen de firma EIP-712 de 32 bytes, keccak256(0x1901 ++ domainSeparator ++ hashStruct(message)), donde ++ es la concatenación de bytes. La validación rechaza el anidamiento de más de 15 niveles, los tipos cíclicos, los elementos de array null y los campos domain que no coinciden con types.EIP712Domain, y conserva los números enteros de 256 bits sin pérdida de precisión de punto flotante.

Una carga útil de EIP712_TYPED_DATA_V1 proyecta los siguientes atributos:

Atributo Valor
blockchain Siempre "ETH".
schema Siempre "EIP712_TYPED_DATA_V1".
contract_address domain.verifyingContract, en formato de suma de comprobación EIP-55 con mayúsculas y minúsculas. Se omite cuando el dominio no establece verifyingContract.
chain_id domain.chainId como Long. Se omite cuando el dominio no establece chainId.
max_fee_atomic Siempre es 0, porque la firma de datos con tipo no paga una tarifa de red.
secondary_key Para los tipos de mensajes reconocidos, la contraparte: spender para ERC-2612 Permit y Uniswap Permit2, o to para ERC-3009 TransferWithAuthorization y Safe SafeTx. Para otros tipos de mensajes, consulta domain.verifyingContract.
amount_token_scaled Para los tipos de mensajes reconocidos (Permit, Permit2, TransferWithAuthorization y SafeTx), el token autorizado o el valor de ETH (value o details.amount), en unidades de 10-9. Se omite para otros tipos de mensajes.
token_symbol "USDC", "USDT", "DAI" o "WBTC" cuando el contrato de verificación o el token Permit2 (details.token) es un token reconocido en la red principal de Ethereum. De lo contrario, se omite.
deadline Es la hora de vencimiento del mensaje, en segundos desde el tiempo Unix, cuando el mensaje tiene un campo deadline, sigDeadline o validBefore. De lo contrario, se omite.
eip712 Un Record con los datos escritos. Para obtener más información, consulta los siguientes recursos:

El registro eip712 tiene los siguientes campos:

Campo Tipo de cedro Valor
context.eip712.primary_type String El nombre de primaryType, por ejemplo, "Permit", "PermitSingle", "TransferWithAuthorization" o "SafeTx".
context.eip712.domain Record Los campos de EIP712Domain que establece la carga útil: name, version, chainId, verifyingContract y salt.
context.eip712.message Record Los campos message Los valores enteros de 256 bits (uint256 y int256) son String en base 10, por lo que las reglas pueden coincidir con valores exactos sin desbordamiento de 64 bits.

Bitcoin

En la siguiente tabla, se describen los atributos de contexto de las cargas útiles de BITCOIN_TX_V2 (BIP 174 PSBT v0):

Atributo Valor
secondary_key La dirección de la única salida que no es de cambio. Para una consolidación, en la que cada salida es un cambio, la dirección de la primera salida.
amount_token_scaled Es el importe enviado a secondary_key, sin contar el cambio (1 satoshi = 10). 0 para una consolidación.
token_symbol Siempre "BTC".
contract_address Nunca está presente.
chain_id Nunca está presente, porque una PSBT no indica para qué red es. Las direcciones siempre tienen el formato de las direcciones de la red principal, por lo que una dirección de la red de pruebas también comienza con bc1, 1 o 3. El prefijo de la dirección muestra el tipo de dirección, no la red.
max_fee_atomic La comisión del minero: entradas totales menos salidas totales (1 satoshi = 10).

Para mantener separadas las redes de Bitcoin, usa claves diferentes para cada red, por ejemplo, en un KeyRing para Mainnet y otro para Testnet, y define el alcance de las reglas para ellas con principal_keyring o principal_key. La misma clave puede firmar en ambas redes, por lo que esto solo funciona si nunca usas una clave de Mainnet en Testnet.

No se puede decodificar una transacción que se envía a más de una dirección que no sea de cambio. No se puede evaluar una transacción sin una dirección de envío, como una cuya única salida que no es de cambio es una salida OP_RETURN.

Solana

En la siguiente tabla, se describen los atributos de contexto de las cargas útiles de SOLANA_TX_V1 (mensajes de Solana heredados o v0 sin firmar):

Atributo Valor
secondary_key Para las transferencias de SOL, la billetera de destino. Para las transferencias de tokens, la cuenta de token de destino, no la billetera propietaria. En base58.
amount_token_scaled El importe Para SOL, la cantidad de lamports (1 lamport = 1). Para los tokens, el importe sin procesar escalado con los decimales que lleva la instrucción TransferChecked.
token_symbol "SOL" para transferencias de SOL. Para los tokens, "USDC", "USDT" o "PYUSD"; se omite para otras acuñaciones.
contract_address Para las transferencias de tokens, la dirección de acuñación, en base58. Se omite para las transferencias de SOL.
chain_id Nunca está presente. Los mensajes de Solana no nombran un clúster.
max_fee_atomic El máximo que puede pagar toda la transacción en lamports: 5,000 por cada firma requerida, más la tarifa de prioridad, ⌈límite de unidades de procesamiento × precio de la unidad de procesamiento en microlamports ÷ 106⌉, si la transacción establece un precio de unidad de procesamiento.

Una transacción de Solana puede contener varias instrucciones:

  • Instrucciones de transferencia: Programa del sistema Transfer (SOL) y token de SPL o Token-2022 TransferChecked. La instrucción Transfer sin marcar y los tokens con más de 9 decimales no se pueden decodificar.
  • Otras instrucciones: ComputeBudget SetComputeUnitLimit y SetComputeUnitPrice, Memo (v1 y v2), Associated Token Account Create y CreateIdempotent, y System Program AdvanceNonceAccount. Estas instrucciones no producen un contexto propio.

Cada instrucción de transferencia se evalúa por separado con su propio contexto. La transacción se permite solo si se permiten todas las transferencias; si se rechaza alguna, se rechaza toda la transacción. max_fee_atomic es la tarifa de toda la transacción y es la misma en todos los contextos, por lo que no debes sumarla en todas las transferencias.

Si la transacción establece un precio de unidad de procesamiento sin un límite de unidades de procesamiento, la comisión usa el límite predeterminado de Solana de 200,000 unidades de procesamiento para cada instrucción que no sea de ComputeBudget, hasta 1,400,000.

Los firmantes de la transacción deben coincidir con las cuentas que cada instrucción necesita firmar, y las cuentas de origen y destino deben ser de escritura. Los mensajes v0 que usan tablas de consulta de direcciones no se pueden decodificar. Pasa los bytes del mensaje sin firmar, no un sobre de transacción firmado, en Transaction.payload y Transaction.rawMessage.

Las acuñaciones reconocidas son las de la red principal de Solana. En Devnet o Testnet, una transferencia de tokens no tiene token_symbol, por lo que debes verificar contract_address.

Una instrucción Create de Associated Token Account financia la reserva exenta de renta de la nueva cuenta en SOL. Ese importe no está en amount_token_scaled.

Ejemplos de reglas

Los siguientes ejemplos son políticas de permit y forbid que puedes adaptar. Cada ejemplo verifica cada atributo opcional con has antes de leerlo.

Límite de compra para un llavero con carga útil y metadatos

Permite transferencias de buy_transaction de hasta 500,000 USDC en Ethereum Mainnet desde cualquier clave en el llavero institutional-treasury, cuando el iniciador etiqueta la transacción con "equities-desk", establece una validez de un máximo de 300 segundos y establece un valor de un máximo de $500,000:

permit (
  principal,
  action == Action::"buy_transaction",
  resource == Resource::"transaction_management"
)
when {
  context.principal_keyring == "institutional-treasury" &&
  context.schema == "ETHEREUM_TX_V2" &&
  context has chain_id && context.chain_id == 1 &&
  context has contract_address &&
  context.contract_address == "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" &&
  context has amount_token_scaled && context.amount_token_scaled <= 500000000000000 &&
  context has fiat_amount && context.fiat_amount <= 500000 &&
  context has validity && context.validity <= 300 &&
  context has principal_value1 && context.principal_value1 == "equities-desk"
};

La computación multipartita no compara fiat_amount con la carga útil. Para obtener más información, consulta Atributos de contexto.

Límite de inversión para una clave

Permitir transferencias de ETH de hasta 1 ETH desde una clave en la red principal de Ethereum. !(context has contract_address) excluye las llamadas de contrato que envían ETH:

permit (principal, action, resource)
when {
  context.principal_keyring == "treasury" &&
  context.principal_key == "hot-wallet-1" &&
  context.schema == "ETHEREUM_TX_V2" &&
  context has chain_id && context.chain_id == 1 &&
  context has token_symbol && context.token_symbol == "ETH" &&
  !(context has contract_address) &&
  context has amount_token_scaled && context.amount_token_scaled <= 1000000000
};

Lista de entidades permitidas de monedas estables en Ethereum

Permitir transferencias de hasta 5,000 USDC a una dirección y aprobaciones (asignaciones) de hasta 5,000 USDC para esa dirección. La política verifica contract_address en lugar de token_symbol, por lo que un token de otro contrato que usa el mismo símbolo no coincide:

permit (principal, action, resource)
when {
  context.schema == "ETHEREUM_TX_V2" &&
  context has contract_address &&
  context.contract_address == "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" &&
  context.secondary_key == "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B" &&
  context has amount_token_scaled && context.amount_token_scaled <= 5000000000000
};

token_symbol es "USDC" para esta transacción.

Protección de transferencia y aprobación de operador de ERC-721

Permitir la transferencia de un pagaré del tesoro con asignación de token (token_id == "1042") de un contrato ERC-721 aprobado a una dirección de liquidación y prohibir el otorgamiento de aprobaciones de operadores para toda la colección (setApprovalForAll con approve_all == true).

La política A permite la transferencia de un NFT:

permit (
  principal,
  action == Action::"internal_transfer_transaction",
  resource == Resource::"transaction_management"
)
when {
  context.schema == "ETHEREUM_TX_V2" &&
  context has chain_id && context.chain_id == 1 &&
  context has token_standard && context.token_standard == "ERC721" &&
  context has contract_address &&
  context.contract_address == "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D" &&
  context has token_id && context.token_id == "1042" &&
  context.secondary_key == "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B"
};

La política B prohíbe las aprobaciones de operadores para toda la colección:

forbid (principal, action, resource)
when {
  context.schema == "ETHEREUM_TX_V2" &&
  context has approve_all && context.approve_all == true
};

Límite de permisos de USDC sin gas de EIP-712

Permitir la firma de un Permit ERC-2612 fuera de la cadena por hasta 25,000 USDC en Ethereum Mainnet para un router de liquidación aprobado, cuando el permiso vence antes de un tiempo determinado:

permit (
  principal,
  action == Action::"buy_transaction",
  resource == Resource::"transaction_management"
)
when {
  context.schema == "EIP712_TYPED_DATA_V1" &&
  context has chain_id && context.chain_id == 1 &&
  context has contract_address &&
  context.contract_address == "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" &&
  context has eip712 && context.eip712.primary_type == "Permit" &&
  context.secondary_key == "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45" &&
  context has amount_token_scaled && context.amount_token_scaled <= 25000000000000 &&
  context has deadline && context.deadline <= 1793491200
};

Límite de inversión y de tarifa de Bitcoin

Permite transferencias de hasta 0.0025 BTC con una comisión de minero de hasta 10,000 satoshis, desde claves de un llavero de claves que usas solo en la red principal de Bitcoin:

permit (principal, action, resource)
when {
  context.schema == "BITCOIN_TX_V2" &&
  context.principal_keyring == "btc-mainnet" &&
  context has amount_token_scaled && context.amount_token_scaled <= 2500000 &&
  context.max_fee_atomic <= 100000
};

Transferencia de SOL y límite de tarifa de prioridad

Permite transferencias de SOL de hasta 1.5 SOL cuando la tarifa total, incluida cualquier tarifa de prioridad, sea de un máximo de 50,000 lamports (0.00005 SOL):

permit (principal, action, resource)
when {
  context.schema == "SOLANA_TX_V1" &&
  context has token_symbol && context.token_symbol == "SOL" &&
  !(context has contract_address) &&
  context has amount_token_scaled && context.amount_token_scaled <= 1500000000 &&
  context.max_fee_atomic <= 50000
};

Transferencia de token SPL o Token-2022 en Solana

Permitir transferencias de hasta 250 USDC a una cuenta de token. La misma regla coincide con los programas SPL Token y Token-2022, ya que el contexto no indica qué programa usa la transferencia:

permit (principal, action, resource)
when {
  context.schema == "SOLANA_TX_V1" &&
  context has contract_address &&
  context.contract_address == "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" &&
  context.secondary_key == "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin" &&
  context has amount_token_scaled && context.amount_token_scaled <= 250000000000
};

secondary_key es la cuenta de token del destinatario para esta acuñación. Para permitir una billetera de destinatario, enumera su cuenta de token para cada acuñación que permitas. En una transacción con varias transferencias, esta regla debe coincidir con cada transferencia.

Bloque de recursos no reconocido

Rechazar cualquier transferencia cuyo activo no reconozca la computación multipartita Esta política de forbid solo usa has, por lo que no puede fallar en la evaluación:

forbid (principal, action, resource)
when { context has amount_token_scaled }
unless { context has token_symbol };

Límite de tarifa para una cadena de bloques

max_fee_atomic siempre está presente, por lo que esta política de forbid no puede fallar en la evaluación. Debido a que la escala es de 10-9 de cada moneda nativa, el mismo número es un valor diferente en cada cadena de bloques. Limita el alcance de la política a una cadena de bloques:

forbid (principal, action, resource)
when { context.blockchain == "ETH" && context.max_fee_atomic > 10000000 };

Esto rechaza las transacciones de Ethereum que pueden pagar más de 0.01 ETH en tarifas.

KeyRings

Un KeyRing es un contenedor estático que agrupa claves de MPC, por ejemplo, "institutional-treasury" o "btc-cold-storage". Cada clave se crea dentro de un solo llavero de claves y permanece en él de forma permanente.

Los llaveros de claves participan en las políticas de tres maneras:

  • KeyRing KeyPolicy (quórum de firma). Cuando creas un KeyRing, estableces su KeyPolicy inmutable, que define el árbol de umbral de los equipos y usuarios que tienen claves compartidas y deben aprobar antes de que cualquier clave del KeyRing pueda firmar. Las políticas de transacciones funcionan junto con el KeyPolicy: la política de transacciones evalúa las reglas empresariales para la carga útil (PERMIT o DENY), mientras que el KeyPolicy del llavero rige qué recursos compartidos de claves deben autorizar la ceremonia de firma.
  • Definir el alcance de las políticas de transacciones por llavero de claves de firma (context.principal_keyring). El contexto de cada transacción incluye context.principal_keyring, establecido en el ID del llavero de claves que contiene la clave de firma, y context.principal_key, establecido en el ID de la clave de firma. Una regla con context.principal_keyring == "institutional-treasury" se aplica a todas las claves del llavero de claves, incluidas las que se creen en ese llavero de claves más adelante, sin crear ni aprobar una política nueva:

    permit (
      principal,
      action == Action::"internal_transfer_transaction",
      resource == Resource::"transaction_management"
    )
    when {
      context.principal_keyring == "institutional-treasury" &&
      context has fiat_amount && context.fiat_amount <= 100000
    };
    
  • Lista de entidades permitidas de llaveros de claves de destino (en una KeyList). También puedes agregar un KeyRing como una entrada en una KeyList, de modo que las transferencias a la dirección de cadena de bloques de cualquier clave activa en ese KeyRing, como los barridos internos entre KeyRings activos y pasivos, se permitan automáticamente a medida que se crean claves nuevas. Para ver un ejemplo, consulta Lista de entidades permitidas y bloqueadas de KeyList.

Lista de entidades permitidas y bloqueadas de KeyList

Permitir transferencias de hasta 1 ETH solo a direcciones en la KeyList de trusted-destinations. context.key_lists["trusted-destinations"] es el conjunto de direcciones al que se expande KeyList en la createTime de la transacción, por lo que agregar o quitar una entrada cambia lo que permite esta regla sin una política nueva:

// Assuming you created a KeyList with ID "trusted-destinations":
permit (principal, action, resource)
when {
  context.schema == "ETHEREUM_TX_V2" &&
  context has token_symbol && context.token_symbol == "ETH" &&
  !(context has contract_address) &&
  context.key_lists["trusted-destinations"].contains(context.secondary_key) &&
  context has amount_token_scaled && context.amount_token_scaled <= 1000000000
};

Rechaza cualquier transacción a una dirección en la KeyList de blocked-addresses, en cada cadena de bloques. key_lists y secondary_key siempre están presentes, y CreateTransactionPolicy verifica que KeyList exista, por lo que esta política de forbid no puede fallar en la evaluación:

// Assuming you created a KeyList with ID "blocked-addresses":
forbid (principal, action, resource)
when { context.key_lists["blocked-addresses"].contains(context.secondary_key) };

Escribe el ID de KeyList con la sintaxis de corchetes, context.key_lists["..."], en lugar de la sintaxis de puntos. La sintaxis de puntos no analiza los IDs que contienen un guion o comienzan con un dígito. Las entradas se comparan como cadenas, por lo que debes agregar entradas manuales en el formato de dirección que describe la tabla de cada cadena de bloques. Para obtener más información, consulta KeyLists en el contexto de Cedar.