Build fast, reward everyone, and scale without friction.

Overview

Scrypto

CI

Language for building DeFi apps on Radix.

Terminology

  • Package: A collection of blueprints, compiled and published as a single unit.
  • Blueprint: A template that describes the common behavior and structure of its instances.
  • Component An instance of a blueprint, which lives in ledger state.
  • Function: A set of statements to perform a specific task.
  • Method: A function associated with a component.
  • ResourceDef: The definition of a resource, including metadata, supply and mint auth.
  • Bucket: A transient resource container.
  • Vault: A persistent resource container in ledger state.

Resource Flow

Installation

  1. Install Rust
  2. Enable cargo in the current shell:
    • Windows:
      • Start a new PowerShell
    • Linux and macOS:
      source $HOME/.cargo/env
      
  3. Add WebAssembly target
    rustup target add wasm32-unknown-unknown
    
  4. Install simulator
    git clone [email protected]:radixdlt/radixdlt-scrypto.git
    cd radixdlt-scrypto
    cargo install --path ./simulator
    
  5. (Optional) Open Scrypto documentation for later use
    ./doc.sh
    

Note: For preview release, do not delete or move the repository after installation. It will be used when resolving dependencies of Scrypto packages.

Getting Started

If you want a quick walkthrough of how to deploy and run some code, please see the First Steps tutorial. If you prefer to soldier through on your own, keep reading below.

Writing Scrypto Code

  1. Start by creating a new package:
scrypto new-package 
   
    
cd 
    

    
   
  1. Check out the files under your current directory:
  • Source code is within src/lib.rs;
  • Test code is within tests/lib.rs.
  1. Build your package:
scrypto build
  1. Run tests:
scrypto test

Playing with Radix Engine

Action Command
To create an account resim new-account
To change the default account resim set-default-account
To create a token with fixed supply resim new-token-fixed
To create a token with mutable supply resim new-token-mutable
To create a badge with fixed supply resim new-badge-fixed
To create a badge with mutable supply resim new-badge-mutable
To mint resource resim mint
To transfer resource resim transfer
To publish a package resim publish
To call a function resim call-function
To call a method resim call-method
To export the ABI of a blueprint resim export-abi
To show info about an address resim show

Note: The commands use the default account as transaction sender.

Project Layout

  • sbor: The binary data format used by Scrypto.
  • sbor-derive: Derives for encoding and decoding Rust struct and enum.
  • scrypto: Scrypto standard library.
  • scrypto-abi: Scrypto blueprint ABI.
  • scrypto-derive: Derives for defining and importing Scrypto blueprints.
  • radix-engine: The Scrypto execution engine.
  • simulator: A simulator that run Scrypto code on a filesystem based ledger.
  • examples: Scrypto examples.
Comments
  • Make burn and mint methods accept references of the BucketRef ?

    Make burn and mint methods accept references of the BucketRef ?

    I see that it is not possible to burn two different tokens with the same badge in a authorize block. Maybe making mint and burn methods accept a reference to a BucketRef would solve the issue ?

    pub fn change_supply(&mut self, badge_to_burn: Bucket) {
        self.minter_badge.authorize(|badge| {
            badge_to_burn.burn(badge);
            // todo: error here: use of moved resource: badge
            self.token_vault.take(100).burn(badge);
        });
    }
    
    question 
    opened by cbisaillon 14
  • Feature: Validated Proofs

    Feature: Validated Proofs

    This PR adds ValidatedProofs as a language level concept to Scrypto. With this PR, a Proof would have two main methods:

    • validate_proof: Takes in a ResourceAddress and validates that the proof has a matching resource address.
    • unsafe_skip_proof_validation: Takes no arguments and simply skips the validation of the resource address.

    All of the methods that were previously available on Proofs are now available on ValidatedProofs.

    opened by 0xOmarA 9
  • Feature: Limited caller AuthZone access and AuthZone stack

    Feature: Limited caller AuthZone access and AuthZone stack

    This is an implementation of the ideas I put forward in #285.

    The high level summary: Caller's can optionally use an AuthZone which will be visible to Callee's. The callee's can optionally indicate the caller proofs they want access to by simply using the AccessRules as they already do. When both sides agree, authorization and follow-on business logic (ie. based on a Proof of NonFungableData) works seamlessly. The caller can specify their "pass by intent" by using an AuthZone to group their Proofs instead of seperate args. This is kind of like varargs for Proofs.

    There are 2 complementary features that work together.

    1. AuthZones now live in a stack so actors can push the current one back putting a new empty AuthZone in it's place, or undo that. (instructions StartAuthZone, EndAuthZone and API ComponentAuthZone::start() and ComponentAuthZone::end())
    2. Components can access the caller's AuthZone proofs with the same AuthZone API (not push/pop) using CallerAuthZone::create_proof* as they would have used ComponentAuthZone

    These features are joined up forming a nice usable enhancement but with safety restrictions:

    1. The CallerAuthZone is at most a "shadow" of only the top AuthZone in the stack, so it's fully controlled by the caller.
    2. Which proofs are allowed in to the shadow must be explicitly defined by the callee. This is done by using the same AccessRules they already use to protect method calls. When those HardAuthRules are checked, the shadow AuthZone is built up based on the matches which were already being visited. The only overhead is cloning the Proofs. So nothing happens on "allow_all", only explicit rule matches.
    3. And finally, if the caller is only using the default AuthZone, ie they've never done a single StartAuthZone instruction or AuthZone::start() to push a new AuthZone on the stack, then the shadow calculation does not happen at all, leaving the CallerAuthZone empty. So everything is completely opt-in by the caller and protects their tx signing virtual badges. Even the performance hit for the clones only happens when needed.

    Would love feedback on the idea now that you can see it more concretely @russellharvey . I think the implementation is pretty straight forward, though there are a few places I still had questions. Also I'm not sure I love the vocabulary I used everywhere, start/end, caller, shadow, etc. A second opinion on if that all makes sense would be nice. Maybe @iamyulong or @talekhinezh can take a look at this PR when they have time (I realize there are other priorities). (See the "FIXMEs for some specific questions"). I also think adding try_create_proofs* APIs to return Option instead of panic would be really helpful to enable more use cases. I'd be willing to add those.

    I don't expect this to be merged as is, but it is feature complete with tests and in decent shape. This is mostly meant to move that discussion forward and was a good way for me to dig into some of the Scrypto internals. If it's never accepted that's fine but I think there's room to iterate on this idea for sure at leaset. It was a good learning experience for me either way. I realize some of the SNode and wasm stuff is changing, and at minimum this PR should probably be rebased and fixed up for the develop branch so it certainly needs a little care before it's ready too.

    My use case for wanting this is honestly not fully flushed out. But the friction for me came when I was trying to build up a more complex authorization model and interacting with multiple components. In this case I wanted some components to return badges to the caller and then have the caller use them against other components without having to specify them (because they might not know the resource address or ids if another component is in charge of authentication/authorization for a group of components). And of course they would be NFT badges. So this type of thing isn't possible without this PR because NFT badges have to be passed by intent right now so the callee can access the data.

    opened by devmannic 9
  • powi(i32) function for Decimal implemented

    powi(i32) function for Decimal implemented

    Decimal::powi(&self, exp:i32) -> Decimal function is now implemented with approximation. This solution will also work once we make Decimal::SCALE mutable.

    opened by r001 8
  • Unable to change the library name to anything other than `out`

    Unable to change the library name to anything other than `out`

    It seems we don't have the flexibility to change the lib name inside the Cargo.toml file. Changing it to anything other than out causes issues with testing and compiling. Also when docs are generated, they are labelled as out too.

    Would it be possible to update the following code to allow the lib name to default to maybe CARGO_BIN_NAME to we can at least define a name we would like.

    I believe this is the location of the file that needs to be updated: https://github.com/radixdlt/radixdlt-scrypto/blob/ce6b70929bf487a2cc6779133ddbbc1981893624/scrypto/src/lib.rs

    I think we can do something like the following:

    #[macro_export]
    macro_rules! include_code {
        () => {
            include_bytes!(concat!(
                env!("CARGO_MANIFEST_DIR"),
                format!("/target/wasm32-unknown-unknown/release/{}.wasm", env!("CARGO_BIN_NAME") )
            ))
        };
        ($package_dir: expr) => {
            include_bytes!(concat!(
                $package_dir,
                format!("/target/wasm32-unknown-unknown/release/{}.wasm", env!("CARGO_BIN_NAME"))
            ))
        };
    }
    
    enhancement 
    opened by plymth 8
  • Fix/powi overflow and tighter integers

    Fix/powi overflow and tighter integers

    This PR solves overflow errors in the powi function. The following code would overflow at every line involving powi:

        #[test]
        fn test_powi_max_decimal() {
            let _max_bug = Decimal::MAX.powi(1);
            let _max_sqrt = Decimal::MAX.sqrt().unwrap();
            let _max_cbrt = Decimal::MAX.cbrt();
            let _max_dec_2 = _max_sqrt.powi(2);
            let _max_dec_3 = _max_cbrt.powi(3);
        }
        ```
        
        The PR also changes integer used in root function of `Decimal` and `PreciseDecimal` to tighter integers (I384 and I768 as suggested by @r001)
    opened by arthurvinci 7
  • Re-presenting badges

    Re-presenting badges

    (from discussion on Discord)

    Badges give access rights to the called method, and it would be able to do anything with it (presenting it) on the behalf of the caller... It can be useful, but also it is a lot of trust.


    Maybe it could be made explicit whether a token can be re-presented by a component to other components.

    I can think of scenarios where that such behavior would be really useful. A travel booking component might require me to present my KYC/identity badge but would then also present it to the airline, hotel and rental car booking components, which have a legitimate interest in knowing my identity.

    On the other hand I would not want a misbehaving "travel booking" component taking out a loan somewhere using my identity.


    Proposal:

    The 1st component could specify to which other components it will re-present the badge so the user can check that before signing the transaction

    It could be something similar to the #[auth(badge_ref)] decoration on a method.

    #[auth(badge_ref)]
    #[present_to(a1b2...7890 and c3d4...0987)]
    pub fn do_something() {
        ...
    }
    

    Or using the same auth decorator:

    #[auth(badge_ref -> a1b2...7890 and c3d4...0987)]
    pub fn do_something() {
        ...
    }
    

    (the component addresses are abbreviated above, they should be the complete address)

    Then:

    Option 1: the transaction could include to which other components the badge is allowed to be presented

    Option 2: the Radix Engine logic could control that by itself: once a function with that "decoration" is called, the marked badges for that function can only pre presented to the defined components.

    enhancement 
    opened by kroggen 6
  • Idea: add a way to truncate Decimal

    Idea: add a way to truncate Decimal

    I am trying to remove the floating part of a Decimal but can't find an easy way to do it (other than transforming to String and removing the floating part from there).

    enhancement 
    opened by cbisaillon 6
  • Allow to specify XRD instead of 030000..004 address in resim

    Allow to specify XRD instead of 030000..004 address in resim

    This might not be the best way to do it but I think it is useful to only have to specify "XRD" when sending buckets to functions and methods instead of the full address.

    opened by cbisaillon 6
  • feature: SBOR payloads start with a prefix byte

    feature: SBOR payloads start with a prefix byte

    You need to know if you're encoding a payload or a payload-part. Typically this is obvious, the main caveat is where we pull together multiple sub-parts into a larger struct - notably Transaction Manifest args and Non Fungible Data.

    In these cases, they're encoded as a complete struct, without a separate prefix byte for each argument/field - this felt like the only real correct approach.

    I also had to do some hand-cranked WASM which was fun :).

    The tests aren't running on this PR :( - but I've run them locally and they pass.

    Breaking changes

    • SBOR - Basic payloads start with 0x5b (think [5b]or) and scrypto payloads start with 0x5c (think [5c]rypto).
    opened by dhedey 5
  • NFT update data Critical Bug, cannot withdraw

    NFT update data Critical Bug, cannot withdraw

    Here is an example I have tested withdrawing an NFT when it wasn't updated and when it was changed:

    Transaction manifest:

    CALL_METHOD ComponentAddress("account_sim1qduh9kkxlasynyywer0hl5zdculasfwz9z67qtx6592q9tadqx") "lock_fee" Decimal("100");
    CALL_METHOD ComponentAddress("account_sim1qduh9kkxlasynyywer0hl5zdculasfwz9z67qtx6592q9tadqx") "withdraw" ResourceAddress("resource_sim1qqv26c2pgd0v36qg6rp9uunj8rat09s0aa3kqdalahtsysyhh4");
    TAKE_FROM_WORKTOP ResourceAddress("resource_sim1qqv26c2pgd0v36qg6rp9uunj8rat09s0aa3kqdalahtsysyhh4") Bucket("token");
    CALL_METHOD_WITH_ALL_RESOURCES ComponentAddress("account_sim1qduh9kkxlasynyywer0hl5zdculasfwz9z67qtx6592q9tadqx") "deposit_batch";
    

    Non-updated:

    $ resim run withdraw.rtm
    Transaction Status: COMMITTED SUCCESS
    Transaction Fee: 0.93161 XRD burned, 0.0465805 XRD tipped to validators
    Cost Units: 4294967295 limit, 931610 consumed, 0.000001 XRD per cost unit
    Logs: 0
    Instructions:
    ├─ CallMethod { component_address: account_sim1qw9j97utxsjnxcs2lus4kqm8lu84z5ygpzd2gkn5dljs6ncf0k, method_name: "lock_fee", call_data: Struct(Decimal("100")) }
    ├─ CallMethod { component_address: account_sim1qw9j97utxsjnxcs2lus4kqm8lu84z5ygpzd2gkn5dljs6ncf0k, method_name: "withdraw", call_data: Struct(ResourceAddress("resource_sim1qzhwqhlvelrdjqnd0xp0hd8tfdjqsxkqshzvkylkrmhqydgdur")) }
    ├─ TakeFromWorktop { resource_address: resource_sim1qzhwqhlvelrdjqnd0xp0hd8tfdjqsxkqshzvkylkrmhqydgdur }
    └─ CallMethodWithAllResources { component_address: account_sim1qw9j97utxsjnxcs2lus4kqm8lu84z5ygpzd2gkn5dljs6ncf0k, method: "deposit_batch" }
    Instruction Outputs:
    ├─ ()
    ├─ Bucket(1024u32)
    ├─ Bucket(512u32)
    └─ ()
    New Entities: 0
    

    Updated:

    $ resim run withdraw.rtm
    Transaction Status: COMMITTED FAILURE: ApplicationError(VaultError(ResourceContainerError(InsufficientBalance)))
    Transaction Fee: 0.580059 XRD burned, 0.02900295 XRD tipped to validators
    Cost Units: 4294967295 limit, 580059 consumed, 0.000001 XRD per cost unit
    Logs: 0
    Instructions:
    ├─ CallMethod { component_address: account_sim1qduh9kkxlasynyywer0hl5zdculasfwz9z67qtx6592q9tadqx, method_name: "lock_fee", call_data: Struct(Decimal("100")) }
    ├─ CallMethod { component_address: account_sim1qduh9kkxlasynyywer0hl5zdculasfwz9z67qtx6592q9tadqx, method_name: "withdraw", call_data: Struct(ResourceAddress("resource_sim1qqv26c2pgd0v36qg6rp9uunj8rat09s0aa3kqdalahtsysyhh4")) }
    ├─ TakeFromWorktop { resource_address: resource_sim1qqv26c2pgd0v36qg6rp9uunj8rat09s0aa3kqdalahtsysyhh4 }
    └─ CallMethodWithAllResources { component_address: account_sim1qduh9kkxlasynyywer0hl5zdculasfwz9z67qtx6592q9tadqx, method: "deposit_batch" }
    New Entities: 0
    

    Account state:

    $ resim show account_sim1qduh9kkxlasynyywer0hl5zdculasfwz9z67qtx6592q9tadqx
    Component: account_sim1qduh9kkxlasynyywer0hl5zdculasfwz9z67qtx6592q9tadqx
    Blueprint: { package_address: package_sim1qyqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpsuluv44, blueprint_name: "Account" }
    Authorization
    ├─ "balance" => AllowAll
    ├─ "deposit_batch" => AllowAll
    └─ "deposit" => AllowAll
    State: Struct(KeyValueStore("0444f6d698277561d2a2c7b1e1be4a06066f729cb00154461400eadb8d5ab71802040000"))
    Key Value Store: account_sim1qduh9kkxlasynyywer0hl5zdculasfwz9z67qtx6592q9tadqx(0444f6d698277561d2a2c7b1e1be4a06066f729cb00154461400eadb8d5ab718, 1026)
    ├─ ResourceAddress("resource_sim1qr0700ctxkvf8a0t3k953klq8ehlrmek8g5036v9kmvswyynme") => Vault("f8da93c15b094676798b223c77bbf1c1a424b3853410475d4eb4cab5072a334d09040000")
    ├─ ResourceAddress("resource_sim1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzqu57yag") => Vault("0444f6d698277561d2a2c7b1e1be4a06066f729cb00154461400eadb8d5ab71804040000")
    └─ ResourceAddress("resource_sim1qqv26c2pgd0v36qg6rp9uunj8rat09s0aa3kqdalahtsysyhh4") => Vault("9214a0eb3ec0d2d05ae9f8c29131ad578f0efa125a849e054929e5f9c460cf660a040000")
    Resources:
    ├─ { amount: 0, resource address: resource_sim1qr0700ctxkvf8a0t3k953klq8ehlrmek8g5036v9kmvswyynme, name: "token" }
    ├─ { amount: 999994.7954986, resource address: resource_sim1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzqu57yag, name: "Radix", symbol: "XRD" }
    └─ { amount: 1, resource address: resource_sim1qqv26c2pgd0v36qg6rp9uunj8rat09s0aa3kqdalahtsysyhh4, name: "User Badge" }
       └─ NonFungible { id: NonFungibleId("3007100000007f5f63054c736247c827a93d5ca204d7"), immutable_data: Struct(), mutable_data: Struct(6535u64, Decimal("943465")) }
    

    There's a clear bug when trying to withdraw an NFT after it's data have been updated.

    opened by unghuuduc 5
  • Refactor/alias non fungible address

    Refactor/alias non fungible address

    Removed NonFungibleAddress from the value model, with developer facing inteface untouched:

    • In Manifest, NonFungibleAddress("address", 1u32) is still supported;
    • Scrypto Lib abstraction NonFungibleAddress stays;
    • Scrypto schema type NonFungibleAddress stays;
    • Non-fungible address based auth continues to work.

    Removed ManifestBucket/ManifestProof/ManifestExpression from Scrypto schema.

    opened by iamyulong 0
  • Feature: Virtual package badge

    Feature: Virtual package badge

    • Add concept of "native packages" such that every invocation (scrypto+native) has a package identifier associated with it, imilar to the Rust "crate" concept.
    • Add virtual "package token" which is included as a virtual proof in the AuthZone, one may now only allow certain functions/methods to be called only if in the same package, similar to Rust 'pub(crate)' visibility flags.
    opened by talekhinezh 0
  • Feature/bucket proof expression

    Feature/bucket proof expression

    • Separated ManifestBucket and ManifestProof from Scrypto bucket/proof ("own")
    • Changed ManifestExpression to an enum
    • Split IDAllocator into ManifestIdAllocator and (Runtime)IdAllocator
    • Overhauled Scrypto custom type codec (variant length)
    opened by iamyulong 0
Releases(v0.7.0)
Owner
Radix DLT
Radix DLT
Hi I'm Sophy, a discord bot in devlopment, soon I'll be available to help everyone (❁´◡`❁)

Sophy Bot Hi I'm Sophy, a discord bot in devlopment, soon I'll be available to help everyone (❁´◡`❁) Contribution Do you like me and want to help me?

Far Dragi 0 May 30, 2022
Tells you how many years you need to wait until your subatomic xeon crystal synchronizer has doubled in plasma inversion efficiency on the Goldberg-Moleman scale or whatever.

about Tells you how many years you need to wait until your subatomic xeon crystal synchronizer has doubled in plasma inversion efficiency on the Goldb

null 2 Dec 3, 2021
🚀 Fleet is the blazing fast build tool for Rust

Fleet is the blazing fast build tool for Rust. Compiling with Fleet is up-to 5x faster than with cargo.

Dimension 2.2k Jan 6, 2023
dm-jitaux is a Rust-based JIT compiler using modified auxtools, dmasm and Inkwell LLVM wrapper for boosting Byond DM performance without any hassle!

dm-jitaux is a Rust-based JIT compiler using modified auxtools, dmasm and Inkwell LLVM wrapper for boosting Byond DM performance without any hassle (such as rewriting/refactroing your DM code).

SS220 20 Dec 13, 2022
proc macros for generating mut and non-mut methods without duplicating code

mwt Hey! You! Read this before using! mwt was thrown together pretty quickly for personal use, because I couldn't find an existing crate that does thi

null 1 Dec 24, 2021
HTTP microservice using Axum and Reqwest to request the Google Translate TTS endpoint without rate limits

HTTP microservice using Axum and Reqwest to request the Google Translate TTS endpoint without rate limits

Gnome! 5 Oct 5, 2022
Jonathan Kelley 33 Dec 6, 2022
Allow raw pointer access without those pesky unsafe blocks everywhere!

Allow raw pointer access without those pesky unsafe blocks everywhere!

null 1 Jan 23, 2022
Submit sbatch jobs without the need to create a script

ssubmit Submit sbatch jobs without having to create a submission script Motivation Install Usage Motivation This project is motivated by the fact that

Michael Hall 44 Nov 23, 2022
Expand threaded messages without "Also sent to the channel"

slack-thread-expander Expand threaded messages without "Also sent to the channel" Usage Setup Slack App Create a Slack App for slack-thread-expander.

Kohei Suzuki 7 Feb 15, 2022
Pass cloudflare IUAM using headless chrome without hassle.

FlarelessHeadlessChrome Pass cloudflare turnstile challenge using patched chrome binary (Windows/Linux x64). How it works Currently, with new headless

makin 3 Oct 24, 2023
A GitHub Action to automatically build and deploy your mdbook project.

?? deploy-mdbook The deploy-mdbook action allows you to easily build and deploy your mdBook project to GitHub Pages. See action.yml for configuration

null 27 Oct 24, 2022
RustHunter is a modular incident response framework to build and compare environmental baselines

RustHunter is a modular incident response framework to build and compare environmental baselines. It is written in Rust and uses Ansible to collect data across multiple hosts.

Giovanni Pecoraro 13 Dec 12, 2022
QueingSimulator is an application that can be used to build intuitions about behavior of synchronous request/reply systems

Queueing Simulator QueingSimulator is an application that can be used to build intuitions about behavior of synchronous request/reply systems (such as

Joe Magerramov 7 Sep 11, 2022
An abstraction build on top of discord-rich-presence that makes possible to use it in a more declarative way

Declarative Discord Rich Presence This library is an abstraction build on top of discord-rich-presence crate that allows you to use it in a more decla

null 2 Sep 7, 2022
An implementation of Code Generation and Factoring for Fast Evaluation of Low-order Spherical Harmonic Products and Squares

sh_product An implementation of Code Generation and Factoring for Fast Evaluation of Low-order Spherical Harmonic Products and Squares (paper by John

Simon Brown 7 Dec 2, 2022
MeiliSearch is a powerful, fast, open-source, easy to use and deploy search engine

MeiliSearch is a powerful, fast, open-source, easy to use and deploy search engine. Both searching and indexing are highly customizable. Features such as typo-tolerance, filters, and synonyms are provided out-of-the-box. For more information about features go to our documentation.

MeiliSearch 31.6k Dec 30, 2022
Novus - A blazingly fast and efficient package manager for windows.

Novus - A blazingly fast and efficient package manager for windows. Why Novus Swift Unlike any other package manager, Novus uses multithreaded downloads

Novus 197 Dec 18, 2022
A little bit fast and modern Ruby version manager written in Rust

A little bit fast and modern Ruby version manager written in Rust Features Pure Rust implementation not using ruby-build Cross-platform support (macOS

Takayuki Maeda 510 Jan 5, 2023