ton icon indicating copy to clipboard operation
ton copied to clipboard

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).

Open AlirezaEthDev opened this issue 4 months ago • 0 comments

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!

AlirezaEthDev avatar Oct 08 '24 06:10 AlirezaEthDev