python 之 web3 与智能合约的交互、编译等使用

这篇具有很好参考价值的文章主要介绍了python 之 web3 与智能合约的交互、编译等使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、背景

web3.py是一个用于与以太坊交互的 Python 库。
它常见于去中心化应用程序 (dapps)中,帮助发送交易、与智能合约交互、读取块数据以及各种其他用例。
最初的 API 源自Web3.js Javascript API,但后来不断发展以满足 Python 开发人员的需求和物质享受。

本人在合约审计于模糊测试中需要验证一些基础信息,学习了一下

pip install web3

web3开发文档 https://web3py.readthedocs.io/en/stable/

二、基础应用
  • 连接到以太坊测试节点
    from web3 import Web3
    from web3 import EthereumTesterProvider # 以太网测试程序提供程序
    
    创建区块链链接器 链接到测试节点
    w3 = Web3(EthereumTesterProvider())
    建立web3链接
    w3.is_connected()
    
  • 使用HTTPProvider和web3连接eth节点
    provider_url = 'https://mainnet.infura.io/v3/3c3793ddeca**********299afb1c2dc6458'
    w3 = Web3(Web3.HTTPProvider(provider_url))
    w3.is_connected()
    
  • 获取最新的块信息
    latest_block = w3.eth.get_block('latest')
    
  • 验证智能合约地址是否有效
    is_addr = w3.is_address('0x314ECf414b0987EAf8A3504915******91d24')
    
  • 获取钱包余额有多少eth
    wallet = w3.to_checksum_address('0x314ECf414b0987EAf8A3504915d*****1d24')
    print(w3.eth.get_balance(wallet))
    
  • 将wei转化成eth (wei 是eth最小单位)
    wei = w3.from_wei(111111111111111111111, 'ether')
    print(wei)
    
三、区块链合约交互
  • ABI 包含输入函数名称变量
    ABI 对于每个智能合约都是唯一的,除非代码完全一样 abi = '[]'
    
    abi = '[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]'
    contract_address = '0xda141e275f46F9Df74b29AA3eCf7fF77Bc6781AB'
    
  • 调用合同函数或访问合同变量文章来源地址https://www.toymoban.com/news/detail-510512.html

    例如: contract_instance.functions.someFunction().call()
    
    contract_instance = w3.eth.contract(address=contract_address, abi=abi)
    result = contract_instance.functions.totalSupply().call()
    result = contract_instance.functions.symbol().call()
    print(result)
    
四、智能合约的编译
from solcx import compile_source, compile_standard

# 指定安装某个版本编译器
# install_solc(version='latest')

# 编译合约代码 输出abi、bin 字节码
compile_solidity = compile_source(
    '''
    // SPDX-License-Identifier: GPL-3.0
    pragma solidity ^0.8.18;
    contract HelloWorld {
        string public message;
        constructor(){
            message = 'HelloWorld!';
        }
        function setMessage(string memory _message) public{
            message = _message;
        }
        function sayMessage() public view returns (string memory) {
            return message;
        }
    }
    ''',
    output_values=['abi', 'bin']
)

# 检索合约接口 compile_solidity.popitem()
contract_id, contract_interface = compile_solidity.popitem()
# print(contract_id)                # 合约name
# print(contract_interface)         # 合约abi、bin
# print(contract_interface['abi'])  # 合约abi
python 与eth智能合约进行交互
# 创建连接到以太坊测试器的Web3实例
w3 = Web3(Web3.EthereumTesterProvider())
# w3 = Web3(Web3.WebsocketProvider)

# 设置默认账户为测试器中的第一个账户
# w3.eth.accounts 是以太坊测试器中已创建的账户列表。通过 w3.eth.default_account = w3.eth.accounts[0],将默认账户设置为测试器中的第一个账户。
# 这意味着当您发送交易或调用合约函数时,如果没有显式指定账户,将默认使用 w3.eth.accounts[0] 作为交易的发送者

w3.eth.default_account = w3.eth.accounts[0]

# 合约的ABI和字节码
abi = contract_interface['abi']
bytecode = contract_interface['bin']

# 创建合约实例
helloworld = w3.eth.contract(abi=abi, bytecode=bytecode)

# 发送合约构造函数的交易
transaction_hash = helloworld.constructor().transact()
# print(transaction_hash)

# 等待交易收据
transaction_receipt = w3.eth.wait_for_transaction_receipt(transaction_hash=transaction_hash)
# print(transaction_receipt)
'''
blockHash: 交易所在区块的哈希值。
blockNumber: 交易所在区块的编号。
contractAddress: 如果交易创建了一个新的合约,该参数表示新合约的地址。如果交易不是创建合约的交易,则为一个空字符串。
cumulativeGasUsed: 该交易之前所有交易的累计消耗的燃气量。
effectiveGasPrice: 交易的有效燃气价格。
from: 发送者(发送交易的账户地址)。
gasUsed: 该交易消耗的燃气量。
logs: 交易产生的日志事件。
state_root: 交易执行后的状态树根哈希。
status: 交易的执行状态,1表示成功,0表示失败。
to: 交易的接收者地址。如果是创建合约的交易,则为一个空字符串。
transactionHash: 交易的哈希值。
transactionIndex: 交易在所在区块的索引位置
# type: 交易类型1表示普通交易,2表示合约创建交易
'''
# # 获取合约对象
# helloworldContract = w3.eth.contract(address=transaction_receipt.contractAddress, abi=abi)
# print(helloworldContract) # 获取合约对象
# # 调用合约中函数sayMessage
# print(helloworldContract.functions.sayMessage().call())
# # 调用合约中函数setMessage,修改一个值,下面获取并没有变化,需要我们重新部署,发起交易
# print(helloworldContract.functions.setMessage('BEY').call())
# # 发现并没有变化
# print(helloworldContract.functions.sayMessage().call())
# # 重新调用合约构造函数的交易
# bye_hash = helloworldContract.functions.setMessage('BEY').transact()
# print(bye_hash)
# # 等待交易收据
# bye_receipt = w3.eth.wait_for_transaction_receipt(transaction_hash=bye_hash)
# print(bye_receipt)
# # 重新构造以后才会修改为bye
# print(helloworldContract.functions.sayMessage().call())
# # print(is_addr)
python 编译智能合约
compiled_solidity = compile_standard({
    "language": "Solidity",
    "sources": {
        "SimpleNumber.sol": {
            # "content": contract_file
        }
    },
    "setting": {
        "outputSelection": {
            "*": {"*": ["abi", "metadata", "evm.bytecode", "evm.sourceMap"]}
        }
    }
},
    solc_version='0.8.12'
)

print(compiled_solidity)

# compiled_solidity: 编译后的Solidity结合的结果
# language: Solidity合约的编程语言,这里是"Solidity"
# sources: Solidity源代码文件的字典,这里只有一个源代码文件"SimpleNumber.sol"
# setting: 编辑设置的字典,包选择输出
# outputSelection: 输入选的字典,选包包括ABI、元数据、EVM字节码和EVM源映像
# solc_version: Solidity编译器的版本,这里是"0.8.12"
使用python 部署智能合约
provider_url = 'https://goerli.infura.io/v3/3c3793ddeca5********fb1c2dc6458'
w3 = Web3(Web3.HTTPProvider(provider_url))
w3.is_connected()

abi = compiled_solidity['contracts']['SimpleNumber.sol']['SimpleNumber']['abi']
bytecode = compiled_solidity['contracts']['SimpleNumber.sol']['SimpleNumber']['evm']['bytecode']['object']

SimpleNumber = w3.eth.contract(abi=abi, bytecode=bytecode)
transaction = SimpleNumber.constructor().build_transaction(
    {
        "gasPrice": w3.eth.gas_price,
        "chainId": 3,
        "from": "wallet 钱包地址 来自metamask账户",
        "nonce": w3.eth.get_block_transaction_count("wallet 钱包地址 来自metamask账户")

    }
)
metamask 添加网络 eth 测试网络
sign_transaction = w3.eth.account.sign_transaction(transaction, private_key='私钥')
print(sign_transaction)
transaction_hash = w3.eth.send_raw_transaction(sign_transaction.rawTransaction)
print(transaction_hash)
transaction_receipt2 = w3.eth.wait_for_transaction_receipt(transaction_hash)
print(transaction_receipt2)
在python 中与部署的智能合约交互
contract_instance = w3.eth.contract(address=transaction_receipt2.contractAddress, abi=abi)

contract_instance.functions.getStoreNumber().call()
contract_instance.functions.updateStoreNumber(200).call()

update_number_transaction = contract_instance.functions.updateStoreNumber(200).call().build_transaction(
    {
        "gasPrice": w3.eth.gas_price,
        "chainId": 3,
        "from": "wallet 钱包地址 来自metamask账户",
        "nonce": w3.eth.get_block_transaction_count("wallet 钱包地址 来自metamask账户") + 1 # 每次加1 不能重复使用 nonce
    }
)

sign_transaction3 = w3.eth.account.sign_transaction(update_number_transaction, private_key='私钥')
print(sign_transaction3)
transaction_hash3 = w3.eth.send_raw_transaction(sign_transaction3.rawTransaction)
print(transaction_hash3)
transaction_receipt3 = w3.eth.wait_for_transaction_receipt(transaction_hash3)
print(transaction_receipt3)
# 此时进行变化
contract_instance.functions.getStoreNumber().call()

# print(latest_block)
# print(w3.is_connected())
# print(Web3)
# print(EthereumTesterProvider)

到了这里,关于python 之 web3 与智能合约的交互、编译等使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用nodejs和web3js实现链接metamask钱包并实现合约交互

    在以太坊区块链上,metamask钱包是一个非常常用的钱包,用以管理以太币和其他以太坊资产。同时,它也是一个重要的以太坊智能合约交互工具。在本文中,我们将介绍如何使用nodejs和web3js实现链接metamask钱包并实现合约交互。 在开始之前,首先需要安装NodeJS和Web3JS。 NodeJS是

    2024年02月04日
    浏览(90)
  • 区块链合约交互 web3

    遵循ERC20规则, 钱包里可以有很多种类型的token:USDT,DFI,DFA 1.合约交互之前需要先判断是否仍允许purchasePool合约从账户(钱包里的账户) 中提取的ERC20dfaContract 这本合约里(DFA)的金额 await this.contract.ERC20dfaContract.methods.allowance(this.address,this.addressMap.AcceleratePool).call(); ERC20df

    2024年02月07日
    浏览(63)
  • 手把手部署区块链智能合约及python的web3接口调用

    说句实话,在做区块链、智能合约、搭私链、pythonWeb3接口调用这些东西的时候,心里崩溃了不止四五十回,如果可以选别的方向,博主劝你赶紧换,人生已经很不容易了,别给自己找罪受。。。。。 创世块是什么请自行搜索,网络上很多示例的创世块博主都试过,在实际使

    2024年02月04日
    浏览(49)
  • Java Web3J :使用web3j监听、查询、订阅智能合约的事件

    前面有文章写如何使用Docker-compose方式部署blockscout浏览器+charts图表,区块链浏览器已经部署成功了,同时我们在链上增加了治理投票流程,如何实时的把治理事件快速同步到浏览器呢?这时就想到了Web3J来监听智能合约的事件,来达到同步事件的效果

    2024年02月09日
    浏览(44)
  • Java Web3J :使用web3j调用自己的智能合约的方法(教程)

    代码世界有很多令人大呼小叫的技巧!有的代码像魔术师一样巧妙地隐藏了自己,有的像魔法师一样让你眼花缭乱,还有的像瑜伽大师一样灵活自如。它们让我们惊叹不已,让我们觉得自己仿佛置身于编码的魔幻世界。快来分享你见过哪些令你膛目结舌的代码技巧吧! web3j是

    2024年02月04日
    浏览(69)
  • web3:智能合约浏览器版本的 IDE - remix 使用教程

    如果你是一位web3行业的从业者,那么智能合约一定是要接触的,这里我们就智能合约浏览器版本的 IDE-remix来介绍一下,及简单的使用操作 Remix 是一个开源的 Solidity 智能合约开发环境,是一款浏览器版本的 IDE,提供基本的编译、部署至本地或测试网络、执行合约等功能。S

    2024年02月06日
    浏览(54)
  • web3: 智能合约

    2024年01月09日
    浏览(49)
  • java使用web3j,部署智能合约在测试链上,并调用(万字详细教程)

    最近在学区块链相关,想做点自己感兴趣的。网上关于这块部分的坑也比较多,最近也是问了很多行业从事者才慢慢填坑,因此记录下来分享一下。 钱包 :metemask、 solidity编译器 :remix 、 java ide :idea。 智能合约编写的我选择在remix上方便,而且部署的时候不需要自定义gasP

    2024年01月16日
    浏览(58)
  • Java Web3J :使用web3j调用自己的智能合约,返回一个内部有数组的对象结构时出现NPE问题

    之前有写过一篇文章Java Web3J :使用web3j调用自己的智能合约的方法(教程),当时只是简单的方法调用,也不涉及到什么复杂的数据类型,入参是long类型,出参是String类型。 遇到这个问题是因为有一个方法,需要通过提案的治理id,查询链上提案数据,这个就需要接收提案

    2024年01月19日
    浏览(67)
  • 【区块链】走进web3的世界-合约交互中的异常/边界处理

    在以太坊智能合约中,异常处理是一个非常重要的问题,因为任何一个函数调用都有可能导致异常。常见的异常包括函数调用失败、无效参数、内部错误等。         在 Solidity 中,可以使用 require、assert 和 revert 等来处理异常。这些可以用于检查输入参

    2024年02月09日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包