Basic Operations Examples

Learn how to use basic features of Habtor(e.g. bridges, basic L2 ops) through examples

To see examples of how to perform basic operations on Habtor, please see the react code for the Habtor gateway.

Below, we provide code snippets for several typical operations on the L2:

  1. Check the Gas Price

  2. Estimate the cost of a contract call

  3. An L2->L2 transfer

  4. A 'classic' bridging operation

Overall, note that from the perspective of solidity code and rpc calls, Habtor OVM 2.0 is identical to mainchain in most aspects, so your experience (and code) from mainchain should carry over directly. The main practical differences center on Gas and on cross-chain bridging operations.

1. Check the Current Gas Price

The Gas Price on L2 changes every 30 seconds, with some smoothing to reduce sharp discontinuities in the price from one moment to the next. The maximum percentage change of the l2 gas price is 5% in the gas price oracle. Like on mainchain, the current gas price can be obtained via .getGasPrice():

  this.L2Provider = new ethers.providers.StaticJsonRpcProvider('mainnet.habtor.com')

  const gasPrice = await this.L2Provider.getGasPrice()
   
  console.log("Current gas price:", gasPrice )
  //prints: Current gas price: BigNumber {_hex: '0x02540be400', _isBigNumber: true}

  console.log("Current gas price", gasPrice.toString())
  //prints: Current gas price: 10000000000

Typical values are 3 to 10 Gwei.

2. Estimate the cost of a contract call

Like on mainchain, the cost of a L2 transaction is the product of the current gas price and the 'complexity' of the contract call, with some calls being much more expensive than others. The contract call complexity is quantified via the gas. For example, the cost of an approval on L2 is about 0.0004 BNB, or about $0.170 :

NOTE: The gas for a particular transaction depends both on the nature of the call (e.g. approve) and the call parameters, such as the amount (in this case, 1.0 BNBN). A common source of reverted transactions is to mis-estimate the gas, such as by calling .estimateGas() with a TX generated for a different value.

NOTE: Unlike on L1, on L2 there is no benefit to paying more - you just waste BNB. The sequencer operates in first in first serve, and transaction order is determined by the arrival time of your transaction, not by how much you are willing to pay.

NOTE: To protect users, overpaying by more than a 10% percent will also revert your transactions. The core gas price logic is as follows:

Gas Price tolerance band : The gasPrice you use should be within 10% of the value reported by .getGasPrice(). Let’s say the gasPrice is 100 Gwei. Then, the l2geth will accept any gasPrice between 90 Gwei to 110 Gwei.

3. An L2->L2 transfer

4. An L1->L2 Classic Bridge Operation

5. Accessing latest L1 Block number

NOTICE

The hex value that corresponds to the L1BLOCKNUMBER opcode (0x4B) may be changed in the future (pending further discussion). We strongly discourage direct use of this opcode within your contracts. Instead, if you want to access the latest L1 block number, please use the OVM_L1BlockNumber contract as described below.

The block number of the latest L1 block seen by the L2 system can be accessed via the L1BLOCKNUMBER opcode. Solidity doesn't make it easy to use non-standard opcodes, so we've created a simple contract located at 0x4200000000000000000000000000000000000013 (opens new window)that will allow you to trigger this opcode.

You can use this contract as follows:

Block Numbers and Timestamps

Block production is not constant

On BSC mainnet, the NUMBER opcode (block.number in Solidity) corresponds to the current BSC mainnet block number. Similarly, in Habtor Network, block.number corresponds to the current L2 block number. However, as of the OVM 2.0 release of Optimistic Ethereum (Nov. 2021), each transaction on L2 is placed in a separate block and blocks are NOT produced at a constant rate.

This is important because it means that block.number is currently NOT a reliable source of timing information. If you want access to the current time, you should use block.timestamp (the TIMESTAMP opcode) instead.

Timestamp lags by up to 15 minutes

Note that block.timestamp is pulled automatically from the latest L1 block seen by the L2 system. L2 currently waits for about 15 minutes (~50 confirmations) before the L1 block is accepted. As a result, the timestamp may lag behind the current time by up to 15 minutes.

Last updated