From 7cdea201acf9338780f2e1200701501efe83c162 Mon Sep 17 00:00:00 2001 From: Mohamed Sohail Date: Wed, 13 Dec 2023 09:55:12 +0000 Subject: [PATCH] add: PriceIndexQuote.sol --- PriceIndexQuote.sol | 117 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 PriceIndexQuote.sol diff --git a/PriceIndexQuote.sol b/PriceIndexQuote.sol new file mode 100644 index 0000000..1c386eb --- /dev/null +++ b/PriceIndexQuote.sol @@ -0,0 +1,117 @@ +/** + *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; + } +} \ No newline at end of file