diff --git a/contracts/apm/APMNamehash.sol b/contracts/apm/APMNamehash.sol deleted file mode 100644 index 69f0d0e82..000000000 --- a/contracts/apm/APMNamehash.sol +++ /dev/null @@ -1,17 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - */ - -pragma solidity ^0.4.24; - - -contract APMNamehash { - /* Hardcoded constants to save gas - bytes32 internal constant APM_NODE = keccak256(abi.encodePacked(ETH_TLD_NODE, keccak256(abi.encodePacked("aragonpm")))); - */ - bytes32 internal constant APM_NODE = 0x9065c3e7f7b7ef1ef4e53d2d0b8e0cef02874ab020c1ece79d5f0d3d0111c0ba; - - function apmNamehash(string name) internal pure returns (bytes32) { - return keccak256(abi.encodePacked(APM_NODE, keccak256(bytes(name)))); - } -} diff --git a/contracts/apm/APMRegistry.sol b/contracts/apm/APMRegistry.sol deleted file mode 100644 index 1a0ae42c4..000000000 --- a/contracts/apm/APMRegistry.sol +++ /dev/null @@ -1,112 +0,0 @@ -pragma solidity 0.4.24; - -import "../lib/ens/AbstractENS.sol"; -import "../ens/ENSSubdomainRegistrar.sol"; -import "../factory/AppProxyFactory.sol"; -import "../apps/AragonApp.sol"; -import "../acl/ACL.sol"; -import "./Repo.sol"; - - -contract APMInternalAppNames { - string internal constant APM_APP_NAME = "apm-registry"; - string internal constant REPO_APP_NAME = "apm-repo"; - string internal constant ENS_SUB_APP_NAME = "apm-enssub"; -} - - -contract APMRegistry is AragonApp, AppProxyFactory, APMInternalAppNames { - /* Hardcoded constants to save gas - bytes32 public constant CREATE_REPO_ROLE = keccak256("CREATE_REPO_ROLE"); - */ - bytes32 public constant CREATE_REPO_ROLE = 0x2a9494d64846c9fdbf0158785aa330d8bc9caf45af27fa0e8898eb4d55adcea6; - - string private constant ERROR_INIT_PERMISSIONS = "APMREG_INIT_PERMISSIONS"; - string private constant ERROR_EMPTY_NAME = "APMREG_EMPTY_NAME"; - - AbstractENS public ens; - ENSSubdomainRegistrar public registrar; - - event NewRepo(bytes32 id, string name, address repo); - - /** - * NEEDS CREATE_NAME_ROLE and POINT_ROOTNODE_ROLE permissions on registrar - * @dev Initialize can only be called once. It saves the block number in which it was initialized - * @notice Initialize this APMRegistry instance and set `_registrar` as the ENS subdomain registrar - * @param _registrar ENSSubdomainRegistrar instance that holds registry root node ownership - */ - function initialize(ENSSubdomainRegistrar _registrar) public onlyInit { - initialized(); - - registrar = _registrar; - ens = registrar.ens(); - - registrar.pointRootNode(this); - - // Check APM has all permissions it needss - ACL acl = ACL(kernel().acl()); - require(acl.hasPermission(this, registrar, registrar.CREATE_NAME_ROLE()), ERROR_INIT_PERMISSIONS); - require(acl.hasPermission(this, acl, acl.CREATE_PERMISSIONS_ROLE()), ERROR_INIT_PERMISSIONS); - } - - /** - * @notice Create new repo in registry with `_name` - * @param _name Repo name, must be ununsed - * @param _dev Address that will be given permission to create versions - */ - function newRepo(string _name, address _dev) public auth(CREATE_REPO_ROLE) returns (Repo) { - return _newRepo(_name, _dev); - } - - /** - * @notice Create new repo in registry with `_name` and publish a first version with contract `_contractAddress` and content `@fromHex(_contentURI)` - * @param _name Repo name - * @param _dev Address that will be given permission to create versions - * @param _initialSemanticVersion Semantic version for new repo version - * @param _contractAddress address for smart contract logic for version (if set to 0, it uses last versions' contractAddress) - * @param _contentURI External URI for fetching new version's content - */ - function newRepoWithVersion( - string _name, - address _dev, - uint16[3] _initialSemanticVersion, - address _contractAddress, - bytes _contentURI - ) public auth(CREATE_REPO_ROLE) returns (Repo) - { - Repo repo = _newRepo(_name, this); // need to have permissions to create version - repo.newVersion(_initialSemanticVersion, _contractAddress, _contentURI); - - // Give permissions to _dev - ACL acl = ACL(kernel().acl()); - acl.revokePermission(this, repo, repo.CREATE_VERSION_ROLE()); - acl.grantPermission(_dev, repo, repo.CREATE_VERSION_ROLE()); - acl.setPermissionManager(_dev, repo, repo.CREATE_VERSION_ROLE()); - return repo; - } - - function _newRepo(string _name, address _dev) internal returns (Repo) { - require(bytes(_name).length > 0, ERROR_EMPTY_NAME); - - Repo repo = newClonedRepo(); - - ACL(kernel().acl()).createPermission(_dev, repo, repo.CREATE_VERSION_ROLE(), _dev); - - // Creates [name] subdomain in the rootNode and sets registry as resolver - // This will fail if repo name already exists - bytes32 node = registrar.createNameAndPoint(keccak256(abi.encodePacked(_name)), repo); - - emit NewRepo(node, _name, repo); - - return repo; - } - - function newClonedRepo() internal returns (Repo repo) { - repo = Repo(newAppProxy(kernel(), repoAppId())); - repo.initialize(); - } - - function repoAppId() internal view returns (bytes32) { - return keccak256(abi.encodePacked(registrar.rootNode(), keccak256(abi.encodePacked(REPO_APP_NAME)))); - } -} diff --git a/contracts/apm/Repo.sol b/contracts/apm/Repo.sol deleted file mode 100644 index 0cb73c2a8..000000000 --- a/contracts/apm/Repo.sol +++ /dev/null @@ -1,133 +0,0 @@ -pragma solidity 0.4.24; - -import "../apps/AragonApp.sol"; - - -/* solium-disable function-order */ -// Allow public initialize() to be first -contract Repo is AragonApp { - /* Hardcoded constants to save gas - bytes32 public constant CREATE_VERSION_ROLE = keccak256("CREATE_VERSION_ROLE"); - */ - bytes32 public constant CREATE_VERSION_ROLE = 0x1f56cfecd3595a2e6cc1a7e6cb0b20df84cdbd92eff2fee554e70e4e45a9a7d8; - - string private constant ERROR_INVALID_BUMP = "REPO_INVALID_BUMP"; - string private constant ERROR_INVALID_VERSION = "REPO_INVALID_VERSION"; - string private constant ERROR_INEXISTENT_VERSION = "REPO_INEXISTENT_VERSION"; - - struct Version { - uint16[3] semanticVersion; - address contractAddress; - bytes contentURI; - } - - uint256 internal versionsNextIndex; - mapping (uint256 => Version) internal versions; - mapping (bytes32 => uint256) internal versionIdForSemantic; - mapping (address => uint256) internal latestVersionIdForContract; - - event NewVersion(uint256 versionId, uint16[3] semanticVersion); - - /** - * @dev Initialize can only be called once. It saves the block number in which it was initialized. - * @notice Initialize this Repo - */ - function initialize() public onlyInit { - initialized(); - versionsNextIndex = 1; - } - - /** - * @notice Create new version with contract `_contractAddress` and content `@fromHex(_contentURI)` - * @param _newSemanticVersion Semantic version for new repo version - * @param _contractAddress address for smart contract logic for version (if set to 0, it uses last versions' contractAddress) - * @param _contentURI External URI for fetching new version's content - */ - function newVersion( - uint16[3] _newSemanticVersion, - address _contractAddress, - bytes _contentURI - ) public auth(CREATE_VERSION_ROLE) - { - address contractAddress = _contractAddress; - uint256 lastVersionIndex = versionsNextIndex - 1; - - uint16[3] memory lastSematicVersion; - - if (lastVersionIndex > 0) { - Version storage lastVersion = versions[lastVersionIndex]; - lastSematicVersion = lastVersion.semanticVersion; - - if (contractAddress == address(0)) { - contractAddress = lastVersion.contractAddress; - } - // Only allows smart contract change on major version bumps - require( - lastVersion.contractAddress == contractAddress || _newSemanticVersion[0] > lastVersion.semanticVersion[0], - ERROR_INVALID_VERSION - ); - } - - require(isValidBump(lastSematicVersion, _newSemanticVersion), ERROR_INVALID_BUMP); - - uint256 versionId = versionsNextIndex++; - versions[versionId] = Version(_newSemanticVersion, contractAddress, _contentURI); - versionIdForSemantic[semanticVersionHash(_newSemanticVersion)] = versionId; - latestVersionIdForContract[contractAddress] = versionId; - - emit NewVersion(versionId, _newSemanticVersion); - } - - function getLatest() public view returns (uint16[3] semanticVersion, address contractAddress, bytes contentURI) { - return getByVersionId(versionsNextIndex - 1); - } - - function getLatestForContractAddress(address _contractAddress) - public - view - returns (uint16[3] semanticVersion, address contractAddress, bytes contentURI) - { - return getByVersionId(latestVersionIdForContract[_contractAddress]); - } - - function getBySemanticVersion(uint16[3] _semanticVersion) - public - view - returns (uint16[3] semanticVersion, address contractAddress, bytes contentURI) - { - return getByVersionId(versionIdForSemantic[semanticVersionHash(_semanticVersion)]); - } - - function getByVersionId(uint _versionId) public view returns (uint16[3] semanticVersion, address contractAddress, bytes contentURI) { - require(_versionId > 0 && _versionId < versionsNextIndex, ERROR_INEXISTENT_VERSION); - Version storage version = versions[_versionId]; - return (version.semanticVersion, version.contractAddress, version.contentURI); - } - - function getVersionsCount() public view returns (uint256) { - return versionsNextIndex - 1; - } - - function isValidBump(uint16[3] _oldVersion, uint16[3] _newVersion) public pure returns (bool) { - bool hasBumped; - uint i = 0; - while (i < 3) { - if (hasBumped) { - if (_newVersion[i] != 0) { - return false; - } - } else if (_newVersion[i] != _oldVersion[i]) { - if (_oldVersion[i] > _newVersion[i] || _newVersion[i] - _oldVersion[i] != 1) { - return false; - } - hasBumped = true; - } - i++; - } - return hasBumped; - } - - function semanticVersionHash(uint16[3] version) internal pure returns (bytes32) { - return keccak256(abi.encodePacked(version[0], version[1], version[2])); - } -} diff --git a/contracts/ens/ENSConstants.sol b/contracts/ens/ENSConstants.sol deleted file mode 100644 index bcbe0d982..000000000 --- a/contracts/ens/ENSConstants.sol +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - */ - -pragma solidity ^0.4.24; - - -contract ENSConstants { - /* Hardcoded constants to save gas - bytes32 internal constant ENS_ROOT = bytes32(0); - bytes32 internal constant ETH_TLD_LABEL = keccak256("eth"); - bytes32 internal constant ETH_TLD_NODE = keccak256(abi.encodePacked(ENS_ROOT, ETH_TLD_LABEL)); - bytes32 internal constant PUBLIC_RESOLVER_LABEL = keccak256("resolver"); - bytes32 internal constant PUBLIC_RESOLVER_NODE = keccak256(abi.encodePacked(ETH_TLD_NODE, PUBLIC_RESOLVER_LABEL)); - */ - bytes32 internal constant ENS_ROOT = bytes32(0); - bytes32 internal constant ETH_TLD_LABEL = 0x4f5b812789fc606be1b3b16908db13fc7a9adf7ca72641f84d75b47069d3d7f0; - bytes32 internal constant ETH_TLD_NODE = 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae; - bytes32 internal constant PUBLIC_RESOLVER_LABEL = 0x329539a1d23af1810c48a07fe7fc66a3b34fbc8b37e9b3cdb97bb88ceab7e4bf; - bytes32 internal constant PUBLIC_RESOLVER_NODE = 0xfdd5d5de6dd63db72bbc2d487944ba13bf775b50a80805fe6fcaba9b0fba88f5; -} diff --git a/contracts/ens/ENSSubdomainRegistrar.sol b/contracts/ens/ENSSubdomainRegistrar.sol deleted file mode 100644 index 9fa88113b..000000000 --- a/contracts/ens/ENSSubdomainRegistrar.sol +++ /dev/null @@ -1,124 +0,0 @@ -pragma solidity 0.4.24; - -import "../lib/ens/AbstractENS.sol"; -import "../lib/ens/PublicResolver.sol"; -import "./ENSConstants.sol"; - -import "../apps/AragonApp.sol"; - - -/* solium-disable function-order */ -// Allow public initialize() to be first -contract ENSSubdomainRegistrar is AragonApp, ENSConstants { - /* Hardcoded constants to save gas - bytes32 public constant CREATE_NAME_ROLE = keccak256("CREATE_NAME_ROLE"); - bytes32 public constant DELETE_NAME_ROLE = keccak256("DELETE_NAME_ROLE"); - bytes32 public constant POINT_ROOTNODE_ROLE = keccak256("POINT_ROOTNODE_ROLE"); - */ - bytes32 public constant CREATE_NAME_ROLE = 0xf86bc2abe0919ab91ef714b2bec7c148d94f61fdb069b91a6cfe9ecdee1799ba; - bytes32 public constant DELETE_NAME_ROLE = 0x03d74c8724218ad4a99859bcb2d846d39999449fd18013dd8d69096627e68622; - bytes32 public constant POINT_ROOTNODE_ROLE = 0x9ecd0e7bddb2e241c41b595a436c4ea4fd33c9fa0caa8056acf084fc3aa3bfbe; - - string private constant ERROR_NO_NODE_OWNERSHIP = "ENSSUB_NO_NODE_OWNERSHIP"; - string private constant ERROR_NAME_EXISTS = "ENSSUB_NAME_EXISTS"; - string private constant ERROR_NAME_DOESNT_EXIST = "ENSSUB_DOESNT_EXIST"; - - AbstractENS public ens; - bytes32 public rootNode; - - event NewName(bytes32 indexed node, bytes32 indexed label); - event DeleteName(bytes32 indexed node, bytes32 indexed label); - - /** - * @dev Initialize can only be called once. It saves the block number in which it was initialized. This contract must be the owner of the `_rootNode` node so that it can create subdomains. - * @notice Initialize this ENSSubdomainRegistrar instance with `_ens` as the root ENS registry and `_rootNode` as the node to allocate subdomains under - * @param _ens Address of ENS registry - * @param _rootNode Node to allocate subdomains under - */ - function initialize(AbstractENS _ens, bytes32 _rootNode) public onlyInit { - initialized(); - - // We need ownership to create subnodes - require(_ens.owner(_rootNode) == address(this), ERROR_NO_NODE_OWNERSHIP); - - ens = _ens; - rootNode = _rootNode; - } - - /** - * @notice Create a new ENS subdomain record for `_label` and assign ownership to `_owner` - * @param _label Label of new subdomain - * @param _owner Owner of new subdomain - * @return node Hash of created node - */ - function createName(bytes32 _label, address _owner) external auth(CREATE_NAME_ROLE) returns (bytes32 node) { - return _createName(_label, _owner); - } - - /** - * @notice Create a new ENS subdomain record for `_label` that resolves to `_target` and is owned by this ENSSubdomainRegistrar - * @param _label Label of new subdomain - * @param _target Ethereum address this new subdomain label will point to - * @return node Hash of created node - */ - function createNameAndPoint(bytes32 _label, address _target) external auth(CREATE_NAME_ROLE) returns (bytes32 node) { - node = _createName(_label, this); - _pointToResolverAndResolve(node, _target); - } - - /** - * @notice Deregister ENS subdomain record for `_label` - * @param _label Label of subdomain to deregister - */ - function deleteName(bytes32 _label) external auth(DELETE_NAME_ROLE) { - bytes32 node = getNodeForLabel(_label); - - address currentOwner = ens.owner(node); - - require(currentOwner != address(0), ERROR_NAME_DOESNT_EXIST); // fail if deleting unset name - - if (currentOwner != address(this)) { // needs to reclaim ownership so it can set resolver - ens.setSubnodeOwner(rootNode, _label, this); - } - - ens.setResolver(node, address(0)); // remove resolver so it ends resolving - ens.setOwner(node, address(0)); - - emit DeleteName(node, _label); - } - - /** - * @notice Resolve this ENSSubdomainRegistrar's root node to `_target` - * @param _target Ethereum address root node will point to - */ - function pointRootNode(address _target) external auth(POINT_ROOTNODE_ROLE) { - _pointToResolverAndResolve(rootNode, _target); - } - - function _createName(bytes32 _label, address _owner) internal returns (bytes32 node) { - node = getNodeForLabel(_label); - require(ens.owner(node) == address(0), ERROR_NAME_EXISTS); // avoid name reset - - ens.setSubnodeOwner(rootNode, _label, _owner); - - emit NewName(node, _label); - - return node; - } - - function _pointToResolverAndResolve(bytes32 _node, address _target) internal { - address publicResolver = getAddr(PUBLIC_RESOLVER_NODE); - ens.setResolver(_node, publicResolver); - - PublicResolver(publicResolver).setAddr(_node, _target); - } - - function getAddr(bytes32 node) internal view returns (address) { - address resolver = ens.resolver(node); - return PublicResolver(resolver).addr(node); - } - - function getNodeForLabel(bytes32 _label) internal view returns (bytes32) { - return keccak256(abi.encodePacked(rootNode, _label)); - } -} diff --git a/contracts/factory/APMRegistryFactory.sol b/contracts/factory/APMRegistryFactory.sol deleted file mode 100644 index 7f0aa3fd3..000000000 --- a/contracts/factory/APMRegistryFactory.sol +++ /dev/null @@ -1,142 +0,0 @@ -pragma solidity 0.4.24; - - -import "../apm/APMRegistry.sol"; -import "../apm/Repo.sol"; -import "../ens/ENSSubdomainRegistrar.sol"; - -import "./DAOFactory.sol"; -import "./ENSFactory.sol"; -import "./AppProxyFactory.sol"; - - -contract APMRegistryFactory is APMInternalAppNames { - DAOFactory public daoFactory; - APMRegistry public registryBase; - Repo public repoBase; - ENSSubdomainRegistrar public ensSubdomainRegistrarBase; - ENS public ens; - - event DeployAPM(bytes32 indexed node, address apm); - - /** - * @notice Create a new factory for deploying Aragon Package Managers (aragonPM) - * @dev Requires either a given ENS registrar or ENSFactory (used for generating a new ENS in test environments). - * @param _daoFactory Base factory for deploying DAOs - * @param _registryBase APMRegistry base contract location - * @param _repoBase Repo base contract location - * @param _ensSubBase ENSSubdomainRegistrar base contract location - * @param _ens ENS instance - * @param _ensFactory ENSFactory (used to generated a new ENS if no ENS is given) - */ - constructor( - DAOFactory _daoFactory, - APMRegistry _registryBase, - Repo _repoBase, - ENSSubdomainRegistrar _ensSubBase, - ENS _ens, - ENSFactory _ensFactory - ) public // DAO initialized without evmscript run support - { - daoFactory = _daoFactory; - registryBase = _registryBase; - repoBase = _repoBase; - ensSubdomainRegistrarBase = _ensSubBase; - - // Either the ENS address provided is used, if any. - // Or we use the ENSFactory to generate a test instance of ENS - // If not the ENS address nor factory address are provided, this will revert - ens = _ens != address(0) ? _ens : _ensFactory.newENS(this); - } - - /** - * @notice Create a new Aragon Package Manager (aragonPM) DAO, holding the `_label` subdomain from parent `_tld` and controlled by `_root` - * @param _tld The parent node of the controlled subdomain - * @param _label The subdomain label - * @param _root Manager for the new aragonPM DAO - * @return The new aragonPM's APMRegistry app - */ - function newAPM(bytes32 _tld, bytes32 _label, address _root) public returns (APMRegistry) { - bytes32 node = keccak256(abi.encodePacked(_tld, _label)); - - // Assume it is the test ENS - if (ens.owner(node) != address(this)) { - // If we weren't in test ens and factory doesn't have ownership, will fail - require(ens.owner(_tld) == address(this)); - ens.setSubnodeOwner(_tld, _label, this); - } - - Kernel dao = daoFactory.newDAO(this); - ACL acl = ACL(dao.acl()); - - acl.createPermission(this, dao, dao.APP_MANAGER_ROLE(), this); - - // Deploy app proxies - bytes memory noInit = new bytes(0); - ENSSubdomainRegistrar ensSub = ENSSubdomainRegistrar( - dao.newAppInstance( - keccak256(abi.encodePacked(node, keccak256(abi.encodePacked(ENS_SUB_APP_NAME)))), - ensSubdomainRegistrarBase, - noInit, - false - ) - ); - APMRegistry apm = APMRegistry( - dao.newAppInstance( - keccak256(abi.encodePacked(node, keccak256(abi.encodePacked(APM_APP_NAME)))), - registryBase, - noInit, - false - ) - ); - - // APMRegistry controls Repos - bytes32 repoAppId = keccak256(abi.encodePacked(node, keccak256(abi.encodePacked(REPO_APP_NAME)))); - dao.setApp(dao.APP_BASES_NAMESPACE(), repoAppId, repoBase); - - emit DeployAPM(node, apm); - - // Grant permissions needed for APM on ENSSubdomainRegistrar - acl.createPermission(apm, ensSub, ensSub.CREATE_NAME_ROLE(), _root); - acl.createPermission(apm, ensSub, ensSub.POINT_ROOTNODE_ROLE(), _root); - - // allow apm to create permissions for Repos in Kernel - bytes32 permRole = acl.CREATE_PERMISSIONS_ROLE(); - - acl.grantPermission(apm, acl, permRole); - - // Initialize - ens.setOwner(node, ensSub); - ensSub.initialize(ens, node); - apm.initialize(ensSub); - - uint16[3] memory firstVersion; - firstVersion[0] = 1; - - acl.createPermission(this, apm, apm.CREATE_REPO_ROLE(), this); - - apm.newRepoWithVersion(APM_APP_NAME, _root, firstVersion, registryBase, b("ipfs:apm")); - apm.newRepoWithVersion(ENS_SUB_APP_NAME, _root, firstVersion, ensSubdomainRegistrarBase, b("ipfs:enssub")); - apm.newRepoWithVersion(REPO_APP_NAME, _root, firstVersion, repoBase, b("ipfs:repo")); - - configureAPMPermissions(acl, apm, _root); - - // Permission transition to _root - acl.setPermissionManager(_root, dao, dao.APP_MANAGER_ROLE()); - acl.revokePermission(this, acl, permRole); - acl.grantPermission(_root, acl, permRole); - acl.setPermissionManager(_root, acl, permRole); - - return apm; - } - - function b(string memory x) internal pure returns (bytes memory y) { - y = bytes(x); - } - - // Factory can be subclassed and permissions changed - function configureAPMPermissions(ACL _acl, APMRegistry _apm, address _root) internal { - _acl.grantPermission(_root, _apm, _apm.CREATE_REPO_ROLE()); - _acl.setPermissionManager(_root, _apm, _apm.CREATE_REPO_ROLE()); - } -} diff --git a/contracts/factory/ENSFactory.sol b/contracts/factory/ENSFactory.sol deleted file mode 100644 index 51c41c671..000000000 --- a/contracts/factory/ENSFactory.sol +++ /dev/null @@ -1,38 +0,0 @@ -pragma solidity 0.4.24; - -import "../lib/ens/ENS.sol"; -import "../lib/ens/PublicResolver.sol"; -import "../ens/ENSConstants.sol"; - - -// WARNING: This is an incredibly trustful ENS deployment, do NOT use in production! -// This contract is NOT meant to be deployed to a live network. -// Its only purpose is to easily create ENS instances for testing aragonPM. -contract ENSFactory is ENSConstants { - event DeployENS(address ens); - - /** - * @notice Create a new ENS and set `_owner` as the owner of the top level domain. - * @param _owner Owner of .eth - * @return ENS - */ - function newENS(address _owner) public returns (ENS) { - ENS ens = new ENS(); - - // Setup .eth TLD - ens.setSubnodeOwner(ENS_ROOT, ETH_TLD_LABEL, this); - - // Setup public resolver - PublicResolver resolver = new PublicResolver(ens); - ens.setSubnodeOwner(ETH_TLD_NODE, PUBLIC_RESOLVER_LABEL, this); - ens.setResolver(PUBLIC_RESOLVER_NODE, resolver); - resolver.setAddr(PUBLIC_RESOLVER_NODE, resolver); - - ens.setOwner(ETH_TLD_NODE, _owner); - ens.setOwner(ENS_ROOT, _owner); - - emit DeployENS(ens); - - return ens; - } -} diff --git a/contracts/lib/ens/AbstractENS.sol b/contracts/lib/ens/AbstractENS.sol deleted file mode 100644 index ff9d98654..000000000 --- a/contracts/lib/ens/AbstractENS.sol +++ /dev/null @@ -1,26 +0,0 @@ -// See https://github.com/ensdomains/ens/blob/7e377df83f/contracts/AbstractENS.sol - -pragma solidity ^0.4.15; - - -interface AbstractENS { - function owner(bytes32 _node) public constant returns (address); - function resolver(bytes32 _node) public constant returns (address); - function ttl(bytes32 _node) public constant returns (uint64); - function setOwner(bytes32 _node, address _owner) public; - function setSubnodeOwner(bytes32 _node, bytes32 label, address _owner) public; - function setResolver(bytes32 _node, address _resolver) public; - function setTTL(bytes32 _node, uint64 _ttl) public; - - // Logged when the owner of a node assigns a new owner to a subnode. - event NewOwner(bytes32 indexed _node, bytes32 indexed _label, address _owner); - - // Logged when the owner of a node transfers ownership to a new account. - event Transfer(bytes32 indexed _node, address _owner); - - // Logged when the resolver for a node changes. - event NewResolver(bytes32 indexed _node, address _resolver); - - // Logged when the TTL of a node changes - event NewTTL(bytes32 indexed _node, uint64 _ttl); -} diff --git a/contracts/lib/ens/ENS.sol b/contracts/lib/ens/ENS.sol deleted file mode 100644 index 5ff394398..000000000 --- a/contracts/lib/ens/ENS.sol +++ /dev/null @@ -1,97 +0,0 @@ -// See https://github.com/ensdomains/ens/blob/7e377df83f/contracts/ENS.sol - -pragma solidity ^0.4.0; - - -import "./AbstractENS.sol"; - -/** - * The ENS registry contract. - */ -contract ENS is AbstractENS { - struct Record { - address owner; - address resolver; - uint64 ttl; - } - - mapping(bytes32=>Record) records; - - // Permits modifications only by the owner of the specified node. - modifier only_owner(bytes32 node) { - if (records[node].owner != msg.sender) throw; - _; - } - - /** - * Constructs a new ENS registrar. - */ - function ENS() public { - records[0].owner = msg.sender; - } - - /** - * Returns the address that owns the specified node. - */ - function owner(bytes32 node) public constant returns (address) { - return records[node].owner; - } - - /** - * Returns the address of the resolver for the specified node. - */ - function resolver(bytes32 node) public constant returns (address) { - return records[node].resolver; - } - - /** - * Returns the TTL of a node, and any records associated with it. - */ - function ttl(bytes32 node) public constant returns (uint64) { - return records[node].ttl; - } - - /** - * Transfers ownership of a node to a new address. May only be called by the current - * owner of the node. - * @param node The node to transfer ownership of. - * @param owner The address of the new owner. - */ - function setOwner(bytes32 node, address owner) only_owner(node) public { - Transfer(node, owner); - records[node].owner = owner; - } - - /** - * Transfers ownership of a subnode keccak256(node, label) to a new address. May only be - * called by the owner of the parent node. - * @param node The parent node. - * @param label The hash of the label specifying the subnode. - * @param owner The address of the new owner. - */ - function setSubnodeOwner(bytes32 node, bytes32 label, address owner) only_owner(node) public { - var subnode = keccak256(node, label); - NewOwner(node, label, owner); - records[subnode].owner = owner; - } - - /** - * Sets the resolver address for the specified node. - * @param node The node to update. - * @param resolver The address of the resolver. - */ - function setResolver(bytes32 node, address resolver) only_owner(node) public { - NewResolver(node, resolver); - records[node].resolver = resolver; - } - - /** - * Sets the TTL for the specified node. - * @param node The node to update. - * @param ttl The TTL in seconds. - */ - function setTTL(bytes32 node, uint64 ttl) only_owner(node) public { - NewTTL(node, ttl); - records[node].ttl = ttl; - } -} diff --git a/contracts/lib/ens/PublicResolver.sol b/contracts/lib/ens/PublicResolver.sol deleted file mode 100644 index f0e51ff81..000000000 --- a/contracts/lib/ens/PublicResolver.sol +++ /dev/null @@ -1,214 +0,0 @@ -// See https://github.com/ensdomains/ens/blob/7e377df83f/contracts/PublicResolver.sol - -pragma solidity ^0.4.0; - -import "./AbstractENS.sol"; - -/** - * A simple resolver anyone can use; only allows the owner of a node to set its - * address. - */ -contract PublicResolver { - bytes4 constant INTERFACE_META_ID = 0x01ffc9a7; - bytes4 constant ADDR_INTERFACE_ID = 0x3b3b57de; - bytes4 constant CONTENT_INTERFACE_ID = 0xd8389dc5; - bytes4 constant NAME_INTERFACE_ID = 0x691f3431; - bytes4 constant ABI_INTERFACE_ID = 0x2203ab56; - bytes4 constant PUBKEY_INTERFACE_ID = 0xc8690233; - bytes4 constant TEXT_INTERFACE_ID = 0x59d1d43c; - - event AddrChanged(bytes32 indexed node, address a); - event ContentChanged(bytes32 indexed node, bytes32 hash); - event NameChanged(bytes32 indexed node, string name); - event ABIChanged(bytes32 indexed node, uint256 indexed contentType); - event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y); - event TextChanged(bytes32 indexed node, string indexed indexedKey, string key); - - struct PublicKey { - bytes32 x; - bytes32 y; - } - - struct Record { - address addr; - bytes32 content; - string name; - PublicKey pubkey; - mapping(string=>string) text; - mapping(uint256=>bytes) abis; - } - - AbstractENS ens; - mapping(bytes32=>Record) records; - - modifier only_owner(bytes32 node) { - if (ens.owner(node) != msg.sender) throw; - _; - } - - /** - * Constructor. - * @param ensAddr The ENS registrar contract. - */ - function PublicResolver(AbstractENS ensAddr) public { - ens = ensAddr; - } - - /** - * Returns true if the resolver implements the interface specified by the provided hash. - * @param interfaceID The ID of the interface to check for. - * @return True if the contract implements the requested interface. - */ - function supportsInterface(bytes4 interfaceID) public pure returns (bool) { - return interfaceID == ADDR_INTERFACE_ID || - interfaceID == CONTENT_INTERFACE_ID || - interfaceID == NAME_INTERFACE_ID || - interfaceID == ABI_INTERFACE_ID || - interfaceID == PUBKEY_INTERFACE_ID || - interfaceID == TEXT_INTERFACE_ID || - interfaceID == INTERFACE_META_ID; - } - - /** - * Returns the address associated with an ENS node. - * @param node The ENS node to query. - * @return The associated address. - */ - function addr(bytes32 node) public constant returns (address ret) { - ret = records[node].addr; - } - - /** - * Sets the address associated with an ENS node. - * May only be called by the owner of that node in the ENS registry. - * @param node The node to update. - * @param addr The address to set. - */ - function setAddr(bytes32 node, address addr) only_owner(node) public { - records[node].addr = addr; - AddrChanged(node, addr); - } - - /** - * Returns the content hash associated with an ENS node. - * Note that this resource type is not standardized, and will likely change - * in future to a resource type based on multihash. - * @param node The ENS node to query. - * @return The associated content hash. - */ - function content(bytes32 node) public constant returns (bytes32 ret) { - ret = records[node].content; - } - - /** - * Sets the content hash associated with an ENS node. - * May only be called by the owner of that node in the ENS registry. - * Note that this resource type is not standardized, and will likely change - * in future to a resource type based on multihash. - * @param node The node to update. - * @param hash The content hash to set - */ - function setContent(bytes32 node, bytes32 hash) only_owner(node) public { - records[node].content = hash; - ContentChanged(node, hash); - } - - /** - * Returns the name associated with an ENS node, for reverse records. - * Defined in EIP181. - * @param node The ENS node to query. - * @return The associated name. - */ - function name(bytes32 node) public constant returns (string ret) { - ret = records[node].name; - } - - /** - * Sets the name associated with an ENS node, for reverse records. - * May only be called by the owner of that node in the ENS registry. - * @param node The node to update. - * @param name The name to set. - */ - function setName(bytes32 node, string name) only_owner(node) public { - records[node].name = name; - NameChanged(node, name); - } - - /** - * Returns the ABI associated with an ENS node. - * Defined in EIP205. - * @param node The ENS node to query - * @param contentTypes A bitwise OR of the ABI formats accepted by the caller. - * @return contentType The content type of the return value - * @return data The ABI data - */ - function ABI(bytes32 node, uint256 contentTypes) public constant returns (uint256 contentType, bytes data) { - var record = records[node]; - for(contentType = 1; contentType <= contentTypes; contentType <<= 1) { - if ((contentType & contentTypes) != 0 && record.abis[contentType].length > 0) { - data = record.abis[contentType]; - return; - } - } - contentType = 0; - } - - /** - * Sets the ABI associated with an ENS node. - * Nodes may have one ABI of each content type. To remove an ABI, set it to - * the empty string. - * @param node The node to update. - * @param contentType The content type of the ABI - * @param data The ABI data. - */ - function setABI(bytes32 node, uint256 contentType, bytes data) only_owner(node) public { - // Content types must be powers of 2 - if (((contentType - 1) & contentType) != 0) throw; - - records[node].abis[contentType] = data; - ABIChanged(node, contentType); - } - - /** - * Returns the SECP256k1 public key associated with an ENS node. - * Defined in EIP 619. - * @param node The ENS node to query - * @return x, y the X and Y coordinates of the curve point for the public key. - */ - function pubkey(bytes32 node) public constant returns (bytes32 x, bytes32 y) { - return (records[node].pubkey.x, records[node].pubkey.y); - } - - /** - * Sets the SECP256k1 public key associated with an ENS node. - * @param node The ENS node to query - * @param x the X coordinate of the curve point for the public key. - * @param y the Y coordinate of the curve point for the public key. - */ - function setPubkey(bytes32 node, bytes32 x, bytes32 y) only_owner(node) public { - records[node].pubkey = PublicKey(x, y); - PubkeyChanged(node, x, y); - } - - /** - * Returns the text data associated with an ENS node and key. - * @param node The ENS node to query. - * @param key The text data key to query. - * @return The associated text data. - */ - function text(bytes32 node, string key) public constant returns (string ret) { - ret = records[node].text[key]; - } - - /** - * Sets the text data associated with an ENS node and key. - * May only be called by the owner of that node in the ENS registry. - * @param node The node to update. - * @param key The key to set. - * @param value The text data value to set. - */ - function setText(bytes32 node, string key, string value) only_owner(node) public { - records[node].text[key] = value; - TextChanged(node, key, key); - } -} diff --git a/contracts/test/mocks/apm/APMNamehashMock.sol b/contracts/test/mocks/apm/APMNamehashMock.sol deleted file mode 100644 index f741d19a9..000000000 --- a/contracts/test/mocks/apm/APMNamehashMock.sol +++ /dev/null @@ -1,12 +0,0 @@ -pragma solidity 0.4.24; - -import "../../../apm/APMNamehash.sol"; - - -contract APMNamehashMock is APMNamehash { - function getAPMNode() external pure returns (bytes32) { return APM_NODE; } - - function getAPMNamehash(string name) external pure returns (bytes32) { - return apmNamehash(name); - } -} diff --git a/contracts/test/mocks/apm/UnsafeRepo.sol b/contracts/test/mocks/apm/UnsafeRepo.sol deleted file mode 100644 index 129d67f7c..000000000 --- a/contracts/test/mocks/apm/UnsafeRepo.sol +++ /dev/null @@ -1,13 +0,0 @@ -pragma solidity 0.4.24; - -import "../../../apm/Repo.sol"; -import "../../../apps/UnsafeAragonApp.sol"; - - -// Allows Repo to be used without a proxy or access controls -contract UnsafeRepo is Repo, UnsafeAragonApp { - // Protected actions are always performable - function canPerform(address, bytes32, uint256[]) public view returns (bool) { - return true; - } -} diff --git a/contracts/test/mocks/common/KeccakConstants.sol b/contracts/test/mocks/common/KeccakConstants.sol index 6cc9a5bb5..45f39840e 100644 --- a/contracts/test/mocks/common/KeccakConstants.sol +++ b/contracts/test/mocks/common/KeccakConstants.sol @@ -27,14 +27,6 @@ contract KeccakConstants { bytes32 public constant CREATE_PERMISSIONS_ROLE = keccak256(abi.encodePacked("CREATE_PERMISSIONS_ROLE")); bytes32 public constant EMPTY_PARAM_HASH = keccak256(abi.encodePacked(uint256(0))); - // APMRegistry - bytes32 public constant CREATE_REPO_ROLE = keccak256(abi.encodePacked("CREATE_REPO_ROLE")); - - // ENSSubdomainRegistrar - bytes32 public constant CREATE_NAME_ROLE = keccak256(abi.encodePacked("CREATE_NAME_ROLE")); - bytes32 public constant DELETE_NAME_ROLE = keccak256(abi.encodePacked("DELETE_NAME_ROLE")); - bytes32 public constant POINT_ROOTNODE_ROLE = keccak256(abi.encodePacked("POINT_ROOTNODE_ROLE")); - // EVMScriptRegistry bytes32 public constant EVMSCRIPT_REGISTRY_APP_ID = keccak256(abi.encodePacked(APM_NODE, keccak256("evmreg"))); bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); @@ -43,9 +35,6 @@ contract KeccakConstants { // EVMScriptExecutor types bytes32 public constant EVMSCRIPT_EXECUTOR_CALLS_SCRIPT = keccak256(abi.encodePacked("CALLS_SCRIPT")); - // Repo - bytes32 public constant CREATE_VERSION_ROLE = keccak256(abi.encodePacked("CREATE_VERSION_ROLE")); - // Unstructured storage bytes32 public constant initializationBlockPosition = keccak256(abi.encodePacked("aragonOS.initializable.initializationBlock")); bytes32 public constant depositablePosition = keccak256(abi.encodePacked("aragonOS.depositableStorage.depositable")); diff --git a/contracts/test/mocks/ens/ENSConstantsMock.sol b/contracts/test/mocks/ens/ENSConstantsMock.sol deleted file mode 100644 index 2c33a35bb..000000000 --- a/contracts/test/mocks/ens/ENSConstantsMock.sol +++ /dev/null @@ -1,12 +0,0 @@ -pragma solidity 0.4.24; - -import "../../../ens/ENSConstants.sol"; - - -contract ENSConstantsMock is ENSConstants { - function getEnsRoot() external pure returns (bytes32) { return ENS_ROOT; } - function getEthTldLabel() external pure returns (bytes32) { return ETH_TLD_LABEL; } - function getEthTldNode() external pure returns (bytes32) { return ETH_TLD_NODE; } - function getPublicResolverLabel() external pure returns (bytes32) { return PUBLIC_RESOLVER_LABEL; } - function getPublicResolverNode() external pure returns (bytes32) { return PUBLIC_RESOLVER_NODE; } -} diff --git a/contracts/test/mocks/factory/APMRegistryFactoryMock.sol b/contracts/test/mocks/factory/APMRegistryFactoryMock.sol deleted file mode 100644 index 594cea916..000000000 --- a/contracts/test/mocks/factory/APMRegistryFactoryMock.sol +++ /dev/null @@ -1,98 +0,0 @@ -pragma solidity 0.4.24; - -import "../../../apm/APMRegistry.sol"; -import "../../../apm/Repo.sol"; -import "../../../ens/ENSSubdomainRegistrar.sol"; - -import "../../../factory/DAOFactory.sol"; -import "../../../factory/ENSFactory.sol"; - -// Mock that doesn't grant enough permissions -// Only usable with new ENS instance - -contract APMRegistryFactoryMock is APMInternalAppNames { - DAOFactory public daoFactory; - APMRegistry public registryBase; - Repo public repoBase; - ENSSubdomainRegistrar public ensSubdomainRegistrarBase; - ENS public ens; - - constructor( - DAOFactory _daoFactory, - APMRegistry _registryBase, - Repo _repoBase, - ENSSubdomainRegistrar _ensSubBase, - ENSFactory _ensFactory - ) public - { - daoFactory = _daoFactory; - registryBase = _registryBase; - repoBase = _repoBase; - ensSubdomainRegistrarBase = _ensSubBase; - ens = _ensFactory.newENS(this); - } - - function newFailingAPM( - bytes32 _tld, - bytes32 _label, - address _root, - bool _withoutNameRole - ) - public - returns (APMRegistry) - { - // Set up ENS control - bytes32 node = keccak256(abi.encodePacked(_tld, _label)); - ens.setSubnodeOwner(_tld, _label, this); - - Kernel dao = daoFactory.newDAO(this); - ACL acl = ACL(dao.acl()); - - acl.createPermission(this, dao, dao.APP_MANAGER_ROLE(), this); - - // Deploy app proxies - bytes memory noInit = new bytes(0); - ENSSubdomainRegistrar ensSub = ENSSubdomainRegistrar( - dao.newAppInstance( - keccak256(abi.encodePacked(node, keccak256(abi.encodePacked(ENS_SUB_APP_NAME)))), - ensSubdomainRegistrarBase, - noInit, - false - ) - ); - APMRegistry apm = APMRegistry( - dao.newAppInstance( - keccak256(abi.encodePacked(node, keccak256(abi.encodePacked(APM_APP_NAME)))), - registryBase, - noInit, - false - ) - ); - - // APMRegistry controls Repos - bytes32 repoAppId = keccak256(abi.encodePacked(node, keccak256(abi.encodePacked(REPO_APP_NAME)))); - dao.setApp(dao.APP_BASES_NAMESPACE(), repoAppId, repoBase); - - // Grant permissions needed for APM on ENSSubdomainRegistrar - acl.createPermission(apm, ensSub, ensSub.POINT_ROOTNODE_ROLE(), _root); - - // Don't grant all permissions needed for APM to initialize - if (_withoutNameRole) { - acl.createPermission(apm, ensSub, ensSub.CREATE_NAME_ROLE(), _root); - } - - if (!_withoutNameRole) { - bytes32 permRole = acl.CREATE_PERMISSIONS_ROLE(); - acl.grantPermission(apm, acl, permRole); - } - - // Initialize - ens.setOwner(node, ensSub); - ensSub.initialize(ens, node); - - // This should fail since we haven't given all required permissions - apm.initialize(ensSub); - - return apm; - } -} diff --git a/package.json b/package.json index ed5f75530..d14ab0d6f 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,6 @@ "coverage": "SOLIDITY_COVERAGE=true npm run ganache-cli:test", "console": "truffle dev", "ganache-cli:test": "scripts/ganache-cli.sh", - "deploy:devnet:ens": "truffle compile && truffle exec --network devnet scripts/deploy-beta-ens.js", - "deploy:devnet:apm": "truffle compile && truffle exec --network devnet scripts/deploy-beta-apm.js", "abi:extract": "truffle-extract --output abi/ --keys abi", "bytecode:extract": "truffle-bytecode extract -o bytecode", "bytecode:extract:new": "truffle-bytecode extract -o bytecode_new", diff --git a/readme.md b/readme.md index a488211a3..73eac614c 100644 --- a/readme.md +++ b/readme.md @@ -71,13 +71,3 @@ npm test # Lint needs to pass as well npm run lint ``` - -## Deploying - -### APM -```sh -OWNER=[APM owner address] ENS=[ENS registry address] npx truffle exec --network [network] scripts/deploy-apm.js -``` - -- `ENS`: If no ENS registry address is provided, it will deploy a dummy ENS instance to the network. If the ENS registry is provided, the name `aragonpm.eth` must be owned by the deployer account. -- `OWNER`: The account that will be the initial owner of the APM registry diff --git a/scripts/deploy-apm.js b/scripts/deploy-apm.js deleted file mode 100644 index 22d79a6b2..000000000 --- a/scripts/deploy-apm.js +++ /dev/null @@ -1,141 +0,0 @@ -const namehash = require('eth-ens-namehash').hash -const keccak256 = require('js-sha3').keccak_256 - -const deployENS = require('./deploy-test-ens') -const deployDaoFactory = require('./deploy-daofactory') -const logDeploy = require('./helpers/deploy-logger') -const getAccounts = require('./helpers/get-accounts') - -const globalArtifacts = this.artifacts // Not injected unless called directly via truffle -const globalWeb3 = this.web3 // Not injected unless called directly via truffle - -const ZERO_ADDR = '0x0000000000000000000000000000000000000000' - -const defaultOwner = process.env.OWNER -const defaultDaoFactoryAddress = process.env.DAO_FACTORY -const defaultENSAddress = process.env.ENS - -module.exports = async ( - truffleExecCallback, - { - artifacts = globalArtifacts, - web3 = globalWeb3, - ensAddress = defaultENSAddress, - owner = defaultOwner, - daoFactoryAddress = defaultDaoFactoryAddress, - verbose = true - } = {} -) => { - const log = (...args) => { - if (verbose) { console.log(...args) } - } - - const APMRegistry = artifacts.require('APMRegistry') - const Repo = artifacts.require('Repo') - const ENSSubdomainRegistrar = artifacts.require('ENSSubdomainRegistrar') - - const DAOFactory = artifacts.require('DAOFactory') - const APMRegistryFactory = artifacts.require('APMRegistryFactory') - const ENS = artifacts.require('ENS') - - const tldName = 'eth' - const labelName = 'aragonpm' - const tldHash = namehash(tldName) - const labelHash = '0x'+keccak256(labelName) - const apmNode = namehash(`${labelName}.${tldName}`) - - let ens - - log('Deploying APM...') - - const accounts = await getAccounts(web3) - if (!owner) { - owner = accounts[0] - log('OWNER env variable not found, setting APM owner to the provider\'s first account') - } - log('Owner:', owner) - - if (!ensAddress) { - log('=========') - log('Missing ENS! Deploying a custom ENS...') - ens = (await deployENS(null, { artifacts, owner, verbose: false })).ens - ensAddress = ens.address - } else { - ens = ENS.at(ensAddress) - } - - log('ENS:', ensAddress) - log(`TLD: ${tldName} (${tldHash})`) - log(`Label: ${labelName} (${labelHash})`) - - log('=========') - log('Deploying APM bases...') - - const apmRegistryBase = await APMRegistry.new() - await logDeploy(apmRegistryBase, { verbose }) - const apmRepoBase = await Repo.new() - await logDeploy(apmRepoBase, { verbose }) - const ensSubdomainRegistrarBase = await ENSSubdomainRegistrar.new() - await logDeploy(ensSubdomainRegistrarBase, { verbose }) - - let daoFactory - if (daoFactoryAddress) { - daoFactory = DAOFactory.at(daoFactoryAddress) - const hasEVMScripts = await daoFactory.regFactory() !== ZERO_ADDR - - log(`Using provided DAOFactory (with${hasEVMScripts ? '' : 'out' } EVMScripts):`, daoFactoryAddress) - } else { - log('Deploying DAOFactory with EVMScripts...') - daoFactory = (await deployDaoFactory(null, { artifacts, withEvmScriptRegistryFactory: true, verbose: false })).daoFactory - } - - log('Deploying APMRegistryFactory...') - const apmFactory = await APMRegistryFactory.new( - daoFactory.address, - apmRegistryBase.address, - apmRepoBase.address, - ensSubdomainRegistrarBase.address, - ensAddress, - '0x00' - ) - await logDeploy(apmFactory, { verbose }) - - log(`Assigning ENS name (${labelName}.${tldName}) to factory...`) - - if (await ens.owner(apmNode) === accounts[0]) { - log('Transferring name ownership from deployer to APMRegistryFactory') - await ens.setOwner(apmNode, apmFactory.address) - } else { - log('Creating subdomain and assigning it to APMRegistryFactory') - try { - await ens.setSubnodeOwner(tldHash, labelHash, apmFactory.address) - } catch (err) { - console.error( - `Error: could not set the owner of '${labelName}.${tldName}' on the given ENS instance`, - `(${ensAddress}). Make sure you have ownership rights over the subdomain.` - ) - throw err - } - } - - log('Deploying APM...') - const receipt = await apmFactory.newAPM(tldHash, labelHash, owner) - - log('=========') - const apmAddr = receipt.logs.filter(l => l.event == 'DeployAPM')[0].args.apm - log('# APM:') - log('Address:', apmAddr) - log('Transaction hash:', receipt.tx) - log('=========') - - if (typeof truffleExecCallback === 'function') { - // Called directly via `truffle exec` - truffleExecCallback() - } else { - return { - apmFactory, - ens, - apm: APMRegistry.at(apmAddr), - } - } -} diff --git a/scripts/deploy-daofactory.js b/scripts/deploy-daofactory.js deleted file mode 100644 index c613bb8a7..000000000 --- a/scripts/deploy-daofactory.js +++ /dev/null @@ -1,80 +0,0 @@ -const logDeploy = require('./helpers/deploy-logger') - -const globalArtifacts = this.artifacts // Not injected unless called directly via truffle - -const ZERO_ADDR = '0x0000000000000000000000000000000000000000' - -const defaultKernelBase = process.env.KERNEL_BASE -const defaultAclBaseAddress = process.env.ACL_BASE -const defaultEvmScriptRegistryFactoryAddress = process.env.EVM_REG_FACTORY - -module.exports = async ( - truffleExecCallback, - { - artifacts = globalArtifacts, - kernelBaseAddress = defaultKernelBase, - aclBaseAddress = defaultAclBaseAddress, - evmScriptRegistryFactoryAddress = defaultEvmScriptRegistryFactoryAddress, - withEvmScriptRegistryFactory = true, - verbose = true - } = {} -) => { - const log = (...args) => { - if (verbose) { console.log(...args) } - } - - const ACL = artifacts.require('ACL') - const Kernel = artifacts.require('Kernel') - - const DAOFactory = artifacts.require('DAOFactory') - - let kernelBase - if (kernelBaseAddress) { - kernelBase = Kernel.at(kernelBaseAddress) - log(`Skipping deploying new Kernel base, using provided address: ${kernelBaseAddress}`) - } else { - kernelBase = await Kernel.new(true) // immediately petrify - await logDeploy(kernelBase, { verbose }) - } - - let aclBase - if (aclBaseAddress) { - aclBase = ACL.at(aclBaseAddress) - log(`Skipping deploying new ACL base, using provided address: ${aclBaseAddress}`) - } else { - aclBase = await ACL.new() - await logDeploy(aclBase, { verbose }) - } - - let evmScriptRegistryFactory - if (withEvmScriptRegistryFactory) { - const EVMScriptRegistryFactory = artifacts.require('EVMScriptRegistryFactory') - - if (evmScriptRegistryFactoryAddress) { - evmScriptRegistryFactory = EVMScriptRegistryFactory.at(evmScriptRegistryFactoryAddress) - log(`Skipping deploying new EVMScriptRegistryFactory, using provided address: ${evmScriptRegistryFactoryAddress}`) - } else { - evmScriptRegistryFactory = await EVMScriptRegistryFactory.new() - await logDeploy(evmScriptRegistryFactory, { verbose }) - } - } - const daoFactory = await DAOFactory.new( - kernelBase.address, - aclBase.address, - evmScriptRegistryFactory ? evmScriptRegistryFactory.address : ZERO_ADDR - ) - - await logDeploy(daoFactory, { verbose }) - - if (typeof truffleExecCallback === 'function') { - // Called directly via `truffle exec` - truffleExecCallback() - } else { - return { - aclBase, - daoFactory, - evmScriptRegistryFactory, - kernelBase, - } - } -} diff --git a/scripts/deploy-test-ens.js b/scripts/deploy-test-ens.js deleted file mode 100644 index 74efc32fc..000000000 --- a/scripts/deploy-test-ens.js +++ /dev/null @@ -1,52 +0,0 @@ -const logDeploy = require('./helpers/deploy-logger') -const getAccounts = require('./helpers/get-accounts') - -const globalArtifacts = this.artifacts // Not injected unless called directly via truffle -const globalWeb3 = this.web3 // Not injected unless called directly via truffle - -const defaultOwner = process.env.OWNER - -module.exports = async ( - truffleExecCallback, - { - artifacts = globalArtifacts, - web3 = globalWeb3, - owner = defaultOwner, - verbose = true - } = {} -) => { - const log = (...args) => { - if (verbose) { console.log(...args) } - } - - if (!owner) { - const accounts = await getAccounts(web3) - owner = accounts[0] - log(`No OWNER environment variable passed, setting ENS owner to provider's account: ${owner}`) - } - - const ENS = artifacts.require('ENS') - const ENSFactory = artifacts.require('ENSFactory') - - log('Deploying ENSFactory...') - const factory = await ENSFactory.new() - await logDeploy(factory, { verbose }) - const receipt = await factory.newENS(owner) - - const ensAddr = receipt.logs.filter(l => l.event == 'DeployENS')[0].args.ens - log('====================') - log('Deployed ENS:', ensAddr) - - log(ensAddr) - - if (typeof truffleExecCallback === 'function') { - // Called directly via `truffle exec` - truffleExecCallback() - } else { - return { - ens: ENS.at(ensAddr), - ensFactory: factory, - } - } -} - diff --git a/scripts/helpers/deploy-logger.js b/scripts/helpers/deploy-logger.js deleted file mode 100644 index d140ceb2d..000000000 --- a/scripts/helpers/deploy-logger.js +++ /dev/null @@ -1,39 +0,0 @@ -const flatten = require('truffle-flattener') -const mkdirp = require('mkdirp') -const fs = require('fs') -const path = require('path') - -const truffleConfig = require('../../truffle-config') - -const FLATTEN_DIR = './flattened_contracts' - -module.exports = async (instance, { verbose = true, flattenContracts = true } = {}) => { - const { - contractName, - sourcePath, - updatedAt: compiledAt, - compiler: { name: compilerName, version: compilerVersion } - } = instance.constructor._json - - if (flattenContracts) { - const flattenedCode = await flatten([ sourcePath ]) - mkdirp.sync(FLATTEN_DIR) - const savePath = path.join(FLATTEN_DIR, `${contractName}.sol`) - fs.writeFileSync(savePath, flattenedCode) - } - - const optimizer = truffleConfig.solc.optimizer || null - const optimizerStatus = optimizer && optimizer.enabled ? `${optimizer.runs} runs`: 'Disabled' - - if (!verbose) { - console.log(`Deployed ${contractName}: ${instance.address}`) - } else { - console.log('=========') - console.log(`# ${contractName}:`) - console.log(`Address: ${instance.address}`) - console.log(`Transaction hash: ${instance.transactionHash}`) - console.log(`Compiler: ${compilerName}@${compilerVersion} (Optimizer: ${optimizerStatus})`) - console.log(`Compiled at: ${compiledAt}`) - console.log('=========') - } -} \ No newline at end of file diff --git a/scripts/helpers/get-accounts.js b/scripts/helpers/get-accounts.js deleted file mode 100644 index faed9b85b..000000000 --- a/scripts/helpers/get-accounts.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = web3 => ( - new Promise((resolve, reject) => { - web3.eth.getAccounts((err, accounts) => { - if (err) { - return reject(err) - } - resolve(accounts) - }) - }) -) \ No newline at end of file diff --git a/test/contracts/apm/apm_namehash.js b/test/contracts/apm/apm_namehash.js deleted file mode 100644 index f34d55ac5..000000000 --- a/test/contracts/apm/apm_namehash.js +++ /dev/null @@ -1,28 +0,0 @@ -const { hash } = require('eth-ens-namehash') -const APMNamehashMock = artifacts.require('APMNamehashMock') - -contract('APM Name Hash', () => { - let apmNamehashMock - - before(async() => { - apmNamehashMock = await APMNamehashMock.new() - }) - - const assertNamehash = async (name) => { - const node = hash(name + '.aragonpm.eth') - const apmNamehash = await apmNamehashMock.getAPMNamehash(name) - assert.equal(node, apmNamehash.toString(), 'hashes do not match') - } - - it('Kernel name hash matches', async () => { - await assertNamehash('kernel') - }) - - it('ACL name hash matches', async () => { - await assertNamehash('acl') - }) - - it('EVM Registry name hash matches', async () => { - await assertNamehash('evmreg') - }) -}) diff --git a/test/contracts/apm/apm_registry.js b/test/contracts/apm/apm_registry.js deleted file mode 100644 index 79e84af5a..000000000 --- a/test/contracts/apm/apm_registry.js +++ /dev/null @@ -1,178 +0,0 @@ -const { hash } = require('eth-ens-namehash') -const { keccak_256 } = require('js-sha3') -const { assertRevert } = require('../../helpers/assertThrow') -const { getEventArgument } = require('../../helpers/events') - -const ENS = artifacts.require('ENS') -const ENSFactory = artifacts.require('ENSFactory') -const PublicResolver = artifacts.require('PublicResolver') - -const Kernel = artifacts.require('Kernel') -const ACL = artifacts.require('ACL') -const DAOFactory = artifacts.require('DAOFactory') - -const APMRegistry = artifacts.require('APMRegistry') -const ENSSubdomainRegistrar = artifacts.require('ENSSubdomainRegistrar') -const Repo = artifacts.require('Repo') -const APMRegistryFactory = artifacts.require('APMRegistryFactory') -const APMRegistryFactoryMock = artifacts.require('APMRegistryFactoryMock') - -const EMPTY_BYTES = '0x' -const ZERO_ADDR = '0x0000000000000000000000000000000000000000' - -contract('APMRegistry', ([ensOwner, apmOwner, repoDev, notOwner, someone]) => { - let baseDeployed, baseAddrs, ensFactory, apmFactory, daoFactory, ens, registry, acl - - const rootNode = hash('aragonpm.eth') - const testNode = hash('test.aragonpm.eth') - - before(async () => { - const bases = [APMRegistry, Repo, ENSSubdomainRegistrar] - baseDeployed = await Promise.all(bases.map(base => base.new())) - baseAddrs = baseDeployed.map(c => c.address) - - ensFactory = await ENSFactory.new() - - const kernelBase = await Kernel.new(true) // petrify immediately - const aclBase = await ACL.new() - daoFactory = await DAOFactory.new(kernelBase.address, aclBase.address, ZERO_ADDR) - }) - - beforeEach(async () => { - apmFactory = await APMRegistryFactory.new(daoFactory.address, ...baseAddrs, ZERO_ADDR, ensFactory.address) - ens = ENS.at(await apmFactory.ens()) - - const receipt = await apmFactory.newAPM(hash('eth'), '0x'+keccak_256('aragonpm'), apmOwner) - const apmAddr = getEventArgument(receipt, 'DeployAPM', 'apm') - registry = APMRegistry.at(apmAddr) - - const dao = Kernel.at(await registry.kernel()) - acl = ACL.at(await dao.acl()) - const subdomainRegistrar = baseDeployed[2] - - // Get permission to delete names after each test case - await acl.createPermission(apmOwner, await registry.registrar(), await subdomainRegistrar.DELETE_NAME_ROLE(), apmOwner, { from: apmOwner }) - }) - - it('inits with existing ENS deployment', async () => { - const receipt = await ensFactory.newENS(ensOwner) - const ens2 = ENS.at(getEventArgument(receipt, 'DeployENS', 'ens')) - const newFactory = await APMRegistryFactory.new(daoFactory.address, ...baseAddrs, ens2.address, ZERO_ADDR) - - await ens2.setSubnodeOwner(hash('eth'), '0x'+keccak_256('aragonpm'), newFactory.address) - const receipt2 = await newFactory.newAPM(hash('eth'), '0x'+keccak_256('aragonpm'), apmOwner) - const apmAddr = getEventArgument(receipt2, 'DeployAPM', 'apm') - const resolver = PublicResolver.at(await ens2.resolver(rootNode)) - - assert.equal(await resolver.addr(rootNode), apmAddr, 'rootnode should be resolve') - }) - - it('aragonpm.eth should resolve to registry', async () => { - const resolver = PublicResolver.at(await ens.resolver(rootNode)) - - assert.equal(await resolver.addr(rootNode), registry.address, 'rootnode should be resolve') - }) - - it('aragonpm.eth should be owned by ENSSubdomainRegistrar', async () => { - assert.equal(await ens.owner(rootNode), await registry.registrar(), 'rootnode should be owned correctly') - }) - - it('can create repo with version and dev can create new versions', async () => { - const receipt = await registry.newRepoWithVersion('test', repoDev, [1, 0, 0], ZERO_ADDR, EMPTY_BYTES, { from: apmOwner }) - const repo = Repo.at(getEventArgument(receipt, 'NewRepo', 'repo')) - - assert.equal(await repo.getVersionsCount(), 1, 'should have created version') - - await repo.newVersion([2, 0, 0], ZERO_ADDR, EMPTY_BYTES, { from: repoDev }) - - assert.equal(await repo.getVersionsCount(), 2, 'should have created version') - }) - - it('fails to init with existing ENS deployment if not owner of tld', async () => { - const ensReceipt = await ensFactory.newENS(ensOwner) - const ens2 = ENS.at(getEventArgument(ensReceipt, 'DeployENS', 'ens')) - const newFactory = await APMRegistryFactory.new(daoFactory.address, ...baseAddrs, ens2.address, ZERO_ADDR) - - // Factory doesn't have ownership over 'eth' tld - await assertRevert(newFactory.newAPM(hash('eth'), '0x'+keccak_256('aragonpm'), apmOwner)) - }) - - it('fails to create empty repo name', async () => { - await assertRevert(registry.newRepo('', repoDev, { from: apmOwner })) - }) - - it('fails to create repo if not in ACL', async () => { - await assertRevert(registry.newRepo('test', repoDev, { from: notOwner })) - }) - - context('> Creating test.aragonpm.eth repo', () => { - let repo = {} - - beforeEach(async () => { - const receipt = await registry.newRepo('test', repoDev, { from: apmOwner }) - repo = Repo.at(getEventArgument(receipt, 'NewRepo', 'repo')) - }) - - it('resolver is setup correctly', async () => { - const resolverNode = hash('resolver.eth') - const publicResolver = PublicResolver.at(await ens.resolver(resolverNode)) - - assert.equal(await ens.resolver(testNode), await publicResolver.addr(resolverNode), 'resolver should be set to public resolver') - assert.equal(await publicResolver.addr(testNode), repo.address, 'resolver should resolve to repo address') - }) - - it('repo should have 0 versions', async () => { - assert.equal(await repo.getVersionsCount(), 0, 'shouldnt have created version') - }) - - it('fails when creating repo with existing name', async () => { - await assertRevert(registry.newRepo('test', repoDev)) - }) - - it('repo dev can create versions', async () => { - await repo.newVersion([1, 0, 0], ZERO_ADDR, EMPTY_BYTES, { from: repoDev }) - await repo.newVersion([2, 0, 0], ZERO_ADDR, EMPTY_BYTES, { from: repoDev }) - - assert.equal(await repo.getVersionsCount(), 2, 'should have created versions') - }) - - it('repo dev can authorize someone to interact with repo', async () => { - await repo.newVersion([1, 0, 0], ZERO_ADDR, EMPTY_BYTES, { from: repoDev }) - const newOwner = someone - - await acl.grantPermission(newOwner, repo.address, await repo.CREATE_VERSION_ROLE(), { from: repoDev }) - - await repo.newVersion([2, 0, 0], ZERO_ADDR, EMPTY_BYTES, { from: newOwner }) - await repo.newVersion([2, 1, 0], ZERO_ADDR, EMPTY_BYTES, { from: repoDev }) // repoDev can still create them - - assert.equal(await repo.getVersionsCount(), 3, 'should have created versions') - }) - - it('repo dev can no longer create versions if permission is removed', async () => { - await repo.newVersion([1, 0, 0], ZERO_ADDR, EMPTY_BYTES, { from: repoDev }) - await acl.revokePermission(repoDev, repo.address, await repo.CREATE_VERSION_ROLE(), { from: repoDev }) - - await assertRevert(repo.newVersion([2, 0, 0], ZERO_ADDR, EMPTY_BYTES, { from: repoDev })) - }) - - it('cannot create versions if not in ACL', async () => { - await assertRevert(repo.newVersion([1, 0, 0], ZERO_ADDR, EMPTY_BYTES, { from: notOwner })) - }) - }) - - context('> Created with missing permissions', () => { - let apmFactoryMock - - before(async () => { - apmFactoryMock = await APMRegistryFactoryMock.new(daoFactory.address, ...baseAddrs, ensFactory.address) - }) - - it('fails if factory doesnt give permission to create names', async () => { - await assertRevert(apmFactoryMock.newFailingAPM(hash('eth'), '0x'+keccak_256('aragonpm'), apmOwner, true)) - }) - - it('fails if factory doesnt give permission to create permissions', async () => { - await assertRevert(apmFactoryMock.newFailingAPM(hash('eth'), '0x'+keccak_256('aragonpm'), apmOwner, false)) - }) - }) -}) diff --git a/test/contracts/apm/apm_repo.js b/test/contracts/apm/apm_repo.js deleted file mode 100644 index 60bf6c66f..000000000 --- a/test/contracts/apm/apm_repo.js +++ /dev/null @@ -1,127 +0,0 @@ -const { assertRevert } = require('../../helpers/assertThrow') - -const Repo = artifacts.require('UnsafeRepo') - -const EMPTY_BYTES = '0x' -const ZERO_ADDR = '0x0000000000000000000000000000000000000000' - -contract('Repo', accounts => { - let repo - - beforeEach(async () => { - repo = await Repo.new() - await repo.initialize() - }) - - it('computes correct valid bumps', async () => { - await assert.isTrue(await repo.isValidBump([0, 0, 0], [0, 0, 1])) - await assert.isTrue(await repo.isValidBump([0, 0, 0], [0, 1, 0])) - await assert.isTrue(await repo.isValidBump([0, 0, 0], [1, 0, 0])) - await assert.isTrue(await repo.isValidBump([1, 4, 7], [2, 0, 0])) - await assert.isTrue(await repo.isValidBump([147, 4, 7], [147, 5, 0])) - - await assert.isFalse(await repo.isValidBump([0, 0, 1], [0, 0, 1])) - await assert.isFalse(await repo.isValidBump([0, 1, 0], [0, 2, 1])) - await assert.isFalse(await repo.isValidBump([0, 0, 2], [0, 0, 1])) - await assert.isFalse(await repo.isValidBump([2, 1, 0], [2, 2, 1])) - await assert.isFalse(await repo.isValidBump([1, 1, 1], [5, 0, 0])) - await assert.isFalse(await repo.isValidBump([5, 0, 0], [5, 2, 0])) - await assert.isFalse(await repo.isValidBump([0, 1, 2], [1, 1, 2])) - await assert.isFalse(await repo.isValidBump([0, 0, Math.pow(2, 16)], [0, 0, Math.pow(2, 16) - 1])) - }) - - // valid version as being a correct bump from 0.0.0 - it('cannot create invalid first version', async () => { - await assertRevert(repo.newVersion([1, 1, 0], ZERO_ADDR, EMPTY_BYTES)) - }) - - context('creating initial version', () => { - const initialCode = accounts[8] // random addr, irrelevant - const initialContent = '0x12' - - beforeEach(async () => { - await repo.newVersion([1, 0, 0], initialCode, initialContent) - }) - - const assertVersion = (versionData, semanticVersion, code, contentUri) => { - const [[maj, min, pat], addr, content] = versionData - - assert.equal(maj, semanticVersion[0], 'major should match') - assert.equal(min, semanticVersion[1], 'minor should match') - assert.equal(pat, semanticVersion[2], 'patch should match') - - assert.equal(addr, code, 'code should match') - assert.equal(content, contentUri, 'content should match') - } - - it('version is fetchable as latest', async () => { - assertVersion(await repo.getLatest(), [1, 0, 0], initialCode, initialContent) - }) - - it('version is fetchable by semantic version', async () => { - assertVersion(await repo.getBySemanticVersion([1, 0, 0]), [1, 0, 0], initialCode, initialContent) - }) - - it('version is fetchable by contract address', async () => { - assertVersion(await repo.getLatestForContractAddress(initialCode), [1, 0, 0], initialCode, initialContent) - }) - - it('version is fetchable by version id', async () => { - assertVersion(await repo.getByVersionId(1), [1, 0, 0], initialCode, initialContent) - }) - - it('setting contract address to 0 reuses last version address', async () => { - await repo.newVersion([1, 1, 0], ZERO_ADDR, initialContent) - assertVersion(await repo.getByVersionId(2), [1, 1, 0], initialCode, initialContent) - }) - - it('fails when changing contract address in non major version', async () => { - await assertRevert(repo.newVersion([1, 1, 0], accounts[2], initialContent)) - }) - - it('fails when version bump is invalid', async () => { - await assertRevert(repo.newVersion([1, 2, 0], initialCode, initialContent)) - }) - - it('fails if requesting version 0', async () => { - await assertRevert(repo.getByVersionId(0)) - }) - - context('adding new version', () => { - const newCode = accounts[9] // random addr, irrelevant - const newContent = '0x13' - - beforeEach(async () => { - await repo.newVersion([2, 0, 0], newCode, newContent) - }) - - it('new version is fetchable as latest', async () => { - assertVersion(await repo.getLatest(), [2, 0, 0], newCode, newContent) - }) - - it('new version is fetchable by semantic version', async () => { - assertVersion(await repo.getBySemanticVersion([2, 0, 0]), [2, 0, 0], newCode, newContent) - }) - - it('new version is fetchable by contract address', async () => { - assertVersion(await repo.getLatestForContractAddress(newCode), [2, 0, 0], newCode, newContent) - }) - - it('new version is fetchable by version id', async () => { - assertVersion(await repo.getByVersionId(2), [2, 0, 0], newCode, newContent) - }) - - it('old version is fetchable by semantic version', async () => { - assertVersion(await repo.getBySemanticVersion([1, 0, 0]), [1, 0, 0], initialCode, initialContent) - }) - - it('old version is fetchable by contract address', async () => { - assertVersion(await repo.getLatestForContractAddress(initialCode), [1, 0, 0], initialCode, initialContent) - }) - - it('old version is fetchable by version id', async () => { - assertVersion(await repo.getByVersionId(1), [1, 0, 0], initialCode, initialContent) - }) - }) - }) -}) diff --git a/test/contracts/common/keccak_constants.js b/test/contracts/common/keccak_constants.js index 972bb9b03..3a7400fd8 100644 --- a/test/contracts/common/keccak_constants.js +++ b/test/contracts/common/keccak_constants.js @@ -7,21 +7,6 @@ contract('Constants', () => { keccakConstants = await getContract('KeccakConstants').new() }) - it('checks ENS constants', async () => { - const ensConstants = await getContract('ENSConstantsMock').new() - - assert.equal(await ensConstants.getEthTldLabel(), await keccakConstants.ETH_TLD_LABEL(), "ETH tld label doesn't match") - assert.equal(await ensConstants.getEthTldNode(), await keccakConstants.ETH_TLD_NODE(), "ETH tld node doesn't match") - assert.equal(await ensConstants.getPublicResolverLabel(), await keccakConstants.PUBLIC_RESOLVER_LABEL(), "public resolver label doesn't match") - assert.equal(await ensConstants.getPublicResolverNode(), await keccakConstants.PUBLIC_RESOLVER_NODE(), "public resolver node doesn't match") - }) - - it('checks APMNamehash constants', async () => { - const apmNamehash = await getContract('APMNamehashMock').new() - - assert.equal(await apmNamehash.getAPMNode(), await keccakConstants.APM_NODE(), "APM node doesn't match") - }) - it('checks kernel constants', async () => { const kernelConstants = await getContract('KernelConstantsMock').new() assert.equal(await kernelConstants.getKernelAppId(), await keccakConstants.KERNEL_APP_ID(), "kernel app id doesn't match") @@ -40,12 +25,6 @@ contract('Constants', () => { assert.equal(await kernel.APP_ADDR_NAMESPACE(), await keccakConstants.KERNEL_APP_ADDR_NAMESPACE(), "app namespace doesn't match") }) - it('checks APMRegistry constants', async () => { - const apm = await getContract('APMRegistry').new() - - assert.equal(await apm.CREATE_REPO_ROLE(), await keccakConstants.CREATE_REPO_ROLE(), "create repo role doesn't match") - }) - it('checks ACL constants', async () => { const acl = await getContract('ACL').new() @@ -53,14 +32,6 @@ contract('Constants', () => { assert.equal(await acl.EMPTY_PARAM_HASH(), await keccakConstants.EMPTY_PARAM_HASH(), "empty param hash doesn't match") }) - it('checks ENSSubdomainRegistrar constants', async () => { - const ensRegistrar = await getContract('ENSSubdomainRegistrar').new() - - assert.equal(await ensRegistrar.CREATE_NAME_ROLE(), await keccakConstants.CREATE_NAME_ROLE(), "create name role doesn't match") - assert.equal(await ensRegistrar.DELETE_NAME_ROLE(), await keccakConstants.DELETE_NAME_ROLE(), "delete name role doesn't match") - assert.equal(await ensRegistrar.POINT_ROOTNODE_ROLE(), await keccakConstants.POINT_ROOTNODE_ROLE(), "point rootnode role doesn't match") - }) - it('checks EVM Script constants', async () => { const evmScriptConstants = await getContract('EVMScriptRegistryConstantsMock').new() @@ -80,12 +51,6 @@ contract('Constants', () => { assert.equal(await evmScriptRegistry.REGISTRY_MANAGER_ROLE(), await keccakConstants.REGISTRY_MANAGER_ROLE(), "registry manager role doesn't match") }) - it('checks Repo constants', async () => { - const repo = await getContract('Repo').new() - - assert.equal(await repo.CREATE_VERSION_ROLE(), await keccakConstants.CREATE_VERSION_ROLE(), "create version role doesn't match") - }) - it('checks AppStorage unstructured storage constants', async () => { const appStorage = await getContract('AppStorageMock').new() diff --git a/test/contracts/ens/ens_subdomains.js b/test/contracts/ens/ens_subdomains.js deleted file mode 100644 index d34b4640d..000000000 --- a/test/contracts/ens/ens_subdomains.js +++ /dev/null @@ -1,101 +0,0 @@ -const { hash } = require('eth-ens-namehash') -const { keccak_256 } = require('js-sha3') -const { assertRevert } = require('../../helpers/assertThrow') -const { getEventArgument } = require('../../helpers/events') - -const ENS = artifacts.require('ENS') -const ENSFactory = artifacts.require('ENSFactory') - -const Repo = artifacts.require('Repo') -const ACL = artifacts.require('ACL') -const Kernel = artifacts.require('Kernel') -const DAOFactory = artifacts.require('DAOFactory') -const APMRegistry = artifacts.require('APMRegistry') -const APMRegistryFactory = artifacts.require('APMRegistryFactory') -const AppProxyUpgradeable = artifacts.require('AppProxyUpgradeable') -const ENSSubdomainRegistrar = artifacts.require('ENSSubdomainRegistrar') - -const EMPTY_BYTES = '0x' -const ZERO_ADDR = '0x0000000000000000000000000000000000000000' - -// Using APMFactory in order to reuse it -contract('ENSSubdomainRegistrar', ([_, apmOwner, notOwner]) => { - let baseDeployed, apmFactory, ensFactory, dao, daoFactory, ens, registrar - let APP_BASES_NAMESPACE - - const holanode = hash('hola.aragonpm.eth') - const holalabel = '0x'+keccak_256('hola') - - before(async () => { - const bases = [APMRegistry, Repo, ENSSubdomainRegistrar] - baseDeployed = await Promise.all(bases.map(base => base.new())) - - ensFactory = await ENSFactory.new() - - const kernelBase = await Kernel.new(true) // petrify immediately - const aclBase = await ACL.new() - daoFactory = await DAOFactory.new(kernelBase.address, aclBase.address, ZERO_ADDR) - - APP_BASES_NAMESPACE = await kernelBase.APP_BASES_NAMESPACE() - }) - - beforeEach(async () => { - const baseAddrs = baseDeployed.map(c => c.address) - apmFactory = await APMRegistryFactory.new(daoFactory.address, ...baseAddrs, ZERO_ADDR, ensFactory.address) - ens = ENS.at(await apmFactory.ens()) - - const receipt = await apmFactory.newAPM(hash('eth'), '0x'+keccak_256('aragonpm'), apmOwner) - const apmAddr = getEventArgument(receipt, 'DeployAPM', 'apm') - const registry = APMRegistry.at(apmAddr) - - dao = Kernel.at(await registry.kernel()) - const acl = ACL.at(await dao.acl()) - - registrar = ENSSubdomainRegistrar.at(await registry.registrar()) - const subdomainRegistrar = baseDeployed[2] - - await acl.grantPermission(apmOwner, await registry.registrar(), await subdomainRegistrar.CREATE_NAME_ROLE(), { from: apmOwner }) - await acl.createPermission(apmOwner, await registry.registrar(), await subdomainRegistrar.DELETE_NAME_ROLE(), apmOwner, { from: apmOwner }) - }) - - it('can create name', async () => { - await registrar.createName(holalabel, apmOwner, { from: apmOwner }) - - assert.equal(await ens.owner(hash('hola.aragonpm.eth')), apmOwner, 'should have created name') - }) - - it('fails if creating names twice', async () => { - await registrar.createName(holalabel, apmOwner, { from: apmOwner }) - await assertRevert(registrar.createName(holalabel, apmOwner, { from: apmOwner })) - }) - - it('fails if deleting name not yet created', async () => { - await assertRevert(registrar.deleteName(holalabel, { from: apmOwner })) - }) - - it('fails if not authorized to create name', async () => { - await assertRevert(registrar.createName(holalabel, apmOwner, { from: notOwner })) - }) - - it('can delete names', async () => { - await registrar.createName(holalabel, apmOwner, { from: apmOwner }) - await registrar.deleteName(holalabel, { from: apmOwner }) - - assert.equal(await ens.owner(holanode), ZERO_ADDR, 'should have reset name') - }) - - it('can delete names registered to itself', async () => { - await registrar.createName(holalabel, registrar.address, { from: apmOwner }) - await registrar.deleteName(holalabel, { from: apmOwner }) - - assert.equal(await ens.owner(holanode), ZERO_ADDR, 'should have reset name') - }) - - it('fails if initializing without rootnode ownership', async () => { - const ens = await ENS.new() - const newRegProxy = await AppProxyUpgradeable.new(dao.address, hash('apm-enssub.aragonpm.eth'), EMPTY_BYTES) - const newReg = ENSSubdomainRegistrar.at(newRegProxy.address) - - await assertRevert(newReg.initialize(ens.address, holanode)) - }) -}) diff --git a/test/helpers/revertStrings.js b/test/helpers/revertStrings.js index d8c805b66..ee2177102 100644 --- a/test/helpers/revertStrings.js +++ b/test/helpers/revertStrings.js @@ -19,15 +19,6 @@ module.exports = makeErrorMappingProxy({ ACL_AUTH_NO_MANAGER: 'ACL_AUTH_NO_MANAGER', ACL_EXISTENT_MANAGER: 'ACL_EXISTENT_MANAGER', - // apm/APMRegistry.sol - APMREG_INIT_PERMISSIONS: 'APMREG_INIT_PERMISSIONS', - APMREG_EMPTY_NAME: 'APMREG_EMPTY_NAME', - - // apm/Repo.sol - REPO_INVALID_BUMP: 'REPO_INVALID_BUMP', - REPO_INVALID_VERSION: 'REPO_INVALID_VERSION', - REPO_INEXISTENT_VERSION: 'REPO_INEXISTENT_VERSION', - // apps/AragonApp.sol APP_AUTH_FAILED: 'APP_AUTH_FAILED', @@ -47,11 +38,6 @@ module.exports = makeErrorMappingProxy({ RECOVER_VAULT_NOT_CONTRACT: 'RECOVER_VAULT_NOT_CONTRACT', RECOVER_TOKEN_TRANSFER_FAILED: 'RECOVER_TOKEN_TRANSFER_FAILED', - // ens/ENSSubdomainRegistrar.sol - ENSSUB_NO_NODE_OWNERSHIP: 'ENSSUB_NO_NODE_OWNERSHIP', - ENSSUB_NAME_EXISTS: 'ENSSUB_NAME_EXISTS', - ENSSUB_DOESNT_EXIST: 'ENSSUB_DOESNT_EXIST', - // evmscript/EVMScriptRegistry.sol EVMREG_INEXISTENT_EXECUTOR: 'EVMREG_INEXISTENT_EXECUTOR', EVMREG_EXECUTOR_ENABLED: 'EVMREG_EXECUTOR_ENABLED',