Python智能合约教程之原生合约调用
放弃六月们
发表于 2023-1-9 14:16:58
326
0
0
上一期我们介绍了本体 Python 智能合约的合约执行 API,本期我们将讨论如何通过 Native API 来进行本体原生合约调用。原生合约调用最典型的功能就是合约转账,这也是整个智能合约最核心的部分。Native API 只有1个 API。用法如下:
同时,使用 Invoke 函数需要内建的 state 函数辅助来封装参数,用法如下:" a( P* y5 T. Z: H# W3 O) c
下面我们具体讲述一下这两个 API 的使用方法。在这之前,小伙伴们可以在本体智能合约开发工具 SmartX 中新建一个合约,跟着我们进行操作。跟以前的API讲解一样,在文章最后我们将给出这次讲解的所有源代码以及视频讲解。
02 Native API 使用方法, M: b5 q3 J7 N2 W
同样,使用这两个函数前需要引入。下面两条语句分别引入了这两个函数/ n0 V$ O9 F0 q9 R6 l
from ontology.interop.Ontology.Native import Invoke4 p# ^- l! \" u) y
from ontology.builtins import state0 e' ]% ~/ _% B
2.1 本体原生合约列表
目前,本体可供使用的原生合约有六个。以下就是可以使用 Native API 调用的原生合约列表:
. [: S6 e" F O# i
在合约中,将合约地址转成 bytearray 形式传入 Invoke 即可。例如,需要调用 ONT Token 合约时,可以先将 ONT Token 合约对应的地址转成相应的 bytearray 形式,再进行相应的 Invoke 函数调用。在进行 Invoke 函数调用时,传入的参数分别为版本号,合约地址,调用的合约方法以及 state 函数封装的转账相关参数。: x% C" `0 i" ?2 I
这里特别要注意的一点是,在进行 ONG 的合约转账时,所填数量是实际数量的10^9倍。 即,如果需要转10个 ONG,那么数量需要填为10^10。而在采用 ONTO 或者 Cyano 等钱包转账时,所填数量即为转账数量。2 W& \2 [( U5 X+ n" m; ?
param = state(from_acct, to_acct, ont_amount) # 参数为转出地址,转入地址, 转账金额: Y0 F! H8 g3 ?3 V: e9 z% l
res = Invoke(1, contract_address_ONT, 'transfer', [param])
2.2 转账合约代码9 q" R5 |6 b' F$ o1 w- E/ r
下面我们给出一个完整的示例,演示如何使用 Python 语言来实现 ONT 以及 ONG 的转账功能。下述代码以传入的转出账户和转入地址参数类型为string为例实现该合约。另外,也可以以address为类型的账户参数进行传递,从而达到节省调用Gas费用的目的。该合约代码流程如下:! v9 b1 p" l' I
定义合约地址变量 contract_address_ONT,contract_address_ONG;$ p. m1 U, ^8 }; r" n4 ~9 V
将转出地址和转入地址从 base58 格式转成 bytearray 格式;7 H! U' \( E( `2 P; Z
验签,确认转出地址与合约调用地址为同一地址;
state 函数封装转账相关参数;, a; F h( v. W
Invoke 函数调用 ONT Token 和 ONG Token 原生合约转账;! u: ?) _: X4 B$ W2 x* c1 I
通过返回 res 判断转账是否成功。返回值 b’\x01’ 为成功,成功则推送事件“transfer succeed”。, L! k# M6 a9 O' F* c: J# \' z( C
from ontology.interop.System.Runtime import Notify, CheckWitness0 y1 N) w" _8 B# I; [3 Q/ _# A6 M
from ontology.interop.Ontology.Runtime import Base58ToAddress6 ^$ b0 o) d v2 }! X3 f3 J
from ontology.interop.Ontology.Native import Invoke' }. J. z& u5 D/ P2 s
from ontology.builtins import state# z( ~; D! f$ ]/ |
# contract address * u. z2 p( a. G& m/ S5 s6 o
contract_address_ONT = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01')3 l8 W; J9 A' |) k- J+ X
contract_address_ONG = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02') R. Q, Q0 ^7 j& c
def Main(operation, args):
if operation == 'transfer':
from_acct = args[0]! R; h, T* Y, J
to_acct = args[1]
ont_amount = args[2]
ong_amount = args[3]
return transfer(from_acct,to_acct,ont_amount,ong_amount)
4 m6 ^/ D" P1 j. M% E, n
return False- [: b( D F6 ~; V- E
def transfer(from_acct, to_acct, ont_amount, ong_amount):
# 将base58地址转换成 bytearray格式地址
from_acct=Base58ToAddress(from_acct)6 W5 G% L& ~0 _0 {- y, w/ R
to_acct=Base58ToAddress(to_acct)3 N; X! K+ [9 Z, Y& {9 ^ E
# 验签,调用方必须与转出地址为同一地址
if CheckWitness(from_acct):
# ONT转账! `# s d1 e1 n+ C6 h# t+ ~
if ont_amount > 0:" e/ S: ^- R8 R# S: v2 L
param = state(from_acct, to_acct, ont_amount) # state函数用于封装转账相关参数+ W! ~. A- q- v& {/ w) H. i
res = Invoke(1, contract_address_ONT, 'transfer', [param]) # invoke调用ONT token原生合约转账! u% y1 _- H( x/ f
if res and res == b'\x01':
Notify('transfer succeeded')
else:
Notify('transfer failed')
# ONG转账,流程同上; @* G5 W) K+ p! n0 j' V, k: L
if ong_amount > 0:
param = state(from_acct, to_acct, ong_amount)
res = Invoke(1, contract_address_ONG, 'transfer', [param])3 I& R7 q9 L/ M D$ y
if res and res == b'\x01':
Notify('transfer succeeded')
else:
Notify('transfer failed')- g2 O5 P! L! c' W0 q0 ]/ Q
else:
Notify('CheckWitness failed')8 k4 [+ `( }/ v8 V1 Z/ j2 j9 a
03 SmartX 实践0 q# w+ H; f6 l% `
接下来,小伙伴们可以在 SmartX 上进行操作,动手编译和运行上述提供的合约示例代码。具体步骤如下: B3 z" w. ~# S; ^& _( X5 f- w! k: H$ B
编译合约。首先在 SmartX 中新建一个合约项目,并将代码放入该项目中进行编译。7 I. _% G) B7 k0 ~- o* h; {" C) i
部署合约。部署过程中如需申请测试币,申请地址为https://developer.ont.io/applyOng。部署结果示意如下:' ~; {* u1 J: p# [+ L [& x
9 e9 T8 R: R& |5 o( }2 a; ^1 S
执行转账。执行 transfer 函数进行转账前需要进行相关参数设置。在该示例中,需要填入发送地址、接收地址、代转账的 ONT 数量以及 ONG 数量:
5 V7 l7 p1 F% D5 S: G3 T, K
转账成功。当转帐参数设置正确时,执行 transfer 函数将转账成功。上面所填的接收地址中将显示出收到的代币:
成为第一个吐槽的人