diff --git a/README.md b/README.md index 3d6fd33..81383f3 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,11 @@ ___ ___ +Note: `game` branch +* Polygon-based smart contract for NFT cards +* Building an [api component](https://github.com/signal-k/dabpi) on top of smart contract +* Build moralis api into this branch + ## 📝 What is "Signal-K/polygon"? diff --git a/contracts/.DS_Store b/contracts/.DS_Store deleted file mode 100644 index 9e0080c..0000000 Binary files a/contracts/.DS_Store and /dev/null differ diff --git a/contracts/1_Storage.sol b/contracts/1_Storage.sol deleted file mode 100644 index 2958b79..0000000 --- a/contracts/1_Storage.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 - -pragma solidity >=0.7.0 <0.9.0; - -/** - * @title Storage - * @dev Store & retrieve value in a variable - */ -contract Storage { - - uint256 number; - - /** - * @dev Store value in variable - * @param num value to store - */ - function store(uint256 num) public { - number = num; - } - - /** - * @dev Return value - * @return value of 'number' - */ - function retrieve() public view returns (uint256){ - return number; - } -} \ No newline at end of file diff --git a/contracts/2_Owner.sol b/contracts/2_Owner.sol deleted file mode 100644 index 601ee32..0000000 --- a/contracts/2_Owner.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 - -pragma solidity >=0.7.0 <0.9.0; - -/** - * @title Owner - * @dev Set & change owner - */ -contract Owner { - - address private owner; - - // event for EVM logging - event OwnerSet(address indexed oldOwner, address indexed newOwner); - - // modifier to check if caller is owner - modifier isOwner() { - // If the first argument of 'require' evaluates to 'false', execution terminates and all - // changes to the state and to Ether balances are reverted. - // This used to consume all gas in old EVM versions, but not anymore. - // It is often a good idea to use 'require' to check if functions are called correctly. - // As a second argument, you can also provide an explanation about what went wrong. - require(msg.sender == owner, "Caller is not owner"); - _; - } - - /** - * @dev Set contract deployer as owner - */ - constructor() { - owner = msg.sender; // 'msg.sender' is sender of current call, contract deployer for a constructor - emit OwnerSet(address(0), owner); - } - - /** - * @dev Change owner - * @param newOwner address of new owner - */ - function changeOwner(address newOwner) public isOwner { - emit OwnerSet(owner, newOwner); - owner = newOwner; - } - - /** - * @dev Return owner address - * @return address of owner - */ - function getOwner() external view returns (address) { - return owner; - } -} \ No newline at end of file diff --git a/contracts/3_Ballot.sol b/contracts/3_Ballot.sol deleted file mode 100644 index c47be92..0000000 --- a/contracts/3_Ballot.sol +++ /dev/null @@ -1,138 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 - -pragma solidity >=0.7.0 <0.9.0; - -/** - * @title Ballot - * @dev Implements voting process along with vote delegation - */ -contract Ballot { - - struct Voter { - uint weight; // weight is accumulated by delegation - bool voted; // if true, that person already voted - address delegate; // person delegated to - uint vote; // index of the voted proposal - } - - struct Proposal { - // If you can limit the length to a certain number of bytes, - // always use one of bytes1 to bytes32 because they are much cheaper - bytes32 name; // short name (up to 32 bytes) - uint voteCount; // number of accumulated votes - } - - address public chairperson; - - mapping(address => Voter) public voters; - - Proposal[] public proposals; - - /** - * @dev Create a new ballot to choose one of 'proposalNames'. - * @param proposalNames names of proposals - */ - constructor(bytes32[] memory proposalNames) { - chairperson = msg.sender; - voters[chairperson].weight = 1; - - for (uint i = 0; i < proposalNames.length; i++) { - // 'Proposal({...})' creates a temporary - // Proposal object and 'proposals.push(...)' - // appends it to the end of 'proposals'. - proposals.push(Proposal({ - name: proposalNames[i], - voteCount: 0 - })); - } - } - - /** - * @dev Give 'voter' the right to vote on this ballot. May only be called by 'chairperson'. - * @param voter address of voter - */ - function giveRightToVote(address voter) public { - require( - msg.sender == chairperson, - "Only chairperson can give right to vote." - ); - require( - !voters[voter].voted, - "The voter already voted." - ); - require(voters[voter].weight == 0); - voters[voter].weight = 1; - } - - /** - * @dev Delegate your vote to the voter 'to'. - * @param to address to which vote is delegated - */ - function delegate(address to) public { - Voter storage sender = voters[msg.sender]; - require(!sender.voted, "You already voted."); - require(to != msg.sender, "Self-delegation is disallowed."); - - while (voters[to].delegate != address(0)) { - to = voters[to].delegate; - - // We found a loop in the delegation, not allowed. - require(to != msg.sender, "Found loop in delegation."); - } - sender.voted = true; - sender.delegate = to; - Voter storage delegate_ = voters[to]; - if (delegate_.voted) { - // If the delegate already voted, - // directly add to the number of votes - proposals[delegate_.vote].voteCount += sender.weight; - } else { - // If the delegate did not vote yet, - // add to her weight. - delegate_.weight += sender.weight; - } - } - - /** - * @dev Give your vote (including votes delegated to you) to proposal 'proposals[proposal].name'. - * @param proposal index of proposal in the proposals array - */ - function vote(uint proposal) public { - Voter storage sender = voters[msg.sender]; - require(sender.weight != 0, "Has no right to vote"); - require(!sender.voted, "Already voted."); - sender.voted = true; - sender.vote = proposal; - - // If 'proposal' is out of the range of the array, - // this will throw automatically and revert all - // changes. - proposals[proposal].voteCount += sender.weight; - } - - /** - * @dev Computes the winning proposal taking all previous votes into account. - * @return winningProposal_ index of winning proposal in the proposals array - */ - function winningProposal() public view - returns (uint winningProposal_) - { - uint winningVoteCount = 0; - for (uint p = 0; p < proposals.length; p++) { - if (proposals[p].voteCount > winningVoteCount) { - winningVoteCount = proposals[p].voteCount; - winningProposal_ = p; - } - } - } - - /** - * @dev Calls winningProposal() function to get the index of the winner contained in the proposals array and then - * @return winnerName_ the name of the winner - */ - function winnerName() public view - returns (bytes32 winnerName_) - { - winnerName_ = proposals[winningProposal()].name; - } -} diff --git a/contracts/CreditTokenRef.sol b/contracts/CreditTokenRef.sol new file mode 100644 index 0000000..d0e7908 --- /dev/null +++ b/contracts/CreditTokenRef.sol @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +contract LipToken is ERC721, Ownable { + constructor(string memory _name, string memory _symbol) + ERC721(_name, _symbol) + {} + + uint256 COUNTER; + + uint256 fee = 0.01 ether; + + struct Lip { + string name; + uint256 id; + uint256 dna; + uint8 level; + uint8 rarity; + } + + Lip[] public lips; + + event NewLip(address indexed owner, uint256 id, uint256 dna); + + // Helpers + function _createRandomNum(uint256 _mod) internal view returns (uint256) { + uint256 randomNum = uint256( + keccak256(abi.encodePacked(block.timestamp, msg.sender)) + ); + return randomNum % _mod; + } + + function updateFee(uint256 _fee) external onlyOwner { + fee = _fee; + } + + function withdraw() external payable onlyOwner { + address payable _owner = payable(owner()); + _owner.transfer(address(this).balance); + } + + // Creation + function _createLip(string memory _name) internal { + uint8 randRarity = uint8(_createRandomNum(100)); + uint256 randDna = _createRandomNum(10**16); + Lip memory newLip = Lip(_name, COUNTER, randDna, 1, randRarity); + lips.push(newLip); + _safeMint(msg.sender, COUNTER); + emit NewLip(msg.sender, COUNTER, randDna); + COUNTER++; + } + + function createRandomLip(string memory _name) public payable { + require(msg.value >= fee); + _createLip(_name); + } + + // Getters + function getLips() public view returns (Lip[] memory) { + return lips; + } + + function getOwnerLips(address _owner) public view returns (Lip[] memory) { + Lip[] memory result = new Lip[](balanceOf(_owner)); + uint256 counter = 0; + for (uint256 i = 0; i < lips.length; i++) { + if (ownerOf(i) == _owner) { + result[counter] = lips[i]; + counter++; + } + } + return result; + } + + // Actions + function levelUp(uint256 _lipId) public { + require(ownerOf(_lipId) == msg.sender); + Lip storage lip = lips[_lipId]; + lip.level++; + } +} \ No newline at end of file diff --git a/contracts/GearToken.sol b/contracts/GearToken.sol new file mode 100644 index 0000000..d259557 --- /dev/null +++ b/contracts/GearToken.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol"; +import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol"; + +contract GearToken is ERC721, Ownable { + uint256 COUNTER; // Incremental function for indexing of NFTs + + struct Gear { + string name; + uint256 id; + uint256 dna; + uint8 level; + uint8 rarity; + } + + Gear[] public gears; + + constructor(string memory _name, string memory _symbol) + ERC721(_name, _symbol) + {} + + // Minting function + function _createGear(string memory _name, uint256 _dna) internal { + Gear memory newGear = Gear(_name, COUNTER, _dna, 1, 50); + gears.push(newGear); // Adds the new gear onto the array + /*_safeMint(_to, COUNTER); // Who is the NFT for?, what is the identifier of the NFT that's being minted? + COUNTER++;*/ + } +} \ No newline at end of file diff --git a/contracts/Token.sol b/contracts/Token.sol deleted file mode 100644 index 2c263f0..0000000 --- a/contracts/Token.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.11; - -import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol"; - -contract Token is ERC20 { - constructor () public ERC20("KinetiKoin", "SKK") { // Coin name: KinetiKoin, short name: SKK - _mint(msg.sender, 1000000 * (10 ** uint256(decimals()))); // Minting 1000000 tokens to the sender, which is ourselves (at the start) (see bottom comments section) - } -} - -/* - msg.sender refers to whoever is interacting with the s.contract through this function. -*/ \ No newline at end of file diff --git a/scripts/deploy_ethers.js b/scripts/deploy_ethers.js deleted file mode 100644 index 14eae13..0000000 --- a/scripts/deploy_ethers.js +++ /dev/null @@ -1,29 +0,0 @@ -// Right click on the script name and hit "Run" to execute -(async () => { - try { - console.log('Running deployWithEthers script...') - - const contractName = 'Storage' // Change this for other contract - const constructorArgs = [] // Put constructor args (if any) here for your contract - - // Note that the script needs the ABI which is generated from the compilation artifact. - // Make sure contract is compiled and artifacts are generated - const artifactsPath = `browser/contracts/artifacts/${contractName}.json` // Change this for different path - - const metadata = JSON.parse(await remix.call('fileManager', 'getFile', artifactsPath)) - // 'web3Provider' is a remix global variable object - const signer = (new ethers.providers.Web3Provider(web3Provider)).getSigner() - - let factory = new ethers.ContractFactory(metadata.abi, metadata.data.bytecode.object, signer); - - let contract = await factory.deploy(...constructorArgs); - - console.log('Contract Address: ', contract.address); - - // The contract is NOT deployed yet; we must wait until it is mined - await contract.deployed() - console.log('Deployment successful.') - } catch (e) { - console.log(e.message) - } -})() \ No newline at end of file diff --git a/scripts/deploy_web3.js b/scripts/deploy_web3.js deleted file mode 100644 index 441dcd4..0000000 --- a/scripts/deploy_web3.js +++ /dev/null @@ -1,32 +0,0 @@ -// Right click on the script name and hit "Run" to execute -(async () => { - try { - console.log('Running deployWithWeb3 script...') - - const contractName = 'Storage' // Change this for other contract - const constructorArgs = [] // Put constructor args (if any) here for your contract - - // Note that the script needs the ABI which is generated from the compilation artifact. - // Make sure contract is compiled and artifacts are generated - const artifactsPath = `browser/contracts/artifacts/${contractName}.json` // Change this for different path - - const metadata = JSON.parse(await remix.call('fileManager', 'getFile', artifactsPath)) - const accounts = await web3.eth.getAccounts() - - let contract = new web3.eth.Contract(metadata.abi) - - contract = contract.deploy({ - data: metadata.data.bytecode.object, - arguments: constructorArgs - }) - - const newContractInstance = await contract.send({ - from: accounts[0], - gas: 1500000, - gasPrice: '30000000000' - }) - console.log('Contract deployed at address: ', newContractInstance.options.address) - } catch (e) { - console.log(e.message) - } - })() \ No newline at end of file diff --git a/tests/4_Ballot_test.sol b/tests/4_Ballot_test.sol deleted file mode 100644 index cf5ad3a..0000000 --- a/tests/4_Ballot_test.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 - -pragma solidity >=0.7.0 <0.9.0; -import "remix_tests.sol"; // this import is automatically injected by Remix. -import "../contracts/3_Ballot.sol"; - -contract BallotTest { - - bytes32[] proposalNames; - - Ballot ballotToTest; - function beforeAll () public { - proposalNames.push(bytes32("candidate1")); - ballotToTest = new Ballot(proposalNames); - } - - function checkWinningProposal () public { - ballotToTest.vote(0); - Assert.equal(ballotToTest.winningProposal(), uint(0), "proposal at index 0 should be the winning proposal"); - Assert.equal(ballotToTest.winnerName(), bytes32("candidate1"), "candidate1 should be the winner name"); - } - - function checkWinninProposalWithReturnValue () public view returns (bool) { - return ballotToTest.winningProposal() == 0; - } -}