Search code examples
nearprotocolaurora-near

How to Borsh serialize (in Typescript) arguments to interact with Aurora contract from Near?


I have the following contract deployed on Aurora testnet:

pragma solidity >=0.6.12 <0.9.0;

contract Counter {
  uint256 value;

  function print() public view returns (uint256) {
    return value;
  }

  function inc() public {
    value = value + 1;
  }
}

I want to call inc() from a Near account by interacting with aurora contract deployed on Near.

I am trying to Borsh serialize the arguments (using borsh-js) following: https://github.com/aurora-is-near/aurora-contracts-sdk/blob/main/docs/AuroraFromNear.md

As per my understanding (likely wrong) I have the following schema:

const functionCallArgsV2 = {
    struct: {
      contract: "string",
      value: "u8",
      input: { array: { type: "u8" } },
    },
  };

  const schema = {
    enum: [
      {
        struct: {
          FunctionCallArgsV2: functionCallArgsV2,
        },
      },
    ],
  };

For simplicity I want to serialize the following arguments:

const address = "0x202ef3618820deadca5017cc585d489c585cc2e3";
const input = "0x371303c0"; // input data for "inc"
const value = 0;

const inputBase64 = Buffer.from(input, "hex").toString("base64");
const inputEncoded = Buffer.from(inputBase64, "base64");
const data = {
    FunctionCallArgsV2: {
      contract: contractEncoded,
      value: value,
      input: inputEncoded,
    },
  };

const dataEncoded = borsh.serialize(schemaZ, data);

const functionCallResponse = await account.functionCall({
    contractId: AURORA,
    methodName: "call",
    args: dataEncoded,
  });

Transaction result:

{
  "ActionError": {
    "index": 0,
    "kind": {
      "FunctionCallError": {
        "ExecutionError": "Smart contract panicked: ERR_BORSH_DESERIALIZE"
      }
    }
  }
}

How can I Borsh serialize correctly?


Solution

  • The contract expects the input to be of the type CallArgs rather than FunctionCallArgsV2.

    See the definition of CallArgs here:

    #[derive(BorshSerialize, BorshDeserialize, Debug, PartialEq, Eq, Clone)]
    pub enum CallArgs {
        V2(FunctionCallArgsV2),
        V1(FunctionCallArgsV1),
    }
    

    The borsh serialization of the inner type, is not the same as of the wrapped type (they have one byte of difference). You will need to wrap your variable data into an enum following that signature.