//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"; pragma solidity ^0.8.5; /************************************** INTERFACES **************************************/ interface IRoles { function isManager(address account) external view returns(bool); function isUpdatesManager(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 getIsValued(string memory, string memory, uint256) external view returns (bool); function getIsReleased(string memory, string memory, uint256) external view returns (bool); } interface IAddressSmartContract { function getRolesContractAddress() external view returns (address); function getRegistryPart1Address() external view returns (address); } /************************************** CONTRACT **************************************/ contract Atlas is Initializable, UUPSUpgradeable, AccessControlUpgradeable, PausableUpgradeable, OwnableUpgradeable { address private addressSC; function initialize( address AddressSmartContract) public initializer { addressSC = AddressSmartContract; __AccessControl_init(); __Pausable_init(); __Ownable_init(); } function _authorizeUpgrade(address) internal virtual override onlyOwner {} /************************************** STRUCTURES **************************************/ //TABLE STRUCTURE struct Status { bytes32 lld; bytes32 creditType; bytes32 transactionId; bytes32 url; uint256 year; bool isValued; bool mintedStatus; } mapping (bytes32 => Status) public lookUpTable; function stringToBytes32(string memory _str) public pure returns (bytes32) { bytes memory tempBytes = bytes(_str); bytes32 convertedBytes; if(tempBytes.length == 0){ return 0x0; } assembly{ convertedBytes := mload(add(_str,32)) } return convertedBytes; } //----------------------- REGISTER NEW LLD FUNCTIONS -----------------------// //MAKE A NEW ENTRY IN THE TABLE function registerLLD( string memory LLD, string memory CreditType, uint256 Year, string memory Url) public whenNotPaused { require(IRoles(IAddressSmartContract(addressSC).getRolesContractAddress()).isManager(msg.sender), "Access Denied: Caller is NOT Manager!"); require(IRegistry(IAddressSmartContract(addressSC).getRegistryPart1Address()).getIsValued(LLD, CreditType, Year), "Error: Input LLD not found with Registry!"); require(!(IRegistry(IAddressSmartContract(addressSC).getRegistryPart1Address()).getIsReleased(LLD, CreditType, Year)), "Error: Input LLD is released from Registry!"); require(!getIsValued(LLD, CreditType, Year), "Error: LLD is already registered with Atlas!"); bytes32 newEntry = keccak256(abi.encodePacked(LLD,CreditType,Year)); lookUpTable[newEntry].lld = stringToBytes32(LLD); lookUpTable[newEntry].creditType = stringToBytes32(CreditType); lookUpTable[newEntry].year = Year; lookUpTable[newEntry].mintedStatus = false; lookUpTable[newEntry].isValued = true; lookUpTable[newEntry].url = stringToBytes32(Url); } //----------------------- GETTER FUNCTIONS -----------------------// //GET mintedStatus STATUS function getMintedStatus(string memory LLD, string memory CreditType, uint256 Year) public view returns (bool) { require(getIsValued(LLD,CreditType,Year), "Error: Input LLD not found in Atlas!"); return lookUpTable[keccak256(abi.encodePacked(LLD,CreditType,Year))].mintedStatus; } function getIsValued(string memory LLD, string memory CreditType, uint256 Year) public view returns (bool) { if(lookUpTable[keccak256(abi.encodePacked(LLD,CreditType,Year))].isValued) return true; else return false; } function getUrl(string memory LLD, string memory CreditType, uint256 Year) public view returns (string memory) { require(getIsValued(LLD,CreditType,Year), "Error: Input LLD not found in Atlas!"); return string(abi.encodePacked(lookUpTable[keccak256(abi.encodePacked(LLD,CreditType,Year))].url)); } //----------------- UPDATE FUNCTIONS ----------------// 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; } function updateLLDInfo(string memory oldLLD, string memory oldCreditType, uint256 oldYear, string memory newLLD, string memory newCreditType, uint256 newYear) public whenNotPaused () { require(IRoles(IAddressSmartContract(addressSC).getRolesContractAddress()).isManager(msg.sender), "Access Denied: Caller is NOT Manager!"); require(getIsValued(oldLLD,oldCreditType,oldYear), "Error: Input LLD not found in Atlas!"); require(!getIsValued(newLLD,newCreditType,newYear), "Error: Input NEW LLD values are already registered with Registry!"); require(!(keccak256(abi.encodePacked(newLLD)) == keccak256(abi.encodePacked(""))), "Invalid input: Zero or invalid LLD!"); require(!(keccak256(abi.encodePacked(newCreditType)) == keccak256(abi.encodePacked(""))), "Invalid input: Zero or invalid CreditType!"); require(!(newYear == 0), "Invalid input: Zero or invalid year!"); bytes32 oldEntry = keccak256(abi.encodePacked(oldLLD,oldCreditType,oldYear)); bytes32 newEntry = keccak256(abi.encodePacked(newLLD,newCreditType,newYear)); lookUpTable[newEntry].lld = stringToBytes32(newLLD); lookUpTable[newEntry].creditType = stringToBytes32(newCreditType); lookUpTable[newEntry].year = newYear; lookUpTable[newEntry].isValued = true; lookUpTable[newEntry].mintedStatus = lookUpTable[oldEntry].mintedStatus; //getMintedStatus(oldLLD,oldCreditType,oldYear); lookUpTable[newEntry].transactionId = lookUpTable[oldEntry].transactionId; lookUpTable[newEntry].url = lookUpTable[oldEntry].url; deleteLLD(oldLLD, oldCreditType, oldYear); } //UPDATE url function updateUrl(string memory LLD, string memory CreditType, uint256 Year, string memory Url) public whenNotPaused { require(IRoles(IAddressSmartContract(addressSC).getRolesContractAddress()).isUpdatesManager(msg.sender), "Access Denied: Caller is NOT Updates Manager!"); require(getIsValued(LLD,CreditType,Year), "Error: Input LLD not found in Atlas!"); lookUpTable[keccak256(abi.encodePacked(LLD,CreditType,Year))].url = stringToBytes32(Url); } //UPDATE transactionId function updateTransactionId(string memory LLD, string memory CreditType, uint256 Year, string memory TransactionId) public whenNotPaused { require(IRoles(IAddressSmartContract(addressSC).getRolesContractAddress()).isUpdatesManager(msg.sender), "Access Denied: Caller is NOT Updates Manager!"); require(getIsValued(LLD,CreditType,Year), "Error: Input LLD not found in Atlas!"); lookUpTable[keccak256(abi.encodePacked(LLD,CreditType,Year))].transactionId = stringToBytes32(TransactionId); } //----------------------- MINTER (ERC20) FUNCTIONS (Change MintedStatus) -----------------------// //UPDATE mintedStatus function updateMintedStatus(string memory LLD, string memory CreditType, uint256 Year, bool MintedStatus) public { require(getIsValued(LLD,CreditType,Year), "Error: Input LLD not found in Atlas!"); if(getMintedStatus(LLD,CreditType,Year)) { require(IRoles(IAddressSmartContract(addressSC).getRolesContractAddress()).isManager(msg.sender), "Updating Mint Status Failed: Caller is NOT MANAGER!"); lookUpTable[keccak256(abi.encodePacked(LLD,CreditType,Year))].mintedStatus = MintedStatus; } else { require((IRoles(IAddressSmartContract(addressSC).getRolesContractAddress()).isMinter(msg.sender)), "Updating Mint Status Failed: Caller is NOT MINTER!"); lookUpTable[keccak256(abi.encodePacked(LLD,CreditType,Year))].mintedStatus = MintedStatus; } } //----------------- 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(); } //----------------------- KILL FUNCTIONS -----------------------// //DELETE A LLD ENTRY function deleteLLD(string memory LLD, string memory CreditType, uint256 Year) public { require(IRoles(IAddressSmartContract(addressSC).getRolesContractAddress()).isManager(msg.sender), "Access Denied: Caller is NOT Manager!"); require(getIsValued(LLD,CreditType,Year), "Error: Input LLD not registered with Atlas!"); delete lookUpTable[keccak256(abi.encodePacked(LLD,CreditType,Year))]; } }