# Job funds deposition and withdrawal

## Job credit deposition

Should a user desire to top up credits of one of his jobs, he ought to invoke the function `depositJobCredits(bytes32 jobKey_) external virtual payable` (which is defined as `virtual` and therefore can have its functionality overridden in particular realisations, all of which will be described separately). The value of the transaction call corresponds to the amount of credits deposited.&#x20;

### Arguments

1. `bytes32 jobKey_`: a job key, which is a keccak256 hash of a concatenation of the job's address and id (in that order)

### Assertions

1. `_assertNonZeroValue`: ensures the message's value is not zero. Since this value corresponds to the amount of tokens to be deposited, this has the effect of ensuring nonzero deposition.&#x20;
2. It is also checked that the job has an owner (i.e. that its key's value in the mapping `mapping(bytes32 => address) internal jobOwners` is not zero)
3. It is further checked that the job's credit after the tokens sans the fee are deposited does not exceed the maximum admissible value of `uint88`, which is the type used to store credits.&#x20;

Once all assertions are satisfied, the function calculates the deposit fee (which is specified by the Agent parameter `feePpm` in parts per million), increments the total accrued Agent fees by the fee amount, and increments the job's credits by the deposit amount minus the fee. Finally, an overridable `virtual` function `afterDepositJobCredits(jobKey)` is called, which is implementation-specific (e.g., in PPAgentV2RANDAO this function assigns a keeper to the job if need be).

### Job credit deposition update

Having incremented the credits and the fee, the function emits the event `DepositJobCredits(jobKey_, msg.sender, amount, fee)`

## Job credits withdrawal

Should a job owner desire to withdraw some credits of one of his jobs, he ought to invoke the function `withdrawJobCredits( bytes32 jobKey_, address payable to_, uint256 amount_ )`&#x20;

### Arguments

1. `bytes32 jobKey_`: a job key, which is a keccak256 hash of a concatenation of the job's address and id (in that order)
2. `address payable to_`: the withdrawn token recipient address
3. `uint256 amount_`: the amount to withdraw. If this values equals `type(uint256).max`, then the totality of tokens is withdrawn, which is a measure of convenience.&#x20;

### Assertions

1. `_assertOnlyJobOwner`: ensures that only the owner may withdraw
2. `_assertNonZeroAmount`: ensures that the amount withdrawn is nonzero
3. It is also checked that the amount withdrawn does not exceed the amount available

Once all assertions are satisfied, the function decrements the job's credits by the specified amount, transfers them to the specified address, and calls the overridable `virtual` function `afterWithdrawJobCredits(jobKey)`, which allows particular realisations to inject custom behaviour. E.g., the PPAgentV2RANDAO checks if the keeper assigned to the job needs to be released (e.g. if the job is left underfunded, and covering the costs with the job owner credits is not possible) and releases him if so.&#x20;

### Job credit withdrawal update

Having decremented the credits and sent them to the specified address, the function emits the event `WithdrawJobCredits(jobKey_, msg.sender, to_, amount_)`

## Job owner credits deposition

If the job parameters so allow, the credits belonging to the owner and not the job itself may be used to cover the cost of execution (i.e. reward the keeper). Should a user desire to top up his credits, he ought to invoke the function `depositJobOwnerCredits(address for_) external payable`. The value of the transaction call corresponds to the amount of credits deposited.&#x20;

### Arguments

1. `address for_`: the job owner address to deposit for

### Assertions

1. `_assertNonZeroValue`: ensures the message's value is not zero. Since this value corresponds to the amount of tokens to be deposited, this has the effect of ensuring nonzero deposition.&#x20;

Once all assertions are satisfied, the function calculates the deposit fee (which is specified by the Agent parameter `feePpm` in parts per million), increments the total accrued Agent fees by the fee amount, and increments the job owner's credits (stored in the mapping `mapping(address => uint256) public jobOwnerCredits` with address as key) by the deposit amount minus the fee.&#x20;

### Job owner credit deposition update

Having incremented the credits and the fee, the function emits the event `DepositJobOwnerCredits(for_, msg.sender, amount, fee)`

## Job owner credits withdrawal

Should a job owner desire to withdraw some or all of his credits, he ought to invoke the function `withdrawJobOwnerCredits(address payable to_, uint256 amount_)`&#x20;

### Arguments

1. `address payable to_`: the withdrawn token recipient address
2. `uint256 amount_`: the amount to withdraw. If this values equals `type(uint256).max`, then the totality of tokens is withdrawn, which is a measure of convenience.&#x20;

### Assertions

1. `_assertNonZeroAmount`: ensures that the amount withdrawn is nonzero
2. It is also checked that the amount withdrawn does not exceed the amount available

There are no separate checks for the sender to be the job owner because the credits available for withdrawal are taken from the mapping `mapping(address => uint256) public jobOwnerCredits` with the message sender's address as key.&#x20;

Once all assertions are satisfied, the function decrements the job owner's credits by the specified amount and transfers them to the specified address.

### Job owner credit withdrawal update

Having decremented the credits and sent them to the specified address, the function emits the event `WithdrawJobOwnerCredits(msg.sender, to_, amount_)`
