contract ContractLogic is SharedBetweenProxyAndLogic {
    // IUpgradeProxy fake implementation to make Solidity happy. It would be better
    // to just have these calls fall through, but this is not currently possible?
    function proxyTransferOwnership(address) external { revert(); }
    function proxyAcceptOwnership() external { revert(); }
    function proxyPause() external { revert(); }
    function proxyUnpause() external { revert(); }
    function proxyStartUpgrade(address, uint256) external { revert(); }
    function proxyCancelUpgrade() external { revert(); }
    function proxyFinishUpgrade() external { revert(); }
    function proxyCallMigration(bytes calldata) external { revert(); }
    function proxyForceVersionBump() external { revert(); }

    // General recommendation is to not accept funds if not required
    // (can still be forced via self-destruction)
    function () external payable { revert(); }

    // TODO currently unused and untested
    modifier onlyViaProxy() {
        // Must be called on the proxy, not the deployed logic contract
        require(isProxy);
        _;
    }

    modifier migration(uint256 fromVersion, uint256 toVersion) {
        // This is just a sanity check, the fact that we are in CallingMigrationFunction
        // state means that this function call was performed via proxyCallMigration
        assert(msg.sender == owner);

        assert(toVersion - fromVersion == 1);

        // Must be called on the proxy in the correct state, not the deployed
        // logic contract
        require(isProxy);
        require(proxyState == ProxyState.CallingMigrationFunction);

        // Make sure the migration version range is consistent with the
        // actual upgrade version range
        require(fromVersion >= upgradingFromVersion && toVersion <= upgradingToVersion);
        require(version == fromVersion);
        uint256 oldVersion = version;
        _;
        // Migration functions should be monotone in the version, and hold their
        // promise regarding the migrated version range
        assert(version >= oldVersion);
        assert(version <= toVersion);
        // This can be used by the caller to verify that a function with this
        // modifier was used
        proxyState = ProxyState.Upgrading;
    }
}
function proxyTransferOwnership(address) external { revert(); }

// IUpgradeProxy fake implementation to make Solidity happy. It would be better
// to just have these calls fall through, but this is not currently possible?