1

In my smart contract, I would like to accept exactly 1 full HBAR unit in a payable function. The following code would work in Ethereum, by specifying 1 ether.

pragma solidity 0.8.18;

contract Example {
    function payMeOneHbar () public payable {
        require(msg.value == 1 ether, "Payment required is exactly 1 HBAR");
        /* ... other code */
    }
}

Does Hedera have the equivalent concept to 1 ether? (I cannot specify 1 hbar in Solidity, as that isn't recognised by solc.)

I tried accepting 1 HBAR and expected it would have the same function as 1 ether

Defi Girl
  • 186
  • 4

2 Answers2

2

Simply specify 100_000_000 or 10^8 in place of 1 ether, like so:

pragma solidity 0.8.18;

contract Example {
    function payMeOneHbar () public payable {
        require(msg.value == 100_000_000, "Payment required is exactly 1 HBAR");
        /* ... other code */
    }
}

Note that the absolute numerical value is different from that on Ethereum.


Detailed explanation

In Solidity syntax, ether is simply a constant that is equal to 10^18 (1,000,000,000,000,000,000). Ref: Solidity Lang - Ether Units

  • 1 wei = 1 wei
  • 1 gwei = 1,000,000,000 wei
  • 1 ether = 1,000,000,000,000,000,000 wei

In Solidity syntax there is no concept of hbar, but we can use a constant value of 10^8 (100,000,000) in its place. Ref: Hedera - HBAR and Hedera Helpdesk - What are the official HBAR cryptocurrency denominations?

  • 1 Gℏ = 1,000,000,000 ℏ
  • 1 Mℏ = 1,000,000 ℏ
  • 1Kℏ = 1,000 ℏ
  • 1 ℏ = 1 ℏ
  • 1,000 mℏ = 1 ℏ
  • 1,000,000 μℏ = 1 ℏ
  • 100,000,000 tℏ = 1 ℏ

Try it out

You can try this out manually using the following Solidity code:

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.18;

contract NativeCoinUnits {
    // for ethereum,
    // - the "full unit" of the native coin is an ether, and
    // - the "smallest unit" is a wei
    uint256 public oneWei = 1 wei;
    bool public isOneWei = (oneWei == 1);
    uint256 public oneEther = 1 ether;
    bool public isOneEther = (oneEther == 1e18);

    // for hedera,
    // - the "full unit" of the native coin is an hbar, and
    // - the "smallest unit" is a tinyhbar
    uint256 public oneTinybar = 1;
    bool public isOneTinybar = (oneTinybar == 1);
    uint256 public oneHbar = 100_000_000; // note specify manually, no unit
    bool public isOneHbar = (oneHbar == 1e8);
}

Hot link to try this out in Remix

... and if you deploy it, and invoke each of the auto-generated getter functions, you should get this result:

Remix IDE getter invocation results for the NativeCoinUnits smart contract

As you can see, all of the isOne... boolean values are true; and all the one... unsigned integer values are equal to the constants from the reference values copied above.

bguiz
  • 27,371
  • 47
  • 154
  • 243
1

In my previous answer, I realised that I used a bit of circuitous logic.

After reading HIP-410: Wrapping Ethereum Transaction Bytes in a Hedera Transaction , there is a section which defines a new concept called weibars: "Value of gas price and value fields"

For Ethereum transactions, we introduce the concept of “WeiBars”, which are 1 to 10^-18th the value of a HBAR. This is to maximize compatibility with third party tools that expect ether units to be operated on in fractions of 10^18, also known as a Wei. Thus, 1 tinyBar is 10^10 weiBars or 10 gWei.

... it was imperative to "prove" whether the smallest unit used in Solidity smart contracts deployed to Hedera was a tinybar or a weibar.

To do this, I configured MetaMask to connect to Hedera Testnet (via hedera-json-rpc-relay), and used Remix to deploy the following smart contract:

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.18;

contract TinybarsDemo {
    function checkBalance()
        public view
        returns (uint256 senderBalance)
    {
        senderBalance = msg.sender.balance;
    }
}

You can try this out on Remix yourself.

After deployment:

  • In the wallet, I have a balance of approximately 104 HBAR
  • This is approximately 10400000000 tinybar (104 followed by 8 digits)
  • This is approximately 104000000000000000000 weibar (104 followed by 18 digits)

tinybars-or-weibars-metamask-balance

When I invoke the checkBalance function on the smart contract - which simply returns msg.sender.balance - it responded with 10432200425.

tinybars-or-weibars-remix-checkbalance-senderbalance

Since 10432200425 is 104 followed by 8 digits (and not 18 digits), we can confirm that the smallest unit used is indeed tinybar (and not weibar).

bguiz
  • 27,371
  • 47
  • 154
  • 243