You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm building Cordon (registered in #237, repo https://github.com/RaYYeR220/cordon) — a credential and policy gate for shielded value. It's an anonymizer contract: the pool calls privacy_invoke on it, it checks a credential and a published policy against the value passing through, and it panics if the payment breaks the rule so the whole transaction reverts.
The contracts are on mainnet and the wiring is readable:
Composing a payment in my app and signing it in Ready X, the wallet prepares fine and then fails at submission. The wallet's own console shows it getting all the way to submitting:
and then PaymasterV2Error: Paymaster error 156: An error occurred (TRANSACTION_EXECUTION_ERROR).
The action array is the documented three-action shape — withdraw to the gate, transfer with "OPEN", then invoke — and the wallet substitutes ${poolAddress} and ${openNoteIds[0]} itself.
The actual problem: there is no revert reason anywhere
Nothing reaches a block, so there's no receipt to read. I scanned 40 blocks of starknet_getBlockWithReceipts looking for a reverted transaction mentioning the gate or a CORDON_ panic code and found none. The paymaster reports TRANSACTION_EXECUTION_ERROR without the reason, so I can't tell whether my contract panicked and which check did it, or whether the transaction never got that far.
That's what I'm stuck on. Not "it doesn't work" — I can't see why it doesn't work.
What I've ruled out
The gate's state is clean, all read off mainnet just now:
accounted_balance(STRK) = 0, and its STRK balance is 0
allowance(gate → pool) = 0, so it isn't tripping its own stale-allowance guard
the pool is not paused
is_open_note_depositor_blocked(gate) = 0
privacy_invoke is present on the deployed class with the expected signature, and privacy_pool() reads back as the real pool
Third-party anonymizers clearly do work: the pool emitted 30 ExternalContractInvoked events across 6 distinct anonymizer contracts in the last 100k blocks, so this isn't a blanket restriction.
I also tried submitting through executeWithProof after strk20PrepareInvoke, to bind the resolved note id into what the subject signs. Ready rejects that payload outright with INVALID_REQUEST_PAYLOAD (114) before signing anything — same family as #190. Falling back to strk20InvokeTransaction with the same actions gets me to the paymaster error above.
What would help
Is there a way to get the revert reason out of a paymaster-simulated privacy transaction? Even a way to reproduce the simulation locally would do. Right now a failing transaction is completely opaque to the person who wrote the contract it failed in.
Is there any restriction on which anonymizer contracts the wallet's paymaster route will execute — an allowlist, a size or calldata limit, a gas ceiling on the invoke phase? If so it isn't documented anywhere I could find, and it would explain this exactly.
Happy to hand over anything useful — the action array, the calldata, a transaction I can get to land. The contracts, the SDK and a rehearsal script that reads all of this off mainnet are in the repo if it's easier to reproduce than describe.
What I'm trying to do
I'm building Cordon (registered in #237, repo https://github.com/RaYYeR220/cordon) — a credential and policy gate for shielded value. It's an anonymizer contract: the pool calls
privacy_invokeon it, it checks a credential and a published policy against the value passing through, and it panics if the payment breaks the rule so the whole transaction reverts.The contracts are on mainnet and the wiring is readable:
What happens
Composing a payment in my app and signing it in Ready X, the wallet prepares fine and then fails at submission. The wallet's own console shows it getting all the way to submitting:
and then
PaymasterV2Error: Paymaster error 156: An error occurred (TRANSACTION_EXECUTION_ERROR).The action array is the documented three-action shape —
withdrawto the gate,transferwith"OPEN", theninvoke— and the wallet substitutes${poolAddress}and${openNoteIds[0]}itself.The actual problem: there is no revert reason anywhere
Nothing reaches a block, so there's no receipt to read. I scanned 40 blocks of
starknet_getBlockWithReceiptslooking for a reverted transaction mentioning the gate or aCORDON_panic code and found none. The paymaster reportsTRANSACTION_EXECUTION_ERRORwithout the reason, so I can't tell whether my contract panicked and which check did it, or whether the transaction never got that far.That's what I'm stuck on. Not "it doesn't work" — I can't see why it doesn't work.
What I've ruled out
The gate's state is clean, all read off mainnet just now:
accounted_balance(STRK)= 0, and its STRK balance is 0allowance(gate → pool)= 0, so it isn't tripping its own stale-allowance guardis_open_note_depositor_blocked(gate)= 0privacy_invokeis present on the deployed class with the expected signature, andprivacy_pool()reads back as the real poolThird-party anonymizers clearly do work: the pool emitted 30
ExternalContractInvokedevents across 6 distinct anonymizer contracts in the last 100k blocks, so this isn't a blanket restriction.I also tried submitting through
executeWithProofafterstrk20PrepareInvoke, to bind the resolved note id into what the subject signs. Ready rejects that payload outright withINVALID_REQUEST_PAYLOAD(114) before signing anything — same family as #190. Falling back tostrk20InvokeTransactionwith the same actions gets me to the paymaster error above.What would help
Happy to hand over anything useful — the action array, the calldata, a transaction I can get to land. The contracts, the SDK and a rehearsal script that reads all of this off mainnet are in the repo if it's easier to reproduce than describe.