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

Remove Release contract #168

Merged

Conversation

facuspagnuolo
Copy link
Contributor

@facuspagnuolo facuspagnuolo commented Jun 13, 2018

Fixes #69

I removed the Release contract and its JS wrappers.
I refactored a the rest of JS wrappers architecture in order to represent the real hierarchy we have of directory contracts.

@facuspagnuolo facuspagnuolo requested review from frangio and fiiiu June 13, 2018 03:54
@facuspagnuolo facuspagnuolo added the status:review PR waiting for review label Jun 13, 2018
Copy link
Contributor

@fiiiu fiiiu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partial Review: solidity code and modified tests LGTM, plz see minor comments.

@@ -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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two minor style things here:

  • The @dev in lines after the first was deliberately removed in a prior round of editing. @ElOpio plz confirm that we do not want them there.
  • I believe the max-len for lines is 120 (as per this), but again, someone from #static should check.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding @dev there is a good explanation about it here: OpenZeppelin/openzeppelin-contracts#995 (comment)

Copy link
Contributor

@frangio frangio Jun 13, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the comments about max-len. These are all below 120. @fiiiu Can you clarify what change you're suggesting, if any?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I was unclear, I was simply asking whether the max-len is indeed 120, because these comments were recently edited (and split in several lines) by @ElOpio, who is on top of the style guides..

If it is indeed 120, it's good as it is (in the PR).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh! But I did suggest removing the second @dev.

stdlib = _stdlib;
}

/**
* @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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

* @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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See max-len comment above, also other instances below.

*/
function changeDeveloper(address newDeveloper) external onlyDeveloper {
require(newDeveloper != address(0));
emit DeveloperChanged(developer, newDeveloper);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

emit after the change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I followed what we did in AdminUpgradeabilityProxy

function changeAdmin(address newAdmin) external ifAdmin {
require(newAdmin != address(0));
emit AdminChanged(_admin(), newAdmin);
_setAdmin(newAdmin);
}

should we change that too?

* @dev It sets the the developer of this implementation directory.
*/
function ImplementationDirectory(address _developer) public {
developer = _developer;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Release, the developer was set to msg.sender, thus the owner and the developer were the same. Here, they can be independently modified.

Maybe the gist of this PR includes separating these two, but it's not clear from the issue (#69), and I'm yet to see a place where this is actually used. I believe this was relevant in the context of an app's stdlib.. but still, are we adding functionality or we just need an alias? (In an AppDirectory, there will now be: 1) its owner, 2) its developer, 3) its stdlib owner, and 4) its stdlib developer.. )

Copy link
Contributor Author

@facuspagnuolo facuspagnuolo Jun 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly, that was intentional...
IMO, having just an alias doesn't make much sense. We are now making possible to have an owner responsible to set/unset implementations and additionally a developer, that in a future could receive payouts for a stdlib. However, it's just an idea, we can make these two the same address

@zeppelinos zeppelinos deleted a comment from coveralls Jun 13, 2018
@facuspagnuolo facuspagnuolo force-pushed the feature/add_developer_to_implementation_directories branch 3 times, most recently from 7383b4a to 650e7e4 Compare June 14, 2018 16:31
@facuspagnuolo
Copy link
Contributor Author

please @fiiiu review again 🙏

Copy link
Contributor

@frangio frangio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit uncomfortable with the duplication of code in the PackageWith... classes (and their long names). Can we merge them into a common abstraction parameterized by the type of package that they use?

I haven't reviewed the tests. I think this PR is in going in the right direction by abstracting the directory logic of a package into the newVersion function. I would be interested in exploring a bit further the possibility to reduce code duplication across the different package types.

@@ -37,7 +37,7 @@ export default class App {
this.txParams = txParams
}

address() {
get address() {
return this._app.address
Copy link
Contributor

@frangio frangio Jun 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the type of this._app here? We need some inline documentation in these files.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_app is the PackagedApp contract
We have another issue to tackle inline doc for the lib

src/app/App.js Outdated
log.info(`Setting stdlib ${stdlibAddress}...`)
await this.currentDirectory().setStdlib(stdlibAddress, this.txParams)
return stdlibAddress
return this.currentDirectory().setStdlib(stdlibAddress)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this return a tx receipt? Shouldn't we be hiding that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore this. I was wrong.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the directory is a wrapped AppDirectory here, it will return the address directly


static async fetch(address, txParams = {}) {
const provider = new PackageProvider(txParams)
return await provider.fetchForFrezzableDirectories(address)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo here: Frezzable

Copy link
Contributor

@fiiiu fiiiu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solidity code and modified tests LGTM!

@@ -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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh! But I did suggest removing the second @dev.

stdlib = _stdlib;
}

/**
* @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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

@@ -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}`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the record the convention afaict was to log.info("Doing x") and then log.info(" Did x") with the space in the beginning to hint at its relation to the previous log message. (I opened #172 to replace all this by something nicer.)

@frangio frangio closed this Jun 14, 2018
@frangio frangio reopened this Jun 14, 2018
@facuspagnuolo facuspagnuolo force-pushed the feature/add_developer_to_implementation_directories branch from ecfccbf to b6bce97 Compare June 15, 2018 16:27
@facuspagnuolo
Copy link
Contributor Author

@frangio thanks for reviewing, I addressed your comments, please review again 🙏

@facuspagnuolo facuspagnuolo force-pushed the feature/add_developer_to_implementation_directories branch 2 times, most recently from b6bce97 to 7751751 Compare June 15, 2018 22:21
@frangio
Copy link
Contributor

frangio commented Jun 16, 2018

@facuspagnuolo It's not necessary to use npx because npm runs its scripts with the proper $PATH so as to find the local modules first.

@facuspagnuolo facuspagnuolo force-pushed the feature/add_developer_to_implementation_directories branch from 0432aea to f3d3d20 Compare June 16, 2018 21:49
@facuspagnuolo
Copy link
Contributor Author

I know @frangio, I was just trying to see if Travis stops complaining about not finding dependencies

@facuspagnuolo facuspagnuolo force-pushed the feature/add_developer_to_implementation_directories branch from f3d3d20 to 51e0899 Compare June 17, 2018 22:53
@frangio
Copy link
Contributor

frangio commented Jun 17, 2018

I'm going to take a shot at fixing the broken build.

@frangio
Copy link
Contributor

frangio commented Jun 18, 2018

I deleted all caches on Travis and it is working now. Very weird.

@facuspagnuolo
Copy link
Contributor Author

Thanks @frangio !

@facuspagnuolo facuspagnuolo force-pushed the feature/add_developer_to_implementation_directories branch from ddb0708 to 6fe5ccc Compare June 18, 2018 13:30
@facuspagnuolo facuspagnuolo force-pushed the feature/add_developer_to_implementation_directories branch from 6fe5ccc to 14a7960 Compare June 18, 2018 13:45
@frangio frangio changed the title Add developer to implementation directories Remove Release contract Jun 18, 2018
Copy link
Contributor

@frangio frangio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we discussed offline, there are a few places where the JS wrappers reimplement logic that should be delegated to the smart contract.

I found this PR to be too large. I did my best reviewing and I think the pull request is ok, but I can't be too confident about it. There are too many changes to focus on given the limited time that I have and my lack of knowledged of the codebase. Can we try to aim for smaller PRs next time? 🙂

@@ -37,7 +37,7 @@ export default class App {
this.txParams = txParams
}

address() {
get address() {
return this._app.address
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is backwards-incompatible, for the record.

src/app/App.js Outdated
@@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be delegated to the smart contract instead of duplicating the logic.

return new Release(releaseAddress)
async getImplementation(version, contractName) {
const implementationDirectory = await this.getImplementationDirectory(version)
return implementationDirectory.getImplementation(contractName)
Copy link
Contributor

@frangio frangio Jun 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be delegated to the smart contract as well.

src/app/App.js Outdated
async newVersion(version, stdlibAddress = 0x0) {
const directory = await this.package.newVersion(version, stdlibAddress)
await this._app.setVersion(version, this.txParams)
log.info(`Version set`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This message could be a bit more informative like Version ${version} set in app.

src/app/App.js Outdated
const directory = await this.package.newVersion(version, stdlibAddress)
await this._app.setVersion(version, this.txParams)
log.info(`Version set`)
this.directories[version] = directory
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this.directories at all? It's apparently only used in currentDirectory, which duplicates the smart contract logic of BaseApp#getProvider.

this.txParams = txParams
}

async fetch(address) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this async if there is nothing asynchronous in its body? For comparison, PackageProvider#fetch isn't async.


async freeze() {
this.log.info('Freezing implementation directory...')
await this.directory.freeze(this.txParams)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should log "Frozen" after the await.

log.info('Registering implementation in release...')
await this.release.setImplementation(contractAlias, implementation.address, this.txParams)
log.info('Registering implementation in implementation directory...')
await this.directory.setImplementation(contractAlias, implementation.address, this.txParams)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should log something after the await as well.

FreezableImplementationDirectory,
AppDirectory,
PackageWithAppDirectories,
PackageWithNonFreezableDirectories,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to simplify the external interface. We can discuss it in another issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree

@@ -14,7 +14,7 @@ const DEFAULT_COVERAGE_TX_PARAMS = {

export default {
getFromLocal(contractName) {
const buildDir = `${process.cwd()}/build/contracts/`
const buildDir = `${process.cwd()}/build/contracts`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's try to keep these random changes out of random PRs. 😅

@facuspagnuolo facuspagnuolo force-pushed the feature/add_developer_to_implementation_directories branch from 5cc5a4f to 34c46a4 Compare June 18, 2018 19:46
@facuspagnuolo
Copy link
Contributor Author

facuspagnuolo commented Jun 18, 2018

Thanks a lot for the review @frangio! Comments addressed. Regarding the Package interface, I do agree. I pushed another PR to reduce the interface the user should care about. We are now exporting just one object, and the user is free to choose which type of directory will be using, otherwise, AppDirectory will be used by default

@@ -32,12 +32,11 @@ contract('App', function ([_, owner]) {

it('initializes all app properties', async function () {
this.app.version.should.eq(initialVersion);
this.app.directories.should.have.key(initialVersion);
this.app.directory.should.not.be.null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type of assertion doesn't work because if this.app.directory is ever null, it will fail with "cannot access property should of null".

I've used should.exist(this.app.directory) before, but you need to const should = require('chai').should() at the beginning of the file, or we could export it from the setup and do const should = require('../../setup');.

Additionally, this probably only checks for null but we don't want it to be undefined either.

@facuspagnuolo facuspagnuolo merged commit fb74556 into development Jun 19, 2018
@facuspagnuolo facuspagnuolo deleted the feature/add_developer_to_implementation_directories branch June 19, 2018 16:13
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
status:review PR waiting for review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants