5/5
## Interacting with Payable Functions in Vyper This lesson demonstrates how to send Ether (ETH) along with a function call when interacting with a deployed Vyper smart contract. We will specifically call a `fund()` function designed to accept ETH, but only if the amount sent meets a minimum value requirement denominated in USD. The contract achieves this by utilizing a Chainlink Price Feed to perform real-time ETH/USD conversion and validation. ## Setting Up Your Environment in Remix Before interacting with the contract, ensure your development environment is correctly configured. 1. **Tool:** We will use the Remix IDE, a popular browser-based IDE for smart contract development. 2. **Contract Language:** The target contract is written in Vyper. Ensure you have the Vyper compiler plugin activated in Remix and select the appropriate version (e.g., `0.4.0` as specified by `pragma version 0.4.0` in the contract). 3. **Contract:** The example contract file is named `buy_me_a_coffee.vy`. 4. **Remix Environment:** Switch the Remix environment from the default "Remix VM" options to "Injected Provider - MetaMask". This connects Remix to your MetaMask wallet, allowing you to interact with specific blockchain networks configured within MetaMask. 5. **Blockchain Network:** Ensure MetaMask is connected to the target blockchain network. In this example, we use a specific test network ("Our fake chain") because it contains a pre-deployed Chainlink ETH/USD Price Feed contract that our `buy_me_a_coffee.vy` contract depends on. 6. **Wallet:** MetaMask will act as the wallet provider, prompting you to sign and confirm transactions (like contract deployment and function calls) on the selected network. ## Compiling and Deploying the Vyper Contract With the environment set up, follow these steps to compile and deploy the contract: 1. **Compile:** Navigate to the Vyper compiler plugin in Remix, select the `buy_me_a_coffee.vy` file, and click "Compile". Address any compilation errors. 2. **Deployment Arguments:** Examine the contract's `__init__` (constructor) function. It requires the address of the Chainlink ETH/USD Price Feed as an argument (`price_feed: address`). Locate this address (e.g., `0x694AA1769357215DE4FAC081bf309ADC325306` might be provided in comments or configuration) and copy it. 3. **Prepare Deployment:** Go to the "Deploy & Run Transactions" tab in Remix. Ensure your `buy_me_a_coffee.vy` contract is selected. Paste the copied price feed address into the input field next to the "Deploy" button (this field corresponds to the `price_feed` argument of the `__init__` function). 4. **Deploy:** Click the "Deploy" button. * **Troubleshooting:** Sometimes, Remix might not immediately trigger the MetaMask confirmation pop-up, especially when switching between compiler types. If this happens, a common workaround is to: * Temporarily switch to the Solidity compiler tab. * Select and compile any simple Solidity file (e.g., a default `Storage.sol`). * Switch back to the Vyper compiler tab and the "Deploy & Run Transactions" tab. * Try clicking "Deploy" again. 5. **Confirm Deployment:** MetaMask should now prompt you to confirm the contract deployment transaction on your selected network ("Our fake chain"). Review the details and click "Confirm". 6. **Deployed Contract:** Once the transaction is confirmed on the blockchain, Remix will display the interface for your deployed contract under the "Deployed Contracts" section. ## Sending Ether with Transactions: The @payable Decorator A key feature enabling our interaction is the `@payable` decorator in Vyper. * The `fund()` function within our `buy_me_a_coffee.vy` contract is marked with `@payable`. * This decorator modifies the function's behavior, allowing it to receive Ether when called. Any ETH sent along with the call to a `@payable` function is credited to the contract's balance. * Within the function's logic, the amount of Ether sent is accessible via the `msg.value` attribute, which holds the value in Wei (the smallest unit of Ether). * In Remix's "Deploy & Run Transactions" tab, interacting with a deployed contract that has `@payable` functions reveals a "VALUE" input field. You use this field to specify the amount of ETH you wish to send along with the function call, selecting the appropriate unit (Wei, Gwei, Ether). ## Implementing Value Checks with Chainlink Price Feeds Our `fund()` function doesn't just accept any amount of ETH; it enforces a minimum funding requirement based on a USD value (e.g., $5). This logic relies on integrating with a Chainlink Price Feed. 1. **Requirement:** The contract is designed to revert the transaction unless the `msg.value` (the amount of ETH sent) is worth at least a minimum USD amount (e.g., `self.minimum_usd = as_wei_value(5, "ether")`). 2. **Validation Steps:** When `fund()` is called: * It retrieves the ETH amount sent with the call using `msg.value`. * It calls an internal function (`_get_eth_to_usd_rate`) to convert this ETH amount (in Wei) into its equivalent USD value. * The `_get_eth_to_usd_rate` function interacts with the Chainlink Price Feed contract (using the address provided during deployment). It calls the `latestAnswer()` function on the price feed contract to fetch the current ETH/USD price. ```vyper # Simplified logic within _get_eth_to_usd_rate price: int256 = staticcall self.price_feed.latestAnswer() # Get raw price from Chainlink # Adjust price based on feed decimals (e.g., 8) to match Wei's 18 decimals eth_price: uint256 = convert(price, uint256) * (10**(18 - 8)) # Calculate USD value of the sent ETH (msg.value) eth_amount_in_usd: uint256 = (eth_price * eth_amount) // (1 * (10 ** 18)) return eth_amount_in_usd ``` * The main `fund()` function receives this calculated `usd_value_of_eth`. * It uses an `assert` statement to check if this value meets the requirement: ```vyper # Logic within fund() usd_value_of_eth: uint256 = self._get_eth_to_usd_rate(msg.value) assert usd_value_of_eth >= self.minimum_usd, "You must spend more ETH!" ``` * If the `assert` condition is false (the sent ETH is worth less than the minimum required USD), the transaction fails and reverts, returning the specified error message. ## Calculating the Ether Value to Send To successfully call the `fund()` function, you need to determine how much ETH (in Wei) corresponds to the minimum required USD value (e.g., $5) at the current exchange rate. 1. **Estimate Price:** Get a rough estimate of the current ETH/USD price (e.g., $3000 USD/ETH). Note that the contract will use the *live* price from the Chainlink feed on its network, which might differ slightly. 2. **Target Value:** Identify the minimum USD value required by the contract (e.g., $5 USD). 3. **Calculate ETH:** Divide the target USD value by the estimated ETH price: $5 USD / $3000 USD/ETH ≈ 0.00167 ETH. 4. **Convert to Wei:** Smart contracts operate with Wei. Use an online converter like `eth-converter.com` to convert the calculated ETH amount into Wei. * Inputting `0.00167` ETH might yield `1670000000000000` Wei. 5. **Add Buffer:** Since the price feed used by the contract might report a slightly different price than your estimate, and to avoid transaction failures due to minor fluctuations or rounding, it's wise to send slightly *more* than the calculated minimum. For instance, instead of aiming for exactly $5 worth, send an amount closer to $5.50 or $6. In our example, sending `0.002` ETH provides a safe buffer. 6. **Final Wei Amount:** Convert the buffered ETH amount (e.g., `0.002` ETH) to Wei using the converter. This gives `2000000000000000` Wei. ## Executing the Fund Transaction Now, use Remix and MetaMask to call the `fund()` function, sending the calculated Wei amount. 1. **Enter Value:** In the Remix "Deploy & Run Transactions" tab, locate your deployed contract instance. 2. **Set Value and Unit:** Find the "VALUE" input field. Paste the calculated Wei amount (`2000000000000000`) into this field. Ensure the unit dropdown next to it is set to "Wei". 3. **Call Function:** Click the button corresponding to the `fund` function (often colored red for payable functions). 4. **MetaMask Confirmation:** MetaMask will pop up, requesting confirmation for the transaction. * Verify that it's interacting with your deployed contract's address. * Check that the "Amount" displayed matches the ETH value you intended to send (e.g., `0.002 ETH`). * It should show the estimated gas fee. 5. **Confirm:** Click "Confirm" in MetaMask to sign and broadcast the transaction. ## Verifying the Transaction and Contract Balance Once MetaMask confirms the transaction has been sent, observe the results in Remix: 1. **Transaction Status:** The Remix console log will display the transaction details. A successful transaction will typically be indicated by a green checkmark. The log will show that the `fund` function was called and will include the `value` parameter indicating the Wei amount sent (`value: 2000000000000000 Wei`). 2. **Contract Balance:** In the "Deployed Contracts" section of Remix, the display for your contract instance should update to show its new ETH balance. If the transaction was successful, you should see `Balance: 0.002 ETH` (or the equivalent of the Wei value you sent), confirming that the Ether was successfully received by the contract. You have now successfully called a payable function on a Vyper smart contract, sending Ether along with the call and satisfying an on-chain value check condition powered by a Chainlink Price Feed.
This lesson demonstrates how to send Ether (ETH) along with a function call when interacting with a deployed Vyper smart contract. We will specifically call a fund()
function designed to accept ETH, but only if the amount sent meets a minimum value requirement denominated in USD. The contract achieves this by utilizing a Chainlink Price Feed to perform real-time ETH/USD conversion and validation.
Before interacting with the contract, ensure your development environment is correctly configured.
Tool: We will use the Remix IDE, a popular browser-based IDE for smart contract development.
Contract Language: The target contract is written in Vyper. Ensure you have the Vyper compiler plugin activated in Remix and select the appropriate version (e.g., 0.4.0
as specified by pragma version 0.4.0
in the contract).
Contract: The example contract file is named buy_me_a_coffee.vy
.
Remix Environment: Switch the Remix environment from the default "Remix VM" options to "Injected Provider - MetaMask". This connects Remix to your MetaMask wallet, allowing you to interact with specific blockchain networks configured within MetaMask.
Blockchain Network: Ensure MetaMask is connected to the target blockchain network. In this example, we use a specific test network ("Our fake chain") because it contains a pre-deployed Chainlink ETH/USD Price Feed contract that our buy_me_a_coffee.vy
contract depends on.
Wallet: MetaMask will act as the wallet provider, prompting you to sign and confirm transactions (like contract deployment and function calls) on the selected network.
With the environment set up, follow these steps to compile and deploy the contract:
Compile: Navigate to the Vyper compiler plugin in Remix, select the buy_me_a_coffee.vy
file, and click "Compile". Address any compilation errors.
Deployment Arguments: Examine the contract's __init__
(constructor) function. It requires the address of the Chainlink ETH/USD Price Feed as an argument (price_feed: address
). Locate this address (e.g., 0x694AA1769357215DE4FAC081bf309ADC325306
might be provided in comments or configuration) and copy it.
Prepare Deployment: Go to the "Deploy & Run Transactions" tab in Remix. Ensure your buy_me_a_coffee.vy
contract is selected. Paste the copied price feed address into the input field next to the "Deploy" button (this field corresponds to the price_feed
argument of the __init__
function).
Deploy: Click the "Deploy" button.
Troubleshooting: Sometimes, Remix might not immediately trigger the MetaMask confirmation pop-up, especially when switching between compiler types. If this happens, a common workaround is to:
Temporarily switch to the Solidity compiler tab.
Select and compile any simple Solidity file (e.g., a default Storage.sol
).
Switch back to the Vyper compiler tab and the "Deploy & Run Transactions" tab.
Try clicking "Deploy" again.
Confirm Deployment: MetaMask should now prompt you to confirm the contract deployment transaction on your selected network ("Our fake chain"). Review the details and click "Confirm".
Deployed Contract: Once the transaction is confirmed on the blockchain, Remix will display the interface for your deployed contract under the "Deployed Contracts" section.
A key feature enabling our interaction is the @payable
decorator in Vyper.
The fund()
function within our buy_me_a_coffee.vy
contract is marked with @payable
.
This decorator modifies the function's behavior, allowing it to receive Ether when called. Any ETH sent along with the call to a @payable
function is credited to the contract's balance.
Within the function's logic, the amount of Ether sent is accessible via the msg.value
attribute, which holds the value in Wei (the smallest unit of Ether).
In Remix's "Deploy & Run Transactions" tab, interacting with a deployed contract that has @payable
functions reveals a "VALUE" input field. You use this field to specify the amount of ETH you wish to send along with the function call, selecting the appropriate unit (Wei, Gwei, Ether).
Our fund()
function doesn't just accept any amount of ETH; it enforces a minimum funding requirement based on a USD value (e.g., $5). This logic relies on integrating with a Chainlink Price Feed.
Requirement: The contract is designed to revert the transaction unless the msg.value
(the amount of ETH sent) is worth at least a minimum USD amount (e.g., self.minimum_usd = as_wei_value(5, "ether")
).
Validation Steps: When fund()
is called:
It retrieves the ETH amount sent with the call using msg.value
.
It calls an internal function (_get_eth_to_usd_rate
) to convert this ETH amount (in Wei) into its equivalent USD value.
The _get_eth_to_usd_rate
function interacts with the Chainlink Price Feed contract (using the address provided during deployment). It calls the latestAnswer()
function on the price feed contract to fetch the current ETH/USD price.
The main fund()
function receives this calculated usd_value_of_eth
.
It uses an assert
statement to check if this value meets the requirement:
If the assert
condition is false (the sent ETH is worth less than the minimum required USD), the transaction fails and reverts, returning the specified error message.
To successfully call the fund()
function, you need to determine how much ETH (in Wei) corresponds to the minimum required USD value (e.g., $5) at the current exchange rate.
Estimate Price: Get a rough estimate of the current ETH/USD price (e.g., $3000 USD/ETH). Note that the contract will use the live price from the Chainlink feed on its network, which might differ slightly.
Target Value: Identify the minimum USD value required by the contract (e.g., $5 USD).
Calculate ETH: Divide the target USD value by the estimated ETH price: $5 USD / $3000 USD/ETH ≈ 0.00167 ETH.
Convert to Wei: Smart contracts operate with Wei. Use an online converter like eth-converter.com
to convert the calculated ETH amount into Wei.
Inputting 0.00167
ETH might yield 1670000000000000
Wei.
Add Buffer: Since the price feed used by the contract might report a slightly different price than your estimate, and to avoid transaction failures due to minor fluctuations or rounding, it's wise to send slightly more than the calculated minimum. For instance, instead of aiming for exactly $5 worth, send an amount closer to $5.50 or $6. In our example, sending 0.002
ETH provides a safe buffer.
Final Wei Amount: Convert the buffered ETH amount (e.g., 0.002
ETH) to Wei using the converter. This gives 2000000000000000
Wei.
Now, use Remix and MetaMask to call the fund()
function, sending the calculated Wei amount.
Enter Value: In the Remix "Deploy & Run Transactions" tab, locate your deployed contract instance.
Set Value and Unit: Find the "VALUE" input field. Paste the calculated Wei amount (2000000000000000
) into this field. Ensure the unit dropdown next to it is set to "Wei".
Call Function: Click the button corresponding to the fund
function (often colored red for payable functions).
MetaMask Confirmation: MetaMask will pop up, requesting confirmation for the transaction.
Verify that it's interacting with your deployed contract's address.
Check that the "Amount" displayed matches the ETH value you intended to send (e.g., 0.002 ETH
).
It should show the estimated gas fee.
Confirm: Click "Confirm" in MetaMask to sign and broadcast the transaction.
Once MetaMask confirms the transaction has been sent, observe the results in Remix:
Transaction Status: The Remix console log will display the transaction details. A successful transaction will typically be indicated by a green checkmark. The log will show that the fund
function was called and will include the value
parameter indicating the Wei amount sent (value: 2000000000000000 Wei
).
Contract Balance: In the "Deployed Contracts" section of Remix, the display for your contract instance should update to show its new ETH balance. If the transaction was successful, you should see Balance: 0.002 ETH
(or the equivalent of the Wei value you sent), confirming that the Ether was successfully received by the contract.
You have now successfully called a payable function on a Vyper smart contract, sending Ether along with the call and satisfying an on-chain value check condition powered by a Chainlink Price Feed.
A practical guide to Interacting with Payable Functions in Vyper - Learn how to send Ether to Vyper smart contracts using `@payable` functions via Remix and MetaMask. Understand how to calculate the correct ETH amount based on USD requirements using Chainlink Price Feeds.
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