diff --git a/packages/solidity-mapper/src/logs.test.ts b/packages/solidity-mapper/src/logs.test.ts index b270214e..559eb76a 100644 --- a/packages/solidity-mapper/src/logs.test.ts +++ b/packages/solidity-mapper/src/logs.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai'; import '@nomiclabs/hardhat-ethers'; -import { artifacts, ethers } from 'hardhat'; +import { artifacts } from 'hardhat'; import { getEventNameTopics } from './logs'; @@ -21,9 +21,6 @@ const TEST_DATA = [ it('get event name topics', async () => { const testPromises = TEST_DATA.map(async ({ name, output }) => { - const Contract = await ethers.getContractFactory(name); - const contract = await Contract.deploy(); - await contract.deployed(); const { abi } = await artifacts.readArtifact(name); const eventNameTopics = getEventNameTopics(abi); diff --git a/packages/solidity-mapper/src/storage.test.ts b/packages/solidity-mapper/src/storage.test.ts index 33bfc13f..1a7234a9 100644 --- a/packages/solidity-mapper/src/storage.test.ts +++ b/packages/solidity-mapper/src/storage.test.ts @@ -10,6 +10,24 @@ import { EthClient } from '@vulcanize/ipld-eth-client'; import { getStorageInfo, getStorageValue, StorageLayout } from './storage'; import { getStorageLayout, getStorageAt as rpcGetStorageAt, generateDummyAddresses } from '../test/utils'; +const CONTRACTS = [ + 'TestIntegers', + 'TestUnsignedIntegers', + 'TestBooleans', + 'TestAddress', + 'TestContractTypes', + 'TestBytes', + 'TestEnums', + 'TestStrings', + 'TestFixedArrays', + 'TestDynamicArrays', + 'TestNestedArrays', + 'TestValueStructs', + 'TestReferenceStructs', + 'TestBasicMapping', + 'TestNestedMapping' +]; + const TEST_DATA = [ { name: 'TestBooleans', @@ -65,9 +83,6 @@ const TEST_DATA = [ it('get storage information', async () => { const testPromises = TEST_DATA.map(async ({ name, variable, output }) => { - const Contract = await ethers.getContractFactory(name); - const contract = await Contract.deploy(); - await contract.deployed(); const storageLayout = await getStorageLayout(name); const storageInfo = getStorageInfo(storageLayout, variable); @@ -77,6 +92,8 @@ it('get storage information', async () => { await Promise.all(testPromises); }); +type Contracts = {[key: string]: { contract: Contract, storageLayout: StorageLayout }} + describe('Get value from storage', () => { const getBlockHash = async () => { const blockNumber = await ethers.provider.getBlockNumber(); @@ -84,6 +101,27 @@ describe('Get value from storage', () => { return hash; }; + let contracts: Contracts; + + before(async () => { + const contractPromises = CONTRACTS.map(async name => { + const Contract = await ethers.getContractFactory(name); + const contract = await Contract.deploy(); + await contract.deployed(); + const storageLayout = await getStorageLayout(name); + + return { contract, storageLayout, name }; + }); + + const contractData = await Promise.all(contractPromises); + + contracts = contractData.reduce((acc: Contracts, contract) => { + const { name, ...data } = contract; + acc[name] = data; + return acc; + }, {}); + }); + let getStorageAt = rpcGetStorageAt; // Check if running test against ipld graphql endpoint. @@ -100,104 +138,93 @@ describe('Get value from storage', () => { } describe('signed integer type', () => { - let integers: Contract, storageLayout: StorageLayout; + let integers: Contract, storageLayout: StorageLayout, blockHash: string; + const int1Value = 12; + const int2Value = 34; + const int3Value = 123; before(async () => { - const Integers = await ethers.getContractFactory('TestIntegers'); - integers = await Integers.deploy(); - await integers.deployed(); - storageLayout = await getStorageLayout('TestIntegers'); + ({ contract: integers, storageLayout } = contracts.TestIntegers); + + const transactions = await Promise.all([ + integers.setInt1(int1Value), + integers.setInt2(int2Value), + integers.setInt3(int3Value) + ]); + + await Promise.all(transactions.map(transaction => transaction.wait())); + blockHash = await getBlockHash(); }); 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)); + expect(value).to.equal(BigInt(int1Value)); - 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)); + expect(value).to.equal(BigInt(int2Value)); }); 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)); + expect(value).to.equal(BigInt(int3Value)); }); }); describe('unsigned integer type', () => { - let unsignedIntegers: Contract, storageLayout: StorageLayout; + let unsignedIntegers: Contract, storageLayout: StorageLayout, blockHash: string; + const uint1Value = 12; + const uint2Value = 34; + const uint3Value = 123; before(async () => { - const UnsignedIntegers = await ethers.getContractFactory('TestUnsignedIntegers'); - unsignedIntegers = await UnsignedIntegers.deploy(); - await unsignedIntegers.deployed(); - storageLayout = await getStorageLayout('TestUnsignedIntegers'); + ({ contract: unsignedIntegers, storageLayout } = contracts.TestUnsignedIntegers); + + const transactions = await Promise.all([ + unsignedIntegers.setUint1(uint1Value), + unsignedIntegers.setUint2(uint2Value), + unsignedIntegers.setUint3(uint3Value) + ]); + + await Promise.all(transactions.map(transaction => transaction.wait())); + blockHash = await getBlockHash(); }); 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)); + expect(value).to.equal(BigInt(uint1Value)); - 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)); + expect(value).to.equal(BigInt(uint2Value)); }); 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)); + expect(value).to.equal(BigInt(uint3Value)); }); }); it('get value for boolean type', async () => { - const Booleans = await ethers.getContractFactory('TestBooleans'); - const booleans = await Booleans.deploy(); - await booleans.deployed(); - const storageLayout = await getStorageLayout('TestBooleans'); + const { contract: booleans, storageLayout } = contracts.TestBooleans; + const bool1Value = true; + const bool2Value = false; + + const transactions = await Promise.all([ + booleans.setBool1(bool1Value), + booleans.setBool2(bool2Value) + ]); + + await Promise.all(transactions.map(transaction => transaction.wait())); + const blockHash = await getBlockHash(); - let expectedValue = true; - 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); + expect(value).to.equal(bool1Value); - expectedValue = false; - 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); + expect(value).to.equal(bool2Value); }); it('get value for address type', async () => { - const Address = await ethers.getContractFactory('TestAddress'); - const address = await Address.deploy(); - await address.deployed(); - const storageLayout = await getStorageLayout('TestAddress'); - + const { contract: address, storageLayout } = contracts.TestAddress; const [signer] = await ethers.getSigners(); const transaction = await address.setAddress1(signer.address); await transaction.wait(); @@ -208,17 +235,8 @@ describe('Get value from storage', () => { }); it('get value for contract type', async () => { - const contracts = ['TestContractTypes', 'TestAddress']; - - const contractPromises = contracts.map(async (contractName) => { - const Contract = await ethers.getContractFactory(contractName); - const contract = await Contract.deploy(); - return contract.deployed(); - }); - - const [testContractTypes, testAddress] = await Promise.all(contractPromises); - const storageLayout = await getStorageLayout('TestContractTypes'); - + const { contract: testAddress } = contracts.TestAddress; + const { contract: testContractTypes, storageLayout } = contracts.TestContractTypes; const transaction = await testContractTypes.setAddressContract1(testAddress.address); await transaction.wait(); const blockHash = await getBlockHash(); @@ -227,32 +245,27 @@ describe('Get value from storage', () => { }); it('get value for fixed size byte arrays packed together', async () => { - const TestBytes = await ethers.getContractFactory('TestBytes'); - const testBytes = await TestBytes.deploy(); - await testBytes.deployed(); - const storageLayout = await getStorageLayout('TestBytes'); + const { contract: testBytes, storageLayout } = contracts.TestBytes; + const bytesTenValue = ethers.utils.hexlify(ethers.utils.randomBytes(10)); + const bytesTwentyValue = ethers.utils.hexlify(ethers.utils.randomBytes(20)); + + const transactions = await Promise.all([ + testBytes.setBytesTen(bytesTenValue), + testBytes.setBytesTwenty(bytesTwentyValue) + ]); + + await Promise.all(transactions.map(transaction => transaction.wait())); + const blockHash = await getBlockHash(); - let expectedValue = ethers.utils.hexlify(ethers.utils.randomBytes(10)); - 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); + expect(value).to.equal(bytesTenValue); - expectedValue = ethers.utils.hexlify(ethers.utils.randomBytes(20)); - 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); + expect(value).to.equal(bytesTwentyValue); }); it('get value for fixed size byte arrays using single slot', async () => { - const TestBytes = await ethers.getContractFactory('TestBytes'); - const testBytes = await TestBytes.deploy(); - await testBytes.deployed(); - const storageLayout = await getStorageLayout('TestBytes'); - + const { contract: testBytes, storageLayout } = contracts.TestBytes; const expectedValue = ethers.utils.hexlify(ethers.utils.randomBytes(30)); const transaction = await testBytes.setBytesThirty(expectedValue); await transaction.wait(); @@ -262,11 +275,7 @@ describe('Get value from storage', () => { }); it('get value for enum types', async () => { - const TestEnums = await ethers.getContractFactory('TestEnums'); - const testEnums = await TestEnums.deploy(); - await testEnums.deployed(); - const storageLayout = await getStorageLayout('TestEnums'); - + const { contract: testEnums, storageLayout } = contracts.TestEnums; const expectedValue = 1; const transaction = await testEnums.setChoicesEnum1(expectedValue); await transaction.wait(); @@ -276,33 +285,32 @@ describe('Get value from storage', () => { }); describe('string type', () => { - let strings: Contract, storageLayout: StorageLayout; + let strings: Contract, storageLayout: StorageLayout, blockHash: string; + const string1Value = 'Hello world.'; + const string2Value = 'This sentence is more than 32 bytes long.'; before(async () => { - const Strings = await ethers.getContractFactory('TestStrings'); - strings = await Strings.deploy(); - await strings.deployed(); - storageLayout = await getStorageLayout('TestStrings'); + ({ contract: strings, storageLayout } = contracts.TestStrings); + + const transactions = await Promise.all([ + strings.setString1(string1Value), + strings.setString2(string2Value) + ]); + + await Promise.all(transactions.map(transaction => transaction.wait())); + blockHash = await getBlockHash(); }); // 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.'; - 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); + expect(value).to.equal(string1Value); }); // 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.'; - 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); + expect(value).to.equal(string2Value); }); }); @@ -310,10 +318,7 @@ describe('Get value from storage', () => { let testBytes: Contract, storageLayout: StorageLayout; before(async () => { - const TestBytes = await ethers.getContractFactory('TestBytes'); - testBytes = await TestBytes.deploy(); - await testBytes.deployed(); - storageLayout = await getStorageLayout('TestBytes'); + ({ contract: testBytes, storageLayout } = contracts.TestBytes); }); it('get value for byte array length less than 32 bytes', async () => { @@ -336,7 +341,7 @@ describe('Get value from storage', () => { }); describe('fixed size arrays', () => { - let testFixedArrays: Contract, storageLayout: StorageLayout; + let testFixedArrays: Contract, storageLayout: StorageLayout, blockHash: string; const int128Array = [100, 200, 300, 400, 500]; const uint16Array = [10, 20, 30, 40, 50]; const boolArray = [true, false]; @@ -350,21 +355,58 @@ describe('Get value from storage', () => { const addressArray = generateDummyAddresses(4); + const mapArray = addressArray.slice(0, 3) + .map((address, index) => { + const map = new Map(); + map.set(address, BigInt(index * 10)); + return map; + }); + + const fixedBytesArray = Array.from({ length: 5 }, () => ethers.utils.hexlify(ethers.utils.randomBytes(10))); + + const structArray: Array<{[key: string]: any}> = []; + + for (let i = 0; i < 5; i++) { + const structElement = { + int1: BigInt(i + 1), + uint1: BigInt(i + 2), + bool1: Boolean(i % 2) + }; + + structArray[i] = structElement; + } + before(async () => { - const TestFixedArrays = await ethers.getContractFactory('TestFixedArrays'); - testFixedArrays = await TestFixedArrays.deploy(); - await testFixedArrays.deployed(); - storageLayout = await getStorageLayout('TestFixedArrays'); + ({ contract: testFixedArrays, storageLayout } = contracts.TestFixedArrays); + + const structArrayTransactions = structArray.map(async (structElement, index) => testFixedArrays.setStructArray(structElement, index)); + + const mapArrayTransactions = mapArray.map(async (map, index) => { + const [key, value] = map.entries().next().value; + return testFixedArrays.setMapArray(key, value, index); + }); + + const transactions = await Promise.all([ + testFixedArrays.setBoolArray(boolArray), + testFixedArrays.setUint16Array(uint16Array), + testFixedArrays.setInt128Array(int128Array), + testFixedArrays.setUintArray(uint16Array), + testFixedArrays.setAddressArray(addressArray), + testFixedArrays.setFixedBytesArray(fixedBytesArray), + testFixedArrays.setEnumArray(enumArray), + testFixedArrays.setBytesArray(bytesArray), + testFixedArrays.setStringArray(stringArray), + ...structArrayTransactions, + ...mapArrayTransactions + ]); + + await Promise.all(transactions.map(transaction => transaction.wait())); + blockHash = await getBlockHash(); }); // 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 () => { - 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); @@ -380,11 +422,6 @@ 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 () => { - 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))); @@ -399,9 +436,6 @@ describe('Get value from storage', () => { }); it('get value for fixed size arrays of address type', async () => { - 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); const proofData = JSON.parse(proof.data); @@ -409,21 +443,13 @@ 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))); - - 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); + expect(value).to.eql(fixedBytesArray); const proofData = JSON.parse(proof.data); - expect(proofData.length).to.equal(expectedValue.length); + expect(proofData.length).to.equal(fixedBytesArray.length); }); it('get value for fixed size arrays of enum type', async () => { - 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))); const proofData = JSON.parse(proof.data); @@ -431,9 +457,6 @@ describe('Get value from storage', () => { }); it('get value for fixed size arrays of dynamic byte array type', async () => { - 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); const proofData = JSON.parse(proof.data); @@ -441,9 +464,6 @@ describe('Get value from storage', () => { }); it('get value for fixed size arrays of string type', async () => { - 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); const proofData = JSON.parse(proof.data); @@ -451,146 +471,122 @@ describe('Get value from storage', () => { }); it('get value for fixed size array of struct type', async () => { - const expectedValue = []; - - for (let i = 0; i < 5; i++) { - const structElement = { - int1: BigInt(i + 1), - uint1: BigInt(i + 2), - bool1: Boolean(i % 2) - }; - - expectedValue[i] = structElement; - } - - 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); + expect(value).to.eql(structArray); const proofData = JSON.parse(proof.data); - expect(proofData.length).to.equal(expectedValue.length); + expect(proofData.length).to.equal(structArray.length); }); // Get element of array by index. it('get value of signed integer type array by index', async () => { const arrayIndex = 2; - 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])); }); it('get value of unsigned integer type array by index', async () => { const arrayIndex = 3; - 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])); }); it('get value of boolean type array by index', async () => { const arrayIndex = 0; - 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]); }); it('get value of address type array by index', async () => { const arrayIndex = 1; - 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]); }); it('get value of enum type array by index', async () => { const arrayIndex = 3; - const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'enumArray', arrayIndex); expect(value).to.eql(BigInt(enumArray[arrayIndex])); }); it('get value of struct type array by index', async () => { - const expectedValue = { - int1: BigInt(123), - uint1: BigInt(456), - bool1: false - }; - const arrayIndex = 2; - 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); + expect(value).to.eql(structArray[arrayIndex]); // Get value of specified struct member in array element. const structMember = 'uint1'; ({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'structArray', arrayIndex, structMember)); - expect(value).to.eql(expectedValue[structMember]); + expect(value).to.eql(structArray[arrayIndex][structMember]); }); it('get value of dynamic bytes type array by index', async () => { const arrayIndex = 2; - const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'bytesArray', arrayIndex); expect(value).to.eql(bytesArray[arrayIndex]); }); it('get value of string type array by index', async () => { const arrayIndex = 1; - const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'stringArray', arrayIndex); expect(value).to.eql(stringArray[arrayIndex]); }); it('get value of map type array by index', async () => { - // Set map array values. - const addresses = generateDummyAddresses(3); - - 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 = addresses[2]; - const mapArray = await Promise.all(mapArrayPromises); - const blockHash = await getBlockHash(); + const [mapKey, expectedValue] = mapArray[arrayIndex].entries().next().value; const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'mapArray', arrayIndex, mapKey); - expect(value).to.equal(mapArray[arrayIndex].get(mapKey)); + expect(value).to.equal(expectedValue); }); }); describe('dynamic sized arrays', () => { - let testDynamicArrays: Contract, storageLayout: StorageLayout; + let testDynamicArrays: Contract, storageLayout: StorageLayout, blockHash: string; + const boolArray = [true, false, false, true, false]; + const uint128Array = [100, 200, 300, 400, 500]; + const intArray = [10, 20, 30, 40, 50]; + const addressArray = generateDummyAddresses(9); + + const mapArray = addressArray.slice(0, 5) + .map((address, index) => { + const map = new Map(); + map.set(address, BigInt(index * 10)); + return map; + }); + + const fixedBytesArray = Array.from({ length: 4 }, () => ethers.utils.hexlify(ethers.utils.randomBytes(10))); + const enumArray = [0, 1, 2, 3]; + const stringArray = ['abc', 'defgh', 'ij', 'k']; + + const bytesArray = Array.from({ length: 4 }, () => { + const bytesLength = Math.floor(Math.random() * 64); + return ethers.utils.hexlify(ethers.utils.randomBytes(bytesLength)); + }); before(async () => { - const TestFixedArrays = await ethers.getContractFactory('TestDynamicArrays'); - testDynamicArrays = await TestFixedArrays.deploy(); - await testDynamicArrays.deployed(); - storageLayout = await getStorageLayout('TestDynamicArrays'); + ({ contract: testDynamicArrays, storageLayout } = contracts.TestDynamicArrays); + + const transactions = await Promise.all([ + testDynamicArrays.setBoolArray(boolArray), + testDynamicArrays.setUintArray(uint128Array), + testDynamicArrays.setIntArray(intArray), + testDynamicArrays.setAddressArray(addressArray), + testDynamicArrays.setFixedBytesArray(fixedBytesArray), + testDynamicArrays.setEnumArray(enumArray), + testDynamicArrays.setBytesArray(bytesArray), + testDynamicArrays.setStringArray(stringArray) + ]); + + for (const map of mapArray) { + const [key, value] = map.entries().next().value; + transactions.push(await testDynamicArrays.addMapArrayElement(key, value)); + } + + await Promise.all(transactions.map(transaction => transaction.wait())); + blockHash = await getBlockHash(); }); // Get all elements of array. it('get value for dynamic sized array of boolean type', async () => { - const boolArray = [true, false, false, true, false]; - 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); const proofData = JSON.parse(proof.data); @@ -603,10 +599,6 @@ describe('Get value from storage', () => { }); it('get value for dynamic sized array of unsigned integer type', async () => { - const uint128Array = [100, 200, 300, 400, 500]; - 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))); const proofData = JSON.parse(proof.data); @@ -619,10 +611,6 @@ describe('Get value from storage', () => { }); it('get value for dynamic sized array of signed integer type', async () => { - const intArray = [10, 20, 30, 40, 50]; - 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))); const proofData = JSON.parse(proof.data); @@ -635,10 +623,6 @@ describe('Get value from storage', () => { }); it('get value for dynamic sized array of address type', async () => { - 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); const proofData = JSON.parse(proof.data); @@ -651,10 +635,6 @@ 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))); - 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); const proofData = JSON.parse(proof.data); @@ -667,10 +647,6 @@ describe('Get value from storage', () => { }); it('get value for dynamic sized array of enum type', async () => { - const enumArray = [0, 1, 2, 3]; - 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))); const proofData = JSON.parse(proof.data); @@ -683,14 +659,6 @@ describe('Get value from storage', () => { }); it('get value for dynamic sized array of bytes', async () => { - const bytesArray = Array.from({ length: 4 }, () => { - const bytesLength = Math.floor(Math.random() * 64); - return ethers.utils.hexlify(ethers.utils.randomBytes(bytesLength)); - }); - - 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); const proofData = JSON.parse(proof.data); @@ -703,11 +671,6 @@ describe('Get value from storage', () => { }); it('get value for dynamic sized array of string type', async () => { - const stringArray = ['abc', 'defgh', 'ij', 'k']; - - 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); const proofData = JSON.parse(proof.data); @@ -762,23 +725,10 @@ describe('Get value from storage', () => { }); it('get value for dynamic sized array of mapping type', async () => { - const addresses = generateDummyAddresses(5); - const mapArray = []; - const transactions = []; - - for (const [index, address] of addresses.entries()) { - const map = new Map(); - map.set(address, BigInt(index * 10)); - mapArray.push(map); - transactions.push(await testDynamicArrays.addMapArrayElement(address, map.get(address))); - } - - await Promise.all(transactions.map(transaction => transaction.wait())); - const blockHash = await getBlockHash(); const arrayIndex = 2; - const mapKey = addresses[2]; + const [mapKey, expectedValue] = mapArray[arrayIndex].entries().next().value; const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testDynamicArrays.address, 'mapArray', arrayIndex, mapKey); - expect(value).to.equal(mapArray[arrayIndex].get(mapKey)); + expect(value).to.equal(expectedValue); }); }); @@ -800,10 +750,7 @@ describe('Get value from storage', () => { ]; before(async () => { - const TestNestedArrays = await ethers.getContractFactory('TestNestedArrays'); - testNestedArrays = await TestNestedArrays.deploy(); - await testNestedArrays.deployed(); - storageLayout = await getStorageLayout('TestNestedArrays'); + ({ contract: testNestedArrays, storageLayout } = contracts.TestNestedArrays); const transactions = []; const addresses = generateDummyAddresses(7); @@ -927,7 +874,7 @@ describe('Get value from storage', () => { }); describe('structs with value type members', () => { - let testValueStructs: Contract, storageLayout: StorageLayout; + let testValueStructs: Contract, storageLayout: StorageLayout, blockHash: string; let addressStruct: { [key: string]: any }, contractStruct: { [key: string]: any }; const singleSlotStruct = { @@ -954,10 +901,7 @@ describe('Get value from storage', () => { }; before(async () => { - const TestValueStructs = await ethers.getContractFactory('TestValueStructs'); - testValueStructs = await TestValueStructs.deploy(); - await testValueStructs.deployed(); - storageLayout = await getStorageLayout('TestValueStructs'); + ({ contract: testValueStructs, storageLayout } = contracts.TestValueStructs); const [address1, address2] = generateDummyAddresses(2); @@ -968,21 +912,29 @@ describe('Get value from storage', () => { uint1: BigInt(456) }; - const Contract = await ethers.getContractFactory('TestContractTypes'); - const contract = await Contract.deploy(); - await contract.deployed(); + const { contract } = contracts.TestContractTypes; contractStruct = { uint1: BigInt(123), testContract: contract.address.toLowerCase() }; + + const transactions = await Promise.all([ + testValueStructs.setSingleSlotStruct(singleSlotStruct.int1, singleSlotStruct.uint1), + testValueStructs.setMultipleSlotStruct(multipleSlotStruct.uint1, multipleSlotStruct.bool1, multipleSlotStruct.int1), + testValueStructs.setAddressStruct(addressStruct), + testValueStructs.setContractStruct(contractStruct.uint1, contractStruct.testContract), + testValueStructs.setFixedBytesStruct(fixedBytesStruct.uint1, fixedBytesStruct.bytesTen, fixedBytesStruct.bytesTwenty), + testValueStructs.setEnumStruct(enumStruct.uint1, enumStruct.choice1, enumStruct.choice2), + testValueStructs.setSingleSlotStruct(singleSlotStruct.int1, singleSlotStruct.uint1) + ]); + + await Promise.all(transactions.map(transaction => transaction.wait())); + blockHash = await getBlockHash(); }); // Get all members of a struct. it('get value for struct using a single slot', async () => { - 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); const proofData = JSON.parse(proof.data); @@ -990,9 +942,6 @@ describe('Get value from storage', () => { }); it('get value for struct using multiple slots', async () => { - 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); const proofData = JSON.parse(proof.data); @@ -1000,9 +949,6 @@ describe('Get value from storage', () => { }); it('get value for struct with address type members', async () => { - 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); const proofData = JSON.parse(proof.data); @@ -1010,9 +956,6 @@ describe('Get value from storage', () => { }); it('get value for struct with contract type members', async () => { - 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); const proofData = JSON.parse(proof.data); @@ -1020,9 +963,6 @@ describe('Get value from storage', () => { }); it('get value for struct with fixed-sized byte array members', async () => { - 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); const proofData = JSON.parse(proof.data); @@ -1030,9 +970,6 @@ describe('Get value from storage', () => { }); it('get value for struct with enum type members', async () => { - 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); const proofData = JSON.parse(proof.data); @@ -1042,25 +979,17 @@ 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'; - 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]); }); it('get value of unsigned integer type member in a struct', async () => { const member = 'uint1'; - const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'singleSlotStruct', member); expect(value).to.equal(singleSlotStruct[member]); }); it('get value of boolean type member in a struct', async () => { - const transaction = await testValueStructs.setMultipleSlotStruct(multipleSlotStruct.uint1, multipleSlotStruct.bool1, multipleSlotStruct.int1); - await transaction.wait(); - const blockHash = await getBlockHash(); - let member = 'bool1'; let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'multipleSlotStruct', member); expect(value).to.equal(multipleSlotStruct[member]); @@ -1075,9 +1004,6 @@ describe('Get value from storage', () => { }); it('get value of address type member in a struct', async () => { - 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); expect(value).to.equal(addressStruct[member]); @@ -1089,118 +1015,120 @@ describe('Get value from storage', () => { it('get value of contract type member in a struct', async () => { const member = '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]); }); it('get value of fixed byte array member in a struct', async () => { const member = 'bytesTen'; - 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]); }); it('get value of enum type member in a struct', async () => { const member = '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]); }); }); describe('structs with reference type members', () => { - let testReferenceStructs: Contract, storageLayout: StorageLayout; + let testReferenceStructs: Contract, storageLayout: StorageLayout, blockHash: string; + const addresses = generateDummyAddresses(5); - let fixedArrayStruct: {[key: string]: any}, - bytesStruct: {[key: string]: any}, - stringStruct: {[key: string]: any}, - nestedStruct: {[key: string]: any}, - dynamicArrayStruct: {[key: string]: any}; + const fixedArrayStruct = { + int1: BigInt(123), + uintArray: [1, 2, 3, 4].map(el => BigInt(el)), + addressArray: addresses.slice(0, 3) + }; + + const bytesStruct = { + byteArray: ethers.utils.hexlify(ethers.utils.randomBytes(40)), + address1: addresses[1], + uint1: BigInt(1234) + }; + + const stringStruct = { + string1: 'string1', + int1: BigInt(123), + uint1: BigInt(456), + string2: 'string2', + address1: addresses[2], + bool1: false + }; + + const nestedStruct: {[key: string]: any} = { + bytesStruct, + address1: addresses[3] + }; + + const dynamicArrayStruct = { + address1: addresses[4], + uintArray: [1, 2, 3, 4, 5].map(BigInt) + }; + + const valueMappingStruct: { [key: string]: any } = { + uintAddressMap: new Map(), + uint1: 123, + addressIntMap: new Map() + }; + + const referenceMappingStruct: { [key: string]: any } = { + bytesAddressMap: new Map(), + stringUintMap: new Map() + }; before(async () => { - const TestReferenceStructs = await ethers.getContractFactory('TestReferenceStructs'); - testReferenceStructs = await TestReferenceStructs.deploy(); - await testReferenceStructs.deployed(); - storageLayout = await getStorageLayout('TestReferenceStructs'); + ({ contract: testReferenceStructs, storageLayout } = contracts.TestReferenceStructs); - const addresses = generateDummyAddresses(5); + // Set map values for valueMappingStruct. + const addressKey = addresses[2]; + const mappingKey = 456; + valueMappingStruct.uintAddressMap.set(mappingKey, addresses[3]); + valueMappingStruct.addressIntMap.set(addressKey, 789); - fixedArrayStruct = { - int1: BigInt(123), - uintArray: [1, 2, 3, 4].map(el => BigInt(el)), - addressArray: addresses.slice(0, 3) - }; + // Set map values for referenceMappingStruct. + const bytesKey = ethers.utils.hexlify(ethers.utils.randomBytes(40)); + const stringKey = 'abc'; + referenceMappingStruct.bytesAddressMap.set(bytesKey, addresses[1]); + referenceMappingStruct.stringUintMap.set(stringKey, BigInt(123)); - bytesStruct = { - byteArray: ethers.utils.hexlify(ethers.utils.randomBytes(40)), - address1: addresses[1], - uint1: BigInt(1234) - }; + const transactions = await Promise.all([ + testReferenceStructs.setFixedArrayStruct(fixedArrayStruct.int1, fixedArrayStruct.uintArray, fixedArrayStruct.addressArray), + testReferenceStructs.setBytesStruct(bytesStruct), + testReferenceStructs.setStringStruct(stringStruct), + testReferenceStructs.setDynamicArrayStruct(dynamicArrayStruct), + testReferenceStructs.setNestedStruct(nestedStruct), + testReferenceStructs.setValueMappingStruct(mappingKey, valueMappingStruct.uintAddressMap.get(mappingKey), valueMappingStruct.uint1, addressKey, valueMappingStruct.addressIntMap.get(addressKey)), + testReferenceStructs.setReferenceMappingStruct(bytesKey, referenceMappingStruct.bytesAddressMap.get(bytesKey), stringKey, referenceMappingStruct.stringUintMap.get(stringKey)) + ]); - stringStruct = { - string1: 'string1', - int1: BigInt(123), - uint1: BigInt(456), - string2: 'string2', - address1: addresses[2], - bool1: false - }; - - nestedStruct = { - bytesStruct, - address1: addresses[3] - }; - - dynamicArrayStruct = { - address1: addresses[4], - uintArray: [1, 2, 3, 4, 5].map(BigInt) - }; + await Promise.all(transactions.map(transaction => transaction.wait())); + blockHash = await getBlockHash(); }); // Get all members of a struct. it('get value for struct with fixed-size array members', async () => { - 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 () => { - 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 () => { - 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 () => { - 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 () => { - 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); }); @@ -1208,82 +1136,45 @@ 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'; - 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]); }); it('get value of bytes member in a struct', async () => { const member = 'byteArray'; - 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]); }); it('get value of string member in a struct', async () => { const member = 'string2'; - 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]); }); it('get value of dynamic array member in a struct', async () => { const member = 'uintArray'; - const blockHash = await getBlockHash(); const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'dynamicArrayStruct', member); expect(value).to.eql(dynamicArrayStruct[member]); }); it('get value of mapping type member in a struct', async () => { - const [signer1] = await ethers.getSigners(); - const [address2] = generateDummyAddresses(1); - - const valueMappingStruct: { [key: string]: any } = { - uintAddressMap: new Map(), - uint1: 123, - addressIntMap: new Map() - }; - - const mappingKey = 456; - valueMappingStruct.uintAddressMap.set(mappingKey, signer1.address.toLowerCase()); - valueMappingStruct.addressIntMap.set(address2, 789); + // Get value for structs with mapping of value type keys. let member = 'uintAddressMap'; + let [mappingKey, expectedValue] = valueMappingStruct[member].entries().next().value; - 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)); + expect(value).to.equal(expectedValue); // Get value for structs with mapping of reference type keys. - const referenceMappingStruct: { [key: string]: any } = { - bytesAddressMap: new Map(), - stringUintMap: new Map() - }; - - const bytesKey = ethers.utils.hexlify(ethers.utils.randomBytes(40)); - const stringKey = 'abc'; - referenceMappingStruct.bytesAddressMap.set(bytesKey, signer1.address.toLowerCase()); - referenceMappingStruct.stringUintMap.set(stringKey, BigInt(123)); member = 'stringUintMap'; + [mappingKey, expectedValue] = referenceMappingStruct[member].entries().next().value; - 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)); + ({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'referenceMappingStruct', member, mappingKey)); + expect(value).to.equal(expectedValue); }); it('get value of nested struct member', async () => { - 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); expect(value).to.eql(nestedStruct[member]); @@ -1300,52 +1191,90 @@ describe('Get value from storage', () => { }); describe('basic mapping type', () => { - let testMappingTypes: Contract, storageLayout: StorageLayout; + let testMappingTypes: Contract, storageLayout: StorageLayout, blockHash: string; + const addressArray = generateDummyAddresses(3); + const [address1, address2] = addressArray; + const addressUintMap = new Map(); + const boolIntMap = new Map([[true, 123]]); + const intAddressMap = new Map([[123, address1]]); + const uintBytesMap = new Map([[123, ethers.utils.hexlify(ethers.utils.randomBytes(16))]]); + const enumIntMap = new Map([[1, 123]]); + const stringIntMap = new Map([['abc', 123]]); + + const bytesAddressMap = new Map(); + const bytesAddressMapKey = ethers.utils.hexlify(ethers.utils.randomBytes(8)); + bytesAddressMap.set(bytesAddressMapKey, address1); + + const bytesUintMap = new Map(); + const bytesUintMapKey = ethers.utils.hexlify(ethers.utils.randomBytes(64)); + bytesUintMap.set(bytesUintMapKey, 123); + + const structMapValue: {[key: string]: any} = { + uint1: BigInt(123), + int1: BigInt(456), + bool1: true, + address1: address2 + }; + + const intStructMap = new Map([[123, structMapValue]]); + const fixedBytesStructKey = ethers.utils.hexlify(ethers.utils.randomBytes(32)); + const addressStructMapKey = address1; + const uintFixedArrayMap = new Map([[123, addressArray]]); + const intDynamicArrayMap = new Map([[123, [1, 2, 3, 4, 5, 6, 7, 8]]]); + const addressBytesMap = new Map([[address1, ethers.utils.hexlify(ethers.utils.randomBytes(42))]]); + + const bytesStringMapKey = ethers.utils.hexlify(ethers.utils.randomBytes(32)); + const bytesStringMap = new Map([[bytesStringMapKey, 'Hello World.']]); before(async () => { - const TestMappingTypes = await ethers.getContractFactory('TestBasicMapping'); - testMappingTypes = await TestMappingTypes.deploy(); - await testMappingTypes.deployed(); - storageLayout = await getStorageLayout('TestBasicMapping'); + const [signer1] = await ethers.getSigners(); + ({ contract: testMappingTypes, storageLayout } = contracts.TestBasicMapping); + + addressUintMap.set(signer1.address, 123); + + const transactions = await Promise.all([ + testMappingTypes.connect(signer1).setAddressUintMap(addressUintMap.get(signer1.address)), + testMappingTypes.setBoolIntMap(true, boolIntMap.get(true)), + testMappingTypes.setIntAddressMap(123, intAddressMap.get(123)), + testMappingTypes.setUintBytesMap(123, uintBytesMap.get(123)), + testMappingTypes.setBytesAddressMap(bytesAddressMapKey, bytesAddressMap.get(bytesAddressMapKey)), + testMappingTypes.setEnumIntMap(1, enumIntMap.get(1)), + testMappingTypes.setStringIntMap('abc', stringIntMap.get('abc')), + testMappingTypes.setBytesUintMap(bytesUintMapKey, bytesUintMap.get(bytesUintMapKey)), + testMappingTypes.setIntStructMap(123, structMapValue), + testMappingTypes.setFixedBytesStructMap(fixedBytesStructKey, structMapValue), + testMappingTypes.setAddressStructMap(addressStructMapKey, structMapValue), + testMappingTypes.setUintFixedArrayMap(123, uintFixedArrayMap.get(123)), + testMappingTypes.setIntDynamicArrayMap(123, intDynamicArrayMap.get(123)), + testMappingTypes.setAddressBytesMap(address1, addressBytesMap.get(address1)), + testMappingTypes.setBytesStringMap(bytesStringMapKey, bytesStringMap.get(bytesStringMapKey)) + ]); + + await Promise.all(transactions.map(transaction => transaction.wait())); + blockHash = await getBlockHash(); }); // Tests for value type keys. it('get value for mapping with address type keys', async () => { - const expectedValue = 123; - 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); + const [mapKey, expectedValue] = addressUintMap.entries().next().value; + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'addressUintMap', mapKey); expect(value).to.equal(BigInt(expectedValue)); }); it('get value for mapping with boolean type keys', async () => { - const expectedValue = 123; - const mapKey = true; - const transaction = await testMappingTypes.setBoolIntMap(mapKey, expectedValue); - await transaction.wait(); - const blockHash = await getBlockHash(); + const [mapKey, expectedValue] = boolIntMap.entries().next().value; const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'boolIntMap', mapKey); expect(value).to.equal(BigInt(expectedValue)); }); it('get value for mapping with signed integer type keys', async () => { - const mapKey = 123; - const [address1] = generateDummyAddresses(1); - const transaction = await testMappingTypes.setIntAddressMap(mapKey, address1); - await transaction.wait(); - const blockHash = await getBlockHash(); + const [mapKey, expectedValue] = intAddressMap.entries().next().value; const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'intAddressMap', mapKey); - expect(value).to.equal(address1); + expect(value).to.equal(expectedValue); }); it('get value for mapping with unsigned integer type keys', async () => { - const expectedValue = ethers.utils.hexlify(ethers.utils.randomBytes(16)); - const mapKey = 123; - const transaction = await testMappingTypes.setUintBytesMap(mapKey, expectedValue); - await transaction.wait(); - const blockHash = await getBlockHash(); + const [mapKey, expectedValue] = uintBytesMap.entries().next().value; const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'uintBytesMap', mapKey); expect(value).to.equal(expectedValue); }); @@ -1354,121 +1283,61 @@ describe('Get value from storage', () => { // Zero value is returned if using fixed-sized byte array keys of length less than 32 bytes // Type Bytes32 works whereas types like bytes16, bytes24 do not work. 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(); - 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); + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'bytesAddressMap', bytesAddressMapKey); + expect(value).to.equal(bytesAddressMap.get(bytesAddressMapKey)); }); it('get value for mapping with enum type keys', async () => { - const mapKey = 1; - const expectedValue = 123; - const transaction = await testMappingTypes.setEnumIntMap(mapKey, expectedValue); - await transaction.wait(); - const blockHash = await getBlockHash(); + const [mapKey, expectedValue] = enumIntMap.entries().next().value; const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'enumIntMap', mapKey); expect(value).to.equal(BigInt(expectedValue)); }); // Tests for reference type keys. it('get value for mapping with string type keys', async () => { - const mapKey = 'abc'; - const expectedValue = 123; - const transaction = await testMappingTypes.setStringIntMap(mapKey, expectedValue); - await transaction.wait(); - const blockHash = await getBlockHash(); + const [mapKey, expectedValue] = stringIntMap.entries().next().value; const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'stringIntMap', mapKey); expect(value).to.equal(BigInt(expectedValue)); }); 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; - 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)); + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'bytesUintMap', bytesUintMapKey); + expect(value).to.equal(BigInt(bytesUintMap.get(bytesUintMapKey))); }); // Tests for reference type values. it('get value for mapping with struct type values', async () => { - const [signer1] = await ethers.getSigners(); - - const expectedValue: {[key: string]: any} = { - uint1: BigInt(123), - int1: BigInt(456), - bool1: true, - address1: signer1.address.toLowerCase() - }; - - const mapKey = 123; - const transaction = await testMappingTypes.setIntStructMap(mapKey, expectedValue); - await transaction.wait(); - const blockHash = await getBlockHash(); + const mapKey = intStructMap.keys().next().value; let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'intStructMap', mapKey); - expect(value).to.eql(expectedValue); + expect(value).to.eql(structMapValue); // Get value of specified struct member in mapping. let structMember = 'bool1'; ({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'intStructMap', mapKey, structMember)); - expect(value).to.equal(expectedValue[structMember]); + expect(value).to.equal(structMapValue[structMember]); structMember = 'address1'; ({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'intStructMap', mapKey, structMember)); - expect(value).to.equal(expectedValue[structMember]); + expect(value).to.equal(structMapValue[structMember]); }); it('get value for mapping of fixed size bytes keys and struct type values', async () => { - const [signer1] = await ethers.getSigners(); - - const expectedValue = { - uint1: BigInt(123), - int1: BigInt(456), - bool1: true, - address1: signer1.address.toLowerCase() - }; - - const mapKey = ethers.utils.hexlify(ethers.utils.randomBytes(32)); - 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); + let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'fixedBytesStructMap', fixedBytesStructKey); + expect(value).to.eql(structMapValue); // Get value of specified struct member in mapping. const structMember = 'int1'; - ({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'fixedBytesStructMap', mapKey, structMember)); - expect(value).to.equal(expectedValue[structMember]); + ({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'fixedBytesStructMap', fixedBytesStructKey, structMember)); + expect(value).to.equal(structMapValue[structMember]); }); it('get value for mapping of address type keys and struct type values', async () => { - const [address1, address2] = generateDummyAddresses(2); - - const expectedValue = { - uint1: BigInt(123), - int1: BigInt(456), - bool1: true, - address1: address1 - }; - - 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); + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'addressStructMap', addressStructMapKey); + expect(value).to.eql(structMapValue); }); it('get value for mapping of unsigned integer keys and fixed-size array values', async () => { - const mapKey = 123; - const expectedValue = generateDummyAddresses(3); - const transaction = await testMappingTypes.setUintFixedArrayMap(mapKey, expectedValue); - await transaction.wait(); - const blockHash = await getBlockHash(); + const [mapKey, expectedValue] = uintFixedArrayMap.entries().next().value; const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'uintFixedArrayMap', mapKey); expect(value).to.eql(expectedValue); const proofData = JSON.parse(proof.data); @@ -1476,12 +1345,7 @@ describe('Get value from storage', () => { }); it('get value for mapping of signed integer keys and dynamically-sized array values', async () => { - const mapKey = 123; - const expectedValue = [1, 2, 3, 4, 5, 6, 7, 8]; - - const transaction = await testMappingTypes.setIntDynamicArrayMap(mapKey, expectedValue); - await transaction.wait(); - const blockHash = await getBlockHash(); + const [mapKey, expectedValue] = intDynamicArrayMap.entries().next().value; const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'intDynamicArrayMap', mapKey); expect(value).to.eql(expectedValue.map(BigInt)); const proofData = JSON.parse(proof.data); @@ -1489,101 +1353,100 @@ describe('Get value from storage', () => { }); it('get value for mapping of address keys and dynamic byte array values', async () => { - const [signer1] = await ethers.getSigners(); - const expectedValue = ethers.utils.hexlify(ethers.utils.randomBytes(42)); - - 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); + const [mapKey, expectedValue] = addressBytesMap.entries().next().value; + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'addressBytesMap', mapKey); expect(value).to.eql(expectedValue); }); it('get value for mapping of fixed size byte array keys and string type values', async () => { - const mapKey = ethers.utils.hexlify(ethers.utils.randomBytes(32)); - const expectedValue = 'Hello world.'; - - 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); + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'bytesStringMap', bytesStringMapKey); + expect(value).to.eql(bytesStringMap.get(bytesStringMapKey)); }); }); describe('nested mapping type', () => { - let testNestedMapping: Contract, storageLayout: StorageLayout; + let testNestedMapping: Contract, storageLayout: StorageLayout, blockHash: string; + const [address1, address2, address3] = generateDummyAddresses(3); + const nestedAddressUintMap = new Map(); + + const intAddressBoolMap = new Map([[123, new Map()]]); + intAddressBoolMap.get(123)?.set(address1, false); + + const uintStringIntMap = new Map([[456, new Map()]]); + uintStringIntMap.get(456)?.set('abc', 123); + + const bytesIntAddressMapKey = ethers.utils.hexlify(ethers.utils.randomBytes(64)); + const bytesIntAddressMap = new Map([[bytesIntAddressMapKey, new Map()]]); + bytesIntAddressMap.get(bytesIntAddressMapKey)?.set(123, address1); + + const stringAddressIntMap = new Map([['abc', new Map()]]); + stringAddressIntMap.get('abc')?.set(address1, 123); + + const doubleNestedAddressMap = new Map([[address1, new Map()]]); + doubleNestedAddressMap.get(address1)?.set(address2, new Map()); + doubleNestedAddressMap.get(address1)?.get(address2)?.set(123, address3); before(async () => { - const TestNestedMapping = await ethers.getContractFactory('TestNestedMapping'); - testNestedMapping = await TestNestedMapping.deploy(); - await testNestedMapping.deployed(); - storageLayout = await getStorageLayout('TestNestedMapping'); + const [signer1] = await ethers.getSigners(); + ({ contract: testNestedMapping, storageLayout } = contracts.TestNestedMapping); + + nestedAddressUintMap.set(signer1.address, new Map()); + nestedAddressUintMap.get(signer1.address).set(address1, 123); + + const transactions = await Promise.all([ + testNestedMapping.connect(signer1).setNestedAddressUintMap(address1, nestedAddressUintMap.get(signer1.address).get(address1)), + testNestedMapping.setIntAddressBoolMap(123, address1, intAddressBoolMap.get(123)?.get(address1)), + testNestedMapping.setUintStringIntMap(456, 'abc', uintStringIntMap.get(456)?.get('abc')), + testNestedMapping.setBytesIntAddressMap(bytesIntAddressMapKey, 123, bytesIntAddressMap.get(bytesIntAddressMapKey)?.get(123)), + testNestedMapping.setStringAddressIntMap('abc', address1, stringAddressIntMap.get('abc')?.get(address1)), + testNestedMapping.setDoubleNestedAddressMap(address1, address2, 123, doubleNestedAddressMap.get(address1)?.get(address2)?.get(123)) + ]); + + await Promise.all(transactions.map(transaction => transaction.wait())); + blockHash = await getBlockHash(); }); it('get value for nested mapping with address type keys', async () => { - const expectedValue = 123; - 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, address2); + const [mapKey, nestedMap] = nestedAddressUintMap.entries().next().value; + const [nestedKey, expectedValue] = nestedMap.entries().next().value; + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedMapping.address, 'nestedAddressUintMap', mapKey, nestedKey); 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 [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, address1); + const [mapKey, nestedMap] = intAddressBoolMap.entries().next().value; + const [nestedKey, expectedValue] = nestedMap.entries().next().value; + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedMapping.address, 'intAddressBoolMap', mapKey, nestedKey); expect(value).to.equal(expectedValue); }); it('get value for nested mapping with unsigned integer type keys', async () => { - const expectedValue = 123; - const key = 456; - const nestedKey = 'abc'; - 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); + const [mapKey, nestedMap] = uintStringIntMap.entries().next().value; + const [nestedKey, expectedValue] = nestedMap.entries().next().value; + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedMapping.address, 'uintStringIntMap', mapKey, nestedKey); expect(value).to.equal(BigInt(expectedValue)); }); 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 [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(address1); + const [mapKey, nestedMap] = bytesIntAddressMap.entries().next().value; + const [nestedKey, expectedValue] = nestedMap.entries().next().value; + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedMapping.address, 'bytesIntAddressMap', mapKey, nestedKey); + expect(value).to.equal(expectedValue); }); it('get value for nested mapping with string type keys', async () => { - const key = 'abc'; - const expectedValue = 123; - 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, address1); + const [mapKey, nestedMap] = stringAddressIntMap.entries().next().value; + const [nestedKey, expectedValue] = nestedMap.entries().next().value; + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedMapping.address, 'stringAddressIntMap', mapKey, nestedKey); expect(value).to.equal(BigInt(expectedValue)); }); it('get value for double nested mapping with address type keys', async () => { - const [address1, address2, address3] = generateDummyAddresses(3); - const uintKey = 123; - 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', address1, address2, uintKey); - expect(value).to.equal(address3); + const [mapKey, nestedMap] = doubleNestedAddressMap.entries().next().value; + const [nestedKey, doubleNestedMap] = nestedMap.entries().next().value; + const [doubleNestedKey, expectedValue] = doubleNestedMap.entries().next().value; + const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedMapping.address, 'doubleNestedAddressMap', mapKey, nestedKey, doubleNestedKey); + expect(value).to.equal(expectedValue); }); }); });