In Vyper, unsigned integers are a data type that exclusively store non-negative whole numbers. Here are a few examples:
stock_count: uint256
@external
def store_count(num: uint256):
self.stock_count = num
@external
def get_count() -> uint256:
return self.stock_count
@public
def perform_operations(x: uint128, y: uint128) -> (uint128, uint128, uint128):
sum = x + y
difference = x - y
product = x * y
return (sum, difference, product)
@public
def compare_values(x: uint128, y: uint128) -> bool:
return x > y
Unsigned integers, denoted as uintN
(where N ranges from 8 to 256 in multiples of 8 such as uint8
or uint256
), bring predictability and security to developers, addressing a wide array of use-cases.
Whether it’s tracking non-negative quantities like a user’s age or the stock count of a product, or efficiently managing storage by selecting appropriate bit sizes, unsigned integers offer significant flexibility. This versatility makes them a crucial tool in the smart contract developer’s arsenal.
Overview Of Unsigned Integers
In Vyper, integers come in two flavors: signed and unsigned. The unsigned integer, denoted with the uintN
keyword (where N ranges from 8 to 256, in multiples of 8), represents only non-negative integers.
Unsigned integers allow values from 0 up to 2^N-1, where N denotes the bit size of our integer. It’s important to note that integer literals in Vyper do not assume decimal points, indicating they contain whole numbers exclusively.
When To Use Unsigned Integers
Unsigned integers are a very useful datatype where values are always non-negative. Whether it’s representing a product’s inventory in an e-commerce contract or tracking the age of identities in identity verification contracts, scenarios with assured positivity benefit from unsigned integers.
Moreover, unsigned integers help optimize storage costs as developers can choose the appropriate size that suits their specific needs.
Bitwise Operators and Bitwise Shift
It’s also necessary to note that Vyper provides Bitwise operators (&
, |
, ^
, ~
) and Bitwise shifts (<<
, >>
) in its arsenal for unsigned integers. These operators work at the bit level and offer fine-grained control over data. Bitwise shifts are particularly preserved for 256-bit wide types though. We won’t dive into these features in-depth here as they deserve their individual attention.
Example 1: Storing and Retrieving an Unsigned Integer
Let’s dive in by storing an unsigned integer in a smart contract and building functions to store and retrieve the number.
stock_count: uint256
@external
def store_count(num: uint256):
# Store an unsigned integer in the contract.
self.stock_count = num
@external
def get_count() -> uint256:
# Retrieve the stored unsigned integer.
return self.stock_count
We first define a state variable stock_count
as an unsigned integer. The store_count
function enables any unsigned number to be stored into stock_count
, whereas the get_count
function returns the stored value when invoked.
Example 2: Implementing Basic Arithmetic Operations
Next, we present a function performing arithmetic operations like addition, subtraction, and multiplication on unsigned integers.
@public
def perform_operations(x: uint128, y: uint128) -> (uint128, uint128, uint128):
# Perform basic arithmetic operations with unsigned integers.
sum = x + y
difference = x - y
product = x * y
return (sum, difference, product)
Here, the perform_operations
function takes two parameters, x
and y
of type uint128
, and computes their sum, difference, and product. The results are then returned as a tuple of uint128
values.
Example 3: Comparing Unsigned Integers
Our final example showcases a comparison operation between two unsigned integers
@public
def compare_values(x: uint128, y: uint128) -> bool:
# Compare two unsigned integers and return True if x is greater than y.
return x > y
In this function compare_values
, two unsigned integers are taken as parameters, and it’s determined if x
is greater than y
using the >
operator.
Best Practices and Potential Pitfalls
While using unsigned integers, keep these key points in mind:
- Select Appropriate Bit Size: When working with unsigned integers, ensure that you select the smallest bit size that accommodates your data range. This practice helps in optimizing storage and gas costs in your contract.
- Prevent Overflow/Underflow: When performing operations with unsigned integers, beware of potential underflows and overflows. For instance, subtracting from zero can result in an underflow. Make sure to include necessary checks in your code to prevent such situations.
- Avoid Division by Zero: When performing division, ensure the denominator is non-zero. Failing to make this check could result in runtime exceptions.
- Beware of Type Casting: Be careful when casting integers to a smaller bit size data types. This may result in loss of data if the integer being converted is larger than what the smaller bit size can hold.
By leveraging best practices and avoiding common pitfalls, you can make the most of using unsigned integers in your Vyper smart contracts.
In conclusion, unsigned integers are indispensable in many smart contract applications, particularly when we are dealing with values that are always non-negative. Understanding how to use this integer type will go a long way in writing safer and more efficient smart contracts in Vyper. Armed with this knowledge you are one step closer to mastering Vyper for smart contract development!
