/ocw-ebics

This is a Polkadot Fiat on and off ramp (fully bidirectional), provided by an Off-Chain-Worker (OCW) which connects through a REST-proxy to any bank account supporting the EBICS (Electronic Banking Internet Communication Standard) protocol. The OCW implements a fully pegged stable coin: Incoming bank transaction trigger minting of new stablcoins, and burning stablecoins trigger wire transfers on the banking network.

Primary LanguageRustApache License 2.0Apache-2.0

Unit tests

Hyperfridge Parachain

The repository contains a substrate parachain that can be connected to an arbitrary bank account which supports the EBICS banking interface (ISO20022). It synchronizes balances and transaction of a bank account with the solo chain using an off-chain-worker and zero-knowledge proofs. This worker also contains extrinsincs to trigger wire-transfers on the connected bank account.

Zero-Knowledge proofs are used to enable trustless atomic swap between FIAT and any ledger technology. The system is called Hyperfridge - the whitepaper is here.

Getting Started

Our runtime includes a pallet called fiat-ramps that is responsible for synchronization of bank account state with the on-chain state

Fiat-ramps is located inside /pallets folder. It is an offchain-worker pallet that primarily does two activities:

  • Poll EBICS service to get the latest bank statements, puts them in the queue
  • Polls EBICS service for the ZK receipt of the queued statements until it is available
  • Reads the receipt and verifies it
  • Process burn requests registered in the local pallet storage and send unpeg request to EBICS API.

Burn request is a single request to burn, transfer funds from EBICS supporting bank account using extrinsics. Account submits a request to a chain and it is registered in the local storage. Offchain worker picks up the burn request and sends it to the EBICS service. If everything goes well, EBICS service confirms the transaction and includes it in the statement, thus finalizing the burn request. This is done because transactions in traditional banks are not instant and sometimes it takes days to finalize them.

Rust Setup

First, complete the basic Rust setup instructions.

Build

Use the following command to build the node without launching it:

cargo build --release

Note: the above code might take long to compile depending on your machine specs

Run

Setup Zombienet

You should have zombienet installed, at least version 1.3.104.

Compile the node:

cargo build --release

Then, since Hyperfridge is a parachain, it requires a local network which consists of a relay chain and Asset Hub for XCM compatibility. You will need a compiled polkadot and polkadot-parachain binaries. Check out polkadot-sdk and:

Build polkadot:

cd polkadot && cargo install --path . --locked --features fast-runtime

fast-runtime feature is important, because otherwise you will have to wait a long time until parachains start producing blocks.

And then polkadot-parachain binary for Asset Hub:

cargo build --release --locked -p polkadot-parachain-bin --bin polkadot-parachain

And now, you should point path to those binaries in ENV variables:

export POLKADOT_BIN=/path/to/polkadot
export ASSET_HUB_BIN=/path/to/polkadot-parachain

Finally:

zombienet spawn -p native zombienet.toml

The log will print Polkadot.js links to all nodes.

Or you can run the node with consistent state without --tmp flag.

Tests

To run unit tests and integration tests, execute the following command:

cargo test

This runs unit tests specific to the fiat-ramps pallet and integration tests that test Hyperfridge parachain's AssetHub integration.

Linting

To run clippy linter, execute the following command:

cargo clippy

Test bank accounts

Following test accounts are for Alice, Bob and Charlie, respectively.

{
  "accounts" : [ { 
    "ownerName" : "Alice",
    "iban" : "CH2108307000289537320",
    "accountId": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
    "bic" : "HYPLCH22570",
    "offeredAccountId" : "accountname1",
    "nexusBankAccountId" : "CH2108307000289537320"
  }, {
    "ownerName" : "Bob",
    "iban" : "CH1230116000289537312",
    "accountId": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
    "bic" : "HYPLCH22572",
    "offeredAccountId" : "accountname2",
    "nexusBankAccountId" : "CH1230116000289537312"
  }, {
    "ownerName" : "Charlie",
    "iban" : "CH2108307000289537313",
    "accountId": "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y",
    "bic" : "HYPLCH22573",
    "offeredAccountId" : "accountname3",
    "nexusBankAccountId" : "CH2108307000289537313"
  } ]
}

Connect with Polkadot-JS Apps Front-end

Once the node template is running locally, you can connect it with Polkadot-JS Apps front-end to interact with your chain. Click here connecting the Apps to your local node template.

Now you will be able to open the block explorer and see transactions, events that have occured in the blockchain.

For example, you can take a look at chain storage of fiat-ramps here

Inject Signer Account

For the offchain worker to sign transactions, we need to insert authority keys into the chain. This can be done using RPC call author_insert_key which is located in PolkadotJs Apps interface RPC calls section.

For testing puroposes, we can use this account:

key_type: ramp
suri: cup swing hill dinner pioneer mom stick steel sad raven oak practice
public_key: 5C555czPfaHgYhKhsRg2KNCLGCJ82jVsvweTHAnfvT83uy5T

New API url

You can set the new url for the ebics-service via PolkadotJS interface. Follow this link to the Sudo tab and choose FiatRamps.setApiUrl extrinsic. Paste the new url for the API and click Submit transaction. If everything is good, i.e you are the Sudo account and you have the necessary rights, you should see the transaction included in the block and offchain worker starts querying the new API.

Run with Docker

First, install Docker and Docker Compose.

Then run the following command to start a single node development chain.

Run with image from DockerHub:

docker run -it -p 9944:9944 e36io/ebics-ocw:hyperfridge --dev --tmp --unsafe-rpc-external --rpc-cors=all --rpc-methods=unsafe -loffchain-worker

Docker (Linux)

Build:

docker build -t ebics-ocw .

Run:

docker run -it -p 9944:9944 ebics-ocw:latest --dev --tmp --unsafe-rpc-external --rpc-cors=all --rpc-methods=unsafe -loffchain-worker

Docker (MacOS)

Build:

docker build --platform linux/x86_64 -t ebics-ocw .

Run:

docker run --platform=linux/x86_64 -it -p 9944:9944 ebics-ocw:latest --dev --tmp --unsafe-rpc-external --rpc-cors=all --rpc-methods=unsafe -loffchain-worker

Local EBICS Service

This chain needs EBICS Java service, which is responsible for connecting to the bank account and providing an API for our offchain worker to interact with. By default it is connected to a remote EBICS service. If you want to use a local EBICS service, you can find the service here. Follow the instructions in the README to run the service.