From 27b1857a11b2a012e0edc4ec62fa04a68ccdf0b9 Mon Sep 17 00:00:00 2001 From: katzman Date: Thu, 23 May 2024 10:52:42 -0700 Subject: [PATCH] Ownable L1 Resolver (#6) * Add permissioned setUrl endpoint to L1 Resolver, redeploy to testnet * Add script to set URL * Start adding tests for L1 Resolver * Added more tests * L1Resolver tests * Add more tests, reorg existing ones * More L1Resolver Tests * Fix fallback, add test * Updated comments in Constants * Constructor arg name change to match style guide * Add supportsInterface call to rootResolver * Update contracts/src/L1/L1Resolver.sol Co-authored-by: wilsoncusack * Update contracts/src/L1/L1Resolver.sol Co-authored-by: wilsoncusack * Small fixes from PR --------- Co-authored-by: wilsoncusack --- .../11155111/run-1715636813.json | 80 ++++++++++++++++ .../11155111/run-1715636990.json | 50 ++++++++++ .../11155111/run-latest.json | 60 +++++------- .../configure/EstablishBaseNamespace.s.sol | 8 +- contracts/script/configure/MakeNewName.s.sol | 25 ++--- .../script/configure/SetL1ResolverUrl.s.sol | 20 ++++ .../script/deploy/DeployL1Resolver.s.sol | 13 +-- .../script/deploy/DeployL2Resolver.s.sol | 20 ++-- .../deploy/DeployReverseRegistrar.s.sol | 7 +- .../script/deploy/DeployTestnetRegistry.s.sol | 3 +- .../script/resolve/ResolveCallback.s.sol | 64 ++++++++----- contracts/src/L1/L1Resolver.sol | 94 +++++++++++++++++-- contracts/src/L2/Registry.sol | 4 +- contracts/src/lib/SignatureVerifier.sol | 7 +- contracts/src/util/Constants.sol | 6 ++ contracts/test/L1Resolver.t.sol | 23 ----- contracts/test/L1Resolver/AdminMethods.t.sol | 57 +++++++++++ contracts/test/L1Resolver/Fallback.t.sol | 31 ++++++ .../test/L1Resolver/L1ResolverBase.t.sol | 38 ++++++++ .../test/L1Resolver/MakeSignatureHash.t.sol | 20 ++++ contracts/test/L1Resolver/Resolve.t.sol | 42 +++++++++ .../test/L1Resolver/ResolveWithProof.t.sol | 76 +++++++++++++++ .../test/L1Resolver/SupportsInterface.t.sol | 39 ++++++++ contracts/test/mocks/MockPublicResolver.sol | 31 ++++++ 24 files changed, 671 insertions(+), 147 deletions(-) create mode 100644 contracts/broadcast/DeployL1Resolver.s.sol/11155111/run-1715636813.json create mode 100644 contracts/broadcast/DeployL1Resolver.s.sol/11155111/run-1715636990.json create mode 100644 contracts/script/configure/SetL1ResolverUrl.s.sol delete mode 100644 contracts/test/L1Resolver.t.sol create mode 100644 contracts/test/L1Resolver/AdminMethods.t.sol create mode 100644 contracts/test/L1Resolver/Fallback.t.sol create mode 100644 contracts/test/L1Resolver/L1ResolverBase.t.sol create mode 100644 contracts/test/L1Resolver/MakeSignatureHash.t.sol create mode 100644 contracts/test/L1Resolver/Resolve.t.sol create mode 100644 contracts/test/L1Resolver/ResolveWithProof.t.sol create mode 100644 contracts/test/L1Resolver/SupportsInterface.t.sol create mode 100644 contracts/test/mocks/MockPublicResolver.sol diff --git a/contracts/broadcast/DeployL1Resolver.s.sol/11155111/run-1715636813.json b/contracts/broadcast/DeployL1Resolver.s.sol/11155111/run-1715636813.json new file mode 100644 index 00000000..8a0837ba --- /dev/null +++ b/contracts/broadcast/DeployL1Resolver.s.sol/11155111/run-1715636813.json @@ -0,0 +1,80 @@ +{ + "transactions": [ + { + "hash": "0xc904646584f1fd821c8c30b0f4df2eb69f94abccc5a474397e7e22ba90e51269", + "transactionType": "CREATE", + "contractName": "L1Resolver", + "contractAddress": "0x5F15c3B5949F5767F5Ca9013a8E4Ca4D97a053eD", + "function": null, + "arguments": [ + "\"https://localhost:8000/api/v1/domain/resolver/resolveDomain/{sender}/{data}\"", + "[0xa412c16ECd2198A6aBce8235651E105684Fb77ed]", + "0x869140c91eDF43214a3EcEdEAF777cc7107aD71a" + ], + "transaction": { + "type": "0x02", + "from": "0x869140c91edf43214a3ecedeaf777cc7107ad71a", + "gas": "0x1475fd", + "value": "0x0", + "data": "0x60806040523480156200001157600080fd5b50604051620013b8380380620013b8833981016040819052620000349162000226565b6000620000428482620003a5565b5060005b8251811015620000a55760018060008584815181106200006a576200006a62000471565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905560010162000046565b50620000b181620000f3565b7fab0b9cc3a46b568cb08d985497cde8ab7e18892d01f58db7dc7f0d2af859b2d782604051620000e2919062000487565b60405180910390a1505050620004d6565b6001600160a01b0316638b78c6d8198190558060007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a350565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156200017057620001706200012f565b604052919050565b80516001600160a01b03811681146200019057600080fd5b919050565b600082601f830112620001a757600080fd5b815160206001600160401b03821115620001c557620001c56200012f565b8160051b620001d682820162000145565b9283528481018201928281019087851115620001f157600080fd5b83870192505b848310156200021b576200020b8362000178565b82529183019190830190620001f7565b979650505050505050565b6000806000606084860312156200023c57600080fd5b83516001600160401b03808211156200025457600080fd5b818601915086601f8301126200026957600080fd5b8151818111156200027e576200027e6200012f565b602062000294601f8301601f1916820162000145565b8281528982848701011115620002a957600080fd5b60005b83811015620002c9578581018301518282018401528201620002ac565b506000928101820192909252870151909550915080821115620002eb57600080fd5b50620002fa8682870162000195565b9250506200030b6040850162000178565b90509250925092565b600181811c908216806200032957607f821691505b6020821081036200034a57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620003a0576000816000526020600020601f850160051c810160208610156200037b5750805b601f850160051c820191505b818110156200039c5782815560010162000387565b5050505b505050565b81516001600160401b03811115620003c157620003c16200012f565b620003d981620003d2845462000314565b8462000350565b602080601f831160018114620004115760008415620003f85750858301515b600019600386901b1c1916600185901b1785556200039c565b600085815260208120601f198616915b82811015620004425788860151825594840194600190910190840162000421565b5085821015620004615787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052603260045260246000fd5b6020808252825182820181905260009190848201906040850190845b81811015620004ca5783516001600160a01b031683529284019291840191600101620004a3565b50909695505050505050565b610ed280620004e66000396000f3fe6080604052600436106100dd5760003560e01c8063736c0d5b1161007f578063f04e283e11610059578063f04e283e1461021d578063f2fde38b14610230578063f4d4d2f814610243578063fee81cf41461026357600080fd5b8063736c0d5b146101a15780638da5cb5b146101d15780639061b923146101fd57600080fd5b806325692962116100bb578063256929621461016757806354d1f13d1461016f5780635600f04f14610177578063715018a61461019957600080fd5b806301ffc9a7146100e25780631dcfea0914610117578063252498a214610145575b600080fd5b3480156100ee57600080fd5b506101026100fd3660046108c7565b610296565b60405190151581526020015b60405180910390f35b34801561012357600080fd5b506101376101323660046109cf565b6102cd565b60405190815260200161010e565b34801561015157600080fd5b50610165610160366004610a9d565b6102e4565b005b6101656102fe565b61016561034e565b34801561018357600080fd5b5061018c61038a565b60405161010e9190610b25565b610165610418565b3480156101ad57600080fd5b506101026101bc366004610b38565b60016020526000908152604090205460ff1681565b3480156101dd57600080fd5b50638b78c6d819546040516001600160a01b03909116815260200161010e565b34801561020957600080fd5b5061018c610218366004610b53565b61042c565b61016561022b366004610b38565b61058c565b61016561023e366004610b38565b6105cc565b34801561024f57600080fd5b5061018c61025e366004610b53565b6105f3565b34801561026f57600080fd5b5061013761027e366004610b38565b63389a75e1600c908152600091909152602090205490565b60006001600160e01b03198216639061b92360e01b14806102c757506301ffc9a760e01b6001600160e01b03198316145b92915050565b60006102db85858585610687565b95945050505050565b6102ec6106ff565b60006102f9828483610c49565b505050565b60006202a30067ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b6000805461039790610bbf565b80601f01602080910402602001604051908101604052809291908181526020018280546103c390610bbf565b80156104105780601f106103e557610100808354040283529160200191610410565b820191906000526020600020905b8154815290600101906020018083116103f357829003601f168201915b505050505081565b6104206106ff565b61042a600061071a565b565b60606000639061b92360e01b8686868660405160240161044f9493929190610d33565b60408051601f19818403018152918152602080830180516001600160e01b03166001600160e01b031995909516949094179093528051600180825281830190925291935060009282015b6060815260200190600190039081610499579050509050600080546104bd90610bbf565b80601f01602080910402602001604051908101604052809291908181526020018280546104e990610bbf565b80156105365780601f1061050b57610100808354040283529160200191610536565b820191906000526020600020905b81548152906001019060200180831161051957829003601f168201915b50505050508160008151811061054e5761054e610d65565b6020908102919091010152604051630556f18360e41b815261058390309083908590631e9a9a5f60e31b908290600401610d7b565b60405180910390fd5b6105946106ff565b63389a75e1600c52806000526020600c2080544211156105bc57636f5e88186000526004601cfd5b600090556105c98161071a565b50565b6105d46106ff565b8060601b6105ea57637448fbae6000526004601cfd5b6105c98161071a565b606060008061060485858989610758565b6001600160a01b038216600090815260016020526040902054919350915060ff1661067d5760405162461bcd60e51b815260206004820152602360248201527f5369676e617475726556657269666965723a20496e76616c696420736967617460448201526275726560e81b6064820152608401610583565b9695505050505050565b815160209283012081519183019190912060408051601960f81b8186015260609690961b6bffffffffffffffffffffffff1916602287015260c09490941b6001600160c01b0319166036860152603e850191909152605e8085019190915282518085039091018152607e909301909152815191012090565b638b78c6d81954331461042a576382b429006000526004601cfd5b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b6000606081808061076b86880188610e28565b92509250925060006107bf6107b930858d8d8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b9250610687915050565b83610836565b9050428367ffffffffffffffff1610156108275760405162461bcd60e51b8152602060048201526024808201527f5369676e617475726556657269666965723a205369676e6174757265206578706044820152631a5c995960e21b6064820152608401610583565b99929850919650505050505050565b604051600190836000526020830151604052604083510361087257604083015160ff81901c601b016020526001600160ff1b0316606052610898565b604183510361089357606083015160001a6020526040830151606052610898565b600091505b6020600160806000855afa5191503d6108b957638baa579f6000526004601cfd5b600060605260405292915050565b6000602082840312156108d957600080fd5b81356001600160e01b0319811681146108f157600080fd5b9392505050565b80356001600160a01b038116811461090f57600080fd5b919050565b803567ffffffffffffffff8116811461090f57600080fd5b634e487b7160e01b600052604160045260246000fd5b600082601f83011261095357600080fd5b813567ffffffffffffffff8082111561096e5761096e61092c565b604051601f8301601f19908116603f011681019082821181831017156109965761099661092c565b816040528381528660208588010111156109af57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080608085870312156109e557600080fd5b6109ee856108f8565b93506109fc60208601610914565b9250604085013567ffffffffffffffff80821115610a1957600080fd5b610a2588838901610942565b93506060870135915080821115610a3b57600080fd5b50610a4887828801610942565b91505092959194509250565b60008083601f840112610a6657600080fd5b50813567ffffffffffffffff811115610a7e57600080fd5b602083019150836020828501011115610a9657600080fd5b9250929050565b60008060208385031215610ab057600080fd5b823567ffffffffffffffff811115610ac757600080fd5b610ad385828601610a54565b90969095509350505050565b6000815180845260005b81811015610b0557602081850181015186830182015201610ae9565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006108f16020830184610adf565b600060208284031215610b4a57600080fd5b6108f1826108f8565b60008060008060408587031215610b6957600080fd5b843567ffffffffffffffff80821115610b8157600080fd5b610b8d88838901610a54565b90965094506020870135915080821115610ba657600080fd5b50610bb387828801610a54565b95989497509550505050565b600181811c90821680610bd357607f821691505b602082108103610bf357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156102f9576000816000526020600020601f850160051c81016020861015610c225750805b601f850160051c820191505b81811015610c4157828155600101610c2e565b505050505050565b67ffffffffffffffff831115610c6157610c6161092c565b610c7583610c6f8354610bbf565b83610bf9565b6000601f841160018114610ca95760008515610c915750838201355b600019600387901b1c1916600186901b178355610d03565b600083815260209020601f19861690835b82811015610cda5786850135825560209485019460019092019101610cba565b5086821015610cf75760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b604081526000610d47604083018688610d0a565b8281036020840152610d5a818587610d0a565b979650505050505050565b634e487b7160e01b600052603260045260246000fd5b600060a0820160018060a01b0388168352602060a0602085015281885180845260c08601915060c08160051b870101935060208a0160005b82811015610de15760bf19888703018452610dcf868351610adf565b95509284019290840190600101610db3565b50505050508281036040840152610df88187610adf565b6001600160e01b03198616606085015290508281036080840152610e1c8185610adf565b98975050505050505050565b600080600060608486031215610e3d57600080fd5b833567ffffffffffffffff80821115610e5557600080fd5b610e6187838801610942565b9450610e6f60208701610914565b93506040860135915080821115610e8557600080fd5b50610e9286828701610942565b915050925092509256fea26469706673582212202946e0f9776da0c0f03cc6e0dd2bb4a25cc681e857eaeb649eeb7ba3534bb80364736f6c63430008170033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000869140c91edf43214a3ecedeaf777cc7107ad71a000000000000000000000000000000000000000000000000000000000000004b68747470733a2f2f6c6f63616c686f73743a383030302f6170692f76312f646f6d61696e2f7265736f6c7665722f7265736f6c7665446f6d61696e2f7b73656e6465727d2f7b646174617d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a412c16ecd2198a6abce8235651e105684fb77ed", + "nonce": "0x1", + "accessList": [] + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "transactionHash": "0xc904646584f1fd821c8c30b0f4df2eb69f94abccc5a474397e7e22ba90e51269", + "transactionIndex": "0xd", + "blockHash": "0xa18c42d59d547b6d5e389adde6becfad18a06eeea17dd9eccc8d4e75c3d49629", + "blockNumber": "0x59fb34", + "from": "0x869140c91eDF43214a3EcEdEAF777cc7107aD71a", + "to": null, + "cumulativeGasUsed": "0x27273e", + "gasUsed": "0xfbe87", + "contractAddress": "0x5F15c3B5949F5767F5Ca9013a8E4Ca4D97a053eD", + "logs": [ + { + "address": "0x5F15c3B5949F5767F5Ca9013a8E4Ca4D97a053eD", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000869140c91edf43214a3ecedeaf777cc7107ad71a" + ], + "data": "0x", + "blockHash": "0xa18c42d59d547b6d5e389adde6becfad18a06eeea17dd9eccc8d4e75c3d49629", + "blockNumber": "0x59fb34", + "transactionHash": "0xc904646584f1fd821c8c30b0f4df2eb69f94abccc5a474397e7e22ba90e51269", + "transactionIndex": "0xd", + "logIndex": "0x1e", + "removed": false + }, + { + "address": "0x5F15c3B5949F5767F5Ca9013a8E4Ca4D97a053eD", + "topics": [ + "0xab0b9cc3a46b568cb08d985497cde8ab7e18892d01f58db7dc7f0d2af859b2d7" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a412c16ecd2198a6abce8235651e105684fb77ed", + "blockHash": "0xa18c42d59d547b6d5e389adde6becfad18a06eeea17dd9eccc8d4e75c3d49629", + "blockNumber": "0x59fb34", + "transactionHash": "0xc904646584f1fd821c8c30b0f4df2eb69f94abccc5a474397e7e22ba90e51269", + "transactionIndex": "0xd", + "logIndex": "0x1f", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000400000000000000000000000000000000000000000800008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000001000000000000000000000000000000000000020000008000000000000800000000000000000000000000000000400000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000100000000000000000000200000002000000000000000", + "type": "0x2", + "effectiveGasPrice": "0x42d1b609e" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1715636813, + "chain": 11155111, + "commit": "5f0dc54" +} \ No newline at end of file diff --git a/contracts/broadcast/DeployL1Resolver.s.sol/11155111/run-1715636990.json b/contracts/broadcast/DeployL1Resolver.s.sol/11155111/run-1715636990.json new file mode 100644 index 00000000..4423d281 --- /dev/null +++ b/contracts/broadcast/DeployL1Resolver.s.sol/11155111/run-1715636990.json @@ -0,0 +1,50 @@ +{ + "transactions": [ + { + "hash": "0x5385b5f8b2376ca4d7888e7b6d7f429ca4e88640292e38ebddfd3bfd9959063e", + "transactionType": "CALL", + "contractName": null, + "contractAddress": "0x5F15c3B5949F5767F5Ca9013a8E4Ca4D97a053eD", + "function": "setUrl(string)", + "arguments": [ + "\"http://localhost:8000/api/v1/domain/resolver/resolveDomain/{sender}/{data}\"" + ], + "transaction": { + "type": "0x02", + "from": "0x869140c91edf43214a3ecedeaf777cc7107ad71a", + "to": "0x5f15c3b5949f5767f5ca9013a8e4ca4d97a053ed", + "gas": "0x10736", + "value": "0x0", + "data": "0x252498a20000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004a687474703a2f2f6c6f63616c686f73743a383030302f6170692f76312f646f6d61696e2f7265736f6c7665722f7265736f6c7665446f6d61696e2f7b73656e6465727d2f7b646174617d00000000000000000000000000000000000000000000", + "nonce": "0x2", + "accessList": [] + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "transactionHash": "0x5385b5f8b2376ca4d7888e7b6d7f429ca4e88640292e38ebddfd3bfd9959063e", + "transactionIndex": "0x3", + "blockHash": "0x5403573a93adc83ab9b82706d77d82c504b7e8b38921132f0827ee2de56fe02f", + "blockNumber": "0x59fb42", + "from": "0x869140c91eDF43214a3EcEdEAF777cc7107aD71a", + "to": "0x5F15c3B5949F5767F5Ca9013a8E4Ca4D97a053eD", + "cumulativeGasUsed": "0x635df", + "gasUsed": "0xb3fa", + "contractAddress": null, + "logs": [], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0x433be5a18" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1715636990, + "chain": 11155111, + "commit": "5f0dc54" +} \ No newline at end of file diff --git a/contracts/broadcast/DeployL1Resolver.s.sol/11155111/run-latest.json b/contracts/broadcast/DeployL1Resolver.s.sol/11155111/run-latest.json index 79b4cc75..4423d281 100644 --- a/contracts/broadcast/DeployL1Resolver.s.sol/11155111/run-latest.json +++ b/contracts/broadcast/DeployL1Resolver.s.sol/11155111/run-latest.json @@ -1,22 +1,22 @@ { "transactions": [ { - "hash": "0x502eb6d582f6dad91e282470545213ff058ad87fb55f0a776aa082b771035c4d", - "transactionType": "CREATE", - "contractName": "L1Resolver", - "contractAddress": "0xBD69dd64b94fe7435157F4851e4b4Aa3A0988c90", - "function": null, + "hash": "0x5385b5f8b2376ca4d7888e7b6d7f429ca4e88640292e38ebddfd3bfd9959063e", + "transactionType": "CALL", + "contractName": null, + "contractAddress": "0x5F15c3B5949F5767F5Ca9013a8E4Ca4D97a053eD", + "function": "setUrl(string)", "arguments": [ - "\"https://subdomain-did-api-dev.cbhq.net:8000/api/v1/domain/resolver/resolveDomain/{sender}/{data}\"", - "[0xa412c16ECd2198A6aBce8235651E105684Fb77ed]" + "\"http://localhost:8000/api/v1/domain/resolver/resolveDomain/{sender}/{data}\"" ], "transaction": { "type": "0x02", "from": "0x869140c91edf43214a3ecedeaf777cc7107ad71a", - "gas": "0xf3467", + "to": "0x5f15c3b5949f5767f5ca9013a8e4ca4d97a053ed", + "gas": "0x10736", "value": "0x0", - "data": "0x60806040523480156200001157600080fd5b5060405162000efa38038062000efa8339810160408190526200003491620001cf565b60006200004283826200033c565b5060005b8151811015620000a55760018060008484815181106200006a576200006a62000408565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905560010162000046565b507fab0b9cc3a46b568cb08d985497cde8ab7e18892d01f58db7dc7f0d2af859b2d781604051620000d791906200041e565b60405180910390a150506200046d565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715620001285762000128620000e7565b604052919050565b600082601f8301126200014257600080fd5b815160206001600160401b03821115620001605762000160620000e7565b8160051b62000171828201620000fd565b92835284810182019282810190878511156200018c57600080fd5b83870192505b84831015620001c45782516001600160a01b0381168114620001b45760008081fd5b8252918301919083019062000192565b979650505050505050565b60008060408385031215620001e357600080fd5b82516001600160401b0380821115620001fb57600080fd5b818501915085601f8301126200021057600080fd5b815181811115620002255762000225620000e7565b60206200023b601f8301601f19168201620000fd565b82815288828487010111156200025057600080fd5b60005b838110156200027057858101830151828201840152820162000253565b5060009281018201929092528601519094509150808211156200029257600080fd5b50620002a18582860162000130565b9150509250929050565b600181811c90821680620002c057607f821691505b602082108103620002e157634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000337576000816000526020600020601f850160051c81016020861015620003125750805b601f850160051c820191505b8181101562000333578281556001016200031e565b5050505b505050565b81516001600160401b03811115620003585762000358620000e7565b6200037081620003698454620002ab565b84620002e7565b602080601f831160018114620003a857600084156200038f5750858301515b600019600386901b1c1916600185901b17855562000333565b600085815260208120601f198616915b82811015620003d957888601518255948401946001909101908401620003b8565b5085821015620003f85787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052603260045260246000fd5b6020808252825182820181905260009190848201906040850190845b81811015620004615783516001600160a01b0316835292840192918401916001016200043a565b50909695505050505050565b610a7d806200047d6000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806301ffc9a7146100675780631dcfea091461008f5780635600f04f146100b0578063736c0d5b146100c55780639061b923146100e8578063f4d4d2f8146100fb575b600080fd5b61007a6100753660046105c5565b61010e565b60405190151581526020015b60405180910390f35b6100a261009d3660046106cd565b610145565b604051908152602001610086565b6100b861015c565b6040516100869190610798565b61007a6100d33660046107ab565b60016020526000908152604090205460ff1681565b6100b86100f636600461080f565b6101ea565b6100b861010936600461080f565b61034a565b60006001600160e01b03198216639061b92360e01b148061013f57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6000610153858585856103de565b95945050505050565b600080546101699061087b565b80601f01602080910402602001604051908101604052809291908181526020018280546101959061087b565b80156101e25780601f106101b7576101008083540402835291602001916101e2565b820191906000526020600020905b8154815290600101906020018083116101c557829003601f168201915b505050505081565b60606000639061b92360e01b8686868660405160240161020d94939291906108de565b60408051601f19818403018152918152602080830180516001600160e01b03166001600160e01b031995909516949094179093528051600180825281830190925291935060009282015b60608152602001906001900390816102575790505090506000805461027b9061087b565b80601f01602080910402602001604051908101604052809291908181526020018280546102a79061087b565b80156102f45780601f106102c9576101008083540402835291602001916102f4565b820191906000526020600020905b8154815290600101906020018083116102d757829003601f168201915b50505050508160008151811061030c5761030c610910565b6020908102919091010152604051630556f18360e41b815261034190309083908590631e9a9a5f60e31b908290600401610926565b60405180910390fd5b606060008061035b85858989610456565b6001600160a01b038216600090815260016020526040902054919350915060ff166103d45760405162461bcd60e51b815260206004820152602360248201527f5369676e617475726556657269666965723a20496e76616c696420736967617460448201526275726560e81b6064820152608401610341565b9695505050505050565b815160209283012081519183019190912060408051601960f81b8186015260609690961b6bffffffffffffffffffffffff1916602287015260c09490941b6001600160c01b0319166036860152603e850191909152605e8085019190915282518085039091018152607e909301909152815191012090565b60006060818080610469868801886109d3565b92509250925060006104bd6104b730858d8d8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b92506103de915050565b83610534565b9050428367ffffffffffffffff1610156105255760405162461bcd60e51b8152602060048201526024808201527f5369676e617475726556657269666965723a205369676e6174757265206578706044820152631a5c995960e21b6064820152608401610341565b99929850919650505050505050565b604051600190836000526020830151604052604083510361057057604083015160ff81901c601b016020526001600160ff1b0316606052610596565b604183510361059157606083015160001a6020526040830151606052610596565b600091505b6020600160806000855afa5191503d6105b757638baa579f6000526004601cfd5b600060605260405292915050565b6000602082840312156105d757600080fd5b81356001600160e01b0319811681146105ef57600080fd5b9392505050565b80356001600160a01b038116811461060d57600080fd5b919050565b803567ffffffffffffffff8116811461060d57600080fd5b634e487b7160e01b600052604160045260246000fd5b600082601f83011261065157600080fd5b813567ffffffffffffffff8082111561066c5761066c61062a565b604051601f8301601f19908116603f011681019082821181831017156106945761069461062a565b816040528381528660208588010111156106ad57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080608085870312156106e357600080fd5b6106ec856105f6565b93506106fa60208601610612565b9250604085013567ffffffffffffffff8082111561071757600080fd5b61072388838901610640565b9350606087013591508082111561073957600080fd5b5061074687828801610640565b91505092959194509250565b6000815180845260005b818110156107785760208185018101518683018201520161075c565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006105ef6020830184610752565b6000602082840312156107bd57600080fd5b6105ef826105f6565b60008083601f8401126107d857600080fd5b50813567ffffffffffffffff8111156107f057600080fd5b60208301915083602082850101111561080857600080fd5b9250929050565b6000806000806040858703121561082557600080fd5b843567ffffffffffffffff8082111561083d57600080fd5b610849888389016107c6565b9096509450602087013591508082111561086257600080fd5b5061086f878288016107c6565b95989497509550505050565b600181811c9082168061088f57607f821691505b6020821081036108af57634e487b7160e01b600052602260045260246000fd5b50919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6040815260006108f26040830186886108b5565b82810360208401526109058185876108b5565b979650505050505050565b634e487b7160e01b600052603260045260246000fd5b600060a0820160018060a01b0388168352602060a0602085015281885180845260c08601915060c08160051b870101935060208a0160005b8281101561098c5760bf1988870301845261097a868351610752565b9550928401929084019060010161095e565b505050505082810360408401526109a38187610752565b6001600160e01b031986166060850152905082810360808401526109c78185610752565b98975050505050505050565b6000806000606084860312156109e857600080fd5b833567ffffffffffffffff80821115610a0057600080fd5b610a0c87838801610640565b9450610a1a60208701610612565b93506040860135915080821115610a3057600080fd5b50610a3d86828701610640565b915050925092509256fea2646970667358221220a265ab39c6228494ffa9884c7ebfcc369374e5f1d04f44ca3a8776585a7a1a4764736f6c63430008170033000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000006068747470733a2f2f737562646f6d61696e2d6469642d6170692d6465762e636268712e6e65743a383030302f6170692f76312f646f6d61696e2f7265736f6c7665722f7265736f6c7665446f6d61696e2f7b73656e6465727d2f7b646174617d0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a412c16ecd2198a6abce8235651e105684fb77ed", - "nonce": "0x0", + "data": "0x252498a20000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004a687474703a2f2f6c6f63616c686f73743a383030302f6170692f76312f646f6d61696e2f7265736f6c7665722f7265736f6c7665446f6d61696e2f7b73656e6465727d2f7b646174617d00000000000000000000000000000000000000000000", + "nonce": "0x2", "accessList": [] }, "additionalContracts": [], @@ -25,40 +25,26 @@ ], "receipts": [ { - "transactionHash": "0x502eb6d582f6dad91e282470545213ff058ad87fb55f0a776aa082b771035c4d", - "transactionIndex": "0x7", - "blockHash": "0x36e46f4c06ea5316b2e2e54a48d7d2cc9ee07d603cad0bfadfdff111ed540a9c", - "blockNumber": "0x59780a", + "transactionHash": "0x5385b5f8b2376ca4d7888e7b6d7f429ca4e88640292e38ebddfd3bfd9959063e", + "transactionIndex": "0x3", + "blockHash": "0x5403573a93adc83ab9b82706d77d82c504b7e8b38921132f0827ee2de56fe02f", + "blockNumber": "0x59fb42", "from": "0x869140c91eDF43214a3EcEdEAF777cc7107aD71a", - "to": null, - "cumulativeGasUsed": "0xf3377", - "gasUsed": "0xbb328", - "contractAddress": "0xBD69dd64b94fe7435157F4851e4b4Aa3A0988c90", - "logs": [ - { - "address": "0xBD69dd64b94fe7435157F4851e4b4Aa3A0988c90", - "topics": [ - "0xab0b9cc3a46b568cb08d985497cde8ab7e18892d01f58db7dc7f0d2af859b2d7" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a412c16ecd2198a6abce8235651e105684fb77ed", - "blockHash": "0x36e46f4c06ea5316b2e2e54a48d7d2cc9ee07d603cad0bfadfdff111ed540a9c", - "blockNumber": "0x59780a", - "transactionHash": "0x502eb6d582f6dad91e282470545213ff058ad87fb55f0a776aa082b771035c4d", - "transactionIndex": "0x7", - "logIndex": "0x1", - "removed": false - } - ], + "to": "0x5F15c3B5949F5767F5Ca9013a8E4Ca4D97a053eD", + "cumulativeGasUsed": "0x635df", + "gasUsed": "0xb3fa", + "contractAddress": null, + "logs": [], "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000001000000000000000000000008000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000200000000000000000000000", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "type": "0x2", - "effectiveGasPrice": "0x16957ea36" + "effectiveGasPrice": "0x433be5a18" } ], "libraries": [], "pending": [], "returns": {}, - "timestamp": 1715204775, + "timestamp": 1715636990, "chain": 11155111, - "commit": "a77faa2" + "commit": "5f0dc54" } \ No newline at end of file diff --git a/contracts/script/configure/EstablishBaseNamespace.s.sol b/contracts/script/configure/EstablishBaseNamespace.s.sol index fc23c040..f37dab8c 100644 --- a/contracts/script/configure/EstablishBaseNamespace.s.sol +++ b/contracts/script/configure/EstablishBaseNamespace.s.sol @@ -7,16 +7,14 @@ import "src/util/Constants.sol"; contract EstablishNamespaces is Script { function run() external { - uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); address deployerAddress = vm.addr(deployerPrivateKey); vm.startBroadcast(deployerPrivateKey); - address ensAddress = 0xBD69dd64b94fe7435157F4851e4b4Aa3A0988c90; // deployer-owned registry + address ensAddress = 0xBD69dd64b94fe7435157F4851e4b4Aa3A0988c90; // deployer-owned registry Registry registry = Registry(ensAddress); - - // establish the base.eth namespace + // establish the base.eth namespace bytes32 ethLabel = keccak256("eth"); bytes32 baseLabel = keccak256("base"); registry.setSubnodeOwner(0x0, ethLabel, deployerAddress); @@ -24,4 +22,4 @@ contract EstablishNamespaces is Script { vm.stopBroadcast(); } -} \ No newline at end of file +} diff --git a/contracts/script/configure/MakeNewName.s.sol b/contracts/script/configure/MakeNewName.s.sol index e8a554af..4ccbda8a 100644 --- a/contracts/script/configure/MakeNewName.s.sol +++ b/contracts/script/configure/MakeNewName.s.sol @@ -14,39 +14,28 @@ contract MakeNewName is Script { address deployerAddress = vm.addr(deployerPrivateKey); vm.startBroadcast(deployerPrivateKey); - // NAME AND RECORD DEFS ///////////////////////////// string memory NAME = "david"; address NAME_OWNER = deployerAddress; address RESOLVED_ADDR = 0xB18e4C959bccc8EF86D78DC297fb5efA99550d85; - - ///////////////////////////////////////////////////// + ///////////////////////////////////////////////////// - address ensAddress = 0xBD69dd64b94fe7435157F4851e4b4Aa3A0988c90; // deployer-owned registry - address resolverAddr = 0xd9d7B7C7f89985e9abAfCa5Bc1211BA5d7C49d33; // l2 resolver + address ensAddress = 0xBD69dd64b94fe7435157F4851e4b4Aa3A0988c90; // deployer-owned registry + address resolverAddr = 0xd9d7B7C7f89985e9abAfCa5Bc1211BA5d7C49d33; // l2 resolver Registry registry = Registry(ensAddress); - - // establish the new name as a subnode of the base.eth namespace + // establish the new name as a subnode of the base.eth namespace bytes32 nameLabel = keccak256(bytes(NAME)); - registry.setSubnodeRecord( - BASE_ETH_NODE, - nameLabel, - NAME_OWNER, - resolverAddr, - type(uint64).max - ); - (,bytes32 nameNode) = NameEncoder.dnsEncodeName(LibString.concat(NAME, ".base.eth")); + registry.setSubnodeRecord(BASE_ETH_NODE, nameLabel, NAME_OWNER, resolverAddr, type(uint64).max); + (, bytes32 nameNode) = NameEncoder.dnsEncodeName(LibString.concat(NAME, ".base.eth")); assert(registry.resolver(nameNode) == resolverAddr); - // establish records for the new name L2Resolver resolver = L2Resolver(resolverAddr); resolver.setAddr(nameNode, RESOLVED_ADDR); assert(resolver.addr(nameNode) == RESOLVED_ADDR); - vm.stopBroadcast(); } -} \ No newline at end of file +} diff --git a/contracts/script/configure/SetL1ResolverUrl.s.sol b/contracts/script/configure/SetL1ResolverUrl.s.sol new file mode 100644 index 00000000..d2307028 --- /dev/null +++ b/contracts/script/configure/SetL1ResolverUrl.s.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.23; + +import "forge-std/Script.sol"; +import "src/L1/L1Resolver.sol"; + +contract SetL1ResolverUrl is Script { + function run() external { + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + address resolverAddress = 0x5F15c3B5949F5767F5Ca9013a8E4Ca4D97a053eD; + vm.startBroadcast(deployerPrivateKey); + + string memory NEW_URL = ""; + + L1Resolver resolver = L1Resolver(resolverAddress); + resolver.setUrl(NEW_URL); + + vm.stopBroadcast(); + } +} diff --git a/contracts/script/deploy/DeployL1Resolver.s.sol b/contracts/script/deploy/DeployL1Resolver.s.sol index 414b6671..793e4b63 100644 --- a/contracts/script/deploy/DeployL1Resolver.s.sol +++ b/contracts/script/deploy/DeployL1Resolver.s.sol @@ -6,19 +6,20 @@ import "src/L1/L1Resolver.sol"; contract DeployL1Resolver is Script { function run() external { - uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); - // address deployerAddresss = vm.addr(deployerPrivateKey); + address deployerAddresss = vm.addr(deployerPrivateKey); vm.startBroadcast(deployerPrivateKey); /// L1 Resolver constructor data - string memory url = "https://subdomain-did-api-dev.cbhq.net:8000/api/v1/domain/resolver/resolveDomain/{sender}/{data}"; // - address[] memory signers = new address[](1); + string memory url = "http://localhost:8000/api/v1/domain/resolver/resolveDomain/{sender}/{data}"; // + address[] memory signers = new address[](1); signers[0] = 0xa412c16ECd2198A6aBce8235651E105684Fb77ed; // DEV signer + address owner = deployerAddresss; + address rootResolver = address(0); - L1Resolver l1 = new L1Resolver(url, signers); + L1Resolver l1 = new L1Resolver(url, signers, owner, rootResolver); console.log(address(l1)); vm.stopBroadcast(); } -} \ No newline at end of file +} diff --git a/contracts/script/deploy/DeployL2Resolver.s.sol b/contracts/script/deploy/DeployL2Resolver.s.sol index 2542288c..ff18aa64 100644 --- a/contracts/script/deploy/DeployL2Resolver.s.sol +++ b/contracts/script/deploy/DeployL2Resolver.s.sol @@ -13,16 +13,15 @@ import "src/util/Constants.sol"; contract DeployL2Resolver is Script { function run() external { - uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); address deployerAddress = vm.addr(deployerPrivateKey); vm.startBroadcast(deployerPrivateKey); /// L2 Resolver constructor data - address ensAddress = 0xBD69dd64b94fe7435157F4851e4b4Aa3A0988c90; // deployer-owned registry - DummyNameWrapper nameWrapper = new DummyNameWrapper(); // deploy dummy - address controller = deployerAddress; // let deployer manage names - address reverse = 0x5F15c3B5949F5767F5Ca9013a8E4Ca4D97a053eD; // deployer-owned rev registrar + address ensAddress = 0xBD69dd64b94fe7435157F4851e4b4Aa3A0988c90; // deployer-owned registry + DummyNameWrapper nameWrapper = new DummyNameWrapper(); // deploy dummy + address controller = deployerAddress; // let deployer manage names + address reverse = 0x5F15c3B5949F5767F5Ca9013a8E4Ca4D97a053eD; // deployer-owned rev registrar Registry registry = Registry(ensAddress); @@ -32,16 +31,11 @@ contract DeployL2Resolver is Script { console.logBytes32(keccak256(abi.encodePacked(bytes32(0), label))); registry.setSubnodeOwner(0x0, label, deployerAddress); registry.setSubnodeOwner(REVERSE_NODE, keccak256("addr"), reverse); - - L2Resolver l2 = new L2Resolver( - Registry(ensAddress), - INameWrapper(address(nameWrapper)), - controller, - reverse - ); + + L2Resolver l2 = new L2Resolver(Registry(ensAddress), INameWrapper(address(nameWrapper)), controller, reverse); console.log(address(l2)); vm.stopBroadcast(); } -} \ No newline at end of file +} diff --git a/contracts/script/deploy/DeployReverseRegistrar.s.sol b/contracts/script/deploy/DeployReverseRegistrar.s.sol index 8b1c293d..7f59c8c7 100644 --- a/contracts/script/deploy/DeployReverseRegistrar.s.sol +++ b/contracts/script/deploy/DeployReverseRegistrar.s.sol @@ -9,7 +9,6 @@ import "src/util/Constants.sol"; contract DeployReverseRegistrar is Script { function run() external { - uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); address deployerAddress = vm.addr(deployerPrivateKey); vm.startBroadcast(deployerPrivateKey); @@ -18,11 +17,11 @@ contract DeployReverseRegistrar is Script { Registry registry = Registry(ensAddress); ReverseRegistrar revRegstrar = new ReverseRegistrar( - Registry(ensAddress), + Registry(ensAddress), deployerAddress // deployer as owner ); - // establish the reverse registrar as the owner of the 'addr.reverse' node + // establish the reverse registrar as the owner of the 'addr.reverse' node bytes32 reverseLabel = keccak256("reverse"); bytes32 addrLabel = keccak256("addr"); registry.setSubnodeOwner(0x0, reverseLabel, deployerAddress); @@ -32,4 +31,4 @@ contract DeployReverseRegistrar is Script { vm.stopBroadcast(); } -} \ No newline at end of file +} diff --git a/contracts/script/deploy/DeployTestnetRegistry.s.sol b/contracts/script/deploy/DeployTestnetRegistry.s.sol index c86f8105..da10a004 100644 --- a/contracts/script/deploy/DeployTestnetRegistry.s.sol +++ b/contracts/script/deploy/DeployTestnetRegistry.s.sol @@ -6,7 +6,6 @@ import {Registry} from "src/L2/Registry.sol"; contract DeployTestnetRegistry is Script { function run() external { - uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); vm.startBroadcast(deployerPrivateKey); @@ -15,4 +14,4 @@ contract DeployTestnetRegistry is Script { vm.stopBroadcast(); } -} \ No newline at end of file +} diff --git a/contracts/script/resolve/ResolveCallback.s.sol b/contracts/script/resolve/ResolveCallback.s.sol index bee31786..2892745d 100644 --- a/contracts/script/resolve/ResolveCallback.s.sol +++ b/contracts/script/resolve/ResolveCallback.s.sol @@ -17,50 +17,64 @@ interface Addr { function addr(bytes32) external; } -contract ResolveCallback is Script { - function run() external { - // uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); - // vm.startBroadcast(deployerPrivateKey); - - /// L1 Resolver constructor data - string memory url = - "https://subdomain-did-api-dev.cbhq.net:8000/api/v1/domain/resolver/resolveDomain/{sender}/{data}"; // - address[] memory signers = new address[](1); - signers[0] = 0xa412c16ECd2198A6aBce8235651E105684Fb77ed; // DEV signer - address resolverAddr = 0xBD69dd64b94fe7435157F4851e4b4Aa3A0988c90; // l1 resolver +address constant resolverAddr = 0xBD69dd64b94fe7435157F4851e4b4Aa3A0988c90; // l1 resolver +contract ResolveCallback is Script { + function run() external view { + address signer = 0xa412c16ECd2198A6aBce8235651E105684Fb77ed; // DEV signer - L1Resolver resolver = new L1Resolver(url, signers); - (bytes memory dnsName ,bytes32 node) = NameEncoder.dnsEncodeName("david.base.eth"); + (bytes memory dnsName, bytes32 node) = NameEncoder.dnsEncodeName("david.base.eth"); console.log("The data arg for resolve call"); bytes memory extraData = abi.encodeWithSelector( - ExtendedResolver.resolve.selector, - dnsName, - abi.encodeWithSelector( - Addr.addr.selector, - node - ) + ExtendedResolver.resolve.selector, dnsName, abi.encodeWithSelector(Addr.addr.selector, node) ); - // resolver.resolve(dnsName, abi.encodeWithSelector(ExtendedResolver.resolve.selector, dnsName, abi.encodeWithSelector(Addr.addr.selector, node))); + console.log("Extra data"); + console.logBytes(extraData); - bytes memory callbackData = hex"000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000663e975500000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000414c7cdc56f1df622d8055acd4536555ca64cf470e6d8b9b13dc0a73fc3fe9b5282e2ffca4425f003290918b20ddc7208a13dc36324f3f34180f00f314081fbdc21b00000000000000000000000000000000000000000000000000000000000000"; + bytes memory callbackData = + hex"00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000066428903000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000b18e4c959bccc8ef86d78dc297fb5efa99550d850000000000000000000000000000000000000000000000000000000000000041c147deedf5991f457236200665538c1f6f210a644839785aaf772ccecfc54f8318769d37a1ddf14be900b5799c88ca99d10fc5dc8049cb082e04289c3fd6d03f1b00000000000000000000000000000000000000000000000000000000000000"; console.log("Calling verify"); - (address signer, bytes memory response) = verify(extraData, callbackData); + (address recoveredSigner, bytes memory response) = verify(extraData, callbackData); - // bytes memory response = resolver.resolveWithProof(callbackData, extraData); + console.log("Recovered signer:"); + console.log(recoveredSigner); + console.log("Expected signer"); console.log(signer); + console.log("Response"); console.logBytes(response); - // vm.stopBroadcast(); } function verify(bytes memory request, bytes memory response) internal view returns (address, bytes memory) { (bytes memory result, uint64 expires, bytes memory sig) = abi.decode(response, (bytes, uint64, bytes)); + console.log("Result bytes"); console.logBytes(result); + console.log("expiry"); console.log(expires); + console.log("sig"); console.logBytes(sig); - address signer = ECDSA.recover(SignatureVerifier.makeSignatureHash(address(this), expires, request, result), sig); + address signer = ECDSA.recover(makeSignatureHash(resolverAddr, expires, request, result), sig); require(expires >= block.timestamp, "SignatureVerifier: Signature expired"); return (signer, result); } + + function makeSignatureHash(address target, uint64 expires, bytes memory request, bytes memory result) + internal + view + returns (bytes32) + { + bytes32 requestHash = keccak256(request); + bytes32 resultHash = keccak256(result); + console.log("Request hash"); + console.logBytes32(requestHash); + console.log("ResultHash"); + console.logBytes32(resultHash); + bytes memory word = abi.encodePacked(hex"1900", target, expires, requestHash, resultHash); + console.log("Hash Preimage"); + console.logBytes(word); + bytes32 hashed = keccak256(word); + console.log("Hashed"); + console.logBytes32(hashed); + return hashed; + } } diff --git a/contracts/src/L1/L1Resolver.sol b/contracts/src/L1/L1Resolver.sol index ab4a5c36..7f65954b 100644 --- a/contracts/src/L1/L1Resolver.sol +++ b/contracts/src/L1/L1Resolver.sol @@ -3,28 +3,63 @@ pragma solidity 0.8.23; import {IExtendedResolver} from "ens-contracts/resolvers/profiles/IExtendedResolver.sol"; import {ERC165} from "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol"; -import {SignatureVerifier} from "../lib/SignatureVerifier.sol"; +import {Ownable} from "solady/auth/Ownable.sol"; + +import {SignatureVerifier} from "src/lib/SignatureVerifier.sol"; +import {BASE_ETH_NAME} from "src/util/Constants.sol"; /** * Implements an ENS resolver that directs all queries to a CCIP read gateway. * Callers must implement EIP 3668 and ENSIP 10. */ -contract L1Resolver is IExtendedResolver, ERC165 { +contract L1Resolver is IExtendedResolver, ERC165, Ownable { string public url; mapping(address => bool) public signers; + address public rootResolver; + + error InvalidSigner(); + error OffchainLookup(address sender, string[] urls, bytes callData, bytes4 callbackFunction, bytes extraData); event NewSigners(address[] signers); + event NewUrl(string newUrl); + event NewRootResolver(address resolver); + event RemovedSigner(address signer); - error OffchainLookup(address sender, string[] urls, bytes callData, bytes4 callbackFunction, bytes extraData); + constructor(string memory url_, address[] memory signers_, address owner_, address rootResolver_) { + url = url_; + _initializeOwner(owner_); + rootResolver = rootResolver_; - constructor(string memory _url, address[] memory _signers) { - url = _url; - for (uint256 i = 0; i < _signers.length; i++) { - signers[_signers[i]] = true; + for (uint256 i = 0; i < signers_.length; i++) { + signers[signers_[i]] = true; + } + emit NewSigners(signers_); + } + + function setUrl(string calldata url_) external onlyOwner { + url = url_; + emit NewUrl(url_); + } + + function addSigners(address[] calldata _signers) external onlyOwner { + for (uint256 i; i < _signers.length; i++) { + signers[_signers[i]] == true; } emit NewSigners(_signers); } + function removeSigner(address signer) external onlyOwner { + if (signers[signer]) { + delete signers[signer]; + emit RemovedSigner(signer); + } + } + + function setRootResolver(address rootResolver_) external onlyOwner { + rootResolver = rootResolver_; + emit NewRootResolver(rootResolver_); + } + function makeSignatureHash(address target, uint64 expires, bytes memory request, bytes memory result) external pure @@ -40,6 +75,12 @@ contract L1Resolver is IExtendedResolver, ERC165 { * @return The return data, ABI encoded identically to the underlying function. */ function resolve(bytes calldata name, bytes calldata data) external view override returns (bytes memory) { + // Resolution for root name "base.eth" should query the `rootResolver` + // All other requests will be for "*.base.eth" names and should follow the CCIP flow by reverting with OffchainLookup + if (keccak256(BASE_ETH_NAME) == keccak256(name)) { + return IExtendedResolver(rootResolver).resolve(name, data); + } + bytes memory callData = abi.encodeWithSelector(L1Resolver.resolve.selector, name, data); string[] memory urls = new string[](1); urls[0] = url; @@ -51,11 +92,46 @@ contract L1Resolver is IExtendedResolver, ERC165 { */ function resolveWithProof(bytes calldata response, bytes calldata extraData) external view returns (bytes memory) { (address signer, bytes memory result) = SignatureVerifier.verify(extraData, response); - require(signers[signer], "SignatureVerifier: Invalid sigature"); + if(!signers[signer]) revert InvalidSigner(); return result; } + /// @notice ERC165 compliant signal for interface support + /// + /// @dev Checks interface support for this contract OR ERC165 OR rootResolver + /// https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] + /// + /// @param interfaceID the ERC165 iface id being checked for compliance + /// + /// @return bool Whether this contract supports the provided interfaceID function supportsInterface(bytes4 interfaceID) public view override returns (bool) { - return interfaceID == type(IExtendedResolver).interfaceId || super.supportsInterface(interfaceID); + return interfaceID == type(IExtendedResolver).interfaceId || super.supportsInterface(interfaceID) || ERC165(rootResolver).supportsInterface(interfaceID); + } + + // Handler for arbitrary resolver calls + fallback() external { + address RESOLVER = rootResolver; + assembly { + // Copy msg.data. We take full control of memory in this inline assembly + // block because it will not return to Solidity code. We overwrite the + // Solidity scratch pad at memory position 0. + calldatacopy(0, 0, calldatasize()) + + // Call the root resolver. + // out and outsize are 0 because we don't know the size yet. + let result := call(gas(), RESOLVER, 0, 0, calldatasize(), 0, 0) + + // Copy the returned data. + returndatacopy(0, 0, returndatasize()) + + switch result + // delegatecall returns 0 on error. + case 0 { + revert(0, returndatasize()) + } + default { + return(0, returndatasize()) + } + } } } diff --git a/contracts/src/L2/Registry.sol b/contracts/src/L2/Registry.sol index 9468e213..b3450c02 100644 --- a/contracts/src/L2/Registry.sol +++ b/contracts/src/L2/Registry.sol @@ -3,6 +3,4 @@ pragma solidity 0.8.23; import {ENSRegistry} from "ens-contracts/registry/ENSRegistry.sol"; -contract Registry is ENSRegistry { - -} +contract Registry is ENSRegistry {} diff --git a/contracts/src/lib/SignatureVerifier.sol b/contracts/src/lib/SignatureVerifier.sol index fb616901..14f10688 100644 --- a/contracts/src/lib/SignatureVerifier.sol +++ b/contracts/src/lib/SignatureVerifier.sol @@ -1,9 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.23; -import {ECDSA} from "lib/solady/src/utils/ECDSA.sol"; +import {ECDSA} from "solady/utils/ECDSA.sol"; library SignatureVerifier { + + error SignatureExpired(); + /** * @dev Generates a hash for signing/verifying. * @param target: The address the signature is for. @@ -29,7 +32,7 @@ library SignatureVerifier { function verify(bytes calldata request, bytes calldata response) internal view returns (address, bytes memory) { (bytes memory result, uint64 expires, bytes memory sig) = abi.decode(response, (bytes, uint64, bytes)); address signer = ECDSA.recover(makeSignatureHash(address(this), expires, request, result), sig); - require(expires >= block.timestamp, "SignatureVerifier: Signature expired"); + if(expires < block.timestamp) revert SignatureExpired(); return (signer, result); } } diff --git a/contracts/src/util/Constants.sol b/contracts/src/util/Constants.sol index 5fb48390..96625857 100644 --- a/contracts/src/util/Constants.sol +++ b/contracts/src/util/Constants.sol @@ -1,7 +1,13 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.23; +// @param ETH_NODE The node hash of ".eth" bytes32 constant ETH_NODE = 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae; +// @param BASE_ETH_NODE The node hash of "base.eth" bytes32 constant BASE_ETH_NODE = 0xff1e3c0eb00ec714e34b6114125fbde1dea2f24a72fbf672e7b7fd5690328e10; +// @param REVERSE_NODE The node hash of ".reverse" bytes32 constant REVERSE_NODE = 0xa097f6721ce401e757d1223a763fef49b8b5f90bb18567ddb86fd205dff71d34; +// @param ADDR_REVERSE_NODE The node hash of "addr.reverse" bytes32 constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2; +// @param BASE_ETH_NAME The dnsName of "base.eth" returned by NameEncoder.dnsEncode("base.eth") +bytes constant BASE_ETH_NAME = hex"04626173650365746800"; diff --git a/contracts/test/L1Resolver.t.sol b/contracts/test/L1Resolver.t.sol deleted file mode 100644 index 32ddecb1..00000000 --- a/contracts/test/L1Resolver.t.sol +++ /dev/null @@ -1,23 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity 0.8.23; - -import {Test} from "forge-std/Test.sol"; -import {L1Resolver} from "src/L1/L1Resolver.sol"; - -contract L1ResolverTest is Test { - - L1Resolver public resolver; - - function setUp() public { - address[] memory _signer = new address[](1); - _signer[0] = makeAddr("0xal1ce"); - resolver = new L1Resolver( - "", - _signer - ); - } - - function test_supportsInterface() public view { - assertTrue(resolver.supportsInterface(bytes4(0x9061b923))); // https://docs.ens.domains/ensip/10 - } -} \ No newline at end of file diff --git a/contracts/test/L1Resolver/AdminMethods.t.sol b/contracts/test/L1Resolver/AdminMethods.t.sol new file mode 100644 index 00000000..93844515 --- /dev/null +++ b/contracts/test/L1Resolver/AdminMethods.t.sol @@ -0,0 +1,57 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.23; + +import {Test, console} from "forge-std/Test.sol"; +import {L1ResolverTestBase} from "./L1ResolverBase.t.sol"; + +import {L1Resolver} from "src/L1/L1Resolver.sol"; +import {Ownable} from "solady/auth/Ownable.sol"; + +contract AdminMethods is L1ResolverTestBase { + function test_setUrl(string memory newUrl) public { + vm.prank(makeAddr("0x2")); + vm.expectRevert(abi.encodeWithSelector(Ownable.Unauthorized.selector)); + resolver.setUrl(newUrl); + + vm.prank(owner); + vm.expectEmit(); + emit L1Resolver.NewUrl(newUrl); + resolver.setUrl(newUrl); + } + + function test_addSigners(address[] calldata _signers) public { + vm.assume(_signers.length < 10); + vm.prank(makeAddr("0x2")); + vm.expectRevert(abi.encodeWithSelector(Ownable.Unauthorized.selector)); + resolver.addSigners(_signers); + + vm.prank(owner); + vm.expectEmit(); + emit L1Resolver.NewSigners(_signers); + resolver.addSigners(_signers); + } + + function test_removeSigner() public { + vm.prank(makeAddr("0x2")); + vm.expectRevert(abi.encodeWithSelector(Ownable.Unauthorized.selector)); + resolver.removeSigner(signer); + + assertTrue(resolver.signers(signer)); + vm.prank(owner); + vm.expectEmit(); + emit L1Resolver.RemovedSigner(signer); + resolver.removeSigner(signer); + assertFalse(resolver.signers(signer)); + } + + function test_setRootResolver(address newResolver) public { + vm.prank(makeAddr("0x2")); + vm.expectRevert(abi.encodeWithSelector(Ownable.Unauthorized.selector)); + resolver.setRootResolver(newResolver); + + vm.prank(owner); + vm.expectEmit(); + emit L1Resolver.NewRootResolver(newResolver); + resolver.setRootResolver(newResolver); + } +} diff --git a/contracts/test/L1Resolver/Fallback.t.sol b/contracts/test/L1Resolver/Fallback.t.sol new file mode 100644 index 00000000..eda06f4e --- /dev/null +++ b/contracts/test/L1Resolver/Fallback.t.sol @@ -0,0 +1,31 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.23; + +import {Test, console} from "forge-std/Test.sol"; +import {L1ResolverTestBase} from "./L1ResolverBase.t.sol"; + +import {L1Resolver} from "src/L1/L1Resolver.sol"; +import {Ownable} from "solady/auth/Ownable.sol"; +import {SignatureVerifier} from "src/lib/SignatureVerifier.sol"; +import {BASE_ETH_NAME, BASE_ETH_NODE} from "src/util/Constants.sol"; +import {IAddrResolver} from "ens-contracts/resolvers/profiles/IAddrResolver.sol"; +import {ITextResolver} from "ens-contracts/resolvers/profiles/ITextResolver.sol"; +import {NameEncoder} from "ens-contracts/utils/NameEncoder.sol"; +import {MockPublicResolver} from "test/mocks/MockPublicResolver.sol"; + +contract Fallback is L1ResolverTestBase { + + function test_forwardsAddrCall_whenResolvingRootName() public { + bytes memory data = abi.encodeWithSelector(IAddrResolver.addr.selector, BASE_ETH_NODE); + (, bytes memory response) = address(resolver).call{value: 0}(data); + (address resolvedAddress) = abi.decode(response, (address)); + assert(resolvedAddress == MockPublicResolver(rootResolver).ADDRESS()); + } + + function test_forwardsTextCall_whenResolvingRootName() public { + bytes memory data = abi.encodeWithSelector(ITextResolver.text.selector, BASE_ETH_NODE, "test"); + (, bytes memory response) = address(resolver).call{value: 0}(data); + (string memory resolvedText) = abi.decode(response, (string)); + assert(keccak256(bytes(resolvedText)) == keccak256(bytes(MockPublicResolver(rootResolver).TEST_TEXT()))); + } +} diff --git a/contracts/test/L1Resolver/L1ResolverBase.t.sol b/contracts/test/L1Resolver/L1ResolverBase.t.sol new file mode 100644 index 00000000..31ca50e1 --- /dev/null +++ b/contracts/test/L1Resolver/L1ResolverBase.t.sol @@ -0,0 +1,38 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.23; + +import {Test, console} from "forge-std/Test.sol"; +import {L1Resolver} from "src/L1/L1Resolver.sol"; +import {MockPublicResolver} from "test/mocks/MockPublicResolver.sol"; + +contract L1ResolverTestBase is Test { + L1Resolver public resolver; + MockPublicResolver public rootResolver; + string constant URL = "TEST_URL"; + address signer; + uint256 signerPk; + address public owner = makeAddr("0x1"); + + function setUp() public { + (signer, signerPk) = makeAddrAndKey("0xace"); + address[] memory signers = new address[](1); + signers[0] = signer; + rootResolver = new MockPublicResolver(); + vm.expectEmit(); + emit L1Resolver.NewSigners(signers); + resolver = new L1Resolver(URL, signers, owner, address(rootResolver)); + } + + function test_constructor() public { + (signer, signerPk) = makeAddrAndKey("0xace"); + address[] memory signers_ = new address[](1); + signers_[0] = signer; + emit L1Resolver.NewSigners(signers_); + + resolver = new L1Resolver(URL, signers_, owner, address(rootResolver)); + assertTrue(keccak256(bytes(resolver.url())) == keccak256(bytes(URL))); + assertTrue(resolver.signers(signer)); + assertTrue(resolver.owner() == owner); + assertTrue(resolver.rootResolver() == address(rootResolver)); + } +} diff --git a/contracts/test/L1Resolver/MakeSignatureHash.t.sol b/contracts/test/L1Resolver/MakeSignatureHash.t.sol new file mode 100644 index 00000000..70127169 --- /dev/null +++ b/contracts/test/L1Resolver/MakeSignatureHash.t.sol @@ -0,0 +1,20 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.23; + +import {Test, console} from "forge-std/Test.sol"; +import {L1ResolverTestBase} from "./L1ResolverBase.t.sol"; + +import {L1Resolver} from "src/L1/L1Resolver.sol"; +import {Ownable} from "solady/auth/Ownable.sol"; +import {SignatureVerifier} from "src/lib/SignatureVerifier.sol"; + +contract MakeSignatureHash is L1ResolverTestBase { + function test_makesValidSignatureHash(address target, uint64 expires, bytes memory request, bytes memory result) + public + view + { + bytes32 expectedHash = SignatureVerifier.makeSignatureHash(target, expires, request, result); + bytes32 testHash = resolver.makeSignatureHash(target, expires, request, result); + assertEq(expectedHash, testHash); + } +} diff --git a/contracts/test/L1Resolver/Resolve.t.sol b/contracts/test/L1Resolver/Resolve.t.sol new file mode 100644 index 00000000..a72af4fa --- /dev/null +++ b/contracts/test/L1Resolver/Resolve.t.sol @@ -0,0 +1,42 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.23; + +import {Test, console} from "forge-std/Test.sol"; +import {L1ResolverTestBase} from "./L1ResolverBase.t.sol"; + +import {L1Resolver} from "src/L1/L1Resolver.sol"; +import {Ownable} from "solady/auth/Ownable.sol"; +import {SignatureVerifier} from "src/lib/SignatureVerifier.sol"; +import {BASE_ETH_NAME, BASE_ETH_NODE} from "src/util/Constants.sol"; +import {IAddrResolver} from "ens-contracts/resolvers/profiles/IAddrResolver.sol"; +import {ITextResolver} from "ens-contracts/resolvers/profiles/ITextResolver.sol"; +import {NameEncoder} from "ens-contracts/utils/NameEncoder.sol"; +import {MockPublicResolver} from "test/mocks/MockPublicResolver.sol"; + +contract Resolve is L1ResolverTestBase { + function test_revertsWithOffchainLookup_whenResolvingName(string memory name) public { + (bytes memory dnsName, bytes32 node) = NameEncoder.dnsEncodeName(name); + vm.assume(keccak256(dnsName) != keccak256(BASE_ETH_NAME)); + + bytes memory data = abi.encodeWithSelector(IAddrResolver.addr.selector, node); + bytes memory callData = abi.encodeWithSelector(resolver.resolve.selector, dnsName, data); + string[] memory urls = new string[](1); + urls[0] = resolver.url(); + vm.expectRevert(abi.encodeWithSelector(L1Resolver.OffchainLookup.selector, address(resolver), urls, callData, L1Resolver.resolveWithProof.selector, callData)); + resolver.resolve(dnsName, data); + } + + function test_resolvesAddr_whenCallingforRootName() public view { + bytes memory data = abi.encodeWithSelector(IAddrResolver.addr.selector, BASE_ETH_NODE); + bytes memory response = resolver.resolve(BASE_ETH_NAME, data); + (address resolvedAddress) = abi.decode(response, (address)); + assert(resolvedAddress == MockPublicResolver(rootResolver).ADDRESS()); + } + + function test_resolvesText_whenCallingforRootName() public view { + bytes memory data = abi.encodeWithSelector(ITextResolver.text.selector, BASE_ETH_NODE, "test"); + bytes memory response = resolver.resolve(BASE_ETH_NAME, data); + (string memory resolvedText) = abi.decode(response, (string)); + assert(keccak256(bytes(resolvedText)) == keccak256(bytes(MockPublicResolver(rootResolver).TEST_TEXT()))); + } +} diff --git a/contracts/test/L1Resolver/ResolveWithProof.t.sol b/contracts/test/L1Resolver/ResolveWithProof.t.sol new file mode 100644 index 00000000..f1d08001 --- /dev/null +++ b/contracts/test/L1Resolver/ResolveWithProof.t.sol @@ -0,0 +1,76 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.23; + +import {Test, console} from "forge-std/Test.sol"; +import {L1ResolverTestBase} from "./L1ResolverBase.t.sol"; + +import {L1Resolver} from "src/L1/L1Resolver.sol"; +import {Ownable} from "solady/auth/Ownable.sol"; +import {SignatureVerifier} from "src/lib/SignatureVerifier.sol"; +import {ECDSA} from "solady/utils/ECDSA.sol"; +import {BASE_ETH_NAME, BASE_ETH_NODE} from "src/util/Constants.sol"; +import {IAddrResolver} from "ens-contracts/resolvers/profiles/IAddrResolver.sol"; +import {ITextResolver} from "ens-contracts/resolvers/profiles/ITextResolver.sol"; +import {NameEncoder} from "ens-contracts/utils/NameEncoder.sol"; +import {MockPublicResolver} from "test/mocks/MockPublicResolver.sol"; + +contract ResolveWithProof is L1ResolverTestBase { + function test_returnsResultsWithValidSignature(string memory name) public { + (bytes memory dnsName, ) = NameEncoder.dnsEncodeName(name); + vm.assume(keccak256(dnsName) != keccak256(BASE_ETH_NAME)); + + (address expectedAddress, bytes memory callData, bytes memory result) = _setupProofCallback(name); + + uint64 expires = 1893456000; // 1/1/2030 00:00:00 + bytes32 digest = SignatureVerifier.makeSignatureHash(address(resolver), expires, callData, result); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPk, digest); + bytes memory sig = abi.encodePacked(r,s,v); + + bytes memory gatewayResponse = abi.encode(result, expires, sig); + bytes memory response = resolver.resolveWithProof(gatewayResponse, callData); + (address returnedAddress) = abi.decode(response, (address)); + assertEq(returnedAddress, expectedAddress); + } + + function test_revertsWhenTheSignatureIsExpired(string memory name) public { + (bytes memory dnsName, ) = NameEncoder.dnsEncodeName(name); + vm.assume(keccak256(dnsName) != keccak256(BASE_ETH_NAME)); + + (, bytes memory callData, bytes memory result) = _setupProofCallback(name); + + uint64 expires = 0; + bytes32 digest = SignatureVerifier.makeSignatureHash(address(resolver), expires, callData, result); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPk, digest); + bytes memory sig = abi.encodePacked(r,s,v); + + bytes memory gatewayResponse = abi.encode(result, expires, sig); + vm.expectRevert(SignatureVerifier.SignatureExpired.selector); + resolver.resolveWithProof(gatewayResponse, callData); + } + + function test_revertsWhenTheSignerIsInvalid(string memory name) public { + (bytes memory dnsName, ) = NameEncoder.dnsEncodeName(name); + vm.assume(keccak256(dnsName) != keccak256(BASE_ETH_NAME)); + + + (, bytes memory callData, bytes memory result) = _setupProofCallback(name); + + uint64 expires = 1893456000; // 1/1/2030 00:00:00 + bytes32 digest = SignatureVerifier.makeSignatureHash(address(resolver), expires, callData, result); + uint256 pk = 1; + (uint8 v, bytes32 r, bytes32 s) = vm.sign(pk, digest); + bytes memory sig = abi.encodePacked(r,s,v); + + bytes memory gatewayResponse = abi.encode(result, expires, sig); + vm.expectRevert(L1Resolver.InvalidSigner.selector); + resolver.resolveWithProof(gatewayResponse, callData); + } + + function _setupProofCallback(string memory name) internal returns (address expectedAddress, bytes memory callData, bytes memory result) { + (bytes memory dnsName, bytes32 node) = NameEncoder.dnsEncodeName(name); + expectedAddress = makeAddr(name); + bytes memory data = abi.encodeWithSelector(IAddrResolver.addr.selector, node); + callData = abi.encodeWithSelector(resolver.resolve.selector, dnsName, data); + result = abi.encode(expectedAddress); + } +} diff --git a/contracts/test/L1Resolver/SupportsInterface.t.sol b/contracts/test/L1Resolver/SupportsInterface.t.sol new file mode 100644 index 00000000..16706361 --- /dev/null +++ b/contracts/test/L1Resolver/SupportsInterface.t.sol @@ -0,0 +1,39 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.23; + +import {Test, console} from "forge-std/Test.sol"; +import {L1ResolverTestBase} from "./L1ResolverBase.t.sol"; + +import {L1Resolver} from "src/L1/L1Resolver.sol"; +import {Ownable} from "solady/auth/Ownable.sol"; +import {IAddrResolver} from "ens-contracts/resolvers/profiles/IAddrResolver.sol"; +import {ITextResolver} from "ens-contracts/resolvers/profiles/ITextResolver.sol"; +import {IERC165} from "openzeppelin-contracts/contracts/interfaces/IERC165.sol"; + +contract SupportsInterface is L1ResolverTestBase { + function test_supportsExtendedResolver() public view { + assertTrue(resolver.supportsInterface(bytes4(0x9061b923))); // https://docs.ens.domains/ensip/10 + } + + function test_supportsERC165() public view { + assertTrue(resolver.supportsInterface(type(IERC165).interfaceId)); + } + + function test_supportsForwarding_toIAddrCompliantRootResolver() public view { + assertTrue(resolver.supportsInterface(type(IAddrResolver).interfaceId)); + } + + function test_supportsForwarding_toITextCompliantRootResolver() public view { + assertTrue(resolver.supportsInterface(type(ITextResolver).interfaceId)); + } + + function test_doesNotSupportArbitraryInterfaceId(bytes4 interfaceID) public view { + vm.assume( + interfaceID != bytes4(0x9061b923) && + interfaceID != type(IERC165).interfaceId && + interfaceID != type(IAddrResolver).interfaceId && + interfaceID != type(ITextResolver).interfaceId + ); + assertFalse(resolver.supportsInterface(interfaceID)); + } +} diff --git a/contracts/test/mocks/MockPublicResolver.sol b/contracts/test/mocks/MockPublicResolver.sol new file mode 100644 index 00000000..9563b891 --- /dev/null +++ b/contracts/test/mocks/MockPublicResolver.sol @@ -0,0 +1,31 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.23; + +import {BASE_ETH_NODE} from "src/util/Constants.sol"; +import {ExtendedResolver} from "ens-contracts/resolvers/profiles/ExtendedResolver.sol"; +import {IAddrResolver} from "ens-contracts/resolvers/profiles/IAddrResolver.sol"; +import {ITextResolver} from "ens-contracts/resolvers/profiles/ITextResolver.sol"; + +contract MockPublicResolver is ExtendedResolver { + mapping(bytes32 => address) addrs; + mapping(bytes32 => mapping(string => string)) texts; + address public constant ADDRESS = 0x000000000000000000000000000000000000dEaD; + string public constant TEST_TEXT = "pass"; + + constructor() { + addrs[BASE_ETH_NODE] = ADDRESS; + texts[BASE_ETH_NODE]["test"] = TEST_TEXT; + } + + function addr(bytes32 node) external view returns (address) { + return addrs[node]; + } + + function text(bytes32 node, string calldata key) external view returns (string memory) { + return texts[node][key]; + } + + function supportsInterface(bytes4 interfaceID) public pure returns (bool) { + return interfaceID == type(IAddrResolver).interfaceId || interfaceID == type(ITextResolver).interfaceId; + } +}