Proxy.sol 3.1 KB

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