api icon indicating copy to clipboard operation
api copied to clipboard

`api-contracts`: handle foreign events gracefully

Open peetzweg opened this issue 11 months ago • 7 comments

During the adaption of the event decoding for smart contract for ink! v5, https://github.com/polkadot-js/api/pull/5791, it became clear that the prior and current implementation can't handle all circumstances gracefully.

The current implementation supports:

What could be improved:

  • handle inability to determine anonymous event more gracefully by not decoding it and just returning bytes. The overall flow of how the decoding is done, does not allow for this now afaik.

Another usecase for this feature would be in handling foreign events. Foreign events are events emitted by the called contract but are defined in a different contract which was invoked by the called contract. For what I know this case of decoding events from a contract which ABI we don't have is not handled and will result in errors being thrown.

More information about this behavior you can find here:

  • https://use.ink/5.x/basics/cross-contract-calling
  • https://github.com/polkadot-js/api/pull/5791#discussion_r1508979417

peetzweg avatar Mar 04 '24 10:03 peetzweg

Could #5791 be responsible for this error? Expected Option<*> definition for accountId in ContractEnvironment I started getting this today with this new version but it works in old one so it seems like a breaking change?

tad3j avatar Mar 04 '24 14:03 tad3j

@tad3j Feels unlikely to me but not impossible. Could you share some code and steps to reproduce this? In which context is this happening?

peetzweg avatar Mar 04 '24 14:03 peetzweg

It's failing on line marked bellow (old version of code) when parsing this abi. image

Code:

const contract = new PinkContractPromise(
      this.api,
      this.registry,
      contractAbi,
      contractAddress,
      contractKey,
    );
const keyring = new Keyring({ type: 'sr25519' });
const account = keyring.addFromUri('//Alice');
const certificate = await signCertificate({ api: this.api, pair: account });
onst response = await contract.query.encryptContent(
      account.address,
      {
        cert: certificate,
      },
      content,
    );
return response.output.toJSON()['ok'].ok;

tad3j avatar Mar 04 '24 15:03 tad3j

@tad3j I was able to instantiate a ContractPromise instance without a problem with the latest pjs version.

Here is my code:

import { ApiPromise, WsProvider } from "@polkadot/api";
import { ContractPromise } from "@polkadot/api-contract";
import abi from "./abi.json";

const wsProvider = new WsProvider(`wss://rococo-contracts-rpc.polkadot.io`);
const api = await ApiPromise.create({
  provider: wsProvider,
});
const address = "5EnufwqqxnkWT6hc1LgjYWQGUsqQCtcr5192K2HuQJtRJgCi";

try {
  const contract = new ContractPromise(api, abi, address);
  console.log({ environment: contract.abi.environment });
} catch (error) {
  console.error("Initializing contract error", error);
}

process.exit(0);

You could run it by i.e npx tsx abi.ts

Not sure what the PinkContractPromise is about in your code. Maybe you are using some sort of wrapper library?

peetzweg avatar Mar 04 '24 16:03 peetzweg

Strange, maybe it's issue with Phala SDK...will check.

Locking to "@polkadot/types": "10.11.3", (version we used before) fixes the issue.

tad3j avatar Mar 05 '24 09:03 tad3j

@tad3j can you share which sdk you are using? Sounds reasonable that it might cause issues with sdks building ontop of pjs. They have probably not yet upgraded their sdk and this could cause hiccups.

peetzweg avatar Mar 05 '24 09:03 peetzweg

I'm using @phala/sdk. They've said they dont support ink v5 so maybe that's why it didn't work.

EDIT: I've completely removed phala but TX signing is still failing.

tad3j avatar Mar 05 '24 16:03 tad3j