NEO smart contract development (2) Continue the impossible task

Author: Li Jianying

Original link: http://www.cnblogs.com/crazylights/p/8457392.html


In NEO smart contract development, the application contract is relatively simple. Yes, you read that right, the application contract is relatively simple.

Apply the contract trilogy, publish, call, and see the results. In addition to the lack of tools to see the results, publishing calls to neogui can at least support your testing.

 

Authentication contracts are more troublesome, because neogui cannot support your well-tested authentication contracts.

 

This is a difficult point. Last time we asked you to use the authentication contract to withdraw money. With a password, anyone can withdraw money. That's it, it's not easy to get it with neogui, right.

 

This time we continue to explore this topic, a more valuable application scenario.

How to limit how much money a user can withdraw from a smart contract?

 

Don't worry, if you can't understand anything here, it's normal. I guess people in China who really understand NEO's authentication mechanism can count them with one hand. A normal NEO learning mechanism should be:

  1. First develop a wallet client
  2. Then understand the invocation of the application contract, and use your own wallet client and scriptbuilder written by yourself to complete the invocation of the application contract.
  3. Learn about authentication contracts, write some authentication contracts, use your own wallet client to trade transactions, and test them.

There is too little information on the NEO official website. Without reading the NEO source code, no normal human can learn these contents through the information on the NEO official website.

 

If you haven't reached this stage and this text is not for you, just do what should be done.

What is the point of restricting withdrawals?

For example, in Nep5's ico mechanism, users invest in NEO and get Nep5 tokens. This is a vending machine mechanism. You give me gas or neo, and I give you game currency. Use UTXO assets, buy NEP5 assets, or whatever.

Then the ico template provided by NEO now has no return mechanism. Because it is difficult to implement, it is not easy to limit how much money users can withdraw from the ico contract.

 

This is the meaning. If you can limit the amount of money you can withdraw, you can realize the ICO automatic return mechanism.

 

To put it another way, the vending machine mechanism has many functions. For example, I help my friend save a sum of money, and he can take it away on his birthday.

 

比如两个人打赌,猜一下五个区块以后的一个随机数的单双,聪明的你马上懂了,实现了用户能从智能合约里面取出多少UTXO资产的限制,就可以直接用UTXO资产进行各种不可描述的赌博业务。

 

再往远了想一想,一个全自动化的交易所,用GAS买入某种NEO代币,等他涨了再卖掉,把GAS取出来。我还没有看过蓝鲸涛公布源码,neox的源码我也没有研究。那这就是他们实现用户自己提取UTXO资产的一个核心机制。

 

这有什么困难的?

很难,第一反应就是storage直接存个值,取得时候存一下,根据这个值,就可以实现任意限制逻辑。

 

想的美。

100个GAS在这放着,有本事去取呀。

放心你取不出来。

这个合约表面上看谁都能取,但是Storage.Put 引发异常,实际上谁也取不出来。

你看,你想的最美的通过Storage去限制取多少,做不到。在鉴权合约触发时,Storage.Put 整个不能用。

 

回想一下ICO模板,是不是没有实现全自动的退款,准确点说就是没有实现任意用户从智能合约提取NEO。就是这个原因。

那就没有办法了嘛?

有一个金句,办法总比困难多。

如果你只是简单的纵览一下,可能会觉得存储这条路被堵住了,一切都不可行了。

让我们仔细来看一下这个逻辑

 

  1. 需要有个限制取钱的机制,取完就不能再取
  2. 需要用Stroage来控制这个机制
  3. 鉴权合约执行时不能Storage.Put

 

看起来好像逻辑链断了,但是当我们想起来UTXO资产本身的一个特质,这个链条就会再次接上。一个UTXO只能被使用一次,没错就是他。这个不正好可以用来控制用户能取多少钱了么?

 

一、需要有个限制取钱的机制(给每个取钱的用户一个专属的UTXO只能他取)

二、需要用Stroage来控制这个机制(storage直接存一个map<utxo,targetaddr>,限制一个utxo只能向一个固定地址转账)

三、鉴权合约执行时不能Storage.put(但是可以Storage.get 呀,bingo)

 

我们把思路稍微调整了一下,就接上了。我们不需要storage直接控制一个用户能取多少钱。1.用storage 控制一个utxo能往哪个地址转账,这可以实现。

2.一个utxo只能转账一次,这是天然的。

这两条加一起,这个自助提取UTXO资产的逻辑就通了。

 

用两笔交易实现自助提取UTXO资产。

 

第一笔,资产不离开智能合约,智能合约向自身转账,生成某用户专用的UTXO,同时做invoke应用合约,记录将此UTXO专用化。

 

第二笔,取钱,用此专用UTXO向用户地址转账。

实践一下

直接看代码

这里只是为了探究这个机制,我们将第一步设定为由超级管理员给用户撒钱。你仔细想想,实现个用户自己从自己的NEP5地址退钱,和这并没太大区别。我们不要让那么多代码来干扰我们实现核心机制。

 

第一步

用这个智能合约自己给自己转账

如图,就是Gas1000,转给自己100GAS,找零900Gas这笔,钱没有离开智能合约地址。

然后超级管理员给超级管理员转账 30536.6 GAS这笔,超级管理员也没出钱。

然后同时调用智能合约,将该笔交易第0个输出的UTXO,设定为只能向地址

AcfW….转账,如图

由于使用了智能合约,需要一个SC的witness,如下图,随便传俩参数,不能用Array

 

让我们分析下上面做了什么

1.智能合约给自己转账,第零个输出是个utxo,100gas,那就意味着,我们允许AcfW…这个地址从智能合约地址里面转走100GAS

2.超级管理员给自己转账,这个不产生直接价值

他只是为了让鉴权合约能走到这里,附加上超级管理员的鉴证,就随便怎么转都行。

也可以使用交易的Attribute附加上超级管理员的鉴证脚本。

  1. APPcall givemoney(0,Acfw…)

就是这部分代码了,将本交易的hash和本交易的第0个输出编成一个Key。

你也许注意到我写了一个ConvertN函数,因为整数的byte[] 形态是什么不太稳定,我需要他是确定的,要不然0000 00 和空byte[] 都表示0,那key就乱套了

然后你看到我直接stroage.put 将目标地址存了起来。这就是第一步。

制造一个100GAS的UTXO,并且在Storage里记录下来给谁。

 

第二步

第二步就简单了,这交易不需要任何人签名

,智能合约的鉴证脚本也是随便填就行

然后你就可以取到钱啦。

 

分析一下

我把这段鉴权合约分为了三个部分

红色部分是判断,这笔交易,只允许有一个输入一个输出,否则你取不走钱。当然你用循环可以处理更复杂的情况,记住我们只是在探究这个机制。

黄色部分是从存储里取到这个UTXO允许的目标

蓝色部分是判断这笔交易的输出目标和Storage里存的是否一致。

一致,钱你拿走,UTXO销毁。

不一致,交易不成立,UTXO还在那里。

 

我们做了什么

综上所述,我们提出了一种可以在NEO框架上实现用户在智能合约限制下提取UTXO资产的机制,并写代码进行了验证。

 

此机制可用于:

  1. 使用NEO的UTXO资产如NEO、GAS 进行ICO的退货机制。
  2. 扩展上一条,可自动贩卖某种数字资产以及退货。
  3. 使用NEO的UTXO资产进行的彩票、下注等活动。
  4. 去中心化交易所的实现。





Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324398776&siteId=291194637