Example: unknown_return_types

Example

To run this example:

  • Clone the examples repository: git clone git@github.com:alloy-rs/examples.git
  • Run: cargo run --example unknown_return_types
//! Example demonstrating how one can handle unknown / complex return types using `DynSol`.

use alloy::{
    contract::{ContractInstance, Interface},
    dyn_abi::DynSolValue,
    json_abi::JsonAbi,
    network::{Ethereum, TransactionBuilder},
    primitives::{hex, U256},
    providers::{Provider, ProviderBuilder},
    rpc::types::TransactionRequest,
    transports::http::{Client, Http},
};
use eyre::Result;

#[tokio::main]
async fn main() -> Result<()> {
    // Spin up a local Anvil node.
    // Ensure `anvil` is available in $PATH.
    let provider = ProviderBuilder::new().with_recommended_fillers().on_anvil_with_wallet();

    // Get the first account from the wallet, Alice.
    let alice = provider.get_accounts().await?[0];

    let bytecode = hex::decode(
        // contract Colors {
        //     struct Color {
        //         uint8 r;
        //         uint8 g;
        //         uint8 b;
        //     }
        //
        //     mapping(address => Color) public colors;
        //
        //     function setColor(uint8 r, uint8 g, uint8 b) public {
        //         colors[msg.sender] = Color(r, g, b);
        //     }
        //
        //     function getColor(address user) public view returns (Color memory) {
        //         return colors[user];
        //     }
        //
        //     function getColorAsTuple(
        //         address user
        //     ) public view returns (uint8, uint8, uint8) {
        //         return (colors[user].r, colors[user].g, colors[user].b);
        //     }
        // }
        "6080604052348015600f57600080fd5b506105fb8061001f6000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c8063610c76f01461005157806384b5e5961461006d57806399efff171461009d578063befdb4f6146100cf575b600080fd5b61006b60048036038101906100669190610435565b610101565b005b610087600480360381019061008291906104e6565b6101ce565b6040516100949190610564565b60405180910390f35b6100b760048036038101906100b291906104e6565b61027d565b6040516100c69392919061058e565b60405180910390f35b6100e960048036038101906100e491906104e6565b61037c565b6040516100f89392919061058e565b60405180910390f35b60405180606001604052808460ff1681526020018360ff1681526020018260ff168152506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff021916908360ff16021790555060208201518160000160016101000a81548160ff021916908360ff16021790555060408201518160000160026101000a81548160ff021916908360ff160217905550905050505050565b6101d66103cd565b6000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060600160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900460ff1660ff1660ff1681526020016000820160029054906101000a900460ff1660ff1660ff16815250509050919050565b60008060008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff166000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160019054906101000a900460ff166000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160029054906101000a900460ff169250925092509193909250565b60006020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900460ff16908060000160029054906101000a900460ff16905083565b6040518060600160405280600060ff168152602001600060ff168152602001600060ff1681525090565b600080fd5b600060ff82169050919050565b610412816103fc565b811461041d57600080fd5b50565b60008135905061042f81610409565b92915050565b60008060006060848603121561044e5761044d6103f7565b5b600061045c86828701610420565b935050602061046d86828701610420565b925050604061047e86828701610420565b9150509250925092565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006104b382610488565b9050919050565b6104c3816104a8565b81146104ce57600080fd5b50565b6000813590506104e0816104ba565b92915050565b6000602082840312156104fc576104fb6103f7565b5b600061050a848285016104d1565b91505092915050565b61051c816103fc565b82525050565b6060820160008201516105386000850182610513565b50602082015161054b6020850182610513565b50604082015161055e6040850182610513565b50505050565b60006060820190506105796000830184610522565b92915050565b610588816103fc565b82525050565b60006060820190506105a3600083018661057f565b6105b0602083018561057f565b6105bd604083018461057f565b94935050505056fea2646970667358221220ce426adf2fbf80a861f23a5eb1e99a281bb07e427b9beed059e09c285f16db6c64736f6c634300081a0033"
    )?;
    let deploy_tx = TransactionRequest::default().from(alice).with_deploy_code(bytecode);

    let contract_address = provider
        .send_transaction(deploy_tx)
        .await?
        .get_receipt()
        .await?
        .contract_address
        .expect("Failed to get contract address");

    // Get the contract abi.
    let path = std::env::current_dir()?.join("examples/contracts/examples/abi/Colors.json");
    let contents = std::fs::read(path)?;
    let abi: JsonAbi = serde_json::from_slice(&contents)?;

    // Create a new `ContractInstance` of the Counter contract from the abi.
    let counter_instance: ContractInstance<Http<Client>, _, Ethereum> =
        ContractInstance::new(contract_address, provider.clone(), Interface::new(abi));

    // Interact with the contract.
    assert_eq!(counter_instance.abi().functions().count(), 4);

    // Set color to white.
    let r = DynSolValue::Uint(U256::from(255), 8); // uint8
    let g = DynSolValue::Uint(U256::from(255), 8); // uint8
    let b = DynSolValue::Uint(U256::from(255), 8); // uint8
    let set_color_func = counter_instance.function("setColor", &[r, g, b])?;
    let set_color_receipt = set_color_func.send().await?.get_receipt().await?;
    assert!(set_color_receipt.status());

    // Get the color.
    let get_color_func = counter_instance.function("getColor", &[DynSolValue::Address(alice)])?;
    let get_color_result = get_color_func.call().await?;

    // The `r`, `g`, `b` values in the `Color` struct get converted to a `DynSolValue::Tuple`.
    assert!(get_color_result.len() == 1);
    for value in get_color_result {
        if let DynSolValue::Tuple(struct_as_tuple) = value {
            println!("{struct_as_tuple:?}");
        }
    }

    // Get the color as tuple.
    let get_color_tuple =
        counter_instance.function("getColorAsTuple", &[DynSolValue::Address(alice)])?;
    let get_color_tuple_result = get_color_tuple.call().await?;

    // The `r`, `g`, `b` are returned as a solidity tuple and hence represented as individual
    // `DynSolValue::Uint`.
    assert!(get_color_tuple_result.len() == 3);
    for value in get_color_tuple_result {
        println!("{value:?}");
    }

    Ok(())
}

Find the source code on Github here.