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

Func compilation error: cannot assign an expression of type (slice, slice) to a variable or pattern of type (slice, slice, slice, int, int, cell, cell). #1259

Open
AlirezaEthDev opened this issue Oct 8, 2024 · 0 comments

Comments

@AlirezaEthDev
Copy link

This is the whole of my smart contract (called Pugy.fc) that I'm developing it:

#include "stdlib.fc";

;; Storage variables
const int storage::owner = 0;
const int storage::name = 1;
const int storage::symbol = 2;
const int storage::decimals = 3;
const int storage::total_supply = 4;
const int storage::balance_dict = 5;
const int storage::approve_dict = 6;

;; Op codes
const int op::transfer = 1;
const int op::transfer_from = 2;
const int op::approve = 3;
const int op::mint = 4;
const int op::burn = 5;
const int op::change_ownership = 6;

;; Error codes
const int error::unauthorized = 101;
const int error::insufficient_balance = 102;
const int error::insufficient_allowance = 103;

;; Helper functions
(slice) get_pugy_sender() inline {
    return get_current_slice();
}

() send_tokens(slice from, slice to, int amount) impure inline {
    var msg = begin_cell()
        .store_uint(0x10, 6) ;; nobounce
        .store_slice(to)
        .store_coins(0)
        .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
        .store_uint(op::transfer, 32)
        .store_slice(from)
        .store_uint(amount, 256);
    send_raw_message(msg.end_cell(), 64);
}

() transfer(slice to, int amount) impure {
    slice sender = get_pugy_sender();
    var (slice owner, slice name, slice symbol, int decimals, int total_supply, cell balance_dict, cell approve_dict) = load_data();
    
    int sender_balance = balance_dict.dict_get(256, sender);
    throw_unless(error::insufficient_balance, sender_balance >= amount);
    
    balance_dict~dict_set(256, sender, sender_balance - amount);
    balance_dict~dict_set(256, to, balance_dict.dict_get(256, to) + amount);
    
    save_data(owner, name, symbol, decimals, total_supply, balance_dict, approve_dict);
    send_tokens(sender, to, amount);
}

() approve(slice spender, int amount) impure {
    slice sender = get_pugy_sender();
    (slice owner, _, _, _, int total_supply, cell balance_dict, cell approve_dict) = load_data();
    
    cell sender_approvals = approve_dict.dict_get(256, sender);
    sender_approvals~dict_set(256, spender, amount);
    approve_dict~dict_set(256, sender, sender_approvals);
    
    save_data(owner, balance_dict, approve_dict, total_supply);
    
    ;; Emit Approval event (as a message in TON)
    var msg = begin_cell()
        .store_uint(0x10, 6)
        .store_slice(sender)
        .store_coins(0)
        .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
        .store_uint(op::approve, 32)
        .store_slice(spender)
        .store_uint(amount, 256);
    send_raw_message(msg.end_cell(), 64);
}

() mint(int amount) impure {
    slice sender = get_pugy_sender();
    (slice owner, _, _, _, int total_supply, cell balance_dict, cell approve_dict) = load_data();
    
    throw_unless(error::unauthorized, equal_slices(sender, owner));
    
    total_supply += amount;
    balance_dict~dict_set(256, owner, balance_dict.dict_get(256, owner) + amount);
    
    save_data(owner, balance_dict, approve_dict, total_supply);
    send_tokens(begin_cell().store_uint(0, 2).end_cell(), owner, amount); ;; Mint from zero address
}

() burn(int amount) impure {
    slice sender = get_pugy_sender();
    (slice owner, _, _, _, int total_supply, cell balance_dict, cell approve_dict) = load_data();
    
    throw_unless(error::unauthorized, equal_slices(sender, owner));
    
    int owner_balance = balance_dict.dict_get(256, owner);
    throw_unless(error::insufficient_balance, owner_balance >= amount);
    
    total_supply -= amount;
    balance_dict~dict_set(256, owner, owner_balance - amount);
    
    save_data(owner, balance_dict, approve_dict, total_supply);
    send_tokens(owner, begin_cell().store_uint(0, 2).end_cell(), amount); ;; Burn to zero address
}

() change_ownership(slice new_owner) impure {
    slice sender = get_pugy_sender();
    (slice owner, _, _, _, int total_supply, cell balance_dict, cell approve_dict) = load_data();
    
    throw_unless(error::unauthorized, equal_slices(sender, owner));
    
    save_data(new_owner, balance_dict, approve_dict, total_supply);
    
    ;; Emit OwnershipTransferred event (as a message in TON)
    var msg = begin_cell()
        .store_uint(0x10, 6)
        .store_slice(sender)
        .store_coins(0)
        .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
        .store_uint(op::change_ownership, 32)
        .store_slice(new_owner);
    send_raw_message(msg.end_cell(), 64);
}
;; Contract functions
() recv_pugy_internal(int msg_value, cell in_msg_full, slice in_msg_body) impure {
    if (in_msg_body.slice_empty?()) { 
        return (); ;; Ignore empty messages
    }
    
    int op = in_msg_body~load_uint(32);

    if (op == op::transfer) {
        transfer(in_msg_body~load_msg_addr(), in_msg_body~load_uint(256));
    } elseif (op == op::transfer_from) {
        transfer_from(in_msg_body~load_msg_addr(), in_msg_body~load_msg_addr(), in_msg_body~load_uint(256));
    } elseif (op == op::approve) {
        approve(in_msg_body~load_msg_addr(), in_msg_body~load_uint(256));
    } elseif (op == op::mint) {
        mint(in_msg_body~load_uint(256));
    } elseif (op == op::burn) {
        burn(in_msg_body~load_uint(256));
    } elseif (op == op::change_ownership) {
        change_ownership(in_msg_body~load_msg_addr());
    } else {
        throw(0xffff); ;; Unsupported operation
    }
}

;; Getter methods
(int) balance_of(slice address) method_id {
    (_, _, _, _, _, cell balance_dict, _) = load_data();
    return balance_dict.dict_get(256, address);
}

(int) allowance(slice owner, slice spender) method_id {
    (_, _, _, _, _, _, cell approve_dict) = load_data();
    cell owner_approvals = approve_dict.dict_get(256, owner);
    return owner_approvals.dict_get(256, spender);
}

(slice, slice, int, int) get_token_data() method_id {
    (slice owner, slice name, slice symbol, int decimals, int total_supply, _, _) = load_data();
    return (name, symbol, decimals, total_supply);
}

;; Helper functions
(slice, slice, slice, int, int, cell, cell) load_data() inline {
    var ds = get_data().begin_parse();
    
    ;; Load owner directly from the message address
    slice owner = ds~load_msg_addr();

    ;; Load name and symbol references, and extract slices from them
    cell name_ref = ds~load_ref();
    slice name = name_ref.begin_parse()~load_slice();

    cell symbol_ref = ds~load_ref();
    slice symbol = symbol_ref.begin_parse()~load_slice();

    ;; Load decimals and total supply
    int decimals = ds~load_uint(8);
    int total_supply = ds~load_uint(256);

    ;; Load balance_dict and approve_dict dictionaries
    cell balance_dict = ds~load_dict();
    cell approve_dict = ds~load_dict();

    return (owner, name, symbol, decimals, total_supply, balance_dict, approve_dict);
}



() save_data(slice owner, slice name, slice symbol, int decimals, int total_supply, cell balance_dict, cell approve_dict) impure inline {
    set_data(begin_cell()
        .store_slice(owner)
        .store_ref(begin_cell().store_slice(name).end_cell())
        .store_ref(begin_cell().store_slice(symbol).end_cell())
        .store_uint(decimals, 8)
        .store_uint(total_supply, 256)
        .store_dict(balance_dict)
        .store_dict(approve_dict)
        .end_cell());
}

And this is compile.js to compile it:

import { compileFunc } from '@ton-community/func-js';
import { Cell } from 'ton';
import fs from 'node:fs';
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

async function main() {
    const source = fs.readFileSync(path.resolve(__dirname, './contracts/MasterContract.fc'), 'utf-8');

    // Read standard library files
    const stdlib = fs.readFileSync(path.resolve(__dirname, './contracts/imports/stdlib.fc'), 'utf-8');
    const ownable2Step = fs.readFileSync(path.resolve(__dirname, './contracts/imports/Ownable2Step.fc'), 'utf-8');
    const pugy = fs.readFileSync(path.resolve(__dirname, './contracts/imports/Pugy.fc'), 'utf-8');
    const gameFi = fs.readFileSync(path.resolve(__dirname, './contracts/imports/GameFi.fc'), 'utf-8');

    const result = await compileFunc({
        entryPoints: ['main'],
        sources: {
            "stdlib.fc": stdlib,
            "Ownable2Step.fc": ownable2Step,
            "Pugy.fc": pugy,
            "GameFi.fc": gameFi,
            "main.fc": source,
        },
        targets: ['main.fc'],
    });

    if (result.status === 'error') {
        console.error(result.message);
        return;
    }

    const codeCell = Cell.fromBoc(Buffer.from(result.codeBoc, "base64"))[0];
    console.log('Compiled Cell:', codeCell);
}

main().catch(console.error);

But whenever I try to compile the contract via compile.js this error throwed:

Func compilation error: Pugy.fc:44:132: error: cannot assign an expression of type (slice, slice) to a variable or pattern of type (slice, slice, slice, int, int, cell, cell): cannot unify type (slice, slice, slice, int, int, cell, cell) with (slice, slice)
      var (slice owner, slice name, slice symbol, int decimals, int total_supply, cell balance_dict, cell approve_dict) = load_data();

I am using @ton-community/func-js package to compile the contract.

My OS is Windows 10!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant