From 201ba012e52f49e9c6814e0ed513aa66ca3ff90d Mon Sep 17 00:00:00 2001 From: 0xGorilla <84932007+0xGorilla@users.noreply.github.com> Date: Fri, 21 Oct 2022 15:32:31 +0200 Subject: [PATCH] chore(release): 2.3.1 (#165) * feat: added support for call value (#142) Added functionality: - `expect(myFake.myFunction).to.have.been.calledWithValue(1234);` - `expect(myFake.myFunction.getCall(0).value).to.eq(1);` * feat: arrays support for setVariable (#144) * feat: update ethereumjs vm and hardhat (#155) * fix: bug with usage of padNumHexSlotValue (#161) Co-authored-by: 0xOneTony --- CHANGELOG.md | 17 +++++++++++ README.md | 28 ++++++++----------- package.json | 2 +- src/utils/storage.ts | 18 ++++++------ test/contracts/mock/StorageGetter.sol | 6 ++-- test/unit/mock/editable-storage-logic.spec.ts | 15 +++++----- test/unit/mock/readable-storage-logic.spec.ts | 10 +++---- 7 files changed, 54 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42c44c8..fb41ec7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,23 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [2.3.1](https://github.com/defi-wonderland/smock/compare/v2.1.0...v2.3.1) (2022-09-28) + + +### Features + +* added support for call value ([#142](https://github.com/defi-wonderland/smock/issues/142)) ([3c2b80b](https://github.com/defi-wonderland/smock/commit/3c2b80b72fe146634b999df5b9bb9ef5ffc27508)) +* arrays support for setVariable ([#144](https://github.com/defi-wonderland/smock/issues/144)) ([91a7aad](https://github.com/defi-wonderland/smock/commit/91a7aadf0cfa14ba52edb98c15fa0d38562fef39)) +* return hardhat errors on factory failures ([#125](https://github.com/defi-wonderland/smock/issues/125)) ([3b626a3](https://github.com/defi-wonderland/smock/commit/3b626a3891c07ba224d2f12386bae95522843e2b)) +* update ethereumjs vm and hardhat ([#155](https://github.com/defi-wonderland/smock/issues/155)) ([b71cfd1](https://github.com/defi-wonderland/smock/commit/b71cfd118a2a9579517769c0c31abede7d83ca71)) + + +### Bug Fixes + +* bug with usage of padNumHexSlotValue ([#161](https://github.com/defi-wonderland/smock/issues/161)) ([9cffea6](https://github.com/defi-wonderland/smock/commit/9cffea640c4bd5ddc09a638505f6bb0a0cebdbad)) +* delegated calls support ([#132](https://github.com/defi-wonderland/smock/issues/132)) ([812c335](https://github.com/defi-wonderland/smock/commit/812c3354d77603d8a6db172f5297c8e49625a98b)) +* duplicated type ([#138](https://github.com/defi-wonderland/smock/issues/138)) ([823b0ea](https://github.com/defi-wonderland/smock/commit/823b0ea7ed422636e4e763576b6975a422728522)) + ## [2.3.0](https://github.com/defi-wonderland/smock/compare/v2.1.0...v2.3.0) (2022-09-08) diff --git a/README.md b/README.md index 06bbd7c..8612f73 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![image](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.com/invite/22RQcJjau9) +```{=html}
@@ -9,7 +10,7 @@


- +``` **Smock** is the **S**olidity **mock**ing library. It\'s a plugin for [hardhat](https://hardhat.org) that can be used to create mock Solidity contracts entirely in JavaScript (or TypeScript!). With Smock, it\'s @@ -26,8 +27,7 @@ testing frameworks like [Truffle](https://www.trufflesuite.com/). If you wanna chat about the future of Solidity Mocking, join our [Discord](https://discord.com/invite/22RQcJjau9)! -Features -======== +# Features - Get rid of your folder of \"mock\" contracts and **just use JavaScript**. @@ -39,31 +39,27 @@ Features - Make **assertions** about calls, call arguments, and call counts. - We\'ve got extensive documentation and a complete test suite. -Documentation -============= +# Documentation Detailed documentation can be found [here](https://smock.readthedocs.io). -Quick Start -=========== +# Quick Start -Installation ------------- +## Installation You can install Smock via npm or yarn: -``` {.sourceCode .console} +``` console npm install @defi-wonderland/smock ``` -Basic Usage ------------ +## Basic Usage Smock is dead simple to use. Here\'s a basic example of how you might use it to streamline your tests. -``` {.sourceCode .typescript} +``` typescript ... import { FakeContract, smock } from '@defi-wonderland/smock'; @@ -86,16 +82,14 @@ describe('MyContract', () => { }); ``` -License -======= +# License Smock is released under the MIT license. Feel free to use, modify, and/or redistribute this software as you see fit. See the [LICENSE](https://github.com/defi-wonderland/smock/blob/main/LICENSE) file for more information. -Contributors -============ +# Contributors Maintained with love by [Optimism PBC](https://optimism.io) and [DeFi Wonderland](https://defi.sucks). Made possible by viewers like you. diff --git a/package.json b/package.json index 0794ec0..ec0ee58 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@defi-wonderland/smock", - "version": "2.3.0", + "version": "2.3.1", "description": "The Solidity mocking library", "keywords": [ "ethereum", diff --git a/src/utils/storage.ts b/src/utils/storage.ts index 19d9116..eb9a6ca 100644 --- a/src/utils/storage.ts +++ b/src/utils/storage.ts @@ -252,7 +252,7 @@ function encodeVariable( return [ { key: slotKey, - val: padNumHexSlotValue(variable, storageObj.offset), + val: padBytesHexSlotValue(variable, storageObj.offset), }, ]; } else if (variableType.label === 'bool') { @@ -381,19 +381,19 @@ function encodeVariable( // Mapping keys are encoded depending on the key type. let key: string; if (variableType.key.startsWith('t_uint')) { - key = BigNumber.from(varName).toHexString(); + key = padNumHexSlotValue(BigNumber.from(varName).toHexString(), 0); } else if (variableType.key.startsWith('t_bytes')) { - key = '0x' + remove0x(varName).padEnd(64, '0'); + key = padBytesHexSlotValue('0x' + remove0x(varName).padEnd(64, '0'), 0); } else { // Seems to work for everything else. - key = varName; + key = padBytesHexSlotValue(varName, 0); } // Figure out the base slot key that the mapped values need to work off of. // If baseSlotKey is defined here, then we're inside of a nested mapping and we should work // off of that previous baseSlotKey. Otherwise the base slot will be the slot of this map. const prevBaseSlotKey = baseSlotKey || padNumHexSlotValue(storageObj.slot, 0); - const nextBaseSlotKey = ethers.utils.keccak256(padNumHexSlotValue(key, 0) + remove0x(prevBaseSlotKey)); + const nextBaseSlotKey = ethers.utils.keccak256(key + remove0x(prevBaseSlotKey)); // Encode the value. We need to use a dummy storageObj here because the function expects it. // Of course, we're not mapping to a specific variable. We map to a variable /type/. So we @@ -656,12 +656,12 @@ async function getMappingTypeStorageSlots( // In this part we calculate the `h(k)` where k is the mapping key the user provided and h is a function that is applied to the key depending on its type let mappKey: string; if (storageObjectType.key.startsWith('t_uint')) { - mappKey = BigNumber.from(mappingKey[0]).toHexString(); + mappKey = padNumHexSlotValue(BigNumber.from(mappingKey[0]).toHexString(), 0); } else if (storageObjectType.key.startsWith('t_bytes')) { - mappKey = '0x' + remove0x(mappingKey[0] as string).padEnd(64, '0'); + mappKey = padBytesHexSlotValue('0x' + remove0x(mappingKey[0] as string).padEnd(64, '0'), 0); } else { // Seems to work for everything else. - mappKey = mappingKey[0] as string; + mappKey = padBytesHexSlotValue(mappingKey[0] as string, 0); } // Figure out the base slot key that the mapped values need to work off of. @@ -669,7 +669,7 @@ async function getMappingTypeStorageSlots( // off of that previous baseSlotKey. Otherwise the base slot will be the key we already have. const prevBaseSlotKey = baseSlotKey || key; // Since we have `h(k) = mappKey` and `p = key` now we can calculate the slot key - let nextSlotKey = ethers.utils.keccak256(padNumHexSlotValue(mappKey, 0) + remove0x(prevBaseSlotKey)); + let nextSlotKey = ethers.utils.keccak256(mappKey + remove0x(prevBaseSlotKey)); let slotKeysTypes: StorageSlotKeyTypePair[] = []; diff --git a/test/contracts/mock/StorageGetter.sol b/test/contracts/mock/StorageGetter.sol index c458dc3..f7456f7 100644 --- a/test/contracts/mock/StorageGetter.sol +++ b/test/contracts/mock/StorageGetter.sol @@ -29,7 +29,7 @@ contract StorageGetter { PackedStruct internal _packedStruct; mapping(uint256 => uint256) _uint256Map; mapping(uint256 => mapping(uint256 => uint256)) _uint256NestedMap; - mapping(bytes5 => bool) _bytes5ToBoolMap; + mapping(bytes32 => bool) _bytes32ToBoolMap; mapping(address => bool) _addressToBoolMap; mapping(address => address) _addressToAddressMap; uint256[] internal _uint256Array; @@ -119,8 +119,8 @@ contract StorageGetter { return _uint256NestedMap[_keyA][_keyB]; } - function getBytes5ToBoolMapValue(bytes5 _key) public view returns (bool _out) { - return _bytes5ToBoolMap[_key]; + function getBytes32ToBoolMapValue(bytes32 _key) public view returns (bool _out) { + return _bytes32ToBoolMap[_key]; } function getAddressToBoolMapValue(address _key) public view returns (bool _out) { diff --git a/test/unit/mock/editable-storage-logic.spec.ts b/test/unit/mock/editable-storage-logic.spec.ts index 00f13f0..5e5e398 100644 --- a/test/unit/mock/editable-storage-logic.spec.ts +++ b/test/unit/mock/editable-storage-logic.spec.ts @@ -4,6 +4,7 @@ import { ADDRESS_EXAMPLE, BYTES32_EXAMPLE, BYTES_EXAMPLE } from '@test-utils'; import { StorageGetter, StorageGetter__factory } from '@typechained'; import { expect } from 'chai'; import { BigNumber, utils } from 'ethers'; +import { defaultAbiCoder, keccak256 } from 'ethers/lib/utils'; describe('Mock: Editable storage logic', () => { let storageGetterFactory: MockContractFactory; @@ -125,12 +126,12 @@ describe('Mock: Editable storage logic', () => { expect(await mock.getConstructorUint256()).to.equal(1234); }); - it('should be able to set values in a bytes5 => bool mapping', async () => { - const mapKey = '0x0000005678'; + it('should be able to set values in a bytes32 => bool mapping', async () => { + const mapKey = keccak256(defaultAbiCoder.encode(['bytes32'], [BYTES32_EXAMPLE])); const mapValue = true; - await mock.setVariable('_bytes5ToBoolMap', { [mapKey]: mapValue }); + await mock.setVariable('_bytes32ToBoolMap', { [mapKey]: mapValue }); - expect(await mock.getBytes5ToBoolMapValue(mapKey)).to.equal(mapValue); + expect(await mock.getBytes32ToBoolMapValue(mapKey)).to.equal(mapValue); }); it('should be able to set values in a address => bool mapping', async () => { @@ -260,7 +261,7 @@ describe('Mock: Editable storage logic', () => { const mapKeyB = 5678; const mapValue = 4321; const mapValueB = 8765; - const mapKeybytes5ToBool = '0x0000005678'; + const mapKeybytes32ToBool = BYTES32_EXAMPLE; const mapValueAddress = '0x063bE0Af9711a170BE4b07028b320C90705fec7C'; await mock.setVariables({ _address: ADDRESS_EXAMPLE, @@ -276,7 +277,7 @@ describe('Mock: Editable storage logic', () => { [mapKeyB]: mapValueB, }, }, - _bytes5ToBoolMap: { [mapKeybytes5ToBool]: true }, + _bytes32ToBoolMap: { [mapKeybytes32ToBool]: true }, _addressToBoolMap: { [ADDRESS_EXAMPLE]: false }, _addressToAddressMap: { [ADDRESS_EXAMPLE]: mapValueAddress }, }); @@ -290,7 +291,7 @@ describe('Mock: Editable storage logic', () => { expect(convertStructToPojo(await mock.getSimpleStruct())).to.deep.equal(struct); expect(await mock.getUint256MapValue(mapKey)).to.equal(mapValue); expect(await mock.getNestedUint256MapValue(mapKey, mapKeyB)).to.equal(mapValueB); - expect(await mock.getBytes5ToBoolMapValue(mapKeybytes5ToBool)).to.equal(true); + expect(await mock.getBytes32ToBoolMapValue(mapKeybytes32ToBool)).to.equal(true); expect(await mock.getAddressToBoolMapValue(ADDRESS_EXAMPLE)).to.equal(false); expect(await mock.getAddressToAddressMapValue(ADDRESS_EXAMPLE)).to.equal(mapValueAddress); }); diff --git a/test/unit/mock/readable-storage-logic.spec.ts b/test/unit/mock/readable-storage-logic.spec.ts index df1ae45..535d827 100644 --- a/test/unit/mock/readable-storage-logic.spec.ts +++ b/test/unit/mock/readable-storage-logic.spec.ts @@ -121,13 +121,13 @@ describe('Mock: Readable storage logic', () => { expect(getValue).to.equal(await mock.getUint256MapValue(mapKey)); }); - it('should be able to get values in a bytes5 => bool mapping', async () => { - const mapKey = '0x0000005678'; + it('should be able to get values in a bytes32 => bool mapping', async () => { + const mapKey = BYTES32_EXAMPLE; const mapValue = true; - await mock.setVariable('_bytes5ToBoolMap', { [mapKey]: mapValue }); + await mock.setVariable('_bytes32ToBoolMap', { [mapKey]: mapValue }); - const getValue = await mock.getVariable('_bytes5ToBoolMap', [mapKey]); - expect(getValue).to.equal(await mock.getBytes5ToBoolMapValue(mapKey)); + const getValue = await mock.getVariable('_bytes32ToBoolMap', [mapKey]); + expect(getValue).to.equal(await mock.getBytes32ToBoolMapValue(mapKey)); }); it('should be able to get a nested uint256 mapping value', async () => {