Joystream / joystream

Joystream Monorepo
http://www.joystream.org
GNU General Public License v3.0
1.42k stars 115 forks source link

`Argo` Ethereum bridge vision #5084

Open kdembler opened 8 months ago

kdembler commented 8 months ago

⚠️ Update: ⚠️ This version is outdated, please refer the comment below: https://github.com/Joystream/joystream/issues/5084#issuecomment-2051702479


For background see https://pioneerapp.xyz/#/forum/thread/859. In this document I will refer to:

Components

ERC20 eJOY token on Ethereum

We should use something premade like OpenZeppelin contracts. Contract needs to allow the owner (Eth Multisig) to mint new tokens. We should be able to use contracts provided by Sygma right away.

The only custom functionality we need is emitting some metadata when new tokens are minted, so we can automatically update status of transfers. Standard mint function available in OpenZeppelin only accepts destination and amount, but I think it could be possible to do some magic and include the mint metadata as part of additional calldata in the mint transaction for off-chain interpretation. If we manage to do that, maybe we could be able to use contracts provided by Sygma right away.

Bridge contract on Ethereum

We can go 2 ways about this:

It’s either only for utility, with no special powers. It would only contain a single burn function that would burn eJOY and emit event with metadata. It would basically be a burn contract.

Or additionally we allow this contract to mint eJOY on multisig behalf, see the discussion in Payments with metadata

Ethereum multisig

Doesn’t need anything fancy, most likely Gnosis Safe contracts. This multisig will be the owner of the ERC20 and will be able to mint new eJOY tokens.

Joystream multisig

Standard Joystream multisig that will be securing the treasury of locked JOY.

Indexing node

We need an indexing node that will connect Joystream and Ethereum chain data and keep track of all transfers. We can use Subsquid to index 2 chains at the same time. Would keep track of:

  1. All transfers and their status
  2. Multisig transactions and their status

Bridge UI

To make the process simple for both users and signers, we would need an app. It would allow:

  1. Connecting your Ethereum and Joystream wallets
  2. Bridging tokens in both directions
  3. Tracking status of transfers
  4. Multisig operations - signing and executing transactions on both Joystream and Ethereum side

Operations

Payments with metadata

For bridge operations, we need to be able to emit metadata so that indexing node can keep track of all the transfers. This is a bit tricky.

On Ethereum side, we need to keep track of minting and burning. Simple bridge contract can emit events on burn, but standard ERC20 mint doesn’t emit any data aside from recipient and amount. We can:

  1. Override standard mint ERC20 slightly to allow additional data - not recommended, could be problematic with later Sygma migration
  2. Give the bridge contract minting access, add mint function only callable by the multisig that mints new tokens and emits our custom event
  3. Try to manually encode additional metadata in EVM tx calldata, would be decoded by the indexing node. The downside is that there’s no visible event emitted in block explorer for example.

Here 2nd option is probably the way to go.

On Joystream side, we need to keep track of token transfer from and to the multisig treasury. Standard transfer doesn’t emit any additional data. We can:

  1. Limit bridge usage to accounts with memberships and use members.memberRemark that can send payment and emit metadata at the same time.
  2. Require users to use utility.batch with one call being transfer to the treasury and the other would be a system.remarkWithEvent with metadata. Indexing node would join the data.
  3. Experiment with manual encoding of calldata like on EVM side, not sure if possible

Here 2nd option also seems to be the best.

Example wrapping flow

  1. User goes to the app and connects their Joystream wallet.
  2. They use the UI to initiate a bridging to Ethereum. The UI create and executes a utility.batch transaction - balances.transfer sends X + fee JOY to the multsig treasury, system.remarkWithEvent emits the metadata containing the target Ethereum address.
  3. Indexing node picks up the event, creates a new transfer with pending status, assigns it an ID. It also creates a pending transaction for multisig signers to sign.
  4. Multisig signers use the app to browse pending transfers. They confirm the data and sign the pending transcation.
  5. Once signature threshold is reached, the transaction gets executed on the Ethereum side, calling mint function on the bridging contract that mints X new eJOY to a target wallet and emits an event with the bridge transfer ID.
  6. Indexing node picks up the event, marking the transfer as completed.

Example unwrapping flow

  1. User goes to the app and connects their Ethereum wallet.
  2. The app creates and executes a burn call to the bridging contract - it burns X eJOY, collects some ETH fee, and emits an event.
  3. Indexing node picks up the event, creates a new transfer.
  4. Multisig signers confirm the transfer.
  5. Transaction is executed on the Joystream side - utility.batch transferring X JOY from multisig treasury to the target address and emitting an event
  6. Indexing node picks up the event, marking the transfer as completed.

Fees

Unsure yet how to collect and manage fees. On Ethereum side, fee should be collected in ETH as to not impact the circulating supply of eJOY. It could be kept in the bridge contract and be withdrawable by the multsig. On Joystream side, fee can be only in JOY so we would need some procedure of withdrawing fee from the treasury without affecting number of locked funds. Alternatively, on Joystream side we could make the utility.batch have 3 calls - X JOY would go to the treasury but the fee would go to a separate account. This way the JOY treasury size would be always matching the circulating supply of eJOY.

Rough effort estimation

Rough total - 145h

kdembler commented 8 months ago

After more research my conclusion is that this may not be the best strategic move for us and instead we should try to build Sygma bridge as soon as possible. Problems with the community brige:

  1. Arbitrage issues - because the bridging would include a significant delay, the arbitrage between JOY and wJOY markets would be impacted
  2. Multisig inflexibility - native Joystream multisigs are quite inflexible as I have pointed out in the design doc, we would not be able to swap signers without migrating the full multisig.
  3. We would need a bunch of custom code that would become obsolete as soon as Sygma launches.
kdembler commented 7 months ago

Continued with Sygma epic #5108

kdembler commented 7 months ago

We decided not to go with Sygma for a couple of reasons. We have worked out a vision for Argo bridge that should avoid all the mentioned problems and we are actively working on it

kdembler commented 7 months ago

Argo v2 bridge structure

(v2 because of the early version above)

Argo is an official, DAO-operated bridge between Joystream and Ethereum mainnet chains, allowing transfer of JOY tokens between both chains. This document goal is to outline governance structure and operations of the bridge, both on Joystream and Ethereum sides.

Actors

Structure

Joystream-side management

The bridge runtime pallet would keep the following configuration:

All of the above would be adjustable by a council via a 3/3 proposal.

Regular bridge operations (minting new tokens as they are burned on Ethereum) would be carried out by JoyOp multsig, requiring meeting the signatures threshold.

JoyOp signers rotation

Regular Joystream multisig by itself does not allow signers rotation. However, by leveraging the proxy pallet we can work around this.

To illustrate, let’s assume JoyOp is 2/3 multisig with signers Alice, Bob and Charlie (multisig ABC). Without proxies, we would set the ABC address directly as operator. If we wanted to swap Charlie for another signer, Dan, we would create a new multisig with Alice, Bob and Dan as signers (ABD). That multisig would have a different address, requiring the council to update operator address in bridge pallet configuration. That’s not ideal because signers cannot change their own set without council intervention.

Instead, we can use a pure proxy account as JoyOp. Pure proxies are accounts that have their own address but no private key, so no one can control them directly. Following our example, after ABC multisig is set up, ABC would create a pure proxy that it has full control over. This proxy would be set as operator in runtime. Then, when we want to swap Charlie for Dan, we would still create a new multisig ABD. But instead of council updating the operator, ABC could on its own assign ABD as the new owner of pure proxy. This way the change of signers controlling JoyOp changes, but we don’t need to update the on-chain address of operator.

Following this approach both council and the signers themselves can do signers rotation. Council remains the ultimate controller as they can always update address of operator, whether the current signers agree or not.

More reading about this setup:

Fees

Bridging fees should be burned automatically so they don’t need to be withdrawn from the bridge. Then the council can mint new tokens based on this burn to reward the bridge operators.

Image

Ethereum-side management

Ethereum side would consist of 2 smart contracts:

The ERC20 contract would have an admin role (assigned to EthAdmin) and a minter role (assigned to Argo contract).

The Argo contract would also have an admin role (EthAdmin) and an operator role (EthOp), but also a pauser role assigned to all EthPausers.

Multisigs

Both EthAdmin and EthOp will be Gnosis Safe accounts. Those multisigs allow signers swap by a threshold decision.

Fees

Bridging fees would be collected in ETH and kept in the Argo bridge contract. EthAdmin would be able to both withdraw fees and set the fee amount.

Image

Security

Over-minting

On Joystream side, the pallet will keep track of its token mint allowance. Whenever tokens are burned for bridging, the allowance increases. Whenever tokens are minted, the allowance decreases. This ensures that the Argo pallet will never net increase total supply of native token.

On Ethereum side, the ERC20 will have an optional total supply cap. EthAdmin will manage the total supply cap, changeable with a delay.

Ethereum access control

Both ERC20 and Argo bridge contracts will allow updating the owner (EthAdmin) address. EthAdmin will also be able to change minter on ERC20 and operator on Argo bridge. All of those changes would include a delay to give emergency exit window.