Skip to content

Commit

Permalink
support web2 & web3 gateways
Browse files Browse the repository at this point in the history
  • Loading branch information
0xc0de4c0ffee committed Aug 18, 2023
1 parent 49ce7e0 commit 7fd2aec
Show file tree
Hide file tree
Showing 5 changed files with 226 additions and 61 deletions.
31 changes: 14 additions & 17 deletions src/CCIP2ETH.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ contract CCIP2ETH is iCCIP2ETH {
/// @dev - Constructor
constructor(address _gateway) {
gateway = iGatewayManager(_gateway);
chainID = gateway.uintToString(block.chainid);
chainID = block.chainid == 1 ? "1" : "5"; // mainnet or goerli
/// @dev - Sets ENS Mainnet wrapper as Wrapper
isWrapper[0xD4416b13d2b3a9aBae7AcD5D6C2BbDBE25686401] = true;
emit UpdatedWrapper(0xD4416b13d2b3a9aBae7AcD5D6C2BbDBE25686401, true);
Expand All @@ -82,14 +82,6 @@ contract CCIP2ETH is iCCIP2ETH {
supportsInterface[iCallbackType.signedRedirect.selector] = true;
}

/// Note - Checks for admin privileges
modifier OnlyDev() {
if (msg.sender != gateway.owner()) {
revert NotAuthorised("NOT_DEV");
}
_;
}

/**
* @dev Gets recordhash for a node
* @param _node - Namehash of domain.eth, or bytes32(address _Owner)
Expand Down Expand Up @@ -268,9 +260,6 @@ contract CCIP2ETH is iCCIP2ETH {
}
if (_recordhash.length == 0) {
_recordhash = recordhash[bytes32(uint256(uint160(_owner)))];
if (_recordhash.length == 0) {
_recordhash = abi.encodePacked("https://ccip.namesys.xyz"); // Web2 fallback
}
}
string memory _recType = gateway.funcToJson(request); // Filename for the requested record
bytes32 _checkhash =
Expand Down Expand Up @@ -312,14 +301,14 @@ contract CCIP2ETH is iCCIP2ETH {
string memory _domain, // String-formatted complete 'a.b.c.domain.eth'
string memory _recType, // Record type
, // Complete reverse-DNS path for __fallback()
, // DNS-encoded domain.eth
, // DNS-encoded full domain.eth
bytes memory _request // Format: <bytes4> + <namehash> + <extradata>
) = abi.decode(extradata, (bytes32, uint256, bytes32, string, string, string, bytes, bytes));
address _owner = ENS.owner(_node);
if (isWrapper[_owner]) {
_owner = iToken(_owner).ownerOf(uint256(_node));
}
/// @dev - Timeout in 4 blocks (must be < 256 blocks)
/// @dev - Timeout in 4 blocks
if (block.number > _blocknumber + 5) {
revert InvalidRequest("BLOCK_TIMEOUT");
}
Expand Down Expand Up @@ -382,7 +371,7 @@ contract CCIP2ETH is iCCIP2ETH {
"Requesting Signature To Install dApp Service\n",
"\nOrigin: ",
_domain, // e.g. ens.domain.eth
"\ndApp: ",
"\nDApp: ",
_redirectDomain, // e.g. app.ens.eth
"\nExtradata: 0x",
gateway.bytesToHexString(abi.encodePacked(keccak256(result)), 0),
Expand Down Expand Up @@ -568,21 +557,29 @@ contract CCIP2ETH is iCCIP2ETH {

/// @dev : Management functions

/// @dev : Checks for admin privileges
modifier OnlyDev() {
if (msg.sender != gateway.owner()) {
revert NotAuthorised("NOT_DEV");
}
_;
}

/// @dev - Returns owner of the contract
function owner() public view returns (address) {
return gateway.owner();
}
/// @dev - Updates ChainID in case of a hardfork

/// @dev - Updates ChainID in case of a hardfork
function updateChainID() public {
chainID = gateway.uintToString(block.chainid);
}

/**
* @dev Sets fees for ownerhash
* Note - Set to 0 at launch
* @param _wei - Fees in WEI per EOA
*/

function updateOwnerhashFees(uint256 _wei) external OnlyDev {
ownerhashFees = _wei;
}
Expand Down
134 changes: 95 additions & 39 deletions src/GatewayManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ import "./Interface.sol";
*/
contract GatewayManager is iERC173, iGatewayManager {
/// @dev - Events
event AddGateway(string indexed domain);
event RemoveGateway(string indexed domain);
event UpdateFuncFile(bytes4 _func, string _name);

event Web3GatewayUpdated(string indexed domain);
event Web3GatewayRemoved(string indexed domain);
event FuncMapUpdated(bytes4 _func, string _name);
event Web2GatewayUpdated(string indexed domain);
event Web2GatewayRemoved(string indexed domain);
/// @dev - Errors

error ContenthashNotImplemented(bytes1 _type);
error InvalidRequest(string _message);
error UnimplementedFeature(bytes4 func);
error FeatureNotImplemented(bytes4 func);

/// @dev - Contract owner/multisig address
address public owner;
Expand All @@ -33,8 +35,11 @@ contract GatewayManager is iERC173, iGatewayManager {
address immutable THIS = address(this);
/// @dev - Primary IPFS gateway domain, ipfs2.eth.limo
string public PrimaryGateway = "ipfs2.eth.limo";
/// @dev - List of secondary gateway domains
string[] public Gateways;
/// @dev - List of secondary gateway domains (default)
string[] public Web3Gateways;
/// @dev - List of web2/L2 service gateway domains (fallback)
string[] public Web2Gateways;

/// @dev - Resolver function bytes4 selector → Off-chain record filename <name>.json
mapping(bytes4 => string) public funcMap;

Expand All @@ -49,10 +54,13 @@ contract GatewayManager is iERC173, iGatewayManager {
funcMap[iResolver.contenthash.selector] = "contenthash";
funcMap[iResolver.zonehash.selector] = "dns/zonehash";
/// @dev - Set initial list of secondary gateways
Gateways.push("dweb.link");
emit AddGateway("dweb.link");
Gateways.push("ipfs.io");
emit AddGateway("ipfs.io");
Web3Gateways.push("dweb.link");
emit Web3GatewayUpdated("dweb.link");
Web3Gateways.push("ipfs.io");
emit Web3GatewayUpdated("ipfs.io");

Web2Gateways.push("ccip.namesys.xyz");
emit Web2GatewayUpdated("ccip.namesys.xyz");
}

/**
Expand All @@ -69,20 +77,29 @@ contract GatewayManager is iERC173, iGatewayManager {
returns (string[] memory gateways)
{
/// @dev Filter recordhash vs. web2 gateway
if (_recordhash.length == 32) {
// Short IPNS hash
_recordhash = abi.encodePacked(hex"e5010172002408011220", _recordhash);
} else if (iGatewayManager(this).isWeb2(_recordhash)) {
// Web2 fallback
if (_recordhash.length == 0) {
// Default L2/Web2 service fallback
uint256 gateLen = Web2Gateways.length;
gateways = new string[](gateLen);
while (gateLen > 0) {
--gateLen;
gateways[gateLen] = string.concat(string("https://"), Web2Gateways[gateLen], _path, ".json?t={data}");
}
return gateways;
} else if (_recordhash[0] == bytes1("h") && iGatewayManager(this).isWeb2(_recordhash)) {
// Web2 set by owner
gateways = new string[](1);
gateways[0] = string.concat(string(_recordhash), _path, ".json?t={data}");
return gateways;
} else if (_recordhash.length == 32) {
// Short IPNS hash
_recordhash = abi.encodePacked(hex"e5010172002408011220", _recordhash);
}
unchecked {
uint256 gLen = Gateways.length;
uint256 gLen = Web3Gateways.length;
uint256 len = (gLen / 2) + 2;
if (len > 4) len = 4;
gateways = new string[](len);
if (len > 3) len = 3;
gateways = new string[](len+1);
uint256 i;
if (bytes(PrimaryGateway).length > 0) {
gateways[i++] = string.concat(
Expand Down Expand Up @@ -116,8 +133,9 @@ contract GatewayManager is iERC173, iGatewayManager {
}
while (i < len) {
seed = uint256(keccak256(abi.encodePacked(block.number * i, seed)));
gateways[i++] = string.concat("https://", Gateways[seed % gLen], _fullPath);
gateways[i++] = string.concat("https://", Web3Gateways[seed % gLen], _fullPath);
}
gateways[len] = string.concat("https://", Web2Gateways[0], _fullPath); // fallback,
}
}

Expand All @@ -128,7 +146,7 @@ contract GatewayManager is iERC173, iGatewayManager {
this;
response;
extradata;
revert UnimplementedFeature(iGatewayManager.__fallback.selector);
revert FeatureNotImplemented(iGatewayManager.__fallback.selector);
}

/**
Expand Down Expand Up @@ -170,7 +188,7 @@ contract GatewayManager is iERC173, iGatewayManager {
}
_jsonPath = string.concat("dns/", uintToString(resource));
} else {
revert UnimplementedFeature(func);
revert FeatureNotImplemented(func);
}
}

Expand Down Expand Up @@ -281,46 +299,84 @@ contract GatewayManager is iERC173, iGatewayManager {
*/
function addFuncMap(bytes4 _func, string calldata _name) external onlyDev {
funcMap[_func] = _name;
emit UpdateFuncFile(_func, _name);
emit FuncMapUpdated(_func, _name);
}

/**
* @dev Shows list of all available gateways
* @return list - List of gateways
* @dev Shows list of web3 gateways
* @return List of gateways
*/
function listGateways() external view returns (string[] memory list) {
return Gateways;
function listWeb3Gateways() external view returns (string[] memory) {
return Web3Gateways;
}

/**
* @dev Add a single gateway
* @param _domain - New gateway domain to add
*/
function addGateway(string calldata _domain) external onlyDev {
Gateways.push(_domain);
emit AddGateway(_domain);
function addWeb3Gateway(string calldata _domain) external onlyDev {
Web3Gateways.push(_domain);
emit Web3GatewayUpdated(_domain);
}

/**
* @dev Remove a single gateway
* @param _index - Gateway index to remove
*/
function removeWeb3Gateway(uint256 _index) external onlyDev {
require(Web3Gateways.length > 1, "Last Gateway");
emit Web3GatewayRemoved(Web3Gateways[_index]);
Web3Gateways[_index] = Web3Gateways[Web3Gateways.length - 1];
Web3Gateways.pop();
}

/**
* @dev Replace a single gateway
* @param _index : Gateway index to replace
* @param _domain : New gateway domain.tld
*/
function replaceWeb3Gateway(uint256 _index, string calldata _domain) external onlyDev {
emit Web3GatewayRemoved(Web3Gateways[_index]);
Web3Gateways[_index] = _domain;
emit Web3GatewayUpdated(_domain);
}

/**
* @dev Shows list of web2 gateways
* @return List of gateways
*/
function listWeb2Gateways() external view returns (string[] memory) {
return Web2Gateways;
}

/**
* @dev Add a single gateway
* @param _domain - New gateway domain to add
*/
function addWeb2Gateway(string calldata _domain) external onlyDev {
Web2Gateways.push(_domain);
emit Web2GatewayUpdated(_domain);
}
/**
* @dev Remove a single gateway
* @param _index - Gateway index to remove
*/
function removeGateway(uint256 _index) external onlyDev {
require(Gateways.length > 1, "Last Gateway");
emit RemoveGateway(Gateways[_index]);
Gateways[_index] = Gateways[Gateways.length - 1];
Gateways.pop();
function removeWeb2Gateway(uint256 _index) external onlyDev {
require(Web2Gateways.length > 1, "Last Gateway");
emit Web2GatewayRemoved(Web2Gateways[_index]);
Web2Gateways[_index] = Web2Gateways[Web2Gateways.length - 1];
Web2Gateways.pop();
}

/**
* @dev Replace a single gateway
* @param _index : Gateway index to replace
* @param _domain : New gateway domain.tld
*/
function replaceGateway(uint256 _index, string calldata _domain) external onlyDev {
emit RemoveGateway(Gateways[_index]);
Gateways[_index] = _domain;
emit AddGateway(_domain);
function replaceWeb2Gateway(uint256 _index, string calldata _domain) external onlyDev {
emit Web2GatewayRemoved(Web2Gateways[_index]);
Web2Gateways[_index] = _domain;
emit Web2GatewayUpdated(_domain);
}

/**
Expand Down
14 changes: 10 additions & 4 deletions src/Interface.sol
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,24 @@ interface iGatewayManager is iERC173 {
function bytesToHexString(bytes calldata _buffer, uint256 _start) external pure returns (string memory);
function bytes32ToHexString(bytes32 _buffer) external pure returns (string memory);
function funcToJson(bytes calldata _request) external view returns (string memory _jsonPath);
function listGateways() external view returns (string[] memory list);
function toChecksumAddress(address _addr) external pure returns (string memory);
function __fallback(bytes calldata response, bytes calldata extradata)
external
view
returns (bytes memory result);
function addFuncMap(bytes4 _func, string calldata _name) external;
function addGateway(string calldata _domain) external;
function removeGateway(uint256 _index) external;
function replaceGateway(uint256 _index, string calldata _domain) external;
function formatSubdomain(bytes calldata _recordhash) external pure returns (string memory result);
function isWeb2(bytes calldata _recordhash) external pure returns (bool);

function listWeb2Gateways() external view returns (string[] memory list);
function addWeb2Gateway(string calldata _domain) external;
function removeWeb2Gateway(uint256 _index) external;
function replaceWeb2Gateway(uint256 _index, string calldata _domain) external;

function listWeb3Gateways() external view returns (string[] memory list);
function addWeb3Gateway(string calldata _domain) external;
function removeWeb3Gateway(uint256 _index) external;
function replaceWeb3Gateway(uint256 _index, string calldata _domain) external;
}

interface iResolver {
Expand Down
Loading

0 comments on commit 7fd2aec

Please sign in to comment.