PowerPool
Search
⌃K

Modifiers

Herein modifiers are described, including those that are not wrapped into their own distinct functions, instead being implemented as internal conditionals at execution.

ConfigFlags check

A few times the function ConfigFlags.check is invoked to check whether a certain flag is true. This is done by storing a predefined library of possible flags and taking bitwise AND between the given flag and the provided config byte.

ConfigFlags code

library ConfigFlags {
function check(uint256 cfg, uint256 flag) internal pure returns (bool) {
return (cfg & flag) != 0;
}
}

Wrapped modifiers

Modifiers herein listed are wrapped in distinct functions.

_assertOnlyOwner

This is a modifier on the agent ownership (incorporated via inheritance from the well-known Ownable.sol) which is used to keep unauthorized users from performing important function calls (slashing, agent parameter modification, accumulated fee withdrawal).
function _assertOnlyOwner() internal view {
if (msg.sender != owner()) {
revert OnlyOwner();
}
}

Usage scope (functions in main contract)

function slash(uint256 keeperId_, address to_, uint256 currentAmount_, uint256 pendingAmount_) external
function withdrawFees(address payable to_) external
function setAgentParams(uint256 minKeeperCvp_, uint256 timeoutSeconds_, uint256 feePpm_) external

_assertOnlyJobOwner

This is a modifier on job ownership (incorporated via a custom jobkey-owner mapping) used to prevent unauthorized users from changing the settings of the job or withdrawing credits from its balance. Mind that they are still allowed to deposit credits therein, though).
function _assertOnlyJobOwner(bytes32 jobKey_) internal view {
if (msg.sender != jobOwners[jobKey_]) {
revert OnlyJobOwner();
}
}

Usage scope (functions in main contract)

function updateJob(bytes32 jobKey_, uint16 maxBaseFeeGwei_, uint16 rewardPct_, uint32 fixedReward_, uint256 jobMinCvp_, uint24 intervalSeconds_) external
function setJobResolver(bytes32 jobKey_, Resolver calldata resolver_) external
function setJobPreDefinedCalldata(bytes32 jobKey_, bytes calldata preDefinedCalldata_) external
function setJobConfig(bytes32 jobKey_, bool isActive_, bool useJobOwnerCredits_, bool assertResolverSelector_) public virtual
function initiateJobTransfer(bytes32 jobKey_, address to_) external
function withdrawJobCredits(bytes32 jobKey_, address payable to_, uint256 amount_) external

_assertOnlyKeeperAdmin

This is a modifier that checks whether the calling user is an Admin of the supplied keeper (incorporated via a custom keeperId-admin mapping) in order to prevent unauthorized users to change the parameters of a keeper or withdraw some of the CVP stake. Mind that withdrawal of native-token compensation uses a laxer version of this modifier, described in the next subsection.
function _assertOnlyKeeperAdmin(uint256 keeperId_) internal view {
if (msg.sender != keeperAdmins[keeperId_]) {
revert OnlyKeeperAdmin();
}
}

Usage scope (functions in main contract)

function setWorkerAddress(uint256 keeperId_, address worker_) external
function initiateRedeem(uint256 keeperId_, uint256 amount_) external returns (uint256 pendingWithdrawalAfter)
function finalizeRedeem(uint256 keeperId_, address to_) external returns (uint256 redeemedCvp)

_assertOnlyKeeperAdminOrWorker

This is a modifier that checks whether the calling user is an Admin or Worker of the supplied keepers (incorporated via a custom keeperId-admin mapping and Keeper data structure, respectively; in both cases an object, address or Keeper struct, is associated via some mapping with the keeperId), being a laxer version of the preceding one. In the base contract, it has the only use of providing pre-compensation withdrawal checks.
function _assertOnlyKeeperAdminOrWorker(uint256 keeperId_) internal view {
if (msg.sender != keeperAdmins[keeperId_] && msg.sender != keepers[keeperId_].worker) {
revert OnlyKeeperAdminOrWorker();
}
}

Usage scope (functions in main contract)

function withdrawCompensation(uint256 keeperId_, address payable to_, uint256 amount_) external

_assertKeeperIdExists

This checks whether a keeper with a given ID exists at all by comparing the ID supplied with the ID of the latest registered keeper, since keepers are enumerated in order. Used to prevent staking to a non-existent keeper.

Usage scope (functions in main contract)

function stake(uint256 keeperId_, uint256 amount_) external

_assertWorkerNotAssigned

This checks that a worker with a given address is not already extant. Used to prevent setting two different keepers to have the same address.

Usage scope (functions in main contract)

function registerAsKeeper(address worker_, uint256 initialDepositAmount_) public virtual returns (uint256 keeperId)
function setWorkerAddress(uint256 keeperId_, address worker_) external

_assertNonZeroAmount

Asserts that the amount supplied is not zero. Used to cut off cases of attempts to invoke the deposition or withdrawal operator in a trivial setting.

Usage scope (functions in main contract)

function withdrawJobCredits(bytes32 jobKey_, address payable to_, uint256 amount_) external
function withdrawJobOwnerCredits(address payable to_, uint256 amount_) external
function stake(uint256 keeperId_, uint256 amount_) external
function initiateRedeem(uint256 keeperId_, uint256 amount_) external returns (uint256 pendingWithdrawalAfter)
function slash(uint256 keeperId_, address to_, uint256 currentAmount_, uint256 pendingAmount_) external

_assertNonZeroValue

Similar to the preceding assertion, but for functions with the payable property instead (i.e. differs in that the amount is not passed explicitly, but rather inferred from the message value). Used to perform the same check for payable functions (e.g. credit deposition in native tokens).

Usage scope (functions in main contract)

function depositJobCredits(bytes32 jobKey_) external virtual payable
function depositJobOwnerCredits(address for_) external payable

_assertJobCalldataSource

Asserts that the calldatasource field of the provided (by key) job is in concord with the specified source. Used to check that a job for which a type-specific property is set actually belongs to that type.

Usage scope (functions in main contract)

function setJobResolver(bytes32 jobKey_, Resolver calldata resolver_) external
function setJobPreDefinedCalldata(bytes32 jobKey_, bytes calldata preDefinedCalldata_) external

_assertJobParams

Asserts that the provided maxBaseFeeGwei_ is nonzero, and that the fixed and dynamic parts of the reward (given correspondingly by the parameters fixed_reward_ and rewardPcts_) is not zero, i.e., the components thereof are not zero simultaneously.

Usage scope (functions in main contract)

function registerJob(RegisterJobParams calldata params_, Resolver calldata resolver_, bytes calldata preDefinedCalldata_) public payable virtual returns (bytes32 jobKey, uint256 jobId)
function updateJob(bytes32 jobKey_, uint16 maxBaseFeeGwei_, uint16 rewardPct_, uint32 fixedReward_, uint256 jobMinCvp_, uint24 intervalSeconds_) external

_assertInterval

Asserts that the provided (by key) job is either of RESOLVER type AND does not have intervals or not of RESOLVER type AND has nonzero interval size specified.

Usage scope (functions in main contract)

function registerJob(RegisterJobParams calldata params_, Resolver calldata resolver_, bytes calldata preDefinedCalldata_) public payable virtual returns (bytes32 jobKey, uint256 jobId)
function updateJob(bytes32 jobKey_, uint16 maxBaseFeeGwei_, uint16 rewardPct_, uint32 fixedReward_, uint256 jobMinCvp_, uint24 intervalSeconds_) external

Ad-hoc modifiers

Modifiers listed hereafter are not wrapped in distinct functions of their own, being instead implemented as ad-hoc logic inside of the functions that utilise them, and are listed under the provisional names given by us.

_msg_sender_is_pending_owner_assertion

Asserts that the user other than a pending owner can not accept the job transfer.

Code of the assertion

if (msg.sender != jobPendingTransfers[jobKey_]) {
revert OnlyPendingOwner();
}

Usage scope (functions in main contract)

function acceptJobTransfer(bytes32 jobKey_, address to_) external

_fee_adjusted_credits_after_deposit_do_not_overflow_uint88_assertion

Asserts that after the fee (specified by the Agent parameter feePpm) has been deducted, the final balance after depositing additional tokens does not overflow the type used to store it (uint88).

Code of the assertion

//return the fee in accordance with the Agent parameter and the amount remaining after deduction thereof
(uint256 fee, uint256 amount) = _calculateDepositFee();
uint256 creditsAfter = jobs[jobKey_].credits + amount;
if (creditsAfter > type(uint88).max) {
revert CreditsDepositOverflow();
}

Usage scope (functions in main contract)

function _processJobCreditsDeposit(bytes32 jobKey_) internal
Function invoking this internal routine
function depositJobCredits(bytes32 jobKey_) external virtual payable

_initial_credits_deposit_does_not_overflow_uint88_assertion

Asserts that for the newly registered job, the initial token balance does not overflow the type used to store it (uint88).

Code of the assertion

//revert if the proposed job credit amount is not storable in uint88
if (msg.value > type(uint88).max) {
revert CreditsDepositOverflow();
}

Usage scope (functions in main contract)

function registerJob( RegisterJobParams calldata params_, Resolver calldata resolver_, bytes calldata preDefinedCalldata_ ) public payable virtual

_job_id_no_uint24_overflow_assertion

Asserts that after the ID of a newly registered job does not overflow the uint24 variable used to store it. Employed at registration, though it is unlikely that any owner ever registers type(uint24).max jobs.

Code of the assertion

if (jobId > type(uint24).max) {
revert JobIdOverflow();
}

Usage scope (functions in main contract)

function registerJob(
RegisterJobParams calldata params_,
Resolver calldata resolver_,
bytes calldata preDefinedCalldata_
) public payable virtual returns (bytes32 jobKey, uint256 jobId)
​

_credits_deposit_overflow_assertion

Asserts that the initial job credit deposit does not overflow the uint88 value used to store it. Registration analogue of other deposit checkers.

Code of the assertion

if (jobId > type(uint24).max) {
revert JobIdOverflow();
}

Usage scope (functions in main contract)

function registerJob(
RegisterJobParams calldata params_,
Resolver calldata resolver_,
bytes calldata preDefinedCalldata_
) public payable virtual returns (bytes32 jobKey, uint256 jobId)

_job_address_exists_assertion

Asserts that the job address provided in the registration parameters is extant and nonzero.

Code of the assertion

if (params_.jobAddress == address(0)) {
revert MissingJobAddress();
}

Usage scope (functions in main contract)

function registerJob(
RegisterJobParams calldata params_,
Resolver calldata resolver_,
bytes calldata preDefinedCalldata_
) public payable virtual returns (bytes32 jobKey, uint256 jobId)

_calldata_source_within_0_2_assertion

Asserts that the specified calldata source is within the [0;2] range, since they are encoded by the first three nonnegative integers (SELECTOR, PRE_DEFINED, RESOLVER in that exact order).

Code of the assertion

if (params_.calldataSource > 2) {
revert InvalidCalldataSource();
}

Usage scope (functions in main contract)

function registerJob(
RegisterJobParams calldata params_,
Resolver calldata resolver_,
bytes calldata preDefinedCalldata_
) public payable virtual returns (bytes32 jobKey, uint256 jobId)

_job_address_not_cvp_or_agent_assertion

Asserts that the specified job address does not correspond to the CVP token or the Agent instance in order to prevent possible arbuses.

Code of the assertion

if (params_.jobAddress == address(CVP) || params_.jobAddress == address(this)) {
revert InvalidJobAddress();
}

Usage scope (functions in main contract)

function registerJob(
RegisterJobParams calldata params_,
Resolver calldata resolver_,
bytes calldata preDefinedCalldata_
) public payable virtual returns (bytes32 jobKey, uint256 jobId)

_sender_is_authorised_as_keeper_assertion

Asserts that the message sender that invokes execute_44g58pv is the keeper authorised to do so (checked via bytes reserved for technical variables in execute calldata). Enforces compliance with the selection made.

Code of the assertion

assembly ("memory-safe") {
// load jobAddress, cfg, and keeperId from calldata to the stack
actualKeeperId := shr(232, calldataload(28))
}
Keeper memory keeper = keepers[actualKeeperId];
if (keeper.worker != msg.sender) {
revert KeeperWorkerNotAuthorized();
}

Usage scope (functions in main contract)

function execute_44g58pv() external

_executing_keeper_stake_sufficient_assertion

Asserts that the message sender that invokes execute_44g58pv has at least the minimal stake demanded by the global level set by the Agent. Ensures a keeper has stake to slash even if the job does not specify any demands in this regard.

Code of the assertion

assembly ("memory-safe") {
// load jobAddress, cfg, and keeperId from calldata to the stack
actualKeeperId := shr(232, calldataload(28))
}
Keeper memory keeper = keepers[actualKeeperId];
if (keeper.cvpStake < minKeeperCvp) {
revert InsufficientKeeperStake();
}

Usage scope (functions in main contract)

function execute_44g58pv() external

_job_is_active_assertion

Asserts that the invoked job is active and therefore potentially executable.

Code of the assertion

assembly ("memory-safe") {
// size of (address(bytes20)+id(uint24/bytes3))
let size := 23
// keccack256(address+id(uint24)) to memory to generate jobKey
calldatacopy(0, 4, size)
jobKey := keccak256(0, size)
}
uint256 binJob = getJobRaw(jobKey);
if (!ConfigFlags.check(binJob, CFG_ACTIVE)) {
revert InactiveJob(jobKey);

Usage scope (functions in main contract)

function execute_44g58pv() external

_keeper_satisfies_job_stake_demand_assertion

Asserts that the keeper invoking execute_44g58pv has sufficient amount of stake with respect to the demands made by the job, given such demands.

Code of the assertion

assembly ("memory-safe") {
// size of (address(bytes20)+id(uint24/bytes3))
let size := 23
// keccack256(address+id(uint24)) to memory to generate jobKey
calldatacopy(0, 4, size)
jobKey := keccak256(0, size)
}
assembly ("memory-safe") {
// load jobAddress, cfg, and keeperId from calldata to the stack
actualKeeperId := shr(232, calldataload(28))
}
Keeper memory keeper = keepers[actualKeeperId];
uint256 binJob = getJobRaw(jobKey);
if (ConfigFlags.check(binJob, CFG_CHECK_KEEPER_MIN_CVP_DEPOSIT) && keepers[actualKeeperId].cvpStake < jobMinKeeperCvp[jobKey]) {
revert InsufficientJobScopedKeeperStake();

Usage scope (functions in main contract)

function execute_44g58pv() external

_execution_interval_reached_assertion

Asserts that if the job being executed is of one of two interval types, at least a full interval duration has elapsed since this job was last executed.

Code of the assertion

assembly ("memory-safe") {
// size of (address(bytes20)+id(uint24/bytes3))
let size := 23
// keccack256(address+id(uint24)) to memory to generate jobKey
calldatacopy(0, 4, size)
jobKey := keccak256(0, size)
}
uint256 binJob = getJobRaw(jobKey);
{
//the interval size occupies bytes 4-6, or bits 32-55. For this reason we first shift left by 32, making interval size the leading bytes, and then shift right by 232, retaining thereby only the first 24 bits (or exactly 3 bytes)
uint256 intervalSeconds = (binJob << 32) >> 232;
if (intervalSeconds > 0) {
//since lastExecutionAt is the leading byte and has field size bytes4 (uint32), we shift right by 224 and retain only the leading 32 bits, or 4 bytes
uint256 lastExecutionAt = binJob >> 224;
if (lastExecutionAt > 0) {
uint256 nextExecutionAt;
unchecked {
nextExecutionAt = lastExecutionAt + intervalSeconds;
}
if (nextExecutionAt > block.timestamp) {
revert IntervalNotReached(lastExecutionAt, intervalSeconds, block.timestamp);
}
}
}
}

Usage scope (functions in main contract)

function execute_44g58pv() external

_msg_sender_is_EoA_assertion

Asserts that the message sender invoking execute_44g58pv is an externally-owned address (i.e. not an automatic contract).

Code of the assertion

//if the sender is not an EoA, the origin will be the EoA which started the chain of transactions that led to the sender's activation and code execution and thereby the message transmission
if (msg.sender != tx.origin) {
revert NonEOASender();
}

Usage scope (functions in main contract)

function execute_44g58pv() external

_invalid_source_type_catcher

The _calldata_source_within_0_2_assertion only makes sure the calldata numerical value is betwen 0 and 2. It will normally coincide with one of the three defined job types (SELECTOR, PRE_DEFINED, RESOLVER), but in a hypothetical case when this does not occur for any reason whatsoever, we need a catcher to raise an error.

Code of the assertion

assembly ("memory-safe") {
// size of (address(bytes20)+id(uint24/bytes3))
let size := 23
// keccack256(address+id(uint24)) to memory to generate jobKey
calldatacopy(0, 4, size)
jobKey := keccak256(0, size)
}
uint256 binJob = getJobRaw(jobKey);
CalldataSourceType calldataSource = CalldataSourceType((binJob << 56) >> 248);
if (calldataSource == CalldataSourceType.SELECTOR) {
...
} else if (calldataSource == CalldataSourceType.PRE_DEFINED) {
...
} else if (calldataSource == CalldataSourceType.RESOLVER) {
...
} else {
//catcher that should never be reached under normal operation
revert InvalidCalldataSource();
}
​

Usage scope (functions in main contract)

function execute_44g58pv() external

_job_has_enough_credits_assertion

Asserts that the job has enough credits to cover the keeper's reward for executing it.

Code of the assertion

compensation = _calculateCompensation(ok, binJob, actualKeeperId, min, gasUsed);
uint256 creditsBefore = (binJob << 128) >> 168;
if (creditsBefore < compensation) {
if (ok) {
revert InsufficientJobCredits(creditsBefore, compensation);
}
}

Usage scope (functions in main contract)

function execute_44g58pv() external

_block_base_fee_within_limits_or_accept_exceeding_assertion

This modifier asserts that the block base gas fee is either not in excess of the job-specified limit or accepted anyway by the appropriately configured flag FLAG_ACCEPT_MAX_BASE_FEE_LIMIT passed along with the execute call in the config calldata byte.

Code of the assertion

uint256 maxBaseFee;
unchecked {
maxBaseFee = ((binJob_ << 112) >> 240) * 1 gwei;
}
if (block.basefee > maxBaseFee && !ConfigFlags.check(cfg_, FLAG_ACCEPT_MAX_BASE_FEE_LIMIT)) {
revert BaseFeeGtGasPrice(block.basefee, maxBaseFee);
}
return maxBaseFee;
}

Usage scope (functions in main contract)

function _checkBaseFee(uint256 binJob_, uint256 cfg_) internal view virtual returns (uint256)

_job_revert_handler

In some cases, job reverts will give traceback messages. Occasionally, however, they will give no traceback, and both occasion need to be handled properly. This code provides such a functionality. It is not properly a modifier, since it does not condition execution of anything and merely serves as an error handler, but we include it here on the basis of collecting on one page all revert-capable routines.

Code of the assertion

if (executionResponse_.length == 0) {
revert JobCallRevertedWithoutDetails();
} else {
assembly ("memory-safe") {
revert(add(32, executionResponse_), mload(executionResponse_))
}
}

Usage scope (functions in main contract)

function _afterExecutionReverted(
bytes32 jobKey_,
CalldataSourceType calldataSource_,
uint256 keeperId_,
bytes memory executionResponse_
) internal virtual
Function invoking this internal routine
function execute_44g58pv() external
​

_job_owner_has_enough_credits_assertion

Asserts that the job owner has enough credits to cover the keeper's reward for executing it. Is only invoked when the CFG_USE_JOB_OWNER_CREDITS job config flag is set to True.

Code of the assertion

uint256 jobOwnerCreditsBefore = jobOwnerCredits[jobOwners[jobKey_]];
if (jobOwnerCreditsBefore < compensation_) {
if (ok_) {
revert InsufficientJobOwnerCredits(jobOwnerCreditsBefore, compensation_);

Usage scope (functions in main contract)

function _useJobOwnerCredits(bool ok_, bytes32 jobKey_, uint256 compensation_) internal
Function invoking this internal routine
function execute_44g58pv() external

_job_owner_has_enough_credits_assertion

Asserts that the job owner has enough credits to cover the keeper's reward for executing it. Is only invoked when the CFG_USE_JOB_OWNER_CREDITS job config flag is set to True.

Code of the assertion

uint256 jobOwnerCreditsBefore = jobOwnerCredits[jobOwners[jobKey_]];
if (jobOwnerCreditsBefore < compensation_) {
if (ok_) {
revert InsufficientJobOwnerCredits(jobOwnerCreditsBefore, compensation_);

Usage scope (functions in main contract)

function _useJobOwnerCredits(bool ok_, bytes32 jobKey_, uint256 compensation_) internal

_resolver_address_extant_assertion

Asserts that the address of the supplied resolver is extant (i.e. nonzero).

Code of the assertion

if (resolver_.resolverAddress == address(0)) {
revert MissingResolverAddress();
}

Usage scope (functions in main contract)

function _setJobResolver(bytes32 jobKey_, Resolver calldata resolver_) internal
Function invoking this internal routine
function setJobResolver(bytes32 jobKey_, Resolver calldata resolver_) external

_target_job_has_owner_assertion

Asserts that the job for which credits are deposited has an owner (i.e. the owner is not a zero address).

Code of the assertion

if (jobOwners[jobKey_] == address(0)) {
revert JobWithoutOwner();
}

Usage scope (functions in main contract)

function _setJobResolver(bytes32 jobKey_, Resolver calldata resolver_) internal

_sufficient_credits_to_withdraw

Asserts that the job/job owner has enough credits (in native chain tokens) to withdraw the specifeid amount.

Code of the assertion

if (creditsBefore < amount_) {
revert CreditsWithdrawalUnderflow();
}

Usage scope (functions in main contract)

function withdrawJobCredits(
bytes32 jobKey_,
address payable to_,
uint256 amount_
) external
function withdrawJobOwnerCredits(address payable to_, uint256 amount_) external

_minKeeperCvp_assertion

Asserts that the registering keeper has a sufficient initial deposit value to stake at least the minKeeperCvp value demanded by the Agent parameter of the same name.

Code of the assertion

if (initialDepositAmount_ < minKeeperCvp) {
revert InsufficientAmount();
}

Usage scope (functions in main contract)

function registerAsKeeper(address worker_, uint256 initialDepositAmount_) public virtual returns (uint256 keeperId)

_amount_not_exceeds_available_assertion

Asserts that a keeper has accrued enough compensation in native chain tokens to withdraw the specified amount.

Code of the assertion

uint256 available = compensations[keeperId_];
if (amount_ > available) {
revert WithdrawAmountExceedsAvailable(amount_, available);
}

Usage scope (functions in main contract)