Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Update reward facet to mint badges #126

Merged
merged 7 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/warm-ladybugs-share.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@openformat/contracts": minor
---

update rewards facet to mint badges
23 changes: 22 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,27 @@ ERC721Badge.setBaseURI:; forge script \
--rpc-url $(rpc) --broadcast $(verbose) $(legacy) $(slow) \
$(word 1, $(args)) $(word 2, $(args))

# example: make ERC721Base.setBaseURI args="0xaf4c80136581212185f37c5e8809120d8fbf6224 sometokenuri"
# example: make ERC721Base.mintTo args="0xaf4c80136581212185f37c5e8809120d8fbf6224 sometokenuri"
ERC721Base.mintTo:; forge script \
scripts/tokens/ERC721Base.s.sol:MintTo \
--sig "run(address,string)" \
--rpc-url $(rpc) --broadcast $(verbose) $(legacy) $(slow) \
$(word 1, $(args)) $(word 2, $(args))

# pass the badge contract address as an argument
# example: make RewardFacet.mintBadge args="0xaf4c80136581212185f37c5e8809120d8fbf6224"
RewardsFacet.mintBadge:; forge script \
scripts/facet/RewardsFacet.s.sol:mintBadge \
--sig "run(address)" \
--rpc-url $(rpc) --broadcast $(verbose) $(legacy) $(slow) $(args)

# pass the badge contract address as an argument
# example: make RewardFacet.batchMintBadge args="0xaf4c80136581212185f37c5e8809120d8fbf6224"
RewardsFacet.batchMintBadge:; forge script \
scripts/facet/RewardsFacet.s.sol:batchMintBadge \
--sig "run(address)" \
--rpc-url $(rpc) --broadcast $(verbose) $(legacy) $(slow) $(args)

# Run all update scripts
update:; make \
update-ERC721FactoryFacet \
Expand All @@ -124,6 +138,13 @@ update:; make \
update-ERC721FactoryFacet:; forge script scripts/facet/ERC721FactoryFacet.s.sol:Update --rpc-url $(rpc) --broadcast $(verbose) $(legacy) $(slow)
update-ERC20FactoryFacet:; forge script scripts/facet/ERC20FactoryFacet.s.sol:Update --rpc-url $(rpc) --broadcast $(verbose) $(legacy) $(slow)

# Add badge minting functionality
# Date 20.05.24
# updates ERC721RewardFacet to update mintERC721 function and add mintBadge and batchMintBadge functions
# deploys and registers RewardsFacet contract
# PR #126 https://github.com/open-format/contracts/pull/126
update-RewardsFacet:; forge script scripts/facet/RewardsFacet.s.sol:Update_Add_badgeMintingFunctionality --rpc-url $(rpc) --broadcast $(verbose) $(legacy) $(slow)

# Add ERC721Badge contract
# Date 14.05.24
# updates ERC721FactoryFacet to change the createERC721 function to include a baseTokenURI paramerter
Expand Down
80 changes: 78 additions & 2 deletions scripts/facet/RewardsFacet.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ contract Deploy is Script, Utils {
RewardsFacet rewardsFacet = new RewardsFacet();

// construct array of function selectors
bytes4[] memory selectors = new bytes4[](5);
bytes4[] memory selectors = new bytes4[](7);
selectors[0] = rewardsFacet.mintERC20.selector;
selectors[1] = rewardsFacet.transferERC20.selector;
selectors[2] = rewardsFacet.mintERC721.selector;
selectors[3] = rewardsFacet.transferERC721.selector;
selectors[4] = rewardsFacet.multicall.selector;
selectors[5] = rewardsFacet.mintBadge.selector;
selectors[6] = rewardsFacet.batchMintBadge.selector;

// construct and ADD facet cut
IDiamondWritableInternal.FacetCut[] memory cuts = new IDiamondWritableInternal.FacetCut[](1);
Expand All @@ -53,12 +55,14 @@ contract Update is Script, Utils {
RewardsFacet rewardsFacet = new RewardsFacet();

// construct array of function selectors
bytes4[] memory selectors = new bytes4[](5);
bytes4[] memory selectors = new bytes4[](7);
selectors[0] = rewardsFacet.mintERC20.selector;
selectors[1] = rewardsFacet.transferERC20.selector;
selectors[2] = rewardsFacet.mintERC721.selector;
selectors[3] = rewardsFacet.transferERC721.selector;
selectors[4] = rewardsFacet.multicall.selector;
selectors[5] = rewardsFacet.mintBadge.selector;
selectors[6] = rewardsFacet.batchMintBadge.selector;

// construct and ADD facet cut
IDiamondWritableInternal.FacetCut[] memory cuts = new IDiamondWritableInternal.FacetCut[](1);
Expand All @@ -74,3 +78,75 @@ contract Update is Script, Utils {
exportContractDeployment(CONTRACT_NAME, address(rewardsFacet), block.number);
}
}

contract mintBadge is Script, Utils {
function run(address _badgeContract) public {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
address deployerAddress = vm.addr(deployerPrivateKey);
address appId = vm.envAddress("APP_ID");
vm.startBroadcast(deployerPrivateKey);

RewardsFacet rewardsFacet = RewardsFacet(appId);

rewardsFacet.mintBadge(_badgeContract, deployerAddress, "collected berries", "action", "");

vm.stopBroadcast();
}
}

contract batchMintBadge is Script, Utils {
function run(address _badgeContract) public {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
address deployerAddress = vm.addr(deployerPrivateKey);
address appId = vm.envAddress("APP_ID");
vm.startBroadcast(deployerPrivateKey);

RewardsFacet rewardsFacet = RewardsFacet(appId);

rewardsFacet.batchMintBadge(_badgeContract, deployerAddress, 10, "collected berries", "action", "");

vm.stopBroadcast();
}
}

/**
* @dev use this script to updated deployments made previous to PR #126 https://github.com/open-format/contracts/pull/126/files
*/
contract Update_Add_badgeMintingFunctionality is Script, Utils {
function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);

// deploy
RewardsFacet rewardsFacet = new RewardsFacet();

// construct array of function selectors to replace
bytes4[] memory replaceSelectors = new bytes4[](5);
replaceSelectors[0] = rewardsFacet.mintERC20.selector;
replaceSelectors[1] = rewardsFacet.transferERC20.selector;
replaceSelectors[2] = rewardsFacet.mintERC721.selector;
replaceSelectors[3] = rewardsFacet.transferERC721.selector;
replaceSelectors[4] = rewardsFacet.multicall.selector;

// construct array of function selectors to add
bytes4[] memory addSelectors = new bytes4[](2);
addSelectors[0] = rewardsFacet.mintBadge.selector;
addSelectors[1] = rewardsFacet.batchMintBadge.selector;

// construct and ADD facet cut
IDiamondWritableInternal.FacetCut[] memory cuts = new IDiamondWritableInternal.FacetCut[](2);
cuts[0] = IDiamondWritableInternal.FacetCut(
address(rewardsFacet), IDiamondWritableInternal.FacetCutAction.REPLACE, replaceSelectors
);
cuts[1] = IDiamondWritableInternal.FacetCut(
address(rewardsFacet), IDiamondWritableInternal.FacetCutAction.ADD, addSelectors
);

// add to registry
RegistryMock(payable(getContractDeploymentAddress("Registry"))).diamondCut(cuts, address(0), "");

vm.stopBroadcast();

exportContractDeployment(CONTRACT_NAME, address(rewardsFacet), block.number);
}
}
69 changes: 66 additions & 3 deletions src/facet/RewardsFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ interface NFT {
function ownerOf(uint256 tokenId) external returns (address);
}

interface Badge {
function mintTo(address to) external;
function batchMintTo(address to, uint256 quantity) external;
function transferFrom(address from, address to, uint256 tokenId) external;
function ownerOf(uint256 tokenId) external returns (address);
}

interface Token {
function mintTo(address to, uint256 amount) external;
function transferFrom(address holder, address receipient, uint256 amount) external;
Expand All @@ -28,7 +35,10 @@ bytes32 constant MINTER_ROLE = bytes32(uint256(1));
contract RewardsFacet is Multicall, SafeOwnable {
event TokenMinted(address token, address to, uint256 amount, bytes32 id, bytes32 activityType, string uri);
event TokenTransferred(address token, address to, uint256 amount, bytes32 id, bytes32 activityType, string uri);
event BadgeMinted(address token, uint256 quantity, address to, bytes32 id, bytes32 activityType, string uri);
event ERC721Minted(address token, uint256 quantity, address to, bytes32 id, bytes32 activityType, string uri);
event BadgeMinted(
address token, uint256 quantity, address to, bytes32 activityId, bytes32 activityType, bytes data
);
event BadgeTransferred(address token, address to, uint256 tokenId, bytes32 id, bytes32 activityType, string uri);

error RewardsFacet_NotAuthorized();
Expand Down Expand Up @@ -62,6 +72,60 @@ contract RewardsFacet is Multicall, SafeOwnable {
emit TokenTransferred(_token, _to, _amount, _id, _activityType, _uri);
}

/**
* @notice Mints a number of badges to an address and broadcasts activity metadata
* @dev The sender must have a role of admin or minter on the badge contract.
* The app being called must have a minter role on the badge contract.
* The activity metadata is emitted as an event for indexing.
* @param _badgeContract The address of the ERC721 contract that represents all badges of the same type
* @param _to The address of the recipient of the badges
* @param _quantity The amount of badges to mint
* @param _activityId The id associated with this activity for example "beat the boss" or "collected 100 berries"
* @param _activityType The type of activity e.g "mission" or "action"
* @param _data Any other data that will be useful
*/
function batchMintBadge(
address _badgeContract,
address _to,
uint256 _quantity,
bytes32 _activityId,
bytes32 _activityType,
bytes calldata _data
) public {
if (!_canMint(_badgeContract)) {
revert RewardsFacet_NotAuthorized();
}

Badge(_badgeContract).batchMintTo(_to, _quantity);
emit BadgeMinted(_badgeContract, _quantity, _to, _activityId, _activityType, _data);
}

/**
* @notice Mints one badge to an address and broadcasts activity metadata.
* @dev The sender must have a role of admin or minter on the badge contract.
* The app being called must have a minter role on the badge contract.
* The activity metadata is emitted as an event for indexing.
* @param _badgeContract The address of the ERC721 contract that represents all badges of the same type
* @param _to The address of the recipient of the badge
* @param _activityId The id associated with this activity for example "beat the boss" or "collected 100 berries"
* @param _activityType The type of activity for example "mission" or "action"
* @param _data Any other data that will be useful
*/
function mintBadge(
address _badgeContract,
address _to,
bytes32 _activityId,
bytes32 _activityType,
bytes calldata _data
) public {
if (!_canMint(_badgeContract)) {
revert RewardsFacet_NotAuthorized();
}

Badge(_badgeContract).mintTo(_to);
emit BadgeMinted(_badgeContract, 1, _to, _activityId, _activityType, _data);
}

function mintERC721(
address _token,
address _to,
Expand All @@ -74,9 +138,8 @@ contract RewardsFacet is Multicall, SafeOwnable {
if (!_canMint(_token)) {
revert RewardsFacet_NotAuthorized();
}

NFT(_token).batchMintTo(_to, _quantity, _baseURI);
emit BadgeMinted(_token, _quantity, _to, _id, _activityType, _uri);
emit ERC721Minted(_token, _quantity, _to, _id, _activityType, _uri);
}

function transferERC721(
Expand Down
Loading
Loading