Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
borderlessdaos authored May 23, 2024
0 parents commit b314120
Show file tree
Hide file tree
Showing 3 changed files with 376 additions and 0 deletions.
101 changes: 101 additions & 0 deletions Asset-Tokenization.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract AssetTokenization is ERC1155, Ownable {
uint256 public currentTokenID = 0;

enum AssetScope { Global, Regional, Local }

struct AssetMetadata {
string name;
string description;
string assetType;
string location;
uint256 valuation;
uint256 createdAt;
address createdBy;
AssetScope scope;
}

mapping(uint256 => AssetMetadata) public assetMetadata;
mapping(address => mapping(uint256 => uint256)) public lockedBalance;

event TokensBurned(address indexed burner, uint256 indexed tokenID, uint256 amount);
event TokensTransferred(address indexed from, address indexed to, uint256 indexed tokenID, uint256 amount, bytes data);
event BatchMinted(address indexed minter, uint256[] tokenIDs, uint256[] amounts, AssetMetadata[] metadatas);
event TokensLocked(address indexed locker, uint256 indexed tokenID, uint256 amount, uint256 unlockTimestamp);
event TokensUnlocked(address indexed locker, uint256 indexed tokenID, uint256 amount);

constructor(string memory uri) ERC1155(uri) Ownable(0x7e2eD6241f395E32c2fcEdCE0829e0506cbCFc79) {}

function identifyAssetScope(uint8 scopeValue) internal pure returns (AssetScope) {
require(scopeValue >= uint8(AssetScope.Global) && scopeValue <= uint8(AssetScope.Local), "Invalid scope value");
return AssetScope(scopeValue);
}

function verifyAssetOwner(address account, uint256 tokenID) public view returns (bool) {
return balanceOf(account, tokenID) > 0;
}

function verifyKYC() internal pure returns (bool) {
// Call Oracle API for KYC verification
// Implement your KYC verification logic here
// For demonstration purposes, returning true
return true;
}

function mintAsset(address account, uint256 amount, bytes memory data, AssetMetadata memory metadata) public onlyOwner {
require(verifyKYC(), "Account is not KYC verified");
assetMetadata[currentTokenID] = metadata;
_mint(account, currentTokenID, amount, data);
uint256[] memory tokenIDs = new uint256[](1);
uint256[] memory amountsArray = new uint256[](1);
AssetMetadata[] memory metadatasArray = new AssetMetadata[](1);
tokenIDs[0] = currentTokenID;
amountsArray[0] = amount;
metadatasArray[0] = metadata;
emit BatchMinted(account, tokenIDs, amountsArray, metadatasArray);
currentTokenID++;
}

function batchMintAsset(address[] memory accounts, uint256[] memory amounts, bytes[] memory data, AssetMetadata[] memory metadatas) public onlyOwner {
require(accounts.length == amounts.length && accounts.length == data.length && accounts.length == metadatas.length, "Array lengths must match");
uint256[] memory tokenIDs = new uint256[](accounts.length);
for (uint256 i = 0; i < accounts.length; i++) {
assetMetadata[currentTokenID] = metadatas[i];
_mint(accounts[i], currentTokenID, amounts[i], data[i]);
tokenIDs[i] = currentTokenID;
currentTokenID++;
}
emit BatchMinted(msg.sender, tokenIDs, amounts, metadatas);
}

function burn(uint256 tokenID, uint256 amount) public {
_burn(msg.sender, tokenID, amount);
emit TokensBurned(msg.sender, tokenID, amount);
}

function transferTokens(address from, address to, uint256 tokenID, uint256 amount, bytes memory data) public {
require(from == msg.sender || isApprovedForAll(from, msg.sender), "Sender is not approved to transfer tokens");
require(balanceOf(from, tokenID) >= amount, "Insufficient token balance");
safeTransferFrom(from, to, tokenID, amount, data);
emit TokensTransferred(from, to, tokenID, amount, data);
}

function lockTokens(uint256 tokenID, uint256 amount, uint256 unlockTimestamp) public {
require(unlockTimestamp > block.timestamp, "Unlock timestamp must be in the future");
require(balanceOf(msg.sender, tokenID) >= amount, "Insufficient token balance");
lockedBalance[msg.sender][tokenID] += amount;
emit TokensLocked(msg.sender, tokenID, amount, unlockTimestamp);
}

function unlockTokens(uint256 tokenID, uint256 amount) public {
require(lockedBalance[msg.sender][tokenID] >= amount, "Insufficient locked token balance");
lockedBalance[msg.sender][tokenID] -= amount;
_mint(msg.sender, tokenID, amount, "");
emit TokensUnlocked(msg.sender, tokenID, amount);
}
}
171 changes: 171 additions & 0 deletions DaoVoting.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract FractionalNFTWithVoting is ERC1155, Ownable {
struct Fraction {
uint256 tokenId;
uint256 amount;
uint256 totalSupply;
address owner;
mapping(address => uint256) votes;
}

enum GovernanceModel { SimpleMajority, Supermajority, Consensus }

struct Proposal {
string title;
string description;
string[] options;
uint deadline;
bool votingStarted;
mapping(address => bool) hasVoted;
mapping(string => uint) votes;
}

mapping(uint256 => Fraction) public fractions;
mapping(uint256 => uint256) public tokenIdToFractionId;
uint256 public fractionCounter;
address public factory;
uint256 public decisionThreshold;
mapping(uint256 => Proposal) public proposals;
uint256 public proposalCount;

event FractionCreated(uint256 indexed tokenId, uint256 indexed fractionId, uint256 amount);
event FractionTransferred(uint256 indexed fractionId, address indexed from, address indexed to, uint256 amount);
event VoteCasted(uint256 indexed fractionId, address indexed voter, bool vote);
event ProposalCreated(uint proposalId, string title);
event VotingStarted(uint proposalId, uint deadline);
event VoteRecorded(uint proposalId, string option, address voter);

constructor(address _factory, uint256 _decisionThreshold) ERC1155("") {
factory = _factory;
decisionThreshold = _decisionThreshold;
}

function createFraction(uint256 _tokenId, uint256 _amount) external {
require(msg.sender == factory, "Only factory can create fractions");
require(_amount > 0, "Amount must be greater than zero");
require(fractions[fractionCounter].totalSupply == 0, "Fraction already exists for this token");

fractions[fractionCounter] = Fraction({
tokenId: _tokenId,
amount: _amount,
totalSupply: _amount,
owner: msg.sender
});

tokenIdToFractionId[_tokenId] = fractionCounter;
_mint(msg.sender, fractionCounter, _amount, "");

emit FractionCreated(_tokenId, fractionCounter, _amount);
fractionCounter++;
}

function transferFraction(address _to, uint256 _fractionId, uint256 _amount) external {
require(fractions[_fractionId].owner == msg.sender, "You don't own this fraction");
require(_to != address(0), "Invalid address");
require(_amount > 0 && _amount <= balanceOf(msg.sender, _fractionId), "Invalid amount");

_safeTransferFrom(msg.sender, _to, _fractionId, _amount, "");
fractions[_fractionId].amount -= _amount;

emit FractionTransferred(_fractionId, msg.sender, _to, _amount);
}

function castVote(uint256 _fractionId, bool _vote) external {
require(fractions[_fractionId].owner != address(0), "Fraction does not exist");
require(balanceOf(msg.sender, _fractionId) > 0, "You don't own any fraction of this NFT");

fractions[_fractionId].votes[msg.sender] = _vote ? 1 : 0;

emit VoteCasted(_fractionId, msg.sender, _vote);
}

function calculateDecision(uint256 _fractionId, GovernanceModel _model) external view returns (bool) {
require(fractions[_fractionId].owner != address(0), "Fraction does not exist");

uint256 totalVotes = 0;
uint256 totalSupply = fractions[_fractionId].totalSupply;

// Count votes by iterating over all token holders
for (uint256 i = 0; i < fractionCounter; i++) {
address owner = fractions[i].owner;
if (fractions[_fractionId].votes[owner] == 1) {
totalVotes++;
}
}

if (_model == GovernanceModel.SimpleMajority) {
return totalVotes > (totalSupply / 2);
} else if (_model == GovernanceModel.Supermajority) {
return totalVotes >= ((totalSupply * 2) / 3);
} else if (_model == GovernanceModel.Consensus) {
return totalVotes == totalSupply;
}

return false;
}

function createProposal(
string memory _title,
string memory _description,
string[] memory _options
) public returns (uint) {
proposalCount++;
Proposal storage proposal = proposals[proposalCount];
proposal.title = _title;
proposal.description = _description;
proposal.options = _options;
emit ProposalCreated(proposalCount, _title);
return proposalCount;
}

function startVoting(uint _proposalId, uint _duration) public {
Proposal storage proposal = proposals[_proposalId];
require(!proposal.votingStarted, "Voting already started");
proposal.votingStarted = true;
proposal.deadline = block.timestamp + _duration;
emit VotingStarted(_proposalId, proposal.deadline);
}

function vote(uint _proposalId, string memory _option) public {
Proposal storage proposal = proposals[_proposalId];
require(block.timestamp < proposal.deadline, "Voting has ended");
require(!proposal.hasVoted[msg.sender], "You have already voted");

proposal.votes[_option]++;
proposal.hasVoted[msg.sender] = true;
emit VoteRecorded(_proposalId, _option, msg.sender);
}

function getVotes(uint _proposalId, string memory _option) public view returns (uint) {
Proposal storage proposal = proposals[_proposalId];
return proposal.votes[_option];
}

function getProposal(uint _proposalId) public view returns (
string memory title,
string memory description,
string[] memory options,
uint deadline,
bool votingStarted,
uint[] memory voteCounts
) {
Proposal storage proposal = proposals[_proposalId];
voteCounts = new uint[](proposal.options.length);
for (uint i = 0; i < proposal.options.length; i++) {
voteCounts[i] = proposal.votes[proposal.options[i]];
}
return (
proposal.title,
proposal.description,
proposal.options,
proposal.deadline,
proposal.votingStarted,
voteCounts
);
}
}
104 changes: 104 additions & 0 deletions fractional-NFT.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract DAOVoting is ERC1155, Ownable {
using Counters for Counters.Counter;

uint256 public currentTokenID = 0;
uint256 public constant TOTAL_SHARES = 1000000;

struct Proposal {
string description;
uint256 deadline;
uint256 votingStart;
mapping(address => bool) hasVoted;
uint256 yesVotes;
uint256 noVotes;
bool finalized;
}

mapping(uint256 => Proposal) public proposals;

Counters.Counter private proposalCounter;

event ProposalCreated(uint256 indexed tokenID, string description, uint256 deadline);
event VotingStarted(uint256 indexed tokenID, uint256 votingStart);
event VoteSubmitted(uint256 indexed proposalID, address indexed voter, bool choice);
event ProposalFinalized(uint256 indexed proposalID, uint256 yesVotes, uint256 noVotes);

constructor(string memory uri) ERC1155(uri) Ownable(0x7e2eD6241f395E32c2fcEdCE0829e0506cbCFc79) {
// Fractionalize the NFT "borderlesspower.dao" into 1,000,000 shares
_mint(msg.sender, currentTokenID, TOTAL_SHARES, "");
currentTokenID++;
}

function fractionalize(uint256 tokenID, uint256 amount) public onlyOwner {
require(balanceOf(msg.sender, tokenID) >= amount, "Insufficient token balance to fractionalize");
_mint(msg.sender, tokenID, amount, "");
}

function distributeFractionalShares(uint256 tokenID, address[] memory recipients, uint256[] memory amounts) public onlyOwner {
require(recipients.length == amounts.length, "Recipients and amounts arrays must have the same length");
for (uint256 i = 0; i < recipients.length; i++) {
_mint(recipients[i], tokenID, amounts[i], "");
}
}

function createProposal(string memory description, uint256 deadline) public onlyOwner {
require(deadline > block.timestamp, "Deadline should be in the future");
uint256 proposalID = proposalCounter.current();
proposals[proposalID].description = description;
proposals[proposalID].deadline = deadline;
emit ProposalCreated(proposalID, description, deadline);
_mint(msg.sender, proposalID, 1, "");
proposalCounter.increment();
}

function startVoting(uint256 proposalID, uint256 votingStart) public onlyOwner {
require(votingStart < proposals[proposalID].deadline, "Voting start time must be before the proposal deadline");
proposals[proposalID].votingStart = votingStart;
emit VotingStarted(proposalID, votingStart);
}

function submitVote(uint256 proposalID, bool choice) public {
Proposal storage proposal = proposals[proposalID];
require(proposal.votingStart > 0 && block.timestamp >= proposal.votingStart && block.timestamp <= proposal.deadline, "Voting period has not started or has ended");
require(!proposal.hasVoted[msg.sender], "You have already voted for this proposal");
proposal.hasVoted[msg.sender] = true;
if (choice) {
proposal.yesVotes++;
} else {
proposal.noVotes++;
}
emit VoteSubmitted(proposalID, msg.sender, choice);
}

function finalizeProposal(uint256 proposalID) public onlyOwner {
Proposal storage proposal = proposals[proposalID];
require(block.timestamp > proposal.deadline, "Voting period has not ended");
require(!proposal.finalized, "Proposal has already been finalized");
proposal.finalized = true;
emit ProposalFinalized(proposalID, proposal.yesVotes, proposal.noVotes);
}

function getVotingHistory(uint256 proposalID) public view returns (uint256 yesVotes, uint256 noVotes, bool finalized) {
Proposal storage proposal = proposals[proposalID];
return (proposal.yesVotes, proposal.noVotes, proposal.finalized);
}

function getCurrentProposalID() public view returns (uint256) {
return proposalCounter.current();
}

function getCurrentTimestamp() public view returns (uint256) {
return block.timestamp;
}

function getRandomNumber(uint256 range) public view returns (uint256) {
return uint256(keccak256(abi.encodePacked(block.timestamp, blockhash(block.number - 1), range))) % range;
}
}

0 comments on commit b314120

Please sign in to comment.