-
-
Save 0xc0de4c0ffee/5ffe2ecd4448e7c7daf1a98f2e90ece4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: WTFPL v4.20 | |
pragma solidity >0.8.0; | |
interface iENS { | |
function setRecord(bytes32 node, address _owner, address _resolver, uint64 _ttl) external; | |
function setSubnodeRecord(bytes32 node, bytes32 label, address _owner, address _resolver, uint64 _ttl) external; | |
function setSubnodeOwner(bytes32 node, bytes32 label, address _owner) external returns(bytes32); | |
function setResolver(bytes32 node, address _resolver) external; | |
function setOwner(bytes32 node, address _owner) external; | |
function setTTL(bytes32 node, uint64 _ttl) external; | |
function setApprovalForAll(address operator, bool approved) external; // pre registration | |
function owner(bytes32 node) external view returns (address); | |
function resolver(bytes32 node) external view returns (address); | |
function ttl(bytes32 node) external view returns (uint64); | |
function recordExists(bytes32 node) external view returns (bool); | |
function isApprovedForAll(address _owner, address operator) external view returns (bool); | |
event NewOwner(bytes32 indexed node, bytes32 indexed label, address _owner); | |
event Transfer(bytes32 indexed node, address _owner); | |
event NewResolver(bytes32 indexed node, address _resolver); | |
event NewTTL(bytes32 indexed node, uint64 _ttl); | |
event ApprovalForAll(address indexed owner, address indexed operator, bool approved); | |
} | |
interface iERC20 { | |
function balanceOf(address _addr) external returns(uint); | |
function transfer(address _from, address _to, uint256 _value) external returns(bool); | |
function transferFrom(address _from, address _to, uint256 _value) external returns(bool); | |
} | |
interface iERC165 { | |
function supportsInterface(bytes4 interfaceId) external view returns (bool); | |
} | |
interface iERC721 is iERC165 { | |
function balanceOf(address owner) external view returns (uint256 balance); | |
function ownerOf(uint256 tokenId) external view returns (address owner); | |
function safeTransferFrom(address from, address to, uint256 tokenId) external; | |
function transferFrom(address from, address to, uint256 tokenId) external; | |
function approve(address to, uint256 tokenId) external; | |
function getApproved(uint256 tokenId) external view returns (address operator); | |
function setApprovalForAll(address operator, bool _approved) external; | |
function isApprovedForAll(address owner, address operator) external view returns (bool); | |
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; | |
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); | |
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); | |
event ApprovalForAll(address indexed owner, address indexed operator, bool approved); | |
} | |
interface iERC721Metadata is iERC721 { | |
function name() external view returns (string memory); | |
function symbol() external view returns (string memory); | |
function tokenURI(uint256 tokenId) external view returns (string memory); | |
} | |
interface iERC1155 is iERC165 { | |
function balanceOf(address account, uint256 id) external view returns (uint256); | |
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); | |
function setApprovalForAll(address operator, bool approved) external; | |
function isApprovedForAll(address account, address operator) external view returns (bool); | |
function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external; | |
function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external; | |
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); | |
event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values); | |
event ApprovalForAll(address indexed account, address indexed operator, bool approved); | |
event URI(string value, uint256 indexed id); | |
} | |
library Logic { | |
function read() public view{ | |
//bytes32 position = keccak256("diamond.standard.diamond.storage"); | |
//assembly { ds.slot := position } | |
} | |
} | |
contract ERC165 { | |
function supportsInterface(bytes4 interfaceId) external pure returns (bool) { | |
return interfaceId == type(iERC165).interfaceId || | |
interfaceId == type(iERC1155).interfaceId || | |
interfaceId == type(iERC721Metadata).interfaceId; | |
} | |
} | |
contract Core { | |
address public ADMIN; // EOA, OR GU Admin Contract | |
iENS public ENS; | |
iERC20 public UBI; | |
bytes32 public immutable FREECLOUD = bytes32(0); // freecloud.eth namehash | |
bytes32 public immutable COLLECTIVE = bytes32(0); // collective.freecloud.eth namehash | |
bytes32 public immutable COLLECTION = bytes32(0); // collection.freecloud.eth namehash | |
uint8 public immutable decimals = 18; | |
string public constant name = "freecloud.eth"; | |
string public constant symbol = "DUST"; | |
mapping(address => uint64) public lastActive; // lock and disallow address reuse | |
mapping(bytes32 => address) private _approved; | |
mapping(address => mapping(address => uint64)) private _operator; | |
uint256 public totalCreators; | |
uint256 public totalCollectives; | |
uint256 public totalCollections; | |
uint256 public totalCreations; | |
// mapping(bytes32 => address) Map2Addr; | |
mapping(address => bytes32) Addr2Map; | |
mapping(bytes32 => bytes) public Contenthash; | |
mapping(bytes32 => bytes32) public Redirect; | |
mapping(bytes32 => mapping(address => bool)) private ownerOf; | |
mapping(bytes32 => Creator) internal _creators; | |
mapping(bytes32 => Collective) internal _collectives; | |
mapping(bytes32 => Collection) internal _collections; | |
mapping(bytes32 => Creation) internal _creations; | |
mapping(bytes32 => uint256) public totalSupply; | |
mapping(bytes32 => uint256) public _daiBalance; | |
mapping(bytes32 => uint256) public _ubiBalance; | |
function namehash(bytes32 node, bytes32 label) public pure returns(bytes32) { | |
return keccak256(abi.encodePacked(node, keccak256(abi.encodePacked(label)))); | |
} | |
modifier addrInit(address addr) { | |
require(lastActive[addr] == 0, "Error: Address Already Used."); | |
lastActive[addr] = uint64(block.timestamp); | |
_; | |
} | |
modifier addrUpdate(address addr) { | |
require(lastActive[addr] > 9000, "Error: This address can't be reused."); | |
lastActive[addr] = uint64(block.timestamp); | |
_; | |
} | |
struct Creator { // artists | |
//uint64 joined; // joined date | |
uint16 collections; // number of albums | |
uint16 collectives; // member of bands | |
uint16 creations; // number of music/track NFT | |
uint32 fans; // | |
bytes32 name; // label of creator | |
address primary; // Primary active controller "Hot" | |
address backup; // secondary backup controller "Cold" | |
address PoH; // Human address | |
} | |
struct Collective { // group/ bands = creator | |
uint8 members; // number of members | |
uint16 collections; // total Albums | |
uint16 creations; // total tracks | |
uint32 fans; // number of fans | |
address manager; // manager address | |
bytes32 name; // | |
} | |
struct Collection { // Album | |
bytes32 by; // artist / collective | |
uint8 tracks; // number of tracks | |
//uint64 royalty; // base Royalty UBI | |
uint128 totalSupply; | |
} | |
struct Creation { | |
uint8 moon; // base to moon ratio | |
uint16 bar; // seconds per bar | |
uint16 timer; // seconds length of track | |
uint128 base; // base starting price | |
uint128 supply; // total NFT supply | |
uint128 price; // price tag | |
bytes32 collection; // album | |
bytes32 name; // title | |
} | |
//mapping(bytes32 => mapping(address => uint64)) collector; | |
modifier isAdmin() { | |
require(msg.sender == ADMIN, "Core: Only Admin"); | |
_; | |
} | |
function isAuthorised(bytes32 node) internal view returns(bool){ | |
} | |
modifier authorised(bytes32 node) { | |
require(isAuthorised(node)); | |
_; | |
} | |
event ContenthashChanged(bytes32 indexed node, bytes hash); | |
function str_b32(string memory str) internal pure returns (bytes32 b32) { | |
assembly { | |
str := mload(add(b32, 32)) | |
} | |
} | |
function b32_str(bytes32 _b32) public pure returns (string memory) { | |
return string(abi.encodePacked(_b32)); | |
} | |
function isValidName(string memory str) public pure returns(bool ok) { | |
bytes memory _b = bytes(str); | |
if(_b.length < 32 && _b[0] != 0x2D && _b[0] != 0x30) { // can't start with zero / hyphen, max 32 * bytes1 = bytes32 | |
uint i = 0; | |
ok = true; | |
while(ok && i < _b.length) { | |
// small caps a-z || 0-9 || "-" hyphen | |
ok = (_b[i] > 0x60 && _b[i] < 0x7B) || (_b[i] > 0x2F && _b[i] < 0x3A) || _b[i] == 0x2D; | |
i++; | |
} | |
// block punycoded format "xn--" | |
if((ok && _b[2] == 0x2D) && (_b[0] == 0x78 && _b[1] == 0x6E)) { | |
ok = false; | |
} | |
} | |
} | |
} | |
contract EIP712 is Core { | |
// keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); | |
bytes32 public immutable PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; | |
// | |
bytes32 public immutable DOMAIN_SEPARATOR = 0x5e053d4308076b8b3966d832197af0284e834abfc18d362c9a366e1a17c80f35; | |
mapping(bytes32 => uint64) public _lock; | |
function verify(address signer, bytes32 digest, uint8 v, bytes32 r, bytes32 s) external pure returns(bool) { | |
return (signer == ecrecover(digest, v, r, s) && signer != address(0)); | |
} | |
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external view { | |
require(deadline > block.timestamp, 'UniswapV2: EXPIRED'); | |
bytes32 digest = keccak256( | |
abi.encodePacked( | |
'\x19\x01', | |
DOMAIN_SEPARATOR, | |
keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, deadline)) | |
) | |
); | |
address recoveredAddress = ecrecover(digest, v, r, s); | |
require(recoveredAddress != address(0) && recoveredAddress == owner, 'UniswapV2: INVALID_SIGNATURE'); | |
//_approve(owner, spender, value); | |
} | |
} | |
contract Creators is Core { | |
event NewCreator(bytes32 indexed name, bytes32 indexed namehash); | |
function newCreator(address primary, bytes32 name, bytes calldata _contenthash) external addrInit(primary) { | |
bytes32 _namehash = namehash(FREECLOUD, name); | |
Creator storage creator = _creators[_namehash]; | |
require(creator.backup == address(0), "Creators: Nick already registered"); | |
creator.name = name; | |
creator.primary = primary; | |
Addr2Map[primary] = _namehash; | |
ENS.setSubnodeRecord(FREECLOUD, name, address(this), address(this), 9000); | |
Contenthash[_namehash] = _contenthash; | |
emit ContenthashChanged(_namehash, _contenthash); | |
emit NewCreator(name, _namehash); | |
} | |
function creatorAlias(bytes32 _alias) external { | |
bytes32 _namehash = Addr2Map[msg.sender]; | |
require(msg.sender == _creators[_namehash].primary || msg.sender == _creators[_namehash].backup,"Creators: Only creator keys can set alias."); | |
require(ENS.owner(_alias) != address(this), "ENS : alias is owned by this contract address"); | |
require(ENS.resolver(_alias) == address(this), "ENS : resolver isn't set to this contract address"); | |
require(Redirect[_alias] == bytes32(0), "Redirect already set"); | |
Redirect[_alias] = _namehash; | |
emit ContenthashChanged(_alias, Contenthash[_namehash]); | |
} | |
event NewBackupKey(bytes32 indexed _namehash, address by, address backup); | |
function newBackupKey(address backup) addrInit(backup) external { | |
bytes32 _namehash = Addr2Map[msg.sender]; | |
Creator storage creator = _creators[_namehash]; | |
require((msg.sender == creator.primary && creator.backup == address(0)) || msg.sender == creator.backup, "Creators: Only backup key can change backup."); | |
creator.backup = backup; | |
emit NewBackupKey(_namehash, msg.sender, backup); | |
} | |
event NewPrimaryKey(bytes32 indexed _namehash, address by, address backup); | |
function newPrimaryKey(address primary) addrInit(primary) external { | |
bytes32 _namehash = Addr2Map[msg.sender]; | |
Creator storage creator = _creators[_namehash]; | |
require(msg.sender == creator.backup,"Creators: Only backup key can change primary."); | |
creator.primary = primary; | |
emit NewPrimaryKey(_namehash, msg.sender, primary); | |
} | |
function Lock() external { | |
bytes32 _namehash = Addr2Map[msg.sender]; | |
Creator storage creator = _creators[_namehash]; | |
require((creator.primary == msg.sender || msg.sender == creator.backup), "Creators: Only backup or primary key can lock."); | |
creator.primary = address(418); | |
emit NewPrimaryKey(_namehash, msg.sender, address(418)); | |
} | |
event AdminLock(bytes32 indexed _namehash, uint16 indexed reason, bytes content); | |
function adminLock(bytes32 _namehash, uint16 _reason, bytes memory _contenthash) isAdmin external { | |
Creator storage creator = _creators[_namehash]; | |
creator.primary = address(uint160(_reason)); | |
creator.backup = address(uint160(_reason)); | |
emit AdminLock(_namehash, _reason, _contenthash); | |
} | |
event AdminUnlock(bytes32 indexed _namehash, uint16 indexed reason, bytes content); | |
function adminUnlock(bytes32 _namehash, address backup, uint16 _reason, bytes memory _contenthash) isAdmin external { | |
Creator storage creator = _creators[_namehash]; | |
require(creator.primary == creator.backup && uint160(creator.backup) <= type(uint16).max, "Namehash not locked"); | |
creator.backup = backup; | |
emit AdminUnlock(_namehash, _reason, _contenthash); | |
} | |
} | |
contract Collectives is Core { | |
event NewCollective(bytes32 indexed hash, bytes32 name); | |
event NewMember(bytes32 indexed colllection, bytes32 indexed creator); | |
mapping(bytes32 => mapping(bytes32 => uint64)) internal Members; | |
function newCollective(bytes32 _name, address manager, bytes calldata _contenthash) external isAdmin { | |
bytes32 _namehash = namehash(COLLECTIVE, _name); | |
Collective storage collective = _collectives[_namehash]; | |
require(collective.manager == address(0), "Collectives: Nick already registered"); | |
ENS.setSubnodeRecord(COLLECTIVE, _name, address(this), address(this), 9000); | |
collective.manager = manager; | |
collective.name = _name; | |
emit NewCollective(_namehash, _name); | |
Contenthash[_namehash] = _contenthash; | |
emit ContenthashChanged(_namehash, _contenthash); | |
} | |
function addMembers(bytes32 _namehash, bytes32[] calldata members) external { | |
Collective storage collective = _collectives[_namehash]; | |
require(msg.sender == collective.manager, "Only Manager"); | |
collective.members += members.length; | |
for(uint i= 0; i < members.length; i++) { | |
require(uint160(_creators[members[i]].backup) > 9000, "Creator Not Active"); | |
require(Members[_namehash][members[i]] == 0, "Already Member"); | |
Members[_namehash][members[i]] = uint64(block.timestamp); | |
emit NewMember(_namehash, members[i]); | |
} | |
} | |
function addMember(bytes32 _namehash, bytes32 member) external { | |
Collective storage collective = _collectives[_namehash]; | |
require(msg.sender == collective.manager, "Only Manager"); | |
collective.members++; | |
require(uint160(_creators[member].backup) > 9000, "Creator Not Active"); | |
require(Members[_namehash][member] == 0, "Already Member"); | |
Members[_namehash][member] = uint64(block.timestamp); | |
emit NewMember(_namehash, member); | |
} | |
function rageQuit(bytes32 _namehash) external { | |
bytes32 member = Addr2Map[msg.sender]; | |
Collective storage collective = _collectives[_namehash]; | |
require(Members[_namehash][member] > 9000, "Not Member"); | |
require(msg.sender == _creators[member].backup, "Only backup Keys can rage quit"); | |
Members[_namehash][member] = uint64(501); | |
emit NewMember(_namehash, member); | |
uint256 _dai = _daiBalance[_namehash][member] | |
collective.members--; | |
} | |
} | |
contract AFreecloud is ERC165, EIP712 { | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment