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
15// 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/>.
1616
17import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';
18import {GAS_ARGS} from './util/helpers';
1819
19import {itEth, expect, usingEthPlaygrounds, EthUniqueHelper} from './util/playgrounds';20import {itEth, expect, usingEthPlaygrounds, EthUniqueHelper} from './util/playgrounds';
2021
2930
30 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 });
5156
52 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: UNLICENSED
55 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 result
87 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 }
8299
83 async function deployRealContractV1(helper: EthUniqueHelper, deployer: string) {100 async function deployRealContractV1(helper: EthUniqueHelper, deployer: string) {