Solidity

如何發送字節數據與 web3.py 簽約進行解碼

  • February 18, 2022

我正在做一個測試並嘗試將字節數據發送到契約,以便它可以解析、儲存在變數中並返回一個值。

堅固性程式碼

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 以不同的方式處理事情。也許有人可以在評論中解釋如何正確使用它。

引用自:https://ethereum.stackexchange.com/questions/121718