diff --git a/.changeset/lucky-vans-hope.md b/.changeset/lucky-vans-hope.md new file mode 100644 index 0000000000..461e9b9cf7 --- /dev/null +++ b/.changeset/lucky-vans-hope.md @@ -0,0 +1,6 @@ +--- +'@chainlink/proof-of-reserves-adapter': major +'@chainlink/view-function-multi-chain-adapter': minor +--- + +USDO PoR EA Update - Remove viewFunctionIndexerResultDecimals input param diff --git a/packages/composites/proof-of-reserves/src/endpoint/reserves.ts b/packages/composites/proof-of-reserves/src/endpoint/reserves.ts index 61aa8014d9..f6f0ab3d15 100644 --- a/packages/composites/proof-of-reserves/src/endpoint/reserves.ts +++ b/packages/composites/proof-of-reserves/src/endpoint/reserves.ts @@ -31,7 +31,6 @@ export type TInputParameters = { description?: string startUTC?: string endUTC?: string - viewFunctionIndexerResultDecimals?: number } const inputParameters: InputParameters = { @@ -115,13 +114,6 @@ const inputParameters: InputParameters = { type: 'string', description: 'end time for scheduleWindow in UTC [Format HHMM]', }, - // TODO: https://smartcontract-it.atlassian.net/browse/OPDATA-3775 - viewFunctionIndexerResultDecimals: { - required: false, - type: 'number', - description: - 'The decimal precision of the value returned by the view-function-multi-chain indexer for the contract answer.', - }, } export const execute: ExecuteWithConfig = async (input, context, config) => { const validator = new Validator(input, inputParameters, config.options) @@ -168,13 +160,7 @@ export const execute: ExecuteWithConfig = async (input, context, config) validator.validated.data.indexerParams, ) - const reduceOutput = await runReduceAdapter( - indexer, - context, - balanceOutput, - indexerEndpoint, - validator.validated.data.viewFunctionIndexerResultDecimals, - ) + const reduceOutput = await runReduceAdapter(indexer, context, balanceOutput, indexerEndpoint) reduceOutput.data.description = validator.validated.data.description return reduceOutput } diff --git a/packages/composites/proof-of-reserves/src/utils/reduce.ts b/packages/composites/proof-of-reserves/src/utils/reduce.ts index 727186ee14..1447871742 100644 --- a/packages/composites/proof-of-reserves/src/utils/reduce.ts +++ b/packages/composites/proof-of-reserves/src/utils/reduce.ts @@ -49,7 +49,6 @@ export const runReduceAdapter = async ( context: AdapterContext, input: AdapterResponse, indexerEndpoint?: string, - viewFunctionIndexerResultDecimals?: number, ): Promise => { // Some adapters' balances come already reduced // but needs to be converted from their base unit @@ -114,15 +113,10 @@ export const runReduceAdapter = async ( } break case viewFunctionMultiChain.name: - if (!viewFunctionIndexerResultDecimals) { - throw new Error( - 'viewFunctionIndexerResultDecimals is a required parameter when using the view-function-multi-chain indexer', - ) - } return returnParsedUnits( input.jobRunID, parseHexToBigInt(input.data.result).toString(), - 18 - (viewFunctionIndexerResultDecimals as number), + 18 - (input.data.decimals as number), false, 18, ) diff --git a/packages/composites/proof-of-reserves/test/integration/__snapshots__/adapter.test.ts.snap b/packages/composites/proof-of-reserves/test/integration/__snapshots__/adapter.test.ts.snap index 8c69196fa5..a385184ec1 100644 --- a/packages/composites/proof-of-reserves/test/integration/__snapshots__/adapter.test.ts.snap +++ b/packages/composites/proof-of-reserves/test/integration/__snapshots__/adapter.test.ts.snap @@ -67,19 +67,6 @@ exports[`execute multiReserves endpoint should return success 1`] = ` } `; -exports[`execute multiReserves endpoint view-function-multi-chain fails 1`] = ` -{ - "error": { - "feedID": "054baf47a9ff27c8384416a3ce83c17c", - "message": "viewFunctionIndexerResultDecimals is a required parameter when using the view-function-multi-chain indexer", - "name": "Error", - }, - "jobRunID": "1", - "status": "errored", - "statusCode": 500, -} -`; - exports[`execute multiReserves endpoint view-function-multi-chain should return success 1`] = ` { "data": { diff --git a/packages/composites/proof-of-reserves/test/integration/adapter.test.ts b/packages/composites/proof-of-reserves/test/integration/adapter.test.ts index 87707ac572..5b93ef5c43 100644 --- a/packages/composites/proof-of-reserves/test/integration/adapter.test.ts +++ b/packages/composites/proof-of-reserves/test/integration/adapter.test.ts @@ -208,7 +208,6 @@ describe('execute', () => { network: 'BASE', }, disableDuplicateAddressFiltering: true, - viewFunctionIndexerResultDecimals: 6, }, } mockViewFunctionMultiChainSuccess() @@ -222,36 +221,6 @@ describe('execute', () => { .expect(200) expect(response.body).toMatchSnapshot() }) - - it('view-function-multi-chain fails', async () => { - const data: AdapterRequest = { - id: '1', - data: { - endpoint: 'reserves', - protocol: 'list', - addresses: [''], - indexer: 'view_function_multi_chain', - indexerEndpoint: 'function', - indexerParams: { - signature: 'function getPending() public view returns (uint256)', - address: '0xa69b964a597435A2F938cc55FaAbe34F2A9AF278', - network: 'BASE', - }, - disableDuplicateAddressFiltering: true, - }, - } - mockViewFunctionMultiChainSuccess() - - const response = await (context.req as SuperTest) - .post('/') - .send(data) - .set('Accept', '*/*') - .set('Content-Type', 'application/json') - .expect('Content-Type', /json/) - .expect(500) - - expect(response.body).toMatchSnapshot() - }) }) describe('multiReserves endpoint with scaling', () => { diff --git a/packages/composites/proof-of-reserves/test/integration/fixtures.ts b/packages/composites/proof-of-reserves/test/integration/fixtures.ts index 6b06643bbe..9912e023a1 100644 --- a/packages/composites/proof-of-reserves/test/integration/fixtures.ts +++ b/packages/composites/proof-of-reserves/test/integration/fixtures.ts @@ -9,6 +9,7 @@ export const mockViewFunctionMultiChainSuccess = (): nock.Scope => { statusCode: 200, data: { result: '0x000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF', + decimals: 6, }, metricsMeta: { feedId: diff --git a/packages/sources/view-function-multi-chain/src/endpoint/function.ts b/packages/sources/view-function-multi-chain/src/endpoint/function.ts index a91815f874..c0d852d3f5 100644 --- a/packages/sources/view-function-multi-chain/src/endpoint/function.ts +++ b/packages/sources/view-function-multi-chain/src/endpoint/function.ts @@ -36,6 +36,7 @@ export type BaseEndpointTypes = { Response: { Data: { result: string + decimals: number } Result: string } diff --git a/packages/sources/view-function-multi-chain/src/transport/function-common.ts b/packages/sources/view-function-multi-chain/src/transport/function-common.ts index b3abc36789..e6c33fa1b9 100644 --- a/packages/sources/view-function-multi-chain/src/transport/function-common.ts +++ b/packages/sources/view-function-multi-chain/src/transport/function-common.ts @@ -110,6 +110,8 @@ export class MultiChainFunctionTransport< data: encoded, }) + let decimals = await this._get_decimals(networkName, address) + const timestamps = { providerDataRequestedUnixMs, providerDataReceivedUnixMs: Date.now(), @@ -120,7 +122,8 @@ export class MultiChainFunctionTransport< return { data: { - result, + result: result, + decimals: decimals, }, statusCode: 200, result, @@ -128,6 +131,25 @@ export class MultiChainFunctionTransport< } } + async _get_decimals(networkName: string, address: string): Promise { + let decimals: number = 0 + + try { + const decimalsIface = new ethers.Interface(['function decimals() view returns (uint8)']) + const decimalsData = decimalsIface.encodeFunctionData('decimals') + const decimalsEncoded = await this.providers[networkName].call({ + to: address, + data: decimalsData, + }) + const [decodedDecimals] = decimalsIface.decodeFunctionResult('decimals', decimalsEncoded) + decimals = Number(decodedDecimals) + } catch (err) { + logger.warn(`Error fetching decimals, defaulting to 0: ${err}`) + } + + return decimals + } + getSubscriptionTtlFromConfig(adapterSettings: T['Settings']): number { return (adapterSettings as { WARMUP_SUBSCRIPTION_TTL: number }).WARMUP_SUBSCRIPTION_TTL } diff --git a/packages/sources/view-function-multi-chain/test/integration/__snapshots__/adapter.test.ts.snap b/packages/sources/view-function-multi-chain/test/integration/__snapshots__/adapter.test.ts.snap index 03ec5557b5..e513d7b5b5 100644 --- a/packages/sources/view-function-multi-chain/test/integration/__snapshots__/adapter.test.ts.snap +++ b/packages/sources/view-function-multi-chain/test/integration/__snapshots__/adapter.test.ts.snap @@ -31,6 +31,7 @@ exports[`execute aptos-df-reader endpoint should return success 1`] = ` exports[`execute function endpoint should return success 1`] = ` { "data": { + "decimals": 8, "result": "0x000000000000000000000000000000000000000000000000000000005ad789f8", }, "result": "0x000000000000000000000000000000000000000000000000000000005ad789f8", @@ -45,6 +46,7 @@ exports[`execute function endpoint should return success 1`] = ` exports[`execute function endpoint should return success for different network 1`] = ` { "data": { + "decimals": 24, "result": "0x000000000000000000000000000000000000000000000000eead809f678d30f0", }, "result": "0x000000000000000000000000000000000000000000000000eead809f678d30f0", @@ -59,6 +61,7 @@ exports[`execute function endpoint should return success for different network 1 exports[`execute function endpoint should return success with parameters 1`] = ` { "data": { + "decimals": 8, "result": "0x000000000000000000000000000000000000000000000000000000005cf7ff3b", }, "result": "0x000000000000000000000000000000000000000000000000000000005cf7ff3b", @@ -84,6 +87,7 @@ exports[`execute function-response-selector endpoint should fail with non-exista exports[`execute function-response-selector endpoint should return success with resultField 1`] = ` { "data": { + "decimals": 0, "result": "123456789", }, "result": "123456789", diff --git a/packages/sources/view-function-multi-chain/test/integration/fixtures.ts b/packages/sources/view-function-multi-chain/test/integration/fixtures.ts index 9adefeaffb..003c1202a8 100644 --- a/packages/sources/view-function-multi-chain/test/integration/fixtures.ts +++ b/packages/sources/view-function-multi-chain/test/integration/fixtures.ts @@ -37,6 +37,27 @@ export const mockETHMainnetContractCallResponseSuccess = (): nock.Scope => id: request.id, result: '0x000000000000000000000000000000000000000000000000000000005ad789f8', } + } else if ( + request.method === 'eth_call' && + request.params[0].to === '0x2c1d072e956affc0d435cb7ac38ef18d24d9127c' && + request.params[0].data === '0x313ce567' // decimals() + ) { + return { + jsonrpc: '2.0', + id: request.id, + result: '0x0000000000000000000000000000000000000000000000000000000000000008', + } + } else if ( + request.method === 'eth_call' && + request.params[0].to === '0x2c1d072e956affc0d435cb7ac38ef18d24d9127c' && + request.params[0].data === + '0xb5ab58dc0000000000000000000000000000000000000000000000060000000000001df4' + ) { + return { + jsonrpc: '2.0', + id: request.id, + result: '0x000000000000000000000000000000000000000000000000000000005cf7ff3b', + } } else if ( request.method === 'eth_call' && request.params[0].to === '0x2c1d072e956affc0d435cb7ac38ef18d24d9127c' && @@ -110,6 +131,16 @@ export const mockETHGoerliContractCallResponseSuccess = (): nock.Scope => id: request.id, result: '0x000000000000000000000000000000000000000000000000eead809f678d30f0', } + } else if ( + request.method === 'eth_call' && + request.params[0].to === '0x779877a7b0d9e8603169ddbd7836e478b4624789' && + request.params[0].data === '0x313ce567' // decimals() + ) { + return { + jsonrpc: '2.0', + id: request.id, + result: '0x0000000000000000000000000000000000000000000000000000000000000018', + } } else { // Default response for unsupported calls return {