UpgradeableProxy.sol 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Integration test against the delegatecall() function in combination with input forwarding and tail call flags.
  2. // WARNING: This code is neither EIP compliant nor secure nor audited nor intended to be used in production.
  3. // SPDX-License-Identifier: MIT
  4. // OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)
  5. /**
  6. * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
  7. * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
  8. * be specified by overriding the virtual {_implementation} function.
  9. *
  10. * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
  11. * different contract through the {_delegate} function.
  12. *
  13. * The success and return data of the delegated call will be returned back to the caller of the proxy.
  14. */
  15. abstract contract Proxy {
  16. uint32 constant FORWARD_INPUT = 1;
  17. uint32 constant TAIL_CALL = 4;
  18. /**
  19. * @dev Delegates the current call to `implementation`.
  20. *
  21. * This function does not return to its internal call site. It will return directly to the external caller.
  22. */
  23. function _delegate(address implementation) internal virtual {
  24. implementation.delegatecall{flags: FORWARD_INPUT | TAIL_CALL}(hex"");
  25. }
  26. /**
  27. * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
  28. * and {_fallback} should delegate.
  29. */
  30. function _implementation() internal view virtual returns (address);
  31. /**
  32. * @dev Delegates the current call to the address returned by `_implementation()`.
  33. *
  34. * This function does not return to its internal call site. It will return directly to the external caller.
  35. */
  36. function _fallback() internal virtual {
  37. _beforeFallback();
  38. _delegate(_implementation());
  39. }
  40. /**
  41. * @dev Fallback function that delegates calls to the address returned by `_implementation()`. It will run if no other
  42. * function in the contract matches the call data.
  43. */
  44. fallback() external virtual {
  45. _fallback();
  46. }
  47. /**
  48. * @dev Fallback function that delegates calls to the address returned by `_implementation()`. It will run if call data
  49. * is empty.
  50. */
  51. receive() external payable virtual {
  52. _fallback();
  53. }
  54. /**
  55. * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
  56. * call, or as part of the Solidity `fallback` or `receive` functions.
  57. *
  58. * If overridden should call `super._beforeFallback()`.
  59. */
  60. function _beforeFallback() internal virtual {}
  61. }
  62. // FIXME: This is NOT EIP-1967.
  63. // Have to mock it this way until issues #1387 and #1388 are resolved.
  64. abstract contract StorageSlot {
  65. mapping(bytes32 => address) getAddressSlot;
  66. }
  67. // Minimal proxy implementation; without security
  68. contract UpgradeableProxy is Proxy, StorageSlot {
  69. event Upgraded(address indexed implementation);
  70. bytes32 internal constant IMPLEMENTATION_SLOT =
  71. 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
  72. function _setImplementation(address newImplementation) private {
  73. // FIXME once issue #809 (supporting address.code) is solved
  74. // if (newImplementation.code.length == 0) {
  75. // revert ERC1967InvalidImplementation(newImplementation);
  76. // }
  77. // FIXME see #1387 and #1388
  78. getAddressSlot[IMPLEMENTATION_SLOT] = newImplementation;
  79. }
  80. function upgradeTo(address newImplementation) public {
  81. _setImplementation(newImplementation);
  82. emit Upgraded(newImplementation);
  83. }
  84. function upgradeToAndCall(
  85. address newImplementation,
  86. bytes memory data
  87. ) public returns (bytes ret) {
  88. upgradeTo(newImplementation);
  89. (bool ok, ret) = newImplementation.delegatecall(data);
  90. require(ok);
  91. }
  92. function _implementation()
  93. internal
  94. view
  95. virtual
  96. override
  97. returns (address)
  98. {
  99. return getAddressSlot[IMPLEMENTATION_SLOT];
  100. }
  101. }
  102. // Proxy implementation v1
  103. contract UpgradeableImplV1 {
  104. uint public count;
  105. function inc() external {
  106. print("v1");
  107. count += 1;
  108. }
  109. }
  110. // Proxy implementation v2
  111. contract UpgradeableImplV2 {
  112. uint public count;
  113. string public version;
  114. function setVersion() public {
  115. version = "v2";
  116. }
  117. function inc() external {
  118. count += 1;
  119. }
  120. function dec() external {
  121. count -= 1;
  122. }
  123. }