BLDS TMWSTW BUILDINGS
Featured: Register HENS (.etc) Domain Name Click to register
Overview [ERC-721]
Max Total Supply:
0
Holders:
115
Transfers:
5,268
Profile Summary
Decimals:
0
Official Site:
FILTERED BY TOKEN HOLDER
BALANCE
263 BLDS
VALUE
$0 (~0 ETC)
Contract name:
tmwstw_buildings
Optimization enabled :
true
Compiler version:
v0.8.11+commit.d7f03943
EVM Version:
default
Contract source code
// SPDX-License-Identifier: GLWTPL
pragma solidity ^0.8.11;


contract tmwstw_buildings{

    string private token_name = "TMWSTW BUILDINGS";
    string private token_symbol = "BLDS";
    address private contract_creator;
    string private base_uri = "";
	address private bob_contract;
	uint nukewei = 10000000000000;//for rent price division

    //AT START
    constructor(){
        contract_creator = msg.sender;
		
        burnable_by_router_types[8] = true; //walls		
		rentable_b_types[0] = true; //small ground
		rentable_b_types[1] = true; //big ground
		rentable_b_types[2] = true; //residential
		rentable_b_types[3] = true; //mansion
		rentable_b_types[5] = true; //lvr
    }
	
    //MAPS
    mapping(uint => address) private token_ownership;// Mapping from token ID to owner address
    mapping(address => uint256) private balance_per_owner;// Mapping owner address to token count
    mapping(uint => address) private approval_per_token;// Mapping from token ID to approved address
    mapping(address => mapping(address => bool)) private operator_approvals;// Mapping from owner to operator approvals
	
	//TYPE MAPS
	mapping(uint8 => bool) private burnable_by_router_types; // all b_types that are burnable without ownership via router
	mapping(uint8 => bool) private rentable_b_types; //all b types that can be rented out
	mapping(uint8 => bool) private damageable_b_types; //all b types that can be damaged
	
	
	//....................................PROXY
	
	function register_bob(address this_bob)public CREATOR_ONLY{
		bob_contract = this_bob;
	}
	//SEND BOB to core, send GAS to router, emit request event
	function build_proxy_request(address build_router, uint bob_amount)public payable{
		require(all_build_routers[build_router],"Bad build router");
		require(bob_amount>0,"Send more BOB");
		require(msg.value>0,"Send more GAS");
		
		bool sent;
        bytes memory response;
		(sent,response) = build_router.call{value: msg.value}("");
        require(sent, "Failed to send GAS");
		
		bob(bob_contract).transferFrom(msg.sender,bob_contract, bob_amount);
		
		emit build_request_event(msg.sender,build_router,bob_amount,msg.value);
	}
	event build_request_event(address from,address b_router,uint bob_amount,uint gas_amount);
	
	//....................................BUILD_ROUTERS
	
	mapping(address => bool) private all_build_routers;
	
	//fillup claim routers array
    function add_or_remove_build_routers(bool this_action, address[] calldata those_addresses) public  CREATOR_ONLY{
        require(those_addresses.length>0,"no input");
        for(uint i = 0; i < those_addresses.length; i++){
            all_build_routers[those_addresses[i]] = this_action;
        }
    }
	
	
    //...................................BUILD/BURN functions	
	
    //BUILD DATA MAPS
    struct build_data{
        uint8 b_type; //type of building
        uint16 plot_id; //plot_id
        bool buildable_on_top;
	    bool is_ground;
	    bool is_double_floor;
	    bool is_base;
        uint8 top_unit_shell_rotation; //random rotation of residential units
	    uint16 mesh_id; //mesh id representing token
        uint8 color_id; //1-5 unit base color id 
	    uint8 color_scheme_id; //unit color scheme id
		bool is_damaged; //true = damaged , false = repaired
		
		uint8 style_by_claster; //store style_id by cluster
		uint8 extra_cluster_randomizer_1; //store extra cluster rand 1-250 for future
		uint8 extra_cluster_randomizer_2;
		uint8 extra_cluster_randomizer_3;
    }

    struct build_position_data{
        int32 quat_x; //2,000,000,000x quaternion
        int32 quat_y; //2,000,000,000x quaternion
        int32 quat_z; //2,000,000,000x quaternion
        int32 quat_w; //2,000,000,000x quaternion
        int32 pos_x; //100,000x position
        int32 pos_y; //100,000x position
        int32 pos_z; //100,000x position
    }
 
    mapping(uint => build_position_data) private p_data_per_build;// building data
    mapping(uint => build_data) private data_per_building;// building data

	//BUILD/MINT
    function build(
        address b_owner,
        uint this_token_id,
        uint16 plot_id,
        uint16 mesh_id,
        uint8[] calldata all_uints8,
        bool[] calldata all_bools,
        int32[] calldata pos_data
    ) public BUILD_ROUTER_ONLY{
        require(b_owner != address(0),"cant be minted to null");
        require(token_ownership[this_token_id] == address(0),"token already exists");

        balance_per_owner[b_owner] += 1;
        token_ownership[this_token_id] = b_owner;
		
        data_per_building[this_token_id].plot_id = plot_id;
	    data_per_building[this_token_id].mesh_id = mesh_id;
		data_per_building[this_token_id].is_damaged = false;
		
		//ALL UINTS8
		data_per_building[this_token_id].b_type = all_uints8[0];
		data_per_building[this_token_id].top_unit_shell_rotation = all_uints8[1]; 
		data_per_building[this_token_id].color_id = all_uints8[2]; 
		data_per_building[this_token_id].color_scheme_id = all_uints8[3];
		data_per_building[this_token_id].style_by_claster = all_uints8[4]; 
		data_per_building[this_token_id].extra_cluster_randomizer_1 = all_uints8[5]; 
		data_per_building[this_token_id].extra_cluster_randomizer_2 = all_uints8[6];
		data_per_building[this_token_id].extra_cluster_randomizer_3 = all_uints8[7];
		
		//BOOLS
		data_per_building[this_token_id].buildable_on_top = all_bools[0];
	    data_per_building[this_token_id].is_ground = all_bools[1];
	    data_per_building[this_token_id].is_double_floor = all_bools[2];
	    data_per_building[this_token_id].is_base = all_bools[3];
		
		//POS DATA
        p_data_per_build[this_token_id].quat_x = pos_data[0]; 
        p_data_per_build[this_token_id].quat_y = pos_data[1]; 
        p_data_per_build[this_token_id].quat_z = pos_data[2]; 
        p_data_per_build[this_token_id].quat_w = pos_data[3];
        p_data_per_build[this_token_id].pos_x = pos_data[4]; 
        p_data_per_build[this_token_id].pos_y = pos_data[5]; 
        p_data_per_build[this_token_id].pos_z = pos_data[6]; 


        emit Transfer(address(0), b_owner, this_token_id);
		emit Build_event(this_token_id);
    }
	
	event Build_event(uint token_id);
	
	//return available token id
	function get_token_id(uint id_search_start,bool is_base)public view returns(uint){
		uint next_id;
		uint mutiplier = 1;
		if(is_base){
			mutiplier = 100000;
		}
		for (uint i = 1; i < 10000; i++) { 
			next_id = id_search_start + (mutiplier * i);
            if(token_ownership[next_id] == address(0)){
                return next_id;
            }
        }
	}

	//ALL COMBINED DATA
	function retrieve_all_building_data(uint this_token_id)public view returns(int32[7] memory,uint8[16] memory,uint16[2] memory,uint32[2] memory, uint,address,address){
		require(token_exists(this_token_id), "Token doesn't exist");

		return (
		[
            p_data_per_build[this_token_id].quat_x,
            p_data_per_build[this_token_id].quat_y,
            p_data_per_build[this_token_id].quat_z,
            p_data_per_build[this_token_id].quat_w,
            p_data_per_build[this_token_id].pos_x,
            p_data_per_build[this_token_id].pos_y,
            p_data_per_build[this_token_id].pos_z
        ],
        [
            data_per_building[this_token_id].b_type,
            data_per_building[this_token_id].top_unit_shell_rotation,
            data_per_building[this_token_id].color_id,
            data_per_building[this_token_id].color_scheme_id,
            data_per_building[this_token_id].style_by_claster,
            data_per_building[this_token_id].extra_cluster_randomizer_1,
            data_per_building[this_token_id].extra_cluster_randomizer_2,
            data_per_building[this_token_id].extra_cluster_randomizer_3,
			rent_data_by_token[this_token_id].rent_period, //end of uint8
			bool_to_uint8(data_per_building[this_token_id].buildable_on_top),
	        bool_to_uint8(data_per_building[this_token_id].is_ground),
	        bool_to_uint8(data_per_building[this_token_id].is_double_floor),
	        bool_to_uint8(data_per_building[this_token_id].is_base),
            bool_to_uint8(data_per_building[this_token_id].is_damaged),
			bool_to_uint8(rent_data_by_token[this_token_id].ever_listed),
			bool_to_uint8(rent_data_by_token[this_token_id].is_listed)
        ],
        [
            data_per_building[this_token_id].plot_id,
	        data_per_building[this_token_id].mesh_id
        ],
		[
            rent_data_by_token[this_token_id].rent_price,
			rent_data_by_token[this_token_id].rented_until
        ],
		sale_price_per_token[this_token_id],
		rent_data_by_token[this_token_id].renter_address,
		token_ownership[this_token_id]
        );
	}
	
	function bool_to_uint8(bool this_bool)private pure returns(uint8){
        if(this_bool){
            return 1;
        }
        else{
            return 0;
        }
    }
    
	
	//BURN particular buildings via router ,like walls 
    function burn_by_router(uint this_token_id, address burn_requester) public BUILD_ROUTER_ONLY{
        require(token_exists(this_token_id), "Token doesn't exist");
		require(is_burnable_by_router(this_token_id), "Cant be burned by router");
		burn_it(this_token_id,burn_requester);
    }
	//BURN buildings in ownership by owner
	function burn_by_owner(uint this_token_id)public{
		require(token_exists(this_token_id), "Token doesn't exist");
		require(is_owner(this_token_id,msg.sender), "Wrong owner");
		require(!is_in_rent(this_token_id), "Token in rent");
		require(nothing_on_top(this_token_id));
		require(base_has_no_nftbox(this_token_id));
		burn_it(this_token_id,msg.sender);
	}
	//burn finalize
	function burn_it(uint this_token_id,address burn_requester)internal{
		
		inner_approve(address(0), this_token_id);
		clean_rent_data(this_token_id);
		cleanup_sale_listing(this_token_id);
		balance_per_owner[burn_requester] -= 1;
		token_ownership[this_token_id] = address(0);
		
		emit Transfer(burn_requester, address(0), this_token_id);
	}
	
    //check if unit has nothing built on top
    function nothing_on_top(uint this_token_id)internal view returns(bool){
		if(data_per_building[this_token_id].buildable_on_top){
			uint top_token_id = this_token_id + 1;
			if(!token_exists(top_token_id)){
				return true;
			}
            else{
                return false;
            }
		}
		else{
			return true;
		}
    }
	//check if base has nft_box on top
	function base_has_no_nftbox(uint this_token_id)internal view returns(bool){
		if(data_per_building[this_token_id].is_base){
			uint nftbox_token_id = this_token_id + 99999;
			if(!token_exists(nftbox_token_id)){
				return true;
			}
			else{
				return false;
			}
		}
		else{
			return true;
		}
    }
	//check if belongs to walls
    function is_burnable_by_router(uint this_token_id)internal view returns(bool){
		uint8 this_b_type = data_per_building[this_token_id].b_type;
		return burnable_by_router_types[this_b_type];
	}


	//DAMAGE/REPAIR BUILDING
	function damage_repair_building(uint this_token_id,bool this_action)public BUILD_ROUTER_ONLY{
		require(token_exists(this_token_id), "Token doesn't exist");
		require(is_of_damageable_type(this_token_id),"Cant be damaged/repaired");
		
		data_per_building[this_token_id].is_damaged = this_action;
		
		emit damage_repair_event(this_token_id,this_action);
	}
	
	event damage_repair_event(uint token_id,bool is_damaged);
	
	function is_of_damageable_type(uint this_token_id)internal view returns(bool){
		uint8 this_b_type = data_per_building[this_token_id].b_type;
		return damageable_b_types[this_b_type];
	}


    ///...............................RENT FUNCTIONS
	
	struct rent_data{
		bool ever_listed; //set true on first listing
		bool is_listed; //yes no 
		uint32 rent_price;// max value 40000,00000 -- input in WEI converted to 1ETH/100000 (nukewei)
		uint8 rent_period; //rent period in days 1-250
		address renter_address; //160 bits
		uint32 rented_until; //timestamp
	}

	mapping(uint => rent_data) private rent_data_by_token; //all rent related data
	
	//RENT LISTING
	function list_for_rent(uint this_token_id, uint rent_price_in_wei, uint8 rent_period_in_days)public{
		require(token_exists(this_token_id), "Token doesn't exist");
		require(is_rentable(this_token_id),"Building type cant be rented");
		require(is_owner(this_token_id,msg.sender), "Wrong owner");
		require(rent_period_in_days>0 && rent_period_in_days<255, "Bad rent period");
		require(verify_rent_price_input(rent_price_in_wei), "Bad rent price");
		
		uint32 rent_price = uint32(rent_price_in_wei/nukewei);
		
		rent_data_by_token[this_token_id].ever_listed = true;
		rent_data_by_token[this_token_id].is_listed = true;
		rent_data_by_token[this_token_id].rent_price = rent_price;
		rent_data_by_token[this_token_id].rent_period = rent_period_in_days;
		
		emit rent_listing(this_token_id,rent_price_in_wei,rent_period_in_days);
	}
	
	
	//CANCEL RENT LISTING
	function cancel_rent_listing(uint this_token_id)public{
		require(token_exists(this_token_id), "Token doesn't exist");
		require(is_rentable(this_token_id),"Building type cant be rented");
		require(is_owner(this_token_id,msg.sender), "Wrong owner");
		
		rent_data_by_token[this_token_id].is_listed = false;
		rent_data_by_token[this_token_id].rent_price = 0;
		rent_data_by_token[this_token_id].rent_period = 0;
		
		emit cancel_rent_listing_event(this_token_id);
	}
	
	//clean rent data on transfer or burn
	function clean_rent_data(uint this_token_id)internal{
		if(rent_data_by_token[this_token_id].ever_listed){
			bool if_is_listed = rent_data_by_token[this_token_id].is_listed;
			rent_data_by_token[this_token_id].ever_listed=false;
			rent_data_by_token[this_token_id].is_listed=false; 
			rent_data_by_token[this_token_id].rent_price=0;
			rent_data_by_token[this_token_id].rent_period=0;
			rent_data_by_token[this_token_id].renter_address=address(0); 
			rent_data_by_token[this_token_id].rented_until=0; 
			if(if_is_listed){
				emit cancel_rent_listing_event(this_token_id);
			}
		}
	}
	
	//RENT UNIT
	function rent_unit(uint this_token_id)public payable{
		require(token_exists(this_token_id), "Token doesn't exist");
		require(is_rentable(this_token_id),"Building type cant be rented");
		require(!is_in_rent(this_token_id), "Token in rent");
		require(rent_data_by_token[this_token_id].is_listed, "Token not listed");
		require(!is_owner(this_token_id,msg.sender), "Owner cant rent to himself");
		require(rent_price_match(this_token_id,msg.value), "Wrong amount of ETC sent");
		
		address unit_owner = token_ownership[this_token_id];
        bool sent;
        bytes memory response;
		(sent,response) = unit_owner.call{value: msg.value}("");
        require(sent, "Failed to send ETC");
		
		uint8 rent_period = rent_data_by_token[this_token_id].rent_period;
		
		finalize_rent(this_token_id,msg.sender,rent_period);
		
		
	}
	
	//rent unit to someone forcefully
	function rent_to(uint this_token_id,address this_renter,uint8 rent_period_in_days) public{
		require(this_renter != address(0), "Cant rent to zero");
		require(this_renter != msg.sender, "Owner cant rent to himself");
		require(token_exists(this_token_id), "Token doesn't exist");
		require(is_rentable(this_token_id),"Building type cant be rented");
		require(!is_in_rent(this_token_id), "Token in rent");
		require(is_owner(this_token_id,msg.sender), "Bad ownership");
		require(rent_period_in_days>0 && rent_period_in_days<255, "Bad rent period");
		
		finalize_rent(this_token_id,this_renter,rent_period_in_days);
		
	}
	
	//internal rent finish
	function finalize_rent(uint this_token_id, address renter, uint8 rent_period)internal{
		uint32 rent_end_time = calculate_rent_end_time(rent_period);
		rent_data_by_token[this_token_id].ever_listed = true;
		rent_data_by_token[this_token_id].rented_until = rent_end_time;
		rent_data_by_token[this_token_id].renter_address = renter; 
		
		emit unit_rented(this_token_id, renter, rent_end_time);
	}
	
	event rent_listing(uint token_id,uint rent_price,uint8 rent_period);
	event cancel_rent_listing_event(uint token_id);
	event unit_rented(uint token_id, address renter_address, uint rented_until);

	function is_rentable(uint this_token_id) internal view returns(bool){
		uint8 this_b_type = data_per_building[this_token_id].b_type;
		return rentable_b_types[this_b_type];
	}
	function rent_price_match(uint this_token_id,uint this_amount)internal view returns(bool){
		if(this_amount>0 && rent_data_by_token[this_token_id].rent_price>0){
			uint32 nukewei_rent_price = uint32(this_amount/nukewei);
			if(nukewei_rent_price == rent_data_by_token[this_token_id].rent_price){
				return true;
			}
		}
        return false;
	}
	//get end of rent timestamp
	function calculate_rent_end_time(uint8 rent_period) internal view returns(uint32) {
		uint32 time_now = uint32(block.timestamp);
		uint32 cur_rent_period = uint32(rent_period);
		uint32 rent_period_in_seconds = uint32(cur_rent_period * 24 * 60 * 60);
		uint32 rented_until_time = time_now + rent_period_in_seconds;
		return rented_until_time;
	}
	//check if token is in rent
    function is_in_rent(uint this_token_id)public view returns(bool){
		if(rent_data_by_token[this_token_id].rented_until != 0){
			uint32 time_now = uint32(block.timestamp);
			if(rent_data_by_token[this_token_id].rented_until > time_now){
				return true;
			}
		}
        return false;
    }
    //check if price fits within uint32
	function verify_rent_price_input(uint rent_price_in_wei)internal view returns(bool){
		if(rent_price_in_wei>0){
			uint price_in_nukewei = rent_price_in_wei/nukewei;  //convert from wei to inner format of 1ETH/100000
			if(price_in_nukewei<4000000000){
				return true;
			}
		}
        return false;
	}
	
	//..............................MARKET FUNCTIONS
	

	mapping(uint => uint) private sale_price_per_token;
	
	//SALE LISTING
	function list_for_sale(uint this_token_id, uint sale_price) public{
		require(token_exists(this_token_id), "Token doesn't exist");
		require(is_owner(this_token_id,msg.sender), "Wrong owner");
        require(sale_price>0,"Bad price");
		sale_price_per_token[this_token_id] = sale_price;
		emit sale_listing(this_token_id,sale_price);
	}
	//SALE CANCEL
	function cancel_sale_listing(uint this_token_id)public{
		require(token_exists(this_token_id), "Token doesn't exist");
		require(is_owner(this_token_id,msg.sender), "Wrong owner");
		cleanup_sale_listing(this_token_id);
	}
	//internal cancel and cleanup
	function cleanup_sale_listing(uint this_token_id) internal{
		sale_price_per_token[this_token_id] = 0;
		emit cancel_sale_listing_event(this_token_id);
	}
	//BUY UNIT
	function buy_unit(uint this_token_id) public payable{
		require(token_exists(this_token_id), "Token doesn't exist");
		require(!is_owner(this_token_id,msg.sender), "Cant buy from yourself");
		require(sale_price_per_token[this_token_id] > 0,"Unit not listed for sale");
		require(!is_in_rent(this_token_id), "Token in rent");
		require(msg.value == sale_price_per_token[this_token_id],"Sale price mismatch");
		
		address this_token_owner = token_ownership[this_token_id];
        bool sent;
        bytes memory response;
		(sent, response) = this_token_owner.call{value: msg.value}("");
        require(sent, "Failed to send ETC");
		
		transfer_token(this_token_owner,msg.sender,this_token_id);
		
		emit sale_event(this_token_id, msg.value);
	}
	
	event sale_listing(uint token_id,uint sale_price);
	event cancel_sale_listing_event(uint token_id);
	event sale_event(uint token_id,uint sale_price);


	//..............................ADD DATA FUCTIONs
	
	//add remove wall type
	function add_remove_router_burnable_b_types(uint8 b_type,bool is_add)public CREATOR_ONLY{
		burnable_by_router_types[b_type] = is_add;
	}
	//add remove rentable types
	function add_remove_rentable_b_types(uint8 b_type,bool is_add)public CREATOR_ONLY{
		rentable_b_types[b_type] = is_add;
	}
	//add remove damageable_b_types
	function add_remove_damageable_b_types(uint8 b_type,bool is_add)public CREATOR_ONLY{
		damageable_b_types[b_type] = is_add;
	}
	
	//.............................MODIFIERS

    modifier CREATOR_ONLY {
        require(msg.sender == contract_creator,"must be creator"); 
        _;
    }
    modifier BUILD_ROUTER_ONLY {
		require(all_build_routers[msg.sender],"must be build_router");
        _;
    }
    


    //kinda ERC721 classics

    function name() external view returns (string memory){
        return token_name;
    }
    function symbol() external view returns (string memory){
        return token_symbol;
    }
    function tokenURI(uint this_token_id) external view returns (string memory){
        require(token_exists(this_token_id),"Token doesn't exist");
        string memory baseURI = base_uri;
        if(bytes(baseURI).length > 0){
            string memory string_token = toString(this_token_id);
            return string(abi.encodePacked(baseURI, string_token));
        }
        else{
            return "";
        }
    }
    function set_base_uri(string calldata this_base_uri)public CREATOR_ONLY{
        base_uri = this_base_uri;
    }

    //good
    function balanceOf(address this_owner) external view returns (uint256){
        require(this_owner != address(0), "Zero address has nothing in ownership");
        return balance_per_owner[this_owner];
    }

    //good
    function ownerOf(uint this_token_id) public view returns (address){
        address this_owner = token_ownership[this_token_id];
        require(this_owner != address(0), "Token doesn't exist");
        return this_owner;
    }

    //ERC721 pack of transfers
    function safeTransferFrom(address from, address to, uint this_token_id) public{
        safeTransferFrom(from, to, this_token_id, "");
    }
    function safeTransferFrom(address from, address to, uint this_token_id, bytes memory ) public{
        require(is_owner_or_approved(msg.sender, this_token_id),"not owner or approved");
		
        transfer_token(from, to, this_token_id);
    }
    function transferFrom( address from,address to,uint this_token_id) public {
        require(is_owner_or_approved(msg.sender, this_token_id),"not owner or approved");
        transfer_token(from, to, this_token_id);
    }

    //MAIN TRANSFER
    function transfer_token(address from,address to,uint this_token_id) internal {
		require(!is_in_rent(this_token_id), "Token in rent");
        require(ownerOf(this_token_id) == from, "bad owner");
        require(to != address(0), "no zero transfers");

        inner_approve(address(0), this_token_id); // Clear approvals from the previous owner
		clean_rent_data(this_token_id);
		cleanup_sale_listing(this_token_id);
		
        balance_per_owner[from] -= 1;
        balance_per_owner[to] += 1;
        token_ownership[this_token_id] = to;

        emit Transfer(from, to, this_token_id);
    }
    event Transfer(address indexed from, address indexed to, uint256 indexed token_id);

    //APPROVALS
    function approve(address to, uint this_token_id) public {
        address owner = ownerOf(this_token_id);
        require(to != owner, "cant approve to owner");
        require(msg.sender == owner || isApprovedForAll(owner,msg.sender), "sender is not owner nor approved for all");

        inner_approve(to, this_token_id);
    }
    function inner_approve(address to, uint this_token_id) internal {
		if(approval_per_token[this_token_id] != to){
			approval_per_token[this_token_id] = to;
			emit Approval(ownerOf(this_token_id), to, this_token_id);
		}
    }
    event Approval(address indexed owner, address indexed is_approved, uint256 indexed token_id);

    function setApprovalForAll(address operator, bool approved) public {
        require(msg.sender != operator, "cant approve to itself");
        operator_approvals[msg.sender][operator] = approved;
        emit ApprovalForAll(msg.sender, operator, approved);
    }
    event ApprovalForAll(address indexed owner, address indexed operator, bool is_approved);

    


    //Verify STF
    function is_owner_or_approved(address msg_sender, uint this_token_id) internal view returns (bool) {
        address this_owner = ownerOf(this_token_id);
        return (msg_sender == this_owner || isApprovedForAll(this_owner, msg_sender) || getApproved(this_token_id) == msg_sender);
    }
    function is_owner(uint this_token_id, address requester)internal view returns (bool){
        address this_owner = ownerOf(this_token_id);
        if(this_owner == requester){
            return true;
        }
        return false;
    }
    function isApprovedForAll(address this_owner, address operator) public view returns (bool) {
        return operator_approvals[this_owner][operator];
    }
    function getApproved(uint this_token_id) public view returns (address) {
        require(token_exists(this_token_id), "Token doesn't exist");
        return approval_per_token[this_token_id];
    }
    function token_exists(uint this_token_id) public view returns (bool) {
        return token_ownership[this_token_id] != address(0);
    }

    //...................................INTERFACES

    function supportsInterface(bytes4 interface_id) external pure returns (bool){
		return interface_id == 0x80ac58cd;
    }
    function onERC721Received(address ,address ,uint256 ,bytes calldata ) external pure returns (bytes4){
        return 0;
    }

    //..........................................UTILS
	
    function toString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }
}

contract bob{
	function transferFrom(address _from, address _to, uint256 _value) public {}
}
Contract ABI
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"is_approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"token_id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"is_approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"token_id","type":"uint256"}],"name":"Build_event","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"token_id","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"b_router","type":"address"},{"indexed":false,"internalType":"uint256","name":"bob_amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gas_amount","type":"uint256"}],"name":"build_request_event","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"token_id","type":"uint256"}],"name":"cancel_rent_listing_event","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"token_id","type":"uint256"}],"name":"cancel_sale_listing_event","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"token_id","type":"uint256"},{"indexed":false,"internalType":"bool","name":"is_damaged","type":"bool"}],"name":"damage_repair_event","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"token_id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rent_price","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"rent_period","type":"uint8"}],"name":"rent_listing","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"token_id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sale_price","type":"uint256"}],"name":"sale_event","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"token_id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sale_price","type":"uint256"}],"name":"sale_listing","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"token_id","type":"uint256"},{"indexed":false,"internalType":"address","name":"renter_address","type":"address"},{"indexed":false,"internalType":"uint256","name":"rented_until","type":"uint256"}],"name":"unit_rented","type":"event"},{"inputs":[{"internalType":"bool","name":"this_action","type":"bool"},{"internalType":"address[]","name":"those_addresses","type":"address[]"}],"name":"add_or_remove_build_routers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"b_type","type":"uint8"},{"internalType":"bool","name":"is_add","type":"bool"}],"name":"add_remove_damageable_b_types","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"b_type","type":"uint8"},{"internalType":"bool","name":"is_add","type":"bool"}],"name":"add_remove_rentable_b_types","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"b_type","type":"uint8"},{"internalType":"bool","name":"is_add","type":"bool"}],"name":"add_remove_router_burnable_b_types","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"this_token_id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"this_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"b_owner","type":"address"},{"internalType":"uint256","name":"this_token_id","type":"uint256"},{"internalType":"uint16","name":"plot_id","type":"uint16"},{"internalType":"uint16","name":"mesh_id","type":"uint16"},{"internalType":"uint8[]","name":"all_uints8","type":"uint8[]"},{"internalType":"bool[]","name":"all_bools","type":"bool[]"},{"internalType":"int32[]","name":"pos_data","type":"int32[]"}],"name":"build","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"build_router","type":"address"},{"internalType":"uint256","name":"bob_amount","type":"uint256"}],"name":"build_proxy_request","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"this_token_id","type":"uint256"}],"name":"burn_by_owner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"this_token_id","type":"uint256"},{"internalType":"address","name":"burn_requester","type":"address"}],"name":"burn_by_router","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"this_token_id","type":"uint256"}],"name":"buy_unit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"this_token_id","type":"uint256"}],"name":"cancel_rent_listing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"this_token_id","type":"uint256"}],"name":"cancel_sale_listing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"this_token_id","type":"uint256"},{"internalType":"bool","name":"this_action","type":"bool"}],"name":"damage_repair_building","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"this_token_id","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_search_start","type":"uint256"},{"internalType":"bool","name":"is_base","type":"bool"}],"name":"get_token_id","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"this_owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"this_token_id","type":"uint256"}],"name":"is_in_rent","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"this_token_id","type":"uint256"},{"internalType":"uint256","name":"rent_price_in_wei","type":"uint256"},{"internalType":"uint8","name":"rent_period_in_days","type":"uint8"}],"name":"list_for_rent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"this_token_id","type":"uint256"},{"internalType":"uint256","name":"sale_price","type":"uint256"}],"name":"list_for_sale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"this_token_id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"this_bob","type":"address"}],"name":"register_bob","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"this_token_id","type":"uint256"},{"internalType":"address","name":"this_renter","type":"address"},{"internalType":"uint8","name":"rent_period_in_days","type":"uint8"}],"name":"rent_to","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"this_token_id","type":"uint256"}],"name":"rent_unit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"this_token_id","type":"uint256"}],"name":"retrieve_all_building_data","outputs":[{"internalType":"int32[7]","name":"","type":"int32[7]"},{"internalType":"uint8[16]","name":"","type":"uint8[16]"},{"internalType":"uint16[2]","name":"","type":"uint16[2]"},{"internalType":"uint32[2]","name":"","type":"uint32[2]"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"this_token_id","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"this_token_id","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"this_base_uri","type":"string"}],"name":"set_base_uri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interface_id","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"this_token_id","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"this_token_id","type":"uint256"}],"name":"token_exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"this_token_id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]