From 45eddc26b3471e5c4e3e31788554d0033e714cca Mon Sep 17 00:00:00 2001 From: Makoto Inoue <2630+makoto@users.noreply.github.com> Date: Wed, 21 Feb 2024 17:52:45 +0000 Subject: [PATCH] Add fallback for text --- .../contracts/L1ReverseResolver.sol | 22 ++++++--- .../test/testReverseResolver.ts | 49 +++++++++++++++++-- 2 files changed, 60 insertions(+), 11 deletions(-) diff --git a/crosschain-reverse-resolver/contracts/L1ReverseResolver.sol b/crosschain-reverse-resolver/contracts/L1ReverseResolver.sol index 8828ce18..2ae509a6 100644 --- a/crosschain-reverse-resolver/contracts/L1ReverseResolver.sol +++ b/crosschain-reverse-resolver/contracts/L1ReverseResolver.sol @@ -46,14 +46,14 @@ contract L1ReverseResolver is EVMFetchTarget, IExtendedResolver, ERC165 { function resolve(bytes calldata name, bytes calldata data) external view returns (bytes memory result) { bytes4 selector = bytes4(data); + (address addr,) = HexUtils.hexToAddress(name, 1, ADDRESS_LENGTH + 1); if (selector == INameResolver.name.selector) { (bytes32 node) = abi.decode(data[4:], (bytes32)); - (address addr,) = HexUtils.hexToAddress(name, 1, ADDRESS_LENGTH + 1); return bytes(_name(node, addr)); } if (selector == ITextResolver.text.selector) { (bytes32 node, string memory key) = abi.decode(data[4:], (bytes32, string)); - return bytes(text(node, key)); + return bytes(_text(node, key, addr)); } } @@ -92,9 +92,10 @@ contract L1ReverseResolver is EVMFetchTarget, IExtendedResolver, ERC165 { * @param key The text data key to query. * @return The associated text data. */ - function text( + function _text( bytes32 node, - string memory key + string memory key, + address addr ) public view returns (string memory) { EVMFetcher.newFetchRequest(verifier, target) .getStatic(RECORD_VERSIONS_SLOT) @@ -103,14 +104,19 @@ contract L1ReverseResolver is EVMFetchTarget, IExtendedResolver, ERC165 { .ref(0) .element(node) .element(key) - .fetch(this.textCallback.selector, ''); + .fetch(this.textCallback.selector, abi.encode(addr, key)); } function textCallback( bytes[] memory values, - bytes memory - ) public pure returns (string memory) { - return string(values[1]); + bytes memory callbackdata + ) public view returns (string memory) { + if(values[1].length == 0 ){ + (address addr, string memory key) = abi.decode(callbackdata, (address, string)); + return defaultReverseResolver.text(addr, key); + }else{ + return string(values[1]); + } } function supportsInterface( diff --git a/crosschain-reverse-resolver/test/testReverseResolver.ts b/crosschain-reverse-resolver/test/testReverseResolver.ts index 789223a6..107d2e58 100644 --- a/crosschain-reverse-resolver/test/testReverseResolver.ts +++ b/crosschain-reverse-resolver/test/testReverseResolver.ts @@ -158,16 +158,59 @@ describe('Crosschain Reverse Resolver', () => { it("should test text record", async() => { const key = 'name' const value = 'nick.eth' + const testAddress = await signer.getAddress() const node = await l2contract.node( - await signer.getAddress() + testAddress ) + const reverseLabel = testAddress.substring(2).toLowerCase() + const l2ReverseName = `${reverseLabel}.${NAMESPACE}.reverse` + const encodedL2ReverseName = encodeName(l2ReverseName) + await l2contract.clearRecords(await signer.getAddress()) await l2contract.setText(key, value) await provider.send("evm_mine", []); const result = await l2contract.text(node, key) expect(result).to.equal(value); - const result2 = await target.text(node, key, { enableCcipRead: true }) - expect(result2).to.equal(value); + const i = new ethers.Interface(["function text(bytes32, string) returns(string)"]) + const calldata = i.encodeFunctionData("text", [node, key]) + const result2 = await target.resolve(encodedL2ReverseName, calldata, { enableCcipRead: true }) + expect(ethers.toUtf8String(result2)).to.equal(value); + }) + + it("should test fallback text", async() => { + const testSigner = new ethers.Wallet('0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'); + const testAddress = testSigner.address + const key = 'name' + const value = 'myname.eth' + const reverseLabel = testAddress.substring(2).toLowerCase() + const l2ReverseName = `${reverseLabel}.${NAMESPACE}.reverse` + const l2ReverseNode = ethers.namehash(l2ReverseName) + const encodedL2ReverseName = encodeName(l2ReverseName) + + const funcId = ethers + .id('setTextForAddrWithSignature(address,string,string,uint256,bytes)') + .substring(0, 10) + + const block = await provider.getBlock('latest') + const inceptionDate = block?.timestamp + const message = ethers.solidityPackedKeccak256( + ['bytes32', 'address', 'uint256', 'uint256'], + [ethers.solidityPackedKeccak256(['bytes4', 'string', 'string'], [funcId, key, value]), testAddress, inceptionDate, 0], + ) + const signature = await testSigner.signMessage(ethers.toBeArray(message)) + await defaultReverseResolver['setTextForAddrWithSignature']( + testAddress, + key, + value, + inceptionDate, + signature, + ) + await provider.send("evm_mine", []); + expect(await defaultReverseResolver.text(testAddress, key)).to.equal(value) + const i = new ethers.Interface(["function text(bytes32,string) returns(string)"]) + const calldata = i.encodeFunctionData("text", [l2ReverseNode, key]) + const result2 = await target.resolve(encodedL2ReverseName, calldata, { enableCcipRead: true }) + expect(ethers.toUtf8String(result2)).to.equal(value); }) it("should support interface", async() => {