// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; contract TestCO2 is ERC1155 { uint256 public constant CO2 = 1; address public supplier; // Supplier of the project address public verifier; // Verifier of the project bytes32 public documentHash; // Project Document hash string public offsetMethodName; // Offset method name uint256 public issuedQuantity; // Amount of CO2 purchased by supplier enum ProjectStatus { Published, Verified } ProjectStatus public projectStatus; // Project status mapping(address => uint256) public retireBalances; // List of all users retireBalances // constructor() ERC1155("https://ipfs.io/ipfs/bafybeihjjkwdrxxjnuwevlqtqmh3iegcadc32sio4wmo7bv2gbf34qs34a/{id}.json") { // _mint(msg.sender, CO2, 10 * 10 ** 8, ""); //create 1000000000 copies of co2, here co2 is erc20 // } constructor( address _supplier, //bytes32 _documentHash, string memory _offsetMethodName, uint256 co2quantity, address _verifier, string memory _uri ) ERC1155(_uri) { supplier = _supplier; //documentHash = _documentHash; issuedQuantity = co2quantity; offsetMethodName = _offsetMethodName; projectStatus = ProjectStatus.Published; verifier = _verifier; } function uri(uint256 _tokenid) override public pure returns (string memory) { return string( abi.encodePacked( "https://ipfs.io/ipfs/bafybeihjjkwdrxxjnuwevlqtqmh3iegcadc32sio4wmo7bv2gbf34qs34a/", Strings.toString(_tokenid),".json" ) ); } /** * verify the project based on the project co2 quantity and this project is called by only verifier * this method changes the project status to Verified on success else the project status remains the same * @param co2quantity co2quantity of the project * Requirements: * - `co2quantity` must be same as the issuedQuantity given at the time of deployment. * - project status must be in published state. */ function verifyProject(uint256 co2quantity) public onlyVerifer isProjectPublished { require( issuedQuantity == co2quantity, "Purchased CO2 quantity is incorrect" ); _mint(supplier, CO2, co2quantity, ""); projectStatus = ProjectStatus.Verified; } /** * modifier to check if the sender is only verifier */ modifier onlyVerifer() { require(msg.sender == verifier, "Only verifier allowed to call this"); _; } /** * modifier to check if the project is in verified state */ modifier isProjectAccepted() { require( projectStatus == ProjectStatus.Verified, "Project is not in Verified state" ); _; } /** * modifier to check if the project is in published state */ modifier isProjectPublished() { require( projectStatus == ProjectStatus.Published, "Project is not in Published state" ); _; } /** * transfer co2 quantity from sender to the given recipient * @param sender address of the sender * @param recipient address of the recipient * @param amount co2 quantity to be sent * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` and `msg.sender` both needs to be same. * - `sender` must have a balance of at least `amount`. * - project status must be in verified state. */ function safeTransferFrom( address sender, address recipient, uint256 id, uint256 amount, bytes memory data ) public virtual override isProjectAccepted { require(msg.sender != address(0), "Given sender address is invalid"); require( msg.sender == address(sender), "Given sender address is not same as sender address" ); require(address(recipient) != address(0), "Given address is invalid"); require( getCO2Balance(sender, id) >= amount, "No Sufficient balance avaliable" ); //approve(sender, amount); super.safeTransferFrom(sender, recipient, id, amount, data); } /** * decimals of the amount * @return the number of decimals used to get its user representation * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). */ function decimals() public view virtual returns (uint8) { return 8; } /** * make retire the given amount of co2 quantity * @param _amount co2 quantity to be retired * on success this method burn the given amount of co2 quantity from the sender and update it to retireBalances mapping * Requirements: * - `sender` cannot be the zero address. * - `sender` must have a balance of at least `_amount`. * - project status must be in verified state. */ function makeRetire(uint256 _amount, uint256 id) public isProjectAccepted { require(msg.sender != address(0), "Given address is invalid"); require( getCO2Balance(msg.sender, id) >= _amount, "No Sufficient balance avaliable" ); super._burn(msg.sender, id, _amount); retireBalances[msg.sender] += _amount; } /** * get current co2 balance of the given address * @param owner to get current co2 balance * returns current co2 balance */ function getCO2Balance(address owner, uint256 id) public view virtual returns (uint256) { uint256 erc20Balance = super.balanceOf(owner, id); return erc20Balance; } }