CipherPhi splits custody, policy and eligibility across three Soroban contracts and three key sets. The floor is collusion between two organisations.
Aladdin Battikh||9 min read
CipherPhi separates the key that moves money from the key that decides who receives it, and gives neither party the other's capability.
Nothing is deployed. The design is public at Revision 2 in the project repository,1 the SCF #45 Build Award submission sits in panel review on the Open Track, and funded contract development begins at grant kickoff. Every control below is a design commitment the delivered code can be checked against, rather than a property of running software. The system moves zakat for the Swiss Zakat Foundation, a federally supervised Swiss foundation collecting and redistributing zakat since its founding deed of 6 July 2021, audited annually.2 The institution works. What is being built is the rail underneath it.
One contract holds funds. The other two are consulted by it and can never move anything.
The alternative was a single binary with three modules and a promise to split it later. That loses on upgrade granularity. The two components most likely to change are a refinement to the Shariah parameters and a change to the eligibility scheme, and in a single binary each of those redeploys the thing holding donor money. Split as below, refining the administration cap redeploys policy, changing the attestation scheme redeploys attestation, and custody is untouched by either.
| CONTRACT | RESPONSIBILITY | HOLDS FUNDS |
|---|---|---|
zakat_pool | Custody, the eight category balances, and the only two entry points that move value | Yes |
policy | Shariah parameters and the allocation computation over a contribution | No |
attestation | The attestation authority key set, and verification of an eligibility signature | No |
THE SPLIT LINE IS VALUE, NOT TIDINESS. A DEFECT IN POLICY OR ATTESTATION PRODUCES A WRONG ANSWER RATHER THAN A LOSS, WHICH IS THE WHOLE RETURN ON THE SEPARATION.
The cost is a wider audit scope, three Wasm binaries rather than one, and a cross-contract call is a place where a wrong answer can enter. It is paid by treating both callees as untrusted input. An allocation is rejected unless the returned vector has exactly eight elements, every element is zero or positive, and they sum exactly to the amount received. Checking only the sum would not be enough. A split of the shape [amount + x, -x, 0, ...] sums correctly, passes checked arithmetic, and leaves total custody intact while silently crediting one category from another's beneficiaries. Neither callee holds an address that lets it call back into the pool, so no defect in either reaches the money.
A treasury multisig lets one quorum both approve a payment and send it.
Access control ranks first in the OWASP Smart Contract Top 10 for 2026, derived from 122 deduplicated smart contract incidents recorded during 2025 and totalling approximately USD 905.4 million in losses.3 The category covers privilege concentration and insufficient separation of duties, so separation is the control worth paying for, and paying for it means enforcing it in the contract rather than in a policy document.
distribute accepts a signed attestation and verifies it before any transfer. The signature binds recipient, asset, category, amount, the pool's distribution sequence, the pool's contract address, and the network passphrase. The distributor key cannot produce that signature. The attestation quorum holds no key that can call the contract.
| ROLE | HOLDS | CAN | CANNOT |
|---|---|---|---|
| Governance | 3-of-5 multisig | Deploy, pause contributions, disable the distributor, repoint policy and attestation, change parameters under timelock | Move funds. Sign eligibility |
| Distributor | Single operational key | Call distribute | Change policy. Create a valid attestation |
| Attestation authority | 2-of-3 multisig | Sign recipient eligibility off-chain | Move funds. Change policy |
THE DESIGN ASSUMES ONE KEY IS EVENTUALLY COMPROMISED. A COMPROMISED DISTRIBUTOR PRODUCES FAILED TRANSACTIONS, AND A COMPROMISED ATTESTATION QUORUM PRODUCES SIGNATURES NOBODY EXECUTES.
Severity here is argued through the precondition. Theft by the distributor requires a forgeable attestation, which the scheme does not provide. Theft by the attestation quorum requires a key that can call distribute, which it does not hold. Neither precondition is available to a single compromised party.
Sequence binding carries a cost worth stating before a reviewer finds it. A valid signature executes exactly once, with no stored list of used signatures, but attestations then execute in the order they were signed. One abandoned at sequence N strands every attestation signed after it until they are reissued. At pilot cadence, a handful of distributions to one partner organisation, serial execution is the behaviour you want. At scale it is a throughput constraint.
The attestation contract has no setter for its key set.
authority is fixed at construction, so changing the quorum means deploying a new attestation contract and repointing the pool at it, under the same delay and the same events as every other governance change. The in-place setter lost on one point: it would be an instant path to a quorum of governance's choosing, which defeats the delay sitting beside it. Removing it also removes a setter from the audit surface, and the mainnet attestation contract is then constructed with the final 2-of-3 set rather than migrating into it.
Custody goes further. A Soroban contract is mutable only if it compiles in an upgrade entry point, so a contract omitting update_current_contract_wasm is immutable by construction.4 zakat_pool omits it, because code that can be silently replaced over donor funds is an admin key by another name. The cost is that a custody defect cannot be patched in place, paid by a new deployment with a published address and a migration a donor can watch, and by entering independent review well before mainnet rather than alongside it.
Two things are deliberately instant.
| ACTION | TIMING | WHY |
|---|---|---|
Repoint policy or attestation | Seven-day timelock | The change is visible before it takes effect, and governance can cancel it |
| Approve an asset | Seven-day timelock | Adds eight category buckets and a new custody surface |
| Change a Shariah parameter | Seven-day timelock | Methodology change, visible to donors before it applies |
| Pause contributions | Immediate | A brake that takes a week is not a brake |
| Disable the distributor | Immediate | A compromised operational key must be evictable in minutes |
EACH DELAYED CHANGE EMITS AN EVENT AT PROPOSAL, AT EXECUTION AND AT CANCELLATION. INSTANT REVOCATION COSTS NOTHING THE DELAY WAS PROTECTING, BECAUSE A DISABLED DISTRIBUTOR STILL CANNOT MOVE FUNDS WITHOUT AN ATTESTATION.
What remains is collusion between the Foundation and the delivery team, through governance repointing attestation at a permissive contract.
That is the floor rather than an oversight: two organisations, two key sets, and no way to reduce it further without a third party holding neither. Three things constrain it. The pilot runs with capped amounts, bounding the window between a visible proposal and a possible loss. A named party monitors the proposal, execution and cancellation events with an off-chain escalation path, because a timelock nobody observes is a delay rather than a control. And one invariant governs the seats: delivery-team seats stay below the governance quorum threshold, otherwise the floor is one organisation plus a seven-day wait.
The same reasoning keeps the delivery team out of the attestation quorum, whose three seats are the Foundation's Executive Director, the Shariah authority, and an independent seat appointed by the Foundation. With a delivery seat, the delivery team plus any one other signer would produce a valid attestation and execute it in the same transaction, instantly and with no timelock. That is a strictly easier path than the collusion above, which is why the exclusion is a design constraint rather than an accident of staffing.
A donor can verify that their category was distributed to a recipient whose eligibility was signed before the funds moved.
They cannot verify that their individual coins reached a named person. Zakat is pooled by construction, and the eight-category split is what the methodology operates on, so per-donor tracing to an individual recipient would be a fiction dressed as cryptography. Category-level delivery with a verifiable attestation on every disbursement is the strongest true claim available.
Every figure a donor sees resolves to a ledger event carrying the transaction hash that produced it. The pool moves USDC through the Stellar Asset Contract, which implements the SEP-41 token interface, so asset movements surface as standardised transfer events whether they originate from a payment operation or a contract call.5 The interface reading those events can go down, and if it does the donor flow goes down with it. It cannot go wrong quietly, because the record it renders is not a record it holds.
| NOT COVERED | WHY NOT, AND WHAT WOULD CHANGE IT |
|---|---|
| Deployed code | No contract is written or deployed. Funded development begins at grant kickoff, contingent on the SCF #45 Build Award outcome.1 |
| Independent audit | Review is requested through the SCF Soroban Audit Bank and has not started.6 Programme rules put a twenty business day window on resolving critical, high and medium findings, and publish the report once resolution is verified.7 The report is published with the mainnet deployment |
| Test evidence | cargo-fuzz on contribute and distribute, plus unit and invariant tests in CI, are planned against code that does not yet exist.8 The trigger is the first commit of contract source |
| Live attestation quorum | Governance is a multisig from deployment. The attestation authority is exercised on testnet and constructed as the final 2-of-3 set at mainnet deployment. The trigger is the first mainnet distribution |
| Governance seat holders | Identities, seat allocation and custody method are published with the mainnet deployment. The invariant, delivery-team seats below the governance quorum threshold, is a design constraint from today |
| Individual-recipient payouts | The pilot pays a vetted partner organisation directly, removing every live dependency between the pool and the recipient. The Stellar Disbursement Platform is the planned rail,9 triggered by expansion beyond partner organisations |
| Standing Shariah board | One qualified advisor validates the pilot parameter set. A board is planned for scale, triggered by the first distribution beyond the pilot partner |
| Bug bounty and formal verification | Neither at launch. A bounty with no live value to protect attracts noise rather than researchers, so the trigger is a pool balance large enough to be worth attacking |
| Issuer freeze | Revision 2 records that USDC on Stellar is issued with authorisation revocable, so the issuer can freeze a holder's balance including a contract's, with no remediation in CipherPhi's bytecode.1 Accepted at pilot size: the response is to pause contributions and escalate to the issuer, and issuer flags are reviewed when approving any asset |
The next checkable thing is the first commit of contract source against the architecture published at Revision 2. Until then every claim above is a design commitment, and that document is the one a reviewer should hold it to.
CIPHERPHI ARCHITECTURE, REVISION 2. github.com
SWISS ZAKAT FOUNDATION. zakat.ch
OWASP SMART CONTRACT TOP 10 FOR 2026. scs.owasp.org
STELLAR DEVELOPER DOCS, UPGRADING CONTRACTS. developers.stellar.org
STELLAR DEVELOPER DOCS, STELLAR ASSET CONTRACT AND SEP-41. developers.stellar.org
SOROBAN SECURITY AUDIT BANK. stellar.org
SCF HANDBOOK, AUDIT BANK OFFICIAL RULES. stellar.gitbook.io
STELLAR DEVELOPER DOCS, FUZZING SOROBAN CONTRACTS. developers.stellar.org
STELLAR DISBURSEMENT PLATFORM. developers.stellar.org