Skip to content

Commit f3ee89f

Browse files
committed
allow arguments to Sleuth queries
1 parent d1762e0 commit f3ee89f

File tree

4 files changed

+44
-15
lines changed

4 files changed

+44
-15
lines changed

cli/sleuth.ts

+26-14
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ const defaultOpts = {
1717

1818
const sleuthDeployer = process.env['SLEUTH_DEPLOYER'] ?? '0x84C3e20985d9E7aEc46F80d2EB52b731D8CC40F8';
1919

20-
interface Query<T> {
20+
interface Query<T, A extends any[] = []> {
2121
bytecode: string,
2222
callargs?: string,
23-
abi: ReadonlyArray<ParamType>
23+
fn: FunctionFragment
2424
}
2525

2626
interface Source {
@@ -84,16 +84,18 @@ export class Sleuth {
8484
version: number;
8585
sleuthAddr: string;
8686
sources: Source[];
87+
coder: AbiCoder;
8788

8889
constructor(provider: Provider, opts: Opts = {}) {
8990
this.provider = provider;
9091
this.network = opts.network ?? defaultOpts.network;
9192
this.version = opts.version ?? defaultOpts.version;
9293
this.sleuthAddr = getContractAddress({ from: sleuthDeployer, nonce: this.version - 1 });
9394
this.sources = [];
95+
this.coder = new AbiCoder();
9496
}
9597

96-
query<T>(q: string): Query<T> {
98+
query<T>(q: string): Query<T, []> {
9799
let registrations = this.sources.map((source) => {
98100
let iface = JSON.stringify(source.iface.format(FormatTypes.full));
99101
return `REGISTER CONTRACT ${source.name} AT ${source.address} WITH INTERFACE ${iface};`
@@ -132,11 +134,17 @@ export class Sleuth {
132134

133135
return {
134136
bytecode: bytecode,
135-
abi: ParamType.from(tuple).components
137+
fn: FunctionFragment.from({
138+
name: 'query',
139+
inputs: [],
140+
outputs: ParamType.from(tuple).components,
141+
stateMutability: 'pure',
142+
type: 'function'
143+
})
136144
};
137145
}
138146

139-
static querySol<T>(q: string | object, opts: SolidityQueryOpts = {}): Query<T> {
147+
static querySol<T, A extends any[] = []>(q: string | object, opts: SolidityQueryOpts = {}): Query<T, A> {
140148
if (typeof(q) === 'string') {
141149
let r;
142150
try {
@@ -159,7 +167,7 @@ export class Sleuth {
159167
}
160168
}
161169

162-
static querySolOutput<T>(c: SolcContract, opts: SolidityQueryOpts = {}): Query<T> {
170+
static querySolOutput<T, A extends any[] = []>(c: SolcContract, opts: SolidityQueryOpts = {}): Query<T, A> {
163171
let queryFunctionName = opts.queryFunctionName ?? 'query';
164172
let b = c.evm?.bytecode?.object ?? c.bytecode?.object;
165173
if (!b) {
@@ -173,11 +181,11 @@ export class Sleuth {
173181

174182
return {
175183
bytecode: b,
176-
abi: (queryAbi as FunctionFragment).outputs ?? []
184+
fn: queryAbi as FunctionFragment
177185
};
178186
}
179187

180-
static querySolSource<T>(q: string, opts: SolidityQueryOpts = {}): Query<T> {
188+
static querySolSource<T, A extends any[] = []>(q: string, opts: SolidityQueryOpts = {}): Query<T, A> {
181189
let fnName = opts.queryFunctionName ?? 'query';
182190
let input = {
183191
language: 'Solidity',
@@ -219,12 +227,16 @@ export class Sleuth {
219227
this.sources.push({name, address, iface});
220228
}
221229

222-
async fetch<T>(q: Query<T>): Promise<T> {
223-
let sleuthCtx = new Contract(this.sleuthAddr, ['function query(bytes) public view returns (bytes)'], this.provider);
224-
let queryResult = await sleuthCtx.query(hexify(q.bytecode));
225-
console.log(q.abi);
230+
async fetch<T, A extends any[] = []>(q: Query<T, A>, args?: A): Promise<T> {
231+
let sleuthCtx = new Contract(this.sleuthAddr, [
232+
'function query(bytes,bytes) public view returns (bytes)'
233+
], this.provider);
234+
let iface = new Interface([q.fn]);
235+
let argsCoded = iface.encodeFunctionData(q.fn.name, args ?? []);
236+
let queryResult = await sleuthCtx.query(hexify(q.bytecode), argsCoded);
237+
console.log(q.fn);
226238
console.log(queryResult);
227-
let r = new AbiCoder().decode(q.abi, queryResult) as unknown;
239+
let r = this.coder.decode(q.fn.outputs ?? [], queryResult) as unknown;
228240
if (Array.isArray(r) && r.length === 1) {
229241
return r[0] as T;
230242
} else {
@@ -234,6 +246,6 @@ export class Sleuth {
234246

235247
async fetchSql<T>(q: string): Promise<T> {
236248
let query = this.query<T>(q);
237-
return this.fetch<T>(query);
249+
return this.fetch<T, []>(query, []);
238250
}
239251
}

cli/test/sleuth.test.ts

+9
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@ describe('testing sleuthing', () => {
2727
expect(res.toNumber()).toBe(1);
2828
});
2929

30+
test('should handle args', async () => {
31+
let sleuth = new Sleuth(provider);
32+
let solidity = await fs.readFile(path.join(__dirname, '../../out/Birthday.sol/Birthday.json'), 'utf8');
33+
console.log({solidity})
34+
let res = await sleuth.fetch(Sleuth.querySol<BigNumber, [number]>(solidity), [5]);
35+
console.log("res", res);
36+
expect(res.toNumber()).toBe(6);
37+
});
38+
3039
test('should return the pair', async () => {
3140
let sleuth = new Sleuth(provider);
3241
let solidity = await fs.readFile(path.join(__dirname, '../../src/examples/Pair.sol'), 'utf8');

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@compound-finance/sleuth",
3-
"version": "1.0.1-alpha3",
3+
"version": "1.0.1-alpha4",
44
"main": "dist/index.js",
55
"types": "dist/index.d.ts",
66
"files": ["dist/**/*", "parser/pkg/**/*"],

src/examples/Birthday.sol

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.16;
3+
4+
contract Birthday {
5+
function query(uint256 age) external pure returns (uint256) {
6+
return age + 1;
7+
}
8+
}

0 commit comments

Comments
 (0)