编写交易政策规则

本页面介绍了交易政策可以检查的属性,并展示了以太坊(ETHEREUM_TX_V2 和 EIP712_TYPED_DATA_V1)、比特币 (BITCOIN_TX_V2) 和 Solana (SOLANA_TX_V1) 交易的示例规则。

如需了解如何组合政策、强制执行哪些政策以及事务被拒绝的原因,请参阅事务政策评估。

规则结构

事务政策是针对主账号、操作、资源和上下文的单个 Cedar permit 或 forbid 语句:

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
};

请注意以下几点:

  • 属性位于上下文的顶级。请写 context.amount_token_scaled,而不是 context.transaction.spend_amount_scaled,如 v1alpha1 中所示。
  • 某些属性是可选属性。如果可选属性不在上下文中,则会导致政策无法评估,而无法评估的政策不匹配。在读取可选属性之前,请先使用 has 检查该属性是否存在,或在 forbid 规则中使用 unless { context has ... } 检查。如需了解详情,请参阅场景 6 和场景 8。
  • Cedar 字符串区分大小写。以每个链的表格中所述的格式比较地址。

对于主账号,请参阅 Cedar 请求。如需了解 CreateTransaction 接受的操作(buy_transaction、sell_transaction 和 internal_transfer_transaction),请参阅操作和资源。

上下文属性

每个事务的上下文都具有从其载荷解码的属性、签名密钥及其 KeyRing 的 ID,以及发起方设置的元数据属性(fiat_amount、validity、principal_value1 和 principal_value2)。

每个区块链的载荷属性都相同。下表介绍了所有上下文属性,以太坊、比特币和 Solana 的表格介绍了多方计算如何为该区块链填充每个属性:

属性 雪松类型 始终存在? 值
schema String 是 载荷格式:"ETHEREUM_TX_V2"、"BITCOIN_TX_V2"、"SOLANA_TX_V1" 或 "EIP712_TYPED_DATA_V1"。如需了解详情,请参阅架构名称。
blockchain String 是 "ETH"、"BTC"或"SOL"。
principal_keyring String 是 包含签名密钥的 KeyRing 的 ID,例如 "treasury"。
principal_key String 是 签名密钥的 ID,例如 "hot-wallet-1"。
secondary_key String 是 从载荷中解码出的目标地址、代币或 NFT 接收方、已获批准的支出方或操作方,或 EIP-712 交易对手。
amount_token_scaled Long 否 已转移或已批准的可替代金额,以资产的 10-9 为单位。如果未转移任何可替代金额,例如 ERC-721 操作或不发送 ETH 的合约调用,则省略此字段。如需了解详情,请参阅金额。
token_symbol String 否 资产的代码,例如 "ETH"、"BTC"、"SOL" 或 "USDC"。如果资产不是多方计算可识别的资产,以及对于 ERC-721 操作,则省略。
contract_address String 否 ERC-20 或 ERC-721 代币合约或被调用合约 (Ethereum)、验证合约 (EIP-712) 或铸币合约 (Solana)。对于原生转移作业,此字段会被省略。
token_standard String 否 "ERC721",用于 ERC-721 转移和批准 (ETHEREUM_TX_V2)。对于原生转移和可替代代币操作,此字段会被省略。
token_id String 否 256 位 ERC-721 tokenId,以 10 进制字符串 (ETHEREUM_TX_V2) 表示。对于 setApprovalForAll 和非 ERC-721 交易,此字段会被省略。
from_address String 否 ERC-721 transferFrom 和 safeTransferFrom 调用中的当前所有者 (from),采用大小写混合的 EIP-55 校验和格式。
approve_all Bool 否 ERC-721 setApprovalForAll(operator, approved) 调用中的 approved 标志:授予操作员批准时为 true,撤销批准时为 false。
deadline Long 否 EIP712_TYPED_DATA_V1 消息的过期时间(自 Unix 纪元以来的秒数),取自其 deadline、sigDeadline 或 validBefore 字段。
eip712 Record 否 结构化 EIP-712 载荷:primary_type、domain 和 message,其中 256 位整数表示为十进制字符串。仅限EIP712_TYPED_DATA_V1。
chain_id Long 否 EVM 链 ID,例如以太坊主网的 1 或 Sepolia 的 11155111。仅限以太坊和 EIP-712。
max_fee_atomic Long 是 交易可支付的最高网络费用,以区块链原生代币的 10-9 为单位。0,EIP712_TYPED_DATA_V1。
payload String 是 载荷的十六进制编码摘要,采用小写形式。
time_stamp Long 是 交易的 createTime(与 Unix 纪元之间相隔的秒数)。
key_lists Record/Set<String> 是 一条记录,用于将实例中的每个 KeyList ID 映射到该 KeyList 中区块链地址的 Set<String>,在 createTime 解析。如果实例没有 KeyList,则为空记录。使用方括号语法读取 KeyList,例如 context.key_lists["trusted-destinations"]。如需了解详情,请参阅 Cedar 上下文中的 KeyList。

principal_keyring 和 principal_key 是 ID,而不是完整资源名称。密钥 ID 仅在其 KeyRing 中是唯一的。选中 principal_keyring,将规则应用于 KeyRing 中的每个密钥,或同时选中这两个属性来指定一个密钥:

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

如果载荷无法由 Transaction.schema 的解析器解码,或者无法投影到上下文中,则不会评估任何政策,并且事务会被拒绝,并显示 UNRECOGNIZED_PAYLOAD。如需了解详情,请参阅拒绝原因。

架构名称

schema 属性是 v1beta API 中 PayloadSchema 值的名称:"ETHEREUM_TX_V2"、"BITCOIN_TX_V2"、"SOLANA_TX_V1" 或 "EIP712_TYPED_DATA_V1"。v1alpha1 规则使用的小写名称(例如 "ethereum.transaction.v2")永远不会在 v1beta 中匹配。

没有 schema 或 blockchain 检查的规则适用于每个区块链。如需将规则限制为仅适用于一个区块链,请勾选 schema。

金额

amount_token_scaled 和 max_fee_atomic 对每种资产使用相同的比例:1 个单位是资产的 10-9,因此任何资产的 1.0 都是 1000000000。如需获取规则的值,请将金额乘以 1,000,000,000 (109)。下表列出了一些示例:

金额 amount_token_scaled
0.1 ETH 100000000
1.0 ETH、1.0 BTC、1.0 SOL 或 1.0 USDC 1000000000
0.0025 BTC(250,000 聪) 2500000
1.5 SOL(1,500,000,000 lamport) 1500000000
5,000 USDC 5000000000000

对于小数位数超过 9 位的资产(例如 ETH),金额中低于 10-9 的部分会被舍弃。规则无法检查。

以太坊

下表介绍了 ETHEREUM_TX_V2 载荷(RLP 编码的旧版和 EIP-2718 交易,包括 EIP-1559)的上下文属性:

属性 值
secondary_key 对于 ETH 转账和合约调用,为交易的 to 地址。对于 ERC-20 transfer 和 transferFrom,以及 ERC-721 transferFrom 和 safeTransferFrom,此字段表示代币或 NFT 接收者。对于 ERC-20 和 ERC-721 approve,为已获批准的支出方。对于 ERC-721 setApprovalForAll,则为操作者。采用大小写混合的 EIP-55 校验和格式。
amount_token_scaled 对于 ETH 转账以及 ERC-20 转账和批准,则为金额。对于合约调用,指随调用发送的 ETH;如果未发送 ETH,则省略。对于 ERC-721 转账和批准,此字段始终省略,以便同质化支出限额与 NFT 代币 ID 不匹配。
token_symbol "ETH",适用于 ETH 转账以及发送 ETH 的合约调用。对于以太坊主网、"USDC"、"USDT"、"DAI" 或 "WBTC" 上公认的 ERC-20 代币,此字段为必填;对于其他代币和 ERC-721 操作,此字段会被省略。
contract_address 对于 ERC-20 和 ERC-721 转账和批准,则为代币或 NFT 合约。对于合约调用,则为调用的合约。采用大小写混合的 EIP-55 校验和格式。对于 ETH 转账,此字段会被省略。
token_standard "ERC721",用于 ERC-721 转移和批准。对于 ETH 转账、ERC-20 操作和其他合约调用,此字段会被省略。
token_id 对于 ERC-721 transferFrom、safeTransferFrom 和 approve,256 位 tokenId 作为 10 进制 String,因此 NFT ID 永远不会溢出 Cedar 的 64 位 Long。由于它是 String,因此请将其与 == 或 in [...] 进行比较,以确定是否相等;< 和 > 比较的是字符串,而不是数字。对于 setApprovalForAll 和非 ERC-721 交易,此字段会被省略。
from_address 对于 ERC-721 transferFrom 和 safeTransferFrom,当前所有者 (from),采用大小写混合的 EIP-55 校验和格式。
approve_all 对于 ERC-721 setApprovalForAll(operator, approved),approved 标志作为 Bool:在向操作员授予对集合中每个 NFT 的批准时为 true,在撤销批准时为 false。
chain_id 交易中的链 ID。在旧版交易中可以省略,因此请使用 has 进行检查。
max_fee_atomic Gas 限制 × 每单位 Gas 的最高费用(或旧版交易的 Gas 价格),以 gwei 为单位。

对于 ERC-20 transfer(address, uint256) (0xa9059cbb)(其选择器对 ERC-20 而言是唯一的),多方计算无法识别的代币会将其金额缩放为具有 18 位小数。按 contract_address 匹配已识别的代币,不要对小数位数不为 18 的未识别代币设置金额限制。ERC-20 transferFrom 和 approve 与 ERC-721 共享其选择器,因此它们需要一个已识别的合约;使用这些选择器之一对未识别合约的调用会被拒绝,并显示 UNRECOGNIZED_PAYLOAD。如需了解详情,请参阅 ERC-721 非同质化代币。

上下文未说明这是哪种以太坊交易,因此请注意以下几点:

  • 发送 ETH 的合约调用看起来像 ETH 转账。两者都具有 token_symbol "ETH" 和 amount_token_scaled。只有合约调用具有 contract_address。如需仅允许 ETH 转账,请添加 !(context has contract_address)。
  • ERC-20 批准看起来像 ERC-20 转账。approve 与向同一地址转移相同金额的交易具有相同的 contract_address、amount_token_scaled 和 secondary_key(支出者)。允许转移的政策也允许审批。

合约创建交易(具有空 to 地址)无法解码,并会被拒绝,错误代码为 UNRECOGNIZED_PAYLOAD。

ERC-721 非同质化代币

在 ETHEREUM_TX_V2 下,多方计算会解码以下 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 和 ERC-721 具有相同的 4 字节选择器,分别用于 transferFrom (0x23b872dd) 和 approve (0x095ea7b3)。为了确定 uint256 参数是可替代金额还是 token ID,多方计算会在其已识别代币合约的注册表中查找 to 合约地址。对于 ERC-721 调用,amount_token_scaled 会被省略,token_standard 为 "ERC721",token_id 为以 10 为底的 String。对具有这些共享选择器的无法识别合约的调用会被拒绝,并返回 UNRECOGNIZED_PAYLOAD。

EIP-712 类型化数据

对于 EIP712_TYPED_DATA_V1 载荷(采用 UTF-8 JSON 编码的 EIP-712 类型化数据,包含 types、primaryType、domain 和 message),多方计算会验证 JSON 结构并计算 32 字节的 EIP-712 签名摘要 keccak256(0x1901 ++ domainSeparator ++ hashStruct(message)),其中 ++ 是字节串联。验证会拒绝超过 15 层的嵌套、循环类型、null 数组元素以及与 types.EIP712Domain 不匹配的 domain 字段,并保留 256 位整数,而不会造成浮点精度损失。

EIP712_TYPED_DATA_V1 载荷会投影以下属性:

属性 值
blockchain 始终为 "ETH"。
schema 始终为 "EIP712_TYPED_DATA_V1"。
contract_address domain.verifyingContract,采用大小写混合的 EIP-55 校验和格式。如果网域未设置 verifyingContract,则省略。
chain_id domain.chainId,以 Long 形式表示。如果网域未设置 chainId,则省略。
max_fee_atomic 始终为 0,因为对类型化数据进行签名无需支付网络费用。
secondary_key 对于可识别的消息类型,交易对手方为:spender(对于 ERC-2612 Permit 和 Uniswap Permit2)或 to(对于 ERC-3009 TransferWithAuthorization 和 Safe SafeTx)。对于其他消息类型,请参阅domain.verifyingContract。
amount_token_scaled 对于已识别的消息类型(Permit、Permit2、TransferWithAuthorization 和 SafeTx),授权的代币或 ETH 值(value 或 details.amount),单位为 10-9。对于其他消息类型,此字段会被省略。
token_symbol 如果验证合约或 Permit2 代币 (details.token) 是以太坊主网上的公认代币,则为 "USDC"、"USDT"、"DAI" 或 "WBTC"。否则省略。
deadline 消息的到期时间(与 Unix 纪元之间相隔的秒数),此时消息具有 deadline、sigDeadline 或 validBefore 字段。否则省略。
eip712 包含类型化数据的 Record。有关详情,请参阅下表。

eip712 记录包含以下字段:

字段 雪松类型 值
context.eip712.primary_type String primaryType 名称,例如 "Permit"、"PermitSingle"、"TransferWithAuthorization" 或 "SafeTx"。
context.eip712.domain Record 载荷设置的 EIP712Domain 字段:name、version、chainId、verifyingContract 和 salt。
context.eip712.message Record message 字段。256 位整数值(uint256 和 int256)是 10 进制String,因此规则可以匹配确切的值,而不会发生 64 位溢出。

比特币

下表介绍了 BITCOIN_TX_V2 载荷(BIP 174 PSBT v0)的上下文属性:

属性 值
secondary_key 未发生变化的输出的地址。对于合并(其中每个输出都是找零),第一个输出的地址。
amount_token_scaled 发送到 secondary_key 的金额,不包括找零(1 聪 = 10)。0(对于合并)。
token_symbol 始终为 "BTC"。
contract_address 一律不显示。
chain_id 永远不会出现,因为 PSBT 不会说明它适用于哪个网络。地址始终采用主网地址格式,因此测试网地址也以 bc1、1 或 3 开头。地址前缀显示的是地址类型,而不是网络。
max_fee_atomic 矿工费:总输入减去总输出(1 聪 = 10)。

为了区分比特币网络,请为每个网络使用不同的密钥(例如,一个密钥环用于主网,另一个密钥环用于测试网),并使用 principal_keyring 或 principal_key 将规则范围限定为这些密钥。同一密钥可以在两个网络上签名,因此只有在您从不在 Testnet 上使用 Mainnet 密钥时,此方法才有效。

无法解码发送到多个非找零地址的交易。无法评估没有发送地址的交易,例如唯一非找零输出为 OP_RETURN 输出的交易。

Solana

下表介绍了 SOLANA_TX_V1 载荷(未签名的旧版或 v0 Solana 消息)的上下文属性:

属性 值
secondary_key 对于 SOL 转账,目标钱包。对于代币转账,目标代币账号,而非拥有该账号的钱包。采用 base58 格式。
amount_token_scaled 金额。对于 SOL,为 lamport 数量(1 lamport = 1)。对于代币,为按 TransferChecked 指令所带小数缩放的原始金额。
token_symbol "SOL"(对于 SOL 转账)。对于代币,为 "USDC"、"USDT" 或 "PYUSD";对于其他铸造,则省略。
contract_address 对于代币转账,则为铸造地址(采用 base58 格式)。对于 SOL 转账,此字段会被省略。
chain_id 一律不提供。Solana 消息不指定集群。
max_fee_atomic 整个交易可以支付的最高 lamport 费用:每个必需签名 5,000 lamport,加上优先费用(如果交易设置了计算单位价格,则为 ⌈计算单位限制 × 计算单位价格 [以 micro-lamport 为单位] ÷ 106⌉)。

一个 Solana 交易可以包含多条指令:

  • 转账指令:系统程序 Transfer (SOL) 以及 SPL 代币或 Token-2022 TransferChecked。未选中的 Transfer 指令以及小数位数超过 9 位的代币无法解码。
  • 其他指令:ComputeBudget SetComputeUnitLimit 和 SetComputeUnitPrice、Memo(v1 和 v2)、Associated Token Account Create 和 CreateIdempotent,以及 System Program AdvanceNonceAccount。这些指令不会产生自己的上下文。

每条转移指令都会根据其自身上下文单独评估。只有在每项转账都获得许可的情况下,交易才会被允许;如果任何转账被拒绝,则整个交易都会被拒绝。max_fee_atomic 是整个交易的费用,在每种情况下都相同,因此请勿在转账中累加。

如果交易设置了计算单元价格,但未设置计算单元上限,则费用将使用 Solana 默认上限,即除 ComputeBudget 指令外,每条指令最多 200,000 个计算单元,上限为 1,400,000 个。

交易的签名者必须与每条指令需要签名的账号匹配,并且来源账号和目标账号必须可写。无法解码使用地址对照表的 v0 消息。在 Transaction.payload 和 Transaction.rawMessage 中传递未签名的消息字节,而不是已签名的交易信封。

可识别的铸币是 Solana Mainnet 铸币。在 Devnet 或 Testnet 上,代币转账没有 token_symbol,因此请改为检查 contract_address。

关联的代币账号 Create 指令会为新账号的免租金准备金提供 SOL 资金。该金额不是amount_token_scaled。

示例规则

以下示例是您可以调整的 permit 和 forbid 政策。每个示例都会在读取每个可选属性之前使用 has 进行检查。

使用载荷和元数据的密钥环的购买限制

当发起方使用 "equities-desk" 标记交易、设置最多 300 秒的有效期并声明最多 500,000 美元的价值时,允许从 institutional-treasury 密钥环中的任何密钥在以太坊主网上进行最多 500,000 USDC 的 buy_transaction 转账:

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"
};

多方计算不会根据载荷检查 fiat_amount。如需了解详情,请参阅上下文属性。

一个密钥的支出限额

允许从以太坊主网上的一个密钥转移最多 1 ETH。 !(context has contract_address) 排除发送 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
};

以太坊上的稳定币许可清单

允许向一个地址最多转账 5,000 USDC,并允许该地址最多批准(限额)5,000 USDC。该政策会检查 contract_address,而不是 token_symbol,因此来自使用相同符号的其他合约的代币不匹配:

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为"USDC"。

ERC-721 转移和操作员批准保护

允许将一个代币化国库券 (token_id == "1042") 从已获批准的 ERC-721 合约转移到结算地址,并禁止授予集合范围的操作员批准(setApprovalForAll 搭配 approve_all == true)。

政策 A 允许进行一次 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"
};

政策 B 禁止集合范围内的操作员审批:

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

EIP-712 免 gas 费 USDC 许可限额

允许在以太坊主网上为已获批准的结算路由器签署链下 ERC-2612 Permit,金额最高为 25,000 USDC,前提是该许可在给定时间之前到期:

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
};

比特币支出限额和费用上限

允许从您仅在比特币主网上使用的 KeyRing 中的密钥进行最多 0.0025 BTC 的转账,矿工费最多为 10,000 聪:

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
};

SOL 转账和优先费限额

当总费用(包括任何优先费用)不超过 50,000 lamport(0.00005 SOL)时,允许最多 1.5 SOL 的 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
};

Solana 上的 SPL 代币或 Token-2022 转账

允许向一个代币账户转账最多 250 USDC。同一规则会匹配 SPL Token 和 Token-2022 程序,因为上下文未说明转账使用的是哪个程序:

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 是此铸造操作的接收方代币账号。如需允许收款方钱包,请为您允许的每个铸币列出其代币账号。在包含多项转账的交易中,此规则必须与每项转账都匹配。

无法识别的素材资源块

拒绝资产多方计算无法识别的任何转移。此 forbid 政策仅使用 has,因此不会评估失败:

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

区块链的费用上限

max_fee_atomic 始终存在,因此此 forbid 政策不会评估失败。由于比例是每个原生代币的 10-9,因此相同的数字在每个区块链上代表不同的值。将政策范围限定为一个区块链:

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

这会拒绝费用可能超过 0.01 ETH 的以太坊交易。

密钥环

KeyRing 是一个静态容器,用于对 MPC 密钥(例如 "institutional-treasury" 或 "btc-cold-storage")进行分组。每个密钥都是在单个 KeyRing 中创建的,并永久保留在该 KeyRing 中。

密钥环通过以下三种方式参与政策:

  • KeyRing KeyPolicy(签名法定人数)。创建 KeyRing 时,您需要设置其不可变的 KeyPolicy,该政策定义了持有密钥共享的团队和用户的阈值树,并且必须在 KeyRing 中的任何密钥可以签名之前获得批准。交易政策与 KeyPolicy 协同工作:交易政策评估载荷(PERMIT 或 DENY)的业务规则,而 KeyRing 的 KeyPolicy 则控制哪些密钥共享必须授权签名仪式。
  • 按签名 KeyRing (context.principal_keyring) 限定事务政策的范围。每个事务的上下文都包含 context.principal_keyring(设置为保存签名密钥的 KeyRing 的 ID)和 context.principal_key(设置为签名密钥的 ID)。具有 context.principal_keyring == "institutional-treasury" 的规则适用于 KeyRing 中的每个密钥,包括稍后在该 KeyRing 中创建的密钥,而无需创建或批准新政策:

    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
    };
    
  • 目标 KeyRing 许可清单(在 KeyList 中)。您还可以将 KeyRing 作为条目添加到 KeyList 中,这样,当创建新密钥时,系统会自动允许向该 KeyRing 中任何有效密钥的区块链地址进行转账,例如在热 KeyRing 和冷 KeyRing 之间进行内部清扫。如需查看示例,请参阅 KeyList 许可清单和屏蔽清单。

KeyList 许可清单和屏蔽清单

仅允许向 trusted-destinations KeyList 中的地址转移最多 1 ETH。context.key_lists["trusted-destinations"] 是 KeyList 在事务的 createTime 处扩展到的地址集,因此添加或移除条目会更改此规则允许的内容,而无需新政策:

// 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
};

在每个区块链上,拒绝向 blocked-addresses KeyList 中的地址进行的任何交易。key_lists 和 secondary_key 始终存在,并且 CreateTransactionPolicy 会验证 KeyList 是否存在,因此此 forbid 政策不会无法评估:

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

请使用方括号语法 context.key_lists["..."](而非点语法)编写 KeyList ID。点语法无法解析包含连字符或以数字开头的 ID。条目会作为字符串进行比较,因此请按照每个区块链的表所描述的地址格式添加手动条目。如需了解详情,请参阅 Cedar 上下文中的 KeyList。