/** *Submitted for verification at celoscan.io on 2023-12-12 */ pragma solidity ^0.8.0; // Author: Louis Holbrook 0826EDA1702D1E87C6E2875121D2E7BB88C2A746 // Author: Mohamed Sohail // SPDX-License-Identifier: AGPL-3.0-or-later // File-Version: 1 // Description: ACL-enabled ERC20 token swap quoter that queries a price index for the latest exchange rates. contract PriceIndexQuote { // Implements EIP173 address public owner; // consts uint256 constant EXCHANGE_RATE_PRECISION = 10 ** 4; mapping(address => uint256) public priceIndex; event PriceIndexUpdated(address _tokenAddress, uint256 _exchangeRate); // Implements ERC173 event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); constructor() { owner = msg.sender; } function setPriceIndexValue( address _tokenAddress, uint256 _exchangeRate ) public returns (uint256) { require(owner == msg.sender, "ERR_NOT_OWNER"); priceIndex[_tokenAddress] = _exchangeRate; emit PriceIndexUpdated(_tokenAddress, _exchangeRate); return _exchangeRate; } // Implements TokenQuote function valueFor( address _outToken, address _inToken, uint256 _value ) public returns (uint256) { uint8 dout; uint8 din; bool r; bytes memory v; uint256 exchangeRate = priceIndex[_inToken] > 0 ? priceIndex[_inToken] : priceIndex[_outToken]; (r, v) = _outToken.call(abi.encodeWithSignature("decimals()")); require(r, "ERR_TOKEN_OUT"); dout = abi.decode(v, (uint8)); (r, v) = _inToken.call(abi.encodeWithSignature("decimals()")); require(r, "ERR_TOKEN_IN"); din = abi.decode(v, (uint8)); if (din == dout) { uint256 x = _value; if (exchangeRate > 0) { x = (x * exchangeRate) / EXCHANGE_RATE_PRECISION; } return x; } uint256 d = din > dout ? 10 ** ((din - dout)) : 10 ** ((dout - din)); if (din > dout) { uint256 x = _value / d; if (exchangeRate > 0) { x = (x * exchangeRate) / EXCHANGE_RATE_PRECISION; } return x; } else { uint256 x = _value * d; if (exchangeRate > 0) { x = (x / exchangeRate) * EXCHANGE_RATE_PRECISION; } return x; } } // Implements EIP173 function transferOwnership(address _newOwner) public returns (bool) { address oldOwner; require(msg.sender == owner, "ERR_AXX"); oldOwner = owner; owner = _newOwner; emit OwnershipTransferred(oldOwner, owner); return true; } // Implements EIP165 function supportsInterface(bytes4 _sum) public pure returns (bool) { if (_sum == 0x01ffc9a7) { // ERC165 return true; } if (_sum == 0x9493f8b2) { // ERC173 return true; } if (_sum == 0xdbb21d40) { // TokenQuote return true; } return false; } }