Commit a656f06b authored by smartcontracts's avatar smartcontracts Committed by GitHub

feat[smock]: add a wallet that be used to send transactions from a smock (#896)

* feat[smock]: add support for sending txs from mocks

* fix: remove unused imports

* chore: add changeset

* fix: readme errors

* Update packages/smock/README.md

* Update packages/smock/README.md
Co-authored-by: default avatarMaurelian <maurelian@protonmail.ch>
Co-authored-by: default avatarMaurelian <maurelian@protonmail.ch>
parent 2d352de8
---
'@eth-optimism/smock': patch
---
Adds a wallet object to smock contracts that can be used to send transactions
......@@ -51,40 +51,6 @@ const config: HardhatUserConfig = {
export default config
```
## Table of Contents
- [API](#api)
* [Functions](#functions)
+ [`smockit`](#-smockit-)
- [Import](#import)
- [Signature](#signature)
+ [`smoddit`](#-smoddit-)
- [Import](#import-1)
- [Signature](#signature-1)
* [Types](#types)
+ [`smockit`](#-smockit--1)
- [`MockContract`](#-mockcontract-)
- [`MockContractFunction`](#-mockcontractfunction-)
- [`MockReturnValue`](#-mockreturnvalue-)
+ [`smoddit`](#-smoddit--1)
- [`ModifiableContractFactory`](#-modifiablecontractfactory-)
- [`ModifiableContract`](#-modifiablecontract-)
- [Examples (smockit)](#examples--smockit-)
* [Via `ethers.Contract`](#via--etherscontract-)
* [Asserting Call Count](#asserting-call-count)
* [Asserting Call Data](#asserting-call-data)
* [Returning (w/o Data)](#returning--w-o-data-)
* [Returning a Struct](#returning-a-struct)
* [Returning a Function](#returning-a-function)
* [Returning a Function (w/ Arguments)](#returning-a-function--w--arguments-)
* [Reverting (w/o Data)](#reverting--w-o-data-)
* [Reverting (w/ Data)](#reverting--w--data-)
- [Examples (smoddit)](#examples--smoddit-)
* [Creating a Modifiable Contract](#creating-a-modifiable-contract)
* [Modifying a `uint256`](#modifying-a--uint256-)
* [Modifying a Struct](#modifying-a-struct)
* [Modifying a Mapping](#modifying-a-mapping)
* [Modifying a Nested Mapping](#modifying-a-nested-mapping)
## API
### Functions
#### `smockit`
......@@ -122,10 +88,13 @@ const smoddit = async (
#### `smockit`
##### `MockContract`
```typescript
interface MockContract extends Contract {
interface MockContract extends ethers.Contract {
smocked: {
[functionName: string]: MockContractFunction
}
// A wallet you can use to send transactions *from* a smocked contract
wallet: ethers.Signer
}
```
......@@ -159,14 +128,14 @@ export type MockReturnValue =
#### `smoddit`
##### `ModifiableContractFactory`
```typescript
interface ModifiableContractFactory extends ContractFactory {
interface ModifiableContractFactory extends ethers.ContractFactory {
deploy: (...args: any[]) => Promise<ModifiableContract>
}
```
##### `ModifiableContract`
```typescript
interface ModifiableContract extends Contract {
interface ModifiableContract extends ethers.Contract {
smodify: {
put: (storage: any) => Promise<void>
}
......@@ -339,6 +308,20 @@ MyMockContract.smocked.myFunction.will.revert.with('0x1234')
console.log(await MyMockContract.myFunction('Some return value!')) // Revert!
```
### Sending transactions from a smocked contract
```typescript
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
```
## Examples (smoddit)
### Creating a Modifiable Contract
......
......@@ -17,6 +17,9 @@
"clean": "rimraf ./artifacts ./cache ./dist ./tsconfig.build.tsbuildinfo"
},
"peerDependencies": {
"@ethersproject/abi": "^5",
"@ethersproject/abstract-provider": "^5",
"@ethersproject/abstract-signer": "^5",
"@nomiclabs/ethereumjs-vm": "^4",
"@nomiclabs/hardhat-ethers": "^2",
"ethers": "^5",
......@@ -24,11 +27,12 @@
},
"dependencies": {
"@eth-optimism/core-utils": "^0.4.1",
"@ethersproject/abi": "^5.0.13",
"@ethersproject/abstract-provider": "^5.0.10",
"bn.js": "^5.2.0"
},
"devDependencies": {
"@ethersproject/abi": "^5.1.2",
"@ethersproject/abstract-provider": "^5.1.0",
"@ethersproject/abstract-signer": "^5.1.0",
"@nomiclabs/ethereumjs-vm": "^4.2.2",
"@nomiclabs/hardhat-ethers": "^2.0.2",
"@nomiclabs/hardhat-waffle": "^2.0.1",
......
......@@ -162,6 +162,17 @@ export const smockit = async (
opts.provider || (hre as any).ethers.provider // TODO: Probably check that this exists.
) as MockContract
// We attach a wallet to the contract so that users can send transactions *from* a smock.
await hre.network.provider.request({
method: 'hardhat_impersonateAccount',
params: [contract.address]
})
// Now we actually get the signer and attach it to the mock.
contract.wallet = await (hre as any).ethers.getSigner(
contract.address
)
// Start by smocking the fallback.
contract.smocked = {
fallback: smockifyFunction(
......
/* Imports: External */
import { Artifact } from 'hardhat/types'
import { Contract, ContractFactory, ethers } from 'ethers'
import { Signer } from '@ethersproject/abstract-signer'
import { Provider } from '@ethersproject/abstract-provider'
import { JsonFragment, Fragment } from '@ethersproject/abi'
......@@ -47,6 +48,8 @@ export type MockContract = Contract & {
smocked: {
[name: string]: MockContractFunction
}
wallet: Signer
}
export interface SmockedVM {
......
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
contract TestHelpers_SenderAssertions {
function getSender()
public
view
returns (
address
)
{
return msg.sender;
}
}
/* Imports: External */
import hre from 'hardhat'
import { expect } from 'chai'
import { Contract } from 'ethers'
/* Imports: Internal */
import { smockit } from '../../src'
describe('[smock]: sending transactions from smock contracts', () => {
const ethers = (hre as any).ethers
let TestHelpers_SenderAssertions: Contract
before(async () => {
TestHelpers_SenderAssertions = await(
await ethers.getContractFactory(
'TestHelpers_SenderAssertions'
)
).deploy()
})
it('should attach a signer for a mock with a random address', async () => {
const mock = await smockit('TestHelpers_BasicReturnContract')
expect(
await TestHelpers_SenderAssertions.connect(mock.wallet).getSender()
).to.equal(mock.address)
})
it('should attach a signer for a mock with a fixed address', async () => {
const mock = await smockit('TestHelpers_BasicReturnContract', {
address: '0x1234123412341234123412341234123412341234'
})
expect(
await TestHelpers_SenderAssertions.connect(mock.wallet).getSender()
).to.equal(mock.address)
})
})
......@@ -992,7 +992,7 @@
"@ethersproject/properties" "^5.0.3"
"@ethersproject/strings" "^5.0.4"
"@ethersproject/abi@5.1.0", "@ethersproject/abi@^5.0.0", "@ethersproject/abi@^5.0.1", "@ethersproject/abi@^5.0.13", "@ethersproject/abi@^5.0.2", "@ethersproject/abi@^5.1.0":
"@ethersproject/abi@5.1.0", "@ethersproject/abi@^5.0.0", "@ethersproject/abi@^5.0.1", "@ethersproject/abi@^5.0.2", "@ethersproject/abi@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.1.0.tgz#d582c9f6a8e8192778b5f2c991ce19d7b336b0c5"
integrity sha512-N/W9Sbn1/C6Kh2kuHRjf/hX6euMK4+9zdJRBB8sDWmihVntjUAfxbusGZKzDQD8i3szAHhTz8K7XADV5iFNfJw==
......@@ -1007,7 +1007,7 @@
"@ethersproject/properties" "^5.1.0"
"@ethersproject/strings" "^5.1.0"
"@ethersproject/abi@^5.0.0-beta.146":
"@ethersproject/abi@5.1.2", "@ethersproject/abi@^5.0.0-beta.146", "@ethersproject/abi@^5.1.2":
version "5.1.2"
resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.1.2.tgz#a8e75cd0455e6dc9e4861c3d1c22bbe436c1d775"
integrity sha512-uMhoQVPX0UtfzTpekYQSEUcJGDgsJ25ifz+SV6PDETWaUFhcR8RNgb1QPTASP13inW8r6iy0/Xdq9D5hK2pNvA==
......@@ -1022,7 +1022,7 @@
"@ethersproject/properties" "^5.1.0"
"@ethersproject/strings" "^5.1.0"
"@ethersproject/abstract-provider@5.1.0", "@ethersproject/abstract-provider@^5.0.0", "@ethersproject/abstract-provider@^5.0.10", "@ethersproject/abstract-provider@^5.0.5", "@ethersproject/abstract-provider@^5.0.8", "@ethersproject/abstract-provider@^5.0.9", "@ethersproject/abstract-provider@^5.1.0":
"@ethersproject/abstract-provider@5.1.0", "@ethersproject/abstract-provider@^5.0.0", "@ethersproject/abstract-provider@^5.0.5", "@ethersproject/abstract-provider@^5.0.8", "@ethersproject/abstract-provider@^5.0.9", "@ethersproject/abstract-provider@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.1.0.tgz#1f24c56cda5524ef4ed3cfc562a01d6b6f8eeb0b"
integrity sha512-8dJUnT8VNvPwWhYIau4dwp7qe1g+KgdRm4XTWvjkI9gAT2zZa90WF5ApdZ3vl1r6NDmnn6vUVvyphClRZRteTQ==
......@@ -1314,6 +1314,21 @@
"@ethersproject/rlp" "^5.1.0"
"@ethersproject/signing-key" "^5.1.0"
"@ethersproject/transactions@5.1.1", "@ethersproject/transactions@^5.0.21":
version "5.1.1"
resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.1.1.tgz#5a6bbb25fb062c3cc75eb0db12faefcdd3870813"
integrity sha512-Nwgbp09ttIVN0OoUBatCXaHxR7grWPHbozJN8v7AXDLrl6nnOIBEMDh+yJTnosSQlFhcyjfTGGN+Mx6R8HdvMw==
dependencies:
"@ethersproject/address" "^5.1.0"
"@ethersproject/bignumber" "^5.1.0"
"@ethersproject/bytes" "^5.1.0"
"@ethersproject/constants" "^5.1.0"
"@ethersproject/keccak256" "^5.1.0"
"@ethersproject/logger" "^5.1.0"
"@ethersproject/properties" "^5.1.0"
"@ethersproject/rlp" "^5.1.0"
"@ethersproject/signing-key" "^5.1.0"
"@ethersproject/units@5.1.0", "@ethersproject/units@^5.0.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.1.0.tgz#b6ab3430ebc22adc3cb4839516496f167bee3ad5"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment