# 调用未开源合约（搬运）

By [tp](https://paragraph.com/@tpwallet) · 2022-02-16

---

源起 前几天，回答了一个问题，感觉还可以，写成一篇文章记录一下。 问题在： 如何用web3py调用闭源合约 | 登链社区 | 技术问答 ([learnblockchain.cn](http://learnblockchain.cn))

问题中提到的交易记录在 Binance Transaction Hash (Txhash) Details | BscScan

首先查看交易记录，bscscan不能解析出来函数名，也就是abi没有公开。

确定函数调用签名

![](https://storage.googleapis.com/papyrus_images/77569a06bc066ee43fecf0ca0f72bf5d8a33267f0544d4073b73efb8a9017dbe.png)

也就是0xb45112b2

区块链中合约代码执行，需要指定某个合约地址的某个函数，其中这个执行的函数是使用Keccak-256(SHA-3)编码后的散列，取散列的前四个字节作为函数签名。官方定义："签名被定义为没有数据位置说明符的基本原型规范表达式，即具有带括号的参数类型列表的函数名称"。通俗的说就是：将函数名，带顺序的变量类型以及参数括号进行Keccak-256编码后，取前四个字节的二进制字符串，即以太坊的合约函数签名。

1，搜索网上的签名数据库： [https://www.4byte.directory/signatures/](https://www.4byte.directory/signatures/) 搜索结果如下：

![](https://storage.googleapis.com/papyrus_images/38e58668a649b7baba8827f849412592961760e807ea91509be82c01e67f3a93.png)

说明还没有上传函数的abi定义 2，没有函数的abi信息，就没办法调用了吗？ 当然不是！ 只需要找到函数的定义，就相当于，你定义一个函数指针，签名只是这个函数指针，函数的参数保证调用堆栈不出错，而函数签名我们是有的。 3，找到函数原型，找到合约 点击合约地址 0x217这个

![](https://storage.googleapis.com/papyrus_images/f045bf5499db83dffe0c376ebd1972d3f6ddc5beb5db6bf51279d68f6027f45b.png)

合约代码不公开

![](https://storage.googleapis.com/papyrus_images/3ccc75674facf1b8c6f51d8e0478ecbecf0a6dd690233d85ffb81b3705c4a1a2.png)

点击 bytecode-decompiler，得到这样的代码：

![](https://storage.googleapis.com/papyrus_images/f719a8d904b8a3ebdf6e98aeb29b91b9cb50764fb93f6bec291840f16d0cdab5.png)

16435433551.png 搜索函数签名，得到函数原型

def unknownb45112b2(uint256 \_param1): # not payable require calldata.size - 4 >=′ 32 require \_param1 == \_param1 require ext\_code.size(heroContractAddress) 4，构建函数名不一样，函数参数一样的函数 这个函数有返回值，只是为了方便演示效果

function greet3(uint256 num) public view returns (string memory) { return "greet3"; } 用你的合约生成调用接口 在使用的时候，address为合约地址

greeter = w3.eth.contract( address='0xB5816B1C17ce9386019ac42310dB523749F5f2c3', abi=jsobjs\['abi'\] ) 再就是调用方法

搞定问题 1，查看webpy的代码，显然这样的调用是不支持的。 2，自己修改webpy的代码，支持签名替换 我开源的代码里面提供了，修改过的，[contract.py](http://contract.py) 替换即可使用。github上有修改说明。 代码里面有个例子，一个合约里面提供2个函数，函数签名

function greet2(uint256 num) public view returns (string memory) { return "greet2"; }

    function greet3(uint256 num) public view returns (string memory) {
        return "greet3";
    }
    

*   greet2 函数签名 '0xf9220889'
    
*   greet3 函数签名 '0x02d355dc' print(greeter.functions.greet3(456).call(sigfn="0xf9220889")) 打印
    

greet2 开源代码在： daodao2007/e001: call smart contract method without abi file ([github.com](http://github.com))

[emn178.github.io/online-tool](http://emn178.github.io/online-tool)s/keccak\_256.html 解码工具网站

---

*Originally published on [tp](https://paragraph.com/@tpwallet/c4XmrxRF8DleRqsHio4S)*
