BeaconProxy.sol 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v4.7.0) (proxy/beacon/BeaconProxy.sol)
  3. pragma solidity ^0.8.20;
  4. import {IBeacon} from "./IBeacon.sol";
  5. import {Proxy} from "../Proxy.sol";
  6. import {ERC1967Utils} from "../ERC1967/ERC1967Utils.sol";
  7. /**
  8. * @dev This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}.
  9. *
  10. * The beacon address can only be set once during construction, and cannot be changed afterwards. It is stored in an
  11. * immutable variable to avoid unnecessary storage reads, and also in the beacon storage slot specified by
  12. * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] so that it can be accessed externally.
  13. *
  14. * CAUTION: Since the beacon address can never be changed, you must ensure that you either control the beacon, or trust
  15. * the beacon to not upgrade the implementation maliciously.
  16. *
  17. * IMPORTANT: Do not use the implementation logic to modify the beacon storage slot. Doing so would leave the proxy in
  18. * an inconsistent state where the beacon storage slot does not match the beacon address.
  19. */
  20. contract BeaconProxy is Proxy {
  21. // An immutable address for the beacon to avoid unnecessary SLOADs before each delegate call.
  22. address private immutable _beacon;
  23. /**
  24. * @dev Initializes the proxy with `beacon`.
  25. *
  26. * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This
  27. * will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity
  28. * constructor.
  29. *
  30. * Requirements:
  31. *
  32. * - `beacon` must be a contract with the interface {IBeacon}.
  33. * - If `data` is empty, `msg.value` must be zero.
  34. */
  35. constructor(address beacon, bytes memory data) payable {
  36. ERC1967Utils.upgradeBeaconToAndCall(beacon, data);
  37. _beacon = beacon;
  38. }
  39. /**
  40. * @dev Returns the current implementation address of the associated beacon.
  41. */
  42. function _implementation() internal view virtual override returns (address) {
  43. return IBeacon(_getBeacon()).implementation();
  44. }
  45. /**
  46. * @dev Returns the beacon.
  47. */
  48. function _getBeacon() internal view virtual returns (address) {
  49. return _beacon;
  50. }
  51. }