Skip to content

Commit

Permalink
refactor(contracts): upgrade to Vyper 0.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
fubuloubu committed Sep 10, 2024
1 parent a53f9fc commit 6860d41
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 33 deletions.
4 changes: 2 additions & 2 deletions contracts/StreamFactory.vy
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# @version 0.3.9
# pragma version 0.4.0

"""
@title StreamFactory
Expand All @@ -16,7 +16,7 @@ BLUEPRINT: public(immutable(address))
deployments: public(HashMap[address, address])


@external
@deploy
def __init__(blueprint: address):
BLUEPRINT = blueprint

Expand Down
50 changes: 24 additions & 26 deletions contracts/StreamManager.vy
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# @version 0.3.9
# pragma version 0.4.0

"""
@title StreamManager
Expand All @@ -18,7 +18,7 @@
defined goods or services.
"""

from vyper.interfaces import ERC20
from ethereum.ercs import IERC20

from . import Validator

Expand All @@ -32,7 +32,7 @@ MIN_STREAM_LIFE: public(immutable(uint256))


struct Stream:
token: ERC20
token: IERC20
amount_per_second: uint256
max_stream_life: uint256
funded_amount: uint256
Expand All @@ -45,11 +45,11 @@ streams: public(HashMap[address, HashMap[uint256, Stream]])


owner: public(address)
token_is_accepted: public(HashMap[ERC20, bool])
token_is_accepted: public(HashMap[IERC20, bool])


event StreamCreated:
token: indexed(ERC20)
token: indexed(IERC20)
creator: indexed(address)
stream_id: indexed(uint256)
amount_per_second: uint256
Expand Down Expand Up @@ -77,18 +77,18 @@ event Claimed:
claimed_amount: uint256


@external
@deploy
def __init__(
owner: address,
min_stream_life: uint256, # timedelta in seconds
validators: DynArray[Validator, MAX_VALIDATORS],
accepted_tokens: DynArray[ERC20, 20],
accepted_tokens: DynArray[IERC20, 20],
):
self.owner = owner
MIN_STREAM_LIFE = min_stream_life
self.validators = validators

for token in accepted_tokens:
for token: IERC20 in accepted_tokens:
self.token_is_accepted[token] = True


Expand All @@ -99,46 +99,46 @@ def set_validators(validators: DynArray[Validator, MAX_VALIDATORS]):


@external
def add_token(token: ERC20):
def add_token(token: IERC20):
assert msg.sender == self.owner
self.token_is_accepted[token] = True


@external
def remove_token(token: ERC20):
def remove_token(token: IERC20):
assert msg.sender == self.owner
self.token_is_accepted[token] = False


@external
def create_stream(
token: ERC20,
token: IERC20,
amount_per_second: uint256,
reason: Bytes[MAX_REASON_SIZE] = b"",
start_time: uint256 = block.timestamp,
) -> uint256:
assert self.token_is_accepted[token] # dev: token not accepted
assert start_time <= block.timestamp # dev: start time < block

funded_amount: uint256 = token.allowance(msg.sender, self)
funded_amount: uint256 = staticcall token.allowance(msg.sender, self)
if funded_amount == max_value(uint256):
funded_amount = token.balanceOf(msg.sender)
funded_amount = staticcall token.balanceOf(msg.sender)

max_stream_life: uint256 = max_value(uint256)
for validator in self.validators:
for validator: Validator in self.validators:
# NOTE: Validator either raises or returns a max stream life to use
max_stream_life = min(
max_stream_life,
validator.validate(msg.sender, token.address, amount_per_second, reason),
extcall validator.validate(msg.sender, token, amount_per_second, reason),
)

assert max_stream_life >= funded_amount / amount_per_second # dev: max stream life small
assert max_stream_life >= funded_amount // amount_per_second # dev: max stream life small

prefunded_stream_life: uint256 = max(MIN_STREAM_LIFE, block.timestamp - start_time)
assert max_stream_life >= prefunded_stream_life # dev: prefunded stream life large
assert funded_amount >= prefunded_stream_life * amount_per_second # dev: not enough funds

assert token.transferFrom(msg.sender, self, funded_amount, default_return_value=True) # dev: transfer fail
assert extcall token.transferFrom(msg.sender, self, funded_amount, default_return_value=True) # dev: transfer fail

stream_id: uint256 = self.num_streams[msg.sender]
self.streams[msg.sender][stream_id] = Stream({
Expand All @@ -158,7 +158,6 @@ def create_stream(


@view
@internal
def _amount_unlocked(creator: address, stream_id: uint256) -> uint256:
return min(
(
Expand All @@ -176,12 +175,11 @@ def amount_unlocked(creator: address, stream_id: uint256) -> uint256:


@view
@internal
def _time_left(creator: address, stream_id: uint256) -> uint256:
unlocked: uint256 = self._amount_unlocked(creator, stream_id)
return (
(self.streams[creator][stream_id].funded_amount - unlocked)
/ self.streams[creator][stream_id].amount_per_second
// self.streams[creator][stream_id].amount_per_second
)


Expand All @@ -193,8 +191,8 @@ def time_left(creator: address, stream_id: uint256) -> uint256:

@external
def add_funds(creator: address, stream_id: uint256, amount: uint256) -> uint256:
token: ERC20 = self.streams[creator][stream_id].token
assert token.transferFrom(msg.sender, self, amount, default_return_value=True)
token: IERC20 = self.streams[creator][stream_id].token
assert extcall token.transferFrom(msg.sender, self, amount, default_return_value=True)
self.streams[creator][stream_id].funded_amount += amount

time_left: uint256 = self._time_left(creator, stream_id)
Expand Down Expand Up @@ -231,8 +229,8 @@ def cancel_stream(
assert amount_locked > 0 # NOTE: reverts if stream doesn't exist, or already cancelled
self.streams[creator][stream_id].funded_amount = funded_amount - amount_locked

token: ERC20 = self.streams[creator][stream_id].token
assert token.transfer(creator, amount_locked, default_return_value=True)
token: IERC20 = self.streams[creator][stream_id].token
assert extcall token.transfer(creator, amount_locked, default_return_value=True)

log StreamCancelled(creator, stream_id, amount_locked, reason)

Expand All @@ -246,8 +244,8 @@ def claim(creator: address, stream_id: uint256) -> uint256:
self.streams[creator][stream_id].funded_amount = funded_amount - claim_amount
self.streams[creator][stream_id].last_pull = block.timestamp

token: ERC20 = self.streams[creator][stream_id].token
assert token.transfer(self.owner, claim_amount, default_return_value=True)
token: IERC20 = self.streams[creator][stream_id].token
assert extcall token.transfer(self.owner, claim_amount, default_return_value=True)

log Claimed(creator, stream_id, funded_amount == claim_amount, claim_amount)

Expand Down
7 changes: 4 additions & 3 deletions contracts/test/TestToken.vy
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# pragma version ^0.4
# TODO: Replace w/ Snekmate
totalSupply: public(uint256)
balanceOf: public(HashMap[address, uint256])
Expand All @@ -7,10 +8,10 @@ name: public(constant(String[10])) = "Test Token"
symbol: public(constant(String[4])) = "TEST"
decimals: public(constant(uint8)) = 18

@external
@deploy
def __init__():
self.totalSupply = 100 * 10 ** decimals
self.balanceOf[msg.sender] = 100 * 10 ** decimals
self.totalSupply = 100 * 10 ** convert(decimals, uint256)
self.balanceOf[msg.sender] = 100 * 10 ** convert(decimals, uint256)


@external
Expand Down
8 changes: 6 additions & 2 deletions contracts/test/TestValidator.vy
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
from vyper.interfaces import ERC20
# pragma version ^0.4
from ethereum.ercs import IERC20

from .. import Validator

MAX_REASON_SIZE: constant(uint16) = 1024

implements: Validator

@external
def validate(
creator: address,
token: ERC20,
token: IERC20,
amount_per_second: uint256,
reason: Bytes[MAX_REASON_SIZE],
) -> uint256:
Expand Down

0 comments on commit 6860d41

Please sign in to comment.