BrimSyndicate
0xbdfb289abd173a7e4d338e9dc5c43a469a70f2a0
Verification
Verified
v0.8.33+commit.64118f21
Type
Contract
13,278 bytes
ABI entries
61
29 read · 21 write
License
none
Contract information
- Address
- 0xbdfb289abd173a7e4d338e9dc5c43a469a70f2a0
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.33+commit.64118f21
- Optimization
- Enabled
- Creator
- 0xaB2390473E…48Bd1232FE
- Creation tx
- 0x190b198d0d…e80ba9dab6
Token
- Name
- Brim Syndicate
- Symbol
- BRIM
- Decimals
- —
- Holders
- 1,231
- Market
- View token page →
Read contract (29)
BOUNTY_PER_WALLET() → uint256
DEFAULT_TRANSFER_VALIDATOR() → address
FREE_ALLOCATION() → uint256
FREE_PER_WALLET() → uint256
MAX_SUPPLY() → uint256
TEAM_RESERVE() → uint256
autoApproveTransfersFromValidator() → bool
bailClaimed(address) → uint256
bailClaimedTotal() → uint256
bailOpen() → bool
balanceOf(address) → uint256
baseURI() → string
bountyClaimed(address) → uint256
bountyOpen() → bool
bountyPrice() → uint256
getApproved(uint256) → address
getTransferValidationFunction() → bytes4, bool
getTransferValidator() → address
isApprovedForAll(address, address) → bool
name() → string
owner() → address
ownerOf(uint256) → address
royaltyInfo(uint256, uint256) → address, uint256
signer() → address
supportsInterface(bytes4) → bool
symbol() → string
teamMintedTotal() → uint256
tokenURI(uint256) → string
totalMinted() → uint256
Events (8)
ApprovalApprovalForAllAutomaticApprovalOfTransferValidatorSetDefaultRoyaltySetOwnershipTransferredTokenRoyaltySetTransferTransferValidatorUpdated
ABI
[
{
"inputs": [
{
"internalType": "address",
"name": "_signer",
"type": "address"
},
{
"internalType": "string",
"name": "_baseURI",
"type": "string"
},
{
"internalType": "address",
"name": "royaltyReceiver_",
"type": "address"
},
{
"internalType": "uint96",
"name": "royaltyFeeNumerator_",
"type": "uint96"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "CreatorTokenBase__InvalidTransferValidatorContract",
"type": "error"
},
{
"inputs": [],
"name": "ShouldNotMintToBurnAddress",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "approved",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "operator",
"type": "address"
},
{
"indexed": false,
"internalType": "bool",
"name": "approved",
"type": "bool"
}
],
"name": "ApprovalForAll",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "bool",
"name": "autoApproved",
"type": "bool"
}
],
"name": "AutomaticApprovalOfTransferValidatorSet",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "receiver",
"type": "address"
},
{
"indexed": false,
"internalType": "uint96",
"name": "feeNumerator",
"type": "uint96"
}
],
"name": "DefaultRoyaltySet",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "receiver",
"type": "address"
},
{
"indexed": false,
"internalType": "uint96",
"name": "feeNumerator",
"type": "uint96"
}
],
"name": "TokenRoyaltySet",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "oldValidator",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "newValidator",
"type": "address"
}
],
"name": "TransferValidatorUpdated",
"type": "event"
},
{
"inputs": [],
"name": "BOUNTY_PER_WALLET",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "DEFAULT_TRANSFER_VALIDATOR",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "FREE_ALLOCATION",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "FREE_PER_WALLET",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MAX_SUPPLY",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "TEAM_RESERVE",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "approve",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "autoApproveTransfersFromValidator",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "bailClaimed",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "bailClaimedTotal",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "signature",
"type": "bytes"
}
],
"name": "bailMint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "bailOpen",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "baseURI",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "bountyClaimed",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "bountyMint",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256[]",
"name": "tokenIds",
"type": "uint256[]"
}
],
"name": "bountyMintBatch",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [],
"name": "bountyOpen",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "bountyPrice",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getApproved",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getTransferValidationFunction",
"outputs": [
{
"internalType": "bytes4",
"name": "functionSignature",
"type": "bytes4"
},
{
"internalType": "bool",
"name": "isViewFunction",
"type": "bool"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [],
"name": "getTransferValidator",
"outputs": [
{
"internalType": "address",
"name": "validator",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "operator",
"type": "address"
}
],
"name": "isApprovedForAll",
"outputs": [
{
"internalType": "bool",
"name": "isApproved",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "name",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "ownerOf",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_tokenId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_salePrice",
"type": "uint256"
}
],
"name": "royaltyInfo",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "safeTransferFrom",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "data",
"type": "bytes"
}
],
"name": "safeTransferFrom",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "operator",
"type": "address"
},
{
"internalType": "bool",
"name": "approved",
"type": "bool"
}
],
"name": "setApprovalForAll",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bool",
"name": "autoApprove",
"type": "bool"
}
],
"name": "setAutomaticApprovalOfTransfersFromValidator",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bool",
"name": "_open",
"type": "bool"
}
],
"name": "setBailOpen",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "u",
"type": "string"
}
],
"name": "setBaseURI",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bool",
"name": "_open",
"type": "bool"
}
],
"name": "setBountyOpen",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_p",
"type": "uint256"
}
],
"name": "setBountyPrice",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "receiver",
"type": "address"
},
{
"internalType": "uint96",
"name": "feeNumerator",
"type": "uint96"
}
],
"name": "setDefaultRoyalty",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_signer",
"type": "address"
}
],
"name": "setSigner",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "address",
"name": "receiver",
"type": "address"
},
{
"internalType": "uint96",
"name": "feeNumerator",
"type": "uint96"
}
],
"name": "setTokenRoyalty",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "transferValidator_",
"type": "address"
}
],
"name": "setTransferValidator",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "signer",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes4",
"name": "interfaceId",
"type": "bytes4"
}
],
"name": "supportsInterface",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "teamMint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "teamMintedTotal",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "tokenURI",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalMinted",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "withdraw",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
// ERC721C's royalty enforcement needs an on-chain transfer validator set via
// setTransferValidator (inherited from CreatorTokenBase); until one is
// configured, royalties are advisory only, same as plain ERC-2981.
import "creator-token-standards/access/OwnableBasic.sol";
import "creator-token-standards/erc721c/ERC721C.sol";
import "creator-token-standards/programmable-royalties/BasicRoyalties.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
contract BrimSyndicate is OwnableBasic, ERC721C, BasicRoyalties, EIP712 {
using ECDSA for bytes32;
using Strings for uint256;
uint256 public constant MAX_SUPPLY = 5000;
uint256 public constant TEAM_RESERVE = 100;
uint256 public constant FREE_ALLOCATION = 900;
uint256 public constant FREE_PER_WALLET = 1;
uint256 public constant BOUNTY_PER_WALLET = 10;
uint256 public bountyPrice = 0.0005 ether;
bool public bailOpen;
bool public bountyOpen;
address public signer;
string public baseURI;
mapping(address => uint256) public bailClaimed;
mapping(address => uint256) public bountyClaimed;
uint256 public bailClaimedTotal;
uint256 public teamMintedTotal;
uint256 public totalMinted;
bytes32 private constant VOUCHER_TYPEHASH =
keccak256("Voucher(address wallet,uint256 tokenId)");
constructor(address _signer, string memory _baseURI, address royaltyReceiver_, uint96 royaltyFeeNumerator_)
ERC721OpenZeppelin("Brim Syndicate", "BRIM")
BasicRoyalties(royaltyReceiver_, royaltyFeeNumerator_)
EIP712("Brim Syndicate", "1")
{
signer = _signer;
baseURI = _baseURI;
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721C, ERC2981) returns (bool) {
return ERC721C.supportsInterface(interfaceId) || ERC2981.supportsInterface(interfaceId);
}
modifier onlyEOA() {
require(tx.origin == msg.sender, "no contracts");
_;
}
modifier mintable(uint256 tokenId) {
require(tokenId > TEAM_RESERVE && tokenId <= MAX_SUPPLY, "invalid tokenId");
require(_ownerOf(tokenId) == address(0), "already minted");
_;
}
function teamMint(address to, uint256 tokenId) external {
_requireCallerIsContractOwner();
require(tokenId >= 1 && tokenId <= TEAM_RESERVE, "not reserved");
require(_ownerOf(tokenId) == address(0), "already minted");
teamMintedTotal += 1;
_safeMint(to, tokenId);
}
function bailMint(uint256 tokenId, bytes calldata signature)
external onlyEOA mintable(tokenId)
{
require(bailOpen, "bail closed");
require(bailClaimed[msg.sender] < FREE_PER_WALLET, "already claimed");
require(bailClaimedTotal < FREE_ALLOCATION, "bail sold out");
require(_verify(msg.sender, tokenId, signature), "bad voucher");
bailClaimed[msg.sender] += 1;
bailClaimedTotal += 1;
totalMinted += 1;
_safeMint(msg.sender, tokenId);
}
function bountyMint(uint256 tokenId) external payable onlyEOA mintable(tokenId) {
require(bountyOpen, "bounty closed");
require(bountyClaimed[msg.sender] < BOUNTY_PER_WALLET, "wallet cap");
require(msg.value >= bountyPrice, "underpaid");
bountyClaimed[msg.sender] += 1;
totalMinted += 1;
_safeMint(msg.sender, tokenId);
}
function bountyMintBatch(uint256[] calldata tokenIds) external payable onlyEOA {
require(bountyOpen, "bounty closed");
uint256 n = tokenIds.length;
require(bountyClaimed[msg.sender] + n <= BOUNTY_PER_WALLET, "wallet cap");
require(msg.value >= bountyPrice * n, "underpaid");
bountyClaimed[msg.sender] += n;
totalMinted += n;
for (uint256 i = 0; i < n; i++) {
uint256 tokenId = tokenIds[i];
require(tokenId > TEAM_RESERVE && tokenId <= MAX_SUPPLY, "invalid tokenId");
require(_ownerOf(tokenId) == address(0), "already minted");
_safeMint(msg.sender, tokenId);
}
}
function _verify(address wallet, uint256 tokenId, bytes calldata sig) internal view returns (bool) {
bytes32 digest = _hashTypedDataV4(
keccak256(abi.encode(VOUCHER_TYPEHASH, wallet, tokenId))
);
return digest.recover(sig) == signer;
}
function tokenURI(uint256 tokenId) public view override returns (string memory) {
require(_ownerOf(tokenId) != address(0), "nonexistent");
return string(abi.encodePacked(baseURI, _pad4(tokenId)));
}
function _pad4(uint256 id) internal pure returns (string memory) {
string memory s = id.toString();
bytes memory b = bytes(s);
if (b.length >= 4) return s;
bytes memory padded = new bytes(4);
uint256 zeros = 4 - b.length;
for (uint256 i = 0; i < zeros; i++) padded[i] = "0";
for (uint256 i = 0; i < b.length; i++) padded[zeros + i] = b[i];
return string(padded);
}
function setBailOpen(bool _open) external { _requireCallerIsContractOwner(); bailOpen = _open; }
function setBountyOpen(bool _open) external { _requireCallerIsContractOwner(); bountyOpen = _open; }
function setSigner(address _signer) external { _requireCallerIsContractOwner(); signer = _signer; }
function setBountyPrice(uint256 _p) external { _requireCallerIsContractOwner(); bountyPrice = _p; }
function setBaseURI(string calldata u) external { _requireCallerIsContractOwner(); baseURI = u; }
function setDefaultRoyalty(address receiver, uint96 feeNumerator) public {
_requireCallerIsContractOwner();
_setDefaultRoyalty(receiver, feeNumerator);
}
function setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) public {
_requireCallerIsContractOwner();
_setTokenRoyalty(tokenId, receiver, feeNumerator);
}
function withdraw() external {
_requireCallerIsContractOwner();
(bool ok, ) = payable(owner()).call{value: address(this).balance}("");
require(ok, "withdraw failed");
}
}
Chain explorer5358msChain node86ms