Skip to content

Commit

Permalink
Trap CALL_EXCEPTION errors when resolving ENS entries (#1690).
Browse files Browse the repository at this point in the history
  • Loading branch information
ricmoo committed Jun 22, 2021
1 parent 8277f5a commit 91951dc
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 21 deletions.
57 changes: 38 additions & 19 deletions packages/providers/src.ts/base-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,19 +250,23 @@ export class Resolver implements EnsResolver {
}

async _fetchBytes(selector: string, parameters?: string): Promise<string> {

// keccak256("addr(bytes32,uint256)")
const transaction = {
to: this.address,
data: hexConcat([ selector, namehash(this.name), (parameters || "0x") ])
};

const result = await this.provider.call(transaction);
if (result === "0x") { return null; }
try {
const result = await this.provider.call(transaction);
if (result === "0x") { return null; }

const offset = BigNumber.from(hexDataSlice(result, 0, 32)).toNumber();
const length = BigNumber.from(hexDataSlice(result, offset, offset + 32)).toNumber();
return hexDataSlice(result, offset + 32, offset + 32 + length);
const offset = BigNumber.from(hexDataSlice(result, 0, 32)).toNumber();
const length = BigNumber.from(hexDataSlice(result, offset, offset + 32)).toNumber();
return hexDataSlice(result, offset + 32, offset + 32 + length);
} catch (error) {
if (error.code === Logger.errors.CALL_EXCEPTION) { return null; }
return null;
}
}

_getAddress(coinType: number, hexBytes: string): string {
Expand Down Expand Up @@ -332,17 +336,22 @@ export class Resolver implements EnsResolver {

// If Ethereum, use the standard `addr(bytes32)`
if (coinType === 60) {
// keccak256("addr(bytes32)")
const transaction = {
to: this.address,
data: ("0x3b3b57de" + namehash(this.name).substring(2))
};
const hexBytes = await this.provider.call(transaction);
try {
// keccak256("addr(bytes32)")
const transaction = {
to: this.address,
data: ("0x3b3b57de" + namehash(this.name).substring(2))
};
const hexBytes = await this.provider.call(transaction);

// No address
if (hexBytes === "0x" || hexBytes === HashZero) { return null; }
// No address
if (hexBytes === "0x" || hexBytes === HashZero) { return null; }

return this.provider.formatter.callAddress(hexBytes);
return this.provider.formatter.callAddress(hexBytes);
} catch (error) {
if (error.code === Logger.errors.CALL_EXCEPTION) { return null; }
throw error;
}
}

// keccak256("addr(bytes32,uint256")
Expand Down Expand Up @@ -1499,9 +1508,14 @@ export class BaseProvider extends Provider implements EnsProvider {


async getResolver(name: string): Promise<Resolver> {
const address = await this._getResolver(name);
if (address == null) { return null; }
return new Resolver(this, address, name);
try {
const address = await this._getResolver(name);
if (address == null) { return null; }
return new Resolver(this, address, name);
} catch (error) {
if (error.code === Logger.errors.CALL_EXCEPTION) { return null; }
return null;
}
}

async _getResolver(name: string): Promise<string> {
Expand All @@ -1523,7 +1537,12 @@ export class BaseProvider extends Provider implements EnsProvider {
data: ("0x0178b8bf" + namehash(name).substring(2))
};

return this.formatter.callAddress(await this.call(transaction));
try {
return this.formatter.callAddress(await this.call(transaction));
} catch (error) {
if (error.code === Logger.errors.CALL_EXCEPTION) { return null; }
throw error;
}
}

async resolveName(name: string | Promise<string>): Promise<string> {
Expand Down
14 changes: 12 additions & 2 deletions packages/providers/src.ts/etherscan-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,18 @@ function checkError(method: string, error: any, transaction: any): any {
// incompatibility; maybe for v6 consider forwarding reverts as errors
if (method === "call" && error.code === Logger.errors.SERVER_ERROR) {
const e = error.error;
if (e && e.message.match("reverted") && isHexString(e.data)) {
return e.data;

// Etherscan keeps changing their string
if (e && (e.message.match(/reverted/i) || e.message.match(/VM execution error/i))) {
// Etherscan prefixes the data like "Reverted 0x1234"
let data = e.data;
if (data) { data = "0x" + data.replace(/^.*0x/i, ""); }

if (isHexString(data)) { return data; }

logger.throwError("missing revert data in call exception", Logger.errors.CALL_EXCEPTION, {
error, data: "0x"
});
}
}

Expand Down