Skip to content

Commit

Permalink
🔐☕️↣ Adding contract metadata for [#18 #16 #6] and a rudimentary fron…
Browse files Browse the repository at this point in the history
…tend component for connecting to APIs (including with Py) for #1

Two new directories:
`./Ansible` ↣ Contract & build files here. Will be moved into a new folder in the root React/Next.js project, but for now I'm leaving this in a separate node project to keep things separated for easier debugging

`./client` ↣ Frontend client for interacting with the smart contracts in `Ansible` directory. Similar story to the directory positioning in `Ansible`. We'll migrate it over to the Node project in the root directory before merging this branch, however we will also transition as much as possible out of typescript.
  • Loading branch information
Gizmotronn committed Nov 21, 2022
1 parent 03854d5 commit 61087ad
Show file tree
Hide file tree
Showing 42 changed files with 8,240 additions and 13 deletions.
Binary file modified .DS_Store
Binary file not shown.
11 changes: 11 additions & 0 deletions Ansible/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
node_modules
.env
coverage
coverage.json
typechain
typechain-types

#Hardhat files
cache
artifacts

92 changes: 92 additions & 0 deletions Ansible/contracts/SailorsMultitoolProtocol.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.11;

/* Import thirdweb contracts
import "@thirdweb-dev/contracts/drop/DropERC1155.sol"; // For tool collection
import "@thirdweb-dev/contracts/token/TokenERC20.sol"; // For the minerals collection
// OpenZeppelin ReentrancyGuard
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@thirdweb-dev/contracts/openzeppelin-presets/utils/ERC1155/ERC1155Holder.sol"; // This contract is now capable of holding 1155 nfts */

// Import thirdweb contracts
import "@thirdweb-dev/contracts/drop/DropERC1155.sol"; // For my collection of Pickaxes
import "@thirdweb-dev/contracts/token/TokenERC20.sol"; // For my ERC-20 Token contract
import "@thirdweb-dev/contracts/openzeppelin-presets/utils/ERC1155/ERC1155Holder.sol"; // For my ERC-1155 Receiver contract

// OpenZeppelin (ReentrancyGuard)
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

contract Multitooling is ReentrancyGuard, ERC1155Holder {
DropERC1155 public immutable multitoolNftCollection;
TokenERC20 public immutable mineralsToken;

// Set the rewards token & the NFT collection address
constructor(DropERC1155 multitoolContractAddress, TokenERC20 mineralsContractAddress) {
multitoolNftCollection = multitoolContractAddress;
mineralsToken = mineralsContractAddress;
}

struct MapValue {
bool isData; // Turn on/off depending on if nft data is currently staked
uint256 value; // Stores tokenId of nft being staked
}

mapping (address => MapValue) public playerMultitool; // Map the player to their current multitool. Occurs when they stake a multitool
mapping(address => MapValue) public playerLastUpdate; // Player address to last time they staked/withdrew/claimed rewards.

// Stake functionality
function stake(uint256 _tokenId) external nonReentrant {
require(multitoolNftCollection.balanceOf(msg.sender, _tokenId) >= 1, "You require at least one multitool to stake"); // Takes the desired level of multitool (tokenId) into account as well

if (playerMultitool[msg.sender].isData) { // If the player already has a multitool, send it back to them
multitoolNftCollection.safeTransferFrom(address(this), msg.sender, playerMultitool[msg.sender].value, 1, "Returning your old multitool");
}

uint256 reward = calculateRewards(msg.sender);
mineralsToken.transfer(msg.sender, reward);

// Transfer the multitool to the contract
multitoolNftCollection.safeTransferFrom(msg.sender, address(this), _tokenId, 1, "Staking your multitool now"); // From user/player address to this contract's address
playerMultitool[msg.sender].value = _tokenId; // Update multitool mapping
playerMultitool[msg.sender].isData = true;
playerLastUpdate[msg.sender].isData = true; // Update playerLastUpdate mapping
playerLastUpdate[msg.sender].value = block.timestamp;
}

// Withdraw your multitool from this staking contract
function withdraw() external nonReentrant {
require(playerMultitool[msg.sender].isData, "You do not have a multitool to withdraw"); // Ensure the player has a multitool
uint256 reward = calculateRewards(msg.sender); // Calculate rewards owed to the player
mineralsToken.transfer(msg.sender, reward);
multitoolNftCollection.safeTransferFrom(address(this), msg.sender, playerMultitool[msg.sender].value, 1, "Returning the multitool to you");

// Update mapping
playerMultitool[msg.sender].isData = false;
playerLastUpdate[msg.sender].isData = true;
playerLastUpdate[msg.sender].value = block.timestamp;
}

// Claim owed minerals manually
function claim() external nonReentrant {
uint256 reward = calculateRewards(msg.sender);
mineralsToken.transfer(msg.sender, reward);

// Update mappings
playerLastUpdate[msg.sender].isData = true;
playerLastUpdate[msg.sender].value = block.timestamp; // Last call is set to the current block time
}

// Calculate & process rewards
function calculateRewards(address _player) /// Rewards rate -> 20M minerals per block.
public /// Calculate rewards since last time the player was paid out
view /// use block.timestamp and playerLastUpdate
returns (uint256 _rewards) {
if (!playerLastUpdate[_player].isData || !playerMultitool[_player].isData) { // If either is not set
return 0;
}
uint256 timeDifference = block.timestamp - playerLastUpdate[_player].value; // Calculate time difference between NOW and when the player last actioned their reward
uint256 rewards = timeDifference * 10_000_000_000_000 * (playerMultitool[_player].value + 1); // Calculate rewards user is owed. Formatted to 18 decimals
return rewards; // View for each player
}
}
12 changes: 12 additions & 0 deletions Ansible/hardhat.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: {
version: '0.8.11',
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
};
16 changes: 16 additions & 0 deletions Ansible/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "hardhat-javascript-starter",
"scripts": {
"build": "npx thirdweb@latest detect",
"deploy": "npx thirdweb@latest deploy",
"release": "npx thirdweb@latest release"
},
"devDependencies": {
"hardhat": "^2.10.1"
},
"dependencies": {
"@openzeppelin/contracts": "^4.7.3",
"@openzeppelin/contracts-upgradeable": "4.8.0",
"@thirdweb-dev/contracts": "^3"
}
}
Loading

0 comments on commit 61087ad

Please sign in to comment.