Skip to content

Commit

Permalink
Compile erc-20
Browse files Browse the repository at this point in the history
  • Loading branch information
virgil-serbanuta committed Oct 24, 2024
1 parent 115fd63 commit 5ffa724
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 46 deletions.
70 changes: 70 additions & 0 deletions compilation/prepare-contract.sh
Original file line number Diff line number Diff line change
@@ -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
7 changes: 7 additions & 0 deletions compilation/prepare-erc20.sh
Original file line number Diff line number Diff line change
@@ -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,"
13 changes: 13 additions & 0 deletions parsers/args-ukm-preprocessing-execution.sh
Original file line number Diff line number Diff line change
@@ -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

5 changes: 5 additions & 0 deletions parsers/crates-ukm-preprocessing-execution.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#! /bin/bash

source ${BASH_SOURCE%/*}/inc-crates.sh

parse_crates .build/ukm-preprocessing-kompiled $1
97 changes: 51 additions & 46 deletions tests/ukm-contracts/erc_20_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<u64>;
fn s_total_supply(&self) -> ::single_value_mapper::SingleValueMapper<u256>;

#[view(getName)]
// #[view(getName)]
#[storage_mapper("name")]
fn s_name(&self) -> SingleValueMapper<ManagedBuffer>;
fn s_name(&self) -> ::single_value_mapper::SingleValueMapper<ManagedBuffer>;

#[view(getSymbol)]
// #[view(getSymbol)]
#[storage_mapper("symbol")]
fn s_symbol(&self) -> SingleValueMapper<ManagedBuffer>;
fn s_symbol(&self) -> ::single_value_mapper::SingleValueMapper<ManagedBuffer>;

#[view(getBalances)]
// #[view(getBalances)]
#[storage_mapper("balances")]
fn s_balances(&self, address: u64) -> SingleValueMapper<u64>;
fn s_balances(&self, address: u160) -> ::single_value_mapper::SingleValueMapper<u256>;

#[view(getAllowances)]
// #[view(getAllowances)]
#[storage_mapper("balances")]
fn s_allowances(&self, account: u64, spender: u64) -> SingleValueMapper<u64>;
fn s_allowances(&self, account: u160, spender: u160) -> ::single_value_mapper::SingleValueMapper<u256>;

#[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);
}

Expand All @@ -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 <= &current_allowance, "Insuficient allowance");
::helpers::require(value <= &current_allowance, "Insuficient allowance");
self._approve(owner, spender, &(current_allowance - value), false);
}

Expand Down

0 comments on commit 5ffa724

Please sign in to comment.