Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tuple return values from contract calls cannot be used as parameters in subsequent calls. #4730

Open
mountainpath9 opened this issue May 16, 2024 · 1 comment
Assignees
Labels
investigate Under investigation and may be a bug. v6 Issues regarding v6

Comments

@mountainpath9
Copy link

mountainpath9 commented May 16, 2024

Ethers Version

6.12.1

Search Terms

abi

Describe the Problem

expected:

  1. call a contract view method that returns a tuple
  2. use the returned tuple as a parameter to a subsequent contract view method call

the second call should succeed

observed:

the second call fails with an exception

Code Snippet

import { Contract, JsonRpcProvider } from "ethers";

const MORPHO_ABI = [
  "function idToMarketParams(bytes32 id) external view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)",
  "function market(bytes32 id) external view returns (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee)",
];

const IIRM_ABI = [
  "function borrowRateView((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) memory marketParams, (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee) memory market) external view returns (uint256)",
];

async function broken() {
  const provider = new JsonRpcProvider("https://eth.llamarpc.com");
  const marketId = "0xc581c5f70bd1afa283eed57d1418c6432cbff1d862f94eaf58fdd4e46afbb67f"
  const morpho = new Contract("0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb", MORPHO_ABI, provider);
  const marketParams = await morpho.idToMarketParams(marketId);
  console.log("marketParams", marketParams);
  const market = await morpho.market(marketId);
  console.log("market", market);

  const irm = new Contract(marketParams[3], IIRM_ABI, provider);
  const borrowRate = await irm.borrowRateView(marketParams, market);
  console.log("borrowRate", borrowRate);
}

broken()

Contract ABI

(see code above)

Errors

marketParams Result(5) [
  '0x6B175474E89094C44Da98b954EedeAC495271d0F',
  '0x4c9EDD5852cd905f086C759E8383e09bff1E68B3',
  '0xaE4750d0813B5E37A51f7629beedd72AF1f9cA35',
  '0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC',
  860000000000000000n
]
market Result(6) [
  143646693420632712048392077n,
  138787440880551261968694027994569n,
  119618520385587078436088379n,
  115178926608471665264960764648817n,
  1715823875n,
  0n
]
/tmp/test/node_modules/ethers/src.ts/abi/fragments.ts:772
                    result[index] = value;
                                 ^


TypeError: Cannot assign to read only property '0' of object '[object Array]'
    at <anonymous> (/tmp/test/node_modules/ethers/src.ts/abi/fragments.ts:772:34)
    at ParamType.#walkAsync (/tmp/test/node_modules/ethers/src.ts/abi/fragments.ts:783:13)
    at <anonymous> (/tmp/test/node_modules/ethers/src.ts/abi/fragments.ts:771:45)
    at Result.forEach (<anonymous>)
    at Proxy.<anonymous> (/tmp/test/node_modules/ethers/src.ts/abi/coders/abstract-coder.ts:118:42)
    at ParamType.#walkAsync (/tmp/test/node_modules/ethers/src.ts/abi/fragments.ts:770:20)
    at ParamType.walkAsync (/tmp/test/node_modules/ethers/src.ts/abi/fragments.ts:797:24)
    at <anonymous> (/tmp/test/node_modules/ethers/src.ts/contract/contract.ts:170:22)
    at Array.map (<anonymous>)
    at resolveArgs (/tmp/test/node_modules/ethers/src.ts/contract/contract.ts:169:37)

Environment

Ethereum (mainnet/ropsten/rinkeby/goerli)

Environment (Other)

No response

@mountainpath9 mountainpath9 added investigate Under investigation and may be a bug. v6 Issues regarding v6 labels May 16, 2024
@mountainpath9
Copy link
Author

A workaround is to shallow copy the tuples, ie:

  const borrowRate = await irm.borrowRateView([...marketParams], [...market]);

but this:

  • shouldn't be necessary
  • doesn't work with contracts that are statically typed via typechain

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
investigate Under investigation and may be a bug. v6 Issues regarding v6
Projects
None yet
Development

No branches or pull requests

2 participants