TransientSlot.js 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. const format = require('../format-lines');
  2. const { TYPES } = require('./Slot.opts');
  3. const header = `\
  4. pragma solidity ^0.8.24;
  5. /**
  6. * @dev Library for reading and writing value-types to specific transient storage slots.
  7. *
  8. * Transient slots are often used to store temporary values that are removed after the current transaction.
  9. * This library helps with reading and writing to such slots without the need for inline assembly.
  10. *
  11. * * Example reading and writing values using transient storage:
  12. * \`\`\`solidity
  13. * contract Lock {
  14. * using TransientSlot for *;
  15. *
  16. * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
  17. * bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542;
  18. *
  19. * modifier locked() {
  20. * require(!_LOCK_SLOT.asBoolean().tload());
  21. *
  22. * _LOCK_SLOT.asBoolean().tstore(true);
  23. * _;
  24. * _LOCK_SLOT.asBoolean().tstore(false);
  25. * }
  26. * }
  27. * \`\`\`
  28. *
  29. * TIP: Consider using this library along with {SlotDerivation}.
  30. */
  31. `;
  32. const udvt = ({ type, name }) => `\
  33. /**
  34. * @dev UDVT that represents a slot holding a ${type}.
  35. */
  36. type ${name}Slot is bytes32;
  37. /**
  38. * @dev Cast an arbitrary slot to a ${name}Slot.
  39. */
  40. function as${name}(bytes32 slot) internal pure returns (${name}Slot) {
  41. return ${name}Slot.wrap(slot);
  42. }
  43. `;
  44. const transient = ({ type, name }) => `\
  45. /**
  46. * @dev Load the value held at location \`slot\` in transient storage.
  47. */
  48. function tload(${name}Slot slot) internal view returns (${type} value) {
  49. assembly ("memory-safe") {
  50. value := tload(slot)
  51. }
  52. }
  53. /**
  54. * @dev Store \`value\` at location \`slot\` in transient storage.
  55. */
  56. function tstore(${name}Slot slot, ${type} value) internal {
  57. assembly ("memory-safe") {
  58. tstore(slot, value)
  59. }
  60. }
  61. `;
  62. // GENERATE
  63. module.exports = format(
  64. header.trimEnd(),
  65. 'library TransientSlot {',
  66. format(
  67. [].concat(
  68. TYPES.filter(type => type.isValueType).map(type => udvt(type)),
  69. TYPES.filter(type => type.isValueType).map(type => transient(type)),
  70. ),
  71. ).trimEnd(),
  72. '}',
  73. );