storage.js 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. const { ethers } = require('hardhat');
  2. const { setStorageAt } = require('@nomicfoundation/hardhat-network-helpers');
  3. const ImplementationLabel = 'eip1967.proxy.implementation';
  4. const AdminLabel = 'eip1967.proxy.admin';
  5. const BeaconLabel = 'eip1967.proxy.beacon';
  6. const erc1967Slot = label => ethers.toBeHex(ethers.toBigInt(ethers.id(label)) - 1n);
  7. const erc7201Slot = label => ethers.toBeHex(ethers.toBigInt(ethers.keccak256(erc1967Slot(label))) & ~0xffn);
  8. const erc7201format = contractName => `openzeppelin.storage.${contractName}`;
  9. const getSlot = (address, slot) =>
  10. ethers.provider.getStorage(address, ethers.isBytesLike(slot) ? slot : erc1967Slot(slot));
  11. const setSlot = (address, slot, value) =>
  12. Promise.all([
  13. ethers.isAddressable(address) ? address.getAddress() : Promise.resolve(address),
  14. ethers.isAddressable(value) ? value.getAddress() : Promise.resolve(value),
  15. ]).then(([address, value]) => setStorageAt(address, ethers.isBytesLike(slot) ? slot : erc1967Slot(slot), value));
  16. const getAddressInSlot = (address, slot) =>
  17. getSlot(address, slot).then(slotValue => ethers.AbiCoder.defaultAbiCoder().decode(['address'], slotValue)[0]);
  18. const upgradeableSlot = (contractName, offset) => {
  19. try {
  20. // Try to get the artifact paths, will throw if it doesn't exist
  21. artifacts._getArtifactPathSync(`${contractName}Upgradeable`);
  22. return offset + ethers.toBigInt(erc7201Slot(erc7201format(contractName)));
  23. } catch {
  24. return offset;
  25. }
  26. };
  27. module.exports = {
  28. ImplementationLabel,
  29. AdminLabel,
  30. BeaconLabel,
  31. ImplementationSlot: erc1967Slot(ImplementationLabel),
  32. AdminSlot: erc1967Slot(AdminLabel),
  33. BeaconSlot: erc1967Slot(BeaconLabel),
  34. erc1967Slot,
  35. erc7201Slot,
  36. erc7201format,
  37. setSlot,
  38. getSlot,
  39. getAddressInSlot,
  40. upgradeableSlot,
  41. };