Sistem Perdagangan Lokal Tanpa Kepercayaan
29 Mei 2019

Sistem Perdagangan Lokal (LETS) bertujuan untuk mengembangkan ekonomi lokal dan biasanya digunakan oleh orang-orang di suatu daerah yang saling berdekatan. Untuk gambaran singkat tentang LETS lihat tautan ini, yang juga menjelaskan implementasi ErgoScript dari LETS yang dikelola oleh komite. Kami menyebut sistem semacam itu sebagai dikelola atau berizin, karena bergantung pada komite anggota tepercaya untuk mendaftarkan anggota baru ke dalam LETS.
Di sini kami menjelaskan LETS tanpa kepercayaan, yaitu, satu di mana tidak ada komite manajemen yang diperlukan untuk pendaftaran.
Gambaran Umum
LETS melibatkan beberapa pihak yang setuju untuk menggunakan beberapa bentuk "mata uang lokal", biasanya dipatok pada mata uang utama negara dengan rasio 1:1. Anggaplah LETS kami berbasis di negara Eropa di mana mata uangnya adalah Euro, dan pertukaran dilakukan dalam "Euro lokal", yang dianggap setara dengan Euro nasional.
Setiap pengguna di LETS memiliki akun, yang berisi saldo LETS pengguna tersebut (dalam Euro Lokal). Saat bergabung, setiap pengguna memiliki saldo nol. Saldo disimpan dalam buku besar (mungkin terdesentralisasi). Fitur menarik dari LETS adalah bahwa pengguna dengan saldo nol juga dapat "menarik" uang, tetapi hanya untuk membayar pengguna LETS lainnya. Pada setiap saat jumlah saldo LETS dari semua pengguna adalah nol.
Sebagai contoh, Alice dengan saldo nol ingin membeli satu liter susu seharga 2 Euro dari Bob yang juga merupakan anggota LETS dengan saldo nol. Dia mentransfer 2 Euro dari akunnya ke akun Bob, membuat saldonya -2 dan saldo Bob +2. Bob kemudian dapat mentransfer sebagian atau seluruh saldonya ke pengguna LETS lainnya sebagai imbalan untuk barang atau jasa.
LETS Tanpa Kepercayaan
Karena kami menginginkan LETS tanpa kepercayaan, kami tidak dapat bergantung pada kelompok orang tepercaya untuk menerima pengguna. Perhatikan bahwa kami masih akan memiliki komite untuk melakukan beberapa tugas seperti mengatur parameter LETS (mata uang lokal, jumlah maksimum anggota, dll) dan mengkonsumsi biaya pendaftaran.
Kami hanya akan mengasumsikan oracle harga yang tepercaya yang memberikan tarif euro saat ini ke erg yang diidentifikasi oleh beberapa id global (rateTokenID) dan kotak singleton yang berisi tepat satu token dengan id ini. Kotak singleton, yang dijelaskan di sini, adalah kotak yang berisi token singleton, yaitu, token dengan hanya satu kuantitas yang ada. Kotak ini juga berisi tarif erg ke euro pada periode waktu tertentu. Tarif diperbarui dengan menghabiskan kotak ini dan membuat kotak singleton lain dengan tarif baru.
Pada setiap saat, LETS kami didefinisikan secara unik oleh kotak token global yang berisi beberapa token keanggotaan dengan id letsTokenID. Kotak ini mendefinisikan parameter LETS seperti lokasi, unit mata uang, rateTokenID, dll. Kotak token awalnya dimulai dengan, katakanlah, 10000 token keanggotaan. Pengguna dapat menghabiskan kotak ini dan membuat kotak LETS individu mereka sebagai keluaran dari transaksi, sehingga setiap keluaran tersebut memiliki tepat satu token keanggotaan dan token keanggotaan yang tersisa dimasukkan ke dalam kotak token yang baru dibuat.
Kotak LETS mewakili anggota LETS dan harus digunakan dalam setiap transaksi. Untuk kesederhanaan, artikel ini membatasi semua transaksi LETS untuk melibatkan tepat dua anggota, satu sebagai pengirim dan yang lainnya sebagai penerima, sehingga pengirim mentransfer sejumlah positif dari mata uang LETS (euro lokal) ke penerima. Transaksi semacam itu mengkonsumsi kotak anggota dan membuatnya kembali sebagai keluaran dengan saldo yang diperbarui.
Varian Dasar
Untuk mencegah spam dan serangan DDoS, kami memerlukan setidaknya sejumlah minimum erg (minErgsToJoin) untuk dikunci di kotak anggota yang baru dibuat. Erg akan dikunci sampai setidaknya minWithdrawTime jumlah blok telah ditambang. Sebuah kotak diperbolehkan memiliki saldo LETS negatif hingga jumlah yang dapat ditutupi oleh erg yang terkunci (menggunakan tarif pada saat perdagangan).
// 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
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) == memberBoxScriptHash &&
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 // store the creation height in R6
}
// how many lets boxes creared in the tx
val numLetsBoxes = OUTPUTS.filter({(b:Box) => isLets(b)}).size
// 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 - numLetsBoxes && // quantity
tokenBox.propositionBytes == SELF.propositionBytes // script
Kotak anggota LETS dilindungi oleh skrip di bawah ini, yang hash-nya memberBoxScriptHash digunakan di atas. Skrip ini memerlukan tepat satu pasangan (pengirim, penerima) per transaksi.
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 createdAt = SELF.R6[Long].get // height at which current input was mined
val index = getVar[Int](0).get // index of the corresponding output
val out = OUTPUTS(index)
val outBalance = out.R4[Long].get // LETS balance of the output
// A LETS box is one that has the same script as the current box
val isMemberBox = {(b:Box) => b.propositionBytes == SELF.propositionBytes}
val letsInputs = INPUTS.filter(isMemberBox) // all LETS input boxes
val letsOutputs = OUTPUTS.filter(isMemberBox) // all LETS output boxes
// The current input belongs to the receiver if its LETS balance increases
// There may be some ergs in receiver's input box. We need to ensure that
// the receiver's output box also contains the same amount of ergs as input
val receiver = outBalance > inBalance && out.value == SELF.value
val getBalance = {(b:Box) => b.R4[Long].get} // returns LETS balance of a box
val letsBalIn = letsInputs.map(getBalance).fold(0L, {(l:Long, r:Long) => l + r})
val letsBalOut = letsOutputs.map(getBalance).fold(0L, {(l:Long, r:Long) => l + r})
// 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 = out.value >= -outBalance * rate && (
out.value >= SELF.value || SELF.R6[Long].get + minWithdrawTime > HEIGHT
)
// 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.tokens(0)._1 == letsTokenID && // the current input has the right token
out.tokens(0)._1 == letsTokenID && // corresponding output has the right token
validRateOracle && // oracle providing rate has the correct "rate token"
letsBalIn == letsBalOut && // total LETS balance is preserved in the transaction
letsInputs.size == 2 && letsOutputs.size == 2 && // only two LETS inputs, outputs
out.propositionBytes == SELF.propositionBytes && // out is a LETS box ...
out.R5[SigmaProp].get == pubKey && // ... with the right pub key
out.R6[Long].get == SELF.R6[Long].get && // ... and creation height
(receiver || // either current input belongs to receiver ...
(pubKey && correctErgs) // ... or out has correct ergs and tx has signature
)
Transaksi yang menghabiskan kotak dengan skrip di atas memerlukan:
- Jumlah saldo LETS dari input dan output dipertahankan
- Terdapat dua input LETS dan dua output LETS
- Kunci publik (disimpan di R5) dipertahankan di output yang sesuai
- Tinggi pembuatan (disimpan di R6) dipertahankan di output yang sesuai
Kami mengatakan bahwa beberapa kunci publik adalah penerima jika saldo LETS dari outputnya lebih tinggi daripada inputnya.
Kondisi terakhir mengharuskan bahwa baik kotak input dan output milik penerima (sehingga erg dipertahankan), atau, jika mereka milik pengirim, tanda tangan disediakan dan output didukung oleh jumlah erg yang diperlukan jika saldo LETS-nya negatif. Selain itu, ini mengharuskan bahwa saldo erg pengirim tidak dapat dikurangi sampai setidaknya minWithdrawTime jumlah blok telah ditambang setelah erg dikunci.
Dibandingkan dengan LETS yang dikelola, sistem di atas memiliki perbedaan berikut:
- Tidak ada catatan keanggotaan: Tidak seperti LETS yang dikelola, kami tidak menyimpan informasi keanggotaan di sini.
- Kotak ganda: Seseorang dapat membuat beberapa kotak keanggotaan, yang diperbolehkan. Kami hanya memerlukan bahwa saldo negatif apa pun didukung oleh jumlah erg yang terkunci di dalamnya.
LETS-1: Jumlah Nol, Jaminan
Di atas adalah varian dasar, yang kami sebut LETS-1. Ini memiliki fitur berikut:
- Biaya Pendaftaran Terkunci Waktu: Untuk mencegah serangan spam, seorang anggota harus membayar biaya minimum tertentu dalam erg pada saat bergabung. Biaya ini dapat dikembalikan tetapi hanya setelah sejumlah blok yang telah ditentukan.
- Jumlah Nol: Jumlah saldo LETS dari semua kotak anggota adalah nol. Kotak anggota diperbolehkan memiliki saldo negatif selama masih dalam batas tertentu.
- Jaminan: Untuk output pengirim, erg digunakan sebagai jaminan untuk menutupi saldo LETS negatif pada tarif pertukaran saat ini.
Berikut adalah beberapa variasi dari LETS-1.
LETS-2: Jumlah Nol, Tanpa Jaminan
Ini adalah variasi sedikit dari LETS-1 sebagai berikut:
- Biaya pendaftaran yang tidak dapat dikembalikan: Mirip dengan LETS-1, biaya pendaftaran diperlukan untuk mencegah serangan spam. Namun, tidak seperti LETS-1, biaya ini tidak dapat dikembalikan dan harus dikirim ke beberapa komite manajemen yang telah ditentukan.
- Jumlah Nol: Seperti di LETS-1.
LETS-3: Jumlah Positif, Jaminan
Dua varian di atas mengharuskan total saldo LETS selalu nol. Di sini kami mempertimbangkan nilai positif untuk jumlah ini. Secara khusus, varian ini memiliki sifat-sifat berikut:
- Biaya Pendaftaran Terkunci Waktu: Seperti di LETS-1.
- Jumlah Positif: Saldo LETS setiap anggota harus selalu tidak negatif. Ini memastikan bahwa jumlah saldo LETS dari semua kotak anggota adalah positif. Saldo LETS awal diatur ke nilai positif berdasarkan biaya pendaftaran pada tarif saat ini, dibatasi pada nilai maksimum tertentu.
- Jaminan: Setiap pengurangan dalam saldo erg pengirim harus disertai dengan pengurangan saldo LETS yang sesuai pada tarif pertukaran saat ini.
Kami juga dapat mengizinkan penambahan saldo LETS selama transaksi dengan menambahkan jumlah erg yang setara.
LETS-4: Jumlah Positif, Tanpa Jaminan
Ini mirip dengan LETS-3 tetapi dengan beberapa variasi kecil:
- Biaya Pendaftaran yang Tidak Dapat Dikembalikan: Seperti di LETS-2
- Jumlah Positif: Seperti di LETS-3
Tabel berikut merangkum varian-varian tersebut:
| Jumlah Nol | Jumlah Positif | |
|---|---|---|
| Jaminan | LETS-1 | LETS-3 |
| Tanpa jaminan | LETS-2 | LETS-4 |
Kami mempertimbangkan transaksi LETS yang melibatkan satu pasangan pengirim-penerima. Model yang lebih canggih dapat memungkinkan beberapa pengirim dan penerima, dan tidak harus dalam pasangan.
Share post
13 Agustus 2025
9 Juli 2025






