Skip to content

Commit

Permalink
Implement call with support for bytecode (deployless) calls
Browse files Browse the repository at this point in the history
  • Loading branch information
ryangoree committed Dec 9, 2024
1 parent 16d7393 commit 81e5362
Show file tree
Hide file tree
Showing 21 changed files with 1,765 additions and 383 deletions.
5 changes: 5 additions & 0 deletions .changeset/wise-camels-marry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@delvtech/drift": patch
---

Added a `call` method to `Drift` and adapters with support for bytecode (deployless) calls.
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[submodule "contracts/lib/forge-std"]
path = contracts/lib/forge-std
url = https://github.com/foundry-rs/forge-std
url = git@github.com:foundry-rs/forge-std.git
1 change: 1 addition & 0 deletions contracts/lib/forge-std
Submodule forge-std added at 1eea5b
14 changes: 14 additions & 0 deletions contracts/src/MockErc20Example.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.24;

import {MockERC20} from "forge-std/mocks/MockERC20.sol";

/**
* @title MockErc20Example
* @notice
*/
contract MockErc20Example is MockERC20 {
constructor() MockERC20() {
initialize("MockERC20Example", "ME", 18);
}
}
45 changes: 45 additions & 0 deletions packages/drift/src/adapter/MockAdapter.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { MockAdapter } from "src/adapter/MockAdapter";
import type {
CallParams,
DecodeFunctionDataParams,
EncodeFunctionDataParams,
GetEventsParams,
Expand Down Expand Up @@ -389,6 +390,50 @@ describe("MockAdapter", () => {
});
});

describe("call", () => {
it("Rejects with an error by default", async () => {
const adapter = new MockAdapter();
let error: unknown;
try {
await adapter.call({
to: "0x",
});
} catch (e) {
error = e;
}
expect(error).toBeInstanceOf(Error);
});

it("Can be stubbed with specific params", async () => {
const adapter = new MockAdapter();
const params1: CallParams = {
to: "0x1",
};
const params2: CallParams = {
to: "0x2",
};
adapter.onCall(params1).resolves("0xA");
adapter.onCall(params2).resolves("0xB");
expect(await adapter.call(params1)).toBe("0xA");
expect(await adapter.call(params2)).toBe("0xB");
});

it("Can be stubbed with partial params", async () => {
const adapter = new MockAdapter();
adapter
.onCall({
to: "0x1",
})
.resolves("0xA");
expect(
await adapter.call({
to: "0x1",
data: "0x2",
}),
).toBe("0xA");
});
});

describe("getEvents", () => {
it("Rejects with an error by default", async () => {
const adapter = new MockAdapter();
Expand Down
18 changes: 18 additions & 0 deletions packages/drift/src/adapter/MockAdapter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Abi } from "abitype";
import type { Address, Bytes, Hash } from "src/adapter/types/Abi";
import type {
CallParams,
DecodeFunctionDataParams,
EncodeFunctionDataParams,
GetEventsParams,
Expand Down Expand Up @@ -220,6 +221,23 @@ export class MockAdapter implements ReadWriteAdapter {
})(params as DecodeFunctionDataParams<TAbi, TFunctionName>);
}

// call //

onCall(params: Partial<CallParams>) {
return this.stubs.get<[CallParams], Promise<Bytes>>({
method: "call",
key: this.createKey(params),
});
}

async call(params: CallParams) {
return this.stubs.get<[CallParams], Promise<Bytes>>({
method: "call",
key: this.createKey(params),
matchPartial: true,
})(params);
}

// getEvents //

onGetEvents<TAbi extends Abi, TEventName extends EventName<TAbi>>(
Expand Down
41 changes: 41 additions & 0 deletions packages/drift/src/adapter/OxAdapter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
Transaction,
TransactionReceipt,
} from "src/adapter/types/Transaction";
import { MockErc20Example } from "src/artifacts/MockErc20Example";
import { ZERO_ADDRESS } from "src/constants";
import { erc20 } from "src/utils/testing/erc20";
import { describe, expect, it } from "vitest";
Expand Down Expand Up @@ -118,6 +119,46 @@ describe("OxAdapter", () => {
);
});

describe("call", () => {
it("reads from deployed contracts", async () => {
const adapter = new OxAdapter({ rpcUrl });
const data = adapter.encodeFunctionData({
abi: erc20.abi,
fn: "symbol",
});
const result = await adapter.call({
to: address,
data,
});
// TODO:
// const decoded = adapter.decodeFunctionResult({
// abi: erc20.abi,
// fn: "symbol",
// data: symbol,
// });
expect(result).toEqual(expect.stringMatching(/^0x/));
});

it("reads from bytecodes", async () => {
const adapter = new OxAdapter({ rpcUrl });
const data = adapter.encodeFunctionData({
abi: MockErc20Example.abi,
fn: "name",
});
const result = await adapter.call({
bytecode: MockErc20Example.bytecode,
data,
});
// TODO:
// const decoded = adapter.decodeFunctionResult({
// abi: erc20.abi,
// fn: "symbol",
// data: symbol,
// });
expect(result).toEqual(expect.stringMatching(/^0x/));
});
});

it("fetches events", async () => {
const adapter = new OxAdapter({ rpcUrl });
const currentBlock = await adapter.getBlockNumber();
Expand Down
Loading

0 comments on commit 81e5362

Please sign in to comment.