Tests for getting array and string type member value in struct (#57)

* Add tests for structs with fixed array and string type
 members.

* Refactor functions in solidity-mapper storage.

* Add tests for getting array and string type member value in struct.

Co-authored-by: nikugogoi <95nikass@gmail.com>
This commit is contained in:
Ashwin Phatak 2021-06-14 16:12:42 +05:30 committed by GitHub
parent 2fcfadecc2
commit f5c1a22fdc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 282 additions and 116 deletions

View File

@ -376,8 +376,8 @@ describe('Get value from storage', () => {
});
});
describe('structs type', () => {
let testStructs: Contract, storageLayout: StorageLayout;
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 };
@ -400,10 +400,10 @@ describe('Get value from storage', () => {
};
before(async () => {
const TestStructs = await ethers.getContractFactory('TestStructs');
testStructs = await TestStructs.deploy();
await testStructs.deployed();
storageLayout = await getStorageLayout('TestStructs');
const TestValueStructs = await ethers.getContractFactory('TestValueStructs');
testValueStructs = await TestValueStructs.deploy();
await testValueStructs.deployed();
storageLayout = await getStorageLayout('TestValueStructs');
const [signer1, signer2] = await ethers.getSigners();
@ -431,54 +431,54 @@ describe('Get value from storage', () => {
uint1: BigInt(4)
};
await testStructs.setSingleSlotStruct(expectedValue.int1, expectedValue.uint1);
await testValueStructs.setSingleSlotStruct(expectedValue.int1, expectedValue.uint1);
const blockHash = await getBlockHash();
const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testStructs.address, 'singleSlotStruct');
const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'singleSlotStruct');
expect(value).to.eql(expectedValue);
const proofData = JSON.parse(proof.data);
expect(proofData).to.have.all.keys('int1', 'uint1');
});
it('get value for struct using multiple slots', async () => {
await testStructs.setMultipleSlotStruct(multipleSlotStruct.uint1, multipleSlotStruct.bool1, multipleSlotStruct.int1);
await testValueStructs.setMultipleSlotStruct(multipleSlotStruct.uint1, multipleSlotStruct.bool1, multipleSlotStruct.int1);
const blockHash = await getBlockHash();
const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testStructs.address, 'multipleSlotStruct');
const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'multipleSlotStruct');
expect(value).to.eql(multipleSlotStruct);
const proofData = JSON.parse(proof.data);
expect(proofData).to.have.all.keys(Object.keys(multipleSlotStruct));
});
it('get value for struct with address type members', async () => {
await testStructs.setAddressStruct(addressStruct.int1, addressStruct.address1, addressStruct.address2, addressStruct.uint1);
await testValueStructs.setAddressStruct(addressStruct.int1, addressStruct.address1, addressStruct.address2, addressStruct.uint1);
const blockHash = await getBlockHash();
const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testStructs.address, 'addressStruct');
const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'addressStruct');
expect(value).to.eql(addressStruct);
const proofData = JSON.parse(proof.data);
expect(proofData).to.have.all.keys(Object.keys(addressStruct));
});
it('get value for struct with contract type members', async () => {
await testStructs.setContractStruct(contractStruct.uint1, contractStruct.testContract);
await testValueStructs.setContractStruct(contractStruct.uint1, contractStruct.testContract);
const blockHash = await getBlockHash();
const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testStructs.address, 'contractStruct');
const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'contractStruct');
expect(value).to.eql(contractStruct);
const proofData = JSON.parse(proof.data);
expect(proofData).to.have.all.keys(Object.keys(contractStruct));
});
it('get value for struct with fixed-sized byte array members', async () => {
await testStructs.setFixedBytesStruct(fixedBytesStruct.uint1, fixedBytesStruct.bytesTen, fixedBytesStruct.bytesTwenty);
await testValueStructs.setFixedBytesStruct(fixedBytesStruct.uint1, fixedBytesStruct.bytesTen, fixedBytesStruct.bytesTwenty);
const blockHash = await getBlockHash();
const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testStructs.address, 'fixedBytesStruct');
const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'fixedBytesStruct');
expect(value).to.eql(fixedBytesStruct);
const proofData = JSON.parse(proof.data);
expect(proofData).to.have.all.keys('uint1', 'bytesTen', 'bytesTwenty');
});
it('get value for struct with enum type members', async () => {
await testStructs.setEnumStruct(enumStruct.uint1, enumStruct.choice1, enumStruct.choice2);
await testValueStructs.setEnumStruct(enumStruct.uint1, enumStruct.choice1, enumStruct.choice2);
const blockHash = await getBlockHash();
const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testStructs.address, 'enumStruct');
const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'enumStruct');
expect(value).to.eql(enumStruct);
const proofData = JSON.parse(proof.data);
expect(proofData).to.have.all.keys('uint1', 'choice1', 'choice2');
@ -487,59 +487,153 @@ 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 testStructs.setMultipleSlotStruct(multipleSlotStruct.uint1, multipleSlotStruct.bool1, multipleSlotStruct.int1);
await testValueStructs.setMultipleSlotStruct(multipleSlotStruct.uint1, multipleSlotStruct.bool1, multipleSlotStruct.int1);
const blockHash = await getBlockHash();
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testStructs.address, 'multipleSlotStruct', member);
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'multipleSlotStruct', member);
expect(value).to.equal(multipleSlotStruct[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, testStructs.address, 'multipleSlotStruct', member);
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'multipleSlotStruct', member);
expect(value).to.equal(multipleSlotStruct[member]);
});
it('get value of boolean type member in a struct', async () => {
const member = 'bool1';
const blockHash = await getBlockHash();
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testStructs.address, 'multipleSlotStruct', member);
const { 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 testStructs.setAddressStruct(addressStruct.int1, addressStruct.address1, addressStruct.address2, addressStruct.uint1);
await testValueStructs.setAddressStruct(addressStruct.int1, addressStruct.address1, addressStruct.address2, addressStruct.uint1);
const blockHash = await getBlockHash();
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testStructs.address, 'addressStruct', member);
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testValueStructs.address, 'addressStruct', member);
expect(value).to.equal(addressStruct[member]);
});
it('get value of contract type member in a struct', async () => {
const member = 'testContract';
await testStructs.setContractStruct(contractStruct.uint1, contractStruct.testContract);
await testValueStructs.setContractStruct(contractStruct.uint1, contractStruct.testContract);
const blockHash = await getBlockHash();
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testStructs.address, 'contractStruct', member);
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';
await testStructs.setFixedBytesStruct(fixedBytesStruct.uint1, fixedBytesStruct.bytesTen, fixedBytesStruct.bytesTwenty);
await testValueStructs.setFixedBytesStruct(fixedBytesStruct.uint1, fixedBytesStruct.bytesTen, fixedBytesStruct.bytesTwenty);
const blockHash = await getBlockHash();
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testStructs.address, 'fixedBytesStruct', member);
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';
await testStructs.setEnumStruct(enumStruct.uint1, enumStruct.choice1, enumStruct.choice2);
await testValueStructs.setEnumStruct(enumStruct.uint1, enumStruct.choice1, enumStruct.choice2);
const blockHash = await getBlockHash();
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testStructs.address, 'enumStruct', member);
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 fixedArrayStruct: {[key: string]: any};
const stringStruct = {
string1: 'string1',
uint1: BigInt(123),
string2: 'string2'
};
before(async () => {
const TestReferenceStructs = await ethers.getContractFactory('TestReferenceStructs');
testReferenceStructs = await TestReferenceStructs.deploy();
await testReferenceStructs.deployed();
storageLayout = await getStorageLayout('TestReferenceStructs');
const signers = await ethers.getSigners();
fixedArrayStruct = {
int1: BigInt(123),
uintArray: [1, 2, 3, 4].map(el => BigInt(el)),
addressArray: signers.slice(0, 3).map(signer => signer.address.toLowerCase())
};
});
// Get all members of a struct.
it('get value for struct with fixed-size array members', async () => {
await testReferenceStructs.setFixedArrayStruct(fixedArrayStruct.int1, fixedArrayStruct.uintArray, fixedArrayStruct.addressArray);
const blockHash = await getBlockHash();
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'fixedArrayStruct');
expect(value).to.eql(fixedArrayStruct);
});
it('get value for struct with string type members', async () => {
await testReferenceStructs.setStringStruct(stringStruct.string1, stringStruct.uint1, stringStruct.string2);
const blockHash = await getBlockHash();
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'stringStruct');
expect(value).to.eql(stringStruct);
});
// Get value of a member in a struct
it('get value of fixed-size array member in a struct', async () => {
const member = 'uintArray';
await testReferenceStructs.setFixedArrayStruct(fixedArrayStruct.int1, fixedArrayStruct.uintArray, fixedArrayStruct.addressArray);
const blockHash = await getBlockHash();
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'fixedArrayStruct', member);
expect(value).to.eql(fixedArrayStruct[member]);
});
it('get value of string member in a struct', async () => {
const member = 'string2';
await testReferenceStructs.setStringStruct(stringStruct.string1, stringStruct.uint1, stringStruct.string2);
const blockHash = await getBlockHash();
const { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'stringStruct', member);
expect(value).to.eql(stringStruct[member]);
});
it.skip('get value of mapping type member in a struct', async () => {
const [signer1, signer2] = await ethers.getSigners();
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(signer2.address, 789);
let member = 'uintAddressMap';
await testReferenceStructs.setValueMappingStruct(mappingKey, valueMappingStruct.uintAddressMap.get(mappingKey), valueMappingStruct.uint1, signer2.address, valueMappingStruct.addressIntMap.get(signer2.address));
let blockHash = await getBlockHash();
let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'valueMappingStruct', member, mappingKey);
expect(value).to.equal(valueMappingStruct[member].get(mappingKey));
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, 123);
member = 'stringAddressMap';
await testReferenceStructs.setReferenceMappingStruct(bytesKey, referenceMappingStruct.bytesAddressMap.get(bytesKey), stringKey, referenceMappingStruct.stringUintMap.get(stringKey));
blockHash = await getBlockHash();
({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testReferenceStructs.address, 'referenceMappingStruct', member, stringKey));
expect(value).to.equal(referenceMappingStruct[member].get(stringKey));
});
});
describe('basic mapping type', () => {
let testMappingTypes: Contract, storageLayout: StorageLayout;

View File

@ -110,90 +110,14 @@ const getDecodedValue = async (getStorageAt: GetStorageAt, blockHash: string, ad
// If variable is array type.
if (isArray && base) {
const resultArray = [];
const proofs = [];
let { numberOfBytes: baseNumberOfBytes, label: baseTypeLabel } = 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 (index: number, mappingKeys: MappingKey[]) => {
const arrayOffset = index * Number(baseNumberOfBytes);
const arraySlot = BigNumber.from(slot).add(Math.floor(arrayOffset / 32)).toHexString();
const arraySlotOffset = arrayOffset % 32;
return getDecodedValue(getStorageAt, blockHash, address, types, { slot: arraySlot, offset: arraySlotOffset, type: base }, mappingKeys);
};
const [arrayIndex, ...remainingKeys] = mappingKeys;
if (typeof arrayIndex === 'number') {
return getArrayElement(arrayIndex, remainingKeys);
}
// TODO: Get values in single call and parse according to type.
// Loop over elements of array and get value.
for (let i = 0; i < Number(arraySize); i++) {
({ value, proof } = await getArrayElement(i, mappingKeys));
resultArray.push(value);
// Each element in array gets its own proof even if it is packed.
proofs.push(JSON.parse(proof.data));
}
return {
value: resultArray,
proof: {
data: JSON.stringify(proofs)
}
};
return getArrayValue(getStorageAt, blockHash, address, types, mappingKeys, slot, base, Number(arraySize));
}
const isStruct = /^struct .+/.test(typeLabel);
// If variable is struct type.
if (isStruct && members) {
// Get value of specified member in struct.
const getStructMember = async (member: Storage, mappingKeys: MappingKey[]) => {
const structSlot = BigNumber.from(slot).add(member.slot).toHexString();
return getDecodedValue(getStorageAt, blockHash, address, types, { slot: structSlot, offset: member.offset, type: member.type }, mappingKeys);
};
const [memberName, ...remainingKeys] = mappingKeys;
const member = members.find(member => member.label === memberName);
// If member name passed in argument is present.
if (member) {
return getStructMember(member, remainingKeys);
}
// TODO: Get values in single call and parse according to type.
// Get member values specified for the struct in storage layout.
const resultPromises = members.map(async member => {
return getStructMember(member, mappingKeys);
});
const results = await Promise.all(resultPromises);
const initialValue: {
value: {[key: string]: any},
proof: { data: string }
} = {
value: {},
proof: { data: JSON.stringify({}) }
};
// Return struct type value as an object with keys as the struct member labels.
return members.reduce((acc, member, index) => {
acc.value[member.label] = results[index].value;
const proofData = JSON.parse(acc.proof.data);
proofData[member.label] = results[index].proof;
acc.proof.data = JSON.stringify(proofData);
return acc;
}, initialValue);
return getStructureValue(getStorageAt, blockHash, address, types, mappingKeys, slot, members);
}
// Get value according to encoding i.e. how the data is encoded in storage.
@ -201,17 +125,17 @@ const getDecodedValue = async (getStorageAt: GetStorageAt, blockHash: string, ad
switch (encoding) {
// https://docs.soliditylang.org/en/v0.8.4/internals/layout_in_storage.html#layout-of-state-variables-in-storage
case 'inplace':
({ value, proof } = await getInplaceValue(blockHash, address, slot, offset, numberOfBytes, getStorageAt));
({ value, proof } = await getInplaceValue(getStorageAt, blockHash, address, slot, offset, numberOfBytes));
break;
// https://docs.soliditylang.org/en/v0.8.4/internals/layout_in_storage.html#bytes-and-string
case 'bytes':
({ value, proof } = await getBytesValue(blockHash, address, slot, getStorageAt));
({ value, proof } = await getBytesValue(getStorageAt, blockHash, address, slot));
break;
case 'mapping': {
if (mappingValueType && mappingKeyType) {
const mappingSlot = getMappingSlot(slot, types, mappingKeyType, mappingKeys[0]);
const mappingSlot = getMappingSlot(types, slot, mappingKeyType, mappingKeys[0]);
return getDecodedValue(getStorageAt, blockHash, address, types, { slot: mappingSlot, offset: 0, type: mappingValueType }, mappingKeys.slice(1));
} else {
@ -236,7 +160,7 @@ const getDecodedValue = async (getStorageAt: GetStorageAt, blockHash: string, ad
* @param mappingSlot
* @param key
*/
export const getMappingSlot = (mappingSlot: string, types: Types, keyType: string, key: MappingKey): string => {
export const getMappingSlot = (types: Types, mappingSlot: string, keyType: string, key: MappingKey): string => {
const { encoding, label: typeLabel } = types[keyType];
// If key is boolean type convert to 1 or 0 which is the way value is stored in memory.
@ -245,7 +169,7 @@ export const getMappingSlot = (mappingSlot: string, types: Types, keyType: strin
}
// If key is string convert to hex string representation.
if (typeLabel.includes('string') && typeof key === 'string') {
if (typeLabel === 'string' && typeof key === 'string') {
key = utils.hexlify(utils.toUtf8Bytes(key));
}
@ -271,6 +195,90 @@ export const getMappingSlot = (mappingSlot: string, types: Types, keyType: strin
return slot;
};
const getArrayValue = async (getStorageAt: GetStorageAt, blockHash: string, address: string, types: Types, mappingKeys: MappingKey[], slot: string, base: string, arraySize: number) => {
const resultArray = [];
const proofs = [];
let { numberOfBytes: baseNumberOfBytes, label: baseTypeLabel } = 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 arrayOffset = index * Number(baseNumberOfBytes);
const arraySlot = BigNumber.from(slot).add(Math.floor(arrayOffset / 32)).toHexString();
const arraySlotOffset = arrayOffset % 32;
return getDecodedValue(getStorageAt, blockHash, address, types, { slot: arraySlot, offset: arraySlotOffset, type: base }, mappingKeys);
};
const [arrayIndex, ...remainingKeys] = mappingKeys;
if (typeof arrayIndex === 'number') {
return getArrayElement(remainingKeys, arrayIndex);
}
// TODO: Get values in single call and parse according to type.
// Loop over elements of array and get value.
for (let i = 0; i < arraySize; i++) {
const { value, proof } = await getArrayElement(mappingKeys, i);
resultArray.push(value);
// Each element in array gets its own proof even if it is packed.
proofs.push(JSON.parse(proof.data));
}
return {
value: resultArray,
proof: {
data: JSON.stringify(proofs)
}
};
};
const getStructureValue = async (getStorageAt: GetStorageAt, blockHash: string, address: string, types: Types, mappingKeys: MappingKey[], slot: string, members: Storage[]) => {
// Get value of specified member in struct.
const getStructMember = async (mappingKeys: MappingKey[], member: Storage) => {
const structSlot = BigNumber.from(slot).add(member.slot).toHexString();
return getDecodedValue(getStorageAt, blockHash, address, types, { slot: structSlot, offset: member.offset, type: member.type }, mappingKeys);
};
const [memberName, ...remainingKeys] = mappingKeys;
const member = members.find(member => member.label === memberName);
// If member name passed in argument is present.
if (member) {
return getStructMember(remainingKeys, member);
}
// TODO: Get values in single call and parse according to type.
// Get member values specified for the struct in storage layout.
const resultPromises = members.map(async member => {
return getStructMember(mappingKeys, member);
});
const results = await Promise.all(resultPromises);
const initialValue: {
value: {[key: string]: any},
proof: { data: string }
} = {
value: {},
proof: { data: JSON.stringify({}) }
};
// Return struct type value as an object with keys as the struct member labels.
return members.reduce((acc, member, index) => {
acc.value[member.label] = results[index].value;
const proofData = JSON.parse(acc.proof.data);
proofData[member.label] = results[index].proof;
acc.proof.data = JSON.stringify(proofData);
return acc;
}, initialValue);
};
/**
* Function to get value for inplace encoding.
* @param address
@ -279,7 +287,7 @@ export const getMappingSlot = (mappingSlot: string, types: Types, keyType: strin
* @param numberOfBytes
* @param getStorageAt
*/
const getInplaceValue = async (blockHash: string, address: string, slot: string, offset: number, numberOfBytes: string, getStorageAt: GetStorageAt) => {
const getInplaceValue = async (getStorageAt: GetStorageAt, blockHash: string, address: string, slot: string, offset: number, numberOfBytes: string) => {
const { value, proof } = await getStorageAt({ blockHash, contract: address, slot });
const valueLength = utils.hexDataLength(value);
@ -299,7 +307,7 @@ const getInplaceValue = async (blockHash: string, address: string, slot: string,
* @param slot
* @param getStorageAt
*/
const getBytesValue = async (blockHash: string, address: string, slot: string, getStorageAt: GetStorageAt) => {
const getBytesValue = async (getStorageAt: GetStorageAt, blockHash: string, address: string, slot: string) => {
const { value, proof } = await getStorageAt({ blockHash, contract: address, slot });
let length = 0;

View File

@ -0,0 +1,62 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
contract TestReferenceStructs {
struct FixedArrayStruct {
int8 int1;
uint16[4] uintArray;
address[3] addressArray;
}
FixedArrayStruct fixedArrayStruct;
struct StringStruct {
string string1;
uint8 uint1;
string string2;
}
StringStruct stringStruct;
struct ValueMappingStruct {
mapping(uint => address) uintAddressMap;
uint32 uint1;
mapping(address => int) addressIntMap;
}
ValueMappingStruct public valueMappingStruct;
struct ReferenceMappingStruct {
mapping(bytes => address) bytesAddressMap;
mapping(string => uint) stringUintMap;
}
ReferenceMappingStruct referenceMappingStruct;
// Set variable fixedArrayStruct.
function setFixedArrayStruct(int8 int1Value, uint16[4] calldata uintArrayValue, address[3] calldata addressArrayValue) external {
fixedArrayStruct.int1 = int1Value;
fixedArrayStruct.uintArray = uintArrayValue;
fixedArrayStruct.addressArray = addressArrayValue;
}
// Set variable stringStruct.
function setStringStruct(string calldata string1Value, uint8 uint1Value, string calldata string2Value) external {
stringStruct.string1 = string1Value;
stringStruct.uint1 = uint1Value;
stringStruct.string2 = string2Value;
}
// Set variable valueMappingStruct.
function setValueMappingStruct(uint uintAddressKey, address uintAddressValue, uint32 uint1Value, address addressIntKey, int addressIntValue) external {
valueMappingStruct.uintAddressMap[uintAddressKey] = uintAddressValue;
valueMappingStruct.uint1 = uint1Value;
valueMappingStruct.addressIntMap[addressIntKey] = addressIntValue;
}
// Set variable referenceMappingStruct.
function setReferenceMappingStruct(bytes calldata bytesAddressKey, address bytesAddressValue, string calldata stringUintKey, uint stringUintValue) external {
referenceMappingStruct.bytesAddressMap[bytesAddressKey] = bytesAddressValue;
referenceMappingStruct.stringUintMap[stringUintKey] = stringUintValue;
}
}

View File

@ -3,7 +3,7 @@ pragma solidity ^0.7.0;
import "./TestContractTypes.sol";
contract TestStructs {
contract TestValueStructs {
struct SingleSlotStruct {
int16 int1;
uint8 uint1;

View File

@ -62,6 +62,8 @@ export const getStorageAt: GetStorageAt = async ({ blockHash, contract, slot })
return {
value,
proof: {
// Returning null value as proof, since ethers library getStorageAt method doesnt return proof.
// This function is used in tests to mock the getStorageAt method of ipld-eth-client which returns proof along with value.
data: JSON.stringify(null)
}
};