upgradeable_proxy.spec.ts 3.4 KB

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