Python智能合约教程之原生合约调用
放弃六月们
发表于 2023-1-9 14:16:58
457
0
0
上一期我们介绍了本体 Python 智能合约的合约执行 API,本期我们将讨论如何通过 Native API 来进行本体原生合约调用。原生合约调用最典型的功能就是合约转账,这也是整个智能合约最核心的部分。Native API 只有1个 API。用法如下:
同时,使用 Invoke 函数需要内建的 state 函数辅助来封装参数,用法如下:
下面我们具体讲述一下这两个 API 的使用方法。在这之前,小伙伴们可以在本体智能合约开发工具 SmartX 中新建一个合约,跟着我们进行操作。跟以前的API讲解一样,在文章最后我们将给出这次讲解的所有源代码以及视频讲解。# P0 U. a- m) k( I; Q* `# Y4 t* O
02 Native API 使用方法) N |- t( `2 K4 K
同样,使用这两个函数前需要引入。下面两条语句分别引入了这两个函数
from ontology.interop.Ontology.Native import Invoke
from ontology.builtins import state
2.1 本体原生合约列表# h0 p( H, C5 P$ f
目前,本体可供使用的原生合约有六个。以下就是可以使用 Native API 调用的原生合约列表:
4 ^1 _8 R' p) H* M
在合约中,将合约地址转成 bytearray 形式传入 Invoke 即可。例如,需要调用 ONT Token 合约时,可以先将 ONT Token 合约对应的地址转成相应的 bytearray 形式,再进行相应的 Invoke 函数调用。在进行 Invoke 函数调用时,传入的参数分别为版本号,合约地址,调用的合约方法以及 state 函数封装的转账相关参数。9 {) C6 T0 I, W
这里特别要注意的一点是,在进行 ONG 的合约转账时,所填数量是实际数量的10^9倍。 即,如果需要转10个 ONG,那么数量需要填为10^10。而在采用 ONTO 或者 Cyano 等钱包转账时,所填数量即为转账数量。/ i, ~" p0 q0 }. l3 a; K
param = state(from_acct, to_acct, ont_amount) # 参数为转出地址,转入地址, 转账金额
res = Invoke(1, contract_address_ONT, 'transfer', [param])
2.2 转账合约代码! @- E% R3 i5 @5 w. R' F
下面我们给出一个完整的示例,演示如何使用 Python 语言来实现 ONT 以及 ONG 的转账功能。下述代码以传入的转出账户和转入地址参数类型为string为例实现该合约。另外,也可以以address为类型的账户参数进行传递,从而达到节省调用Gas费用的目的。该合约代码流程如下:0 e, j" w+ V+ ~
定义合约地址变量 contract_address_ONT,contract_address_ONG;
将转出地址和转入地址从 base58 格式转成 bytearray 格式;' O- a% S4 Z0 q' f7 G) e! P( q
验签,确认转出地址与合约调用地址为同一地址;: t# }8 P/ \$ @: O% f0 y# |
state 函数封装转账相关参数; B' }! z' n9 t9 l9 X4 e- k2 D$ [
Invoke 函数调用 ONT Token 和 ONG Token 原生合约转账;0 l7 Q1 W4 Z: ^1 `, V
通过返回 res 判断转账是否成功。返回值 b’\x01’ 为成功,成功则推送事件“transfer succeed”。& F; k( n. @6 G
from ontology.interop.System.Runtime import Notify, CheckWitness
from ontology.interop.Ontology.Runtime import Base58ToAddress
from ontology.interop.Ontology.Native import Invoke) ?/ A% G# B& l( ^6 m
from ontology.builtins import state
# contract address + ^0 B' x% H! q
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')( K: S) r+ G8 p( Z6 n
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')6 t7 Z% f: z* B0 A2 _* }
def Main(operation, args):
if operation == 'transfer':
from_acct = args[0]6 y# |6 a; U, y
to_acct = args[1]
ont_amount = args[2]
ong_amount = args[3]- i! p( P/ z. G/ g0 j# R! b2 m
return transfer(from_acct,to_acct,ont_amount,ong_amount)7 E2 [! M/ a$ S
2 G! [# `( y7 _ Y/ w, U, D& w
return False8 o3 G2 ] s; z6 u, B e' l: b: y
def transfer(from_acct, to_acct, ont_amount, ong_amount):
# 将base58地址转换成 bytearray格式地址
from_acct=Base58ToAddress(from_acct)
to_acct=Base58ToAddress(to_acct)" | x& y4 l6 }
# 验签,调用方必须与转出地址为同一地址: B# w7 A% P7 [8 w
if CheckWitness(from_acct):4 P& h" l, x* E
# ONT转账& s1 C; B7 h* v9 W
if ont_amount > 0:
param = state(from_acct, to_acct, ont_amount) # state函数用于封装转账相关参数8 B! U. R5 s" J7 [& z1 p
res = Invoke(1, contract_address_ONT, 'transfer', [param]) # invoke调用ONT token原生合约转账
if res and res == b'\x01':
Notify('transfer succeeded')
else:
Notify('transfer failed')8 ]' u/ |. \7 a8 K$ [
# ONG转账,流程同上
if ong_amount > 0:4 A5 W) E# |. L9 Y3 `$ {
param = state(from_acct, to_acct, ong_amount)/ C$ S. l, q' g: x$ H! A
res = Invoke(1, contract_address_ONG, 'transfer', [param])
if res and res == b'\x01':
Notify('transfer succeeded')
else:; J& z3 D1 [7 M0 o2 L+ B& \
Notify('transfer failed')
else:/ A% { U3 K3 w0 |5 V
Notify('CheckWitness failed')7 ]3 R, G% p/ S0 U1 F
( y0 V- H/ D2 J, {+ f% `+ h1 U2 @
03 SmartX 实践& i" c" {0 P+ p' p# }' K$ W( p
接下来,小伙伴们可以在 SmartX 上进行操作,动手编译和运行上述提供的合约示例代码。具体步骤如下:: [) U) H" r( e4 L$ y9 {
7 g% G. o# N$ c' y, ?
编译合约。首先在 SmartX 中新建一个合约项目,并将代码放入该项目中进行编译。7 J T6 r, g! ^& D
X% R8 o9 S; k- q. ~8 T
4 Y2 m$ W; e: C( W% y
部署合约。部署过程中如需申请测试币,申请地址为https://developer.ont.io/applyOng。部署结果示意如下:$ K$ D y% Y8 X9 v* h, d
. U5 g: s/ P" ~$ ]% f: y. e
9 k4 {' J U' ^7 p
3 B3 i. L0 g2 s
执行转账。执行 transfer 函数进行转账前需要进行相关参数设置。在该示例中,需要填入发送地址、接收地址、代转账的 ONT 数量以及 ONG 数量:$ S6 J8 C; |& Y+ s5 l) K
( w' H R9 `- _6 B- x' J
转账成功。当转帐参数设置正确时,执行 transfer 函数将转账成功。上面所填的接收地址中将显示出收到的代币:
成为第一个吐槽的人