// SPDX-License-Identifier: MPL-2.0
pragma solidity ^0.8.17;
import {console} from "forge-std/console.sol";
import "@le7el/generative_art/src/SVG9x9.sol";
import "@le7el/generative_art/src/EncodeUtils.sol";
import {ContributorMetadataProxyV1} from "src/nft/ContributorMetadataProxyV1.sol";
import {TestWithDeployments} from "./util/TestWithDeployments.sol";
import {ERC1155BurnableMock} from "@openzeppelin/contracts/mocks/ERC1155BurnableMock.sol";
import {IVirtualDistributor} from "../src/interface/IVirtualDistributor.sol";
contract MockRewarder is IVirtualDistributor {
mapping(uint256 => uint256) public rewardsFor;
mapping(uint256 => bool) public unlockedFor;
function test() public {}
function setRewardFor(uint256 _tokenId, uint256 _amount) external {
rewardsFor[_tokenId] = _amount;
}
function setUnlockedFor(uint256 _tokenId, bool _status) external {
unlockedFor[_tokenId] = _status;
}
function pendingRewards(address, uint256 _tokenId) external view returns (uint256) {
return rewardsFor[_tokenId];
}
function isRewardSafelyLocked(address, uint256 _tokenId) external view returns (bool) {
return !unlockedFor[_tokenId];
}
}
contract ContributorMetadataTest is TestWithDeployments {
uint256 internal constant YEAR = 365 days;
ERC1155BurnableMock internal expToken;
MockRewarder internal rewarder;
address internal admin = address(1);
address internal user = address(2);
function setUp() public {
vm.label(admin, "Admin");
vm.label(user, "User");
// Setup smart contracts
vm.startPrank(admin);
deployAll(admin);
rewarder = new MockRewarder();
ContributorMetadataProxyV1 metadata = new ContributorMetadataProxyV1(crs, contributorController.baseNode());
contributorNFT.setBasenodeResolverSettings(abi.encodeWithSignature(
"setProxyConfig(bytes32,address,bytes4,address)",
contributorNFT.baseNode(),
address(contributorNFT),
bytes4(keccak256("tokenURI(uint256,string,string)")),
address(metadata)
));
expToken = new ERC1155BurnableMock("https://test.metadata/{id}");
expToken.mint(user, 1, 190000, "");
contributorNFT.setBasenodeResolverSettings(abi.encodeWithSignature(
"setProjectLevelingRules(bytes32,address,address,uint256,bytes4)",
contributorController.baseNode(),
address(0),
address(expToken),
1,
bytes4(0xf5298aca)
));
contributorNFT.setBasenodeResolverSettings(abi.encodeWithSignature(
"setText(bytes32,string,string)",
contributorController.baseNode(),
"L7L_REWARDS_DISTRIBUTOR",
string(abi.encode(address(rewarder)))
));
vm.stopPrank();
}
function testMetadataValidness() public {
vm.startPrank(user);
registerContributorNFT(user, keccak256("secret"), YEAR, "johndoe");
string memory rawMetadata = contributorNFT.tokenURI(86745341786912841616557368118532256523691956314975099975829920571153145112669);
string memory refMetadata = string(abi.encodePacked(
"data:application/json;base64,",
EncodeUtils.base64(bytes('{\"name\":\"johndoe.contributor\",\"description\":\"LE7EL contributor\",\"image_data\":\"\",\"attributes\":[{\"trait_type\":\"Type\",\"value\":\"Contributor\"},{\"trait_type\":\"Level\",\"value\":1},{\"trait_type\":\"Experience\",\"value\":0},{\"trait_type\":\"L7L claims\",\"value\":0.00}]}'))
));
assertTrue(keccak256(bytes(rawMetadata)) == keccak256(bytes(refMetadata)));
vm.stopPrank();
}
function testMetadataWithLevels() public {
vm.startPrank(user);
registerContributorNFT(user, keccak256("secret"), YEAR, "johndoe");
expToken.setApprovalForAll(address(resolver), true);
assertTrue(resolver.advanceToNextLevel(contributorController.baseNode(), nameToContributorNode("johndoe"), 1200) == 1200);
string memory rawMetadata = contributorNFT.tokenURI(86745341786912841616557368118532256523691956314975099975829920571153145112669);
string memory refMetadata = string(abi.encodePacked(
"data:application/json;base64,",
EncodeUtils.base64(bytes('{\"name\":\"johndoe.contributor\",\"description\":\"LE7EL contributor\",\"image_data\":\"\",\"attributes\":[{\"trait_type\":\"Type\",\"value\":\"Contributor\"},{\"trait_type\":\"Level\",\"value\":2},{\"trait_type\":\"Experience\",\"value\":1200},{\"trait_type\":\"L7L claims\",\"value\":0.00}]}'))
));
assertTrue(keccak256(bytes(rawMetadata)) == keccak256(bytes(refMetadata)));
vm.stopPrank();
}
function testCustomNFTImages() public {
vm.startPrank(user);
registerContributorNFT(user, keccak256("secret"), YEAR, "johndoe");
resolver.setText(0xc7c7c25e735ebd8bc31c2434182c6c760cfadb7ffaa60d3b08a287c50ad57554, "L7L_CONTRIBUTOR_IMAGE", "ipfs://chubaka.jpg");
string memory rawMetadata = contributorNFT.tokenURI(86745341786912841616557368118532256523691956314975099975829920571153145112669);
string memory refMetadata = string(abi.encodePacked(
"data:application/json;base64,",
EncodeUtils.base64(bytes('{\"name\":\"johndoe.contributor\",\"description\":\"LE7EL contributor\",\"image\":\"ipfs://chubaka.jpg\",\"attributes\":[{\"trait_type\":\"Type\",\"value\":\"Contributor\"},{\"trait_type\":\"Level\",\"value\":1},{\"trait_type\":\"Experience\",\"value\":0},{\"trait_type\":\"L7L claims\",\"value\":0.00}]}'))
));
assertTrue(keccak256(bytes(rawMetadata)) == keccak256(bytes(refMetadata)));
vm.stopPrank();
}
function testMetadataWithLevelTokens() public {
vm.startPrank(user);
registerContributorNFT(user, keccak256("secret"), YEAR, "johndoe");
resolver.setText(0xc7c7c25e735ebd8bc31c2434182c6c760cfadb7ffaa60d3b08a287c50ad57554, "L7L_CONTRIBUTOR_IMAGE", "ipfs://chubaka.jpg");
// 0.00
rewarder.setRewardFor(86745341786912841616557368118532256523691956314975099975829920571153145112669, 0);
string memory rawMetadata = contributorNFT.tokenURI(86745341786912841616557368118532256523691956314975099975829920571153145112669);
string memory refMetadata = string(abi.encodePacked(
"data:application/json;base64,",
EncodeUtils.base64(bytes('{\"name\":\"johndoe.contributor\",\"description\":\"LE7EL contributor\",\"image\":\"ipfs://chubaka.jpg\",\"attributes\":[{\"trait_type\":\"Type\",\"value\":\"Contributor\"},{\"trait_type\":\"Level\",\"value\":1},{\"trait_type\":\"Experience\",\"value\":0},{\"trait_type\":\"L7L claims\",\"value\":0.00}]}'))
));
assertTrue(keccak256(bytes(rawMetadata)) == keccak256(bytes(refMetadata)));
// 0.05
rewarder.setRewardFor(86745341786912841616557368118532256523691956314975099975829920571153145112669, 5e16);
rawMetadata = contributorNFT.tokenURI(86745341786912841616557368118532256523691956314975099975829920571153145112669);
refMetadata = string(abi.encodePacked(
"data:application/json;base64,",
EncodeUtils.base64(bytes('{\"name\":\"johndoe.contributor\",\"description\":\"LE7EL contributor\",\"image\":\"ipfs://chubaka.jpg\",\"attributes\":[{\"trait_type\":\"Type\",\"value\":\"Contributor\"},{\"trait_type\":\"Level\",\"value\":1},{\"trait_type\":\"Experience\",\"value\":0},{\"trait_type\":\"L7L claims\",\"value\":0.05}]}'))
));
// 0.50
rewarder.setRewardFor(86745341786912841616557368118532256523691956314975099975829920571153145112669, 5e17);
rawMetadata = contributorNFT.tokenURI(86745341786912841616557368118532256523691956314975099975829920571153145112669);
refMetadata = string(abi.encodePacked(
"data:application/json;base64,",
EncodeUtils.base64(bytes('{\"name\":\"johndoe.contributor\",\"description\":\"LE7EL contributor\",\"image\":\"ipfs://chubaka.jpg\",\"attributes\":[{\"trait_type\":\"Type\",\"value\":\"Contributor\"},{\"trait_type\":\"Level\",\"value\":1},{\"trait_type\":\"Experience\",\"value\":0},{\"trait_type\":\"L7L claims\",\"value\":0.50}]}'))
));
// 5.00
rewarder.setRewardFor(86745341786912841616557368118532256523691956314975099975829920571153145112669, 5e18);
rawMetadata = contributorNFT.tokenURI(86745341786912841616557368118532256523691956314975099975829920571153145112669);
refMetadata = string(abi.encodePacked(
"data:application/json;base64,",
EncodeUtils.base64(bytes('{\"name\":\"johndoe.contributor\",\"description\":\"LE7EL contributor\",\"image\":\"ipfs://chubaka.jpg\",\"attributes\":[{\"trait_type\":\"Type\",\"value\":\"Contributor\"},{\"trait_type\":\"Level\",\"value\":1},{\"trait_type\":\"Experience\",\"value\":0},{\"trait_type\":\"L7L claims\",\"value\":5.00}]}'))
));
assertTrue(keccak256(bytes(rawMetadata)) == keccak256(bytes(refMetadata)));
// 5.55
rewarder.setRewardFor(86745341786912841616557368118532256523691956314975099975829920571153145112669, 5e18 + 5e17 + 5e16);
rawMetadata = contributorNFT.tokenURI(86745341786912841616557368118532256523691956314975099975829920571153145112669);
refMetadata = string(abi.encodePacked(
"data:application/json;base64,",
EncodeUtils.base64(bytes('{\"name\":\"johndoe.contributor\",\"description\":\"LE7EL contributor\",\"image\":\"ipfs://chubaka.jpg\",\"attributes\":[{\"trait_type\":\"Type\",\"value\":\"Contributor\"},{\"trait_type\":\"Level\",\"value\":1},{\"trait_type\":\"Experience\",\"value\":0},{\"trait_type\":\"L7L claims\",\"value\":5.55}]}'))
));
assertTrue(keccak256(bytes(rawMetadata)) == keccak256(bytes(refMetadata)));
// 55.55
rewarder.setRewardFor(86745341786912841616557368118532256523691956314975099975829920571153145112669, 5e19 + 5e18 + 5e17 + 5e16);
rawMetadata = contributorNFT.tokenURI(86745341786912841616557368118532256523691956314975099975829920571153145112669);
refMetadata = string(abi.encodePacked(
"data:application/json;base64,",
EncodeUtils.base64(bytes('{\"name\":\"johndoe.contributor\",\"description\":\"LE7EL contributor\",\"image\":\"ipfs://chubaka.jpg\",\"attributes\":[{\"trait_type\":\"Type\",\"value\":\"Contributor\"},{\"trait_type\":\"Level\",\"value\":1},{\"trait_type\":\"Experience\",\"value\":0},{\"trait_type\":\"L7L claims\",\"value\":55.55}]}'))
));
assertTrue(keccak256(bytes(rawMetadata)) == keccak256(bytes(refMetadata)));
// 55.5555 overflow
rewarder.setRewardFor(86745341786912841616557368118532256523691956314975099975829920571153145112669, 5e19 + 5e18 + 5e17 + 5e16 + 5e15 + 5e14);
rawMetadata = contributorNFT.tokenURI(86745341786912841616557368118532256523691956314975099975829920571153145112669);
refMetadata = string(abi.encodePacked(
"data:application/json;base64,",
EncodeUtils.base64(bytes('{\"name\":\"johndoe.contributor\",\"description\":\"LE7EL contributor\",\"image\":\"ipfs://chubaka.jpg\",\"attributes\":[{\"trait_type\":\"Type\",\"value\":\"Contributor\"},{\"trait_type\":\"Level\",\"value\":1},{\"trait_type\":\"Experience\",\"value\":0},{\"trait_type\":\"L7L claims\",\"value\":55.55}]}'))
));
assertTrue(keccak256(bytes(rawMetadata)) == keccak256(bytes(refMetadata)));
vm.stopPrank();
}
}