erc1967.js 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637
  1. const { ethers } = require('hardhat');
  2. const { getStorageAt, 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 getSlot = (address, slot) =>
  9. (ethers.isAddressable(address) ? address.getAddress() : Promise.resolve(address)).then(address =>
  10. getStorageAt(address, ethers.isBytesLike(slot) ? slot : erc1967slot(slot)),
  11. );
  12. const setSlot = (address, slot, value) =>
  13. Promise.all([
  14. ethers.isAddressable(address) ? address.getAddress() : Promise.resolve(address),
  15. ethers.isAddressable(value) ? value.getAddress() : Promise.resolve(value),
  16. ]).then(([address, value]) => setStorageAt(address, ethers.isBytesLike(slot) ? slot : erc1967slot(slot), value));
  17. const getAddressInSlot = (address, slot) =>
  18. getSlot(address, slot).then(slotValue => ethers.AbiCoder.defaultAbiCoder().decode(['address'], slotValue)[0]);
  19. module.exports = {
  20. ImplementationLabel,
  21. AdminLabel,
  22. BeaconLabel,
  23. ImplementationSlot: erc1967slot(ImplementationLabel),
  24. AdminSlot: erc1967slot(AdminLabel),
  25. BeaconSlot: erc1967slot(BeaconLabel),
  26. erc1967slot,
  27. erc7201slot,
  28. setSlot,
  29. getSlot,
  30. getAddressInSlot,
  31. };