mirror of
https://github.com/cerc-io/watcher-ts
synced 2025-02-08 19:12:49 +00:00
Fix getting values for arrays. (#73)
Co-authored-by: nikugogoi <95nikass@gmail.com>
This commit is contained in:
parent
7d609f9a2b
commit
e3ef17d547
@ -26,24 +26,24 @@ $ yarn test
|
|||||||
* [x] Fixed-size byte arrays
|
* [x] Fixed-size byte arrays
|
||||||
* [x] Enums
|
* [x] Enums
|
||||||
* [ ] Function Types
|
* [ ] Function Types
|
||||||
* [ ] Reference Types
|
* [x] Reference Types
|
||||||
* [ ] Arrays
|
* [x] Arrays
|
||||||
* [x] Get all elements in array
|
* [x] Get all elements in array
|
||||||
* [x] Get element in array by index
|
* [x] Get element in array by index
|
||||||
* [ ] Fixed size arrays
|
* [x] Fixed size arrays
|
||||||
* [x] Integer Type
|
* [x] Integer Type
|
||||||
* [x] Boolean Type
|
* [x] Boolean Type
|
||||||
* [x] Address Type
|
* [x] Address Type
|
||||||
* [ ] Fixed-size byte arrays
|
* [x] Fixed-size byte arrays
|
||||||
* [x] Enum type
|
* [x] Enum type
|
||||||
* [x] Dynamically-sized byte array
|
* [x] Dynamically-sized byte array
|
||||||
* [x] Struct Type
|
* [x] Struct Type
|
||||||
* [x] Mapping Type
|
* [x] Mapping Type
|
||||||
* [ ] Dynamically-sized arrays
|
* [x] Dynamically-sized arrays
|
||||||
* [x] Integer Type
|
* [x] Integer Type
|
||||||
* [x] Boolean Type
|
* [x] Boolean Type
|
||||||
* [x] Address Type
|
* [x] Address Type
|
||||||
* [ ] Fixed-size byte arrays
|
* [x] Fixed-size byte arrays
|
||||||
* [x] Enum Type
|
* [x] Enum Type
|
||||||
* [x] Dynamically-sized byte array
|
* [x] Dynamically-sized byte array
|
||||||
* [x] Struct Type
|
* [x] Struct Type
|
||||||
@ -54,14 +54,14 @@ $ yarn test
|
|||||||
* [x] Dynamically-sized byte array
|
* [x] Dynamically-sized byte array
|
||||||
* [x] Bytes
|
* [x] Bytes
|
||||||
* [x] String
|
* [x] String
|
||||||
* [ ] Structs
|
* [x] Structs
|
||||||
* [x] Get struct value with all members
|
* [x] Get struct value with all members
|
||||||
* [x] Value Types
|
* [x] Value Types
|
||||||
* [x] Get value of a single member in struct
|
* [x] Get value of a single member in struct
|
||||||
* [ ] Reference Types
|
* [x] Reference Types
|
||||||
* [x] Struct type members (nested)
|
* [x] Struct type members (nested)
|
||||||
* [x] Fixed size Array members
|
* [x] Fixed size Array members
|
||||||
* [ ] Dynamically sized Array members
|
* [x] Dynamically sized Array members
|
||||||
* [x] Bytes and string type members
|
* [x] Bytes and string type members
|
||||||
* [x] Mapping type members
|
* [x] Mapping type members
|
||||||
* [ ] Mapping Types
|
* [ ] Mapping Types
|
||||||
|
@ -367,7 +367,7 @@ describe('Get value from storage', () => {
|
|||||||
expect(proofData.length).to.equal(addressArray.length);
|
expect(proofData.length).to.equal(addressArray.length);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('get value for fixed size arrays of fixed size bytes type', async () => {
|
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 expectedValue = Array.from({ length: 5 }, () => ethers.utils.hexlify(ethers.utils.randomBytes(10)));
|
||||||
|
|
||||||
await testFixedArrays.setFixedBytesArray(expectedValue);
|
await testFixedArrays.setFixedBytesArray(expectedValue);
|
||||||
@ -592,7 +592,7 @@ describe('Get value from storage', () => {
|
|||||||
expect(value).to.equal(addressArray[arrayIndex]);
|
expect(value).to.equal(addressArray[arrayIndex]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('get value for dynamic sized array of fixed size byte array', async () => {
|
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 fixedBytesArray = Array.from({ length: 4 }, () => ethers.utils.hexlify(ethers.utils.randomBytes(10)));
|
||||||
await testDynamicArrays.setFixedBytesArray(fixedBytesArray);
|
await testDynamicArrays.setFixedBytesArray(fixedBytesArray);
|
||||||
const blockHash = await getBlockHash();
|
const blockHash = await getBlockHash();
|
||||||
@ -1072,7 +1072,7 @@ describe('Get value from storage', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
dynamicArrayStruct = {
|
dynamicArrayStruct = {
|
||||||
address1: signers[4].address,
|
address1: signers[4].address.toLowerCase(),
|
||||||
uintArray: [1, 2, 3, 4, 5].map(BigInt)
|
uintArray: [1, 2, 3, 4, 5].map(BigInt)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -1099,7 +1099,7 @@ describe('Get value from storage', () => {
|
|||||||
expect(value).to.eql(stringStruct);
|
expect(value).to.eql(stringStruct);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('get value for struct with dynamic array members', async () => {
|
it('get value for struct with dynamic array members', async () => {
|
||||||
await testReferenceStructs.setDynamicArrayStruct(dynamicArrayStruct);
|
await testReferenceStructs.setDynamicArrayStruct(dynamicArrayStruct);
|
||||||
const blockHash = await getBlockHash();
|
const blockHash = await getBlockHash();
|
||||||
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'dynamicArrayStruct');
|
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'dynamicArrayStruct');
|
||||||
@ -1138,7 +1138,7 @@ describe('Get value from storage', () => {
|
|||||||
expect(value).to.eql(stringStruct[member]);
|
expect(value).to.eql(stringStruct[member]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('get value of dynamic array member in a struct', async () => {
|
it('get value of dynamic array member in a struct', async () => {
|
||||||
const member = 'uintArray';
|
const member = 'uintArray';
|
||||||
const blockHash = await getBlockHash();
|
const blockHash = await getBlockHash();
|
||||||
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'dynamicArrayStruct', member);
|
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'dynamicArrayStruct', member);
|
||||||
@ -1247,6 +1247,9 @@ describe('Get value from storage', () => {
|
|||||||
expect(value).to.equal(expectedValue);
|
expect(value).to.equal(expectedValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: Fix getting value for mapping with keys as fixed-size byte array
|
||||||
|
// 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 () => {
|
it.skip('get value for mapping with fixed-size byte array keys', async () => {
|
||||||
const mapKey = ethers.utils.hexlify(ethers.utils.randomBytes(8));
|
const mapKey = ethers.utils.hexlify(ethers.utils.randomBytes(8));
|
||||||
const [, signer1] = await ethers.getSigners();
|
const [, signer1] = await ethers.getSigners();
|
||||||
|
@ -219,17 +219,22 @@ const getDynamicArrayInfo = async (getStorageAt: GetStorageAt, blockHash: string
|
|||||||
const getArrayValue = async (getStorageAt: GetStorageAt, blockHash: string, address: string, types: Types, mappingKeys: MappingKey[], slot: string, base: string, arraySize: number) => {
|
const getArrayValue = async (getStorageAt: GetStorageAt, blockHash: string, address: string, types: Types, mappingKeys: MappingKey[], slot: string, base: string, arraySize: number) => {
|
||||||
const resultArray = [];
|
const resultArray = [];
|
||||||
const proofs = [];
|
const proofs = [];
|
||||||
let { numberOfBytes: baseNumberOfBytes, label: baseTypeLabel } = types[base];
|
const { numberOfBytes: baseNumberOfBytes } = types[base];
|
||||||
|
|
||||||
// Address type elements use an entire single slot i.e. 32 bytes.
|
|
||||||
if (baseTypeLabel === 'address' || baseTypeLabel.includes('contract')) {
|
|
||||||
baseNumberOfBytes = '32';
|
|
||||||
}
|
|
||||||
|
|
||||||
const getArrayElement = async (mappingKeys: MappingKey[], index: number) => {
|
const getArrayElement = async (mappingKeys: MappingKey[], index: number) => {
|
||||||
const arrayOffset = index * Number(baseNumberOfBytes);
|
let arraySlotOffset = 0;
|
||||||
const arraySlot = BigNumber.from(slot).add(Math.floor(arrayOffset / 32)).toHexString();
|
let slotIndex;
|
||||||
const arraySlotOffset = arrayOffset % 32;
|
|
||||||
|
if (Number(baseNumberOfBytes) <= 32) {
|
||||||
|
const elementsInSlot = Math.floor(32 / Number(baseNumberOfBytes));
|
||||||
|
slotIndex = Math.floor(index / elementsInSlot);
|
||||||
|
arraySlotOffset = (index % elementsInSlot) * Number(baseNumberOfBytes);
|
||||||
|
} else {
|
||||||
|
const slotsUsedByElement = Math.ceil(Number(baseNumberOfBytes) / 32);
|
||||||
|
slotIndex = slotsUsedByElement * index;
|
||||||
|
}
|
||||||
|
|
||||||
|
const arraySlot = BigNumber.from(slot).add(slotIndex).toHexString();
|
||||||
|
|
||||||
return getDecodedValue(getStorageAt, blockHash, address, types, { slot: arraySlot, offset: arraySlotOffset, type: base }, mappingKeys);
|
return getDecodedValue(getStorageAt, blockHash, address, types, { slot: arraySlot, offset: arraySlotOffset, type: base }, mappingKeys);
|
||||||
};
|
};
|
||||||
@ -240,7 +245,6 @@ const getArrayValue = async (getStorageAt: GetStorageAt, blockHash: string, addr
|
|||||||
return getArrayElement(remainingKeys, arrayIndex);
|
return getArrayElement(remainingKeys, arrayIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Get values in single call and parse according to type.
|
|
||||||
// Loop over elements of array and get value.
|
// Loop over elements of array and get value.
|
||||||
for (let i = 0; i < arraySize; i++) {
|
for (let i = 0; i < arraySize; i++) {
|
||||||
const { value, proof } = await getArrayElement(mappingKeys, i);
|
const { value, proof } = await getArrayElement(mappingKeys, i);
|
||||||
@ -309,6 +313,7 @@ const getStructureValue = async (getStorageAt: GetStorageAt, blockHash: string,
|
|||||||
* @param getStorageAt
|
* @param getStorageAt
|
||||||
*/
|
*/
|
||||||
const getInplaceValue = async (getStorageAt: GetStorageAt, blockHash: string, address: string, slot: string, offset: number, numberOfBytes: string) => {
|
const getInplaceValue = async (getStorageAt: GetStorageAt, blockHash: string, address: string, slot: string, offset: number, numberOfBytes: string) => {
|
||||||
|
// TODO: Memoize getStorageAt function for duplicate multiple calls.
|
||||||
const { value, proof } = await getStorageAt({ blockHash, contract: address, slot });
|
const { value, proof } = await getStorageAt({ blockHash, contract: address, slot });
|
||||||
const valueLength = utils.hexDataLength(value);
|
const valueLength = utils.hexDataLength(value);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user