Get fixed size array of type address (#53)

* Add test for fixed array of address type.

* Add tests for verifying proof data.

Co-authored-by: nikugogoi <95nikass@gmail.com>
This commit is contained in:
Ashwin Phatak
2021-06-11 11:16:02 +05:30
committed by GitHub
co-authored by nikugogoi
parent df025433ec
commit 5316b19fbf
4 changed files with 94 additions and 38 deletions
+65 -32
View File
@@ -269,45 +269,78 @@ describe('Get value from storage', () => {
});
});
// 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 TestFixedArrays = await ethers.getContractFactory('TestFixedArrays');
const testFixedArrays = await TestFixedArrays.deploy();
await testFixedArrays.deployed();
const storageLayout = await getStorageLayout('TestFixedArrays');
describe('fixed size arrays', () => {
let testFixedArrays: Contract, storageLayout: StorageLayout;
let expectedValue: Array<number|boolean> = [true, false];
before(async () => {
const TestFixedArrays = await ethers.getContractFactory('TestFixedArrays');
testFixedArrays = await TestFixedArrays.deploy();
await testFixedArrays.deployed();
storageLayout = await getStorageLayout('TestFixedArrays');
});
await testFixedArrays.setBoolArray(expectedValue);
let blockHash = await getBlockHash();
let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'boolArray');
expect(value).to.eql(expectedValue);
// 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 () => {
let expectedValue: Array<number|boolean> = [true, false];
expectedValue = [1, 2, 3, 4, 5];
await testFixedArrays.setUint16Array(expectedValue);
blockHash = await getBlockHash();
({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'uint16Array'));
expect(value).to.eql(expectedValue.map(el => BigInt(el)));
});
await testFixedArrays.setBoolArray(expectedValue);
let blockHash = await getBlockHash();
let { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'boolArray');
expect(value).to.eql(expectedValue);
let proofData = JSON.parse(proof.data);
expect(proofData.length).to.equal(expectedValue.length);
// 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 TestFixedArrays = await ethers.getContractFactory('TestFixedArrays');
const testFixedArrays = await TestFixedArrays.deploy();
await testFixedArrays.deployed();
const storageLayout = await getStorageLayout('TestFixedArrays');
expectedValue = [1, 2, 3, 4, 5];
await testFixedArrays.setUint16Array(expectedValue);
blockHash = await getBlockHash();
({ value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'uint16Array'));
expect(value).to.eql(expectedValue.map(el => BigInt(el)));
proofData = JSON.parse(proof.data);
expect(proofData.length).to.equal(expectedValue.length);
});
const expectedValue = [1, 2, 3, 4, 5];
// 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 expectedValue = [1, 2, 3, 4, 5];
await testFixedArrays.setInt128Array(expectedValue);
let blockHash = await getBlockHash();
let { value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'int128Array');
expect(value).to.eql(expectedValue.map(el => BigInt(el)));
await testFixedArrays.setInt128Array(expectedValue);
let blockHash = await getBlockHash();
let { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'int128Array');
expect(value).to.eql(expectedValue.map(el => BigInt(el)));
let proofData = JSON.parse(proof.data);
expect(proofData.length).to.equal(expectedValue.length);
await testFixedArrays.setUintArray(expectedValue);
blockHash = await getBlockHash();
({ value } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'uintArray'));
expect(value).to.eql(expectedValue.map(el => BigInt(el)));
await testFixedArrays.setUintArray(expectedValue);
blockHash = await getBlockHash();
({ value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'uintArray'));
expect(value).to.eql(expectedValue.map(el => BigInt(el)));
proofData = JSON.parse(proof.data);
expect(proofData.length).to.equal(expectedValue.length);
});
it('get value for fixed size arrays of address type', async () => {
const signers = await ethers.getSigners();
const expectedValue = signers.map(signer => signer.address.toLowerCase())
.slice(0, 4);
await testFixedArrays.setAddressArray(expectedValue);
const blockHash = await getBlockHash();
const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'addressArray');
expect(value).to.eql(expectedValue);
const proofData = JSON.parse(proof.data);
expect(proofData.length).to.equal(expectedValue.length);
});
it.skip('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)));
await testFixedArrays.setBytesArray(expectedValue);
const blockHash = await getBlockHash();
const { value, proof } = await getStorageValue(storageLayout, getStorageAt, blockHash, testFixedArrays.address, 'bytesArray');
expect(value).to.eql(expectedValue);
const proofData = JSON.parse(proof.data);
expect(proofData.length).to.equal(expectedValue.length);
});
});
describe('basic mapping type', () => {
+8 -1
View File
@@ -111,7 +111,12 @@ const getDecodedValue = async (getStorageAt: GetStorageAt, blockHash: string, ad
if (isArray && base) {
const resultArray = [];
const proofs = [];
const { numberOfBytes: baseNumberOfBytes } = types[base];
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';
}
// TODO: Get values in single call and parse according to type.
// Loop over elements of array and get value.
@@ -120,6 +125,8 @@ const getDecodedValue = async (getStorageAt: GetStorageAt, blockHash: string, ad
const slotOffset = i % 32;
({ value, proof } = await getDecodedValue(getStorageAt, blockHash, address, types, { slot: arraySlot, offset: slotOffset, type: base }, []));
resultArray.push(value);
// Each element in array gets its own proof even if it is packed.
proofs.push(JSON.parse(proof.data));
}