机密同质化代币

机密同质化代币 是一个标准的同质化代币实现,与 ERC20 类似,但从一开始就考虑了保密性。所有余额和转移金额都表示为密文句柄,确保不会向公众泄露任何数据。

虽然该标准的设计灵感来自 ERC-20,但它并不符合 ERC-20 标准——该标准借鉴了过去 10 年来构建的所有代币(ERC-20、ERC-721、ERC-1155、ERC-6909 等)的经验,并提供了一个功能接口,以实现最大的功能性。

使用

转移

该代币标准公开了八种不同的转移函数。它们都是以下选项的排列组合:

  • transfertransferFromtransfer 从发送者处转移代币,而 transferFrom 从指定的 from 地址转移代币。参见 operator

  • 有和没有 inputProof:可以提供一个 inputProof 来证明发送者知道提供的密文 amount 的值。

  • 有和没有 ERC1363 风格的回调:该标准实现了回调,有关更多详细信息,请参见 callback 部分。

选择适当的转移函数并使用 fhevm-js 生成一个密文。如果密文是一个新值,或者发送者没有访问该密文的权限,则必须提供一个输入证明来表明发送者知道该密文的值。

操作员

操作员是一个地址,它有权通过调用 transferFrom 代表另一个地址转移代币。如果 Bob 是 Alice 的操作员,那么 Bob 可以在任何时间点转移 Alice 的任何数量的代币。操作员使用过期时间戳进行设置——这可以被认为是 ERC20 的有限持续时间的无限额度。下面是一个将 Bob 设置为 Alice 的操作员 24 小时的例子。

const alice: Wallet;
const expirationTimestamp = Math.round(Date.now()) + 60 * 60 * 24; // 现在 + 24 小时

await tokenContract.connect(alice).setOperator(bob, expirationTimestamp);
操作员无权重新加密/解密其他地址的余额句柄。这意味着操作员不能转移全部余额,并且只能在交易后(通过解密转移的金额)知道成功与否。
为任何时间设置操作员都允许该操作员 拿走你所有的代币。在授予操作员批准之前,请仔细审查所有潜在的操作员。

回调

该代币标准公开了带有和不带有回调的转移函数。调用者可以自行决定转移是否需要回调。对于支持回调的智能合约,回调允许跳过操作员批准步骤,并通过回调直接调用接收者合约。

作为回调目标的智能合约必须实现 IConfidentialFungibleTokenReceiver。在更新转移的余额后,通过调用 onConfidentialTransferReceived 函数来触发回调。该函数必须恢复或返回一个表示成功的 ebool。如果回调返回 false,则代币转移将被撤销。

例子

特权铸币者/销毁者

这是一个具有特权铸币者和销毁者的机密同质化代币的合约示例。

Unresolved include directive in modules/ROOT/pages/token.adoc - include::api:example$ConfidentialFungibleTokenMintableBurnable.sol[]

交换

交换是同质化代币最原始的用例之一。以下是在机密和非机密代币之间进行交换的示例。

ERC20 交换为 ConfidentialFungibleToken

从非机密 ERC20 交换到机密 ConfidentialFungibleToken 非常简单,实际上是在 ConfidentialFungibleTokenERC20Wrapper 中完成的。请参见下面 wrap 函数的摘录。

function wrap(address to, uint256 amount) public virtual {
    // 获取代币的所有权
    SafeERC20.safeTransferFrom(underlying(), msg.sender, address(this), amount - (amount % rate()));

    // 铸造机密代币
    _mint(to, (amount / rate()).toUint64().asEuint64());
}

ERC20 代币只是被转移进来,如果失败就会恢复。然后,我们使用内部 _mint 函数转移出正确数量的 ConfidentialFungibleToken,这保证会成功。

ConfidentialFungibleToken 交换为 ConfidentialFungibleToken

从一个机密 ConfidentialFungibleToken 交换到另一个机密 ConfidentialFungibleToken 要稍微复杂一些,但考虑到 TFHE 库的使用,这非常简单。为了示例的方便,我们将以 1:1 的汇率从 fromToken 交换到 toToken

Unresolved include directive in modules/ROOT/pages/token.adoc - include::api:example$SwapConfidentialFungibleTokenToConfidentialFungibleToken.sol[]

步骤如下:

  1. 检查操作员批准

  2. 允许 fromToken 访问 amount

  3. amountfrom 转移到此合约

  4. 允许 toToken 访问 amountTransferred

  5. amountTransferred 转移到 msg.sender

ConfidentialFungibleToken 交换为 ERC20

从机密代币交换到非机密代币是最复杂的,因为必须访问解密后的数据才能准确地完成请求。在我们的示例中,解密将在链下完成,并使用 Zama 的 Gateway 中继回来。下面是一个从机密代币以 1:1 的汇率交换到 ERC20 代币的合约的示例。

Unresolved include directive in modules/ROOT/pages/token.adoc - include::api:example$SwapConfidentialToERC20.sol[]