Vyper Decimals (Usage and Examples)

whiteboard crypto logo
Published by:
Whiteboard Crypto
on

Vyper’s decimal data type is a vital tool for managing fixed-point decimal numbers when building Ethereum smart contracts. Here are a few examples:

@public
@constant
def multiply_decimals(a: decimal, b: decimal) -> decimal:
    return a * b

@public
@constant
def add_decimals(a: decimal, b: decimal) -> decimal:
    return a + b

stored_amount: decimal

@external
def store_amount(_amount: decimal):
    self.stored_amount = _amount

@external
@constant
def get_stored_amount() -> decimal:
    return self.stored_amount

@external
@constant
def get_double_amount() -> decimal:
    return self.stored_amount * 2

pi: decimal = 3.1415926535

@external
@constant
def calculate_area(radius: decimal) -> decimal:
    return self.pi * radius * radius

Overview of Decimals

In Vyper, the decimal data type is a fixed-point decimal value. The precision is up to 10 decimal places, ranging from -1.871 x 10^37 to 1.871 x 10^37 but not reaching +/- 2^168.

Value literals can be interpreted as decimals by including a decimal point. For example, 123.45 is a decimal value, while 123 would be interpreted as an integer.

Interestingly, one of the striking differences between Vyper and Solidity (another popular language for writing Ethereum smart contracts) is in the handling of fixed-point numbers. Currently, Solidity does not support fixed-point numbers, whereas Vyper allows the use of decimal fixed-point numbers. This was a deliberate design choice made by the creators of Vyper to provide safer and more accessible financial computations within smart contracts.

Therefore, understanding, using, and being comfortable with decimals is critical for any Vyper developer. Whether you’re writing a finance smart contract dealing with monetary values or creating formulas requiring higher precision, Vyper’s decimal is what you need.

Arithmetic with Decimals

Arithmetic operations including addition (+), subtraction (-), multiplication (*), division (/), and modulo (%) can be performed on decimals in Vyper. The arithmetic operations involving decimal types will require two decimal inputs and the resulting type will also be a decimal. Also, remember that dividing by zero will throw an error.

Example 1: Basic Operations with Decimals

Let’s look at some simple Vyper code performing basic arithmetic operations using decimals.

@public
@constant
def multiply_decimals(a: decimal, b: decimal) -> decimal:
    # Multiplies two decimal values and returns the result
    return a * b

@public
@constant
def add_decimals(a: decimal, b: decimal) -> decimal:
    # Adds two decimal values and returns the sum
    return a + b

In the code above, we have two functions – multiply_decimals and add_decimals which performs multiplication and addition on decimal variables respectively.

Example 2: Handling Ether Amounts as Decimals

Often smart contract developers must handle ether amounts that require decimal precision. The following contract stores a specified Ether amount in a decimal variable and provides functionality to retrieve the stored value and its double.

stored_amount: decimal

@external
def store_amount(_amount: decimal):
    # Store the ether amount in the contract.
    self.stored_amount = _amount

@external
@constant
def get_stored_amount() -> decimal:
    # Retrieve the stored ether amount.
    return self.stored_amount

@external
@constant
def get_double_amount() -> decimal:
    # Return the double of the stored ether amount
    return self.stored_amount * 2

In the contract above, we first declare a decimal variable stored_amount, then define a function store_amount() that takes a decimal argument and stores it. get_stored_amount() retrieves the stored ether amount, and get_double_amount() returns its double.

Example 3: Calculating Area using Decimals

Suppose we’re making a smart contract to calculate the area of a circle. The precision offered by decimals would make it ideal for this task.

pi: decimal = 3.1415926535

@external
@constant
def calculate_area(radius: decimal) -> decimal:
    # Calculate the area of a circle with the provided radius using the formula Pi*r^2
    return self.pi * radius * radius

In this contract, we store the value of pi in a decimal variable and define a method calculate_area() to calculate the area of a circle of a given radius.

Best Practices and Trouble Spots

Here are few best practices and potential trouble spots to watch for when working with decimals in Vyper:

  1. Beware of Overflow and Underflow: Vyper’s decimal type has a maximum and minimum value. Ensure your operations do not result in a value outside of this range, which would cause an overflow or underflow error.
  2. Mind your Precision: Remember that the decimal datatype allows up to 10 decimal places of precision.
  3. Correct use of Modulo: Modulo operation with decimals will return the same type as the operands but do note that it will follow the floor division convention which might lead to unexpected results.
  4. Know Your Types: When working with other numerical types like integers, know their types, and convert other numerical types to decimal before performing operations if decimal precision is required.
  5. Avoid Division By Zero Errors: Ensure that the divisor is not zero before performing the division operation to avoid a runtime error.

By carefully considering these nuances and capitalizing on the precise mathematical capabilities that decimal provides, developers can unlock a vast spectrum of possibilities for their Vyper smart contracts. Now, it’s your turn to put these decimals to work – happy coding!

whiteboard crypto logo

WhiteboardCrypto is the #1 online resource for crypto education that explains topics of the cryptocurrency world using analogies, stories, and examples so that anyone can easily understand them. Growing to over 870,000 Youtube subscribers, the content has been shared around the world, played in public conferences and universities, and even in Congress.