diff --git a/_data/chains/1.json b/_data/chains/1.json index cf504990..ed73126e 100644 --- a/_data/chains/1.json +++ b/_data/chains/1.json @@ -16,5 +16,8 @@ "shortName": "eth", "chainId": 1, "networkId": 1, - "slip44": 60 -} \ No newline at end of file + "slip44": 60, + "ens": { + "registry":"0x314159265dd8dbb310642f98f50c066173c1259b" + } +} diff --git a/_data/chains/3.json b/_data/chains/3.json index 729e78df..2397249e 100644 --- a/_data/chains/3.json +++ b/_data/chains/3.json @@ -16,5 +16,8 @@ "infoURL": "https://github.com/ethereum/ropsten", "shortName": "rop", "chainId": 3, - "networkId": 3 -} \ No newline at end of file + "networkId": 3, + "ens": { + "registry":"0x112234455c3a32fd11230c42e7bccd4a84e02010" + } +} diff --git a/_data/chains/4.json b/_data/chains/4.json index 6231b39f..6e05e11d 100644 --- a/_data/chains/4.json +++ b/_data/chains/4.json @@ -16,5 +16,8 @@ "infoURL": "https://www.rinkeby.io", "shortName": "rin", "chainId": 4, - "networkId": 4 -} \ No newline at end of file + "networkId": 4, + "ens": { + "registry":"0xe7410170f87102df0055eb195163a03b7f2bff4a" + } +} diff --git a/_data/chains/5.json b/_data/chains/5.json index 42df8803..8546b535 100644 --- a/_data/chains/5.json +++ b/_data/chains/5.json @@ -19,5 +19,8 @@ "infoURL": "https://goerli.net/#about", "shortName": "gor", "chainId": 5, - "networkId": 5 -} \ No newline at end of file + "networkId": 5, + "ens": { + "registry":"0x112234455c3a32fd11230c42e7bccd4a84e02010" + } +} diff --git a/src/main/kotlin/org/ethereum/lists/chains/ChainChecker.kt b/src/main/kotlin/org/ethereum/lists/chains/ChainChecker.kt index 24174b43..4227387c 100644 --- a/src/main/kotlin/org/ethereum/lists/chains/ChainChecker.kt +++ b/src/main/kotlin/org/ethereum/lists/chains/ChainChecker.kt @@ -2,6 +2,8 @@ package org.ethereum.lists.chains import com.beust.klaxon.JsonObject import com.beust.klaxon.Klaxon +import org.kethereum.functions.isValid +import org.kethereum.model.Address import org.kethereum.rpc.HttpEthereumRPC import java.io.File import java.math.BigInteger @@ -19,7 +21,8 @@ val mandatory_fields = listOf( "nativeCurrency" ) val optionalFields = listOf( - "slip44" + "slip44", + "ens" ) class FileNameMustMatchChainId : Exception("chainId must match the filename") @@ -28,6 +31,9 @@ class ShouldHaveNoExtraFields(fields: Set) : Exception("should have no e class ShouldHaveNoMissingFields(fields: Set) : Exception("missing field(s) $fields") class RPCMustBeList : Exception("rpc must be a list") class RPCMustBeListOfStrings : Exception("rpc must be a list of strings") +class ENSMustBeObject: Exception("ens must be an object") +class ENSMustHaveOnlyRegistry: Exception("ens can only have a registry currently") +class ENSRegistryAddressMustBeValid: Exception("ens registry must have valid address") fun checkChain(it: File, connectRPC: Boolean) { println("processing $it") @@ -53,6 +59,21 @@ fun checkChain(it: File, connectRPC: Boolean) { if (missingFields.isNotEmpty()) { throw ShouldHaveNoMissingFields(missingFields) } + + jsonObject["ens"]?.let { + if (it !is JsonObject) { + throw ENSMustBeObject() + } + if (it.keys != mutableSetOf("registry")) { + throw ENSMustHaveOnlyRegistry() + } + + val address = Address(it["registry"] as String) + if (!address.isValid()) { + throw ENSRegistryAddressMustBeValid() + } + } + if (connectRPC) { if (jsonObject["rpc"] is List<*>) { (jsonObject["rpc"] as List<*>).forEach { diff --git a/src/test/kotlin/TheChainChecker.kt b/src/test/kotlin/TheChainChecker.kt index 7bebe31e..7805d3a8 100644 --- a/src/test/kotlin/TheChainChecker.kt +++ b/src/test/kotlin/TheChainChecker.kt @@ -39,6 +39,35 @@ class TheChainChecker { checkChain(file, false) } + + @Test(expected = ENSRegistryAddressMustBeValid::class) + fun shouldFailForInvalidENSAddress() { + val file = getFile("invalid/99.json") + + checkChain(file, false) + } + + @Test(expected = ENSMustHaveOnlyRegistry::class) + fun shouldFailForExtraENSFields() { + val file = getFile("invalid/100.json") + + checkChain(file, false) + } + + @Test(expected = ENSMustHaveOnlyRegistry::class) + fun shouldFailForNoRegistryField() { + val file = getFile("invalid/101.json") + + checkChain(file, false) + } + + @Test(expected = ENSMustBeObject::class) + fun shouldFailForENSISNotObject() { + val file = getFile("invalid/102.json") + + checkChain(file, false) + } + @Test(expected = ExtensionMustBeJSON::class) fun shouldFailFoNonJSON() { val file = getFile("invalid/1.nojson") diff --git a/src/test/resources/test_chains/invalid/100.json b/src/test/resources/test_chains/invalid/100.json new file mode 100644 index 00000000..81e25dab --- /dev/null +++ b/src/test/resources/test_chains/invalid/100.json @@ -0,0 +1,23 @@ +{ + "name": "Ethereum Mainnet", + "shortName": "eth", + "chain": "ETH", + "network": "mainnet", + "chainId": 100, + "networkId": 1, + "rpc": [ + "https://mainnet.infura.io/v3/${INFURA_API_KEY}", + "https://api.mycryptoapi.com/eth" + ], + "faucets": [], + "infoURL": "https://ethereum.org", + "nativeCurrency": { + "name": "Ether", + "symbol": "ETH", + "decimals": 18 + }, + "ens": { + "registry":"0x112234455c3a32fd11230c42e7bccd4a84e02010", + "yolo": 1 + } +} diff --git a/src/test/resources/test_chains/invalid/101.json b/src/test/resources/test_chains/invalid/101.json new file mode 100644 index 00000000..77b47d36 --- /dev/null +++ b/src/test/resources/test_chains/invalid/101.json @@ -0,0 +1,21 @@ +{ + "name": "Ethereum Mainnet", + "shortName": "eth", + "chain": "ETH", + "network": "mainnet", + "chainId": 101, + "networkId": 1, + "rpc": [ + "https://mainnet.infura.io/v3/${INFURA_API_KEY}", + "https://api.mycryptoapi.com/eth" + ], + "faucets": [], + "infoURL": "https://ethereum.org", + "nativeCurrency": { + "name": "Ether", + "symbol": "ETH", + "decimals": 18 + }, + "ens": { + } +} diff --git a/src/test/resources/test_chains/invalid/102.json b/src/test/resources/test_chains/invalid/102.json new file mode 100644 index 00000000..4fa97075 --- /dev/null +++ b/src/test/resources/test_chains/invalid/102.json @@ -0,0 +1,20 @@ +{ + "name": "Ethereum Mainnet", + "shortName": "eth", + "chain": "ETH", + "network": "mainnet", + "chainId": 102, + "networkId": 1, + "rpc": [ + "https://mainnet.infura.io/v3/${INFURA_API_KEY}", + "https://api.mycryptoapi.com/eth" + ], + "faucets": [], + "infoURL": "https://ethereum.org", + "nativeCurrency": { + "name": "Ether", + "symbol": "ETH", + "decimals": 18 + }, + "ens": "" +} diff --git a/src/test/resources/test_chains/invalid/99.json b/src/test/resources/test_chains/invalid/99.json new file mode 100644 index 00000000..a48d9479 --- /dev/null +++ b/src/test/resources/test_chains/invalid/99.json @@ -0,0 +1,22 @@ +{ + "name": "Ethereum Mainnet", + "shortName": "eth", + "chain": "ETH", + "network": "mainnet", + "chainId": 99, + "networkId": 1, + "rpc": [ + "https://mainnet.infura.io/v3/${INFURA_API_KEY}", + "https://api.mycryptoapi.com/eth" + ], + "faucets": [], + "infoURL": "https://ethereum.org", + "nativeCurrency": { + "name": "Ether", + "symbol": "ETH", + "decimals": 18 + }, + "ens": { + "registry":"0x112234455c3a32fd11230c42e7bccd4a84e02010yolo" + } +} diff --git a/src/test/resources/test_chains/valid/5.json b/src/test/resources/test_chains/valid/5.json new file mode 100644 index 00000000..f8c7e5a0 --- /dev/null +++ b/src/test/resources/test_chains/valid/5.json @@ -0,0 +1,26 @@ +{ + "name": "Ethereum Testnet Görli", + "chain": "ETH", + "network": "goerli", + "rpc": [ + "https://rpc.goerli.mudit.blog/", + "https://rpc.slock.it/goerli ", + "https://goerli.prylabs.net" + ], + "faucets": [ + "https://goerli-faucet.slock.it/?address=${ADDRESS}", + "https://faucet.goerli.mudit.blog" + ], + "nativeCurrency": { + "name": "Görli Ether", + "symbol": "GOR", + "decimals": 18 + }, + "infoURL": "https://goerli.net/#about", + "shortName": "gor", + "chainId": 5, + "networkId": 5, + "ens": { + "registry":"0x112234455c3a32fd11230c42e7bccd4a84e02010" + } +}