etherts / ewasm-as

Ethereum-flavored WebAssembly AssemblyScript API
MIT License
9 stars 0 forks source link

[Proposal] Transfer '<<' operator #4

Open lrettig opened 6 years ago

lrettig commented 6 years ago

@MaxGraey proposal from https://github.com/lrettig/ewasm-as-wrc20/issues/1:

For EOS smart contracts I proposed this high-level transfer operator:

function transfer(sender: Address, recipient: Address, quantity: Amount): void {
   Account.get(recipient) << quantity << Account.get(sender);
}

WDYT about this convention also for ewasm smart contracts?

lrettig commented 6 years ago

Cool! How do the balance checks happen? What happens if the sender balance is insufficient?

MaxGraey commented 6 years ago

You can see the details with some comments in this WAS playgound: https://webassembly.studio/?f=tz9pgrvb7u

So in future AS it looks like:

class Account {
  constructor(
    owner: Address,
    public balance: U64,
  ) {
    this.owner = owner;
  }

  static get(address: Address): Account { ... }

  // [Currently]
  @operator("<<")
  static transferTo(quantity: U64, account: Account): U64 {
    assert(this.balance > quantity); // check balance
    account.balance -= quantity.value;
    return quantity;
  }

  /* Unfortunately we cannot do this now and in future
  @operator("<<")
  static transferTo(account: Account, quantity: U64): Account {
    account.balance += quantity.value;
    return account;
  }
  */

  // but in future we could do something like that
  // <----  NOT SUPPORT YET!
  @operator("<<")
  static transferTo<
     Q extends Amount | Account, 
     T extends Amount | Account
  >(a: Q, b: T): Q {
     // Handle "quantity << Account.get(from)" case
     if (a instanceof Amount && b instanceof Account) {
       assert(b.balance >= a); // check balance
       b.balance -= a;
       return <Q>a;
     }
     // Handle "Account.get(to) << quantity" case
     if (a instanceof Account && b instanceof Amount) {
       a.balance += b;
       return <Q>a;
     }
     throw new TypeError("Unsupported generic type combination");
     return <Q>0;
  }
  // ---->
}

Currently we can't overload methods with same name so for now we need U64 proxy wrapper which just boxing u64 type. That's works but require stuff like Account.get(to) << U64.wrap(quant) << Account.get(from). With simulation overloading via Generics and conditional typing if needed we can skip this wrapping. But may be we will do this better. Need more investigation.

lrettig commented 6 years ago

Thanks, great idea, I didn't know this sort of operator overloading was even possible with TS.

MaxGraey commented 6 years ago

Not in TS. Operator overloading valid only for AssemblyScript. It's pretty useful for math as well. You can investigate how this using for bignum (like u128, i128, u256 and etc) types for example.