// SPDX-License-Identifier: LGPL-3.0-only// Creatd By: Art Blocks Inc.pragmasolidity ^0.5.0;import"../../libs/0.5.x/SafeMath.sol";
import"../../libs/0.5.x/Strings.sol";
import"../../interfaces/0.5.x/IGenArt721CoreV2_PBAB.sol";
interfaceERC20{
functionbalanceOf(address _owner) externalviewreturns (uint256 balance);
functiontransferFrom(address _from,
address _to,
uint256 _value
) externalreturns (bool success);
functionallowance(address _owner, address _spender)
externalviewreturns (uint256 remaining);
}
interfaceBonusContract{
functiontriggerBonus(address _to) externalreturns (bool);
functionbonusIsActive() externalviewreturns (bool);
}
contractGenArt721Minter_BrightMoments{
usingSafeMathforuint256;
IGenArt721CoreV2_PBAB public genArtCoreContract;
uint256constant ONE_MILLION =1_000_000;
addresspayablepublic ownerAddress;
uint256public ownerPercentage;
mapping(uint256=>bool) public projectIdToBonus;
mapping(uint256=>address) public projectIdToBonusContractAddress;
mapping(uint256=>bool) public contractFilterProject;
mapping(address=>mapping(uint256=>uint256)) public projectMintCounter;
mapping(uint256=>uint256) public projectMintLimit;
mapping(uint256=>bool) public projectMaxHasBeenInvoked;
mapping(uint256=>uint256) public projectMaxInvocations;
constructor(address _genArt721Address) public{
genArtCoreContract = IGenArt721CoreV2_PBAB(_genArt721Address);
}
functiongetYourBalanceOfProjectERC20(uint256 _projectId)
publicviewreturns (uint256)
{
uint256 balance = ERC20(
genArtCoreContract.projectIdToCurrencyAddress(_projectId)
).balanceOf(msg.sender);
return balance;
}
functioncheckYourAllowanceOfProjectERC20(uint256 _projectId)
publicviewreturns (uint256)
{
uint256 remaining = ERC20(
genArtCoreContract.projectIdToCurrencyAddress(_projectId)
).allowance(msg.sender, address(this));
return remaining;
}
functionsetProjectMintLimit(uint256 _projectId, uint8 _limit) public{
require(
genArtCoreContract.isWhitelisted(msg.sender),
"can only be set by admin"
);
projectMintLimit[_projectId] = _limit;
}
functionsetProjectMaxInvocations(uint256 _projectId) public{
require(
genArtCoreContract.isWhitelisted(msg.sender),
"can only be set by admin"
);
uint256 maxInvocations;
uint256 invocations;
(, , invocations, maxInvocations, , , , , ) = genArtCoreContract
.projectTokenInfo(_projectId);
projectMaxInvocations[_projectId] = maxInvocations;
if (invocations < maxInvocations) {
projectMaxHasBeenInvoked[_projectId] =false;
}
}
functionsetOwnerAddress(addresspayable _ownerAddress) public{
require(
genArtCoreContract.isWhitelisted(msg.sender),
"can only be set by admin"
);
ownerAddress = _ownerAddress;
}
functionsetOwnerPercentage(uint256 _ownerPercentage) public{
require(
genArtCoreContract.isWhitelisted(msg.sender),
"can only be set by admin"
);
ownerPercentage = _ownerPercentage;
}
functiontoggleContractFilter(uint256 _projectId) public{
require(
genArtCoreContract.isWhitelisted(msg.sender),
"can only be set by admin"
);
contractFilterProject[_projectId] =!contractFilterProject[_projectId];
}
functionartistToggleBonus(uint256 _projectId) public{
require(
msg.sender==
genArtCoreContract.projectIdToArtistAddress(_projectId),
"can only be set by artist"
);
projectIdToBonus[_projectId] =!projectIdToBonus[_projectId];
}
functionartistSetBonusContractAddress(uint256 _projectId,
address _bonusContractAddress
) public{
require(
msg.sender==
genArtCoreContract.projectIdToArtistAddress(_projectId),
"can only be set by artist"
);
projectIdToBonusContractAddress[_projectId] = _bonusContractAddress;
}
functionpurchase(uint256 _projectId)
publicpayablereturns (uint256 _tokenId)
{
return purchaseTo(msg.sender, _projectId);
}
// Remove `public`` and `payable`` to prevent public use// of the `purchaseTo`` function.functionpurchaseTo(address _to, uint256 _projectId)
publicpayablereturns (uint256 _tokenId)
{
require(
!projectMaxHasBeenInvoked[_projectId],
"Maximum number of invocations reached"
);
if (
keccak256(
abi.encodePacked(
genArtCoreContract.projectIdToCurrencySymbol(_projectId)
)
) !=keccak256(abi.encodePacked("ETH"))
) {
require(
msg.value==0,
"this project accepts a different currency and cannot accept ETH"
);
require(
ERC20(genArtCoreContract.projectIdToCurrencyAddress(_projectId))
.allowance(msg.sender, address(this)) >=
genArtCoreContract.projectIdToPricePerTokenInWei(
_projectId
),
"Insufficient Funds Approved for TX"
);
require(
ERC20(genArtCoreContract.projectIdToCurrencyAddress(_projectId))
.balanceOf(msg.sender) >=
genArtCoreContract.projectIdToPricePerTokenInWei(
_projectId
),
"Insufficient balance."
);
_splitFundsERC20(_projectId);
} else {
require(
msg.value>=
genArtCoreContract.projectIdToPricePerTokenInWei(
_projectId
),
"Must send minimum value to mint!"
);
_splitFundsETH(_projectId);
}
// if contract filter is active prevent calls from another contractif (contractFilterProject[_projectId])
require(msg.sender==tx.origin, "No Contract Buys");
// limit mints per address by projectif (projectMintLimit[_projectId] >0) {
require(
projectMintCounter[msg.sender][_projectId] <
projectMintLimit[_projectId],
"Reached minting limit"
);
projectMintCounter[msg.sender][_projectId]++;
}
uint256 tokenId = genArtCoreContract.mint(_to, _projectId, msg.sender);
// What if this overflows, since default value of uint256 is 0?// That is intended, so that by default the minter allows infinite// transactions, allowing the `genArtCoreContract` to stop minting// `uint256 tokenInvocation = tokenId % ONE_MILLION;`if (tokenId % ONE_MILLION == projectMaxInvocations[_projectId] -1) {
projectMaxHasBeenInvoked[_projectId] =true;
}
if (projectIdToBonus[_projectId]) {
require(
BonusContract(projectIdToBonusContractAddress[_projectId])
.bonusIsActive(),
"bonus must be active"
);
BonusContract(projectIdToBonusContractAddress[_projectId])
.triggerBonus(msg.sender);
}
return tokenId;
}
function_splitFundsETH(uint256 _projectId) internal{
if (msg.value>0) {
uint256 pricePerTokenInWei = genArtCoreContract
.projectIdToPricePerTokenInWei(_projectId);
uint256 refund =msg.value.sub(
genArtCoreContract.projectIdToPricePerTokenInWei(_projectId)
);
if (refund >0) {
msg.sender.transfer(refund);
}
uint256 renderProviderAmount = pricePerTokenInWei.div(100).mul(
genArtCoreContract.renderProviderPercentage()
);
if (renderProviderAmount >0) {
genArtCoreContract.renderProviderAddress().transfer(
renderProviderAmount
);
}
uint256 remainingFunds = pricePerTokenInWei.sub(
renderProviderAmount
);
uint256 ownerFunds = remainingFunds.div(100).mul(ownerPercentage);
if (ownerFunds >0) {
ownerAddress.transfer(ownerFunds);
}
uint256 projectFunds = pricePerTokenInWei
.sub(renderProviderAmount)
.sub(ownerFunds);
uint256 additionalPayeeAmount;
if (
genArtCoreContract.projectIdToAdditionalPayeePercentage(
_projectId
) >0
) {
additionalPayeeAmount = projectFunds.div(100).mul(
genArtCoreContract.projectIdToAdditionalPayeePercentage(
_projectId
)
);
if (additionalPayeeAmount >0) {
genArtCoreContract
.projectIdToAdditionalPayee(_projectId)
.transfer(additionalPayeeAmount);
}
}
uint256 creatorFunds = projectFunds.sub(additionalPayeeAmount);
if (creatorFunds >0) {
genArtCoreContract
.projectIdToArtistAddress(_projectId)
.transfer(creatorFunds);
}
}
}
function_splitFundsERC20(uint256 _projectId) internal{
uint256 pricePerTokenInWei = genArtCoreContract
.projectIdToPricePerTokenInWei(_projectId);
uint256 renderProviderAmount = pricePerTokenInWei.div(100).mul(
genArtCoreContract.renderProviderPercentage()
);
if (renderProviderAmount >0) {
ERC20(genArtCoreContract.projectIdToCurrencyAddress(_projectId))
.transferFrom(
msg.sender,
genArtCoreContract.renderProviderAddress(),
renderProviderAmount
);
}
uint256 remainingFunds = pricePerTokenInWei.sub(renderProviderAmount);
uint256 ownerFunds = remainingFunds.div(100).mul(ownerPercentage);
if (ownerFunds >0) {
ERC20(genArtCoreContract.projectIdToCurrencyAddress(_projectId))
.transferFrom(msg.sender, ownerAddress, ownerFunds);
}
uint256 projectFunds = pricePerTokenInWei.sub(renderProviderAmount).sub(
ownerFunds
);
uint256 additionalPayeeAmount;
if (
genArtCoreContract.projectIdToAdditionalPayeePercentage(
_projectId
) >0
) {
additionalPayeeAmount = projectFunds.div(100).mul(
genArtCoreContract.projectIdToAdditionalPayeePercentage(
_projectId
)
);
if (additionalPayeeAmount >0) {
ERC20(genArtCoreContract.projectIdToCurrencyAddress(_projectId))
.transferFrom(
msg.sender,
genArtCoreContract.projectIdToAdditionalPayee(
_projectId
),
additionalPayeeAmount
);
}
}
uint256 creatorFunds = projectFunds.sub(additionalPayeeAmount);
if (creatorFunds >0) {
ERC20(genArtCoreContract.projectIdToCurrencyAddress(_projectId))
.transferFrom(
msg.sender,
genArtCoreContract.projectIdToArtistAddress(_projectId),
creatorFunds
);
}
}
}
Contract Source Code
File 2 of 4: IGenArt721CoreV2_PBAB.sol
// SPDX-License-Identifier: LGPL-3.0-only// Creatd By: Art Blocks Inc.pragmasolidity ^0.5.0;interfaceIGenArt721CoreV2_PBAB{
/**
* @notice Token ID `_tokenId` minted on project ID `_projectId` to `_to`.
* @dev NatSpec for events not supported in Solidity ^0.5.0
*/eventMint(addressindexed _to,
uint256indexed _tokenId,
uint256indexed _projectId
);
// getter function of public variablefunctionadmin() externalviewreturns (address);
// getter function of public variablefunctionnextProjectId() externalviewreturns (uint256);
// getter function of public mappingfunctiontokenIdToProjectId(uint256 tokenId)
externalviewreturns (uint256 projectId);
functionisWhitelisted(address sender) externalviewreturns (bool);
functionprojectIdToCurrencySymbol(uint256 _projectId)
externalviewreturns (stringmemory);
functionprojectIdToCurrencyAddress(uint256 _projectId)
externalviewreturns (address);
functionprojectIdToArtistAddress(uint256 _projectId)
externalviewreturns (addresspayable);
functionprojectIdToPricePerTokenInWei(uint256 _projectId)
externalviewreturns (uint256);
functionprojectIdToAdditionalPayee(uint256 _projectId)
externalviewreturns (addresspayable);
functionprojectIdToAdditionalPayeePercentage(uint256 _projectId)
externalviewreturns (uint256);
functionprojectTokenInfo(uint256 _projectId)
externalviewreturns (address,
uint256,
uint256,
uint256,
bool,
address,
uint256,
stringmemory,
address);
functionrenderProviderAddress() externalviewreturns (addresspayable);
functionrenderProviderPercentage() externalviewreturns (uint256);
functionmint(address _to,
uint256 _projectId,
address _by
) externalreturns (uint256 tokenId);
functiongetRoyaltyData(uint256 _tokenId)
externalviewreturns (address artistAddress,
address additionalPayee,
uint256 additionalPayeePercentage,
uint256 royaltyFeeByID
);
}
Contract Source Code
File 3 of 4: SafeMath.sol
// SPDX-License-Identifier: MIT// File: openzeppelin-solidity/contracts/math/SafeMath.sol// **Please Note**: This library is not necessary for ^0.8.0 contracts and thus// only exists for posterity reasons for compatibility with// existing already-deployed ^0.5.0 PBAB contracts.pragmasolidity ^0.5.0;/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/librarySafeMath{
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/functionadd(uint256 a, uint256 b) internalpurereturns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/functionsub(uint256 a, uint256 b) internalpurereturns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/functionmul(uint256 a, uint256 b) internalpurereturns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the// benefit is lost if 'b' is also tested.// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522if (a ==0) {
return0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/functiondiv(uint256 a, uint256 b) internalpurereturns (uint256) {
// Solidity only automatically asserts when dividing by 0require(b >0, "SafeMath: division by zero");
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't holdreturn c;
}
}
Contract Source Code
File 4 of 4: Strings.sol
// SPDX-License-Identifier: MIT// File: contracts/Strings.sol// Source: https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol// **Please Note**: This library is not necessary for ^0.8.0 contracts and thus// only exists for posterity reasons for compatibility with// existing already-deployed ^0.5.0 PBAB contracts.pragmasolidity ^0.5.0;libraryStrings{
functionstrConcat(stringmemory _a, stringmemory _b)
internalpurereturns (stringmemory _concatenatedString)
{
return strConcat(_a, _b, "", "", "");
}
functionstrConcat(stringmemory _a,
stringmemory _b,
stringmemory _c
) internalpurereturns (stringmemory _concatenatedString) {
return strConcat(_a, _b, _c, "", "");
}
functionstrConcat(stringmemory _a,
stringmemory _b,
stringmemory _c,
stringmemory _d
) internalpurereturns (stringmemory _concatenatedString) {
return strConcat(_a, _b, _c, _d, "");
}
functionstrConcat(stringmemory _a,
stringmemory _b,
stringmemory _c,
stringmemory _d,
stringmemory _e
) internalpurereturns (stringmemory _concatenatedString) {
bytesmemory _ba =bytes(_a);
bytesmemory _bb =bytes(_b);
bytesmemory _bc =bytes(_c);
bytesmemory _bd =bytes(_d);
bytesmemory _be =bytes(_e);
stringmemory abcde =newstring(
_ba.length+ _bb.length+ _bc.length+ _bd.length+ _be.length
);
bytesmemory babcde =bytes(abcde);
uint256 k =0;
uint256 i =0;
for (i =0; i < _ba.length; i++) {
babcde[k++] = _ba[i];
}
for (i =0; i < _bb.length; i++) {
babcde[k++] = _bb[i];
}
for (i =0; i < _bc.length; i++) {
babcde[k++] = _bc[i];
}
for (i =0; i < _bd.length; i++) {
babcde[k++] = _bd[i];
}
for (i =0; i < _be.length; i++) {
babcde[k++] = _be[i];
}
returnstring(babcde);
}
functionuint2str(uint256 _i)
internalpurereturns (stringmemory _uintAsString)
{
if (_i ==0) {
return"0";
}
uint256 j = _i;
uint256 len;
while (j !=0) {
len++;
j /=10;
}
bytesmemory bstr =newbytes(len);
uint256 k = len -1;
while (_i !=0) {
bstr[k--] =bytes1(uint8(48+ (_i %10)));
_i /=10;
}
returnstring(bstr);
}
}