DEV Community

Rafael Abuawad
Rafael Abuawad

Posted on • Updated on

Challenge #1: πŸ₯© Decentralized Staking App | Speedrun Ethereum With Vyper 🐍

Table of contents

πŸ₯© Introductionn

The ERC20 standard has long been the backbone of token development on EVM-compatible blockchains, serving as a fundamental component not only for DeFi but for a wide range of blockchain applications. However, as the DeFi ecosystem continues to evolve, the need for new standards that can support more advanced features and functions has become increasingly apparent.

ERC4626 is one such standard, specifically designed for yield-generating vaults. By providing a more consistent and interoperable framework for developing these critical components of DeFi, ERC4626 promises to open up new opportunities for developers and users alike.

In the upcoming challenge, we will delve into the implementation process for both tokens and vaults, leveraging the Vyper programming language to explore the key concepts and principles involved in this exciting area of blockchain development. Through this process, participants will gain a deeper understanding of the challenges and opportunities involved in building DeFi applications, and be equipped with the skills and knowledge necessary to succeed in this dynamic and rapidly-evolving field.

πŸ“¦ Setup

For setting up the project on a local machine, only one essential component is required:

Python is the primary programming language used in the project, it includes PIP, which serves as the package manager for Python and Virtual ENV is an essential tool used for creating a virtual environment that will house the application's code.

While the process for setting up these components is beyond the scope of this challenge, in essence, it involves installing Python and configuring a virtual environment for the application's code. It is important to note that creating a virtual environment for the project ensures that the application's dependencies and requirements are isolated from those of the host system, thereby improving stability and reproducibility.

Brownie

If you are going to use Brownie in this challenge, in your virtual environment, go ahead and install Brownie, after you installed it, create a new folder called vaults and inside it run the following command:

$ brownie init
Enter fullscreen mode Exit fullscreen mode

Also, you might want to use the Hardhat node to test our smart contracts, so inside your project folder, run the following command:

$ npm install --save-dev hardhat
Enter fullscreen mode Exit fullscreen mode

ApeWorx

If you are going to use ApeWorx in this challenge, activate your virtual environment and install ApeWorx:

$ pip install eth-ape'[recommended-plugins]'
Enter fullscreen mode Exit fullscreen mode

After you installed it, create a new folder called vaults and inside it run the following command:

$ ape init
Enter fullscreen mode Exit fullscreen mode

πŸ“‘ Code

The ERC-20 token standard serves as the foundation for DeFi applications on EVM blockchains. Inside your contracts folder, create a file called token.vy this will contain all of the code necessary to implement the ERC-20.

Token (ERC-20)

Here is a barebones implementation of the ERC20 token standard in Vyper, can you turn it into a working smart contract?

Important: ⚠️🐍 If you are new to Vyper, don't worry, it was designed to be simple and readable, making it easier for programmers with any level of experience to quickly grasp the language. If you need more guidance, there are many resources available online to help you get started, such as the Vyper documentation, tutorials, and community forums.

# @version >=0.3.3
from vyper.interfaces import ERC20
from vyper.interfaces import ERC20Detailed

### INTERFACES ###
implements: ERC20
implements: ERC20Detailed

### EVENTS ###
event Transfer:
    sender: indexed(address)
    receiver: indexed(address)
    value: uint256

event Approval:
    owner: indexed(address)
    spender: indexed(address)
    value: uint256

### METHODS ###
@view
@external
def name() -> String[10]:
    # ... TODO: Implementation
    return NAME


@view
@external
def symbol() -> String[5]:
    # ... TODO: Implementation
    return SYMBOL


@view
@external
def decimals() -> uint8:
    # ... TODO: Implementation
    return DECIMALS


@external
def transfer(_to : address, _value : uint256) -> bool:
    # ... TODO: Implementation 
    return False


@external
def transferFrom(_from : address, _to : address, _value : uint256) -> bool:
    # ... TODO: Implementation 
    return False


@external
def approve(_spender : address, _value : uint256) -> bool:
    # ... TODO: Implementation
    return False


@external
def mint(_to: address, _value: uint256):
    # ... TODO: Implementation
    # ... TODO: Security
    pass


@external
def burn(_value: uint256):
    # ... TODO: Implementation
    # ... TODO: Security
    pass


@external
def burnFrom(_to: address, _value: uint256):
    # ... TODO: Implementation
    # ... TODO: Security
    pass

Enter fullscreen mode Exit fullscreen mode

Feel stuck? Take a look at the Vyperlang Official Implemenation

Here is a barebones implementation of the ERC4626 token standard in Vyper, can you turn it into a working smart contract?

Note: πŸ’‘ There are many ways to generate yield. Take a look at this one, implemented in Solidity

# @version >=0.3.3
from vyper.interfaces import ERC20
from vyper.interfaces import ERC4626

### INTERFACES ####
implements: ERC20
implements: ERC4626

#### ERC20 | EVENTS ####

event Transfer:
    sender: indexed(address)
    receiver: indexed(address)
    amount: uint256

event Approval:
    owner: indexed(address)
    spender: indexed(address)
    allowance: uint256

#### ERC4626 | EVENTS ####

event Deposit:
    depositor: indexed(address)
    receiver: indexed(address)
    assets: uint256
    shares: uint256

event Withdraw:
    withdrawer: indexed(address)
    receiver: indexed(address)
    owner: indexed(address)
    assets: uint256
    shares: uint256


### METHODS ###
@view
@external
def name() -> String[10]:
    # ... TODO: Implementation
    return NAME


@view
@external
def symbol() -> String[5]:
    # ... TODO: Implementation
    return SYMBOL


@view
@external
def decimals() -> uint8:
    # ... TODO: Implementation
    return DECIMALS


@external
def transfer(receiver: address, amount: uint256) -> bool:
    # ... TODO: Implementation
    return True


@external
def approve(spender: address, amount: uint256) -> bool:
    # ... TODO: Implementation
    return True


@external
def transferFrom(sender: address, receiver: address, amount: uint256) -> bool:
    # ... TODO: Implementation
    return True


@view
@external
def totalAssets() -> uint256:
    # ... TODO: Implementation
    return 0


@view
@external
def convertToAssets(shareAmount: uint256) -> uint256:
    # ... TODO: Implementation
    return 0


@view
@external
def convertToShares(assetAmount: uint256) -> uint256:
    # ... TODO: Implementation
    return 0


@view
@external
def maxDeposit(owner: address) -> uint256:
    # ... TODO: Implementation
    return 0


@view
@external
def previewDeposit(assets: uint256) -> uint256:
    # ... TODO: Implementation
    return 0


@external
def deposit(assets: uint256, receiver: address=msg.sender) -> uint256:
    # ... TODO: Implementation
    return 0


@view
@external
def maxMint(owner: address) -> uint256:
    # ... TODO: Implementation
    return 0


@view
@external
def previewMint(shares: uint256) -> uint256:
    # ... TODO: Implementation
    return 0


@external
def mint(shares: uint256, receiver: address=msg.sender) -> uint256:
    # ... TODO: Implementation
    return 0


@view
@external
def maxWithdraw(owner: address) -> uint256:
    # ... TODO: Implementation
    return 0

@view
@external
def previewWithdraw(assets: uint256) -> uint256:
    # ... TODO: Implementation
    return 0


@external
def withdraw(assets: uint256, receiver: address=msg.sender, owner: address=msg.sender) -> uint256:
    # ... TODO: Implementation
    return 0


@view
@external
def maxRedeem(owner: address) -> uint256:
    # ... TODO: Implementation
    return 0


@view
@external
def previewRedeem(shares: uint256) -> uint256:
    # ... TODO: Implementation
    return 0


@external
def redeem(shares: uint256, receiver: address=msg.sender, owner: address=msg.sender) -> uint256:
    # ... TODO: Implementation
    return 0

Enter fullscreen mode Exit fullscreen mode

Feel stuck? Take a look at the Vyperlang Official Implemenation

πŸ”¬ Conclusion

In this challenge, we have explored the ERC20 token standard and its role as a fundamental building block of DeFi applications on EVM-compatible blockchains. We have learned how to use the Vyper programming language to create a basic implementation of the ERC20 standard, including the definition of token properties, the specification of events, and the implementation of essential token transfer methods.

Going beyond this, we have also introduced the ERC4626 standard, which is specifically designed for yield-generating vaults. By providing a consistent and interoperable framework for the development of these critical DeFi components, ERC4626 offers a significant opportunity for developers and users alike to benefit from new features and functionality in the DeFi ecosystem.

πŸ“’ Note: Whether using Brownie or ApeWorx, creating a virtual environment for the project ensures that the application's dependencies and requirements are isolated from those of the host system, improving stability and reproducibility.

🐍 Note: The Vyper programming language offers several advantages over other languages, including higher security, improved gas efficiency, and enhanced code readability, making it a great option for NFT development projects.

Top comments (0)