5/5
## Exploring Advanced Vyper Function Syntax Welcome! In this lesson, we move beyond the basics and delve into some more advanced aspects of defining functions in Vyper. While some concepts might seem challenging initially, remember that understanding comes with practice and repetition. We'll explore specific syntax elements using practical examples within a sample contract. All functions demonstrated here will be marked `@external`, meaning they can be called from outside the contract once deployed. ## Understanding Function Decorators Decorators are special keywords prefixed with `@` that modify the behavior or properties of a function. We'll focus on two key decorators here: * **`@external`**: This is perhaps the most common decorator you'll encounter. It marks a function as part of the contract's public Application Binary Interface (ABI). This means the function can be called via transactions sent to the contract or through calls from other contracts or external accounts. All our examples in this lesson use `@external`. * **`@pure`**: This decorator signifies that a function promises not to read from or modify the contract's state storage. Functions marked `@pure` (along with `@view` functions, which we'll discuss later) can often be called off-chain without incurring gas costs, provided the call itself doesn't trigger a state-changing transaction. We'll explore the nuances of `@pure` and `@view` in more detail in a subsequent lesson. We will also briefly mention `@internal` functions later, which are callable only from within the same contract. ## Defining Functions in Vyper As a reminder, defining a function in Vyper uses the standard Python `def` keyword, followed by the function name, parameters, and return type annotation. The general syntax looks like this: ```vyper def function_name(parameter_name: parameter_type, ...) -> return_type: # Function body return value ``` * `parameter_name: parameter_type`: Defines input parameters with their respective data types (e.g., `x: uint256`). * `-> return_type`: Specifies the data type of the value the function will return (e.g., `-> uint256`). ## Handling Integer Division A crucial point in Vyper involves integer division. When dividing two integers where the result might not be a whole number, Vyper requires a specific operator: * **`//`**: This is the **floor division** operator. It performs the division and rounds the result *down* to the nearest whole number. Using a single slash `/` is not the standard way to perform integer division in Vyper as demonstrated here. Always use `//` when dividing integers to ensure predictable, floored results. ## Using the 'pass' Keyword Sometimes, you might want to define a function's signature (its name, parameters, and return type) but aren't ready to implement its logic yet. In Python and Vyper, you can use the `pass` keyword as a placeholder. * **`pass`**: This is a null operation – nothing happens when it executes. It acts as a valid placeholder for the function body, allowing the contract to compile successfully even if the function does nothing. ## Returning Multiple Values Vyper functions are not limited to returning just a single value. You can return multiple values, potentially of different types. * **Declaring Multiple Return Types**: In the function signature, enclose the multiple return types within parentheses: `-> (type1, type2, ...)`. * **Returning Multiple Values**: In the `return` statement, provide the values as a tuple, enclosed in parentheses: `return (value1, value2, ...)`. ## Practical Examples: The Func.vy Contract Let's illustrate these concepts with a simple contract, `Func.vy`. ```vyper # pragma version ^0.4.0 # Example 1: Basic multiplication @external @pure def multiply(x: uint256, y: uint256) -> uint256: """ @notice Multiplies two unsigned integers. @param x The first number. @param y The second number. @return The product of x and y. """ return x * y # Example 2: Integer division @external @pure def divide(x: uint256, y: uint256) -> uint256: """ @notice Divides two unsigned integers using floor division. @param x The dividend. @param y The divisor. @return The result of x // y (rounded down). """ # Note the use of // for integer division return x // y # Example 3: Placeholder function using 'pass' @external def todo(): """ @notice A placeholder function that does nothing yet. """ # 'pass' allows an empty function body pass # Example 4: Returning multiple values @external @pure def return_many() -> (uint256, bool): """ @notice Demonstrates returning multiple values of different types. @return A uint256 value (123) and a boolean value (True). """ # Return types are (uint256, bool) # Return values as a tuple return (123, True) ``` **Explanation:** 1. **`multiply`**: A straightforward function demonstrating `@external`, `@pure`, parameter/return type definitions (`uint256`), and the standard multiplication operator (`*`). 2. **`divide`**: This function highlights the critical use of the floor division operator `//` for integer division in Vyper. 3. **`todo`**: Shows how `pass` can be used to create a valid, empty function body. Note it doesn't use `@pure` as its purpose might eventually involve state changes (though currently, it doesn't). 4. **`return_many`**: Demonstrates the syntax for returning multiple values. The signature declares `-> (uint256, bool)`, and the function returns a tuple `(123, True)`. ## Demonstrating Function Behavior After writing this code in an environment like the Remix IDE with the Vyper plugin: 1. **Compile:** The `Func.vy` contract compiles successfully. 2. **Deploy:** The contract is deployed (e.g., to the Remix VM). 3. **Interact:** We can now call the deployed functions: * Calling `todo()` executes successfully but performs no actions, as expected due to `pass`. * Calling `return_many()` (as an off-chain call since it's `@pure`) returns the values: `uint256: 123` and `bool: true`. * Calling `multiply(x=2, y=3)` returns `uint256: 6`. * Calling `divide(x=4, y=2)` returns `uint256: 2`. * Calling `divide(x=1, y=2)` returns `uint256: 0` (because 1 / 2 = 0.5, which floors down to 0). * Calling `divide(x=3, y=2)` returns `uint256: 1` (because 3 / 2 = 1.5, which floors down to 1). This clearly demonstrates the floor division behavior of `//`. ## Key Takeaways * Functions intended to be called from outside the contract must be marked `@external`. * `@pure` functions promise not to read or write contract storage. * Use the floor division operator `//` for integer division in Vyper. * The `pass` keyword serves as a placeholder for an empty function body. * Specify multiple return types using parentheses in the signature: `-> (type1, type2)`. * Return multiple values as a tuple: `return (value1, value2)`. This lesson covered several important syntactical elements for defining more complex functions in Vyper. Mastering these will allow you to build more sophisticated smart contracts.
An essential guide to Exploring Advanced Vyper Function Syntax - Master advanced Vyper function features, including decorators (`@external`, `@pure`) and the crucial floor division operator (`//`). Learn to handle placeholders with `pass` and return multiple values efficiently.
Previous lesson
Previous
Next lesson
Next
Give us feedback
Course Overview
About the course
The basics of blockchain transactions, how to send and receive money on a blockchain network.
How to write Python based smart contracts using Vyper.
How to read and understand Vyper smart contracts.
Vyper data structures, arrays, structs, hash maps.
How to build a smart contract application and deploy on ZKsync with Moccasin.
Smart Contract Auditor
$100,000 - $200,000 (avg. salary)
On-chain Data Analyst
$59,000 - $139,000 (avg. salary)
DeFi Developer
$75,000 - $200,000 (avg. salary)
Smart Contract Engineer
$100,000 - $150,000 (avg. salary)
Web3 developer
$60,000 - $150,000 (avg. salary)
Web3 Developer Relations
$85,000 - $125,000 (avg. salary)
Last updated on June 11, 2025
Duration: 2h 08min
Duration: 2h 32min
Duration: 24min
Course Overview
About the course
The basics of blockchain transactions, how to send and receive money on a blockchain network.
How to write Python based smart contracts using Vyper.
How to read and understand Vyper smart contracts.
Vyper data structures, arrays, structs, hash maps.
How to build a smart contract application and deploy on ZKsync with Moccasin.
Smart Contract Auditor
$100,000 - $200,000 (avg. salary)
On-chain Data Analyst
$59,000 - $139,000 (avg. salary)
DeFi Developer
$75,000 - $200,000 (avg. salary)
Smart Contract Engineer
$100,000 - $150,000 (avg. salary)
Web3 developer
$60,000 - $150,000 (avg. salary)
Web3 Developer Relations
$85,000 - $125,000 (avg. salary)
Last updated on June 11, 2025