@eth-optimism/smock

中文文档
1.1.10发布于 2021/07/28MITTypeScriptCommonJS近 30 天下载 2003

smock 是一种可以生成模拟固态合同(用于测试)的通用软件包. smock 钩入一 ethereumjs-vm 实例,以便模拟合同函数可以完全用 JavaScript 写入. smock 目前只支持[Hardhat](http://har)

此软件包已被标记为弃用

Smock v1 is being deprecated. Please migrate to Smock v2: https://github.com/defi-wonderland/smock

中文使用文档
文档目录23 节
  1. 安装
  2. 关于使用的说明 smoddit
  3. API 密码
  4. 职能
  5. 类型
  6. 实例(嘲笑)
  7. 通过 ethers.Contract
  8. 请求数
  9. 调用数据
  10. 返回(w/o数据)
  11. 正在返回 Struct
  12. 返回多阵列
  13. 返回函数
  14. 返回函数(w/参数)
  15. 还原(w/o数据)
  16. 还原(w/数据)
  17. B. 从毁损的合同发送交易
  18. 实例( smoddit)
  19. 创建可修改的合同
  20. 正在修改 a uint256
  21. 修改字符串
  22. 修改绘图
  23. 修改嵌入式映射

@eth-乐观主义/smock

smock 是一种可以生成模拟固态合同(用于测试)的通用软件包. smock 钩入一 ethereumjs-vm 实例,以便模拟合同函数可以完全用 JavaScript 写入. smock 目前仅支持 哈达特,但将扩展用于支持其他测试框架.

在VM一级钩入的一些好处:

  • 不需要因为嘲笑而部署任何特别合同!
  • 所有通话都是同步的.
  • 在返回值(返回一个函数)中执行任意的javascript逻辑.
  • 这听起来很酷.

smock 还载有 smoddit,可以修改合同的内部存储。 我们发现这在单个合同内发生许多相互作用(通常是为了节省气体)的情况下相当有用.

安装

你可以轻松安装 smock 通过 npm数字 :

npm install @eth-optimism/smock

或者通过 yarn数字 :

yarn add @eth-optimism/smock

关于使用的说明 smoddit

smoddit 需要访问智能合同的内部存储布局。 团结编译器通过 storageLayout 旗帜,您需要启用 您的硬帽子配置.

这里有个例子 hardhat.config.ts 显示如何导入插件 :

// hardhat.config.ts
import { HardhatUserConfig } from 'hardhat/config'

const config: HardhatUserConfig = {
  ...,
  solidity: {
    version: '0.7.0',
    settings: {
      outputSelection: {
        "*": {
            "*": ["storageLayout"],
        },
      },
    }
  },
}

export default config

API 密码

职能

smockit

导入
import { smockit } from '@eth-optimism/smock'
签署
const smockit = async (
  spec: ContractInterface | Contract | ContractFactory,
  opts: {
    provider?: any,
    address?: string,
  },
): Promise<MockContract>

smoddit

导入
import { smoddit } from '@eth-optimism/smock'
签署
const smoddit = async (
  name: string,
  signer?: any
): Promise<ModifiableContractFactory>

类型

smockit

MockContract
interface MockContract extends ethers.Contract {
  smocked: {
    [functionName: string]: MockContractFunction
  }

  // A wallet you can use to send transactions *from* a smocked contract
  wallet: ethers.Signer
}
MockContractFunction
interface MockContractFunction {
  calls: string[]
  will: {
    return: {
      (): void
      with: (returnValue?: MockReturnValue) => void
    }
    revert: {
      (): void
      with: (revertValue?: string) => void
    }
    resolve: 'return' | 'revert'
  }
}
MockReturnValue
export type MockReturnValue =
  | string
  | Object
  | any[]
  | ((...params: any[]) => MockReturnValue)

smoddit

ModifiableContractFactory
interface ModifiableContractFactory extends ethers.ContractFactory {
  deploy: (...args: any[]) => Promise<ModifiableContract>
}
ModifiableContract
interface ModifiableContract extends ethers.Contract {
  smodify: {
    put: (storage: any) => Promise<void>
  }
}

实例(嘲笑)

通过 ethers.Contract

import { ethers } from 'hardhat'
import { smockit } from '@eth-optimism/smock'

const MyContractFactory = await ethers.getContractFactory('MyContract')
const MyContract = await MyContractFactory.deploy(...)

// Smockit!
const MyMockContract = await smockit(MyContract)

MyMockContract.smocked.myFunction.will.return.with('Some return value!')

console.log(await MyMockContract.myFunction()) // 'Some return value!'

请求数

import { ethers } from 'hardhat'
import { smockit } from '@eth-optimism/smock'

const MyContractFactory = await ethers.getContractFactory('MyContract')
const MyContract = await MyContractFactory.deploy(...)

const MyOtherContractFactory = await ethers.getContractFactory('MyOtherContract')
const MyOtherContract = await MyOtherContract.deploy(...)

// Smockit!
const MyMockContract = await smockit(MyContract)

MyMockContract.smocked.myFunction.will.return.with('Some return value!')

// Assuming that MyOtherContract.myOtherFunction calls MyContract.myFunction.
await MyOtherContract.myOtherFunction()

console.log(MyMockContract.smocked.myFunction.calls.length) // 1

调用数据

import { ethers } from 'hardhat'
import { smockit } from '@eth-optimism/smock'

const MyContractFactory = await ethers.getContractFactory('MyContract')
const MyContract = await MyContractFactory.deploy(...)

const MyOtherContractFactory = await ethers.getContractFactory('MyOtherContract')
const MyOtherContract = await MyOtherContract.deploy(...)

// Smockit!
const MyMockContract = await smockit(MyContract)

MyMockContract.smocked.myFunction.will.return.with('Some return value!')

// Assuming that MyOtherContract.myOtherFunction calls MyContract.myFunction with 'Hello World!'.
await MyOtherContract.myOtherFunction()

console.log(MyMockContract.smocked.myFunction.calls[0]) // 'Hello World!'

返回(w/o数据)

import { ethers } from 'hardhat'
import { smockit } from '@eth-optimism/smock'

const MyContractFactory = await ethers.getContractFactory('MyContract')
const MyContract = await MyContractFactory.deploy(...)

// Smockit!
const MyMockContract = await smockit(MyContract)

MyMockContract.smocked.myFunction.will.return()

console.log(await MyMockContract.myFunction()) // []

正在返回 Struct

import { ethers } from 'hardhat'
import { smockit } from '@eth-optimism/smock'

const MyContractFactory = await ethers.getContractFactory('MyContract')
const MyContract = await MyContractFactory.deploy(...)

// Smockit!
const MyMockContract = await smockit(MyContract)

MyMockContract.smocked.myFunction.will.return.with({
    valueA: 'Some value',
    valueB: 1234,
    valueC: true
})

console.log(await MyMockContract.myFunction()) // ['Some value', 1234, true]

返回多阵列

import { ethers } from 'hardhat'
import { smockit } from '@eth-optimism/smock'

const MyContractFactory = await ethers.getContractFactory('MyContract')
const MyContract = await MyContractFactory.deploy(...)

// Smockit!
const MyMockContract = await smockit(MyContract)

MyMockContract.smocked.myFunction.will.return.with([
  [1234, 5678],
  [4321, 8765]
])

console.log(await MyMockContract.myFunction()) // [ [1234, 5678], [4321, 8765] ]

返回函数

import { ethers } from 'hardhat'
import { smockit } from '@eth-optimism/smock'

const MyContractFactory = await ethers.getContractFactory('MyContract')
const MyContract = await MyContractFactory.deploy(...)

// Smockit!
const MyMockContract = await smockit(MyContract)

MyMockContract.smocked.myFunction.will.return.with(() => {
  return 'Some return value!'
})

console.log(await MyMockContract.myFunction()) // 'Some return value!'

返回函数(w/参数)

import { ethers } from 'hardhat'
import { smockit } from '@eth-optimism/smock'

const MyContractFactory = await ethers.getContractFactory('MyContract')
const MyContract = await MyContractFactory.deploy(...)

// Smockit!
const MyMockContract = await smockit(MyContract)

MyMockContract.smocked.myFunction.will.return.with((myFunctionArgument: string) => {
  return myFunctionArgument
})

console.log(await MyMockContract.myFunction('Some return value!')) // 'Some return value!'

还原(w/o数据)

import { ethers } from 'hardhat'
import { smockit } from '@eth-optimism/smock'

const MyContractFactory = await ethers.getContractFactory('MyContract')
const MyContract = await MyContractFactory.deploy(...)

// Smockit!
const MyMockContract = await smockit(MyContract)

MyMockContract.smocked.myFunction.will.revert()

console.log(await MyMockContract.myFunction()) // Revert!

还原(w/数据)

import { ethers } from 'hardhat'
import { smockit } from '@eth-optimism/smock'

const MyContractFactory = await ethers.getContractFactory('MyContract')
const MyContract = await MyContractFactory.deploy(...)

// Smockit!
const MyMockContract = await smockit(MyContract)

MyMockContract.smocked.myFunction.will.revert.with('0x1234')

console.log(await MyMockContract.myFunction('Some return value!')) // Revert!

B. 从毁损的合同发送交易

import { ethers } from 'hardhat'
import { smockit } from '@eth-optimism/smock'

const myContractFactory = await ethers.getContractFactory('MyContract')
const myContract = await myContractFactory.deploy(...)

// Smockit!
const mock = await smockit('AnotherContract')

await myContract.connect(mock.wallet).doSomeFunction() // msg.sender == mock.address

实例( smoddit)

创建可修改的合同

import { ethers } from 'hardhat'
import { smoddit } from '@eth-optimism/smock'

// Smoddit!
const MyModifiableContractFactory = await smoddit('MyContract')
const MyModifiableContract = await MyModifiableContractFactory.deploy(...)

正在修改 a uint256

import { ethers } from 'hardhat'
import { smoddit } from '@eth-optimism/smock'

// Smoddit!
const MyModifiableContractFactory = await smoddit('MyContract')
const MyModifiableContract = await MyModifiableContractFactory.deploy(...)

await MyModifiableContract.smodify.put({
  myInternalUint256: 1234
})

console.log(await MyMockContract.getMyInternalUint256()) // 1234

修改字符串

import { ethers } from 'hardhat'
import { smoddit } from '@eth-optimism/smock'

// Smoddit!
const MyModifiableContractFactory = await smoddit('MyContract')
const MyModifiableContract = await MyModifiableContractFactory.deploy(...)

await MyModifiableContract.smodify.put({
  myInternalStruct: {
    valueA: 1234,
    valueB: true
  }
})

console.log(await MyMockContract.getMyInternalStruct()) // { valueA: 1234, valueB: true }

修改绘图

import { ethers } from 'hardhat'
import { smoddit } from '@eth-optimism/smock'

// Smoddit!
const MyModifiableContractFactory = await smoddit('MyContract')
const MyModifiableContract = await MyModifiableContractFactory.deploy(...)

await MyModifiableContract.smodify.put({
  myInternalMapping: {
    1234: 5678
  }
})

console.log(await MyMockContract.getMyInternalMappingValue(1234)) // 5678

修改嵌入式映射

import { ethers } from 'hardhat'
import { smoddit } from '@eth-optimism/smock'

// Smoddit!
const MyModifiableContractFactory = await smoddit('MyContract')
const MyModifiableContract = await MyModifiableContractFactory.deploy(...)

await MyModifiableContract.smodify.put({
  myInternalNestedMapping: {
    1234: {
      4321: 5678
    }
  }
})

console.log(await MyMockContract.getMyInternalNestedMappingValue(1234, 4321)) // 5678

版本与发布记录

@eth-optimism/smock 共发布 38 个版本,首次发布于 2020/09/30;过去 12 个月发布了 0 个版本。

版本发布日期距今
1.1.10latest2021/07/285 年前
1.1.92021/07/135 年前
1.1.82021/07/135 年前
1.1.72021/07/075 年前
1.1.62021/06/235 年前
0.0.0-2021521222130canary2021/06/225 年前

关于 @eth-optimism/smock 的常见问题

@eth-optimism/smock 是什么?

smock 是一种可以生成模拟固态合同(用于测试)的通用软件包. smock 钩入一 ethereumjs-vm 实例,以便模拟合同函数可以完全用 JavaScript 写入. smock 目前只支持[Hardhat](http://har)注意:该包已被作者标记为弃用——Smock v1 is being deprecated. Please migrate to Smock v2: https://github.com/defi-wonderland/smock

如何安装 @eth-optimism/smock?

在项目目录运行 npm install @eth-optimism/smock,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:ethers(^5)、hardhat(^2)、@ethersproject/abi(^5)、@nomiclabs/ethereumjs-vm(^4)、@nomiclabs/hardhat-ethers(^2)、@ethersproject/abstract-signer(^5)、@ethersproject/abstract-provider(^5)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@eth-optimism/smock 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@eth-optimism/smock 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@eth-optimism/smock 可以商用吗?

@eth-optimism/smock 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@eth-optimism/smock 的下载量有多少?

根据 npm 官方下载统计,@eth-optimism/smock 在 2026/10/14 – 2026/11/12 这 30 天内被下载 2,003 次,日均约 67 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@eth-optimism/smock 还在维护吗?

最新版本 1.1.10 发布于 2021/07/28(5 年前);至今共发布 38 个版本,其中过去 12 个月发布了 0 个;首次发布于 2020/09/30。作者已将其标记为弃用,新项目建议寻找替代方案。