2

From the ink! cross-contract docs, contract references give developers a type-safe way of interacting with a contract. However, this is not only available when the contract is already instantiated.

My question is, given the AccountId or code hash of the contract, is there a way to convert that to a ContractRef so I'm sure that AccountId really points to a contract with the expected type?

Currently, ink! has the CallBuilder but this doesn't ensure the contract is of the expected type. For instance, supposed I've 3 contracts. The first contract has the main struct named First, the second Second, and the third Third. Assume both First and Second has a method called flip. Within the Third contract, if I want to call the flip method from the already instantiated First contract, implementing it would be:

let my_return_value = build_call::<DefaultEnvironment>()
    .call(contracts_address)
    .gas_limit(0)
    .transferred_value(10)
    .exec_input(
        ExecutionInput::new(Selector::new(ink::selector_bytes!("flip")))
            .push_arg(42u8)
    )
    .returns::<bool>()
    .invoke();

However this doesn't ensure only the First contract's flip method is called. Using the Second contract's address would also work.

2 Answers 2

2

From the snippet you gave, it looks like you want to call a contract, not create it. You can't convert CodeHash into a ContractRef b/c they're different things. CodeHash represents the code of the contract lives, not an address of a specific instance of the contract.

To turn an AccountId into a specific contract ref, you can follow the example given here https://github.com/Cardinal-Cryptography/bulletin-board-example/blob/main/contracts/bulletin_board/lib.rs#L497-L504

2
  • Thanks. But actually this doesn't really answer my question. From the reference you gave, from_account_id just wraps the account_id in the ContractRef without any checks and eventuality a method call behaves just like the snippet I gave in my question
    – Kofi
    Commented May 17, 2023 at 10:41
  • Yes, that's the point of ContractRef - it gives you a type-safe information about available methods (args, return types) of the contract you want to call. There's nothing more you can do - AccountId itself has no information about the contract that lives under that address so you, as a developer, has to define what type (contract) you're expecting to talk to.
    – deuszx
    Commented May 18, 2023 at 11:09
1

You cannot obtain ContractRef from code-hash or AccountId but you may determine whether a given function (function selector; to be precise) exists at a given address to some extend by using try_invoke rather than invoke (Not the best way though :p).

Bonus: You can also look at ERC165 to know more ways to tackle this kind of problem.

P.S: If a contract supports wildcard selector then this may not hold true.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.