All Downloads are FREE. Search and download functionalities are using the official Maven repository.

contracts.nft.nft-sale.fc Maven / Gradle / Ivy

There is a newer version: 0.8.0
Show newest version
;; NFT sale smart contract

int min_gas_amount() asm "1000000000 PUSHINT"; ;; 1 TON

(slice, slice, slice, int, cell) load_data() inline {
  var ds = get_data().begin_parse();
  return 
    (ds~load_msg_addr(), ;; marketplace_address 
      ds~load_msg_addr(), ;; nft_address
      ds~load_msg_addr(),  ;; nft_owner_address
      ds~load_coins(), ;; full_price
      ds~load_ref() ;; fees_cell
     );
}

(int, slice, int) load_fees(cell fees_cell) inline {
  var ds = fees_cell.begin_parse();
  return 
    (ds~load_coins(), ;; marketplace_fee,
      ds~load_msg_addr(), ;; royalty_address 
      ds~load_coins() ;; royalty_amount
     );
}


() save_data(slice marketplace_address, slice nft_address, slice nft_owner_address, int full_price, cell fees_cell) impure inline {
  set_data(begin_cell()
    .store_slice(marketplace_address)
    .store_slice(nft_address)
    .store_slice(nft_owner_address)
    .store_coins(full_price)
    .store_ref(fees_cell)
    .end_cell());
}

() buy(int my_balance, slice marketplace_address, slice nft_address, slice nft_owner_address, int full_price, cell fees_cell, int msg_value, slice sender_address, int query_id) impure {
  throw_unless(450, msg_value >= full_price + min_gas_amount());

  var (marketplace_fee, royalty_address, royalty_amount) = load_fees(fees_cell);

  var owner_msg = begin_cell()
           .store_uint(0x10, 6) ;; nobounce
           .store_slice(nft_owner_address)
           .store_coins(full_price - marketplace_fee - royalty_amount + (my_balance - msg_value))
           .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1);

  send_raw_message(owner_msg.end_cell(), 1);


  var royalty_msg = begin_cell()
           .store_uint(0x10, 6) ;; nobounce
           .store_slice(royalty_address)
           .store_coins(royalty_amount)
           .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1);

  send_raw_message(royalty_msg.end_cell(), 1);


  var marketplace_msg = begin_cell()
           .store_uint(0x10, 6) ;; nobounce
           .store_slice(marketplace_address)
           .store_coins(marketplace_fee)
           .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1);

  send_raw_message(marketplace_msg.end_cell(), 1);

  var nft_msg = begin_cell()
           .store_uint(0x18, 6) 
           .store_slice(nft_address)
           .store_coins(0)
           .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
           .store_uint(op::transfer(), 32)
           .store_uint(query_id, 64)
           .store_slice(sender_address) ;; new_owner_address
           .store_slice(sender_address) ;; response_address
           .store_int(0, 1) ;; empty custom_payload
           .store_coins(0) ;; forward amount to new_owner_address
           .store_int(0, 1); ;; empty forward_payload


  send_raw_message(nft_msg.end_cell(), 128 + 32);
}

() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {
    slice cs = in_msg_full.begin_parse();
    int flags = cs~load_uint(4);

    if (flags & 1) {  ;; ignore all bounced messages
        return ();
    }

    slice sender_address = cs~load_msg_addr();

    var (marketplace_address, nft_address, nft_owner_address, full_price, fees_cell) = load_data();

    var is_initialized = nft_owner_address.slice_bits() > 2; ;; not initialized if null address

    if (~ is_initialized) {
      
      if (equal_slices(sender_address, marketplace_address)) {
         return (); ;; just accept coins on deploy
      }

      throw_unless(500, equal_slices(sender_address, nft_address));
      int op = in_msg_body~load_uint(32);
      throw_unless(501, op == op::ownership_assigned());
      int query_id = in_msg_body~load_uint(64);
      slice prev_owner_address = in_msg_body~load_msg_addr();

      save_data(marketplace_address, nft_address, prev_owner_address, full_price, fees_cell);

      return ();

    }

    if (in_msg_body.slice_empty?()) {
        buy(my_balance, marketplace_address, nft_address, nft_owner_address, full_price, fees_cell, msg_value, sender_address, 0);
        return ();
    }

    int op = in_msg_body~load_uint(32);
    int query_id = in_msg_body~load_uint(64);

    if (op == 1) { ;; just accept coins
        return ();
    }

    if (op == 2) { ;; buy
     
      buy(my_balance, marketplace_address, nft_address, nft_owner_address, full_price, fees_cell, msg_value, sender_address, query_id);

      return ();

    }

    if (op == 3) { ;; cancel sale
         throw_unless(457, msg_value >= min_gas_amount());
         throw_unless(458, equal_slices(sender_address, nft_owner_address) | equal_slices(sender_address, marketplace_address));

         var msg = begin_cell()
           .store_uint(0x10, 6) ;; nobounce
           .store_slice(nft_address)
           .store_coins(0)
           .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
           .store_uint(op::transfer(), 32)
           .store_uint(query_id, 64) 
           .store_slice(nft_owner_address) ;; new_owner_address
           .store_slice(nft_owner_address) ;; response_address;
           .store_int(0, 1) ;; empty custom_payload
           .store_coins(0) ;; forward amount to new_owner_address
           .store_int(0, 1); ;; empty forward_payload

        send_raw_message(msg.end_cell(), 128 + 32);

        return ();
    }

    throw(0xffff);
    
}

() recv_external(slice in_msg) impure {
}

(slice, slice, slice, int, int, slice, int) get_sale_data() method_id {
  var (marketplace_address, nft_address, nft_owner_address, full_price, fees_cell) = load_data();
  var (marketplace_fee, royalty_address, royalty_amount) = load_fees(fees_cell);
  return (marketplace_address, nft_address, nft_owner_address, full_price, marketplace_fee, royalty_address, royalty_amount);
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy