Skip to content
This repository has been archived by the owner on Jul 11, 2019. It is now read-only.

Commit

Permalink
Merge 242de59 into 15203e3
Browse files Browse the repository at this point in the history
  • Loading branch information
facuspagnuolo committed Jun 16, 2018
2 parents 15203e3 + 242de59 commit 07cb8f7
Show file tree
Hide file tree
Showing 37 changed files with 872 additions and 520 deletions.
9 changes: 3 additions & 6 deletions contracts/application/AppDirectory.sol
Expand Up @@ -7,8 +7,7 @@ import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
/**
* @title AppDirectory
* @dev Implementation directory with a standard library as a fallback provider.
* If the implementation is not found in the directory, it will search in the
* standard library.
* @dev If the implementation is not found in the directory, it will search in the standard library.
*/
contract AppDirectory is ImplementationDirectory {
/**
Expand All @@ -32,11 +31,9 @@ contract AppDirectory is ImplementationDirectory {

/**
* @dev Returns the implementation address for a given contract name.
* If the implementation is not found in the directory, it will search in the
* standard library.
* @dev If the implementation is not found in the directory, it will search in the standard library.
* @param contractName Name of the contract.
* @return Address where the contract is implemented, or 0 if it is not
* found.
* @return Address where the contract is implemented, or 0 if it is not found.
*/
function getImplementation(string contractName) public view returns (address) {
address implementation = super.getImplementation(contractName);
Expand Down
41 changes: 19 additions & 22 deletions contracts/application/BaseApp.sol
Expand Up @@ -38,6 +38,23 @@ contract BaseApp is Ownable {
return getProvider().getImplementation(contractName);
}

/**
* @dev Returns the current implementation of a proxy.
* This is needed because only the proxy admin can query it.
* @return The address of the current implementation of the proxy.
*/
function getProxyImplementation(AdminUpgradeabilityProxy proxy) public view returns (address) {
return proxy.implementation();
}

/**
* @dev Returns the admin of a proxy. Only the admin can query it.
* @return The address of the current admin of the proxy.
*/
function getProxyAdmin(AdminUpgradeabilityProxy proxy) public view returns (address) {
return proxy.admin();
}

/**
* @dev Creates a new proxy for the given contract.
* @param contractName Name of the contract.
Expand All @@ -53,8 +70,7 @@ contract BaseApp is Ownable {
* This is useful to initialize the proxied contract.
* @param contractName Name of the contract.
* @param data Data to send as msg.data in the low level call.
* It should include the signature and the parameters of the function to be
* called, as described in
* It should include the signature and the parameters of the function to be called, as described in
* https://solidity.readthedocs.io/en/develop/abi-spec.html#function-selector-and-argument-encoding.
* @return Address of the new proxy.
*/
Expand All @@ -79,30 +95,11 @@ contract BaseApp is Ownable {
* @param proxy Proxy to be upgraded.
* @param contractName Name of the contract.
* @param data Data to send as msg.data in the low level call.
* It should include the signature and the parameters of the function to be
* called, as described in
* It should include the signature and the parameters of the function to be called, as described in
* https://solidity.readthedocs.io/en/develop/abi-spec.html#function-selector-and-argument-encoding.
*/
function upgradeAndCall(AdminUpgradeabilityProxy proxy, string contractName, bytes data) payable public onlyOwner {
address implementation = getImplementation(contractName);
proxy.upgradeToAndCall.value(msg.value)(implementation, data);
}

/**
* @dev Returns the current implementation of a proxy.
* This is needed because only the proxy admin can query it.
* @return The address of the current implementation of the proxy.
*/
function getProxyImplementation(AdminUpgradeabilityProxy proxy) public view returns (address) {
return proxy.implementation();
}

/**
* @dev Returns the admin of a proxy.
* Only the admin can query it.
* @return The address of the current admin of the proxy.
*/
function getProxyAdmin(AdminUpgradeabilityProxy proxy) public view returns (address) {
return proxy.admin();
}
}
Expand Up @@ -6,7 +6,7 @@ import "./ImplementationDirectory.sol";
* @title FreezableImplementationDirectory
* @dev Implementation directory which can be made irreversibly immutable by the owner.
*/
contract FreezableImplementationDirectory is ImplementationDirectory {
contract FreezableImplementationDirectory is ImplementationDirectory {
/// @dev Mutability state of the directory.
bool public frozen;

Expand Down
25 changes: 0 additions & 25 deletions contracts/application/versioning/Release.sol

This file was deleted.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -4,7 +4,7 @@
"description": "ZeppelinOS library",
"scripts": {
"test": "NODE_ENV=test scripts/test.sh",
"prepack": "truffle compile && babel src --out-dir lib"
"prepack": "npx truffle compile && npx babel-cli src --out-dir lib"
},
"repository": {
"type": "git",
Expand Down
8 changes: 4 additions & 4 deletions scripts/test.sh
Expand Up @@ -3,8 +3,8 @@ set -o errexit

run_lib_tests() {
echo "Testing root project..."
node_modules/.bin/truffle compile
node_modules/.bin/truffle test "$@"
npx truffle compile
npx truffle test "$@"
}

run_example_tests() {
Expand All @@ -17,9 +17,9 @@ run_example_tests() {

if [ "$SOLIDITY_COVERAGE" = true ]; then
echo "Measuring coverage..."
node_modules/.bin/solidity-coverage
npx solidity-coverage
if [ "$CONTINUOUS_INTEGRATION" = true ]; then
cat coverage/lcov.info | node_modules/.bin/coveralls
cat coverage/lcov.info | npx coveralls
fi
else
run_lib_tests && run_example_tests
Expand Down
39 changes: 13 additions & 26 deletions src/app/App.js
Expand Up @@ -37,7 +37,7 @@ export default class App {
this.txParams = txParams
}

address() {
get address() {
return this._app.address
}

Expand All @@ -50,40 +50,27 @@ export default class App {
}

async getImplementation(contractName) {
const directory = this.currentDirectory()
return directory.getImplementation(contractName)
return this.package.getImplementation(this.version, contractName)
}

async getProxyImplementation(proxyAddress) {
return this._app.getProxyImplementation(proxyAddress, this.txParams)
}

async setImplementation(contractClass, contractName) {
log.info(`Setting implementation of ${contractName} in directory...`)
const implementation = await contractClass.new(this.txParams)
const directory = this.currentDirectory()
await directory.setImplementation(contractName, implementation.address, this.txParams)
log.info(` Implementation set: ${implementation.address}`)
return implementation
return this.package.setImplementation(this.version, contractClass, contractName)
}

async setStdlib(stdlibAddress = 0x0) {
log.info(`Setting stdlib ${stdlibAddress}...`)
await this.currentDirectory().setStdlib(stdlibAddress, this.txParams)
return stdlibAddress
return this.currentDirectory().setStdlib(stdlibAddress)
}

async newVersion(versionName, stdlibAddress = 0) {
log.info(`Adding version ${versionName}...`)
const AppDirectory = Contracts.getFromLib('AppDirectory')
const directory = await AppDirectory.new(stdlibAddress, this.txParams)
log.info(` App directory: ${directory.address}`)
await this.package.addVersion(versionName, directory.address, this.txParams)
log.info(` Added version: ${versionName}`)
await this._app.setVersion(versionName, this.txParams)
log.info(` Version set`)
this.directories[versionName] = directory
this.version = versionName
async newVersion(version, stdlibAddress = 0x0) {
const directory = await this.package.newVersion(version, stdlibAddress)
await this._app.setVersion(version, this.txParams)
log.info(`Version set`)
this.directories[version] = directory
this.version = version
}

async createProxy(contractClass, contractName, initMethodName, initArgs) {
Expand All @@ -92,11 +79,11 @@ export default class App {
? await this._createProxy(contractName)
: await this._createProxyAndCall(contractClass, contractName, initMethodName, initArgs)

log.info(` TX receipt received: ${receipt.transactionHash}`)
log.info(`TX receipt received: ${receipt.transactionHash}`)
const UpgradeabilityProxyFactory = Contracts.getFromLib('UpgradeabilityProxyFactory')
const logs = decodeLogs(receipt.logs, UpgradeabilityProxyFactory)
const address = logs.find(l => l.event === 'ProxyCreated').args.proxy
log.info(` ${contractName} proxy: ${address}`)
log.info(`${contractName} proxy: ${address}`)
return new contractClass(address)
}

Expand All @@ -105,7 +92,7 @@ export default class App {
const { receipt } = typeof(initArgs) === 'undefined'
? await this._upgradeProxy(proxyAddress, contractName)
: await this._upgradeProxyAndCall(proxyAddress, contractClass, contractName, initMethodName, initArgs)
log.info(` TX receipt received: ${receipt.transactionHash}`)
log.info(`TX receipt received: ${receipt.transactionHash}`)
}

async _createProxy(contractName) {
Expand Down
24 changes: 7 additions & 17 deletions src/app/AppDeployer.js
Expand Up @@ -3,6 +3,8 @@
import Logger from '../utils/Logger'
import Contracts from '../utils/Contracts'
import App from './App'
import PackageDeployer from "../package/PackageDeployer";
import AppDirectoryDeployer from "../directory/AppDirectoryDeployer";

const log = new Logger('AppDeployer')

Expand All @@ -18,8 +20,7 @@ export default class AppDeployer {
async deployWithStdlib(version, stdlibAddress) {
await this.createFactory()
await this.createPackage()
await this.createAppDirectory(stdlibAddress)
await this.addVersion(version)
await this.addVersion(version, stdlibAddress)
await this.createApp(version)
return new App(this.packagedApp, this.factory, this.appDirectory, this.package, this.version, this.txParams)
}
Expand All @@ -39,23 +40,12 @@ export default class AppDeployer {
}

async createPackage() {
log.info('Deploying new Package...')
const Package = Contracts.getFromLib('Package')
this.package = await Package.new(this.txParams)
log.info(`Deployed Package ${this.package.address}`)
const deployer = new PackageDeployer(this.txParams);
this.package = await deployer.deployForAppDirectories()
}

async createAppDirectory(stdlibAddress) {
log.info('Deploying new AppDirectory...')
const AppDirectory = Contracts.getFromLib('AppDirectory')
this.appDirectory = await AppDirectory.new(stdlibAddress, this.txParams)
log.info(`Deployed AppDirectory ${this.appDirectory.address}`)
}

async addVersion(version) {
log.info('Adding new version...')
async addVersion(version, stdlibAddress) {
this.version = version
await this.package.addVersion(version, this.appDirectory.address, this.txParams)
log.info(`Added version ${version}`)
this.appDirectory = await this.package.newVersion(version, stdlibAddress)
}
}
10 changes: 5 additions & 5 deletions src/app/AppProvider.js
@@ -1,5 +1,7 @@
import Contracts from '../utils/Contracts'
import App from './App'
import PackageWithAppDirectories from "../package/PackageWithAppDirectories";
import AppDirectory from "../directory/AppDirectory";

export default class AppProvider {
constructor(txParams = {}) {
Expand All @@ -20,16 +22,14 @@ export default class AppProvider {
}

async _fetchAppDirectory() {
const AppDirectory = Contracts.getFromLib('AppDirectory')
this.version = await this.packagedApp.version()
const appDirectoryAddress = await this.package.getVersion(this.version)
this.appDirectory = new AppDirectory(appDirectoryAddress)
const appDirectory = await this.package.getImplementationDirectory(this.version)
this.appDirectory = await AppDirectory.fetch(appDirectory.address, this.txParams)
}

async _fetchPackage() {
const Package = Contracts.getFromLib('Package')
const packageAddress = await this.packagedApp.package()
this.package = new Package(packageAddress)
this.package = await PackageWithAppDirectories.fetch(packageAddress, this.txParams)
}

async _fetchFactory() {
Expand Down
35 changes: 35 additions & 0 deletions src/directory/AppDirectory.js
@@ -0,0 +1,35 @@
'use strict';

import Logger from '../utils/Logger'
import AppDirectoryDeployer from './AppDirectoryDeployer'
import ImplementationDirectory from './ImplementationDirectory'
import AppDirectoryProvider from "./AppDirectoryProvider";

export default class AppDirectory extends ImplementationDirectory {

static async fetch(address, txParams = {}) {
const provider = new AppDirectoryProvider(txParams)
return provider.fetch(address)
}

static async deploy(stdlibAddress = 0x0, txParams = {}) {
const deployer = new AppDirectoryDeployer(txParams)
return deployer.deploy(stdlibAddress)
}

constructor(directory, txParams = {}) {
const log = new Logger('AppDirectory');
super(directory, txParams, log)
}

async stdlib() {
return this.directory.stdlib()
}

async setStdlib(stdlibAddress) {
this.log.info(`Setting stdlib ${stdlibAddress}...`)
await this.directory.setStdlib(stdlibAddress, this.txParams)
this.log.info(`Stdlib ${stdlibAddress} set`)
return stdlibAddress
}
}
25 changes: 25 additions & 0 deletions src/directory/AppDirectoryDeployer.js
@@ -0,0 +1,25 @@
'use strict';

import Logger from '../utils/Logger'
import Contracts from '../utils/Contracts'
import AppDirectory from './AppDirectory'

const log = new Logger('AppDirectoryDeployer')

export default class AppDirectoryDeployer {
constructor(txParams = {}) {
this.txParams = txParams
}

async deploy(stdlibAddress = 0x0) {
await this._deployAppDirectory(stdlibAddress)
return new AppDirectory(this.directory, this.txParams)
}

async _deployAppDirectory(stdlibAddress) {
log.info('Deploying new AppDirectory...')
const AppDirectory = Contracts.getFromLib('AppDirectory')
this.directory = await AppDirectory.new(stdlibAddress, this.txParams)
log.info(`App directory created at ${this.directory.address}`)
}
}
20 changes: 20 additions & 0 deletions src/directory/AppDirectoryProvider.js
@@ -0,0 +1,20 @@
'use strict';

import Contracts from '../utils/Contracts'
import AppDirectory from './AppDirectory'

export default class AppDirectoryProvider {
constructor(txParams = {}) {
this.txParams = txParams
}

async fetch(address) {
this._fetchAppDirectory(address)
return new AppDirectory(this.directory, this.txParams)
}

_fetchAppDirectory(address) {
const AppDirectoryContract = Contracts.getFromLib('AppDirectory')
this.directory = new AppDirectoryContract(address)
}
}

0 comments on commit 07cb8f7

Please sign in to comment.