Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ERC1155 contract standard #2605

Closed
wants to merge 2 commits into from
Closed

Conversation

sonnhfit
Copy link

@sonnhfit sonnhfit commented Jan 17, 2022

What I did

I added standard token 1155 updated version 0.3.1

How I did it

update from here

How to verify it

deploy it

Description for the changelog

add an example for token standard erc1155

Cute Animal Picture

@codecov-commenter
Copy link

codecov-commenter commented Jan 17, 2022

Codecov Report

Merging #2605 (2311d14) into master (2735f02) will decrease coverage by 0.03%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2605      +/-   ##
==========================================
- Coverage   86.62%   86.59%   -0.04%     
==========================================
  Files          91       91              
  Lines        9438     9438              
  Branches     2362     2362              
==========================================
- Hits         8176     8173       -3     
- Misses        775      777       +2     
- Partials      487      488       +1     
Impacted Files Coverage Δ
vyper/builtin_functions/functions.py 88.26% <0.00%> (-0.34%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2735f02...2311d14. Read the comment docs.

@fubuloubu
Copy link
Member

@sonnhfit now that DynArray is in the master branch, could you update Soren's example to use DynArray so that we can have full compatibility with ERC-1155?

@sonnhfit
Copy link
Author

@fubuloubu thank u. In the gaming sector. There it has great application since such games have fungible elements (like life/energy), but also non-fungible elements like weapons and other collectables that all differ from one another.
Can you guide me to complete this pull request?

@fubuloubu
Copy link
Member

@fubuloubu thank u. In the gaming sector. There it has great application since such games have fungible elements (like life/energy), but also non-fungible elements like weapons and other collectables that all differ from one another. Can you guide me to complete this pull request?

Sure! Will add some comments.

Copy link
Member

@fubuloubu fubuloubu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try these updates to use the new DynArray type

examples/tokens/ERC1155.vy Outdated Show resolved Hide resolved
examples/tokens/ERC1155.vy Outdated Show resolved Hide resolved
examples/tokens/ERC1155.vy Outdated Show resolved Hide resolved
examples/tokens/ERC1155.vy Outdated Show resolved Hide resolved
assert _to != ZERO_ADDRESS
#assert len(_ids) == len(_values)

for i in range(BATCH_SIZE):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for i in range(BATCH_SIZE):
for i in range(min(len(_ids), BATCH_SIZE)):

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this is because Vyper does not allow unbounded loops, but will allow min(var, const) expressions as it has a defined upper bound

Copy link
Author

@sonnhfit sonnhfit Jan 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this is because Vyper does not allow unbounded loops, but will allow min(var, const) expressions as it has a defined upper bound

oh so I think this for loop is limited by BATCH_SIZE. I also saw your comment here #1047 . could you help me merge pull requests. or give me some suggestions. thank bro @fubuloubu

Comment on lines 195 to 196
_owner: address[BATCH_SIZE],
_ids: uint256[BATCH_SIZE]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_owner: address[BATCH_SIZE],
_ids: uint256[BATCH_SIZE]
_owner: DynArray[address, BATCH_SIZE],
_ids: DynArray[uint256, BATCH_SIZE]

_ids: uint256[BATCH_SIZE]
) -> uint256[BATCH_SIZE]:
returnValues: uint256[BATCH_SIZE] = empty(uint256[BATCH_SIZE])
for i in range(BATCH_SIZE):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for i in range(BATCH_SIZE):
for i in range(min(len(_owners), BATCH_SIZE)):

_owner: address[BATCH_SIZE],
_ids: uint256[BATCH_SIZE]
) -> uint256[BATCH_SIZE]:
returnValues: uint256[BATCH_SIZE] = empty(uint256[BATCH_SIZE])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
returnValues: uint256[BATCH_SIZE] = empty(uint256[BATCH_SIZE])
assert len(_owners) == len(_ids)
returnValues: DynArray[uint256, BATCH_SIZE] = empty(DynArray[uint256, BATCH_SIZE])

@external
def mintBatch(
_to: address,
_supplys: uint256[BATCH_SIZE],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_supplys: uint256[BATCH_SIZE],
_supplys: DynArray[uint256, BATCH_SIZE],

_data: Bytes[256]
) -> uint256[BATCH_SIZE]:
assert _to != ZERO_ADDRESS
ids: uint256[BATCH_SIZE] = empty(uint256[BATCH_SIZE])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ids: uint256[BATCH_SIZE] = empty(uint256[BATCH_SIZE])
ids: DynArray[uint256, BATCH_SIZE] = empty(DynArray[uint256, BATCH_SIZE])

@sonnhfit
Copy link
Author

hi @fubuloubu thank u. I saw your mention at #1440 but I have some unknown issue with DynArray

No builtin or user-defined type named 'DynArray'
  contract "ERC1155.vy", function "onERC1155BatchReceived", line 20:14 
       19         _from: address,
  ---> 20         _ids: DynArray[uint256, BATCH_SIZE],
  ----------------------^
       21         _values: DynArray[uint256, BATCH_SIZE],

this is my vyper version, clone from the master. am I missing something like import right? or something like a version issue?

>>> from vyper.version import version as __version__
>>> __version__
'0.3.2.dev33+g2735f024'

@Doc-Pixel
Copy link
Contributor

hi @fubuloubu thank u. I saw your mention at #1440 but I have some unknown issue with DynArray

No builtin or user-defined type named 'DynArray'
  contract "ERC1155.vy", function "onERC1155BatchReceived", line 20:14 
       19         _from: address,
  ---> 20         _ids: DynArray[uint256, BATCH_SIZE],
  ----------------------^
       21         _values: DynArray[uint256, BATCH_SIZE],

this is my vyper version, clone from the master. am I missing something like import right? or something like a version issue?

>>> from vyper.version import version as __version__
>>> __version__
'0.3.2.dev33+g2735f024'

I had a similar issue. I ended up uninstalling Vyper through pip or maybe even deleting the packages from the directory.
After that I cloned the vyper repo and did a python setup.py to install the 0.3.2.

Seem you have the right version installed already. Maybe stating the obvious, do you use a virtualenv? I've had my share of challenges with multiple python versions and virtualenvs in the past ;-)

On Linux you can do 'which vyper' and it shows you were the vyper command is. On Linux it's a small python script, you might want to check what is in there. Maybe it points to a different python version, which has an older Vyper installed.

@fubuloubu
Copy link
Member

hi @fubuloubu thank u. I saw your mention at #1440 but I have some unknown issue with DynArray

No builtin or user-defined type named 'DynArray'
  contract "ERC1155.vy", function "onERC1155BatchReceived", line 20:14 
       19         _from: address,
  ---> 20         _ids: DynArray[uint256, BATCH_SIZE],
  ----------------------^
       21         _values: DynArray[uint256, BATCH_SIZE],

this is my vyper version, clone from the master. am I missing something like import right? or something like a version issue?

>>> from vyper.version import version as __version__
>>> __version__
'0.3.2.dev33+g2735f024'

@charles-cooper DynArray might not be working in interfaces?

@Doc-Pixel
Copy link
Contributor

Doc-Pixel commented Jan 18, 2022

@sonnhfit @fubuloubu @charles-cooper

This compiles for me when I define an interface

 interface IERC1155Receiver:
    def onERC1155Received(operator: address, fromAddress: address, to: address, id: uint256, _value: uint256, data: bytes32) -> Bytes[4]: payable
    def onERC1155BatchReceived(operator: address, fromAddress: address, to: address, _ids: DynArray[uint256, MAX_MINT], _amounts: DynArray[uint256, MAX_MINT], data: bytes32) -> Bytes[4]: payable`

[edit] so I think there's something sideways in your path maybe, see post above?

@Doc-Pixel
Copy link
Contributor

The vyper command has been hardcoded to use /usr/bin/python3

check with which python3 to figure out which python executable you're using. It might be that your user profile points to a different python3 installation.
set |grep python or env | grep python will show you any environment variables that are set and mention 'python'

image

@fubuloubu
Copy link
Member

The vyper command has been hardcoded to use /usr/bin/python3

check with which python3 to figure out which python executable you're using. It might be that your user profile points to a different python3 installation. set |grep python or env | grep python will show you any environment variables that are set and mention 'python'

image

Yes, this should be changed to #!/usr/bin/env python for sure

@Doc-Pixel
Copy link
Contributor

Yes, this should be changed to #!/usr/bin/env python for sure

Shall I create an issue for this?

@fubuloubu
Copy link
Member

Yes, this should be changed to #!/usr/bin/env python for sure

Shall I create an issue for this?

Yes please! or just PR, it's not really a big change to fix

@Doc-Pixel
Copy link
Contributor

Yes, this should be changed to #!/usr/bin/env python for sure

Shall I create an issue for this?

Yes please! or just PR, it's not really a big change to fix

Not sure where I can find that in the code, where the vyper file gets created and placed in that specific location, any leads? I'll PR it :)

@fubuloubu
Copy link
Member

Yes, this should be changed to #!/usr/bin/env python for sure

Shall I create an issue for this?

Yes please! or just PR, it's not really a big change to fix

Not sure where I can find that in the code, where the vyper file gets created and placed in that specific location, any leads? I'll PR it :)

Might be here https://github.com/vyperlang/vyper/blob/master/vyper/__main__.py

Try it locally

@sonnhfit
Copy link
Author

exactly env error because my machine has 2 env. thank @DataBeast-IT

@fubuloubu
Copy link
Member

This is looking pretty good! I would suggest adding a testing file to the examples tests showing the functionality of the token. Use the ERC as a guide for what should and shouldn't work!

@sonnhfit
Copy link
Author

This is looking pretty good! I would suggest adding a testing file to the examples tests showing the functionality of the token. Use the ERC as a guide for what should and shouldn't work!

thank bro I will add some testing file

@sonnhfit
Copy link
Author

hi @fubuloubu I have a question. when I write a test. I identified a generic error something like a transaction not sent. something like:

E  eth_tester.exceptions.TransactionFailed: execution reverted: b''

../venv/lib/python3.9/site-packages/web3/providers/eth_tester/main.py:109: TransactionFailed
......
1 failed, 1 passed, 9 warnings in 7.76s

I have identified the exact code that caused the error.

    returnValues: DynArray[uint256, BATCH_SIZE] = empty(DynArray[uint256, BATCH_SIZE])

    for i in range(BATCH_SIZE):
        returnValues[i] = self._balanceOf[_owners[i]][_ids[i]]

during the investigation of the cause. I really want to see the values of the variables.
my question is: How to print to console the value of variable returnValues? Or similar method like print() in python, console.log in javascript

@fubuloubu
Copy link
Member

during the investigation of the cause. I really want to see the values of the variables. my question is: How to print to console the value of variable returnValues? Or similar method like print() in python, console.log in javascript

Welcome to the joys of smart contract programming! There is no method to print to the console like this. We are looking to migrate to a framework that would allow you to print the transaction trace (which calls were made during your transaction), which would help isolate it a little, but in general it's still not full debug capabilities.

Best bet is to trace through the code manually and use comments to disable certain lines you think mgiht be problematic as you go.

@fubuloubu
Copy link
Member

fubuloubu commented Jan 22, 2022

I have identified the exact code that caused the error.

    returnValues: DynArray[uint256, BATCH_SIZE] = empty(DynArray[uint256, BATCH_SIZE])

    for i in range(BATCH_SIZE):
        returnValues[i] = self._balanceOf[_owners[i]][_ids[i]]

Also, this one is a little easier to debug at first glance. Seems like you are allowing the array index i to go "out of bounds" of the array, since the len(_owners) <= BATCH_SIZE. What you should do is add an if statement preventing that from happening:

    returnValues: DynArray[uint256, BATCH_SIZE] = empty(DynArray[uint256, BATCH_SIZE])

    for i in range(BATCH_SIZE):
        if i >= len(_owners):  # prevents "out of bounds" access via `i`
            break
        returnValues[i] = self._balanceOf[_owners[i]][_ids[i]]

You'd need to do this for iterating via range(BATCH_SIZE) because you want to mutually iterate over both _owners and _ids via i, at least until support is added for enumrate and zip where you could simply do this:

    returnValues: DynArray[uint256, BATCH_SIZE] = empty(DynArray[uint256, BATCH_SIZE])

    for i, (owner, id) in enumerate(zip(_owners, _ids):
        returnValues[i] = self._balanceOf[owner][id]

@charles-cooper
Copy link
Member

charles-cooper commented Jan 22, 2022

I have identified the exact code that caused the error.

    returnValues: DynArray[uint256, BATCH_SIZE] = empty(DynArray[uint256, BATCH_SIZE])

    for i in range(BATCH_SIZE):
        returnValues[i] = self._balanceOf[_owners[i]][_ids[i]]

The issue here is that returnValues is initialized with a length of 0, any assignments of the form returnValues[i] = ... will fail because it hasn't been resized (OOB). It will probably have to wait for #2611 to be implemented before this is doable - after #2611 is implemented the code would look like

returnValues: DynArray[uint256, BATCH_SIZE] = empty(DynArray[uint256, BATCH_SIZE])
for i in range(BATCH_SIZE):
    if i > len(_owners):
        break
    returnValues.append(self._balanceOf[_owners[i]][_ids[i]])

@sonnhfit
Copy link
Author

@charles-cooper @fubuloubu many thanks. Your information is very helpful. I will write tests for some other functions.

@charles-cooper
Copy link
Member

@sonnhfit @fubuloubu what's the status of this PR?

@fubuloubu
Copy link
Member

@sonnhfit @fubuloubu what's the status of this PR?

Some fixes needed, however some of the newer features in the master branch might help streamline those fixes.

@charles-cooper
Copy link
Member

i think this is superseded by #2807

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants