GithubHelp home page GithubHelp logo

beamer-bridge / beamer Goto Github PK

View Code? Open in Web Editor NEW
46.0 5.0 21.0 11.28 MB

Beamer - Bridging rollups with L1 inherited security

Home Page: https://beamerbridge.com

License: MIT License

Solidity 4.74% Python 33.90% Shell 1.95% Makefile 0.19% JavaScript 0.24% HTML 0.19% Vue 5.45% TypeScript 53.19% CSS 0.05% SCSS 0.04% Dockerfile 0.06%
ethereum rollups blockchain layer2 erc20 bridge

beamer's Introduction

CircleCI

Beamer Bridge

Transfer ERC20 assets directly between EVM compatible rollups - with a world class user experience

Beamer is a protocol to enable users to move tokens from one rollup to another. The user requests a transfer by providing tokens on the source rollup. Liquidity providers then fill the request and directly send tokens to the user on the target rollup.

Documentation: https://docs.beamerbridge.com

Mainnet frontend: https://app.beamerbridge.com

Testnet frontend: https://testnet.beamerbridge.com

For running your own agents, see https://github.com/beamer-bridge/run-your-own-agent. For developer information (e.g. how to run a local test agent), see https://docs.beamerbridge.com/contributing.html.

beamer's People

Contributors

andfletcher avatar bilbeyt avatar cducrest avatar compojoom avatar dependabot[bot] avatar ezdac avatar fredo avatar gabrielburagev avatar manuelwedler avatar nekhaly avatar omahs avatar palango avatar panpilkarz avatar taleldayekh avatar weilbith avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

beamer's Issues

Cancellation for requests

On the contract side:

  • add a function to cancel a request
  • introduce cancellation period

On the node side:

  • mark the requests as cancelled

Watch L2 chains for events

Set up monitoring of L2 chains so that we get events. We need to check only blocks within the last challenge period, 7 days.
For the purpose of monitoring we will use external L2 nodes.

Introduce a ChainMonitor type that handles chain monitoring and stores the necessary state.
A chain monitor should always be running in a separate thread so as not to block the main thread.
All queries to a chain monitor must be non-blocking.

Write whitepaper

I believe that we should have a whitepaper for Raisync. There are two main reasons for it.

  1. External people can review and provide input regarding the soundness of the protocol
  2. Investors will most likely be asking for something like this before they want to invest (similar to point 1, yes). Projects like li.fi will also ask for a whitepaper before they will list us.

Other reasons:

  • We can have a shared understanding and vocabulary to use within the team

Acceptance Criteria

The document should explain the protocol at a detail level that's good enough for an external researcher to read it and understand how the protocol works and the security model it has.

Race condition: `KeyError: 1`

This seems to happen when the fills get synced before the requests.

2021-11-26 09:57:43.652153 [info     ] Using account 0x5a3B85ece0056aab6de2AB163Ca34EF38838365b [raisync.cli]
2021-11-26 09:57:44.015454 [debug    ] Fetching RequestFilled events  [raisync.chain] from_block=142050 to_block=143050
2021-11-26 09:57:44.170384 [debug    ] Got new events                 [raisync.chain] events=(AttributeDict({'args': AttributeDict({'requestId': 1, 'sourceChainId': 421611, 'targetTokenAddress': '0x1F2104Ce7Fe661DBcc833f070C9CF5bEcCc56F08', 'amount': 12345}), 'event': 'RequestFilled', 'logIndex': 0, 'transactionIndex': 0, 'transactionHash': HexBytes('0xde7f8da155883b18cea0995ab0e58e6d539e1485803ad14dcd7a49a234e85c3f'), 'address': '0xd178F316542599c8D9CbfcBcFFa20A94A9B38Dbd', 'blockHash': HexBytes('0xe991ab981fc0ebea61d6579b7e2a83df702140616a1072327e8398e8cec534d4'), 'blockNumber': 142747}),)
2021-11-26 09:57:44.170632 [debug    ] Fetching RequestFilled events  [raisync.chain] from_block=143051 to_block=145051
2021-11-26 09:57:44.333571 [debug    ] Fetching RequestFilled events  [raisync.chain] from_block=145052 to_block=146189
2021-11-26 09:57:44.452444 [info     ] Chain monitor started          [raisync.chain] chain_id=421611 url=https://rinkeby.arbitrum.io/rpc
2021-11-26 09:57:44.490427 [debug    ] Request filled                 [raisync.chain] request_id=1
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/local/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/threading.py", line 973, in _bootstrap_inner
    self.run()
  File "/usr/local/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/threading.py", line 910, in run
    self._target(*self._args, **self._kwargs)
  File "/Users/paul/Projects/brainbot/raisync/raisync/chain.py", line 229, in _fill_monitor_thread
    self._prune_filled_requests(fetcher)
  File "/Users/paul/Projects/brainbot/raisync/raisync/chain.py", line 219, in _prune_filled_requests
    self._pending_requests.remove(event.args.requestId)
  File "/Users/paul/Projects/brainbot/raisync/raisync/chain.py", line 114, in remove
    del self._map[request_id]
KeyError: 1

Add a basic command line interface

Add a basic command line interface:

Usage: raisync [OPTIONS]
                                                                                                                               
Options:                                                      
  --keystore-file FILE            The file that stores the key for the account to be used.
  --password PASSWORD             The password needed to unlock the account.
  --l2a-rpc-url URL               The URL of the first L2 chain RPC server (e.g. http://10.0.0.2:8545).
  --l2b-rpc-url URL               The URL of the second L2 chain RPC server (e.g. http://10.0.0.3:8545).
  --version                       Show version information.
  --help                          Show this message and exit.                                                                  

Create L1 Resolver contract

We need to create the Resolver contract that is responsible for least resort L1 resolution.

  • Trigger message execution from Optimism contracts
  • Send this information to another message box

Unhandled exception: `web3.exceptions.ContractLogicError`

2021-11-25 16:01:32.381657 [debug    ] Got new events                 [raisync.chain] events=(AttributeDict({'args': AttributeDict({'requestId': 3, 'targetChainId': 421611, 'targetTokenAddress': '0xCFeb147eE74132BD506065130cC6EaCa2FE9a73F', 'targetAddress': '0x6D5F4B27d1200770f1e26Ce1C6A5E2Dd90f70Cac', 'amount': 12}), 'event': 'RequestCreated', 'logIndex': 0, 'transactionIndex': 0, 'transactionHash': HexBytes('0x64c16e90e1e67fa1c4b2b35c64282d4389981fe277122fb6be71dceba09b9530'), 'address': '0x6D5F4B27d1200770f1e26Ce1C6A5E2Dd90f70Cac', 'blockHash': HexBytes('0x6e2808d8d276105e8c49f6406d20a67b92c5e732b30794c5415a02c7ab48cc73'), 'blockNumber': 142622}),)
2021-11-25 16:01:33.512178 [debug    ] Fetching RequestCreated events [raisync.chain] from_block=142623 to_block=142623
Exception in thread RequestHandler: https://rinkeby.arbitrum.io/rpc:
Traceback (most recent call last):
  File "/usr/local/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/threading.py", line 973, in _bootstrap_inner
    self.run()
  File "/usr/local/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/threading.py", line 910, in run
    self._target(*self._args, **self._kwargs)
  File "/Users/paul/Projects/brainbot/raisync/raisync/chain.py", line 243, in _thread_func
    self._fulfill_request(request)
  File "/Users/paul/Projects/brainbot/raisync/raisync/chain.py", line 267, in _fulfill_request
    txn_hash = fill_manager.functions.fillRequest(
  File "/Users/paul/Library/Caches/pypoetry/virtualenvs/raisync-NwuNULVI-py3.9/lib/python3.9/site-packages/web3/contract.py", line 999, in transact
    return transact_with_contract_function(
  File "/Users/paul/Library/Caches/pypoetry/virtualenvs/raisync-NwuNULVI-py3.9/lib/python3.9/site-packages/web3/contract.py", line 1592, in transact_with_contract_function
    txn_hash = web3.eth.send_transaction(transact_transaction)
  File "/Users/paul/Library/Caches/pypoetry/virtualenvs/raisync-NwuNULVI-py3.9/lib/python3.9/site-packages/web3/eth.py", line 695, in send_transaction
    return self._send_transaction(transaction)
  File "/Users/paul/Library/Caches/pypoetry/virtualenvs/raisync-NwuNULVI-py3.9/lib/python3.9/site-packages/web3/module.py", line 57, in caller
    result = w3.manager.request_blocking(method_str,
  File "/Users/paul/Library/Caches/pypoetry/virtualenvs/raisync-NwuNULVI-py3.9/lib/python3.9/site-packages/web3/manager.py", line 186, in request_blocking
    response = self._make_request(method, params)
  File "/Users/paul/Library/Caches/pypoetry/virtualenvs/raisync-NwuNULVI-py3.9/lib/python3.9/site-packages/web3/manager.py", line 147, in _make_request
    return request_func(method, params)
  File "/Users/paul/Library/Caches/pypoetry/virtualenvs/raisync-NwuNULVI-py3.9/lib/python3.9/site-packages/web3/middleware/signing.py", line 151, in middleware
    transaction = format_and_fill_tx(params[0])
  File "cytoolz/functoolz.pyx", line 505, in cytoolz.functoolz.Compose.__call__
  File "cytoolz/functoolz.pyx", line 250, in cytoolz.functoolz.curry.__call__
  File "/Users/paul/Library/Caches/pypoetry/virtualenvs/raisync-NwuNULVI-py3.9/lib/python3.9/site-packages/web3/_utils/transactions.py", line 102, in fill_transaction_defaults
    default_val = default_getter(web3, transaction)
  File "/Users/paul/Library/Caches/pypoetry/virtualenvs/raisync-NwuNULVI-py3.9/lib/python3.9/site-packages/web3/_utils/transactions.py", line 66, in <lambda>
    'gas': lambda web3, tx: web3.eth.estimate_gas(tx),
  File "/Users/paul/Library/Caches/pypoetry/virtualenvs/raisync-NwuNULVI-py3.9/lib/python3.9/site-packages/web3/eth.py", line 735, in estimate_gas
    return self._estimate_gas(transaction, block_identifier)
  File "/Users/paul/Library/Caches/pypoetry/virtualenvs/raisync-NwuNULVI-py3.9/lib/python3.9/site-packages/web3/module.py", line 57, in caller
    result = w3.manager.request_blocking(method_str,
  File "/Users/paul/Library/Caches/pypoetry/virtualenvs/raisync-NwuNULVI-py3.9/lib/python3.9/site-packages/web3/manager.py", line 187, in request_blocking
    return self.formatted_response(response,
  File "/Users/paul/Library/Caches/pypoetry/virtualenvs/raisync-NwuNULVI-py3.9/lib/python3.9/site-packages/web3/manager.py", line 167, in formatted_response
    apply_error_formatters(error_formatters, response)
  File "/Users/paul/Library/Caches/pypoetry/virtualenvs/raisync-NwuNULVI-py3.9/lib/python3.9/site-packages/web3/manager.py", line 67, in apply_error_formatters
    formatted_resp = pipe(response, error_formatters)
  File "cytoolz/functoolz.pyx", line 667, in cytoolz.functoolz.pipe
  File "cytoolz/functoolz.pyx", line 642, in cytoolz.functoolz.c_pipe
  File "/Users/paul/Library/Caches/pypoetry/virtualenvs/raisync-NwuNULVI-py3.9/lib/python3.9/site-packages/web3/_utils/method_formatters.py", line 569, in raise_solidity_error_on_revert
    raise ContractLogicError(response['error']['message'])
web3.exceptions.ContractLogicError: execution reverted: ERC20: transfer amount exceeds allowance

Add token matching whitelist

When a request comes in the nodes needs to decide if it wants to fill it.

The request may contain an invalid token pair, e.g. request a payment of 10 WETH while depositing 10 DAI. This may not be obvious, as the token addresses can differ between L2s.

For that reason we need a (white)list of token address pairs that represent the same L1 token.

@czepluch Can you investigate how other bridge solutions do this?

Tasks

- [ ] Define whitelist

  • Implement check during fill

How to compound balance

Unfortunately, I realized that it is quite difficult to compound the balance of the service provider since the claim period ends with no interaction with the blockchain. This means that we end up with a list of claims and when they end, which will increase the balance.
While we can still withdraw everything in one transaction, the complexity grows linearly with the number of claims and is not constant.

One mitigation what we could do is update the balance whenever the service provider starts a new claim.

If you have other suggestions, lets discuss

Frontend prototype

Develop a first prototype for the frontent for requesting transfers, so we have the whole user interaction mocked out.

Fee model 3

This epic groups issues related to implementation of fee model 3.

Respond to challenges

If we fulfilled a request and notice that someone challenged our claim, respond to the challenge.
For now just keep counter-challenging until we run out of funds (L1 resolution is not done yet).

node: SIGINT does not stop the node quickly

Observed by @palango.
Run

raisync --keystore-file <something> \
          --password '' \
          --l2a-rpc-url https://kovan.optimism.io \
          --l2b-rpc-url https://rinkeby.arbitrum.io/rpc \
          --contracts-deployment-dir contracts/build/deployments/69/

and hit Ctrl-C:

2021-11-25 14:52:13.537827 [debug    ] Fetching RequestCreated events [raisync.chain] from_block=5901145 to_block=5965145
^C2021-11-25 14:52:15.742966 [info     ] Received SIGINT, shutting down [raisync.cli]
2021-11-25 14:52:17.056174 [debug    ] Fetching RequestCreated events [raisync.chain] from_block=5965146 to_block=6029146
2021-11-25 14:52:19.358759 [debug    ] Fetching RequestCreated events [raisync.chain] from_block=6029147 to_block=6093147
2021-11-25 14:52:22.952413 [debug    ] Fetching RequestCreated events [raisync.chain] from_block=6093148 to_block=6157148
^C2021-11-25 14:52:25.296997 [debug    ] Fetching RequestCreated events [raisync.chain] from_block=6157149 to_block=6221149
2021-11-25 14:52:27.604568 [debug    ] Fetching RequestCreated events [raisync.chain] from_block=6221150 to_block=6285150
2021-11-25 14:52:29.931197 [debug    ] Fetching RequestCreated events [raisync.chain] from_block=6285151 to_block=6349151
^C^C2021-11-25 14:52:32.195375 [debug    ] Fetching RequestCreated events [raisync.chain] from_block=6349152 to_block=6413152
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C2021-11-25 14:52:35.821445 [debug    ] Fetching RequestCreated events [raisync.chain] from_block=6413153 to_block=6477153
2021-11-25 14:52:38.134028 [debug    ] Fetching RequestCreated events [raisync.chain] from_block=6477154 to_block=6541154
2021-11-25 14:52:42.029041 [debug    ] Fetching RequestCreated events [raisync.chain] from_block=6541155 to_block=6605155

The node stops, but only after 15s or so.

Create e2e test image

We need a way to do e2e tests.

A first idea is to create a docker image with the following components. The tests would then connect to those nodes and run e2e tests on those.

  • Run a private chain that acts as L1 (on geth)
  • Run a private Optimism instance
    • Deploy Raisync contracts

Implement fee model 3

As part of this item, we are going to implement fee model 3, the simplest one.
For detals see https://docs.google.com/spreadsheets/d/1JxefyHC791pnRwi0lVIUkUpNcBxlBFcV9rDEQvwmHHU/edit#gid=0.

Contracts

LP service fee

  • modify the withdraw contract function to give out the LP service fee (formula?) in ETH
  • the formula needs to account for the changing gas price
  • can we get the current gas price from inside the contract?
  • bookkeeping of fees during the request lifecycle

Raisync Service Fee

  • every request costs the same (does not depend on gas price or transfer amount)
  • add another contract function e.g. withdraw_fees that only the controller is allowed to call;
    this sends the accumulated service fees to the controller address

Whitelisting for LPs

On the contract side:

  • add a list of allowed LP addreses to the FillManager
  • add a way for the contract controller to modify the list (add/remove LP addresses)
  • add the membership check in the fillRequest function

On the node side:

  • check whether we are allowed to fill before sending the fill transaction

Document protocol parameters

The Raisync protocol relies on a number of parameters:

claimStake             
claimPeriod            
challengePeriod        
challengePeriodExtension
cancellationPeriod

We need to document, for each parameter:

  • the specific value to be used in production
  • reasoning behind value selection
  • an analysis of how changing the parameter's value influences the protocol

Ideally, the document should be stored in the raisync repo, making it easier to update as the contracts are updated.

Extend node tests

We need to extend node tests to cover everything that has been done so far, including the recent claim and withdraw features.
Make sure that tests are actually run on CI.

Improve sleeping in ContractEventMonitor

Currently we have this in ContractEventMonitor:

        while not self._stop:
            events = fetcher.fetch()
            if events:
                self._on_new_events(events)
            # TODO: wait for new block instead of the sleep here
            time.sleep(1)

(https://github.com/raisync-project/raisync/blob/main/raisync/chain.py#L66-L71)
We sleep for 1s before we fetch next batch of events, which is not that efficient because we may
wake up only to find out that there are no new events because a new block has not been mined yet.
However, we cannot just wait on the new block indefinitely since that would prevent the clean shutdown
of the node via the self._stop flag.

Ideally, our sleep time would be either the time-until-next-block or time-until-stop-is-set, whichever is smaller.

Claim and challenge functionality

Contracts

  • Claim manager contract for making claims and challenges.

Node

  • State machinery for tracking request's state.
  • Functionality for making claims.
  • Functionality for posing a challenge.
  • Functionality for responding to a challenge.

UI

  • Nice to have. Notify user that their funds have been successfully moved to another chain.

Tweak the default log output

We should not emit debug logs by default but instead allow the user to request it explicitly.
This should help with log readability in regular usage.

Create ClaimManager

Handling Claims is quite complex and certain actions on the claim can cause a bunch of automatic consequences.
This is due to the fact that it is possible to have multiple claims ongoing for one request_id. This are disjunct from each other.
In order to handle claims separately, we can introduce a ClaimManager which will keep track of claims and keeps the state of them. This concept is similar to an AuctionHouse in stable systems like Maker.
RaiSync could serve as a proxy for claim creation or vice versa, it only checks if a request_id for a claim exists and does some sanity check (if necessary).

Multiple claims for a single request

We need this otherwise an attacker could block finalization of requests for the real service provider. They should run independently. The first claim for a request which goes through should be the rightful owner of the tokens. This is necessary because he might not withdraw them but should be able to reuse them or store them in the contract.

Claims after Challenge

If a claim is challenged it will not produce an output for whom is the rightful owner of the request. UNLESS L1 validation is triggered. This will introduce the rightful owner into the roll up state and should always overrule any claims. Actually I think we should store information coming from L1 in a separate place.
This means that if a claim is challenged, it must not produce the owner of the request's withdrawable amount.

Successful Claims

After the claim period ends successfully the ClaimManager should return the claimer's address for the request_id.

We should outsource the organisation of claims

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.