Skip to content

feat: outbound transfer authorization#348

Open
sadiq1971 wants to merge 4 commits into
mainfrom
feat/outbound-transfer-authz
Open

feat: outbound transfer authorization#348
sadiq1971 wants to merge 4 commits into
mainfrom
feat/outbound-transfer-authz

Conversation

@sadiq1971

Copy link
Copy Markdown
Member

Closes #318 (epic #321).

Policy (the three open questions)

  1. Whitelist-gate outbound on the sender's EVM address? Yes. Any transfer addressed by raw to_party_id — non-custodial POST /transfer/prepare and custodial POST /transfer/custodial — requires the sender's EVM address to be whitelisted, reusing the same whitelist.Checker that fronts eth_sendRawTransaction. Party-id addressing can move value out to arbitrary external participants, so it gets the same gate as the inbound path. Checking at transfer time (registration is already gated) means removing an address from the whitelist immediately revokes its outbound capability. Transfers addressed by recipient EVM address stay between registered local users and are not gated.
  2. Custodial outbound is allowed, under the same whitelist gate. Custody changes who signs, not whether value may leave the system.
  3. Recipient guards are centralized in validateRecipient, shared by both handlers: syntactic party-id check, reject self-transfers, and reject the issuer party — which is also the bridge-operator party, since client.propagateCommonConfig maps both from canton.issuer_party. Sending user funds to the bridge escrow/mint-burn party would corrupt supply accounting.

Changes

  • pkg/transfer/service.go: TransferService now takes a whitelist.Checker and the issuer party id; new checkSenderWhitelisted (403 on deny, 502 on checker failure) and validateRecipient guards wired into Prepare and SendCustodial. Policy documented on the type.
  • pkg/app/api/server.go: wires the existing shared whitelist service and cfg.Canton.IssuerParty into the transfer service.
  • Tests: allow/deny matrix — whitelisted/not/checker-error for both key modes, EVM-recipient path not gated, issuer/self/malformed recipient rejection, plus a validateRecipient table test.

Note: SendCustodial recipient validation now runs after sender authentication (it needs the sender's party id for the self-check), so a malformed party id from an unknown sender now yields 401 rather than 400.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements outbound authorization policies and recipient validation guards for the transfer service. Specifically, transfers addressed by raw party ID now require the sender's EVM address to be whitelisted, and transfers to the issuer/bridge-operator party or self-transfers are rejected to prevent supply accounting corruption. The review feedback suggests adding a nil guard check for the whitelist checker in checkSenderWhitelisted to prevent potential runtime panics if the service is misconfigured or initialized without it.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread pkg/transfer/service.go
@codecov-commenter

codecov-commenter commented Jul 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 79.31034% with 6 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main@83d4116). Learn more about missing BASE report.

Files with missing lines Patch % Lines
pkg/app/api/server.go 0.00% 4 Missing ⚠️
pkg/transfer/service.go 92.00% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main     #348   +/-   ##
=======================================
  Coverage        ?   32.09%           
=======================================
  Files           ?      154           
  Lines           ?    12270           
  Branches        ?        0           
=======================================
  Hits            ?     3938           
  Misses          ?     8016           
  Partials        ?      316           
Flag Coverage Δ
unittests 32.09% <79.31%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
pkg/transfer/service.go 73.69% <92.00%> (ø)
pkg/app/api/server.go 0.00% <0.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: outbound transfer authorization & whitelist policy

2 participants