What is Geppetto?
Problem
We are handling accounting for modern enterprises — it is something they have to do every day.
DATA, RESEARCH, FEEDBACK | Insert cold-ass facts here
We are entrepreneurs, and we crashed our startup due to a lack of transparency and poor management of our accounting.
This problem creates barriers to financial inclusion. It is important that technology gives us a level playing field to work on.
Proposal
Using Smart Contracts to Establish Decentralized Accounting Contracts:
Geppetto is a bookkeeping assistant in the palm of our hand. It helps us at every step of the accounting process. In our first iteration we wanted to build it as a WhatsApp bot, but we soon discovered that this limited functionality, user interfaces, and versatility.
For the user, Geppetto is a virtual assistant living in a PWA. Behind the scenes, the operation follows (more or less) this diagram:

To fully solve our problem we must …
An indicator of our product’s validity is meeting the cost-efficiency principle, which states that the costs of maintaining a company’s books should not be so high as to impede its efficiency.
To make our product fast, efficient, and scalable we have chosen a modern technology stack that leverages several L2 EVM-compatible networks and off-chain decentralized tables.
Form Submission (current)
Current Development
Prompt Engineering by Emilio @ Zirkel
Our goal is to train / adequate a GPT model to be capable of identifying accounting entries within natural language messages. This accounting entries are the input that the smart contracts will work with. First, we set the “primary function” of the model, by describing to it “who” it is or “why” it exists. Then we establish the context to the model (system promt):
“You are an excellent accountant. You are a specialist on the compliance of the GAAP principles and the FASB standards. I am creating an accountability software system designed for firms. The software enables employees, managers and directors to record and track both internal and external transactions or business day to day operations by simply sending messages to a chat. This innovative program has the ability to understand the information contained in the messages (written in natural language), and seamlessly transform it into an accounting entry. How does this work? The program detects the different accounting accounts (variables) from the messages sent and stores it in a database. As this database encompasses a range of financial, accountability and inventory management variables, the data will then be processed into an array of management, financial statements, and live dashboards. Also, the user (employee, manager, or director) is enabled to search for data points or specific financial statements in the same way: with natural language sent messages in the chat format. In this way the software will, again, find categorized variables or accounting accounts, the database, or final dashboard and metric and give the output to the user.”
Second, we explain the model how it will operate and what to consider to achieve it:
“Now, how will you help me as the high profile accountant you are? First, I need you to be a “generator of accounting catalogues” (the catalogue contains all the accounts of a given business.) The software will first be used in the retail industry, considering both online and offline. As the retail industry circumscribes many different subindustries the idea is that the account generator should be able to produce generic enough accounts always considering the retail industry operations context. The generator should also consider that the accounts have to be exhaustive and specific enough to permit the accounts (catalogue of accounts) to fully consider any operation or transaction that the business might run with suppliers or clients. For this, you should ALWAYS ask for a complete list of suppliers and clients (as each provider and client have particular accounting subaccounts that end up being more general accounts such as “accounts payable”, for example. Also, you have to ALWAYS ask for the current balances of accounts and subaccounts generated by you. You have to ask for a full list of inventory items and their respective prices as this is information required for certain accounting entries. These last points permit the users to have their historic records all set up so they can start recording new transactions /operations. These subaccounts will also be used for inventory management so it is really important and accounts (conformed by subaccounts) will be used for financial statements. Keep in mind that your art is to make each catalogue tailored to the users’ business context and specific requests. The end user will first explain you their business model through the messages and you will respond with questions until you know the required information to meet the previously mentioned standards. Be contundent so the user only has to respond 12 questions maximum. This part of the system will only used the first time to set the software operation.”
Third, we let know the model when to let users start recording business operations / transactions. We also ask the model to give the output (accounting entry) in a specific format:
“Second, you will tell the user through the message chat that they can start recording operations/transactions. As you receive each input, you will display the correspondent accounting entry using the accounts of the account catalogue that you generated. You will use debit and credit system for the values impacted of each account. The result you will then display should always comply with this format:
\ninterface Entry {\n ID: number,\n type: string,\n accIn: string,\n qty: string,\n cash: string || string[],\n accOut: string || string[],\n}\n ”
Lastly, we give some more context of potential issues that might present and explain what to do in such cases. We also assure that the model always has the drive of complying with regulatory standards:
“Now, if the user is not giving you sufficient information for you to properly determine the accounting entry or the accounts affected you will ask the user for more detailed information specific to the part you are missing. If the operation/ transaction was not considered in the initial accounts catalogue you have to ask the user if the new account wants no be added to the catalogue and that the action is required to continue with the respective recording. You will learn from the way every user uses natural language to record specific transactions which will make you faster and meet detail more easily (always considering the key takeaway of the correct standards used to record transactions within the GAAP and FASB.”
We have to consider further work on the prompt. For this initial iteration we learned two remarkable aspects for improvement:
- We know the GPT model can be “manipulated” or implanted with wrong logic. This potentialy could let users modify entries/ records that would make the model change or record wrongly.
- Also, it seems as if the model sometimes would forget the information that was previously stated in the messages. As this is supposed to work as a transaction recorder the model must always keep in storage /memory all variables, accounts, and values.
Prompt Example
Two-step pipeline: Step 1: Geppetto learns about the business
System: “You are Geppetto, you are a bookkeeping assistant under IFRS standards…” AI: “I have a questionnaire to understand your business well
- What is your business?
- Do your suppliers extend credit?
- … User: “1. A bicycle workshop and store
- Yes, Benotto leaves me merchandise and I pay at the end of the month …
- …”
AI: Okay, I have generated your chart of accounts
{ [0001, Inventory], [00011, Frames], [0002, Benotto], … , }
Step 2: Geppetto performs the accounting entries
System: “You are Geppetto, you are a bookkeeping assistant under IFRS standards… and you will return an object in this format FORMAT for each accounting entry” User: “I bought 2 Santa Cruz frames model 9182 for $7,000 and paid with my BBVA card”
AI: ****
”
C: Inventory (Bicycles) 7000 D: Banks (BBVA) 7000
“
Chart of Accounts
1. ASSETS
1.1. Current Assets
1.1.1. Cash 1.1.2. Banks 1.1.3. Temporary Investments 1.1.4. Accounts Receivable 1.1.5. Bicycle Inventory 1.1.6. Accessories Inventory 1.1.7. Spare Parts Inventory 1.1.8. Prepaid Expenses (e.g. Rent or insurance paid in advance)
1.2. Non-Current Assets
1.2.1. Property, Plant and Equipment 1.2.1.1. Store Building 1.2.1.2. Furniture and Equipment 1.2.1.3. Computer Equipment 1.2.1.4. Delivery Vehicles
1.2.2. Accumulated Depreciation (contra account) 1.2.3. Intangible Assets 1.2.3.1. Point of Sale Software 1.2.3.2. Licenses 1.2.4. Accumulated Amortization (contra account)
2. LIABILITIES
2.1. Current Liabilities
2.1.1. Accounts Payable to Suppliers 2.1.2. Short-Term Bank Loans 2.1.3. Taxes Payable 2.1.4. Wages Payable
2.2. Non-Current Liabilities
2.2.1. Long-Term Bank Loans
3. EQUITY
3.1. Share Capital 3.2. Reserves 3.3. Retained Earnings 3.4. Net Income (or Loss) for the Period
4. REVENUE
4.1. Bicycle Sales 4.2. Accessories Sales 4.3. Spare Parts Sales 4.4. Repair and Maintenance Services
5. EXPENSES
5.1. Bicycle Purchases 5.2. Accessories Purchases 5.3. Spare Parts Purchases 5.4. Personnel Expenses 5.5. Rent or Lease 5.6. Depreciation 5.7. Amortization 5.8. General Expenses (water, electricity, telephone) 5.9. Advertising and Marketing 5.10. Bank Charges
Scroll Deployment
Scroll’s Sepolia Testnet
Best on Scroll: (3x 1000)
Polygon:
Polygon zkEVM deploy: $2,500 Best use of zkEVM
SAFE
To simulate the accounting environment, we use SAFE. This is possible because its management of multiple abstract accounts on Ethereum and EVM-compatible networks allows us to control multiple accounts from a single smart contract.
With this control, we can transfer and mint ERC-20 tokens between different accounts to simulate accounting entries quickly, efficiently, and accurately.
(Illustrative image of SAFE Wallet, however the SAFE SDK was used)To be eligible, developers must build with one of the following options:


Safe{Core} Protocol (integrating or implementing any part of the Protocol).
Safe{Core} Account Abstraction SDK (integrating at least one of the existing kits).
Tableland
Only those with the proper on-chain privileges can write to a specific table. Table reads, however, do not have an on-chain operation and use the Tableland gateway.
- Ethereum Testnet
In the future, we want to implement a Filecoin Virtual Machine receipt/storage + Tableland Capabilities
Technical Development
Homomorphic Encryption
Mathematical foundation: preserves sums under elliptical transformation, which allows verifying the accounting balance without publishing the transaction values.
See
a+b @=c vs Enct(a) +Encr(b) = Encr (c)
Deploy on Mantle
A tweet needs to be created to accompany the contract and the repo.
Wormhole Messaging
We start on the abstract chain. When it becomes necessary to send a token to the real world, i.e. a blockchain for receipts with ENS support, USDC, or some other token, the Wormhole message is used.
MEETING October 16:
The idea is to use that diagram as a workflow.
We need to add a step 1 (between the front-end and the interaction with the Tableland contract) — a backend that serves to:
-
Encrypt our entries
-
Generate the transaction parameters that the Safe will send on our behalf
- RegEx + Py(Chart of Accounts Handler) = Safe CLI
e.g. I&O Geppetto I:
“I bought 2 Santa Cruz frames model 9182 for $7,000 and paid with my BBVA card”
O:
”
{
C: Inventory (Frames) 7000 D: Accounts Payable (BBVA) 7000 }“
XMTP Messaging
Best Encrypted Messages Hack with Lit — $1,500
Send Encrypted Messages to Email/SMS Users Using Lit’s “Claimable Keys” and build a user experience around the following idea: “Send your friends a secure message through AGivenDapp. Just enter their email or phone number”.
- For example: When Alix enters an email, bo@site.com, bo@site.com gets an email that says “Alix invited you / sent you a message / send you funds - click here to claim your wallet”, Bo clicks the link to the AGivenDapp, and now has a Lit managed EOA Bo can now access the message and reply over XMTP. If Alix replies to Bo, Bo will get a new notification over email that “they have a new message waiting for them on AGivenDapp.
BONUS: $2000 Best Use of Claimable Keys with the Lit JS SDK V3
TABLELAND
Prizes
Prize #1
Build & deploy using the Studio: create an account, a project, define table(s), and deploy your app within the Tableland Studio web app. Bonus: use the Studio CLI tool to populate tables with data (import into deployed tables, write queries to explore, etc.). Be sure to share your Studio team name (top left corner of web UI) & dev address (top right corner) in the prize submission!
// Noir. use dep::std::hash::posseidon::bn254; // needed for hashing struct Entry { accounts: Vec<u8>, // List of accounts amounts: Vec<u8>, // List of amounts sum: Field, // Sum of amounts } impl Entry { // Constructor that takes accounts and amounts and calculates the sum automatically fn new(accounts: Vec<u8>, amounts: Vec<u8>) -> Self { let sum = amounts.iter().sum(); Entry { accounts, amounts, sum } } } #[test] fn assert_double_entry(debits: &Entry, credits: &Entry) -> bool { // Assert that the sum of debits equals the sum of credits assert(debits.sum = credits.sum) } fn main() { let debits = Entry::new(vec![00111, 03454], vec![100.0, 200.0]); let credits = Entry::new(vec![99910], vec![300.0]); if assert_double_entry(&debits, &credits) { println!("Double-entry bookkeeping is correct."); } else { println!("Double-entry bookkeeping is incorrect."); } }mail hello@ethglobal.com

JOURNAL OF INFORMATION SYSTEMS American Accounting Association Vol. 35, No. 3 DOI: 10.2308/ISYS-19-009 Fall 2021 pp. 17-52 Using Smart Contracts to Establish Decentralized Accounting Contracts: An Example of Revenue Recognition
The results show that smart contracts can be created to fully address complex revenue recognition scenarios according to the Generally Accepted Accounting Principles (GAAPs).
financial assets can be transmitted, and legal ownership of assets can be transferred from one party to another using smart contracts under Ethereum
allows every participant to own and share a replicated copy of the ledger as well as the programs (i.e., smart contracts) that update the ledger. Unlike the traditional system of records, where a firm uses its private programs (e.g., ERP modules) to update its private ledgers (on enterprise databases), DAC users have shared programs to update shared ledgers on the blockchain network (Hyperledger 2020). In an ideal world where all (or most) transactions would be stored on the blockchain, the degree of information asymmetry would be mitigated.
Ethereum The World State Machine
The term ”smart contract” was first introduced in 1994 by Nick Szabo and refers to self-automated computer programs that can carry out the terms and conditions of any realworld contract (Szabo 1997).
Ethereum depends on smart contracts to collect local states and stores the history of the state changes of transactions recorded on it. A function call from a smart contract often ends a stage and then transits the contract into the next stage at a certain point in time (Solidity 2020)—that is, each contract acts as a local state machine before a transaction is confirmed and stored on Ethereum. The local execution of a contract state transition resembles the business process of state transition. Once a transaction is confirmed and stored on Ethereum, it automatically becomes a part of the world state machine. To some extent, this mechanism performs functions similar to those of a bank or an exchange, both of which collect and consolidate customers’ transaction history. Different from a bank or an exchange that only consolidates transactions for one or a few financial assets, Ethereum records all transactional states on the platform
“Abstract Chain”: Notwithstanding that the amount of revenue is measured by a dollar amount, it does not carry purchase power
As suggested by Chow, Hwang, et. al. Geppetto is publishing the following kind of smart contracts:
Transclude of Captura_de_pantalla_2023-10-21_a_la(s
_9.18.06.png)ERC-20 :
Since the token of revenue is different from a token of a physical asset, it should not be declared as a tradable asset. Fortunately, developers have the option to issue a ”tradable token” or a ”non-tradable token” for the target data element according to ERC20. Since the revenue number itself is non-tradable, we selected the ”non-tradable token” approach to record the revenue number in our later implementation.


const Web3 = require('web3'); // Connect to an Ethereum node const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_API_KEY'); // The contract address and its ABI const contractAddress = '0x082827F9e555e8a6dD6DaeA3AB8778a86a6C3fab'; const contractABI = [ Contract ABI fragments (Function getRevenue): "constant": false, "inputs": [ "name": "TransactionAmount", "type": "uint256"} "name": "getRevenue", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function"; ]; // Replace with the actual contract ABI // Create an instance of the contract const contractInstance = new web3.eth.Contract(contractABI, contractAddress); // Assume the contract has a function called "myFunction" contractInstance.methods.myFunction().call() .then(result => { console.log(result); }) .catch(error => { console.error(error); });* Contract Code fragments (RevenueContract RegularSale): contract RevenueContract_RegularSale is StandardToken { string public name = "RevenueToken"; string public symbol = "R@"; uint8 public decimals = 0; string public version = "1.0"; event IssueToken(address indexed _ _to, uint _value); uint public value; // Transaction Amount address public seller; // Seller's address address public buyer; // Buyer's address enum State {Created, Locked, Inactive } // Transaction states for revenue recognition State public state; function getRevenue(uint Transaction Amount) public { balances|seller] += TransactionAmount; //Revenue token is added to Seller's account emit IssueToken(seller, TransactionAmount); /Notify the console of token issued currentSupply = TransactionAmount; // Add the increased amount to the current token supply } /1 Allows seller to recognize revenue while called function confirmReceived) public onlyBuyer // Only Buyer is permitted to call this function inState(State.Locked) emit ItemReceived); state = State.Inactive; uint price-(address(this). balance)/1000000000000000000; // Converts wei to eth seller.transfer (address(this).balance); // Contract automatically calls to transfer the money to the Seller getRevenue(price); // Contract automatically calls to let Seller recognize revenue modifier onlyBuyer) { require msg.sender = buyer, "Only buyer can call this." );Llama2 greaterThan OpenAI
Audit Trails: Tracing Transactions Back to Contracts The implementation of these use cases demonstrates the technical feasibility of the DAC model. One might argue that auditors may not know what DACs have been used by clients to generate the transactional data. As a matter of fact, every transaction generated by a contract will be referenced back to the contract
Despite the use of public key infrastructure to help mask the identities of transaction initiators, one could still argue that advanced technology, like Big Data analytics, can be deployed to connect identities to asset addresses and to generate a comprehensive picture of initiators’ selling/purchasing behaviors. That is, an encryption can be broken if one has sufficient time and computational capability (e.g., quantum computing). Given this concern, it is worthwhile for researchers to examine confidentiality issues in future endeavors.
Smart Contracts on Mainnet: The case for revenue recognition
Use Case 1. Simple, cash settled sale: 0x082827F9e555e8a6dD6DaeA3AB8778a86a6C3fab
Use Case 2. Installment sale: 0x2618Faf1f49E06Af517ABD33A354d9880008D8BD
Contract ABI fragments (Function PVACalculate):
{ “constant”: false, “inputs”: [ { “name”: “amount”, // periodic payment amount “type”: “uint128” “name”: “times”, //number of payments “type”: “uint 128” { “name”: “rate”, //interest rate “type”: “uint128” { “name”: “month”, //if monthly interest rate or not “type”: “bool” } “name”: “PVACalculate”, “outputs”: [ “name”: '''' “type”: “uint128” } “payable”: false, “stateMutability”: “nonpayable”, “type”: “function” }
Contract Code fragments (RevenueContract_Installment):
contract RevenueContract _ Installment is StandardToken { [omitting lines] function getRevenue(uint TransactionAmount) public { balances|seller] += TransactionAmount; emit Issue Token(seller, Transaction Amount); currentSupply += TransactionAmount; } //Allows seller to recognize revenue while called function confirmPurchaseReady(uint thePeriodicPayment, uint theNumberOfPayment, uint 128 theRate ) public inState(State.Ready) only Seller //for Seller to confirm the readiness for delivery // Seller confirms it’s ready to deliver emit PurchaseReadyConfirmed; PeriodicPayment = uint 128(thePeriodicPayment); //convert the periodic payment amount NumberOfPayment = uint128(theNumberOfPayment); //convert the number of payments rate = theRate; //store the interest rate pricePVA = PVACalulate(PeriodicPayment, NumberOfPayment, rate, false); //call PVACalculate to calculate the present value of annuity for the installment sale state = State.Locked; //state locked
function confirmReceived ( public onlyBuyer inState(State.Locked) emit ItemReceived); getRevenue(pricePVA); state = State.NeedtoPay; } function PVACalulate(uint 128 amount, uint128 times, uint 128 rate, bool month) private returns (uint 128){ uint 128 PVA = 0.0; uint128 calRate = rate; // calculating the present value of annuity if(month){ PVA=((( (amount * 10000) * (100 ** (times-1)))) / (100.0 + (calRate/12) ** (times) )); ¡else { PVA =((( (amount * 10000) * (100 ** (times-1)))) / ((100.0 + (calRate)) ** (times))); return PV;
Use Case 3: Gift Card Sale Contract (DAC) address examples:
- Contract RevenueContract_Installment: 0x2a91C75e308774e350E0d792F5639a812cAe859d Contract ABI fragments (Function confirmPurchaseReady):
{ “constant”: false, “inputs”: [ { “name”: “Card _price”, “type”: “uint256” } “name”: “confirmPurchaseReady”, “outputs”: [], “payable”: false, “stateMutability”: “nonpayable”, “type”: “function”
Contract Code fragments (RevenueContract_GiftCardSales):
contract RevenueContract _GiftCardSales is StandardToken { [omitting lines] function getRevenue(uint Transaction Amount) public { balances[seller] += TransactionAmount; emit IssueToken(seller, TransactionAmount); currentSupply += TransactionAmount; //Allows seller to recognize revenue while called function confirmPurchase() public inState2(State2.Created) condition(msg.value = (GiftCardValue)) payable emit PurchaseConfirmed; buyer = msg.sender; state = State2.Ready; //Buyer confirms the purchase and says ready for the transaction } function confirmPurchaseReady(uint Card price) public inState2(State2.Ready) onlySeller emit PurchaseReadyConfirmed); GiftCardPrice = Card_price; //Seller sends and stores the card price into the contract GiftCardRevenue = uint128(Card_price); //Initiate the total deferred revenue state = State2.Locked; //Lock the contract and await buyer’s future redemption
function confirmReceived _GiftCard) public onlyBuyer inState2(State2.Locked) emit ItemReceived); seller.transfer(address(this).balance); //Buyer prepays the money for the gift card GiftCardremains = uint128(GiftCardPrice); //Store the initial card balance state = State2. Redeemable; //Set the state as redeemable function confirmReceived _UponRedemption(uint128 Redemption) public onlyBuyer inState2(State2.Redeemable) condition(GiftCardremains >= (Redemption)) emit ItemReceived; GiftCardremains - = Redemption; //Subtract the redemption amount from the card balance getRevenue(Redemption); //Seller is entitled to recognize the redemption amount as revenue if(GiftCardremains==0){ state = State2.Inactive; //Set the state as inactive if balance becomes zero
Use Case 4: Multiple Performance Obligations Contract (DAC) address examples:
- Contract RevenueContract_Installment: 0x082827F9e555e8a6dD6DaeA3AB8778a86a6C3fab Contract ABI fragments (Function confirmReceived_WholeContract):
“constant”: false, “inputs”: [], “name”: “confirmReceived WholeContract”, “outputs”: [], “payable”: false, “stateMutability”: “nonpayable”, “type”: “function”
Contract Code fragments (RevenueContract_ MultiplePerformanceObligations):
pragma solidity ^0.4.22; import “github.com/provable-things/ethereum-api/provableAPI_0.4.25.sol”; //Import Provable’s API to use its Oracle contract [omitting lines] contract RevenueContract _MultiplePerformanceObligations is RevenueContract_GiftCardSales, RevenueContract RegularSale { I/Use Case 4 is the combination of Use Case 1 and Use Case 3. Therefore, it inherits all properties from the prior two contracts. [omitting lines] function getRevenue (uint Transaction Amount) public { balances[seller] += TransactionAmount; emit Issue Token(seller, TransactionAmount); currentSupply += TransactionAmount; } //Allows seller to recognize revenue while called function updateStandAlonePrice0 inState3(State3.updatePrice) payable { if (this. balance > provable getPrice(“URL”)) { provable_query(“URL”, “json(http://140.119.19.116/price).merchandise”); //Get the stand- alone price for merchandise through Provable query Merchandise Price = queryResult; //Store the stand-alone price for merchandise to M price provable query(“URL”, “json(http://140.119.19.116/price). giftcard”); //Get the stand- alone price for gift card through Provable query GiftCardPrice = query Result; //Store the stand-alone price for merchandise to Card price state = State3.Ready; //Ready to transact function Ethereum callback(bytes32 myid, string result) { query Result = result; ^ //Implement Provable’s API to store external data items into
function confirmPurchaseReady() public inState3(State3.update Price) onlySeller emit PurchaseReady Confirmed; updateStandAlonePrice0; uint total Value = Merchandise Price + GiftCardPrice; //Sum the two stand-alone prices MerchandiseRevenue = uint128((Merchandise Price / totalValue) * value) //Allocate the contract price to the first performance obligation GiftCardRevenue = uint128((GiftCardPrice / totalValue) * value) //Allocate the contract price to the second performance obligation state = State3.Locked; // Lock the contract and await buyer’s future redemption } function confirmReceived WholeContract) public onlyBuyer inState3(State3.Locked) { emit ItemReceived; seller.transfer(value); getRevenue(MerchandiseRevenue); //Recognize revenue for the Merchandise GiftCardremains = uint128(GiftCardPrice); // Store the initial card balance state = State3.Redeemable; // Set the state as redeemable for gift card function confirmReceived UponRedemption(uint128 Redemption) public onlyBuyer inState2(State2.Redeemable) condition(GiftCardremains >= (Redemption)) { emit ItemReceived; GiftCardremains -= Redemption; //Subtract the redemption amount from the card balance getRevenue (Redemption); //Seller is entitled to recognize the redemption amount as revenue if(GiftCardremains==0){ state = State2.Inactive; //Set the state as inactive if balance becomes zero
https://dart.deloitte.com/USDART/home/codification/revenue/asc606
STATE 0: GENESIS
-
Inventory (Bicycles) [0x1] = 0
-
Cash [0x2] = 6000
-
Revenue [0x3] = 0
-
COGS [0x4] = 0
-
Profit [0x5] = 0
Transaction 1: 2 bicycles are purchased for $6,000, paid in cash
Affected accounts:
-
Inventory (Bicycles) [0x1]
-
Cash [0x2]
On-chain Transactions
Cash is transferred to Inventory [0x2] sends 6000 TOKEN to [0x1]
STATE 1:
-
Inventory (Bicycles) [0x1] = 6000
-
Cash [0x2] = 0000
-
Revenue [0x3] = 0
-
COGS [0x4] = 0
-
Profit [0x5] = 0 ***S
Transaction 2: 1 bicycle is sold for $9,000
Affected accounts:
-
Inventory (Bicycles) [0x1]
-
Cash [0x2]
-
Revenue [0x3]
-
COGS [0x4]
-
Profit [0x5] ***
On-chain Transactions
0x1 TRANSFERS 3000 TO 0x4
MINT 9000 TO 2
MINT 9000 TO 3
:=
[0x3] MUST HAVE 9000 TOKENS
[0x4] MUST HAVE 3000 TOKENS
[0x2] MUST HAVE 9000 TOKENS
[0x1] MUST HAVE 3000 TOKENS
[0x5] MUST HAVE 3000 TOKENS
STATE 2:
-
Inventory (Bicycles) [0x1] = 3000
-
Cash [0x2] = 9000
-
Revenue [0x3] = 9000
-
COGS [0x4] = 3000
-
Profit [0x5] = [0x3 - 0x4] = 3000
[0x1] sends 6000 TOKEN to [0x3]
Related: ETH Global NYC, Financial Contracts