# LoggerNFT as a Digitial Twin :::info :bulb: ***NOTE:*** address and public key are used interchangeably ::: ## Outline - for each physical logger, there is a corresponding NFT (its Digital Twin) - the physical logger has a [public/private key pair](https://www.ledger.com/academy/blockchain/what-are-public-keys-and-private-keys) allowing it to sign transactions - in the `LoggerNFT` contract, the loggers variable is mapping of the `loggerId` and the [public key](https://ethereum.org/en/glossary/#public-key) of the physical logger - before the physical device can log data to the NFT, the `newJob()` function needs to be called along with an `amount` of USDC, `loggerID` of the NFT, and duration to job :::danger the insurance protocol will call the `newJob()` function. For now just assume that there is a insurance protocol and it is paying our company to maintain the phiscial hardware as well as paying NFT owners by calling this function ::: - when the logger is switched on it will sign the data it receives from its sensors with its [private key](https://www.ledger.com/academy/blockchain/what-are-public-keys-and-private-keys) and pass it to the `logData()` function with its `loggerId` - if the NFT has an active job it will accept the transaction and record the result and emit an event on chain - each NFT has an `owner` - this owner can claim any revenue accrued to their NFT by calling the `claim()` function - the owner can also transfer ownership via the `transfer()` function <br> ## Pseudo-code This is just pseudo code. This is kind of what the NFT would look like but there will be a bunch more variables and functions but this is the basic outline ```solidity contract LoggerNFT { // state uint lastLoggerId; // the total number of loggers mapping (address => uint) owners // mapping of owner addresses to loggerID's mapping (address => uint) loggers // mapping of logger addresses to loggerID's // Modifiers modifier onlyOwner() // if the caller of the function != owner then the function reverts modifier onlyLogger() // if the caller of the function != logger then the function reverts // functions function newLogger(owner, logger) returns (loggerId) // create a new digitial twin for a logger, reurns its NFT ID function newJob(amount, loggerId, startDate, endDate) // called by the insurance protocol, when the customer buys a policy function claim(loggerId) onlyOwner returns (amount) // transfers all clamable USDC for the owner of the loggerID function transfer(newOwner) onlyOwner // allows the owner to transfer ownership function logData(data[], loggerId) onlyLogger // called by the logger to publish its data on chain } ```