// SPDX-License-Identifier: Apache-2.0 import expect from 'expect'; import { weight, createConnection, deploy, transaction, aliceKeypair, query, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; import { ApiPromise } from '@polkadot/api'; import { KeyringPair } from '@polkadot/keyring/types'; import { DecodedEvent } from '@polkadot/api-contract/types'; import { AccountId, ContractSelector } from '@polkadot/types/interfaces'; interface IMsg { identifier: string, selector: any, }; describe('Deploy the upgradable proxy and implementations; expect the upgrade mechanism to work', () => { // Helper: Upgrade implementation and execute a constructor that takes no arguments async function upgrade_version(impl: AccountId, input: any) { const params = [impl, input]; const gasLimit = await weight(conn, proxy, 'upgradeToAndCall', params); let result: any = await transaction(proxy.tx.upgradeToAndCall({ gasLimit }, ...params), aliceKeypair()); let events: DecodedEvent[] = result.contractEvents; console.log(events); expect(events.length).toEqual(1); expect(events[0].event.identifier).toBe("UpgradeableProxy::Upgraded"); expect(events[0].args.map(a => a.toJSON())[0]).toEqual(params[0].toJSON()); } let conn: ApiPromise; let alice: KeyringPair; let proxy: ContractPromise; let counter: ContractPromise; before(async function () { alice = aliceKeypair(); conn = await createConnection(); const proxy_deployment = await deploy(conn, alice, 'UpgradeableProxy.contract', 0n); proxy = new ContractPromise(conn, proxy_deployment.abi, proxy_deployment.address); // Pretend the proxy contract to be implementation V1 const implV1 = await deploy(conn, alice, 'UpgradeableImplV1.contract', 0n); const selector = implV1.abi.messages.find((m: IMsg) => m.identifier === "inc").selector; await upgrade_version(implV1.address, selector); counter = new ContractPromise(conn, implV1.abi, proxy_deployment.address); const count = await query(conn, alice, counter, "count"); expect(BigInt(count.output?.toString() ?? "")).toStrictEqual(1n); }); after(async function () { await conn.disconnect(); }); it('Tests implementation and upgrading', async function () { // Test implementation V1 let gasLimit = await weight(conn, counter, 'inc', []); await transaction(counter.tx.inc({ gasLimit }), alice); await transaction(counter.tx.inc({ gasLimit }), alice); let count = await query(conn, alice, counter, "count"); expect(BigInt(count.output?.toString() ?? "")).toStrictEqual(3n); // Upgrade to implementation V2 const implV2 = await deploy(conn, alice, 'UpgradeableImplV2.contract', 0n); const selector = implV2.abi.messages.find((m: IMsg) => m.identifier === "setVersion").selector; await upgrade_version(implV2.address, selector); counter = new ContractPromise(conn, implV2.abi, proxy.address); // Test implementation V2 count = await query(conn, alice, counter, "count"); expect(BigInt(count.output?.toString() ?? "")).toStrictEqual(3n); gasLimit = await weight(conn, counter, 'dec', []); await transaction(counter.tx.dec({ gasLimit }), alice); count = await query(conn, alice, counter, "count"); expect(BigInt(count.output?.toString() ?? "")).toStrictEqual(2n); const version = await query(conn, alice, counter, "version"); expect(version.output?.toString()).toStrictEqual("v2"); }); });