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

Simplify smart contract development #2

Open
HDauven opened this issue Jul 17, 2024 · 2 comments
Open

Simplify smart contract development #2

HDauven opened this issue Jul 17, 2024 · 2 comments
Labels
type:feature implementing a new feature

Comments

@HDauven
Copy link
Member

HDauven commented Jul 17, 2024

Summary

This issue comes from the need to simplify smart contract development on Dusk by abstracting away implementation details like the static mut STATE and no_mangle functions.

It follows from the discussion in the issue Investigate foreign trait exposing.

Possible solution design or implementation

We can create a #[contract] macro that generates the necessary boilerplate code automatically. We can take and extend the functionality of the piecrust-macros I did here, and make it do the following:

  • The #[contract] macro should be applicable to a Rust module.
  • The macro should generate no_mangle functions for all public methods within impl blocks.
  • The macro should generate no_mangle functions for every trait implementation function.
  • The macro should automatically generate static mut STATE for a public struct defined within the module.
  • The macro should allow only one public struct.

Example

The following input:

#![no_std]

use piecrust_macros::contract;

#[contract]
pub mod counter {
    pub struct Counter {
        value: i64,
    }

    impl Counter {
        pub fn read_value(&self) -> i64 {
            self.value
        }

        pub fn increment(&mut self) {
            let value = self.value + 1;
            self.value = value;
        }
    }

    pub trait Resettable {
        fn reset(&mut self);
    }

    impl Resettable for Counter {
        fn reset(&mut self) {
            self.value = 0;
        }
    }
}

Should generate the following output:

#![no_std]

use piecrust_uplink as uplink;

pub mod counter {
    pub struct Counter {
        value: i64,
    }

    static mut STATE: Counter = Counter { value: 0 };

    impl Counter {
        pub fn read_value(&self) -> i64 {
            self.value
        }

        pub fn increment(&mut self) {
            let value = self.value + 1;
            self.value = value;
        }
    }

    pub trait Resettable {
        fn reset(&mut self);
    }

    impl Resettable for Counter {
        fn reset(&mut self) {
            self.value = 0;
        }
    }
}

#[no_mangle]
pub unsafe fn read_value(arg_len: u32) -> u32 {
    uplink::wrap_call(arg_len, |_: ()| STATE.read_value())
}

#[no_mangle]
pub unsafe fn increment(arg_len: u32) -> u32 {
    uplink::wrap_call(arg_len, |_: ()| STATE.increment())
}

#[no_mangle]
pub unsafe fn reset(arg_len: u32) -> u32 {
    uplink::wrap_call(arg_len, |_: ()| STATE.reset())
}

By implementing this feature set, developers no longer need to create the no_mangle functions and do not have to define the state explicitly.

@HDauven HDauven added the type:feature implementing a new feature label Jul 17, 2024
@Neotamandua
Copy link
Member

Neotamandua commented Jul 18, 2024

How the static mut STATE gets created should also be standardised and defined. Otherwise it will be unclear how certain data structures within the field of the struct would be created and with which values.

The simplest approach here, in my opinion, would be to require the Default trait to be implemented for the public struct. This way the macro can always create the state with the default() method.

(There could also be another way with the init() function)

@Daksh14
Copy link

Daksh14 commented Sep 20, 2024

I think the name of this repo, "dev-tools" is not specific and generic, ideally this macro we're making should be moved in the rusk mono repo and used by the genesis contracts and exported from there like execution-core is (we will also need types from execution-core so better to have it in the workspace)

I would get a prototype of what Hein developed, out there, let me know if you need help or want me to create the macro package and export it for use with the rusk wallet @HDauven @Neotamandua

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:feature implementing a new feature
Projects
None yet
Development

No branches or pull requests

3 participants