Skip to content

Commit

Permalink
feat(proxy): set up proxy framework
Browse files Browse the repository at this point in the history
  • Loading branch information
epiqueras committed Feb 21, 2018
1 parent 7035757 commit 798dd4f
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 48 deletions.
63 changes: 63 additions & 0 deletions contracts/standard/proxy/Proxy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
pragma solidity ^0.4.15;

/**
* @title Proxy
* @author Enrique Piqueras - <epiquerass@gmail.com>
* @notice A proxy contract that forwards all calls to 'implementation' and optionally keeps all storage.
*/
contract Proxy {
/* Storage */

bool public storageIsEternal;
address public implementation;

/* Constructor */

function Proxy(bool _storageIsEternal, address _implementation) public {
storageIsEternal = _storageIsEternal;
implementation = _implementation;
}

/* Fallback */

function () payable external {
require(implementation != address(0)); // Make sure address is valid

// Store necessary data for assembly in local memory
bool _storageIsEternal = storageIsEternal;
address _implementation = implementation;
bytes memory data = msg.data;

assembly {
// Start of payload raw data (skip over size slot)
let dataPtr := add(data, 0x20)

// Payload's size
let dataSize := mload(data)

// Figure out what OPCODE to use and forward call
let result
switch _storageIsEternal
case 0 { // Not eternal, use implementation's storage
result := call(gas, _implementation, callvalue, dataPtr, dataSize, 0, 0)
}
default { // Eternal, use current contract's storage
result := delegatecall(gas, _implementation, dataPtr, dataSize, 0, 0)
}

let retSize := returndatasize // Size of data returned
let retPtr := mload(0x40) // Start of free memory

returndatacopy(retPtr, 0, retSize) // Copy returned data to free memory

// Figure out wether ro revert or return with the returned data
switch result
case 0 { // Error
revert(retPtr, retSize)
}
default { // Success
return(retPtr, retSize)
}
}
}
}
82 changes: 34 additions & 48 deletions contracts/standard/proxy/VersioningProxy.sol
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
pragma solidity ^0.4.15;

import "./Proxy.sol";

/**
* @title VersioningProxy
* @author Enrique Piqueras - <epiquerass@gmail.com>
* @notice A base contract for managing the deployment of versions of another contract.
*/
contract VersioningProxy {
/* Enums */



contract VersioningProxy is Proxy {
/* Structs */

struct Deployment {
Expand All @@ -19,7 +17,14 @@ contract VersioningProxy {

/* Events */


/**
* @notice Called whenever 'stable' changes for off-chain handling.
* @param prevTag The previous 'stable' managed contract version tag.
* @param prevAddress The previous 'stable' managed contract address.
* @param nextTag The next 'stable' managed contract version tag.
* @param nextAddress The next 'stable' managed contract address.
*/
event OnStableChange(bytes32 prevTag, address prevAddress, bytes32 nextTag, address nextAddress);

/* Storage */

Expand Down Expand Up @@ -47,16 +52,12 @@ contract VersioningProxy {
/**
* @notice Constructs the version proxy with the first version of the managed contract, `firstTag`, at `firstAddress`.
* @param firstTag The version tag of the first version of the managed contract.
* @param firstAddress The address of the managed contract.
* @param firstAddress The address of the first verion of the managed contract.
*/
function VersioningProxy(bytes32 firstTag, address firstAddress) public {
function VersioningProxy(bytes32 firstTag, address firstAddress) Proxy(false, firstAddress) public {
publish(firstTag, firstAddress);
}

/* Fallback */



/* External */

/**
Expand Down Expand Up @@ -87,64 +88,49 @@ contract VersioningProxy {
/**
* @notice Publishes the next version of the managed contract, `nextTag`, at `nextAddress`.
* @param nextTag The next version tag.
* @param nextAddress The address of the managed contract.
* @param nextAddress The next address of the managed contract.
*/
function publish(bytes32 nextTag, address nextAddress) public onlyOwner {
// Save current address for handler
address prevAddress = addresses[tags[tags.length - 1]];

// Publish
tags.push(nextTag); // Push next tag
addresses[nextTag] = nextAddress; // Set next address

// Set stable
stable = Deployment({tag: nextTag, _address: nextAddress});

// Call handler
handleStableChange(prevAddress, nextAddress);
setStable(nextTag);
}

/**
* @notice Sets the value of 'stable' to the address of `publishedTag`.
* @param publishedTag The already published version tag.
* @notice Sets the value of 'stable' to the address of `nextTag`.
* @param nextTag The already published version tag.
*/
function setStable(bytes32 publishedTag) public onlyOwner {
function setStable(bytes32 nextTag) public onlyOwner {
// Make sure this version has already been published
address nextAddress = addresses[publishedTag];
address nextAddress = addresses[nextTag];
require(nextAddress != address(0));

// Save current address for handler
address prevAddress = addresses[tags[tags.length - 1]];
// Save current tag and address for handlers
bytes32 prevTag = stable.tag;
address prevAddress = stable._address;

// Set stable
stable = Deployment({tag: publishedTag, _address: nextAddress});

// Call handler
handleStableChange(prevAddress, nextAddress);
}

/* Public Views */



/* Internal */



/* Internal Views */
stable = Deployment({tag: nextTag, _address: nextAddress});

// Call handler and fire event
handleStableChange(prevTag, prevAddress, nextTag, nextAddress); // on-chain
OnStableChange(prevTag, prevAddress, nextTag, nextAddress); // off-chain

// Change proxy target
implementation = nextAddress;
}

/* Private */

/**
* @notice Called whenever 'stable' changes.
* @notice Called whenever 'stable' changes for on-chain handling.
* @param prevTag The previous 'stable' managed contract version tag.
* @param prevAddress The previous 'stable' managed contract address.
* @param nextTag The next 'stable' managed contract version tag.
* @param nextAddress The next 'stable' managed contract address.
*/
function handleStableChange(address prevAddress, address nextAddress) private;

/* Private Views */



function handleStableChange(bytes32 prevTag, address prevAddress, bytes32 nextTag, address nextAddress) private;
}

0 comments on commit 798dd4f

Please sign in to comment.