## Predicates are the new Contracts <br /> ![image](https://hackmd.io/_uploads/rJxODUXsQ0.png =x100) <br /> David Mihal (@dmihal) Senior Architect https://hackmd.io/@dmihal/predicates-v3 --- ## Blockchains are getting heavy --- <style > img { max-height: 90vh !important; } </style> ![image](https://hackmd.io/_uploads/rkkxCMcXA.png) --- ### What happens when a blockchain gets heavy? --- ![image.png](https://hackmd.io/_uploads/ryYchPGma.png) --- ![blockchain-cycle.excalidraw](https://hackmd.io/_uploads/BJM18E570.png) --- ![image](https://hackmd.io/_uploads/rkkxCMcXA.png) --- ### How do we break the cycle? --- ### How do we break the cycle? ### Make a chain that doesn't grow as quickly --- ### We need to change the way we build applications --- # Let's rewind a bit --- ## Bitcoin has: * Coins * Accounts <br /> <br /> ```graphviz digraph UTXO { node [shape=box, style="rounded,filled", fillcolor="#E8F6FF", fontname="Arial"]; edge [style=invis]; subgraph cluster_UTXO { label = "UTXO"; labeljust = "l"; fontname = "Arial"; color = "#A9D0F5"; style = "rounded,filled"; fillcolor = "#D6EAF8"; UTXO [label="0.1 BTC\nOwner: 12higD...Wv"]; } subgraph cluster_UTXO1 { label = "UTXO"; labeljust = "l"; fontname = "Arial"; color = "#A9D0F5"; style = "rounded,filled"; fillcolor = "#D6EAF8"; UTXO2 [label="0.2 BTC\nOwner: 12higD...Wv"]; } subgraph cluster_UTXO2 { label = "UTXO"; labeljust = "l"; fontname = "Arial"; color = "#A9D0F5"; style = "rounded,filled"; fillcolor = "#D6EAF8"; UTXO3 [label="0.15 BTC\nOwner: b1cDh...4a"]; } } ``` --- ## Bitcoin account types <style> .container-x { display: flex; } .col{ flex: 1; text-align: center; } </style> <div class="container-x"> <div class="col"> ### Public keys _Pay to public-key hash (P2PKH)_ <br /> Spend coins by signing the transaction with the associated private key. </div> <div class="col"> ### Scripts _Pay to script hash (P2SH)_ <br /> Spend the coins by providing a script that: - Bytecode hashes to the address - Executes successfully </div> </div> --- ### "Create" a script ![p2sh.excalidraw](https://hackmd.io/_uploads/SJWuUcqXA.png =x450) _Notice we never sent the code?_ --- ## "Run" a script Provide a transaction with: - Input coins - Matching script bytecode - Any script inputs (signatures, etc) The script is _still_ never stored in the chain state. --- ## What goes into "state"? <div class="container-x"> <div class="col"> ### Bitcoin * UTXOs<br />(amount & owner) </div> <div class="col"> ### Ethereum * Accounts<br />(ETH balance & nonce) * Contract bytecode * Contract storage </div> </div> --- Can we combine the lightweight simplicity of Bitcoin with the power & expressivity of Ethereum? --- ![image](https://hackmd.io/_uploads/SJK395qXC.png) --- Simplicity of Bitcoin's stateless P2SH \+ Expressivity of Ethereum's EVM = Predicates! --- Predicate is just an _address_ It's not created or deployed It's only useful if it owns assets Code is only revealed when trying to _take_ (spend) tokens from a predicate --- ## Let's look at some example predicates --- ## Free giveaway ```rust predicate; fn main() -> bool { true } ``` --- ## Password-protected token ```rust predicate; use std::hash::sha256; fn main(password: str[16]) -> bool // sha256("Hello World ") let expected_hash = 0x0a692e936c61cc37c9dc4517e88aa3604780b273fed61b7690d41efaa51fa03d; sha256(password) == expected_hash } ``` --- ## Native account abstraction New wallet signatures ```rust predicate; configurable { PREDICATE_ADDR: b256 = ZERO_B256, } fn main(signature: B512) -> bool { let evm_address: EvmAddress = EvmAddress::from(PREDICATE_ADDR); let res = ec_recover_evm_address(signature, personal_sign_hash(tx_id())); if res.is_ok() { if evm_address == EvmAddress::from(res.unwrap().value) { return true; } } false } ``` --- ### We've built predicate-based accounts... ### Can we build predicate-based apps? --- ## Predicate-based limit order? ``` fn main() { // I'll give you any of my ETH IF: // - You send 3800 USDC to David for each ETH you take // - Or your name is David Mihal } ``` --- ![predicate-limit-order.excalidraw](https://hackmd.io/_uploads/r1PxPMjmC.png) --- ### Predicates can pay gas --- ## Gas-sponsoring predicate ``` fn main() { // I'll let you spend my ETH on gas if: // - You hold a Pudgy Penguin NFT // - AND your transaction is playing PudgyWorld } ``` --- ### Let's dig into what a predicate is --- ## Predicates are _stateless_ Can't access data stored on chain * Can't read data from smart contracts * Can't check the current date/time * Can't read the block hash/number _if a predicate evaluates to `true` then it will always evaluate to `true` in the future_ --- ## What can a predicate access? Anything included in the transaction! * Predicate input parameters * Input coins * Output coins * The transaction script --- ### Predicates are executed _before_ any smart contracts Fuel transaction lifecycle: 1. Check inputs exist 2. Check input/output amounts add up 3. Check normal signatures 4. **Execute predicates** 5. Execute script (smart-contract calls) --- ## Are predicates intents? ![image](https://hackmd.io/_uploads/Hy6P-fsQ0.png) --- | | Rigid | Flexible | | ----------- | -------------- | --------- | | **Account** | Public Key/EoA | Predicate | | **Action** | Transaction | Intent | --- ### But... you can use predicates to _build_ intent-powered accounts --- ### What else can we do with predicates? ![image](https://hackmd.io/_uploads/HyRr2fiXR.png) --- ## Predicates are key for<br />"State-Rehydration" _**State-Rehydration**:<br />The technique of storing minimal state-commitments on-chain, and including the full state inside transactions._ --- ### Predicates _already_ "rehydrate" code ![state-rehydration-code.excalidraw](https://hackmd.io/_uploads/HymTgQsXA.png) --- ### Full state-rehydration ![state-rehydration-dynamic.excalidraw](https://hackmd.io/_uploads/By5fWQjQR.png) --- ### Full state-rehydration with predicates & UTXOs * State commitments inside UTXO asset IDs * State commitments inside predicate configurable values --- ## Uniswap V2 Predicate ```rust configurables { ASSET_A: AssetId = AssetId::zero(), ASSET_B: AssetId = AssetId::zero(), RESERVE_A: u64 = 0, RESERVE_B: u64 = 0, TOTAL_LIQUIDITY: u64 = 0, } fn main() {...} ``` --- ![predicate-univ2.excalidraw](https://hackmd.io/_uploads/H16_FEjXR.png) --- ![predicate-univ2-transition.excalidraw](https://hackmd.io/_uploads/Bk5EKVs70.png) --- ![roulette](https://hackmd.io/_uploads/ryYJG7sX0.jpg) --- ## What have we achieved by this? An architecture for decentralized apps that are _sustainably_ fast and cheap. An architecture for blockchains that can _stay decentralized_. --- ### That's our mission at Fuel ![image](https://hackmd.io/_uploads/rJxODUXsQ0.png)
{"contributors":"[{\"id\":\"614d3dfc-f939-4def-b3a0-c5f195aff96c\",\"add\":7483,\"del\":2443}]","breaks":true,"description":"View the slide with \"Slide Mode\".","title":"Predicates are the new Contracts"}
    244 views