Skip to content

Add ownKeys trap to Result #4170

Open
Open
@drortirosh

Description

@drortirosh

Ethers Version

6.6.0

Search Terms

abi, decode

Describe the Problem

The following sample (executable in both ethers 5.7 and ethers 6.x), shows how AbiCoder.decode of v6 returns the correct value, but removes type information.
The returned struct is only valid as a 2-entry array, but field names are lost.

v5 returned data:

decoded struct= [
  BigNumber { _hex: '0x01', _isBigNumber: true },
  BigNumber { _hex: '0x02', _isBigNumber: true },
  stake: BigNumber { _hex: '0x01', _isBigNumber: true },
  unstakeDelaySec: BigNumber { _hex: '0x02', _isBigNumber: true }
]
decomposed struct: {
  '0': BigNumber { _hex: '0x01', _isBigNumber: true },
  '1': BigNumber { _hex: '0x02', _isBigNumber: true },
  stake: BigNumber { _hex: '0x01', _isBigNumber: true },
  unstakeDelaySec: BigNumber { _hex: '0x02', _isBigNumber: true }
}
decomposed manually: {
  stake: BigNumber { _hex: '0x01', _isBigNumber: true },
  unstakeDelaySec: BigNumber { _hex: '0x02', _isBigNumber: true }
}

(that is, can be parsed both as an array and as a struct)

v6 returned data:

decoded struct= Result(2) [ 1n, 2n ]
decomposed struct: { '0': 1n, '1': 2n }
decomposed manually: { stake: 1n, unstakeDelaySec: 2n }

(that is, it is a 2-element array, with no field names - they if referenced manually, the value by field can be extracted)

The following sample can be executed as both ethers v5 and ethers v6:

Code Snippet

// save the following code as "testDecode.js" and execute with "node testDecode.js"
// works with either ethers v5.7 and ethers v6.6
// ethers v6 decodes the struct into an array, and lose the original field names.
// ethers v5 returns a struct can can be used both as an array AND as a struct (mapping)
const ethers = require('ethers')
const { AbiCoder } = require('ethers')

function run () {
  let coder
  //ethers v6:
  if (AbiCoder) {
    coder = AbiCoder.defaultAbiCoder()
  } else {
    //ethers v5:
    coder = ethers.utils.defaultAbiCoder
  }

  const info = {
    stake: 1,
    unstakeDelaySec: 2
  }
  const stakeInfoType = {
    name: 'stakeInfo',
    components: [
      {
        internalType: 'uint256',
        name: 'stake',
        type: 'uint256'
      },
      {
        internalType: 'uint256',
        name: 'unstakeDelaySec',
        type: 'uint256'
      }
    ],
    internalType: 'struct StakeInfo',
    type: 'tuple'
  } 

  console.log('input struct:', info)
  const enc = coder.encode([stakeInfoType], [info])
  console.log('enc=', enc)
  const dec = coder.decode([stakeInfoType], enc)[0]
  console.log('decoded struct=', dec)
  console.log('decomposed struct:',{...dec })
  const {stake, unstakeDelaySec} = dec 
  console.log('decomposed manually:',{ stake, unstakeDelaySec })

}

run()

Contract ABI

No response

Errors

No response

Environment

node.js (v12 or newer), Hardhat

Environment (Other)

No response

Metadata

Metadata

Assignees

Labels

enhancementNew feature or improvement.minor-bumpPlanned for the next minor version bump.next-patchIssues scheduled for the next arch release.v6Issues regarding v6

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions