Skip to content

Commit

Permalink
Initial implementation of Stateful Precompile Contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
evgeniy-scherbina committed Jan 31, 2024
1 parent d51a703 commit a7ad11f
Show file tree
Hide file tree
Showing 24 changed files with 1,070 additions and 102 deletions.
2 changes: 2 additions & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ import (
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
_ "github.com/ethereum/go-ethereum/eth/tracers/native"

_ "github.com/ethereum/go-ethereum/precompile/registry"

"github.com/urfave/cli/v2"
)

Expand Down
21 changes: 21 additions & 0 deletions contracts/contracts/ExampleSum3.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
pragma solidity ^0.8.0;

import "hardhat/console.sol";

address constant PRECOMPILED_SUM3_CONTRACT_ADDRESS = address(0x0300000000000000000000000000000000000000);

interface ISum3 {
function calcSum3(uint256 a, uint256 b, uint256 c) external;
function getSum3() external view returns (uint256 result);
}

contract ExampleSum3 {
function calcSum3(uint256 a, uint256 b, uint256 c) public {
ISum3(PRECOMPILED_SUM3_CONTRACT_ADDRESS).calcSum3(a,b,c);
}

function getSum3() public view returns (uint256) {
uint256 result = ISum3(PRECOMPILED_SUM3_CONTRACT_ADDRESS).getSum3();
return result;
}
}
44 changes: 44 additions & 0 deletions contracts/test/sum3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { expect } from "chai";
import { ethers } from "hardhat";
import {BaseContract, Contract} from "ethers";
import {HardhatEthersSigner} from "@nomicfoundation/hardhat-ethers/src/signers";

const PRECOMPILED_SUM3_CONTRACT_ADDRESS: string = "0x0300000000000000000000000000000000000000";

const sum3ContractABI: string[] = [
"function calcSum3(uint256 a, uint256 b, uint256 c) external",
"function getSum3() external view returns (uint256)",
];

describe("Testing precompiled sum3 contract", function() {
it("Should properly calculate sum of 3 numbers (direct call to precompiled contract)", async function () {
const sum3Contract: Contract = new ethers.Contract(PRECOMPILED_SUM3_CONTRACT_ADDRESS, sum3ContractABI, ethers.provider);
const signers: HardhatEthersSigner[] = await ethers.getSigners();
const sum3ContractWithSigner: BaseContract = sum3Contract.connect(signers[0]);

await sum3ContractWithSigner.calcSum3(2, 3, 4);
let actual: string = await sum3Contract.getSum3();
let expected: string = "0x0000000000000000000000000000000000000000000000000000000000000009";
expect(actual).to.equal(expected);

await sum3ContractWithSigner.calcSum3(3, 5, 7);
actual = await sum3Contract.getSum3();
expected = "0x000000000000000000000000000000000000000000000000000000000000000f"
expect(actual).to.equal(expected);
})

it("Should properly calculate sum of 3 numbers (call to example contract)", async function () {
const ExampleSum3 = await ethers.getContractFactory("ExampleSum3");
const exampleSum3 = await ExampleSum3.deploy();

await exampleSum3.calcSum3(2, 3, 4);
let actual: string = await exampleSum3.getSum3();
let expected: string = "0x0000000000000000000000000000000000000000000000000000000000000009";
expect(actual).to.equal(expected);

await exampleSum3.calcSum3(3, 5, 7);
actual = await exampleSum3.getSum3();
expected = "0x000000000000000000000000000000000000000000000000000000000000000f";
expect(actual).to.equal(expected);
})
})
103 changes: 103 additions & 0 deletions contracts/typechain-types/ExampleSum3.sol/ExampleSum3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */
import type {
BaseContract,
BigNumberish,
BytesLike,
FunctionFragment,
Result,
Interface,
ContractRunner,
ContractMethod,
Listener,
} from "ethers";
import type {
TypedContractEvent,
TypedDeferredTopicFilter,
TypedEventLog,
TypedListener,
TypedContractMethod,
} from "../common";

export interface ExampleSum3Interface extends Interface {
getFunction(nameOrSignature: "calcSum3" | "getSum3"): FunctionFragment;

encodeFunctionData(
functionFragment: "calcSum3",
values: [BigNumberish, BigNumberish, BigNumberish]
): string;
encodeFunctionData(functionFragment: "getSum3", values?: undefined): string;

decodeFunctionResult(functionFragment: "calcSum3", data: BytesLike): Result;
decodeFunctionResult(functionFragment: "getSum3", data: BytesLike): Result;
}

export interface ExampleSum3 extends BaseContract {
connect(runner?: ContractRunner | null): ExampleSum3;
waitForDeployment(): Promise<this>;

interface: ExampleSum3Interface;

queryFilter<TCEvent extends TypedContractEvent>(
event: TCEvent,
fromBlockOrBlockhash?: string | number | undefined,
toBlock?: string | number | undefined
): Promise<Array<TypedEventLog<TCEvent>>>;
queryFilter<TCEvent extends TypedContractEvent>(
filter: TypedDeferredTopicFilter<TCEvent>,
fromBlockOrBlockhash?: string | number | undefined,
toBlock?: string | number | undefined
): Promise<Array<TypedEventLog<TCEvent>>>;

on<TCEvent extends TypedContractEvent>(
event: TCEvent,
listener: TypedListener<TCEvent>
): Promise<this>;
on<TCEvent extends TypedContractEvent>(
filter: TypedDeferredTopicFilter<TCEvent>,
listener: TypedListener<TCEvent>
): Promise<this>;

once<TCEvent extends TypedContractEvent>(
event: TCEvent,
listener: TypedListener<TCEvent>
): Promise<this>;
once<TCEvent extends TypedContractEvent>(
filter: TypedDeferredTopicFilter<TCEvent>,
listener: TypedListener<TCEvent>
): Promise<this>;

listeners<TCEvent extends TypedContractEvent>(
event: TCEvent
): Promise<Array<TypedListener<TCEvent>>>;
listeners(eventName?: string): Promise<Array<Listener>>;
removeAllListeners<TCEvent extends TypedContractEvent>(
event?: TCEvent
): Promise<this>;

calcSum3: TypedContractMethod<
[a: BigNumberish, b: BigNumberish, c: BigNumberish],
[void],
"nonpayable"
>;

getSum3: TypedContractMethod<[], [bigint], "view">;

getFunction<T extends ContractMethod = ContractMethod>(
key: string | FunctionFragment
): T;

getFunction(
nameOrSignature: "calcSum3"
): TypedContractMethod<
[a: BigNumberish, b: BigNumberish, c: BigNumberish],
[void],
"nonpayable"
>;
getFunction(
nameOrSignature: "getSum3"
): TypedContractMethod<[], [bigint], "view">;

filters: {};
}
103 changes: 103 additions & 0 deletions contracts/typechain-types/ExampleSum3.sol/ISum3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */
import type {
BaseContract,
BigNumberish,
BytesLike,
FunctionFragment,
Result,
Interface,
ContractRunner,
ContractMethod,
Listener,
} from "ethers";
import type {
TypedContractEvent,
TypedDeferredTopicFilter,
TypedEventLog,
TypedListener,
TypedContractMethod,
} from "../common";

export interface ISum3Interface extends Interface {
getFunction(nameOrSignature: "calcSum3" | "getSum3"): FunctionFragment;

encodeFunctionData(
functionFragment: "calcSum3",
values: [BigNumberish, BigNumberish, BigNumberish]
): string;
encodeFunctionData(functionFragment: "getSum3", values?: undefined): string;

decodeFunctionResult(functionFragment: "calcSum3", data: BytesLike): Result;
decodeFunctionResult(functionFragment: "getSum3", data: BytesLike): Result;
}

export interface ISum3 extends BaseContract {
connect(runner?: ContractRunner | null): ISum3;
waitForDeployment(): Promise<this>;

interface: ISum3Interface;

queryFilter<TCEvent extends TypedContractEvent>(
event: TCEvent,
fromBlockOrBlockhash?: string | number | undefined,
toBlock?: string | number | undefined
): Promise<Array<TypedEventLog<TCEvent>>>;
queryFilter<TCEvent extends TypedContractEvent>(
filter: TypedDeferredTopicFilter<TCEvent>,
fromBlockOrBlockhash?: string | number | undefined,
toBlock?: string | number | undefined
): Promise<Array<TypedEventLog<TCEvent>>>;

on<TCEvent extends TypedContractEvent>(
event: TCEvent,
listener: TypedListener<TCEvent>
): Promise<this>;
on<TCEvent extends TypedContractEvent>(
filter: TypedDeferredTopicFilter<TCEvent>,
listener: TypedListener<TCEvent>
): Promise<this>;

once<TCEvent extends TypedContractEvent>(
event: TCEvent,
listener: TypedListener<TCEvent>
): Promise<this>;
once<TCEvent extends TypedContractEvent>(
filter: TypedDeferredTopicFilter<TCEvent>,
listener: TypedListener<TCEvent>
): Promise<this>;

listeners<TCEvent extends TypedContractEvent>(
event: TCEvent
): Promise<Array<TypedListener<TCEvent>>>;
listeners(eventName?: string): Promise<Array<Listener>>;
removeAllListeners<TCEvent extends TypedContractEvent>(
event?: TCEvent
): Promise<this>;

calcSum3: TypedContractMethod<
[a: BigNumberish, b: BigNumberish, c: BigNumberish],
[void],
"nonpayable"
>;

getSum3: TypedContractMethod<[], [bigint], "view">;

getFunction<T extends ContractMethod = ContractMethod>(
key: string | FunctionFragment
): T;

getFunction(
nameOrSignature: "calcSum3"
): TypedContractMethod<
[a: BigNumberish, b: BigNumberish, c: BigNumberish],
[void],
"nonpayable"
>;
getFunction(
nameOrSignature: "getSum3"
): TypedContractMethod<[], [bigint], "view">;

filters: {};
}
5 changes: 5 additions & 0 deletions contracts/typechain-types/ExampleSum3.sol/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */
export type { ExampleSum3 } from "./ExampleSum3";
export type { ISum3 } from "./ISum3";
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */
import {
Contract,
ContractFactory,
ContractTransactionResponse,
Interface,
} from "ethers";
import type { Signer, ContractDeployTransaction, ContractRunner } from "ethers";
import type { NonPayableOverrides } from "../../common";
import type {
ExampleSum3,
ExampleSum3Interface,
} from "../../ExampleSum3.sol/ExampleSum3";

const _abi = [
{
inputs: [
{
internalType: "uint256",
name: "a",
type: "uint256",
},
{
internalType: "uint256",
name: "b",
type: "uint256",
},
{
internalType: "uint256",
name: "c",
type: "uint256",
},
],
name: "calcSum3",
outputs: [],
stateMutability: "nonpayable",
type: "function",
},
{
inputs: [],
name: "getSum3",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256",
},
],
stateMutability: "view",
type: "function",
},
] as const;

const _bytecode =
"0x608060405234801561001057600080fd5b506102f3806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80638e2a5b251461003b578063a104464e14610057575b600080fd5b610055600480360381019061005091906101c7565b610075565b005b61005f6100fd565b60405161006c9190610229565b60405180910390f35b73030000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16638e2a5b258484846040518463ffffffff1660e01b81526004016100c693929190610244565b600060405180830381600087803b1580156100e057600080fd5b505af11580156100f4573d6000803e3d6000fd5b50505050505050565b60008073030000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a104464e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561015f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101839190610290565b90508091505090565b600080fd5b6000819050919050565b6101a481610191565b81146101af57600080fd5b50565b6000813590506101c18161019b565b92915050565b6000806000606084860312156101e0576101df61018c565b5b60006101ee868287016101b2565b93505060206101ff868287016101b2565b9250506040610210868287016101b2565b9150509250925092565b61022381610191565b82525050565b600060208201905061023e600083018461021a565b92915050565b6000606082019050610259600083018661021a565b610266602083018561021a565b610273604083018461021a565b949350505050565b60008151905061028a8161019b565b92915050565b6000602082840312156102a6576102a561018c565b5b60006102b48482850161027b565b9150509291505056fea2646970667358221220809168385427697f8571a2fa81d6ffd9fcb93182e02b234996ae8c93bb63b97664736f6c63430008130033";

type ExampleSum3ConstructorParams =
| [signer?: Signer]
| ConstructorParameters<typeof ContractFactory>;

const isSuperArgs = (
xs: ExampleSum3ConstructorParams
): xs is ConstructorParameters<typeof ContractFactory> => xs.length > 1;

export class ExampleSum3__factory extends ContractFactory {
constructor(...args: ExampleSum3ConstructorParams) {
if (isSuperArgs(args)) {
super(...args);
} else {
super(_abi, _bytecode, args[0]);
}
}

override getDeployTransaction(
overrides?: NonPayableOverrides & { from?: string }
): Promise<ContractDeployTransaction> {
return super.getDeployTransaction(overrides || {});
}
override deploy(overrides?: NonPayableOverrides & { from?: string }) {
return super.deploy(overrides || {}) as Promise<
ExampleSum3 & {
deploymentTransaction(): ContractTransactionResponse;
}
>;
}
override connect(runner: ContractRunner | null): ExampleSum3__factory {
return super.connect(runner) as ExampleSum3__factory;
}

static readonly bytecode = _bytecode;
static readonly abi = _abi;
static createInterface(): ExampleSum3Interface {
return new Interface(_abi) as ExampleSum3Interface;
}
static connect(address: string, runner?: ContractRunner | null): ExampleSum3 {
return new Contract(address, _abi, runner) as unknown as ExampleSum3;
}
}
Loading

0 comments on commit a7ad11f

Please sign in to comment.