GPT V2 - Smart Contracts

Greener - Rede Ethereum

contract GPT is ERC20, Ownable { address _admin; bytes32 generatedHash; mapping(bytes32 => string[]) public compensatedData; mapping(address => bool) public approvedBurners;

n the GPT contract, we inherited the ERC20 from Openzeppelin, and the custom Ownable, which will be explained below.

We have variables to store the contract admin (or owner), and bytes32 generatedHash, which are the hashes generated with compensation.

We have 2 mappings, the first takes the hash created in compensation as its key, and shows the data, such as farm id, quantity, etc. The second mapping is just to verify if an address is true, so you can call the burn function. (Only the admin can be added as approvedburner).).

constructor( string memory name, string memory symbol, uint256 initialSupply, address admin ) ERC20(name, symbol) { _admin = admin; _mint(msg.sender, initialSupply); } We start the contract normally by passing the 4 parameters. The admin must be Fireblocks' address, and we mint the total value to the msg.sender, which is also Fireblocks.

function mint(address to, uint256 amount) public onlyOwner { _mint(to, amount); } Standard mint function. onlyOwner, because Fireblocks and any added owners can mint (bridge, for example).

function decimals() public view virtual override returns (uint8) { return 6; } Function for decimals, because by default it is 18. Changing it to 6.

function approveBurner() public { require(msg.sender != _admin, "admin can't self approve"); approvedBurners[address(_admin)] = true; Function to approve the admin to compensate the GPT. Admin cannot self-approve. function revokeBurnerApproval() internal { approvedBurners[address(_admin)] = false; } Internal function, after the compensation, the admin returns to false, waiting for another compensation request to be able to burn again.

function generate(string[] memory data) internal returns (bytes32) { generatedHash = keccak256(abi.encode(data)); compensatedData[generatedHash] = data; return generatedHash; } Internal function used by the offseting function. This function takes an array of strings with the offseting data, encodes it, and generates a hash.

function burnFrom(address from, uint256 amount) internal returns (bool) { require( approvedBurners[msg.sender] == true, "Only approved burner can call this function" ); _burn(from, amount); revokeBurnerApproval(); return true; } BurnFrom: internal function where the msg.sender must be approved in approvedBurners, performs the burn on the address passed as a parameter, and loses the right to burn. It is used in the function below.

function compensate( address from, uint256 amount, string[] memory data ) public onlyOwner returns (bytes32) { generate(data); require(burnFrom(from, amount), "Burn didn't worked"); return (generatedHash); } Compensate function: Receives the user's address, the amount to be compensated, and the compensation data. Generates the hash, then performs the burn and returns this hash, so that we can store and retrieve it in the future.

function burn( address from, uint256 amount ) public onlyOwner returns (bool) { _burn(from, amount); return true; } Standard burn function: OnlyOwner, as Fireblocks and any added owner can perform the burn (e.g., bridge).


abstract contract Ownable is Context { mapping(address => bool) private _owner;

event OwnershipAdded(address indexed newOwner); event OwnershipRemoved(address indexed removedOwner);

Mapping that saves the owner's address with true or false. And two events indicating owner added or removed.

constructor() { _addOwnership(_msgSender()); } It is already initiated by adding the msg.sender as an owner (in this case, Fireblocks, which will perform the deployment).

modifier onlyOwner() { _checkOwner(); _; } Modifier that we are using

function _checkOwner() internal view virtual { require( _owner[_msgSender()] == true, "Ownable: caller is not the owner" ); } Check owner, as used in the modifier, checks if the address is set to true; if it's not, it's not an owner.

function addOwnership(address newOwner) public virtual onlyOwner { require( newOwner != address(0), "Ownable: new owner is the zero address" ); _addOwnership(newOwner); } "Add ownership" receives an address and sets it to true, allowing it to become an owner (Fireblocks can add another address, enabling the bridge). Only an owner can add another one.

function _addOwnership(address newOwner) internal virtual { _owner[newOwner] = true; emit OwnershipAdded(newOwner); } Internal function that actually sets the address to true and emits the "owner added" event.

function renounceOwnership(address removedOwner) public virtual onlyOwner { _owner[removedOwner] = false; emit OwnershipRemoved(removedOwner); } Function that can only be called by an owner, receives an address and sets it to false as an owner, removing the permissions.

function readOwner(address owner) public view returns (bool) { return _owner[owner]; } ReadOwner function receives an address and checks if it is true or false. Read-only function.

Last updated