Guest User

Untitled

a guest
May 24th, 2016
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.26 KB | None | 0 0
  1. /**
  2. * Base contract that all upgradeable contracts should use.
  3. *
  4. * Contracts implementing this interface are all called using delegatecall from
  5. * a dispatcher. As a result, the _sizes and _dest variables are shared with the
  6. * dispatcher contract, which allows the called contract to update these at will.
  7. *
  8. * _sizes is a map of function signatures to return value sizes. Due to EVM
  9. * limitations, these need to be populated by the target contract, so the
  10. * dispatcher knows how many bytes of data to return from called functions.
  11. * Unfortunately, this makes variable-length return values impossible.
  12. *
  13. * _dest is the address of the contract currently implementing all the
  14. * functionality of the composite contract. Contracts should update this by
  15. * calling the internal function `replace`, which updates _dest and calls
  16. * `initialize()` on the new contract.
  17. *
  18. * When upgrading a contract, restrictions on permissible changes to the set of
  19. * storage variables must be observed. New variables may be added, but existing
  20. * ones may not be deleted or replaced. Changing variable names is acceptable.
  21. * Structs in arrays may not be modified, but structs in maps can be, following
  22. * the same rules described above.
  23. */
  24. contract Upgradeable {
  25. mapping(bytes4=>uint32) _sizes;
  26. address _dest;
  27.  
  28. /**
  29. * This function is called using delegatecall from the dispatcher when the
  30. * target contract is first initialized. It should use this opportunity to
  31. * insert any return data sizes in _sizes, and perform any other upgrades
  32. * necessary to change over from the old contract implementation (if any).
  33. *
  34. * Implementers of this function should either perform strictly harmless,
  35. * idempotent operations like setting return sizes, or use some form of
  36. * access control, to prevent outside callers.
  37. */
  38. function initialize();
  39.  
  40. /**
  41. * Performs a handover to a new implementing contract.
  42. */
  43. function replace(address target) internal {
  44. _dest = target;
  45. target.delegatecall(bytes4(sha3("initialize()")));
  46. }
  47. }
  48.  
  49. /**
  50. * The dispatcher is a minimal 'shim' that dispatches calls to a targeted
  51. * contract. Calls are made using 'delegatecall', meaning all storage and value
  52. * is kept on the dispatcher. As a result, when the target is updated, the new
  53. * contract inherits all the stored data and value from the old contract.
  54. */
  55. contract Dispatcher is Upgradeable {
  56. function Dispatcher(address target) {
  57. replace(target);
  58. }
  59.  
  60. function initialize() {
  61. // Should only be called by on target contracts, not on the dispatcher
  62. throw;
  63. }
  64.  
  65. function() {
  66. bytes4 sig;
  67. assembly { sig := calldataload(0) }
  68. var len = _sizes[sig];
  69. var target = _dest;
  70.  
  71. assembly {
  72. // return _dest.delegatecall(msg.data)
  73. calldatacopy(0x0, 0x0, calldatasize)
  74. delegatecall(sub(gas, 10000), target, 0x0, calldatasize, 0, len)
  75. return(0, len)
  76. }
  77. }
  78. }
  79.  
  80. contract Example is Upgradeable {
  81. uint _value;
  82.  
  83. function initialize() {
  84. _sizes[bytes4(sha3("getUint()"))] = 32;
  85. }
  86.  
  87. function getUint() returns (uint) {
  88. return _value;
  89. }
  90.  
  91. function setUint(uint value) {
  92. _value = value;
  93. }
  94. }
Add Comment
Please, Sign In to add comment