// SPDX-License-Identifier: MIT import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; pragma solidity ^0.8.5; /************************************** INTERFACES **************************************/ interface IRoles { function isManager(address account) external view returns(bool); function isMinter(address account) external view returns(bool); function isPauser(address account) external view returns(bool); } interface IRegistry { function getNumberOfCarbonCredits(string memory, string memory, uint256) external view returns (uint256); function getIsValued(string memory, string memory, uint256) external view returns (bool); function getIsReleased(string memory, string memory, uint256) external view returns (bool); } interface IAtlas { function getMintedStatus(string memory, string memory, uint256) external view returns (bool); function getIsValued(string memory, string memory, uint256) external view returns (bool); function getUrl(string memory, string memory, uint256) external view returns (string memory); function updateMintedStatus(string memory, string memory, uint256, bool) external; } interface IAddressSmartContract { function getRolesContractAddress() external view returns (address); function getRegistryPart1Address() external view returns (address); function getAtlasAddress() external view returns (address); function getWalletAddress() external view returns (address); } /************************************** CONTRACT **************************************/ contract CarbonCredits is Initializable, UUPSUpgradeable, ERC20Upgradeable, ERC20BurnableUpgradeable, PausableUpgradeable, AccessControlUpgradeable, ReentrancyGuardUpgradeable, OwnableUpgradeable { address private addressSC; event MintEvent(string LLD, string CreditType, uint256 Year, bytes32 Hash, uint256 NumOfCredits, address To, string URL); function initialize( address AddressSmartContract) public initializer { addressSC = AddressSmartContract; __ERC20_init("AtlasX Carbon Credits", "ATLASX"); __ERC20Burnable_init(); __Pausable_init(); __AccessControl_init(); __Ownable_init(); } function _authorizeUpgrade(address) internal virtual override onlyOwner {} //----------------- MINT FUNCTION ----------------// function mintCarbonCredits(string memory LLD, string memory CreditType, uint256 Year) public whenNotPaused nonReentrant { require(IRoles(IAddressSmartContract(addressSC).getRolesContractAddress()).isMinter(msg.sender), "Minting Access Denied: Caller is NOT MINTER!"); require((IRegistry(IAddressSmartContract(addressSC).getRegistryPart1Address()).getIsValued(LLD, CreditType, Year)), "Error: Input LLD not registered with Registry!"); require(!IRegistry(IAddressSmartContract(addressSC).getRegistryPart1Address()).getIsReleased(LLD, CreditType, Year), "Released Credits: Carbon credits released for this LLD"); require((IAtlas(IAddressSmartContract(addressSC).getAtlasAddress()).getIsValued(LLD, CreditType, Year)), "Error: Input LLD not registered with Atlas!"); require(!IAtlas(IAddressSmartContract(addressSC).getAtlasAddress()).getMintedStatus(LLD, CreditType, Year), "Double Minting: Carbon Credits minted already for this LLD"); IAtlas(IAddressSmartContract(addressSC).getAtlasAddress()).updateMintedStatus(LLD, CreditType, Year, true); _mint(IAddressSmartContract(addressSC).getWalletAddress(), IRegistry(IAddressSmartContract(addressSC).getRegistryPart1Address()).getNumberOfCarbonCredits(LLD, CreditType, Year)*10**18); emit MintEvent( LLD, CreditType, Year, keccak256(abi.encodePacked(LLD,CreditType,Year)), IRegistry(IAddressSmartContract(addressSC).getRegistryPart1Address()).getNumberOfCarbonCredits(LLD, CreditType, Year), IAddressSmartContract(addressSC).getWalletAddress(), IAtlas(IAddressSmartContract(addressSC).getAtlasAddress()).getUrl(LLD, CreditType, Year)); } function updateAddressSmartContract(address AddressSmartContract) public whenNotPaused { require(IRoles(IAddressSmartContract(addressSC).getRolesContractAddress()).isManager(msg.sender), "Access Denied: Caller is NOT Manager!"); require(AddressSmartContract != address(0), "Account: Zero or Invalid address!"); addressSC = AddressSmartContract; } //----------------- PAUSER FUNCTION ----------------// function pauseContract() public whenNotPaused { require(IRoles(IAddressSmartContract(addressSC).getRolesContractAddress()).isPauser(msg.sender), "Access Denied: Caller is NOT Pauser!"); _pause(); } function unpauseContract() public whenPaused { require(IRoles(IAddressSmartContract(addressSC).getRolesContractAddress()).isPauser(msg.sender), "Access Denied: Caller is NOT Pauser!"); _unpause(); } }