add: PriceIndexQuote.sol

This commit is contained in:
Mohamed Sohail 2023-12-13 09:55:12 +00:00
commit 7cdea201ac

117
PriceIndexQuote.sol Normal file
View File

@ -0,0 +1,117 @@
/**
*Submitted for verification at celoscan.io on 2023-12-12
*/
pragma solidity ^0.8.0;
// Author: Louis Holbrook <dev@holbrook.no> 0826EDA1702D1E87C6E2875121D2E7BB88C2A746
// Author: Mohamed Sohail <sohail@grassecon.org>
// 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;
}
}