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

[WIP] EIP-0026: Local Exchange Trading System #51

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions eip-0026.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
Local Exchange Trading System
=============================

* Author: kushti, scalahub
* Track: applications
* Status: Proposed
* Created: 09-Aug-2019
* Last edited: 17-June-2020
* License: CC0
* Forking: not needed

Motivation
----------

Trustless LETS
--------------

**Registration Contract** allows new members to join by depositing collateral more than minimal value.

```
{
val letsTokenId = fromBase58("")
val letsBoxScriptHash = fromBase58("")
val deadline = 1024
val minErgsToJoin = 100000000


// a tokenBox stores the membership tokens and has this script
val tokenBox = OUTPUTS(0) // the first output must also be a tokenBox
// first output contains remaining LETS tokens

val letsBox = OUTPUTS(1)

def isLets(b:Box) = { // returns true if b is a LETS box
// A LETS box must have exactly 1 membership token in tokens(0)
b.tokens(0)._1 == letsTokenId && b.tokens(0)._2 == 1 &&
blake2b256(b.propositionBytes) == letsBoxScriptHash &&
SELF.R4[Long].get == 0 && // start the box with zero LETS balance
b.value >= minErgsToJoin && // the box must contain some minimum ergs
b.R6[Long].get >= HEIGHT + deadline // store deposit deadline height in R6
}

// In the transaction following is preserved for the token box ...
tokenBox.tokens(0)._1 == SELF.tokens(0)._1 && // token id
tokenBox.tokens(0)._2 == SELF.tokens(0)._2 - 1 && // quantity
tokenBox.propositionBytes == SELF.propositionBytes &&
isLets(letsBox)
}
```

**LETS contract* allows participants to perform an act of economic exchange, creating IOC (I Own Community) debt to back
the exchange

```
{
val rateTokenId = fromBase58("") // oracle NFT
val letsTokenId = fromBase58("") // LETS membership token

val validRateOracle = CONTEXT.dataInputs(0).tokens(0)._1 == rateTokenId
val rate = CONTEXT.dataInputs(0).R4[Int].get

val inBalance = SELF.R4[Long].get // LETS balance of current input
val pubKey = SELF.R5[SigmaProp].get // owner of the current input
val deadline = SELF.R6[Long].get // minHeight to withdraw collateral, even partly

val otherInputIndex = getVar[Short](0).get
val selfOutIndex = getVar[Short](1).get // index of the self-related output
val otherOutIndex = getVar[Short](2).get // index of the counterparty's output]

val otherInput = INPUTS(otherInputIndex)
val selfOut = OUTPUTS(selfOutIndex)
val otherOut = OUTPUTS(otherOutIndex)
val outBalance = selfOut.R4[Long].get // LETS balance of the output

// A LETS box is one that has the same script as the current box

val getBalance = {(b:Box) => b.R4[Long].get} // returns LETS balance of a box

// sender box can contain less amount of ergs (sender may withdraw ergs provided
// that any negative LETS balance of sender in out is backed by sufficient ergs)
val correctErgs = selfOut.value >= -outBalance * rate && (
selfOut.value >= SELF.value || SELF.R6[Long].get < HEIGHT
)

val balancePreserved = {
getBalance(SELF) + getBalance(otherInput) == getBalance(selfOut) + getBalance(otherOut)
}

// for the receiver, we don't touch the erg balance,
// since a receiver is not actively involved in the transaction
inBalance != outBalance && // some transaction should occur; balance must change
SELF.id != otherInput.id &&
SELF.tokens(0)._1 == letsTokenId && // the current input has the right token
selfOut.tokens(0)._1 == letsTokenId && // corresponding output has the right token
validRateOracle && // oracle providing rate has the correct "rate token"
balancePreserved && // total LETS balance is preserved in the transaction
selfOut.propositionBytes == SELF.propositionBytes && // out is a LETS box ...
selfOut.R5[SigmaProp].get == pubKey && // ... with the right pub key
selfOut.R6[Long].get == SELF.R6[Long].get && // ... and creation height
(pubKey && correctErgs) // ... or out has correct ergs and tx has signature
}
```