-
Notifications
You must be signed in to change notification settings - Fork 55
/
Keep3rJobFundableCredits.sol
65 lines (54 loc) · 2.49 KB
/
Keep3rJobFundableCredits.sol
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
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4 <0.9.0;
import './Keep3rJobOwnership.sol';
import '../Keep3rAccountance.sol';
import '../Keep3rParameters.sol';
import '../../../interfaces/peripherals/IKeep3rJobs.sol';
import '@openzeppelin/contracts/security/ReentrancyGuard.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import '@openzeppelin/contracts/utils/math/Math.sol';
abstract contract Keep3rJobFundableCredits is IKeep3rJobFundableCredits, ReentrancyGuard, Keep3rJobOwnership, Keep3rParameters {
using EnumerableSet for EnumerableSet.AddressSet;
using SafeERC20 for IERC20;
/// @notice Cooldown between withdrawals
uint256 internal constant _WITHDRAW_TOKENS_COOLDOWN = 1 minutes;
/// @inheritdoc IKeep3rJobFundableCredits
mapping(address => mapping(address => uint256)) public override jobTokenCreditsAddedAt;
/// @inheritdoc IKeep3rJobFundableCredits
function addTokenCreditsToJob(
address _job,
address _token,
uint256 _amount
) external override nonReentrant {
if (!_jobs.contains(_job)) revert JobUnavailable();
// KP3R shouldn't be used for direct token payments
if (_token == keep3rV1) revert TokenUnallowed();
uint256 _before = IERC20(_token).balanceOf(address(this));
IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);
uint256 _received = IERC20(_token).balanceOf(address(this)) - _before;
uint256 _tokenFee = (_received * fee) / BASE;
jobTokenCredits[_job][_token] += _received - _tokenFee;
jobTokenCreditsAddedAt[_job][_token] = block.timestamp;
IERC20(_token).safeTransfer(governance, _tokenFee);
_jobTokens[_job].add(_token);
emit TokenCreditAddition(_job, _token, msg.sender, _received);
}
/// @inheritdoc IKeep3rJobFundableCredits
function withdrawTokenCreditsFromJob(
address _job,
address _token,
uint256 _amount,
address _receiver
) external override nonReentrant onlyJobOwner(_job) {
if (block.timestamp <= jobTokenCreditsAddedAt[_job][_token] + _WITHDRAW_TOKENS_COOLDOWN) revert JobTokenCreditsLocked();
if (jobTokenCredits[_job][_token] < _amount) revert InsufficientJobTokenCredits();
if (disputes[_job]) revert JobDisputed();
jobTokenCredits[_job][_token] -= _amount;
IERC20(_token).safeTransfer(_receiver, _amount);
if (jobTokenCredits[_job][_token] == 0) {
_jobTokens[_job].remove(_token);
}
emit TokenCreditWithdrawal(_job, _token, _receiver, _amount);
}
}