use-ink / ink

Polkadot's ink! to write smart contracts.
https://use.ink
Apache License 2.0
1.34k stars 424 forks source link

Cross contract calling produces unsupported code #2172

Open kroist opened 4 months ago

kroist commented 4 months ago

I have a contract with a function deposit, which has the following cross-contract calling inside:

let mut psp22: ink::contract_ref!(PSP22) = AccountId::from(token.bytes).into();
psp22.transfer_from(
   AccountId::from(user.bytes),
   self.env().account_id(),
   amount,
   [].to_vec(),
)?;

PSP22 is declared as a trait with #[ink::trait_definition]

I'm running local env of aleph zero node

And when I upload code using cargo upload I get:

 Result ModuleError: Contracts::CodeRejected: ["The contract's code was found to be invalid during validation.", "", "The most likely cause of this is that an API was used which is not supported by the", "node. This happens if an older node is used with a new version of ink!. Try updating", "your node to the newest available version.", "", "A more detailed error can be found on the node console if debug messages are enabled", "by supplying `-lruntime::contracts=debug`."]

The node logs produce the following error

DEBUG tokio-runtime-worker runtime::contracts: can't instantiate module with provided definitions

It works well when I use CallBuilder

ascjones commented 4 months ago

By default the cross contract calls via traits will call into the new call_v2 host function. See https://use.ink/faq/migrating-from-ink-4-to-5/#call-and-instantiate-v2.

The aleph zero node likely does not support the v2 function currently, so you will need to explicitly indicate you want to call the legacy call_v1 method.

You need to do something like the following to call:

let mut psp22: contract_ref!(PSP22) = AccountId::from(token.bytes).into();
let psp22_builder = erc20.call_mut();
psp22_builder
  .transfer_from(
     AccountId::from(user.bytes),
     self.env().account_id(),
     amount,
     [].to_vec(),
  )
  .call_v1()
  .invoke()