Skip to content
This repository has been archived by the owner on Jan 24, 2022. It is now read-only.

Commit

Permalink
Rename: zos-lib contracts and zos command (#1074)
Browse files Browse the repository at this point in the history
* Update contract names and references in code

* Fix comment reference

* Export admin & implementation slots references

* Reference deprecated and now slot reference
for both admin and implementation slots

* Change bin name from zos to oz, and add aliases

* Change admin and implementation keccak256 values

* Fix leaked log in Bytecode.ts

* Change some oz bin reference names

* Uncomment tests

* Remove commented code in contracts

* Add check new proxy slots labels in tests

* Add deprecated warning when calling `zos` bin

* Change comment syntax

* Use eip1967 for admin and implementation slots

* Add legacy contracts as mocks for tests

* Set eip1967 storage slots labels in Constants

* Update packages/cli/src/bin/oz-cli.ts

Co-Authored-By: Santiago Palladino <santiago@openzeppelin.com>

* Enhance tests

* Rollback changes in < 2.x deprecated contract
  • Loading branch information
jbcarpanelli committed Jul 11, 2019
1 parent 7273429 commit 71c9ad7
Show file tree
Hide file tree
Showing 38 changed files with 524 additions and 117 deletions.
6 changes: 3 additions & 3 deletions examples/first-project/scripts/test-ci.sh
Expand Up @@ -6,14 +6,14 @@ ganache_port=9555

# Lerna bootstrap is failing to create the symlink in node_modules/.bin in the CI for some reason
# When fixed, we should change the line below to zos="node_modules/.bin/zos"
zos="node node_modules/zos/lib/bin/zos-cli.js"
zos="node node_modules/zos/lib/bin/oz-cli.js"

cleanup() {
if [ -n "$ganache_pid" ] && ps -p $ganache_pid > /dev/null; then
kill -9 $ganache_pid
fi

rm -f zos.dev-4447.json
rm -f ./openzeppelin/dev-4447.json
}

start_ganache() {
Expand All @@ -36,4 +36,4 @@ if [ "$RESULT" != "20" ]; then
exit 1
fi

echo $RESULT
echo $RESULT
6 changes: 4 additions & 2 deletions packages/cli/package.json
Expand Up @@ -8,7 +8,7 @@
"scripts": {
"copy-files": "./scripts/copy-files.sh",
"compile-ts": "rm -rf lib && tsc",
"prepare": "npm run compile-ts && npm run copy-files && chmod 755 ./lib/bin/zos-cli.js",
"prepare": "npm run compile-ts && npm run copy-files && chmod 755 ./lib/bin/oz-cli.js",
"test": "./scripts/test.sh",
"gen-docs": "./scripts/gen-docs.sh",
"watch": "tsc -w",
Expand All @@ -25,7 +25,9 @@
}
},
"bin": {
"zos": "./lib/bin/zos-cli.js"
"openzeppelin": "./lib/bin/oz-cli.js",
"oz": "./lib/bin/oz-cli.js",
"zos": "./lib/bin/oz-cli.js"
},
"files": [
"lib"
Expand Down
Expand Up @@ -10,7 +10,7 @@ import { LOCK_FILE_PATH, OPEN_ZEPPELIN_FOLDER } from '../models/files/constants'

const IGNORED_COMMANDS_IN_ROOT_DIR = ['init', 'unpack'];

const [nodePath, zosPath, command] = process.argv;
const [nodePath, binPath, command] = process.argv;

if (!IGNORED_COMMANDS_IN_ROOT_DIR.includes(command)) {
const currentPath = process.cwd();
Expand All @@ -32,5 +32,14 @@ try {

Loggy.silent(false);

if (binPath.match(/zos$/)) {
Loggy.noSpin.warn(
__filename,
'oz-cli',
`deprecated-zos-bin`,
`'zos' command is deprecated and will be removed in the next major version. Please use 'openzeppelin' or 'oz' instead.`,
);
}

program.parse(process.argv);
if (program.args.length === 0) program.help();
4 changes: 3 additions & 1 deletion packages/cli/src/bin/program.ts
Expand Up @@ -30,7 +30,9 @@ commandsList = commandsList.filter(c => c.name !== 'status');
const maxLength: number = Math.max(...commandsList.map(command => command.signature.length));

program
.name('zos')
.name('openzeppelin')
.alias('oz')
.alias('zos')
.usage('<command> [options]')
.description(`where <command> is one of: ${commandsList.map(c => c.name).join(', ')}`)
.version(version, '--version')
Expand Down
2 changes: 0 additions & 2 deletions packages/cli/test/scripts/migrate.test.js
Expand Up @@ -12,8 +12,6 @@ import setAdmin from '../../src/scripts/set-admin';
import ProjectFile from '../../src/models/files/ProjectFile';
import NetworkFile from '../../src/models/files/NetworkFile';

const should = require('chai').should();

const Package = Contracts.getFromLib('Package');
const DeprecatedApp = Contracts.getFromLib('DeprecatedApp');
const ImplementationDirectory = Contracts.getFromLib('ImplementationDirectory');
Expand Down
2 changes: 1 addition & 1 deletion packages/lib/contracts/application/App.sol
Expand Up @@ -10,7 +10,7 @@ import "../ownership/Ownable.sol";
* @dev Contract for upgradeable applications.
* It handles the creation of proxies.
*/
contract App is ZOSLibOwnable {
contract App is OpenZeppelinUpgradesOwnable {
/**
* @dev Emitted when a new proxy is created.
* @param proxy Address of the created proxy.
Expand Down
Expand Up @@ -8,7 +8,7 @@ import '../utils/Address.sol';
* @title ImplementationDirectory
* @dev Implementation provider that stores contract implementations in a mapping.
*/
contract ImplementationDirectory is ImplementationProvider, ZOSLibOwnable {
contract ImplementationDirectory is ImplementationProvider, OpenZeppelinUpgradesOwnable {
/**
* @dev Emitted when the implementation of a contract is changed.
* @param contractName Name of the contract.
Expand Down Expand Up @@ -59,7 +59,7 @@ contract ImplementationDirectory is ImplementationProvider, ZOSLibOwnable {
* @param implementation Address of the implementation.
*/
function setImplementation(string memory contractName, address implementation) public onlyOwner whenNotFrozen {
require(ZOSLibAddress.isContract(implementation), "Cannot set implementation in directory with a non-contract address");
require(OpenZeppelinUpgradesAddress.isContract(implementation), "Cannot set implementation in directory with a non-contract address");
implementations[contractName] = implementation;
emit ImplementationChanged(contractName, implementation);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/lib/contracts/application/Package.sol
Expand Up @@ -9,7 +9,7 @@ import "../ownership/Ownable.sol";
* plus an optional content URI with metadata. Note that the semver identifier is restricted
* to major, minor, and patch, as prerelease tags are not supported.
*/
contract Package is ZOSLibOwnable {
contract Package is OpenZeppelinUpgradesOwnable {
/**
* @dev Emitted when a version is added to the package.
* @param semanticVersion Name of the added version.
Expand Down
4 changes: 2 additions & 2 deletions packages/lib/contracts/cryptography/ECDSA.sol
Expand Up @@ -12,7 +12,7 @@ pragma solidity ^0.5.2;
* build/artifacts folder) as well as the vanilla implementation from an openzeppelin version.
*/

library ZOSLibECDSA {
library OpenZeppelinUpgradesECDSA {
/**
* @dev Recover signer address from a message by using their signature
* @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address.
Expand Down Expand Up @@ -69,4 +69,4 @@ library ZOSLibECDSA {
// enforced by the type signature above
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
}
}
2 changes: 1 addition & 1 deletion packages/lib/contracts/mocks/DeprecatedApp.sol
Expand Up @@ -10,7 +10,7 @@ import "../ownership/Ownable.sol";
* @dev Contract for upgradeable applications.
* It handles the creation and upgrading of proxies.
*/
contract DeprecatedApp is ZOSLibOwnable {
contract DeprecatedApp is OpenZeppelinUpgradesOwnable {
/**
* @dev Emitted when a new proxy is created.
* @param proxy Address of the created proxy.
Expand Down
24 changes: 24 additions & 0 deletions packages/lib/contracts/mocks/zos/ZosAdminUpgradeabilityProxy.sol
@@ -0,0 +1,24 @@
pragma solidity ^0.5.0;

import './ZosBaseAdminUpgradeabilityProxy.sol';

/**
* @title AdminUpgradeabilityProxy
* @dev Extends from BaseAdminUpgradeabilityProxy with a constructor for
* initializing the implementation, admin, and init data.
*/
contract ZosAdminUpgradeabilityProxy is ZosBaseAdminUpgradeabilityProxy, ZosUpgradeabilityProxy {
/**
* Contract constructor.
* @param _logic address of the initial implementation.
* @param _admin Address of the proxy administrator.
* @param _data Data to send as msg.data to the implementation to initialize the proxied contract.
* It should include the signature and the parameters of the function to be called, as described in
* https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
* This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.
*/
constructor(address _logic, address _admin, bytes memory _data) ZosUpgradeabilityProxy(_logic, _data) public payable {
assert(ADMIN_SLOT == keccak256("org.zeppelinos.proxy.admin"));
_setAdmin(_admin);
}
}
120 changes: 120 additions & 0 deletions packages/lib/contracts/mocks/zos/ZosBaseAdminUpgradeabilityProxy.sol
@@ -0,0 +1,120 @@
pragma solidity ^0.5.0;

import './ZosUpgradeabilityProxy.sol';

/**
* @title BaseAdminUpgradeabilityProxy
* @dev This contract combines an upgradeability proxy with an authorization
* mechanism for administrative tasks.
* All external functions in this contract must be guarded by the
* `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity
* feature proposal that would enable this to be done automatically.
*/
contract ZosBaseAdminUpgradeabilityProxy is ZosBaseUpgradeabilityProxy {
/**
* @dev Emitted when the administration has been transferred.
* @param previousAdmin Address of the previous admin.
* @param newAdmin Address of the new admin.
*/
event AdminChanged(address previousAdmin, address newAdmin);

/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "org.zeppelinos.proxy.admin", and is
* validated in the constructor.
*/

bytes32 internal constant ADMIN_SLOT = 0x10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b;

/**
* @dev Modifier to check whether the `msg.sender` is the admin.
* If it is, it will run the function. Otherwise, it will delegate the call
* to the implementation.
*/
modifier ifAdmin() {
if (msg.sender == _admin()) {
_;
} else {
_fallback();
}
}

/**
* @return The address of the proxy admin.
*/
function admin() external ifAdmin returns (address) {
return _admin();
}

/**
* @return The address of the implementation.
*/
function implementation() external ifAdmin returns (address) {
return _implementation();
}

/**
* @dev Changes the admin of the proxy.
* Only the current admin can call this function.
* @param newAdmin Address to transfer proxy administration to.
*/
function changeAdmin(address newAdmin) external ifAdmin {
require(newAdmin != address(0), "Cannot change the admin of a proxy to the zero address");
emit AdminChanged(_admin(), newAdmin);
_setAdmin(newAdmin);
}

/**
* @dev Upgrade the backing implementation of the proxy.
* Only the admin can call this function.
* @param newImplementation Address of the new implementation.
*/
function upgradeTo(address newImplementation) external ifAdmin {
_upgradeTo(newImplementation);
}

/**
* @dev Upgrade the backing implementation of the proxy and call a function
* on the new implementation.
* This is useful to initialize the proxied contract.
* @param newImplementation Address of the new implementation.
* @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
* https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
*/
function upgradeToAndCall(address newImplementation, bytes calldata data) payable external ifAdmin {
_upgradeTo(newImplementation);
(bool success,) = newImplementation.delegatecall(data);
require(success);
}

/**
* @return The admin slot.
*/
function _admin() internal view returns (address adm) {
bytes32 slot = ADMIN_SLOT;
assembly {
adm := sload(slot)
}
}

/**
* @dev Sets the address of the proxy admin.
* @param newAdmin Address of the new proxy admin.
*/
function _setAdmin(address newAdmin) internal {
bytes32 slot = ADMIN_SLOT;

assembly {
sstore(slot, newAdmin)
}
}

/**
* @dev Only fall back when the sender is not the admin.
*/
function _willFallback() internal {
require(msg.sender != _admin(), "Cannot call fallback function from the proxy admin");
super._willFallback();
}
}
59 changes: 59 additions & 0 deletions packages/lib/contracts/mocks/zos/ZosBaseUpgradeabilityProxy.sol
@@ -0,0 +1,59 @@
pragma solidity ^0.5.0;

import '../../upgradeability/Proxy.sol';
import '../../utils/Address.sol';

/**
* @title BaseUpgradeabilityProxy
* @dev This contract implements a proxy that allows to change the
* implementation address to which it will delegate.
* Such a change is called an implementation upgrade.
*/
contract ZosBaseUpgradeabilityProxy is Proxy {
/**
* @dev Emitted when the implementation is upgraded.
* @param implementation Address of the new implementation.
*/
event Upgraded(address indexed implementation);

/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "org.zeppelinos.proxy.implementation", and is
* validated in the constructor.
*/
bytes32 internal constant IMPLEMENTATION_SLOT = 0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3;

/**
* @dev Returns the current implementation.
* @return Address of the current implementation
*/
function _implementation() internal view returns (address impl) {
bytes32 slot = IMPLEMENTATION_SLOT;
assembly {
impl := sload(slot)
}
}

/**
* @dev Upgrades the proxy to a new implementation.
* @param newImplementation Address of the new implementation.
*/
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}

/**
* @dev Sets the implementation address of the proxy.
* @param newImplementation Address of the new implementation.
*/
function _setImplementation(address newImplementation) internal {
require(OpenZeppelinUpgradesAddress.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address");

bytes32 slot = IMPLEMENTATION_SLOT;

assembly {
sstore(slot, newImplementation)
}
}
}
@@ -0,0 +1,27 @@
pragma solidity ^0.5.0;

import './ZosBaseAdminUpgradeabilityProxy.sol';
import './ZosInitializableUpgradeabilityProxy.sol';

/**
* @title InitializableAdminUpgradeabilityProxy
* @dev Extends from BaseAdminUpgradeabilityProxy with an initializer for
* initializing the implementation, admin, and init data.
*/
contract ZosInitializableAdminUpgradeabilityProxy is ZosBaseAdminUpgradeabilityProxy, ZosInitializableUpgradeabilityProxy {
/**
* Contract initializer.
* @param _logic address of the initial implementation.
* @param _admin Address of the proxy administrator.
* @param _data Data to send as msg.data to the implementation to initialize the proxied contract.
* It should include the signature and the parameters of the function to be called, as described in
* https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
* This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.
*/
function initialize(address _logic, address _admin, bytes memory _data) public payable {
require(_implementation() == address(0));
ZosInitializableUpgradeabilityProxy.initialize(_logic, _data);
assert(ADMIN_SLOT == keccak256("org.zeppelinos.proxy.admin"));
_setAdmin(_admin);
}
}

0 comments on commit 71c9ad7

Please sign in to comment.