@openzeppelin/upgrades-core 1.25.0 → 1.26.1
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/artifacts/@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol/ERC1967Proxy.dbg.json +1 -1
- package/artifacts/@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol/ERC1967Proxy.json +2 -2
- package/artifacts/@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol/BeaconProxy.dbg.json +1 -1
- package/artifacts/@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol/BeaconProxy.json +2 -2
- package/artifacts/@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol/UpgradeableBeacon.dbg.json +1 -1
- package/artifacts/@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol/UpgradeableBeacon.json +2 -2
- package/artifacts/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json +7 -7
- package/artifacts/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json +2 -72
- package/artifacts/AdminUpgradeabilityProxy.json +2 -72
- package/artifacts/ProxyAdmin.json +7 -7
- package/artifacts/build-info.json +21225 -12
- package/artifacts/contracts/proxy/AdminUpgradeabilityProxy.sol/AdminUpgradeabilityProxy.json +2 -72
- package/artifacts/contracts/proxy/ProxyAdmin.sol/ProxyAdmin.json +7 -7
- package/dist/deployment.d.ts +28 -4
- package/dist/deployment.d.ts.map +1 -1
- package/dist/deployment.js +106 -25
- package/dist/deployment.js.map +1 -1
- package/dist/deployment.test.js +116 -0
- package/dist/deployment.test.js.map +1 -1
- package/dist/impl-store.d.ts +27 -2
- package/dist/impl-store.d.ts.map +1 -1
- package/dist/impl-store.js +39 -8
- package/dist/impl-store.js.map +1 -1
- package/dist/impl-store.test.js +30 -0
- package/dist/impl-store.test.js.map +1 -1
- package/dist/manifest.d.ts +3 -3
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +1 -1
- package/dist/manifest.js.map +1 -1
- package/dist/manifest.test.js +1 -0
- package/dist/manifest.test.js.map +1 -1
- package/dist/validate/error.d.ts +3 -0
- package/dist/validate/error.d.ts.map +1 -1
- package/dist/validate/error.js +7 -1
- package/dist/validate/error.js.map +1 -1
- package/dist/validate/index.d.ts +1 -1
- package/dist/validate/index.d.ts.map +1 -1
- package/dist/validate/index.js +2 -1
- package/dist/validate/index.js.map +1 -1
- package/dist/validate/query.js +1 -1
- package/dist/validate/query.js.map +1 -1
- package/package.json +5 -4
- package/src/deployment.test.ts +182 -1
- package/src/deployment.ts +134 -26
- package/src/impl-store.test.ts +52 -1
- package/src/impl-store.ts +69 -11
- package/src/manifest.test.ts +1 -0
- package/src/manifest.ts +11 -8
- package/src/validate/error.ts +6 -0
- package/src/validate/index.ts +1 -1
- package/src/validate/query.ts +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/validate/error.ts"],"names":[],"mappings":";;;AACA,oCAAyC;AACzC,qCAA0D;AAE1D,MAAa,gBAAiB,SAAQ,qBAAa;IACjD,YAAY,YAAoB,EAAW,MAAyB;QAClE,KAAK,CAAC,cAAc,YAAY,wBAAwB,EAAE,GAAG,EAAE,CAC7D,IAAI,uCAA8B,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,CACrD,CAAC;QAHuC,WAAM,GAAN,MAAM,CAAmB;IAIpE,CAAC;CACF;AAND,4CAMC"}
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/validate/error.ts"],"names":[],"mappings":";;;AACA,oCAAyC;AACzC,qCAA0D;AAE1D,MAAa,gBAAiB,SAAQ,qBAAa;IACjD,YAAY,YAAoB,EAAW,MAAyB;QAClE,KAAK,CAAC,cAAc,YAAY,wBAAwB,EAAE,GAAG,EAAE,CAC7D,IAAI,uCAA8B,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,CACrD,CAAC;QAHuC,WAAM,GAAN,MAAM,CAAmB;IAIpE,CAAC;CACF;AAND,4CAMC;AAED,MAAa,2BAA4B,SAAQ,qBAAa;IAC5D;QACE,KAAK,CAAC,8FAA8F,CAAC,CAAC;IACxG,CAAC;CACF;AAJD,kEAIC"}
|
package/dist/validate/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { validate, ValidationRunData, ContractValidation } from './run';
|
|
2
2
|
export { ProxyKindOption, StandaloneValidationOptions, ValidationOptions, withValidationDefaults } from './overrides';
|
|
3
|
-
export { ValidationErrors } from './error';
|
|
3
|
+
export { ValidationErrors, ContractSourceNotFoundError } from './error';
|
|
4
4
|
export { RunValidation, ValidationLog, Validation, ValidationResult } from './compat';
|
|
5
5
|
export { ValidationData, ValidationDataCurrent, isCurrentValidationData, concatRunData } from './data';
|
|
6
6
|
export { getContractVersion, getContractNameAndRunValidation, getStorageLayout, assertUpgradeSafe, getUnlinkedBytecode, getErrors, isUpgradeSafe, inferProxyKind, } from './query';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/validate/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,2BAA2B,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACtH,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/validate/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,2BAA2B,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACtH,OAAO,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACtF,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvG,OAAO,EACL,kBAAkB,EAClB,+BAA+B,EAC/B,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,SAAS,EACT,aAAa,EACb,cAAc,GACf,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,8BAA8B,EAAE,MAAM,UAAU,CAAC;AAG1D,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/validate/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.silenceWarnings = exports.UpgradeableContractErrorReport = exports.inferProxyKind = exports.isUpgradeSafe = exports.getErrors = exports.getUnlinkedBytecode = exports.assertUpgradeSafe = exports.getStorageLayout = exports.getContractNameAndRunValidation = exports.getContractVersion = exports.concatRunData = exports.isCurrentValidationData = exports.ValidationErrors = exports.withValidationDefaults = exports.validate = void 0;
|
|
3
|
+
exports.silenceWarnings = exports.UpgradeableContractErrorReport = exports.inferProxyKind = exports.isUpgradeSafe = exports.getErrors = exports.getUnlinkedBytecode = exports.assertUpgradeSafe = exports.getStorageLayout = exports.getContractNameAndRunValidation = exports.getContractVersion = exports.concatRunData = exports.isCurrentValidationData = exports.ContractSourceNotFoundError = exports.ValidationErrors = exports.withValidationDefaults = exports.validate = void 0;
|
|
4
4
|
var run_1 = require("./run");
|
|
5
5
|
Object.defineProperty(exports, "validate", { enumerable: true, get: function () { return run_1.validate; } });
|
|
6
6
|
var overrides_1 = require("./overrides");
|
|
7
7
|
Object.defineProperty(exports, "withValidationDefaults", { enumerable: true, get: function () { return overrides_1.withValidationDefaults; } });
|
|
8
8
|
var error_1 = require("./error");
|
|
9
9
|
Object.defineProperty(exports, "ValidationErrors", { enumerable: true, get: function () { return error_1.ValidationErrors; } });
|
|
10
|
+
Object.defineProperty(exports, "ContractSourceNotFoundError", { enumerable: true, get: function () { return error_1.ContractSourceNotFoundError; } });
|
|
10
11
|
var data_1 = require("./data");
|
|
11
12
|
Object.defineProperty(exports, "isCurrentValidationData", { enumerable: true, get: function () { return data_1.isCurrentValidationData; } });
|
|
12
13
|
Object.defineProperty(exports, "concatRunData", { enumerable: true, get: function () { return data_1.concatRunData; } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/validate/index.ts"],"names":[],"mappings":";;;AAAA,6BAAwE;AAA/D,+FAAA,QAAQ,OAAA;AACjB,yCAAsH;AAA5C,mHAAA,sBAAsB,OAAA;AAChG,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/validate/index.ts"],"names":[],"mappings":";;;AAAA,6BAAwE;AAA/D,+FAAA,QAAQ,OAAA;AACjB,yCAAsH;AAA5C,mHAAA,sBAAsB,OAAA;AAChG,iCAAwE;AAA/D,yGAAA,gBAAgB,OAAA;AAAE,oHAAA,2BAA2B,OAAA;AAEtD,+BAAuG;AAAvD,+GAAA,uBAAuB,OAAA;AAAE,qGAAA,aAAa,OAAA;AACtF,iCASiB;AARf,2GAAA,kBAAkB,OAAA;AAClB,wHAAA,+BAA+B,OAAA;AAC/B,yGAAA,gBAAgB,OAAA;AAChB,0GAAA,iBAAiB,OAAA;AACjB,4GAAA,mBAAmB,OAAA;AACnB,kGAAA,SAAS,OAAA;AACT,sGAAA,aAAa,OAAA;AACb,uGAAA,cAAc,OAAA;AAEhB,mCAA0D;AAAjD,wHAAA,8BAA8B,OAAA;AAEvC,0BAA0B;AAC1B,oCAA+C;AAAtC,sGAAA,eAAe,OAAA"}
|
package/dist/validate/query.js
CHANGED
|
@@ -64,7 +64,7 @@ function getContractNameAndRunValidation(data, version) {
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
if (fullContractName === undefined || runValidation === undefined) {
|
|
67
|
-
throw new
|
|
67
|
+
throw new error_1.ContractSourceNotFoundError();
|
|
68
68
|
}
|
|
69
69
|
return [fullContractName, runValidation];
|
|
70
70
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/validate/query.ts"],"names":[],"mappings":";;;AAAA,wCAAiD;AACjD,+BAA0E;AAE1E,4CAA8C;AAC9C,2CAAmE;AACnE,
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/validate/query.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openzeppelin/upgrades-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.26.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": "https://github.com/OpenZeppelin/openzeppelin-upgrades/tree/master/packages/core",
|
|
6
6
|
"license": "MIT",
|
|
@@ -34,14 +34,15 @@
|
|
|
34
34
|
"@ava/typescript": "^2.0.0",
|
|
35
35
|
"@nomiclabs/hardhat-ethers": "^2.0.2",
|
|
36
36
|
"@nomiclabs/hardhat-etherscan": "^3.0.0",
|
|
37
|
-
"@openzeppelin/contracts": "4.
|
|
38
|
-
"@openzeppelin/contracts-upgradeable": "4.
|
|
37
|
+
"@openzeppelin/contracts": "4.8.3",
|
|
38
|
+
"@openzeppelin/contracts-upgradeable": "4.8.3",
|
|
39
39
|
"@types/cbor": "^5.0.0",
|
|
40
40
|
"@types/debug": "^4.1.5",
|
|
41
41
|
"@types/mocha": "^7.0.2",
|
|
42
42
|
"@types/node": "^10.17.26",
|
|
43
43
|
"@types/proper-lockfile": "^4.1.1",
|
|
44
44
|
"@types/rimraf": "^3.0.0",
|
|
45
|
+
"@types/sinon": "^10.0.13",
|
|
45
46
|
"ava": "^5.0.0",
|
|
46
47
|
"dotenv": "^16.0.0",
|
|
47
48
|
"fgbg": "^0.1.4",
|
|
@@ -58,5 +59,5 @@
|
|
|
58
59
|
"proper-lockfile": "^4.1.1",
|
|
59
60
|
"solidity-ast": "^0.4.15"
|
|
60
61
|
},
|
|
61
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "6fb1e164bfd005e4e13212c5d6881dd37b602dce"
|
|
62
63
|
}
|
package/src/deployment.test.ts
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import test from 'ava';
|
|
2
2
|
import { promisify } from 'util';
|
|
3
3
|
import { TransactionMinedTimeout } from '.';
|
|
4
|
+
import sinon from 'sinon';
|
|
4
5
|
|
|
5
|
-
import { Deployment, resumeOrDeploy, waitAndValidateDeployment } from './deployment';
|
|
6
|
+
import { Deployment, RemoteDeploymentId, resumeOrDeploy, waitAndValidateDeployment } from './deployment';
|
|
6
7
|
import { stubProvider } from './stub-provider';
|
|
7
8
|
|
|
8
9
|
const sleep = promisify(setTimeout);
|
|
9
10
|
|
|
11
|
+
test.afterEach.always(() => {
|
|
12
|
+
sinon.restore();
|
|
13
|
+
});
|
|
14
|
+
|
|
10
15
|
test('deploys new contract', async t => {
|
|
11
16
|
const provider = stubProvider();
|
|
12
17
|
const deployment = await resumeOrDeploy(provider, undefined, provider.deploy);
|
|
@@ -121,3 +126,179 @@ test('tx mined timeout - params', async t => {
|
|
|
121
126
|
t.true(EXPECTED.test(e.message), e.message);
|
|
122
127
|
}
|
|
123
128
|
});
|
|
129
|
+
|
|
130
|
+
test('platform - resumes existing deployment id and replaces tx hash', async t => {
|
|
131
|
+
const provider = stubProvider();
|
|
132
|
+
|
|
133
|
+
const getDeploymentResponse = sinon.stub().returns({
|
|
134
|
+
status: 'submitted',
|
|
135
|
+
txHash: '0x2',
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
const first: Deployment & RemoteDeploymentId = await resumeOrDeploy(provider, undefined, provider.deployPending);
|
|
139
|
+
first.txHash = '0x1';
|
|
140
|
+
first.remoteDeploymentId = 'abc';
|
|
141
|
+
|
|
142
|
+
const second: Deployment & RemoteDeploymentId = await resumeOrDeploy(
|
|
143
|
+
provider,
|
|
144
|
+
first,
|
|
145
|
+
provider.deployPending,
|
|
146
|
+
undefined,
|
|
147
|
+
undefined,
|
|
148
|
+
undefined,
|
|
149
|
+
undefined,
|
|
150
|
+
getDeploymentResponse,
|
|
151
|
+
);
|
|
152
|
+
t.is(second.address, first.address);
|
|
153
|
+
t.is(second.remoteDeploymentId, first.remoteDeploymentId);
|
|
154
|
+
t.is(second.txHash, '0x2');
|
|
155
|
+
t.is(provider.deployCount, 1);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test('platform - resumes existing deployment id and uses tx hash', async t => {
|
|
159
|
+
const provider = stubProvider();
|
|
160
|
+
|
|
161
|
+
const getDeploymentResponse = sinon.stub().throws();
|
|
162
|
+
|
|
163
|
+
const first: Deployment & RemoteDeploymentId = await resumeOrDeploy(provider, undefined, provider.deploy);
|
|
164
|
+
// tx hash was mined
|
|
165
|
+
first.remoteDeploymentId = 'abc';
|
|
166
|
+
|
|
167
|
+
const second: Deployment & RemoteDeploymentId = await resumeOrDeploy(
|
|
168
|
+
provider,
|
|
169
|
+
first,
|
|
170
|
+
provider.deployPending,
|
|
171
|
+
undefined,
|
|
172
|
+
undefined,
|
|
173
|
+
undefined,
|
|
174
|
+
undefined,
|
|
175
|
+
getDeploymentResponse,
|
|
176
|
+
);
|
|
177
|
+
t.is(second.address, first.address);
|
|
178
|
+
t.is(second.txHash, first.txHash);
|
|
179
|
+
t.is(second.remoteDeploymentId, first.remoteDeploymentId);
|
|
180
|
+
t.is(provider.deployCount, 1);
|
|
181
|
+
|
|
182
|
+
await waitAndValidateDeployment(provider, second);
|
|
183
|
+
t.is(provider.getMethodCount('eth_getTransactionReceipt'), 1);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
test('platform - errors if tx and deployment id are not found', async t => {
|
|
187
|
+
const provider = stubProvider();
|
|
188
|
+
|
|
189
|
+
const getDeploymentResponse = sinon.stub().returns(undefined);
|
|
190
|
+
|
|
191
|
+
const fakeDeployment: Deployment & RemoteDeploymentId = {
|
|
192
|
+
address: '0x1aec6468218510f19bb19f52c4767996895ce711',
|
|
193
|
+
txHash: '0xc48e21ac9c051922f5ccf1b47b62000f567ef9bbc108d274848b44351a6872cb',
|
|
194
|
+
remoteDeploymentId: 'abc',
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
await t.throwsAsync(
|
|
198
|
+
resumeOrDeploy(
|
|
199
|
+
provider,
|
|
200
|
+
fakeDeployment,
|
|
201
|
+
provider.deploy,
|
|
202
|
+
undefined,
|
|
203
|
+
undefined,
|
|
204
|
+
undefined,
|
|
205
|
+
undefined,
|
|
206
|
+
getDeploymentResponse,
|
|
207
|
+
),
|
|
208
|
+
);
|
|
209
|
+
t.true(getDeploymentResponse.calledOnceWithExactly('abc'));
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
test('platform - waits for a deployment to be completed', async t => {
|
|
213
|
+
const timeout = Symbol('timeout');
|
|
214
|
+
const provider = stubProvider();
|
|
215
|
+
|
|
216
|
+
const deployment: Deployment & RemoteDeploymentId = await provider.deployPending();
|
|
217
|
+
deployment.remoteDeploymentId = 'abc';
|
|
218
|
+
provider.removeContract(deployment.address);
|
|
219
|
+
|
|
220
|
+
const getDeploymentResponse = sinon.stub();
|
|
221
|
+
getDeploymentResponse.onCall(0).returns({
|
|
222
|
+
status: 'submitted',
|
|
223
|
+
txHash: deployment.txHash,
|
|
224
|
+
});
|
|
225
|
+
getDeploymentResponse.onCall(1).returns({
|
|
226
|
+
status: 'completed',
|
|
227
|
+
txHash: deployment.txHash,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// checks that status is completed but code not at address yet
|
|
231
|
+
const result = await Promise.race([
|
|
232
|
+
waitAndValidateDeployment(provider, deployment, undefined, { pollingInterval: 0 }, getDeploymentResponse),
|
|
233
|
+
sleep(100).then(() => timeout),
|
|
234
|
+
]);
|
|
235
|
+
t.is(result, timeout);
|
|
236
|
+
t.is(getDeploymentResponse.callCount, 2);
|
|
237
|
+
|
|
238
|
+
// code mined to address
|
|
239
|
+
provider.addContract(deployment.address);
|
|
240
|
+
provider.mine();
|
|
241
|
+
|
|
242
|
+
// checks that the code is at address
|
|
243
|
+
await waitAndValidateDeployment(provider, deployment, undefined, { pollingInterval: 0 }, getDeploymentResponse);
|
|
244
|
+
|
|
245
|
+
t.is(getDeploymentResponse.callCount, 2);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
test('platform - fails deployment fast if deployment id failed', async t => {
|
|
249
|
+
const provider = stubProvider();
|
|
250
|
+
|
|
251
|
+
const getDeploymentResponse = sinon.stub().returns({
|
|
252
|
+
status: 'failed',
|
|
253
|
+
txHash: '0x2',
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
const fakeDeployment: Deployment & RemoteDeploymentId = {
|
|
257
|
+
address: '0x1aec6468218510f19bb19f52c4767996895ce711',
|
|
258
|
+
txHash: '0xc48e21ac9c051922f5ccf1b47b62000f567ef9bbc108d274848b44351a6872cb',
|
|
259
|
+
remoteDeploymentId: 'abc',
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
const deployment = await resumeOrDeploy(
|
|
263
|
+
provider,
|
|
264
|
+
fakeDeployment,
|
|
265
|
+
provider.deployPending,
|
|
266
|
+
undefined,
|
|
267
|
+
undefined,
|
|
268
|
+
undefined,
|
|
269
|
+
undefined,
|
|
270
|
+
getDeploymentResponse,
|
|
271
|
+
);
|
|
272
|
+
t.true(getDeploymentResponse.calledOnceWithExactly('abc'));
|
|
273
|
+
await t.throwsAsync(waitAndValidateDeployment(provider, deployment, undefined, undefined, getDeploymentResponse));
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
test('platform - deployment id timeout - no params', async t => {
|
|
277
|
+
const fakeDeployment: Deployment & RemoteDeploymentId = {
|
|
278
|
+
address: '0x1aec6468218510f19bb19f52c4767996895ce711',
|
|
279
|
+
txHash: '0xc48e21ac9c051922f5ccf1b47b62000f567ef9bbc108d274848b44351a6872cb',
|
|
280
|
+
remoteDeploymentId: 'abc',
|
|
281
|
+
};
|
|
282
|
+
try {
|
|
283
|
+
throw new TransactionMinedTimeout(fakeDeployment);
|
|
284
|
+
} catch (e: any) {
|
|
285
|
+
const EXPECTED =
|
|
286
|
+
/Timed out waiting for contract deployment to address \S+ with deployment id abc\n\nRun the function again to continue waiting for the transaction confirmation./;
|
|
287
|
+
t.true(EXPECTED.test(e.message), e.message);
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
test('platform - deployment id timeout - params', async t => {
|
|
292
|
+
const fakeDeployment: Deployment & RemoteDeploymentId = {
|
|
293
|
+
address: '0x1aec6468218510f19bb19f52c4767996895ce711',
|
|
294
|
+
txHash: '0xc48e21ac9c051922f5ccf1b47b62000f567ef9bbc108d274848b44351a6872cb',
|
|
295
|
+
remoteDeploymentId: 'abc',
|
|
296
|
+
};
|
|
297
|
+
try {
|
|
298
|
+
throw new TransactionMinedTimeout(fakeDeployment, 'implementation', true);
|
|
299
|
+
} catch (e: any) {
|
|
300
|
+
const EXPECTED =
|
|
301
|
+
/Timed out waiting for implementation contract deployment to address \S+ with deployment id abc+\n\nRun the function again to continue waiting for the transaction confirmation. If the problem persists, adjust the polling parameters with the timeout and pollingInterval options./;
|
|
302
|
+
t.true(EXPECTED.test(e.message), e.message);
|
|
303
|
+
}
|
|
304
|
+
});
|
package/src/deployment.ts
CHANGED
|
@@ -22,6 +22,13 @@ export interface Deployment {
|
|
|
22
22
|
txHash?: string;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
export interface RemoteDeploymentId {
|
|
26
|
+
remoteDeploymentId?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Options for deploying an implementation contract, proxy admin contract, or remote deployment.
|
|
31
|
+
*/
|
|
25
32
|
export interface DeployOpts {
|
|
26
33
|
/**
|
|
27
34
|
* Timeout in milliseconds to wait for the transaction confirmation when deploying an implementation contract or proxy admin contract. Use `0` to wait indefinitely.
|
|
@@ -50,6 +57,7 @@ export interface DeployOpts {
|
|
|
50
57
|
* If not provided, invalid deployments will not be deleted in a dev network (which is not a problem if merge is false,
|
|
51
58
|
* since it will be overwritten with the new deployment).
|
|
52
59
|
* @param merge whether the cached deployment is intended to be merged with the new deployment. Defaults to false.
|
|
60
|
+
* @param getRemoteDeployment a function to get the remote deployment status by id. If the deployment id is not found, returns undefined.
|
|
53
61
|
* @returns the cached deployment if it should be used, otherwise the new deployment from the deploy function
|
|
54
62
|
* @throws {InvalidDeployment} if the cached deployment is invalid and we are not on a dev network
|
|
55
63
|
*/
|
|
@@ -61,8 +69,9 @@ export async function resumeOrDeploy<T extends Deployment, U extends T = T>(
|
|
|
61
69
|
opts?: DeployOpts,
|
|
62
70
|
deployment?: ManifestField<T>,
|
|
63
71
|
merge?: boolean,
|
|
72
|
+
getRemoteDeployment?: (remoteDeploymentId: string) => Promise<RemoteDeployment | undefined>,
|
|
64
73
|
): Promise<T | U> {
|
|
65
|
-
const validated = await validateCached(cached, provider, type, opts, deployment, merge);
|
|
74
|
+
const validated = await validateCached(cached, provider, type, opts, deployment, merge, getRemoteDeployment);
|
|
66
75
|
if (validated === undefined || merge) {
|
|
67
76
|
const deployment = await deploy();
|
|
68
77
|
debug('initiated deployment', 'transaction hash:', deployment.txHash, 'merge:', merge);
|
|
@@ -79,10 +88,11 @@ async function validateCached<T extends Deployment>(
|
|
|
79
88
|
opts?: DeployOpts,
|
|
80
89
|
deployment?: ManifestField<T>,
|
|
81
90
|
merge?: boolean,
|
|
91
|
+
getRemoteDeployment?: (remoteDeploymentId: string) => Promise<RemoteDeployment | undefined>,
|
|
82
92
|
): Promise<T | undefined> {
|
|
83
93
|
if (cached !== undefined) {
|
|
84
94
|
try {
|
|
85
|
-
await validateStoredDeployment(cached, provider, type, opts, merge);
|
|
95
|
+
return await validateStoredDeployment(cached, provider, type, opts, merge, getRemoteDeployment);
|
|
86
96
|
} catch (e) {
|
|
87
97
|
if (e instanceof InvalidDeployment && (await isDevelopmentNetwork(provider))) {
|
|
88
98
|
debug('ignoring invalid deployment in development network', e.deployment.address);
|
|
@@ -94,50 +104,79 @@ async function validateCached<T extends Deployment>(
|
|
|
94
104
|
throw e;
|
|
95
105
|
}
|
|
96
106
|
}
|
|
107
|
+
} else {
|
|
108
|
+
return undefined;
|
|
97
109
|
}
|
|
98
|
-
return cached;
|
|
99
110
|
}
|
|
100
111
|
|
|
101
|
-
async function validateStoredDeployment<T extends Deployment>(
|
|
112
|
+
async function validateStoredDeployment<T extends Deployment & RemoteDeploymentId>(
|
|
102
113
|
stored: T,
|
|
103
114
|
provider: EthereumProvider,
|
|
104
115
|
type?: string,
|
|
105
116
|
opts?: DeployOpts,
|
|
106
117
|
merge?: boolean,
|
|
107
|
-
)
|
|
108
|
-
|
|
118
|
+
getRemoteDeployment?: (remoteDeploymentId: string) => Promise<RemoteDeployment | undefined>,
|
|
119
|
+
): Promise<T> {
|
|
120
|
+
const { txHash, remoteDeploymentId } = stored;
|
|
121
|
+
let deployment = stored;
|
|
122
|
+
|
|
109
123
|
if (txHash !== undefined) {
|
|
110
124
|
// If there is a deployment with txHash stored, we look its transaction up. If the
|
|
111
125
|
// transaction is found, the deployment is reused.
|
|
112
126
|
debug('found previous deployment', txHash);
|
|
113
127
|
const tx = await getTransactionByHash(provider, txHash);
|
|
128
|
+
let foundDeployment = undefined;
|
|
114
129
|
if (tx !== null) {
|
|
115
|
-
|
|
130
|
+
foundDeployment = txHash;
|
|
131
|
+
} else if (remoteDeploymentId !== undefined && getRemoteDeployment !== undefined) {
|
|
132
|
+
// If the transaction is not found, try checking the deployment id since the transaction may have been replaced
|
|
133
|
+
const response = await getRemoteDeployment(remoteDeploymentId);
|
|
134
|
+
if (response !== undefined) {
|
|
135
|
+
foundDeployment = remoteDeploymentId;
|
|
136
|
+
|
|
137
|
+
// update the stored tx hash
|
|
138
|
+
deployment = { ...stored, txHash: response.txHash };
|
|
139
|
+
debug('updating previous deployment to tx hash ', response.txHash);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (foundDeployment) {
|
|
144
|
+
debug('resuming previous deployment', foundDeployment);
|
|
116
145
|
if (merge) {
|
|
117
146
|
// If merging, wait for the existing deployment to be mined
|
|
118
|
-
waitAndValidateDeployment(provider,
|
|
147
|
+
waitAndValidateDeployment(provider, deployment, type, opts, getRemoteDeployment);
|
|
119
148
|
}
|
|
120
149
|
} else {
|
|
121
150
|
// If the transaction is not found we throw an error, except if we're in
|
|
122
151
|
// a development network then we simply silently redeploy.
|
|
123
152
|
// This error should be caught by the caller to determine if we're in a dev network.
|
|
124
|
-
throw new InvalidDeployment(
|
|
153
|
+
throw new InvalidDeployment(deployment);
|
|
125
154
|
}
|
|
126
155
|
} else {
|
|
127
|
-
const existingBytecode = await getCode(provider,
|
|
156
|
+
const existingBytecode = await getCode(provider, deployment.address);
|
|
128
157
|
if (isEmpty(existingBytecode)) {
|
|
129
|
-
throw new InvalidDeployment(
|
|
158
|
+
throw new InvalidDeployment(deployment);
|
|
130
159
|
}
|
|
131
160
|
}
|
|
161
|
+
return deployment;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* A deployment that is performed remotely, which has a status and transaction hash.
|
|
166
|
+
*/
|
|
167
|
+
export interface RemoteDeployment {
|
|
168
|
+
status: 'completed' | 'failed' | 'submitted';
|
|
169
|
+
txHash: string;
|
|
132
170
|
}
|
|
133
171
|
|
|
134
172
|
export async function waitAndValidateDeployment(
|
|
135
173
|
provider: EthereumProvider,
|
|
136
|
-
deployment: Deployment,
|
|
174
|
+
deployment: Deployment & RemoteDeploymentId,
|
|
137
175
|
type?: string,
|
|
138
176
|
opts?: DeployOpts,
|
|
177
|
+
getRemoteDeployment?: (remoteDeploymentId: string) => Promise<RemoteDeployment | undefined>,
|
|
139
178
|
): Promise<void> {
|
|
140
|
-
const { txHash, address } = deployment;
|
|
179
|
+
const { txHash, address, remoteDeploymentId } = deployment;
|
|
141
180
|
|
|
142
181
|
// Poll for 60 seconds with a 5 second poll interval by default.
|
|
143
182
|
const pollTimeout = opts?.timeout ?? 60e3;
|
|
@@ -145,7 +184,38 @@ export async function waitAndValidateDeployment(
|
|
|
145
184
|
|
|
146
185
|
debug('polling timeout', pollTimeout, 'polling interval', pollInterval);
|
|
147
186
|
|
|
148
|
-
|
|
187
|
+
let foundCode = false;
|
|
188
|
+
|
|
189
|
+
if (remoteDeploymentId !== undefined && getRemoteDeployment !== undefined) {
|
|
190
|
+
const startTime = Date.now();
|
|
191
|
+
|
|
192
|
+
// eslint-disable-next-line no-constant-condition
|
|
193
|
+
while (true) {
|
|
194
|
+
if (await hasCode(provider, address)) {
|
|
195
|
+
debug('code in target address found', address);
|
|
196
|
+
foundCode = true;
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const completed = await isDeploymentCompleted(
|
|
201
|
+
address,
|
|
202
|
+
remoteDeploymentId,
|
|
203
|
+
await getRemoteDeployment(remoteDeploymentId),
|
|
204
|
+
);
|
|
205
|
+
if (completed) {
|
|
206
|
+
break;
|
|
207
|
+
} else {
|
|
208
|
+
await sleep(pollInterval);
|
|
209
|
+
}
|
|
210
|
+
if (pollTimeout != 0) {
|
|
211
|
+
const elapsedTime = Date.now() - startTime;
|
|
212
|
+
if (elapsedTime >= pollTimeout) {
|
|
213
|
+
// A timeout is NOT an InvalidDeployment
|
|
214
|
+
throw new TransactionMinedTimeout(deployment, type, !!opts);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
} else if (txHash !== undefined) {
|
|
149
219
|
const startTime = Date.now();
|
|
150
220
|
|
|
151
221
|
// eslint-disable-next-line no-constant-condition
|
|
@@ -172,24 +242,28 @@ export async function waitAndValidateDeployment(
|
|
|
172
242
|
}
|
|
173
243
|
}
|
|
174
244
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
245
|
+
if (!foundCode) {
|
|
246
|
+
debug('verifying code in target address', address);
|
|
247
|
+
const startTime = Date.now();
|
|
248
|
+
while (!(await hasCode(provider, address))) {
|
|
249
|
+
const elapsedTime = Date.now() - startTime;
|
|
250
|
+
if (elapsedTime >= pollTimeout || txHash === undefined) {
|
|
251
|
+
throw new InvalidDeployment(deployment);
|
|
252
|
+
}
|
|
253
|
+
await sleep(pollInterval);
|
|
181
254
|
}
|
|
182
|
-
|
|
255
|
+
debug('code in target address found', address);
|
|
183
256
|
}
|
|
184
|
-
debug('code in target address found', address);
|
|
185
257
|
}
|
|
186
258
|
|
|
187
259
|
export class TransactionMinedTimeout extends UpgradesError {
|
|
188
|
-
constructor(readonly deployment: Deployment, type?: string, configurableTimeout?: boolean) {
|
|
260
|
+
constructor(readonly deployment: Deployment & RemoteDeploymentId, type?: string, configurableTimeout?: boolean) {
|
|
189
261
|
super(
|
|
190
|
-
`Timed out waiting for ${type ? type + ' ' : ''}contract deployment to address ${
|
|
191
|
-
deployment.
|
|
192
|
-
|
|
262
|
+
`Timed out waiting for ${type ? type + ' ' : ''}contract deployment to address ${deployment.address} with ${
|
|
263
|
+
deployment.remoteDeploymentId
|
|
264
|
+
? `deployment id ${deployment.remoteDeploymentId}`
|
|
265
|
+
: `transaction ${deployment.txHash}`
|
|
266
|
+
}`,
|
|
193
267
|
() =>
|
|
194
268
|
'Run the function again to continue waiting for the transaction confirmation.' +
|
|
195
269
|
(configurableTimeout
|
|
@@ -217,3 +291,37 @@ export class InvalidDeployment extends Error {
|
|
|
217
291
|
return msg;
|
|
218
292
|
}
|
|
219
293
|
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Checks if the deployment id is completed.
|
|
297
|
+
*
|
|
298
|
+
* @param address The expected address of the deployment.
|
|
299
|
+
* @param remoteDeploymentId The deployment id.
|
|
300
|
+
* @param remoteDeploymentResponse The remote deployment response corresponding to the given id.
|
|
301
|
+
* @returns true if the deployment id is completed, false otherwise.
|
|
302
|
+
* @throws {InvalidDeployment} if the deployment id failed.
|
|
303
|
+
*/
|
|
304
|
+
export async function isDeploymentCompleted(
|
|
305
|
+
address: string,
|
|
306
|
+
remoteDeploymentId: string,
|
|
307
|
+
remoteDeploymentResponse: RemoteDeployment | undefined,
|
|
308
|
+
): Promise<boolean> {
|
|
309
|
+
debug('verifying deployment id', remoteDeploymentId);
|
|
310
|
+
if (remoteDeploymentResponse === undefined) {
|
|
311
|
+
throw new Error(`Could not find remote deployment with id ${remoteDeploymentId}`);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const status = remoteDeploymentResponse.status;
|
|
315
|
+
if (status === 'completed') {
|
|
316
|
+
debug('succeeded verifying deployment id completed', remoteDeploymentId);
|
|
317
|
+
return true;
|
|
318
|
+
} else if (status === 'failed') {
|
|
319
|
+
debug(`deployment id ${remoteDeploymentId} failed with tx hash ${remoteDeploymentResponse.txHash}`);
|
|
320
|
+
throw new InvalidDeployment({ address, txHash: remoteDeploymentResponse.txHash });
|
|
321
|
+
} else if (status === 'submitted') {
|
|
322
|
+
debug('waiting for deployment id to be completed', remoteDeploymentId);
|
|
323
|
+
return false;
|
|
324
|
+
} else {
|
|
325
|
+
throw new Error(`Broken invariant: Unrecognized status ${status} for deployment id ${remoteDeploymentId}`);
|
|
326
|
+
}
|
|
327
|
+
}
|
package/src/impl-store.test.ts
CHANGED
|
@@ -5,8 +5,9 @@ import rimrafAsync from 'rimraf';
|
|
|
5
5
|
import util from 'util';
|
|
6
6
|
import path from 'path';
|
|
7
7
|
import os from 'os';
|
|
8
|
+
import sinon from 'sinon';
|
|
8
9
|
|
|
9
|
-
import { fetchOrDeploy, mergeAddresses } from './impl-store';
|
|
10
|
+
import { fetchOrDeploy, fetchOrDeployGetDeployment, mergeAddresses } from './impl-store';
|
|
10
11
|
import { getVersion } from './version';
|
|
11
12
|
import { stubProvider } from './stub-provider';
|
|
12
13
|
import { ImplDeployment } from './manifest';
|
|
@@ -89,3 +90,53 @@ test('merge all addresses', async t => {
|
|
|
89
90
|
function unorderedEqual(arr1: string[], arr2: string[]) {
|
|
90
91
|
return arr1.every(i => arr2.includes(i)) && arr2.every(i => arr1.includes(i));
|
|
91
92
|
}
|
|
93
|
+
|
|
94
|
+
test('platform - replace tx hash for deployment', async t => {
|
|
95
|
+
const provider = stubProvider();
|
|
96
|
+
|
|
97
|
+
// create a pending deployment with id
|
|
98
|
+
const fakeDeploy = await provider.deployPending();
|
|
99
|
+
provider.removeContract(fakeDeploy.address);
|
|
100
|
+
async function fakeDeployWithId() {
|
|
101
|
+
return {
|
|
102
|
+
...fakeDeploy,
|
|
103
|
+
txHash: '0x1',
|
|
104
|
+
remoteDeploymentId: 'abc',
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const getDeploymentResponse1 = sinon.stub().returns({
|
|
109
|
+
status: 'submitted',
|
|
110
|
+
txHash: '0x1',
|
|
111
|
+
});
|
|
112
|
+
// let it timeout
|
|
113
|
+
await t.throwsAsync(
|
|
114
|
+
fetchOrDeployGetDeployment(
|
|
115
|
+
version1,
|
|
116
|
+
provider,
|
|
117
|
+
fakeDeployWithId,
|
|
118
|
+
{ timeout: 1, pollingInterval: 0 },
|
|
119
|
+
undefined,
|
|
120
|
+
getDeploymentResponse1,
|
|
121
|
+
),
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
// make the contract code exist
|
|
125
|
+
provider.addContract(fakeDeploy.address);
|
|
126
|
+
|
|
127
|
+
// simulate a changed tx hash
|
|
128
|
+
const getDeploymentResponse2 = sinon.stub().returns({
|
|
129
|
+
status: 'completed',
|
|
130
|
+
txHash: '0x2',
|
|
131
|
+
});
|
|
132
|
+
const deployment = await fetchOrDeployGetDeployment(
|
|
133
|
+
version1,
|
|
134
|
+
provider,
|
|
135
|
+
fakeDeployWithId,
|
|
136
|
+
{ timeout: 1, pollingInterval: 0 },
|
|
137
|
+
undefined,
|
|
138
|
+
getDeploymentResponse2,
|
|
139
|
+
);
|
|
140
|
+
t.is(deployment.address, fakeDeploy.address);
|
|
141
|
+
t.is(deployment.txHash, '0x2');
|
|
142
|
+
});
|