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

External Contract Calls / References #347

Closed
DavidKnott opened this issue Sep 11, 2017 · 5 comments
Closed

External Contract Calls / References #347

DavidKnott opened this issue Sep 11, 2017 · 5 comments

Comments

@DavidKnott
Copy link
Contributor

What's your issue about?

This issue is a continuation of #297 (Please see it for context) and #335 for the current implementation.

Cute Animal Picture

image

@fubuloubu
Copy link
Member

fubuloubu commented Sep 11, 2017

To summarize, our current suggestion is to implement contract references as a new type contract (extended from address, e.g. address of a contract) where the required methods are supplied for the type.

Some examples:
basic usage

item: contract {
    foo(bool) -> bool
}
def __init__(_item: contract):
    self.item = _item

def change_item(_item: contract):
    self.item = _item

lists/maps (this contract is deployed 1 per account and inter-contract communication happens)

friends: contract {
    receive_message(bytes <= 192)
}[num]
num_friends: num
messages: (bytes <= 192)[num]
num_messages: num

def add_friend(_friend: contract):
    self.friends[self.num_friends] = _friend
    self.num_friends += 1

def send_message(friend_num: num, message: bytes <= 192):
    self.friends[friend_num].receive_message(message)

def receive_message(_message: bytes <= 192):
    self.messages[self.num_messages] = _message
    self.num_messages += 1

Further suggestions are:

  1. Type checking a contract's required methods when assigned/re-assigned to avoid lock-outs of methods in contract calls due to purposely improper assignments.
  2. Ensuring a contract type is assigned on init to ensure all methods are available (similar to 1)
  3. Moving explicit contract type checking (writing at the top of a contract) to implicit, compiler-based scanning to reduce potential errors

@JackieXu
Copy link
Contributor

JackieXu commented Sep 11, 2017

The explicit type checking at the top stays very much in line with Viper's design philosophy of being easy on the reader, I like that.

I wouldn't move that explicitness away into a scan later, as per suggestion 3. But, I do like suggestion 1 very much as a type of safety net and I feel this is actually a must, as else it would leave the reader open to be fooled, would it not?

Also, could we add the small bit of context here that contract means the address of a contract?

@fubuloubu
Copy link
Member

Well, I both agree and disagree with you that point. I think it is clearer now to see what the explicit types are you are checking for, plus it makes the compiler's job easier. But in the end, I believe the reader is more interested in the method name and where it is used, and the ancillary work of figuring out if the external contract method's types work with the one in the contract they might be less interested in, thereby willing to offload that work to the compiler/runtime environment. For now, as most of the functionality is unimplemented, I believe explicit is better.

Yes, I think there is a potentially insidious attack that can be performed here if you create a reference to a contract that does not implement part of the methods specified, thereby "shutting down" access to methods other users might require (e.g. imagine a withdraw method that breaks because the contract owner updated some reference contract maliciously, now they can keep all your money.

P.S. I updated to top comment to state that. Basically, contract is of type address (or at least how I see it) so you could "typecast" an address to a contract in some way, if that's not too opaque.

@fubuloubu
Copy link
Member

fubuloubu commented Sep 11, 2017

Also, another thing that is enabled by implicit type checking via asserts is that if you wanted to use a method from a contract without saving the reference, you could do that as long as the types check out e.g.

def get_currency_of(item: contract) -> currency_value:
    return item.get_currency() # Type check occurs to ensure this meshes with return type

Since item is not a global, I wouldn't be able to do this with explicit typing

I don't believe this adds any additional vectors of attack beyond whats already possible.

@DavidKnott
Copy link
Contributor Author

Closing as this has extern contract calling has been implemented.

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

No branches or pull requests

3 participants