all files / contracts/peripherals/jobs/ Keep3rJobMigration.sol

0% Statements 0/24
0% Branches 0/8
0% Functions 0/2
0% Lines 0/32
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77                                                                                                                                                         
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4 <0.9.0;
 
import '../../../interfaces/peripherals/IKeep3rJobs.sol';
import './Keep3rJobFundableCredits.sol';
import './Keep3rJobFundableLiquidity.sol';
 
abstract contract Keep3rJobMigration is IKeep3rJobMigration, Keep3rJobFundableCredits, Keep3rJobFundableLiquidity {
  using EnumerableSet for EnumerableSet.AddressSet;
 
  uint256 internal constant _MIGRATION_COOLDOWN = 1 minutes;
 
  /// @inheritdoc IKeep3rJobMigration
  mapping(address => address) public override pendingJobMigrations;
  mapping(address => mapping(address => uint256)) internal _migrationCreatedAt;
 
  /// @inheritdoc IKeep3rJobMigration
  function migrateJob(address _fromJob, address _toJob) external override onlyJobOwner(_fromJob) {
    if (_fromJob == _toJob) revert JobMigrationImpossible();
 
    pendingJobMigrations[_fromJob] = _toJob;
    _migrationCreatedAt[_fromJob][_toJob] = block.timestamp;
 
    emit JobMigrationRequested(_fromJob, _toJob);
  }
 
  /// @inheritdoc IKeep3rJobMigration
  function acceptJobMigration(address _fromJob, address _toJob) external override onlyJobOwner(_toJob) {
    if (disputes[_fromJob] || disputes[_toJob]) revert JobDisputed();
    if (pendingJobMigrations[_fromJob] != _toJob) revert JobMigrationUnavailable();
    if (block.timestamp < _migrationCreatedAt[_fromJob][_toJob] + _MIGRATION_COOLDOWN) revert JobMigrationLocked();
 
    // force job credits update for both jobs
    _settleJobAccountance(_fromJob);
    _settleJobAccountance(_toJob);
 
    // migrate tokens
    while (_jobTokens[_fromJob].length() > 0) {
      address _tokenToMigrate = _jobTokens[_fromJob].at(0);
      jobTokenCredits[_toJob][_tokenToMigrate] += jobTokenCredits[_fromJob][_tokenToMigrate];
      jobTokenCredits[_fromJob][_tokenToMigrate] = 0;
      _jobTokens[_fromJob].remove(_tokenToMigrate);
      _jobTokens[_toJob].add(_tokenToMigrate);
    }
 
    // migrate liquidities
    while (_jobLiquidities[_fromJob].length() > 0) {
      address _liquidity = _jobLiquidities[_fromJob].at(0);
 
      liquidityAmount[_toJob][_liquidity] += liquidityAmount[_fromJob][_liquidity];
      delete liquidityAmount[_fromJob][_liquidity];
 
      _jobLiquidities[_toJob].add(_liquidity);
      _jobLiquidities[_fromJob].remove(_liquidity);
    }
 
    // migrate job balances
    _jobPeriodCredits[_toJob] += _jobPeriodCredits[_fromJob];
    delete _jobPeriodCredits[_fromJob];
 
    _jobLiquidityCredits[_toJob] += _jobLiquidityCredits[_fromJob];
    delete _jobLiquidityCredits[_fromJob];
 
    // stop _fromJob from being a job
    delete rewardedAt[_fromJob];
    _jobs.remove(_fromJob);
 
    // delete unused data slots
    delete jobOwner[_fromJob];
    delete jobPendingOwner[_fromJob];
    delete _migrationCreatedAt[_fromJob][_toJob];
    delete pendingJobMigrations[_fromJob];
 
    emit JobMigrationSuccessful(_fromJob, _toJob);
  }
}