Refactor to support multiple contracts in the registry
This allows to manage different contracts (Token, Collaborator, etc.) with one registry. The registry serves as main source for all contracts and versions. Versions are independently deployed and added to the registry. From there the proxy contract's implementation can be upgraded to the new version. Currently no access control is implemented.
This commit is contained in:
parent
4051093f72
commit
6cbfc88159
@ -4,13 +4,14 @@ import './upgradeable/Upgradeable.sol';
|
|||||||
|
|
||||||
contract Token1 is Upgradeable {
|
contract Token1 is Upgradeable {
|
||||||
|
|
||||||
uint public value;
|
uint public value = 0;
|
||||||
function Token() public {
|
|
||||||
value = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function mint() public {
|
function mint() public {
|
||||||
value += 10;
|
value += 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initialize(address sender) public payable {
|
||||||
|
value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,28 +7,39 @@ pragma solidity ^0.4.18;
|
|||||||
interface IRegistry {
|
interface IRegistry {
|
||||||
/**
|
/**
|
||||||
* @dev This event will be emitted every time a new proxy is created
|
* @dev This event will be emitted every time a new proxy is created
|
||||||
|
* @param name of the contract, as specified in the registry
|
||||||
* @param proxy representing the address of the proxy created
|
* @param proxy representing the address of the proxy created
|
||||||
*/
|
*/
|
||||||
event ProxyCreated(address proxy);
|
event ProxyCreated(bytes32 name, address proxy);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev This event will be emitted every time a new implementation is registered
|
* @dev This event will be emitted every time a new implementation is registered
|
||||||
|
* @param name of the contract, as specified in the registry
|
||||||
* @param version representing the version name of the registered implementation
|
* @param version representing the version name of the registered implementation
|
||||||
* @param implementation representing the address of the registered implementation
|
* @param implementation representing the address of the registered implementation
|
||||||
*/
|
*/
|
||||||
event VersionAdded(string version, address implementation);
|
event VersionAdded(bytes32 name, uint version, address implementation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Registers a new version with its implementation address
|
* @dev Registers a new version with its implementation address
|
||||||
* @param version representing the version name of the new implementation to be registered
|
* @param name of the contract, as specified in the registry
|
||||||
* @param implementation representing the address of the new implementation to be registered
|
* @param implementation representing the address of the new implementation to be registered
|
||||||
*/
|
*/
|
||||||
function addVersion(string version, address implementation) public;
|
function addVersion(bytes32 name, address implementation) public;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Tells the address of the implementation for a given version
|
* @dev Tells the address of the implementation for a given version
|
||||||
|
* @param name of the contract, as specified in the registry
|
||||||
* @param version to query the implementation of
|
* @param version to query the implementation of
|
||||||
* @return address of the implementation registered for the given version
|
* @return address of the implementation registered for the given version
|
||||||
*/
|
*/
|
||||||
function getVersion(string version) public view returns (address);
|
function getVersion(bytes32 name, uint version) public view returns (address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Tells the latest address of the implementation
|
||||||
|
* @param name of the contract, as specified in the registry
|
||||||
|
* @return address of the implementation registered for the latest version
|
||||||
|
*/
|
||||||
|
function getLatestVersion(bytes32 name) public view returns (address);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,38 +9,60 @@ import './UpgradeabilityProxy.sol';
|
|||||||
* @dev This contract works as a registry of versions, it holds the implementations for the registered versions.
|
* @dev This contract works as a registry of versions, it holds the implementations for the registered versions.
|
||||||
*/
|
*/
|
||||||
contract Registry is IRegistry {
|
contract Registry is IRegistry {
|
||||||
// Mapping of versions to implementations of different functions
|
// mapping of contract names to versions to implementation
|
||||||
mapping (string => address) internal versions;
|
// "Token" => "1.0.0" => "0x123"
|
||||||
|
mapping(bytes32 => mapping(uint => address)) public versions;
|
||||||
|
|
||||||
|
// current version for a certain contract
|
||||||
|
mapping(bytes32 => uint) public currentVersions;
|
||||||
|
|
||||||
|
// mapping of the contract names to the proxy addresses
|
||||||
|
mapping(bytes32 => address) public proxies;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Registers a new version with its implementation address
|
* @dev Registers a new version with its implementation address
|
||||||
* @param version representing the version name of the new implementation to be registered
|
* @param name of the contract
|
||||||
* @param implementation representing the address of the new implementation to be registered
|
* @param implementation representing the address of the new implementation to be registered
|
||||||
*/
|
*/
|
||||||
function addVersion(string version, address implementation) public {
|
function addVersion(bytes32 name, address implementation) public {
|
||||||
require(versions[version] == 0x0);
|
currentVersions[name] = currentVersions[name] + 1;
|
||||||
versions[version] = implementation;
|
uint version = currentVersions[name];
|
||||||
VersionAdded(version, implementation);
|
require(versions[name][version] == 0x0);
|
||||||
|
versions[name][version] = implementation;
|
||||||
|
VersionAdded(name, version, implementation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Tells the address of the implementation for a given version
|
* @dev Tells the address of the implementation for a given version
|
||||||
|
* @param name of the contract
|
||||||
* @param version to query the implementation of
|
* @param version to query the implementation of
|
||||||
* @return address of the implementation registered for the given version
|
* @return address of the implementation registered for the given version
|
||||||
*/
|
*/
|
||||||
function getVersion(string version) public view returns (address) {
|
function getVersion(bytes32 name, uint version) public view returns (address) {
|
||||||
return versions[version];
|
return versions[name][version];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLatestVersion(bytes32 name) public view returns (address) {
|
||||||
|
uint current = currentVersions[name];
|
||||||
|
return getVersion(name, current);
|
||||||
|
}
|
||||||
|
|
||||||
|
function upgrade(bytes32 name, uint version) public {
|
||||||
|
UpgradeabilityProxy(proxies[name]).upgradeTo(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Creates an upgradeable proxy
|
* @dev Creates an upgradeable proxy
|
||||||
|
* @param name of the contract
|
||||||
* @param version representing the first version to be set for the proxy
|
* @param version representing the first version to be set for the proxy
|
||||||
* @return address of the new proxy created
|
* @return address of the new proxy created
|
||||||
*/
|
*/
|
||||||
function createProxy(string version) public payable returns (UpgradeabilityProxy) {
|
function createProxy(bytes32 name, uint version) public payable returns (UpgradeabilityProxy) {
|
||||||
UpgradeabilityProxy proxy = new UpgradeabilityProxy(version);
|
require(proxies[name] == 0x0);
|
||||||
|
UpgradeabilityProxy proxy = new UpgradeabilityProxy(name, version);
|
||||||
|
proxies[name] = address(proxy);
|
||||||
Upgradeable(proxy).initialize.value(msg.value)(msg.sender);
|
Upgradeable(proxy).initialize.value(msg.value)(msg.sender);
|
||||||
ProxyCreated(proxy);
|
ProxyCreated(name, proxy);
|
||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,10 +10,8 @@ import './UpgradeabilityStorage.sol';
|
|||||||
*/
|
*/
|
||||||
contract UpgradeabilityProxy is Proxy, UpgradeabilityStorage {
|
contract UpgradeabilityProxy is Proxy, UpgradeabilityStorage {
|
||||||
|
|
||||||
/**
|
function UpgradeabilityProxy(bytes32 _name, uint _version) public {
|
||||||
* @dev Constructor function
|
_proxiedContractName = _name;
|
||||||
*/
|
|
||||||
function UpgradeabilityProxy(string _version) public {
|
|
||||||
registry = IRegistry(msg.sender);
|
registry = IRegistry(msg.sender);
|
||||||
upgradeTo(_version);
|
upgradeTo(_version);
|
||||||
}
|
}
|
||||||
@ -22,8 +20,17 @@ contract UpgradeabilityProxy is Proxy, UpgradeabilityStorage {
|
|||||||
* @dev Upgrades the implementation to the requested version
|
* @dev Upgrades the implementation to the requested version
|
||||||
* @param _version representing the version name of the new implementation to be set
|
* @param _version representing the version name of the new implementation to be set
|
||||||
*/
|
*/
|
||||||
function upgradeTo(string _version) public {
|
function upgradeTo(uint _version) public {
|
||||||
_implementation = registry.getVersion(_version);
|
require(msg.sender == address(registry));
|
||||||
|
_implementation = registry.getVersion(_proxiedContractName, _version);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Upgrades the implementation to the latest version
|
||||||
|
*/
|
||||||
|
function upgradeToLatest() public {
|
||||||
|
require(msg.sender == address(registry));
|
||||||
|
_implementation = registry.getLatestVersion(_proxiedContractName);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,9 @@ contract UpgradeabilityStorage {
|
|||||||
// Address of the current implementation
|
// Address of the current implementation
|
||||||
address internal _implementation;
|
address internal _implementation;
|
||||||
|
|
||||||
|
// contract name
|
||||||
|
bytes32 public _proxiedContractName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Tells the address of the current implementation
|
* @dev Tells the address of the current implementation
|
||||||
* @return address of the current implementation
|
* @return address of the current implementation
|
||||||
|
5
migrations/1519035571_registry.js
Normal file
5
migrations/1519035571_registry.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
var Registry = artifacts.require('./upgradeable/Registry.sol');
|
||||||
|
|
||||||
|
module.exports = function(deployer) {
|
||||||
|
deployer.deploy(Registry);
|
||||||
|
};
|
@ -1,20 +1,12 @@
|
|||||||
var Registry = artifacts.require('./upgradeable/Registry.sol');
|
var Registry = artifacts.require('./Registry.sol');
|
||||||
|
|
||||||
var Token = artifacts.require('./Token1.sol');
|
var Token = artifacts.require('./Token1.sol');
|
||||||
|
|
||||||
module.exports = function(deployer) {
|
module.exports = function(deployer) {
|
||||||
deployer.deploy(Registry).then(function() {
|
deployer.deploy(Token).then(function(token) {
|
||||||
return Registry.deployed();
|
|
||||||
}).then(function(registry) {
|
|
||||||
return deployer.deploy(Token);
|
|
||||||
}).then(function(token) {
|
|
||||||
console.log('Registry address: ', Registry.address);
|
console.log('Registry address: ', Registry.address);
|
||||||
console.log('Token address: ', Token.address);
|
console.log('Token address: ', Token.address);
|
||||||
Registry.deployed().then(function(registry) {
|
Registry.deployed().then(function(registry) {
|
||||||
registry.addVersion('Token_1.0', Token.address);
|
registry.addVersion('Token', Token.address);
|
||||||
registry.createProxy('Token_1.0').then(function(r) {
|
|
||||||
console.log(r.logs[0]);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,7 @@ module.exports = function(deployer) {
|
|||||||
}).then(function(token) {
|
}).then(function(token) {
|
||||||
Registry.deployed().then(function(registry) {
|
Registry.deployed().then(function(registry) {
|
||||||
console.log('Token address: ', Token.address);
|
console.log('Token address: ', Token.address);
|
||||||
registry.addVersion('Token_2.0', Token.address);
|
registry.addVersion('Token', Token.address);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user