ethers.js
ethers.js copied to clipboard
Add ownKeys trap to Result
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
Can I work on this issue ?
UPDATED: The returned object DOES contain internally the field names - it is just very shy about it, and doesn't expose them. caller must know field names and ask them explicitly, but { ...dec } decompose operator doesn't return the field names, only by numerical indices
Yes, all named parameters are available on the Result object. You may also use result.toObject() to flatten it into a put JavaScript object.
The keys aren't visible because getters are not enumerable. I will research whether adding the ownKeys trap to make the names show up to the Object.keys() function, which should make console.log more noisy, which sounds like what you want.
is there any update here?