Preventing Attacks on XCM Reserves

This is the outcome of a recent discussion with @kckyeung about XCM, reserve location, and its security.

First, I will rephrase the situation at hand, to the best of my knowledge. I am fairly new to this, so please correct me if I am wrong.

As I learned, most chains use themselves as the reserve location for their own token, not statemint and statemine. That is, chain A puts some aToken into a sovereign account of chain B, and B can mint the equivalent on aToken on its side. We can assume that parachains that establish this trust among one another audit and trust each others’ runtime.

The problem with this however, is that if the state transition of A gets compromised in any way, it will have full control over these funds. This can happen either through uploading a faulty WASM blob (which can itself happen through multitude of events) or through some kind of governance attack, such as what happened recently to Mangata.

I recall that the idea with statemint and statemine was to act as the trusted reserve location, mainly to prevent such events. So, if chain A would go down, the assets would remain safe in statemint/mine. Although, recently I realized, if these chains control the assets that they use as reserve on statemint/mine as well, it does not help, because the rogue chain A could also send an XCM to manipulate the asset. In this case, using statemine/mint at best makes the attack “more complicated”, and no less infeasible.

Having come to this conclusion, it became clear to me that using statemint/mine, in itself, will not prevent such attacks. But, further down the road, we discussed how one can protect against these attacks. One interesting idea here is to have some kind of middleware that sits between XCM and balance/assets (e.g. AssetsAdapter) prevent malicious activities, based on some pre-defined rules and heuristics.

For example, a sovereign account that is acting as reserve should not be drained with a rate more than X, and certainly all at once. It is, in my opinion, well worth it to make these attacks significantly less feasible, at the cost of preventing some XCM transfers in rare occasions. More ideas like these safeguards are discussed in this episode of the unchained podcast about the Nomad hack.

As a first step, we can think of a few safeguards like this, and hopefully put them in all chains that act as reserve for one another. And them, only then, I think there is a clear advantage in using statemint/mine, which is that even if a chain goes badly rogue, it could technically wipe out these safeguards from its own runtime, but it cannot wipe them out from statemint/mine.

Using Statemine to issue token does reduce some attack vector but IMO it isn’t really have meaningful impact.

The parachain is likely need the ability to mint/burn the token. Therefore is the parachain runtime/governance is compromised, it can simply mint infinite amount of the token on Statement and cash out the liquidity.

The only way it will work is that the parachain token have fixed supply and therefore parachain doesn’t need any special privilege for the asset issued on Statemine. This ensures the compromised parachain cannot have much impact on the tokens on Statemine.

Another thing is the rate limiting, which is a completely different topic. I do think we could implement some special rate limiting logic on token transfer to reduce impact of a compromised parachain. For example, improve the orml-xtokens pallet to ensure only a limited amount token can be transferred in a given period.

1 Like

I think the middleware thing can be done by setting up the “right team” for the asset, a middleware is pretty much a proxy and we already have those, perhaps a bit of extra functionality in the existing delay of proxies could be useful(e.g. proxy accounts with dynamic delay), ideally an improved Proxy Pallet On Steriods could provide a more robust authorization framework with more options to configure. The rate limiting could be done this way and would be better as filtering is done on the receiving side, malicious users that already have root control of a chain can bypass the usage of a pallet like orml-tokens.

As a bit of a related note, I plan to do something like this with Virto, we won’t be the reserve of any token, we plan to use Statemint as the reserve for the tokens of our commercial communities and when the chain comes live(likely wait for parathreads) we bring tokens over. Something special about the setup is that after minting the total supply we made the owner and issuer an account with no private key, perhaps in the future with could gain ownership back with a referendum adding a proxy to that account using utility::dispatch_as but in the meantime it serves as guarantee that supply cannot be inflated. For the admin and freezer we setup a pure proxy that could later be controlled by the parachain and/or a special origin in the collectives parachain.

  owner: 1VirtoSwapCash111111111111111111111111111111BFT <- no private key
  issuer: 1VirtoSwapCash111111111111111111111111111111BFT
  admin: 14duqNVtQ9SWGe1kahf8tkXxu5npaGrZ9numtftgNvqowCTd <-pure proxy
  freezer: 14duqNVtQ9SWGe1kahf8tkXxu5npaGrZ9numtftgNvqowCTd
  supply: 31,415,926,535,897,932
  deposit: 100,000,000,000
  minBalance: 1,000,000
  isSufficient: false
  accounts: 4
  sufficients: 0
  approvals: 0
  isFrozen: false

Not really to prevent attacks like these. The main design goal[1] (at least for fungible asset classes) was a “management portal” to the Polkadot network. So if an manager (let’s say Tether of USDT) wants their asset to be available in the Polkadot network, they don’t want to manage deployments on potentially thousands of para{chains, threads}.

This is because managing deployments means accounting (how much of my asset exists in this network) and active management (issuing/burning units). Since Statemint is the reserve location for these assets in the entire network, the manager can use Statemint as their one gateway into all of Polkadot.

Statemint wasn’t really set up with the main goal of being used for parachain native tokens, so it’s no surprise that it doesn’t cover this attack vector. If having one parachain be the reserve for all parachain native assets makes sense and helps with security, then we can see how Statemint could play a role in that.

  1. Some reference: the initial blog post describing some of these use cases: ↩︎

Once Make Assets Pallet's Privileged Roles `Option` · Issue #12458 · paritytech/substrate · GitHub is implemented you can just use owner: None.

I am not sure if I agree. I am not suggesting that all parachains issue their native tokens in statemint. What I had in mind is that each parachain’s native token can live in either statemint or their own parachain, similar to how DOT can live in both the relay and statemint. If you want to send an asset from Parachain A to Parachain B however, you would only send that from the portion that lives in statemint. In other words, to Go from parachain A to B, you go from A to statemint, then B.

I still think there might be more advantages to this, if we can somehow prevent a rogue runtime from altering the issuance of the assets that it owns on statemint, as opposed to just hosting it itself.

That aside, it seems like the idea of rate limit for transfers (and potentially other operations such as staking) is a clear action item that we can extract from this discussion.

I don’t have a great idea about how to implement this in a general way at this point. Integrating it into the x-tokens and balances pallet and alike is certainly simple, but seemingly not as elegant as doing it via a more advance proxy system.

This is off topic from XCM attacks, but @santi had an interesting idea in a discussion yesterday. By supporting any parachain’s native token on Statemint, other integration services (Ledger, custodians, &c.) can support basic fungible token operations, like transfer just by supporting Statemint.

If there’s a way to get that benefit and provide extra security guarantees behind these assets, then that’s a double win.

1 Like