智能合约开发 :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 | 调用合约时创建合约交易 |
- 合约命令通过 Contract调用参数生成器
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"}