diff --git a/compilation/prepare-contract.sh b/compilation/prepare-contract.sh new file mode 100755 index 0000000..9bf5555 --- /dev/null +++ b/compilation/prepare-contract.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +# This should run in the repository root +# It expects two args: the contract path and the arguments for the init function. + +set -e + +UKM_CONTRACTS_TESTING_INPUT_DIR=tests/ukm-contracts +UKM_PREPROCESSING_KOMPILED=.build/ukm-preprocessing-kompiled +TEMP_DIR=tmp + +mkdir -p $TEMP_DIR + +echo "<(<" > $TEMP_DIR/input.tmp +echo "::address" >> $TEMP_DIR/input.tmp +echo "<|>" >> $TEMP_DIR/input.tmp +cat $UKM_CONTRACTS_TESTING_INPUT_DIR/address.rs >> $TEMP_DIR/input.tmp +echo ">)>" >> $TEMP_DIR/input.tmp + +echo "<(<" >> $TEMP_DIR/input.tmp +echo "::bytes_hooks" >> $TEMP_DIR/input.tmp +echo "<|>" >> $TEMP_DIR/input.tmp +cat $UKM_CONTRACTS_TESTING_INPUT_DIR/bytes_hooks.rs >> $TEMP_DIR/input.tmp +echo ">)>" >> $TEMP_DIR/input.tmp + +echo "<(<" >> $TEMP_DIR/input.tmp +echo "::test_helpers" >> $TEMP_DIR/input.tmp +echo "<|>" >> $TEMP_DIR/input.tmp +cat $UKM_CONTRACTS_TESTING_INPUT_DIR/test_helpers.rs >> $TEMP_DIR/input.tmp +echo ">)>" >> $TEMP_DIR/input.tmp + +echo "<(<" >> $TEMP_DIR/input.tmp +echo "::helpers" >> $TEMP_DIR/input.tmp +echo "<|>" >> $TEMP_DIR/input.tmp +cat $UKM_CONTRACTS_TESTING_INPUT_DIR/helpers.rs >> $TEMP_DIR/input.tmp +echo ">)>" >> $TEMP_DIR/input.tmp + +echo "<(<" >> $TEMP_DIR/input.tmp +echo "::state_hooks" >> $TEMP_DIR/input.tmp +echo "<|>" >> $TEMP_DIR/input.tmp +cat $UKM_CONTRACTS_TESTING_INPUT_DIR/state_hooks.rs >> $TEMP_DIR/input.tmp +echo ">)>" >> $TEMP_DIR/input.tmp + +echo "<(<" >> $TEMP_DIR/input.tmp +echo "::single_value_mapper" >> $TEMP_DIR/input.tmp +echo "<|>" >> $TEMP_DIR/input.tmp +cat $UKM_CONTRACTS_TESTING_INPUT_DIR/single_value_mapper.rs >> $TEMP_DIR/input.tmp +echo ">)>" >> $TEMP_DIR/input.tmp + +echo "<(<" >> $TEMP_DIR/input.tmp +echo "::ukm" >> $TEMP_DIR/input.tmp +echo "<|>" >> $TEMP_DIR/input.tmp +cat $UKM_CONTRACTS_TESTING_INPUT_DIR/ukm.rs >> $TEMP_DIR/input.tmp +echo ">)>" >> $TEMP_DIR/input.tmp + +echo "<(<" >> $TEMP_DIR/input.tmp +echo "$1" | sed 's%^.*/%%' | sed 's/\..*//' | sed 's/^/::/' >> $TEMP_DIR/input.tmp +echo "<|>" >> $TEMP_DIR/input.tmp +cat "$1" >> $TEMP_DIR/input.tmp +echo ">)>" >> $TEMP_DIR/input.tmp + +krun \ + $TEMP_DIR/input.tmp \ + --parser $(pwd)/parsers/crates-ukm-preprocessing-execution.sh \ + --definition $UKM_PREPROCESSING_KOMPILED \ + --output kore \ + --output-file $TEMP_DIR/output.kore \ + +echo "not finished, must extract the bytes from the result: $TEMP_DIR/output.kore" +false diff --git a/compilation/prepare-erc20.sh b/compilation/prepare-erc20.sh new file mode 100755 index 0000000..3fc541d --- /dev/null +++ b/compilation/prepare-erc20.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# This should run in the repository root + +set -e + +compilation/prepare-contract.sh tests/ukm-contracts/erc_20_token.rs "1000000000000000000_u256," diff --git a/parsers/args-ukm-preprocessing-execution.sh b/parsers/args-ukm-preprocessing-execution.sh new file mode 100755 index 0000000..9de7193 --- /dev/null +++ b/parsers/args-ukm-preprocessing-execution.sh @@ -0,0 +1,13 @@ +#! /bin/bash + +function parse_args() { + kast \ + --output kore \ + --definition $1 \ + --module RUST-CRATES-SYNTAX \ + --sort ArgumentList \ + $2 +} + +parse_args .build/ukm-preprocessing-kompiled $1 + diff --git a/parsers/crates-ukm-preprocessing-execution.sh b/parsers/crates-ukm-preprocessing-execution.sh new file mode 100755 index 0000000..03545b7 --- /dev/null +++ b/parsers/crates-ukm-preprocessing-execution.sh @@ -0,0 +1,5 @@ +#! /bin/bash + +source ${BASH_SOURCE%/*}/inc-crates.sh + +parse_crates .build/ukm-preprocessing-kompiled $1 diff --git a/tests/ukm-contracts/erc_20_token.rs b/tests/ukm-contracts/erc_20_token.rs index fe396c3..f88b02a 100644 --- a/tests/ukm-contracts/erc_20_token.rs +++ b/tests/ukm-contracts/erc_20_token.rs @@ -2,7 +2,7 @@ // https://github.com/Pi-Squared-Inc/pi2-examples/blob/b63d0a78922874a486be8a0395a627425fb5a052/solidity/src/tokens/SomeToken.sol // // The main change is that the contract does not issue specific error objects -// (e.g. ERC20InsufficientBalance), it just calls `require!` with various +// (e.g. ERC20InsufficientBalance), it just calls `::helpers::require` with various // (string) explanations. // // Also, the `totalSupply` endpoint is declared implicitely as a view for @@ -22,45 +22,45 @@ TODOs: inits; - Support some sort of struct for implementing MessageResult within the UKM module. We also have to figure out the contents of MessageResult. - + Observations: - ManagedAddress was replaced by an integer to fit the behaviors of UKM; - + ---------------------------------------------------------------------------- */ #[ukm::contract] pub trait Erc20Token { - #[view(totalSupply)] + // #[view(totalSupply)] #[storage_mapper("total_supply")] - fn s_total_supply(&self) -> SingleValueMapper; + fn s_total_supply(&self) -> ::single_value_mapper::SingleValueMapper; - #[view(getName)] + // #[view(getName)] #[storage_mapper("name")] - fn s_name(&self) -> SingleValueMapper; + fn s_name(&self) -> ::single_value_mapper::SingleValueMapper; - #[view(getSymbol)] + // #[view(getSymbol)] #[storage_mapper("symbol")] - fn s_symbol(&self) -> SingleValueMapper; + fn s_symbol(&self) -> ::single_value_mapper::SingleValueMapper; - #[view(getBalances)] + // #[view(getBalances)] #[storage_mapper("balances")] - fn s_balances(&self, address: u64) -> SingleValueMapper; + fn s_balances(&self, address: u160) -> ::single_value_mapper::SingleValueMapper; - #[view(getAllowances)] + // #[view(getAllowances)] #[storage_mapper("balances")] - fn s_allowances(&self, account: u64, spender: u64) -> SingleValueMapper; + fn s_allowances(&self, account: u160, spender: u160) -> ::single_value_mapper::SingleValueMapper; #[event("Transfer")] - fn transfer_event(&self, #[indexed] from: u64, #[indexed] to: u64, value: u64); - + fn transfer_event(&self, #[indexed] from: u160, #[indexed] to: u160, value: u256); + #[event("Approval")] - fn approval_event(&self, #[indexed] owner: u64, #[indexed] spender: u64, value: u64); + fn approval_event(&self, #[indexed] owner: u160, #[indexed] spender: u160, value: u256); #[init] - fn init(&self, name: &ManagedBuffer, symbol: &ManagedBuffer, init_supply: u64) { - self.s_name().set_if_empty(name); - self.s_symbol().set_if_empty(symbol); + fn init(&self, /*name: &ManagedBuffer, symbol: &ManagedBuffer, */init_supply: u256) { + // self.s_name().set_if_empty(name); + // self.s_symbol().set_if_empty(symbol); self._mint(::ukm::Caller(), init_supply); } @@ -72,88 +72,93 @@ pub trait Erc20Token { 18 } - #[view(name)] - fn name(&self) -> ManagedBuffer { - self.s_name().get() + #[view(totalSupply)] + fn total_supply(&self) -> u256 { + self.s_total_supply().get() } - #[view(symbol)] - fn symbol(&self) -> ManagedBuffer { - self.s_symbol().get() - } + // #[view(name)] + // fn name(&self) -> ManagedBuffer { + // self.s_name().get() + // } + + // #[view(symbol)] + // fn symbol(&self) -> ManagedBuffer { + // self.s_symbol().get() + // } #[view(balanceOf)] - fn balance_of(&self, account: u64) -> u64 { + fn balance_of(&self, account: u160) -> u256 { self.s_balances(account).get() } #[endpoint(transfer)] - fn transfer(&self, to: u64, value: u64) -> bool { + fn transfer(&self, to: u160, value: u256) -> bool { let owner = ::ukm::Caller(); self._transfer(&owner, to, &value); true } #[view(allowance)] - fn allowance(&self, owner: u64, spender: u64) -> u64 { + fn allowance(&self, owner: u160, spender: u160) -> u256 { self.s_allowances(owner, spender).get() } #[endpoint(approve)] - fn approve(&self, spender: u64, value: u64) -> bool { + fn approve(&self, spender: u160, value: u256) -> bool { let owner = ::ukm::Caller(); self._approve(&owner, spender, value, true); true } #[endpoint(transferFrom)] - fn transfer_from(&self, from: u64, to: u64, value: u64) -> bool { + fn transfer_from(&self, from: u160, to: u160, value: u256) -> bool { let spender = ::ukm::Caller(); self._spend_allowance(from, &spender, value); self._transfer(from, to, value); true } - fn _transfer(&self, from: u64, to: u64, value: u64) { - require!(!from.is_zero(), "Invalid sender"); - require!(!to.is_zero(), "Invalid receiver"); + fn _transfer(&self, from: u160, to: u160, value: u256) { + ::helpers::require(!::address::is_zero(from), "Invalid sender"); + ::helpers::require(!::address::is_zero(to), "Invalid receiver"); self._update(from, to, value); self.transfer_event(from, to, value); } - fn _update(&self, from: u64, to: u64, value: u64) { - if from.is_zero() { + fn _update(&self, from: u160, to: u160, value: u256) { + if ::address::is_zero(from) { self.s_total_supply().set(self.s_total_supply().get() + value); } else { let from_balance = self.s_balances(from).get(); - require!(value <= &from_balance, "Insufficient balance"); + ::helpers::require(value <= &from_balance, "Insufficient balance"); self.s_balances(from).set(self.s_balances(from).get() - value); }; - if to.is_zero() { + if ::address::is_zero(to) { self.s_total_supply().set(self.s_total_supply().get() - value); } else { self.s_balances(to).set(self.s_balances(to).get() + value); } } - fn _mint(&self, account: u64, value: u64) { - require!(!account.is_zero(), "Zero address"); - self._update(0_u64, account, value); + fn _mint(&self, account: u160, value: u256) { + ::helpers::require(!::address::is_zero(account), "Zero address"); + self._update(0_u160, account, value); } - fn _approve(&self, owner: u64, spender: u64, value: u64, emit_event: bool) { - require!(!owner.is_zero(), "Invalid approver"); - require!(!spender.is_zero(), "Invalid spender"); + fn _approve(&self, owner: u160, spender: u160, value: u256, emit_event: bool) { + ::helpers::require(!::address::is_zero(owner), "Invalid approver"); + ::helpers::require(!::address::is_zero(spender), "Invalid spender"); self.s_allowances(owner, spender).set(value); if emit_event { self.approval_event(owner, spender, value); } } - fn _spend_allowance(&self, owner: u64, spender: u64, value: u64) { + fn _spend_allowance(&self, owner: u160, spender: u160, value: u256) { let current_allowance = self.allowance(owner, spender); - require!(value <= ¤t_allowance, "Insuficient allowance"); + ::helpers::require(value <= ¤t_allowance, "Insuficient allowance"); self._approve(owner, spender, &(current_allowance - value), false); }