upgradeable_proxy.spec.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. // SPDX-License-Identifier: Apache-2.0
  2. import expect from 'expect';
  3. import { weight, createConnection, deploy, transaction, aliceKeypair, query, } from './index';
  4. import { ContractPromise } from '@polkadot/api-contract';
  5. import { ApiPromise } from '@polkadot/api';
  6. import { KeyringPair } from '@polkadot/keyring/types';
  7. import { DecodedEvent } from '@polkadot/api-contract/types';
  8. import { AccountId, ContractSelector } from '@polkadot/types/interfaces';
  9. interface IMsg {
  10. identifier: string,
  11. selector: any,
  12. };
  13. describe('Deploy the upgradable proxy and implementations; expect the upgrade mechanism to work', () => {
  14. // Helper: Upgrade implementation and execute a constructor that takes no arguments
  15. async function upgrade_version(impl: AccountId, input: any) {
  16. const params = [impl, input];
  17. const gasLimit = await weight(conn, proxy, 'upgradeToAndCall', params);
  18. let result: any = await transaction(proxy.tx.upgradeToAndCall({ gasLimit }, ...params), aliceKeypair());
  19. let events: DecodedEvent[] = result.contractEvents;
  20. console.log(events);
  21. expect(events.length).toEqual(1);
  22. expect(events[0].event.identifier).toBe("UpgradeableProxy::Upgraded");
  23. expect(events[0].args.map(a => a.toJSON())[0]).toEqual(params[0].toJSON());
  24. }
  25. let conn: ApiPromise;
  26. let alice: KeyringPair;
  27. let proxy: ContractPromise;
  28. let counter: ContractPromise;
  29. before(async function () {
  30. alice = aliceKeypair();
  31. conn = await createConnection();
  32. const proxy_deployment = await deploy(conn, alice, 'UpgradeableProxy.contract', 0n);
  33. proxy = new ContractPromise(conn, proxy_deployment.abi, proxy_deployment.address);
  34. // Pretend the proxy contract to be implementation V1
  35. const implV1 = await deploy(conn, alice, 'UpgradeableImplV1.contract', 0n);
  36. const selector = implV1.abi.messages.find((m: IMsg) => m.identifier === "inc").selector;
  37. await upgrade_version(implV1.address, selector);
  38. counter = new ContractPromise(conn, implV1.abi, proxy_deployment.address);
  39. const count = await query(conn, alice, counter, "count");
  40. expect(BigInt(count.output?.toString() ?? "")).toStrictEqual(1n);
  41. });
  42. after(async function () {
  43. await conn.disconnect();
  44. });
  45. it('Tests implementation and upgrading', async function () {
  46. // Test implementation V1
  47. let gasLimit = await weight(conn, counter, 'inc', []);
  48. await transaction(counter.tx.inc({ gasLimit }), alice);
  49. await transaction(counter.tx.inc({ gasLimit }), alice);
  50. let count = await query(conn, alice, counter, "count");
  51. expect(BigInt(count.output?.toString() ?? "")).toStrictEqual(3n);
  52. // Upgrade to implementation V2
  53. const implV2 = await deploy(conn, alice, 'UpgradeableImplV2.contract', 0n);
  54. const selector = implV2.abi.messages.find((m: IMsg) => m.identifier === "setVersion").selector;
  55. await upgrade_version(implV2.address, selector);
  56. counter = new ContractPromise(conn, implV2.abi, proxy.address);
  57. // Test implementation V2
  58. count = await query(conn, alice, counter, "count");
  59. expect(BigInt(count.output?.toString() ?? "")).toStrictEqual(3n);
  60. gasLimit = await weight(conn, counter, 'dec', []);
  61. await transaction(counter.tx.dec({ gasLimit }), alice);
  62. count = await query(conn, alice, counter, "count");
  63. expect(BigInt(count.output?.toString() ?? "")).toStrictEqual(2n);
  64. const version = await query(conn, alice, counter, "version");
  65. expect(version.output?.toString()).toStrictEqual("v2");
  66. });
  67. });