mirror of
https://github.com/cerc-io/watcher-ts
synced 2024-11-19 20:36:19 +00:00
Get value for nested array, mapping with address keys and struct value (#64)
* Add test for mapping with address keys and struct value. * Implement getting value for nested array. Co-authored-by: nikugogoi <95nikass@gmail.com>
This commit is contained in:
parent
3815853f7b
commit
3439dd4041
@ -49,7 +49,7 @@ $ yarn test
|
||||
* [ ] Struct Type
|
||||
* [ ] Mapping Type
|
||||
* [ ] Nested Arrays
|
||||
* [ ] Fixed size arrays
|
||||
* [x] Fixed size arrays
|
||||
* [ ] Dynamically-sized arrays
|
||||
* [ ] Dynamically-sized byte array
|
||||
* [ ] Bytes
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { Contract } from '@ethersproject/contracts';
|
||||
import { expect } from 'chai';
|
||||
import { ethers } from 'hardhat';
|
||||
@ -416,9 +417,63 @@ describe('Get value from storage', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('nested arrays', () => {
|
||||
let testNestedArrays: Contract, storageLayout: StorageLayout;
|
||||
const nestedStructArray: Array<Array<{[key: string]: any}>> = [];
|
||||
|
||||
before(async () => {
|
||||
const TestNestedArrays = await ethers.getContractFactory('TestNestedArrays');
|
||||
testNestedArrays = await TestNestedArrays.deploy();
|
||||
await testNestedArrays.deployed();
|
||||
storageLayout = await getStorageLayout('TestNestedArrays');
|
||||
|
||||
const signers = await ethers.getSigners();
|
||||
|
||||
// Set value for nestedStructArray.
|
||||
for (let i = 0; i < 5; i++) {
|
||||
nestedStructArray[i] = [];
|
||||
|
||||
for (let j = 0; j < 3; j++) {
|
||||
const value = {
|
||||
uint1: BigInt((i + j) * 100),
|
||||
address1: signers[(i + j) % 5].address.toLowerCase()
|
||||
};
|
||||
|
||||
nestedStructArray[i][j] = value;
|
||||
|
||||
// Set value in contract.
|
||||
await testNestedArrays.setNestedStructArray(i, j, value);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 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);
|
||||
expect(proofData.length).to.equal(nestedStructArray.length);
|
||||
expect(proofData[0].length).to.equal(nestedStructArray[0].length);
|
||||
expect(proofData[0]).to.have.all.keys(Object.keys(nestedStructArray[0]));
|
||||
});
|
||||
|
||||
// Get element of array by index.
|
||||
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]);
|
||||
|
||||
const structMember = 'address1';
|
||||
({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedArrays.address, 'nestedStructArray', arrayIndex, nestedArrayIndex, structMember));
|
||||
expect(value).to.equal(nestedStructArray[arrayIndex][nestedArrayIndex][structMember]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('structs with value type members', () => {
|
||||
let testValueStructs: Contract, storageLayout: StorageLayout;
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
let addressStruct: { [key: string]: any }, contractStruct: { [key: string]: any };
|
||||
|
||||
const singleSlotStruct = {
|
||||
@ -691,7 +746,7 @@ describe('Get value from storage', () => {
|
||||
expect(value).to.eql(stringStruct[member]);
|
||||
});
|
||||
|
||||
it.skip('get value of mapping type member in a struct', async () => {
|
||||
it('get value of mapping type member in a struct', async () => {
|
||||
const [signer1, signer2] = await ethers.getSigners();
|
||||
|
||||
const valueMappingStruct: { [key: string]: any } = {
|
||||
@ -710,6 +765,7 @@ describe('Get value from storage', () => {
|
||||
let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'valueMappingStruct', member, mappingKey);
|
||||
expect(value).to.equal(valueMappingStruct[member].get(mappingKey));
|
||||
|
||||
// Get value for structs with mapping of reference type keys.
|
||||
const referenceMappingStruct: { [key: string]: any } = {
|
||||
bytesAddressMap: new Map(),
|
||||
stringUintMap: new Map()
|
||||
@ -718,8 +774,8 @@ describe('Get value from storage', () => {
|
||||
const bytesKey = ethers.utils.hexlify(ethers.utils.randomBytes(40));
|
||||
const stringKey = 'abc';
|
||||
referenceMappingStruct.bytesAddressMap.set(bytesKey, signer1.address.toLowerCase());
|
||||
referenceMappingStruct.stringUintMap.set(stringKey, 123);
|
||||
member = 'stringAddressMap';
|
||||
referenceMappingStruct.stringUintMap.set(stringKey, BigInt(123));
|
||||
member = 'stringUintMap';
|
||||
|
||||
await testReferenceStructs.setReferenceMappingStruct(bytesKey, referenceMappingStruct.bytesAddressMap.get(bytesKey), stringKey, referenceMappingStruct.stringUintMap.get(stringKey));
|
||||
blockHash = await getBlockHash();
|
||||
@ -877,6 +933,23 @@ describe('Get value from storage', () => {
|
||||
({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'fixedBytesStructMap', mapKey, structMember));
|
||||
expect(value).to.equal(expectedValue[structMember]);
|
||||
});
|
||||
|
||||
it('get value for mapping of address type keys and struct type values', async () => {
|
||||
const [signer1, signer2] = await ethers.getSigners();
|
||||
|
||||
const expectedValue = {
|
||||
uint1: BigInt(123),
|
||||
int1: BigInt(456),
|
||||
bool1: true,
|
||||
address1: signer1.address.toLowerCase()
|
||||
};
|
||||
|
||||
const mapKey = signer2.address;
|
||||
await testMappingTypes.setAddressStructMap(mapKey, expectedValue);
|
||||
const blockHash = await getBlockHash();
|
||||
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'addressStructMap', mapKey);
|
||||
expect(value).to.eql(expectedValue);
|
||||
});
|
||||
});
|
||||
|
||||
describe('nested mapping type', () => {
|
||||
|
@ -105,11 +105,13 @@ const getDecodedValue = async (getStorageAt: GetStorageAt, blockHash: string, ad
|
||||
const { slot, offset, type } = storageInfo;
|
||||
const { encoding, numberOfBytes, label: typeLabel, base, value: mappingValueType, key: mappingKeyType, members } = types[type];
|
||||
|
||||
const [isArray, arraySize] = typeLabel.match(/\[([0-9]*)\]/) || [false];
|
||||
let value: string, proof: { data: string };
|
||||
const arrayMatch = [...typeLabel.matchAll(/\[([0-9]*)\]/g)];
|
||||
|
||||
// If variable is array type.
|
||||
if (isArray && base) {
|
||||
if (arrayMatch.length && base) {
|
||||
const arraySize = arrayMatch[arrayMatch.length - 1][1];
|
||||
|
||||
return getArrayValue(getStorageAt, blockHash, address, types, mappingKeys, slot, base, Number(arraySize));
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,9 @@ contract TestBasicMapping {
|
||||
// Mapping with signed integer as keys and struct type values.
|
||||
mapping(bytes32 => TestStruct) public fixedBytesStructMap;
|
||||
|
||||
// Mapping with address as keys and struct type values.
|
||||
mapping(address => TestStruct) public addressStructMap;
|
||||
|
||||
// Set variable addressUintMap.
|
||||
function setAddressUintMap(uint value) external {
|
||||
addressUintMap[msg.sender] = value;
|
||||
@ -93,4 +96,9 @@ contract TestBasicMapping {
|
||||
function setFixedBytesStructMap(bytes32 key, TestStruct calldata value) external {
|
||||
fixedBytesStructMap[key] = value;
|
||||
}
|
||||
|
||||
// Set variable fixedBytesStructMap.
|
||||
function setAddressStructMap(address key, TestStruct calldata value) external {
|
||||
addressStructMap[key] = value;
|
||||
}
|
||||
}
|
||||
|
17
packages/solidity-mapper/test/contracts/TestNestedArrays.sol
Normal file
17
packages/solidity-mapper/test/contracts/TestNestedArrays.sol
Normal file
@ -0,0 +1,17 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
contract TestNestedArrays {
|
||||
struct TestStruct {
|
||||
uint256 uint1;
|
||||
address address1;
|
||||
}
|
||||
|
||||
TestStruct[3][5] nestedStructArray;
|
||||
|
||||
// Set variable nestedStructArray.
|
||||
function setNestedStructArray(uint index, uint nestedIndex, TestStruct calldata value) external {
|
||||
nestedStructArray[index][nestedIndex] = value;
|
||||
}
|
||||
}
|
@ -6,11 +6,11 @@
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
|
||||
// "lib": [], /* Specify library files to be included in the compilation. */
|
||||
"lib": [ "ES2020" ], /* Specify library files to be included in the compilation. */
|
||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
|
||||
"declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
"declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
@ -21,7 +21,7 @@
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
"downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
|
@ -6,7 +6,7 @@
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
|
||||
"lib": [ "ES5", "ES6" ], /* Specify library files to be included in the compilation. */
|
||||
"lib": [ "ES5", "ES6", "ES2020" ], /* Specify library files to be included in the compilation. */
|
||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
|
||||
@ -21,7 +21,7 @@
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
"downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
|
Loading…
Reference in New Issue
Block a user