Skip to content

Commit

Permalink
Merge branch 'master' of github.com:vyperlang/vyper into 3768/range_b…
Browse files Browse the repository at this point in the history
…ound
  • Loading branch information
DanielSchiavini committed Feb 27, 2024
2 parents f8412ee + 3798cb6 commit dd9d132
Show file tree
Hide file tree
Showing 23 changed files with 933 additions and 628 deletions.
7 changes: 4 additions & 3 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@ Because of this Vyper provides the following features:
* **Support for signed integers and decimal fixed point numbers**
* **Decidability**: It is possible to compute a precise upper bound for the gas consumption of any Vyper function call.
* **Strong typing**
* **Small and understandable compiler code**
* **Limited support for pure functions**: Anything marked constant is not allowed to change the state.
* **Clean and understandable compiler code**
* **Support for pure functions**: Anything marked ``pure`` is not allowed to change the state.
* **Code reuse through composition**: Vyper supports code reuse through composition, and to help auditors, requires syntactic marking of dependencies which potentially modify state.

Following the principles and goals, Vyper **does not** provide the following features:

* **Modifiers**: For example in Solidity you can define a ``function foo() mod1 { ... }``, where ``mod1`` can be defined elsewhere in the code to include a check that is done before execution, a check that is done after execution, some state changes, or possibly other things. Vyper does not have this, because it makes it too easy to write misleading code. ``mod1`` just looks too innocuous for something that could add arbitrary pre-conditions, post-conditions or state changes. Also, it encourages people to write code where the execution jumps around the file, harming auditability. The usual use case for a modifier is something that performs a single check before execution of a program; our recommendation is to simply inline these checks as asserts.
* **Class inheritance**: Class inheritance requires people to jump between multiple files to understand what a program is doing, and requires people to understand the rules of precedence in case of conflicts ("Which class's function ``X`` is the one that's actually used?"). Hence, it makes code too complicated to understand which negatively impacts auditability.
* **Class inheritance**: Class inheritance requires readers to jump between multiple files to understand what a program is doing, and requires readers to understand the rules of precedence in case of conflicts ("Which class's function ``X`` is the one that's actually used?").
* **Inline assembly**: Adding inline assembly would make it no longer possible to search for a variable name in order to find all instances where that variable is read or modified.
* **Function overloading**: This can cause lots of confusion on which function is called at any given time. Thus it's easier to write misleading code (``foo("hello")`` logs "hello" but ``foo("hello", "world")`` steals your funds). Another problem with function overloading is that it makes the code much harder to search through as you have to keep track on which call refers to which function.
* **Operator overloading**: Operator overloading makes writing misleading code possible. For example ``+`` could be overloaded so that it executes commands that are not visible at a first glance, such as sending funds the user did not want to send.
Expand Down
8 changes: 8 additions & 0 deletions docs/release-notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ Release Notes
for advisory links:
:'<,'>s/\v(https:\/\/github.com\/vyperlang\/vyper\/security\/advisories\/)([-A-Za-z0-9]+)/(`\2 <\1\2>`_)/g
v0.4.0b1 ("Nagini")
*******************

Date released: TBD
==================

v0.4.0 represents a major overhaul to the Vyper language. Notably, it overhauls the import system and adds support for code reuse. It also adds a new, experimental backend to Vyper which lays the foundation for improved analysis, optimization and integration with third party tools.

v0.3.10 ("Black Adder")
***********************

Expand Down
22 changes: 6 additions & 16 deletions examples/tokens/ERC20.vy
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,6 @@ from ethereum.ercs import IERC20Detailed
implements: IERC20
implements: IERC20Detailed

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

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

name: public(String[32])
symbol: public(String[32])
decimals: public(uint8)
Expand All @@ -49,7 +39,7 @@ def __init__(_name: String[32], _symbol: String[32], _decimals: uint8, _supply:
self.balanceOf[msg.sender] = init_supply
self.totalSupply = init_supply
self.minter = msg.sender
log Transfer(empty(address), msg.sender, init_supply)
log IERC20.Transfer(empty(address), msg.sender, init_supply)



Expand All @@ -64,7 +54,7 @@ def transfer(_to : address, _value : uint256) -> bool:
# so the following subtraction would revert on insufficient balance
self.balanceOf[msg.sender] -= _value
self.balanceOf[_to] += _value
log Transfer(msg.sender, _to, _value)
log IERC20.Transfer(msg.sender, _to, _value)
return True


Expand All @@ -83,7 +73,7 @@ def transferFrom(_from : address, _to : address, _value : uint256) -> bool:
# NOTE: vyper does not allow underflows
# so the following subtraction would revert on insufficient allowance
self.allowance[_from][msg.sender] -= _value
log Transfer(_from, _to, _value)
log IERC20.Transfer(_from, _to, _value)
return True


Expand All @@ -99,7 +89,7 @@ def approve(_spender : address, _value : uint256) -> bool:
@param _value The amount of tokens to be spent.
"""
self.allowance[msg.sender][_spender] = _value
log Approval(msg.sender, _spender, _value)
log IERC20.Approval(msg.sender, _spender, _value)
return True


Expand All @@ -116,7 +106,7 @@ def mint(_to: address, _value: uint256):
assert _to != empty(address)
self.totalSupply += _value
self.balanceOf[_to] += _value
log Transfer(empty(address), _to, _value)
log IERC20.Transfer(empty(address), _to, _value)


@internal
Expand All @@ -130,7 +120,7 @@ def _burn(_to: address, _value: uint256):
assert _to != empty(address)
self.totalSupply -= _value
self.balanceOf[_to] -= _value
log Transfer(_to, empty(address), _value)
log IERC20.Transfer(_to, empty(address), _value)


@external
Expand Down
37 changes: 7 additions & 30 deletions examples/tokens/ERC4626.vy
Original file line number Diff line number Diff line change
Expand Up @@ -24,33 +24,10 @@ NAME: constant(String[10]) = "Test Vault"
SYMBOL: constant(String[5]) = "vTEST"
DECIMALS: constant(uint8) = 18

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

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

##### ERC4626 #####

asset: public(IERC20)

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


@deploy
def __init__(asset: IERC20):
Expand Down Expand Up @@ -79,14 +56,14 @@ def decimals() -> uint8:
def transfer(receiver: address, amount: uint256) -> bool:
self.balanceOf[msg.sender] -= amount
self.balanceOf[receiver] += amount
log Transfer(msg.sender, receiver, amount)
log IERC20.Transfer(msg.sender, receiver, amount)
return True


@external
def approve(spender: address, amount: uint256) -> bool:
self.allowance[msg.sender][spender] = amount
log Approval(msg.sender, spender, amount)
log IERC20.Approval(msg.sender, spender, amount)
return True


Expand All @@ -95,7 +72,7 @@ def transferFrom(sender: address, receiver: address, amount: uint256) -> bool:
self.allowance[sender][msg.sender] -= amount
self.balanceOf[sender] -= amount
self.balanceOf[receiver] += amount
log Transfer(sender, receiver, amount)
log IERC20.Transfer(sender, receiver, amount)
return True


Expand Down Expand Up @@ -160,7 +137,7 @@ def deposit(assets: uint256, receiver: address=msg.sender) -> uint256:

self.totalSupply += shares
self.balanceOf[receiver] += shares
log Deposit(msg.sender, receiver, assets, shares)
log IERC4626.Deposit(msg.sender, receiver, assets, shares)
return shares


Expand Down Expand Up @@ -193,7 +170,7 @@ def mint(shares: uint256, receiver: address=msg.sender) -> uint256:

self.totalSupply += shares
self.balanceOf[receiver] += shares
log Deposit(msg.sender, receiver, assets, shares)
log IERC4626.Deposit(msg.sender, receiver, assets, shares)
return assets


Expand Down Expand Up @@ -230,7 +207,7 @@ def withdraw(assets: uint256, receiver: address=msg.sender, owner: address=msg.s
self.balanceOf[owner] -= shares

self.asset.transfer(receiver, assets)
log Withdraw(msg.sender, receiver, owner, assets, shares)
log IERC4626.Withdraw(msg.sender, receiver, owner, assets, shares)
return shares


Expand All @@ -256,7 +233,7 @@ def redeem(shares: uint256, receiver: address=msg.sender, owner: address=msg.sen
self.balanceOf[owner] -= shares

self.asset.transfer(receiver, assets)
log Withdraw(msg.sender, receiver, owner, assets, shares)
log IERC4626.Withdraw(msg.sender, receiver, owner, assets, shares)
return assets


Expand Down
45 changes: 5 additions & 40 deletions examples/tokens/ERC721.vy
Original file line number Diff line number Diff line change
Expand Up @@ -24,41 +24,6 @@ interface ERC721Receiver:
) -> bytes4: nonpayable


# @dev Emits when ownership of any NFT changes by any mechanism. This event emits when NFTs are
# created (`from` == 0) and destroyed (`to` == 0). Exception: during contract creation, any
# number of NFTs may be created and assigned without emitting Transfer. At the time of any
# transfer, the approved address for that NFT (if any) is reset to none.
# @param _from Sender of NFT (if address is zero address it indicates token creation).
# @param _to Receiver of NFT (if address is zero address it indicates token destruction).
# @param _tokenId The NFT that got transferred.
event Transfer:
sender: indexed(address)
receiver: indexed(address)
tokenId: indexed(uint256)

# @dev This emits when the approved address for an NFT is changed or reaffirmed. The zero
# address indicates there is no approved address. When a Transfer event emits, this also
# indicates that the approved address for that NFT (if any) is reset to none.
# @param _owner Owner of NFT.
# @param _approved Address that we are approving.
# @param _tokenId NFT which we are approving.
event Approval:
owner: indexed(address)
approved: indexed(address)
tokenId: indexed(uint256)

# @dev This emits when an operator is enabled or disabled for an owner. The operator can manage
# all NFTs of the owner.
# @param _owner Owner of NFT.
# @param _operator Address to which we are setting operator rights.
# @param _approved Status of operator rights(true if operator rights are given and false if
# revoked).
event ApprovalForAll:
owner: indexed(address)
operator: indexed(address)
approved: bool


# @dev Mapping from NFT ID to the address that owns it.
idToOwner: HashMap[uint256, address]

Expand Down Expand Up @@ -236,7 +201,7 @@ def _transferFrom(_from: address, _to: address, _tokenId: uint256, _sender: addr
# Add NFT
self._addTokenTo(_to, _tokenId)
# Log the transfer
log Transfer(_from, _to, _tokenId)
log IERC721.Transfer(_from, _to, _tokenId)


### TRANSFER FUNCTIONS ###
Expand Down Expand Up @@ -310,7 +275,7 @@ def approve(_approved: address, _tokenId: uint256):
assert (senderIsOwner or senderIsApprovedForAll)
# Set the approval
self.idToApprovals[_tokenId] = _approved
log Approval(owner, _approved, _tokenId)
log IERC721.Approval(owner, _approved, _tokenId)


@external
Expand All @@ -326,7 +291,7 @@ def setApprovalForAll(_operator: address, _approved: bool):
# Throws if `_operator` is the `msg.sender`
assert _operator != msg.sender
self.ownerToOperators[msg.sender][_operator] = _approved
log ApprovalForAll(msg.sender, _operator, _approved)
log IERC721.ApprovalForAll(msg.sender, _operator, _approved)


### MINT & BURN FUNCTIONS ###
Expand All @@ -348,7 +313,7 @@ def mint(_to: address, _tokenId: uint256) -> bool:
assert _to != empty(address)
# Add NFT. Throws if `_tokenId` is owned by someone
self._addTokenTo(_to, _tokenId)
log Transfer(empty(address), _to, _tokenId)
log IERC721.Transfer(empty(address), _to, _tokenId)
return True


Expand All @@ -368,7 +333,7 @@ def burn(_tokenId: uint256):
assert owner != empty(address)
self._clearApproval(owner, _tokenId)
self._removeTokenFrom(owner, _tokenId)
log Transfer(owner, empty(address), _tokenId)
log IERC721.Transfer(owner, empty(address), _tokenId)


@view
Expand Down
Loading

0 comments on commit dd9d132

Please sign in to comment.