Skip to content
This repository has been archived by the owner on Nov 7, 2023. It is now read-only.

Commit

Permalink
Merge pull request #9 from rnsdomains/v2
Browse files Browse the repository at this point in the history
New resolver
  • Loading branch information
ilanolkies authored Jun 11, 2020
2 parents c6e23ed + dc35b00 commit f07ebdd
Show file tree
Hide file tree
Showing 22 changed files with 5,621 additions and 693 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@ build/
types
AddrResolverData.json
ChainAddrResolverData.json
ProxyAdminData.json
ProxyFactoryData.json
ResolverV1Data.json
.secret
115 changes: 101 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,59 @@
# rns-resolver

[![npm version](https://badge.fury.io/js/%40rsksmart%2Frns-resolver.svg)](https://badge.fury.io/js/%40rsksmart%2Frns-resolver)

RNS Resolver

## Install
<p align="middle">
<img src="https://www.rifos.org/assets/img/logo.svg" alt="logo" height="100" >
</p>
<h3 align="middle"><code>rns-resolver</code></h3>
<p align="middle">
RNS Resolver
</p>
<p align="middle">
<a href="https://circleci.com/gh/rnsdomains/rns-resolver">
<img src="https://circleci.com/gh/rnsdomains/rns-resolver.svg?style=svg" alt="CircleCI" />
</a>
<a href="https://badge.fury.io/js/%40rsksmart%2Frns-resolver">
<img src="https://badge.fury.io/js/%40rsksmart%2Frns-resolver.svg" alt="npm" />
</a>
<a href="https://developers.rsk.co/rif/rns/architecture/Resolver/">
<img src="https://img.shields.io/badge/-docs-brightgreen" alt="docs" />
</a>
<a href="https://developers.rsk.co/rif/rns/specs/resolvers/">
<img src="https://img.shields.io/badge/-specs-lightgrey" alt="specs" />
</a>
</p>

```
npm i @rsksmart/rns-resolver
```

Deployments:

- RSK Mainnet: [0xD87f8121D44F3717d4bAdC50b24E50044f86D64B](https://explorer.rsk.co/address/0xd87f8121d44f3717d4badc50b24e50044f86d64b)
- RSK Testnet: [0x25C289ccCFFf700c6a38722F4913924fE504De0e](https://explorer.testnet.rsk.co/address/0x25c289cccfff700c6a38722f4913924fe504de0e)

## Features

Supported resolution protocols:

- Contract addresses - [EIP-137](https://eips.ethereum.org/EIPS/eip-137#resolver-specification)
- Multicoin addresses - [EIP-2304](https://eips.ethereum.org/EIPS/eip-2304)
- Contenthash - [EIP-1577](https://eips.ethereum.org/EIPS/eip-1577)
- Contract ABI - [EIP-205](https://eips.ethereum.org/EIPS/eip-205)
- SECP256k1 public keys - [EIP-619](https://github.com/ethereum/EIPs/pull/619)
- Text records - [EIP-634](https://eips.ethereum.org/EIPS/eip-634)
- Interface discovery - [EIP-1844](https://eips.ethereum.org/EIPS/eip-1844)

Architecture:

- Upgradeable contracts using OpenZeppelin Upgrades [OpenZeppelin Upgrades](https://docs.openzeppelin.com/upgrades/2.8/).
- Use `setAuthorisation` to enable others set your records.
- Use `multicall` to perform multiple operations in one call/transaction.

## Usage

```solidity
pragma solidity ^0.5.0;
import "@rsksmart/rns-resolver/contracts/AbstractRNS.sol";
import "@rsksmart/rns-registry/contracts/AbstractRNS.sol";
import "@rsksmart/rns-resolver/contracts/RSKAddrResolver.sol";
contract RNSTransfer {
AbstractRNS rns;
Expand All @@ -25,7 +63,7 @@ contract RNSTransfer {
}
function transfer(bytes32 node) public {
address resolver = AbstractAddrResolver(rns.resolver(node));
address resolver = RSKAddrResolver(rns.resolver(node));
address addr = resolver.addr(node);
addr.transfer(msg.value);
Expand All @@ -35,16 +73,16 @@ contract RNSTransfer {

```js
const Web3 = require('web3');
const AddrResolverData = require('@rsksmart/rns-resolver/AddrResolverData.json');
const ResolverData = require('@rsksmart/rns-resolver/ResolverData.json');

const web3 = new Web3('https://public-node.rsk.co')
const AddrResolver = new web3.eth.Contract(AddrResolverData.abi, AddrResolverData.address.rskMainnet);
const Resolver = new web3.eth.Contract(ResolverData.abi, ResolverData.address.rskMainnet);
```

## Types

There are TypeScript typing definitions of the contracts published together with the original contracts.
Supported contract's libraries are:
There are TypeScript typing definitions of the contracts published together with the original contracts.
Supported contract's libraries are:

* `web3` version 1.* - `web3-v1-contracts`
* `web3` version 2.* - `web3-v2-contracts`
Expand All @@ -53,6 +91,55 @@ Supported contract's libraries are:

You can use them as follow:

```typescript
import Web3 from 'web3'
import AddrResolver from '@rsksmart/rns-resolver/types/web3-v1-contracts/ResolverV1.d.ts'
import ResolverData from '@rsksmart/rns-resolver/ResolverData.json'

const web3 = new Web3('https://public-node.rsk.co')
const resolver = new web3.eth.Contract(ResolverData.abi, ResolverData.address.rskMainnet) as AddrResolver
```

Replace `web3-v1-contracts` with the proper library version.

---

Legacy contracts:

## Usage

```solidity
pragma solidity ^0.5.0;
import "@rsksmart/rns-registry/contracts/legacy/AbstractRNS.sol";
import "@rsksmart/rns-resolver/contracts/legacy/AbstractAddrResolver.sol";
contract RNSTransfer {
AbstractRNS rns;
constructor(AbstractRNS _rns) public {
rns = _rns;
}
function transfer(bytes32 node) public {
address resolver = AbstractAddrResolver(rns.resolver(node));
address addr = resolver.addr(node);
addr.transfer(msg.value);
}
}
```

```js
const Web3 = require('web3');
const AddrResolverData = require('@rsksmart/rns-resolver/AddrResolverData.json');

const web3 = new Web3('https://public-node.rsk.co')
const AddrResolver = new web3.eth.Contract(AddrResolverData.abi, AddrResolverData.address.rskMainnet);
```

## Types

```typescript
import Web3 from 'web3'
import AddrResolver from '@rsksmart/rns-resolver/types/web3-v1-contracts/AddrResolverData.d.ts'
Expand All @@ -64,7 +151,7 @@ const resolver = new web3.eth.Contract(AddrResolverData.abi, AddrResolverData.ad

Replace `web3-v1-contracts` with the proper library version.

---
## Old deployments

- Public Resolver
- [Docs](https://developers.rsk.co/rif/rns/architecture/RSKResolver/)
Expand Down
12 changes: 12 additions & 0 deletions addresses.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,17 @@
"ChainAddrResolver": {
"rskMainnet": "0x99a12be4c89cbf6cfd11d1f2c029904a7b644368",
"rskTestnet": "0x404308f2a2eec2cdc3cb53d7d295af11c903414e"
},
"ProxyAdmin": {
"rskMainnet": "0xccdbc15edd43b15911895a5a592f7bfa43d9cfb1",
"rskTestnet": "0x02761e40db981268ee80e9e5302e6df212259fd4"
},
"ProxyFactory": {
"rskMainnet": "0x30569c0999f0c7fd7be9957ac4b4dee803cac293",
"rskTestnet": "0xbb71c17b28baf2b9e7f5b31660ecf758113b3fef"
},
"ResolverV1": {
"rskMainnet": "0x2d6eeddde13832512c68f9ed7ccf44b728a2be70",
"rskTestnet": "0xe559e468c08f30518b4ee8bf7f9374736489c38b"
}
}
47 changes: 47 additions & 0 deletions contracts/RSKAddrResolver.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
pragma solidity ^0.5.0;

import "@ensdomains/resolver/contracts/profiles/AddrResolver.sol";

// Source: https://github.com/ensdomains/resolvers/blob/9c3ed5377501d77738089c81c2a0b141878048f9/contracts/profiles/AddrResolver.sol
contract RSKAddrResolver is AddrResolver {
uint constant private COIN_TYPE_RSK = 137;

/**
* Sets the address associated with an RNS node.
* @param node The node to update.
* @param a The address to set.
*/
function setAddr(bytes32 node, address a) external authorised(node) {
bytes memory b = addressToBytes(a);
emit AddressChanged(node, COIN_TYPE_RSK, b);
emit AddrChanged(node, a);
_addresses[node][COIN_TYPE_RSK] = b;
}

/**
* Returns the address associated with an RNS node.
* @param node The RNS node to query.
* @return The associated address.
*/
function addr(bytes32 node) public view returns (address payable) {
bytes memory a = addr(node, COIN_TYPE_RSK);
if (a.length == 0) {
return address(0);
}
return bytesToAddress(a);
}

/**
* Sets the coin address associated with an RNS node .
* @param node The node to update.
* @param coinType slip0044 coin type.
* @param a The address to set.
*/
function setAddr(bytes32 node, uint coinType, bytes memory a) public authorised(node) {
emit AddressChanged(node, coinType, a);
if(coinType == COIN_TYPE_RSK) {
emit AddrChanged(node, bytesToAddress(a));
}
_addresses[node][coinType] = a;
}
}
72 changes: 72 additions & 0 deletions contracts/ResolverV1.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
pragma solidity ^0.5.0;
pragma experimental ABIEncoderV2;

import "@rsksmart/rns-registry/contracts/AbstractRNS.sol";
import "@openzeppelin/upgrades/contracts/Initializable.sol";
import "./RSKAddrResolver.sol";
import "@ensdomains/resolver/contracts/profiles/ContentHashResolver.sol";
import "@ensdomains/resolver/contracts/profiles/ABIResolver.sol";
import "@ensdomains/resolver/contracts/profiles/PubkeyResolver.sol";
import "@ensdomains/resolver/contracts/profiles/TextResolver.sol";
import "@ensdomains/resolver/contracts/profiles/InterfaceResolver.sol";

/**
* @title ResolverV1
* @dev A public resolver implementation. This implementation can
* be as an openzeppelin/upgrades v2.8 proxy contract implementation.
* Source: https://github.com/ensdomains/resolvers/blob/9c3ed5377501d77738089c81c2a0b141878048f9/contracts/PublicResolver.sol
*/
contract ResolverV1 is Initializable, RSKAddrResolver, ContentHashResolver, ABIResolver, PubkeyResolver, TextResolver, InterfaceResolver {
AbstractRNS public rns;

/**
* A mapping of authorisations. An address that is authorised for a name
* may make any changes to the name that the owner could, but may not update
* the set of authorisations.
* (node, owner, caller) => isAuthorised
*/
mapping(bytes32=>mapping(address=>mapping(address=>bool))) public authorisations;

event AuthorisationChanged(bytes32 indexed node, address indexed owner, address indexed target, bool isAuthorised);

/**
* @notice Initializes the contract.
* @dev Replace the usage of a constructor.
* @param _rns the RNS Registry address.
*/
function initialize(AbstractRNS _rns) initializer external {
rns = _rns;
}

/**
* @dev Sets or clears an authorisation.
* Authorisations are specific to the caller. Any account can set an authorisation
* for any name, but the authorisation that is checked will be that of the
* current owner of a name. Thus, transferring a name effectively clears any
* existing authorisations, and new authorisations can be set in advance of
* an ownership transfer if desired.
*
* @param node The name to change the authorisation on.
* @param target The address that is to be authorised or deauthorised.
* @param isAuthorised True if the address should be authorised, or false if it should be deauthorised.
*/
function setAuthorisation(bytes32 node, address target, bool isAuthorised) external {
authorisations[node][msg.sender][target] = isAuthorised;
emit AuthorisationChanged(node, msg.sender, target, isAuthorised);
}

function isAuthorised(bytes32 node) internal view returns(bool) {
address owner = rns.owner(node);
return owner == msg.sender || authorisations[node][owner][msg.sender];
}

function multicall(bytes[] calldata data) external returns(bytes[] memory results) {
results = new bytes[](data.length);
for(uint i = 0; i < data.length; i++) {
(bool success, bytes memory result) = address(this).delegatecall(data[i]);
require(success);
results[i] = result;
}
return results;
}
}
35 changes: 35 additions & 0 deletions contracts/dummy/Dummy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
pragma solidity ^0.5.0;
pragma experimental ABIEncoderV2;

import "../ResolverV1.sol";
import "@openzeppelin/contracts/introspection/IERC165.sol";

contract DummyVersion is ResolverV1 {
uint public v;

event Log();

function initialize() public {
emit Log();
}

function setV(uint _v) public {
v = _v;
}

function supportsInterface(bytes4 interfaceID) public pure returns(bool) {
return interfaceID == this.setV.selector || super.supportsInterface(interfaceID);
}
}

contract TruthyERC165 is IERC165 {
function supportsInterface(bytes4 /*interfaceId*/) external view returns (bool) {
return true;
}
}

contract FalsyERC165 is IERC165 {
function supportsInterface(bytes4 /*interfaceId*/) external view returns (bool) {
return false;
}
}
10 changes: 10 additions & 0 deletions contracts/dummy/Imports.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
pragma solidity ^0.5.0;

import "@openzeppelin/upgrades/contracts/upgradeability/ProxyFactory.sol";
import "@openzeppelin/upgrades/contracts/upgradeability/ProxyAdmin.sol";

contract Dummy {
constructor() internal {
revert("This contract is used to import dependencies. Do not use.");
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
39 changes: 39 additions & 0 deletions datagen.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,42 @@ const chainAddrResolverData = {
};

fs.writeFileSync('./ChainAddrResolverData.json', JSON.stringify(chainAddrResolverData));

const resolverV1Build = require('./build/contracts/ResolverV1');

const resolverV1BuildData = {
abi: resolverV1Build.abi,
bytecode: resolverV1Build.bytecode,
address: {
rskMainnet: addresses.ResolverV1.rskMainnet,
rskTestnet: addresses.ResolverV1.rskTestnet,
},
};

fs.writeFileSync('./ResolverV1Data.json', JSON.stringify(resolverV1BuildData));

const proxyAdminBuild = require('./build/contracts/ProxyAdmin');

const proxyAdminBuildData = {
abi: proxyAdminBuild.abi,
bytecode: proxyAdminBuild.bytecode,
address: {
rskMainnet: addresses.ProxyFactory.rskMainnet,
rskTestnet: addresses.ProxyFactory.rskTestnet,
},
};

fs.writeFileSync('./ProxyAdminData.json', JSON.stringify(proxyAdminBuildData));

const proxyFactoryBuild = require('./build/contracts/ProxyFactory');

const proxyFactoryBuildData = {
abi: proxyFactoryBuild.abi,
bytecode: proxyFactoryBuild.bytecode,
address: {
rskMainnet: addresses.ProxyAdmin.rskMainnet,
rskTestnet: addresses.ProxyAdmin.rskTestnet,
},
};

fs.writeFileSync('./ProxyFactoryData.json', JSON.stringify(proxyFactoryBuildData));
Loading

0 comments on commit f07ebdd

Please sign in to comment.