孤荷凌寒自学python第126天区块链040以太坊的 erc20代币10

孤荷凌寒自学python第126天区块链040以太坊的 erc20代币10

【主要内容】

今天继续使用erc20标准规范按另一篇网络博文的教程进行复制代码来批注一个可以发行代币的智能合约。学习共用时50分钟。

(此外整理作笔记花费了约52分钟)

详细学习过程见文末学习过程屏幕录像。

 

【学习笔记】

一、今天首先通过remix在线编译器成功向测试eth网络部署了合约:

本次学习使用的智能合约一次性编译通过,没有任何警告信息与错误提示。

部署成功的合约地址是:0xf89074dcdd8798b7e20b8cd88a9a38f27479411c

 

二、今天通过写Python代码来与智能合约交互,明白了调用合约的两种情况

一种情况是:需要支付gas才能调用的智能合约中的函数,这种合约中的函数的操作结果会被记录到区块中,因此需要矿工产出新区块并进行打包进区块的操作,因此需要支付gas,这种合约函数不是静态的,函数的修饰关键词不是使用的constant或view.

要调用合约中的这种非静态函数,就需要在调用函数之后,调用函数的

buildTransaction()

方法来进行事务(交易)信息生成,以向网络支付gas。

 

如:

```

    #下面调用了合约的发起授权的函数

    txn_dict = contract.functions.approve(receiveadd,approvevalue).buildTransaction({

        'chainId': 3, #指测试网络

        'gas': 140000,

        'gasPrice': w3.toWei('40', 'gwei'),

        'nonce': nonce,

    })

    #开始执行发送方的私钥签名操作

    signed_txn = w3.eth.account.signTransaction(txn_dict, private_key=sendprivate) #这儿使用发起授权操作节点的私钥来签名

    #向网络发送交易信息

    result = w3.eth.sendRawTransaction(signed_txn.rawTransaction)

    #准备接收发送回执

    tx_receipt = w3.eth.getTransactionReceipt(result)

 

```

第二种情况是:不需要支付gas就可以调用的合约中的函数,因为这些合约函数是静态函数,不产生需要打包到区块中的任何信息,因此直接调用即可,只需要调用合约函数的call()方法即可。

如:

```

    return contract.functions.isApproved(address).call()

```

 

三、今天写的用以调用合约的Python代码

```

import time

from web3 import Web3, HTTPProvider

 

import contract_abi

 

contract_address="0xf89074dcdd8798b7e20b8cd88a9a38f27479411c"  #CloudImage代币合约地址,就是我自己创建(部署)的智能合约

 

#下面两行定义的是部署合约的节点(创世节点)的信息,私钥和公钥

wallet_private_key="D8EF07D32389148E9DA6C54237BD5A39C92917D59340AA5D6064485C01E96FB2" #狐狸钱包的私钥

wallet_address="0x5227C3EF48B5A1bcF784593e46D9579D26a3b592" #狐狸钱包的公钥,就是钱包地址,是eth网络上的一个节点。

#下面两行定义的是节点2的信息

w2pkey="D5EC2E192E0362FF81B46F6AFB331772F85CE9B4A79F2A0962858301E72AAF1C" #私钥

w2add="0xe2d6c2f289c53B5aEA44C47293Ba179a3bfa21f0" #公钥

 

#下面两行定义的是节点3 的信息

w3pkey="1DCA9DF70412154D19FA78EFDAD1E9AC4AB60FB44DCFBC4323051DDF3141E98A" #私钥

w3add="0x70c8461366d5368B1E79CBFc2Acf4ba56C745977" #公钥

 

w3 = Web3(HTTPProvider("https://ropsten.infura.io/v3/79124269dc454e47bee73f964c971d3c")) #里面的参数字符串是在infura.io网站上申请 到的一个节点地址。

 

w3.eth.enable_unaudited_features() #确认我们知道可能会发生问题的情况。

 

contract = w3.eth.contract(address = contract_address, abi = contract_abi.abi)

#---上一行中,contract_abi.abi,表示引用了存放在contract_abi.py文件中的变量abi的列表

#---整个代码就是通过智能合约在eth网络上的地址 和对应ABI连接列表来得到指定的智能合约对象contract

 

print(w3.eth.blockNumber) #打印eth网络最后一个区块的id

 

def transfer(toadd,v):

    nonce = w3.eth.getTransactionCount(wallet_address)

 

    txn_dict = contract.functions.transfer(toadd,v).buildTransaction({

        'chainId': 3, #指测试网络

        'gas': 140000,

        'gasPrice': w3.toWei('40', 'gwei'),

        'nonce': nonce,

    })

 

    signed_txn = w3.eth.account.signTransaction(txn_dict, private_key=wallet_private_key)

 

    result = w3.eth.sendRawTransaction(signed_txn.rawTransaction)

 

    tx_receipt = w3.eth.getTransactionReceipt(result)

 

    count = 0

    while tx_receipt is None and (count < 30):

 

        time.sleep(10)

 

        tx_receipt = w3.eth.getTransactionReceipt(result)

 

        print(tx_receipt)

 

        count+=1

 

    if tx_receipt is None:

        return {'status': 'failed', 'error': 'timeout'}

 

    processed_receipt = contract.events.Transfer().processReceipt(tx_receipt)

    #---监测智能合约的事件的写法与调用智能合约的函数的写法是不同的。-----

    #---将tx_receipt作为参数传入,作用是定位吗?用以确定是哪个互动引发的事件?

 

    print(processed_receipt)

    #---processed_receipt变量中得到了通过监听事件而获取的事件广播的全部信息(合约中的此事件广播了两个信息:一个是发起交易方的地址,二个是发表的意见。)

   

    output = "Address {} broadcasted the opinion: {}"\

        .format(processed_receipt[0].args._soapboxer, processed_receipt[0].args._opinion)

    #上一行代码将两个信息分别提取出来 ,使用到了.args子对象,args子对象中包含了智能合约指定事件的两个形参的标识名称。

    #--注意这儿使用了processed_receipt[0],说明包含了多个事件广播 的内容。

    print(output)

 

    return {'status': 'added', 'processed_receipt': processed_receipt}

 

def approve(sendadd,receiveadd,sendprivate,approvevalue):

    nonce = w3.eth.getTransactionCount(sendadd) #这儿使用的发起授权操作节点的地址

 

    #下面调用了合约的发起授权的函数

    txn_dict = contract.functions.approve(receiveadd,approvevalue).buildTransaction({

        'chainId': 3, #指测试网络

        'gas': 140000,

        'gasPrice': w3.toWei('40', 'gwei'),

        'nonce': nonce,

    })

    #开始执行发送方的私钥签名操作

    signed_txn = w3.eth.account.signTransaction(txn_dict, private_key=sendprivate) #这儿使用发起授权操作节点的私钥来签名

    #向网络发送交易信息

    result = w3.eth.sendRawTransaction(signed_txn.rawTransaction)

    #准备接收发送回执

    tx_receipt = w3.eth.getTransactionReceipt(result)

 

    count = 0

    while tx_receipt is None and (count < 60):

 

        time.sleep(10)

 

        tx_receipt = w3.eth.getTransactionReceipt(result)

 

        print(tx_receipt)

 

        count+=1

 

    #如果收到回执,检查

    if tx_receipt is None:

        return {'status': 'failed', 'error': 'timeout'}

 

    #监听本次事务(交易)的事件广播

    processed_receipt = contract.events.Approval().processReceipt(tx_receipt)

    #---监测智能合约的事件的写法与调用智能合约的函数的写法是不同的。-----

    #---将tx_receipt作为参数传入,作用是定位吗?用以确定是哪个互动引发的事件?

 

    print(processed_receipt)

    #---processed_receipt变量中得到了通过监听事件而获取的事件广播的全部信息(合约中的此事件广播了两个信息:一个是发起交易方的地址,二个是发表的意见。)

   

    output = "Address {} broadcasted the opinion: {}"\

        .format(processed_receipt[0].args._soapboxer, processed_receipt[0].args._opinion)

    #上一行代码将两个信息分别提取出来 ,使用到了.args子对象,args子对象中包含了智能合约指定事件的两个形参的标识名称。

    #--注意这儿使用了processed_receipt[0],说明包含了多个事件广播 的内容。

    print(output)

 

    return {'status': 'added', 'processed_receipt': processed_receipt}



#执行代币转移---

#r=transfer(w2add,100)

#print(r)

 

#节点一向节点二授权可以使用节点一的200个代币

r=approve(wallet_address,w2add,wallet_private_key,200)

print(r)

 

```

下面是部分执行结果:

```

#下面是转移代币的调用:

6029924

None

None

None

None

None

None

None

None

None

None

None

None

None

None

None

NoneNoneNoneAttributeDict({'blockHash': HexBytes('0x2294b1a138e00eaacbfa5b6d960c244cf5ebde594ee613edcbe0529e0bd9ed02'), 'blockNumber': 6029926, 'contractAddress': None, 'cumulativeGasUsed': 144768, 'from': '0x5227c3ef48b5a1bcf784593e46d9579d26a3b592', 'gasUsed': 52059, 'logs': [AttributeDict({'address': '0xF89074dcDd8798B7E20b8cd88A9a38F27479411C', 'blockHash': HexBytes('0x2294b1a138e00eaacbfa5b6d960c244cf5ebde594ee613edcbe0529e0bd9ed02'), 'blockNumber': 6029926, 'data': '0x0000000000000000000000000000000000000000000000000000000000000064', 'logIndex': 1, 'removed': False, 'topics': [HexBytes('0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'), HexBytes('0x0000000000000000000000005227c3ef48b5a1bcf784593e46d9579d26a3b592'), HexBytes('0x000000000000000000000000e2d6c2f289c53b5aea44c47293ba179a3bfa21f0')], 'transactionHash': HexBytes('0xca06c97cf89de38927db10e422308ecc7288f2fbd3869d0bff7cbed2295f890a'), 'transactionIndex': 3})], 'logsBloom': HexBytes('0x00200000000000000000000080000000000000000000000000000000000000000000000000000040000000000400000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000040000000000000000000000002000000000000000000000000000010000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000'), 'status': 1, 'to': '0xf89074dcdd8798b7e20b8cd88a9a38f27479411c', 'transactionHash': HexBytes('0xca06c97cf89de38927db10e422308ecc7288f2fbd3869d0bff7cbed2295f890a'), 'transactionIndex': 3})

```

 

【我关于自学的思考分享】

人生而痛苦,生活对于每个人来说都绝非易事,所以痛苦是常态,快乐要么是稍纵即逝,要么只是强颜欢笑。

这是多数人的人生写照。正如《红楼梦》中的悲观看法:“那红尘中有却有些乐事,但不能永远依恃,况又有‘美中不足,好事多磨’八个字紧相连属,瞬息间则又乐极悲生,人非物换,究竟是到头一梦,万境归空,倒不如不去的好。”

只是来不来,去不去都由不得自己呵!怎么办?

除了伪装出我真的好开心这一烂招之外,真的就没有别的办法摆脱痛苦?

其实坚持自学就是最好的一剂“去痛汤”!

欢迎加我的QQ号一起交流探讨:我的qq号码是:578652607

 

【关于坚持自学的例行说明】

最后例行说明下,我为什么要坚持自学。

 

“如果我不曾见过太阳,我本可以忍受黑暗,然而阳光已使我的荒凉,成为更新的荒凉。”

——艾米莉·狄金森

如果要问我对自己的前半生如何看待时,我想昨天和今天的答案都将完全不同。

昨天的我,生活在荒凉的满意之中,自觉怡然自得,拿着包身包月的工资,听着仁慈的命令,过着几乎一成不变的生活;时而与周遭的人儿和睦互往,时而唇舌相抵斤斤计较,演出着生活的鸡毛蒜皮,工作的吹拉弹唱;忘我,忘我,才能融入这平和无奇的乐章中,迈着细碎的步伐,原地踏步。那时的我觉得这就是悠然自得的听天由命的平凡人生,也就是我的宿命了。

可是某一天,我见到了不一样的太阳以及太阳下不一样的人生光景——那并不荒凉。

今天的我,生活在荒凉的痛苦之中,自觉渴望改变,迈着不知所措的步伐,看着流逝的年华,睁着悔恨错失一切的双眼… …

我知道我将再无法回到过去的我,只有改变才是唯一正确的方向。

 

一、为什么一把年纪还在学习

放弃很多去聚餐,去HI歌,去游玩,去看电影,去追剧……的时间,然后进行着这个年纪似乎已不应当再进行的学习,引来身边人们无尽的不解与鄙夷甚至可怜……

但我不想放弃终身学习的誓言。

因为——

我对我今天的生活现状并不认同!

罗伯特清崎告诉过我们,反省自己当下的生活是不是自己想要的,这难道不是最好的动力与答案?

走过了大半生,然后才发现曾经、当下所正在进行的人生并不是自己想要的,那是一种怎样的体验?

只有心中真切的感受才能回答这个问题,而任凭再丰富的语言也是无法描绘出来的。

经历半生的跋涉,却发现走得并不正确,有多少人有勇气承认自己过去的一切都是错误的呢?

而我愿意告诉过去的我:“你错了!”

那么已经历半生错误,年岁之大又压于头顶,还有希望从这架的*的半端重新爬下,再蹒跚着爬上另一架*吗?

我宁愿相信还有希望!

这便是我为什么要继续坚持终身学习下去的全部理由。

 

二、这个年纪还在学这些技术有意义吗

纯的技术对这把年纪其实已没有意义。

但兴趣可以超越意义。

但技术可以引来思想的变革,这才是意义。

投资自己的头脑 ,改革自己的思想,这是最保值,更长远的投资,过去我从来没有投资过,错过太多,那就从投资自己头脑开始吧。

罗伯特清崎告诉我们,真正的富有是时间的富有;真正的*是可以决定自己愿意做什么的*。

因为我愿意做我兴趣所在的事,所以我希望我有*选择的那一天,虽然今天离那一天可能还是那么遥远,但我愿意相信,每天多赶几步,离希望就更近一步。

再者,虽然我可能再已无法完全完整的掌握这些技术了,但技术本身却可以启迪心的觉醒,激发灵感,那么只要多了解一点,我相信我将离那个正离我而去跑得越来越快的未来更近一点,不至于被未知的那个未来抛弃得太远。

于是我怎能放弃追逐求索的步伐?

我要坚信:感觉太迟的时候,也许还不算太迟。

 

 

【同步语音笔记】

https://www.ximalaya.com/keji/19103006/272607108

 

【学习过程屏幕录屏】

链接:https://pan.baidu.com/s/1V3qz8-RvOanyUiKQMCDNRQ

提取码:omjz

 

上一篇:[EIPs] Gas Station eip-1613 与 Gas Relay eip-1077


下一篇:配置交换机Trunk接口流量本地优先转发(集群/堆叠)