@gnosis-guild/zodiac 4.2.1 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +107 -4
- package/dist/cjs/abis/bridge/1.0.0.js +385 -0
- package/dist/cjs/abis/circulatingSupplyERC20/1.0.0.js +248 -0
- package/dist/cjs/abis/circulatingSupplyERC20/1.1.0.js +248 -0
- package/dist/cjs/abis/circulatingSupplyERC20/1.2.0.js +248 -0
- package/dist/cjs/abis/circulatingSupplyERC721/1.1.0.js +248 -0
- package/dist/cjs/abis/circulatingSupplyERC721/1.2.0.js +248 -0
- package/dist/cjs/abis/connext/1.0.0.js +496 -0
- package/dist/cjs/abis/delay/1.0.0.js +731 -0
- package/dist/cjs/abis/delay/1.0.1.js +731 -0
- package/dist/cjs/abis/delay/1.1.0.js +941 -0
- package/dist/cjs/abis/delay/1.1.1.js +941 -0
- package/dist/cjs/abis/erc20Votes/1.0.0.js +800 -0
- package/dist/cjs/abis/erc721Votes/1.0.0.js +795 -0
- package/dist/cjs/abis/exit/1.0.0.js +403 -0
- package/dist/cjs/abis/exit/1.1.0.js +422 -0
- package/dist/cjs/abis/exit/1.2.0.js +422 -0
- package/dist/cjs/abis/exitERC721/1.1.0.js +422 -0
- package/dist/cjs/abis/exitERC721/1.2.0.js +422 -0
- package/dist/cjs/abis/factory/1.0.0.js +53 -0
- package/dist/cjs/abis/factory/1.1.0.js +80 -0
- package/dist/cjs/abis/factory/1.2.0.js +91 -0
- package/dist/cjs/abis/index.js +101 -0
- package/dist/cjs/abis/metaGuard/1.0.0.js +474 -0
- package/dist/cjs/abis/multisendEncoder/1.0.0.js +64 -0
- package/dist/cjs/abis/ozGovernor/1.0.0.js +1066 -0
- package/dist/cjs/abis/realityERC20/2.0.0.js +874 -0
- package/dist/cjs/abis/realityETH/2.0.0.js +874 -0
- package/dist/cjs/abis/roles/1.0.0.js +993 -0
- package/dist/cjs/abis/roles/1.1.0.js +993 -0
- package/dist/cjs/abis/roles/2.1.0.js +1411 -0
- package/dist/cjs/abis/roles/2.1.1.js +1411 -0
- package/dist/cjs/abis/scopeGuard/1.0.0.js +595 -0
- package/dist/cjs/contracts.js +145 -0
- package/dist/cjs/explorer.js +264 -0
- package/dist/cjs/extract.js +117 -0
- package/dist/cjs/index.js +16 -0
- package/dist/cjs/mastercopies.js +34 -0
- package/dist/cjs/networks.js +233 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/rpc.js +36 -0
- package/dist/cjs/singleton.js +42 -0
- package/dist/cjs/types.js +7 -0
- package/dist/cjs/ui.js +64 -0
- package/dist/cjs/zodiacModule.js +61 -0
- package/dist/esm/abis/bridge/1.0.0.d.ts +297 -0
- package/dist/esm/abis/bridge/1.0.0.js +382 -0
- package/dist/esm/abis/circulatingSupplyERC20/1.0.0.d.ts +188 -0
- package/dist/esm/abis/circulatingSupplyERC20/1.0.0.js +245 -0
- package/dist/esm/abis/circulatingSupplyERC20/1.1.0.d.ts +188 -0
- package/dist/esm/abis/circulatingSupplyERC20/1.1.0.js +245 -0
- package/dist/esm/abis/circulatingSupplyERC20/1.2.0.d.ts +188 -0
- package/dist/esm/abis/circulatingSupplyERC20/1.2.0.js +245 -0
- package/dist/esm/abis/circulatingSupplyERC721/1.1.0.d.ts +188 -0
- package/dist/esm/abis/circulatingSupplyERC721/1.1.0.js +245 -0
- package/dist/esm/abis/circulatingSupplyERC721/1.2.0.d.ts +188 -0
- package/dist/esm/abis/circulatingSupplyERC721/1.2.0.js +245 -0
- package/dist/esm/abis/connext/1.0.0.d.ts +383 -0
- package/dist/esm/abis/connext/1.0.0.js +493 -0
- package/dist/esm/abis/delay/1.0.0.d.ts +562 -0
- package/dist/esm/abis/delay/1.0.0.js +728 -0
- package/dist/esm/abis/delay/1.0.1.d.ts +562 -0
- package/dist/esm/abis/delay/1.0.1.js +728 -0
- package/dist/esm/abis/delay/1.1.0.d.ts +720 -0
- package/dist/esm/abis/delay/1.1.0.js +938 -0
- package/dist/esm/abis/delay/1.1.1.d.ts +720 -0
- package/dist/esm/abis/delay/1.1.1.js +938 -0
- package/dist/esm/abis/erc20Votes/1.0.0.d.ts +613 -0
- package/dist/esm/abis/erc20Votes/1.0.0.js +797 -0
- package/dist/esm/abis/erc721Votes/1.0.0.d.ts +610 -0
- package/dist/esm/abis/erc721Votes/1.0.0.js +792 -0
- package/dist/esm/abis/exit/1.0.0.d.ts +309 -0
- package/dist/esm/abis/exit/1.0.0.js +400 -0
- package/dist/esm/abis/exit/1.1.0.d.ts +323 -0
- package/dist/esm/abis/exit/1.1.0.js +419 -0
- package/dist/esm/abis/exit/1.2.0.d.ts +323 -0
- package/dist/esm/abis/exit/1.2.0.js +419 -0
- package/dist/esm/abis/exitERC721/1.1.0.d.ts +323 -0
- package/dist/esm/abis/exitERC721/1.1.0.js +419 -0
- package/dist/esm/abis/exitERC721/1.2.0.d.ts +323 -0
- package/dist/esm/abis/exitERC721/1.2.0.js +419 -0
- package/dist/esm/abis/factory/1.0.0.d.ts +38 -0
- package/dist/esm/abis/factory/1.0.0.js +50 -0
- package/dist/esm/abis/factory/1.1.0.d.ts +58 -0
- package/dist/esm/abis/factory/1.1.0.js +77 -0
- package/dist/esm/abis/factory/1.2.0.d.ts +66 -0
- package/dist/esm/abis/factory/1.2.0.js +88 -0
- package/dist/esm/abis/index.d.ts +13970 -0
- package/dist/esm/abis/index.js +98 -0
- package/dist/esm/abis/metaGuard/1.0.0.d.ts +363 -0
- package/dist/esm/abis/metaGuard/1.0.0.js +471 -0
- package/dist/esm/abis/multisendEncoder/1.0.0.d.ts +47 -0
- package/dist/esm/abis/multisendEncoder/1.0.0.js +61 -0
- package/dist/esm/abis/ozGovernor/1.0.0.d.ts +821 -0
- package/dist/esm/abis/ozGovernor/1.0.0.js +1063 -0
- package/dist/esm/abis/realityERC20/2.0.0.d.ts +674 -0
- package/dist/esm/abis/realityERC20/2.0.0.js +871 -0
- package/dist/esm/abis/realityETH/2.0.0.d.ts +674 -0
- package/dist/esm/abis/realityETH/2.0.0.js +871 -0
- package/dist/esm/abis/roles/1.0.0.d.ts +770 -0
- package/dist/esm/abis/roles/1.0.0.js +990 -0
- package/dist/esm/abis/roles/1.1.0.d.ts +770 -0
- package/dist/esm/abis/roles/1.1.0.js +990 -0
- package/dist/esm/abis/roles/2.1.0.d.ts +1094 -0
- package/dist/esm/abis/roles/2.1.0.js +1408 -0
- package/dist/esm/abis/roles/2.1.1.d.ts +1094 -0
- package/dist/esm/abis/roles/2.1.1.js +1408 -0
- package/dist/esm/abis/scopeGuard/1.0.0.d.ts +457 -0
- package/dist/esm/abis/scopeGuard/1.0.0.js +592 -0
- package/dist/esm/contracts.d.ts +66 -0
- package/dist/esm/contracts.js +142 -0
- package/dist/esm/explorer.d.ts +81 -0
- package/dist/esm/explorer.js +256 -0
- package/dist/esm/extract.d.ts +15 -0
- package/dist/esm/extract.js +114 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/mastercopies.d.ts +21 -0
- package/dist/esm/mastercopies.js +27 -0
- package/dist/esm/networks.d.ts +37 -0
- package/dist/esm/networks.js +229 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/rpc.d.ts +6 -0
- package/dist/esm/rpc.js +33 -0
- package/dist/esm/singleton.d.ts +24 -0
- package/dist/esm/singleton.js +38 -0
- package/dist/esm/types.d.ts +43 -0
- package/dist/esm/types.js +6 -0
- package/dist/esm/ui.d.ts +16 -0
- package/dist/esm/ui.js +53 -0
- package/dist/esm/zodiacModule.d.ts +4 -0
- package/dist/esm/zodiacModule.js +56 -0
- package/package.json +29 -74
- package/contracts/core/GuardableModifier.sol +0 -96
- package/contracts/core/GuardableModule.sol +0 -95
- package/contracts/core/Modifier.sol +0 -204
- package/contracts/core/Module.sol +0 -73
- package/contracts/factory/FactoryFriendly.sol +0 -10
- package/contracts/factory/ModuleProxyFactory.sol +0 -51
- package/contracts/guard/BaseGuard.sol +0 -36
- package/contracts/guard/Guardable.sol +0 -32
- package/contracts/interfaces/IAvatar.sol +0 -71
- package/contracts/interfaces/IGuard.sol +0 -22
- package/contracts/signature/ExecutionTracker.sol +0 -17
- package/contracts/signature/IERC1271.sol +0 -19
- package/contracts/signature/SignatureChecker.sol +0 -154
- package/contracts/test/TestAvatar.sol +0 -64
- package/contracts/test/TestGuard.sol +0 -82
- package/contracts/test/TestGuardableModifier.sol +0 -82
- package/contracts/test/TestModifier.sol +0 -88
- package/contracts/test/TestModule.sol +0 -66
- package/contracts/test/TestSignature.sol +0 -71
- package/dist/index.d.mts +0 -16332
- package/dist/index.d.ts +0 -16332
- package/dist/index.js +0 -24880
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -24845
- package/dist/index.mjs.map +0 -1
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Known Zodiac contracts and their canonical mastercopy addresses.
|
|
3
|
+
*
|
|
4
|
+
* Canonical mastercopy addresses by `name@version`. Most are deployed through
|
|
5
|
+
* CREATE2 singleton factories, but the registry itself is pure address/name
|
|
6
|
+
* data — no ABIs, bytecode or typechain types (use `extract` to capture
|
|
7
|
+
* per-version artifacts into `mastercopies/`).
|
|
8
|
+
*/
|
|
9
|
+
export var KnownContracts;
|
|
10
|
+
(function (KnownContracts) {
|
|
11
|
+
KnownContracts["META_GUARD"] = "metaGuard";
|
|
12
|
+
KnownContracts["OPTIMISTIC_GOVERNOR"] = "optimisticGovernor";
|
|
13
|
+
KnownContracts["TELLOR"] = "tellor";
|
|
14
|
+
KnownContracts["REALITY_ETH"] = "realityETH";
|
|
15
|
+
KnownContracts["REALITY_ERC20"] = "realityERC20";
|
|
16
|
+
KnownContracts["BRIDGE"] = "bridge";
|
|
17
|
+
KnownContracts["DELAY"] = "delay";
|
|
18
|
+
KnownContracts["EXIT_ERC20"] = "exit";
|
|
19
|
+
KnownContracts["EXIT_ERC721"] = "exitERC721";
|
|
20
|
+
KnownContracts["CIRCULATING_SUPPLY_ERC20"] = "circulatingSupplyERC20";
|
|
21
|
+
KnownContracts["CIRCULATING_SUPPLY_ERC721"] = "circulatingSupplyERC721";
|
|
22
|
+
KnownContracts["SCOPE_GUARD"] = "scopeGuard";
|
|
23
|
+
KnownContracts["FACTORY"] = "factory";
|
|
24
|
+
KnownContracts["ROLES"] = "roles";
|
|
25
|
+
KnownContracts["ROLES_V1"] = "roles";
|
|
26
|
+
KnownContracts["ROLES_V2"] = "roles";
|
|
27
|
+
KnownContracts["OZ_GOVERNOR"] = "ozGovernor";
|
|
28
|
+
KnownContracts["ERC20_VOTES"] = "erc20Votes";
|
|
29
|
+
KnownContracts["ERC721_VOTES"] = "erc721Votes";
|
|
30
|
+
KnownContracts["MULTISEND_ENCODER"] = "multisendEncoder";
|
|
31
|
+
KnownContracts["CONNEXT"] = "connext";
|
|
32
|
+
})(KnownContracts || (KnownContracts = {}));
|
|
33
|
+
export const SupportedNetworks = Object.freeze({
|
|
34
|
+
MAINNET: 1,
|
|
35
|
+
OPTIMISM: 10,
|
|
36
|
+
FLARE: 14,
|
|
37
|
+
BSC: 56,
|
|
38
|
+
BNB: 56,
|
|
39
|
+
GNOSIS: 100,
|
|
40
|
+
UNICHAIN: 130,
|
|
41
|
+
POLYGON: 137,
|
|
42
|
+
SONIC: 146,
|
|
43
|
+
WORLDCHAIN: 480,
|
|
44
|
+
HYPEREVM: 999,
|
|
45
|
+
MEGAETH: 4326,
|
|
46
|
+
MANTLE: 5000,
|
|
47
|
+
BASE: 8453,
|
|
48
|
+
PLASMA: 9745,
|
|
49
|
+
ARBITRUM: 42161,
|
|
50
|
+
CELO: 42220,
|
|
51
|
+
AVALANCHE: 43114,
|
|
52
|
+
INK: 57073,
|
|
53
|
+
LINEA: 59144,
|
|
54
|
+
BOB: 60808,
|
|
55
|
+
BERACHAIN: 80094,
|
|
56
|
+
SCROLL: 534352,
|
|
57
|
+
KATANA: 747474,
|
|
58
|
+
SEPOLIA: 11155111,
|
|
59
|
+
});
|
|
60
|
+
/** Canonical mastercopy address for each known contract, by version. */
|
|
61
|
+
export const CanonicalAddresses = {
|
|
62
|
+
[KnownContracts.META_GUARD]: {
|
|
63
|
+
"1.0.0": "0xe2847462a574bfd43014d1c7BB6De5769C294691",
|
|
64
|
+
},
|
|
65
|
+
[KnownContracts.REALITY_ETH]: {
|
|
66
|
+
"2.0.0": "0x4e35DA39Fa5893a70A40Ce964F993d891E607cC0",
|
|
67
|
+
},
|
|
68
|
+
[KnownContracts.REALITY_ERC20]: {
|
|
69
|
+
"2.0.0": "0x7276813b21623d89BA8984B225d5792943DD7dbF",
|
|
70
|
+
},
|
|
71
|
+
[KnownContracts.BRIDGE]: {
|
|
72
|
+
"1.0.0": "0x03B5eBD2CB2e3339E93774A1Eb7c8634B8C393A9",
|
|
73
|
+
},
|
|
74
|
+
[KnownContracts.DELAY]: {
|
|
75
|
+
"1.0.0": "0xD62129BF40CD1694b3d9D9847367783a1A4d5cB4",
|
|
76
|
+
"1.0.1": "0xd54895B1121A2eE3f37b502F507631FA1331BED6",
|
|
77
|
+
"1.1.0": "0x01F8cabB808D7dE0dF4202D4B60C8310d2f1339b",
|
|
78
|
+
"1.1.1": "0x824175b945838d127c1ca83cbce11d8e44f6df01",
|
|
79
|
+
},
|
|
80
|
+
[KnownContracts.FACTORY]: {
|
|
81
|
+
"1.0.0": "0x00000000062c52e29e8029dc2413172f6d619d85",
|
|
82
|
+
"1.1.0": "0x00000000000DC7F163742Eb4aBEf650037b1f588",
|
|
83
|
+
"1.2.0": "0x000000000000aDdB49795b0f9bA5BC298cDda236",
|
|
84
|
+
},
|
|
85
|
+
[KnownContracts.EXIT_ERC20]: {
|
|
86
|
+
"1.0.0": "0x35E35dcDc7Cd112B93C7c55987C86e5D6D419C69",
|
|
87
|
+
"1.1.0": "0x33bCa41bda8A3983afbAd8fc8936Ce2Fb29121da",
|
|
88
|
+
"1.2.0": "0x3ed380a282aDfA3460da28560ebEB2F6D967C9f5",
|
|
89
|
+
},
|
|
90
|
+
[KnownContracts.EXIT_ERC721]: {
|
|
91
|
+
"1.1.0": "0xD3579C14a4181EfC3DF35C3103D20823A8C8d718",
|
|
92
|
+
"1.2.0": "0xE0eCE32Eb4BE4E9224dcec6a4FcB335c1fe05CDe",
|
|
93
|
+
},
|
|
94
|
+
[KnownContracts.CIRCULATING_SUPPLY_ERC20]: {
|
|
95
|
+
"1.0.0": "0xd7a85e7D0813F8440602E243Acb67df3CCeb5a60",
|
|
96
|
+
"1.1.0": "0xb50fab2e2892E3323A5300870C042B428B564FE3",
|
|
97
|
+
"1.2.0": "0x5Ed57C291a184cc244F5c9B5E9F11a8DD08BBd12",
|
|
98
|
+
},
|
|
99
|
+
[KnownContracts.CIRCULATING_SUPPLY_ERC721]: {
|
|
100
|
+
"1.1.0": "0x71530ec830CBE363bab28F4EC52964a550C0AB1E",
|
|
101
|
+
"1.2.0": "0xBD34D00dC0ae37C687F784A11FA6a0F2c5726Ba3",
|
|
102
|
+
},
|
|
103
|
+
[KnownContracts.SCOPE_GUARD]: {
|
|
104
|
+
"1.0.0": "0xeF27fcd3965a866b22Fb2d7C689De9AB7e611f1F",
|
|
105
|
+
},
|
|
106
|
+
[KnownContracts.ROLES]: {
|
|
107
|
+
"1.0.0": "0x85388a8cd772b19a468F982Dc264C238856939C9",
|
|
108
|
+
"1.1.0": "0xD8DfC1d938D7D163C5231688341e9635E9011889",
|
|
109
|
+
"2.1.0": "0x9646fDAD06d3e24444381f44362a3B0eB343D337",
|
|
110
|
+
"2.1.1": "0xf2964ce6161ce0e75964fe7927ce114cb0b283d5",
|
|
111
|
+
},
|
|
112
|
+
[KnownContracts.TELLOR]: {
|
|
113
|
+
"2.1.0": "0xa89EC2C1e218CfBb0F82829E95352CeAbDEe9A69",
|
|
114
|
+
},
|
|
115
|
+
[KnownContracts.OPTIMISTIC_GOVERNOR]: {
|
|
116
|
+
"1.0.0": "",
|
|
117
|
+
"1.2.0": "0x28CeBFE94a03DbCA9d17143e9d2Bd1155DC26D5d",
|
|
118
|
+
},
|
|
119
|
+
[KnownContracts.OZ_GOVERNOR]: {
|
|
120
|
+
"1.0.0": "0xe28c39FAC73cce2B33C4C003049e2F3AE43f77d5",
|
|
121
|
+
},
|
|
122
|
+
[KnownContracts.ERC20_VOTES]: {
|
|
123
|
+
"1.0.0": "0x752c61de75ADA0F8a33e048d2F773f51172f033e",
|
|
124
|
+
},
|
|
125
|
+
[KnownContracts.ERC721_VOTES]: {
|
|
126
|
+
"1.0.0": "0xeFf38b2eBB95ACBA09761246045743f40e762568",
|
|
127
|
+
},
|
|
128
|
+
[KnownContracts.MULTISEND_ENCODER]: {
|
|
129
|
+
"1.0.0": "0xb67EDe523171325345780fA3016b7F5221293df0",
|
|
130
|
+
},
|
|
131
|
+
[KnownContracts.CONNEXT]: {
|
|
132
|
+
"1.0.0": "0x7dE07b9De0bf0FABf31A188DE1527034b2aF36dB",
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
export const FAULTY = {
|
|
136
|
+
[KnownContracts.DELAY]: {
|
|
137
|
+
"1.1.0": "0x01F8cabB808D7dE0dF4202D4B60C8310d2f1339b",
|
|
138
|
+
},
|
|
139
|
+
[KnownContracts.ROLES]: {
|
|
140
|
+
"2.1.0": "0x9646fDAD06d3e24444381f44362a3B0eB343D337",
|
|
141
|
+
},
|
|
142
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal Etherscan-compatible explorer client.
|
|
3
|
+
*
|
|
4
|
+
* Everything `extract` needs is reachable through the explorer:
|
|
5
|
+
* - `getsourcecode` -> verified source, ABI, compiler input, constructor args
|
|
6
|
+
* - `getcontractcreation` -> the deployment transaction hash
|
|
7
|
+
* - `eth_getTransactionByHash` (proxy module) -> the raw deployment calldata
|
|
8
|
+
*
|
|
9
|
+
* so no separate JSON-RPC endpoint is required for extraction.
|
|
10
|
+
*/
|
|
11
|
+
export interface SourceCode {
|
|
12
|
+
contractName: string;
|
|
13
|
+
sourceName: string;
|
|
14
|
+
compilerVersion: string;
|
|
15
|
+
compilerInput: any;
|
|
16
|
+
abi: any;
|
|
17
|
+
/** abi-encoded constructor arguments (hex, no leading 0x). */
|
|
18
|
+
constructorArguments: string;
|
|
19
|
+
}
|
|
20
|
+
export interface ContractCreation {
|
|
21
|
+
txHash?: string;
|
|
22
|
+
creationBytecode?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface VerificationRequest {
|
|
25
|
+
address: string;
|
|
26
|
+
network: string | number;
|
|
27
|
+
sourceCode: string;
|
|
28
|
+
contractName: string;
|
|
29
|
+
compilerVersion: string;
|
|
30
|
+
constructorArguments?: string;
|
|
31
|
+
evmVersion?: string;
|
|
32
|
+
licenseType?: string;
|
|
33
|
+
apiKey?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Fetch verified source, ABI and compiler input for a deployed contract.
|
|
37
|
+
*/
|
|
38
|
+
export declare function getSourceCode({ address, network, apiKey, }: {
|
|
39
|
+
address: string;
|
|
40
|
+
network: string | number;
|
|
41
|
+
apiKey?: string;
|
|
42
|
+
}): Promise<SourceCode>;
|
|
43
|
+
/**
|
|
44
|
+
* Get creation metadata (tx hash and bytecode) for a contract.
|
|
45
|
+
*/
|
|
46
|
+
export declare function getContractCreation({ address, network, apiKey, }: {
|
|
47
|
+
address: string;
|
|
48
|
+
network: string | number;
|
|
49
|
+
apiKey?: string;
|
|
50
|
+
}): Promise<ContractCreation | undefined>;
|
|
51
|
+
/**
|
|
52
|
+
* Fetch a transaction (input + to) via the explorer's proxy module.
|
|
53
|
+
*/
|
|
54
|
+
export declare function getTransaction({ txHash, network, apiKey, }: {
|
|
55
|
+
txHash: string;
|
|
56
|
+
network: string | number;
|
|
57
|
+
apiKey?: string;
|
|
58
|
+
}): Promise<{
|
|
59
|
+
to: string | null;
|
|
60
|
+
input: string;
|
|
61
|
+
} | undefined>;
|
|
62
|
+
/**
|
|
63
|
+
* Fetch the deployed (runtime) bytecode at an address via the proxy module.
|
|
64
|
+
*/
|
|
65
|
+
export declare function getCode({ address, network, apiKey, }: {
|
|
66
|
+
address: string;
|
|
67
|
+
network: string | number;
|
|
68
|
+
apiKey?: string;
|
|
69
|
+
}): Promise<string>;
|
|
70
|
+
/**
|
|
71
|
+
* Submit standard-JSON Solidity source for verification.
|
|
72
|
+
*/
|
|
73
|
+
export declare function verifySourceCode({ address, network, sourceCode, contractName, compilerVersion, constructorArguments, evmVersion, licenseType, apiKey, }: VerificationRequest): Promise<string>;
|
|
74
|
+
/**
|
|
75
|
+
* Check the async source verification status for a submitted GUID.
|
|
76
|
+
*/
|
|
77
|
+
export declare function checkVerificationStatus({ guid, network, apiKey, }: {
|
|
78
|
+
guid: string;
|
|
79
|
+
network: string | number;
|
|
80
|
+
apiKey?: string;
|
|
81
|
+
}): Promise<string>;
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { resolveNetwork } from "./networks.js";
|
|
2
|
+
function isOk(status) {
|
|
3
|
+
return String(status) === "1";
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Etherscan double-wraps the standard-JSON source in extra braces. Parse
|
|
7
|
+
* tolerantly so both `{{...}}` and `{...}` payloads succeed.
|
|
8
|
+
*/
|
|
9
|
+
function safeJsonParse(input) {
|
|
10
|
+
const trimmed = input.trim();
|
|
11
|
+
try {
|
|
12
|
+
return JSON.parse(trimmed);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return JSON.parse(trimmed.replace(/^\{|\}$/g, "").trim());
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function parseLibraries(input) {
|
|
19
|
+
const libraries = {};
|
|
20
|
+
for (const entry of (input || "").split(/[;,]/)) {
|
|
21
|
+
const match = entry.trim().match(/^(.+?)(?::|\s)+(0x[0-9a-fA-F]{40})$/);
|
|
22
|
+
if (match)
|
|
23
|
+
libraries[match[1].trim()] = match[2];
|
|
24
|
+
}
|
|
25
|
+
return libraries;
|
|
26
|
+
}
|
|
27
|
+
function compilerInputFromExplorerEntry(entry) {
|
|
28
|
+
const sourceCode = entry.SourceCode.trim();
|
|
29
|
+
const contractName = entry.ContractName;
|
|
30
|
+
if (sourceCode.startsWith("{")) {
|
|
31
|
+
const compilerInput = safeJsonParse(sourceCode);
|
|
32
|
+
return {
|
|
33
|
+
compilerInput,
|
|
34
|
+
sourceName: sourceNameFor(compilerInput, contractName),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const sourceName = entry.ContractFileName || `${contractName}.sol`;
|
|
38
|
+
const settings = {};
|
|
39
|
+
if (entry.OptimizationUsed !== "") {
|
|
40
|
+
settings.optimizer = {
|
|
41
|
+
enabled: String(entry.OptimizationUsed) === "1",
|
|
42
|
+
runs: Number(entry.Runs) || 200,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (entry.EVMVersion && entry.EVMVersion !== "Default") {
|
|
46
|
+
settings.evmVersion = entry.EVMVersion;
|
|
47
|
+
}
|
|
48
|
+
const libraries = parseLibraries(entry.Library);
|
|
49
|
+
if (Object.keys(libraries).length > 0) {
|
|
50
|
+
settings.libraries = { [sourceName]: libraries };
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
sourceName,
|
|
54
|
+
compilerInput: {
|
|
55
|
+
language: "Solidity",
|
|
56
|
+
sources: {
|
|
57
|
+
[sourceName]: { content: sourceCode },
|
|
58
|
+
},
|
|
59
|
+
settings,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function resolveApiKey(network, explicit) {
|
|
64
|
+
return (explicit ||
|
|
65
|
+
process.env[`ETHERSCAN_API_KEY_${network.toUpperCase()}`] ||
|
|
66
|
+
process.env.ETHERSCAN_API_KEY ||
|
|
67
|
+
"");
|
|
68
|
+
}
|
|
69
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
70
|
+
function isRateLimited(body) {
|
|
71
|
+
const text = `${body?.message ?? ""} ${body?.result ?? ""}`.toLowerCase();
|
|
72
|
+
return text.includes("rate limit");
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Internal helper to perform a GET against the explorer API.
|
|
76
|
+
* Resolves network, API key, and handles rate-limiting retries.
|
|
77
|
+
*/
|
|
78
|
+
async function explorerGet(networkOrChainId, params, apiKey, attempt = 0) {
|
|
79
|
+
const network = resolveNetwork(networkOrChainId);
|
|
80
|
+
if (!network.etherscanApiUrl) {
|
|
81
|
+
throw new Error(`${network.name} (chain ${network.chainId}) is not supported by Etherscan V2.`);
|
|
82
|
+
}
|
|
83
|
+
const url = new URL(network.etherscanApiUrl);
|
|
84
|
+
url.searchParams.set("apikey", resolveApiKey(network.name, apiKey));
|
|
85
|
+
for (const [key, value] of Object.entries(params)) {
|
|
86
|
+
url.searchParams.set(key, value);
|
|
87
|
+
}
|
|
88
|
+
const response = await fetch(url);
|
|
89
|
+
if (!response.ok) {
|
|
90
|
+
throw new Error(`Explorer request failed: ${response.status}`);
|
|
91
|
+
}
|
|
92
|
+
const body = (await response.json());
|
|
93
|
+
if (isRateLimited(body) && attempt < 5) {
|
|
94
|
+
await sleep(1000 * (attempt + 1));
|
|
95
|
+
return explorerGet(networkOrChainId, params, apiKey, attempt + 1);
|
|
96
|
+
}
|
|
97
|
+
return body;
|
|
98
|
+
}
|
|
99
|
+
async function explorerPost(networkOrChainId, params, apiKey, attempt = 0) {
|
|
100
|
+
const network = resolveNetwork(networkOrChainId);
|
|
101
|
+
if (!network.etherscanApiUrl) {
|
|
102
|
+
throw new Error(`${network.name} (chain ${network.chainId}) is not supported by Etherscan V2.`);
|
|
103
|
+
}
|
|
104
|
+
const body = new URLSearchParams();
|
|
105
|
+
body.set("apikey", resolveApiKey(network.name, apiKey));
|
|
106
|
+
for (const [key, value] of new URL(network.etherscanApiUrl).searchParams) {
|
|
107
|
+
body.set(key, value);
|
|
108
|
+
}
|
|
109
|
+
for (const [key, value] of Object.entries(params)) {
|
|
110
|
+
body.set(key, value);
|
|
111
|
+
}
|
|
112
|
+
const response = await fetch(network.etherscanApiUrl, {
|
|
113
|
+
method: "POST",
|
|
114
|
+
headers: {
|
|
115
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
116
|
+
},
|
|
117
|
+
body,
|
|
118
|
+
});
|
|
119
|
+
if (!response.ok) {
|
|
120
|
+
throw new Error(`Explorer request failed: ${response.status}`);
|
|
121
|
+
}
|
|
122
|
+
const responseBody = (await response.json());
|
|
123
|
+
if (isRateLimited(responseBody) && attempt < 5) {
|
|
124
|
+
await sleep(1000 * (attempt + 1));
|
|
125
|
+
return explorerPost(networkOrChainId, params, apiKey, attempt + 1);
|
|
126
|
+
}
|
|
127
|
+
return responseBody;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Fetch verified source, ABI and compiler input for a deployed contract.
|
|
131
|
+
*/
|
|
132
|
+
export async function getSourceCode({ address, network, apiKey, }) {
|
|
133
|
+
const { status, message, result } = await explorerGet(network, {
|
|
134
|
+
module: "contract",
|
|
135
|
+
action: "getsourcecode",
|
|
136
|
+
address,
|
|
137
|
+
}, apiKey);
|
|
138
|
+
if (!isOk(status)) {
|
|
139
|
+
throw new Error(`getsourcecode failed for ${address}: ${message}${result ? ` (${result})` : ""}`);
|
|
140
|
+
}
|
|
141
|
+
const entry = result[0];
|
|
142
|
+
if (!entry?.SourceCode) {
|
|
143
|
+
throw new Error(`Contract ${address} is not verified on ${network}`);
|
|
144
|
+
}
|
|
145
|
+
const { compilerInput, sourceName } = compilerInputFromExplorerEntry(entry);
|
|
146
|
+
return {
|
|
147
|
+
contractName: entry.ContractName,
|
|
148
|
+
sourceName,
|
|
149
|
+
compilerVersion: entry.CompilerVersion,
|
|
150
|
+
compilerInput,
|
|
151
|
+
abi: entry.ABI ? safeJsonParse(entry.ABI) : undefined,
|
|
152
|
+
constructorArguments: entry.ConstructorArguments || "",
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Resolve the full source path for a contract name within a standard-JSON input.
|
|
157
|
+
*/
|
|
158
|
+
function sourceNameFor(compilerInput, contractName) {
|
|
159
|
+
const sources = compilerInput?.sources || {};
|
|
160
|
+
// Prefer a source file whose path basename matches the contract name.
|
|
161
|
+
const match = Object.keys(sources).find((path) => path
|
|
162
|
+
.split("/")
|
|
163
|
+
.pop()
|
|
164
|
+
?.replace(/\.sol$/, "") === contractName);
|
|
165
|
+
if (match)
|
|
166
|
+
return match;
|
|
167
|
+
const [only] = Object.keys(sources);
|
|
168
|
+
if (only)
|
|
169
|
+
return only;
|
|
170
|
+
throw new Error(`Could not resolve sourceName for ${contractName}`);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Get creation metadata (tx hash and bytecode) for a contract.
|
|
174
|
+
*/
|
|
175
|
+
export async function getContractCreation({ address, network, apiKey, }) {
|
|
176
|
+
const { status, result } = await explorerGet(network, {
|
|
177
|
+
module: "contract",
|
|
178
|
+
action: "getcontractcreation",
|
|
179
|
+
contractaddresses: address,
|
|
180
|
+
}, apiKey);
|
|
181
|
+
if (!isOk(status) || !Array.isArray(result) || result.length === 0) {
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
txHash: result[0].txHash,
|
|
186
|
+
creationBytecode: result[0].creationBytecode,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Fetch a transaction (input + to) via the explorer's proxy module.
|
|
191
|
+
*/
|
|
192
|
+
export async function getTransaction({ txHash, network, apiKey, }) {
|
|
193
|
+
const { result } = await explorerGet(network, {
|
|
194
|
+
module: "proxy",
|
|
195
|
+
action: "eth_getTransactionByHash",
|
|
196
|
+
txhash: txHash,
|
|
197
|
+
}, apiKey);
|
|
198
|
+
if (!result?.input)
|
|
199
|
+
return undefined;
|
|
200
|
+
return { to: result.to ?? null, input: result.input };
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Fetch the deployed (runtime) bytecode at an address via the proxy module.
|
|
204
|
+
*/
|
|
205
|
+
export async function getCode({ address, network, apiKey, }) {
|
|
206
|
+
const { result } = await explorerGet(network, {
|
|
207
|
+
module: "proxy",
|
|
208
|
+
action: "eth_getCode",
|
|
209
|
+
address,
|
|
210
|
+
tag: "latest",
|
|
211
|
+
}, apiKey);
|
|
212
|
+
return result ?? "0x";
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Submit standard-JSON Solidity source for verification.
|
|
216
|
+
*/
|
|
217
|
+
export async function verifySourceCode({ address, network, sourceCode, contractName, compilerVersion, constructorArguments = "", evmVersion = "default", licenseType = "1", apiKey, }) {
|
|
218
|
+
const { status, message, result } = await explorerPost(network, {
|
|
219
|
+
module: "contract",
|
|
220
|
+
action: "verifysourcecode",
|
|
221
|
+
contractaddress: address,
|
|
222
|
+
sourceCode,
|
|
223
|
+
codeformat: "solidity-standard-json-input",
|
|
224
|
+
contractname: contractName,
|
|
225
|
+
compilerversion: compilerVersion,
|
|
226
|
+
optimizationUsed: "0",
|
|
227
|
+
runs: "200",
|
|
228
|
+
constructorArguments,
|
|
229
|
+
evmVersion,
|
|
230
|
+
licenseType,
|
|
231
|
+
}, apiKey);
|
|
232
|
+
if (!isOk(status)) {
|
|
233
|
+
if (typeof result === "string" &&
|
|
234
|
+
result.toLowerCase().includes("already")) {
|
|
235
|
+
return result;
|
|
236
|
+
}
|
|
237
|
+
throw new Error(`${message}${result ? ` (${result})` : ""}`);
|
|
238
|
+
}
|
|
239
|
+
return result;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Check the async source verification status for a submitted GUID.
|
|
243
|
+
*/
|
|
244
|
+
export async function checkVerificationStatus({ guid, network, apiKey, }) {
|
|
245
|
+
const { status, message, result } = await explorerPost(network, {
|
|
246
|
+
module: "contract",
|
|
247
|
+
action: "checkverifystatus",
|
|
248
|
+
guid,
|
|
249
|
+
}, apiKey);
|
|
250
|
+
if (!isOk(status)) {
|
|
251
|
+
if (typeof result === "string" && result)
|
|
252
|
+
return result;
|
|
253
|
+
throw new Error(`${message}${result ? ` (${result})` : ""}`);
|
|
254
|
+
}
|
|
255
|
+
return result;
|
|
256
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Asset } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Extract an asset (and, recursively, every library it links) from a block
|
|
4
|
+
* explorer.
|
|
5
|
+
*
|
|
6
|
+
* Recursion is depth-first and deduplicated by address, so a library shared by
|
|
7
|
+
* several contracts is fetched once.
|
|
8
|
+
*
|
|
9
|
+
* @returns every asset produced, keyed by lower-cased address.
|
|
10
|
+
*/
|
|
11
|
+
export declare function extract({ network, address, apiKey, }: {
|
|
12
|
+
network: string | number;
|
|
13
|
+
address: string;
|
|
14
|
+
apiKey?: string;
|
|
15
|
+
}): Promise<Map<string, Asset>>;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { getAddress } from "ethers";
|
|
2
|
+
import { predictSingletonAddress } from "@gnosis-guild/zodiac-core";
|
|
3
|
+
import { resolveNetwork } from "./networks.js";
|
|
4
|
+
import { getCode, getContractCreation, getSourceCode, getTransaction, } from "./explorer.js";
|
|
5
|
+
import { recoverDeployment } from "./singleton.js";
|
|
6
|
+
/**
|
|
7
|
+
* Enumerate the libraries a contract links, from its standard-JSON compiler
|
|
8
|
+
* input. Shape: `settings.libraries = { [sourceName]: { [libName]: address } }`.
|
|
9
|
+
*/
|
|
10
|
+
function enumerateLibraries(input) {
|
|
11
|
+
const libraries = input?.settings?.libraries || {};
|
|
12
|
+
const out = [];
|
|
13
|
+
for (const sourceName of Object.keys(libraries)) {
|
|
14
|
+
for (const libraryName of Object.keys(libraries[sourceName] || {})) {
|
|
15
|
+
const address = libraries[sourceName][libraryName];
|
|
16
|
+
if (address)
|
|
17
|
+
out.push({ sourceName, libraryName, address });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return out;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Extract an asset (and, recursively, every library it links) from a block
|
|
24
|
+
* explorer.
|
|
25
|
+
*
|
|
26
|
+
* Recursion is depth-first and deduplicated by address, so a library shared by
|
|
27
|
+
* several contracts is fetched once.
|
|
28
|
+
*
|
|
29
|
+
* @returns every asset produced, keyed by lower-cased address.
|
|
30
|
+
*/
|
|
31
|
+
export async function extract({ network, address, apiKey, }) {
|
|
32
|
+
const net = resolveNetwork(network);
|
|
33
|
+
const visited = new Map();
|
|
34
|
+
await extractOne({
|
|
35
|
+
address,
|
|
36
|
+
networkName: net.name,
|
|
37
|
+
apiKey,
|
|
38
|
+
visited,
|
|
39
|
+
});
|
|
40
|
+
return visited;
|
|
41
|
+
}
|
|
42
|
+
async function extractOne({ address, nameHint, networkName, apiKey, visited, }) {
|
|
43
|
+
const key = getAddress(address).toLowerCase();
|
|
44
|
+
const existing = visited.get(key);
|
|
45
|
+
if (existing)
|
|
46
|
+
return existing;
|
|
47
|
+
const source = await getSourceCode({ address, network: networkName, apiKey });
|
|
48
|
+
const name = nameHint || source.contractName;
|
|
49
|
+
const creation = await getContractCreation({
|
|
50
|
+
address,
|
|
51
|
+
network: networkName,
|
|
52
|
+
apiKey,
|
|
53
|
+
});
|
|
54
|
+
const tx = creation?.txHash
|
|
55
|
+
? await getTransaction({
|
|
56
|
+
txHash: creation.txHash,
|
|
57
|
+
network: networkName,
|
|
58
|
+
apiKey,
|
|
59
|
+
})
|
|
60
|
+
: undefined;
|
|
61
|
+
const recovered = tx && recoverDeployment(tx);
|
|
62
|
+
if (!recovered) {
|
|
63
|
+
throw new Error(`${name} @ ${address} was not deployed via a known singleton factory.`);
|
|
64
|
+
}
|
|
65
|
+
const { factory, initCode: creationBytecode, salt } = recovered;
|
|
66
|
+
// Sanity: the recovered creation bytecode must reproduce the on-chain address
|
|
67
|
+
// via CREATE2. By construction it always does — a failure means a parsing bug.
|
|
68
|
+
// zodiac-core's helper concatenates bytecode + encoded constructor args; we
|
|
69
|
+
// already hold the full creation bytecode, so pass it as `bytecode` with empty
|
|
70
|
+
// args (the concat is then a no-op).
|
|
71
|
+
const predicted = predictSingletonAddress({
|
|
72
|
+
factory,
|
|
73
|
+
bytecode: creationBytecode,
|
|
74
|
+
constructorArgs: { types: [], values: [] },
|
|
75
|
+
salt,
|
|
76
|
+
});
|
|
77
|
+
if (predicted.toLowerCase() !== key) {
|
|
78
|
+
throw new Error(`${name} @ ${address}: recovered creation bytecode reproduces ` +
|
|
79
|
+
`${predicted}, not the on-chain address. Refusing to write.`);
|
|
80
|
+
}
|
|
81
|
+
// Deployed (runtime) bytecode actually stored at the address.
|
|
82
|
+
const bytecode = await getCode({ address, network: networkName, apiKey });
|
|
83
|
+
// Record this asset before recursing so shared libraries dedupe correctly.
|
|
84
|
+
const asset = {
|
|
85
|
+
name,
|
|
86
|
+
abi: source.abi,
|
|
87
|
+
sourceCode: {
|
|
88
|
+
contractName: source.contractName,
|
|
89
|
+
sourceName: source.sourceName,
|
|
90
|
+
compilerVersion: source.compilerVersion,
|
|
91
|
+
constructorArguments: source.constructorArguments,
|
|
92
|
+
input: source.compilerInput,
|
|
93
|
+
},
|
|
94
|
+
bytecode: {
|
|
95
|
+
address: predicted,
|
|
96
|
+
factory,
|
|
97
|
+
salt,
|
|
98
|
+
creationBytecode,
|
|
99
|
+
bytecode,
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
visited.set(key, asset);
|
|
103
|
+
// Recurse into linked libraries.
|
|
104
|
+
for (const lib of enumerateLibraries(source.compilerInput)) {
|
|
105
|
+
await extractOne({
|
|
106
|
+
address: lib.address,
|
|
107
|
+
nameHint: lib.libraryName,
|
|
108
|
+
networkName,
|
|
109
|
+
apiKey,
|
|
110
|
+
visited,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
return asset;
|
|
114
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { encodeDeployProxy, encodeDeploySingleton, predictProxyAddress, predictSingletonAddress, } from "@gnosis-guild/zodiac-core";
|
|
2
|
+
export { CanonicalAddresses, KnownContracts, SupportedNetworks, } from "./contracts.js";
|
|
3
|
+
export { getZodiacModuleAbi, getZodiacModuleAddress, sanityCheckZodiacModuleAddress, } from "./zodiacModule.js";
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { encodeDeployProxy, encodeDeploySingleton, predictProxyAddress, predictSingletonAddress, } from "@gnosis-guild/zodiac-core";
|
|
2
|
+
export { CanonicalAddresses, KnownContracts, SupportedNetworks, } from "./contracts.js";
|
|
3
|
+
export { getZodiacModuleAbi, getZodiacModuleAddress, sanityCheckZodiacModuleAddress, } from "./zodiacModule.js";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Asset } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* The on-disk layout:
|
|
4
|
+
*
|
|
5
|
+
* mastercopies/<module>/<version>/<asset>/abi.json
|
|
6
|
+
* mastercopies/<module>/<version>/<asset>/sourcecode.json
|
|
7
|
+
* mastercopies/<module>/<version>/<asset>/bytecode.json
|
|
8
|
+
*
|
|
9
|
+
* where <asset> is the main contract name or a linked-library name.
|
|
10
|
+
*/
|
|
11
|
+
export declare function defaultMastercopiesDir(): string;
|
|
12
|
+
/**
|
|
13
|
+
* Write one asset's three files, creating directories as needed.
|
|
14
|
+
* Returns the asset directory.
|
|
15
|
+
*/
|
|
16
|
+
export declare function writeAsset({ module, version, asset, mastercopiesDir, }: {
|
|
17
|
+
module: string;
|
|
18
|
+
version: string;
|
|
19
|
+
asset: Asset;
|
|
20
|
+
mastercopiesDir?: string;
|
|
21
|
+
}): string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { cwd } from "process";
|
|
4
|
+
/**
|
|
5
|
+
* The on-disk layout:
|
|
6
|
+
*
|
|
7
|
+
* mastercopies/<module>/<version>/<asset>/abi.json
|
|
8
|
+
* mastercopies/<module>/<version>/<asset>/sourcecode.json
|
|
9
|
+
* mastercopies/<module>/<version>/<asset>/bytecode.json
|
|
10
|
+
*
|
|
11
|
+
* where <asset> is the main contract name or a linked-library name.
|
|
12
|
+
*/
|
|
13
|
+
export function defaultMastercopiesDir() {
|
|
14
|
+
return path.join(cwd(), "mastercopies");
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Write one asset's three files, creating directories as needed.
|
|
18
|
+
* Returns the asset directory.
|
|
19
|
+
*/
|
|
20
|
+
export function writeAsset({ module, version, asset, mastercopiesDir = defaultMastercopiesDir(), }) {
|
|
21
|
+
const dir = path.join(mastercopiesDir, module, version, asset.name);
|
|
22
|
+
mkdirSync(dir, { recursive: true });
|
|
23
|
+
writeFileSync(path.join(dir, "abi.json"), JSON.stringify(asset.abi, null, 2), "utf8");
|
|
24
|
+
writeFileSync(path.join(dir, "sourcecode.json"), JSON.stringify(asset.sourceCode, null, 2), "utf8");
|
|
25
|
+
writeFileSync(path.join(dir, "bytecode.json"), JSON.stringify(asset.bytecode, null, 2), "utf8");
|
|
26
|
+
return dir;
|
|
27
|
+
}
|