Skip to content

Force-transfer-enabled vaulted markers let the asset issuer pull backing out of the vault #222

Description

@nullpointer0x00

Context

Surfacing a custody characteristic of vaulting restricted markers that have allow_forced_transfer = true. When a vault holds such an asset as backing, the asset's issuer (or governance) retains the ability to forcibly pull that asset back out of the vault at any time, without the vault's or depositors' consent. This is inherent to the marker's force-transfer design, not a code defect in the vault, but it is a trust assumption worth making explicit and deciding on deliberately. Filing for discussion.

The exposure

A vault holds depositor backing in its principal marker account (vault.PrincipalMarkerAddress()). The marker module explicitly permits forced transfers out of marker accounts (x/marker/keeper/marker.go canForceTransferFrom, lines 737-739), unlike module accounts and smart-contract accounts which it protects (sequence-0 accounts are blocked at line 746).

So for any vaulted asset whose marker has allow_forced_transfer = true, a holder of Access_ForceTransfer on that marker can submit MsgTransferRequest with from = the vault's principal marker and move the asset to themselves. TransferCoin (marker.go:647-698) requires the marker be active, allow_forced_transfer = true, and the signer hold Access_ForceTransfer. No depositor signature is involved. The vault's share accounting (TotalShares / NAV) is not updated, so the result is outstanding shares with reduced or missing backing.

Confirmed on-chain (payment denom uylds.fcc)

uylds.fcc is a restricted marker, status active, allow_forced_transfer = true on both pio-mainnet-1 and pio-testnet-1. It has live keys holding Access_ForceTransfer:

  • mainnet (5): pb10r29n9w7ja6qt7l3dzls32x7alvmc9j9l9q8x79xwusy0fjf372s348dzu, pb18r6ncean59nm9d2pql7ely74jxn7g7s4tqrldw, pb17eswnfkr0nl8p7jt52l2gpxpap7205zavkls07, pb1qt67v5kr6hdvwlwlenxvnjtzsm56j4msax696p, pb1lez9xkd8mw27xzzlyu0cjyqxxyapvcqq3fj3ld
  • testnet (4): tp10f4ga4mw9m7n8xnwvws4rchhygkm8088ew6275, tp1ma38wztmxlega6na60vwhqr8dkvzk63pte3r0f, tp17mptaudww2hnh3udlqeazpa7h3hvm5tygpysqn, tp17uu9hgey9epcjhr4dft6cfq4532mxr4sujpun0

allow_governance_control is also true on uylds.fcc, so a gov proposal could perform the transfer or grant the role to a new address.

Reproduce (REST marker route is disabled on public endpoints, use the RPC gRPC query):

curl -s 'https://rpc.provenance.io/abci_query?path=%22/provenance.marker.v1.Query/Marker%22&data=0x0a0975796c64732e666363'
# decode the MarkerAccount: field 10 = allow_forced_transfer, field 3 = access_control grants

How we see it

This looks like a known and accepted property of using a force-transfer-enabled marker: it hands a central entity (the issuer, or governance) the ability to claw funds back from any holder, including a vault, at any time. The question is not whether the code is wrong, but whether that trust assumption is acceptable for our vaults and depositors, and whether we want any guardrails.

To discuss / decide

  • Is the issuer-clawback trust assumption acceptable for the assets we vault, and is it communicated to depositors?
  • Inventory: which production-vaulted markers (underlying and payment) have allow_forced_transfer = true, and who holds Access_ForceTransfer on each?
  • Do we want any guardrail, e.g. refusing to onboard / flagging an asset whose marker allows forced transfer, monitoring for forced-transfer events against vault marker addresses, or accepting it as documented behavior?
  • Record a decision (accept-as-designed / mitigate) with rationale.

Metadata

Metadata

Assignees

No one assigned

    Labels

    securityThis issue/request improves or addresses the security of the system

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions