pragma ever-solidity >= 0.68.0; pragma AbiHeader time; pragma AbiHeader expire; pragma AbiHeader pubkey; import "locklift/src/console.tsol"; import "../../../contracts/access/abstract/Ownable.tsol"; import "../../../contracts/libraries/UtilityErrors.tsol"; import "../../../contracts/libraries/MsgFlag.tsol"; import "../../../contracts/libraries/UtilityGas.tsol"; import "../../../contracts/upgrade/abstract/UpgradableWithData.tsol"; contract UpgradableWithDataExample is UpgradableWithData, Ownable { uint32 private static _nonce; uint32 private _extra; function _getTargetBalanceInternal() internal view override returns (uint128) { return UtilityGas.INITIAL_BALANCE; } constructor( optional(address) _initialOwner, optional(address) _remainingGasTo ) public reserveAcceptAndRefund(_getTargetBalanceInternal(), _remainingGasTo, msg.sender) validAddressOrNull(_initialOwner, UtilityErrors.INVALID_NEW_OWNER) { address initialOwner = _initialOwner.hasValue() ? _initialOwner.get() : msg.sender; _setOwnerInternal(initialOwner); _setCurrentVersionInternal(1, 0); } function getExtra() external view responsible returns (uint32) { return { value: 0, flag: MsgFlag.REMAINING_GAS, bounce: false } _extra; } function upgrade( TvmCell _code, optional(uint32) _version, TvmCell _data, optional(address) _remainingGasTo ) external override reserve(_getTargetBalanceInternal()) onlyOwner validTvmCell(_code, UtilityErrors.INVALID_CODE) { address remainingGasTo = _remainingGasTo.hasValue() ? _remainingGasTo.get() : msg.sender; TvmCell data = abi.encode( _nonce, _getCurrentVersionInternal(), _version, _getOwnerInternal(), _data, remainingGasTo ); tvm.setcode(_code); tvm.setCurrentCode(_code); onCodeUpgrade(data); } function onCodeUpgrade(TvmCell _data) private { tvm.resetStorage(); ( uint32 nonce, uint32 previousVersion, optional(uint32) currentVersion, address owner, TvmCell data, address remainingGasTo ) = abi.decode(_data, ( uint32, uint32, optional(uint32), address, TvmCell, address )); _nonce = nonce; _extra = abi.decode(data, uint32); _setOwnerSilent(owner); _setCurrentVersionInternal( currentVersion.hasValue() ? currentVersion.get() : previousVersion + 1, previousVersion ); console.log(format("New version: {}", _getCurrentVersionInternal())); remainingGasTo.transfer({ value: 0, flag: MsgFlag.ALL_NOT_RESERVED + MsgFlag.IGNORE_ERRORS, bounce: false }); } }