pay
Contract: JBETHERC20SplitsPayer
Interface: IJBSplitsPayer
- Step by step
- Code
- Errors
- Events
- Bug bounty
Make a payment to the specified project after first splitting the amount among the stored default splits.
Definitionβ
function pay(
uint256 _projectId,
address _token,
uint256 _amount,
uint256 _decimals,
address _beneficiary,
uint256 _minReturnedTokens,
bool _preferClaimedTokens,
string calldata _memo,
bytes calldata _metadata
) public payable virtual override nonReentrant { ... }
- Arguments:
_projectId
is the ID of the project that is being paid after._token
is the token being paid in._amount
is the amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place._decimals
is the number of decimals in the_amount
fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value._beneficiary
is the address who will receive tokens from the payment._minReturnedTokens
is the minimum number of project tokens expected in return, as a fixed point number with 18 decimals._preferClaimedTokens
is a flag indicating whether the request prefers to mint project tokens into the beneficiaries wallet rather than leaving them unclaimed. This is only possible if the project has an attached token contract. Leaving them unclaimed saves gas._memo
is a memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate._metadata
are bytes to send along to the data source, delegate, and emitted event, if provided.
- The function can be accessed externally by anyone, or internally from this contract or one that inherits it.
- The function can be overriden by inheriting contracts.
- The function overrides a function definition from the
IJBProjectPayer
interface. - The function doesn't return anything.
Bodyβ
-
If the token isn't ETH, make sure ETH wasn't sent to the function, then transfer the amount of tokens from the message sender to this contract. If the token is ETH, override the specified amount and decimals values with with amount of ETH sent to the function, which is denoted as a fixed point number with 18 decimals.
// ETH shouldn't be sent if the token isn't ETH.
if (address(_token) != JBTokens.ETH) {
if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();
// Transfer tokens to this contract from the msg sender.
IERC20(_token).transferFrom(msg.sender, address(this), _amount);
} else {
// If ETH is being paid, set the amount to the message value, and decimals to 18.
_amount = msg.value;
_decimals = 18;
}Library references:
JBTokens
.ETH
External references:
-
Send the funds to the splits and get a reference to the leftover amount.
// Pay the splits and get a reference to the amount leftover.
uint256 _leftoverAmount = _payToSplits(
defaultSplitsProjectId,
defaultSplitsDomain,
defaultSplitsGroup,
_token,
_amount,
_decimals,
defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender
);Internal references:
-
If there's any leftover amount, pay the specified project. If no project is specified, send the leftover funds to the beneficiary or the msg.sender.
// Pay any leftover amount.
if (_leftoverAmount > 0) {
// If there's a default project ID, try to pay it.
if (_projectId != 0) {
_pay(
_projectId,
_token,
_leftoverAmount,
_decimals,
_beneficiary != address(0) ? _beneficiary : msg.sender,
_minReturnedTokens,
_preferClaimedTokens,
_memo,
_metadata
);
}
// If no project was specified, send the funds directly to the beneficiary or the msg.sender.
else {
// Transfer the ETH.
if (_token == JBTokens.ETH)
Address.sendValue(
// If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.
_beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),
_leftoverAmount
);
// Or, transfer the ERC20.
else
IERC20(_token).transfer(
// If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.
_beneficiary != address(0) ? _beneficiary : msg.sender,
_leftoverAmount
);
}
}Library references:
Internal references:
External references:
-
Emit a
Pay
event with the relevant parameters.emit Pay(
_projectId,
_beneficiary != address(0) ? defaultBeneficiary : msg.sender,
_token,
_amount,
_decimals,
_leftoverAmount,
_minReturnedTokens,
_preferClaimedTokens,
_memo,
_metadata,
msg.sender
);Event references:
/**
@notice
Make a payment to the specified project after first splitting the amount among the stored default splits.
@param _projectId The ID of the project that is being paid after.
@param _token The token being paid in.
@param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.
@param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.
@param _beneficiary The address who will receive tokens from the payment made with leftover funds.
@param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.
@param _preferClaimedTokens A flag indicating whether the request prefers to mint project tokens into the beneficiaries wallet rather than leaving them unclaimed. This is only possible if the project has an attached token contract. Leaving them unclaimed saves gas.
@param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.
@param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.
*/
function pay(
uint256 _projectId,
address _token,
uint256 _amount,
uint256 _decimals,
address _beneficiary,
uint256 _minReturnedTokens,
bool _preferClaimedTokens,
string calldata _memo,
bytes calldata _metadata
) public payable virtual override nonReentrant {
// ETH shouldn't be sent if the token isn't ETH.
if (address(_token) != JBTokens.ETH) {
if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();
// Transfer tokens to this contract from the msg sender.
IERC20(_token).transferFrom(msg.sender, address(this), _amount);
} else {
// If ETH is being paid, set the amount to the message value, and decimals to 18.
_amount = msg.value;
_decimals = 18;
}
// Pay the splits and get a reference to the amount leftover.
uint256 _leftoverAmount = _payToSplits(
defaultSplitsProjectId,
defaultSplitsDomain,
defaultSplitsGroup,
_token,
_amount,
_decimals,
defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender
);
// Pay any leftover amount.
if (_leftoverAmount > 0) {
// If there's a default project ID, try to pay it.
if (_projectId != 0) {
_pay(
_projectId,
_token,
_leftoverAmount,
_decimals,
_beneficiary != address(0) ? _beneficiary : msg.sender,
_minReturnedTokens,
_preferClaimedTokens,
_memo,
_metadata
);
}
// If no project was specified, send the funds directly to the beneficiary or the msg.sender.
else {
// Transfer the ETH.
if (_token == JBTokens.ETH)
Address.sendValue(
// If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.
_beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),
_leftoverAmount
);
// Or, transfer the ERC20.
else
IERC20(_token).transfer(
// If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.
_beneficiary != address(0) ? _beneficiary : msg.sender,
_leftoverAmount
);
}
}
emit Pay(
_projectId,
_beneficiary != address(0) ? defaultBeneficiary : msg.sender,
_token,
_amount,
_decimals,
_leftoverAmount,
_minReturnedTokens,
_preferClaimedTokens,
_memo,
_metadata,
msg.sender
);
}
String | Description |
---|---|
NO_MSG_VALUE_ALLOWED | Thrown if ETH was sent to a non-ETH terminal. |
Name | Data |
---|---|
Pay |
|
Category | Description | Reward |
---|---|---|
Optimization | Help make this operation more efficient. | 0.5ETH |
Low severity | Identify a vulnerability in this operation that could lead to an inconvenience for a user of the protocol or for a protocol developer. | 1ETH |
High severity | Identify a vulnerability in this operation that could lead to data corruption or loss of funds. | 5+ETH |