Skip to content

Instantly share code, notes, and snippets.

@tserg
Last active September 11, 2023 03:17
Show Gist options
  • Save tserg/5e183209ecd2a001097df562652088ed to your computer and use it in GitHub Desktop.
Save tserg/5e183209ecd2a001097df562652088ed to your computer and use it in GitHub Desktop.
Library sketch
# Sketch of ERC-20 contract that imports ERC20
from vyper.interfaces import IERC20
from snekmate.tokens import ERC20
implements: IERC20
@external
def __init__(
name_: String[25],
symbol_: String[5],
initial_supply_: uint256
):
ERC20.initializer(name_, symbol_, initial_supply_)
@external
def transfer(to: address, amount: uint256) -> bool:
return ERC20.transfer(to, amount)
@external
def transferFrom(owner: address, receiver: address, amount: uint256) -> bool:
return ERC20.transferFrom(owner, receiver, amount)
@external
def approve(owner: address, receiver: address, amount: uint256) -> bool:
return ERC20.approve(owner, receiver, amount)
@external
def mint(owner: address, amount: uint256):
ERC20.mint(owner, amount)
# Sketch of ERC-20 library
decimals: public(uint8)
name: public(String[25])
symbol: public(String[5])
balanceOf: public(HashMap[address, uint256])
allowance: public(HashMap[address, HashMap[address, uint256]])
totalSupply: public(uint256)
event Transfer:
owner: indexed(address)
to: indexed(address)
amount: uint256
event Approval:
owner: indexed(address)
spender: indexed(address)
amount: uint256
# This is meant to be called in the constructor of the contract importing this
# library, but can take on any name.
@internal
def initializer(name_: String[25], symbol_: String[5], initial_supply_: uint256):
initial_supply: uint256 = initial_supply_ * 10 ** convert(decimals, uint256)
name = name_
symbol = symbol_
if (initial_supply != empty(uint256)):
self._before_token_transfer(empty(address), msg.sender, initial_supply)
self.totalSupply = initial_supply
self.balanceOf[msg.sender] = initial_supply
log Transfer(empty(address), msg.sender, initial_supply)
self._after_token_transfer(empty(address), msg.sender, initial_supply)
@internal
def transfer(to: address, amount: uint256) -> bool:
self._transfer(msg.sender, to, amount)
return True
@internal
def transferFrom(owner: address, to: address, amount: uint256) -> bool:
self._spend_allowance(owner, msg.sender, amount)
self._transfer(owner, to, amount)
return True
@internal
def approve(spender: address, amount: uint256) -> bool:
self._approve(msg.sender, spender, amount)
return True
@internal
def mint(owner: address, amount: uint256):
self._mint(owner, amount)
@internal
def _transfer(owner: address, to: address, amount: uint256):
assert owner != empty(address), "ERC20: transfer from the zero address"
assert to != empty(address), "ERC20: transfer to the zero address"
owner_balanceOf: uint256 = self.balanceOf[owner]
assert owner_balanceOf >= amount, "ERC20: transfer amount exceeds balance"
self.balanceOf[owner] = unsafe_sub(owner_balanceOf, amount)
self.balanceOf[to] = unsafe_add(self.balanceOf[to], amount)
log Transfer(owner, to, amount)
@internal
def _spend_allowance(owner: address, spender: address, amount: uint256):
current_allowance: uint256 = self.allowance[owner][spender]
if (current_allowance != max_value(uint256)):
assert current_allowance >= amount, "ERC20: insufficient allowance"
self._approve(owner, spender, unsafe_sub(current_allowance, amount))
@internal
def _approve(owner: address, spender: address, amount: uint256):
assert owner != empty(address), "ERC20: approve from the zero address"
assert spender != empty(address), "ERC20: approve to the zero address"
self.allowance[owner][spender] = amount
log Approval(owner, spender, amount)
@internal
def _mint(owner: address, amount: uint256):
assert owner != empty(address), "ERC20: mint to the zero address"
self.totalSupply += amount
self.balanceOf[owner] = unsafe_add(self.balanceOf[owner], amount)
log Transfer(empty(address), owner, amount)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment