This repository has been archived by the owner on Mar 17, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 94
/
etherRouter.js
71 lines (63 loc) · 2.78 KB
/
etherRouter.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
const ethers = require("ethers");
/**
* Example of a method that resolves the contract names of method calls routed through
* an EtherRouter style contract. This function gets bound to the `this` property of
* eth-gas-reporter's ProxyResolver class and inherits its resources including
* helpers to match methods to contracts and a way of making synchronous calls to the client.
*
* Helper methods of this type receive a web3 transaction object representing a tx the reporter
* could not deterministically associate with any contract. They rely on your knowledge
* of a proxy contract's API to derive the correct contract name.
*
* Returns contract name matching the resolved address.
* @param {Object} transaction result of web3.eth.getTransaction
* @return {String} contract name
*/
function etherRouter(transaction) {
let contractAddress;
let contractName;
try {
const ABI = ["function resolver()", "function lookup(bytes4 sig)"];
const iface = new ethers.utils.Interface(ABI);
// The tx passed to this method had input data which didn't map to any methods on
// the contract it was sent to. It's possible the tx's `to` address points to
// an EtherRouter contract which is designed to forward calls. We'll grab the
// method signature and ask the router if it knows who the intended recipient is.
const signature = transaction.input.slice(0, 10);
// EtherRouter has a public state variable called `resolver()` which stores the
// address of a contract which maps method signatures to their parent contracts.
// Lets fetch it ....
const resolverAddress = this.sync.call(
{
to: transaction.to,
data: iface.functions.resolver.encode([])
},
transaction.blockNumber
);
// Now we'll call the Resolver's `lookup(sig)` method to get the address of the contract
// our tx was actually getting forwarded to.
contractAddress = this.sync.call(
{
to: ethers.utils.hexStripZeros(resolverAddress),
data: iface.functions.lookup.encode([signature])
},
transaction.blockNumber
);
// Don't forget this is all a bit speculative...
} catch (err) {
this.unresolvedCalls++;
return;
}
// With the correct address, we can use the ProxyResolver class's
// data.getNameByAddress and/or resolveByDeployedBytecode methods
// (both are available in this scope, bound to `this`) to derive
// the target contract's name.
if (contractAddress) {
contractAddress = ethers.utils.hexStripZeros(contractAddress);
contractName = this.data.getNameByAddress(contractAddress);
// Try to resolve by deployedBytecode
if (contractName) return contractName;
else return this.resolveByDeployedBytecode(contractAddress);
}
}
module.exports = etherRouter;