Skip to content

Instantly share code, notes, and snippets.

@thurendous
Last active January 8, 2025 04:56
Show Gist options
  • Save thurendous/dad3997b26c5c2b7a0adfa4f47f8596c to your computer and use it in GitHub Desktop.
Save thurendous/dad3997b26c5c2b7a0adfa4f47f8596c to your computer and use it in GitHub Desktop.
This contract is for creating a sample funding contract written in Vyper.
# 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()
# 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