Python智能合约教程之原生合约调用
放弃六月们
发表于 2023-1-9 14:16:58
329
0
0
上一期我们介绍了本体 Python 智能合约的合约执行 API,本期我们将讨论如何通过 Native API 来进行本体原生合约调用。原生合约调用最典型的功能就是合约转账,这也是整个智能合约最核心的部分。Native API 只有1个 API。用法如下:3 D0 s' y6 h1 }+ s. u" K
同时,使用 Invoke 函数需要内建的 state 函数辅助来封装参数,用法如下:
下面我们具体讲述一下这两个 API 的使用方法。在这之前,小伙伴们可以在本体智能合约开发工具 SmartX 中新建一个合约,跟着我们进行操作。跟以前的API讲解一样,在文章最后我们将给出这次讲解的所有源代码以及视频讲解。
02 Native API 使用方法
同样,使用这两个函数前需要引入。下面两条语句分别引入了这两个函数& j- y& q# Q6 \+ N* w0 ]/ I
from ontology.interop.Ontology.Native import Invoke' A. P! ~. c% Z5 w
from ontology.builtins import state
2.1 本体原生合约列表
目前,本体可供使用的原生合约有六个。以下就是可以使用 Native API 调用的原生合约列表:) g C& F8 i0 W
在合约中,将合约地址转成 bytearray 形式传入 Invoke 即可。例如,需要调用 ONT Token 合约时,可以先将 ONT Token 合约对应的地址转成相应的 bytearray 形式,再进行相应的 Invoke 函数调用。在进行 Invoke 函数调用时,传入的参数分别为版本号,合约地址,调用的合约方法以及 state 函数封装的转账相关参数。0 W0 H; C$ h$ F0 F9 b, R2 I& _
这里特别要注意的一点是,在进行 ONG 的合约转账时,所填数量是实际数量的10^9倍。 即,如果需要转10个 ONG,那么数量需要填为10^10。而在采用 ONTO 或者 Cyano 等钱包转账时,所填数量即为转账数量。
param = state(from_acct, to_acct, ont_amount) # 参数为转出地址,转入地址, 转账金额
res = Invoke(1, contract_address_ONT, 'transfer', [param])
2.2 转账合约代码: Z3 f* W b$ g0 o, R- C* w5 D
下面我们给出一个完整的示例,演示如何使用 Python 语言来实现 ONT 以及 ONG 的转账功能。下述代码以传入的转出账户和转入地址参数类型为string为例实现该合约。另外,也可以以address为类型的账户参数进行传递,从而达到节省调用Gas费用的目的。该合约代码流程如下:
定义合约地址变量 contract_address_ONT,contract_address_ONG;/ B5 D- W1 o) m, o$ d* u1 B7 x) v
将转出地址和转入地址从 base58 格式转成 bytearray 格式;/ j+ Q8 N! z+ s( Q" @
验签,确认转出地址与合约调用地址为同一地址;4 z+ p: i8 ~. ]+ _+ G1 g
state 函数封装转账相关参数;' d( \) d# u+ ]% X
Invoke 函数调用 ONT Token 和 ONG Token 原生合约转账;( @/ [, J# \' x8 \+ i; l9 F
通过返回 res 判断转账是否成功。返回值 b’\x01’ 为成功,成功则推送事件“transfer succeed”。
from ontology.interop.System.Runtime import Notify, CheckWitness' w! C5 c6 l5 ]
from ontology.interop.Ontology.Runtime import Base58ToAddress# F0 ], x4 [+ q) e9 W' s- o6 j8 d
from ontology.interop.Ontology.Native import Invoke
from ontology.builtins import state; @' X! P Z6 H0 D6 D t
# contract address
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')2 A' p# C! b% 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$ N8 O& W% j" P' B
def Main(operation, args):
if operation == 'transfer':
from_acct = args[0]
to_acct = args[1]7 {% {; t8 e2 c- N) ]' p: t
ont_amount = args[2]
ong_amount = args[3]) [% j# K1 a6 C- n
return transfer(from_acct,to_acct,ont_amount,ong_amount)
! i. Q1 U# H5 }$ a" {
return False& k9 j: O9 l1 A b$ K$ A2 _* \, m0 y
def transfer(from_acct, to_acct, ont_amount, ong_amount):
# 将base58地址转换成 bytearray格式地址
from_acct=Base58ToAddress(from_acct)3 Q+ n6 n" a4 b c" D
to_acct=Base58ToAddress(to_acct)
# 验签,调用方必须与转出地址为同一地址7 B. @5 Y1 V, H' v
if CheckWitness(from_acct):
# ONT转账& M" f8 A- j0 z, d R' l- r- ~
if ont_amount > 0:1 S/ y, C8 \% S6 c) g
param = state(from_acct, to_acct, ont_amount) # state函数用于封装转账相关参数
res = Invoke(1, contract_address_ONT, 'transfer', [param]) # invoke调用ONT token原生合约转账( R! y1 C5 N9 `% ^$ q$ ^( _
if res and res == b'\x01':. f* i% R& G% m( M
Notify('transfer succeeded')
else:
Notify('transfer failed')+ O9 y& u" R# s/ y( f3 u
# ONG转账,流程同上
if ong_amount > 0:9 \+ f3 y& M1 |+ Y1 ~* U: m
param = state(from_acct, to_acct, ong_amount)# U8 n" J! \7 \' Q
res = Invoke(1, contract_address_ONG, 'transfer', [param])
if res and res == b'\x01':
Notify('transfer succeeded')
else:
Notify('transfer failed')* e. \( ?$ I6 g) [) L& R7 g9 u; E
else:
Notify('CheckWitness failed')+ U( @4 u; g) M; \! g5 f9 V3 h) o
( x( {3 J9 n# t( K1 N
03 SmartX 实践
接下来,小伙伴们可以在 SmartX 上进行操作,动手编译和运行上述提供的合约示例代码。具体步骤如下:4 O' z$ R7 ?' P4 f0 O
7 x0 L# ^: R! t+ i9 A0 V$ ~/ C6 W
编译合约。首先在 SmartX 中新建一个合约项目,并将代码放入该项目中进行编译。- `( y! h+ ~+ V7 U6 g+ x
部署合约。部署过程中如需申请测试币,申请地址为https://developer.ont.io/applyOng。部署结果示意如下:4 T! `$ Y' Y. [+ g! F: V6 ?5 r
, G7 O& d" p, ]+ s4 E; L6 g9 R+ n& l
- J, n# G2 W6 d; M
执行转账。执行 transfer 函数进行转账前需要进行相关参数设置。在该示例中,需要填入发送地址、接收地址、代转账的 ONT 数量以及 ONG 数量:6 i9 ], ?- q' Y
* M) e I% J8 `9 W% a% c
' ?7 j0 e8 F* ^. \ F
转账成功。当转帐参数设置正确时,执行 transfer 函数将转账成功。上面所填的接收地址中将显示出收到的代币:
成为第一个吐槽的人