diff --git a/contracts/AdventureParty.sol b/contracts/AdventureParty.sol index 57023e8..0e3e2c2 100644 --- a/contracts/AdventureParty.sol +++ b/contracts/AdventureParty.sol @@ -1,30 +1,33 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.7; -import "./rarity.sol"; +import "./Rarity.sol"; +import "./RarityGold.sol"; import "./Ownable.sol"; contract AdventureParty is Ownable { - rarity public Rarity = rarity(0xce761D788DF608BD21bdd59d6f4B54b2e27F25Bb); + Rarity public rarity = Rarity(0xce761D788DF608BD21bdd59d6f4B54b2e27F25Bb); + RarityGold public rarityGold = RarityGold(0x2069B76Afe6b734Fb65D1d099E7ec64ee9CC76B2); uint[] public adventurers; constructor(uint[] memory classes) { - Rarity.setApprovalForAll(msg.sender, true); + rarity.setApprovalForAll(msg.sender, true); for (uint i = 0; i < classes.length; i++) { - adventurers.push(Rarity.next_summoner()); - Rarity.summon(classes[i]); + adventurers.push(rarity.next_summoner()); + rarity.summon(classes[i]); } } function adventureAll() external { for (uint i = 0; i < adventurers.length; i++) { - Rarity.adventure(adventurers[i]); + rarity.adventure(adventurers[i]); } } function levelUpAll() external { for (uint i = 0; i < adventurers.length; i++) { - Rarity.level_up(adventurers[i]); + rarity.level_up(adventurers[i]); + rarityGold.claim(adventurers[i]); } } } \ No newline at end of file diff --git a/contracts/Greeter.sol b/contracts/Greeter.sol deleted file mode 100644 index efffb8f..0000000 --- a/contracts/Greeter.sol +++ /dev/null @@ -1,22 +0,0 @@ -//SPDX-License-Identifier: Unlicense -pragma solidity ^0.8.0; - -import "hardhat/console.sol"; - -contract Greeter { - string private greeting; - - constructor(string memory _greeting) { - console.log("Deploying a Greeter with greeting:", _greeting); - greeting = _greeting; - } - - function greet() public view returns (string memory) { - return greeting; - } - - function setGreeting(string memory _greeting) public { - console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); - greeting = _greeting; - } -} diff --git a/contracts/rarity.sol b/contracts/Rarity.sol similarity index 99% rename from contracts/rarity.sol rename to contracts/Rarity.sol index 108b9ca..2bc0077 100644 --- a/contracts/rarity.sol +++ b/contracts/Rarity.sol @@ -556,7 +556,7 @@ abstract contract ERC721Enumerable is ERC721, IERC721Enumerable { } } -contract rarity is ERC721 { +contract Rarity is ERC721 { uint public next_summoner; uint constant xp_per_day = 250e18; uint constant DAY = 1 days; diff --git a/contracts/RarityGold.sol b/contracts/RarityGold.sol new file mode 100644 index 0000000..43a2911 --- /dev/null +++ b/contracts/RarityGold.sol @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.7; + +interface IRarity { + function level(uint) external view returns (uint); + function getApproved(uint) external view returns (address); + function ownerOf(uint) external view returns (address); +} + +contract RarityGold { + string public constant name = "Rarity Gold"; + string public constant symbol = "gold"; + uint8 public constant decimals = 18; + + uint public totalSupply = 0; + + IRarity constant rm = IRarity(0xce761D788DF608BD21bdd59d6f4B54b2e27F25Bb); + + mapping(uint => mapping (uint => uint)) public allowance; + mapping(uint => uint) public balanceOf; + + mapping(uint => uint) public claimed; + + event Transfer(uint indexed from, uint indexed to, uint amount); + event Approval(uint indexed from, uint indexed to, uint amount); + + function wealth_by_level(uint level) public pure returns (uint wealth) { + for (uint i = 1; i < level; i++) { + wealth += i * 1000e18; + } + } + + function _isApprovedOrOwner(uint _summoner) internal view returns (bool) { + return rm.getApproved(_summoner) == msg.sender || rm.ownerOf(_summoner) == msg.sender; + } + + + function claimable(uint summoner) external view returns (uint amount) { + require(_isApprovedOrOwner(summoner)); + uint _current_level = rm.level(summoner); + uint _claimed_for = claimed[summoner]+1; + for (uint i = _claimed_for; i <= _current_level; i++) { + amount += wealth_by_level(i); + } + } + + function claim(uint summoner) external { + require(_isApprovedOrOwner(summoner)); + uint _current_level = rm.level(summoner); + uint _claimed_for = claimed[summoner]+1; + for (uint i = _claimed_for; i <= _current_level; i++) { + _mint(summoner, wealth_by_level(i)); + } + claimed[summoner] = _current_level; + } + + function _mint(uint dst, uint amount) internal { + totalSupply += amount; + balanceOf[dst] += amount; + emit Transfer(dst, dst, amount); + } + + function approve(uint from, uint spender, uint amount) external returns (bool) { + require(_isApprovedOrOwner(from)); + allowance[from][spender] = amount; + + emit Approval(from, spender, amount); + return true; + } + + function transfer(uint from, uint to, uint amount) external returns (bool) { + require(_isApprovedOrOwner(from)); + _transferTokens(from, to, amount); + return true; + } + + function transferFrom(uint executor, uint from, uint to, uint amount) external returns (bool) { + require(_isApprovedOrOwner(executor)); + uint spender = executor; + uint spenderAllowance = allowance[from][spender]; + + if (spender != from && spenderAllowance != type(uint).max) { + uint newAllowance = spenderAllowance - amount; + allowance[from][spender] = newAllowance; + + emit Approval(from, spender, newAllowance); + } + + _transferTokens(from, to, amount); + return true; + } + + function _transferTokens(uint from, uint to, uint amount) internal { + balanceOf[from] -= amount; + balanceOf[to] += amount; + + emit Transfer(from, to, amount); + } +} \ No newline at end of file diff --git a/test/test.ts b/test/test.ts index 0a42120..bf6f5b0 100644 --- a/test/test.ts +++ b/test/test.ts @@ -1,9 +1,9 @@ import { expect } from "chai"; import { ethers } from "hardhat"; -import { AdventureParty__factory, Rarity } from "../typechain" +import { AdventureParty__factory, Rarity, RarityGold } from "../typechain" describe("AdventurePaty", function () { - it("Should summon and level up", async function () { + it("Should summon", async function () { const AdventureParty = await ethers.getContractFactory("AdventureParty"); const adventureParty = await AdventureParty.deploy([1,2,3,4,5]); await adventureParty.deployed(); @@ -12,7 +12,7 @@ describe("AdventurePaty", function () { await adventureParty.adventureAll(); - const rarity = await ethers.getContractAt("rarity", await adventureParty.Rarity()); + const rarity = await ethers.getContractAt("Rarity", await adventureParty.rarity()); const xp0 = parseInt(ethers.utils.formatEther(await rarity.xp(p0))); @@ -23,4 +23,24 @@ describe("AdventurePaty", function () { await ethers.provider.send('evm_increaseTime', [24*60*60]); await adventureParty.adventureAll(); }); -}); + + it("Should level up and claim gold", async function () { + const AdventureParty = await ethers.getContractFactory("AdventureParty"); + const adventureParty = await AdventureParty.deploy([1,2,3,4,5]); + await adventureParty.deployed(); + + await adventureParty.adventureAll(); + + for (let i = 0; i < 3; i ++) { + await ethers.provider.send('evm_increaseTime', [24*60*60 + 1]); + await adventureParty.adventureAll(); + } + + await adventureParty.levelUpAll(); + + const rarityGold = await ethers.getContractAt("RarityGold", await adventureParty.rarityGold()); + + console.log("Adventurer 0 balance ", + ethers.utils.formatEther(await rarityGold.balanceOf(await adventureParty.adventurers(0)))); + }); +}); \ No newline at end of file