四個原語
Reserve · Note · Tracker · Predicate
Reserve
資本擔保
一個將ERG或代幣作為抵押品持有的鏈上合約。任何人都可以隨時驗證準備金比率。Reserve就是銀行——無需中間人。
- 持有ERG / 原生代幣
- 隨時可審計
- 以1:1或部分方式支撐Note發行
- 合約強制執行贖回
ErgoScript
{
// Reserve contract: allow withdrawal only
// if redemption note is burned
val noteBox = INPUTS(1)
val burnCheck = noteBox.tokens.size == 0
sigmaProp(burnCheck && SELF.R4[Long].get > 0)
}Note
可程式化IOU
代表對Reserve的請求權的不記名代幣。Note可以轉移、拆分和贖回。接受Predicate定義誰可以接收或贖回Note。
- 不記名工具——無需身份
- 點對點可轉移
- 可對Reserve合約贖回
- 以任何代幣計價
ErgoScript
{
// Note: transferable by holder,
// redeemable against reserve
val holder = SELF.R4[GroupElement].get
val isHolder = proveDlog(holder)
val isRedemption = INPUTS.exists { box =>
box.tokens.exists(_._1 == reserveId)
}
isHolder || isRedemption
}Tracker
鏈上會計
追蹤從Reserve發行的所有Note的累計餘額、信用使用量和贖回歷史。可以把它看作任何人都能驗證的公開帳本。
- 追蹤已發行vs已贖回總額
- 執行信用限額
- 公開可審計
- 可與其他合約組合
ErgoScript
{
// Tracker: ensure running total
// doesn't exceed credit limit
val limit = SELF.R4[Long].get
val used = SELF.R5[Long].get
val newUsed = used + INPUTS(0).value
sigmaProp(newUsed <= limit)
}Acceptance Predicate
可程式化信任規則
代理接受Note作為支付的條件。條件可以包括任務雜湊驗證、截止日期檢查、憑證證明或任何鏈上資料。
- 任意接受條件
- 任務雜湊驗證
- 截止日期執行
- 可與Sigma證明組合
ErgoScript
{
// Accept note only if:
// 1. Task hash matches R4
// 2. Deadline not passed
val taskHash = SELF.R4[Coll[Byte]].get
val deadline = SELF.R5[Int].get
val inputHash = INPUTS(0).R4[Coll[Byte]].get
val onTime = HEIGHT <= deadline
sigmaProp(taskHash == inputHash && onTime)
}範例流程
三個可組合流程
流程A:代理購買API呼叫
一次呼叫。一個證明。無需持久帳戶。
- 1
代理建立Note
0.001 ERG面值,R4中的提供者地址
- 2
提供者檢查Predicate
驗證Note價值、Reserve擔保、截止日期
- 3
提供者交付回應
返回API結果,將Note標記為已使用
- 4
結算
Note被銷毀,ERG從Reserve釋放給提供者
Fleet SDK (TypeScript)
// Fleet SDK: create a note for API payment
import { TransactionBuilder, OutputBuilder, SAFE_MIN_BOX_VALUE } from "@fleet-sdk/core"
const noteBox = new OutputBuilder(
1_000_000n, // 0.001 ERG
NOTE_CONTRACT_ADDRESS
)
.setAdditionalRegisters({
R4: SGroupElement(providerPubKey), // recipient
R5: SLong(BigInt(HEIGHT + 100)), // deadline
R6: SColl(SByte, taskHashBytes), // task identifier
})
const tx = new TransactionBuilder(currentHeight)
.from(inputs)
.to(noteBox)
.sendChangeTo(agentAddress)
.payMinFee()
.build()流程B:代理以信用支付
部署Reserve。發行Note。Tracker監控。
- 1
部署Reserve
將ERG鎖定在帶信用限額的Reserve合約中
- 2
發行Note
在信用限額內對Reserve建立Note
- 3
代理使用Note
Note轉移給提供者,Tracker更新
- 4
自動結算
達到閾值時,Reserve結算未清Note
Fleet SDK (TypeScript)
// Deploy a reserve with 10 ERG, 100 ERG credit limit
const reserveBox = new OutputBuilder(
10_000_000_000n, // 10 ERG collateral
RESERVE_CONTRACT_ADDRESS
)
.setAdditionalRegisters({
R4: SLong(100_000_000_000n), // 100 ERG credit limit
R5: SLong(0n), // issued so far
R6: SGroupElement(ownerKey), // reserve controller
})
// Issue a note against the reserve
const noteBox = new OutputBuilder(
1_000_000_000n, // 1 ERG face value
NOTE_CONTRACT_ADDRESS
)
.setAdditionalRegisters({
R4: SGroupElement(agentKey), // holder
R5: SColl(SByte, reserveId), // backing reserve
})流程C:社區Reserve + Tracker
本地市場、運算合作社、代理網路。
- 1
社區部署Reserve
社區成員共同匯集ERG
- 2
發行社區Note
成員按貢獻比例獲得Note
- 3
本地商務
社區內接受Note,Predicate定義規則
- 4
贖回
成員隨時可從Reserve贖回Note換取ERG
Fleet SDK (TypeScript)
// Community reserve: multiple funders
const communityReserve = new OutputBuilder(
TOTAL_POOLED_ERG,
MULTISIG_RESERVE_CONTRACT
)
.setAdditionalRegisters({
R4: SColl(SGroupElement, memberKeys), // governance
R5: SInt(3), // 3-of-5 threshold
R6: SColl(SByte, communityTokenId), // community token
})
// Acceptance predicate: only members of community
const memberPredicate = `{
val isMember = CONTEXT.dataInputs(0)
.R4[Coll[GroupElement]].get
.exists(pk => proveDlog(pk))
sigmaProp(isMember)
}`