Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@ethereum-waffle/mock-contract

Package Overview
Dependencies
Maintainers
1
Versions
143
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ethereum-waffle/mock-contract - npm Package Compare versions

Comparing version 4.0.3-dev.f3d5029 to 4.0.3-dev.f8ca718

23

dist/cjs/src/index.d.ts

@@ -1,8 +0,13 @@

import { Contract, Signer, utils } from 'ethers';
import { BaseContract, Contract, Signer, utils } from 'ethers';
import type { JsonFragment } from '@ethersproject/abi';
declare type ABI = string | Array<utils.Fragment | JsonFragment | string>;
export declare type Stub = ReturnType<typeof stub>;
export interface MockContract extends Contract {
interface StubInterface {
returns(...args: any): StubInterface;
reverts(): StubInterface;
revertsWithReason(reason: string): StubInterface;
withArgs(...args: any[]): StubInterface;
}
export interface MockContract<T extends BaseContract = BaseContract> extends Contract {
mock: {
[key: string]: Stub;
[key in ((keyof T['functions'] | 'receive'))]: StubInterface;
};

@@ -12,10 +17,8 @@ call(contract: Contract, functionName: string, ...params: any[]): Promise<any>;

}
declare function stub(mockContract: Contract, encoder: utils.AbiCoder, func: utils.FunctionFragment, params?: any[]): {
returns: (...args: any) => Promise<void>;
reverts: () => Promise<any>;
revertsWithReason: (reason: string) => Promise<any>;
withArgs: (...args: any[]) => any;
declare type DeployOptions = {
address: string;
override?: boolean;
};
export declare function deployMockContract(signer: Signer, abi: ABI): Promise<MockContract>;
export declare function deployMockContract<T extends BaseContract = BaseContract>(signer: Signer, abi: ABI, options?: DeployOptions): Promise<MockContract<T>>;
export {};
//# sourceMappingURL=index.d.ts.map

@@ -9,22 +9,129 @@ "use strict";

const Doppelganger_json_1 = __importDefault(require("./Doppelganger.json"));
async function deploy(signer) {
class Stub {
constructor(mockContract, encoder, func) {
this.mockContract = mockContract;
this.encoder = encoder;
this.func = func;
this.stubCalls = [];
this.revertSet = false;
this.argsSet = false;
this.callData = mockContract.interface.getSighash(func);
}
err(reason) {
this.stubCalls = [];
this.revertSet = false;
this.argsSet = false;
throw new Error(reason);
}
returns(...args) {
if (this.revertSet)
this.err('Revert must be the last call');
if (!this.func.outputs)
this.err('Cannot mock return values from a void function');
const encoded = this.encoder.encode(this.func.outputs, args);
// if there no calls then this is the first call and we need to use mockReturns to override the queue
if (this.stubCalls.length === 0) {
this.stubCalls.push(async () => {
await this.mockContract.__waffle__mockReturns(this.callData, encoded);
});
}
else {
this.stubCalls.push(async () => {
await this.mockContract.__waffle__queueReturn(this.callData, encoded);
});
}
return this;
}
reverts() {
if (this.revertSet)
this.err('Revert must be the last call');
// if there no calls then this is the first call and we need to use mockReturns to override the queue
if (this.stubCalls.length === 0) {
this.stubCalls.push(async () => {
await this.mockContract.__waffle__mockReverts(this.callData, 'Mock revert');
});
}
else {
this.stubCalls.push(async () => {
await this.mockContract.__waffle__queueRevert(this.callData, 'Mock revert');
});
}
this.revertSet = true;
return this;
}
revertsWithReason(reason) {
if (this.revertSet)
this.err('Revert must be the last call');
// if there no calls then this is the first call and we need to use mockReturns to override the queue
if (this.stubCalls.length === 0) {
this.stubCalls.push(async () => {
await this.mockContract.__waffle__mockReverts(this.callData, reason);
});
}
else {
this.stubCalls.push(async () => {
await this.mockContract.__waffle__queueRevert(this.callData, reason);
});
}
this.revertSet = true;
return this;
}
withArgs(...params) {
if (this.argsSet)
this.err('withArgs can be called only once');
this.callData = this.mockContract.interface.encodeFunctionData(this.func, params);
this.argsSet = true;
return this;
}
async then(resolve, reject) {
for (let i = 0; i < this.stubCalls.length; i++) {
try {
await this.stubCalls[i]();
}
catch (e) {
this.stubCalls = [];
this.argsSet = false;
this.revertSet = false;
reject(e);
return;
}
}
this.stubCalls = [];
this.argsSet = false;
this.revertSet = false;
resolve();
}
}
async function deploy(signer, options) {
if (options) {
const { address, override } = options;
const provider = signer.provider;
if (!override && await provider.getCode(address) !== '0x') {
throw new Error(`${address} already contains a contract. ` +
'If you want to override it, set the override parameter.');
}
if (provider._hardhatNetwork) {
if (await provider.send('hardhat_setCode', [
address,
'0x' + Doppelganger_json_1.default.evm.deployedBytecode.object
])) {
return new ethers_1.Contract(address, Doppelganger_json_1.default.abi, signer);
}
else
throw new Error(`Couldn't deploy at ${address}`);
}
else {
if (await provider.send('evm_setAccountCode', [
address,
'0x' + Doppelganger_json_1.default.evm.deployedBytecode.object
])) {
return new ethers_1.Contract(address, Doppelganger_json_1.default.abi, signer);
}
else
throw new Error(`Couldn't deploy at ${address}`);
}
}
const factory = new ethers_1.ContractFactory(Doppelganger_json_1.default.abi, Doppelganger_json_1.default.bytecode, signer);
return factory.deploy();
}
function stub(mockContract, encoder, func, params) {
const callData = params
? mockContract.interface.encodeFunctionData(func, params)
: mockContract.interface.getSighash(func);
return {
returns: async (...args) => {
if (!func.outputs)
return;
const encoded = encoder.encode(func.outputs, args);
await mockContract.__waffle__mockReturns(callData, encoded);
},
reverts: async () => mockContract.__waffle__mockReverts(callData, 'Mock revert'),
revertsWithReason: async (reason) => mockContract.__waffle__mockReverts(callData, reason),
withArgs: (...args) => stub(mockContract, encoder, func, args)
};
}
function createMock(abi, mockContractInstance) {

@@ -34,3 +141,3 @@ const { functions } = new ethers_1.utils.Interface(abi);

const mockedAbi = Object.values(functions).reduce((acc, func) => {
const stubbed = stub(mockContractInstance, encoder, func);
const stubbed = new Stub(mockContractInstance, encoder, func);
return {

@@ -42,6 +149,12 @@ ...acc,

}, {});
mockedAbi.receive = {
returns: () => { throw new Error('Receive function return is not implemented.'); },
withArgs: () => { throw new Error('Receive function return is not implemented.'); },
reverts: () => mockContractInstance.__waffle__receiveReverts('Mock Revert'),
revertsWithReason: (reason) => mockContractInstance.__waffle__receiveReverts(reason)
};
return mockedAbi;
}
async function deployMockContract(signer, abi) {
const mockContractInstance = await deploy(signer);
async function deployMockContract(signer, abi, options) {
const mockContractInstance = await deploy(signer, options);
const mock = createMock(abi, mockContractInstance);

@@ -48,0 +161,0 @@ const mockedContract = new ethers_1.Contract(mockContractInstance.address, abi, signer);

@@ -1,8 +0,13 @@

import { Contract, Signer, utils } from 'ethers';
import { BaseContract, Contract, Signer, utils } from 'ethers';
import type { JsonFragment } from '@ethersproject/abi';
declare type ABI = string | Array<utils.Fragment | JsonFragment | string>;
export declare type Stub = ReturnType<typeof stub>;
export interface MockContract extends Contract {
interface StubInterface {
returns(...args: any): StubInterface;
reverts(): StubInterface;
revertsWithReason(reason: string): StubInterface;
withArgs(...args: any[]): StubInterface;
}
export interface MockContract<T extends BaseContract = BaseContract> extends Contract {
mock: {
[key: string]: Stub;
[key in ((keyof T['functions'] | 'receive'))]: StubInterface;
};

@@ -12,10 +17,8 @@ call(contract: Contract, functionName: string, ...params: any[]): Promise<any>;

}
declare function stub(mockContract: Contract, encoder: utils.AbiCoder, func: utils.FunctionFragment, params?: any[]): {
returns: (...args: any) => Promise<void>;
reverts: () => Promise<any>;
revertsWithReason: (reason: string) => Promise<any>;
withArgs: (...args: any[]) => any;
declare type DeployOptions = {
address: string;
override?: boolean;
};
export declare function deployMockContract(signer: Signer, abi: ABI): Promise<MockContract>;
export declare function deployMockContract<T extends BaseContract = BaseContract>(signer: Signer, abi: ABI, options?: DeployOptions): Promise<MockContract<T>>;
export {};
//# sourceMappingURL=index.d.ts.map
import { Contract, ContractFactory, utils } from 'ethers';
import DoppelgangerContract from './Doppelganger.json';
async function deploy(signer) {
class Stub {
constructor(mockContract, encoder, func) {
this.mockContract = mockContract;
this.encoder = encoder;
this.func = func;
this.stubCalls = [];
this.revertSet = false;
this.argsSet = false;
this.callData = mockContract.interface.getSighash(func);
}
err(reason) {
this.stubCalls = [];
this.revertSet = false;
this.argsSet = false;
throw new Error(reason);
}
returns(...args) {
if (this.revertSet)
this.err('Revert must be the last call');
if (!this.func.outputs)
this.err('Cannot mock return values from a void function');
const encoded = this.encoder.encode(this.func.outputs, args);
// if there no calls then this is the first call and we need to use mockReturns to override the queue
if (this.stubCalls.length === 0) {
this.stubCalls.push(async () => {
await this.mockContract.__waffle__mockReturns(this.callData, encoded);
});
}
else {
this.stubCalls.push(async () => {
await this.mockContract.__waffle__queueReturn(this.callData, encoded);
});
}
return this;
}
reverts() {
if (this.revertSet)
this.err('Revert must be the last call');
// if there no calls then this is the first call and we need to use mockReturns to override the queue
if (this.stubCalls.length === 0) {
this.stubCalls.push(async () => {
await this.mockContract.__waffle__mockReverts(this.callData, 'Mock revert');
});
}
else {
this.stubCalls.push(async () => {
await this.mockContract.__waffle__queueRevert(this.callData, 'Mock revert');
});
}
this.revertSet = true;
return this;
}
revertsWithReason(reason) {
if (this.revertSet)
this.err('Revert must be the last call');
// if there no calls then this is the first call and we need to use mockReturns to override the queue
if (this.stubCalls.length === 0) {
this.stubCalls.push(async () => {
await this.mockContract.__waffle__mockReverts(this.callData, reason);
});
}
else {
this.stubCalls.push(async () => {
await this.mockContract.__waffle__queueRevert(this.callData, reason);
});
}
this.revertSet = true;
return this;
}
withArgs(...params) {
if (this.argsSet)
this.err('withArgs can be called only once');
this.callData = this.mockContract.interface.encodeFunctionData(this.func, params);
this.argsSet = true;
return this;
}
async then(resolve, reject) {
for (let i = 0; i < this.stubCalls.length; i++) {
try {
await this.stubCalls[i]();
}
catch (e) {
this.stubCalls = [];
this.argsSet = false;
this.revertSet = false;
reject(e);
return;
}
}
this.stubCalls = [];
this.argsSet = false;
this.revertSet = false;
resolve();
}
}
async function deploy(signer, options) {
if (options) {
const { address, override } = options;
const provider = signer.provider;
if (!override && await provider.getCode(address) !== '0x') {
throw new Error(`${address} already contains a contract. ` +
'If you want to override it, set the override parameter.');
}
if (provider._hardhatNetwork) {
if (await provider.send('hardhat_setCode', [
address,
'0x' + DoppelgangerContract.evm.deployedBytecode.object
])) {
return new Contract(address, DoppelgangerContract.abi, signer);
}
else
throw new Error(`Couldn't deploy at ${address}`);
}
else {
if (await provider.send('evm_setAccountCode', [
address,
'0x' + DoppelgangerContract.evm.deployedBytecode.object
])) {
return new Contract(address, DoppelgangerContract.abi, signer);
}
else
throw new Error(`Couldn't deploy at ${address}`);
}
}
const factory = new ContractFactory(DoppelgangerContract.abi, DoppelgangerContract.bytecode, signer);
return factory.deploy();
}
function stub(mockContract, encoder, func, params) {
const callData = params
? mockContract.interface.encodeFunctionData(func, params)
: mockContract.interface.getSighash(func);
return {
returns: async (...args) => {
if (!func.outputs)
return;
const encoded = encoder.encode(func.outputs, args);
await mockContract.__waffle__mockReturns(callData, encoded);
},
reverts: async () => mockContract.__waffle__mockReverts(callData, 'Mock revert'),
revertsWithReason: async (reason) => mockContract.__waffle__mockReverts(callData, reason),
withArgs: (...args) => stub(mockContract, encoder, func, args)
};
}
function createMock(abi, mockContractInstance) {

@@ -27,3 +134,3 @@ const { functions } = new utils.Interface(abi);

const mockedAbi = Object.values(functions).reduce((acc, func) => {
const stubbed = stub(mockContractInstance, encoder, func);
const stubbed = new Stub(mockContractInstance, encoder, func);
return {

@@ -35,6 +142,12 @@ ...acc,

}, {});
mockedAbi.receive = {
returns: () => { throw new Error('Receive function return is not implemented.'); },
withArgs: () => { throw new Error('Receive function return is not implemented.'); },
reverts: () => mockContractInstance.__waffle__receiveReverts('Mock Revert'),
revertsWithReason: (reason) => mockContractInstance.__waffle__receiveReverts(reason)
};
return mockedAbi;
}
export async function deployMockContract(signer, abi) {
const mockContractInstance = await deploy(signer);
export async function deployMockContract(signer, abi, options) {
const mockContractInstance = await deploy(signer, options);
const mock = createMock(abi, mockContractInstance);

@@ -41,0 +154,0 @@ const mockedContract = new Contract(mockContractInstance.address, abi, signer);

{
"name": "@ethereum-waffle/mock-contract",
"description": "Mock smart contracts in a smart way.",
"version": "4.0.3-dev.f3d5029",
"version": "4.0.3-dev.f8ca718",
"author": "Marek Kirejczyk <account@ethworks.io> (http://ethworks.io)",

@@ -39,14 +39,15 @@ "repository": "git@github.com:EthWorks/Waffle.git",

"devDependencies": {
"@ethereum-waffle/chai": "4.0.9-dev.f8ca718",
"@ethereum-waffle/compiler": "4.0.3-dev.f8ca718",
"@ethereum-waffle/provider": "4.0.5-dev.f8ca718",
"@ethersproject/abi": "^5.6.1",
"@ethersproject/providers": "5.6.2",
"eslint": "^7.14.0",
"ethers": "5.6.2",
"@ethersproject/abi": "^5.6.1",
"@ethereum-waffle/chai": "4.0.8-dev.f3d5029",
"@ethereum-waffle/compiler": "4.0.3-dev.f3d5029",
"mocha": "^8.2.1",
"rimraf": "^3.0.2",
"solc": "0.8.15",
"@ethereum-waffle/provider": "4.0.5-dev.f3d5029",
"ts-node": "^9.0.0",
"typechain": "^8.0.0",
"mocha": "^8.2.1",
"rimraf": "^3.0.2",
"typescript": "^4.6.2",
"eslint": "^7.14.0",
"ts-node": "^9.0.0"
"typescript": "^4.6.2"
},

@@ -57,12 +58,11 @@ "peerDependencies": {

"scripts": {
"test": "export NODE_ENV=test && yarn test:build && mocha",
"test": "ts-node ./test/helpers/buildTestContracts.ts && export NODE_ENV=test && mocha",
"lint": "eslint '{src,test}/**/*.ts'",
"lint:fix": "eslint --fix '{src,test}/**/*.ts'",
"build": "rimraf ./dist && yarn build:sol && yarn build:esm && yarn build:cjs",
"build": "rimraf ./dist && yarn build:sol && yarn build:esm && yarn build:cjs && ts-node ./test/helpers/buildTestContracts.ts",
"build:sol": "ts-node compile.ts",
"build:esm": "tsc -p tsconfig.build.json --outDir dist/esm --module ES6",
"build:cjs": "tsc -p tsconfig.build.json --outDir dist/cjs",
"test:build": "ts-node ./test/helpers/buildTestContracts.ts",
"clean": "rimraf ./dist ./test/example/build"
}
}

@@ -1,13 +0,19 @@

import {Contract, ContractFactory, Signer, utils} from 'ethers';
import {BaseContract, Contract, ContractFactory, Signer, utils} from 'ethers';
import type {JsonFragment} from '@ethersproject/abi';
import DoppelgangerContract from './Doppelganger.json';
import type {JsonRpcProvider} from '@ethersproject/providers';
type ABI = string | Array<utils.Fragment | JsonFragment | string>
export type Stub = ReturnType<typeof stub>;
interface StubInterface {
returns(...args: any): StubInterface;
reverts(): StubInterface;
revertsWithReason(reason: string): StubInterface;
withArgs(...args: any[]): StubInterface;
}
export interface MockContract extends Contract {
export interface MockContract<T extends BaseContract = BaseContract> extends Contract {
mock: {
[key: string]: Stub;
[key in ((keyof T['functions'] | 'receive'))]: StubInterface;
};

@@ -18,25 +24,137 @@ call (contract: Contract, functionName: string, ...params: any[]): Promise<any>;

async function deploy(signer: Signer) {
const factory = new ContractFactory(DoppelgangerContract.abi, DoppelgangerContract.bytecode, signer);
return factory.deploy();
class Stub implements StubInterface {
callData: string;
stubCalls: Array<() => Promise<any>> = [];
revertSet = false;
argsSet = false;
constructor(
private mockContract: Contract,
private encoder: utils.AbiCoder,
private func: utils.FunctionFragment
) {
this.callData = mockContract.interface.getSighash(func);
}
private err(reason: string): never {
this.stubCalls = [];
this.revertSet = false;
this.argsSet = false;
throw new Error(reason);
}
returns(...args: any) {
if (this.revertSet) this.err('Revert must be the last call');
if (!this.func.outputs) this.err('Cannot mock return values from a void function');
const encoded = this.encoder.encode(this.func.outputs, args);
// if there no calls then this is the first call and we need to use mockReturns to override the queue
if (this.stubCalls.length === 0) {
this.stubCalls.push(async () => {
await this.mockContract.__waffle__mockReturns(this.callData, encoded);
});
} else {
this.stubCalls.push(async () => {
await this.mockContract.__waffle__queueReturn(this.callData, encoded);
});
}
return this;
}
reverts() {
if (this.revertSet) this.err('Revert must be the last call');
// if there no calls then this is the first call and we need to use mockReturns to override the queue
if (this.stubCalls.length === 0) {
this.stubCalls.push(async () => {
await this.mockContract.__waffle__mockReverts(this.callData, 'Mock revert');
});
} else {
this.stubCalls.push(async () => {
await this.mockContract.__waffle__queueRevert(this.callData, 'Mock revert');
});
}
this.revertSet = true;
return this;
}
revertsWithReason(reason: string) {
if (this.revertSet) this.err('Revert must be the last call');
// if there no calls then this is the first call and we need to use mockReturns to override the queue
if (this.stubCalls.length === 0) {
this.stubCalls.push(async () => {
await this.mockContract.__waffle__mockReverts(this.callData, reason);
});
} else {
this.stubCalls.push(async () => {
await this.mockContract.__waffle__queueRevert(this.callData, reason);
});
}
this.revertSet = true;
return this;
}
withArgs(...params: any[]) {
if (this.argsSet) this.err('withArgs can be called only once');
this.callData = this.mockContract.interface.encodeFunctionData(this.func, params);
this.argsSet = true;
return this;
}
async then(resolve: () => void, reject: (e: any) => void) {
for (let i = 0; i < this.stubCalls.length; i++) {
try {
await this.stubCalls[i]();
} catch (e) {
this.stubCalls = [];
this.argsSet = false;
this.revertSet = false;
reject(e);
return;
}
}
this.stubCalls = [];
this.argsSet = false;
this.revertSet = false;
resolve();
}
}
function stub(mockContract: Contract, encoder: utils.AbiCoder, func: utils.FunctionFragment, params?: any[]) {
const callData = params
? mockContract.interface.encodeFunctionData(func, params)
: mockContract.interface.getSighash(func);
type DeployOptions = {
address: string;
override?: boolean;
}
return {
returns: async (...args: any) => {
if (!func.outputs) return;
const encoded = encoder.encode(func.outputs, args);
await mockContract.__waffle__mockReturns(callData, encoded);
},
reverts: async () => mockContract.__waffle__mockReverts(callData, 'Mock revert'),
revertsWithReason: async (reason: string) => mockContract.__waffle__mockReverts(callData, reason),
withArgs: (...args: any[]) => stub(mockContract, encoder, func, args)
};
async function deploy(signer: Signer, options?: DeployOptions) {
if (options) {
const {address, override} = options;
const provider = signer.provider as JsonRpcProvider;
if (!override && await provider.getCode(address) !== '0x') {
throw new Error(
`${address} already contains a contract. ` +
'If you want to override it, set the override parameter.');
}
if ((provider as any)._hardhatNetwork) {
if (await provider.send('hardhat_setCode', [
address,
'0x' + DoppelgangerContract.evm.deployedBytecode.object
])) {
return new Contract(address, DoppelgangerContract.abi, signer);
} else throw new Error(`Couldn't deploy at ${address}`);
} else {
if (await provider.send('evm_setAccountCode', [
address,
'0x' + DoppelgangerContract.evm.deployedBytecode.object
])) {
return new Contract(address, DoppelgangerContract.abi, signer);
} else throw new Error(`Couldn't deploy at ${address}`);
}
}
const factory = new ContractFactory(DoppelgangerContract.abi, DoppelgangerContract.bytecode, signer);
return factory.deploy();
}
function createMock(abi: ABI, mockContractInstance: Contract) {
function createMock<T extends BaseContract>(abi: ABI, mockContractInstance: Contract): MockContract<T>['mock'] {
const {functions} = new utils.Interface(abi);

@@ -46,3 +164,3 @@ const encoder = new utils.AbiCoder();

const mockedAbi = Object.values(functions).reduce((acc, func) => {
const stubbed = stub(mockContractInstance, encoder, func);
const stubbed = new Stub(mockContractInstance as MockContract, encoder, func);
return {

@@ -53,12 +171,23 @@ ...acc,

};
}, {} as MockContract['mock']);
}, {} as MockContract<T>['mock']);
(mockedAbi as any).receive = {
returns: () => { throw new Error('Receive function return is not implemented.'); },
withArgs: () => { throw new Error('Receive function return is not implemented.'); },
reverts: () => mockContractInstance.__waffle__receiveReverts('Mock Revert'),
revertsWithReason: (reason: string) => mockContractInstance.__waffle__receiveReverts(reason)
};
return mockedAbi;
}
export async function deployMockContract(signer: Signer, abi: ABI): Promise<MockContract> {
const mockContractInstance = await deploy(signer);
export async function deployMockContract<T extends BaseContract = BaseContract>(
signer: Signer,
abi: ABI,
options?: DeployOptions
): Promise<MockContract<T>> {
const mockContractInstance = await deploy(signer, options);
const mock = createMock(abi, mockContractInstance);
const mockedContract = new Contract(mockContractInstance.address, abi, signer) as MockContract;
const mock = createMock<T>(abi, mockContractInstance);
const mockedContract = new Contract(mockContractInstance.address, abi, signer) as MockContract<T>;
mockedContract.mock = mock;

@@ -65,0 +194,0 @@

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc