difftreelog
Save contract state between upgrades
in: master
1 file changed
tests/src/eth/proxyContract.test.tsdiffbeforeafterboth15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161617import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import {GAS_ARGS} from './util/helpers';181919import {itEth, expect, usingEthPlaygrounds, EthUniqueHelper} from './util/playgrounds';20import {itEth, expect, usingEthPlaygrounds, EthUniqueHelper} from './util/playgrounds';2021293030 itEth('Update proxy contract', async({helper}) => {31 itEth('Update proxy contract', async({helper}) => {31 const deployer = await helper.eth.createAccountWithBalance(donor);32 const deployer = await helper.eth.createAccountWithBalance(donor);33 const caller = await helper.eth.createAccountWithBalance(donor);32 const proxyContract = await deployProxyContract(helper, deployer);34 const proxyContract = await deployProxyContract(helper, deployer);33 const realContractV1 = await deployRealContractV1(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});34 await proxyContract.methods.updateVersion(realContractV1.options.address).send();37 await proxyContract.methods.updateVersion(realContractV1.options.address).send();38 35 await proxyContract.methods.flip().send();39 await realContractV1proxy.methods.flip().send();36 await proxyContract.methods.flip().send();40 await realContractV1proxy.methods.flip().send();37 await proxyContract.methods.flip().send();41 await realContractV1proxy.methods.flip().send();38 const value1 = await proxyContract.methods.getValue().call();42 const value1 = await realContractV1proxy.methods.getValue().call();39 const flipCount1 = await proxyContract.methods.getFlipCount().call();43 const flipCount1 = await realContractV1proxy.methods.getFlipCount().call();40 expect(value1).to.be.equal(true);44 expect(flipCount1).to.be.equal('3');41 expect(flipCount1).to.be.equal('3');45 expect(value1).to.be.equal(true);42 const realContractV2 = await deployRealContractV2(helper, deployer);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});43 await proxyContract.methods.updateVersion(realContractV2.options.address).send();48 await proxyContract.methods.updateVersion(realContractV2.options.address).send();44 await proxyContract.methods.flip().send();49 await realContractV2proxy.methods.flip().send();45 await proxyContract.methods.flip().send();50 await realContractV2proxy.methods.flip().send();46 const value2 = await proxyContract.methods.getValue().call();51 const value2 = await realContractV2proxy.methods.getValue().call();47 const flipCount2 = await proxyContract.methods.getFlipCount().call();52 const flipCount2 = await realContractV2proxy.methods.getFlipCount().call();48 expect(value2).to.be.equal(true);53 expect(value2).to.be.equal(true);49 expect(flipCount2).to.be.equal('1');54 expect(flipCount2).to.be.equal('1');50 });55 });515652 async function deployProxyContract(helper: EthUniqueHelper, deployer: string) {57 async function deployProxyContract(helper: EthUniqueHelper, deployer: string) {53 return await helper.ethContract.deployByCode(deployer, 'ProxyContract', `58 return await helper.ethContract.deployByCode(deployer, 'ProxyContract', `54 // SPDX-License-Identifier: UNLICENSED59 // SPDX-License-Identifier: UNLICENSED55 pragma solidity ^0.8.6;60 pragma solidity ^0.8.6;56 61 57 contract ProxyContract {62 contract ProxyContract {58 address realContract;63 event NewEvent(uint data);59 event NewEvent(uint data);64 receive() external payable {}60 receive() external payable {}65 bytes32 private constant implementationSlot = bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1);61 constructor() {}66 constructor() {}62 function updateVersion(address newContractAddress) external {67 function updateVersion(address newContractAddress) external {63 realContract = newContractAddress;68 bytes32 slot = implementationSlot;64 }69 assembly {65 function flip() external {70 sstore(slot, newContractAddress)66 RealContract(realContract).flip();71 }67 }72 }68 function getValue() external view returns (bool) {73 fallback() external {69 return RealContract(realContract).getValue();74 bytes32 slot = implementationSlot;70 }75 assembly {71 function getFlipCount() external view returns (uint) {76 let ptr := mload(0x40)72 return RealContract(realContract).getFlipCount();77 let contractAddress := sload(slot)73 }78 74 }79 calldatacopy(ptr, 0, calldatasize())75 80 76 interface RealContract {81 let result := delegatecall(gas(), contractAddress, ptr, calldatasize(), 0, 0)77 function flip() external;82 let size := returndatasize()78 function getValue() external view returns (bool);83 79 function getFlipCount() external view returns (uint);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);80 }`);97 }`);81 }98 }829983 async function deployRealContractV1(helper: EthUniqueHelper, deployer: string) {100 async function deployRealContractV1(helper: EthUniqueHelper, deployer: string) {