Trap CALL_EXCEPTION errors when resolving ENS entries (#1690).
This commit is contained in:
parent
8277f5a62a
commit
91951dc825
@ -250,19 +250,23 @@ export class Resolver implements EnsResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _fetchBytes(selector: string, parameters?: string): Promise<string> {
|
async _fetchBytes(selector: string, parameters?: string): Promise<string> {
|
||||||
|
|
||||||
// keccak256("addr(bytes32,uint256)")
|
// keccak256("addr(bytes32,uint256)")
|
||||||
const transaction = {
|
const transaction = {
|
||||||
to: this.address,
|
to: this.address,
|
||||||
data: hexConcat([ selector, namehash(this.name), (parameters || "0x") ])
|
data: hexConcat([ selector, namehash(this.name), (parameters || "0x") ])
|
||||||
};
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
const result = await this.provider.call(transaction);
|
const result = await this.provider.call(transaction);
|
||||||
if (result === "0x") { return null; }
|
if (result === "0x") { return null; }
|
||||||
|
|
||||||
const offset = BigNumber.from(hexDataSlice(result, 0, 32)).toNumber();
|
const offset = BigNumber.from(hexDataSlice(result, 0, 32)).toNumber();
|
||||||
const length = BigNumber.from(hexDataSlice(result, offset, offset + 32)).toNumber();
|
const length = BigNumber.from(hexDataSlice(result, offset, offset + 32)).toNumber();
|
||||||
return hexDataSlice(result, offset + 32, offset + 32 + length);
|
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 {
|
_getAddress(coinType: number, hexBytes: string): string {
|
||||||
@ -332,6 +336,7 @@ export class Resolver implements EnsResolver {
|
|||||||
|
|
||||||
// If Ethereum, use the standard `addr(bytes32)`
|
// If Ethereum, use the standard `addr(bytes32)`
|
||||||
if (coinType === 60) {
|
if (coinType === 60) {
|
||||||
|
try {
|
||||||
// keccak256("addr(bytes32)")
|
// keccak256("addr(bytes32)")
|
||||||
const transaction = {
|
const transaction = {
|
||||||
to: this.address,
|
to: this.address,
|
||||||
@ -343,6 +348,10 @@ export class Resolver implements EnsResolver {
|
|||||||
if (hexBytes === "0x" || hexBytes === HashZero) { return null; }
|
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")
|
// keccak256("addr(bytes32,uint256")
|
||||||
@ -1499,9 +1508,14 @@ export class BaseProvider extends Provider implements EnsProvider {
|
|||||||
|
|
||||||
|
|
||||||
async getResolver(name: string): Promise<Resolver> {
|
async getResolver(name: string): Promise<Resolver> {
|
||||||
|
try {
|
||||||
const address = await this._getResolver(name);
|
const address = await this._getResolver(name);
|
||||||
if (address == null) { return null; }
|
if (address == null) { return null; }
|
||||||
return new Resolver(this, address, name);
|
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> {
|
async _getResolver(name: string): Promise<string> {
|
||||||
@ -1523,7 +1537,12 @@ export class BaseProvider extends Provider implements EnsProvider {
|
|||||||
data: ("0x0178b8bf" + namehash(name).substring(2))
|
data: ("0x0178b8bf" + namehash(name).substring(2))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
return this.formatter.callAddress(await this.call(transaction));
|
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> {
|
async resolveName(name: string | Promise<string>): Promise<string> {
|
||||||
|
@ -98,8 +98,18 @@ function checkError(method: string, error: any, transaction: any): any {
|
|||||||
// incompatibility; maybe for v6 consider forwarding reverts as errors
|
// incompatibility; maybe for v6 consider forwarding reverts as errors
|
||||||
if (method === "call" && error.code === Logger.errors.SERVER_ERROR) {
|
if (method === "call" && error.code === Logger.errors.SERVER_ERROR) {
|
||||||
const e = error.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"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,10 @@ function checkError(method: string, error: any, params: any): any {
|
|||||||
if (e && e.message.match("reverted") && isHexString(e.data)) {
|
if (e && e.message.match("reverted") && isHexString(e.data)) {
|
||||||
return e.data;
|
return e.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.throwError("missing revert data in call exception", Logger.errors.CALL_EXCEPTION, {
|
||||||
|
error, data: "0x"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let message = error.message;
|
let message = error.message;
|
||||||
|
Loading…
Reference in New Issue
Block a user