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

Support for impl blocks implementing a trait #291

Merged
merged 6 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions examples2/src/counter_pack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ use odra::Mapping;
use odra::Module;
use odra::ModuleWrapper;

pub trait ICounter {
fn get_count(&self, index_a: u8, index_b: u8) -> u32;
fn increment(&mut self, index_a: u8, index_b: u8);
}
#[odra::module]
pub struct CounterPack {
counter0: ModuleWrapper<Counter>,
Expand All @@ -22,8 +26,8 @@ pub struct CounterPack {
}

#[odra::module]
impl CounterPack {
pub fn get_count(&self, index_a: u8, index_b: u8) -> u32 {
impl ICounter for CounterPack {
fn get_count(&self, index_a: u8, index_b: u8) -> u32 {
match index_a {
0 => self.counter0.get_count(index_b),
1 => self.counter1.get_count(index_b),
Expand All @@ -41,7 +45,7 @@ impl CounterPack {
// self.counters_map.module(index_a).get_count(index_b)
}

pub fn increment(&mut self, index_a: u8, index_b: u8) {
fn increment(&mut self, index_a: u8, index_b: u8) {
match index_a {
0 => self.counter0.increment(index_b),
1 => self.counter1.increment(index_b),
Expand Down
39 changes: 39 additions & 0 deletions odra-macros/src/ast/deployer_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,43 @@ mod deployer_impl {
let deployer_item = DeployerItem::try_from(&module).unwrap();
test_utils::assert_eq(deployer_item, &expected);
}

#[test]
fn deployer_trait_impl() {
let module = test_utils::mock_module_trait_impl();
let expected = quote! {
pub struct Erc20Deployer;

impl Erc20Deployer {
pub fn init(env: &odra::HostEnv) -> Erc20HostRef {
let caller = odra::EntryPointsCaller::new(env.clone(), |contract_env, call_def| {
match call_def.method() {
"total_supply" => {
let result = execute_total_supply(contract_env);
odra::ToBytes::to_bytes(&result).map(Into::into).unwrap()
}
"pay_to_mint" => {
let result = execute_pay_to_mint(contract_env);
odra::ToBytes::to_bytes(&result).map(Into::into).unwrap()
}
_ => panic!("Unknown method")
}
});

let address = env.new_contract(
"Erc20",
None,
Some(caller)
);
Erc20HostRef {
address,
env: env.clone(),
attached_value: odra::U512::zero()
}
}
}
};
let deployer_item = DeployerItem::try_from(&module).unwrap();
test_utils::assert_eq(deployer_item, &expected);
}
}
18 changes: 10 additions & 8 deletions odra-macros/src/ast/deployer_utils.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::{fn_utils, ref_utils};
use crate::utils::misc::AsBlock;
use crate::utils::misc::AsType;
use crate::{
ir::{FnIR, ModuleIR},
utils
Expand All @@ -23,7 +23,7 @@ impl TryFrom<&'_ ModuleIR> for DeployerInitSignature {
type Error = syn::Error;

fn try_from(module: &'_ ModuleIR) -> Result<Self, Self::Error> {
let host_ref_ident = module.host_ref_ident()?;
let host_ref_ident = module.host_ref_ident()?.as_type();
let ty_host_env = utils::ty::host_env();
let env = utils::ident::env();

Expand All @@ -35,7 +35,7 @@ impl TryFrom<&'_ ModuleIR> for DeployerInitSignature {
init_token: utils::ident::init(),
paren_token: Default::default(),
inputs,
output: parse_quote!(-> #host_ref_ident)
output: utils::misc::ret_ty(&host_ref_ident)
})
}
}
Expand Down Expand Up @@ -101,18 +101,19 @@ impl TryFrom<&'_ ModuleIR> for NewContractExpr {

fn try_from(module: &'_ ModuleIR) -> Result<Self, Self::Error> {
let module_str = module.module_str()?;
let caller_ident = utils::ident::caller();
let caller_expr = utils::expr::some(utils::ident::caller());
let env_ident = utils::ident::env();
let args = module
.constructor()
.map(|f| fn_utils::runtime_args_block(&f, ref_utils::insert_arg_stmt))
.unwrap_or(utils::expr::new_runtime_args().as_block());
.map(utils::expr::some)
.unwrap_or_else(utils::expr::none);

let new_contract_expr = parse_quote!(
#env_ident.new_contract(
#module_str,
Some(#args),
Some(#caller_ident)
#args,
#caller_expr
)
);

Expand Down Expand Up @@ -143,10 +144,11 @@ impl TryFrom<&'_ ModuleIR> for HostRefInstanceExpr {
let env_ident = utils::ident::env();
let attached_value_ident = utils::ident::attached_value();
let zero = utils::expr::u512_zero();
let env_expr = utils::expr::clone(&env_ident);

let fields = parse_quote!(
#address_ident,
#env_ident: #env_ident.clone(),
#env_ident: #env_expr,
#attached_value_ident: #zero

);
Expand Down
31 changes: 31 additions & 0 deletions odra-macros/src/ast/entrypoints_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,4 +190,35 @@ mod test {
let actual = HasEntrypointsImplItem::try_from(&module).unwrap();
test_utils::assert_eq(actual, expected);
}

#[test]
fn test_trait_impl_entrypoints() {
let module = test_utils::mock_module_trait_impl();
let expected = quote!(
impl odra::contract_def::HasEntrypoints for Erc20 {
fn entrypoints() -> Vec<odra::contract_def::Entrypoint> {
vec![
odra::contract_def::Entrypoint {
ident: String::from("total_supply"),
args: vec![],
is_mut: false,
ret: <U256 as odra::casper_types::CLTyped>::cl_type(),
ty: odra::contract_def::EntrypointType::Public,
attributes: vec![]
},
odra::contract_def::Entrypoint {
ident: String::from("pay_to_mint"),
args: vec![],
is_mut: true,
ret: <() as odra::casper_types::CLTyped>::cl_type(),
ty: odra::contract_def::EntrypointType::Public,
attributes: vec![odra::contract_def::EntrypointAttribute::Payable]
}
]
}
}
);
let actual = HasEntrypointsImplItem::try_from(&module).unwrap();
test_utils::assert_eq(actual, expected);
}
}
36 changes: 35 additions & 1 deletion odra-macros/src/ast/exec_parts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ impl ExecEnvStmt {
#[cfg(test)]
mod test {
use super::*;
use crate::test_utils::{self, mock_module};
use crate::test_utils::{self, mock_module, mock_module_trait_impl};

#[test]
fn test_parts() {
Expand Down Expand Up @@ -277,4 +277,38 @@ mod test {

test_utils::assert_eq(actual, expected);
}

#[test]
fn test_trait_impl_parts() {
let module = mock_module_trait_impl();
let actual = ExecPartsItem::try_from(&module).unwrap();

let expected = quote::quote! {
mod __erc20_exec_parts {
use super::*;
use odra::prelude::*;

#[inline]
pub fn execute_total_supply(env: odra::ContractEnv) -> U256 {
let env_rc = Rc::new(env);
let contract = <Erc20 as odra::Module>::new(env_rc);
let result = contract.total_supply();
return result;
}

#[inline]
pub fn execute_pay_to_mint(env: odra::ContractEnv) {
let env_rc = Rc::new(env);
let exec_env = odra::ExecutionEnv::new(env_rc.clone());
exec_env.handle_attached_value();
let mut contract = <Erc20 as odra::Module>::new(env_rc);
let result = contract.pay_to_mint();
exec_env.clear_attached_value();
return result;
}
}
};

test_utils::assert_eq(actual, expected);
}
}
77 changes: 77 additions & 0 deletions odra-macros/src/ast/host_ref_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,4 +263,81 @@ mod ref_item_tests {
let actual = HostRefItem::try_from(&module).unwrap();
test_utils::assert_eq(actual, expected);
}

#[test]
fn host_trait_impl_ref() {
let module = test_utils::mock_module_trait_impl();
let expected = quote! {
pub struct Erc20HostRef {
pub address: odra::Address,
pub env: odra::HostEnv,
pub attached_value: odra::U512
}

impl Erc20HostRef {
pub fn with_tokens(&self, tokens: odra::U512) -> Self {
Self {
address: self.address,
env: self.env.clone(),
attached_value: tokens
}
}

pub fn get_event<T>(&self, index: i32) -> Result<T, odra::event::EventError>
where
T: odra::FromBytes + odra::casper_event_standard::EventInstance,
{
self.env.get_event(&self.address, index)
}

pub fn last_call(&self) -> odra::ContractCallResult {
self.env.last_call().contract_last_call(self.address)
}

pub fn try_total_supply(&self) -> Result<U256, odra::OdraError> {
self.env.call_contract(
self.address,
odra::CallDef::new(
String::from("total_supply"),
{
let mut named_args = odra::RuntimeArgs::new();
if self.attached_value > odra::U512::zero() {
let _ = named_args.insert("amount", self.attached_value);
}
named_args
}
).with_amount(self.attached_value),
)
}

pub fn total_supply(&self) -> U256 {
self.try_total_supply().unwrap()
}

pub fn try_pay_to_mint(&mut self) -> Result<(), odra::OdraError> {
self.env
.call_contract(
self.address,
odra::CallDef::new(
String::from("pay_to_mint"),
{
let mut named_args = odra::RuntimeArgs::new();
if self.attached_value > odra::U512::zero() {
let _ = named_args.insert("amount", self.attached_value);
}
named_args
},
)
.with_amount(self.attached_value),
)
}

pub fn pay_to_mint(&mut self) {
self.try_pay_to_mint().unwrap()
}
}
};
let actual = HostRefItem::try_from(&module).unwrap();
test_utils::assert_eq(actual, expected);
}
}
47 changes: 47 additions & 0 deletions odra-macros/src/ast/ref_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,51 @@ mod ref_item_tests {
let actual = RefItem::try_from(&module).unwrap();
test_utils::assert_eq(actual, expected);
}

#[test]
fn contract_trait_impl_ref() {
let module = test_utils::mock_module_trait_impl();
let expected = quote! {
pub struct Erc20ContractRef {
env: Rc<odra::ContractEnv>,
address: odra::Address,
}

impl Erc20ContractRef {
// TODO: this means "address", can't be entrypoint name.
pub fn address(&self) -> &odra::Address {
&self.address
}

pub fn total_supply(&self) -> U256 {
self.env.call_contract(
self.address,
odra::CallDef::new(
String::from("total_supply"),
{
let mut named_args = odra::RuntimeArgs::new();
named_args
}
),
)
}

pub fn pay_to_mint(&mut self) {
self.env
.call_contract(
self.address,
odra::CallDef::new(
String::from("pay_to_mint"),
{
let mut named_args = odra::RuntimeArgs::new();
named_args
},
),
)
}
}
};
let actual = RefItem::try_from(&module).unwrap();
test_utils::assert_eq(actual, expected);
}
}
Loading
Loading