rust-web3
rust-web3 copied to clipboard
Function::decode_input need help
input data=Bytes([24, 203, 175, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 196, 154, 165, 147, 207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 198, 5, 152, 144, 190, 233, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 100, 61, 138, 212, 127, 55, 193, 43, 206, 248, 33, 146, 238, 213, 82, 224, 138, 193, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 97, 163, 109, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 240, 6, 238, 103, 47, 143, 57, 198, 230, 60, 167, 91 , 28, 161, 64, 103, 179, 195, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 76, 219, 156, 189, 54, 176, 27, 209, 203, 174, 191, 45, 224, 141, 145, 115, 188, 9, 92]);
if transaction != None && transaction.as_ref().unwrap().to == Some(self.router_address) { println!("got hash_id: {:?}", hash_id); let input_data = &transaction.as_ref().unwrap().input; let data = self.router_contract .abi() .function("swapExactETHForTokens") .unwrap().decode_output((&hex::encode(&input_data.0)).as_bytes()).unwrap(); println!("{:?}", data); }
when i decode this input_data,error:InvalidDatam,How can I strive to parse the byte array into correct data?
+1
Same here, given a transaction t
and the router abi I have:
for f in context.router.abi().functions() {
match f.decode_input(&t.input.0) {
Ok(tokens) => {
println!(
"Transaction {} called function {} with args {:?}",
t.hash, f.name, tokens
);
}
_ => (),
}
}
and for some reason it matches multiple functions with multiple parameters. However taking a random swap transaction you can see it identifies the swapExactTokensForETHSupportingFeeOnTransferTokens function.
I've also tried to match the function by the first 4 bytes which match the first 4 bytes of the input data:
if f.short_signature() == fn_sign_bytes {
let input = f.decode_input(&t.input.0).unwrap();
println!("input {:?}", input);
}
however I get invalid data
Any idea? It would be also nice to be able to figure out the function by itself, like web3.py
Found the problem, decode_input doesn't consider that the first 4 bytes are the function signature.
You can use f.decode_input(&t.input.0[4..]).unwrap();
which should work
This way you can do something like:
let fn_sign_bytes = &t.input.0[0..4];
for f in router.abi().functions() {
if f.short_signature() == *fn_sign_bytes {
let input = f.decode_input(&t.input.0[4..]).unwrap();
println!(
"Transaction {} called function {}:{} with args {:?}",
t.hash,
f.name,
hex::encode(f.short_signature()),
input
);
}
}
This way you can do something like:
let fn_sign_bytes = &t.input.0[0..4]; for f in router.abi().functions() { if f.short_signature() == *fn_sign_bytes { let input = f.decode_input(&t.input.0[4..]).unwrap(); println!( "Transaction {} called function {}:{} with args {:?}", t.hash, f.name, hex::encode(f.short_signature()), input ); } }
Thanks bro, I'll try it later. Thanks again.
This way you can do something like:
let fn_sign_bytes = &t.input.0[0..4]; for f in router.abi().functions() { if f.short_signature() == *fn_sign_bytes { let input = f.decode_input(&t.input.0[4..]).unwrap(); println!( "Transaction {} called function {}:{} with args {:?}", t.hash, f.name, hex::encode(f.short_signature()), input ); } }
there is no function like f.short_signature(),what's your version?Could u pls give me a complete demo,thanks
you have to use latest master in your cargo.toml file
web3 = { git = "https://github.com/tomusdrw/rust-web3.git" }
you have to use latest master in your cargo.toml file
web3 = { git = "https://github.com/tomusdrw/rust-web3.git" }
Really thank you very much
@alex88 @Antake2333 do you have a full code working example? I'm running into the same issues as described above.
Basically I have the ABI and want to decode the transaction input into a serde value
, but I keep getting InvalidData
Is it possible to get a working code example on how to decode data?
@Corfucinas unfortunately that's all I have, I didn't work on that project anymore
@Antake2333 is there's a working example to decode function parameters given that you have
- smart contract address, 2) smart contract ABI
I'm referring to the following example taken from web3py
>>> transaction = w3.eth.get_transaction('0x5798fbc45e3b63832abc4984b0f3574a13545f415dd672cd8540cd71f735db56')
>>> transaction.input
'0x612e45a3000000000000000000000000b656b2a9c3b2416437a811e07466ca712f5a5b5a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000093a80000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000116c6f6e656c792c20736f206c6f6e656c7900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
>>> contract.decode_function_input(transaction.input)
(<Function newProposal(address,uint256,string,bytes,uint256,bool)>,
{'_recipient': '0xB656b2a9c3b2416437A811e07466cA712F5a5b5a',
'_amount': 0,
'_description': b'lonely, so lonely',
'_transactionData': b'',
'_debatingPeriod': 604800,
'_newCurator': True})
I keep running into errors in rust-web3
Found a workaround, but limited.
Basically I know thetx_data
so I don't have to call to get the Transaction
// Need to take out the "Ox" prefix
let tx_data = "f7a1696300000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000d53d5ea1c50cae08bf29566bb9060b88146e7c400000000000000000000000000000000000000000000000000000000001e18558830977d8ab1b655dda456cd9a447d8f5e5f5625677dbebe34caa587876f6426a0000000000000000000000004976fb03c32e5b8cfe2b6ccb31c09ba78ebaba41000000000000000000000000d53d5ea1c50cae08bf29566bb9060b88146e7c40000000000000000000000000000000000000000000000000000000000000000764616f6261627900000000000000000000000000000000000000000000000000";
// This works
let correct_format: [u8;260] = hex_literal::hex!("f7a1696300000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000d53d5ea1c50cae08bf29566bb9060b88146e7c400000000000000000000000000000000000000000000000000000000001e18558830977d8ab1b655dda456cd9a447d8f5e5f5625677dbebe34caa587876f6426a0000000000000000000000004976fb03c32e5b8cfe2b6ccb31c09ba78ebaba41000000000000000000000000d53d5ea1c50cae08bf29566bb9060b88146e7c40000000000000000000000000000000000000000000000000000000000000000764616f6261627900000000000000000000000000000000000000000000000000");
let decoded_data = contract
.abi()
.function("Foo")
.unwrap()
.decode_input(&correct_format[4..])
.unwrap();
The problem is that hex_literal::hex!
only works with literals
(only hard coded). How to deserialize a rax_data into (what it seems) works correctly which is [u8;260]
Found the solution
// Need to take out the "Ox" prefix
let tx_data = "f7a1696300000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000d53d5ea1c50cae08bf29566bb9060b88146e7c400000000000000000000000000000000000000000000000000000000001e18558830977d8ab1b655dda456cd9a447d8f5e5f5625677dbebe34caa587876f6426a0000000000000000000000004976fb03c32e5b8cfe2b6ccb31c09ba78ebaba41000000000000000000000000d53d5ea1c50cae08bf29566bb9060b88146e7c40000000000000000000000000000000000000000000000000000000000000000764616f6261627900000000000000000000000000000000000000000000000000";
let mut byte_array = [0u8; 260];
hex::decode_to_slice(tx_data, &mut byte_array).unwrap();
let decoded_data = contract
.abi()
.function("Foo")
.unwrap()
.decode_input(&byte_array[4..])
.unwrap();
it works!