kadena-io / KIPs

Kadena Improvement Proposals
17 stars 18 forks source link

Fungible Token KIP proposal #3

Closed sirlensalot closed 4 years ago

sirlensalot commented 5 years ago

Pre-discussion and design for KIP PR.

FungibleAsset specifies an ERC-20-style API. https://eips.ethereum.org/EIPS/eip-20

Design Questions:

lilamila commented 5 years ago

2 Current issues in ERC-20 cited in this article https://medium.com/@dexaran820/erc20-token-standard-critical-problems-3c10fd48657b

sirlensalot commented 5 years ago

Initial Proposal

See https://github.com/kadena-io/KIPs/blob/master/assets/fungible-token-v1-proposal.pact.

Also reproducing here:

(interface fungible-token-v1

  @doc
  " FungibleToken represents a transferrable undifferentiated token. \
  \ Authors: Stuart Popejoy, Emily Pillmore"

  (defun transfer:string
    (
      sender:string
      reciever:string
      receiver-guard:guard
      amount:decimal
    )

    @doc
    " Transfer AMOUNT between accounts SENDER and RECEIVER on the \
    \ same chain. Creates RECEIVER account using RECEIVER-GUARD if \
    \ account does not already exist."

    @model [
      (property (> amount 0.0))
    ]
  )

  (defun transfer-to:string
    (
      sender:string
      reciever:string
      amount:decimal
    )

    @doc
    " Transfer AMOUNT between accounts SENDER and RECEIVER on the \
    \ same chain. Fails if RECEIVER account does not already exist."

    @model [
      (property (> amount 0.0))
    ]
  )

  (defun create-account:string
    (
      account:string
      guard:guard
    )

    @doc
    " Create ACCOUNT with GUARD and zero balance. Fails if account \
    \ already exists."
  )

  (defun get-balance:decimal
    (
      account:string
    )

    @doc
    " Get balance for ACCOUNT. Fails if account does not exist."

    @model [
      (property (result >= 0.0))
    ]
  )

)
sirlensalot commented 5 years ago

Items for discussion:

On-behalf-of transfers

ERC-20 has transferFrom and approve with known problems. We could consider instead a version that allows a "one-time spend" or simply some kind of escrow procedure.

Minimum denomination

ERC-20 is denominated in integers, whereas this proposal uses decimal for compatibility with the coin contract. We could consider a (defun denomination:decimal ()) that returns some minimum denomination, with models to support it.

Or, should we have decimal- and integer-denominated interfaces?

Cross-chain interface

Once automatic SPV is in pact we will want to add cross-chain functions.

joelburget commented 5 years ago

Is there any constraint on the strings transfer, transfer-to, and create-account return? I assume they're expected to be something like "success"?

When we say "create account with guard", does that mean that it's expected that the row representing the user is expected to have a guard field?

@bts I think the stronger property system would be useful for expressing the (currently informal) failure properties ("Fails if account does not exist").

Spelling nits:

bts commented 5 years ago

@bts I think the stronger property system would be useful for expressing the (currently informal) failure properties ("Fails if account does not exist").

When I was reading the proposal I had the same thought! One way we could do this here would be a combination of:

(1) implement kadena-io/pact#124 (2) add one more function to the interface that we can reference in properties:

(defun account-exists:bool (account:string))
sirlensalot commented 5 years ago

Is there any constraint on the strings transfer, transfer-to, and create-account return? I assume they're expected to be something like "success"?

It would probably be good to lock these down but OTOH they don't represent meaningful values in the interface. But we could certainly limit their length. Or just make them bool ...

When we say "create account with guard", does that mean that it's expected that the row representing the user is expected to have a guard field?

This is the essence of the difference between transferTo and transfer: the latter operates like Ethereum where if that address doesn't exist (and is valid) then it is simply created. When it does exist, the requirement is currently that the guard must exactly match the existing guard, which is admittedly awkward, but in fact is no different from the single-signature semantics of say Ethereum where the ID and the public key have been conflated into a single value, which is obviously inadequate for say, multi-sig.

One thing we haven't addressed in this interface is key rotation but I would imagine that being part of some RotatableAccount API that would equally apply to non-fungible ledgers, etc.

sirlensalot commented 5 years ago

Along with accounts-exist, I was wondering if we could simulate column-delta properties with another operation get-ledger:[object{keyed-ledger}] (where keyed-ledger is simply {acct:string, balance:decimal}) that returns the entire ledger?

The larger question for is in general, what is required for model-checking to do column-delta stuff on an interface?

EDIT: is totalSupply sufficient?

sirlensalot commented 4 years ago

Note this was implemented in #7 and released with Chainweb in October 2019.