理解 ABI规范, 学习如何使用 web3 及 solidity 来与合约交互
智能合约部署在区块链上,它们是包含一些逻辑的代码片段,由EVM执行,将以太坊区块链变成一种世界分布式计算机。
智能合约可以被链下用户/程序调用,向区块链提交交易。链上的合约之间也可以通过调用对方的方法进行交互(不过是在链下调用之后,智能合约不能 "主动触发" 调用)。
智能合约的交互必须遵循ABI规范,这是一套规则和定义,用于规范以太坊生态系统中的智能合约通信。
在这篇博客中,我将以简化的方式介绍,根据ABI规范,必须如何提交数据给区块链,以触发智能合约。然后,我将谈论用不同方法从链下和链上调用智能合约函数。
在我们开始之前,我将简单地说明我将在这篇博客中使用哪些工具。
对于链下实体,我将使用web3 javascript库( web3.js),因为它封装了JSON-RPC协议,这是用于与区块链通信的实际协议。, 也可以使用其他相同目的的库库,如: ethers.js,不过语法可能会有所不同。
对于链上智能合约,我将使用solidity语言,但任何其他EVM兼容的编程语言也可以。
ABI规范指出了在调用智能合约函数时如何构建发送到 "交易"中作为 "data" 的字节数据。字节数据包含2个主要部分:
橙色字节 = 函数选择器,keccak256("baz(uint32,bool)")的前4个字节。
蓝色字节 = 第一个编码参数,它是一个静态参数,值为 "69"(0x....45)。
红色字节 = 第二个编码参数,它是一个值为 "true"的静态参数(0x....01)。
橙色字节=函数选择器, keccak256("sam(bytes,bool,uint256[])") 的前4个字节。
蓝色字节=第一个编码参数,它是一个动态的参数,首先表明它的位置(字节0x60)。然后在位置0x60上,第一个字节表示长度(0x.....04 = 4字节,因为数据类型是字节),第二个字节表示参数的实际值: "dave" (0x646176650.........0)。
红色字节=第二个编码参数,它是一个静态参数,值为 "true"(0x....01)。
绿色字节=第三个编码参数,它是一个动态参数,首先指示它的位置(字节0xa0)。然后在位置0xa0上,第一个字节表示长度(0x....03 = 3个字,因为它是一个uint256数组),然后三个字节表示值: "1"、"2"、"3"(0x.....01, 0x....02, 0x......03)。
你有一个前端或后端应用程序,需要与一些以太坊智能合约交互。我将使用javascript的web3.js库,它将处理JSON-RPC协议,也会生成必须提交给区块链的符合abi规范的字节串。
有两种可能的情况,你要么有智能合约JSON ABI,要么没有。
智能合约JSON ABI是一个JSON文件,在你构建智能合约时由solidity编译器生成。编译器实际上会生成两个文件:
JSON ABI对象包含以下信息:
函数对象:
事件对象:
错误对象:
为了从你的链下应用程序与智能合约进行交互,首先需要导入JSON Abi文件,然后提供JSON Abi和指向智能合约的地址来实例化一个的对象。从那一刻起,你可以像对待其他对象一样直接调用合约的方法。
智能合约的调用将以异步方式完成:
// Reference the smart contract
const SmartContract= require(“SmartContract”);
// Retrieve the JSON ABI and address
const SmartContractAbi = SmartContract.abi;
const SmartContractAddress = "0x......"
// Instantiate an object that "encapsulates" the smart contract
const SmartContractObject = new web3.eth.Contract(SmartContractAbi, SmartContractAddress);
// Now you are ready to interact with the smart contract. Functions // invocations will return promises.
SmartContractObject.methods.func1(…).send({from: …, …}).on(…);
SmartContractObject.methods.func2(…).call({from: …}).on(…);
如果你没有JSON ABI,你仍然可以与智能合约进行交互,但这将是一个有点麻烦和烦人的过程。
你将不得不自己从方法定义(json格式)、希望提交的输入参数中创建区块链交易,并将其直接发送到智能合约地址。
你可以提交一个 "send"交易(将改变区块链状态的实际交易)或一个 "call" 交易(从以太坊的角度看不是一个实际的交易,因为它将只读取数据)。
交易将以异步方式提交:
// Define the Transaction Data
const TransactionData = web3.eth.abi.encodeFunctionCall({
name: 'myMethod',
type: 'function',
inputs: [{
type: 'uint256',
name: 'myNumber'
},{
type: 'string',
name: 'myString'
}]
}, ['2345675643', 'Hello!%']);
// Now you can either send a transaction or make a call. In both
// cases you will be dealing with Promises
web3.eth.sendTransaction({from: …, to: …, data: TransactionData, …}).on(…);
web3.eth.call({from: …, to: …, data: TransactionData, …}).on(…);
你正在实现一个智能合约,想从你的代码中调用另一个合约的函数。可以使用 solidity 编程语言,它提供了一些内置的函数,来生成符合 abi 规范的字节串。
就像链下到链上的情况一样,有两种可能的情况,你要么有智能合约接口,要么没有。
如果你有你想调用的智能合约的接口,solidity将为你做大部分的工作。
你只需要将接口导入到智能合约文件,实例化一个接口类型的对象,并传递智能合约地址,你就可以开始了。就可以像其他对象一样调用合约的方法了。
// Import the interface and define the contract object using the
// interface as a data type
import "IContract.sol";
IContract Contract;
// Instantiate the contract with its address
address contractAddress = 0x.......;
Contract = IContract(contractAddress);
// Invoke the contract's methods as defined by the interface
Contract.func1(....);
如果你没有合约接口,那么你将不得不构建整个消息。
你将需要合约地址,方法签名(方法名称和输入参数类型用逗号分隔)和你希望提交的参数(也用逗号分隔)。
// Contract Address and function signature
address contractAddress = 0x.......;
string memory Method = “func1(uint256,bool)”;
// Define the abi compliant data
bytes memory AbiData = abi.encodeWithSignature(Method, 345223, true);
// Send the message
(bool success, bytes memory data) = contractAddress.call(AbiData);
需要注意的是,不管你与智能合约的交互方式如何,如果你使用的智能合约地址是错误的,你仍然可以提交交易,没有任何的检查。如果智能合约确实有一个与你的调用相匹配的函数,它将被执行,如果没有,那么交易可能失败,也可能成功,如果智能合约有一个 "fallback()" 函数......重点是,后果可能是意想不到的,而且可能是无法检测的,这就是为什么你必须确定你向哪个合约发送交易,始终确保合约地址是正确的。
参考原文: https://medium.com/coinmonks/ethereum-smart-contracts-how-to-communicate-with-them-abi-specification-web3-solidity-db056218b251
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!
聚圣源江苏专接本和专转本可以一起报名吗自媒体起名网女孩起名字用什么字甘姓女孩起名大全大全起取个英文名字男生男士专用品栀子花开百度云证件照片背景www.色小姐.com1518公司起名评分表生死狙击第一季今年出生小孩起名大全仁寿黑龙滩天天理财免费婴儿起名字生辰八字起名嫡女重生记义不容情结局给火起名字我和我的祖国百度云厚道的意思背着奶奶进城开店怎么起名字好吗黄财神心咒达达免费起名网有哪些网站姓覃的女孩起名影视大全纯净版下载2021免费版烧饼店起名彭姓孩子起名大全绿茵逆转狂魔淀粉肠小王子日销售额涨超10倍罗斯否认插足凯特王妃婚姻让美丽中国“从细节出发”清明节放假3天调休1天男孩疑遭霸凌 家长讨说法被踢出群国产伟哥去年销售近13亿网友建议重庆地铁不准乘客携带菜筐雅江山火三名扑火人员牺牲系谣言代拍被何赛飞拿着魔杖追着打月嫂回应掌掴婴儿是在赶虫子山西高速一大巴发生事故 已致13死高中生被打伤下体休学 邯郸通报李梦为奥运任务婉拒WNBA邀请19岁小伙救下5人后溺亡 多方发声王树国3次鞠躬告别西交大师生单亲妈妈陷入热恋 14岁儿子报警315晚会后胖东来又人满为患了倪萍分享减重40斤方法王楚钦登顶三项第一今日春分两大学生合买彩票中奖一人不认账张家界的山上“长”满了韩国人?周杰伦一审败诉网易房客欠租失踪 房东直发愁男子持台球杆殴打2名女店员被抓男子被猫抓伤后确诊“猫抓病”“重生之我在北大当嫡校长”槽头肉企业被曝光前生意红火男孩8年未见母亲被告知被遗忘恒大被罚41.75亿到底怎么缴网友洛杉矶偶遇贾玲杨倩无缘巴黎奥运张立群任西安交通大学校长黑马情侣提车了西双版纳热带植物园回应蜉蝣大爆发妈妈回应孩子在校撞护栏坠楼考生莫言也上北大硕士复试名单了韩国首次吊销离岗医生执照奥巴马现身唐宁街 黑色着装引猜测沈阳一轿车冲入人行道致3死2伤阿根廷将发行1万与2万面值的纸币外国人感慨凌晨的中国很安全男子被流浪猫绊倒 投喂者赔24万手机成瘾是影响睡眠质量重要因素春分“立蛋”成功率更高?胖东来员工每周单休无小长假“开封王婆”爆火:促成四五十对专家建议不必谈骨泥色变浙江一高校内汽车冲撞行人 多人受伤许家印被限制高消费