Solidity
如何發送字節數據與 web3.py 簽約進行解碼
我正在做一個測試並嘗試將字節數據發送到契約,以便它可以解析、儲存在變數中並返回一個值。
堅固性程式碼
pragma solidity 0.6.12; contract testbyte { function sendBytes(bytes calldata _data) external pure returns (address) { (uint amountIn, uint amountOut, address pool) = abi.decode(_data, (uint, uint, address)); return pool; } }
我在這裡查看了這個答案,但是傳遞字節數據是用 Javascript 完成的。 將solidity字節解析為參數
Python程式碼
w3 = Web3(Web3.HTTPProvider(node_provider)) # I collect all data, abi, etc in between. data = { 'amountIn': 1, 'amountOut': 2, 'pool': 'pool address here' } # I usually do w3.toBytes(text='') to pass nothing on mainnet contracts. bytes_data = w3.toBytes(text=str(data)) pool = contract.functions.sendBytes(bytes_data).call() print(pool)
我得到字節輸出
b"{'amountIn': 1, 'amountOut': 2, 'pool': 'pool address here'}"
如果我嘗試通過契約恢復並且如果我嘗試通過混音我得到
transact to testbyte.sendBytes errored: Error encoding arguments: Error: invalid arrayify value (argument="value", value="{'amountIn': 1, 'amountOut': 2, 'pool': 'pool address here'}", code=INVALID_ARGUMENT, version=bytes/5.5.0)
通過研究,我只能猜測我的字節輸入不正確,或者我的契約中的某些內容是錯誤的,但我不確定。
更新 1:
在查看評論中的範例後,我最終來到這裡:web3py 編碼方法呼叫參數
我嘗試使用第二種方法,但我恢復了契約。
test_encode = encode_abi(['uint', 'uint', 'address'], [1, 2, '0xAD5ce863aE3E4E9394Ab43d4ba0D80f419F61789']) contract.functions.sendBytes(test_encode).call()
當我嘗試第一種方法與第二種方法混合時
contract.encodeABI(fn_name='sendBytes', args=[test_encode])
它返回
0x4c93893a0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000ad5ce863ae3e4e9394ab43d4ba0d80f419f61789
我隨機將其輸入到 remix 中,它返回值,但所有值都是錯誤的。
所以我仍然很困惑,js部分似乎更容易。 使用 Assembly 從 Bytes 中恢復數據
更新 2:
當我將輸出輸入到混音中時,此程式碼有效
test_encode = encode_abi(['uint', 'uint', 'address'], [1, 2, '0xAD5ce863aE3E4E9394Ab43d4ba0D80f419F61789'],) contract.encodeABI(fn_name='sendBytes', args=[test_encode], data=test_encode)
輸出:
0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000ad5ce863ae3e4e9394ab43d4ba0d80f419f617890000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000ad5ce863ae3e4e9394ab43d4ba0d80f419f61789
當輸入 remix 時,它會返回正確的值!但現在我不知道如何在 web3.py 呼叫中傳遞數據。我一直在恢復執行。
找到了答案。我的 .env 文件中的契約地址似乎有誤(哎呀)。在我更正之後,我使用了下面的程式碼。
from eth_abi import encode_abi test_encode = encode_abi(['uint', 'uint', 'address'], [1, 2, '0xAD5ce863aE3E4E9394Ab43d4ba0D80f419F61789'],) # Basically map the types to the values pool = contract.functions.sendBytes(test_encode).call() print(pool)
輸出
['0xAD5ce863aE3E4E9394Ab43d4ba0D80f419F61789']
如果你想使用數組,你可以這樣做
test_encode = encode_abi(['uint[]', 'uint[]', 'address'], [[1,2], [3,4], '0xAD5ce863aE3E4E9394Ab43d4ba0D80f419F61789'],)
我無法使用
contract.encodeABI(fn_name='sendBytes', args=[test_encode], data=test_encode)
我相信我用錯了,它輸出的數據是一個字元串。當您將值輸入到 remix 中時,它會起作用。我只能假設 remix 以不同的方式處理事情。也許有人可以在評論中解釋如何正確使用它。