mirror of
https://github.com/cerc-io/watcher-ts
synced 2025-01-08 12:28:05 +00:00
Tests for maps with struct type value and double nested maps (#58)
* Tests for fixed array of struct type. * Add tests for maps with struct type value and double nested maps. Co-authored-by: nikugogoi <95nikass@gmail.com>
This commit is contained in:
parent
f5c1a22fdc
commit
eb20708faf
@ -37,7 +37,7 @@ $ yarn test
|
||||
* [ ] Fixed-size byte arrays
|
||||
* [ ] Enum type
|
||||
* [ ] Dynamically-sized byte array
|
||||
* [ ] Struct Type
|
||||
* [x] Struct Type
|
||||
* [ ] Mapping Type
|
||||
* [ ] Dynamically-sized arrays
|
||||
* [ ] Integer Type
|
||||
@ -64,6 +64,9 @@ $ yarn test
|
||||
* [ ] Fixed-size byte array keys
|
||||
* [x] Dynamically-sized byte array keys
|
||||
* [ ] Reference Type Mapping values
|
||||
* [x] Struct type values
|
||||
* [ ] Array type values
|
||||
* [ ] Dynamically sized Bytes and string type values
|
||||
* [x] Nested Mapping
|
||||
|
||||
## Observations
|
||||
|
@ -16,7 +16,7 @@ task('accounts', 'Prints the list of accounts', async (args, hre) => {
|
||||
|
||||
const config: HardhatUserConfig = {
|
||||
solidity: {
|
||||
version: '0.7.3',
|
||||
version: '0.7.6',
|
||||
settings: {
|
||||
outputSelection: {
|
||||
'*': {
|
||||
|
@ -342,6 +342,27 @@ describe('Get value from storage', () => {
|
||||
expect(proofData.length).to.equal(expectedValue.length);
|
||||
});
|
||||
|
||||
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;
|
||||
await testFixedArrays.setStructArray(structElement, i);
|
||||
}
|
||||
|
||||
const blockHash = await getBlockHash();
|
||||
const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'structArray');
|
||||
expect(value).to.eql(expectedValue);
|
||||
const proofData = JSON.parse(proof.data);
|
||||
expect(proofData.length).to.equal(expectedValue.length);
|
||||
});
|
||||
|
||||
// Get element of array by index.
|
||||
it('get value of signed integer type array by index', async () => {
|
||||
const arrayIndex = 2;
|
||||
@ -374,6 +395,25 @@ describe('Get value from storage', () => {
|
||||
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'addressArray', arrayIndex);
|
||||
expect(value).to.equal(addressArray[arrayIndex]);
|
||||
});
|
||||
|
||||
it('get value of struct type array by index', async () => {
|
||||
const expectedValue = {
|
||||
int1: BigInt(123),
|
||||
uint1: BigInt(456),
|
||||
bool1: false
|
||||
};
|
||||
|
||||
const arrayIndex = 2;
|
||||
await testFixedArrays.setStructArray(expectedValue, arrayIndex);
|
||||
const blockHash = await getBlockHash();
|
||||
let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'structArray', arrayIndex);
|
||||
expect(value).to.eql(expectedValue);
|
||||
|
||||
// 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]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('structs with value type members', () => {
|
||||
@ -381,7 +421,12 @@ describe('Get value from storage', () => {
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
let addressStruct: { [key: string]: any }, contractStruct: { [key: string]: any };
|
||||
|
||||
const multipleSlotStruct = {
|
||||
const singleSlotStruct = {
|
||||
int1: BigInt(123),
|
||||
uint1: BigInt(4)
|
||||
};
|
||||
|
||||
const multipleSlotStruct: { [key: string]: any } = {
|
||||
uint1: BigInt(123),
|
||||
bool1: false,
|
||||
int1: BigInt(456)
|
||||
@ -426,15 +471,10 @@ describe('Get value from storage', () => {
|
||||
|
||||
// Get all members of a struct.
|
||||
it('get value for struct using a single slot', async () => {
|
||||
const expectedValue = {
|
||||
int1: BigInt(123),
|
||||
uint1: BigInt(4)
|
||||
};
|
||||
|
||||
await testValueStructs.setSingleSlotStruct(expectedValue.int1, expectedValue.uint1);
|
||||
await testValueStructs.setSingleSlotStruct(singleSlotStruct.int1, singleSlotStruct.uint1);
|
||||
const blockHash = await getBlockHash();
|
||||
const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'singleSlotStruct');
|
||||
expect(value).to.eql(expectedValue);
|
||||
expect(value).to.eql(singleSlotStruct);
|
||||
const proofData = JSON.parse(proof.data);
|
||||
expect(proofData).to.have.all.keys('int1', 'uint1');
|
||||
});
|
||||
@ -449,7 +489,7 @@ describe('Get value from storage', () => {
|
||||
});
|
||||
|
||||
it('get value for struct with address type members', async () => {
|
||||
await testValueStructs.setAddressStruct(addressStruct.int1, addressStruct.address1, addressStruct.address2, addressStruct.uint1);
|
||||
await testValueStructs.setAddressStruct(addressStruct);
|
||||
const blockHash = await getBlockHash();
|
||||
const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'addressStruct');
|
||||
expect(value).to.eql(addressStruct);
|
||||
@ -487,31 +527,45 @@ 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.setMultipleSlotStruct(multipleSlotStruct.uint1, multipleSlotStruct.bool1, multipleSlotStruct.int1);
|
||||
await testValueStructs.setSingleSlotStruct(singleSlotStruct.int1, singleSlotStruct.uint1);
|
||||
const blockHash = await getBlockHash();
|
||||
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'multipleSlotStruct', member);
|
||||
expect(value).to.equal(multipleSlotStruct[member]);
|
||||
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, 'multipleSlotStruct', member);
|
||||
expect(value).to.equal(multipleSlotStruct[member]);
|
||||
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 member = 'bool1';
|
||||
await testValueStructs.setMultipleSlotStruct(multipleSlotStruct.uint1, multipleSlotStruct.bool1, multipleSlotStruct.int1);
|
||||
const blockHash = await getBlockHash();
|
||||
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'multipleSlotStruct', member);
|
||||
|
||||
let member = 'bool1';
|
||||
let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'multipleSlotStruct', member);
|
||||
expect(value).to.equal(multipleSlotStruct[member]);
|
||||
|
||||
member = 'int1';
|
||||
({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'multipleSlotStruct', member));
|
||||
expect(value).to.equal(multipleSlotStruct[member]);
|
||||
|
||||
member = 'uint1';
|
||||
({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'multipleSlotStruct', member));
|
||||
expect(value).to.equal(multipleSlotStruct[member]);
|
||||
});
|
||||
|
||||
it('get value of address type member in a struct', async () => {
|
||||
const member = 'address1';
|
||||
await testValueStructs.setAddressStruct(addressStruct.int1, addressStruct.address1, addressStruct.address2, addressStruct.uint1);
|
||||
await testValueStructs.setAddressStruct(addressStruct);
|
||||
const blockHash = await getBlockHash();
|
||||
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'addressStruct', member);
|
||||
let member = 'address1';
|
||||
let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'addressStruct', member);
|
||||
expect(value).to.equal(addressStruct[member]);
|
||||
|
||||
member = 'uint1';
|
||||
({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'addressStruct', member));
|
||||
expect(value).to.equal(addressStruct[member]);
|
||||
});
|
||||
|
||||
@ -644,6 +698,7 @@ describe('Get value from storage', () => {
|
||||
storageLayout = await getStorageLayout('TestBasicMapping');
|
||||
});
|
||||
|
||||
// Tests for value type keys.
|
||||
it('get value for mapping with address type keys', async () => {
|
||||
const expectedValue = 123;
|
||||
const [, signer1] = await ethers.getSigners();
|
||||
@ -698,6 +753,7 @@ describe('Get value from storage', () => {
|
||||
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;
|
||||
@ -715,6 +771,45 @@ describe('Get value from storage', () => {
|
||||
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'bytesUintMap', mapKey);
|
||||
expect(value).to.equal(BigInt(expectedValue));
|
||||
});
|
||||
|
||||
// Tests for reference type values.
|
||||
it('get value for mapping with struct type values', async () => {
|
||||
const expectedValue = {
|
||||
uint1: BigInt(123),
|
||||
int1: BigInt(456),
|
||||
bool1: true
|
||||
};
|
||||
|
||||
const mapKey = 123;
|
||||
await testMappingTypes.setIntStructMap(mapKey, expectedValue);
|
||||
const blockHash = await getBlockHash();
|
||||
let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'intStructMap', mapKey);
|
||||
expect(value).to.eql(expectedValue);
|
||||
|
||||
// Get value of specified struct member in mapping.
|
||||
const structMember = 'bool1';
|
||||
({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'intStructMap', mapKey, structMember));
|
||||
expect(value).to.equal(expectedValue[structMember]);
|
||||
});
|
||||
|
||||
it('get value for mapping of fixed size bytes keys and struct type values', async () => {
|
||||
const expectedValue = {
|
||||
uint1: BigInt(123),
|
||||
int1: BigInt(456),
|
||||
bool1: true
|
||||
};
|
||||
|
||||
const mapKey = ethers.utils.hexlify(ethers.utils.randomBytes(32));
|
||||
await testMappingTypes.setFixedBytesStructMap(mapKey, expectedValue);
|
||||
const blockHash = await getBlockHash();
|
||||
let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testMappingTypes.address, 'fixedBytesStructMap', mapKey);
|
||||
expect(value).to.eql(expectedValue);
|
||||
|
||||
// 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]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('nested mapping type', () => {
|
||||
@ -775,5 +870,14 @@ describe('Get value from storage', () => {
|
||||
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testNestedMapping.address, 'stringAddressIntMap', key, signer1.address);
|
||||
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 uintKey = 123;
|
||||
await testNestedMapping.setDoubleNestedAddressMap(signer1.address, signer2.address, uintKey, signer3.address);
|
||||
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());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
contract TestBasicMapping {
|
||||
// Mapping type variable occupies one single slot but the actual elements are stored at a different storage slot that is computed using a Keccak-256 hash.
|
||||
@ -30,6 +31,18 @@ contract TestBasicMapping {
|
||||
// Mapping with dynamically-sized byte array as keys and unsigned integer type values.
|
||||
mapping(bytes => uint) public bytesUintMap;
|
||||
|
||||
struct TestStruct {
|
||||
uint128 uint1;
|
||||
int56 int1;
|
||||
bool bool1;
|
||||
}
|
||||
|
||||
// Mapping with signed integer as keys and struct type values.
|
||||
mapping(int24 => TestStruct) public intStructMap;
|
||||
|
||||
// Mapping with signed integer as keys and struct type values.
|
||||
mapping(bytes32 => TestStruct) public fixedBytesStructMap;
|
||||
|
||||
// Set variable addressUintMap.
|
||||
function setAddressUintMap(uint value) external {
|
||||
addressUintMap[msg.sender] = value;
|
||||
@ -69,4 +82,14 @@ contract TestBasicMapping {
|
||||
function setBytesUintMap(bytes calldata key, uint value) external {
|
||||
bytesUintMap[key] = value;
|
||||
}
|
||||
|
||||
// Set variable intStruct.
|
||||
function setIntStructMap(int24 key, TestStruct calldata value) external {
|
||||
intStructMap[key] = value;
|
||||
}
|
||||
|
||||
// Set variable fixedBytesStructMap.
|
||||
function setFixedBytesStructMap(bytes32 key, TestStruct calldata value) external {
|
||||
fixedBytesStructMap[key] = value;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
contract TestFixedArrays {
|
||||
// Fixed size array variable will use 5 consecutive slots as size of 1 element is 32 bytes.
|
||||
@ -19,6 +20,14 @@ contract TestFixedArrays {
|
||||
|
||||
bytes10[5] bytesArray;
|
||||
|
||||
struct TestStruct {
|
||||
uint32 uint1;
|
||||
int56 int1;
|
||||
bool bool1;
|
||||
}
|
||||
|
||||
TestStruct[5] structArray;
|
||||
|
||||
// Set variable boolArray.
|
||||
function setBoolArray(bool[2] calldata value) external {
|
||||
boolArray = value;
|
||||
@ -48,4 +57,9 @@ contract TestFixedArrays {
|
||||
function setBytesArray(bytes10[5] calldata value) external {
|
||||
bytesArray = value;
|
||||
}
|
||||
|
||||
// Set variable structArray.
|
||||
function setStructArray(TestStruct calldata value, uint index) external {
|
||||
structArray[index] = value;
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ contract TestNestedMapping {
|
||||
|
||||
mapping (string => mapping (address => int)) private stringAddressIntMap;
|
||||
|
||||
mapping (address => mapping (address => mapping (uint24 => address))) public doubleNestedAddressMap;
|
||||
|
||||
// Set variable nestedAddressUintMap.
|
||||
function setNestedAddressUintMap(address nestedKey, uint value) external {
|
||||
nestedAddressUintMap[msg.sender][nestedKey] = value;
|
||||
@ -38,4 +40,9 @@ contract TestNestedMapping {
|
||||
function setStringAddressIntMap(string calldata key, address nestedKey, int value) external {
|
||||
stringAddressIntMap[key][nestedKey] = value;
|
||||
}
|
||||
|
||||
// Set variable doubleNestedAddressMap.
|
||||
function setDoubleNestedAddressMap(address key, address nestedKey, uint24 doubleNestedKey, address value) external {
|
||||
doubleNestedAddressMap[key][nestedKey][doubleNestedKey] = value;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
import "./TestContractTypes.sol";
|
||||
|
||||
@ -69,11 +70,8 @@ contract TestValueStructs {
|
||||
}
|
||||
|
||||
// Set variable addressStruct.
|
||||
function setAddressStruct(int8 int1Value, address address1Value, address address2Value, uint16 uint1Value) external {
|
||||
addressStruct.int1 = int1Value;
|
||||
addressStruct.address1 = address1Value;
|
||||
addressStruct.address2 = address2Value;
|
||||
addressStruct.uint1 = uint1Value;
|
||||
function setAddressStruct(AddressStruct calldata value) external {
|
||||
addressStruct = value;
|
||||
}
|
||||
|
||||
// Set variable contractStruct.
|
||||
|
Loading…
Reference in New Issue
Block a user