Proxy.sol 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts v4.4.0 (proxy/Proxy.sol)
  3. pragma solidity ^0.8.0;
  4. /**
  5. * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
  6. * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
  7. * be specified by overriding the virtual {_implementation} function.
  8. *
  9. * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
  10. * different contract through the {_delegate} function.
  11. *
  12. * The success and return data of the delegated call will be returned back to the caller of the proxy.
  13. */
  14. abstract contract Proxy {
  15. /**
  16. * @dev Delegates the current call to `implementation`.
  17. *
  18. * This function does not return to its internall call site, it will return directly to the external caller.
  19. */
  20. function _delegate(address implementation) internal virtual {
  21. assembly {
  22. // Copy msg.data. We take full control of memory in this inline assembly
  23. // block because it will not return to Solidity code. We overwrite the
  24. // Solidity scratch pad at memory position 0.
  25. calldatacopy(0, 0, calldatasize())
  26. // Call the implementation.
  27. // out and outsize are 0 because we don't know the size yet.
  28. let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
  29. // Copy the returned data.
  30. returndatacopy(0, 0, returndatasize())
  31. switch result
  32. // delegatecall returns 0 on error.
  33. case 0 {
  34. revert(0, returndatasize())
  35. }
  36. default {
  37. return(0, returndatasize())
  38. }
  39. }
  40. }
  41. /**
  42. * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
  43. * and {_fallback} should delegate.
  44. */
  45. function _implementation() internal view virtual returns (address);
  46. /**
  47. * @dev Delegates the current call to the address returned by `_implementation()`.
  48. *
  49. * This function does not return to its internall call site, it will return directly to the external caller.
  50. */
  51. function _fallback() internal virtual {
  52. _beforeFallback();
  53. _delegate(_implementation());
  54. }
  55. /**
  56. * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
  57. * function in the contract matches the call data.
  58. */
  59. fallback() external payable virtual {
  60. _fallback();
  61. }
  62. /**
  63. * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
  64. * is empty.
  65. */
  66. receive() external payable virtual {
  67. _fallback();
  68. }
  69. /**
  70. * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
  71. * call, or as part of the Solidity `fallback` or `receive` functions.
  72. *
  73. * If overriden should call `super._beforeFallback()`.
  74. */
  75. function _beforeFallback() internal virtual {}
  76. }