Smart-Contract-Vulnerabilities-DB / Base Sample / call_to_uknown / call_to_unknow_4.sol
call_to_unknow_4.sol
Raw
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

contract TokenExchange {
    // Mapping of user addresses to their token balances
    mapping(address => uint256) private balances;
    
    // Reference to the TokenLibrary contract
    address public tokenLibrary;
    string public price;
    string public buy;
    string public sell;

    // Event emitted when tokens are bought
    event TokensBought(address indexed buyer, uint256 amount, uint256 cost);

    // Event emitted when tokens are sold
    event TokensSold(address indexed seller, uint256 amount, uint256 revenue);

    // Event emitted when the library is updated
    event LibraryUpdate(address indexed auth, address newLibAddress);

    // Constructor - Pass the address of the TokenLibrary contract during deployment
    constructor(address _tokenLibrary, string memory p, string memory b, string memory s) {
         tokenLibrary = _tokenLibrary;
         price = p;
         buy = b;
         sell = s;
    }

    // Function to buy tokens
    function buyTokens() external payable {
        // Call library to see how many tokens you cound buy
        (bool ok, bytes memory data) = tokenLibrary.call(abi.encodeWithSignature(price));
        require(ok, "Call failed");
        uint256 _price = uint256(bytes32(data));
        uint256 _amount = msg.value / _price;
        require(_amount > 0, "Insufficient funds to buy token");

        // Call library to buy tokens
        (ok, ) = tokenLibrary.call{value: _price*_amount}(abi.encodeWithSignature(buy, _amount));
        require(ok, "Call failed");

        // Update number of tokens that the user owns
        balances[msg.sender] += _amount;

        // Emit the TokensBought event
        emit TokensBought(msg.sender, _amount, _price);

        // Give back exchanges
        uint256 leftOver = msg.value - _price*_amount;
        if (leftOver > 0) {
            payable(msg.sender).transfer(leftOver);
        }
    }

    // Function to sell tokens
    function sellTokens(uint256 _amount) external {
        require(_amount <= balances[msg.sender], "Insufficient amount");

        // Contract balance before selling tokens
        uint256 temp = address(this).balance;

        // Call library to sell tokens
        (bool ok, ) = tokenLibrary.call(abi.encodeWithSignature(sell, _amount));
        require(ok, "Call failed");

        // Update number of tokens that the user owns
        balances[msg.sender] -= _amount;

        // Calculate revenue and transfer to seller
        uint256 revenue = address(this).balance - temp;
        payable(msg.sender).transfer(revenue);

        // Emit the TokensSold event
        emit TokensSold(msg.sender, _amount, revenue);
    }

    // Function to see token price
    function priceToken() external returns(uint256){
        (bool ok, bytes memory data) = tokenLibrary.call(abi.encodeWithSignature(price));
        require(ok, "Call failed");

        return (uint256(bytes32(data)));
    }

    // Function to get the user's token balance
    function getBalance() external view returns (uint256) {
        require(balances[msg.sender] > 0, "You don't have any tokens");
        return balances[msg.sender];
    }

    //Functions to update library settings
    function updateLibrary(address newLib) public returns(bool){
        tokenLibrary = newLib;
        emit LibraryUpdate(msg.sender, newLib);
        return true;
    }

    function updatePrice(string calldata newPrice) public returns(bool){
        price = newPrice;
        return true;
    }

    function updateBuy(string calldata newBuy) public returns(bool){
        buy = newBuy;
        return true;
    }

    function updatesell(string calldata newSell) public returns(bool){
        sell = newSell;
        return true;
    }
}

contract invOracle{
    uint256 public bought;
    uint256 public sold;

    receive() external payable {

    }
    
    function getPrice() public pure returns(uint256){
        return 1 ether;
    }

    function buy(uint256 _amt) public payable returns(bool){
        bought += _amt;
        return true;
    }

    function sell(uint256 _sll) public returns(bool){
        sold += _sll;
        return true;
    }
}

contract invOracleMalicious{
    invOracle InvOracle;

    constructor(address addr) {
        InvOracle = invOracle(payable(addr));
    }

    receive() external payable {

    }

    function getPrice() public pure returns(uint256){
        return 100 wei;
    }

    function buy(uint256 _amt) public payable returns(bool){
        InvOracle.buy(_amt);
        return true;
    }

    function sell(uint256 _sll) public returns(bool){
        InvOracle.sell(_sll);
        return true;
    }
}