维基链开发(9)--智能合约开发-token合约

智能合约开发 :token Sample

本文为维基链智能合约开发进阶,发布一个代币合约,详见官方文档

1.合约源码

mylib = require "mylib"

-----------------------------------------------------------------------------------------------------------

-- Please do not change the common key
standardKey = "standard"
ownerKey = "owner"
nameKey = "name"
symbolKey = "symbol"

-- The Developer should change the value for contract

-- the waykichain contract stardard, if you do not know the waykichain stardard, please do not change it.
standard = "WS1802"

-- the contract ownder address, please write the right address
owner = "wd3hLkmd5Jrmck4Rsg8WCcJ3PfFrKFDbbA"

-- the contract name
name="ICOS"

-- the contract symbol
symbol="ICO Sample"

-- the contract coin total supply,100000000 is for decimal, the decimal digits is 8.
totalSupply = 210000000 * 100000000

----------------------------------------------below is internal method and table ---------------------------------------------------------------

OP_TYPE = {
    ADD_FREE     = 1,
    SUB_FREE     = 2
}
ADDR_TYPE = {
    REGID  = 1,
    BASE58 = 2
}
TX_TYPE =
{
  TX_CONFIG = 0x11,
  TX_SEND_ASSET = 0x16,
}

TableIsNotEmpty = function (t)
    return _G.next(t) ~= nil
end

Unpack = function (t,i)
    i = i or 1
    if t[i] then
      return t[i], Unpack(t,i+1)
    end
end

LogMsg = function (msg)
   local logTable = {
        key = 3,
        length = string.len(msg),
        value = msg
  }
  mylib.LogPrint(logTable)
end

GetContractValue = function (key)
    assert(#key > 0, "Key is empty")

    local tValue = { mylib.ReadData(key) }
    if TableIsNotEmpty(tValue) then
      return true,tValue
    else
      LogMsg("Key not exist")
      return false,nil
    end
end

GetContractTxParam = function (startIndex, length)
    assert(startIndex > 0, "GetContractTxParam start error(<=0).")
    assert(length > 0, "GetContractTxParam length error(<=0).")
    assert(startIndex+length-1 <= #contract, "GetContractTxParam length ".. length .." exceeds limit: " .. #contract)

    local newTbl = {}
    local i = 1
    for i = 1,length do
      newTbl[i] = contract[startIndex+i-1]
    end
    return newTbl
end

WriteAppData = function (opType, moneyTbl, userIdTbl)
    local appOperateTbl = {
      operatorType = opType,
      outHeight = 0,
      moneyTbl = moneyTbl,
      userIdLen = #userIdTbl,
      userIdTbl = userIdTbl,
      fundTagLen = 0,
      fundTagTbl = {}
    }
    assert(mylib.WriteOutAppOperate(appOperateTbl), "WriteAppData: ".. opType .." op err")
end

GetFreeTokenCount = function (accountTbl)
    local freeMoneyTbl = { mylib.GetUserAppAccValue( {idLen = #accountTbl, idValueTbl = accountTbl} ) }
    assert(TableIsNotEmpty(freeMoneyTbl), "GetUserAppAccValue error")
    return mylib.ByteToInteger(Unpack(freeMoneyTbl))
end

TransferToken = function (fromAddrTbl, toAddrTbl, moneyTbl)
    local money = mylib.ByteToInteger(Unpack(moneyTbl))
    assert(money > 0, money .. " <=0 error")
    local freeMoney = GetFreeTokenCount(fromAddrTbl)
    assert(freeMoney >= money, "Insufficient money to transfer in the account.")

    WriteAppData(OP_TYPE.SUB_FREE, moneyTbl, fromAddrTbl )
    WriteAppData(OP_TYPE.ADD_FREE, moneyTbl, toAddrTbl )
end

GetCurrTxAccountAddress = function ()
    return {mylib.GetBase58Addr(mylib.GetCurTxAccount())}
end

------------------------------------below is contract method to caller------------------------------------------------------------------------

--trasfer assert
function Send()
  local valueTbl = {}
  local isConfig = false
  isConfig,valueTbl = GetContractValue("config")
  if not isConfig then
	LogMsg("Not configured")
    error("Not configured")
  end

  base58Addr = GetCurrTxAccountAddress()
  assert(TableIsNotEmpty(base58Addr),"GetBase58Addr error")
  local pos = 5
  local toAddrTbl = GetContractTxParam(pos, 34)
  pos = pos + 34
  local moneyTbl = GetContractTxParam(pos, 8)

  TransferToken(base58Addr, toAddrTbl, moneyTbl)
end

function Config()
  local valueTbl = {}
  local isConfig = false
  isConfig,valueTbl = GetContractValue("config")
  if isConfig then
    LogMsg("Already configured")
    error("Already configured")
  end

  local writeConfigTbl = {
    key = "config",
    length = #contract,
    value = contract
  }
  if not mylib.WriteData(writeConfigTbl) then
    LogMsg("SaveConfig WriteData error")
    error("SaveConfig WriteData error")
  end

  local standardTbl = {string.byte(standard,1,string.len(standard))}
  local writeStandardTbl = {
    key = standardKey,
    length = #standardTbl,
    value = standardTbl
  }
  if not mylib.WriteData(writeStandardTbl) then
    LogMsg("Standard WriteData error.")
    error("Standard WriteData error.")
  end

  local ownerTbl = {string.byte(owner,1,string.len(owner))}
  local writOwnerTbl = {
    key = ownerKey,
    length = #ownerTbl,
    value = ownerTbl
  }
  if not mylib.WriteData(writOwnerTbl) then
    LogMsg("Owner WriteData error.")
    error("Owner WriteData error.")
  end

  local nameTbl = {string.byte(name,1,string.len(name))}
  local writNameTbl = {
    key = nameKey,
    length = #nameTbl,
    value = nameTbl
  }
  if not mylib.WriteData(writNameTbl) then
    LogMsg("Name WriteData error.")
    error("Name WriteData error.")
  end

  local symbolTbl = {string.byte(symbol,1,string.len(symbol))}
  local writeSymbolTbl = {
    key = symbolKey,
    length = #symbolTbl,
    value = symbolTbl
  }
  if not mylib.WriteData(writeSymbolTbl) then
    LogMsg("Symbol WriteData error.")
    error("Symbol WriteData error.")
  end

  local totalSupplyTbl =  {mylib.IntegerToByte8(totalSupply)}
  WriteAppData(OP_TYPE.ADD_FREE, totalSupplyTbl, ownerTbl)
end

function Main()
  assert(#contract >=2, "Param length error (<2): " ..#contract )
  assert(contract[1] == 0xf0, "Param MagicNo error (~=0xf0): " .. contract[1])

  if contract[2] == TX_TYPE.TX_CONFIG then
    Config()
  elseif contract[2] == TX_TYPE.TX_SEND_ASSET then
    Send()
  else
    error('method# '..string.format("%02x", contract[2])..' not found')
  end
end

Main()

2.部署智能合约

  • 任何地址都可以发布智能合约,智能合约发布者不一定是合约的拥有者。
Used API Description
registercontracttx 用于发布智能合约

Example

curl -u Waykichain:admin -d '{"jsonrpc":"2.0","id":"curltext","method":"registercontracttx","params":["wd3hLkmd5Jrmck4Rsg8WCcJ3PfFrKFDbbA","/tmp/lua/sample.lua",110000000]}' -H 'content-type:application/json;' http://127.0.0.1:6967
{"result":{"hash":"43ce796da7c92a7aa29ac3f3778114a20496babcae9130cb1539db89bd450739"},"error":null,"id":"curltext"}

3. 查询智能合约的regid

Used API Description
getcontractregid 通过发布智能合约时产生的交易hash,来查询合约的regid
getaccountinfo 查询合约详细信息

Example

curl -u Waykichain:admin -d '{"jsonrpc":"2.0","id":"curltext","method":"getcontractregid","params":["43ce796da7c92a7aa29ac3f3778114a20496babcae9130cb1539db89bd450739"]}' -H 'content-type:application/json;' http://127.0.0.1:6967
{"result":{"regid:":"346703-1","script":"4f4a05000100"},"error":null,"id":"curltext"}

curl -u Waykichain:admin -d '{"jsonrpc":"2.0","id":"curltext","method":"getaccountinfo","params":["346703-1"]}' -H 'content-type:application/json;' http://127.0.0.1:6967
{"result":{"Address":"wTP1JcKfoJXbFa3hzq47rp7bciJtf3GrWQ","KeyID":"5506a1383e34feee6b1aed77a18067a6ebe32ca1","RegID":"346703-1","PublicKey":"","MinerPKey":"","Balance":0,"Votes":0,"UpdateHeight":0,"voteFundList":[],"postion":"inblock"},"error":null,"id":"curltext"}

4. 查询合约代币金额

Used API Description
getcontractaccountinfo 查询地址在某个合约拥有币的数量。

Example

curl -u Waykichain:admin -d '{"jsonrpc":"2.0","id":"curltext","method":"getcontractaccountinfo","params":["346703-1","wd3hLkmd5Jrmck4Rsg8WCcJ3PfFrKFDbbA"]}' -H 'content-type:application/json;' http://127.0.0.1:6967
{"result":{"mAccUserID":"776433684c6b6d64354a726d636b34527367385743634a33506646724b4644626241","FreeValues":0,"vFreezedFund":[]},"error":null,"id":"curltext"}

5. 调用合约配置合约代币参数

Used API Description
callcontracttx 调用合约命令来配置合约信息
  • 合约命令
          +--------+--------------+
          |  魔法数 + 指定的合约方法 |
"f011" =  +--------+--------------
          |  0xf0  |  0x11        |
          +--------+--------------+

Example

curl -u Waykichain:admin -d '{"jsonrpc":"2.0","id":"curltext","method":"callcontracttx","params":["wd3hLkmd5Jrmck4Rsg8WCcJ3PfFrKFDbbA","346703-1",0,"f011",1000000]}' -H 'content-type:application/json;' http://127.0.0.1:6967
{"result":{"hash":"647400c0fd9b345bed73925fbb36efc08b895f800007daf0e09c660346c46e9f"},"error":null,"id":"curltext"}

6. 获取合约owner

Used API Description
getcontractdata 获取智能合约相关数据信息
+--------------------------------------+---------------------------------------------------------------------+
| String                               |     hex                                                             |
+------------------------------------------------------------------------------------------------------------+
| "owner"                              |  6f776e6572                                                         |
+--------------------------------------+---------------------------------------------------------------------+
| "wd3hLkmd5Jrmck4Rsg8WCcJ3PfFrKFDbbA" | 776433684c6b6d64354a726d636b34527367385743634a33506646724b4644626241|
+------------------------------------------------------------------------------------------------------------+

Example

curl -u Waykichain:admin -d '{"jsonrpc":"2.0","id":"curltext","method":"getscriptdata","params":["346703-1","6f776e6572"]}' -H 'content-type:application/json;' http://127.0.0.1:6967
{"result":{"scritpid":"346703-1","key":"6f776e6572","value":"776433684c6b6d64354a726d636b34527367385743634a33506646724b4644626241"},"error":null,"id":"curltext"}

7. 检查合约代币金额

Used API Description
getcontractaccountinfo 查询地址在某个合约拥有币的数量

Example

curl -u Waykichain:admin -d '{"jsonrpc":"2.0","id":"curltext","method":"getcontractaccountinfo","params":["346703-1","wd3hLkmd5Jrmck4Rsg8WCcJ3PfFrKFDbbA"]}' -H 'content-type:application/json;' http://127.0.0.1:6967
{"result":{"mAccUserID":"776433684c6b6d64354a726d636b34527367385743634a33506646724b4644626241","FreeValues":21000000000000000,"vFreezedFund":[]},"error":null,"id":"curltext"}

8. 对代币进行转账

Used API Description
callcontracttx 调用合约时创建合约交易

example

“f01600007756436654696d326d374636753571743953556978556e6762716b70474d6f534c361027000000000000”  =
+--------------+---------------------+----------------+---------------------------------------------------------------------+-------------------------------+
|魔法数(1 byte)+ 指定的合约方法(1 byte)+ 保留位(2 bytes)+ receiver:wVCfTim2m7F6u5qt9SUixUngbqkpGMoSL6(34 bytes)               + 金额:1000`sawi`(8 bytes)  |
+--------------+---------------------+----------------+---------------------------------------------------------------------+-------------------------------+
|  0xf0        |  0x16               | 0000           |7756436654696d326d374636753571743953556978556e6762716b70474d6f534c36 | 1027000000000000              |
+--------------+---------------------+----------------+---------------------------------------------------------------------+-------------------------------+

Example

curl -u Waykichain:admin -d '{"jsonrpc":"2.0","id":"curltext","method":"callcontracttx","params":["wd3hLkmd5Jrmck4Rsg8WCcJ3PfFrKFDbbA","346703-1",0,"f01600007756436654696d326d374636753571743953556978556e6762716b70474d6f534c361027000000000000",1000000]}' -H 'content-type:application/json;' http://127.0.0.1:6967
{"result":{"hash":"d841dfa77a5785297e643fd372e893943a8348b6b9660287adcb0eaafb52addb"},"error":null,"id":"curltext"}

9. 确认转账是否成功

Example

curl -u Waykichain:admin -d '{"jsonrpc":"2.0","id":"curltext","method":"getcontractaccountinfo","params":["346703-1","wVCfTim2m7F6u5qt9SUixUngbqkpGMoSL6"]}' -H 'content-type:application/json;' http://127.0.0.1:6967
{"result":{"mAccUserID":"7756436654696d326d374636753571743953556978556e6762716b70474d6f534c36","FreeValues":10000,"vFreezedFund":[]},"error":null,"id":"curltext"}


发布了32 篇原创文章 · 获赞 15 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/u010159567/article/details/88427385