tomusdrw / rust-web3

Ethereum JSON-RPC multi-transport client. Rust implementation of web3 library. ENS address: rust-web3.eth
MIT License
1.45k stars 465 forks source link

How to convert a &str or String to a bytes32? #276

Closed BlinkyStitt closed 4 years ago

BlinkyStitt commented 4 years ago

I am trying to call a contract function that takes a bytes32 as its input. I've found some javascript helpers to convert from a string to a bytes32, but I don't see anything similar here.

https://github.com/Synthetixio/synthetix/issues/295

https://github.com/Synthetixio/synthetix-js/blob/414cd138d12fc16e6239d46a0e651eac118688b7/src/util/index.js#L82

                exchange_rates_contract
                    .query(
                        "ratesForCurrencies",
                        // TODO: need a function like "toUtf8Bytes32" that "converts a string to a bytes4 array (right padding for Solidity)"
                        ("SNX", "ETH"),
                        None,
                        contract::Options::default(),
                        None,
                    )

Do you have any suggestions for how to convert these short strings into a [u8; 32]? I think that is the type that can be tokenized to what I need. In the end, I need a bytes32[]

tomusdrw commented 4 years ago

doesn't b"SNX" work good enough?

BlinkyStitt commented 4 years ago

Oh! That is the simple thing I should have expected. Thank you!!!

On Oct 29, 2019, at 3:43 AM, Tomasz Drwięga notifications@github.com wrote:

doesn't b"SNX" work good enough?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.

BlinkyStitt commented 4 years ago

That almost works, but it isn't padded.

the trait bound `(&[u8; 3],): web3::contract::tokens::Tokenize` is not satisfied

the trait `web3::contract::tokens::Tokenize` is not implemented for `(&[u8; 3],)`

help: the following implementations were found:
        <(A,) as web3::contract::tokens::Tokenize>
BlinkyStitt commented 4 years ago
fn pad_to_bytes32(s: &[u8]) -> Option<[u8; 32]> {
    let s_len = s.len();

    if s_len > 32 {
        return None;
    }

    let mut result: [u8; 32] = Default::default();

    result[..s_len].clone_from_slice(s);

    Some(result)
}
BlinkyStitt commented 4 years ago

This is working! Thank you!

    let snx_str_bytes = pad_to_bytes32(b"SNX").unwrap();
    let eth_str_bytes = pad_to_bytes32(b"ETH").unwrap();

    exchange_rates_contract
        .query(
            "ratesForCurrencies",
            (vec![snx_str_bytes, eth_str_bytes], ),
            None,
            contract::Options::default(),
            None,
        )