Vyper logo

yper

示例Vyper 中文文档

链上做市商

基于恒定乘积公式的自动做市商,实现 ETH 与代币的去中心化兑换。

链上做市商合约:基于恒定乘积公式的自动做市商(AMM),实现 ETH 与代币之间的去中心化兑换。

学习用途

本示例仅用于学习目的。请勿在未经充分审查和测试的情况下用于生产环境。

概览

这个合约实现了最基础的 AMM:

  • 使用恒定乘积公式 x * y = k
  • 支持 ETH 换代币和代币换 ETH
  • 收取 0.2% 手续费
  • 所有者可提取流动性并关闭交易

完整合约代码

vyper

#pragma version >0.3.10

from ethereum.ercs import IERC20

totalEthQty: public(uint256)
totalTokenQty: public(uint256)
invariant: public(uint256)
token: IERC20
owner: public(address)
finalized: bool

@external
@payable
def initiate(token_addr: address, token_quantity: uint256):
    assert self.invariant == 0
    self.token = IERC20(token_addr)
    extcall self.token.transferFrom(msg.sender, self, token_quantity)
    self.owner = msg.sender
    self.totalEthQty = msg.value
    self.totalTokenQty = token_quantity
    self.invariant = msg.value * token_quantity
    assert self.invariant > 0

@external
@payable
def ethToTokens():
    assert not self.finalized
    fee: uint256 = msg.value // 500
    eth_in_purchase: uint256 = msg.value - fee
    new_total_eth: uint256 = self.totalEthQty + eth_in_purchase
    new_total_tokens: uint256 = self.invariant // new_total_eth
    extcall self.token.transfer(msg.sender, self.totalTokenQty - new_total_tokens)
    self.totalEthQty = new_total_eth
    self.totalTokenQty = new_total_tokens

@external
def tokensToEth(sell_quantity: uint256):
    assert not self.finalized
    extcall self.token.transferFrom(msg.sender, self, sell_quantity)
    new_total_tokens: uint256 = self.totalTokenQty + sell_quantity
    new_total_eth: uint256 = self.invariant // new_total_tokens
    eth_to_send: uint256 = self.totalEthQty - new_total_eth
    send(msg.sender, eth_to_send)
    self.totalEthQty = new_total_eth
    self.totalTokenQty = new_total_tokens

@external
def ownerWithdraw():
    assert self.owner == msg.sender
    self.finalized = True
    extcall self.token.transfer(self.owner, self.totalTokenQty)
    if self.balance > 0:
        send(self.owner, self.balance)

代码解析

恒定乘积公式

initiate 设置初始的 ETH 和代币数量,计算不变量 k = ethQty * tokenQty。后续每次交易都维持这个不变量。

兑换机制

ethToTokens:用户发送 ETH,合约根据新的 ETH 总量反算代币总量,差额即为用户获得的代币数。手续费通过在计算前扣除 0.2% 的 ETH 实现。

tokensToEth:反向操作。使用 extcall 从用户处转入代币,计算应发送的 ETH 数量。

注意 extcall 的使用

这个合约展示了 Vyper 0.4.0+ 要求的 extcall 关键字——所有修改外部状态的调用都必须显式标记。