git.delta.rocks / unique-network / refs/commits / 301e4e6b0f10

difftreelog

Save contract state between upgrades

Grigoriy Simonov2022-09-30parent: #7aba0b5.patch.diff
in: master

1 file changed

modifiedtests/src/eth/proxyContract.test.tsdiffbeforeafterboth
before · tests/src/eth/proxyContract.test.ts
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {IKeyringPair} from '@polkadot/types/types';1819import {itEth, expect, usingEthPlaygrounds, EthUniqueHelper} from './util/playgrounds';2021describe('EVM payable contracts', () => {22  let donor: IKeyringPair;2324  before(async function() {25    await usingEthPlaygrounds(async (_, privateKey) => {26      donor = privateKey('//Alice');27    });28  });2930  itEth('Update proxy contract', async({helper}) => {31    const deployer = await helper.eth.createAccountWithBalance(donor);32    const proxyContract = await deployProxyContract(helper, deployer);33    const realContractV1 = await deployRealContractV1(helper, deployer);34    await proxyContract.methods.updateVersion(realContractV1.options.address).send();35    await proxyContract.methods.flip().send();36    await proxyContract.methods.flip().send();37    await proxyContract.methods.flip().send();38    const value1 = await proxyContract.methods.getValue().call();39    const flipCount1 = await proxyContract.methods.getFlipCount().call();40    expect(value1).to.be.equal(true);41    expect(flipCount1).to.be.equal('3');42    const realContractV2 = await deployRealContractV2(helper, deployer);43    await proxyContract.methods.updateVersion(realContractV2.options.address).send();44    await proxyContract.methods.flip().send();45    await proxyContract.methods.flip().send();46    const value2 = await proxyContract.methods.getValue().call();47    const flipCount2 = await proxyContract.methods.getFlipCount().call();48    expect(value2).to.be.equal(true);49    expect(flipCount2).to.be.equal('1');50  });5152  async function deployProxyContract(helper: EthUniqueHelper, deployer: string) {53    return await helper.ethContract.deployByCode(deployer, 'ProxyContract', `54      // SPDX-License-Identifier: UNLICENSED55      pragma solidity ^0.8.6;56      57      contract ProxyContract {58        address realContract;59        event NewEvent(uint data);60        receive() external payable {}61        constructor() {}62        function updateVersion(address newContractAddress) external {63          realContract = newContractAddress;64        }65        function flip() external {66          RealContract(realContract).flip();67        }68        function getValue() external view returns (bool) {69          return RealContract(realContract).getValue();70        }71        function getFlipCount() external view returns (uint) {72            return RealContract(realContract).getFlipCount();73        }74      }75      76      interface RealContract {77        function flip() external;78        function getValue() external view returns (bool);79        function getFlipCount() external view returns (uint);80      }`);81  }8283  async function deployRealContractV1(helper: EthUniqueHelper, deployer: string) {84    return await helper.ethContract.deployByCode(deployer, 'RealContractV1', `85      // SPDX-License-Identifier: UNLICENSED86      pragma solidity ^0.8.6;87  88      contract RealContractV1 {89        bool value = false;90        uint flipCount = 0;91        function flip() external {92          value = !value;93          flipCount++;94        }95        function getValue() external view returns (bool) {96          return value;97        }98        function getFlipCount() external view returns (uint) {99          return flipCount;100        }101      }`);102  }103104  async function deployRealContractV2(helper: EthUniqueHelper, deployer: string) {105    return await helper.ethContract.deployByCode(deployer, 'RealContractV2', `106      // SPDX-License-Identifier: UNLICENSED107      pragma solidity ^0.8.6;108  109      contract RealContractV2 {110        bool value = false;111        uint flipCount = 10;112        function flip() external {113          value = !value;114          flipCount--;115        }116        function getValue() external view returns (bool) {117          return value;118        }119        function getFlipCount() external view returns (uint) {120          return flipCount;121        }122      }`);123  }124});
after · tests/src/eth/proxyContract.test.ts
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {IKeyringPair} from '@polkadot/types/types';18import {GAS_ARGS} from './util/helpers';1920import {itEth, expect, usingEthPlaygrounds, EthUniqueHelper} from './util/playgrounds';2122describe('EVM payable contracts', () => {23  let donor: IKeyringPair;2425  before(async function() {26    await usingEthPlaygrounds(async (_, privateKey) => {27      donor = privateKey('//Alice');28    });29  });3031  itEth('Update proxy contract', async({helper}) => {32    const deployer = await helper.eth.createAccountWithBalance(donor);33    const caller = await helper.eth.createAccountWithBalance(donor);34    const proxyContract = await deployProxyContract(helper, deployer);35    const realContractV1 = await deployRealContractV1(helper, deployer);36    const realContractV1proxy = new helper.web3!.eth.Contract(realContractV1.options.jsonInterface, proxyContract.options.address, {from: caller, ...GAS_ARGS});37    await proxyContract.methods.updateVersion(realContractV1.options.address).send();38    39    await realContractV1proxy.methods.flip().send();40    await realContractV1proxy.methods.flip().send();41    await realContractV1proxy.methods.flip().send();42    const value1 = await realContractV1proxy.methods.getValue().call();43    const flipCount1 = await realContractV1proxy.methods.getFlipCount().call();44    expect(flipCount1).to.be.equal('3');45    expect(value1).to.be.equal(true);46    const realContractV2 = await deployRealContractV2(helper, deployer);47    const realContractV2proxy = new helper.web3!.eth.Contract(realContractV2.options.jsonInterface, proxyContract.options.address, {from: caller, ...GAS_ARGS});48    await proxyContract.methods.updateVersion(realContractV2.options.address).send();49    await realContractV2proxy.methods.flip().send();50    await realContractV2proxy.methods.flip().send();51    const value2 = await realContractV2proxy.methods.getValue().call();52    const flipCount2 = await realContractV2proxy.methods.getFlipCount().call();53    expect(value2).to.be.equal(true);54    expect(flipCount2).to.be.equal('1');55  });5657  async function deployProxyContract(helper: EthUniqueHelper, deployer: string) {58    return await helper.ethContract.deployByCode(deployer, 'ProxyContract', `59      // SPDX-License-Identifier: UNLICENSED60      pragma solidity ^0.8.6;61      62      contract ProxyContract {63        event NewEvent(uint data);64        receive() external payable {}65        bytes32 private constant implementationSlot =  bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1);66        constructor() {}67        function updateVersion(address newContractAddress) external {68          bytes32 slot = implementationSlot;69          assembly {70            sstore(slot, newContractAddress)71          }72        }73        fallback() external {74          bytes32 slot = implementationSlot;75          assembly {76            let ptr := mload(0x40)77            let contractAddress := sload(slot)78            79            calldatacopy(ptr, 0, calldatasize())80            81            let result := delegatecall(gas(), contractAddress, ptr, calldatasize(), 0, 0)82            let size := returndatasize()83            84            returndatacopy(ptr, 0, size)85            86            switch result87            case 0 { revert(ptr, size) }88            default { return(ptr, size) }89          }90        }91      }92      93      interface RealContract {94        function flip() external;95        function getValue() external view returns (bool);96        function getFlipCount() external view returns (uint);97      }`);98  }99100  async function deployRealContractV1(helper: EthUniqueHelper, deployer: string) {101    return await helper.ethContract.deployByCode(deployer, 'RealContractV1', `102      // SPDX-License-Identifier: UNLICENSED103      pragma solidity ^0.8.6;104  105      contract RealContractV1 {106        bool value = false;107        uint flipCount = 0;108        function flip() external {109          value = !value;110          flipCount++;111        }112        function getValue() external view returns (bool) {113          return value;114        }115        function getFlipCount() external view returns (uint) {116          return flipCount;117        }118      }`);119  }120121  async function deployRealContractV2(helper: EthUniqueHelper, deployer: string) {122    return await helper.ethContract.deployByCode(deployer, 'RealContractV2', `123      // SPDX-License-Identifier: UNLICENSED124      pragma solidity ^0.8.6;125  126      contract RealContractV2 {127        bool value = false;128        uint flipCount = 10;129        function flip() external {130          value = !value;131          flipCount--;132        }133        function getValue() external view returns (bool) {134          return value;135        }136        function getFlipCount() external view returns (uint) {137          return flipCount;138        }139      }`);140  }141});