IPrivacy.transferWithAuthorization
transferWithAuthorization(
PrivacyTransferRequest request,
PrivacyActionAuthorization authorization
) external returns (bool success) EIP-712 PrivacyActionAuthorization에 서명한 effectiveSender를 대신하여 셸디드 transfer를 실행합니다. 릴레이어가 msg.sender이며, authorization이 nonce가 소비되고 PCL 규칙이 적용되는 발신자를 지정합니다. 실패는 이제 IPrivacy의 타입 지정 커스텀 오류(authorization 검사, 요청 만료, nullifier/커밋먼트 충돌, 배치 한도) 또는 IPrecompile의 상속 오류(InvalidNumberOfArgs, RequesterIsNotMsgSender 등)로 revert됩니다. PCL 정책 실패는 여전히 IPcl의 PCL ReasonCode로 노출됩니다.
파라미터
| 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
request | PrivacyTransferRequest | ✓ | 셸디드 transfer 페이로드입니다. expiresAtUnix는 현재 블록 시간보다 반드시 커야 합니다. 만료되었거나 0이면 PrivacyRequestExpired(expiresAtUnix)로 revert됩니다. |
authorization | PrivacyActionAuthorization | ✓ | effective sender가 EIP-712로 서명한 권한입니다. effectiveSender, executor, nonce, deadline이 모두 설정되어야 하며, 누락 시 PrivacyInvalidAuthorizationField(field)로 revert됩니다. executor는 msg.sender와 같아야 하며, 다르면 RequesterIsNotMsgSender로 revert됩니다. 서명은 effectiveSender로 복원되어야 하며, 다르면 PrivacyAuthorizationSignerMismatch(expected, got)로 revert됩니다. 정확한 typeHash 원본은 privacy-authorization-eip712-domain을 참고합니다. |
반환값
타입:
bool 성공 시 true를 반환합니다. 실패는 false 반환이 아니라 타입 지정 커스텀 오류로 revert됩니다.
에러
| 코드 | 이름 | 설명 |
|---|---|---|
PrivacyNonPayable | PrivacyNonPayable | msg.value가 0이 아닐 때 revert됩니다. payable은 deposit뿐입니다. PrivacyNonPayable(string methodName)으로 인코딩됩니다. |
PrivacyRequestExpired | PrivacyRequestExpired | request.expiresAtUnix가 0이거나 이미 지났을 때 revert됩니다. 페이로드에는 문제가 된 unix 타임스탬프가 담깁니다. |
PrivacyInvalidAuthorizationField | PrivacyInvalidAuthorizationField | 필수 authorization 필드가 누락되었거나 유효하지 않을 때 revert됩니다. 페이로드는 필드 이름("effectiveSender", "executor", "nonce", "deadline")입니다. |
PrivacyAuthorizationExpired | PrivacyAuthorizationExpired | authorization의 deadline이 현재 블록 시간을 기준으로 지났을 때 revert됩니다. |
PrivacyAuthorizationNonceUsed | PrivacyAuthorizationNonceUsed | 해당 effective sender에 대해 nonce가 이미 소비되었을 때 revert됩니다. 페이로드는 (sender, nonce)입니다. |
PrivacyAuthorizationSignerMismatch | PrivacyAuthorizationSignerMismatch | 복원된 서명자가 effectiveSender와 다를 때 revert됩니다. 페이로드는 (expected, got)입니다. |
PrivacyAuthorizationRejected | PrivacyAuthorizationRejected | ERC-1271 또는 EIP-7702 authorization이 검증기에서 거절되었을 때(잘못된 코드 형태, 검증기 revert, 지원되지 않는 authorization kind) revert됩니다. 페이로드는 authorization kind입니다. |
PrivacyInvalidAuthorizationMagic | PrivacyInvalidAuthorizationMagic | ERC-1271 스마트 계정이 0x1626ba7e 매직이 아닌 바이트를 반환했을 때 revert됩니다. 페이로드는 반환된 매직 바이트입니다. |
PrivacyNullifierAlreadySpent | PrivacyNullifierAlreadySpent | 요청의 nullifier가 이미 온체인에 기록되어 있을 때 revert됩니다. |
PrivacyCommitmentAlreadyExists | PrivacyCommitmentAlreadyExists | 요청의 새 커밋먼트가 이미 Merkle 트리에 존재할 때 revert됩니다. |
PrivacyMerkleCapacityExceeded | PrivacyMerkleCapacityExceeded | 요청의 새 커밋먼트들을 추가하면 Merkle 트리 용량을 초과할 때 revert됩니다. |
PrivacyTxLimitExceeded | PrivacyTxLimitExceeded | 단일 EVM 실행 내에서 전역 stateful-privacy 호출 한도를 트랜잭션이 이미 초과했을 때 revert됩니다. |
PrivacySenderTxLimitExceeded | PrivacySenderTxLimitExceeded | effective sender별 stateful-privacy 호출 한도를 트랜잭션이 이미 초과했을 때 revert됩니다. |
RequesterIsNotMsgSender | RequesterIsNotMsgSender | IPrecompile에서 상속됩니다. authorization.executor가 msg.sender와 다를 때 revert됩니다. 페이로드는 (msgSender, requester)입니다. |
InvalidNumberOfArgs | InvalidNumberOfArgs | IPrecompile에서 상속됩니다. ABI 인코딩된 호출이 정확히 두 개의 인자를 담고 있지 않을 때 revert됩니다. |
UnknownMethod | UnknownMethod | IPrecompile에서 상속됩니다. ABI selector가 프리컴파일의 어떤 함수와도 일치하지 않을 때 revert됩니다. 보통 ABI가 오래된 상황을 의미합니다. |
예제
릴레이어가 인증된 transfer 제출
릴레이어가 msg.sender가 되며, PCL은 authorization.effectiveSender를 기준으로 규칙을 평가합니다. 검사에 실패하면 호출 전체가 해당 타입 지정 오류로 revert됩니다.
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { privacyAbi } from "@maroo-chain/contracts/abi/IPrivacy";
const PRIVACY = "0x100000000000000000000000000000000000000b" as const;
const relayer = createWalletClient({
account: privateKeyToAccount(process.env.RELAYER_KEY as `0x${string}`),
transport: http("https://rpc-testnet.maroo.io"),
});
// `request` and `authorization` are built off-chain; the effective sender
// signs the EIP-712 typeHash preimage (see privacy-authorization-eip712-domain).
// authorization.executor MUST equal the relayer address.
await relayer.writeContract({
address: PRIVACY,
abi: privacyAbi,
functionName: "transferWithAuthorization",
args: [request, authorization],
}); authorization / 만료 오류 디코드
decoded.errorName으로 분기합니다. 각 타입 지정 오류의 인자 튜플은 안정적이며 (address, bigint) 같은 타입 값으로 디코드되어 UX에 바로 사용할 수 있습니다.
import { decodeErrorResult } from "viem";
import { privacyAbi } from "@maroo-chain/contracts/abi/IPrivacy";
try {
await relayer.writeContract({
address: PRIVACY,
abi: privacyAbi,
functionName: "transferWithAuthorization",
args: [request, authorization],
});
} catch (err: any) {
if (!err?.data) throw err;
const decoded = decodeErrorResult({ abi: privacyAbi, data: err.data });
switch (decoded.errorName) {
case "PrivacyAuthorizationNonceUsed": {
const [sender, nonce] = decoded.args as [`0x${string}`, bigint];
console.warn(`nonce ${nonce} already consumed for ${sender}`);
break;
}
case "PrivacyRequestExpired": {
const [expiresAtUnix] = decoded.args as [bigint];
console.warn(`request expired at ${expiresAtUnix}`);
break;
}
case "PrivacyAuthorizationSignerMismatch": {
const [expected, got] = decoded.args as [`0x${string}`, `0x${string}`];
console.warn(`bad signature: expected ${expected}, got ${got}`);
break;
}
default:
throw err;
}
}