IPrivacy.singleProofBatchTransferWithAuthorization

singleProofBatchTransferWithAuthorization(
  PrivacySingleProofBatchTransferRequest request,
  PrivacyActionAuthorization authorization
) external returns (bool success)

singleProofBatchTransfer의 메타 트랜잭션 변형입니다. 릴레이어가 authorization.effectiveSender를 대신하여 배치를 제출하며, 서명자는 요청 해시를 특정 executor·nonce·deadline에 묶어 오프체인에서 서명해 둡니다. authorization.authorizationKind에 따라 EOA 서명, ERC-1271 스마트 계정 서명, EIP-7702 위임 EOA 서명을 지원합니다. 요청 해시 도메인은 이 단일 증명 배치 메서드 전용이라 다른 프라이버시 호출용 인가와 충돌하지 않습니다. 이 프리컴파일은 커스텀 오류 타입을 선언하지 않으므로 모든 실패는 일반 문자열 revert로 전달됩니다.

파라미터

이름 타입 필수 설명
request PrivacySingleProofBatchTransferRequest singleProofBatchTransfer와 동일한 배치 페이로드입니다. 메서드 ID와 ABI 인코딩된 요청 튜플로 계산한 요청 해시가 인가 서명에 함께 묶입니다.
authorization PrivacyActionAuthorization 오프체인 인가입니다. 필드는 다음과 같습니다. effectiveSender(정책 엔진이 실제 발신자로 취급하는 계정), executor(msg.sender와 같아야 하며 릴레이어 주소입니다), nonce(effectiveSender별로 고유하며 리플레이 보호가 적용됩니다), deadline(unix 초 단위이며 미래여야 합니다), authorizationKind(0=EOA, 1=ERC-1271, 2=EIP-7702이며 그 외 값은 revert됩니다), signature(bytes이며 EOA는 65바이트 (r, s, v)입니다).

반환값

타입: bool

성공 시 true를 반환합니다. 실패는 일반 문자열 revert로 전달됩니다.

에러

코드 이름 설명
privacy authorization effectiveSender is required privacy authorization effectiveSender is required authorization.effectiveSender가 0 주소이면 이 문자열로 revert됩니다.
privacy authorization executor is required privacy authorization executor is required authorization.executor가 0 주소이면 이 문자열로 revert됩니다.
privacy authorization executor mismatch privacy authorization executor mismatch msg.senderauthorization.executor와 일치하지 않으면 이 문자열로 revert됩니다.
privacy authorization deadline is required privacy authorization deadline is required authorization.deadline이 0이면 이 문자열로 revert됩니다.
privacy authorization expired privacy authorization expired 블록 시간이 authorization.deadline을 지나면 이 문자열로 revert됩니다.
privacy authorization nonce already used privacy authorization nonce already used 동일한 effectiveSender에 대해 이전 프라이버시 호출에서 authorization.nonce가 이미 사용되었을 때 이 문자열로 revert됩니다.
unsupported privacy authorization kind %d unsupported privacy authorization kind %d authorizationKind가 지원 값(0 EOA, 1 ERC-1271, 2 EIP-7702) 중 하나가 아니면 이 문자열로 revert됩니다.
privacy EOA authorization signer mismatch privacy EOA authorization signer mismatch 복원된 EOA 서명자가 authorization.effectiveSender와 일치하지 않으면 이 문자열로 revert됩니다.
privacy EOA authorization signature must be 65 bytes privacy EOA authorization signature must be 65 bytes EOA 서명 blob의 길이가 65바이트가 아니면 이 문자열로 revert됩니다.
privacy ERC-1271 authorization rejected: %w privacy ERC-1271 authorization rejected effectiveSender에 대한 ERC-1271 스마트 계정 서명 검증이 실패하면 이 문자열로 revert됩니다.
single-proof batch transfer payload has expired single-proof batch transfer payload has expired 블록 시간이 이미 request.expiresAtUnix에 도달하면 이 문자열로 revert됩니다.
privacy single-proof batch nullifier already spent privacy single-proof batch nullifier already spent 제출한 nullifier 중 하나가 이전 프라이버시 호출에서 이미 소비된 경우 이 문자열로 revert됩니다.
privacy single-proof batch output commitment already exists privacy single-proof batch output commitment already exists 출력의 commitment이 이미 온체인 commitment 인덱스에 존재하면 이 문자열로 revert됩니다.

예제

릴레이어가 인가된 단일 증명 배치를 제출

릴레이어 자신의 주소가 authorization.executor와 대조되며, 불일치하면 증명 검증 이전에 revert됩니다. nonce는 오프체인에서 관리하며, effectiveSender별 단조 증가 카운터로도 충분합니다.

import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";

const PRIVACY = "0x100000000000000000000000000000000000000b" as const;

// ABI snippet — reuse the `PrivacySingleProofBatchTransferRequest` shape
// documented on `contract-privacy-single-proof-batch-transfer`.
const privacyAbi = [{
  type: "function",
  name: "singleProofBatchTransferWithAuthorization",
  stateMutability: "nonpayable",
  inputs: [
    { name: "request",       type: "tuple", components: [ /* … */ ] },
    { name: "authorization", type: "tuple", components: [
      { name: "effectiveSender",   type: "address" },
      { name: "executor",          type: "address" },
      { name: "nonce",             type: "uint256" },
      { name: "deadline",          type: "uint64"  },
      { name: "authorizationKind", type: "uint8"   },
      { name: "signature",         type: "bytes"   },
    ]},
  ],
  outputs: [{ type: "bool" }],
}] as const;

// The relayer's key. Must equal `authorization.executor`.
// TODO: replace with the real relayer address before production.
const relayer = createWalletClient({
  account: privateKeyToAccount(process.env.RELAYER_KEY as `0x${string}`),
  transport: http("https://rpc-testnet.maroo.io"),
});

// `request` and `authorization` come from the effective sender's wallet.
// `authorization.signature` is over the EIP-712 domain documented on
// `privacy-authorization-eip712-domain`, using the single-proof batch
// request-hash.
await relayer.writeContract({
  address:      PRIVACY,
  abi:          privacyAbi,
  functionName: "singleProofBatchTransferWithAuthorization",
  args:         [request, authorization],
});

인가 실패 처리

인가 계층은 문자열 revert만 발행합니다. UX 분기는 revert.reason의 부분 문자열로 처리하며, 여기서 decodeErrorResult를 호출해서는 안 됩니다.

import { BaseError, ContractFunctionRevertedError } from "viem";

try {
  await relayer.writeContract({
    address:      PRIVACY,
    abi:          privacyAbi,
    functionName: "singleProofBatchTransferWithAuthorization",
    args:         [request, authorization],
  });
} catch (err) {
  if (err instanceof BaseError) {
    const revert = err.walk(e => e instanceof ContractFunctionRevertedError);
    if (revert instanceof ContractFunctionRevertedError) {
      // Match on the verbatim reason substring — the privacy precompile
      // does not use typed custom errors.
      const r = revert.reason ?? "";
      if (r.includes("privacy authorization expired")) {
        // ask the effective sender to re-sign with a later deadline
      } else if (r.includes("privacy authorization nonce already used")) {
        // bump the nonce and re-sign
      } else if (r.includes("privacy authorization executor mismatch")) {
        // the signature was bound to a different relayer
      }
    }
  }
  throw err;
}
ESC
검색어를 입력하세요