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

Commit

Permalink
Last call fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
0xjac authored and jbaylina committed Nov 2, 2018
1 parent 12f3889 commit f1f6d40
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 46 deletions.
2 changes: 1 addition & 1 deletion .soliumrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"deprecated-suicide": "error",
"emit": "error",
"error-reason": "error",
"function-order": "error",
"function-whitespace": "error",
"imports-on-top": "error",
"lbrace": "error",
Expand All @@ -33,6 +32,7 @@
"visibility-first": "error",

"arg-overflow": "off",
"function-order": "off",
"whitespace": "off"
}
}
2 changes: 1 addition & 1 deletion contracts/ERC820Client.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ contract ERC820Registry {

/// Base client to interact with the registry.
contract ERC820Client {
ERC820Registry erc820Registry = ERC820Registry(0x820c4597Fc3E4193282576750Ea4fcfe34DdF0a7);
ERC820Registry erc820Registry = ERC820Registry(0x820A8Cfd018b159837d50656c49d28983f18f33c);

function setInterfaceImplementation(string _interfaceLabel, address _implementation) internal {
bytes32 interfaceHash = keccak256(abi.encodePacked(_interfaceLabel));
Expand Down
4 changes: 2 additions & 2 deletions contracts/ERC820ImplementerInterface.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ contract ERC820ImplementerInterface {
bytes32 constant ERC820_ACCEPT_MAGIC = keccak256(abi.encodePacked("ERC820_ACCEPT_MAGIC"));

/// @notice Indicates whether the contract implements the interface `interfaceHash` for the address `addr`.
/// @param addr Address for which the contract will implement the interface
/// @param interfaceHash keccak256 hash of the name of the interface
/// @param addr Address for which the contract will implement the interface
/// @return ERC820_ACCEPT_MAGIC only if the contract implements `ìnterfaceHash` for the address `addr`.
function canImplementInterfaceForAddress(address addr, bytes32 interfaceHash) public view returns(bytes32);
function canImplementInterfaceForAddress(bytes32 interfaceHash, address addr) external view returns(bytes32);
}
69 changes: 36 additions & 33 deletions contracts/ERC820Registry.sol
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
/* ERC820: Pseudo-introspection Registry Contract
* by Jordi Baylina and Jacques Dafflon

/* ERC820 Pseudo-introspection Registry Contract
* This standard defines a universal registry smart contract where any address
* (contract or regular account) can register which interface it supports and
* which smart contract is responsible for its implementation.
*
* Written in 2018 by Jordi Baylina and Jacques Dafflon
*
* To the extent possible under law, Jordi Baylina and Jacques Dafflon who
* associated CC0 with the ERC820: Pseudo-introspection Registry Contract have
* waived all copyright and related or neighboring rights to the
* ERC820: Pseudo-introspection Registry Contract.
* To the extent possible under law, the author(s) have dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty.
*
* You should have received a copy of the CC0 legalcode along with this work.
* If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
* You should have received a copy of the CC0 Public Domain Dedication along
* with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*
* ███████╗██████╗ ██████╗ █████╗ ██████╗ ██████╗
* ██╔════╝██╔══██╗██╔════╝██╔══██╗╚════██╗██╔═████╗
Expand All @@ -26,16 +31,16 @@
*/
pragma solidity 0.4.24;
// IV is value needed to have a vanity address starting with `0x820`.
// IV: 2241
// IV: 15222

/// @dev The interface a contract MUST implement if it is the implementer of
/// some (other) interface for any address other than itself.
interface ERC820ImplementerInterface {
/// @notice Indicates whether the contract implements the interface `interfaceHash` for the address `addr` or not.
/// @param addr Address for which the contract will implement the interface
/// @param interfaceHash keccak256 hash of the name of the interface
/// @param addr Address for which the contract will implement the interface
/// @return ERC820_ACCEPT_MAGIC only if the contract implements `interfaceHash` for the address `addr`.
function canImplementInterfaceForAddress(address addr, bytes32 interfaceHash) public view returns(bytes32);
function canImplementInterfaceForAddress(bytes32 interfaceHash, address addr) external view returns(bytes32);
}


Expand Down Expand Up @@ -90,7 +95,7 @@ contract ERC820Registry {
if (_implementer != 0 && _implementer != msg.sender) {
require(
ERC820ImplementerInterface(_implementer)
.canImplementInterfaceForAddress(addr, _interfaceHash) == ERC820_ACCEPT_MAGIC,
.canImplementInterfaceForAddress(_interfaceHash, addr) == ERC820_ACCEPT_MAGIC,
"Does not implement the interface"
);
}
Expand All @@ -100,13 +105,12 @@ contract ERC820Registry {

/// @notice Sets the `_newManager` as manager for the `_addr` address.
/// The new manager will be able to call `setInterfaceImplementer` for `_addr`.
/// @param _addr Address for which to set the new manager. (If `_addr == 0` then `msg.sender` is assumed.)
/// @param _addr Address for which to set the new manager.
/// @param _newManager Address of the new manager for `addr`. (Pass `0x0` to reset the manager to `_addr` itself.)
function setManager(address _addr, address _newManager) external {
address addr = _addr == 0 ? msg.sender : _addr;
require(getManager(addr) == msg.sender, "Not the manager");
managers[addr] = _newManager == addr ? 0 : _newManager;
emit ManagerChanged(addr, _newManager);
require(getManager(_addr) == msg.sender, "Not the manager");
managers[_addr] = _newManager == _addr ? 0 : _newManager;
emit ManagerChanged(_addr, _newManager);
}

/// @notice Get the manager of an address.
Expand All @@ -124,33 +128,31 @@ contract ERC820Registry {
/// @notice Compute the keccak256 hash of an interface given its name.
/// @param _interfaceName Name of the interface.
/// @return The keccak256 hash of an interface name.
function interfaceHash(string _interfaceName) public pure returns(bytes32) {
function interfaceHash(string _interfaceName) external pure returns(bytes32) {
return keccak256(abi.encodePacked(_interfaceName));
}

/* --- ERC165 Related Functions --- */
/* --- Developed in collaboration with William Entriken. --- */

/// @notice Updates the cache with whether the contract implements an ERC165 interface or not.
/// @param _contract Address of the contract for which to update the cache.
/// @param _interfaceId ERC165 interface for which to update the cache.
function updateERC165Cache(address _contract, bytes4 _interfaceId) external {
interfaces[_contract][_interfaceId] = implementsERC165InterfaceNoCache(_contract, _interfaceId) ? _contract : 0;
erc165Cached[_contract][_interfaceId] = true;
}

/// @notice Checks whether a contract implements an ERC165 interface or not.
/// The result is cached. If the cache is out of date, it must be updated by calling `updateERC165Cache`.
/// The result may be cached, if not a direct lookup is performed.
/// @param _contract Address of the contract to check.
/// @param _interfaceId ERC165 interface to check.
/// @return `true` if `_contract` implements `_interfaceId`, false otherwise.
/// @dev This function may modify the state when updating the cache. However, this function must have the `view`
/// modifier since `getInterfaceImplementer` also calls it. If called from within a transaction, the ERC165 cache
/// is updated.
function implementsERC165Interface(address _contract, bytes4 _interfaceId) public view returns (bool) {
if (!erc165Cached[_contract][_interfaceId]) {
updateERC165Cache(_contract, _interfaceId);
return implementsERC165InterfaceNoCache(_contract, _interfaceId);
}
return interfaces[_contract][_interfaceId] != 0;
}

/// @notice Updates the cache with whether the contract implements an ERC165 interface or not.
/// @param _contract Address of the contract for which to update the cache.
/// @param _interfaceId ERC165 interface for which to update the cache.
function updateERC165Cache(address _contract, bytes4 _interfaceId) public {
interfaces[_contract][_interfaceId] = implementsERC165InterfaceNoCache(_contract, _interfaceId) ? _contract : 0;
erc165Cached[_contract][_interfaceId] = true;
return interfaces[_contract][_interfaceId] == _contract;
}

/// @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.
Expand Down Expand Up @@ -185,14 +187,15 @@ contract ERC820Registry {
return _interfaceHash & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0;
}

/// @dev Make a call on a contract without throwing if the function does not exist.
function noThrowCall(address _contract, bytes4 _interfaceId)
internal view returns (uint256 success, uint256 result)
{
bytes4 erc165ID = ERC165ID;

assembly {
let x := mload(0x40) // Find empty storage location using "free memory pointer"
mstore(x, erc165ID) // Place signature at begining of empty storage
mstore(x, erc165ID) // Place signature at beginning of empty storage
mstore(add(x, 0x04), _interfaceId) // Place first argument directly next to signature

success := staticcall(
Expand Down
2 changes: 1 addition & 1 deletion contracts/ExampleImplementer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "./ERC820ImplementerInterface.sol";


contract ExampleImplementer is ERC820ImplementerInterface {
function canImplementInterfaceForAddress(address addr, bytes32 interfaceHash) public view returns(bytes32) {
function canImplementInterfaceForAddress(bytes32 interfaceHash, address addr) external view returns(bytes32) {
return ERC820_ACCEPT_MAGIC;
}
}
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"chai-as-promised": "7.1.1",
"ganache-cli": "6.1.8",
"mocha": "4.1.0",
"solc": "0.4.24",
"solcpiler": "1.0.0-beta.9",
"solium": "^1.1.8"
}
Expand Down
4 changes: 1 addition & 3 deletions test/ERC165.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ describe('ERC165 Compatibility Test', () => {

it('should be compatible with ERC820', async () => {
const g1 = await erc820Registry.$contract.methods.getInterfaceImplementer(lisa.$address, Simpson_Id).estimateGas();
// console.log(g1);
const a = await erc820Registry.getInterfaceImplementer(lisa.$address, Simpson_Id);
assert.equal(a, lisa.$address);
const nc = await erc820Registry.getInterfaceImplementer(lisa.$address, Invalid_Id);
Expand All @@ -132,7 +131,6 @@ describe('ERC165 Compatibility Test', () => {
assert.equal(b, lisa.$address);
await erc820Registry.updateERC165Cache(lisa.$address, Simpson_Id);
const g2 = await erc820Registry.$contract.methods.getInterfaceImplementer(lisa.$address, Simpson_Id).estimateGas();
assert(g2<g1/2); // It is much lower the gas after caching!
// console.log(g2 );
assert(g2 < g1); // Gas after caching is lower!
});
});
4 changes: 2 additions & 2 deletions test/MainScenario.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ describe('ERC820 Test', () => {
}).timeout(6000);

it('should change manager', async () => {
await erc820Registry.setManager(ZERO_ADDRESS, manager1, {from: addr});
await erc820Registry.setManager(addr, manager1, {from: addr});
const rManager1 = await erc820Registry.getManager(addr);
assert.equal(rManager1, manager1);
}).timeout(6000);
Expand Down Expand Up @@ -97,7 +97,7 @@ describe('ERC820 Test', () => {
assert.equal(rImplementer, ZERO_ADDRESS);
}).timeout(6000);

it('Should not allow to set an interface an invalid contract', async() => {
it('should not allow to set an invalid implementer for an address', async() => {
await erc820Registry.setInterfaceImplementer(addr, interfaceHash, erc820Registry.$address, {from: manager2, gas: 200000})
.should.be.rejectedWith('revert');
}).timeout(6000);
Expand Down

0 comments on commit f1f6d40

Please sign in to comment.