Last active
January 8, 2025 04:56
-
-
Save thurendous/dad3997b26c5c2b7a0adfa4f47f8596c to your computer and use it in GitHub Desktop.
This contract is for creating a sample funding contract written in Vyper.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# pragma version 0.4.0 | |
""" | |
@license MIT | |
@title Buy Me A Coffee! | |
@author Me | |
@notice This contract is for creating a sample funding contract | |
""" | |
# sepolia testnet chainlink eth / usd: 0x694AA1769357215DE4FAC081bf1f309aDC325306 | |
# We'll learn a new way to do this later... | |
interface AggregatorV3Interface: | |
def decimals() -> uint8: view | |
def description() -> String[1000]: view | |
def version() -> uint256: view | |
def latestAnswer() -> int256: view | |
# Constants & Immutables | |
MINIMUM_USD: public(constant(uint256)) = as_wei_value(5, "ether") | |
PRICE_FEED: public(immutable(AggregatorV3Interface)) | |
OWNER: public(immutable(address)) | |
PRICISION: constant(uint256) = 1 * (10 ** 18) | |
# Storage | |
funders: public(DynArray[address, 1000]) | |
funders_to_amount_funded: public(HashMap[address, uint256]) | |
# With constants: 262, 853 | |
@deploy | |
def __init__(price_feed: address): | |
PRICE_FEED = AggregatorV3Interface(price_feed) | |
OWNER = msg.sender | |
@external | |
@payable | |
def fund(): | |
self._fund() | |
@internal | |
@payable | |
def _fund(): | |
"""Allows users to send $ to this contract | |
Have a minimum & amount to send | |
How do we convert the ETH amount to dollars amount? | |
""" | |
usd_value_of_eth: uint256 = self._get_eth_to_usd_rate(msg.value) | |
assert usd_value_of_eth >= MINIMUM_USD, "You must spend more ETH than 5 dollar" | |
self.funders.append(msg.sender) | |
self.funders_to_amount_funded[msg.sender] += msg.value | |
@external | |
def withdraw(): | |
""" | |
Take the money out of the contract, that people sent via the fund function. | |
How do we make sure only we can pull the money out? | |
""" | |
assert msg.sender == OWNER, "Not the owner of the contract! " | |
raw_call(OWNER, b"", value = self.balance) | |
# send(OWNER, self.balance) | |
# resetting | |
for funder: address in self.funders: | |
self.funders_to_amount_funded[funder] = 0 | |
self.funders = [] | |
@internal | |
@view | |
def _get_eth_to_usd_rate(eth_amount: uint256) -> uint256: | |
""" | |
Chris sent us 0.01 ETH for us to buy a coffee | |
Is that more or less than $5? | |
""" | |
price: int256 = staticcall PRICE_FEED.latestAnswer() | |
eth_price: uint256 = (convert(price, uint256)) * (10 ** 10) | |
eth_amount_in_usd: uint256 = (eth_price * eth_amount) // PRICISION | |
return eth_amount_in_usd | |
@external | |
@view | |
def get_eth_to_usd_rate(eth_amount: uint256) -> uint256: | |
return self._get_eth_to_usd_rate(eth_amount) | |
@external | |
@payable | |
def __default__(): | |
self._fund() | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# SPDX-License-Identifier: MIT | |
# pragma 和版本说明 | |
# Vyper版本必须指定,不能有浮动范围 | |
# 这是因为Vyper的安全性和语法更新比较频繁 | |
@version ^0.4.0 | |
# 状态变量的声明 | |
# 状态变量会永久存储在以太坊区块链上 | |
owner: public(address) | |
balance: public(uint256) | |
is_active: public(bool) | |
user_data: public(map(address, uint256)) | |
# 事件定义 | |
# 事件用于在区块链上记录信息,以便前端或外部观察器监听 | |
# 这里定义了一个转账事件 | |
Transfer: event({recipient: address, amount: uint256}) | |
# 构造函数 | |
# @external 和 @payable 关键字的使用 | |
# @external 表示这个函数可以从合约外部调用 | |
# @payable 表示这个函数可以接收以太币 | |
@external | |
@payable | |
def __init__(): | |
# msg.sender 表示调用该合约的地址 | |
self.owner = msg.sender | |
self.balance = msg.value | |
self.is_active = True | |
# 修改器的实现 (Vyper中没有modifier,使用内联的require实现) | |
# 这里用一个内联require来检查只有owner才能调用 | |
@external | |
def set_active(active: bool): | |
assert msg.sender == self.owner, "Only owner can change status" | |
self.is_active = active | |
# 发送以太币 | |
# @payable 标识允许接收以太币 | |
# emit 用于触发事件 | |
@external | |
@payable | |
def deposit(): | |
self.balance += msg.value | |
log Transfer(msg.sender, msg.value) | |
# 提款功能 | |
# 处理ETH转账以及安全性检查 | |
@external | |
def withdraw(amount: uint256): | |
assert msg.sender == self.owner, "Only owner can withdraw" | |
assert amount <= self.balance, "Insufficient balance" | |
self.balance -= amount | |
send(msg.sender, amount) | |
# 更新用户数据 (映射操作) | |
@external | |
def update_user_data(user: address, data: uint256): | |
self.user_data[user] = data | |
# 读取用户数据 | |
# view修饰符表示这个函数不会修改区块链上的数据 | |
@external | |
@view | |
def get_user_data(user: address) -> uint256: | |
return self.user_data[user] | |
# 删除合约的函数已在 Vyper 0.4.0 中移除,因此不再使用 selfdestruct | |
# 主要的Vyper语言特性: | |
# 1. 状态变量: `owner`, `balance`, `is_active`, `user_data` | |
# 2. 数据类型: `address`, `uint256`, `bool`, `map` | |
# 3. 事件: `Transfer` | |
# 4. 修饰符 (通过assert实现) | |
# 5. 构造函数: `__init__` | |
# 6. 以太币传输: `send`, `msg.value` | |
# 7. 可见性修饰符: `@public`, `@external`, `@view`, `@payable` | |
# 8. 映射: `map` | |
# 9. 断言: `assert` | |
# 10. 删除了 selfdestruct |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment