Proxy.sol 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.6.0;
  3. /**
  4. * @title Proxy
  5. * @dev Implements delegation of calls to other contracts, with proper
  6. * forwarding of return values and bubbling of failures.
  7. * It defines a fallback function that delegates all calls to the address
  8. * returned by the abstract _implementation() internal function.
  9. */
  10. abstract contract Proxy {
  11. /**
  12. * @dev Fallback function.
  13. * Implemented entirely in `_fallback`.
  14. */
  15. fallback () payable external {
  16. _fallback();
  17. }
  18. /**
  19. * @dev Receive function.
  20. * Implemented entirely in `_fallback`.
  21. */
  22. receive () payable external {
  23. _fallback();
  24. }
  25. /**
  26. * @return The Address of the implementation.
  27. */
  28. function _implementation() internal virtual view returns (address);
  29. /**
  30. * @dev Delegates execution to an implementation contract.
  31. * This is a low level function that doesn't return to its internal call site.
  32. * It will return to the external caller whatever the implementation returns.
  33. * @param implementation Address to delegate.
  34. */
  35. function _delegate(address implementation) internal {
  36. // solhint-disable-next-line no-inline-assembly
  37. assembly {
  38. // Copy msg.data. We take full control of memory in this inline assembly
  39. // block because it will not return to Solidity code. We overwrite the
  40. // Solidity scratch pad at memory position 0.
  41. calldatacopy(0, 0, calldatasize())
  42. // Call the implementation.
  43. // out and outsize are 0 because we don't know the size yet.
  44. let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
  45. // Copy the returned data.
  46. returndatacopy(0, 0, returndatasize())
  47. switch result
  48. // delegatecall returns 0 on error.
  49. case 0 { revert(0, returndatasize()) }
  50. default { return(0, returndatasize()) }
  51. }
  52. }
  53. /**
  54. * @dev Function that is run as the first thing in the fallback function.
  55. * Can be redefined in derived contracts to add functionality.
  56. * Redefinitions must call super._willFallback().
  57. */
  58. function _willFallback() internal virtual {
  59. }
  60. /**
  61. * @dev fallback implementation.
  62. * Extracted to enable manual triggering.
  63. */
  64. function _fallback() internal {
  65. _willFallback();
  66. _delegate(_implementation());
  67. }
  68. }