From c9bf002675f5d1588f184267aca29aea24345730 Mon Sep 17 00:00:00 2001 From: Ashwin Phatak Date: Fri, 18 Jun 2021 18:09:50 +0530 Subject: [PATCH] Test decoder using hardhat RPC, geth-statediff RPC and ipld-eth-server GQL endpoints for fetching storage slots (#77) * Implement test for getStorageValue with geth server. * Wait for transaction to complete in tests. * Implement tests with ipld-eth-client using graphql endpoint. Co-authored-by: nikugogoi <95nikass@gmail.com> --- packages/solidity-mapper/.env.example | 3 + packages/solidity-mapper/.gitignore | 3 + packages/solidity-mapper/README.md | 23 +- packages/solidity-mapper/hardhat.config.ts | 9 + packages/solidity-mapper/package.json | 7 +- packages/solidity-mapper/src/logs.test.ts | 1 + packages/solidity-mapper/src/storage.test.ts | 611 +++++++++++-------- packages/solidity-mapper/test/utils.ts | 11 + yarn.lock | 5 + 9 files changed, 420 insertions(+), 253 deletions(-) create mode 100644 packages/solidity-mapper/.env.example diff --git a/packages/solidity-mapper/.env.example b/packages/solidity-mapper/.env.example new file mode 100644 index 00000000..2c4bf229 --- /dev/null +++ b/packages/solidity-mapper/.env.example @@ -0,0 +1,3 @@ +ETH_RPC_URL=http://127.0.0.1:8545 + +GQL_ENDPOINT=http://127.0.0.1:8083/graphql diff --git a/packages/solidity-mapper/.gitignore b/packages/solidity-mapper/.gitignore index 0759c65f..c7b0dfe8 100644 --- a/packages/solidity-mapper/.gitignore +++ b/packages/solidity-mapper/.gitignore @@ -6,3 +6,6 @@ artifacts #yarn yarn-error.log + +#Environment variables +.env diff --git a/packages/solidity-mapper/README.md b/packages/solidity-mapper/README.md index a0060708..d17f980b 100644 --- a/packages/solidity-mapper/README.md +++ b/packages/solidity-mapper/README.md @@ -10,10 +10,23 @@ Get value of state variable from storage for a solidity contract. ## Instructions -Run the tests using the following command -```bash -$ yarn test -``` +* Create environment variable file + ```bash + $ cp .env.example .env + ``` + +* Run the tests using the following command + ```bash + $ yarn test + + # For testing on private network using RPC getStorageAt. + # Set ETH_RPC_URL in .env + $ yarn test:geth-rpc + + # For testing on private network using ipld-eth-client getStorageAt. + # Set GQL_ENDPOINT in .env + $ yarn test:ipld-gql + ``` ## Different Types @@ -26,7 +39,7 @@ $ yarn test * [x] Fixed-size byte arrays * [x] Enums * [ ] Function Types -* [x] Reference Types +* [ ] Reference Types * [x] Arrays * [x] Get all elements in array * [x] Get element in array by index diff --git a/packages/solidity-mapper/hardhat.config.ts b/packages/solidity-mapper/hardhat.config.ts index e8559256..2455b3ab 100644 --- a/packages/solidity-mapper/hardhat.config.ts +++ b/packages/solidity-mapper/hardhat.config.ts @@ -1,3 +1,4 @@ +import 'dotenv/config'; import { task, HardhatUserConfig } from 'hardhat/config'; import '@nomiclabs/hardhat-waffle'; @@ -35,6 +36,14 @@ const config: HardhatUserConfig = { paths: { sources: './test/contracts', tests: './src' + }, + networks: { + private: { + url: process.env.ETH_RPC_URL + } + }, + mocha: { + timeout: 50000 } }; diff --git a/packages/solidity-mapper/package.json b/packages/solidity-mapper/package.json index 0eafccee..66c35d0e 100644 --- a/packages/solidity-mapper/package.json +++ b/packages/solidity-mapper/package.json @@ -12,6 +12,7 @@ "@types/mocha": "^8.2.2", "@typescript-eslint/eslint-plugin": "^4.25.0", "@typescript-eslint/parser": "^4.25.0", + "@vulcanize/ipld-eth-client": "^0.1.0", "chai": "^4.3.4", "eslint": "^7.27.0", "eslint-config-semistandard": "^15.0.1", @@ -29,7 +30,11 @@ "scripts": { "build": "tsc", "test": "hardhat test", + "test:geth-rpc": "hardhat --network private test", + "test:ipld-gql": "IPLD_GQL=true hardhat --network private test", "lint": "eslint ." }, - "dependencies": {} + "dependencies": { + "dotenv": "^10.0.0" + } } diff --git a/packages/solidity-mapper/src/logs.test.ts b/packages/solidity-mapper/src/logs.test.ts index d84cb300..b270214e 100644 --- a/packages/solidity-mapper/src/logs.test.ts +++ b/packages/solidity-mapper/src/logs.test.ts @@ -1,4 +1,5 @@ import { expect } from 'chai'; +import '@nomiclabs/hardhat-ethers'; import { artifacts, ethers } from 'hardhat'; import { getEventNameTopics } from './logs'; diff --git a/packages/solidity-mapper/src/storage.test.ts b/packages/solidity-mapper/src/storage.test.ts index 326c071c..33bfc13f 100644 --- a/packages/solidity-mapper/src/storage.test.ts +++ b/packages/solidity-mapper/src/storage.test.ts @@ -1,11 +1,14 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Contract } from '@ethersproject/contracts'; import { expect } from 'chai'; -import { ethers } from 'hardhat'; import '@nomiclabs/hardhat-ethers'; +import { ethers } from 'hardhat'; +import { ContractTransaction } from 'ethers'; + +import { EthClient } from '@vulcanize/ipld-eth-client'; import { getStorageInfo, getStorageValue, StorageLayout } from './storage'; -import { getStorageLayout, getStorageAt } from '../test/utils'; +import { getStorageLayout, getStorageAt as rpcGetStorageAt, generateDummyAddresses } from '../test/utils'; const TEST_DATA = [ { @@ -81,68 +84,91 @@ describe('Get value from storage', () => { return hash; }; - it('get value for integer type variables packed together', async () => { - const Integers = await ethers.getContractFactory('TestIntegers'); - const integers = await Integers.deploy(); - await integers.deployed(); - const storageLayout = await getStorageLayout('TestIntegers'); + let getStorageAt = rpcGetStorageAt; - let expectedValue = 12; - await integers.setInt1(expectedValue); - let blockHash = await getBlockHash(); - let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, integers.address, 'int1'); - expect(value).to.equal(BigInt(expectedValue)); + // Check if running test against ipld graphql endpoint. + if (process.env.IPLD_GQL) { + // Set ipld-eth-client. + const ethClient = new EthClient({ + gqlEndpoint: process.env.GQL_ENDPOINT || '', + gqlSubscriptionEndpoint: process.env.GQL_ENDPOINT || '', + cache: undefined + }); - expectedValue = 34; - await integers.setInt2(expectedValue); - blockHash = await getBlockHash(); - ({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, integers.address, 'int2')); - expect(value).to.equal(BigInt(expectedValue)); + // Use ipld graphql endpoint to get storage value. + getStorageAt = ethClient.getStorageAt.bind(ethClient); + } + + describe('signed integer type', () => { + let integers: Contract, storageLayout: StorageLayout; + + before(async () => { + const Integers = await ethers.getContractFactory('TestIntegers'); + integers = await Integers.deploy(); + await integers.deployed(); + storageLayout = await getStorageLayout('TestIntegers'); + }); + + it('get value for integer type variables packed together', async () => { + let expectedValue = 12; + let transaction = await integers.setInt1(expectedValue); + await transaction.wait(); + let blockHash = await getBlockHash(); + let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, integers.address, 'int1'); + expect(value).to.equal(BigInt(expectedValue)); + + expectedValue = 34; + transaction = await integers.setInt2(expectedValue); + await transaction.wait(); + blockHash = await getBlockHash(); + ({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, integers.address, 'int2')); + expect(value).to.equal(BigInt(expectedValue)); + }); + + it('get value for integer type variables using single slot', async () => { + const expectedValue = 123; + const transaction = await integers.setInt3(expectedValue); + await transaction.wait(); + const blockHash = await getBlockHash(); + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, integers.address, 'int3'); + expect(value).to.equal(BigInt(expectedValue)); + }); }); - it('get value for integer type variables using single slot', async () => { - const Integers = await ethers.getContractFactory('TestIntegers'); - const integers = await Integers.deploy(); - await integers.deployed(); - const storageLayout = await getStorageLayout('TestIntegers'); + describe('unsigned integer type', () => { + let unsignedIntegers: Contract, storageLayout: StorageLayout; - const expectedValue = 123; - await integers.setInt3(expectedValue); - const blockHash = await getBlockHash(); - const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, integers.address, 'int3'); - expect(value).to.equal(BigInt(expectedValue)); - }); + before(async () => { + const UnsignedIntegers = await ethers.getContractFactory('TestUnsignedIntegers'); + unsignedIntegers = await UnsignedIntegers.deploy(); + await unsignedIntegers.deployed(); + storageLayout = await getStorageLayout('TestUnsignedIntegers'); + }); - it('get value for unsigned integer type variables packed together', async () => { - const UnsignedIntegers = await ethers.getContractFactory('TestUnsignedIntegers'); - const unsignedIntegers = await UnsignedIntegers.deploy(); - await unsignedIntegers.deployed(); - const storageLayout = await getStorageLayout('TestUnsignedIntegers'); + it('get value for unsigned integer type variables packed together', async () => { + let expectedValue = 12; + let transaction = await unsignedIntegers.setUint1(expectedValue); + await transaction.wait(); + let blockHash = await getBlockHash(); + let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, unsignedIntegers.address, 'uint1'); + expect(value).to.equal(BigInt(expectedValue)); - let expectedValue = 12; - await unsignedIntegers.setUint1(expectedValue); - let blockHash = await getBlockHash(); - let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, unsignedIntegers.address, 'uint1'); - expect(value).to.equal(BigInt(expectedValue)); + expectedValue = 34; + transaction = await unsignedIntegers.setUint2(expectedValue); + await transaction.wait(); + blockHash = await getBlockHash(); + ({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, unsignedIntegers.address, 'uint2')); + expect(value).to.equal(BigInt(expectedValue)); + }); - expectedValue = 34; - await unsignedIntegers.setUint2(expectedValue); - blockHash = await getBlockHash(); - ({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, unsignedIntegers.address, 'uint2')); - expect(value).to.equal(BigInt(expectedValue)); - }); - - it('get value for unsigned integer type variables using single slot', async () => { - const UnsignedIntegers = await ethers.getContractFactory('TestUnsignedIntegers'); - const unsignedIntegers = await UnsignedIntegers.deploy(); - await unsignedIntegers.deployed(); - const storageLayout = await getStorageLayout('TestUnsignedIntegers'); - - const expectedValue = 123; - await unsignedIntegers.setUint3(expectedValue); - const blockHash = await getBlockHash(); - const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, unsignedIntegers.address, 'uint3'); - expect(value).to.equal(BigInt(expectedValue)); + it('get value for unsigned integer type variables using single slot', async () => { + const expectedValue = 123; + const transaction = await unsignedIntegers.setUint3(expectedValue); + await transaction.wait(); + const blockHash = await getBlockHash(); + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, unsignedIntegers.address, 'uint3'); + expect(value).to.equal(BigInt(expectedValue)); + }); }); it('get value for boolean type', async () => { @@ -152,13 +178,15 @@ describe('Get value from storage', () => { const storageLayout = await getStorageLayout('TestBooleans'); let expectedValue = true; - await booleans.setBool1(expectedValue); + let transaction = await booleans.setBool1(expectedValue); + await transaction.wait(); let blockHash = await getBlockHash(); let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, booleans.address, 'bool1'); expect(value).to.equal(expectedValue); expectedValue = false; - await booleans.setBool2(expectedValue); + transaction = await booleans.setBool2(expectedValue); + await transaction.wait(); blockHash = await getBlockHash(); ({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, booleans.address, 'bool2')); expect(value).to.equal(expectedValue); @@ -171,7 +199,8 @@ describe('Get value from storage', () => { const storageLayout = await getStorageLayout('TestAddress'); const [signer] = await ethers.getSigners(); - await address.setAddress1(signer.address); + const transaction = await address.setAddress1(signer.address); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, address.address, 'address1'); expect(value).to.be.a('string'); @@ -190,7 +219,8 @@ describe('Get value from storage', () => { const [testContractTypes, testAddress] = await Promise.all(contractPromises); const storageLayout = await getStorageLayout('TestContractTypes'); - await testContractTypes.setAddressContract1(testAddress.address); + const transaction = await testContractTypes.setAddressContract1(testAddress.address); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testContractTypes.address, 'addressContract1'); expect(value).to.equal(testAddress.address.toLowerCase()); @@ -203,13 +233,15 @@ describe('Get value from storage', () => { const storageLayout = await getStorageLayout('TestBytes'); let expectedValue = ethers.utils.hexlify(ethers.utils.randomBytes(10)); - await testBytes.setBytesTen(expectedValue); + let transaction = await testBytes.setBytesTen(expectedValue); + await transaction.wait(); let blockHash = await getBlockHash(); let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testBytes.address, 'bytesTen'); expect(value).to.equal(expectedValue); expectedValue = ethers.utils.hexlify(ethers.utils.randomBytes(20)); - await testBytes.setBytesTwenty(expectedValue); + transaction = await testBytes.setBytesTwenty(expectedValue); + await transaction.wait(); blockHash = await getBlockHash(); ({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testBytes.address, 'bytesTwenty')); expect(value).to.equal(expectedValue); @@ -222,7 +254,8 @@ describe('Get value from storage', () => { const storageLayout = await getStorageLayout('TestBytes'); const expectedValue = ethers.utils.hexlify(ethers.utils.randomBytes(30)); - await testBytes.setBytesThirty(expectedValue); + const transaction = await testBytes.setBytesThirty(expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testBytes.address, 'bytesThirty'); expect(value).to.equal(expectedValue); @@ -235,7 +268,8 @@ describe('Get value from storage', () => { const storageLayout = await getStorageLayout('TestEnums'); const expectedValue = 1; - await testEnums.setChoicesEnum1(expectedValue); + const transaction = await testEnums.setChoicesEnum1(expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testEnums.address, 'choicesEnum1'); expect(value).to.equal(BigInt(expectedValue)); @@ -254,7 +288,8 @@ describe('Get value from storage', () => { // Test for string of size less than 32 bytes which use only one slot. it('get value for string length less than 32 bytes', async () => { const expectedValue = 'Hello world.'; - await strings.setString1(expectedValue); + const transaction = await strings.setString1(expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, strings.address, 'string1'); expect(value).to.equal(expectedValue); @@ -263,7 +298,8 @@ describe('Get value from storage', () => { // Test for string of size 32 bytes or more which use multiple slots. it('get value for string length more than 32 bytes', async () => { const expectedValue = 'This sentence is more than 32 bytes long.'; - await strings.setString2(expectedValue); + const transaction = await strings.setString2(expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, strings.address, 'string2'); expect(value).to.equal(expectedValue); @@ -282,7 +318,8 @@ describe('Get value from storage', () => { it('get value for byte array length less than 32 bytes', async () => { const expectedValue = ethers.utils.hexlify(ethers.utils.randomBytes(24)); - await testBytes.setBytesArray(expectedValue); + const transaction = await testBytes.setBytesArray(expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testBytes.address, 'bytesArray'); expect(value).to.equal(expectedValue); @@ -290,7 +327,8 @@ describe('Get value from storage', () => { it('get value for byte array length more than 32 bytes', async () => { const expectedValue = ethers.utils.hexlify(ethers.utils.randomBytes(100)); - await testBytes.setBytesArray(expectedValue); + const transaction = await testBytes.setBytesArray(expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testBytes.address, 'bytesArray'); expect(value).to.equal(expectedValue); @@ -310,31 +348,30 @@ describe('Get value from storage', () => { return ethers.utils.hexlify(ethers.utils.randomBytes(bytesLength)); }); - let addressArray: string[]; + const addressArray = generateDummyAddresses(4); before(async () => { const TestFixedArrays = await ethers.getContractFactory('TestFixedArrays'); testFixedArrays = await TestFixedArrays.deploy(); await testFixedArrays.deployed(); storageLayout = await getStorageLayout('TestFixedArrays'); - - const signers = await ethers.getSigners(); - addressArray = signers.slice(0, 4) - .map(signer => signer.address.toLowerCase()); }); // Get all elements of array. // Test for array variables which are 32 bytes or less and packed into a single slot. it('get value for fixed size arrays using single slot', async () => { - await testFixedArrays.setBoolArray(boolArray); - let blockHash = await getBlockHash(); + const transaction1 = await testFixedArrays.setBoolArray(boolArray); + const transaction2 = await testFixedArrays.setUint16Array(uint16Array); + await Promise.all([transaction1.wait(), transaction2.wait()]); + const blockHash = await getBlockHash(); + + // Test for variable boolArray. let { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'boolArray'); expect(value).to.eql(boolArray); let proofData = JSON.parse(proof.data); expect(proofData.length).to.equal(boolArray.length); - await testFixedArrays.setUint16Array(uint16Array); - blockHash = await getBlockHash(); + // Test for variable uint16Array. ({ value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'uint16Array')); expect(value).to.eql(uint16Array.map(el => BigInt(el))); proofData = JSON.parse(proof.data); @@ -343,15 +380,18 @@ describe('Get value from storage', () => { // Test for array variables which are more than 32 bytes and use multiple slots. it('get value for fixed size arrays using multiple slots', async () => { - await testFixedArrays.setInt128Array(int128Array); - let blockHash = await getBlockHash(); + const transaction1 = await testFixedArrays.setInt128Array(int128Array); + const transaction2 = await testFixedArrays.setUintArray(uint16Array); + await Promise.all([transaction1.wait(), transaction2.wait()]); + const blockHash = await getBlockHash(); + + // Test for variable int128Array. let { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'int128Array'); expect(value).to.eql(int128Array.map(el => BigInt(el))); let proofData = JSON.parse(proof.data); expect(proofData.length).to.equal(int128Array.length); - await testFixedArrays.setUintArray(uint16Array); - blockHash = await getBlockHash(); + // Test for variable uintArray. ({ value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'uintArray')); expect(value).to.eql(uint16Array.map(el => BigInt(el))); proofData = JSON.parse(proof.data); @@ -359,7 +399,8 @@ describe('Get value from storage', () => { }); it('get value for fixed size arrays of address type', async () => { - await testFixedArrays.setAddressArray(addressArray); + const transaction = await testFixedArrays.setAddressArray(addressArray); + await transaction.wait(); const blockHash = await getBlockHash(); const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'addressArray'); expect(value).to.eql(addressArray); @@ -370,7 +411,8 @@ describe('Get value from storage', () => { it('get value for fixed size arrays of fixed size bytes type', async () => { const expectedValue = Array.from({ length: 5 }, () => ethers.utils.hexlify(ethers.utils.randomBytes(10))); - await testFixedArrays.setFixedBytesArray(expectedValue); + const transaction = await testFixedArrays.setFixedBytesArray(expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'fixedBytesArray'); expect(value).to.eql(expectedValue); @@ -379,7 +421,8 @@ describe('Get value from storage', () => { }); it('get value for fixed size arrays of enum type', async () => { - await testFixedArrays.setEnumArray(enumArray); + const transaction = await testFixedArrays.setEnumArray(enumArray); + await transaction.wait(); const blockHash = await getBlockHash(); const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'enumArray'); expect(value).to.eql(enumArray.map(el => BigInt(el))); @@ -388,7 +431,8 @@ describe('Get value from storage', () => { }); it('get value for fixed size arrays of dynamic byte array type', async () => { - await testFixedArrays.setBytesArray(bytesArray); + const transaction = await testFixedArrays.setBytesArray(bytesArray); + await transaction.wait(); const blockHash = await getBlockHash(); const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'bytesArray'); expect(value).to.eql(bytesArray); @@ -397,7 +441,8 @@ describe('Get value from storage', () => { }); it('get value for fixed size arrays of string type', async () => { - await testFixedArrays.setStringArray(stringArray); + const transaction = await testFixedArrays.setStringArray(stringArray); + await transaction.wait(); const blockHash = await getBlockHash(); const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'stringArray'); expect(value).to.eql(stringArray); @@ -416,9 +461,14 @@ describe('Get value from storage', () => { }; expectedValue[i] = structElement; - await testFixedArrays.setStructArray(structElement, i); } + const transactionPromises = expectedValue.map(async (structElement, index) => { + const transaction = await testFixedArrays.setStructArray(structElement, index); + return transaction.wait(); + }); + await Promise.all(transactionPromises); + const blockHash = await getBlockHash(); const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'structArray'); expect(value).to.eql(expectedValue); @@ -429,7 +479,8 @@ describe('Get value from storage', () => { // Get element of array by index. it('get value of signed integer type array by index', async () => { const arrayIndex = 2; - await testFixedArrays.setInt128Array(int128Array); + const transaction = await testFixedArrays.setInt128Array(int128Array); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'int128Array', arrayIndex); expect(value).to.equal(BigInt(int128Array[arrayIndex])); @@ -437,7 +488,8 @@ describe('Get value from storage', () => { it('get value of unsigned integer type array by index', async () => { const arrayIndex = 3; - await testFixedArrays.setUint16Array(uint16Array); + const transaction = await testFixedArrays.setUint16Array(uint16Array); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'uint16Array', arrayIndex); expect(value).to.equal(BigInt(uint16Array[arrayIndex])); @@ -445,7 +497,8 @@ describe('Get value from storage', () => { it('get value of boolean type array by index', async () => { const arrayIndex = 0; - await testFixedArrays.setBoolArray(boolArray); + const transaction = await testFixedArrays.setBoolArray(boolArray); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'boolArray', arrayIndex); expect(value).to.equal(boolArray[arrayIndex]); @@ -453,7 +506,8 @@ describe('Get value from storage', () => { it('get value of address type array by index', async () => { const arrayIndex = 1; - await testFixedArrays.setAddressArray(addressArray); + const transaction = await testFixedArrays.setAddressArray(addressArray); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'addressArray', arrayIndex); expect(value).to.equal(addressArray[arrayIndex]); @@ -474,7 +528,8 @@ describe('Get value from storage', () => { }; const arrayIndex = 2; - await testFixedArrays.setStructArray(expectedValue, arrayIndex); + const transaction = await testFixedArrays.setStructArray(expectedValue, arrayIndex); + await transaction.wait(); const blockHash = await getBlockHash(); let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'structArray', arrayIndex); expect(value).to.eql(expectedValue); @@ -501,18 +556,18 @@ describe('Get value from storage', () => { it('get value of map type array by index', async () => { // Set map array values. - const signers = await ethers.getSigners(); + const addresses = generateDummyAddresses(3); - const mapArrayPromises = signers.slice(0, 3) - .map(async (signer, index) => { - const map = new Map(); - map.set(signer.address, BigInt(index * 10)); - await testFixedArrays.setMapArray(signer.address, map.get(signer.address), index); - return map; - }); + const mapArrayPromises = addresses.map(async (address, index) => { + const map = new Map(); + map.set(address, BigInt(index * 10)); + const transaction = await testFixedArrays.setMapArray(address, map.get(address), index); + await transaction.wait(); + return map; + }); const arrayIndex = 2; - const mapKey = signers[2].address; + const mapKey = addresses[2]; const mapArray = await Promise.all(mapArrayPromises); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'mapArray', arrayIndex, mapKey); @@ -533,7 +588,8 @@ describe('Get value from storage', () => { // Get all elements of array. it('get value for dynamic sized array of boolean type', async () => { const boolArray = [true, false, false, true, false]; - await testDynamicArrays.setBoolArray(boolArray); + const transaction = await testDynamicArrays.setBoolArray(boolArray); + await transaction.wait(); const blockHash = await getBlockHash(); let { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testDynamicArrays.address, 'boolArray'); expect(value).to.eql(boolArray); @@ -548,7 +604,8 @@ describe('Get value from storage', () => { it('get value for dynamic sized array of unsigned integer type', async () => { const uint128Array = [100, 200, 300, 400, 500]; - await testDynamicArrays.setUintArray(uint128Array); + const transaction = await testDynamicArrays.setUintArray(uint128Array); + await transaction.wait(); const blockHash = await getBlockHash(); let { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testDynamicArrays.address, 'uintArray'); expect(value).to.eql(uint128Array.map(el => BigInt(el))); @@ -563,7 +620,8 @@ describe('Get value from storage', () => { it('get value for dynamic sized array of signed integer type', async () => { const intArray = [10, 20, 30, 40, 50]; - await testDynamicArrays.setIntArray(intArray); + const transaction = await testDynamicArrays.setIntArray(intArray); + await transaction.wait(); const blockHash = await getBlockHash(); let { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testDynamicArrays.address, 'intArray'); expect(value).to.eql(intArray.map(el => BigInt(el))); @@ -577,9 +635,9 @@ describe('Get value from storage', () => { }); it('get value for dynamic sized array of address type', async () => { - const signers = await ethers.getSigners(); - const addressArray = signers.map(signer => signer.address.toLowerCase()); - await testDynamicArrays.setAddressArray(addressArray); + const addressArray = generateDummyAddresses(9); + const transaction = await testDynamicArrays.setAddressArray(addressArray); + await transaction.wait(); const blockHash = await getBlockHash(); let { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testDynamicArrays.address, 'addressArray'); expect(value).to.eql(addressArray); @@ -594,7 +652,8 @@ describe('Get value from storage', () => { it('get value for dynamic sized array of fixed size byte array', async () => { const fixedBytesArray = Array.from({ length: 4 }, () => ethers.utils.hexlify(ethers.utils.randomBytes(10))); - await testDynamicArrays.setFixedBytesArray(fixedBytesArray); + const transaction = await testDynamicArrays.setFixedBytesArray(fixedBytesArray); + await transaction.wait(); const blockHash = await getBlockHash(); let { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testDynamicArrays.address, 'fixedBytesArray'); expect(value).to.eql(fixedBytesArray); @@ -609,7 +668,8 @@ describe('Get value from storage', () => { it('get value for dynamic sized array of enum type', async () => { const enumArray = [0, 1, 2, 3]; - await testDynamicArrays.setEnumArray(enumArray); + const transaction = await testDynamicArrays.setEnumArray(enumArray); + await transaction.wait(); const blockHash = await getBlockHash(); let { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testDynamicArrays.address, 'enumArray'); expect(value).to.eql(enumArray.map(el => BigInt(el))); @@ -628,7 +688,8 @@ describe('Get value from storage', () => { return ethers.utils.hexlify(ethers.utils.randomBytes(bytesLength)); }); - await testDynamicArrays.setBytesArray(bytesArray); + const transaction = await testDynamicArrays.setBytesArray(bytesArray); + await transaction.wait(); const blockHash = await getBlockHash(); let { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testDynamicArrays.address, 'bytesArray'); expect(value).to.eql(bytesArray); @@ -644,7 +705,8 @@ describe('Get value from storage', () => { it('get value for dynamic sized array of string type', async () => { const stringArray = ['abc', 'defgh', 'ij', 'k']; - await testDynamicArrays.setStringArray(stringArray); + const transaction = await testDynamicArrays.setStringArray(stringArray); + await transaction.wait(); const blockHash = await getBlockHash(); let { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testDynamicArrays.address, 'stringArray'); expect(value).to.eql(stringArray); @@ -657,58 +719,71 @@ describe('Get value from storage', () => { expect(value).to.equal(stringArray[arrayIndex]); }); - it('get value for dynamic sized array of struct type', async () => { - const structArray = []; + describe('get value for dynamic sized array of struct type', async () => { + const structArray: Array<{[key: string]: any}> = []; + let blockHash: string; + const transactions: Array = []; - for (let i = 0; i < 5; i++) { - const structElement = { - int1: BigInt(i + 1), - uint1: BigInt(i + 2), - bool1: Boolean(i % 2) - }; + before(async () => { + for (let i = 0; i < 5; i++) { + const structElement = { + int1: BigInt(i + 1), + uint1: BigInt(i + 2), + bool1: Boolean(i % 2) + }; - structArray[i] = structElement; - await testDynamicArrays.addStructArrayElement(structElement); - } + structArray[i] = structElement; + transactions.push(await testDynamicArrays.addStructArrayElement(structElement)); + } - const blockHash = await getBlockHash(); - let { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testDynamicArrays.address, 'structArray'); - expect(value).to.eql(structArray); - const proofData = JSON.parse(proof.data); - expect(proofData.length).to.equal(structArray.length); + await Promise.all(transactions.map(transaction => transaction.wait())); + blockHash = await getBlockHash(); + }); - // Get value by index. - const arrayIndex = 3; - ({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testDynamicArrays.address, 'structArray', arrayIndex)); - expect(value).to.eql(structArray[arrayIndex]); + it('get whole array', async () => { + const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testDynamicArrays.address, 'structArray'); + expect(value).to.eql(structArray); + const proofData = JSON.parse(proof.data); + expect(proofData.length).to.equal(structArray.length); + }); - // Get struct member value. - const structMember = 'uint1'; - ({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testDynamicArrays.address, 'structArray', arrayIndex, structMember)); - expect(value).to.eql(structArray[arrayIndex][structMember]); + it('get array element by index', async () => { + const arrayIndex = 3; + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testDynamicArrays.address, 'structArray', arrayIndex); + expect(value).to.eql(structArray[arrayIndex]); + }); + + it('get struct member value from array element', async () => { + const arrayIndex = 2; + const structMember = 'uint1'; + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testDynamicArrays.address, 'structArray', arrayIndex, structMember); + expect(value).to.eql(structArray[arrayIndex][structMember]); + }); }); it('get value for dynamic sized array of mapping type', async () => { - const signers = await ethers.getSigners(); + const addresses = generateDummyAddresses(5); + const mapArray = []; + const transactions = []; - const mapArrayPromises = signers.map(async (signer, index) => { + for (const [index, address] of addresses.entries()) { const map = new Map(); - map.set(signer.address, BigInt(index * 10)); - await testDynamicArrays.addMapArrayElement(signer.address, map.get(signer.address)); - return map; - }); + map.set(address, BigInt(index * 10)); + mapArray.push(map); + transactions.push(await testDynamicArrays.addMapArrayElement(address, map.get(address))); + } - const mapArray = await Promise.all(mapArrayPromises); + await Promise.all(transactions.map(transaction => transaction.wait())); const blockHash = await getBlockHash(); const arrayIndex = 2; - const mapKey = signers[2].address; + const mapKey = addresses[2]; const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testDynamicArrays.address, 'mapArray', arrayIndex, mapKey); expect(value).to.equal(mapArray[arrayIndex].get(mapKey)); }); }); describe('nested arrays', () => { - let testNestedArrays: Contract, storageLayout: StorageLayout; + let testNestedArrays: Contract, storageLayout: StorageLayout, blockHash: string; const nestedStructArray: Array> = []; const nestedAddressArray: Array> = []; @@ -729,8 +804,10 @@ describe('Get value from storage', () => { testNestedArrays = await TestNestedArrays.deploy(); await testNestedArrays.deployed(); storageLayout = await getStorageLayout('TestNestedArrays'); + const transactions = []; - const signers = await ethers.getSigners(); + const addresses = generateDummyAddresses(7); + const transactionPromises = []; // Set value for nestedStructArray. for (let i = 0; i < 5; i++) { @@ -739,32 +816,36 @@ describe('Get value from storage', () => { for (let j = 0; j < 3; j++) { const value = { uint1: BigInt((i + j) * 100), - address1: signers[(i + j) % 5].address.toLowerCase() + address1: addresses[(i + j) % 5] }; nestedStructArray[i][j] = value; // Set value in contract. - await testNestedArrays.setNestedStructArray(i, j, value); + transactionPromises.push(testNestedArrays.setNestedStructArray(i, j, value)); } } + transactions.push(...await Promise.all(transactionPromises)); + // Set value for nestedAddressArray. for (let i = 0; i < 3; i++) { - nestedAddressArray[i] = signers.slice(i, i + 4).map(signer => signer.address.toLowerCase()); + nestedAddressArray[i] = addresses.slice(i, i + 4); } - await testNestedArrays.setNestedAddressArray(nestedAddressArray); + transactions.push(await testNestedArrays.setNestedAddressArray(nestedAddressArray)); // Set value for nested dynamic arrays - await testNestedArrays.setNestedFixedDynamicArray(nestedFixedDynamicArray); - await testNestedArrays.setNestedDynamicFixedArray(nestedDynamicArray); - await testNestedArrays.setNestedDynamicArray(nestedDynamicArray); + transactions.push(await testNestedArrays.setNestedFixedDynamicArray(nestedFixedDynamicArray)); + transactions.push(await testNestedArrays.setNestedDynamicFixedArray(nestedDynamicArray)); + transactions.push(await testNestedArrays.setNestedDynamicArray(nestedDynamicArray)); + + await Promise.all(transactions.map(transaction => transaction.wait())); + blockHash = await getBlockHash(); }); // Get all elements of array. it('get value for fixed size nested array of struct type', async () => { - const blockHash = await getBlockHash(); const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedArrays.address, 'nestedStructArray'); expect(value).to.eql(nestedStructArray); const proofData = JSON.parse(proof.data); @@ -774,7 +855,6 @@ describe('Get value from storage', () => { }); it('get value for fixed size nested array of address type', async () => { - const blockHash = await getBlockHash(); const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedArrays.address, 'nestedAddressArray'); expect(value).to.eql(nestedAddressArray); const proofData = JSON.parse(proof.data); @@ -782,27 +862,26 @@ describe('Get value from storage', () => { expect(proofData[0].length).to.equal(nestedAddressArray[0].length); }); - it('get value for nested dynamic array of integer type', async () => { - const blockHash = await getBlockHash(); - - // Test for variable nestedFixedDynamicArray. - let { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedArrays.address, 'nestedFixedDynamicArray'); + it('get value for nested fixed dynamic array of integer type', async () => { + const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedArrays.address, 'nestedFixedDynamicArray'); expect(value).to.eql(nestedFixedDynamicArray); - let proofData = JSON.parse(proof.data); + const proofData = JSON.parse(proof.data); expect(proofData.length).to.equal(nestedFixedDynamicArray.length); expect(proofData[0].length).to.equal(nestedFixedDynamicArray[0].length); + }); - // Test for variable nestedFixedDynamicArray. - ({ value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedArrays.address, 'nestedDynamicFixedArray')); + it('get value for nested dynamic fixed array of integer type', async () => { + const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedArrays.address, 'nestedDynamicFixedArray'); expect(value).to.eql(nestedDynamicArray); - proofData = JSON.parse(proof.data); + const proofData = JSON.parse(proof.data); expect(proofData.length).to.equal(nestedDynamicArray.length); expect(proofData[0].length).to.equal(nestedDynamicArray[0].length); + }); - // Test for variable nestedDynamicArray. - ({ value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedArrays.address, 'nestedDynamicArray')); + it('get value for nested dynamic array of integer type', async () => { + const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedArrays.address, 'nestedDynamicArray'); expect(value).to.eql(nestedDynamicArray); - proofData = JSON.parse(proof.data); + const proofData = JSON.parse(proof.data); expect(proofData.length).to.equal(nestedDynamicArray.length); expect(proofData[0].length).to.equal(nestedDynamicArray[0].length); }); @@ -811,7 +890,6 @@ describe('Get value from storage', () => { it('get value of fixed size struct type nested array by index', async () => { const arrayIndex = 2; const nestedArrayIndex = 1; - const blockHash = await getBlockHash(); let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedArrays.address, 'nestedStructArray', arrayIndex, nestedArrayIndex); expect(value).to.eql(nestedStructArray[arrayIndex][nestedArrayIndex]); @@ -823,14 +901,11 @@ describe('Get value from storage', () => { it('get value of fixed size address type nested array by index', async () => { const arrayIndex = 2; const nestedArrayIndex = 1; - const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedArrays.address, 'nestedAddressArray', arrayIndex, nestedArrayIndex); expect(value).to.eql(nestedAddressArray[arrayIndex][nestedArrayIndex]); }); it('get value of dynamically sized nested array by index', async () => { - const blockHash = await getBlockHash(); - // Test for variable nestedFixedDynamicArray. let arrayIndex = 1; let nestedArrayIndex = 2; @@ -884,12 +959,12 @@ describe('Get value from storage', () => { await testValueStructs.deployed(); storageLayout = await getStorageLayout('TestValueStructs'); - const [signer1, signer2] = await ethers.getSigners(); + const [address1, address2] = generateDummyAddresses(2); addressStruct = { int1: BigInt(123), - address1: signer1.address.toLowerCase(), - address2: signer2.address.toLowerCase(), + address1, + address2, uint1: BigInt(456) }; @@ -905,7 +980,8 @@ describe('Get value from storage', () => { // Get all members of a struct. it('get value for struct using a single slot', async () => { - await testValueStructs.setSingleSlotStruct(singleSlotStruct.int1, singleSlotStruct.uint1); + const transaction = await testValueStructs.setSingleSlotStruct(singleSlotStruct.int1, singleSlotStruct.uint1); + await transaction.wait(); const blockHash = await getBlockHash(); const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'singleSlotStruct'); expect(value).to.eql(singleSlotStruct); @@ -914,7 +990,8 @@ describe('Get value from storage', () => { }); it('get value for struct using multiple slots', async () => { - await testValueStructs.setMultipleSlotStruct(multipleSlotStruct.uint1, multipleSlotStruct.bool1, multipleSlotStruct.int1); + const transaction = await testValueStructs.setMultipleSlotStruct(multipleSlotStruct.uint1, multipleSlotStruct.bool1, multipleSlotStruct.int1); + await transaction.wait(); const blockHash = await getBlockHash(); const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'multipleSlotStruct'); expect(value).to.eql(multipleSlotStruct); @@ -923,7 +1000,8 @@ describe('Get value from storage', () => { }); it('get value for struct with address type members', async () => { - await testValueStructs.setAddressStruct(addressStruct); + const transaction = await testValueStructs.setAddressStruct(addressStruct); + await transaction.wait(); const blockHash = await getBlockHash(); const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'addressStruct'); expect(value).to.eql(addressStruct); @@ -932,7 +1010,8 @@ describe('Get value from storage', () => { }); it('get value for struct with contract type members', async () => { - await testValueStructs.setContractStruct(contractStruct.uint1, contractStruct.testContract); + const transaction = await testValueStructs.setContractStruct(contractStruct.uint1, contractStruct.testContract); + await transaction.wait(); const blockHash = await getBlockHash(); const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'contractStruct'); expect(value).to.eql(contractStruct); @@ -941,7 +1020,8 @@ describe('Get value from storage', () => { }); it('get value for struct with fixed-sized byte array members', async () => { - await testValueStructs.setFixedBytesStruct(fixedBytesStruct.uint1, fixedBytesStruct.bytesTen, fixedBytesStruct.bytesTwenty); + const transaction = await testValueStructs.setFixedBytesStruct(fixedBytesStruct.uint1, fixedBytesStruct.bytesTen, fixedBytesStruct.bytesTwenty); + await transaction.wait(); const blockHash = await getBlockHash(); const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'fixedBytesStruct'); expect(value).to.eql(fixedBytesStruct); @@ -950,7 +1030,8 @@ describe('Get value from storage', () => { }); it('get value for struct with enum type members', async () => { - await testValueStructs.setEnumStruct(enumStruct.uint1, enumStruct.choice1, enumStruct.choice2); + const transaction = await testValueStructs.setEnumStruct(enumStruct.uint1, enumStruct.choice1, enumStruct.choice2); + await transaction.wait(); const blockHash = await getBlockHash(); const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'enumStruct'); expect(value).to.eql(enumStruct); @@ -961,7 +1042,8 @@ describe('Get value from storage', () => { // Get value of a member in a struct it('get value of signed integer type member in a struct', async () => { const member = 'int1'; - await testValueStructs.setSingleSlotStruct(singleSlotStruct.int1, singleSlotStruct.uint1); + const transaction = await testValueStructs.setSingleSlotStruct(singleSlotStruct.int1, singleSlotStruct.uint1); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'singleSlotStruct', member); expect(value).to.equal(singleSlotStruct[member]); @@ -975,7 +1057,8 @@ describe('Get value from storage', () => { }); it('get value of boolean type member in a struct', async () => { - await testValueStructs.setMultipleSlotStruct(multipleSlotStruct.uint1, multipleSlotStruct.bool1, multipleSlotStruct.int1); + const transaction = await testValueStructs.setMultipleSlotStruct(multipleSlotStruct.uint1, multipleSlotStruct.bool1, multipleSlotStruct.int1); + await transaction.wait(); const blockHash = await getBlockHash(); let member = 'bool1'; @@ -992,7 +1075,8 @@ describe('Get value from storage', () => { }); it('get value of address type member in a struct', async () => { - await testValueStructs.setAddressStruct(addressStruct); + const transaction = await testValueStructs.setAddressStruct(addressStruct); + await transaction.wait(); const blockHash = await getBlockHash(); let member = 'address1'; let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'addressStruct', member); @@ -1005,7 +1089,8 @@ describe('Get value from storage', () => { it('get value of contract type member in a struct', async () => { const member = 'testContract'; - await testValueStructs.setContractStruct(contractStruct.uint1, contractStruct.testContract); + const transaction = await testValueStructs.setContractStruct(contractStruct.uint1, contractStruct.testContract); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'contractStruct', member); expect(value).to.equal(contractStruct[member]); @@ -1013,7 +1098,8 @@ describe('Get value from storage', () => { it('get value of fixed byte array member in a struct', async () => { const member = 'bytesTen'; - await testValueStructs.setFixedBytesStruct(fixedBytesStruct.uint1, fixedBytesStruct.bytesTen, fixedBytesStruct.bytesTwenty); + const transaction = await testValueStructs.setFixedBytesStruct(fixedBytesStruct.uint1, fixedBytesStruct.bytesTen, fixedBytesStruct.bytesTwenty); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'fixedBytesStruct', member); expect(value).to.equal(fixedBytesStruct[member]); @@ -1021,7 +1107,8 @@ describe('Get value from storage', () => { it('get value of enum type member in a struct', async () => { const member = 'choice2'; - await testValueStructs.setEnumStruct(enumStruct.uint1, enumStruct.choice1, enumStruct.choice2); + const transaction = await testValueStructs.setEnumStruct(enumStruct.uint1, enumStruct.choice1, enumStruct.choice2); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'enumStruct', member); expect(value).to.equal(enumStruct[member]); @@ -1043,17 +1130,17 @@ describe('Get value from storage', () => { await testReferenceStructs.deployed(); storageLayout = await getStorageLayout('TestReferenceStructs'); - const signers = await ethers.getSigners(); + const addresses = generateDummyAddresses(5); fixedArrayStruct = { int1: BigInt(123), uintArray: [1, 2, 3, 4].map(el => BigInt(el)), - addressArray: signers.slice(0, 3).map(signer => signer.address.toLowerCase()) + addressArray: addresses.slice(0, 3) }; bytesStruct = { byteArray: ethers.utils.hexlify(ethers.utils.randomBytes(40)), - address1: signers[1].address.toLowerCase(), + address1: addresses[1], uint1: BigInt(1234) }; @@ -1062,52 +1149,57 @@ describe('Get value from storage', () => { int1: BigInt(123), uint1: BigInt(456), string2: 'string2', - address1: signers[2].address.toLowerCase(), + address1: addresses[2], bool1: false }; nestedStruct = { bytesStruct, - address1: signers[3].address.toLowerCase() + address1: addresses[3] }; dynamicArrayStruct = { - address1: signers[4].address.toLowerCase(), + address1: addresses[4], uintArray: [1, 2, 3, 4, 5].map(BigInt) }; }); // Get all members of a struct. it('get value for struct with fixed-size array members', async () => { - await testReferenceStructs.setFixedArrayStruct(fixedArrayStruct.int1, fixedArrayStruct.uintArray, fixedArrayStruct.addressArray); + const transaction = await testReferenceStructs.setFixedArrayStruct(fixedArrayStruct.int1, fixedArrayStruct.uintArray, fixedArrayStruct.addressArray); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'fixedArrayStruct'); expect(value).to.eql(fixedArrayStruct); }); it('get value for struct with dynamically sized byte members', async () => { - await testReferenceStructs.setBytesStruct(bytesStruct); + const transaction = await testReferenceStructs.setBytesStruct(bytesStruct); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'bytesStruct'); expect(value).to.eql(bytesStruct); }); it('get value for struct with string type members', async () => { - await testReferenceStructs.setStringStruct(stringStruct); + const transaction = await testReferenceStructs.setStringStruct(stringStruct); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'stringStruct'); expect(value).to.eql(stringStruct); }); it('get value for struct with dynamic array members', async () => { - await testReferenceStructs.setDynamicArrayStruct(dynamicArrayStruct); + const transaction = await testReferenceStructs.setDynamicArrayStruct(dynamicArrayStruct); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'dynamicArrayStruct'); expect(value).to.eql(dynamicArrayStruct); }); it('get value for nested struct with struct type members', async () => { - await testReferenceStructs.setNestedStruct(nestedStruct); + const transaction = await testReferenceStructs.setNestedStruct(nestedStruct); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'nestedStruct'); expect(value).to.eql(nestedStruct); @@ -1116,7 +1208,8 @@ describe('Get value from storage', () => { // Get value of a member in a struct it('get value of fixed-size array member in a struct', async () => { const member = 'uintArray'; - await testReferenceStructs.setFixedArrayStruct(fixedArrayStruct.int1, fixedArrayStruct.uintArray, fixedArrayStruct.addressArray); + const transaction = await testReferenceStructs.setFixedArrayStruct(fixedArrayStruct.int1, fixedArrayStruct.uintArray, fixedArrayStruct.addressArray); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'fixedArrayStruct', member); expect(value).to.eql(fixedArrayStruct[member]); @@ -1124,7 +1217,8 @@ describe('Get value from storage', () => { it('get value of bytes member in a struct', async () => { const member = 'byteArray'; - await testReferenceStructs.setBytesStruct(bytesStruct); + const transaction = await testReferenceStructs.setBytesStruct(bytesStruct); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'bytesStruct', member); expect(value).to.equal(bytesStruct[member]); @@ -1132,7 +1226,8 @@ describe('Get value from storage', () => { it('get value of string member in a struct', async () => { const member = 'string2'; - await testReferenceStructs.setStringStruct(stringStruct); + const transaction = await testReferenceStructs.setStringStruct(stringStruct); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'stringStruct', member); expect(value).to.eql(stringStruct[member]); @@ -1146,7 +1241,8 @@ describe('Get value from storage', () => { }); it('get value of mapping type member in a struct', async () => { - const [signer1, signer2] = await ethers.getSigners(); + const [signer1] = await ethers.getSigners(); + const [address2] = generateDummyAddresses(1); const valueMappingStruct: { [key: string]: any } = { uintAddressMap: new Map(), @@ -1156,10 +1252,11 @@ describe('Get value from storage', () => { const mappingKey = 456; valueMappingStruct.uintAddressMap.set(mappingKey, signer1.address.toLowerCase()); - valueMappingStruct.addressIntMap.set(signer2.address, 789); + valueMappingStruct.addressIntMap.set(address2, 789); let member = 'uintAddressMap'; - await testReferenceStructs.setValueMappingStruct(mappingKey, valueMappingStruct.uintAddressMap.get(mappingKey), valueMappingStruct.uint1, signer2.address, valueMappingStruct.addressIntMap.get(signer2.address)); + let transaction = await testReferenceStructs.setValueMappingStruct(mappingKey, valueMappingStruct.uintAddressMap.get(mappingKey), valueMappingStruct.uint1, address2, valueMappingStruct.addressIntMap.get(address2)); + await transaction.wait(); let blockHash = await getBlockHash(); let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'valueMappingStruct', member, mappingKey); expect(value).to.equal(valueMappingStruct[member].get(mappingKey)); @@ -1176,14 +1273,16 @@ describe('Get value from storage', () => { referenceMappingStruct.stringUintMap.set(stringKey, BigInt(123)); member = 'stringUintMap'; - await testReferenceStructs.setReferenceMappingStruct(bytesKey, referenceMappingStruct.bytesAddressMap.get(bytesKey), stringKey, referenceMappingStruct.stringUintMap.get(stringKey)); + transaction = await testReferenceStructs.setReferenceMappingStruct(bytesKey, referenceMappingStruct.bytesAddressMap.get(bytesKey), stringKey, referenceMappingStruct.stringUintMap.get(stringKey)); + await transaction.wait(); blockHash = await getBlockHash(); ({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'referenceMappingStruct', member, stringKey)); expect(value).to.equal(referenceMappingStruct[member].get(stringKey)); }); it('get value of nested struct member', async () => { - await testReferenceStructs.setNestedStruct(nestedStruct); + const transaction = await testReferenceStructs.setNestedStruct(nestedStruct); + await transaction.wait(); const blockHash = await getBlockHash(); const member = 'bytesStruct'; let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'nestedStruct', member); @@ -1213,8 +1312,9 @@ describe('Get value from storage', () => { // Tests for value type keys. it('get value for mapping with address type keys', async () => { const expectedValue = 123; - const [, signer1] = await ethers.getSigners(); - await testMappingTypes.connect(signer1).setAddressUintMap(expectedValue); + const [signer1] = await ethers.getSigners(); + const transaction = await testMappingTypes.connect(signer1).setAddressUintMap(expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'addressUintMap', signer1.address); expect(value).to.equal(BigInt(expectedValue)); @@ -1223,7 +1323,8 @@ describe('Get value from storage', () => { it('get value for mapping with boolean type keys', async () => { const expectedValue = 123; const mapKey = true; - await testMappingTypes.setBoolIntMap(mapKey, expectedValue); + const transaction = await testMappingTypes.setBoolIntMap(mapKey, expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'boolIntMap', mapKey); expect(value).to.equal(BigInt(expectedValue)); @@ -1231,17 +1332,19 @@ describe('Get value from storage', () => { it('get value for mapping with signed integer type keys', async () => { const mapKey = 123; - const [, signer1] = await ethers.getSigners(); - await testMappingTypes.setIntAddressMap(mapKey, signer1.address); + const [address1] = generateDummyAddresses(1); + const transaction = await testMappingTypes.setIntAddressMap(mapKey, address1); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'intAddressMap', mapKey); - expect(value).to.equal(signer1.address.toLowerCase()); + expect(value).to.equal(address1); }); it('get value for mapping with unsigned integer type keys', async () => { const expectedValue = ethers.utils.hexlify(ethers.utils.randomBytes(16)); const mapKey = 123; - await testMappingTypes.setUintBytesMap(mapKey, expectedValue); + const transaction = await testMappingTypes.setUintBytesMap(mapKey, expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'uintBytesMap', mapKey); expect(value).to.equal(expectedValue); @@ -1253,7 +1356,8 @@ describe('Get value from storage', () => { it.skip('get value for mapping with fixed-size byte array keys', async () => { const mapKey = ethers.utils.hexlify(ethers.utils.randomBytes(8)); const [, signer1] = await ethers.getSigners(); - await testMappingTypes.setBytesAddressMap(mapKey, signer1.address); + const transaction = await testMappingTypes.setBytesAddressMap(mapKey, signer1.address); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'bytesAddressMap', mapKey); expect(value).to.equal(signer1.address); @@ -1262,7 +1366,8 @@ describe('Get value from storage', () => { it('get value for mapping with enum type keys', async () => { const mapKey = 1; const expectedValue = 123; - await testMappingTypes.setEnumIntMap(mapKey, expectedValue); + const transaction = await testMappingTypes.setEnumIntMap(mapKey, expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'enumIntMap', mapKey); expect(value).to.equal(BigInt(expectedValue)); @@ -1272,7 +1377,8 @@ describe('Get value from storage', () => { it('get value for mapping with string type keys', async () => { const mapKey = 'abc'; const expectedValue = 123; - await testMappingTypes.setStringIntMap(mapKey, expectedValue); + const transaction = await testMappingTypes.setStringIntMap(mapKey, expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'stringIntMap', mapKey); expect(value).to.equal(BigInt(expectedValue)); @@ -1281,7 +1387,8 @@ describe('Get value from storage', () => { it('get value for mapping with dynamically-sized byte array as keys', async () => { const mapKey = ethers.utils.hexlify(ethers.utils.randomBytes(64)); const expectedValue = 123; - await testMappingTypes.setBytesUintMap(mapKey, expectedValue); + const transaction = await testMappingTypes.setBytesUintMap(mapKey, expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'bytesUintMap', mapKey); expect(value).to.equal(BigInt(expectedValue)); @@ -1299,7 +1406,8 @@ describe('Get value from storage', () => { }; const mapKey = 123; - await testMappingTypes.setIntStructMap(mapKey, expectedValue); + const transaction = await testMappingTypes.setIntStructMap(mapKey, expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'intStructMap', mapKey); expect(value).to.eql(expectedValue); @@ -1325,7 +1433,8 @@ describe('Get value from storage', () => { }; const mapKey = ethers.utils.hexlify(ethers.utils.randomBytes(32)); - await testMappingTypes.setFixedBytesStructMap(mapKey, expectedValue); + const transaction = await testMappingTypes.setFixedBytesStructMap(mapKey, expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'fixedBytesStructMap', mapKey); expect(value).to.eql(expectedValue); @@ -1337,17 +1446,18 @@ describe('Get value from storage', () => { }); it('get value for mapping of address type keys and struct type values', async () => { - const [signer1, signer2] = await ethers.getSigners(); + const [address1, address2] = generateDummyAddresses(2); const expectedValue = { uint1: BigInt(123), int1: BigInt(456), bool1: true, - address1: signer1.address.toLowerCase() + address1: address1 }; - const mapKey = signer2.address; - await testMappingTypes.setAddressStructMap(mapKey, expectedValue); + const mapKey = address2; + const transaction = await testMappingTypes.setAddressStructMap(mapKey, expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'addressStructMap', mapKey); expect(value).to.eql(expectedValue); @@ -1355,12 +1465,9 @@ describe('Get value from storage', () => { it('get value for mapping of unsigned integer keys and fixed-size array values', async () => { const mapKey = 123; - const signers = await ethers.getSigners(); - - const expectedValue = signers.slice(0, 3) - .map(signer => signer.address.toLowerCase()); - - await testMappingTypes.setUintFixedArrayMap(mapKey, expectedValue); + const expectedValue = generateDummyAddresses(3); + const transaction = await testMappingTypes.setUintFixedArrayMap(mapKey, expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'uintFixedArrayMap', mapKey); expect(value).to.eql(expectedValue); @@ -1372,7 +1479,8 @@ describe('Get value from storage', () => { const mapKey = 123; const expectedValue = [1, 2, 3, 4, 5, 6, 7, 8]; - await testMappingTypes.setIntDynamicArrayMap(mapKey, expectedValue); + const transaction = await testMappingTypes.setIntDynamicArrayMap(mapKey, expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'intDynamicArrayMap', mapKey); expect(value).to.eql(expectedValue.map(BigInt)); @@ -1384,7 +1492,8 @@ describe('Get value from storage', () => { const [signer1] = await ethers.getSigners(); const expectedValue = ethers.utils.hexlify(ethers.utils.randomBytes(42)); - await testMappingTypes.setAddressBytesMap(signer1.address, expectedValue); + const transaction = await testMappingTypes.setAddressBytesMap(signer1.address, expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'addressBytesMap', signer1.address); expect(value).to.eql(expectedValue); @@ -1394,7 +1503,8 @@ describe('Get value from storage', () => { const mapKey = ethers.utils.hexlify(ethers.utils.randomBytes(32)); const expectedValue = 'Hello world.'; - await testMappingTypes.setBytesStringMap(mapKey, expectedValue); + const transaction = await testMappingTypes.setBytesStringMap(mapKey, expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'bytesStringMap', mapKey); expect(value).to.eql(expectedValue); @@ -1413,20 +1523,23 @@ describe('Get value from storage', () => { it('get value for nested mapping with address type keys', async () => { const expectedValue = 123; - const [, signer1, signer2] = await ethers.getSigners(); - await testNestedMapping.connect(signer1).setNestedAddressUintMap(signer2.address, expectedValue); + const [signer1] = await ethers.getSigners(); + const [address2] = generateDummyAddresses(1); + const transaction = await testNestedMapping.connect(signer1).setNestedAddressUintMap(address2, expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); - const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedMapping.address, 'nestedAddressUintMap', signer1.address, signer2.address); + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedMapping.address, 'nestedAddressUintMap', signer1.address, address2); expect(value).to.equal(BigInt(expectedValue)); }); it('get value for nested mapping with signed integer type keys', async () => { const expectedValue = false; const key = 123; - const [, signer1] = await ethers.getSigners(); - await testNestedMapping.setIntAddressBoolMap(key, signer1.address, expectedValue); + const [address1] = generateDummyAddresses(1); + const transaction = await testNestedMapping.setIntAddressBoolMap(key, address1, expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); - const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedMapping.address, 'intAddressBoolMap', key, signer1.address); + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedMapping.address, 'intAddressBoolMap', key, address1); expect(value).to.equal(expectedValue); }); @@ -1434,7 +1547,8 @@ describe('Get value from storage', () => { const expectedValue = 123; const key = 456; const nestedKey = 'abc'; - await testNestedMapping.setUintStringIntMap(key, nestedKey, expectedValue); + const transaction = await testNestedMapping.setUintStringIntMap(key, nestedKey, expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedMapping.address, 'uintStringIntMap', key, nestedKey); expect(value).to.equal(BigInt(expectedValue)); @@ -1443,30 +1557,33 @@ describe('Get value from storage', () => { it('get value for nested mapping with dynamically-sized byte array as keys', async () => { const key = ethers.utils.hexlify(ethers.utils.randomBytes(64)); const nestedKey = 123; - const [, signer1] = await ethers.getSigners(); - await testNestedMapping.setBytesIntAddressMap(key, nestedKey, signer1.address); + const [address1] = generateDummyAddresses(1); + const transaction = await testNestedMapping.setBytesIntAddressMap(key, nestedKey, address1); + await transaction.wait(); const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedMapping.address, 'bytesIntAddressMap', key, nestedKey); - expect(value).to.equal(signer1.address.toLowerCase()); + expect(value).to.equal(address1); }); it('get value for nested mapping with string type keys', async () => { const key = 'abc'; const expectedValue = 123; - const [, signer1] = await ethers.getSigners(); - await testNestedMapping.setStringAddressIntMap(key, signer1.address, expectedValue); + const [address1] = generateDummyAddresses(1); + const transaction = await testNestedMapping.setStringAddressIntMap(key, address1, expectedValue); + await transaction.wait(); const blockHash = await getBlockHash(); - const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedMapping.address, 'stringAddressIntMap', key, signer1.address); + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedMapping.address, 'stringAddressIntMap', key, address1); expect(value).to.equal(BigInt(expectedValue)); }); it('get value for double nested mapping with address type keys', async () => { - const [signer1, signer2, signer3] = await ethers.getSigners(); + const [address1, address2, address3] = generateDummyAddresses(3); const uintKey = 123; - await testNestedMapping.setDoubleNestedAddressMap(signer1.address, signer2.address, uintKey, signer3.address); + const transaction = await testNestedMapping.setDoubleNestedAddressMap(address1, address2, uintKey, address3); + await transaction.wait(); const blockHash = await getBlockHash(); - const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedMapping.address, 'doubleNestedAddressMap', signer1.address, signer2.address, uintKey); - expect(value).to.equal(signer3.address.toLowerCase()); + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedMapping.address, 'doubleNestedAddressMap', address1, address2, uintKey); + expect(value).to.equal(address3); }); }); }); diff --git a/packages/solidity-mapper/test/utils.ts b/packages/solidity-mapper/test/utils.ts index b7e1a716..d4f38f5c 100644 --- a/packages/solidity-mapper/test/utils.ts +++ b/packages/solidity-mapper/test/utils.ts @@ -1,4 +1,5 @@ import { ContractInterface } from '@ethersproject/contracts'; +import '@nomiclabs/hardhat-ethers'; import { artifacts, ethers } from 'hardhat'; import { CompilerOutput, CompilerOutputBytecode } from 'hardhat/types'; @@ -68,3 +69,13 @@ export const getStorageAt: GetStorageAt = async ({ blockHash, contract, slot }) } }; }; + +/** + * Generate array of dummy addresses of specified length. + * @param length + */ +export const generateDummyAddresses = (length: number): Array => { + return Array.from({ length }, () => { + return ethers.utils.hexlify(ethers.utils.randomBytes(20)); + }); +}; diff --git a/yarn.lock b/yarn.lock index dcf22524..04cd7801 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5229,6 +5229,11 @@ dot-prop@^6.0.1: dependencies: is-obj "^2.0.0" +dotenv@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" + integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== + dotenv@^8.2.0: version "8.6.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b"