Skip to content

Commit

Permalink
Merge pull request #2 from oscarpascualbakker:feature/general-improve…
Browse files Browse the repository at this point in the history
…ments

General improvements to Txoco Cal Padrí Smart Contract
  • Loading branch information
oscarpascualbakker authored Aug 23, 2023
2 parents 036f34c + 17b0829 commit e4274c7
Show file tree
Hide file tree
Showing 12 changed files with 133 additions and 5,785 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,7 @@ yarn-error.log

# Directory for deployed contracts, not needed in version control
deployed/

# Cache & Artifacts
cache/
artifacts/
11 changes: 9 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
FROM node:14
FROM node:16

WORKDIR /app

COPY package*.json ./
COPY package.json ./

# Install Truffle globally
RUN npm install -g truffle

# Install Truffle tools
RUN npm install @truffle/hdwallet-provider truffle-plugin-verify

RUN npm install @openzeppelin/contracts
RUN npm install chai truffle-assertions
RUN npm install dotenv

# Install dependencies
ARG CACHE_INVALIDATE=1
RUN npm install
Expand Down
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ TxocoCalPadri is a smart contract written in Solidity for the Ethereum Virtual M

## Functions

##### `setBaseURI(string memory baseURI)`

Allows the contract owner to set the URI for the token metadata.

##### `setAdministrator(address _admin, bool _status)`

Allows the contract owner to add or remove administrators. Set `_status` to true to add, and false to remove.
Expand Down Expand Up @@ -52,12 +56,28 @@ Returns the index, name, and vote count of the winning option for a specific pro
- `Voted`
- `NFTMinted`


## Overridden Functions
This contract overrides the following functions from its inherited contracts to adapt their behavior for the specific requirements of this contract:

##### `uri(uint256 tokenId) -> string`

This function overrides the uri function from the ERC1155 contract. It is used to get the URI for a token's metadata. However, in this contract, it ignores the tokenId parameter and returns the base URI for all tokens.

##### `safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes memory _data)`

This function overrides the safeTransferFrom function from the ERC1155 contract. It is used to safely transfer tokens from one address to another. In this contract, the function has been modified to only allow administrators to transfer tokens.

##### `safeBatchTransferFrom(address _from, address _to, uint256[] memory _ids, uint256[] memory _values, bytes memory _data)`

This function overrides the safeBatchTransferFrom function from the ERC1155 contract. It is used to perform a batch transfer of multiple tokens from one address to another. In this contract, the function has been modified to only allow administrators to transfer tokens.

## Testing

1. Clone this repository.
2. Navigate to the project folder and run `docker-compose build --no-cache`.
3. Run the containers using `docker-compose up -d`.
4. Compile and run tests using the following command: `docker-compose run txoco truffle test`.
4. Compile and run tests using the following command: `docker-compose run --rm txoco truffle test`.

#### Expected result:
![Resultado de los tests](https://oscarpascual.com/test-results-txococalpadri.jpg)
Expand Down
73 changes: 63 additions & 10 deletions contracts/TxocoCalPadri.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
pragma solidity >=0.8.0 <0.9.0;

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


contract TxocoCalPadri is ERC1155, Ownable {
contract TxocoCalPadri is ERC1155 {

address public owner;

struct Proposal {
string title;
Expand All @@ -30,39 +31,62 @@ contract TxocoCalPadri is ERC1155, Ownable {
event NFTMinted(address to);


modifier onlyOwner() {
require(msg.sender == owner, "You are not the owner");
_;
}

modifier onlyAdministrator() {
require(administrators[msg.sender], "You are not an administrator");
_;
}

constructor(string memory _baseURI) ERC1155(_baseURI) {

/**
* @notice Initializes the contract and sets the base URI for tokens.
*/
constructor() ERC1155("") {
owner = msg.sender;
administrators[msg.sender] = true; // The contract deployer is the first administrator
setBaseURI(_baseURI);
baseURI = "https://oscarpascual.com/txococalpadri/metadata.json";
_setURI(baseURI);
}


/**
* @notice Allows the owner to set the base URI.
* @param _baseURI The new base URI to be set.
*/
function setBaseURI(string memory _baseURI) public onlyOwner {
baseURI = _baseURI;
_setURI(_baseURI);
}


/**
* @notice Overrides the uri function from ERC1155 to return the base URI for all tokens.
* @param tokenId The ID of the token.
* @return The base URI string.
*/
function uri(uint256 tokenId) public view override returns (string memory) {
// Ignore tokenId, as it is not needed in this contract
return baseURI;
}


/**
* Set or unset administrators.
* @notice Set or unset an address as an administrator.
* @param _admin The address to be set or unset as administrator.
* @param _status The status to set, true for set and false for unset.
*/
function setAdministrator(address _admin, bool _status) external onlyOwner {
administrators[_admin] = _status;
}


/**
* In this smart contract you can only have 1 NFT.
* @notice Mints a new NFT to the specified address. Members can only have one.
* @param _to The address to mint the NFT to.
*/
function mintNFT(address _to) external onlyAdministrator {
require(balanceOf(_to, 0) == 0, "Address already owns the NFT");
Expand All @@ -72,15 +96,23 @@ contract TxocoCalPadri is ERC1155, Ownable {


/**
* NFTs can also be revoked in this smart contract. When you are no longer a member of
* the association, your NFT is burned.
* @notice Burns the NFT from the specified address. Non-members can't hold the NFT.
* @param _from The address to burn the NFT from.
*/
function revokeNFT(address _from) external onlyAdministrator {
require(balanceOf(_from, 0) > 0, "Address does not own the NFT");
_burn(_from, 0, 1);
}


/**
* @notice Allows an administrator to create a new proposal.
* @param _title The title of the proposal.
* @param _description The description of the proposal.
* @param _options The options for the proposal.
* @param _startTime The start time of the proposal.
* @param _endTime The end time of the proposal.
*/
function createProposal(string memory _title, string memory _description, string[] memory _options, uint256 _startTime, uint256 _endTime) external onlyAdministrator {
require(_endTime > _startTime, "End time must be after start time");

Expand All @@ -99,6 +131,10 @@ contract TxocoCalPadri is ERC1155, Ownable {
}


/**
* @notice Allows an administrator to close a proposal.
* @param _proposalId The ID of the proposal to be closed.
*/
function closeProposal(uint256 _proposalId) external onlyAdministrator {
require(_proposalId < proposalCount, "Proposal does not exist");
require(proposals[_proposalId].active, "Proposal is already closed");
Expand All @@ -109,6 +145,11 @@ contract TxocoCalPadri is ERC1155, Ownable {
}


/**
* @notice Allows a member to vote on a proposal.
* @param _proposalId The ID of the proposal to vote on.
* @param _selectedOption The index of the selected option.
*/
function vote(uint256 _proposalId, uint256 _selectedOption) external {
require(balanceOf(msg.sender, 0) > 0, "Must be a member to vote");
require(proposals[_proposalId].active, "Proposal is not active");
Expand All @@ -131,13 +172,22 @@ contract TxocoCalPadri is ERC1155, Ownable {
}


/**
* @notice Get the vote counts for each option in a proposal.
* @param _proposalId The ID of the proposal.
* @return An array containing the vote counts for each option.
*/
function getOptionVoteCounts(uint256 _proposalId) external view returns (uint256[] memory) {
return proposals[_proposalId].optionVoteCounts;
}


/**
* It returns the winning option, its name and its number of votes
* @notice Get the winning option for a proposal.
* @param _proposalId The ID of the proposal.
* @return winningOption The index of the winning option.
* @return optionName The name of the winning option.
* @return voteCount The vote count of the winning option.
*/
function getWinningOption(uint256 _proposalId) external view returns (uint256 winningOption, string memory optionName, uint256 voteCount) {
uint256[] memory counts = proposals[_proposalId].optionVoteCounts;
Expand All @@ -158,14 +208,17 @@ contract TxocoCalPadri is ERC1155, Ownable {


/**
* Membership of the association is not transferable.
* @notice Overrides safeTransferFrom function to only allow administrators to transfer tokens.
*/
function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes memory _data) public override {
require(administrators[msg.sender] || msg.sender == address(this), "Only administrators can transfer tokens");
super.safeTransferFrom(_from, _to, _id, _value, _data);
}


/**
* @notice Overrides safeBatchTransferFrom function to only allow administrators to transfer tokens.
*/
function safeBatchTransferFrom(address _from, address _to, uint256[] memory _ids, uint256[] memory _values, bytes memory _data) public override {
require(administrators[msg.sender] || msg.sender == address(this), "Only administrators can transfer tokens");
super.safeBatchTransferFrom(_from, _to, _ids, _values, _data);
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ services:
build: .
volumes:
- .:/app
- /app/node_modules
command: /bin/sh
depends_on:
- ganache
17 changes: 0 additions & 17 deletions metadata-example.json

This file was deleted.

3 changes: 1 addition & 2 deletions migrations/2_deploy_txococalpadri.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@
var TxocoCalPadri = artifacts.require("./TxocoCalPadri.sol");

module.exports = function(deployer) {
const initialBaseURI = "https://ipfs.io/ipfs/QmNkgQe8meF31ZZ7fZ3rAvSEYtjnfxtWgiXgh7Xte7ack3";
deployer.deploy(TxocoCalPadri, initialBaseURI);
deployer.deploy(TxocoCalPadri);
};
Loading

0 comments on commit e4274c7

Please sign in to comment.