Skip to content

Commit

Permalink
Merge pull request #6 from YourJustice-Live/Game-Souls
Browse files Browse the repository at this point in the history
Everything can have a Soul
  • Loading branch information
toledoroy authored Jul 11, 2022
2 parents c47c2f7 + f0ffb64 commit 91f172c
Show file tree
Hide file tree
Showing 14 changed files with 141 additions and 86 deletions.
6 changes: 3 additions & 3 deletions archive/Hub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ contract Hub is
/// Update Hub
function hubChange(address newHubAddr) external override onlyOwner {
//Avatar
address avatarContract = getAssoc("avatar");
address avatarContract = getAssoc("SBT");
if(avatarContract != address(0)){
IProtocolEntity(avatarContract).setHub(newHubAddr);
}
Expand Down Expand Up @@ -207,7 +207,7 @@ contract Hub is

// console.log("Hub: Add Reputation to Contract:", contractAddr, tokenId, amount);
// console.log("Hub: Add Reputation in Domain:", domain);
address avatarContract = getAssoc("avatar");
address avatarContract = getAssoc("SBT");
//Update Avatar's Reputation //TODO: Just Check if Contract Implements IRating
if(avatarContract != address(0) && avatarContract == contractAddr){
_repAddAvatar(tokenId, domain, rating, amount);
Expand All @@ -216,7 +216,7 @@ contract Hub is

/// Add Repuation to Avatar
function _repAddAvatar(uint256 tokenId, string calldata domain, bool rating, uint8 amount) internal {
address avatarContract = getAssoc("avatar");
address avatarContract = getAssoc("SBT");
// require(avatarContract != address(0), "AVATAR_CONTRACT_UNKNOWN");
// repAdd(avatarContract, tokenId, domain, rating, amount);
// IAvatar(avatarContract).repAdd(tokenId, domain, rating, amount);
Expand Down
2 changes: 1 addition & 1 deletion contracts/ActionRepoTrackerUp.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ contract ActionRepoTrackerUp is
//Initializers
__UUPSUpgradeable_init();
__ProtocolEntity_init(hub);
__setTargetContract( repo().addressGetOf(address(_HUB), "avatar") );
__setTargetContract( repo().addressGetOf(address(_HUB), "SBT") );
//Set Contract URI
// _setContractURI(uri_);
}
Expand Down
22 changes: 13 additions & 9 deletions contracts/GameUpgradable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol";
// import "./abstract/Votes.sol";
// import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/draft-ERC721VotesUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/governance/utils/VotesUpgradeable.sol"; //Adds 3.486Kb
import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
import "./interfaces/IGameUp.sol";
import "./interfaces/IRules.sol";
import "./interfaces/IReaction.sol";
Expand Down Expand Up @@ -124,11 +125,10 @@ contract GameUpgradable is
//Initializers
// __ERC1155RolesUpgradable_init("");
__ProtocolEntity_init(hub);
// __setTargetContract(IAssoc(address(_HUB)).getAssoc("avatar"));
__setTargetContract(repo().addressGetOf(address(_HUB), "avatar"));
__setTargetContract(repo().addressGetOf(address(_HUB), "SBT"));

//Init Recursion Controls
// __Recursion_init(address(_HUB)); //DEPRECATED
// __Recursion_init(address(_HUB)); //CANCELLED

//Set Contract URI
_setContractURI(uri_);
Expand All @@ -145,6 +145,8 @@ contract GameUpgradable is
//Assign Creator as Admin & Member
_roleAssign(tx.origin, "admin", 1);
_roleAssign(tx.origin, "member", 1);


}

//** Reaction Functions
Expand Down Expand Up @@ -211,7 +213,7 @@ contract GameUpgradable is
/// @param uri_ post URI
function post(string calldata entRole, uint256 tokenId, string calldata uri_) external override {
//Validate that User Controls The Token
require(ISoul( repo().addressGetOf(address(_HUB), "avatar") ).hasTokenControl(tokenId), "SOUL:NOT_YOURS");
require(ISoul( repo().addressGetOf(address(_HUB), "SBT") ).hasTokenControl(tokenId), "SOUL:NOT_YOURS");
//Validate: Soul Assigned to the Role
require(roleHasByToken(tokenId, entRole), "ROLE:NOT_ASSIGNED"); //Validate the Calling Account
// require(roleHasByToken(tokenId, entRole), string(abi.encodePacked("TOKEN: ", tokenId, " NOT_ASSIGNED_AS: ", entRole)) ); //Validate the Calling Account
Expand Down Expand Up @@ -253,12 +255,14 @@ contract GameUpgradable is

/// Proxy Fallback Implementations
function _implementations() internal view virtual override returns (address[] memory){
// string memory gameType = confGet("type");
require (!Utils.stringMatch(confGet("type"), ""), "NO_GAME_TYPE");
address[] memory implementationAddresses;
string memory gameType = confGet("type");
if(Utils.stringMatch(gameType, "")) return implementationAddresses;
// require (!Utils.stringMatch(gameType, ""), "NO_GAME_TYPE");
//UID
string memory gameType = string(abi.encodePacked("GAME_", confGet("type")));
string memory gameTypeFull = string(abi.encodePacked("GAME_", gameType));
//Fetch Implementations
address[] memory implementationAddresses = repo().addressGetAllOf(address(_HUB), gameType); //Specific
implementationAddresses = repo().addressGetAllOf(address(_HUB), gameTypeFull); //Specific
require(implementationAddresses.length > 0, "NO_FALLBACK_CONTRACT");
return implementationAddresses;
}
Expand Down Expand Up @@ -352,7 +356,7 @@ contract GameUpgradable is
roleRemove(account, roleOld);
}

/** DEPRECATE - Allow Uneven Role Distribution
/** TODO: DEPRECATE - Allow Uneven Role Distribution
* @dev Hook that is called before any token transfer. This includes minting and burning, as well as batched variants.
* - Max of Single Token for each account
*/
Expand Down
15 changes: 12 additions & 3 deletions contracts/HubUpgradable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ contract HubUpgradable is
/// Update Hub
function hubChange(address newHubAddr) external override onlyOwner {
//Avatar
address avatarContract = repo().addressGet("avatar");
address avatarContract = repo().addressGet("SBT");
if(avatarContract != address(0)){
try IProtocolEntity(avatarContract).setHub(newHubAddr){} //Failure should not be fatal
catch Error(string memory /*reason*/) {}
Expand Down Expand Up @@ -182,6 +182,15 @@ contract HubUpgradable is
emit ContractCreated("game", address(newGameProxy));
//Remember
_games[address(newGameProxy)] = true;

//Register as a Soul
try ISoul(repo().addressGet("SBT")).mintFor(address(newGameProxy), uri_) {} //Failure should not be fatal
catch Error(string memory reason) {
console.log("Failed to mint a soul for the new Game Contract", reason);
}

// repo().addressAdd("GAME", address(newGameProxy));

//Return
return address(newGameProxy);
}
Expand Down Expand Up @@ -223,15 +232,15 @@ contract HubUpgradable is
//Validate - Known & Active Game
require(_games[_msgSender()], "UNAUTHORIZED: Valid Game Only");
//Update Avatar's Reputation //TODO: Just Check if Contract Implements IRating
address avatarContract = repo().addressGet("avatar");
address avatarContract = repo().addressGet("SBT");
if(avatarContract != address(0) && avatarContract == contractAddr){
_repAddAvatar(tokenId, domain, rating, amount);
}
}

/// Add Repuation to Avatar
function _repAddAvatar(uint256 tokenId, string calldata domain, bool rating, uint8 amount) internal {
address avatarContract = repo().addressGet("avatar");
address avatarContract = repo().addressGet("SBT");
try ISoul(avatarContract).repAdd(tokenId, domain, rating, amount) {} //Failure should not be fatal
catch Error(string memory /*reason*/) {}
}
Expand Down
8 changes: 4 additions & 4 deletions contracts/ReactionUpgradable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ contract ReactionUpgradable is

/// Get Soul Contract Address
function getSoulAddr() internal view returns(address){
return repo().addressGetOf(address(_HUB), "avatar");
return repo().addressGetOf(address(_HUB), "SBT");
}

/// Request to Join
Expand Down Expand Up @@ -214,7 +214,7 @@ contract ReactionUpgradable is
function post(string calldata entRole, uint256 tokenId, string calldata uri_) external override {
//Validate that User Controls The Token
// require(_hasTokenControl(tokenId), "SOUL:NOT_YOURS");
// require(ISoul( IAssoc(address(_HUB)).getAssoc("avatar") ).hasTokenControl(tokenId), "SOUL:NOT_YOURS");
// require(ISoul( IAssoc(address(_HUB)).getAssoc("SBT") ).hasTokenControl(tokenId), "SOUL:NOT_YOURS");
require(ISoul( getSoulAddr() ).hasTokenControl(tokenId), "SOUL:NOT_YOURS");
//Validate: Soul Assigned to the Role
// require(roleHas(tx.origin, entRole), "ROLE:NOT_ASSIGNED"); //Validate the Calling Account
Expand Down Expand Up @@ -336,8 +336,8 @@ contract ReactionUpgradable is
/// Rule (Action) Confirmed (Currently Only Judging Avatars)
function _ruleConfirmed(uint256 ruleId) internal {
//Get Avatar Contract
// ISoul avatarContract = ISoul(_HUB.getAssoc("avatar"));
// ISoul avatarContract = ISoul(IAssoc(address(_HUB)).getAssoc("avatar"));
// ISoul avatarContract = ISoul(_HUB.getAssoc("SBT"));
// ISoul avatarContract = ISoul(IAssoc(address(_HUB)).getAssoc("SBT"));
ISoul avatarContract = ISoul( getSoulAddr() );


Expand Down
123 changes: 74 additions & 49 deletions contracts/SoulUpgradable.sol
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.4;

// import "hardhat/console.sol";
import "hardhat/console.sol";

// import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol";
// import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
// import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
import "./interfaces/ISoul.sol";
import "./abstract/Opinions.sol";
import "./abstract/ProtocolEntityUpgradable.sol";


/**
* @title Soulbound NFT Identity Tokens + Reputation Tracking
* @dev Version 2.0
* @dev Version 2.1
* - Contract is open for everyone to mint.
* - Max of one NFT assigned for each account
* - Can create un-assigned NFT (Kept on contract)
* - Minted Token's URI is updatable by Token holder
* - Assets are non-transferable by owner
* - Tokens can be merged (Multiple Owners)
* - Tokens can be merged (multiple owners)
* - Owner can mint tokens for Contracts
* - [TODO] Orphan tokens can be claimed/linked
*/
contract SoulUpgradable is
Expand All @@ -42,10 +43,9 @@ contract SoulUpgradable is
using CountersUpgradeable for CountersUpgradeable.Counter;
CountersUpgradeable.Counter private _tokenIds;

//Positive & Negative Reputation Tracking Per Domain (Personal,Community,Professional)
// mapping(uint256 => mapping(DataTypes.Domain => mapping(DataTypes.Rating => uint256))) internal _rep; //[Token][Domain][bool] => Rep //Inherited from Opinions
mapping(address => uint256) internal _owners; //Map Multiple Accounts to Tokens (Aliases)

mapping(uint256 => string) public types; //Soul Types
mapping(uint256 => address) internal _link; //[TBD] Linked Souls

//--- Modifiers

Expand All @@ -68,7 +68,9 @@ contract SoulUpgradable is

/// ERC165 - Supported Interfaces
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(ISoul).interfaceId || super.supportsInterface(interfaceId);
return interfaceId == type(ISoul).interfaceId
|| interfaceId == type(IERC721Upgradeable).interfaceId
|| super.supportsInterface(interfaceId);
}

//** Token Owner Index **/
Expand Down Expand Up @@ -131,34 +133,37 @@ contract SoulUpgradable is

//** Token Actions **/

/// Mint (Create New Avatar for oneself)
function mint(string memory tokenURI) public override returns (uint256) {
//One Per Account
require(balanceOf(_msgSender()) == 0, "Requesting account already has an avatar");
/// Mint (Create New Token for Someone Else)
function mintFor(address to, string memory tokenURI) public override returns (uint256) {
//Validate - Contract Owner
// require(_msgSender() == owner(), "Only Owner");
require(_msgSender() == owner() || _msgSender() == address(_HUB), "Only Owner or Hub");
//Mint
uint256 tokenId = _createAvatar(_msgSender(), tokenURI);
//Index Owner
// _tokenOwnerAdd(_msgSender(), tokenId); //MOVED TO TokenTransfer Logic
//Return
return tokenId;
return _mint(to, tokenURI);
}

/// Mint (Create New Token for oneself)
function mint(string memory tokenURI) external override returns (uint256) {
//Mint
return _mint(_msgSender(), tokenURI);
}

/// Add (Create New Avatar Without an Owner)
/// Add (Create New Token Without an Owner)
function add(string memory tokenURI) external override returns (uint256) {
//Mint
return _createAvatar(address(this), tokenURI);
return _mint(address(this), tokenURI);
}

/// Burn NFTs
function burn(uint256 tokenId) external {
//Validate Owner of Contract
//Validate - Contract Owner
require(_msgSender() == owner(), "Only Owner");
//Burn Token
_burn(tokenId);
}

/// Update Token's Metadata
function update(uint256 tokenId, string memory uri) public override returns (uint256) {
function update(uint256 tokenId, string memory uri) external override returns (uint256) {
//Validate Owner of Token
require(_isApprovedOrOwner(_msgSender(), tokenId) || _msgSender() == owner(), "caller is not owner nor approved");
_setTokenURI(tokenId, uri); //This Goes for Specific Metadata Set (IPFS and Such)
Expand All @@ -168,34 +173,66 @@ contract SoulUpgradable is
return tokenId;
}

/// Create a new Avatar
function _createAvatar(address to, string memory uri) internal returns (uint256){
/// Create a new Token
function _mint(address to, string memory uri) internal returns (uint256){
//Validate - Bot Protection
require(tx.origin == _msgSender(), "Bots not allowed");
// require(tx.origin == _msgSender(), "Bots not allowed"); //CANCELLED - Allow Contracts to Have Souls
//One Per Account
require(to == address(this) || balanceOf(_msgSender()) == 0, "Requesting account already has a token");
//Mint
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_safeMint(to, newItemId);
_mint(to, newItemId);
//Set URI
_setTokenURI(newItemId, uri); //This Goes for Specific Metadata Set (IPFS and Such)
//Emit URI Changed Event
emit URI(uri, newItemId);
//Soul Type
string memory soulType = _getType(to);
//Set
types[newItemId] = soulType;
//Emit Soul Type as Event
emit SoulType(newItemId, soulType);
//Done
return newItemId;
}

/// Get Owner Type
function _getType(address account) private view returns(string memory){

// console.log("** _getType() Return: ", response);

if (account.isContract() && account != address(this)) {

// console.log("THIS IS A Contract:", account);

try IToken(account).symbol() returns (string memory response) {

// console.log("* * * Contract Symbol:", account, response);

//Contract's Symbol
return response;
} catch {
//Unrecognized Contract
return "CONTRACT";
}
}
// console.log("THIS IS NOT A Contract:", account);
//Not a contract
return "";
}

/// Token Transfer Rules
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override(ERC721Upgradeable) {
super._beforeTokenTransfer(from, to, tokenId);
//Can't be owned by a Contract
require(to == address(this) || !to.isContract(), "Destination is a Contract");
//Can't be owned by a Contract //CANCELLED - Allow Contracts to have Souls
// require(to == address(this) || !to.isContract(), "Destination is a Contract");

//Non-Transferable (by client)
require(
_msgSender() == owner()
|| from == address(0) //Minting
// || to == address(0) //Burning
,
"Sorry, Assets are non-transferable"
, "Sorry, assets are non-transferable"
);

//Update Address Index
Expand All @@ -215,24 +252,6 @@ contract SoulUpgradable is
return true;
}

/// Receiver Function For Holding NFTs on Contract
/// @dev needed in order to keep tokens in the contract
function onERC721Received(address, address, uint256, bytes memory) public pure returns (bytes4) {
return this.onERC721Received.selector;
}

/* Try without it, since we don't want any regular ERC1155 to be received
/// Receiver Function For Holding NFTs on Contract (Allow for internal NFTs to assume Roles)
function onERC1155Received(address, address, uint256, uint256, bytes memory) public pure returns (bytes4) {
return this.onERC1155Received.selector;
}
/// Receiver Function For Holding NFTs on Contract
function onERC1155BatchReceived(address, address, uint256[] memory, uint256[] memory, bytes memory) public pure returns (bytes4) {
return this.onERC1155BatchReceived.selector;
}
*/

/// Check if the Current Account has Control over a Token
function hasTokenControl(uint256 tokenId) public view override returns (bool) {
address ownerAccount = ownerOf(tokenId);
Expand All @@ -252,3 +271,9 @@ contract SoulUpgradable is
}

}

/// Generic Interface used to get Symbol
interface IToken {
/// Arbitrary contract symbol
function symbol() external view returns (string memory);
}
Loading

0 comments on commit 91f172c

Please sign in to comment.