I'm doing a test and trying to send bytes data to a contract so it can parse, store in variables, and return a value.
Solidity code
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;
}
}
I was looking at this answer here but passing the bytes data was done in Javascript. Parsing solidity bytes to params
Python code
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)
I get the bytes output
b"{'amountIn': 1, 'amountOut': 2, 'pool': 'pool address here'}"
If I try to pass that the contract reverts and if I try via remix I get
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)
From researching I can only guess that my byte input is incorrect, or something in my contract is wrong, but I'm unsure.
UPDATE 1:
After looking at example in comment I ended up here: web3py encode method call parameters
I tried using the second method but I get contract reverted.
test_encode = encode_abi(['uint', 'uint', 'address'], [1, 2, '0xAD5ce863aE3E4E9394Ab43d4ba0D80f419F61789'])
contract.functions.sendBytes(test_encode).call()
When I try the first method mixed with the second
contract.encodeABI(fn_name='sendBytes', args=[test_encode])
It returns
0x4c93893a0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000ad5ce863ae3e4e9394ab43d4ba0d80f419f61789
Randomly I input that into remix it return values, but all wrong values.
So I am still confused, the js portion seemed easier. Recovering data from Bytes using Assembly
UPDATE 2:
This code works when I take the output and input it into remix
test_encode = encode_abi(['uint', 'uint', 'address'], [1, 2, '0xAD5ce863aE3E4E9394Ab43d4ba0D80f419F61789'],)
contract.encodeABI(fn_name='sendBytes', args=[test_encode], data=test_encode)
output:
0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000ad5ce863ae3e4e9394ab43d4ba0d80f419f617890000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000ad5ce863ae3e4e9394ab43d4ba0d80f419f61789
When entered into remix it returns the right values! But now I don't know how to pass the data in a web3.py call. I keep getting execution reverted.
[1,2,pool]
but I'm not sure how I would send a struct via web3 py to the contract to decode.