Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Smart contract wallets using predicates and NFTs (state minimized approach) #527

Open
SilentCicero opened this issue Oct 23, 2023 · 0 comments
Labels
documentation Improvements or additions to documentation

Comments

@SilentCicero
Copy link
Member

SilentCicero commented Oct 23, 2023

Abstract

Many developers would like to use native level predicates as a smart contract wallet. This usually presents a problem that predicates are stateless and thus have no way to manage state.

Solution

Use a single native level NFT to represent state of the predicate wallet.

Pros

  • State minimization: a single smart contract wallet would only be using a single NFT UTXO as their entire state representation which is vastly less than its smart contract counterparts.

Cons

  • Account setup: would require an NFT to be minted to act as the state, which is some stateful setup
  • More bandwidth: the state would need to be presented over bandwidth each time you spend

Pre-Construction:

  • Unique NFT is minted with sub asset ID X
  • Build the hash for predicate wallet W which looks for sub asset ID X as state
  • Build the hash for state storing predicate Y which looks for W as the owner to spend to be present in the transaction and contains state hash S, ideally Y has the logic to unwrap W and ensure only W met spending conditions are fulfilled in the transaction
  • NFT X is sent to state storing predicate Y

Transaction Construction

  • Predicate wallet W looks for sub asset ID X in the current transaction T
  • W unwraps the code at found predicate Y for asset X and reveals the state hash S
  • W looks for the preimage of S in the transaction T found in witness W
  • When updating state, W creates a new state predicate Y2 containing the new state hash for S2 with enforcement still remaining on W
  • W sends state NFT X to the new state predicate at Y2

Witnesses:

  • Pre-image state for S
  • Signatures for owner W

Inputs:

  • Asset A with owner W
  • NFT X with owner Y

Outputs:

  • Asset A sent to desired owner
  • NFT X with new owner Y2

TLDR: we are using the NFT identifier as a constant identifier for state and the owner as the recorded state root. State and pre-images have to be re-exposed every time you spend over bandwidth, but bandwidth could be reduced further by using LDC, and likely one other read-only contract input.

State Hash Predicate

predicate;

use std::inputs::input_owner;

fn main(input_id:u8) {
    const owner_hash = Address::from(0xe895f77829b48401388b1491e651ad2136345162a8544c452c54689183c9fb71);
    const state_hash = 0x923413b0bbcf6644c132c3c316f63fb58a4260c2d9f63481653d189d5ee9c955;
    
    let input_owner = input_owner(input_id);
    assert(owner_hash == input_owner.unwrap()); // Ensure the input is a coin input.
}

Owner Predicate

predicate;

use std::inputs::{ input_asset_id, input_message_sender };

fn parse_state_hash(input_index:u8) {} // will parse from the code in state predicate

fn main(state_input_index:u8, state_preimage:b256) {
    const state_subasset_identifier = 0xec82761b42f51fd3e99a74d75ef7a787688565f0ca02bcf3dfa256465de691f8;
    const state_predicate = input_message_sender(state_input_index);
    const state_hash = parse_state_hash(state_input_index);
    
    assert(input_asset_id(state_input_index).unwrap() == state_subasset_identifier);
}

Naming:

  • "Stateful predicates"
  • "Smart predicates"
@SilentCicero SilentCicero added the documentation Improvements or additions to documentation label Oct 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

1 participant