Skip to content

Otmoic

Introduction

Otmoic 是一个基于 Snowinning Protocol 的,无需第三方信任的,为 Depin,AI Agent,Crypto Trading 打造的自动化价值交换协议。

它的愿景是: Giving Public Goods a Fair Price。

Otmoic Protocol 在设计时有以下的特色:

  • 为 Trader 和 Liquidity Provider 提供了链上的 Reputation机制,解决 Free Mint 问题。
  • 支持基于 Verifiable CredentialKYC
  • 价格发现基于 RFQ。
  • 链上的交易基于原子交换。
  • 通过在 Terminus OS 里安装应用,支持 Liquidity Provider 自动做市。

通过上述设计,可以让 Otmoic Protocol 广泛应用于 DePin,AI Bot,Creator Economy,Crypto Trading,Crypto Cross-Chain,Fiat and Crypto Gateway 等场景。

开源项目

你可以在这里查看协议的代码:

以下是协议的细节

Spec

Resources

Data

  • BridgeInfo
nametyperequireddescription
src_chain_iduint用户换出代币的链码,遵循 bip44 中的链码
dst_chain_iduint用户换入代币的链码,遵循 bip44 中的链码
src_tokenString用户换出的 token
dst_tokenString用户换入的 token
bridge_nameString<src_chain_id>-<src_token>-<dst_chain_id>-<dst_token>
  • QuoteBase
nametyperequired: amm -> lpnoderequired: lpnode -> relayrequired: ask reply: amm -> lpnoderequired: ask reply: lpnode -> relaydescription
bridgeBridgeInfo此次报价所属的交易对信息
lp_bridge_addressStringlp 的收款地址
lp_node_uriStringlp 程序的公网访问地址, relay 依赖此地址与 lpnode 通信
quote_hashString本次报价的 hash, 作用报价的唯一标识
priceString兑换价格, 以 token 的整数位为单位进行报价
native_token_priceString兑换 native token 的价格, 同样以 token 的整数位为单位进行报价
native_token_maxString本次最多可以兑换多少 native token
native_token_minString如果要兑换 native token, 最少需要兑换多少
  • QuoteAuthenticationLimiter
nametyperequireddescription
limiter_stateString是否开启限制器, “on”为开启, “off”为关闭
country_white_listString按国家进行限制,白名单列表,以“,”分割
country_black_listString按国家进行限制,黑名单列表,以“,”分割
min_ageString可以进行交易的最小年纪

NOTE

  • 如果开启限制器, 则所有未在 relay 进行 kyc 的对手方, 都将不支持
  • 黑名单和白名单仅有 1 个生效, 白名单优先级更高, 白名单为空时黑名单生效
  • 如配置白名单国家, 则其余国家全为黑名
  • LPInfo
nametyperequireddescription
nameStringlp 的名字, 此名字必须使用 TerminusName
profileStringlp 的对外介绍信息, 内容无限制
credit_scoreuintlp 在当前 relay 中的信用分

NOTE

  • credit_score 的计算由两部分组成, 基础分和投诉扣分
    • 基础分依据最近一段时间的交易数,平均等待时间等信息计算得出
    • 投诉扣分是在交易有投诉,并且投诉情况被系统确认的情况下进行永久计分
  • Quote
nametyperequireddescription
quote_baseQuoteBase报价信息
authentication_limiterQuoteAuthenticationLimiter此次报价的限制器
lp_infoLPInfolp 信息
timestampLong此次报价的时间戳
  • Ask
nametyperequireddescription
bridgeString交易对的名字,与 BridgeInfo 中的 bridge_name 相同
amountString期望换出的 token 数量
  • SwapAssetInformation
nametyperequired: FE -> relayrequired: relay -> lpnoderequired: lpnode -> ammdescription
bridge_nameString交易对的名字
lp_idStringlp 的名字
senderString执行换出 token 的钱包地址
amountString换出的 token 数量
dst_addressString换入 token 的接收地址
dst_amountString换入 token 的数量
dst_native_amountString换入操作附带交换的 native token 数量
step_time_lockLong每一步操作的限制时间
agreement_reached_timeLong双方达成交易的时间
requestorString交换发起方的身份认证地址
user_signString用户对于交易信息的签名
lp_signStringlp 对于交易信息的签名
quoteQuote交易发起方所选择的报价
system_fee_srcuint系统当前合约所收取的手续费-换出链
system_fee_dstuint系统当前合约所收取的手续费-换入链
dst_amount_needString是否交换 token
dst_native_amount_needString是否交换 native token
append_informationString附加信息

NOTE

dst_amount_needdst_native_amount_need由 relay 基于本次交换的信息计算得出 system_fee_dstsystem_fee_src由 relay 从链上获取

上述四条信息均非交换流程的必要参数, 目的仅为降低后续流程及其他模块的实现难度。

  • 关于每一步的操作时间限制
    • transferOut: agreement_reached_time + 1 \* step_time_lock之前调用,否则调用失败。
    • transferIn: agreement_reached_time + 2 \* step_time_lock之前调用,否则调用失败。
    • confirmTransferOut:
      • 使用交易发起者提供的 hashlock 进行验证时, agreement_reached_time + 3 \* step_time_lock之前调用,否则调用失败。
      • 使用 relay 提供的 hashlock 进行验证时, agreement_reached_time + 6 \* step_time_lock之前调用,否则调用失败。
    • confirmTransferIn: agreement_reached_time + 5 \* step_time_lock之前调用,否则调用失败。
    • refundTransferOut: agreement_reached_time + 7 \* step_time_lock之后调用,否则调用失败。
    • refundTransferIn: agreement_reached_time + 7 \* step_time_lock之后调用,否则调用失败。

NOTE

预期的正常操作流程和时间限制是:

  • transferOut: 1 \* step_time_lock
  • transferIn: 2 \* step_time_lock
  • confirmTransferOut: 3 \* step_time_lock
  • confirmTransferIn: 4 \* step_time_lock

但是, 考虑到交换双方可能出现的作弊行为, 所以confirmTransferOutconfirmTransferIn的时间限制需要调整。

  • 如果4 * step_time_lock时间到达后, LP 未进行ConfirmTransferIn操作, 此时 relay 会主动介入, 进行ConfirmTransferIn操作, 所以4 * step_time_lock ~ 5 * step_time_lock的时间段是留给 relay 进行防作弊操作的时间。
  • TransferIn所使用的 hashlock 由交换发起者提供, 如果交易发起者在5 * step_time_lock的时间边界直接操作ConfirmTransferIn, 则 relay 会在此时介入, 使用 relay 提供的 hashlock 进行ConfirmTransferOut, 5 * step_time_lock ~ 6 * step_time_lock的时间段就是此流程的执行时间。
  • 关于交易签名

交易发起方需要使用requestor对交易信息进行签名, 签名后的结果填入user_sign字段 lp 则需要使用已在 DID 合约中认证过的地址对交易进行签名, 签名后的结果填入lp_sign字段

NOTE

在 evm 类型的链中, 签名遵循 EIP712 进行。 其他类型的链, 签名遵循链上支持的类似协议进行。

  • EIP712 Types
types: {
	EIP712Domain: [
		{ name: 'name', type: 'string' },
		{ name: 'version', type: 'string' },
		{ name: 'chainId', type: 'uint256' },
	],
	Message: [
		{ name: 'src_chain_id', type: 'uint256' },
		{ name: 'src_address', type: 'string' },
		{ name: 'src_token', type: 'string' },
		{ name: 'src_amount', type: 'string' },
		{ name: 'dst_chain_id', type: 'uint256' },
		{ name: 'dst_address', type: 'string' },
		{ name: 'dst_token', type: 'string' },
		{ name: 'dst_amount', type: 'string' },
		{ name: 'dst_native_amount', type: 'string' },
		{ name: 'requestor', type: 'string' },
		{ name: 'lp_id', type: 'string' },
		{ name: 'step_time_lock', type: 'uint256' },
		{ name: 'agreement_reached_time', type: 'uint256' },
	],
}

BidId 生成规范

sha3(
	agreement_reached_time +
	src_chain_id +
	lp_bridge_address +
	src_token +
	dst_chain_id +
	dst_address +
	dst_token +
	amount +
	dst_amount +
	dst_native_amount +
	requestor +
	lp_id +
	step_time_lock +
	user_sign +
	lp_sign
)
  • PreBusiness
nametyperequired: relay -> lpnoderequired: lpnode -> ammrequired: relay -> FEdescription
swap_asset_informationSwapAssetInformation交换信息
hashString交换中主要信息生成的 hash
relay_hashlockStringrelay 提供的 hashlock
is_kycBoolean交换发起者是否在 relay 的系统中进行了 kyc
kyc_infoKycInfo交易发起者的完整 kyc 信息
lockedBoolean交易是否达成的状态位
  • 关于 KYC Info

用户在 relay 进行 kyc 是需提供链上地址, 在 kyc 完成之后, 使用此地址签名发起的交换会以 kyc 成功的状态与限制器进行匹配, 同时也会像 lp 提供完整的 kyc 信息, 以供确认. 更多关于 kyc 的信息可查看下方的 kyc 章节

  • 关于 Lock 标记位

返回给前端的数据中, locked 代码是否达成交易并初步锁定份额, 以下几种情况标记位会为 false

NOTE

  • user_sign 和 其他交换信息计算得出的签名地址与 requestor 地址不符
  • lp_sign 和 其他交换信息计算得出的签名地址没有在链上认证过
  • 交易发起者不满足报价中设置的限制器条件
  • 其他未知原因(lp 可能在余额不足, 价格偏离过大等各种情况下拒绝本次交换请求)
  • TransferOut-EVM

此结构为合约方法调用参数

nametyperequireddescription
senderaddress本操作的发起者, 大多数情况下与 requestor 相同, 但并无必须相同的限制
bridgeaddressQuoteBase 中 lp_bridge_address
tokenaddressBridgeInfo 中 src_token
amountuint256SwapAssetInformation 中 amount
hashlockbytes32交换发起方生成的锁
relayHashlockbytes32PreBusiness 中 relay_hashlock
stepTimelockuint64SwapAssetInformation 中 step_time_lock
dstChainIduint64BridgeInfo 中 dst_chain_id
dstAddressuint256SwapAssetInformation 中 dst_address
bidIdbytes32PreBusiness 中 hash
tokenDstuint256BridgeInfo 中 dst_token
amountDstuint256SwapAssetInformation 中 dst_amount
nativeAmountDstuint256SwapAssetInformation 中 dst_native_amount
agreementReachedTimeuint64SwapAssetInformation 中 agreement_reached_time
requestorstringSwapAssetInformation 中 requestor
lpIdstringSwapAssetInformation 中 lp_id
userSignstringSwapAssetInformation 中 userSign
lpSignstringSwapAssetInformation 中 lpSign

关于 hashlock

NOTE

  • 交换发起方提供一个 bytes32 数据, 用作 release 时的锁, 并在 Confirm 操作时通过 keccak256(preimage) 进行验证, 如果验证成功并且满足其他检查条件, 则可以释放锁定的 token
  • TransferIn 操作与 TransferOut 使用同一把锁
  • 在 ConfirmTransferOut 时, 公开计算 hashlock 所需的 preimage, 之后 lp 就可以使用 preimage 进行 TransferIn 的释放操作
  • EventTransferOut-EVM
nametyperequireddescription
transfer_idbytes32本次操作的 id
senderaddressTransferOut 中的对应数据
bridgeaddressTransferOut 中的对应数据
tokenaddressTransferOut 中的对应数据
amountuint256TransferOut 中的对应数据
hashlockbytes32TransferOut 中的对应数据
relay_hashlockbytes32TransferOut 中的对应数据
step_time_lockuint64TransferOut 中的对应数据
dst_chain_iduint64TransferOut 中的对应数据
dst_addressuint256TransferOut 中的对应数据
bid_idbytes32TransferOut 中的对应数据
token_dstuint256TransferOut 中的对应数据
amount_dstuint256TransferOut 中的对应数据
native_amount_dstuint256TransferOut 中的对应数据
agreement_reached_timeuint64TransferOut 中的对应数据
requestorstringTransferOut 中的对应数据
lp_idstringTransferOut 中的对应数据
user_signstringTransferOut 中的对应数据
lp_signstringTransferOut 中的对应数据
  • TransferIn-EVM

此结构为合约方法调用参数

nametyperequireddescription
senderaddress本操作的发起者
dst_addressaddressSwapAssetInformation 中 dst_address
tokenaddressBridgeInfo 中 dst_token
token_amountuint256SwapAssetInformation 中 dst_amount
eth_amountuint256SwapAssetInformation 中 dst_native_amount
hashlockbytes32EventTransferOut 中 hashlock
step_time_lockuint64SwapAssetInformation 中 step_time_lock
src_chain_iduint64BridgeInfo 中 src_chain_id
src_transfer_idbytes32EventTransferOut 中 transfer_id
agreement_reached_timeuint64SwapAssetInformation 中 agreement_reached_time
  • EventTransferIn-EVM
nametyperequireddescription
transfer_idbytes32本次操作的 id
senderaddressTransferIn 中的对应数据
receiveraddressTransferIn 中的对应数据
tokenaddressTransferIn 中的对应数据
token_amountuint256TransferIn 中的对应数据
eth_amountuint256TransferIn 中的对应数据
hashlockbytes32TransferIn 中的对应数据
step_time_lockuint64TransferIn 中的对应数据
src_chain_iduint64TransferIn 中的对应数据
src_transfer_idbytes32TransferIn 中的对应数据
agreement_reached_timeuint64TransferIn 中的对应数据
  • ConfirmTransferOut-EVM

此结构为合约方法调用参数

nametyperequireddescription
senderaddressTransferOut 中的对应数据
receiveraddressTransferOut 中的对应数据
tokenaddressTransferOut 中的对应数据
token_amountuint256TransferOut 中的对应数据
eth_amountuint256TransferOut 中的对应数据
hashlockbytes32TransferOut 中的对应数据
relay_hashlockbytes32TransferOut 中的对应数据
step_time_lockuint64TransferOut 中的对应数据
preimagebytes32可以计算出 hashlock 的原项
relay_preimagebytes32可以计算出 relay_hashlock 的原项
agreement_reached_timeuint64TransferOut 中的对应数据
  • EventConfirmTransferOut-EVM
nametyperequireddescription
transfer_idbytes32EventTransferOut 中的 transfer_id
preimagebytes32ConfirmTransferOut 中的对应数据
  • ConfirmTransferIn-EVM

此结构为合约方法调用参数

nametyperequireddescription
senderaddressTransferIn 中的对应数据
dst_addressaddressTransferIn 中的对应数据
tokenaddressTransferIn 中的对应数据
token_amountuint256TransferIn 中的对应数据
eth_amountuint256TransferIn 中的对应数据
hashlockbytes32TransferIn 中的对应数据
step_time_lockuint64TransferIn 中的对应数据
preimagebytes32EventConfirmTransferOut 中的 preimage
agreement_reached_timeuint64TransferIn 中的对应数据
  • EventConfirmTransferIn-EVM
nametyperequireddescription
transfer_idbytes32EventTransferIn 中 transfer_id
preimagebytes32ConfirmTransferIn 中 preimage
  • RefundTransferOut-EVM

此结构为合约方法调用参数

nametyperequireddescription
senderaddressTransferOut 中的对应数据
receiveraddressTransferOut 中的对应数据
tokenaddressTransferOut 中的对应数据
token_amountuint256TransferOut 中的对应数据
eth_amountuint256TransferOut 中的对应数据
hashlockbytes32TransferOut 中的对应数据
relay_hashlockbytes32TransferOut 中的对应数据
step_time_lockuint64TransferOut 中的对应数据
agreement_reached_timeuint64TransferOut 中的对应数据
  • EventRefundTransferOut-EVM
nametyperequireddescript
transfer_idbytes32EventTransferOut 中的 transfer_id
  • RefundTransferIn-EVM

此结构为合约方法调用参数

nametyperequireddescription
senderaddressTransferIn 中的对应数据
dst_addressaddressTransferIn 中的对应数据
tokenaddressTransferIn 中的对应数据
token_amountuint256TransferIn 中的对应数据
eth_amountuint256TransferIn 中的对应数据
hashlockbytes32TransferIn 中的对应数据
step_time_lockuint64TransferIn 中的对应数据
agreement_reached_timeuint64TransferIn 中的对应数据
  • EventRefundTransferIn-EVM
nametyperequireddescript
transfer_idbytes32EventTransferIn 中 transfer_id
  • Business
nametyperequireddescription
stepuint交换流程当前的进度
business_hashStringPreBusiness 中 hash

NOTE

step 由 relay 维护

  • 1: 交易已达成, lp 已锁定份额
  • 2: 换出操作已锁仓
  • 3: 换入操作已锁仓
  • 4: 换出操作已释放锁仓
  • 5: 换入操作已释放锁仓
  • 6: 换出操作已退款
  • 7: 换入操作已退款
  • BusinessFullData

已产生的数据的完整包装

ametyperequireddescription
pre_businessPreBusiness
businessBusiness
event_transfer_outEventTransferOut
event_transfer_inEventTransferIn
event_transfer_out_confirmEventTransferOutConfirm
event_transfer_in_confirmEventTransferInConfirm
event_transfer_out_refundEventTransferOutRefund
event_transfer_in_refundEventTransferInRefund

Lpnode Event Command

  • structure
parameter nametypedescription
cmdString本次命令的类型
cidString本次命令的 id
others
  • type
namedescription
CMD_UPDATE_QUOTEamm 发送给 lpnode, 通知 lpnode 向 relay 发送 bridge 存活消息
EVENT_QUOTE_REMOVERlpnode 发送给 amm, 长时间未发送存活消息, bridge 已被 relay 移出可用列表
CMD_ASK_QUOTElpnode 发送给 amm, 询问报价
EVENT_ASK_REPLYamm 发送给 lpnode, 进行实时报价
EVENT_LOCK_QUOTElpnode 发送给 amm, 有新的交换请求
CALLBACK_LOCK_QUOTEamm 发送给 lpnode, 告知 lpnode 是否同意此笔交易
EVENT_TRANSFER_OUTlpnode 发送给 amm, 交换发起方已在合约中锁定 token
CMD_TRANSFER_INamm 发送给 lpnode, 通知 lpnode 执行 TransferIn 操作
EVENT_TRANSFER_OUT_CONFIRMlpnode 发送给 amm, 交换发起方已在合约中释放锁定的 token
CMD_TRANSFER_IN_CONFIRMamm 发送给 lpnode, 通知 lpnode 执行 ConfirmTransferIn 操作
EVENT_TRANSFER_OUT_REFUNDlpnode 发送给 amm, 交换发起方已在合约中退款
CMD_TRANSFER_IN_REFUNDamm 发送给 lpnode, 通知 lpnode 执行 RefundTransferIn 操作
EVENT_TRANSFER_INlpnode 发送给 amm, lpnode 已在合约中锁定 token
EVENT_TRANSFER_IN_CONFIRMlpnode 发送给 amm, lpnode 已在合约中释放锁定的 token
EVENT_TRANSFER_IN_REFUNDlpnode 发送给 amm, lpnode 已在合约中退款

Message

Quotation process

  • Trading pair survives

Flow Direction

null

Data

flowdata
amm -> lpnodeLpnodeEventCommand<QuoteBase>
lpnode -> relayQuoteBase
  • Ask

Flow Direction

null

Data

flowdata
front end -> relayAsk
relay -> lpnodeAsk
lpnode -> ammLpnodeEventCommand<Ask>
  • Ask Reply

Flow Direction

null

Data

flowdata
amm -> lpnodeLpnodeEventCommand<QuoteBase>
lpnode -> relayQuoteBase
relay -> front endQuote

Exchange process

  • Confirm Quotation

Flow Direction

null

Data

flowdata
Confirm Quotation - FE -> relaySwapAssetInformation
Confirm Quotation - relay -> lpnodePreBusiness
Confirm Quotation - lpnode -> ammLpnodeEventCommand<PreBusiness>
agree/not - amm -> lpnodeLpnodeEventCommand<PreBusiness>
agree/not - lpnode -> relayPreBusiness
agree/not - relay -> FEPreBusiness
  • TransferOut

Flow Direction

null

Data

flowdata
TransferOutTransferOut
EventTransferOutEventTransferOut
BusinessUpdate - relay -> FEBusiness
BusinessUpdate - relay -> lpnodeBusinessFullData
BusinessUpdate - lpnode -> ammLpnodeEventCommand<BusinessFullData>
  • TransferIn

Flow Direction

null

Data

flowdata
DoTransferInLpnodeEventCommand<BusinessFullData>
TransferInTransferIn
EventTransferInEventTransferIn
TransferInFinishedBusinessFullData
BusinessUpdateBusiness
  • ConfirmTransferOut

Flow Direction

null

Data

flowdata
ConfirmTransferOutConfirmTransferOut
EventConfirmTransferOutEventConfirmTransferOut
BusinessUpdate - relay -> FEBusiness
BusinessUpdate - relay -> lpnodeBusinessFullData
BusinessUpdate - lpnode -> ammLpnodeEventCommand<BusinessFullData>
  • ConfirmTransferIn

Flow Direction

null

Data

flowdata
DoTransferInLpnodeEventCommand<BusinessFullData>
TransferInConfirmTransferIn
EventTransferInEventConfirmTransferIn
ConfirmTransferInFinishedBusinessFullData
BusinessUpdateBusiness

KYC

使用 TermiPass 浏览器插件对 "Otmoic KYC Verifiable Credential Request Schema" 进行签名, 并提交至 relay, relay 的管理人员人工审核过后, 系统将签发“Otmoic KYC Verifiable Credential Schema”, 然后在前端中同步签发的 VC 至 TermiPass, 并向 relay 提交 “Otmoic KYC Presentation Definition” 完成 kyc 操作

KYC 中的主要信息

namedescription
address现实中的住址
address_on_chain钱包地址,使用“,”隔开
birthday生日, 会跟 限制器 进行匹配
country国家, 会跟 限制器 进行匹配
email邮箱
first_name姓名
last_name姓名
gender性别
id_number身份证件号码
id_type身份证件类型
phone电话
id_end_image身份证件背面照片
id_front_image身份证件正面照片
image1其他身份认证资料(如: 住址生活缴费账单)
image2其他身份认证资料(如: 住址生活缴费账单)