diff --git a/yarn-project/foundation/src/abi/decoder.ts b/yarn-project/foundation/src/abi/decoder.ts index 3cba542cb49d..35ac4e9c7ca9 100644 --- a/yarn-project/foundation/src/abi/decoder.ts +++ b/yarn-project/foundation/src/abi/decoder.ts @@ -24,11 +24,30 @@ class AbiDecoder { switch (abiType.kind) { case 'field': return this.getNextField().toBigInt(); - case 'integer': + case 'integer': { + const nextField = this.getNextField(); + if (abiType.sign === 'signed') { - throw new Error('Unsupported type: signed integer'); + // We get the last (width / 8) bytes where width = bits of type (i64, i32 etc) + const buf = nextField.toBuffer().subarray(-(abiType.width / 8)); + + // We then parse the buffer using 2's complement + + // If our most significant bit is high + if (0x80 & buf.subarray(0, 1).readUInt8()) { + // We flip the bits + for (let i = 0; i < buf.length; i++) { + buf[i] = ~buf[i]; + } + + // Add one, then negate it + return -(BigInt(buf.toString('hex')) + 1n); + } + + return BigInt(buf.toString('hex')); } - return this.getNextField().toBigInt(); + return nextField.toBigInt(); + } case 'boolean': return !this.getNextField().isZero(); case 'array': {