diff --git a/contracts/common/UsingRegistry.sol b/contracts/common/UsingRegistry.sol new file mode 100644 index 0000000..1ff264b --- /dev/null +++ b/contracts/common/UsingRegistry.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.5.13; + +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; + +import "celo/contracts/common/interfaces/IFreezer.sol"; +import "celo/contracts/common/interfaces/IRegistry.sol"; + +import "../interfaces/IExchange.sol"; +import "../interfaces/IStableTokenV2.sol"; +import "../interfaces/IReserve.sol"; +import "../interfaces/ISortedOracles.sol"; + +contract UsingRegistry is Ownable { + event RegistrySet(address indexed registryAddress); + + // solhint-disable state-visibility + bytes32 constant ACCOUNTS_REGISTRY_ID = keccak256(abi.encodePacked("Accounts")); + bytes32 constant ATTESTATIONS_REGISTRY_ID = keccak256(abi.encodePacked("Attestations")); + bytes32 constant DOWNTIME_SLASHER_REGISTRY_ID = keccak256(abi.encodePacked("DowntimeSlasher")); + bytes32 constant DOUBLE_SIGNING_SLASHER_REGISTRY_ID = keccak256(abi.encodePacked("DoubleSigningSlasher")); + bytes32 constant ELECTION_REGISTRY_ID = keccak256(abi.encodePacked("Election")); + bytes32 constant EXCHANGE_REGISTRY_ID = keccak256(abi.encodePacked("Exchange")); + bytes32 constant FEE_CURRENCY_WHITELIST_REGISTRY_ID = keccak256(abi.encodePacked("FeeCurrencyWhitelist")); + bytes32 constant FREEZER_REGISTRY_ID = keccak256(abi.encodePacked("Freezer")); + bytes32 constant GOLD_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("GoldToken")); + bytes32 constant GOVERNANCE_REGISTRY_ID = keccak256(abi.encodePacked("Governance")); + bytes32 constant GOVERNANCE_SLASHER_REGISTRY_ID = keccak256(abi.encodePacked("GovernanceSlasher")); + bytes32 constant LOCKED_GOLD_REGISTRY_ID = keccak256(abi.encodePacked("LockedGold")); + bytes32 constant RESERVE_REGISTRY_ID = keccak256(abi.encodePacked("Reserve")); + bytes32 constant RANDOM_REGISTRY_ID = keccak256(abi.encodePacked("Random")); + bytes32 constant SORTED_ORACLES_REGISTRY_ID = keccak256(abi.encodePacked("SortedOracles")); + bytes32 constant STABLE_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("StableToken")); + bytes32 constant VALIDATORS_REGISTRY_ID = keccak256(abi.encodePacked("Validators")); + // solhint-enable state-visibility + + IRegistry public registry; + + modifier onlyRegisteredContract(bytes32 identifierHash) { + require(registry.getAddressForOrDie(identifierHash) == msg.sender, "only registered contract"); + _; + } + + modifier onlyRegisteredContracts(bytes32[] memory identifierHashes) { + require(registry.isOneOf(identifierHashes, msg.sender), "only registered contracts"); + _; + } + + /** + * @notice Updates the address pointing to a Registry contract. + * @param registryAddress The address of a registry contract for routing to other contracts. + */ + function setRegistry(address registryAddress) public onlyOwner { + require(registryAddress != address(0), "Cannot register the null address"); + registry = IRegistry(registryAddress); + emit RegistrySet(registryAddress); + } + + function getExchange() internal view returns (IExchange) { + return IExchange(registry.getAddressForOrDie(EXCHANGE_REGISTRY_ID)); + } + + function getFreezer() internal view returns (IFreezer) { + return IFreezer(registry.getAddressForOrDie(FREEZER_REGISTRY_ID)); + } + + function getGoldToken() internal view returns (IERC20) { + return IERC20(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID)); + } + + function getReserve() internal view returns (IReserve) { + return IReserve(registry.getAddressForOrDie(RESERVE_REGISTRY_ID)); + } + + function getSortedOracles() internal view returns (ISortedOracles) { + return ISortedOracles(registry.getAddressForOrDie(SORTED_ORACLES_REGISTRY_ID)); + } + + function getStableToken() internal view returns (IStableTokenV2) { + return IStableTokenV2(registry.getAddressForOrDie(STABLE_TOKEN_REGISTRY_ID)); + } +} diff --git a/contracts/interfaces/IBreakerBox.sol b/contracts/interfaces/IBreakerBox.sol new file mode 100644 index 0000000..f74b7d0 --- /dev/null +++ b/contracts/interfaces/IBreakerBox.sol @@ -0,0 +1,232 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity >0.5.13 <0.9; +pragma experimental ABIEncoderV2; + +import { ISortedOracles } from "./ISortedOracles.sol"; + +/** + * @title Breaker Box Interface + * @notice Defines the basic interface for the Breaker Box + */ +interface IBreakerBox { + /** + * @dev Used to keep track of the status of a breaker for a specific rate feed. + * + * - TradingMode: Represents the trading mode the breaker is in for a rate feed. + * This uses a bitmask approach, meaning each bit represents a + * different trading mode. The final trading mode of the rate feed + * is obtained by applying a logical OR operation to the TradingMode + * of all breakers associated with that rate feed. This allows multiple + * breakers to contribute to the final trading mode simultaneously. + * Possible values: + * 0: bidirectional trading. + * 1: inflow only. + * 2: outflow only. + * 3: trading halted. + * + * - LastUpdatedTime: Records the last time the breaker status was updated. This is + * used to manage cooldown periods before the breaker can be reset. + * + * - Enabled: Indicates whether the breaker is enabled for the associated rate feed. + */ + struct BreakerStatus { + uint8 tradingMode; + uint64 lastUpdatedTime; + bool enabled; + } + + /** + * @notice Emitted when a new breaker is added to the breaker box. + * @param breaker The address of the breaker. + */ + event BreakerAdded(address indexed breaker); + + /** + * @notice Emitted when a breaker is removed from the breaker box. + * @param breaker The address of the breaker. + */ + event BreakerRemoved(address indexed breaker); + + /** + * @notice Emitted when a breaker is tripped by a rate feed. + * @param breaker The address of the breaker. + * @param rateFeedID The address of the rate feed. + */ + event BreakerTripped(address indexed breaker, address indexed rateFeedID); + + /** + * @notice Emitted when a new rate feed is added to the breaker box. + * @param rateFeedID The address of the rate feed. + */ + event RateFeedAdded(address indexed rateFeedID); + + /** + * @notice Emitted when dependencies for a rate feed are set. + * @param rateFeedID The address of the rate feed. + * @param dependencies The addresses of the dependendent rate feeds. + */ + event RateFeedDependenciesSet(address indexed rateFeedID, address[] indexed dependencies); + + /** + * @notice Emitted when a rate feed is removed from the breaker box. + * @param rateFeedID The address of the rate feed. + */ + event RateFeedRemoved(address indexed rateFeedID); + + /** + * @notice Emitted when the trading mode for a rate feed is updated + * @param rateFeedID The address of the rate feed. + * @param tradingMode The new trading mode. + */ + event TradingModeUpdated(address indexed rateFeedID, uint256 tradingMode); + + /** + * @notice Emitted after a reset attempt is successful. + * @param rateFeedID The address of the rate feed. + * @param breaker The address of the breaker. + */ + event ResetSuccessful(address indexed rateFeedID, address indexed breaker); + + /** + * @notice Emitted after a reset attempt fails when the + * rate feed fails the breakers reset criteria. + * @param rateFeedID The address of the rate feed. + * @param breaker The address of the breaker. + */ + event ResetAttemptCriteriaFail(address indexed rateFeedID, address indexed breaker); + + /** + * @notice Emitted after a reset attempt fails when cooldown time has not elapsed. + * @param rateFeedID The address of the rate feed. + * @param breaker The address of the breaker. + */ + event ResetAttemptNotCool(address indexed rateFeedID, address indexed breaker); + + /** + * @notice Emitted when the sortedOracles address is updated. + * @param newSortedOracles The address of the new sortedOracles. + */ + event SortedOraclesUpdated(address indexed newSortedOracles); + + /** + * @notice Emitted when the breaker is enabled or disabled for a rate feed. + * @param breaker The address of the breaker. + * @param rateFeedID The address of the rate feed. + * @param status Indicating the status. + */ + event BreakerStatusUpdated(address breaker, address rateFeedID, bool status); + + /** + * @notice Retrives an array of all breaker addresses. + */ + function getBreakers() external view returns (address[] memory); + + /** + * @notice Checks if a breaker with the specified address has been added to the breaker box. + * @param breaker The address of the breaker to check; + * @return A bool indicating whether or not the breaker has been added. + */ + function isBreaker(address breaker) external view returns (bool); + + /** + * @notice Checks breakers for the rateFeedID and sets correct trading mode + * if any breakers are tripped or need to be reset. + * @param rateFeedID The address of the rate feed to run checks for. + */ + function checkAndSetBreakers(address rateFeedID) external; + + /** + * @notice Gets the trading mode for the specified rateFeedID. + * @param rateFeedID The address of the rate feed to retrieve the trading mode for. + */ + function getRateFeedTradingMode(address rateFeedID) external view returns (uint8 tradingMode); + + /** + * @notice Adds a breaker to the end of the list of breakers & the breakerTradingMode mapping. + * @param breaker The address of the breaker to be added. + * @param tradingMode The trading mode of the breaker to be added. + */ + function addBreaker(address breaker, uint8 tradingMode) external; + + /** + * @notice Removes the specified breaker from the list of breakers + * and resets breakerTradingMode mapping + BreakerStatus. + * @param breaker The address of the breaker to be removed. + */ + function removeBreaker(address breaker) external; + + /** + * @notice Enables or disables a breaker for the specified rate feed. + * @param breakerAddress The address of the breaker. + * @param rateFeedID The address of the rateFeed to be toggled. + * @param enable Boolean indicating whether the breaker should be + * enabled or disabled for the given rateFeed. + */ + function toggleBreaker(address breakerAddress, address rateFeedID, bool enable) external; + + /** + * @notice Adds a rateFeedID to the mapping of monitored rateFeedIDs. + * @param rateFeedID The address of the rateFeed to be added. + */ + function addRateFeed(address rateFeedID) external; + + /** + * @notice Adds the specified rateFeedIDs to the mapping of monitored rateFeedIDs. + * @param newRateFeedIDs The array of rateFeed addresses to be added. + */ + function addRateFeeds(address[] calldata newRateFeedIDs) external; + + /** + * @notice Sets dependent rate feeds for a given rate feed. + * @param rateFeedID The address of the rate feed. + * @param dependencies The array of dependent rate feeds. + */ + function setRateFeedDependencies(address rateFeedID, address[] calldata dependencies) external; + + /** + * @notice Removes a rateFeed from the mapping of monitored rateFeeds + * and resets all the BreakerStatus entries for that rateFeed. + * @param rateFeedID The address of the rateFeed to be removed. + */ + function removeRateFeed(address rateFeedID) external; + + /** + * @notice Sets the trading mode for the specified rateFeed. + * @param rateFeedID The address of the rateFeed. + * @param tradingMode The trading mode that should be set. + */ + function setRateFeedTradingMode(address rateFeedID, uint8 tradingMode) external; + + /** + * @notice Returns addresses of rateFeedIDs that have been added. + */ + function getRateFeeds() external view returns (address[] memory); + + /** + * @notice Checks if a breaker is enabled for a specific rate feed. + * @param breaker The address of the breaker we're checking for. + * @param rateFeedID The address of the rateFeed. + */ + function isBreakerEnabled(address breaker, address rateFeedID) external view returns (bool); + + /** + * @notice Sets the address of the sortedOracles contract. + * @param _sortedOracles The new address of the sorted oracles contract. + */ + function setSortedOracles(ISortedOracles _sortedOracles) external; + + /// @notice Public state variable getters: + function breakerTradingMode(address) external view returns (uint8); + + function sortedOracles() external view returns (address); + + function rateFeedStatus(address) external view returns (bool); + + function owner() external view returns (address); + + function rateFeedBreakerStatus(address, address) external view returns (BreakerStatus memory); + + function rateFeedDependencies(address, uint256) external view returns (address); + + function rateFeedTradingMode(address) external view returns (uint8); +} diff --git a/contracts/interfaces/IExchange.sol b/contracts/interfaces/IExchange.sol new file mode 100644 index 0000000..6e18611 --- /dev/null +++ b/contracts/interfaces/IExchange.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.5.13; + +interface IExchange { + function buy(uint256, uint256, bool) external returns (uint256); + + function sell(uint256, uint256, bool) external returns (uint256); + + function exchange(uint256, uint256, bool) external returns (uint256); + + function setUpdateFrequency(uint256) external; + + function getBuyTokenAmount(uint256, bool) external view returns (uint256); + + function getSellTokenAmount(uint256, bool) external view returns (uint256); + + function getBuyAndSellBuckets(bool) external view returns (uint256, uint256); +} diff --git a/contracts/interfaces/ISortedOracles.sol b/contracts/interfaces/ISortedOracles.sol new file mode 100644 index 0000000..2a57852 --- /dev/null +++ b/contracts/interfaces/ISortedOracles.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity >0.5.13 <0.9; + +import { IBreakerBox } from "./IBreakerBox.sol"; + +interface ISortedOracles { + enum MedianRelation { + Undefined, + Lesser, + Greater, + Equal + } + + function addOracle(address, address) external; + + function removeOracle(address, address, uint256) external; + + function report(address, uint256, address, address) external; + + function removeExpiredReports(address, uint256) external; + + function isOldestReportExpired(address token) external view returns (bool, address); + + function numRates(address) external view returns (uint256); + + function medianRate(address) external view returns (uint256, uint256); + + function numTimestamps(address) external view returns (uint256); + + function medianTimestamp(address) external view returns (uint256); + + function getOracles(address) external view returns (address[] memory); + + function getRates(address token) external view returns (address[] memory, uint256[] memory, MedianRelation[] memory); + + function getTimestamps( + address token + ) external view returns (address[] memory, uint256[] memory, MedianRelation[] memory); + + function initialize(uint256) external; + + function setBreakerBox(IBreakerBox) external; + + function getTokenReportExpirySeconds(address token) external view returns (uint256); + + function oracles(address, uint256) external view returns (address); + + function breakerBox() external view returns (IBreakerBox); +} diff --git a/contracts/swap/Reserve.sol b/contracts/swap/Reserve.sol index 918e938..397801a 100644 --- a/contracts/swap/Reserve.sol +++ b/contracts/swap/Reserve.sol @@ -19,734 +19,937 @@ import "contracts/interfaces/ISortedOracles.sol"; * @title Ensures price stability of StableTokens with respect to their pegs */ // solhint-disable-next-line max-states-count -contract Reserve is IReserve, ICeloVersionedContract, Ownable, Initializable, UsingRegistry, ReentrancyGuard { - using SafeMath for uint256; - using FixidityLib for FixidityLib.Fraction; - using Address for address payable; // prettier-ignore - using SafeERC20 for IERC20; - - struct TobinTaxCache { - uint128 numerator; - uint128 timestamp; - } - - mapping(address => bool) public isToken; - address[] private _tokens; - TobinTaxCache public tobinTaxCache; - uint256 public tobinTaxStalenessThreshold; - uint256 public tobinTax; - uint256 public tobinTaxReserveRatio; - mapping(address => bool) public isSpender; - - mapping(address => bool) public isOtherReserveAddress; - address[] public otherReserveAddresses; - - bytes32[] public assetAllocationSymbols; - mapping(bytes32 => uint256) public assetAllocationWeights; - - uint256 public lastSpendingDay; - uint256 public spendingLimit; - FixidityLib.Fraction private spendingRatio; - - uint256 public frozenReserveGoldStartBalance; - uint256 public frozenReserveGoldStartDay; - uint256 public frozenReserveGoldDays; - - mapping(address => bool) public isExchangeSpender; - address[] public exchangeSpenderAddresses; - mapping(address => FixidityLib.Fraction) private collateralAssetDailySpendingRatio; - mapping(address => uint256) public collateralAssetLastSpendingDay; - address[] public collateralAssets; - mapping(address => bool) public isCollateralAsset; - mapping(address => uint256) public collateralAssetSpendingLimit; - - event TobinTaxStalenessThresholdSet(uint256 value); - event DailySpendingRatioSet(uint256 ratio); - event TokenAdded(address indexed token); - event TokenRemoved(address indexed token, uint256 index); - event SpenderAdded(address indexed spender); - event SpenderRemoved(address indexed spender); - event OtherReserveAddressAdded(address indexed otherReserveAddress); - event OtherReserveAddressRemoved(address indexed otherReserveAddress, uint256 index); - event AssetAllocationSet(bytes32[] symbols, uint256[] weights); - event ReserveGoldTransferred(address indexed spender, address indexed to, uint256 value); - event TobinTaxSet(uint256 value); - event TobinTaxReserveRatioSet(uint256 value); - event ExchangeSpenderAdded(address indexed exchangeSpender); - event ExchangeSpenderRemoved(address indexed exchangeSpender); - event DailySpendingRatioForCollateralAssetSet(address collateralAsset, uint256 collateralAssetDailySpendingRatios); - event ReserveCollateralAssetsTransferred(address indexed spender, address indexed to, uint256 value, address token); - event CollateralAssetRemoved(address collateralAsset); - event CollateralAssetAdded(address collateralAsset); - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - modifier isStableToken(address token) { - require(isToken[token], "token addr was never registered"); - _; - } - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (2, 1, 0, 0); - } - - function() external payable {} // solhint-disable no-empty-blocks - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - * @param registryAddress The address of the registry core smart contract. - * @param _tobinTaxStalenessThreshold The initial number of seconds to cache tobin tax value for. - * @param _spendingRatioForCelo The relative daily spending limit for the reserve spender. - * @param _frozenGold The balance of reserve gold that is frozen. - * @param _frozenDays The number of days during which the frozen gold thaws. - * @param _assetAllocationSymbols The symbols of the reserve assets. - * @param _assetAllocationWeights The reserve asset weights. - * @param _tobinTax The tobin tax value as a fixidity fraction. - * @param _tobinTaxReserveRatio When to turn on the tobin tax, as a fixidity fraction. - * @param _collateralAssets The relative daily spending limit - * of an ERC20 collateral asset for the reserve spender. - * @param _collateralAssetDailySpendingRatios The address of an ERC20 collateral asset - */ - function initialize( - address registryAddress, - uint256 _tobinTaxStalenessThreshold, - uint256 _spendingRatioForCelo, - uint256 _frozenGold, - uint256 _frozenDays, - bytes32[] calldata _assetAllocationSymbols, - uint256[] calldata _assetAllocationWeights, - uint256 _tobinTax, - uint256 _tobinTaxReserveRatio, - address[] calldata _collateralAssets, - uint256[] calldata _collateralAssetDailySpendingRatios - ) external initializer { - _transferOwnership(msg.sender); - setRegistry(registryAddress); - setTobinTaxStalenessThreshold(_tobinTaxStalenessThreshold); - setDailySpendingRatio(_spendingRatioForCelo); - setFrozenGold(_frozenGold, _frozenDays); - setAssetAllocations(_assetAllocationSymbols, _assetAllocationWeights); - setTobinTax(_tobinTax); - setTobinTaxReserveRatio(_tobinTaxReserveRatio); - for (uint256 i = 0; i < _collateralAssets.length; i++) { - addCollateralAsset(_collateralAssets[i]); - } - setDailySpendingRatioForCollateralAssets(_collateralAssets, _collateralAssetDailySpendingRatios); - } - - /** - * @notice Sets the number of seconds to cache the tobin tax value for. - * @param value The number of seconds to cache the tobin tax value for. - */ - function setTobinTaxStalenessThreshold(uint256 value) public onlyOwner { - require(value > 0, "value was zero"); - tobinTaxStalenessThreshold = value; - emit TobinTaxStalenessThresholdSet(value); - } - - /** - * @notice Sets the tobin tax. - * @param value The tobin tax. - */ - function setTobinTax(uint256 value) public onlyOwner { - require(FixidityLib.wrap(value).lte(FixidityLib.fixed1()), "tobin tax cannot be larger than 1"); - tobinTax = value; - emit TobinTaxSet(value); - } - - /** - * @notice Sets the reserve ratio at which the tobin tax sets in. - * @param value The reserve ratio at which the tobin tax sets in. - */ - function setTobinTaxReserveRatio(uint256 value) public onlyOwner { - tobinTaxReserveRatio = value; - emit TobinTaxReserveRatioSet(value); - } - - /** - * @notice Set the ratio of reserve that is spendable per day. - * @param ratio Spending ratio as unwrapped Fraction. - */ - function setDailySpendingRatio(uint256 ratio) public onlyOwner { - spendingRatio = FixidityLib.wrap(ratio); - require(spendingRatio.lte(FixidityLib.fixed1()), "spending ratio cannot be larger than 1"); - emit DailySpendingRatioSet(ratio); - } - - /** - * @notice Set the ratio of reserve for a given collateral asset - * that is spendable per day. - * @param _collateralAssets Collection of the addresses of collateral assets - * we're setting a limit for. - * @param collateralAssetDailySpendingRatios Collection of the relative daily spending limits - * of collateral assets. - */ - function setDailySpendingRatioForCollateralAssets( - address[] memory _collateralAssets, - uint256[] memory collateralAssetDailySpendingRatios - ) public onlyOwner { - require( - _collateralAssets.length == collateralAssetDailySpendingRatios.length, - "token addresses and spending ratio lengths have to be the same" +contract Reserve is + IReserve, + ICeloVersionedContract, + Ownable, + Initializable, + UsingRegistry, + ReentrancyGuard +{ + using SafeMath for uint256; + using FixidityLib for FixidityLib.Fraction; + using Address for address payable; // prettier-ignore + using SafeERC20 for IERC20; + + struct TobinTaxCache { + uint128 numerator; + uint128 timestamp; + } + + mapping(address => bool) public isToken; + address[] private _tokens; + TobinTaxCache public tobinTaxCache; + uint256 public tobinTaxStalenessThreshold; + uint256 public tobinTax; + uint256 public tobinTaxReserveRatio; + mapping(address => bool) public isSpender; + + mapping(address => bool) public isOtherReserveAddress; + address[] public otherReserveAddresses; + + bytes32[] public assetAllocationSymbols; + mapping(bytes32 => uint256) public assetAllocationWeights; + + uint256 public lastSpendingDay; + uint256 public spendingLimit; + FixidityLib.Fraction private spendingRatio; + + uint256 public frozenReserveGoldStartBalance; + uint256 public frozenReserveGoldStartDay; + uint256 public frozenReserveGoldDays; + + mapping(address => bool) public isExchangeSpender; + address[] public exchangeSpenderAddresses; + mapping(address => FixidityLib.Fraction) + private collateralAssetDailySpendingRatio; + mapping(address => uint256) public collateralAssetLastSpendingDay; + address[] public collateralAssets; + mapping(address => bool) public isCollateralAsset; + mapping(address => uint256) public collateralAssetSpendingLimit; + + event TobinTaxStalenessThresholdSet(uint256 value); + event DailySpendingRatioSet(uint256 ratio); + event TokenAdded(address indexed token); + event TokenRemoved(address indexed token, uint256 index); + event SpenderAdded(address indexed spender); + event SpenderRemoved(address indexed spender); + event OtherReserveAddressAdded(address indexed otherReserveAddress); + event OtherReserveAddressRemoved( + address indexed otherReserveAddress, + uint256 index + ); + event AssetAllocationSet(bytes32[] symbols, uint256[] weights); + event ReserveGoldTransferred( + address indexed spender, + address indexed to, + uint256 value + ); + event TobinTaxSet(uint256 value); + event TobinTaxReserveRatioSet(uint256 value); + event ExchangeSpenderAdded(address indexed exchangeSpender); + event ExchangeSpenderRemoved(address indexed exchangeSpender); + event DailySpendingRatioForCollateralAssetSet( + address collateralAsset, + uint256 collateralAssetDailySpendingRatios + ); + event ReserveCollateralAssetsTransferred( + address indexed spender, + address indexed to, + uint256 value, + address token ); - for (uint256 i = 0; i < _collateralAssets.length; i++) { - if (_collateralAssets[i] != address(0) && collateralAssetDailySpendingRatios[i] != 0) { + event CollateralAssetRemoved(address collateralAsset); + event CollateralAssetAdded(address collateralAsset); + + /** + * @notice Sets initialized == true on implementation contracts + * @param test Set to true to skip implementation initialization + */ + constructor(bool test) public Initializable(test) {} + + modifier isStableToken(address token) { + require(isToken[token], "token addr was never registered"); + _; + } + + /** + * @notice Returns the storage, major, minor, and patch version of the contract. + * @return Storage version of the contract. + * @return Major version of the contract. + * @return Minor version of the contract. + * @return Patch version of the contract. + */ + function getVersionNumber() + external + pure + returns (uint256, uint256, uint256, uint256) + { + return (2, 1, 0, 0); + } + + function() external payable {} // solhint-disable no-empty-blocks + + /** + * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. + * @param registryAddress The address of the registry core smart contract. + * @param _tobinTaxStalenessThreshold The initial number of seconds to cache tobin tax value for. + * @param _spendingRatioForCelo The relative daily spending limit for the reserve spender. + * @param _frozenGold The balance of reserve gold that is frozen. + * @param _frozenDays The number of days during which the frozen gold thaws. + * @param _assetAllocationSymbols The symbols of the reserve assets. + * @param _assetAllocationWeights The reserve asset weights. + * @param _tobinTax The tobin tax value as a fixidity fraction. + * @param _tobinTaxReserveRatio When to turn on the tobin tax, as a fixidity fraction. + * @param _collateralAssets The relative daily spending limit + * of an ERC20 collateral asset for the reserve spender. + * @param _collateralAssetDailySpendingRatios The address of an ERC20 collateral asset + */ + function initialize( + address registryAddress, + uint256 _tobinTaxStalenessThreshold, + uint256 _spendingRatioForCelo, + uint256 _frozenGold, + uint256 _frozenDays, + bytes32[] calldata _assetAllocationSymbols, + uint256[] calldata _assetAllocationWeights, + uint256 _tobinTax, + uint256 _tobinTaxReserveRatio, + address[] calldata _collateralAssets, + uint256[] calldata _collateralAssetDailySpendingRatios + ) external initializer { + _transferOwnership(msg.sender); + setRegistry(registryAddress); + setTobinTaxStalenessThreshold(_tobinTaxStalenessThreshold); + setDailySpendingRatio(_spendingRatioForCelo); + setFrozenGold(_frozenGold, _frozenDays); + setAssetAllocations(_assetAllocationSymbols, _assetAllocationWeights); + setTobinTax(_tobinTax); + setTobinTaxReserveRatio(_tobinTaxReserveRatio); + for (uint256 i = 0; i < _collateralAssets.length; i++) { + addCollateralAsset(_collateralAssets[i]); + } + setDailySpendingRatioForCollateralAssets( + _collateralAssets, + _collateralAssetDailySpendingRatios + ); + } + + /** + * @notice Sets the number of seconds to cache the tobin tax value for. + * @param value The number of seconds to cache the tobin tax value for. + */ + function setTobinTaxStalenessThreshold(uint256 value) public onlyOwner { + require(value > 0, "value was zero"); + tobinTaxStalenessThreshold = value; + emit TobinTaxStalenessThresholdSet(value); + } + + /** + * @notice Sets the tobin tax. + * @param value The tobin tax. + */ + function setTobinTax(uint256 value) public onlyOwner { require( - checkIsCollateralAsset(_collateralAssets[i]), - "the address specified is not a reserve collateral asset" + FixidityLib.wrap(value).lte(FixidityLib.fixed1()), + "tobin tax cannot be larger than 1" ); + tobinTax = value; + emit TobinTaxSet(value); + } + + /** + * @notice Sets the reserve ratio at which the tobin tax sets in. + * @param value The reserve ratio at which the tobin tax sets in. + */ + function setTobinTaxReserveRatio(uint256 value) public onlyOwner { + tobinTaxReserveRatio = value; + emit TobinTaxReserveRatioSet(value); + } + + /** + * @notice Set the ratio of reserve that is spendable per day. + * @param ratio Spending ratio as unwrapped Fraction. + */ + function setDailySpendingRatio(uint256 ratio) public onlyOwner { + spendingRatio = FixidityLib.wrap(ratio); require( - FixidityLib.wrap(collateralAssetDailySpendingRatios[i]).lte(FixidityLib.fixed1()), - "spending ratio cannot be larger than 1" + spendingRatio.lte(FixidityLib.fixed1()), + "spending ratio cannot be larger than 1" ); - collateralAssetDailySpendingRatio[_collateralAssets[i]] = FixidityLib.wrap( - collateralAssetDailySpendingRatios[i] + emit DailySpendingRatioSet(ratio); + } + + /** + * @notice Set the ratio of reserve for a given collateral asset + * that is spendable per day. + * @param _collateralAssets Collection of the addresses of collateral assets + * we're setting a limit for. + * @param collateralAssetDailySpendingRatios Collection of the relative daily spending limits + * of collateral assets. + */ + function setDailySpendingRatioForCollateralAssets( + address[] memory _collateralAssets, + uint256[] memory collateralAssetDailySpendingRatios + ) public onlyOwner { + require( + _collateralAssets.length == + collateralAssetDailySpendingRatios.length, + "token addresses and spending ratio lengths have to be the same" ); - emit DailySpendingRatioForCollateralAssetSet(_collateralAssets[i], collateralAssetDailySpendingRatios[i]); - } - } - } - - /** - * @notice Get daily spending ratio. - * @return Spending ratio as unwrapped Fraction. - */ - function getDailySpendingRatio() public view returns (uint256) { - return spendingRatio.unwrap(); - } - - /** - * @notice Get daily spending ratio of a collateral asset. - * @param collateralAsset The address of a collateral asset we're getting a spending ratio for. - * @return Daily spending ratio for the collateral asset as unwrapped Fraction. - */ - function getDailySpendingRatioForCollateralAsset(address collateralAsset) public view returns (uint256) { - return collateralAssetDailySpendingRatio[collateralAsset].unwrap(); - } - - /** - * @notice Sets the balance of reserve gold frozen from transfer. - * @param frozenGold The amount of CELO frozen. - * @param frozenDays The number of days the frozen CELO thaws over. - */ - function setFrozenGold(uint256 frozenGold, uint256 frozenDays) public onlyOwner { - require(frozenGold <= address(this).balance, "Cannot freeze more than balance"); - frozenReserveGoldStartBalance = frozenGold; - // slither-disable-start events-maths - frozenReserveGoldStartDay = now / 1 days; - frozenReserveGoldDays = frozenDays; - // slither-disable-end events-maths - } - - /** - * @notice Sets target allocations for CELO and a diversified basket of non-Celo assets. - * @param symbols The symbol of each asset in the Reserve portfolio. - * @param weights The weight for the corresponding asset as unwrapped Fixidity.Fraction. - */ - function setAssetAllocations(bytes32[] memory symbols, uint256[] memory weights) public onlyOwner { - require(symbols.length == weights.length, "Array length mismatch"); - FixidityLib.Fraction memory sum = FixidityLib.wrap(0); - for (uint256 i = 0; i < weights.length; i = i.add(1)) { - sum = sum.add(FixidityLib.wrap(weights[i])); - } - require(sum.equals(FixidityLib.fixed1()), "Sum of asset allocation must be 1"); - // slither-disable-next-line cache-array-length - for (uint256 i = 0; i < assetAllocationSymbols.length; i = i.add(1)) { - delete assetAllocationWeights[assetAllocationSymbols[i]]; - } - assetAllocationSymbols = symbols; - for (uint256 i = 0; i < symbols.length; i = i.add(1)) { - require(assetAllocationWeights[symbols[i]] == 0, "Cannot set weight twice"); - assetAllocationWeights[symbols[i]] = weights[i]; - } - // NOTE: The CELO asset launched as "Celo Gold" (cGLD), but was renamed to - // just CELO by the community. - // TODO: Change "cGLD" to "CELO" in this file, after ensuring that any - // off chain tools working with asset allocation weights are aware of this - // change. - require(assetAllocationWeights["cGLD"] != 0, "Must set cGLD asset weight"); - emit AssetAllocationSet(symbols, weights); - } - - /** - * @notice Add a token that the reserve will stabilize. - * @param token The address of the token being stabilized. - * @return Returns true if the transaction succeeds. - */ - function addToken(address token) external onlyOwner returns (bool) { - require(!isToken[token], "token addr already registered"); - isToken[token] = true; - _tokens.push(token); - emit TokenAdded(token); - return true; - } - - /** - * @notice Remove a token that the reserve will no longer stabilize. - * @param token The address of the token no longer being stabilized. - * @param index The index of the token in _tokens. - * @return Returns true if the transaction succeeds. - */ - function removeToken(address token, uint256 index) external onlyOwner isStableToken(token) returns (bool) { - require(index < _tokens.length && _tokens[index] == token, "index into tokens list not mapped to token"); - isToken[token] = false; - address lastItem = _tokens[_tokens.length.sub(1)]; - _tokens[index] = lastItem; - _tokens.length = _tokens.length.sub(1); - emit TokenRemoved(token, index); - return true; - } - - /** - * @notice Add a reserve address whose balance shall be included in the reserve ratio. - * @param reserveAddress The reserve address to add. - * @return Returns true if the transaction succeeds. - */ - function addOtherReserveAddress(address reserveAddress) external onlyOwner returns (bool) { - require(!isOtherReserveAddress[reserveAddress], "reserve addr already added"); - isOtherReserveAddress[reserveAddress] = true; - otherReserveAddresses.push(reserveAddress); - emit OtherReserveAddressAdded(reserveAddress); - return true; - } - - /** - * @notice Remove reserve address whose balance shall no longer be included in the reserve ratio. - * @param reserveAddress The reserve address to remove. - * @param index The index of the reserve address in otherReserveAddresses. - * @return Returns true if the transaction succeeds. - */ - function removeOtherReserveAddress(address reserveAddress, uint256 index) external onlyOwner returns (bool) { - require(isOtherReserveAddress[reserveAddress], "reserve addr was never added"); - require( - index < otherReserveAddresses.length && otherReserveAddresses[index] == reserveAddress, - "index into reserve list not mapped to address" - ); - isOtherReserveAddress[reserveAddress] = false; - address lastItem = otherReserveAddresses[otherReserveAddresses.length.sub(1)]; - otherReserveAddresses[index] = lastItem; - otherReserveAddresses.length = otherReserveAddresses.length.sub(1); - emit OtherReserveAddressRemoved(reserveAddress, index); - return true; - } - - /** - * @notice Gives an address permission to spend Reserve funds. - * @param spender The address that is allowed to spend Reserve funds. - */ - function addSpender(address spender) external onlyOwner { - require(address(0) != spender, "Spender can't be null"); - isSpender[spender] = true; - emit SpenderAdded(spender); - } - - /** - * @notice Takes away an address's permission to spend Reserve funds. - * @param spender The address that is to be no longer allowed to spend Reserve funds. - */ - function removeSpender(address spender) external onlyOwner { - require(isSpender[spender], "Spender hasn't been added"); - isSpender[spender] = false; - emit SpenderRemoved(spender); - } - - /** - * @notice Checks if an address is able to spend as an exchange. - * @dev isExchangeSpender was introduced after cUSD, so the cUSD Exchange is not included in it. - * If cUSD's Exchange were to be added to isExchangeSpender, the check with the - * registry could be removed. - * @param spender The address to be checked. - */ - modifier isAllowedToSpendExchange(address spender) { - require( - isExchangeSpender[spender] || (registry.getAddressForOrDie(EXCHANGE_REGISTRY_ID) == spender), - "Address not allowed to spend" - ); - _; - } - - /** - * @notice Gives an address permission to spend Reserve without limit. - * @param spender The address that is allowed to spend Reserve funds. - */ - function addExchangeSpender(address spender) external onlyOwner { - require(address(0) != spender, "Spender can't be null"); - require(!isExchangeSpender[spender], "Address is already Exchange Spender"); - isExchangeSpender[spender] = true; - exchangeSpenderAddresses.push(spender); - emit ExchangeSpenderAdded(spender); - } - - /** - * @notice Takes away an address's permission to spend Reserve funds without limits. - * @param spender The address that is to be no longer allowed to spend Reserve funds. - * @param index The index in exchangeSpenderAddresses of spender. - */ - function removeExchangeSpender(address spender, uint256 index) external onlyOwner { - isExchangeSpender[spender] = false; - uint256 numAddresses = exchangeSpenderAddresses.length; - require(index < numAddresses, "Index is invalid"); - require(spender == exchangeSpenderAddresses[index], "Index does not match spender"); - uint256 newNumAddresses = numAddresses.sub(1); - - if (index != newNumAddresses) { - exchangeSpenderAddresses[index] = exchangeSpenderAddresses[newNumAddresses]; - } - - exchangeSpenderAddresses[newNumAddresses] = address(0x0); - exchangeSpenderAddresses.length = newNumAddresses; - emit ExchangeSpenderRemoved(spender); - } - - /** - * @notice Returns addresses of exchanges permitted to spend Reserve funds. - * Because exchangeSpenderAddresses was introduced after cUSD, cUSD's exchange - * is not included in this list. - * @return An array of addresses permitted to spend Reserve funds. - */ - function getExchangeSpenders() external view returns (address[] memory) { - return exchangeSpenderAddresses; - } - - /** - * @notice Transfer gold to a whitelisted address subject to reserve spending limits. - * @param to The address that will receive the gold. - * @param value The amount of gold to transfer. - * @return Returns true if the transaction succeeds. - */ - function transferGold(address payable to, uint256 value) external returns (bool) { - require(isSpender[msg.sender], "sender not allowed to transfer Reserve funds"); - require(isOtherReserveAddress[to], "can only transfer to other reserve address"); - uint256 currentDay = now / 1 days; - if (currentDay > lastSpendingDay) { - uint256 balance = getUnfrozenReserveGoldBalance(); - lastSpendingDay = currentDay; - spendingLimit = spendingRatio.multiply(FixidityLib.newFixed(balance)).fromFixed(); - } - require(spendingLimit >= value, "Exceeding spending limit"); - spendingLimit = spendingLimit.sub(value); - return _transferGold(to, value); - } - - /** - * @notice Transfer collateral asset subject to reserve spending limits to the trader, - * if the limit is set, othersise the limit is 100%. - * @param collateralAsset The token address you're transferring. - * @param to The address that will receive the funds. - * @param value The amount of collateral assets to transfer. - * @return Returns true if the transaction succeeds. - */ - function transferCollateralAsset(address collateralAsset, address payable to, uint256 value) external returns (bool) { - require(isSpender[msg.sender], "sender not allowed to transfer Reserve funds"); - require(isOtherReserveAddress[to], "can only transfer to other reserve address"); - require( - getDailySpendingRatioForCollateralAsset(collateralAsset) > 0, - "this asset has no spending ratio, therefore can't be transferred" - ); - uint256 currentDay = now / 1 days; - if (currentDay > collateralAssetLastSpendingDay[collateralAsset]) { - uint256 balance = getReserveAddressesCollateralAssetBalance(collateralAsset); - collateralAssetLastSpendingDay[collateralAsset] = currentDay; - collateralAssetSpendingLimit[collateralAsset] = collateralAssetDailySpendingRatio[collateralAsset] - .multiply(FixidityLib.newFixed(balance)) - .fromFixed(); - } - uint256 spendingLimitForThisAsset = collateralAssetSpendingLimit[collateralAsset]; - require(spendingLimitForThisAsset >= value, "Exceeding spending limit"); - - collateralAssetSpendingLimit[collateralAsset] = spendingLimitForThisAsset.sub(value); - return _transferCollateralAsset(collateralAsset, to, value); - } - - /** - * @notice Transfer collateral asset to any address. - * @param collateralAsset The token address you're transferring. - * @param to The address that will receive the funds. - * @param value The amount of collateral assets to transfer. - * @return Returns true if the transaction succeeds. - */ - function _transferCollateralAsset( - address collateralAsset, - address payable to, - uint256 value - ) internal returns (bool) { - require(value <= getReserveAddressesCollateralAssetBalance(collateralAsset), "Exceeding the amount reserve holds"); - // slither-disable-next-line reentrancy-events - IERC20(collateralAsset).safeTransfer(to, value); - emit ReserveCollateralAssetsTransferred(msg.sender, to, value, collateralAsset); - return true; - } - - /** - * @notice Transfer collateral asset to any address. - * @dev Transfers are not subject to a daily spending limit. - * @param collateralAsset The address of collateral asset being transferred. - * @param to The address that will receive the collateral asset. - * @param value The amount of collateral asset to transfer. - * @return Returns true if the transaction succeeds. - */ - function transferExchangeCollateralAsset( - address collateralAsset, - address payable to, - uint256 value - ) external returns (bool) { - require(isExchangeSpender[msg.sender], "Address not allowed to spend"); - return _transferCollateralAsset(collateralAsset, to, value); - } - - /** - * @notice Transfer unfrozen gold to any address. - * @param to The address that will receive the gold. - * @param value The amount of gold to transfer. - * @return Returns true if the transaction succeeds. - */ - function _transferGold(address payable to, uint256 value) internal returns (bool) { - require(value <= getUnfrozenBalance(), "Exceeding unfrozen reserves"); - // slither-disable-next-line reentrancy-events - to.sendValue(value); - emit ReserveGoldTransferred(msg.sender, to, value); - return true; - } - - /** - * @notice Transfer unfrozen gold to any address, used for one side of CP-DOTO. - * @dev Transfers are not subject to a daily spending limit. - * @param to The address that will receive the gold. - * @param value The amount of gold to transfer. - * @return Returns true if the transaction succeeds. - */ - function transferExchangeGold( - address payable to, - uint256 value - ) external isAllowedToSpendExchange(msg.sender) returns (bool) { - return _transferGold(to, value); - } - - /** - * @notice Returns the tobin tax, recomputing it if it's stale. - * @return The numerator - tobin tax amount as a fraction. - * @return The denominator - tobin tax amount as a fraction. - */ - function getOrComputeTobinTax() external nonReentrant returns (uint256, uint256) { - // solhint-disable-next-line not-rely-on-time - if (now.sub(tobinTaxCache.timestamp) > tobinTaxStalenessThreshold) { - tobinTaxCache.numerator = uint128(computeTobinTax().unwrap()); - tobinTaxCache.timestamp = uint128(now); // solhint-disable-line not-rely-on-time - } - return (uint256(tobinTaxCache.numerator), FixidityLib.fixed1().unwrap()); - } - - /** - * @notice Returns the list of stabilized token addresses. - * @return An array of addresses of stabilized tokens. - */ - function getTokens() external view returns (address[] memory) { - return _tokens; - } - - /** - * @notice Returns the list other addresses included in the reserve total. - * @return An array of other addresses included in the reserve total. - */ - function getOtherReserveAddresses() external view returns (address[] memory) { - return otherReserveAddresses; - } - - /** - * @notice Returns a list of token symbols that have been allocated. - * @return An array of token symbols that have been allocated. - */ - function getAssetAllocationSymbols() external view returns (bytes32[] memory) { - return assetAllocationSymbols; - } - - /** - * @notice Returns a list of weights used for the allocation of reserve assets. - * @return An array of a list of weights used for the allocation of reserve assets. - */ - function getAssetAllocationWeights() external view returns (uint256[] memory) { - uint256[] memory weights = new uint256[](assetAllocationSymbols.length); - // slither-disable-next-line cache-array-length - for (uint256 i = 0; i < assetAllocationSymbols.length; i = i.add(1)) { - weights[i] = assetAllocationWeights[assetAllocationSymbols[i]]; - } - return weights; - } - - /** - * @notice Returns the amount of unfrozen CELO in the reserve. - * @return The total unfrozen CELO in the reserve. - */ - function getUnfrozenBalance() public view returns (uint256) { - uint256 balance = address(this).balance; - uint256 frozenReserveGold = getFrozenReserveGoldBalance(); - return balance > frozenReserveGold ? balance.sub(frozenReserveGold) : 0; - } - - /** - * @notice Returns the amount of CELO included in the reserve. - * @return The CELO amount included in the reserve. - */ - function getReserveGoldBalance() public view returns (uint256) { - return address(this).balance.add(getOtherReserveAddressesGoldBalance()); - } - - /** - * @notice Returns the amount of CELO included in other reserve addresses. - * @return The CELO amount included in other reserve addresses. - */ - function getOtherReserveAddressesGoldBalance() public view returns (uint256) { - uint256 reserveGoldBalance = 0; - // slither-disable-next-line cache-array-length - for (uint256 i = 0; i < otherReserveAddresses.length; i = i.add(1)) { - reserveGoldBalance = reserveGoldBalance.add(otherReserveAddresses[i].balance); - } - return reserveGoldBalance; - } - - /** - * @notice Returns the amount of unfrozen CELO included in the reserve. - * @return The unfrozen CELO amount included in the reserve. - */ - function getUnfrozenReserveGoldBalance() public view returns (uint256) { - return getUnfrozenBalance().add(getOtherReserveAddressesGoldBalance()); - } - - /** - * @notice Returns the amount of particular collateral asset - * in reserve including other reserve addresses. - * @param collateralAsset the asset we're checking a balance of - * @return The balance of particular collateral asset. - */ - function getReserveAddressesCollateralAssetBalance(address collateralAsset) public view returns (uint256) { - require(checkIsCollateralAsset(collateralAsset), "specified address is not a collateral asset"); - uint256 reserveCollateralAssetBalance = 0; - // slither-disable-next-line cache-array-length - for (uint256 i = 0; i < otherReserveAddresses.length; i++) { - // slither-disable-next-line calls-loop - reserveCollateralAssetBalance = reserveCollateralAssetBalance.add( - IERC20(collateralAsset).balanceOf(otherReserveAddresses[i]) - ); - } - return reserveCollateralAssetBalance.add(IERC20(collateralAsset).balanceOf(address(this))); - } - - /** - * @notice Add a collateral asset in the reserve. - * @param collateralAsset The address of the token being added. - * @return Returns true if the transaction succeeds. - */ - function addCollateralAsset(address collateralAsset) public onlyOwner returns (bool) { - require(!checkIsCollateralAsset(collateralAsset), "specified address is already added as a collateral asset"); - require(collateralAsset != address(0), "can't be a zero address"); - isCollateralAsset[collateralAsset] = true; - collateralAssets.push(collateralAsset); - emit CollateralAssetAdded(collateralAsset); - return true; - } - - /** - * @notice Remove a collateral asset in the reserve. - * @param collateralAsset The address of the token being removed. - * @param index The index of the token being removed. - * @return Returns true if the transaction succeeds. - */ - function removeCollateralAsset(address collateralAsset, uint256 index) external onlyOwner returns (bool) { - require(checkIsCollateralAsset(collateralAsset), "specified address is not a collateral asset"); - require( - index < collateralAssets.length && collateralAssets[index] == collateralAsset, - "index into collateralAssets list not mapped to token" - ); - collateralAssets[index] = collateralAssets[collateralAssets.length.sub(1)]; - collateralAssets.pop(); - delete isCollateralAsset[collateralAsset]; - emit CollateralAssetRemoved(collateralAsset); - return true; - } - - /** - * @notice Check if a collateral asset is added to the reserve. - * @param collateralAsset The address of the token being checked. - * @return Returns true if the token was added as a collateral asset. - */ - function checkIsCollateralAsset(address collateralAsset) public view returns (bool) { - return isCollateralAsset[collateralAsset]; - } - - /** - * @notice Returns the amount of frozen CELO in the reserve. - * @return The total frozen CELO in the reserve. - */ - function getFrozenReserveGoldBalance() public view returns (uint256) { - uint256 currentDay = now / 1 days; - uint256 frozenDays = currentDay.sub(frozenReserveGoldStartDay); - if (frozenDays >= frozenReserveGoldDays) return 0; - return frozenReserveGoldStartBalance.sub(frozenReserveGoldStartBalance.mul(frozenDays).div(frozenReserveGoldDays)); - } - - /** - * @notice Computes the ratio of current reserve balance to total stable token valuation. - * @return Reserve ratio in a fixed point format. - */ - function getReserveRatio() public view returns (uint256) { - address sortedOraclesAddress = registry.getAddressForOrDie(SORTED_ORACLES_REGISTRY_ID); - ISortedOracles sortedOracles = ISortedOracles(sortedOraclesAddress); - uint256 reserveGoldBalance = getUnfrozenReserveGoldBalance(); - uint256 stableTokensValueInGold = 0; - FixidityLib.Fraction memory cgldWeight = FixidityLib.wrap(assetAllocationWeights["cGLD"]); - - // slither-disable-next-line cache-array-length - for (uint256 i = 0; i < _tokens.length; i = i.add(1)) { - uint256 stableAmount; - uint256 goldAmount; - // slither-disable-next-line calls-loop - (stableAmount, goldAmount) = sortedOracles.medianRate(_tokens[i]); - - if (goldAmount != 0) { - // tokens with no oracle reports don't count towards collateralization ratio - // slither-disable-next-line calls-loop - uint256 stableTokenSupply = IERC20(_tokens[i]).totalSupply(); - uint256 aStableTokenValueInGold = stableTokenSupply.mul(goldAmount).div(stableAmount); - stableTokensValueInGold = stableTokensValueInGold.add(aStableTokenValueInGold); - } - } - return - FixidityLib - .newFixed(reserveGoldBalance) - .divide(cgldWeight) - .divide(FixidityLib.newFixed(stableTokensValueInGold)) - .unwrap(); - } - - /* - * Internal functions - */ - - /** - * @notice Computes a tobin tax based on the reserve ratio. - * @return The tobin tax expresesed as a fixidity fraction. - */ - function computeTobinTax() private view returns (FixidityLib.Fraction memory) { - FixidityLib.Fraction memory ratio = FixidityLib.wrap(getReserveRatio()); - if (ratio.gte(FixidityLib.wrap(tobinTaxReserveRatio))) { - return FixidityLib.wrap(0); - } else { - return FixidityLib.wrap(tobinTax); - } - } - - function isStableAsset(address token) external view returns (bool) { - return isToken[token]; - } + for (uint256 i = 0; i < _collateralAssets.length; i++) { + if ( + _collateralAssets[i] != address(0) && + collateralAssetDailySpendingRatios[i] != 0 + ) { + require( + checkIsCollateralAsset(_collateralAssets[i]), + "the address specified is not a reserve collateral asset" + ); + require( + FixidityLib.wrap(collateralAssetDailySpendingRatios[i]).lte( + FixidityLib.fixed1() + ), + "spending ratio cannot be larger than 1" + ); + collateralAssetDailySpendingRatio[ + _collateralAssets[i] + ] = FixidityLib.wrap(collateralAssetDailySpendingRatios[i]); + emit DailySpendingRatioForCollateralAssetSet( + _collateralAssets[i], + collateralAssetDailySpendingRatios[i] + ); + } + } + } + + /** + * @notice Get daily spending ratio. + * @return Spending ratio as unwrapped Fraction. + */ + function getDailySpendingRatio() public view returns (uint256) { + return spendingRatio.unwrap(); + } + + /** + * @notice Get daily spending ratio of a collateral asset. + * @param collateralAsset The address of a collateral asset we're getting a spending ratio for. + * @return Daily spending ratio for the collateral asset as unwrapped Fraction. + */ + function getDailySpendingRatioForCollateralAsset( + address collateralAsset + ) public view returns (uint256) { + return collateralAssetDailySpendingRatio[collateralAsset].unwrap(); + } + + /** + * @notice Sets the balance of reserve gold frozen from transfer. + * @param frozenGold The amount of CELO frozen. + * @param frozenDays The number of days the frozen CELO thaws over. + */ + function setFrozenGold( + uint256 frozenGold, + uint256 frozenDays + ) public onlyOwner { + require( + frozenGold <= address(this).balance, + "Cannot freeze more than balance" + ); + frozenReserveGoldStartBalance = frozenGold; + // slither-disable-start events-maths + frozenReserveGoldStartDay = now / 1 days; + frozenReserveGoldDays = frozenDays; + // slither-disable-end events-maths + } + + /** + * @notice Sets target allocations for CELO and a diversified basket of non-Celo assets. + * @param symbols The symbol of each asset in the Reserve portfolio. + * @param weights The weight for the corresponding asset as unwrapped Fixidity.Fraction. + */ + function setAssetAllocations( + bytes32[] memory symbols, + uint256[] memory weights + ) public onlyOwner { + require(symbols.length == weights.length, "Array length mismatch"); + FixidityLib.Fraction memory sum = FixidityLib.wrap(0); + for (uint256 i = 0; i < weights.length; i = i.add(1)) { + sum = sum.add(FixidityLib.wrap(weights[i])); + } + require( + sum.equals(FixidityLib.fixed1()), + "Sum of asset allocation must be 1" + ); + // slither-disable-next-line cache-array-length + for (uint256 i = 0; i < assetAllocationSymbols.length; i = i.add(1)) { + delete assetAllocationWeights[assetAllocationSymbols[i]]; + } + assetAllocationSymbols = symbols; + for (uint256 i = 0; i < symbols.length; i = i.add(1)) { + require( + assetAllocationWeights[symbols[i]] == 0, + "Cannot set weight twice" + ); + assetAllocationWeights[symbols[i]] = weights[i]; + } + // NOTE: The CELO asset launched as "Celo Gold" (cGLD), but was renamed to + // just CELO by the community. + // TODO: Change "cGLD" to "CELO" in this file, after ensuring that any + // off chain tools working with asset allocation weights are aware of this + // change. + require( + assetAllocationWeights["cGLD"] != 0, + "Must set cGLD asset weight" + ); + emit AssetAllocationSet(symbols, weights); + } + + /** + * @notice Add a token that the reserve will stabilize. + * @param token The address of the token being stabilized. + * @return Returns true if the transaction succeeds. + */ + function addToken(address token) external onlyOwner returns (bool) { + require(!isToken[token], "token addr already registered"); + isToken[token] = true; + _tokens.push(token); + emit TokenAdded(token); + return true; + } + + /** + * @notice Remove a token that the reserve will no longer stabilize. + * @param token The address of the token no longer being stabilized. + * @param index The index of the token in _tokens. + * @return Returns true if the transaction succeeds. + */ + function removeToken( + address token, + uint256 index + ) external onlyOwner isStableToken(token) returns (bool) { + require( + index < _tokens.length && _tokens[index] == token, + "index into tokens list not mapped to token" + ); + isToken[token] = false; + address lastItem = _tokens[_tokens.length.sub(1)]; + _tokens[index] = lastItem; + _tokens.length = _tokens.length.sub(1); + emit TokenRemoved(token, index); + return true; + } + + /** + * @notice Add a reserve address whose balance shall be included in the reserve ratio. + * @param reserveAddress The reserve address to add. + * @return Returns true if the transaction succeeds. + */ + function addOtherReserveAddress( + address reserveAddress + ) external onlyOwner returns (bool) { + require( + !isOtherReserveAddress[reserveAddress], + "reserve addr already added" + ); + isOtherReserveAddress[reserveAddress] = true; + otherReserveAddresses.push(reserveAddress); + emit OtherReserveAddressAdded(reserveAddress); + return true; + } + + /** + * @notice Remove reserve address whose balance shall no longer be included in the reserve ratio. + * @param reserveAddress The reserve address to remove. + * @param index The index of the reserve address in otherReserveAddresses. + * @return Returns true if the transaction succeeds. + */ + function removeOtherReserveAddress( + address reserveAddress, + uint256 index + ) external onlyOwner returns (bool) { + require( + isOtherReserveAddress[reserveAddress], + "reserve addr was never added" + ); + require( + index < otherReserveAddresses.length && + otherReserveAddresses[index] == reserveAddress, + "index into reserve list not mapped to address" + ); + isOtherReserveAddress[reserveAddress] = false; + address lastItem = otherReserveAddresses[ + otherReserveAddresses.length.sub(1) + ]; + otherReserveAddresses[index] = lastItem; + otherReserveAddresses.length = otherReserveAddresses.length.sub(1); + emit OtherReserveAddressRemoved(reserveAddress, index); + return true; + } + + /** + * @notice Gives an address permission to spend Reserve funds. + * @param spender The address that is allowed to spend Reserve funds. + */ + function addSpender(address spender) external onlyOwner { + require(address(0) != spender, "Spender can't be null"); + isSpender[spender] = true; + emit SpenderAdded(spender); + } + + /** + * @notice Takes away an address's permission to spend Reserve funds. + * @param spender The address that is to be no longer allowed to spend Reserve funds. + */ + function removeSpender(address spender) external onlyOwner { + require(isSpender[spender], "Spender hasn't been added"); + isSpender[spender] = false; + emit SpenderRemoved(spender); + } + + /** + * @notice Checks if an address is able to spend as an exchange. + * @dev isExchangeSpender was introduced after cUSD, so the cUSD Exchange is not included in it. + * If cUSD's Exchange were to be added to isExchangeSpender, the check with the + * registry could be removed. + * @param spender The address to be checked. + */ + modifier isAllowedToSpendExchange(address spender) { + require( + isExchangeSpender[spender] || + (registry.getAddressForOrDie(EXCHANGE_REGISTRY_ID) == spender), + "Address not allowed to spend" + ); + _; + } + + /** + * @notice Gives an address permission to spend Reserve without limit. + * @param spender The address that is allowed to spend Reserve funds. + */ + function addExchangeSpender(address spender) external onlyOwner { + require(address(0) != spender, "Spender can't be null"); + require( + !isExchangeSpender[spender], + "Address is already Exchange Spender" + ); + isExchangeSpender[spender] = true; + exchangeSpenderAddresses.push(spender); + emit ExchangeSpenderAdded(spender); + } + + /** + * @notice Takes away an address's permission to spend Reserve funds without limits. + * @param spender The address that is to be no longer allowed to spend Reserve funds. + * @param index The index in exchangeSpenderAddresses of spender. + */ + function removeExchangeSpender( + address spender, + uint256 index + ) external onlyOwner { + isExchangeSpender[spender] = false; + uint256 numAddresses = exchangeSpenderAddresses.length; + require(index < numAddresses, "Index is invalid"); + require( + spender == exchangeSpenderAddresses[index], + "Index does not match spender" + ); + uint256 newNumAddresses = numAddresses.sub(1); + + if (index != newNumAddresses) { + exchangeSpenderAddresses[index] = exchangeSpenderAddresses[ + newNumAddresses + ]; + } + + exchangeSpenderAddresses[newNumAddresses] = address(0x0); + exchangeSpenderAddresses.length = newNumAddresses; + emit ExchangeSpenderRemoved(spender); + } + + /** + * @notice Returns addresses of exchanges permitted to spend Reserve funds. + * Because exchangeSpenderAddresses was introduced after cUSD, cUSD's exchange + * is not included in this list. + * @return An array of addresses permitted to spend Reserve funds. + */ + function getExchangeSpenders() external view returns (address[] memory) { + return exchangeSpenderAddresses; + } + + /** + * @notice Transfer gold to a whitelisted address subject to reserve spending limits. + * @param to The address that will receive the gold. + * @param value The amount of gold to transfer. + * @return Returns true if the transaction succeeds. + */ + function transferGold( + address payable to, + uint256 value + ) external returns (bool) { + require( + isSpender[msg.sender], + "sender not allowed to transfer Reserve funds" + ); + require( + isOtherReserveAddress[to], + "can only transfer to other reserve address" + ); + uint256 currentDay = now / 1 days; + if (currentDay > lastSpendingDay) { + uint256 balance = getUnfrozenReserveGoldBalance(); + lastSpendingDay = currentDay; + spendingLimit = spendingRatio + .multiply(FixidityLib.newFixed(balance)) + .fromFixed(); + } + require(spendingLimit >= value, "Exceeding spending limit"); + spendingLimit = spendingLimit.sub(value); + return _transferGold(to, value); + } + + /** + * @notice Transfer collateral asset subject to reserve spending limits to the trader, + * if the limit is set, othersise the limit is 100%. + * @param collateralAsset The token address you're transferring. + * @param to The address that will receive the funds. + * @param value The amount of collateral assets to transfer. + * @return Returns true if the transaction succeeds. + */ + function transferCollateralAsset( + address collateralAsset, + address payable to, + uint256 value + ) external returns (bool) { + require( + isSpender[msg.sender], + "sender not allowed to transfer Reserve funds" + ); + require( + isOtherReserveAddress[to], + "can only transfer to other reserve address" + ); + require( + getDailySpendingRatioForCollateralAsset(collateralAsset) > 0, + "this asset has no spending ratio, therefore can't be transferred" + ); + uint256 currentDay = now / 1 days; + if (currentDay > collateralAssetLastSpendingDay[collateralAsset]) { + uint256 balance = getReserveAddressesCollateralAssetBalance( + collateralAsset + ); + collateralAssetLastSpendingDay[collateralAsset] = currentDay; + collateralAssetSpendingLimit[ + collateralAsset + ] = collateralAssetDailySpendingRatio[collateralAsset] + .multiply(FixidityLib.newFixed(balance)) + .fromFixed(); + } + uint256 spendingLimitForThisAsset = collateralAssetSpendingLimit[ + collateralAsset + ]; + require(spendingLimitForThisAsset >= value, "Exceeding spending limit"); + + collateralAssetSpendingLimit[ + collateralAsset + ] = spendingLimitForThisAsset.sub(value); + return _transferCollateralAsset(collateralAsset, to, value); + } + + /** + * @notice Transfer collateral asset to any address. + * @param collateralAsset The token address you're transferring. + * @param to The address that will receive the funds. + * @param value The amount of collateral assets to transfer. + * @return Returns true if the transaction succeeds. + */ + function _transferCollateralAsset( + address collateralAsset, + address payable to, + uint256 value + ) internal returns (bool) { + require( + value <= getReserveAddressesCollateralAssetBalance(collateralAsset), + "Exceeding the amount reserve holds" + ); + // slither-disable-next-line reentrancy-events + IERC20(collateralAsset).safeTransfer(to, value); + emit ReserveCollateralAssetsTransferred( + msg.sender, + to, + value, + collateralAsset + ); + return true; + } + + /** + * @notice Transfer collateral asset to any address. + * @dev Transfers are not subject to a daily spending limit. + * @param collateralAsset The address of collateral asset being transferred. + * @param to The address that will receive the collateral asset. + * @param value The amount of collateral asset to transfer. + * @return Returns true if the transaction succeeds. + */ + function transferExchangeCollateralAsset( + address collateralAsset, + address payable to, + uint256 value + ) external returns (bool) { + require(isExchangeSpender[msg.sender], "Address not allowed to spend"); + return _transferCollateralAsset(collateralAsset, to, value); + } + + /** + * @notice Transfer unfrozen gold to any address. + * @param to The address that will receive the gold. + * @param value The amount of gold to transfer. + * @return Returns true if the transaction succeeds. + */ + function _transferGold( + address payable to, + uint256 value + ) internal returns (bool) { + require(value <= getUnfrozenBalance(), "Exceeding unfrozen reserves"); + // slither-disable-next-line reentrancy-events + to.sendValue(value); + emit ReserveGoldTransferred(msg.sender, to, value); + return true; + } + + /** + * @notice Transfer unfrozen gold to any address, used for one side of CP-DOTO. + * @dev Transfers are not subject to a daily spending limit. + * @param to The address that will receive the gold. + * @param value The amount of gold to transfer. + * @return Returns true if the transaction succeeds. + */ + function transferExchangeGold( + address payable to, + uint256 value + ) external isAllowedToSpendExchange(msg.sender) returns (bool) { + return _transferGold(to, value); + } + + /** + * @notice Returns the tobin tax, recomputing it if it's stale. + * @return The numerator - tobin tax amount as a fraction. + * @return The denominator - tobin tax amount as a fraction. + */ + function getOrComputeTobinTax() + external + nonReentrant + returns (uint256, uint256) + { + // solhint-disable-next-line not-rely-on-time + if (now.sub(tobinTaxCache.timestamp) > tobinTaxStalenessThreshold) { + tobinTaxCache.numerator = uint128(computeTobinTax().unwrap()); + tobinTaxCache.timestamp = uint128(now); // solhint-disable-line not-rely-on-time + } + return ( + uint256(tobinTaxCache.numerator), + FixidityLib.fixed1().unwrap() + ); + } + + /** + * @notice Returns the list of stabilized token addresses. + * @return An array of addresses of stabilized tokens. + */ + function getTokens() external view returns (address[] memory) { + return _tokens; + } + + /** + * @notice Returns the list other addresses included in the reserve total. + * @return An array of other addresses included in the reserve total. + */ + function getOtherReserveAddresses() + external + view + returns (address[] memory) + { + return otherReserveAddresses; + } + + /** + * @notice Returns a list of token symbols that have been allocated. + * @return An array of token symbols that have been allocated. + */ + function getAssetAllocationSymbols() + external + view + returns (bytes32[] memory) + { + return assetAllocationSymbols; + } + + /** + * @notice Returns a list of weights used for the allocation of reserve assets. + * @return An array of a list of weights used for the allocation of reserve assets. + */ + function getAssetAllocationWeights() + external + view + returns (uint256[] memory) + { + uint256[] memory weights = new uint256[](assetAllocationSymbols.length); + // slither-disable-next-line cache-array-length + for (uint256 i = 0; i < assetAllocationSymbols.length; i = i.add(1)) { + weights[i] = assetAllocationWeights[assetAllocationSymbols[i]]; + } + return weights; + } + + /** + * @notice Returns the amount of unfrozen CELO in the reserve. + * @return The total unfrozen CELO in the reserve. + */ + function getUnfrozenBalance() public view returns (uint256) { + uint256 balance = address(this).balance; + uint256 frozenReserveGold = getFrozenReserveGoldBalance(); + return balance > frozenReserveGold ? balance.sub(frozenReserveGold) : 0; + } + + /** + * @notice Returns the amount of CELO included in the reserve. + * @return The CELO amount included in the reserve. + */ + function getReserveGoldBalance() public view returns (uint256) { + return address(this).balance.add(getOtherReserveAddressesGoldBalance()); + } + + /** + * @notice Returns the amount of CELO included in other reserve addresses. + * @return The CELO amount included in other reserve addresses. + */ + function getOtherReserveAddressesGoldBalance() + public + view + returns (uint256) + { + uint256 reserveGoldBalance = 0; + // slither-disable-next-line cache-array-length + for (uint256 i = 0; i < otherReserveAddresses.length; i = i.add(1)) { + reserveGoldBalance = reserveGoldBalance.add( + otherReserveAddresses[i].balance + ); + } + return reserveGoldBalance; + } + + /** + * @notice Returns the amount of unfrozen CELO included in the reserve. + * @return The unfrozen CELO amount included in the reserve. + */ + function getUnfrozenReserveGoldBalance() public view returns (uint256) { + return getUnfrozenBalance().add(getOtherReserveAddressesGoldBalance()); + } + + /** + * @notice Returns the amount of particular collateral asset + * in reserve including other reserve addresses. + * @param collateralAsset the asset we're checking a balance of + * @return The balance of particular collateral asset. + */ + function getReserveAddressesCollateralAssetBalance( + address collateralAsset + ) public view returns (uint256) { + require( + checkIsCollateralAsset(collateralAsset), + "specified address is not a collateral asset" + ); + uint256 reserveCollateralAssetBalance = 0; + // slither-disable-next-line cache-array-length + for (uint256 i = 0; i < otherReserveAddresses.length; i++) { + // slither-disable-next-line calls-loop + reserveCollateralAssetBalance = reserveCollateralAssetBalance.add( + IERC20(collateralAsset).balanceOf(otherReserveAddresses[i]) + ); + } + return + reserveCollateralAssetBalance.add( + IERC20(collateralAsset).balanceOf(address(this)) + ); + } + + /** + * @notice Add a collateral asset in the reserve. + * @param collateralAsset The address of the token being added. + * @return Returns true if the transaction succeeds. + */ + function addCollateralAsset( + address collateralAsset + ) public onlyOwner returns (bool) { + require( + !checkIsCollateralAsset(collateralAsset), + "specified address is already added as a collateral asset" + ); + require(collateralAsset != address(0), "can't be a zero address"); + isCollateralAsset[collateralAsset] = true; + collateralAssets.push(collateralAsset); + emit CollateralAssetAdded(collateralAsset); + return true; + } + + /** + * @notice Remove a collateral asset in the reserve. + * @param collateralAsset The address of the token being removed. + * @param index The index of the token being removed. + * @return Returns true if the transaction succeeds. + */ + function removeCollateralAsset( + address collateralAsset, + uint256 index + ) external onlyOwner returns (bool) { + require( + checkIsCollateralAsset(collateralAsset), + "specified address is not a collateral asset" + ); + require( + index < collateralAssets.length && + collateralAssets[index] == collateralAsset, + "index into collateralAssets list not mapped to token" + ); + collateralAssets[index] = collateralAssets[ + collateralAssets.length.sub(1) + ]; + collateralAssets.pop(); + delete isCollateralAsset[collateralAsset]; + emit CollateralAssetRemoved(collateralAsset); + return true; + } + + /** + * @notice Check if a collateral asset is added to the reserve. + * @param collateralAsset The address of the token being checked. + * @return Returns true if the token was added as a collateral asset. + */ + function checkIsCollateralAsset( + address collateralAsset + ) public view returns (bool) { + return isCollateralAsset[collateralAsset]; + } + + /** + * @notice Returns the amount of frozen CELO in the reserve. + * @return The total frozen CELO in the reserve. + */ + function getFrozenReserveGoldBalance() public view returns (uint256) { + uint256 currentDay = now / 1 days; + uint256 frozenDays = currentDay.sub(frozenReserveGoldStartDay); + if (frozenDays >= frozenReserveGoldDays) return 0; + return + frozenReserveGoldStartBalance.sub( + frozenReserveGoldStartBalance.mul(frozenDays).div( + frozenReserveGoldDays + ) + ); + } + + /** + * @notice Computes the ratio of current reserve balance to total stable token valuation. + * @return Reserve ratio in a fixed point format. + */ + function getReserveRatio() public view returns (uint256) { + address sortedOraclesAddress = registry.getAddressForOrDie( + SORTED_ORACLES_REGISTRY_ID + ); + ISortedOracles sortedOracles = ISortedOracles(sortedOraclesAddress); + uint256 reserveGoldBalance = getUnfrozenReserveGoldBalance(); + uint256 stableTokensValueInGold = 0; + FixidityLib.Fraction memory cgldWeight = FixidityLib.wrap( + assetAllocationWeights["cGLD"] + ); + + // slither-disable-next-line cache-array-length + for (uint256 i = 0; i < _tokens.length; i = i.add(1)) { + uint256 stableAmount; + uint256 goldAmount; + // slither-disable-next-line calls-loop + (stableAmount, goldAmount) = sortedOracles.medianRate(_tokens[i]); + + if (goldAmount != 0) { + // tokens with no oracle reports don't count towards collateralization ratio + // slither-disable-next-line calls-loop + uint256 stableTokenSupply = IERC20(_tokens[i]).totalSupply(); + uint256 aStableTokenValueInGold = stableTokenSupply + .mul(goldAmount) + .div(stableAmount); + stableTokensValueInGold = stableTokensValueInGold.add( + aStableTokenValueInGold + ); + } + } + return + FixidityLib + .newFixed(reserveGoldBalance) + .divide(cgldWeight) + .divide(FixidityLib.newFixed(stableTokensValueInGold)) + .unwrap(); + } + + /* + * Internal functions + */ + + /** + * @notice Computes a tobin tax based on the reserve ratio. + * @return The tobin tax expresesed as a fixidity fraction. + */ + function computeTobinTax() + private + view + returns (FixidityLib.Fraction memory) + { + FixidityLib.Fraction memory ratio = FixidityLib.wrap(getReserveRatio()); + if (ratio.gte(FixidityLib.wrap(tobinTaxReserveRatio))) { + return FixidityLib.wrap(0); + } else { + return FixidityLib.wrap(tobinTax); + } + } + + function isStableAsset(address token) external view returns (bool) { + return isToken[token]; + } } diff --git a/coverage_report/cmd_line b/coverage_report/cmd_line index fc262d8..e348a86 100644 --- a/coverage_report/cmd_line +++ b/coverage_report/cmd_line @@ -1 +1 @@ -genhtml -o coverage_report lcov.info --ignore-errors corrupt --ignore-errors inconsistent +genhtml -o coverage_report lcov.info --ignore-errors inconsistent diff --git a/coverage_report/contracts/BancorExchangeProvider.sol.func-c.html b/coverage_report/contracts/BancorExchangeProvider.sol.func-c.html index b5ca3fd..4ce4744 100644 --- a/coverage_report/contracts/BancorExchangeProvider.sol.func-c.html +++ b/coverage_report/contracts/BancorExchangeProvider.sol.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % @@ -107,77 +107,77 @@ BancorExchangeProvider.getAmountIn - 5 + 7 - BancorExchangeProvider.currentPrice + BancorExchangeProvider.getPoolExchange - 6 + 9 BancorExchangeProvider.executeSwap - 6 + 10 - BancorExchangeProvider.getPoolExchange + BancorExchangeProvider.swapIn - 7 + 10 - BancorExchangeProvider.swapIn + BancorExchangeProvider.swapOut - 8 + 10 - BancorExchangeProvider.swapOut + BancorExchangeProvider.onlyBroker - 8 + 11 - BancorExchangeProvider.onlyBroker + BancorExchangeProvider.getAmountOut - 9 + 13 BancorExchangeProvider._getAmountIn - 10 + 14 - BancorExchangeProvider.getAmountOut + BancorExchangeProvider.currentPrice - 11 + 18 BancorExchangeProvider._getAmountOut - 16 + 20 BancorExchangeProvider.verifyExchangeTokens - 16 + 20 @@ -191,28 +191,28 @@ BancorExchangeProvider.validate - 63 + 69 BancorExchangeProvider.createExchange - 64 + 70 BancorExchangeProvider. - 88 + 94 BancorExchangeProvider._initialize - 88 + 94 diff --git a/coverage_report/contracts/BancorExchangeProvider.sol.func.html b/coverage_report/contracts/BancorExchangeProvider.sol.func.html index 5597d0e..503e92a 100644 --- a/coverage_report/contracts/BancorExchangeProvider.sol.func.html +++ b/coverage_report/contracts/BancorExchangeProvider.sol.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % @@ -65,42 +65,42 @@ BancorExchangeProvider. - 88 + 94 BancorExchangeProvider._getAmountIn - 10 + 14 BancorExchangeProvider._getAmountOut - 16 + 20 BancorExchangeProvider._initialize - 88 + 94 BancorExchangeProvider.createExchange - 64 + 70 BancorExchangeProvider.currentPrice - 6 + 18 @@ -114,21 +114,21 @@ BancorExchangeProvider.executeSwap - 6 + 10 BancorExchangeProvider.getAmountIn - 5 + 7 BancorExchangeProvider.getAmountOut - 11 + 13 @@ -149,7 +149,7 @@ BancorExchangeProvider.getPoolExchange - 7 + 9 @@ -163,7 +163,7 @@ BancorExchangeProvider.onlyBroker - 9 + 11 @@ -191,28 +191,28 @@ BancorExchangeProvider.swapIn - 8 + 10 BancorExchangeProvider.swapOut - 8 + 10 BancorExchangeProvider.validate - 63 + 69 BancorExchangeProvider.verifyExchangeTokens - 16 + 20 diff --git a/coverage_report/contracts/BancorExchangeProvider.sol.gcov.html b/coverage_report/contracts/BancorExchangeProvider.sol.gcov.html index 0673c2b..c4df836 100644 --- a/coverage_report/contracts/BancorExchangeProvider.sol.gcov.html +++ b/coverage_report/contracts/BancorExchangeProvider.sol.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % @@ -129,17 +129,17 @@ 67 : address _broker, 68 : address _reserve 69 : ) internal onlyInitializing { - 70 88 : __Ownable_init(); + 70 94 : __Ownable_init(); 71 : - 72 88 : BancorFormula.init(); - 73 88 : setBroker(_broker); - 74 88 : setReserve(_reserve); + 72 94 : BancorFormula.init(); + 73 94 : setBroker(_broker); + 74 94 : setReserve(_reserve); 75 : } 76 : 77 : /* ==================== Modifiers ==================== */ 78 : 79 : modifier onlyBroker() { - 80 9 : require(msg.sender == broker, "Caller is not the Broker"); + 80 11 : require(msg.sender == broker, "Caller is not the Broker"); 81 : _; 82 : } 83 : @@ -148,7 +148,7 @@ 86 : address tokenOut, 87 : PoolExchange memory exchange 88 : ) { - 89 16 : require( + 89 20 : require( 90 : (tokenIn == exchange.reserveAsset && 91 : tokenOut == exchange.tokenAddress) || 92 : (tokenIn == exchange.tokenAddress && @@ -167,8 +167,8 @@ 105 : function getPoolExchange( 106 : bytes32 exchangeId 107 : ) public view returns (PoolExchange memory exchange) { - 108 63 : exchange = exchanges[exchangeId]; - 109 63 : require( + 108 91 : exchange = exchanges[exchangeId]; + 109 91 : require( 110 : exchange.tokenAddress != address(0), 111 : "An exchange with the specified id does not exist" 112 : ); @@ -213,16 +213,16 @@ 151 : address tokenOut, 152 : uint256 amountIn 153 : ) external view virtual returns (uint256 amountOut) { - 154 11 : PoolExchange memory exchange = getPoolExchange(exchangeId); - 155 10 : uint256 scaledAmountIn = amountIn * tokenPrecisionMultipliers[tokenIn]; - 156 10 : uint256 scaledAmountOut = _getAmountOut( + 154 13 : PoolExchange memory exchange = getPoolExchange(exchangeId); + 155 12 : uint256 scaledAmountIn = amountIn * tokenPrecisionMultipliers[tokenIn]; + 156 12 : uint256 scaledAmountOut = _getAmountOut( 157 : exchange, 158 : tokenIn, 159 : tokenOut, 160 : scaledAmountIn 161 : ); - 162 4 : amountOut = scaledAmountOut / tokenPrecisionMultipliers[tokenOut]; - 163 4 : return amountOut; + 162 6 : amountOut = scaledAmountOut / tokenPrecisionMultipliers[tokenOut]; + 163 6 : return amountOut; 164 : } 165 : 166 : /** @@ -239,17 +239,17 @@ 177 : address tokenOut, 178 : uint256 amountOut 179 : ) external view virtual returns (uint256 amountIn) { - 180 5 : PoolExchange memory exchange = getPoolExchange(exchangeId); - 181 4 : uint256 scaledAmountOut = amountOut * + 180 7 : PoolExchange memory exchange = getPoolExchange(exchangeId); + 181 6 : uint256 scaledAmountOut = amountOut * 182 : tokenPrecisionMultipliers[tokenOut]; - 183 4 : uint256 scaledAmountIn = _getAmountIn( + 183 6 : uint256 scaledAmountIn = _getAmountIn( 184 : exchange, 185 : tokenIn, 186 : tokenOut, 187 : scaledAmountOut 188 : ); - 189 4 : amountIn = scaledAmountIn / tokenPrecisionMultipliers[tokenIn]; - 190 4 : return amountIn; + 189 6 : amountIn = scaledAmountIn / tokenPrecisionMultipliers[tokenIn]; + 190 6 : return amountIn; 191 : } 192 : 193 : /** @@ -261,17 +261,17 @@ 199 : bytes32 exchangeId 200 : ) public view returns (uint256 price) { 201 : // calculates: reserveBalance / (tokenSupply * reserveRatio) - 202 8 : require( + 202 20 : require( 203 : exchanges[exchangeId].reserveAsset != address(0), 204 : "Exchange does not exist" 205 : ); - 206 7 : PoolExchange memory exchange = getPoolExchange(exchangeId); - 207 7 : uint256 scaledReserveRatio = uint256(exchange.reserveRatio) * 1e10; - 208 7 : UD60x18 denominator = wrap(exchange.tokenSupply).mul( + 206 19 : PoolExchange memory exchange = getPoolExchange(exchangeId); + 207 19 : uint256 scaledReserveRatio = uint256(exchange.reserveRatio) * 1e10; + 208 19 : UD60x18 denominator = wrap(exchange.tokenSupply).mul( 209 : wrap(scaledReserveRatio) 210 : ); - 211 7 : price = unwrap(wrap(exchange.reserveBalance).div(denominator)); - 212 7 : return price; + 211 19 : price = unwrap(wrap(exchange.reserveBalance).div(denominator)); + 212 19 : return price; 213 : } 214 : 215 : /* ==================== Mutative Functions ==================== */ @@ -281,9 +281,9 @@ 219 : * @param _broker The new address of the broker contract. 220 : */ 221 : function setBroker(address _broker) public onlyOwner { - 222 90 : require(_broker != address(0), "Broker address must be set"); - 223 89 : broker = _broker; - 224 89 : emit BrokerUpdated(_broker); + 222 96 : require(_broker != address(0), "Broker address must be set"); + 223 95 : broker = _broker; + 224 95 : emit BrokerUpdated(_broker); 225 : } 226 : 227 : /** @@ -291,9 +291,9 @@ 229 : * @param _reserve The new address of the reserve contract. 230 : */ 231 : function setReserve(address _reserve) public onlyOwner { - 232 90 : require(address(_reserve) != address(0), "Reserve address must be set"); - 233 89 : reserve = IReserve(_reserve); - 234 89 : emit ReserveUpdated(address(_reserve)); + 232 96 : require(address(_reserve) != address(0), "Reserve address must be set"); + 233 95 : reserve = IReserve(_reserve); + 234 95 : emit ReserveUpdated(address(_reserve)); 235 : } 236 : 237 : /** @@ -324,36 +324,36 @@ 262 : function createExchange( 263 : PoolExchange calldata _exchange 264 : ) external onlyOwner returns (bytes32 exchangeId) { - 265 63 : PoolExchange memory exchange = _exchange; - 266 63 : validate(exchange); + 265 69 : PoolExchange memory exchange = _exchange; + 266 69 : validate(exchange); 267 : - 268 55 : exchangeId = keccak256( + 268 61 : exchangeId = keccak256( 269 : abi.encodePacked( 270 : IERC20(exchange.reserveAsset).symbol(), 271 : IERC20(exchange.tokenAddress).symbol() 272 : ) 273 : ); - 274 55 : require( + 274 61 : require( 275 : exchanges[exchangeId].reserveAsset == address(0), 276 : "Exchange already exists" 277 : ); 278 : - 279 54 : uint256 reserveAssetDecimals = IERC20(exchange.reserveAsset).decimals(); - 280 54 : uint256 tokenDecimals = IERC20(exchange.tokenAddress).decimals(); - 281 54 : require( + 279 60 : uint256 reserveAssetDecimals = IERC20(exchange.reserveAsset).decimals(); + 280 60 : uint256 tokenDecimals = IERC20(exchange.tokenAddress).decimals(); + 281 60 : require( 282 : reserveAssetDecimals <= 18, 283 : "reserve token decimals must be <= 18" 284 : ); - 285 53 : require(tokenDecimals <= 18, "token decimals must be <= 18"); + 285 59 : require(tokenDecimals <= 18, "token decimals must be <= 18"); 286 : - 287 52 : tokenPrecisionMultipliers[exchange.reserveAsset] = + 287 58 : tokenPrecisionMultipliers[exchange.reserveAsset] = 288 : 10 ** (18 - uint256(reserveAssetDecimals)); - 289 52 : tokenPrecisionMultipliers[exchange.tokenAddress] = + 289 58 : tokenPrecisionMultipliers[exchange.tokenAddress] = 290 : 10 ** (18 - uint256(tokenDecimals)); 291 : - 292 52 : exchanges[exchangeId] = exchange; - 293 52 : exchangeIds.push(exchangeId); - 294 52 : emit ExchangeCreated( + 292 58 : exchanges[exchangeId] = exchange; + 293 58 : exchangeIds.push(exchangeId); + 294 58 : emit ExchangeCreated( 295 : exchangeId, 296 : exchange.reserveAsset, 297 : exchange.tokenAddress @@ -406,18 +406,18 @@ 344 : address tokenOut, 345 : uint256 amountIn 346 : ) public virtual onlyBroker returns (uint256 amountOut) { - 347 7 : PoolExchange memory exchange = getPoolExchange(exchangeId); - 348 6 : uint256 scaledAmountIn = amountIn * tokenPrecisionMultipliers[tokenIn]; - 349 6 : uint256 scaledAmountOut = _getAmountOut( + 347 9 : PoolExchange memory exchange = getPoolExchange(exchangeId); + 348 8 : uint256 scaledAmountIn = amountIn * tokenPrecisionMultipliers[tokenIn]; + 349 8 : uint256 scaledAmountOut = _getAmountOut( 350 : exchange, 351 : tokenIn, 352 : tokenOut, 353 : scaledAmountIn 354 : ); - 355 3 : executeSwap(exchangeId, tokenIn, scaledAmountIn, scaledAmountOut); + 355 5 : executeSwap(exchangeId, tokenIn, scaledAmountIn, scaledAmountOut); 356 : - 357 3 : amountOut = scaledAmountOut / tokenPrecisionMultipliers[tokenOut]; - 358 3 : return amountOut; + 357 5 : amountOut = scaledAmountOut / tokenPrecisionMultipliers[tokenOut]; + 358 5 : return amountOut; 359 : } 360 : 361 : /** @@ -434,19 +434,19 @@ 372 : address tokenOut, 373 : uint256 amountOut 374 : ) public virtual onlyBroker returns (uint256 amountIn) { - 375 7 : PoolExchange memory exchange = getPoolExchange(exchangeId); - 376 6 : uint256 scaledAmountOut = amountOut * + 375 9 : PoolExchange memory exchange = getPoolExchange(exchangeId); + 376 8 : uint256 scaledAmountOut = amountOut * 377 : tokenPrecisionMultipliers[tokenOut]; - 378 6 : uint256 scaledAmountIn = _getAmountIn( + 378 8 : uint256 scaledAmountIn = _getAmountIn( 379 : exchange, 380 : tokenIn, 381 : tokenOut, 382 : scaledAmountOut 383 : ); - 384 3 : executeSwap(exchangeId, tokenIn, scaledAmountIn, scaledAmountOut); + 384 5 : executeSwap(exchangeId, tokenIn, scaledAmountIn, scaledAmountOut); 385 : - 386 3 : amountIn = scaledAmountIn / tokenPrecisionMultipliers[tokenIn]; - 387 3 : return amountIn; + 386 5 : amountIn = scaledAmountIn / tokenPrecisionMultipliers[tokenIn]; + 387 5 : return amountIn; 388 : } 389 : 390 : /* ==================== Private Functions ==================== */ @@ -465,16 +465,16 @@ 403 : uint256 scaledAmountIn, 404 : uint256 scaledAmountOut 405 : ) internal { - 406 6 : PoolExchange memory exchange = getPoolExchange(exchangeId); - 407 6 : if (tokenIn == exchange.reserveAsset) { - 408 4 : exchange.reserveBalance += scaledAmountIn; - 409 4 : exchange.tokenSupply += scaledAmountOut; + 406 10 : PoolExchange memory exchange = getPoolExchange(exchangeId); + 407 10 : if (tokenIn == exchange.reserveAsset) { + 408 6 : exchange.reserveBalance += scaledAmountIn; + 409 6 : exchange.tokenSupply += scaledAmountOut; 410 : } else { - 411 2 : exchange.reserveBalance -= scaledAmountOut; - 412 2 : exchange.tokenSupply -= scaledAmountIn; + 411 4 : exchange.reserveBalance -= scaledAmountOut; + 412 4 : exchange.tokenSupply -= scaledAmountIn; 413 : } - 414 6 : exchanges[exchangeId].reserveBalance = exchange.reserveBalance; - 415 6 : exchanges[exchangeId].tokenSupply = exchange.tokenSupply; + 414 10 : exchanges[exchangeId].reserveBalance = exchange.reserveBalance; + 415 10 : exchanges[exchangeId].tokenSupply = exchange.tokenSupply; 416 : } 417 : 418 : /** @@ -496,22 +496,22 @@ 434 : verifyExchangeTokens(tokenIn, tokenOut, exchange) 435 : returns (uint256 scaledAmountIn) 436 : { - 437 7 : if (tokenIn == exchange.reserveAsset) { - 438 4 : scaledAmountIn = fundCost( + 437 11 : if (tokenIn == exchange.reserveAsset) { + 438 6 : scaledAmountIn = fundCost( 439 : exchange.tokenSupply, 440 : exchange.reserveBalance, 441 : exchange.reserveRatio, 442 : scaledAmountOut 443 : ); 444 : } else { - 445 3 : scaledAmountIn = fundSupplyAmount( + 445 5 : scaledAmountIn = fundSupplyAmount( 446 : exchange.tokenSupply, 447 : exchange.reserveBalance, 448 : exchange.reserveRatio, 449 : scaledAmountOut 450 : ); 451 : - 452 3 : scaledAmountIn = + 452 5 : scaledAmountIn = 453 : (scaledAmountIn * MAX_WEIGHT) / 454 : (MAX_WEIGHT - exchange.exitContribution); 455 : } @@ -536,18 +536,18 @@ 474 : verifyExchangeTokens(tokenIn, tokenOut, exchange) 475 : returns (uint256 scaledAmountOut) 476 : { - 477 7 : if (tokenIn == exchange.reserveAsset) { - 478 4 : scaledAmountOut = purchaseTargetAmount( + 477 11 : if (tokenIn == exchange.reserveAsset) { + 478 6 : scaledAmountOut = purchaseTargetAmount( 479 : exchange.tokenSupply, 480 : exchange.reserveBalance, 481 : exchange.reserveRatio, 482 : scaledAmountIn 483 : ); 484 : } else { - 485 3 : scaledAmountIn = + 485 5 : scaledAmountIn = 486 : (scaledAmountIn * (MAX_WEIGHT - exchange.exitContribution)) / 487 : MAX_WEIGHT; - 488 3 : scaledAmountOut = saleTargetAmount( + 488 5 : scaledAmountOut = saleTargetAmount( 489 : exchange.tokenSupply, 490 : exchange.reserveBalance, 491 : exchange.reserveRatio, @@ -562,19 +562,19 @@ 500 : * @param exchange The PoolExchange to validate 501 : */ 502 : function validate(PoolExchange memory exchange) private view { - 503 63 : require(exchange.reserveAsset != address(0), "Invalid reserve asset"); - 504 62 : require( + 503 69 : require(exchange.reserveAsset != address(0), "Invalid reserve asset"); + 504 68 : require( 505 : reserve.isCollateralAsset(exchange.reserveAsset), 506 : "reserve asset must be a collateral registered with the reserve" 507 : ); - 508 61 : require(exchange.tokenAddress != address(0), "Invalid token address"); - 509 60 : require( + 508 67 : require(exchange.tokenAddress != address(0), "Invalid token address"); + 509 66 : require( 510 : reserve.isStableAsset(exchange.tokenAddress), 511 : "token must be a stable registered with the reserve" 512 : ); - 513 59 : require(exchange.reserveRatio > 1, "Invalid reserve ratio"); - 514 57 : require(exchange.reserveRatio <= MAX_WEIGHT, "Invalid reserve ratio"); - 515 56 : require( + 513 65 : require(exchange.reserveRatio > 1, "Invalid reserve ratio"); + 514 63 : require(exchange.reserveRatio <= MAX_WEIGHT, "Invalid reserve ratio"); + 515 62 : require( 516 : exchange.exitContribution <= MAX_WEIGHT, 517 : "Invalid exit contribution" 518 : ); diff --git a/coverage_report/contracts/BancorFormula.sol.func-c.html b/coverage_report/contracts/BancorFormula.sol.func-c.html index 782e431..687c859 100644 --- a/coverage_report/contracts/BancorFormula.sol.func-c.html +++ b/coverage_report/contracts/BancorFormula.sol.func-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 65.3 % + 65.8 % 357 - 233 + 235 Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 61.5 % @@ -100,56 +100,56 @@ BancorFormula.fundSupplyAmount - 3 + 5 BancorFormula.saleTargetAmount - 3 + 5 BancorFormula.fundCost - 4 + 6 BancorFormula.purchaseTargetAmount - 4 + 6 BancorFormula.optimalExp - 14 + 22 BancorFormula.optimalLog - 14 + 22 BancorFormula.power - 14 + 22 BancorFormula.initMaxExpArray - 88 + 94 diff --git a/coverage_report/contracts/BancorFormula.sol.func.html b/coverage_report/contracts/BancorFormula.sol.func.html index 48b8d4c..795de4a 100644 --- a/coverage_report/contracts/BancorFormula.sol.func.html +++ b/coverage_report/contracts/BancorFormula.sol.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 65.3 % + 65.8 % 357 - 233 + 235 Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 61.5 % @@ -79,14 +79,14 @@ BancorFormula.fundCost - 4 + 6 BancorFormula.fundSupplyAmount - 3 + 5 @@ -114,42 +114,42 @@ BancorFormula.initMaxExpArray - 88 + 94 BancorFormula.optimalExp - 14 + 22 BancorFormula.optimalLog - 14 + 22 BancorFormula.power - 14 + 22 BancorFormula.purchaseTargetAmount - 4 + 6 BancorFormula.saleTargetAmount - 3 + 5 diff --git a/coverage_report/contracts/BancorFormula.sol.gcov.html b/coverage_report/contracts/BancorFormula.sol.gcov.html index ee7354a..5e5239f 100644 --- a/coverage_report/contracts/BancorFormula.sol.gcov.html +++ b/coverage_report/contracts/BancorFormula.sol.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 65.3 % + 65.8 % 357 - 233 + 235 Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 61.5 % @@ -131,109 +131,109 @@ 69 : // maxExpArray[ 29] = 0x1fffffffffffffffffffffffffffffffff; 70 : // maxExpArray[ 30] = 0x1eaefdbdabffffffffffffffffffffffff; 71 : // maxExpArray[ 31] = 0x1d6bd8b2ebffffffffffffffffffffffff; - 72 88 : maxExpArray[32] = 0x1c35fedd14ffffffffffffffffffffffff; - 73 88 : maxExpArray[33] = 0x1b0ce43b323fffffffffffffffffffffff; - 74 88 : maxExpArray[34] = 0x19f0028ec1ffffffffffffffffffffffff; - 75 88 : maxExpArray[35] = 0x18ded91f0e7fffffffffffffffffffffff; - 76 88 : maxExpArray[36] = 0x17d8ec7f0417ffffffffffffffffffffff; - 77 88 : maxExpArray[37] = 0x16ddc6556cdbffffffffffffffffffffff; - 78 88 : maxExpArray[38] = 0x15ecf52776a1ffffffffffffffffffffff; - 79 88 : maxExpArray[39] = 0x15060c256cb2ffffffffffffffffffffff; - 80 88 : maxExpArray[40] = 0x1428a2f98d72ffffffffffffffffffffff; - 81 88 : maxExpArray[41] = 0x13545598e5c23fffffffffffffffffffff; - 82 88 : maxExpArray[42] = 0x1288c4161ce1dfffffffffffffffffffff; - 83 88 : maxExpArray[43] = 0x11c592761c666fffffffffffffffffffff; - 84 88 : maxExpArray[44] = 0x110a688680a757ffffffffffffffffffff; - 85 88 : maxExpArray[45] = 0x1056f1b5bedf77ffffffffffffffffffff; - 86 88 : maxExpArray[46] = 0x0faadceceeff8bffffffffffffffffffff; - 87 88 : maxExpArray[47] = 0x0f05dc6b27edadffffffffffffffffffff; - 88 88 : maxExpArray[48] = 0x0e67a5a25da4107fffffffffffffffffff; - 89 88 : maxExpArray[49] = 0x0dcff115b14eedffffffffffffffffffff; - 90 88 : maxExpArray[50] = 0x0d3e7a392431239fffffffffffffffffff; - 91 88 : maxExpArray[51] = 0x0cb2ff529eb71e4fffffffffffffffffff; - 92 88 : maxExpArray[52] = 0x0c2d415c3db974afffffffffffffffffff; - 93 88 : maxExpArray[53] = 0x0bad03e7d883f69bffffffffffffffffff; - 94 88 : maxExpArray[54] = 0x0b320d03b2c343d5ffffffffffffffffff; - 95 88 : maxExpArray[55] = 0x0abc25204e02828dffffffffffffffffff; - 96 88 : maxExpArray[56] = 0x0a4b16f74ee4bb207fffffffffffffffff; - 97 88 : maxExpArray[57] = 0x09deaf736ac1f569ffffffffffffffffff; - 98 88 : maxExpArray[58] = 0x0976bd9952c7aa957fffffffffffffffff; - 99 88 : maxExpArray[59] = 0x09131271922eaa606fffffffffffffffff; - 100 88 : maxExpArray[60] = 0x08b380f3558668c46fffffffffffffffff; - 101 88 : maxExpArray[61] = 0x0857ddf0117efa215bffffffffffffffff; - 102 88 : maxExpArray[62] = 0x07ffffffffffffffffffffffffffffffff; - 103 88 : maxExpArray[63] = 0x07abbf6f6abb9d087fffffffffffffffff; - 104 88 : maxExpArray[64] = 0x075af62cbac95f7dfa7fffffffffffffff; - 105 88 : maxExpArray[65] = 0x070d7fb7452e187ac13fffffffffffffff; - 106 88 : maxExpArray[66] = 0x06c3390ecc8af379295fffffffffffffff; - 107 88 : maxExpArray[67] = 0x067c00a3b07ffc01fd6fffffffffffffff; - 108 88 : maxExpArray[68] = 0x0637b647c39cbb9d3d27ffffffffffffff; - 109 88 : maxExpArray[69] = 0x05f63b1fc104dbd39587ffffffffffffff; - 110 88 : maxExpArray[70] = 0x05b771955b36e12f7235ffffffffffffff; - 111 88 : maxExpArray[71] = 0x057b3d49dda84556d6f6ffffffffffffff; - 112 88 : maxExpArray[72] = 0x054183095b2c8ececf30ffffffffffffff; - 113 88 : maxExpArray[73] = 0x050a28be635ca2b888f77fffffffffffff; - 114 88 : maxExpArray[74] = 0x04d5156639708c9db33c3fffffffffffff; - 115 88 : maxExpArray[75] = 0x04a23105873875bd52dfdfffffffffffff; - 116 88 : maxExpArray[76] = 0x0471649d87199aa990756fffffffffffff; - 117 88 : maxExpArray[77] = 0x04429a21a029d4c1457cfbffffffffffff; - 118 88 : maxExpArray[78] = 0x0415bc6d6fb7dd71af2cb3ffffffffffff; - 119 88 : maxExpArray[79] = 0x03eab73b3bbfe282243ce1ffffffffffff; - 120 88 : maxExpArray[80] = 0x03c1771ac9fb6b4c18e229ffffffffffff; - 121 88 : maxExpArray[81] = 0x0399e96897690418f785257fffffffffff; - 122 88 : maxExpArray[82] = 0x0373fc456c53bb779bf0ea9fffffffffff; - 123 88 : maxExpArray[83] = 0x034f9e8e490c48e67e6ab8bfffffffffff; - 124 88 : maxExpArray[84] = 0x032cbfd4a7adc790560b3337ffffffffff; - 125 88 : maxExpArray[85] = 0x030b50570f6e5d2acca94613ffffffffff; - 126 88 : maxExpArray[86] = 0x02eb40f9f620fda6b56c2861ffffffffff; - 127 88 : maxExpArray[87] = 0x02cc8340ecb0d0f520a6af58ffffffffff; - 128 88 : maxExpArray[88] = 0x02af09481380a0a35cf1ba02ffffffffff; - 129 88 : maxExpArray[89] = 0x0292c5bdd3b92ec810287b1b3fffffffff; - 130 88 : maxExpArray[90] = 0x0277abdcdab07d5a77ac6d6b9fffffffff; - 131 88 : maxExpArray[91] = 0x025daf6654b1eaa55fd64df5efffffffff; - 132 88 : maxExpArray[92] = 0x0244c49c648baa98192dce88b7ffffffff; - 133 88 : maxExpArray[93] = 0x022ce03cd5619a311b2471268bffffffff; - 134 88 : maxExpArray[94] = 0x0215f77c045fbe885654a44a0fffffffff; - 135 88 : maxExpArray[95] = 0x01ffffffffffffffffffffffffffffffff; - 136 88 : maxExpArray[96] = 0x01eaefdbdaaee7421fc4d3ede5ffffffff; - 137 88 : maxExpArray[97] = 0x01d6bd8b2eb257df7e8ca57b09bfffffff; - 138 88 : maxExpArray[98] = 0x01c35fedd14b861eb0443f7f133fffffff; - 139 88 : maxExpArray[99] = 0x01b0ce43b322bcde4a56e8ada5afffffff; - 140 88 : maxExpArray[100] = 0x019f0028ec1fff007f5a195a39dfffffff; - 141 88 : maxExpArray[101] = 0x018ded91f0e72ee74f49b15ba527ffffff; - 142 88 : maxExpArray[102] = 0x017d8ec7f04136f4e5615fd41a63ffffff; - 143 88 : maxExpArray[103] = 0x016ddc6556cdb84bdc8d12d22e6fffffff; - 144 88 : maxExpArray[104] = 0x015ecf52776a1155b5bd8395814f7fffff; - 145 88 : maxExpArray[105] = 0x015060c256cb23b3b3cc3754cf40ffffff; - 146 88 : maxExpArray[106] = 0x01428a2f98d728ae223ddab715be3fffff; - 147 88 : maxExpArray[107] = 0x013545598e5c23276ccf0ede68034fffff; - 148 88 : maxExpArray[108] = 0x01288c4161ce1d6f54b7f61081194fffff; - 149 88 : maxExpArray[109] = 0x011c592761c666aa641d5a01a40f17ffff; - 150 88 : maxExpArray[110] = 0x0110a688680a7530515f3e6e6cfdcdffff; - 151 88 : maxExpArray[111] = 0x01056f1b5bedf75c6bcb2ce8aed428ffff; - 152 88 : maxExpArray[112] = 0x00faadceceeff8a0890f3875f008277fff; - 153 88 : maxExpArray[113] = 0x00f05dc6b27edad306388a600f6ba0bfff; - 154 88 : maxExpArray[114] = 0x00e67a5a25da41063de1495d5b18cdbfff; - 155 88 : maxExpArray[115] = 0x00dcff115b14eedde6fc3aa5353f2e4fff; - 156 88 : maxExpArray[116] = 0x00d3e7a3924312399f9aae2e0f868f8fff; - 157 88 : maxExpArray[117] = 0x00cb2ff529eb71e41582cccd5a1ee26fff; - 158 88 : maxExpArray[118] = 0x00c2d415c3db974ab32a51840c0b67edff; - 159 88 : maxExpArray[119] = 0x00bad03e7d883f69ad5b0a186184e06bff; - 160 88 : maxExpArray[120] = 0x00b320d03b2c343d4829abd6075f0cc5ff; - 161 88 : maxExpArray[121] = 0x00abc25204e02828d73c6e80bcdb1a95bf; - 162 88 : maxExpArray[122] = 0x00a4b16f74ee4bb2040a1ec6c15fbbf2df; - 163 88 : maxExpArray[123] = 0x009deaf736ac1f569deb1b5ae3f36c130f; - 164 88 : maxExpArray[124] = 0x00976bd9952c7aa957f5937d790ef65037; - 165 88 : maxExpArray[125] = 0x009131271922eaa6064b73a22d0bd4f2bf; - 166 88 : maxExpArray[126] = 0x008b380f3558668c46c91c49a2f8e967b9; - 167 88 : maxExpArray[127] = 0x00857ddf0117efa215952912839f6473e6; + 72 94 : maxExpArray[32] = 0x1c35fedd14ffffffffffffffffffffffff; + 73 94 : maxExpArray[33] = 0x1b0ce43b323fffffffffffffffffffffff; + 74 94 : maxExpArray[34] = 0x19f0028ec1ffffffffffffffffffffffff; + 75 94 : maxExpArray[35] = 0x18ded91f0e7fffffffffffffffffffffff; + 76 94 : maxExpArray[36] = 0x17d8ec7f0417ffffffffffffffffffffff; + 77 94 : maxExpArray[37] = 0x16ddc6556cdbffffffffffffffffffffff; + 78 94 : maxExpArray[38] = 0x15ecf52776a1ffffffffffffffffffffff; + 79 94 : maxExpArray[39] = 0x15060c256cb2ffffffffffffffffffffff; + 80 94 : maxExpArray[40] = 0x1428a2f98d72ffffffffffffffffffffff; + 81 94 : maxExpArray[41] = 0x13545598e5c23fffffffffffffffffffff; + 82 94 : maxExpArray[42] = 0x1288c4161ce1dfffffffffffffffffffff; + 83 94 : maxExpArray[43] = 0x11c592761c666fffffffffffffffffffff; + 84 94 : maxExpArray[44] = 0x110a688680a757ffffffffffffffffffff; + 85 94 : maxExpArray[45] = 0x1056f1b5bedf77ffffffffffffffffffff; + 86 94 : maxExpArray[46] = 0x0faadceceeff8bffffffffffffffffffff; + 87 94 : maxExpArray[47] = 0x0f05dc6b27edadffffffffffffffffffff; + 88 94 : maxExpArray[48] = 0x0e67a5a25da4107fffffffffffffffffff; + 89 94 : maxExpArray[49] = 0x0dcff115b14eedffffffffffffffffffff; + 90 94 : maxExpArray[50] = 0x0d3e7a392431239fffffffffffffffffff; + 91 94 : maxExpArray[51] = 0x0cb2ff529eb71e4fffffffffffffffffff; + 92 94 : maxExpArray[52] = 0x0c2d415c3db974afffffffffffffffffff; + 93 94 : maxExpArray[53] = 0x0bad03e7d883f69bffffffffffffffffff; + 94 94 : maxExpArray[54] = 0x0b320d03b2c343d5ffffffffffffffffff; + 95 94 : maxExpArray[55] = 0x0abc25204e02828dffffffffffffffffff; + 96 94 : maxExpArray[56] = 0x0a4b16f74ee4bb207fffffffffffffffff; + 97 94 : maxExpArray[57] = 0x09deaf736ac1f569ffffffffffffffffff; + 98 94 : maxExpArray[58] = 0x0976bd9952c7aa957fffffffffffffffff; + 99 94 : maxExpArray[59] = 0x09131271922eaa606fffffffffffffffff; + 100 94 : maxExpArray[60] = 0x08b380f3558668c46fffffffffffffffff; + 101 94 : maxExpArray[61] = 0x0857ddf0117efa215bffffffffffffffff; + 102 94 : maxExpArray[62] = 0x07ffffffffffffffffffffffffffffffff; + 103 94 : maxExpArray[63] = 0x07abbf6f6abb9d087fffffffffffffffff; + 104 94 : maxExpArray[64] = 0x075af62cbac95f7dfa7fffffffffffffff; + 105 94 : maxExpArray[65] = 0x070d7fb7452e187ac13fffffffffffffff; + 106 94 : maxExpArray[66] = 0x06c3390ecc8af379295fffffffffffffff; + 107 94 : maxExpArray[67] = 0x067c00a3b07ffc01fd6fffffffffffffff; + 108 94 : maxExpArray[68] = 0x0637b647c39cbb9d3d27ffffffffffffff; + 109 94 : maxExpArray[69] = 0x05f63b1fc104dbd39587ffffffffffffff; + 110 94 : maxExpArray[70] = 0x05b771955b36e12f7235ffffffffffffff; + 111 94 : maxExpArray[71] = 0x057b3d49dda84556d6f6ffffffffffffff; + 112 94 : maxExpArray[72] = 0x054183095b2c8ececf30ffffffffffffff; + 113 94 : maxExpArray[73] = 0x050a28be635ca2b888f77fffffffffffff; + 114 94 : maxExpArray[74] = 0x04d5156639708c9db33c3fffffffffffff; + 115 94 : maxExpArray[75] = 0x04a23105873875bd52dfdfffffffffffff; + 116 94 : maxExpArray[76] = 0x0471649d87199aa990756fffffffffffff; + 117 94 : maxExpArray[77] = 0x04429a21a029d4c1457cfbffffffffffff; + 118 94 : maxExpArray[78] = 0x0415bc6d6fb7dd71af2cb3ffffffffffff; + 119 94 : maxExpArray[79] = 0x03eab73b3bbfe282243ce1ffffffffffff; + 120 94 : maxExpArray[80] = 0x03c1771ac9fb6b4c18e229ffffffffffff; + 121 94 : maxExpArray[81] = 0x0399e96897690418f785257fffffffffff; + 122 94 : maxExpArray[82] = 0x0373fc456c53bb779bf0ea9fffffffffff; + 123 94 : maxExpArray[83] = 0x034f9e8e490c48e67e6ab8bfffffffffff; + 124 94 : maxExpArray[84] = 0x032cbfd4a7adc790560b3337ffffffffff; + 125 94 : maxExpArray[85] = 0x030b50570f6e5d2acca94613ffffffffff; + 126 94 : maxExpArray[86] = 0x02eb40f9f620fda6b56c2861ffffffffff; + 127 94 : maxExpArray[87] = 0x02cc8340ecb0d0f520a6af58ffffffffff; + 128 94 : maxExpArray[88] = 0x02af09481380a0a35cf1ba02ffffffffff; + 129 94 : maxExpArray[89] = 0x0292c5bdd3b92ec810287b1b3fffffffff; + 130 94 : maxExpArray[90] = 0x0277abdcdab07d5a77ac6d6b9fffffffff; + 131 94 : maxExpArray[91] = 0x025daf6654b1eaa55fd64df5efffffffff; + 132 94 : maxExpArray[92] = 0x0244c49c648baa98192dce88b7ffffffff; + 133 94 : maxExpArray[93] = 0x022ce03cd5619a311b2471268bffffffff; + 134 94 : maxExpArray[94] = 0x0215f77c045fbe885654a44a0fffffffff; + 135 94 : maxExpArray[95] = 0x01ffffffffffffffffffffffffffffffff; + 136 94 : maxExpArray[96] = 0x01eaefdbdaaee7421fc4d3ede5ffffffff; + 137 94 : maxExpArray[97] = 0x01d6bd8b2eb257df7e8ca57b09bfffffff; + 138 94 : maxExpArray[98] = 0x01c35fedd14b861eb0443f7f133fffffff; + 139 94 : maxExpArray[99] = 0x01b0ce43b322bcde4a56e8ada5afffffff; + 140 94 : maxExpArray[100] = 0x019f0028ec1fff007f5a195a39dfffffff; + 141 94 : maxExpArray[101] = 0x018ded91f0e72ee74f49b15ba527ffffff; + 142 94 : maxExpArray[102] = 0x017d8ec7f04136f4e5615fd41a63ffffff; + 143 94 : maxExpArray[103] = 0x016ddc6556cdb84bdc8d12d22e6fffffff; + 144 94 : maxExpArray[104] = 0x015ecf52776a1155b5bd8395814f7fffff; + 145 94 : maxExpArray[105] = 0x015060c256cb23b3b3cc3754cf40ffffff; + 146 94 : maxExpArray[106] = 0x01428a2f98d728ae223ddab715be3fffff; + 147 94 : maxExpArray[107] = 0x013545598e5c23276ccf0ede68034fffff; + 148 94 : maxExpArray[108] = 0x01288c4161ce1d6f54b7f61081194fffff; + 149 94 : maxExpArray[109] = 0x011c592761c666aa641d5a01a40f17ffff; + 150 94 : maxExpArray[110] = 0x0110a688680a7530515f3e6e6cfdcdffff; + 151 94 : maxExpArray[111] = 0x01056f1b5bedf75c6bcb2ce8aed428ffff; + 152 94 : maxExpArray[112] = 0x00faadceceeff8a0890f3875f008277fff; + 153 94 : maxExpArray[113] = 0x00f05dc6b27edad306388a600f6ba0bfff; + 154 94 : maxExpArray[114] = 0x00e67a5a25da41063de1495d5b18cdbfff; + 155 94 : maxExpArray[115] = 0x00dcff115b14eedde6fc3aa5353f2e4fff; + 156 94 : maxExpArray[116] = 0x00d3e7a3924312399f9aae2e0f868f8fff; + 157 94 : maxExpArray[117] = 0x00cb2ff529eb71e41582cccd5a1ee26fff; + 158 94 : maxExpArray[118] = 0x00c2d415c3db974ab32a51840c0b67edff; + 159 94 : maxExpArray[119] = 0x00bad03e7d883f69ad5b0a186184e06bff; + 160 94 : maxExpArray[120] = 0x00b320d03b2c343d4829abd6075f0cc5ff; + 161 94 : maxExpArray[121] = 0x00abc25204e02828d73c6e80bcdb1a95bf; + 162 94 : maxExpArray[122] = 0x00a4b16f74ee4bb2040a1ec6c15fbbf2df; + 163 94 : maxExpArray[123] = 0x009deaf736ac1f569deb1b5ae3f36c130f; + 164 94 : maxExpArray[124] = 0x00976bd9952c7aa957f5937d790ef65037; + 165 94 : maxExpArray[125] = 0x009131271922eaa6064b73a22d0bd4f2bf; + 166 94 : maxExpArray[126] = 0x008b380f3558668c46c91c49a2f8e967b9; + 167 94 : maxExpArray[127] = 0x00857ddf0117efa215952912839f6473e6; 168 : } 169 : 170 : /** 171 : * @dev should be executed after construction (too large for the constructor) 172 : */ 173 : function init() public { - 174 88 : initMaxExpArray(); + 174 94 : initMaxExpArray(); 175 : } 176 : 177 : /** @@ -257,22 +257,22 @@ 195 : uint256 _amount 196 : ) internal view returns (uint256) { 197 : // validate input - 198 4 : require(_supply > 0, "ERR_INVALID_SUPPLY"); - 199 4 : require(_reserveBalance > 0, "ERR_INVALID_RESERVE_BALANCE"); - 200 4 : require(_reserveWeight > 0 && _reserveWeight <= MAX_WEIGHT, "ERR_INVALID_RESERVE_WEIGHT"); + 198 6 : require(_supply > 0, "ERR_INVALID_SUPPLY"); + 199 6 : require(_reserveBalance > 0, "ERR_INVALID_RESERVE_BALANCE"); + 200 6 : require(_reserveWeight > 0 && _reserveWeight <= MAX_WEIGHT, "ERR_INVALID_RESERVE_WEIGHT"); 201 : 202 : // special case for 0 deposit amount - 203 4 : if (_amount == 0) return 0; + 203 6 : if (_amount == 0) return 0; 204 : 205 : // special case if the weight = 100% - 206 4 : if (_reserveWeight == MAX_WEIGHT) return (_supply * _amount) / _reserveBalance; + 206 6 : if (_reserveWeight == MAX_WEIGHT) return (_supply * _amount) / _reserveBalance; 207 : - 208 4 : uint256 result; - 209 4 : uint8 precision; - 210 4 : uint256 baseN = _amount + _reserveBalance; - 211 4 : (result, precision) = power(baseN, _reserveBalance, _reserveWeight, MAX_WEIGHT); - 212 4 : uint256 temp = (_supply * result) >> precision; - 213 4 : return temp - _supply; + 208 6 : uint256 result; + 209 6 : uint8 precision; + 210 6 : uint256 baseN = _amount + _reserveBalance; + 211 6 : (result, precision) = power(baseN, _reserveBalance, _reserveWeight, MAX_WEIGHT); + 212 6 : uint256 temp = (_supply * result) >> precision; + 213 6 : return temp - _supply; 214 : } 215 : 216 : /** @@ -296,27 +296,27 @@ 234 : uint256 _amount 235 : ) internal view returns (uint256) { 236 : // validate input - 237 3 : require(_supply > 0, "ERR_INVALID_SUPPLY"); - 238 3 : require(_reserveBalance > 0, "ERR_INVALID_RESERVE_BALANCE"); - 239 3 : require(_reserveWeight > 0 && _reserveWeight <= MAX_WEIGHT, "ERR_INVALID_RESERVE_WEIGHT"); - 240 3 : require(_amount <= _supply, "ERR_INVALID_AMOUNT"); + 237 5 : require(_supply > 0, "ERR_INVALID_SUPPLY"); + 238 5 : require(_reserveBalance > 0, "ERR_INVALID_RESERVE_BALANCE"); + 239 5 : require(_reserveWeight > 0 && _reserveWeight <= MAX_WEIGHT, "ERR_INVALID_RESERVE_WEIGHT"); + 240 5 : require(_amount <= _supply, "ERR_INVALID_AMOUNT"); 241 : 242 : // special case for 0 sell amount - 243 3 : if (_amount == 0) return 0; + 243 5 : if (_amount == 0) return 0; 244 : 245 : // special case for selling the entire supply - 246 3 : if (_amount == _supply) return _reserveBalance; + 246 5 : if (_amount == _supply) return _reserveBalance; 247 : 248 : // special case if the weight = 100% - 249 3 : if (_reserveWeight == MAX_WEIGHT) return (_reserveBalance * _amount) / _supply; + 249 5 : if (_reserveWeight == MAX_WEIGHT) return (_reserveBalance * _amount) / _supply; 250 : - 251 3 : uint256 result; - 252 3 : uint8 precision; - 253 3 : uint256 baseD = _supply - _amount; - 254 3 : (result, precision) = power(_supply, baseD, MAX_WEIGHT, _reserveWeight); - 255 3 : uint256 temp1 = _reserveBalance * result; - 256 3 : uint256 temp2 = _reserveBalance << precision; - 257 3 : return (temp1 - temp2) / result; + 251 5 : uint256 result; + 252 5 : uint8 precision; + 253 5 : uint256 baseD = _supply - _amount; + 254 5 : (result, precision) = power(_supply, baseD, MAX_WEIGHT, _reserveWeight); + 255 5 : uint256 temp1 = _reserveBalance * result; + 256 5 : uint256 temp2 = _reserveBalance << precision; + 257 5 : return (temp1 - temp2) / result; 258 : } 259 : 260 : /** @@ -340,22 +340,22 @@ 278 : uint256 _amount 279 : ) internal view returns (uint256) { 280 : // validate input - 281 4 : require(_supply > 0, "ERR_INVALID_SUPPLY"); - 282 4 : require(_reserveBalance > 0, "ERR_INVALID_RESERVE_BALANCE"); - 283 4 : require(_reserveRatio > 1 && _reserveRatio <= MAX_WEIGHT * 2, "ERR_INVALID_RESERVE_RATIO"); + 281 6 : require(_supply > 0, "ERR_INVALID_SUPPLY"); + 282 6 : require(_reserveBalance > 0, "ERR_INVALID_RESERVE_BALANCE"); + 283 6 : require(_reserveRatio > 1 && _reserveRatio <= MAX_WEIGHT * 2, "ERR_INVALID_RESERVE_RATIO"); 284 : 285 : // special case for 0 amount - 286 4 : if (_amount == 0) return 0; + 286 6 : if (_amount == 0) return 0; 287 : 288 : // special case if the reserve ratio = 100% - 289 4 : if (_reserveRatio == MAX_WEIGHT) return (_amount * _reserveBalance - 1) / _supply + 1; + 289 6 : if (_reserveRatio == MAX_WEIGHT) return (_amount * _reserveBalance - 1) / _supply + 1; 290 : - 291 4 : uint256 result; - 292 4 : uint8 precision; - 293 4 : uint256 baseN = _supply + _amount; - 294 4 : (result, precision) = power(baseN, _supply, MAX_WEIGHT, _reserveRatio); - 295 4 : uint256 temp = ((_reserveBalance * result - 1) >> precision) + 1; - 296 4 : return temp - _reserveBalance; + 291 6 : uint256 result; + 292 6 : uint8 precision; + 293 6 : uint256 baseN = _supply + _amount; + 294 6 : (result, precision) = power(baseN, _supply, MAX_WEIGHT, _reserveRatio); + 295 6 : uint256 temp = ((_reserveBalance * result - 1) >> precision) + 1; + 296 6 : return temp - _reserveBalance; 297 : } 298 : 299 : /** @@ -379,22 +379,22 @@ 317 : uint256 _amount 318 : ) internal view returns (uint256) { 319 : // validate input - 320 3 : require(_supply > 0, "ERR_INVALID_SUPPLY"); - 321 3 : require(_reserveBalance > 0, "ERR_INVALID_RESERVE_BALANCE"); - 322 3 : require(_reserveRatio > 1 && _reserveRatio <= MAX_WEIGHT * 2, "ERR_INVALID_RESERVE_RATIO"); + 320 5 : require(_supply > 0, "ERR_INVALID_SUPPLY"); + 321 5 : require(_reserveBalance > 0, "ERR_INVALID_RESERVE_BALANCE"); + 322 5 : require(_reserveRatio > 1 && _reserveRatio <= MAX_WEIGHT * 2, "ERR_INVALID_RESERVE_RATIO"); 323 : 324 : // special case for 0 amount - 325 3 : if (_amount == 0) return 0; + 325 5 : if (_amount == 0) return 0; 326 : 327 : // special case if the reserve ratio = 100% - 328 3 : if (_reserveRatio == MAX_WEIGHT) return (_amount * _supply) / _reserveBalance; + 328 5 : if (_reserveRatio == MAX_WEIGHT) return (_amount * _supply) / _reserveBalance; 329 : - 330 3 : uint256 result; - 331 3 : uint8 precision; - 332 3 : uint256 baseN = _reserveBalance + _amount; - 333 3 : (result, precision) = power(baseN, _reserveBalance, _reserveRatio, MAX_WEIGHT); - 334 3 : uint256 temp = (_supply * result) >> precision; - 335 3 : return temp - _supply; + 330 5 : uint256 result; + 331 5 : uint8 precision; + 332 5 : uint256 baseN = _reserveBalance + _amount; + 333 5 : (result, precision) = power(baseN, _reserveBalance, _reserveRatio, MAX_WEIGHT); + 334 5 : uint256 temp = (_supply * result) >> precision; + 335 5 : return temp - _supply; 336 : } 337 : 338 : /** @@ -416,19 +416,19 @@ 354 : * Since we rely on unsigned-integer arithmetic and "base < 1" ==> "log(base) < 0", this function does not support "_baseN < _baseD". 355 : */ 356 : function power(uint256 _baseN, uint256 _baseD, uint32 _expN, uint32 _expD) internal view returns (uint256, uint8) { - 357 14 : require(_baseN < MAX_NUM); + 357 22 : require(_baseN < MAX_NUM); 358 : - 359 14 : uint256 baseLog; - 360 14 : uint256 base = (_baseN * FIXED_1) / _baseD; - 361 14 : if (base < OPT_LOG_MAX_VAL) { - 362 14 : baseLog = optimalLog(base); + 359 22 : uint256 baseLog; + 360 22 : uint256 base = (_baseN * FIXED_1) / _baseD; + 361 22 : if (base < OPT_LOG_MAX_VAL) { + 362 22 : baseLog = optimalLog(base); 363 : } else { 364 0 : baseLog = generalLog(base); 365 : } 366 : - 367 14 : uint256 baseLogTimesExp = (baseLog * _expN) / _expD; - 368 14 : if (baseLogTimesExp < OPT_EXP_MAX_VAL) { - 369 14 : return (optimalExp(baseLogTimesExp), MAX_PRECISION); + 367 22 : uint256 baseLogTimesExp = (baseLog * _expN) / _expD; + 368 22 : if (baseLogTimesExp < OPT_EXP_MAX_VAL) { + 369 22 : return (optimalExp(baseLogTimesExp), MAX_PRECISION); 370 : } else { 371 0 : uint8 precision = findPositionInMaxExpArray(baseLogTimesExp); 372 0 : return (generalExp(baseLogTimesExp >> (MAX_PRECISION - precision), precision), precision); @@ -600,64 +600,64 @@ 538 : * - For example: log(250) = log(e^4 * e^1 * e^0.5 * 1.021692859) = 4 + 1 + 0.5 + log(1 + 0.021692859) 539 : */ 540 : function optimalLog(uint256 x) internal pure returns (uint256) { - 541 14 : uint256 res = 0; + 541 22 : uint256 res = 0; 542 : - 543 14 : uint256 y; - 544 14 : uint256 z; - 545 14 : uint256 w; + 543 22 : uint256 y; + 544 22 : uint256 z; + 545 22 : uint256 w; 546 : - 547 14 : if (x >= 0xd3094c70f034de4b96ff7d5b6f99fcd8) { + 547 22 : if (x >= 0xd3094c70f034de4b96ff7d5b6f99fcd8) { 548 0 : res += 0x40000000000000000000000000000000; 549 0 : x = (x * FIXED_1) / 0xd3094c70f034de4b96ff7d5b6f99fcd8; 550 : } // add 1 / 2^1 - 551 14 : if (x >= 0xa45af1e1f40c333b3de1db4dd55f29a7) { + 551 22 : if (x >= 0xa45af1e1f40c333b3de1db4dd55f29a7) { 552 0 : res += 0x20000000000000000000000000000000; 553 0 : x = (x * FIXED_1) / 0xa45af1e1f40c333b3de1db4dd55f29a7; 554 : } // add 1 / 2^2 - 555 14 : if (x >= 0x910b022db7ae67ce76b441c27035c6a1) { + 555 22 : if (x >= 0x910b022db7ae67ce76b441c27035c6a1) { 556 0 : res += 0x10000000000000000000000000000000; 557 0 : x = (x * FIXED_1) / 0x910b022db7ae67ce76b441c27035c6a1; 558 : } // add 1 / 2^3 - 559 14 : if (x >= 0x88415abbe9a76bead8d00cf112e4d4a8) { + 559 22 : if (x >= 0x88415abbe9a76bead8d00cf112e4d4a8) { 560 0 : res += 0x08000000000000000000000000000000; 561 0 : x = (x * FIXED_1) / 0x88415abbe9a76bead8d00cf112e4d4a8; 562 : } // add 1 / 2^4 - 563 14 : if (x >= 0x84102b00893f64c705e841d5d4064bd3) { + 563 22 : if (x >= 0x84102b00893f64c705e841d5d4064bd3) { 564 0 : res += 0x04000000000000000000000000000000; 565 0 : x = (x * FIXED_1) / 0x84102b00893f64c705e841d5d4064bd3; 566 : } // add 1 / 2^5 - 567 14 : if (x >= 0x8204055aaef1c8bd5c3259f4822735a2) { - 568 0 : res += 0x02000000000000000000000000000000; - 569 0 : x = (x * FIXED_1) / 0x8204055aaef1c8bd5c3259f4822735a2; + 567 22 : if (x >= 0x8204055aaef1c8bd5c3259f4822735a2) { + 568 4 : res += 0x02000000000000000000000000000000; + 569 4 : x = (x * FIXED_1) / 0x8204055aaef1c8bd5c3259f4822735a2; 570 : } // add 1 / 2^6 - 571 14 : if (x >= 0x810100ab00222d861931c15e39b44e99) { + 571 22 : if (x >= 0x810100ab00222d861931c15e39b44e99) { 572 0 : res += 0x01000000000000000000000000000000; 573 0 : x = (x * FIXED_1) / 0x810100ab00222d861931c15e39b44e99; 574 : } // add 1 / 2^7 - 575 14 : if (x >= 0x808040155aabbbe9451521693554f733) { + 575 22 : if (x >= 0x808040155aabbbe9451521693554f733) { 576 0 : res += 0x00800000000000000000000000000000; 577 0 : x = (x * FIXED_1) / 0x808040155aabbbe9451521693554f733; 578 : } // add 1 / 2^8 579 : - 580 14 : z = y = x - FIXED_1; - 581 14 : w = (y * y) / FIXED_1; - 582 14 : res += (z * (0x100000000000000000000000000000000 - y)) / 0x100000000000000000000000000000000; - 583 14 : z = (z * w) / FIXED_1; // add y^01 / 01 - y^02 / 02 - 584 14 : res += (z * (0x0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - y)) / 0x200000000000000000000000000000000; - 585 14 : z = (z * w) / FIXED_1; // add y^03 / 03 - y^04 / 04 - 586 14 : res += (z * (0x099999999999999999999999999999999 - y)) / 0x300000000000000000000000000000000; - 587 14 : z = (z * w) / FIXED_1; // add y^05 / 05 - y^06 / 06 - 588 14 : res += (z * (0x092492492492492492492492492492492 - y)) / 0x400000000000000000000000000000000; - 589 14 : z = (z * w) / FIXED_1; // add y^07 / 07 - y^08 / 08 - 590 14 : res += (z * (0x08e38e38e38e38e38e38e38e38e38e38e - y)) / 0x500000000000000000000000000000000; - 591 14 : z = (z * w) / FIXED_1; // add y^09 / 09 - y^10 / 10 - 592 14 : res += (z * (0x08ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8b - y)) / 0x600000000000000000000000000000000; - 593 14 : z = (z * w) / FIXED_1; // add y^11 / 11 - y^12 / 12 - 594 14 : res += (z * (0x089d89d89d89d89d89d89d89d89d89d89 - y)) / 0x700000000000000000000000000000000; - 595 14 : z = (z * w) / FIXED_1; // add y^13 / 13 - y^14 / 14 - 596 14 : res += (z * (0x088888888888888888888888888888888 - y)) / 0x800000000000000000000000000000000; // add y^15 / 15 - y^16 / 16 + 580 22 : z = y = x - FIXED_1; + 581 22 : w = (y * y) / FIXED_1; + 582 22 : res += (z * (0x100000000000000000000000000000000 - y)) / 0x100000000000000000000000000000000; + 583 22 : z = (z * w) / FIXED_1; // add y^01 / 01 - y^02 / 02 + 584 22 : res += (z * (0x0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - y)) / 0x200000000000000000000000000000000; + 585 22 : z = (z * w) / FIXED_1; // add y^03 / 03 - y^04 / 04 + 586 22 : res += (z * (0x099999999999999999999999999999999 - y)) / 0x300000000000000000000000000000000; + 587 22 : z = (z * w) / FIXED_1; // add y^05 / 05 - y^06 / 06 + 588 22 : res += (z * (0x092492492492492492492492492492492 - y)) / 0x400000000000000000000000000000000; + 589 22 : z = (z * w) / FIXED_1; // add y^07 / 07 - y^08 / 08 + 590 22 : res += (z * (0x08e38e38e38e38e38e38e38e38e38e38e - y)) / 0x500000000000000000000000000000000; + 591 22 : z = (z * w) / FIXED_1; // add y^09 / 09 - y^10 / 10 + 592 22 : res += (z * (0x08ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8b - y)) / 0x600000000000000000000000000000000; + 593 22 : z = (z * w) / FIXED_1; // add y^11 / 11 - y^12 / 12 + 594 22 : res += (z * (0x089d89d89d89d89d89d89d89d89d89d89 - y)) / 0x700000000000000000000000000000000; + 595 22 : z = (z * w) / FIXED_1; // add y^13 / 13 - y^14 / 14 + 596 22 : res += (z * (0x088888888888888888888888888888888 - y)) / 0x800000000000000000000000000000000; // add y^15 / 15 - y^16 / 16 597 : - 598 14 : return res; + 598 22 : return res; 599 : } 600 : 601 : /** @@ -672,68 +672,68 @@ 610 : * - For example: e^5.521692859 = e^(4 + 1 + 0.5 + 0.021692859) = e^4 * e^1 * e^0.5 * e^0.021692859 611 : */ 612 : function optimalExp(uint256 x) internal pure returns (uint256) { - 613 14 : uint256 res = 0; + 613 22 : uint256 res = 0; 614 : - 615 14 : uint256 y; - 616 14 : uint256 z; + 615 22 : uint256 y; + 616 22 : uint256 z; 617 : - 618 14 : z = y = x % 0x10000000000000000000000000000000; // get the input modulo 2^(-3) - 619 14 : z = (z * y) / FIXED_1; - 620 14 : res += z * 0x10e1b3be415a0000; // add y^02 * (20! / 02!) - 621 14 : z = (z * y) / FIXED_1; - 622 14 : res += z * 0x05a0913f6b1e0000; // add y^03 * (20! / 03!) - 623 14 : z = (z * y) / FIXED_1; - 624 14 : res += z * 0x0168244fdac78000; // add y^04 * (20! / 04!) - 625 14 : z = (z * y) / FIXED_1; - 626 14 : res += z * 0x004807432bc18000; // add y^05 * (20! / 05!) - 627 14 : z = (z * y) / FIXED_1; - 628 14 : res += z * 0x000c0135dca04000; // add y^06 * (20! / 06!) - 629 14 : z = (z * y) / FIXED_1; - 630 14 : res += z * 0x0001b707b1cdc000; // add y^07 * (20! / 07!) - 631 14 : z = (z * y) / FIXED_1; - 632 14 : res += z * 0x000036e0f639b800; // add y^08 * (20! / 08!) - 633 14 : z = (z * y) / FIXED_1; - 634 14 : res += z * 0x00000618fee9f800; // add y^09 * (20! / 09!) - 635 14 : z = (z * y) / FIXED_1; - 636 14 : res += z * 0x0000009c197dcc00; // add y^10 * (20! / 10!) - 637 14 : z = (z * y) / FIXED_1; - 638 14 : res += z * 0x0000000e30dce400; // add y^11 * (20! / 11!) - 639 14 : z = (z * y) / FIXED_1; - 640 14 : res += z * 0x000000012ebd1300; // add y^12 * (20! / 12!) - 641 14 : z = (z * y) / FIXED_1; - 642 14 : res += z * 0x0000000017499f00; // add y^13 * (20! / 13!) - 643 14 : z = (z * y) / FIXED_1; - 644 14 : res += z * 0x0000000001a9d480; // add y^14 * (20! / 14!) - 645 14 : z = (z * y) / FIXED_1; - 646 14 : res += z * 0x00000000001c6380; // add y^15 * (20! / 15!) - 647 14 : z = (z * y) / FIXED_1; - 648 14 : res += z * 0x000000000001c638; // add y^16 * (20! / 16!) - 649 14 : z = (z * y) / FIXED_1; - 650 14 : res += z * 0x0000000000001ab8; // add y^17 * (20! / 17!) - 651 14 : z = (z * y) / FIXED_1; - 652 14 : res += z * 0x000000000000017c; // add y^18 * (20! / 18!) - 653 14 : z = (z * y) / FIXED_1; - 654 14 : res += z * 0x0000000000000014; // add y^19 * (20! / 19!) - 655 14 : z = (z * y) / FIXED_1; - 656 14 : res += z * 0x0000000000000001; // add y^20 * (20! / 20!) - 657 14 : res = res / 0x21c3677c82b40000 + y + FIXED_1; // divide by 20! and then add y^1 / 1! + y^0 / 0! + 618 22 : z = y = x % 0x10000000000000000000000000000000; // get the input modulo 2^(-3) + 619 22 : z = (z * y) / FIXED_1; + 620 22 : res += z * 0x10e1b3be415a0000; // add y^02 * (20! / 02!) + 621 22 : z = (z * y) / FIXED_1; + 622 22 : res += z * 0x05a0913f6b1e0000; // add y^03 * (20! / 03!) + 623 22 : z = (z * y) / FIXED_1; + 624 22 : res += z * 0x0168244fdac78000; // add y^04 * (20! / 04!) + 625 22 : z = (z * y) / FIXED_1; + 626 22 : res += z * 0x004807432bc18000; // add y^05 * (20! / 05!) + 627 22 : z = (z * y) / FIXED_1; + 628 22 : res += z * 0x000c0135dca04000; // add y^06 * (20! / 06!) + 629 22 : z = (z * y) / FIXED_1; + 630 22 : res += z * 0x0001b707b1cdc000; // add y^07 * (20! / 07!) + 631 22 : z = (z * y) / FIXED_1; + 632 22 : res += z * 0x000036e0f639b800; // add y^08 * (20! / 08!) + 633 22 : z = (z * y) / FIXED_1; + 634 22 : res += z * 0x00000618fee9f800; // add y^09 * (20! / 09!) + 635 22 : z = (z * y) / FIXED_1; + 636 22 : res += z * 0x0000009c197dcc00; // add y^10 * (20! / 10!) + 637 22 : z = (z * y) / FIXED_1; + 638 22 : res += z * 0x0000000e30dce400; // add y^11 * (20! / 11!) + 639 22 : z = (z * y) / FIXED_1; + 640 22 : res += z * 0x000000012ebd1300; // add y^12 * (20! / 12!) + 641 22 : z = (z * y) / FIXED_1; + 642 22 : res += z * 0x0000000017499f00; // add y^13 * (20! / 13!) + 643 22 : z = (z * y) / FIXED_1; + 644 22 : res += z * 0x0000000001a9d480; // add y^14 * (20! / 14!) + 645 22 : z = (z * y) / FIXED_1; + 646 22 : res += z * 0x00000000001c6380; // add y^15 * (20! / 15!) + 647 22 : z = (z * y) / FIXED_1; + 648 22 : res += z * 0x000000000001c638; // add y^16 * (20! / 16!) + 649 22 : z = (z * y) / FIXED_1; + 650 22 : res += z * 0x0000000000001ab8; // add y^17 * (20! / 17!) + 651 22 : z = (z * y) / FIXED_1; + 652 22 : res += z * 0x000000000000017c; // add y^18 * (20! / 18!) + 653 22 : z = (z * y) / FIXED_1; + 654 22 : res += z * 0x0000000000000014; // add y^19 * (20! / 19!) + 655 22 : z = (z * y) / FIXED_1; + 656 22 : res += z * 0x0000000000000001; // add y^20 * (20! / 20!) + 657 22 : res = res / 0x21c3677c82b40000 + y + FIXED_1; // divide by 20! and then add y^1 / 1! + y^0 / 0! 658 : - 659 14 : if ((x & 0x010000000000000000000000000000000) != 0) + 659 22 : if ((x & 0x010000000000000000000000000000000) != 0) 660 0 : res = (res * 0x1c3d6a24ed82218787d624d3e5eba95f9) / 0x18ebef9eac820ae8682b9793ac6d1e776; // multiply by e^2^(-3) - 661 14 : if ((x & 0x020000000000000000000000000000000) != 0) + 661 22 : if ((x & 0x020000000000000000000000000000000) != 0) 662 0 : res = (res * 0x18ebef9eac820ae8682b9793ac6d1e778) / 0x1368b2fc6f9609fe7aceb46aa619baed4; // multiply by e^2^(-2) - 663 14 : if ((x & 0x040000000000000000000000000000000) != 0) + 663 22 : if ((x & 0x040000000000000000000000000000000) != 0) 664 0 : res = (res * 0x1368b2fc6f9609fe7aceb46aa619baed5) / 0x0bc5ab1b16779be3575bd8f0520a9f21f; // multiply by e^2^(-1) - 665 14 : if ((x & 0x080000000000000000000000000000000) != 0) + 665 22 : if ((x & 0x080000000000000000000000000000000) != 0) 666 0 : res = (res * 0x0bc5ab1b16779be3575bd8f0520a9f21e) / 0x0454aaa8efe072e7f6ddbab84b40a55c9; // multiply by e^2^(+0) - 667 14 : if ((x & 0x100000000000000000000000000000000) != 0) + 667 22 : if ((x & 0x100000000000000000000000000000000) != 0) 668 0 : res = (res * 0x0454aaa8efe072e7f6ddbab84b40a55c5) / 0x00960aadc109e7a3bf4578099615711ea; // multiply by e^2^(+1) - 669 14 : if ((x & 0x200000000000000000000000000000000) != 0) + 669 22 : if ((x & 0x200000000000000000000000000000000) != 0) 670 0 : res = (res * 0x00960aadc109e7a3bf4578099615711d7) / 0x0002bf84208204f5977f9a8cf01fdce3d; // multiply by e^2^(+2) - 671 14 : if ((x & 0x400000000000000000000000000000000) != 0) + 671 22 : if ((x & 0x400000000000000000000000000000000) != 0) 672 0 : res = (res * 0x0002bf84208204f5977f9a8cf01fdc307) / 0x0000003c6ab775dd0b95b4cbee7e65d11; // multiply by e^2^(+3) 673 : - 674 14 : return res; + 674 22 : return res; 675 : } 676 : } diff --git a/coverage_report/contracts/GoodDollarExchangeProvider.sol.func-c.html b/coverage_report/contracts/GoodDollarExchangeProvider.sol.func-c.html index ca7637b..3ddd205 100644 --- a/coverage_report/contracts/GoodDollarExchangeProvider.sol.func-c.html +++ b/coverage_report/contracts/GoodDollarExchangeProvider.sol.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % @@ -70,44 +70,44 @@ - GoodDollarExchangeProvider.swapIn + GoodDollarExchangeProvider.unpause 2 - GoodDollarExchangeProvider.swapOut + GoodDollarExchangeProvider.pause - 2 + 3 - GoodDollarExchangeProvider.unpause + GoodDollarExchangeProvider.setAvatar - 2 + 3 - GoodDollarExchangeProvider.pause + GoodDollarExchangeProvider.setExpansionController 3 - GoodDollarExchangeProvider.setAvatar + GoodDollarExchangeProvider.swapIn - 3 + 4 - GoodDollarExchangeProvider.setExpansionController + GoodDollarExchangeProvider.swapOut - 3 + 4 @@ -121,35 +121,35 @@ GoodDollarExchangeProvider.mintFromInterest - 7 + 8 GoodDollarExchangeProvider.mintFromExpansion - 8 + 9 GoodDollarExchangeProvider.onlyExpansionController - 8 + 9 GoodDollarExchangeProvider. - 25 + 31 GoodDollarExchangeProvider.initialize - 25 + 31 diff --git a/coverage_report/contracts/GoodDollarExchangeProvider.sol.func.html b/coverage_report/contracts/GoodDollarExchangeProvider.sol.func.html index 0914bc6..f68594f 100644 --- a/coverage_report/contracts/GoodDollarExchangeProvider.sol.func.html +++ b/coverage_report/contracts/GoodDollarExchangeProvider.sol.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % @@ -65,28 +65,28 @@ GoodDollarExchangeProvider. - 25 + 31 GoodDollarExchangeProvider.initialize - 25 + 31 GoodDollarExchangeProvider.mintFromExpansion - 8 + 9 GoodDollarExchangeProvider.mintFromInterest - 7 + 8 @@ -100,7 +100,7 @@ GoodDollarExchangeProvider.onlyExpansionController - 8 + 9 @@ -128,14 +128,14 @@ GoodDollarExchangeProvider.swapIn - 2 + 4 GoodDollarExchangeProvider.swapOut - 2 + 4 diff --git a/coverage_report/contracts/GoodDollarExchangeProvider.sol.gcov.html b/coverage_report/contracts/GoodDollarExchangeProvider.sol.gcov.html index 7fdce5a..acad0fd 100644 --- a/coverage_report/contracts/GoodDollarExchangeProvider.sol.gcov.html +++ b/coverage_report/contracts/GoodDollarExchangeProvider.sol.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % @@ -110,11 +110,11 @@ 48 : address _expansionController, 49 : address _avatar 50 : ) public initializer { - 51 25 : BancorExchangeProvider._initialize(_broker, _reserve); - 52 25 : __Pausable_init(); + 51 31 : BancorExchangeProvider._initialize(_broker, _reserve); + 52 31 : __Pausable_init(); 53 : - 54 25 : setExpansionController(_expansionController); - 55 25 : setAvatar(_avatar); + 54 31 : setExpansionController(_expansionController); + 55 31 : setAvatar(_avatar); 56 : } 57 : 58 : /* ==================== Modifiers ==================== */ @@ -125,7 +125,7 @@ 63 : } 64 : 65 : modifier onlyExpansionController() { - 66 8 : require(msg.sender == address(expansionController), "Only ExpansionController can call this function"); + 66 9 : require(msg.sender == address(expansionController), "Only ExpansionController can call this function"); 67 : _; 68 : } 69 : @@ -136,9 +136,9 @@ 74 : * @param _avatar The address of the DAO contract. 75 : */ 76 : function setAvatar(address _avatar) public onlyOwner { - 77 27 : require(_avatar != address(0), "Avatar address must be set"); - 78 26 : AVATAR = _avatar; - 79 26 : emit AvatarUpdated(_avatar); + 77 33 : require(_avatar != address(0), "Avatar address must be set"); + 78 32 : AVATAR = _avatar; + 79 32 : emit AvatarUpdated(_avatar); 80 : } 81 : 82 : /** @@ -146,9 +146,9 @@ 84 : * @param _expansionController The address of the Expansion Controller contract. 85 : */ 86 : function setExpansionController(address _expansionController) public onlyOwner { - 87 27 : require(_expansionController != address(0), "ExpansionController address must be set"); - 88 26 : expansionController = IGoodDollarExpansionController(_expansionController); - 89 26 : emit ExpansionControllerUpdated(_expansionController); + 87 33 : require(_expansionController != address(0), "ExpansionController address must be set"); + 88 32 : expansionController = IGoodDollarExpansionController(_expansionController); + 89 32 : emit ExpansionControllerUpdated(_expansionController); 90 : } 91 : 92 : /** @@ -165,7 +165,7 @@ 103 : address tokenOut, 104 : uint256 amountIn 105 : ) public override onlyBroker whenNotPaused returns (uint256 amountOut) { - 106 1 : amountOut = BancorExchangeProvider.swapIn(exchangeId, tokenIn, tokenOut, amountIn); + 106 3 : amountOut = BancorExchangeProvider.swapIn(exchangeId, tokenIn, tokenOut, amountIn); 107 : } 108 : 109 : /** @@ -182,7 +182,7 @@ 120 : address tokenOut, 121 : uint256 amountOut 122 : ) public override onlyBroker whenNotPaused returns (uint256 amountIn) { - 123 1 : amountIn = BancorExchangeProvider.swapOut(exchangeId, tokenIn, tokenOut, amountOut); + 123 3 : amountIn = BancorExchangeProvider.swapOut(exchangeId, tokenIn, tokenOut, amountOut); 124 : } 125 : 126 : /** @@ -198,24 +198,24 @@ 136 : bytes32 exchangeId, 137 : uint256 expansionScaler 138 : ) external onlyExpansionController whenNotPaused returns (uint256 amountToMint) { - 139 6 : require(expansionScaler > 0, "Expansion rate must be greater than 0"); - 140 5 : PoolExchange memory exchange = getPoolExchange(exchangeId); + 139 7 : require(expansionScaler > 0, "Expansion rate must be greater than 0"); + 140 6 : PoolExchange memory exchange = getPoolExchange(exchangeId); 141 : - 142 4 : UD60x18 scaledRatio = wrap(uint256(exchange.reserveRatio) * 1e10); - 143 4 : UD60x18 newRatio = scaledRatio.mul(wrap(expansionScaler)); + 142 5 : UD60x18 scaledRatio = wrap(uint256(exchange.reserveRatio) * 1e10); + 143 5 : UD60x18 newRatio = scaledRatio.mul(wrap(expansionScaler)); 144 : - 145 4 : UD60x18 numerator = wrap(exchange.tokenSupply).mul(scaledRatio); - 146 4 : numerator = numerator.sub(wrap(exchange.tokenSupply).mul(newRatio)); + 145 5 : UD60x18 numerator = wrap(exchange.tokenSupply).mul(scaledRatio); + 146 5 : numerator = numerator.sub(wrap(exchange.tokenSupply).mul(newRatio)); 147 : - 148 4 : uint256 scaledAmountToMint = unwrap(numerator.div(newRatio)); - 149 4 : uint32 newRatioUint = uint32(unwrap(newRatio) / 1e10); + 148 5 : uint256 scaledAmountToMint = unwrap(numerator.div(newRatio)); + 149 5 : uint32 newRatioUint = uint32(unwrap(newRatio) / 1e10); 150 : - 151 4 : exchanges[exchangeId].reserveRatio = newRatioUint; - 152 4 : exchanges[exchangeId].tokenSupply += scaledAmountToMint; + 151 5 : exchanges[exchangeId].reserveRatio = newRatioUint; + 152 5 : exchanges[exchangeId].tokenSupply += scaledAmountToMint; 153 : - 154 4 : amountToMint = scaledAmountToMint / tokenPrecisionMultipliers[exchange.tokenAddress]; - 155 4 : emit ReserveRatioUpdated(exchangeId, newRatioUint); - 156 4 : return amountToMint; + 154 5 : amountToMint = scaledAmountToMint / tokenPrecisionMultipliers[exchange.tokenAddress]; + 155 5 : emit ReserveRatioUpdated(exchangeId, newRatioUint); + 156 5 : return amountToMint; 157 : } 158 : 159 : /** @@ -231,18 +231,18 @@ 169 : bytes32 exchangeId, 170 : uint256 reserveInterest 171 : ) external onlyExpansionController whenNotPaused returns (uint256 amountToMint) { - 172 5 : PoolExchange memory exchange = getPoolExchange(exchangeId); + 172 6 : PoolExchange memory exchange = getPoolExchange(exchangeId); 173 : - 174 4 : uint256 reserveinterestScaled = reserveInterest * tokenPrecisionMultipliers[exchange.reserveAsset]; - 175 4 : uint256 amountToMintScaled = unwrap( + 174 5 : uint256 reserveinterestScaled = reserveInterest * tokenPrecisionMultipliers[exchange.reserveAsset]; + 175 5 : uint256 amountToMintScaled = unwrap( 176 : wrap(reserveinterestScaled).mul(wrap(exchange.tokenSupply)).div(wrap(exchange.reserveBalance)) 177 : ); - 178 4 : amountToMint = amountToMintScaled / tokenPrecisionMultipliers[exchange.tokenAddress]; + 178 5 : amountToMint = amountToMintScaled / tokenPrecisionMultipliers[exchange.tokenAddress]; 179 : - 180 4 : exchanges[exchangeId].tokenSupply += amountToMintScaled; - 181 4 : exchanges[exchangeId].reserveBalance += reserveinterestScaled; + 180 5 : exchanges[exchangeId].tokenSupply += amountToMintScaled; + 181 5 : exchanges[exchangeId].reserveBalance += reserveinterestScaled; 182 : - 183 4 : return amountToMint; + 183 5 : return amountToMint; 184 : } 185 : 186 : /** diff --git a/coverage_report/contracts/GoodDollarExpansionController.sol.func-c.html b/coverage_report/contracts/GoodDollarExpansionController.sol.func-c.html index 0f897a4..093ab65 100644 --- a/coverage_report/contracts/GoodDollarExpansionController.sol.func-c.html +++ b/coverage_report/contracts/GoodDollarExpansionController.sol.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % @@ -63,16 +63,16 @@ - GoodDollarExpansionController.mintUBIFromInterest + GoodDollarExpansionController.mintUBIFromReserveBalance 2 - GoodDollarExpansionController.mintUBIFromReserveBalance + GoodDollarExpansionController.mintUBIFromInterest - 2 + 3 @@ -119,14 +119,14 @@ - GoodDollarExpansionController.mintUBIFromExpansion + GoodDollarExpansionController.getExpansionConfig - 9 + 10 - GoodDollarExpansionController.getExpansionConfig + GoodDollarExpansionController.mintUBIFromExpansion 10 @@ -135,21 +135,21 @@ GoodDollarExpansionController.setExpansionConfig - 20 + 26 GoodDollarExpansionController. - 34 + 40 GoodDollarExpansionController.initialize - 34 + 40 diff --git a/coverage_report/contracts/GoodDollarExpansionController.sol.func.html b/coverage_report/contracts/GoodDollarExpansionController.sol.func.html index b93b9f3..fea0aa9 100644 --- a/coverage_report/contracts/GoodDollarExpansionController.sol.func.html +++ b/coverage_report/contracts/GoodDollarExpansionController.sol.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % @@ -65,7 +65,7 @@ GoodDollarExpansionController. - 34 + 40 @@ -79,7 +79,7 @@ GoodDollarExpansionController.initialize - 34 + 40 @@ -93,14 +93,14 @@ GoodDollarExpansionController.mintUBIFromExpansion - 9 + 10 GoodDollarExpansionController.mintUBIFromInterest - 2 + 3 @@ -135,7 +135,7 @@ GoodDollarExpansionController.setExpansionConfig - 20 + 26 diff --git a/coverage_report/contracts/GoodDollarExpansionController.sol.gcov.html b/coverage_report/contracts/GoodDollarExpansionController.sol.gcov.html index ab83374..2963aff 100644 --- a/coverage_report/contracts/GoodDollarExpansionController.sol.gcov.html +++ b/coverage_report/contracts/GoodDollarExpansionController.sol.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % @@ -133,13 +133,13 @@ 71 : address _reserve, 72 : address _avatar 73 : ) public initializer { - 74 34 : __Pausable_init(); - 75 34 : __Ownable_init(); + 74 40 : __Pausable_init(); + 75 40 : __Ownable_init(); 76 : - 77 34 : setGoodDollarExchangeProvider(_goodDollarExchangeProvider); - 78 34 : setDistributionHelper(_distributionHelper); - 79 34 : setReserve(_reserve); - 80 34 : setAvatar(_avatar); + 77 40 : setGoodDollarExchangeProvider(_goodDollarExchangeProvider); + 78 40 : setDistributionHelper(_distributionHelper); + 79 40 : setReserve(_reserve); + 80 40 : setAvatar(_avatar); 81 : } 82 : 83 : /* ==================== Modifiers ==================== */ @@ -159,11 +159,11 @@ 97 : function getExpansionConfig( 98 : bytes32 exchangeId 99 : ) public view returns (ExchangeExpansionConfig memory) { - 100 19 : require( + 100 20 : require( 101 : exchangeExpansionConfigs[exchangeId].expansionRate > 0, 102 : "Expansion config not set" 103 : ); - 104 17 : return exchangeExpansionConfigs[exchangeId]; + 104 18 : return exchangeExpansionConfigs[exchangeId]; 105 : } 106 : 107 : /* ==================== Mutative Functions ==================== */ @@ -175,14 +175,14 @@ 113 : function setGoodDollarExchangeProvider( 114 : address _goodDollarExchangeProvider 115 : ) public onlyOwner { - 116 36 : require( + 116 42 : require( 117 : _goodDollarExchangeProvider != address(0), 118 : "GoodDollarExchangeProvider address must be set" 119 : ); - 120 35 : goodDollarExchangeProvider = IGoodDollarExchangeProvider( + 120 41 : goodDollarExchangeProvider = IGoodDollarExchangeProvider( 121 : _goodDollarExchangeProvider 122 : ); - 123 35 : emit GoodDollarExchangeProviderUpdated(_goodDollarExchangeProvider); + 123 41 : emit GoodDollarExchangeProviderUpdated(_goodDollarExchangeProvider); 124 : } 125 : 126 : /** @@ -192,12 +192,12 @@ 130 : function setDistributionHelper( 131 : address _distributionHelper 132 : ) public onlyOwner { - 133 36 : require( + 133 42 : require( 134 : _distributionHelper != address(0), 135 : "DistributionHelper address must be set" 136 : ); - 137 35 : distributionHelper = IDistributionHelper(_distributionHelper); - 138 35 : emit DistributionHelperUpdated(_distributionHelper); + 137 41 : distributionHelper = IDistributionHelper(_distributionHelper); + 138 41 : emit DistributionHelperUpdated(_distributionHelper); 139 : } 140 : 141 : /** @@ -205,9 +205,9 @@ 143 : * @param _reserve The address of the reserve contract. 144 : */ 145 : function setReserve(address _reserve) public onlyOwner { - 146 36 : require(_reserve != address(0), "Reserve address must be set"); - 147 35 : reserve = _reserve; - 148 35 : emit ReserveUpdated(_reserve); + 146 42 : require(_reserve != address(0), "Reserve address must be set"); + 147 41 : reserve = _reserve; + 148 41 : emit ReserveUpdated(_reserve); 149 : } 150 : 151 : /** @@ -215,9 +215,9 @@ 153 : * @param _avatar The address of the AVATAR contract. 154 : */ 155 : function setAvatar(address _avatar) public onlyOwner { - 156 36 : require(_avatar != address(0), "Avatar address must be set"); - 157 35 : AVATAR = _avatar; - 158 35 : emit AvatarUpdated(_avatar); + 156 42 : require(_avatar != address(0), "Avatar address must be set"); + 157 41 : AVATAR = _avatar; + 158 41 : emit AvatarUpdated(_avatar); 159 : } 160 : 161 : /** @@ -231,21 +231,21 @@ 169 : uint64 expansionRate, 170 : uint32 expansionFrequency 171 : ) external onlyAvatar { - 172 19 : require( + 172 25 : require( 173 : expansionRate < MAX_WEIGHT, 174 : "Expansion rate must be less than 100%" 175 : ); - 176 18 : require(expansionRate > 0, "Expansion rate must be greater than 0"); - 177 17 : require( + 176 24 : require(expansionRate > 0, "Expansion rate must be greater than 0"); + 177 23 : require( 178 : expansionFrequency > 0, 179 : "Expansion frequency must be greater than 0" 180 : ); 181 : - 182 16 : exchangeExpansionConfigs[exchangeId].expansionRate = expansionRate; - 183 16 : exchangeExpansionConfigs[exchangeId] + 182 22 : exchangeExpansionConfigs[exchangeId].expansionRate = expansionRate; + 183 22 : exchangeExpansionConfigs[exchangeId] 184 : .expansionFrequency = expansionFrequency; 185 : - 186 16 : emit ExpansionConfigSet(exchangeId, expansionRate, expansionFrequency); + 186 22 : emit ExpansionConfigSet(exchangeId, expansionRate, expansionFrequency); 187 : } 188 : 189 : /** @@ -257,18 +257,18 @@ 195 : bytes32 exchangeId, 196 : uint256 reserveInterest 197 : ) external { - 198 2 : require(reserveInterest > 0, "reserveInterest must be greater than 0"); - 199 1 : IBancorExchangeProvider.PoolExchange - 200 1 : memory exchange = IBancorExchangeProvider( + 198 3 : require(reserveInterest > 0, "reserveInterest must be greater than 0"); + 199 2 : IBancorExchangeProvider.PoolExchange + 200 2 : memory exchange = IBancorExchangeProvider( 201 : address(goodDollarExchangeProvider) 202 : ).getPoolExchange(exchangeId); 203 : - 204 1 : uint256 amountToMint = goodDollarExchangeProvider.mintFromInterest( + 204 2 : uint256 amountToMint = goodDollarExchangeProvider.mintFromInterest( 205 : exchangeId, 206 : reserveInterest 207 : ); 208 : - 209 1 : require( + 209 2 : require( 210 : IERC20(exchange.reserveAsset).transferFrom( 211 : msg.sender, 212 : reserve, @@ -276,11 +276,11 @@ 214 : ), 215 : "Transfer failed" 216 : ); - 217 1 : IGoodDollar(exchange.tokenAddress).mint( + 217 2 : IGoodDollar(exchange.tokenAddress).mint( 218 : address(distributionHelper), 219 : amountToMint 220 : ); - 221 1 : emit InterestUBIMinted(exchangeId, amountToMint); + 221 2 : emit InterestUBIMinted(exchangeId, amountToMint); 222 : } 223 : 224 : /** @@ -322,45 +322,45 @@ 260 : function mintUBIFromExpansion( 261 : bytes32 exchangeId 262 : ) external returns (uint256 amountMinted) { - 263 9 : ExchangeExpansionConfig memory config = getExpansionConfig(exchangeId); - 264 8 : IBancorExchangeProvider.PoolExchange - 265 8 : memory exchange = IBancorExchangeProvider( + 263 10 : ExchangeExpansionConfig memory config = getExpansionConfig(exchangeId); + 264 9 : IBancorExchangeProvider.PoolExchange + 265 9 : memory exchange = IBancorExchangeProvider( 266 : address(goodDollarExchangeProvider) 267 : ).getPoolExchange(exchangeId); 268 : - 269 8 : bool shouldExpand = block.timestamp > - 270 8 : config.lastExpansion + config.expansionFrequency; - 271 8 : if (shouldExpand || config.lastExpansion == 0) { - 272 7 : uint256 numberOfExpansions; + 269 9 : bool shouldExpand = block.timestamp > + 270 9 : config.lastExpansion + config.expansionFrequency; + 271 9 : if (shouldExpand || config.lastExpansion == 0) { + 272 8 : uint256 numberOfExpansions; 273 : 274 : //special case for first expansion - 275 7 : if (config.lastExpansion == 0) { - 276 5 : numberOfExpansions = 1; + 275 8 : if (config.lastExpansion == 0) { + 276 6 : numberOfExpansions = 1; 277 : } else { 278 2 : numberOfExpansions = 279 : (block.timestamp - config.lastExpansion) / 280 : config.expansionFrequency; 281 : } 282 : - 283 7 : uint256 stepExpansionScaler = MAX_WEIGHT - config.expansionRate; - 284 7 : uint256 expansionScaler = unwrap( + 283 8 : uint256 stepExpansionScaler = MAX_WEIGHT - config.expansionRate; + 284 8 : uint256 expansionScaler = unwrap( 285 : powu(wrap(stepExpansionScaler), numberOfExpansions) 286 : ); 287 : - 288 7 : exchangeExpansionConfigs[exchangeId].lastExpansion = uint32( + 288 8 : exchangeExpansionConfigs[exchangeId].lastExpansion = uint32( 289 : block.timestamp 290 : ); - 291 7 : amountMinted = goodDollarExchangeProvider.mintFromExpansion( + 291 8 : amountMinted = goodDollarExchangeProvider.mintFromExpansion( 292 : exchangeId, 293 : expansionScaler 294 : ); 295 : - 296 7 : IGoodDollar(exchange.tokenAddress).mint( + 296 8 : IGoodDollar(exchange.tokenAddress).mint( 297 : address(distributionHelper), 298 : amountMinted 299 : ); - 300 7 : distributionHelper.onDistribution(amountMinted); - 301 7 : emit ExpansionUBIMinted(exchangeId, amountMinted); + 300 8 : distributionHelper.onDistribution(amountMinted); + 301 8 : emit ExpansionUBIMinted(exchangeId, amountMinted); 302 : } 303 : } 304 : diff --git a/coverage_report/contracts/common/SafeERC20MintableBurnable.sol.func-c.html b/coverage_report/contracts/common/SafeERC20MintableBurnable.sol.func-c.html index 27eba3e..7cc7c51 100644 --- a/coverage_report/contracts/common/SafeERC20MintableBurnable.sol.func-c.html +++ b/coverage_report/contracts/common/SafeERC20MintableBurnable.sol.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % @@ -65,28 +65,28 @@ SafeERC20MintableBurnable.safeBurn - 3 + 5 SafeERC20MintableBurnable.safeMint - 3 + 5 SafeERC20MintableBurnable.safeTransferFrom - 6 + 10 SafeERC20MintableBurnable._callOptionalReturn - 12 + 20 diff --git a/coverage_report/contracts/common/SafeERC20MintableBurnable.sol.func.html b/coverage_report/contracts/common/SafeERC20MintableBurnable.sol.func.html index 3f7ae2f..4524c34 100644 --- a/coverage_report/contracts/common/SafeERC20MintableBurnable.sol.func.html +++ b/coverage_report/contracts/common/SafeERC20MintableBurnable.sol.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % @@ -65,28 +65,28 @@ SafeERC20MintableBurnable._callOptionalReturn - 12 + 20 SafeERC20MintableBurnable.safeBurn - 3 + 5 SafeERC20MintableBurnable.safeMint - 3 + 5 SafeERC20MintableBurnable.safeTransferFrom - 6 + 10 diff --git a/coverage_report/contracts/common/SafeERC20MintableBurnable.sol.gcov.html b/coverage_report/contracts/common/SafeERC20MintableBurnable.sol.gcov.html index f3d6b18..ca155ad 100644 --- a/coverage_report/contracts/common/SafeERC20MintableBurnable.sol.gcov.html +++ b/coverage_report/contracts/common/SafeERC20MintableBurnable.sol.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % @@ -78,15 +78,15 @@ 16 : using Address for address; 17 : 18 : function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { - 19 6 : _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); + 19 10 : _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 20 : } 21 : 22 : function safeMint(IERC20 token, address account, uint256 amount) internal { - 23 3 : _callOptionalReturn(token, abi.encodeWithSelector(token.mint.selector, account, amount)); + 23 5 : _callOptionalReturn(token, abi.encodeWithSelector(token.mint.selector, account, amount)); 24 : } 25 : 26 : function safeBurn(IERC20 token, uint256 amount) internal { - 27 3 : _callOptionalReturn(token, abi.encodeWithSelector(token.burn.selector, amount)); + 27 5 : _callOptionalReturn(token, abi.encodeWithSelector(token.burn.selector, amount)); 28 : } 29 : 30 : /** @@ -100,10 +100,10 @@ 38 : // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that 39 : // the target address contains contract code and also asserts for success in the low-level call. 40 : - 41 12 : bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - 42 12 : if (returndata.length > 0) { + 41 20 : bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); + 42 20 : if (returndata.length > 0) { 43 : // Return data is optional - 44 12 : require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); + 44 18 : require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 45 : } 46 : } 47 : } diff --git a/coverage_report/contracts/common/UsingRegistry.sol.func-c.html b/coverage_report/contracts/common/UsingRegistry.sol.func-c.html new file mode 100644 index 0000000..bb7b22d --- /dev/null +++ b/coverage_report/contracts/common/UsingRegistry.sol.func-c.html @@ -0,0 +1,138 @@ + + + + + + + LCOV - lcov.info - contracts/common/UsingRegistry.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - contracts/common - UsingRegistry.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:27.3 %113
Test Date:2024-10-08 18:32:54Functions:0.0 %90
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
UsingRegistry.getExchange0
UsingRegistry.getFreezer0
UsingRegistry.getGoldToken0
UsingRegistry.getReserve0
UsingRegistry.getSortedOracles0
UsingRegistry.getStableToken0
UsingRegistry.onlyRegisteredContract0
UsingRegistry.onlyRegisteredContracts0
UsingRegistry.setRegistry0
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage_report/contracts/common/UsingRegistry.sol.func.html b/coverage_report/contracts/common/UsingRegistry.sol.func.html new file mode 100644 index 0000000..92ec904 --- /dev/null +++ b/coverage_report/contracts/common/UsingRegistry.sol.func.html @@ -0,0 +1,138 @@ + + + + + + + LCOV - lcov.info - contracts/common/UsingRegistry.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - contracts/common - UsingRegistry.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:27.3 %113
Test Date:2024-10-08 18:32:54Functions:0.0 %90
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
UsingRegistry.getExchange0
UsingRegistry.getFreezer0
UsingRegistry.getGoldToken0
UsingRegistry.getReserve0
UsingRegistry.getSortedOracles0
UsingRegistry.getStableToken0
UsingRegistry.onlyRegisteredContract0
UsingRegistry.onlyRegisteredContracts0
UsingRegistry.setRegistry0
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage_report/contracts/common/UsingRegistry.sol.gcov.html b/coverage_report/contracts/common/UsingRegistry.sol.gcov.html new file mode 100644 index 0000000..0756447 --- /dev/null +++ b/coverage_report/contracts/common/UsingRegistry.sol.gcov.html @@ -0,0 +1,159 @@ + + + + + + + LCOV - lcov.info - contracts/common/UsingRegistry.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - contracts/common - UsingRegistry.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:27.3 %113
Test Date:2024-10-08 18:32:54Functions:0.0 %90
+
+ + + + + + + + +

+
            Line data    Source code
+
+       1              : // SPDX-License-Identifier: GPL-3.0-or-later
+       2              : pragma solidity ^0.5.13;
+       3              : 
+       4              : import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
+       5              : import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
+       6              : 
+       7              : import "celo/contracts/common/interfaces/IFreezer.sol";
+       8              : import "celo/contracts/common/interfaces/IRegistry.sol";
+       9              : 
+      10              : import "../interfaces/IExchange.sol";
+      11              : import "../interfaces/IStableTokenV2.sol";
+      12              : import "../interfaces/IReserve.sol";
+      13              : import "../interfaces/ISortedOracles.sol";
+      14              : 
+      15              : contract UsingRegistry is Ownable {
+      16              :   event RegistrySet(address indexed registryAddress);
+      17              : 
+      18              :   // solhint-disable state-visibility
+      19              :   bytes32 constant ACCOUNTS_REGISTRY_ID = keccak256(abi.encodePacked("Accounts"));
+      20              :   bytes32 constant ATTESTATIONS_REGISTRY_ID = keccak256(abi.encodePacked("Attestations"));
+      21              :   bytes32 constant DOWNTIME_SLASHER_REGISTRY_ID = keccak256(abi.encodePacked("DowntimeSlasher"));
+      22              :   bytes32 constant DOUBLE_SIGNING_SLASHER_REGISTRY_ID = keccak256(abi.encodePacked("DoubleSigningSlasher"));
+      23              :   bytes32 constant ELECTION_REGISTRY_ID = keccak256(abi.encodePacked("Election"));
+      24              :   bytes32 constant EXCHANGE_REGISTRY_ID = keccak256(abi.encodePacked("Exchange"));
+      25              :   bytes32 constant FEE_CURRENCY_WHITELIST_REGISTRY_ID = keccak256(abi.encodePacked("FeeCurrencyWhitelist"));
+      26              :   bytes32 constant FREEZER_REGISTRY_ID = keccak256(abi.encodePacked("Freezer"));
+      27              :   bytes32 constant GOLD_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("GoldToken"));
+      28              :   bytes32 constant GOVERNANCE_REGISTRY_ID = keccak256(abi.encodePacked("Governance"));
+      29              :   bytes32 constant GOVERNANCE_SLASHER_REGISTRY_ID = keccak256(abi.encodePacked("GovernanceSlasher"));
+      30              :   bytes32 constant LOCKED_GOLD_REGISTRY_ID = keccak256(abi.encodePacked("LockedGold"));
+      31              :   bytes32 constant RESERVE_REGISTRY_ID = keccak256(abi.encodePacked("Reserve"));
+      32              :   bytes32 constant RANDOM_REGISTRY_ID = keccak256(abi.encodePacked("Random"));
+      33              :   bytes32 constant SORTED_ORACLES_REGISTRY_ID = keccak256(abi.encodePacked("SortedOracles"));
+      34              :   bytes32 constant STABLE_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("StableToken"));
+      35              :   bytes32 constant VALIDATORS_REGISTRY_ID = keccak256(abi.encodePacked("Validators"));
+      36              :   // solhint-enable state-visibility
+      37              : 
+      38              :   IRegistry public registry;
+      39              : 
+      40              :   modifier onlyRegisteredContract(bytes32 identifierHash) {
+      41            0 :     require(registry.getAddressForOrDie(identifierHash) == msg.sender, "only registered contract");
+      42              :     _;
+      43              :   }
+      44              : 
+      45              :   modifier onlyRegisteredContracts(bytes32[] memory identifierHashes) {
+      46            0 :     require(registry.isOneOf(identifierHashes, msg.sender), "only registered contracts");
+      47              :     _;
+      48              :   }
+      49              : 
+      50              :   /**
+      51              :    * @notice Updates the address pointing to a Registry contract.
+      52              :    * @param registryAddress The address of a registry contract for routing to other contracts.
+      53              :    */
+      54              :   function setRegistry(address registryAddress) public onlyOwner {
+      55            6 :     require(registryAddress != address(0), "Cannot register the null address");
+      56            6 :     registry = IRegistry(registryAddress);
+      57            6 :     emit RegistrySet(registryAddress);
+      58              :   }
+      59              : 
+      60              :   function getExchange() internal view returns (IExchange) {
+      61            0 :     return IExchange(registry.getAddressForOrDie(EXCHANGE_REGISTRY_ID));
+      62              :   }
+      63              : 
+      64              :   function getFreezer() internal view returns (IFreezer) {
+      65            0 :     return IFreezer(registry.getAddressForOrDie(FREEZER_REGISTRY_ID));
+      66              :   }
+      67              : 
+      68              :   function getGoldToken() internal view returns (IERC20) {
+      69            0 :     return IERC20(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID));
+      70              :   }
+      71              : 
+      72              :   function getReserve() internal view returns (IReserve) {
+      73            0 :     return IReserve(registry.getAddressForOrDie(RESERVE_REGISTRY_ID));
+      74              :   }
+      75              : 
+      76              :   function getSortedOracles() internal view returns (ISortedOracles) {
+      77            0 :     return ISortedOracles(registry.getAddressForOrDie(SORTED_ORACLES_REGISTRY_ID));
+      78              :   }
+      79              : 
+      80              :   function getStableToken() internal view returns (IStableTokenV2) {
+      81            0 :     return IStableTokenV2(registry.getAddressForOrDie(STABLE_TOKEN_REGISTRY_ID));
+      82              :   }
+      83              : }
+        
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage_report/contracts/common/index-sort-f.html b/coverage_report/contracts/common/index-sort-f.html index 7d54efc..b49cb19 100644 --- a/coverage_report/contracts/common/index-sort-f.html +++ b/coverage_report/contracts/common/index-sort-f.html @@ -31,17 +31,17 @@ lcov.info Lines: - 100.0 % - 6 - 6 + 52.9 % + 17 + 9 Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: - 100.0 % - 4 + 30.8 % + 13 4 @@ -79,6 +79,18 @@ Total Hit + + UsingRegistry.sol + +
27.3%27.3%
+ + 27.3 % + 11 + 3 + 0.0 % + 9 + + SafeERC20MintableBurnable.sol diff --git a/coverage_report/contracts/common/index-sort-l.html b/coverage_report/contracts/common/index-sort-l.html index f0828ff..b2bd6af 100644 --- a/coverage_report/contracts/common/index-sort-l.html +++ b/coverage_report/contracts/common/index-sort-l.html @@ -31,17 +31,17 @@ lcov.info Lines: - 100.0 % - 6 - 6 + 52.9 % + 17 + 9 Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: - 100.0 % - 4 + 30.8 % + 13 4 @@ -79,6 +79,18 @@ Total Hit + + UsingRegistry.sol + +
27.3%27.3%
+ + 27.3 % + 11 + 3 + 0.0 % + 9 + + SafeERC20MintableBurnable.sol diff --git a/coverage_report/contracts/common/index.html b/coverage_report/contracts/common/index.html index b1319f6..cd0e31e 100644 --- a/coverage_report/contracts/common/index.html +++ b/coverage_report/contracts/common/index.html @@ -31,17 +31,17 @@ lcov.info Lines: - 100.0 % - 6 - 6 + 52.9 % + 17 + 9 Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: - 100.0 % - 4 + 30.8 % + 13 4 @@ -91,6 +91,18 @@ 4 4 + + UsingRegistry.sol + +
27.3%27.3%
+ + 27.3 % + 11 + 3 + 0.0 % + 9 + +
diff --git a/coverage_report/contracts/index-sort-f.html b/coverage_report/contracts/index-sort-f.html index a3aa641..43eae4b 100644 --- a/coverage_report/contracts/index-sort-f.html +++ b/coverage_report/contracts/index-sort-f.html @@ -31,13 +31,13 @@ lcov.info Lines: - 77.4 % + 77.8 % 576 - 446 + 448 Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 91.8 % @@ -82,11 +82,11 @@ BancorFormula.sol -
65.3%65.3%
+
65.8%65.8%
- 65.3 % + 65.8 % 357 - 233 + 235 61.5 % 13 8 diff --git a/coverage_report/contracts/index-sort-l.html b/coverage_report/contracts/index-sort-l.html index 73c07fc..3622cf7 100644 --- a/coverage_report/contracts/index-sort-l.html +++ b/coverage_report/contracts/index-sort-l.html @@ -31,13 +31,13 @@ lcov.info Lines: - 77.4 % + 77.8 % 576 - 446 + 448 Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 91.8 % @@ -82,11 +82,11 @@ BancorFormula.sol -
65.3%65.3%
+
65.8%65.8%
- 65.3 % + 65.8 % 357 - 233 + 235 61.5 % 13 8 diff --git a/coverage_report/contracts/index.html b/coverage_report/contracts/index.html index a8b509b..ddb499d 100644 --- a/coverage_report/contracts/index.html +++ b/coverage_report/contracts/index.html @@ -31,13 +31,13 @@ lcov.info Lines: - 77.4 % + 77.8 % 576 - 446 + 448 Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 91.8 % @@ -94,11 +94,11 @@ BancorFormula.sol -
65.3%65.3%
+
65.8%65.8%
- 65.3 % + 65.8 % 357 - 233 + 235 61.5 % 13 8 diff --git a/coverage_report/contracts/libraries/TradingLimits.sol.func-c.html b/coverage_report/contracts/libraries/TradingLimits.sol.func-c.html index 86691a5..2cb412a 100644 --- a/coverage_report/contracts/libraries/TradingLimits.sol.func-c.html +++ b/coverage_report/contracts/libraries/TradingLimits.sol.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/contracts/libraries/TradingLimits.sol.func.html b/coverage_report/contracts/libraries/TradingLimits.sol.func.html index c49b1d8..feeae5d 100644 --- a/coverage_report/contracts/libraries/TradingLimits.sol.func.html +++ b/coverage_report/contracts/libraries/TradingLimits.sol.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/contracts/libraries/TradingLimits.sol.gcov.html b/coverage_report/contracts/libraries/TradingLimits.sol.gcov.html index 13f9b71..673b851 100644 --- a/coverage_report/contracts/libraries/TradingLimits.sol.gcov.html +++ b/coverage_report/contracts/libraries/TradingLimits.sol.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/contracts/libraries/index-sort-f.html b/coverage_report/contracts/libraries/index-sort-f.html index 08ff325..43fa2f0 100644 --- a/coverage_report/contracts/libraries/index-sort-f.html +++ b/coverage_report/contracts/libraries/index-sort-f.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/contracts/libraries/index-sort-l.html b/coverage_report/contracts/libraries/index-sort-l.html index 4428711..7dfda71 100644 --- a/coverage_report/contracts/libraries/index-sort-l.html +++ b/coverage_report/contracts/libraries/index-sort-l.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/contracts/libraries/index.html b/coverage_report/contracts/libraries/index.html index dfc53f9..26721b4 100644 --- a/coverage_report/contracts/libraries/index.html +++ b/coverage_report/contracts/libraries/index.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/contracts/swap/Broker.sol.func-c.html b/coverage_report/contracts/swap/Broker.sol.func-c.html index 3ff2513..1aca676 100644 --- a/coverage_report/contracts/swap/Broker.sol.func-c.html +++ b/coverage_report/contracts/swap/Broker.sol.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % @@ -77,23 +77,23 @@ - Broker.getAmountIn + Broker.getExchangeProviders - 2 + 3 - Broker.getAmountOut + Broker.getAmountIn - 2 + 4 - Broker.getExchangeProviders + Broker.getAmountOut - 3 + 4 @@ -112,65 +112,65 @@ - Broker.swapOut + Broker.addExchangeProvider - 4 + 5 - Broker.addExchangeProvider + Broker.swapOut - 5 + 6 Broker.swapIn - 5 + 7 Broker.transferIn - 5 + 9 Broker.transferOut - 5 + 9 Broker.guardTradingLimits - 6 + 10 Broker.guardTradingLimit - 11 + 19 Broker. - 30 + 36 Broker.initialize - 30 + 36 diff --git a/coverage_report/contracts/swap/Broker.sol.func.html b/coverage_report/contracts/swap/Broker.sol.func.html index deafa07..0603335 100644 --- a/coverage_report/contracts/swap/Broker.sol.func.html +++ b/coverage_report/contracts/swap/Broker.sol.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % @@ -65,7 +65,7 @@ Broker. - 30 + 36 @@ -93,14 +93,14 @@ Broker.getAmountIn - 2 + 4 Broker.getAmountOut - 2 + 4 @@ -114,21 +114,21 @@ Broker.guardTradingLimit - 11 + 19 Broker.guardTradingLimits - 6 + 10 Broker.initialize - 30 + 36 @@ -149,28 +149,28 @@ Broker.swapIn - 5 + 7 Broker.swapOut - 4 + 6 Broker.transferIn - 5 + 9 Broker.transferOut - 5 + 9 diff --git a/coverage_report/contracts/swap/Broker.sol.gcov.html b/coverage_report/contracts/swap/Broker.sol.gcov.html index ae3b04e..0850a55 100644 --- a/coverage_report/contracts/swap/Broker.sol.gcov.html +++ b/coverage_report/contracts/swap/Broker.sol.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % @@ -122,9 +122,9 @@ 60 : * @param _reserves The addresses of the Reserve contracts. 61 : */ 62 : function initialize(address[] calldata _exchangeProviders, address[] calldata _reserves) external initializer { - 63 30 : _transferOwnership(msg.sender); - 64 30 : for (uint256 i = 0; i < _exchangeProviders.length; i++) { - 65 90 : addExchangeProvider(_exchangeProviders[i], _reserves[i]); + 63 36 : _transferOwnership(msg.sender); + 64 36 : for (uint256 i = 0; i < _exchangeProviders.length; i++) { + 65 96 : addExchangeProvider(_exchangeProviders[i], _reserves[i]); 66 : } 67 : } 68 : @@ -157,15 +157,15 @@ 95 : address exchangeProvider, 96 : address reserve 97 : ) public override(IBroker, IBrokerAdmin) onlyOwner returns (uint256 index) { - 98 94 : require(!isExchangeProvider[exchangeProvider], "ExchangeProvider already exists in the list"); - 99 93 : require(exchangeProvider != address(0), "ExchangeProvider address can't be 0"); - 100 92 : require(reserve != address(0), "Reserve address can't be 0"); - 101 91 : exchangeProviders.push(exchangeProvider); - 102 91 : isExchangeProvider[exchangeProvider] = true; - 103 91 : exchangeReserve[exchangeProvider] = reserve; - 104 91 : emit ExchangeProviderAdded(exchangeProvider); - 105 91 : emit ReserveSet(exchangeProvider, reserve); - 106 91 : index = exchangeProviders.length - 1; + 98 100 : require(!isExchangeProvider[exchangeProvider], "ExchangeProvider already exists in the list"); + 99 99 : require(exchangeProvider != address(0), "ExchangeProvider address can't be 0"); + 100 98 : require(reserve != address(0), "Reserve address can't be 0"); + 101 97 : exchangeProviders.push(exchangeProvider); + 102 97 : isExchangeProvider[exchangeProvider] = true; + 103 97 : exchangeReserve[exchangeProvider] = reserve; + 104 97 : emit ExchangeProviderAdded(exchangeProvider); + 105 97 : emit ReserveSet(exchangeProvider, reserve); + 106 97 : index = exchangeProviders.length - 1; 107 : } 108 : 109 : /** @@ -201,8 +201,8 @@ 139 : address tokenOut, 140 : uint256 amountOut 141 : ) external view returns (uint256 amountIn) { - 142 2 : require(isExchangeProvider[exchangeProvider], "ExchangeProvider does not exist"); - 143 1 : amountIn = IExchangeProvider(exchangeProvider).getAmountIn(exchangeId, tokenIn, tokenOut, amountOut); + 142 4 : require(isExchangeProvider[exchangeProvider], "ExchangeProvider does not exist"); + 143 3 : amountIn = IExchangeProvider(exchangeProvider).getAmountIn(exchangeId, tokenIn, tokenOut, amountOut); 144 : } 145 : 146 : /** @@ -221,8 +221,8 @@ 159 : address tokenOut, 160 : uint256 amountIn 161 : ) external view returns (uint256 amountOut) { - 162 2 : require(isExchangeProvider[exchangeProvider], "ExchangeProvider does not exist"); - 163 1 : amountOut = IExchangeProvider(exchangeProvider).getAmountOut(exchangeId, tokenIn, tokenOut, amountIn); + 162 4 : require(isExchangeProvider[exchangeProvider], "ExchangeProvider does not exist"); + 163 3 : amountOut = IExchangeProvider(exchangeProvider).getAmountOut(exchangeId, tokenIn, tokenOut, amountIn); 164 : } 165 : 166 : /** @@ -243,16 +243,16 @@ 181 : uint256 amountIn, 182 : uint256 amountOutMin 183 : ) external nonReentrant returns (uint256 amountOut) { - 184 5 : require(isExchangeProvider[exchangeProvider], "ExchangeProvider does not exist"); + 184 7 : require(isExchangeProvider[exchangeProvider], "ExchangeProvider does not exist"); 185 : // slither-disable-next-line reentrancy-benign - 186 5 : amountOut = IExchangeProvider(exchangeProvider).swapIn(exchangeId, tokenIn, tokenOut, amountIn); - 187 5 : require(amountOut >= amountOutMin, "amountOutMin not met"); - 188 4 : guardTradingLimits(exchangeId, tokenIn, amountIn, tokenOut, amountOut); + 186 7 : amountOut = IExchangeProvider(exchangeProvider).swapIn(exchangeId, tokenIn, tokenOut, amountIn); + 187 7 : require(amountOut >= amountOutMin, "amountOutMin not met"); + 188 6 : guardTradingLimits(exchangeId, tokenIn, amountIn, tokenOut, amountOut); 189 : - 190 3 : address reserve = exchangeReserve[exchangeProvider]; - 191 3 : transferIn(payable(msg.sender), tokenIn, amountIn, reserve); - 192 3 : transferOut(payable(msg.sender), tokenOut, amountOut, reserve); - 193 3 : emit Swap(exchangeProvider, exchangeId, msg.sender, tokenIn, tokenOut, amountIn, amountOut); + 190 5 : address reserve = exchangeReserve[exchangeProvider]; + 191 5 : transferIn(payable(msg.sender), tokenIn, amountIn, reserve); + 192 5 : transferOut(payable(msg.sender), tokenOut, amountOut, reserve); + 193 5 : emit Swap(exchangeProvider, exchangeId, msg.sender, tokenIn, tokenOut, amountIn, amountOut); 194 : } 195 : 196 : /** @@ -273,16 +273,16 @@ 211 : uint256 amountOut, 212 : uint256 amountInMax 213 : ) external nonReentrant returns (uint256 amountIn) { - 214 4 : require(isExchangeProvider[exchangeProvider], "ExchangeProvider does not exist"); + 214 6 : require(isExchangeProvider[exchangeProvider], "ExchangeProvider does not exist"); 215 : // slither-disable-next-line reentrancy-benign - 216 3 : amountIn = IExchangeProvider(exchangeProvider).swapOut(exchangeId, tokenIn, tokenOut, amountOut); - 217 3 : require(amountIn <= amountInMax, "amountInMax exceeded"); - 218 2 : guardTradingLimits(exchangeId, tokenIn, amountIn, tokenOut, amountOut); + 216 5 : amountIn = IExchangeProvider(exchangeProvider).swapOut(exchangeId, tokenIn, tokenOut, amountOut); + 217 5 : require(amountIn <= amountInMax, "amountInMax exceeded"); + 218 4 : guardTradingLimits(exchangeId, tokenIn, amountIn, tokenOut, amountOut); 219 : - 220 2 : address reserve = exchangeReserve[exchangeProvider]; - 221 2 : transferIn(payable(msg.sender), tokenIn, amountIn, reserve); - 222 2 : transferOut(payable(msg.sender), tokenOut, amountOut, reserve); - 223 2 : emit Swap(exchangeProvider, exchangeId, msg.sender, tokenIn, tokenOut, amountIn, amountOut); + 220 4 : address reserve = exchangeReserve[exchangeProvider]; + 221 4 : transferIn(payable(msg.sender), tokenIn, amountIn, reserve); + 222 4 : transferOut(payable(msg.sender), tokenOut, amountOut, reserve); + 223 4 : emit Swap(exchangeProvider, exchangeId, msg.sender, tokenIn, tokenOut, amountIn, amountOut); 224 : } 225 : 226 : /** @@ -334,11 +334,11 @@ 272 : * @param _reserve The address of the corresponding reserve. 273 : */ 274 : function transferOut(address payable to, address token, uint256 amount, address _reserve) internal { - 275 5 : IReserve reserve = IReserve(_reserve); - 276 5 : if (reserve.isStableAsset(token)) { - 277 3 : IERC20(token).safeMint(to, amount); - 278 2 : } else if (reserve.isCollateralAsset(token)) { - 279 2 : require(reserve.transferExchangeCollateralAsset(token, to, amount), "Transfer of the collateral asset failed"); + 275 9 : IReserve reserve = IReserve(_reserve); + 276 9 : if (reserve.isStableAsset(token)) { + 277 5 : IERC20(token).safeMint(to, amount); + 278 4 : } else if (reserve.isCollateralAsset(token)) { + 279 4 : require(reserve.transferExchangeCollateralAsset(token, to, amount), "Transfer of the collateral asset failed"); 280 : } else { 281 0 : revert("Token must be stable or collateral assert"); 282 : } @@ -354,12 +354,12 @@ 292 : * @param _reserve The address of the corresponding reserve. 293 : */ 294 : function transferIn(address payable from, address token, uint256 amount, address _reserve) internal { - 295 5 : IReserve reserve = IReserve(_reserve); - 296 5 : if (reserve.isStableAsset(token)) { - 297 2 : IERC20(token).safeTransferFrom(from, address(this), amount); - 298 2 : IERC20(token).safeBurn(amount); - 299 3 : } else if (reserve.isCollateralAsset(token)) { - 300 3 : IERC20(token).safeTransferFrom(from, address(reserve), amount); + 295 9 : IReserve reserve = IReserve(_reserve); + 296 9 : if (reserve.isStableAsset(token)) { + 297 4 : IERC20(token).safeTransferFrom(from, address(this), amount); + 298 4 : IERC20(token).safeBurn(amount); + 299 5 : } else if (reserve.isCollateralAsset(token)) { + 300 5 : IERC20(token).safeTransferFrom(from, address(reserve), amount); 301 : } else { 302 0 : revert("Token must be stable or collateral assert"); 303 : } @@ -381,13 +381,13 @@ 319 : address _tokenOut, 320 : uint256 amountOut 321 : ) internal { - 322 6 : bytes32 tokenIn = bytes32(uint256(uint160(_tokenIn))); - 323 6 : bytes32 tokenOut = bytes32(uint256(uint160(_tokenOut))); - 324 6 : require(amountIn <= uint256(MAX_INT256), "amountIn too large"); - 325 6 : require(amountOut <= uint256(MAX_INT256), "amountOut too large"); + 322 10 : bytes32 tokenIn = bytes32(uint256(uint160(_tokenIn))); + 323 10 : bytes32 tokenOut = bytes32(uint256(uint160(_tokenOut))); + 324 10 : require(amountIn <= uint256(MAX_INT256), "amountIn too large"); + 325 10 : require(amountOut <= uint256(MAX_INT256), "amountOut too large"); 326 : - 327 6 : guardTradingLimit(exchangeId ^ tokenIn, int256(amountIn), _tokenIn); - 328 5 : guardTradingLimit(exchangeId ^ tokenOut, -1 * int256(amountOut), _tokenOut); + 327 10 : guardTradingLimit(exchangeId ^ tokenIn, int256(amountIn), _tokenIn); + 328 9 : guardTradingLimit(exchangeId ^ tokenOut, -1 * int256(amountOut), _tokenOut); 329 : } 330 : 331 : /** @@ -398,8 +398,8 @@ 336 : * @param token the address of the token, used to lookup decimals. 337 : */ 338 : function guardTradingLimit(bytes32 tradingLimitId, int256 deltaFlow, address token) internal { - 339 11 : ITradingLimits.Config memory tradingLimitConfig = tradingLimitsConfig[tradingLimitId]; - 340 11 : if (tradingLimitConfig.flags > 0) { + 339 19 : ITradingLimits.Config memory tradingLimitConfig = tradingLimitsConfig[tradingLimitId]; + 340 19 : if (tradingLimitConfig.flags > 0) { 341 2 : ITradingLimits.State memory tradingLimitState = tradingLimitsState[tradingLimitId]; 342 2 : tradingLimitState = tradingLimitState.update(tradingLimitConfig, deltaFlow, IERC20Metadata(token).decimals()); 343 2 : tradingLimitState.verify(tradingLimitConfig); diff --git a/coverage_report/contracts/swap/Reserve.sol.func-c.html b/coverage_report/contracts/swap/Reserve.sol.func-c.html new file mode 100644 index 0000000..40ff607 --- /dev/null +++ b/coverage_report/contracts/swap/Reserve.sol.func-c.html @@ -0,0 +1,397 @@ + + + + + + + LCOV - lcov.info - contracts/swap/Reserve.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - contracts/swap - Reserve.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:38.4 %19876
Test Date:2024-10-08 18:32:54Functions:15.2 %467
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
Reserve._transferGold0
Reserve.addCollateralAsset0
Reserve.addOtherReserveAddress0
Reserve.addSpender0
Reserve.checkIsCollateralAsset0
Reserve.computeTobinTax0
Reserve.getAssetAllocationSymbols0
Reserve.getAssetAllocationWeights0
Reserve.getDailySpendingRatio0
Reserve.getDailySpendingRatioForCollateralAsset0
Reserve.getExchangeSpenders0
Reserve.getFrozenReserveGoldBalance0
Reserve.getOrComputeTobinTax0
Reserve.getOtherReserveAddresses0
Reserve.getOtherReserveAddressesGoldBalance0
Reserve.getReserveAddressesCollateralAssetBalance0
Reserve.getReserveGoldBalance0
Reserve.getReserveRatio0
Reserve.getTokens0
Reserve.getUnfrozenBalance0
Reserve.getUnfrozenReserveGoldBalance0
Reserve.getVersionNumber0
Reserve.isAllowedToSpendExchange0
Reserve.isStableToken0
Reserve.removeCollateralAsset0
Reserve.removeExchangeSpender0
Reserve.removeOtherReserveAddress0
Reserve.removeSpender0
Reserve.removeToken0
Reserve.setAssetAllocations0
Reserve.setDailySpendingRatio0
Reserve.setDailySpendingRatioForCollateralAssets0
Reserve.setFrozenGold0
Reserve.setTobinTax0
Reserve.setTobinTaxReserveRatio0
Reserve.setTobinTaxStalenessThreshold0
Reserve.transferCollateralAsset0
Reserve.transferExchangeGold0
Reserve.transferGold0
Reserve._transferCollateralAsset2
Reserve.transferExchangeCollateralAsset2
Reserve.6
Reserve.addExchangeSpender6
Reserve.addToken6
Reserve.initialize6
Reserve.isStableAsset20
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage_report/contracts/swap/Reserve.sol.func.html b/coverage_report/contracts/swap/Reserve.sol.func.html new file mode 100644 index 0000000..a94aaca --- /dev/null +++ b/coverage_report/contracts/swap/Reserve.sol.func.html @@ -0,0 +1,397 @@ + + + + + + + LCOV - lcov.info - contracts/swap/Reserve.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - contracts/swap - Reserve.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:38.4 %19876
Test Date:2024-10-08 18:32:54Functions:15.2 %467
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
Reserve.6
Reserve._transferCollateralAsset2
Reserve._transferGold0
Reserve.addCollateralAsset0
Reserve.addExchangeSpender6
Reserve.addOtherReserveAddress0
Reserve.addSpender0
Reserve.addToken6
Reserve.checkIsCollateralAsset0
Reserve.computeTobinTax0
Reserve.getAssetAllocationSymbols0
Reserve.getAssetAllocationWeights0
Reserve.getDailySpendingRatio0
Reserve.getDailySpendingRatioForCollateralAsset0
Reserve.getExchangeSpenders0
Reserve.getFrozenReserveGoldBalance0
Reserve.getOrComputeTobinTax0
Reserve.getOtherReserveAddresses0
Reserve.getOtherReserveAddressesGoldBalance0
Reserve.getReserveAddressesCollateralAssetBalance0
Reserve.getReserveGoldBalance0
Reserve.getReserveRatio0
Reserve.getTokens0
Reserve.getUnfrozenBalance0
Reserve.getUnfrozenReserveGoldBalance0
Reserve.getVersionNumber0
Reserve.initialize6
Reserve.isAllowedToSpendExchange0
Reserve.isStableAsset20
Reserve.isStableToken0
Reserve.removeCollateralAsset0
Reserve.removeExchangeSpender0
Reserve.removeOtherReserveAddress0
Reserve.removeSpender0
Reserve.removeToken0
Reserve.setAssetAllocations0
Reserve.setDailySpendingRatio0
Reserve.setDailySpendingRatioForCollateralAssets0
Reserve.setFrozenGold0
Reserve.setTobinTax0
Reserve.setTobinTaxReserveRatio0
Reserve.setTobinTaxStalenessThreshold0
Reserve.transferCollateralAsset0
Reserve.transferExchangeCollateralAsset2
Reserve.transferExchangeGold0
Reserve.transferGold0
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage_report/contracts/swap/Reserve.sol.gcov.html b/coverage_report/contracts/swap/Reserve.sol.gcov.html new file mode 100644 index 0000000..f779c01 --- /dev/null +++ b/coverage_report/contracts/swap/Reserve.sol.gcov.html @@ -0,0 +1,1031 @@ + + + + + + + LCOV - lcov.info - contracts/swap/Reserve.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - contracts/swap - Reserve.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:38.4 %19876
Test Date:2024-10-08 18:32:54Functions:15.2 %467
+
+ + + + + + + + +

+
            Line data    Source code
+
+       1              : // SPDX-License-Identifier: GPL-3.0-or-later
+       2              : pragma solidity ^0.5.13;
+       3              : 
+       4              : import "openzeppelin-solidity/contracts/math/SafeMath.sol";
+       5              : import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
+       6              : import "openzeppelin-solidity/contracts/utils/Address.sol";
+       7              : import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol";
+       8              : 
+       9              : import "celo/contracts/common/FixidityLib.sol";
+      10              : import "celo/contracts/common/Initializable.sol";
+      11              : import "celo/contracts/common/interfaces/ICeloVersionedContract.sol";
+      12              : import "celo/contracts/common/libraries/ReentrancyGuard.sol";
+      13              : 
+      14              : import "contracts/common/UsingRegistry.sol";
+      15              : import "contracts/interfaces/IReserve.sol";
+      16              : import "contracts/interfaces/ISortedOracles.sol";
+      17              : 
+      18              : /**
+      19              :  * @title Ensures price stability of StableTokens with respect to their pegs
+      20              :  */
+      21              : // solhint-disable-next-line max-states-count
+      22              : contract Reserve is
+      23              :     IReserve,
+      24              :     ICeloVersionedContract,
+      25              :     Ownable,
+      26              :     Initializable,
+      27              :     UsingRegistry,
+      28              :     ReentrancyGuard
+      29              : {
+      30              :     using SafeMath for uint256;
+      31              :     using FixidityLib for FixidityLib.Fraction;
+      32              :     using Address for address payable; // prettier-ignore
+      33              :     using SafeERC20 for IERC20;
+      34              : 
+      35              :     struct TobinTaxCache {
+      36              :         uint128 numerator;
+      37              :         uint128 timestamp;
+      38              :     }
+      39              : 
+      40              :     mapping(address => bool) public isToken;
+      41              :     address[] private _tokens;
+      42              :     TobinTaxCache public tobinTaxCache;
+      43              :     uint256 public tobinTaxStalenessThreshold;
+      44              :     uint256 public tobinTax;
+      45              :     uint256 public tobinTaxReserveRatio;
+      46              :     mapping(address => bool) public isSpender;
+      47              : 
+      48              :     mapping(address => bool) public isOtherReserveAddress;
+      49              :     address[] public otherReserveAddresses;
+      50              : 
+      51              :     bytes32[] public assetAllocationSymbols;
+      52              :     mapping(bytes32 => uint256) public assetAllocationWeights;
+      53              : 
+      54              :     uint256 public lastSpendingDay;
+      55              :     uint256 public spendingLimit;
+      56              :     FixidityLib.Fraction private spendingRatio;
+      57              : 
+      58              :     uint256 public frozenReserveGoldStartBalance;
+      59              :     uint256 public frozenReserveGoldStartDay;
+      60              :     uint256 public frozenReserveGoldDays;
+      61              : 
+      62              :     mapping(address => bool) public isExchangeSpender;
+      63              :     address[] public exchangeSpenderAddresses;
+      64              :     mapping(address => FixidityLib.Fraction)
+      65              :         private collateralAssetDailySpendingRatio;
+      66              :     mapping(address => uint256) public collateralAssetLastSpendingDay;
+      67              :     address[] public collateralAssets;
+      68              :     mapping(address => bool) public isCollateralAsset;
+      69              :     mapping(address => uint256) public collateralAssetSpendingLimit;
+      70              : 
+      71              :     event TobinTaxStalenessThresholdSet(uint256 value);
+      72              :     event DailySpendingRatioSet(uint256 ratio);
+      73              :     event TokenAdded(address indexed token);
+      74              :     event TokenRemoved(address indexed token, uint256 index);
+      75              :     event SpenderAdded(address indexed spender);
+      76              :     event SpenderRemoved(address indexed spender);
+      77              :     event OtherReserveAddressAdded(address indexed otherReserveAddress);
+      78              :     event OtherReserveAddressRemoved(
+      79              :         address indexed otherReserveAddress,
+      80              :         uint256 index
+      81              :     );
+      82              :     event AssetAllocationSet(bytes32[] symbols, uint256[] weights);
+      83              :     event ReserveGoldTransferred(
+      84              :         address indexed spender,
+      85              :         address indexed to,
+      86              :         uint256 value
+      87              :     );
+      88              :     event TobinTaxSet(uint256 value);
+      89              :     event TobinTaxReserveRatioSet(uint256 value);
+      90              :     event ExchangeSpenderAdded(address indexed exchangeSpender);
+      91              :     event ExchangeSpenderRemoved(address indexed exchangeSpender);
+      92              :     event DailySpendingRatioForCollateralAssetSet(
+      93              :         address collateralAsset,
+      94              :         uint256 collateralAssetDailySpendingRatios
+      95              :     );
+      96              :     event ReserveCollateralAssetsTransferred(
+      97              :         address indexed spender,
+      98              :         address indexed to,
+      99              :         uint256 value,
+     100              :         address token
+     101              :     );
+     102              :     event CollateralAssetRemoved(address collateralAsset);
+     103              :     event CollateralAssetAdded(address collateralAsset);
+     104              : 
+     105              :     /**
+     106              :      * @notice Sets initialized == true on implementation contracts
+     107              :      * @param test Set to true to skip implementation initialization
+     108              :      */
+     109              :     constructor(bool test) public Initializable(test) {}
+     110              : 
+     111              :     modifier isStableToken(address token) {
+     112            0 :         require(isToken[token], "token addr was never registered");
+     113              :         _;
+     114              :     }
+     115              : 
+     116              :     /**
+     117              :      * @notice Returns the storage, major, minor, and patch version of the contract.
+     118              :      * @return Storage version of the contract.
+     119              :      * @return Major version of the contract.
+     120              :      * @return Minor version of the contract.
+     121              :      * @return Patch version of the contract.
+     122              :      */
+     123              :     function getVersionNumber()
+     124              :         external
+     125              :         pure
+     126              :         returns (uint256, uint256, uint256, uint256)
+     127              :     {
+     128            0 :         return (2, 1, 0, 0);
+     129              :     }
+     130              : 
+     131              :     function() external payable {} // solhint-disable no-empty-blocks
+     132              : 
+     133              :     /**
+     134              :      * @notice Used in place of the constructor to allow the contract to be upgradable via proxy.
+     135              :      * @param registryAddress The address of the registry core smart contract.
+     136              :      * @param _tobinTaxStalenessThreshold The initial number of seconds to cache tobin tax value for.
+     137              :      * @param _spendingRatioForCelo The relative daily spending limit for the reserve spender.
+     138              :      * @param _frozenGold The balance of reserve gold that is frozen.
+     139              :      * @param _frozenDays The number of days during which the frozen gold thaws.
+     140              :      * @param _assetAllocationSymbols The symbols of the reserve assets.
+     141              :      * @param _assetAllocationWeights The reserve asset weights.
+     142              :      * @param _tobinTax The tobin tax value as a fixidity fraction.
+     143              :      * @param _tobinTaxReserveRatio When to turn on the tobin tax, as a fixidity fraction.
+     144              :      * @param _collateralAssets The relative daily spending limit
+     145              :      * of an ERC20 collateral asset for the reserve spender.
+     146              :      * @param _collateralAssetDailySpendingRatios The address of an ERC20 collateral asset
+     147              :      */
+     148              :     function initialize(
+     149              :         address registryAddress,
+     150              :         uint256 _tobinTaxStalenessThreshold,
+     151              :         uint256 _spendingRatioForCelo,
+     152              :         uint256 _frozenGold,
+     153              :         uint256 _frozenDays,
+     154              :         bytes32[] calldata _assetAllocationSymbols,
+     155              :         uint256[] calldata _assetAllocationWeights,
+     156              :         uint256 _tobinTax,
+     157              :         uint256 _tobinTaxReserveRatio,
+     158              :         address[] calldata _collateralAssets,
+     159              :         uint256[] calldata _collateralAssetDailySpendingRatios
+     160              :     ) external initializer {
+     161            6 :         _transferOwnership(msg.sender);
+     162            6 :         setRegistry(registryAddress);
+     163            6 :         setTobinTaxStalenessThreshold(_tobinTaxStalenessThreshold);
+     164            6 :         setDailySpendingRatio(_spendingRatioForCelo);
+     165            6 :         setFrozenGold(_frozenGold, _frozenDays);
+     166            6 :         setAssetAllocations(_assetAllocationSymbols, _assetAllocationWeights);
+     167            6 :         setTobinTax(_tobinTax);
+     168            6 :         setTobinTaxReserveRatio(_tobinTaxReserveRatio);
+     169            6 :         for (uint256 i = 0; i < _collateralAssets.length; i++) {
+     170            6 :             addCollateralAsset(_collateralAssets[i]);
+     171              :         }
+     172            6 :         setDailySpendingRatioForCollateralAssets(
+     173              :             _collateralAssets,
+     174              :             _collateralAssetDailySpendingRatios
+     175              :         );
+     176              :     }
+     177              : 
+     178              :     /**
+     179              :      * @notice Sets the number of seconds to cache the tobin tax value for.
+     180              :      * @param value The number of seconds to cache the tobin tax value for.
+     181              :      */
+     182              :     function setTobinTaxStalenessThreshold(uint256 value) public onlyOwner {
+     183            6 :         require(value > 0, "value was zero");
+     184            6 :         tobinTaxStalenessThreshold = value;
+     185            6 :         emit TobinTaxStalenessThresholdSet(value);
+     186              :     }
+     187              : 
+     188              :     /**
+     189              :      * @notice Sets the tobin tax.
+     190              :      * @param value The tobin tax.
+     191              :      */
+     192              :     function setTobinTax(uint256 value) public onlyOwner {
+     193            6 :         require(
+     194              :             FixidityLib.wrap(value).lte(FixidityLib.fixed1()),
+     195              :             "tobin tax cannot be larger than 1"
+     196              :         );
+     197            6 :         tobinTax = value;
+     198            6 :         emit TobinTaxSet(value);
+     199              :     }
+     200              : 
+     201              :     /**
+     202              :      * @notice Sets the reserve ratio at which the tobin tax sets in.
+     203              :      * @param value The reserve ratio at which the tobin tax sets in.
+     204              :      */
+     205              :     function setTobinTaxReserveRatio(uint256 value) public onlyOwner {
+     206            6 :         tobinTaxReserveRatio = value;
+     207            6 :         emit TobinTaxReserveRatioSet(value);
+     208              :     }
+     209              : 
+     210              :     /**
+     211              :      * @notice Set the ratio of reserve that is spendable per day.
+     212              :      * @param ratio Spending ratio as unwrapped Fraction.
+     213              :      */
+     214              :     function setDailySpendingRatio(uint256 ratio) public onlyOwner {
+     215            6 :         spendingRatio = FixidityLib.wrap(ratio);
+     216            6 :         require(
+     217              :             spendingRatio.lte(FixidityLib.fixed1()),
+     218              :             "spending ratio cannot be larger than 1"
+     219              :         );
+     220            6 :         emit DailySpendingRatioSet(ratio);
+     221              :     }
+     222              : 
+     223              :     /**
+     224              :      * @notice Set the ratio of reserve for a given collateral asset
+     225              :      * that is spendable per day.
+     226              :      * @param _collateralAssets Collection of the addresses of collateral assets
+     227              :      * we're setting a limit for.
+     228              :      * @param collateralAssetDailySpendingRatios Collection of the relative daily spending limits
+     229              :      * of collateral assets.
+     230              :      */
+     231              :     function setDailySpendingRatioForCollateralAssets(
+     232              :         address[] memory _collateralAssets,
+     233              :         uint256[] memory collateralAssetDailySpendingRatios
+     234              :     ) public onlyOwner {
+     235            6 :         require(
+     236              :             _collateralAssets.length ==
+     237              :                 collateralAssetDailySpendingRatios.length,
+     238              :             "token addresses and spending ratio lengths have to be the same"
+     239              :         );
+     240            6 :         for (uint256 i = 0; i < _collateralAssets.length; i++) {
+     241              :             if (
+     242            6 :                 _collateralAssets[i] != address(0) &&
+     243            6 :                 collateralAssetDailySpendingRatios[i] != 0
+     244            6 :             ) {
+     245            6 :                 require(
+     246              :                     checkIsCollateralAsset(_collateralAssets[i]),
+     247              :                     "the address specified is not a reserve collateral asset"
+     248              :                 );
+     249            6 :                 require(
+     250              :                     FixidityLib.wrap(collateralAssetDailySpendingRatios[i]).lte(
+     251              :                         FixidityLib.fixed1()
+     252              :                     ),
+     253              :                     "spending ratio cannot be larger than 1"
+     254              :                 );
+     255            6 :                 collateralAssetDailySpendingRatio[
+     256              :                     _collateralAssets[i]
+     257              :                 ] = FixidityLib.wrap(collateralAssetDailySpendingRatios[i]);
+     258            6 :                 emit DailySpendingRatioForCollateralAssetSet(
+     259              :                     _collateralAssets[i],
+     260              :                     collateralAssetDailySpendingRatios[i]
+     261              :                 );
+     262              :             }
+     263              :         }
+     264              :     }
+     265              : 
+     266              :     /**
+     267              :      * @notice Get daily spending ratio.
+     268              :      * @return Spending ratio as unwrapped Fraction.
+     269              :      */
+     270              :     function getDailySpendingRatio() public view returns (uint256) {
+     271            0 :         return spendingRatio.unwrap();
+     272              :     }
+     273              : 
+     274              :     /**
+     275              :      * @notice Get daily spending ratio of a collateral asset.
+     276              :      * @param collateralAsset The address of a collateral asset we're getting a spending ratio for.
+     277              :      * @return Daily spending ratio for the collateral asset as unwrapped Fraction.
+     278              :      */
+     279              :     function getDailySpendingRatioForCollateralAsset(
+     280              :         address collateralAsset
+     281              :     ) public view returns (uint256) {
+     282            0 :         return collateralAssetDailySpendingRatio[collateralAsset].unwrap();
+     283              :     }
+     284              : 
+     285              :     /**
+     286              :      * @notice Sets the balance of reserve gold frozen from transfer.
+     287              :      * @param frozenGold The amount of CELO frozen.
+     288              :      * @param frozenDays The number of days the frozen CELO thaws over.
+     289              :      */
+     290              :     function setFrozenGold(
+     291              :         uint256 frozenGold,
+     292              :         uint256 frozenDays
+     293              :     ) public onlyOwner {
+     294            6 :         require(
+     295              :             frozenGold <= address(this).balance,
+     296              :             "Cannot freeze more than balance"
+     297              :         );
+     298            6 :         frozenReserveGoldStartBalance = frozenGold;
+     299              :         // slither-disable-start events-maths
+     300            6 :         frozenReserveGoldStartDay = now / 1 days;
+     301            6 :         frozenReserveGoldDays = frozenDays;
+     302              :         // slither-disable-end events-maths
+     303              :     }
+     304              : 
+     305              :     /**
+     306              :      * @notice Sets target allocations for CELO and a diversified basket of non-Celo assets.
+     307              :      * @param symbols The symbol of each asset in the Reserve portfolio.
+     308              :      * @param weights The weight for the corresponding asset as unwrapped Fixidity.Fraction.
+     309              :      */
+     310              :     function setAssetAllocations(
+     311              :         bytes32[] memory symbols,
+     312              :         uint256[] memory weights
+     313              :     ) public onlyOwner {
+     314            6 :         require(symbols.length == weights.length, "Array length mismatch");
+     315            6 :         FixidityLib.Fraction memory sum = FixidityLib.wrap(0);
+     316            6 :         for (uint256 i = 0; i < weights.length; i = i.add(1)) {
+     317           12 :             sum = sum.add(FixidityLib.wrap(weights[i]));
+     318              :         }
+     319            6 :         require(
+     320              :             sum.equals(FixidityLib.fixed1()),
+     321              :             "Sum of asset allocation must be 1"
+     322              :         );
+     323              :         // slither-disable-next-line cache-array-length
+     324            6 :         for (uint256 i = 0; i < assetAllocationSymbols.length; i = i.add(1)) {
+     325            0 :             delete assetAllocationWeights[assetAllocationSymbols[i]];
+     326              :         }
+     327            6 :         assetAllocationSymbols = symbols;
+     328            6 :         for (uint256 i = 0; i < symbols.length; i = i.add(1)) {
+     329           12 :             require(
+     330              :                 assetAllocationWeights[symbols[i]] == 0,
+     331              :                 "Cannot set weight twice"
+     332              :             );
+     333           12 :             assetAllocationWeights[symbols[i]] = weights[i];
+     334              :         }
+     335              :         // NOTE: The CELO asset launched as "Celo Gold" (cGLD), but was renamed to
+     336              :         // just CELO by the community.
+     337              :         // TODO: Change "cGLD" to "CELO" in this file, after ensuring that any
+     338              :         // off chain tools working with asset allocation weights are aware of this
+     339              :         // change.
+     340            6 :         require(
+     341              :             assetAllocationWeights["cGLD"] != 0,
+     342              :             "Must set cGLD asset weight"
+     343              :         );
+     344            6 :         emit AssetAllocationSet(symbols, weights);
+     345              :     }
+     346              : 
+     347              :     /**
+     348              :      * @notice Add a token that the reserve will stabilize.
+     349              :      * @param token The address of the token being stabilized.
+     350              :      * @return Returns true if the transaction succeeds.
+     351              :      */
+     352              :     function addToken(address token) external onlyOwner returns (bool) {
+     353            6 :         require(!isToken[token], "token addr already registered");
+     354            6 :         isToken[token] = true;
+     355            6 :         _tokens.push(token);
+     356            6 :         emit TokenAdded(token);
+     357            6 :         return true;
+     358              :     }
+     359              : 
+     360              :     /**
+     361              :      * @notice Remove a token that the reserve will no longer stabilize.
+     362              :      * @param token The address of the token no longer being stabilized.
+     363              :      * @param index The index of the token in _tokens.
+     364              :      * @return Returns true if the transaction succeeds.
+     365              :      */
+     366              :     function removeToken(
+     367              :         address token,
+     368              :         uint256 index
+     369              :     ) external onlyOwner isStableToken(token) returns (bool) {
+     370            0 :         require(
+     371              :             index < _tokens.length && _tokens[index] == token,
+     372              :             "index into tokens list not mapped to token"
+     373              :         );
+     374            0 :         isToken[token] = false;
+     375            0 :         address lastItem = _tokens[_tokens.length.sub(1)];
+     376            0 :         _tokens[index] = lastItem;
+     377            0 :         _tokens.length = _tokens.length.sub(1);
+     378            0 :         emit TokenRemoved(token, index);
+     379            0 :         return true;
+     380              :     }
+     381              : 
+     382              :     /**
+     383              :      * @notice Add a reserve address whose balance shall be included in the reserve ratio.
+     384              :      * @param reserveAddress The reserve address to add.
+     385              :      * @return Returns true if the transaction succeeds.
+     386              :      */
+     387              :     function addOtherReserveAddress(
+     388              :         address reserveAddress
+     389              :     ) external onlyOwner returns (bool) {
+     390            0 :         require(
+     391              :             !isOtherReserveAddress[reserveAddress],
+     392              :             "reserve addr already added"
+     393              :         );
+     394            0 :         isOtherReserveAddress[reserveAddress] = true;
+     395            0 :         otherReserveAddresses.push(reserveAddress);
+     396            0 :         emit OtherReserveAddressAdded(reserveAddress);
+     397            0 :         return true;
+     398              :     }
+     399              : 
+     400              :     /**
+     401              :      * @notice Remove reserve address whose balance shall no longer be included in the reserve ratio.
+     402              :      * @param reserveAddress The reserve address to remove.
+     403              :      * @param index The index of the reserve address in otherReserveAddresses.
+     404              :      * @return Returns true if the transaction succeeds.
+     405              :      */
+     406              :     function removeOtherReserveAddress(
+     407              :         address reserveAddress,
+     408              :         uint256 index
+     409              :     ) external onlyOwner returns (bool) {
+     410            0 :         require(
+     411              :             isOtherReserveAddress[reserveAddress],
+     412              :             "reserve addr was never added"
+     413              :         );
+     414            0 :         require(
+     415              :             index < otherReserveAddresses.length &&
+     416              :                 otherReserveAddresses[index] == reserveAddress,
+     417              :             "index into reserve list not mapped to address"
+     418              :         );
+     419            0 :         isOtherReserveAddress[reserveAddress] = false;
+     420            0 :         address lastItem = otherReserveAddresses[
+     421              :             otherReserveAddresses.length.sub(1)
+     422              :         ];
+     423            0 :         otherReserveAddresses[index] = lastItem;
+     424            0 :         otherReserveAddresses.length = otherReserveAddresses.length.sub(1);
+     425            0 :         emit OtherReserveAddressRemoved(reserveAddress, index);
+     426            0 :         return true;
+     427              :     }
+     428              : 
+     429              :     /**
+     430              :      * @notice Gives an address permission to spend Reserve funds.
+     431              :      * @param spender The address that is allowed to spend Reserve funds.
+     432              :      */
+     433              :     function addSpender(address spender) external onlyOwner {
+     434            0 :         require(address(0) != spender, "Spender can't be null");
+     435            0 :         isSpender[spender] = true;
+     436            0 :         emit SpenderAdded(spender);
+     437              :     }
+     438              : 
+     439              :     /**
+     440              :      * @notice Takes away an address's permission to spend Reserve funds.
+     441              :      * @param spender The address that is to be no longer allowed to spend Reserve funds.
+     442              :      */
+     443              :     function removeSpender(address spender) external onlyOwner {
+     444            0 :         require(isSpender[spender], "Spender hasn't been added");
+     445            0 :         isSpender[spender] = false;
+     446            0 :         emit SpenderRemoved(spender);
+     447              :     }
+     448              : 
+     449              :     /**
+     450              :      * @notice Checks if an address is able to spend as an exchange.
+     451              :      * @dev isExchangeSpender was introduced after cUSD, so the cUSD Exchange is not included in it.
+     452              :      * If cUSD's Exchange were to be added to isExchangeSpender, the check with the
+     453              :      * registry could be removed.
+     454              :      * @param spender The address to be checked.
+     455              :      */
+     456              :     modifier isAllowedToSpendExchange(address spender) {
+     457            0 :         require(
+     458              :             isExchangeSpender[spender] ||
+     459              :                 (registry.getAddressForOrDie(EXCHANGE_REGISTRY_ID) == spender),
+     460              :             "Address not allowed to spend"
+     461              :         );
+     462              :         _;
+     463              :     }
+     464              : 
+     465              :     /**
+     466              :      * @notice Gives an address permission to spend Reserve without limit.
+     467              :      * @param spender The address that is allowed to spend Reserve funds.
+     468              :      */
+     469              :     function addExchangeSpender(address spender) external onlyOwner {
+     470            6 :         require(address(0) != spender, "Spender can't be null");
+     471            6 :         require(
+     472              :             !isExchangeSpender[spender],
+     473              :             "Address is already Exchange Spender"
+     474              :         );
+     475            6 :         isExchangeSpender[spender] = true;
+     476            6 :         exchangeSpenderAddresses.push(spender);
+     477            6 :         emit ExchangeSpenderAdded(spender);
+     478              :     }
+     479              : 
+     480              :     /**
+     481              :      * @notice Takes away an address's permission to spend Reserve funds without limits.
+     482              :      * @param spender The address that is to be no longer allowed to spend Reserve funds.
+     483              :      * @param index The index in exchangeSpenderAddresses of spender.
+     484              :      */
+     485              :     function removeExchangeSpender(
+     486              :         address spender,
+     487              :         uint256 index
+     488              :     ) external onlyOwner {
+     489            0 :         isExchangeSpender[spender] = false;
+     490            0 :         uint256 numAddresses = exchangeSpenderAddresses.length;
+     491            0 :         require(index < numAddresses, "Index is invalid");
+     492            0 :         require(
+     493              :             spender == exchangeSpenderAddresses[index],
+     494              :             "Index does not match spender"
+     495              :         );
+     496            0 :         uint256 newNumAddresses = numAddresses.sub(1);
+     497              : 
+     498            0 :         if (index != newNumAddresses) {
+     499            0 :             exchangeSpenderAddresses[index] = exchangeSpenderAddresses[
+     500              :                 newNumAddresses
+     501              :             ];
+     502              :         }
+     503              : 
+     504            0 :         exchangeSpenderAddresses[newNumAddresses] = address(0x0);
+     505            0 :         exchangeSpenderAddresses.length = newNumAddresses;
+     506            0 :         emit ExchangeSpenderRemoved(spender);
+     507              :     }
+     508              : 
+     509              :     /**
+     510              :      * @notice Returns addresses of exchanges permitted to spend Reserve funds.
+     511              :      * Because exchangeSpenderAddresses was introduced after cUSD, cUSD's exchange
+     512              :      * is not included in this list.
+     513              :      * @return An array of addresses permitted to spend Reserve funds.
+     514              :      */
+     515              :     function getExchangeSpenders() external view returns (address[] memory) {
+     516            0 :         return exchangeSpenderAddresses;
+     517              :     }
+     518              : 
+     519              :     /**
+     520              :      * @notice Transfer gold to a whitelisted address subject to reserve spending limits.
+     521              :      * @param to The address that will receive the gold.
+     522              :      * @param value The amount of gold to transfer.
+     523              :      * @return Returns true if the transaction succeeds.
+     524              :      */
+     525              :     function transferGold(
+     526              :         address payable to,
+     527              :         uint256 value
+     528              :     ) external returns (bool) {
+     529            0 :         require(
+     530              :             isSpender[msg.sender],
+     531              :             "sender not allowed to transfer Reserve funds"
+     532              :         );
+     533            0 :         require(
+     534              :             isOtherReserveAddress[to],
+     535              :             "can only transfer to other reserve address"
+     536              :         );
+     537            0 :         uint256 currentDay = now / 1 days;
+     538            0 :         if (currentDay > lastSpendingDay) {
+     539            0 :             uint256 balance = getUnfrozenReserveGoldBalance();
+     540            0 :             lastSpendingDay = currentDay;
+     541            0 :             spendingLimit = spendingRatio
+     542              :                 .multiply(FixidityLib.newFixed(balance))
+     543              :                 .fromFixed();
+     544              :         }
+     545            0 :         require(spendingLimit >= value, "Exceeding spending limit");
+     546            0 :         spendingLimit = spendingLimit.sub(value);
+     547            0 :         return _transferGold(to, value);
+     548              :     }
+     549              : 
+     550              :     /**
+     551              :      * @notice Transfer collateral asset subject to reserve spending limits to the trader,
+     552              :      * if the limit is set, othersise the limit is 100%.
+     553              :      * @param collateralAsset The token address you're transferring.
+     554              :      * @param to The address that will receive the funds.
+     555              :      * @param value The amount of collateral assets to transfer.
+     556              :      * @return Returns true if the transaction succeeds.
+     557              :      */
+     558              :     function transferCollateralAsset(
+     559              :         address collateralAsset,
+     560              :         address payable to,
+     561              :         uint256 value
+     562              :     ) external returns (bool) {
+     563            0 :         require(
+     564              :             isSpender[msg.sender],
+     565              :             "sender not allowed to transfer Reserve funds"
+     566              :         );
+     567            0 :         require(
+     568              :             isOtherReserveAddress[to],
+     569              :             "can only transfer to other reserve address"
+     570              :         );
+     571            0 :         require(
+     572              :             getDailySpendingRatioForCollateralAsset(collateralAsset) > 0,
+     573              :             "this asset has no spending ratio, therefore can't be transferred"
+     574              :         );
+     575            0 :         uint256 currentDay = now / 1 days;
+     576            0 :         if (currentDay > collateralAssetLastSpendingDay[collateralAsset]) {
+     577            0 :             uint256 balance = getReserveAddressesCollateralAssetBalance(
+     578              :                 collateralAsset
+     579              :             );
+     580            0 :             collateralAssetLastSpendingDay[collateralAsset] = currentDay;
+     581            0 :             collateralAssetSpendingLimit[
+     582              :                 collateralAsset
+     583              :             ] = collateralAssetDailySpendingRatio[collateralAsset]
+     584              :                 .multiply(FixidityLib.newFixed(balance))
+     585              :                 .fromFixed();
+     586              :         }
+     587            0 :         uint256 spendingLimitForThisAsset = collateralAssetSpendingLimit[
+     588              :             collateralAsset
+     589              :         ];
+     590            0 :         require(spendingLimitForThisAsset >= value, "Exceeding spending limit");
+     591              : 
+     592            0 :         collateralAssetSpendingLimit[
+     593              :             collateralAsset
+     594              :         ] = spendingLimitForThisAsset.sub(value);
+     595            0 :         return _transferCollateralAsset(collateralAsset, to, value);
+     596              :     }
+     597              : 
+     598              :     /**
+     599              :      * @notice Transfer collateral asset to any address.
+     600              :      * @param collateralAsset The token address you're transferring.
+     601              :      * @param to The address that will receive the funds.
+     602              :      * @param value The amount of collateral assets to transfer.
+     603              :      * @return Returns true if the transaction succeeds.
+     604              :      */
+     605              :     function _transferCollateralAsset(
+     606              :         address collateralAsset,
+     607              :         address payable to,
+     608              :         uint256 value
+     609              :     ) internal returns (bool) {
+     610            2 :         require(
+     611              :             value <= getReserveAddressesCollateralAssetBalance(collateralAsset),
+     612              :             "Exceeding the amount reserve holds"
+     613              :         );
+     614              :         // slither-disable-next-line reentrancy-events
+     615            2 :         IERC20(collateralAsset).safeTransfer(to, value);
+     616            2 :         emit ReserveCollateralAssetsTransferred(
+     617              :             msg.sender,
+     618              :             to,
+     619              :             value,
+     620              :             collateralAsset
+     621              :         );
+     622            2 :         return true;
+     623              :     }
+     624              : 
+     625              :     /**
+     626              :      * @notice Transfer collateral asset to any address.
+     627              :      * @dev Transfers are not subject to a daily spending limit.
+     628              :      * @param collateralAsset The address of collateral asset being transferred.
+     629              :      * @param to The address that will receive the collateral asset.
+     630              :      * @param value The amount of collateral asset to transfer.
+     631              :      * @return Returns true if the transaction succeeds.
+     632              :      */
+     633              :     function transferExchangeCollateralAsset(
+     634              :         address collateralAsset,
+     635              :         address payable to,
+     636              :         uint256 value
+     637              :     ) external returns (bool) {
+     638            2 :         require(isExchangeSpender[msg.sender], "Address not allowed to spend");
+     639            2 :         return _transferCollateralAsset(collateralAsset, to, value);
+     640              :     }
+     641              : 
+     642              :     /**
+     643              :      * @notice Transfer unfrozen gold to any address.
+     644              :      * @param to The address that will receive the gold.
+     645              :      * @param value The amount of gold to transfer.
+     646              :      * @return Returns true if the transaction succeeds.
+     647              :      */
+     648              :     function _transferGold(
+     649              :         address payable to,
+     650              :         uint256 value
+     651              :     ) internal returns (bool) {
+     652            0 :         require(value <= getUnfrozenBalance(), "Exceeding unfrozen reserves");
+     653              :         // slither-disable-next-line reentrancy-events
+     654            0 :         to.sendValue(value);
+     655            0 :         emit ReserveGoldTransferred(msg.sender, to, value);
+     656            0 :         return true;
+     657              :     }
+     658              : 
+     659              :     /**
+     660              :      * @notice Transfer unfrozen gold to any address, used for one side of CP-DOTO.
+     661              :      * @dev Transfers are not subject to a daily spending limit.
+     662              :      * @param to The address that will receive the gold.
+     663              :      * @param value The amount of gold to transfer.
+     664              :      * @return Returns true if the transaction succeeds.
+     665              :      */
+     666              :     function transferExchangeGold(
+     667              :         address payable to,
+     668              :         uint256 value
+     669              :     ) external isAllowedToSpendExchange(msg.sender) returns (bool) {
+     670            0 :         return _transferGold(to, value);
+     671              :     }
+     672              : 
+     673              :     /**
+     674              :      * @notice Returns the tobin tax, recomputing it if it's stale.
+     675              :      * @return The numerator - tobin tax amount as a fraction.
+     676              :      * @return The denominator - tobin tax amount as a fraction.
+     677              :      */
+     678              :     function getOrComputeTobinTax()
+     679              :         external
+     680              :         nonReentrant
+     681              :         returns (uint256, uint256)
+     682              :     {
+     683              :         // solhint-disable-next-line not-rely-on-time
+     684            0 :         if (now.sub(tobinTaxCache.timestamp) > tobinTaxStalenessThreshold) {
+     685            0 :             tobinTaxCache.numerator = uint128(computeTobinTax().unwrap());
+     686            0 :             tobinTaxCache.timestamp = uint128(now); // solhint-disable-line not-rely-on-time
+     687              :         }
+     688            0 :         return (
+     689              :             uint256(tobinTaxCache.numerator),
+     690              :             FixidityLib.fixed1().unwrap()
+     691              :         );
+     692              :     }
+     693              : 
+     694              :     /**
+     695              :      * @notice Returns the list of stabilized token addresses.
+     696              :      * @return An array of addresses of stabilized tokens.
+     697              :      */
+     698              :     function getTokens() external view returns (address[] memory) {
+     699            0 :         return _tokens;
+     700              :     }
+     701              : 
+     702              :     /**
+     703              :      * @notice Returns the list other addresses included in the reserve total.
+     704              :      * @return An array of other addresses included in the reserve total.
+     705              :      */
+     706              :     function getOtherReserveAddresses()
+     707              :         external
+     708              :         view
+     709              :         returns (address[] memory)
+     710              :     {
+     711            0 :         return otherReserveAddresses;
+     712              :     }
+     713              : 
+     714              :     /**
+     715              :      * @notice Returns a list of token symbols that have been allocated.
+     716              :      * @return An array of token symbols that have been allocated.
+     717              :      */
+     718              :     function getAssetAllocationSymbols()
+     719              :         external
+     720              :         view
+     721              :         returns (bytes32[] memory)
+     722              :     {
+     723            0 :         return assetAllocationSymbols;
+     724              :     }
+     725              : 
+     726              :     /**
+     727              :      * @notice Returns a list of weights used for the allocation of reserve assets.
+     728              :      * @return An array of a list of weights used for the allocation of reserve assets.
+     729              :      */
+     730              :     function getAssetAllocationWeights()
+     731              :         external
+     732              :         view
+     733              :         returns (uint256[] memory)
+     734              :     {
+     735            0 :         uint256[] memory weights = new uint256[](assetAllocationSymbols.length);
+     736              :         // slither-disable-next-line cache-array-length
+     737            0 :         for (uint256 i = 0; i < assetAllocationSymbols.length; i = i.add(1)) {
+     738            0 :             weights[i] = assetAllocationWeights[assetAllocationSymbols[i]];
+     739              :         }
+     740            0 :         return weights;
+     741              :     }
+     742              : 
+     743              :     /**
+     744              :      * @notice Returns the amount of unfrozen CELO in the reserve.
+     745              :      * @return The total unfrozen CELO in the reserve.
+     746              :      */
+     747              :     function getUnfrozenBalance() public view returns (uint256) {
+     748            0 :         uint256 balance = address(this).balance;
+     749            0 :         uint256 frozenReserveGold = getFrozenReserveGoldBalance();
+     750            0 :         return balance > frozenReserveGold ? balance.sub(frozenReserveGold) : 0;
+     751              :     }
+     752              : 
+     753              :     /**
+     754              :      * @notice Returns the amount of CELO included in the reserve.
+     755              :      * @return The CELO amount included in the reserve.
+     756              :      */
+     757              :     function getReserveGoldBalance() public view returns (uint256) {
+     758            0 :         return address(this).balance.add(getOtherReserveAddressesGoldBalance());
+     759              :     }
+     760              : 
+     761              :     /**
+     762              :      * @notice Returns the amount of CELO included in other reserve addresses.
+     763              :      * @return The CELO amount included in other reserve addresses.
+     764              :      */
+     765              :     function getOtherReserveAddressesGoldBalance()
+     766              :         public
+     767              :         view
+     768              :         returns (uint256)
+     769              :     {
+     770            0 :         uint256 reserveGoldBalance = 0;
+     771              :         // slither-disable-next-line cache-array-length
+     772            0 :         for (uint256 i = 0; i < otherReserveAddresses.length; i = i.add(1)) {
+     773            0 :             reserveGoldBalance = reserveGoldBalance.add(
+     774              :                 otherReserveAddresses[i].balance
+     775              :             );
+     776              :         }
+     777            0 :         return reserveGoldBalance;
+     778              :     }
+     779              : 
+     780              :     /**
+     781              :      * @notice Returns the amount of unfrozen CELO included in the reserve.
+     782              :      * @return The unfrozen CELO amount included in the reserve.
+     783              :      */
+     784              :     function getUnfrozenReserveGoldBalance() public view returns (uint256) {
+     785            0 :         return getUnfrozenBalance().add(getOtherReserveAddressesGoldBalance());
+     786              :     }
+     787              : 
+     788              :     /**
+     789              :      * @notice Returns the amount of particular collateral asset
+     790              :      * in reserve including other reserve addresses.
+     791              :      * @param collateralAsset the asset we're checking a balance of
+     792              :      * @return The balance of particular collateral asset.
+     793              :      */
+     794              :     function getReserveAddressesCollateralAssetBalance(
+     795              :         address collateralAsset
+     796              :     ) public view returns (uint256) {
+     797            2 :         require(
+     798              :             checkIsCollateralAsset(collateralAsset),
+     799              :             "specified address is not a collateral asset"
+     800              :         );
+     801            2 :         uint256 reserveCollateralAssetBalance = 0;
+     802              :         // slither-disable-next-line cache-array-length
+     803            2 :         for (uint256 i = 0; i < otherReserveAddresses.length; i++) {
+     804              :             // slither-disable-next-line calls-loop
+     805            0 :             reserveCollateralAssetBalance = reserveCollateralAssetBalance.add(
+     806              :                 IERC20(collateralAsset).balanceOf(otherReserveAddresses[i])
+     807              :             );
+     808              :         }
+     809            2 :         return
+     810            2 :             reserveCollateralAssetBalance.add(
+     811              :                 IERC20(collateralAsset).balanceOf(address(this))
+     812              :             );
+     813              :     }
+     814              : 
+     815              :     /**
+     816              :      * @notice Add a collateral asset in the reserve.
+     817              :      * @param collateralAsset The address of the token being added.
+     818              :      * @return Returns true if the transaction succeeds.
+     819              :      */
+     820              :     function addCollateralAsset(
+     821              :         address collateralAsset
+     822              :     ) public onlyOwner returns (bool) {
+     823            6 :         require(
+     824              :             !checkIsCollateralAsset(collateralAsset),
+     825              :             "specified address is already added as a collateral asset"
+     826              :         );
+     827            6 :         require(collateralAsset != address(0), "can't be a zero address");
+     828            6 :         isCollateralAsset[collateralAsset] = true;
+     829            6 :         collateralAssets.push(collateralAsset);
+     830            6 :         emit CollateralAssetAdded(collateralAsset);
+     831            6 :         return true;
+     832              :     }
+     833              : 
+     834              :     /**
+     835              :      * @notice Remove a collateral asset in the reserve.
+     836              :      * @param collateralAsset The address of the token being removed.
+     837              :      * @param index The index of the token being removed.
+     838              :      * @return Returns true if the transaction succeeds.
+     839              :      */
+     840              :     function removeCollateralAsset(
+     841              :         address collateralAsset,
+     842              :         uint256 index
+     843              :     ) external onlyOwner returns (bool) {
+     844            0 :         require(
+     845              :             checkIsCollateralAsset(collateralAsset),
+     846              :             "specified address is not a collateral asset"
+     847              :         );
+     848            0 :         require(
+     849              :             index < collateralAssets.length &&
+     850              :                 collateralAssets[index] == collateralAsset,
+     851              :             "index into collateralAssets list not mapped to token"
+     852              :         );
+     853            0 :         collateralAssets[index] = collateralAssets[
+     854              :             collateralAssets.length.sub(1)
+     855              :         ];
+     856            0 :         collateralAssets.pop();
+     857            0 :         delete isCollateralAsset[collateralAsset];
+     858            0 :         emit CollateralAssetRemoved(collateralAsset);
+     859            0 :         return true;
+     860              :     }
+     861              : 
+     862              :     /**
+     863              :      * @notice Check if a collateral asset is added to the reserve.
+     864              :      * @param collateralAsset The address of the token being checked.
+     865              :      * @return Returns true if the token was added as a collateral asset.
+     866              :      */
+     867              :     function checkIsCollateralAsset(
+     868              :         address collateralAsset
+     869              :     ) public view returns (bool) {
+     870           14 :         return isCollateralAsset[collateralAsset];
+     871              :     }
+     872              : 
+     873              :     /**
+     874              :      * @notice Returns the amount of frozen CELO in the reserve.
+     875              :      * @return The total frozen CELO in the reserve.
+     876              :      */
+     877              :     function getFrozenReserveGoldBalance() public view returns (uint256) {
+     878            0 :         uint256 currentDay = now / 1 days;
+     879            0 :         uint256 frozenDays = currentDay.sub(frozenReserveGoldStartDay);
+     880            0 :         if (frozenDays >= frozenReserveGoldDays) return 0;
+     881            0 :         return
+     882            0 :             frozenReserveGoldStartBalance.sub(
+     883              :                 frozenReserveGoldStartBalance.mul(frozenDays).div(
+     884              :                     frozenReserveGoldDays
+     885              :                 )
+     886              :             );
+     887              :     }
+     888              : 
+     889              :     /**
+     890              :      * @notice Computes the ratio of current reserve balance to total stable token valuation.
+     891              :      * @return Reserve ratio in a fixed point format.
+     892              :      */
+     893              :     function getReserveRatio() public view returns (uint256) {
+     894            0 :         address sortedOraclesAddress = registry.getAddressForOrDie(
+     895              :             SORTED_ORACLES_REGISTRY_ID
+     896              :         );
+     897            0 :         ISortedOracles sortedOracles = ISortedOracles(sortedOraclesAddress);
+     898            0 :         uint256 reserveGoldBalance = getUnfrozenReserveGoldBalance();
+     899            0 :         uint256 stableTokensValueInGold = 0;
+     900            0 :         FixidityLib.Fraction memory cgldWeight = FixidityLib.wrap(
+     901              :             assetAllocationWeights["cGLD"]
+     902              :         );
+     903              : 
+     904              :         // slither-disable-next-line cache-array-length
+     905            0 :         for (uint256 i = 0; i < _tokens.length; i = i.add(1)) {
+     906            0 :             uint256 stableAmount;
+     907            0 :             uint256 goldAmount;
+     908              :             // slither-disable-next-line calls-loop
+     909            0 :             (stableAmount, goldAmount) = sortedOracles.medianRate(_tokens[i]);
+     910              : 
+     911            0 :             if (goldAmount != 0) {
+     912              :                 // tokens with no oracle reports don't count towards collateralization ratio
+     913              :                 // slither-disable-next-line calls-loop
+     914            0 :                 uint256 stableTokenSupply = IERC20(_tokens[i]).totalSupply();
+     915            0 :                 uint256 aStableTokenValueInGold = stableTokenSupply
+     916              :                     .mul(goldAmount)
+     917              :                     .div(stableAmount);
+     918            0 :                 stableTokensValueInGold = stableTokensValueInGold.add(
+     919              :                     aStableTokenValueInGold
+     920              :                 );
+     921              :             }
+     922              :         }
+     923            0 :         return
+     924            0 :             FixidityLib
+     925              :                 .newFixed(reserveGoldBalance)
+     926              :                 .divide(cgldWeight)
+     927              :                 .divide(FixidityLib.newFixed(stableTokensValueInGold))
+     928              :                 .unwrap();
+     929              :     }
+     930              : 
+     931              :     /*
+     932              :      * Internal functions
+     933              :      */
+     934              : 
+     935              :     /**
+     936              :      * @notice Computes a tobin tax based on the reserve ratio.
+     937              :      * @return The tobin tax expresesed as a fixidity fraction.
+     938              :      */
+     939              :     function computeTobinTax()
+     940              :         private
+     941              :         view
+     942              :         returns (FixidityLib.Fraction memory)
+     943              :     {
+     944            0 :         FixidityLib.Fraction memory ratio = FixidityLib.wrap(getReserveRatio());
+     945            0 :         if (ratio.gte(FixidityLib.wrap(tobinTaxReserveRatio))) {
+     946            0 :             return FixidityLib.wrap(0);
+     947              :         } else {
+     948            0 :             return FixidityLib.wrap(tobinTax);
+     949              :         }
+     950              :     }
+     951              : 
+     952              :     function isStableAsset(address token) external view returns (bool) {
+     953           20 :         return isToken[token];
+     954              :     }
+     955              : }
+        
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage_report/contracts/swap/index-sort-f.html b/coverage_report/contracts/swap/index-sort-f.html index c10e27a..d58ef98 100644 --- a/coverage_report/contracts/swap/index-sort-f.html +++ b/coverage_report/contracts/swap/index-sort-f.html @@ -31,18 +31,18 @@ lcov.info Lines: - 97.4 % - 77 - 75 + 54.9 % + 275 + 151 Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: - 100.0 % - 16 - 16 + 37.1 % + 62 + 23 @@ -79,6 +79,18 @@ Total Hit + + Reserve.sol + +
38.4%38.4%
+ + 38.4 % + 198 + 76 + 15.2 % + 46 + 7 + Broker.sol diff --git a/coverage_report/contracts/swap/index-sort-l.html b/coverage_report/contracts/swap/index-sort-l.html index 829cf58..201d686 100644 --- a/coverage_report/contracts/swap/index-sort-l.html +++ b/coverage_report/contracts/swap/index-sort-l.html @@ -31,18 +31,18 @@ lcov.info Lines: - 97.4 % - 77 - 75 + 54.9 % + 275 + 151 Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: - 100.0 % - 16 - 16 + 37.1 % + 62 + 23 @@ -79,6 +79,18 @@ Total Hit + + Reserve.sol + +
38.4%38.4%
+ + 38.4 % + 198 + 76 + 15.2 % + 46 + 7 + Broker.sol diff --git a/coverage_report/contracts/swap/index.html b/coverage_report/contracts/swap/index.html index 558c6a6..f215052 100644 --- a/coverage_report/contracts/swap/index.html +++ b/coverage_report/contracts/swap/index.html @@ -31,18 +31,18 @@ lcov.info Lines: - 97.4 % - 77 - 75 + 54.9 % + 275 + 151 Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: - 100.0 % - 16 - 16 + 37.1 % + 62 + 23 @@ -91,6 +91,18 @@ 16 16 + + Reserve.sol + +
38.4%38.4%
+ + 38.4 % + 198 + 76 + 15.2 % + 46 + 7 +
diff --git a/coverage_report/index-sort-f.html b/coverage_report/index-sort-f.html index 8b92d32..a95e10b 100644 --- a/coverage_report/index-sort-f.html +++ b/coverage_report/index-sort-f.html @@ -31,18 +31,18 @@ lcov.info Lines: - 81.3 % - 857 - 697 + 73.0 % + 1070 + 781 Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: - 83.6 % - 146 - 122 + 65.0 % + 203 + 132 @@ -79,6 +79,42 @@ Total Hit + + contracts/common/ + +
52.9%52.9%
+ + 52.9 % + 17 + 9 + 30.8 % + 13 + 4 + + + contracts/swap/ + +
54.9%54.9%
+ + 54.9 % + 275 + 151 + 37.1 % + 62 + 23 + + + node_modules/@celo/contracts/common/libraries/ + +
25.0%25.0%
+ + 25.0 % + 4 + 1 + 50.0 % + 2 + 1 + test/utils/mocks/ @@ -94,23 +130,23 @@ node_modules/@celo/contracts/common/ -
80.0%80.0%
+
83.3%83.3%
- 80.0 % + 83.3 % 60 - 48 - 62.5 % + 50 + 70.8 % 24 - 15 + 17 contracts/ -
77.4%77.4%
+
77.8%77.8%
- 77.4 % + 77.8 % 576 - 446 + 448 91.8 % 61 56 @@ -127,18 +163,6 @@ 1 1 - - contracts/common/ - -
100.0%
- - 100.0 % - 6 - 6 - 100.0 % - 4 - 4 - test/utils/harnesses/ @@ -175,18 +199,6 @@ 6 6 - - contracts/swap/ - -
97.4%97.4%
- - 97.4 % - 77 - 75 - 100.0 % - 16 - 16 -
diff --git a/coverage_report/index-sort-l.html b/coverage_report/index-sort-l.html index e9a1d90..530599e 100644 --- a/coverage_report/index-sort-l.html +++ b/coverage_report/index-sort-l.html @@ -31,18 +31,18 @@ lcov.info Lines: - 81.3 % - 857 - 697 + 73.0 % + 1070 + 781 Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: - 83.6 % - 146 - 122 + 65.0 % + 203 + 132 @@ -79,6 +79,42 @@ Total Hit + + node_modules/@celo/contracts/common/libraries/ + +
25.0%25.0%
+ + 25.0 % + 4 + 1 + 50.0 % + 2 + 1 + + + contracts/common/ + +
52.9%52.9%
+ + 52.9 % + 17 + 9 + 30.8 % + 13 + 4 + + + contracts/swap/ + +
54.9%54.9%
+ + 54.9 % + 275 + 151 + 37.1 % + 62 + 23 + test/utils/mocks/ @@ -94,11 +130,11 @@ contracts/ -
77.4%77.4%
+
77.8%77.8%
- 77.4 % + 77.8 % 576 - 446 + 448 91.8 % 61 56 @@ -106,14 +142,14 @@ node_modules/@celo/contracts/common/ -
80.0%80.0%
+
83.3%83.3%
- 80.0 % + 83.3 % 60 - 48 - 62.5 % + 50 + 70.8 % 24 - 15 + 17 contracts/libraries/ @@ -127,18 +163,6 @@ 5 5 - - contracts/swap/ - -
97.4%97.4%
- - 97.4 % - 77 - 75 - 100.0 % - 16 - 16 - test/utils/harnesses/ @@ -151,18 +175,6 @@ 4 4 - - contracts/common/ - -
100.0%
- - 100.0 % - 6 - 6 - 100.0 % - 4 - 4 - test/unit/swap/ diff --git a/coverage_report/index.html b/coverage_report/index.html index c90260f..5a10654 100644 --- a/coverage_report/index.html +++ b/coverage_report/index.html @@ -31,18 +31,18 @@ lcov.info Lines: - 81.3 % - 857 - 697 + 73.0 % + 1070 + 781 Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: - 83.6 % - 146 - 122 + 65.0 % + 203 + 132 @@ -82,11 +82,11 @@ contracts/ -
77.4%77.4%
+
77.8%77.8%
- 77.4 % + 77.8 % 576 - 446 + 448 91.8 % 61 56 @@ -94,13 +94,13 @@ contracts/common/ -
100.0%
+
52.9%52.9%
- 100.0 % - 6 - 6 - 100.0 % - 4 + 52.9 % + 17 + 9 + 30.8 % + 13 4 @@ -118,26 +118,38 @@ contracts/swap/ -
97.4%97.4%
+
54.9%54.9%
- 97.4 % - 77 - 75 - 100.0 % - 16 - 16 + 54.9 % + 275 + 151 + 37.1 % + 62 + 23 node_modules/@celo/contracts/common/ -
80.0%80.0%
+
83.3%83.3%
- 80.0 % + 83.3 % 60 - 48 - 62.5 % + 50 + 70.8 % 24 - 15 + 17 + + + node_modules/@celo/contracts/common/libraries/ + +
25.0%25.0%
+ + 25.0 % + 4 + 1 + 50.0 % + 2 + 1 test/unit/goodDollar/ diff --git a/coverage_report/test/unit/goodDollar/BancorExchangeProvider.t.sol.func-c.html b/coverage_report/test/unit/goodDollar/BancorExchangeProvider.t.sol.func-c.html index 66d94c1..d835caf 100644 --- a/coverage_report/test/unit/goodDollar/BancorExchangeProvider.t.sol.func-c.html +++ b/coverage_report/test/unit/goodDollar/BancorExchangeProvider.t.sol.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/unit/goodDollar/BancorExchangeProvider.t.sol.func.html b/coverage_report/test/unit/goodDollar/BancorExchangeProvider.t.sol.func.html index fcbdd9b..c993807 100644 --- a/coverage_report/test/unit/goodDollar/BancorExchangeProvider.t.sol.func.html +++ b/coverage_report/test/unit/goodDollar/BancorExchangeProvider.t.sol.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/unit/goodDollar/BancorExchangeProvider.t.sol.gcov.html b/coverage_report/test/unit/goodDollar/BancorExchangeProvider.t.sol.gcov.html index 6d299b6..b7d93f2 100644 --- a/coverage_report/test/unit/goodDollar/BancorExchangeProvider.t.sol.gcov.html +++ b/coverage_report/test/unit/goodDollar/BancorExchangeProvider.t.sol.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/unit/goodDollar/GoodDollarExchangeProvider.t.sol.func-c.html b/coverage_report/test/unit/goodDollar/GoodDollarExchangeProvider.t.sol.func-c.html index 2ac1d3b..db4eaf8 100644 --- a/coverage_report/test/unit/goodDollar/GoodDollarExchangeProvider.t.sol.func-c.html +++ b/coverage_report/test/unit/goodDollar/GoodDollarExchangeProvider.t.sol.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/unit/goodDollar/GoodDollarExchangeProvider.t.sol.func.html b/coverage_report/test/unit/goodDollar/GoodDollarExchangeProvider.t.sol.func.html index ad2d950..6bd05bc 100644 --- a/coverage_report/test/unit/goodDollar/GoodDollarExchangeProvider.t.sol.func.html +++ b/coverage_report/test/unit/goodDollar/GoodDollarExchangeProvider.t.sol.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/unit/goodDollar/GoodDollarExchangeProvider.t.sol.gcov.html b/coverage_report/test/unit/goodDollar/GoodDollarExchangeProvider.t.sol.gcov.html index 5a2f9d7..97042da 100644 --- a/coverage_report/test/unit/goodDollar/GoodDollarExchangeProvider.t.sol.gcov.html +++ b/coverage_report/test/unit/goodDollar/GoodDollarExchangeProvider.t.sol.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/unit/goodDollar/GoodDollarExpansionController.t.sol.func-c.html b/coverage_report/test/unit/goodDollar/GoodDollarExpansionController.t.sol.func-c.html index 7bdd528..b4c2e4d 100644 --- a/coverage_report/test/unit/goodDollar/GoodDollarExpansionController.t.sol.func-c.html +++ b/coverage_report/test/unit/goodDollar/GoodDollarExpansionController.t.sol.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/unit/goodDollar/GoodDollarExpansionController.t.sol.func.html b/coverage_report/test/unit/goodDollar/GoodDollarExpansionController.t.sol.func.html index e0156ba..792ba08 100644 --- a/coverage_report/test/unit/goodDollar/GoodDollarExpansionController.t.sol.func.html +++ b/coverage_report/test/unit/goodDollar/GoodDollarExpansionController.t.sol.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/unit/goodDollar/GoodDollarExpansionController.t.sol.gcov.html b/coverage_report/test/unit/goodDollar/GoodDollarExpansionController.t.sol.gcov.html index bdc607b..be986de 100644 --- a/coverage_report/test/unit/goodDollar/GoodDollarExpansionController.t.sol.gcov.html +++ b/coverage_report/test/unit/goodDollar/GoodDollarExpansionController.t.sol.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/unit/goodDollar/index-sort-f.html b/coverage_report/test/unit/goodDollar/index-sort-f.html index 8f2068c..5be8673 100644 --- a/coverage_report/test/unit/goodDollar/index-sort-f.html +++ b/coverage_report/test/unit/goodDollar/index-sort-f.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/unit/goodDollar/index-sort-l.html b/coverage_report/test/unit/goodDollar/index-sort-l.html index e7627f2..d2250bb 100644 --- a/coverage_report/test/unit/goodDollar/index-sort-l.html +++ b/coverage_report/test/unit/goodDollar/index-sort-l.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/unit/goodDollar/index.html b/coverage_report/test/unit/goodDollar/index.html index 03359d9..e76e0a6 100644 --- a/coverage_report/test/unit/goodDollar/index.html +++ b/coverage_report/test/unit/goodDollar/index.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/unit/swap/Broker.t.sol.func-c.html b/coverage_report/test/unit/swap/Broker.t.sol.func-c.html index b954369..5d934d7 100644 --- a/coverage_report/test/unit/swap/Broker.t.sol.func-c.html +++ b/coverage_report/test/unit/swap/Broker.t.sol.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/unit/swap/Broker.t.sol.func.html b/coverage_report/test/unit/swap/Broker.t.sol.func.html index a89eb83..2bed53c 100644 --- a/coverage_report/test/unit/swap/Broker.t.sol.func.html +++ b/coverage_report/test/unit/swap/Broker.t.sol.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/unit/swap/Broker.t.sol.gcov.html b/coverage_report/test/unit/swap/Broker.t.sol.gcov.html index 72cffa3..89d20c2 100644 --- a/coverage_report/test/unit/swap/Broker.t.sol.gcov.html +++ b/coverage_report/test/unit/swap/Broker.t.sol.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/unit/swap/index-sort-f.html b/coverage_report/test/unit/swap/index-sort-f.html index d06398e..9c55883 100644 --- a/coverage_report/test/unit/swap/index-sort-f.html +++ b/coverage_report/test/unit/swap/index-sort-f.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/unit/swap/index-sort-l.html b/coverage_report/test/unit/swap/index-sort-l.html index 8603b09..945b8f8 100644 --- a/coverage_report/test/unit/swap/index-sort-l.html +++ b/coverage_report/test/unit/swap/index-sort-l.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/unit/swap/index.html b/coverage_report/test/unit/swap/index.html index 1f451f3..88b9f44 100644 --- a/coverage_report/test/unit/swap/index.html +++ b/coverage_report/test/unit/swap/index.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/utils/harnesses/TradingLimitsHarness.sol.func-c.html b/coverage_report/test/utils/harnesses/TradingLimitsHarness.sol.func-c.html index b182f24..2cd45e0 100644 --- a/coverage_report/test/utils/harnesses/TradingLimitsHarness.sol.func-c.html +++ b/coverage_report/test/utils/harnesses/TradingLimitsHarness.sol.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/utils/harnesses/TradingLimitsHarness.sol.func.html b/coverage_report/test/utils/harnesses/TradingLimitsHarness.sol.func.html index 365bc59..33de900 100644 --- a/coverage_report/test/utils/harnesses/TradingLimitsHarness.sol.func.html +++ b/coverage_report/test/utils/harnesses/TradingLimitsHarness.sol.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/utils/harnesses/TradingLimitsHarness.sol.gcov.html b/coverage_report/test/utils/harnesses/TradingLimitsHarness.sol.gcov.html index f3d22eb..1fb91e2 100644 --- a/coverage_report/test/utils/harnesses/TradingLimitsHarness.sol.gcov.html +++ b/coverage_report/test/utils/harnesses/TradingLimitsHarness.sol.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/utils/harnesses/index-sort-f.html b/coverage_report/test/utils/harnesses/index-sort-f.html index 33ba6bd..da6b088 100644 --- a/coverage_report/test/utils/harnesses/index-sort-f.html +++ b/coverage_report/test/utils/harnesses/index-sort-f.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/utils/harnesses/index-sort-l.html b/coverage_report/test/utils/harnesses/index-sort-l.html index 5f582b5..7e6e727 100644 --- a/coverage_report/test/utils/harnesses/index-sort-l.html +++ b/coverage_report/test/utils/harnesses/index-sort-l.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/utils/harnesses/index.html b/coverage_report/test/utils/harnesses/index.html index ed5654b..158ba17 100644 --- a/coverage_report/test/utils/harnesses/index.html +++ b/coverage_report/test/utils/harnesses/index.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/utils/mocks/MockExchangeProvider.sol.func-c.html b/coverage_report/test/utils/mocks/MockExchangeProvider.sol.func-c.html index d43d346..d5f557e 100644 --- a/coverage_report/test/utils/mocks/MockExchangeProvider.sol.func-c.html +++ b/coverage_report/test/utils/mocks/MockExchangeProvider.sol.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 87.5 % diff --git a/coverage_report/test/utils/mocks/MockExchangeProvider.sol.func.html b/coverage_report/test/utils/mocks/MockExchangeProvider.sol.func.html index 9f36ce6..05aca9d 100644 --- a/coverage_report/test/utils/mocks/MockExchangeProvider.sol.func.html +++ b/coverage_report/test/utils/mocks/MockExchangeProvider.sol.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 87.5 % diff --git a/coverage_report/test/utils/mocks/MockExchangeProvider.sol.gcov.html b/coverage_report/test/utils/mocks/MockExchangeProvider.sol.gcov.html index dbf2cf9..765f5fc 100644 --- a/coverage_report/test/utils/mocks/MockExchangeProvider.sol.gcov.html +++ b/coverage_report/test/utils/mocks/MockExchangeProvider.sol.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 87.5 % diff --git a/coverage_report/test/utils/mocks/MockReserve.sol.func-c.html b/coverage_report/test/utils/mocks/MockReserve.sol.func-c.html index 55ef5c5..cfbd34c 100644 --- a/coverage_report/test/utils/mocks/MockReserve.sol.func-c.html +++ b/coverage_report/test/utils/mocks/MockReserve.sol.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 35.7 % diff --git a/coverage_report/test/utils/mocks/MockReserve.sol.func.html b/coverage_report/test/utils/mocks/MockReserve.sol.func.html index f2ae805..21a7991 100644 --- a/coverage_report/test/utils/mocks/MockReserve.sol.func.html +++ b/coverage_report/test/utils/mocks/MockReserve.sol.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 35.7 % diff --git a/coverage_report/test/utils/mocks/MockReserve.sol.gcov.html b/coverage_report/test/utils/mocks/MockReserve.sol.gcov.html index 5b8eaca..02af702 100644 --- a/coverage_report/test/utils/mocks/MockReserve.sol.gcov.html +++ b/coverage_report/test/utils/mocks/MockReserve.sol.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 35.7 % diff --git a/coverage_report/test/utils/mocks/TestERC20.sol.func-c.html b/coverage_report/test/utils/mocks/TestERC20.sol.func-c.html index 87d2e0b..075b5aa 100644 --- a/coverage_report/test/utils/mocks/TestERC20.sol.func-c.html +++ b/coverage_report/test/utils/mocks/TestERC20.sol.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/utils/mocks/TestERC20.sol.func.html b/coverage_report/test/utils/mocks/TestERC20.sol.func.html index 80ca99e..12798c3 100644 --- a/coverage_report/test/utils/mocks/TestERC20.sol.func.html +++ b/coverage_report/test/utils/mocks/TestERC20.sol.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/utils/mocks/TestERC20.sol.gcov.html b/coverage_report/test/utils/mocks/TestERC20.sol.gcov.html index 31ae66c..8dfd788 100644 --- a/coverage_report/test/utils/mocks/TestERC20.sol.gcov.html +++ b/coverage_report/test/utils/mocks/TestERC20.sol.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 100.0 % diff --git a/coverage_report/test/utils/mocks/index-sort-f.html b/coverage_report/test/utils/mocks/index-sort-f.html index 4c650cd..780cd33 100644 --- a/coverage_report/test/utils/mocks/index-sort-f.html +++ b/coverage_report/test/utils/mocks/index-sort-f.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 60.0 % diff --git a/coverage_report/test/utils/mocks/index-sort-l.html b/coverage_report/test/utils/mocks/index-sort-l.html index 37b4c12..e558b14 100644 --- a/coverage_report/test/utils/mocks/index-sort-l.html +++ b/coverage_report/test/utils/mocks/index-sort-l.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 60.0 % diff --git a/coverage_report/test/utils/mocks/index.html b/coverage_report/test/utils/mocks/index.html index 78a69a1..7b1bf24 100644 --- a/coverage_report/test/utils/mocks/index.html +++ b/coverage_report/test/utils/mocks/index.html @@ -37,7 +37,7 @@ Test Date: - 2024-10-08 14:43:01 + 2024-10-08 18:32:54 Functions: 60.0 % diff --git a/lcov.info b/lcov.info index 573661a..e252c7a 100644 --- a/lcov.info +++ b/lcov.info @@ -1,7 +1,7 @@ TN: SF:contracts/BancorExchangeProvider.sol FN:51,BancorExchangeProvider. -FNDA:88,BancorExchangeProvider. +FNDA:94,BancorExchangeProvider. DA:52,0 BRDA:52,0,0,- DA:53,0 @@ -9,27 +9,27 @@ FN:62,BancorExchangeProvider.initialize FNDA:63,BancorExchangeProvider.initialize DA:63,63 FN:66,BancorExchangeProvider._initialize -FNDA:88,BancorExchangeProvider._initialize -DA:70,88 -DA:72,88 -DA:73,88 -DA:74,88 +FNDA:94,BancorExchangeProvider._initialize +DA:70,94 +DA:72,94 +DA:73,94 +DA:74,94 FN:79,BancorExchangeProvider.onlyBroker -FNDA:9,BancorExchangeProvider.onlyBroker -DA:80,9 +FNDA:11,BancorExchangeProvider.onlyBroker +DA:80,11 BRDA:80,1,0,1 -BRDA:80,1,1,7 +BRDA:80,1,1,9 FN:84,BancorExchangeProvider.verifyExchangeTokens -FNDA:16,BancorExchangeProvider.verifyExchangeTokens -DA:89,16 +FNDA:20,BancorExchangeProvider.verifyExchangeTokens +DA:89,20 BRDA:89,2,0,3 -BRDA:89,2,1,7 +BRDA:89,2,1,11 FN:105,BancorExchangeProvider.getPoolExchange -FNDA:7,BancorExchangeProvider.getPoolExchange -DA:108,63 -DA:109,63 +FNDA:9,BancorExchangeProvider.getPoolExchange +DA:108,91 +DA:109,91 BRDA:109,3,0,8 -BRDA:109,3,1,55 +BRDA:109,3,1,83 DA:113,0 FN:120,BancorExchangeProvider.getExchangeIds FNDA:3,BancorExchangeProvider.getExchangeIds @@ -44,43 +44,43 @@ DA:134,3 DA:135,3 DA:136,3 FN:148,BancorExchangeProvider.getAmountOut -FNDA:11,BancorExchangeProvider.getAmountOut -DA:154,11 -DA:155,10 -DA:156,10 -DA:162,4 -DA:163,4 +FNDA:13,BancorExchangeProvider.getAmountOut +DA:154,13 +DA:155,12 +DA:156,12 +DA:162,6 +DA:163,6 FN:174,BancorExchangeProvider.getAmountIn -FNDA:5,BancorExchangeProvider.getAmountIn -DA:180,5 -DA:181,4 -DA:183,4 -DA:189,4 -DA:190,4 +FNDA:7,BancorExchangeProvider.getAmountIn +DA:180,7 +DA:181,6 +DA:183,6 +DA:189,6 +DA:190,6 FN:198,BancorExchangeProvider.currentPrice -FNDA:6,BancorExchangeProvider.currentPrice -DA:202,8 +FNDA:18,BancorExchangeProvider.currentPrice +DA:202,20 BRDA:202,4,0,1 -BRDA:202,4,1,7 -DA:206,7 -DA:207,7 -DA:208,7 -DA:211,7 -DA:212,7 +BRDA:202,4,1,19 +DA:206,19 +DA:207,19 +DA:208,19 +DA:211,19 +DA:212,19 FN:221,BancorExchangeProvider.setBroker FNDA:3,BancorExchangeProvider.setBroker -DA:222,90 +DA:222,96 BRDA:222,5,0,1 -BRDA:222,5,1,89 -DA:223,89 -DA:224,89 +BRDA:222,5,1,95 +DA:223,95 +DA:224,95 FN:231,BancorExchangeProvider.setReserve FNDA:3,BancorExchangeProvider.setReserve -DA:232,90 +DA:232,96 BRDA:232,6,0,1 -BRDA:232,6,1,89 -DA:233,89 -DA:234,89 +BRDA:232,6,1,95 +DA:233,95 +DA:234,95 FN:242,BancorExchangeProvider.setExitContribution FNDA:4,BancorExchangeProvider.setExitContribution DA:246,3 @@ -93,26 +93,26 @@ DA:252,1 DA:253,1 DA:254,1 FN:262,BancorExchangeProvider.createExchange -FNDA:64,BancorExchangeProvider.createExchange -DA:265,63 -DA:266,63 -DA:268,55 -DA:274,55 +FNDA:70,BancorExchangeProvider.createExchange +DA:265,69 +DA:266,69 +DA:268,61 +DA:274,61 BRDA:274,9,0,1 -BRDA:274,9,1,54 -DA:279,54 -DA:280,54 -DA:281,54 +BRDA:274,9,1,60 +DA:279,60 +DA:280,60 +DA:281,60 BRDA:281,10,0,1 -BRDA:281,10,1,53 -DA:285,53 +BRDA:281,10,1,59 +DA:285,59 BRDA:285,11,0,1 -BRDA:285,11,1,52 -DA:287,52 -DA:289,52 -DA:292,52 -DA:293,52 -DA:294,52 +BRDA:285,11,1,58 +DA:287,58 +DA:289,58 +DA:292,58 +DA:293,58 +DA:294,58 FN:307,BancorExchangeProvider.destroyExchange FNDA:4,BancorExchangeProvider.destroyExchange DA:311,3 @@ -128,72 +128,72 @@ DA:323,1 DA:324,1 DA:326,1 FN:341,BancorExchangeProvider.swapIn -FNDA:8,BancorExchangeProvider.swapIn -DA:347,7 -DA:348,6 -DA:349,6 -DA:355,3 -DA:357,3 -DA:358,3 +FNDA:10,BancorExchangeProvider.swapIn +DA:347,9 +DA:348,8 +DA:349,8 +DA:355,5 +DA:357,5 +DA:358,5 FN:369,BancorExchangeProvider.swapOut -FNDA:8,BancorExchangeProvider.swapOut -DA:375,7 -DA:376,6 -DA:378,6 -DA:384,3 -DA:386,3 -DA:387,3 +FNDA:10,BancorExchangeProvider.swapOut +DA:375,9 +DA:376,8 +DA:378,8 +DA:384,5 +DA:386,5 +DA:387,5 FN:400,BancorExchangeProvider.executeSwap -FNDA:6,BancorExchangeProvider.executeSwap -DA:406,6 -DA:407,6 -BRDA:407,14,0,4 -BRDA:407,14,1,2 -DA:408,4 -DA:409,4 -DA:411,2 -DA:412,2 -DA:414,6 -DA:415,6 +FNDA:10,BancorExchangeProvider.executeSwap +DA:406,10 +DA:407,10 +BRDA:407,14,0,6 +BRDA:407,14,1,4 +DA:408,6 +DA:409,6 +DA:411,4 +DA:412,4 +DA:414,10 +DA:415,10 FN:426,BancorExchangeProvider._getAmountIn -FNDA:10,BancorExchangeProvider._getAmountIn -DA:437,7 -BRDA:437,15,0,4 -BRDA:437,15,1,3 -DA:438,4 -DA:445,3 -DA:452,3 +FNDA:14,BancorExchangeProvider._getAmountIn +DA:437,11 +BRDA:437,15,0,6 +BRDA:437,15,1,5 +DA:438,6 +DA:445,5 +DA:452,5 FN:466,BancorExchangeProvider._getAmountOut -FNDA:16,BancorExchangeProvider._getAmountOut -DA:477,7 -BRDA:477,16,0,4 -BRDA:477,16,1,3 -DA:478,4 -DA:485,3 -DA:488,3 +FNDA:20,BancorExchangeProvider._getAmountOut +DA:477,11 +BRDA:477,16,0,6 +BRDA:477,16,1,5 +DA:478,6 +DA:485,5 +DA:488,5 FN:502,BancorExchangeProvider.validate -FNDA:63,BancorExchangeProvider.validate -DA:503,63 +FNDA:69,BancorExchangeProvider.validate +DA:503,69 BRDA:503,17,0,1 -BRDA:503,17,1,62 -DA:504,62 +BRDA:503,17,1,68 +DA:504,68 BRDA:504,18,0,1 -BRDA:504,18,1,61 -DA:508,61 +BRDA:504,18,1,67 +DA:508,67 BRDA:508,19,0,1 -BRDA:508,19,1,60 -DA:509,60 +BRDA:508,19,1,66 +DA:509,66 BRDA:509,20,0,1 -BRDA:509,20,1,59 -DA:513,59 +BRDA:509,20,1,65 +DA:513,65 BRDA:513,21,0,2 -BRDA:513,21,1,57 -DA:514,57 +BRDA:513,21,1,63 +DA:514,63 BRDA:514,22,0,1 -BRDA:514,22,1,56 -DA:515,56 +BRDA:514,22,1,62 +DA:515,62 BRDA:515,23,0,1 -BRDA:515,23,1,55 +BRDA:515,23,1,61 FNF:22 FNH:22 LF:103 @@ -204,204 +204,204 @@ end_of_record TN: SF:contracts/BancorFormula.sol FN:39,BancorFormula.initMaxExpArray -FNDA:88,BancorFormula.initMaxExpArray -DA:72,88 -DA:73,88 -DA:74,88 -DA:75,88 -DA:76,88 -DA:77,88 -DA:78,88 -DA:79,88 -DA:80,88 -DA:81,88 -DA:82,88 -DA:83,88 -DA:84,88 -DA:85,88 -DA:86,88 -DA:87,88 -DA:88,88 -DA:89,88 -DA:90,88 -DA:91,88 -DA:92,88 -DA:93,88 -DA:94,88 -DA:95,88 -DA:96,88 -DA:97,88 -DA:98,88 -DA:99,88 -DA:100,88 -DA:101,88 -DA:102,88 -DA:103,88 -DA:104,88 -DA:105,88 -DA:106,88 -DA:107,88 -DA:108,88 -DA:109,88 -DA:110,88 -DA:111,88 -DA:112,88 -DA:113,88 -DA:114,88 -DA:115,88 -DA:116,88 -DA:117,88 -DA:118,88 -DA:119,88 -DA:120,88 -DA:121,88 -DA:122,88 -DA:123,88 -DA:124,88 -DA:125,88 -DA:126,88 -DA:127,88 -DA:128,88 -DA:129,88 -DA:130,88 -DA:131,88 -DA:132,88 -DA:133,88 -DA:134,88 -DA:135,88 -DA:136,88 -DA:137,88 -DA:138,88 -DA:139,88 -DA:140,88 -DA:141,88 -DA:142,88 -DA:143,88 -DA:144,88 -DA:145,88 -DA:146,88 -DA:147,88 -DA:148,88 -DA:149,88 -DA:150,88 -DA:151,88 -DA:152,88 -DA:153,88 -DA:154,88 -DA:155,88 -DA:156,88 -DA:157,88 -DA:158,88 -DA:159,88 -DA:160,88 -DA:161,88 -DA:162,88 -DA:163,88 -DA:164,88 -DA:165,88 -DA:166,88 -DA:167,88 +FNDA:94,BancorFormula.initMaxExpArray +DA:72,94 +DA:73,94 +DA:74,94 +DA:75,94 +DA:76,94 +DA:77,94 +DA:78,94 +DA:79,94 +DA:80,94 +DA:81,94 +DA:82,94 +DA:83,94 +DA:84,94 +DA:85,94 +DA:86,94 +DA:87,94 +DA:88,94 +DA:89,94 +DA:90,94 +DA:91,94 +DA:92,94 +DA:93,94 +DA:94,94 +DA:95,94 +DA:96,94 +DA:97,94 +DA:98,94 +DA:99,94 +DA:100,94 +DA:101,94 +DA:102,94 +DA:103,94 +DA:104,94 +DA:105,94 +DA:106,94 +DA:107,94 +DA:108,94 +DA:109,94 +DA:110,94 +DA:111,94 +DA:112,94 +DA:113,94 +DA:114,94 +DA:115,94 +DA:116,94 +DA:117,94 +DA:118,94 +DA:119,94 +DA:120,94 +DA:121,94 +DA:122,94 +DA:123,94 +DA:124,94 +DA:125,94 +DA:126,94 +DA:127,94 +DA:128,94 +DA:129,94 +DA:130,94 +DA:131,94 +DA:132,94 +DA:133,94 +DA:134,94 +DA:135,94 +DA:136,94 +DA:137,94 +DA:138,94 +DA:139,94 +DA:140,94 +DA:141,94 +DA:142,94 +DA:143,94 +DA:144,94 +DA:145,94 +DA:146,94 +DA:147,94 +DA:148,94 +DA:149,94 +DA:150,94 +DA:151,94 +DA:152,94 +DA:153,94 +DA:154,94 +DA:155,94 +DA:156,94 +DA:157,94 +DA:158,94 +DA:159,94 +DA:160,94 +DA:161,94 +DA:162,94 +DA:163,94 +DA:164,94 +DA:165,94 +DA:166,94 +DA:167,94 FN:173,BancorFormula.init FNDA:0,BancorFormula.init -DA:174,88 +DA:174,94 FN:191,BancorFormula.purchaseTargetAmount -FNDA:4,BancorFormula.purchaseTargetAmount -DA:198,4 +FNDA:6,BancorFormula.purchaseTargetAmount +DA:198,6 BRDA:198,0,0,- -BRDA:198,0,1,4 -DA:199,4 +BRDA:198,0,1,6 +DA:199,6 BRDA:199,1,0,- -BRDA:199,1,1,4 -DA:200,4 +BRDA:199,1,1,6 +DA:200,6 BRDA:200,2,0,- -BRDA:200,2,1,4 -DA:203,4 -DA:206,4 -DA:208,4 -DA:209,4 -DA:210,4 -DA:211,4 -DA:212,4 -DA:213,4 +BRDA:200,2,1,6 +DA:203,6 +DA:206,6 +DA:208,6 +DA:209,6 +DA:210,6 +DA:211,6 +DA:212,6 +DA:213,6 FN:230,BancorFormula.saleTargetAmount -FNDA:3,BancorFormula.saleTargetAmount -DA:237,3 +FNDA:5,BancorFormula.saleTargetAmount +DA:237,5 BRDA:237,5,0,- -BRDA:237,5,1,3 -DA:238,3 +BRDA:237,5,1,5 +DA:238,5 BRDA:238,6,0,- -BRDA:238,6,1,3 -DA:239,3 +BRDA:238,6,1,5 +DA:239,5 BRDA:239,7,0,- -BRDA:239,7,1,3 -DA:240,3 +BRDA:239,7,1,5 +DA:240,5 BRDA:240,8,0,- -BRDA:240,8,1,3 -DA:243,3 -DA:246,3 -DA:249,3 -DA:251,3 -DA:252,3 -DA:253,3 -DA:254,3 -DA:255,3 -DA:256,3 -DA:257,3 +BRDA:240,8,1,5 +DA:243,5 +DA:246,5 +DA:249,5 +DA:251,5 +DA:252,5 +DA:253,5 +DA:254,5 +DA:255,5 +DA:256,5 +DA:257,5 FN:274,BancorFormula.fundCost -FNDA:4,BancorFormula.fundCost -DA:281,4 +FNDA:6,BancorFormula.fundCost +DA:281,6 BRDA:281,12,0,- -BRDA:281,12,1,4 -DA:282,4 +BRDA:281,12,1,6 +DA:282,6 BRDA:282,13,0,- -BRDA:282,13,1,4 -DA:283,4 +BRDA:282,13,1,6 +DA:283,6 BRDA:283,14,0,- -BRDA:283,14,1,4 -DA:286,4 -DA:289,4 -DA:291,4 -DA:292,4 -DA:293,4 -DA:294,4 -DA:295,4 -DA:296,4 +BRDA:283,14,1,6 +DA:286,6 +DA:289,6 +DA:291,6 +DA:292,6 +DA:293,6 +DA:294,6 +DA:295,6 +DA:296,6 FN:313,BancorFormula.fundSupplyAmount -FNDA:3,BancorFormula.fundSupplyAmount -DA:320,3 +FNDA:5,BancorFormula.fundSupplyAmount +DA:320,5 BRDA:320,17,0,- -BRDA:320,17,1,3 -DA:321,3 +BRDA:320,17,1,5 +DA:321,5 BRDA:321,18,0,- -BRDA:321,18,1,3 -DA:322,3 +BRDA:321,18,1,5 +DA:322,5 BRDA:322,19,0,- -BRDA:322,19,1,3 -DA:325,3 -DA:328,3 -DA:330,3 -DA:331,3 -DA:332,3 -DA:333,3 -DA:334,3 -DA:335,3 +BRDA:322,19,1,5 +DA:325,5 +DA:328,5 +DA:330,5 +DA:331,5 +DA:332,5 +DA:333,5 +DA:334,5 +DA:335,5 FN:356,BancorFormula.power -FNDA:14,BancorFormula.power -DA:357,14 +FNDA:22,BancorFormula.power +DA:357,22 BRDA:357,22,0,- -BRDA:357,22,1,14 -DA:359,14 -DA:360,14 -DA:361,14 -BRDA:361,23,0,14 +BRDA:357,22,1,22 +DA:359,22 +DA:360,22 +DA:361,22 +BRDA:361,23,0,22 BRDA:361,23,1,- -DA:362,14 +DA:362,22 DA:364,0 -DA:367,14 -DA:368,14 -BRDA:368,24,0,14 +DA:367,22 +DA:368,22 +BRDA:368,24,0,22 BRDA:368,24,1,- -DA:369,14 +DA:369,22 DA:371,0 DA:372,0 FN:380,BancorFormula.generalLog @@ -521,201 +521,201 @@ DA:523,0 DA:524,0 DA:526,0 FN:540,BancorFormula.optimalLog -FNDA:14,BancorFormula.optimalLog -DA:541,14 -DA:543,14 -DA:544,14 -DA:545,14 -DA:547,14 +FNDA:22,BancorFormula.optimalLog +DA:541,22 +DA:543,22 +DA:544,22 +DA:545,22 +DA:547,22 BRDA:547,34,0,- DA:548,0 DA:549,0 -DA:551,14 +DA:551,22 BRDA:551,35,0,- DA:552,0 DA:553,0 -DA:555,14 +DA:555,22 BRDA:555,36,0,- DA:556,0 DA:557,0 -DA:559,14 +DA:559,22 BRDA:559,37,0,- DA:560,0 DA:561,0 -DA:563,14 +DA:563,22 BRDA:563,38,0,- DA:564,0 DA:565,0 -DA:567,14 -BRDA:567,39,0,- -DA:568,0 -DA:569,0 -DA:571,14 +DA:567,22 +BRDA:567,39,0,4 +DA:568,4 +DA:569,4 +DA:571,22 BRDA:571,40,0,- DA:572,0 DA:573,0 -DA:575,14 +DA:575,22 BRDA:575,41,0,- DA:576,0 DA:577,0 -DA:580,14 -DA:581,14 -DA:582,14 -DA:583,14 -DA:584,14 -DA:585,14 -DA:586,14 -DA:587,14 -DA:588,14 -DA:589,14 -DA:590,14 -DA:591,14 -DA:592,14 -DA:593,14 -DA:594,14 -DA:595,14 -DA:596,14 -DA:598,14 +DA:580,22 +DA:581,22 +DA:582,22 +DA:583,22 +DA:584,22 +DA:585,22 +DA:586,22 +DA:587,22 +DA:588,22 +DA:589,22 +DA:590,22 +DA:591,22 +DA:592,22 +DA:593,22 +DA:594,22 +DA:595,22 +DA:596,22 +DA:598,22 FN:612,BancorFormula.optimalExp -FNDA:14,BancorFormula.optimalExp -DA:613,14 -DA:615,14 -DA:616,14 -DA:618,14 -DA:619,14 -DA:620,14 -DA:621,14 -DA:622,14 -DA:623,14 -DA:624,14 -DA:625,14 -DA:626,14 -DA:627,14 -DA:628,14 -DA:629,14 -DA:630,14 -DA:631,14 -DA:632,14 -DA:633,14 -DA:634,14 -DA:635,14 -DA:636,14 -DA:637,14 -DA:638,14 -DA:639,14 -DA:640,14 -DA:641,14 -DA:642,14 -DA:643,14 -DA:644,14 -DA:645,14 -DA:646,14 -DA:647,14 -DA:648,14 -DA:649,14 -DA:650,14 -DA:651,14 -DA:652,14 -DA:653,14 -DA:654,14 -DA:655,14 -DA:656,14 -DA:657,14 -DA:659,14 +FNDA:22,BancorFormula.optimalExp +DA:613,22 +DA:615,22 +DA:616,22 +DA:618,22 +DA:619,22 +DA:620,22 +DA:621,22 +DA:622,22 +DA:623,22 +DA:624,22 +DA:625,22 +DA:626,22 +DA:627,22 +DA:628,22 +DA:629,22 +DA:630,22 +DA:631,22 +DA:632,22 +DA:633,22 +DA:634,22 +DA:635,22 +DA:636,22 +DA:637,22 +DA:638,22 +DA:639,22 +DA:640,22 +DA:641,22 +DA:642,22 +DA:643,22 +DA:644,22 +DA:645,22 +DA:646,22 +DA:647,22 +DA:648,22 +DA:649,22 +DA:650,22 +DA:651,22 +DA:652,22 +DA:653,22 +DA:654,22 +DA:655,22 +DA:656,22 +DA:657,22 +DA:659,22 DA:660,0 BRDA:660,42,0,- -DA:661,14 +DA:661,22 DA:662,0 BRDA:662,43,0,- -DA:663,14 +DA:663,22 DA:664,0 BRDA:664,44,0,- -DA:665,14 +DA:665,22 DA:666,0 BRDA:666,45,0,- -DA:667,14 +DA:667,22 DA:668,0 BRDA:668,46,0,- -DA:669,14 +DA:669,22 DA:670,0 BRDA:670,47,0,- -DA:671,14 +DA:671,22 DA:672,0 BRDA:672,48,0,- -DA:674,14 +DA:674,22 FNF:13 FNH:8 LF:357 -LH:233 +LH:235 BRF:57 -BRH:16 +BRH:17 end_of_record TN: SF:contracts/GoodDollarExchangeProvider.sol FN:36,GoodDollarExchangeProvider. -FNDA:25,GoodDollarExchangeProvider. +FNDA:31,GoodDollarExchangeProvider. FN:45,GoodDollarExchangeProvider.initialize -FNDA:25,GoodDollarExchangeProvider.initialize -DA:51,25 -DA:52,25 -DA:54,25 -DA:55,25 +FNDA:31,GoodDollarExchangeProvider.initialize +DA:51,31 +DA:52,31 +DA:54,31 +DA:55,31 FN:60,GoodDollarExchangeProvider.onlyAvatar FNDA:2,GoodDollarExchangeProvider.onlyAvatar DA:61,2 BRDA:61,0,0,1 BRDA:61,0,1,2 FN:65,GoodDollarExchangeProvider.onlyExpansionController -FNDA:8,GoodDollarExchangeProvider.onlyExpansionController -DA:66,8 +FNDA:9,GoodDollarExchangeProvider.onlyExpansionController +DA:66,9 BRDA:66,1,0,1 -BRDA:66,1,1,6 +BRDA:66,1,1,7 FN:76,GoodDollarExchangeProvider.setAvatar FNDA:3,GoodDollarExchangeProvider.setAvatar -DA:77,27 +DA:77,33 BRDA:77,2,0,1 -BRDA:77,2,1,26 -DA:78,26 -DA:79,26 +BRDA:77,2,1,32 +DA:78,32 +DA:79,32 FN:86,GoodDollarExchangeProvider.setExpansionController FNDA:3,GoodDollarExchangeProvider.setExpansionController -DA:87,27 +DA:87,33 BRDA:87,3,0,1 -BRDA:87,3,1,26 -DA:88,26 -DA:89,26 +BRDA:87,3,1,32 +DA:88,32 +DA:89,32 FN:100,GoodDollarExchangeProvider.swapIn -FNDA:2,GoodDollarExchangeProvider.swapIn -DA:106,1 +FNDA:4,GoodDollarExchangeProvider.swapIn +DA:106,3 FN:117,GoodDollarExchangeProvider.swapOut -FNDA:2,GoodDollarExchangeProvider.swapOut -DA:123,1 +FNDA:4,GoodDollarExchangeProvider.swapOut +DA:123,3 FN:135,GoodDollarExchangeProvider.mintFromExpansion -FNDA:8,GoodDollarExchangeProvider.mintFromExpansion -DA:139,6 +FNDA:9,GoodDollarExchangeProvider.mintFromExpansion +DA:139,7 BRDA:139,4,0,1 -BRDA:139,4,1,5 -DA:140,5 -DA:142,4 -DA:143,4 -DA:145,4 -DA:146,4 -DA:148,4 -DA:149,4 -DA:151,4 -DA:152,4 -DA:154,4 -DA:155,4 -DA:156,4 +BRDA:139,4,1,6 +DA:140,6 +DA:142,5 +DA:143,5 +DA:145,5 +DA:146,5 +DA:148,5 +DA:149,5 +DA:151,5 +DA:152,5 +DA:154,5 +DA:155,5 +DA:156,5 FN:168,GoodDollarExchangeProvider.mintFromInterest -FNDA:7,GoodDollarExchangeProvider.mintFromInterest -DA:172,5 -DA:174,4 -DA:175,4 -DA:178,4 -DA:180,4 -DA:181,4 -DA:183,4 +FNDA:8,GoodDollarExchangeProvider.mintFromInterest +DA:172,6 +DA:174,5 +DA:175,5 +DA:178,5 +DA:180,5 +DA:181,5 +DA:183,5 FN:193,GoodDollarExchangeProvider.updateRatioForReward FNDA:5,GoodDollarExchangeProvider.updateRatioForReward DA:194,3 @@ -747,84 +747,84 @@ end_of_record TN: SF:contracts/GoodDollarExpansionController.sol FN:55,GoodDollarExpansionController. -FNDA:34,GoodDollarExpansionController. +FNDA:40,GoodDollarExpansionController. DA:56,0 BRDA:56,0,0,- DA:57,0 FN:68,GoodDollarExpansionController.initialize -FNDA:34,GoodDollarExpansionController.initialize -DA:74,34 -DA:75,34 -DA:77,34 -DA:78,34 -DA:79,34 -DA:80,34 +FNDA:40,GoodDollarExpansionController.initialize +DA:74,40 +DA:75,40 +DA:77,40 +DA:78,40 +DA:79,40 +DA:80,40 FN:85,GoodDollarExpansionController.onlyAvatar FNDA:4,GoodDollarExpansionController.onlyAvatar DA:86,4 BRDA:86,1,0,1 -BRDA:86,1,1,19 +BRDA:86,1,1,25 FN:97,GoodDollarExpansionController.getExpansionConfig FNDA:10,GoodDollarExpansionController.getExpansionConfig -DA:100,19 +DA:100,20 BRDA:100,2,0,2 -BRDA:100,2,1,17 -DA:104,17 +BRDA:100,2,1,18 +DA:104,18 FN:113,GoodDollarExpansionController.setGoodDollarExchangeProvider FNDA:3,GoodDollarExpansionController.setGoodDollarExchangeProvider -DA:116,36 +DA:116,42 BRDA:116,3,0,1 -BRDA:116,3,1,35 -DA:120,35 -DA:123,35 +BRDA:116,3,1,41 +DA:120,41 +DA:123,41 FN:130,GoodDollarExpansionController.setDistributionHelper FNDA:3,GoodDollarExpansionController.setDistributionHelper -DA:133,36 +DA:133,42 BRDA:133,4,0,1 -BRDA:133,4,1,35 -DA:137,35 -DA:138,35 +BRDA:133,4,1,41 +DA:137,41 +DA:138,41 FN:145,GoodDollarExpansionController.setReserve FNDA:3,GoodDollarExpansionController.setReserve -DA:146,36 +DA:146,42 BRDA:146,5,0,1 -BRDA:146,5,1,35 -DA:147,35 -DA:148,35 +BRDA:146,5,1,41 +DA:147,41 +DA:148,41 FN:155,GoodDollarExpansionController.setAvatar FNDA:3,GoodDollarExpansionController.setAvatar -DA:156,36 +DA:156,42 BRDA:156,6,0,1 -BRDA:156,6,1,35 -DA:157,35 -DA:158,35 +BRDA:156,6,1,41 +DA:157,41 +DA:158,41 FN:167,GoodDollarExpansionController.setExpansionConfig -FNDA:20,GoodDollarExpansionController.setExpansionConfig -DA:172,19 +FNDA:26,GoodDollarExpansionController.setExpansionConfig +DA:172,25 BRDA:172,7,0,1 -BRDA:172,7,1,18 -DA:176,18 +BRDA:172,7,1,24 +DA:176,24 BRDA:176,8,0,1 -BRDA:176,8,1,17 -DA:177,17 +BRDA:176,8,1,23 +DA:177,23 BRDA:177,9,0,1 -BRDA:177,9,1,16 -DA:182,16 -DA:183,16 -DA:186,16 +BRDA:177,9,1,22 +DA:182,22 +DA:183,22 +DA:186,22 FN:194,GoodDollarExpansionController.mintUBIFromInterest -FNDA:2,GoodDollarExpansionController.mintUBIFromInterest -DA:198,2 +FNDA:3,GoodDollarExpansionController.mintUBIFromInterest +DA:198,3 BRDA:198,10,0,1 -BRDA:198,10,1,1 -DA:199,1 -DA:200,1 -DA:204,1 -DA:209,1 +BRDA:198,10,1,2 +DA:199,2 +DA:200,2 +DA:204,2 +DA:209,2 BRDA:209,11,0,- -BRDA:209,11,1,1 -DA:217,1 -DA:221,1 +BRDA:209,11,1,2 +DA:217,2 +DA:221,2 FN:229,GoodDollarExpansionController.mintUBIFromReserveBalance FNDA:2,GoodDollarExpansionController.mintUBIFromReserveBalance DA:232,2 @@ -837,27 +837,27 @@ DA:242,1 DA:246,1 DA:251,1 FN:260,GoodDollarExpansionController.mintUBIFromExpansion -FNDA:9,GoodDollarExpansionController.mintUBIFromExpansion -DA:263,9 -DA:264,8 -DA:265,8 -DA:269,8 -DA:270,8 -DA:271,8 -BRDA:271,13,0,7 -DA:272,7 -DA:275,7 -BRDA:275,14,0,5 +FNDA:10,GoodDollarExpansionController.mintUBIFromExpansion +DA:263,10 +DA:264,9 +DA:265,9 +DA:269,9 +DA:270,9 +DA:271,9 +BRDA:271,13,0,8 +DA:272,8 +DA:275,8 +BRDA:275,14,0,6 BRDA:275,14,1,2 -DA:276,5 +DA:276,6 DA:278,2 -DA:283,7 -DA:284,7 -DA:288,7 -DA:291,7 -DA:296,7 -DA:300,7 -DA:301,7 +DA:283,8 +DA:284,8 +DA:288,8 +DA:291,8 +DA:296,8 +DA:300,8 +DA:301,8 FN:311,GoodDollarExpansionController.mintRewardFromRR FNDA:4,GoodDollarExpansionController.mintRewardFromRR DA:316,3 @@ -881,22 +881,22 @@ end_of_record TN: SF:contracts/common/SafeERC20MintableBurnable.sol FN:18,SafeERC20MintableBurnable.safeTransferFrom -FNDA:6,SafeERC20MintableBurnable.safeTransferFrom -DA:19,6 +FNDA:10,SafeERC20MintableBurnable.safeTransferFrom +DA:19,10 FN:22,SafeERC20MintableBurnable.safeMint -FNDA:3,SafeERC20MintableBurnable.safeMint -DA:23,3 +FNDA:5,SafeERC20MintableBurnable.safeMint +DA:23,5 FN:26,SafeERC20MintableBurnable.safeBurn -FNDA:3,SafeERC20MintableBurnable.safeBurn -DA:27,3 +FNDA:5,SafeERC20MintableBurnable.safeBurn +DA:27,5 FN:36,SafeERC20MintableBurnable._callOptionalReturn -FNDA:12,SafeERC20MintableBurnable._callOptionalReturn -DA:41,12 -DA:42,12 -BRDA:42,0,0,12 -DA:44,12 +FNDA:20,SafeERC20MintableBurnable._callOptionalReturn +DA:41,20 +DA:42,20 +BRDA:42,0,0,18 +DA:44,18 BRDA:44,1,0,- -BRDA:44,1,1,12 +BRDA:44,1,1,18 FNF:4 FNH:4 LF:6 @@ -905,6 +905,50 @@ BRF:3 BRH:2 end_of_record TN: +SF:contracts/common/UsingRegistry.sol +FN:40,UsingRegistry.onlyRegisteredContract +FNDA:0,UsingRegistry.onlyRegisteredContract +DA:41,0 +BRDA:41,0,0,- +BRDA:41,0,1,- +FN:45,UsingRegistry.onlyRegisteredContracts +FNDA:0,UsingRegistry.onlyRegisteredContracts +DA:46,0 +BRDA:46,1,0,- +BRDA:46,1,1,- +FN:54,UsingRegistry.setRegistry +FNDA:0,UsingRegistry.setRegistry +DA:55,6 +BRDA:55,2,0,- +BRDA:55,2,1,6 +DA:56,6 +DA:57,6 +FN:60,UsingRegistry.getExchange +FNDA:0,UsingRegistry.getExchange +DA:61,0 +FN:64,UsingRegistry.getFreezer +FNDA:0,UsingRegistry.getFreezer +DA:65,0 +FN:68,UsingRegistry.getGoldToken +FNDA:0,UsingRegistry.getGoldToken +DA:69,0 +FN:72,UsingRegistry.getReserve +FNDA:0,UsingRegistry.getReserve +DA:73,0 +FN:76,UsingRegistry.getSortedOracles +FNDA:0,UsingRegistry.getSortedOracles +DA:77,0 +FN:80,UsingRegistry.getStableToken +FNDA:0,UsingRegistry.getStableToken +DA:81,0 +FNF:9 +FNH:0 +LF:11 +LH:3 +BRF:6 +BRH:1 +end_of_record +TN: SF:contracts/libraries/TradingLimits.sol FN:54,TradingLimits.validate FNDA:14,TradingLimits.validate @@ -1006,12 +1050,12 @@ end_of_record TN: SF:contracts/swap/Broker.sol FN:55,Broker. -FNDA:30,Broker. +FNDA:36,Broker. FN:62,Broker.initialize -FNDA:30,Broker.initialize -DA:63,30 -DA:64,30 -DA:65,90 +FNDA:36,Broker.initialize +DA:63,36 +DA:64,36 +DA:65,96 FN:74,Broker.setReserves FNDA:4,Broker.setReserves DA:78,3 @@ -1025,21 +1069,21 @@ DA:81,2 DA:82,2 FN:94,Broker.addExchangeProvider FNDA:5,Broker.addExchangeProvider -DA:98,94 +DA:98,100 BRDA:98,2,0,1 -BRDA:98,2,1,93 -DA:99,93 +BRDA:98,2,1,99 +DA:99,99 BRDA:99,3,0,1 -BRDA:99,3,1,92 -DA:100,92 +BRDA:99,3,1,98 +DA:100,98 BRDA:100,4,0,1 -BRDA:100,4,1,91 -DA:101,91 -DA:102,91 -DA:103,91 -DA:104,91 -DA:105,91 -DA:106,91 +BRDA:100,4,1,97 +DA:101,97 +DA:102,97 +DA:103,97 +DA:104,97 +DA:105,97 +DA:106,97 FN:114,Broker.removeExchangeProvider FNDA:4,Broker.removeExchangeProvider DA:118,3 @@ -1051,45 +1095,45 @@ DA:121,1 DA:122,1 DA:123,1 FN:135,Broker.getAmountIn -FNDA:2,Broker.getAmountIn -DA:142,2 +FNDA:4,Broker.getAmountIn +DA:142,4 BRDA:142,6,0,1 -BRDA:142,6,1,1 -DA:143,1 +BRDA:142,6,1,3 +DA:143,3 FN:155,Broker.getAmountOut -FNDA:2,Broker.getAmountOut -DA:162,2 +FNDA:4,Broker.getAmountOut +DA:162,4 BRDA:162,7,0,1 -BRDA:162,7,1,1 -DA:163,1 +BRDA:162,7,1,3 +DA:163,3 FN:176,Broker.swapIn -FNDA:5,Broker.swapIn -DA:184,5 +FNDA:7,Broker.swapIn +DA:184,7 BRDA:184,8,0,- -BRDA:184,8,1,5 -DA:186,5 -DA:187,5 +BRDA:184,8,1,7 +DA:186,7 +DA:187,7 BRDA:187,9,0,1 -BRDA:187,9,1,4 -DA:188,4 -DA:190,3 -DA:191,3 -DA:192,3 -DA:193,3 +BRDA:187,9,1,6 +DA:188,6 +DA:190,5 +DA:191,5 +DA:192,5 +DA:193,5 FN:206,Broker.swapOut -FNDA:4,Broker.swapOut -DA:214,4 +FNDA:6,Broker.swapOut +DA:214,6 BRDA:214,10,0,1 -BRDA:214,10,1,3 -DA:216,3 -DA:217,3 +BRDA:214,10,1,5 +DA:216,5 +DA:217,5 BRDA:217,11,0,1 -BRDA:217,11,1,2 -DA:218,2 -DA:220,2 -DA:221,2 -DA:222,2 -DA:223,2 +BRDA:217,11,1,4 +DA:218,4 +DA:220,4 +DA:221,4 +DA:222,4 +DA:223,4 FN:232,Broker.burnStableTokens FNDA:1,Broker.burnStableTokens DA:233,1 @@ -1103,48 +1147,48 @@ DA:258,2 DA:259,2 DA:260,2 FN:274,Broker.transferOut -FNDA:5,Broker.transferOut -DA:275,5 -DA:276,5 -BRDA:276,12,0,3 -BRDA:276,12,1,2 -DA:277,3 -DA:278,2 -BRDA:278,13,0,2 -BRDA:278,13,1,2 -DA:279,2 +FNDA:9,Broker.transferOut +DA:275,9 +DA:276,9 +BRDA:276,12,0,5 +BRDA:276,12,1,4 +DA:277,5 +DA:278,4 +BRDA:278,13,0,4 +BRDA:278,13,1,4 +DA:279,4 BRDA:279,14,0,- -BRDA:279,14,1,2 +BRDA:279,14,1,4 DA:281,0 FN:294,Broker.transferIn -FNDA:5,Broker.transferIn -DA:295,5 -DA:296,5 -BRDA:296,15,0,2 +FNDA:9,Broker.transferIn +DA:295,9 +DA:296,9 +BRDA:296,15,0,4 BRDA:296,15,1,- -DA:297,2 -DA:298,2 -DA:299,3 -BRDA:299,16,0,3 +DA:297,4 +DA:298,4 +DA:299,5 +BRDA:299,16,0,5 BRDA:299,16,1,- -DA:300,3 +DA:300,5 DA:302,0 FN:315,Broker.guardTradingLimits -FNDA:6,Broker.guardTradingLimits -DA:322,6 -DA:323,6 -DA:324,6 +FNDA:10,Broker.guardTradingLimits +DA:322,10 +DA:323,10 +DA:324,10 BRDA:324,17,0,- -BRDA:324,17,1,6 -DA:325,6 +BRDA:324,17,1,10 +DA:325,10 BRDA:325,18,0,- -BRDA:325,18,1,6 -DA:327,6 -DA:328,5 +BRDA:325,18,1,10 +DA:327,10 +DA:328,9 FN:338,Broker.guardTradingLimit -FNDA:11,Broker.guardTradingLimit -DA:339,11 -DA:340,11 +FNDA:19,Broker.guardTradingLimit +DA:339,19 +DA:340,19 BRDA:340,19,0,2 DA:341,2 DA:342,2 @@ -1161,39 +1205,553 @@ BRF:39 BRH:33 end_of_record TN: +SF:contracts/swap/Reserve.sol +FN:109,Reserve. +FNDA:6,Reserve. +FN:111,Reserve.isStableToken +FNDA:0,Reserve.isStableToken +DA:112,0 +BRDA:112,0,0,- +BRDA:112,0,1,- +FN:123,Reserve.getVersionNumber +FNDA:0,Reserve.getVersionNumber +DA:128,0 +FN:131,Reserve. +FNDA:0,Reserve. +FN:148,Reserve.initialize +FNDA:6,Reserve.initialize +DA:161,6 +DA:162,6 +DA:163,6 +DA:164,6 +DA:165,6 +DA:166,6 +DA:167,6 +DA:168,6 +DA:169,6 +DA:170,6 +DA:172,6 +FN:182,Reserve.setTobinTaxStalenessThreshold +FNDA:0,Reserve.setTobinTaxStalenessThreshold +DA:183,6 +BRDA:183,1,0,- +BRDA:183,1,1,6 +DA:184,6 +DA:185,6 +FN:192,Reserve.setTobinTax +FNDA:0,Reserve.setTobinTax +DA:193,6 +BRDA:193,2,0,- +BRDA:193,2,1,6 +DA:197,6 +DA:198,6 +FN:205,Reserve.setTobinTaxReserveRatio +FNDA:0,Reserve.setTobinTaxReserveRatio +DA:206,6 +DA:207,6 +FN:214,Reserve.setDailySpendingRatio +FNDA:0,Reserve.setDailySpendingRatio +DA:215,6 +DA:216,6 +BRDA:216,3,0,- +BRDA:216,3,1,6 +DA:220,6 +FN:231,Reserve.setDailySpendingRatioForCollateralAssets +FNDA:0,Reserve.setDailySpendingRatioForCollateralAssets +DA:235,6 +BRDA:235,4,0,- +BRDA:235,4,1,6 +DA:240,6 +DA:242,6 +DA:243,6 +DA:244,6 +BRDA:244,5,0,6 +DA:245,6 +BRDA:245,6,0,- +BRDA:245,6,1,6 +DA:249,6 +BRDA:249,7,0,- +BRDA:249,7,1,6 +DA:255,6 +DA:258,6 +FN:270,Reserve.getDailySpendingRatio +FNDA:0,Reserve.getDailySpendingRatio +DA:271,0 +FN:279,Reserve.getDailySpendingRatioForCollateralAsset +FNDA:0,Reserve.getDailySpendingRatioForCollateralAsset +DA:282,0 +FN:290,Reserve.setFrozenGold +FNDA:0,Reserve.setFrozenGold +DA:294,6 +BRDA:294,8,0,- +BRDA:294,8,1,6 +DA:298,6 +DA:300,6 +DA:301,6 +FN:310,Reserve.setAssetAllocations +FNDA:0,Reserve.setAssetAllocations +DA:314,6 +BRDA:314,9,0,- +BRDA:314,9,1,6 +DA:315,6 +DA:316,6 +DA:317,12 +DA:319,6 +BRDA:319,10,0,- +BRDA:319,10,1,6 +DA:324,6 +DA:325,0 +DA:327,6 +DA:328,6 +DA:329,12 +BRDA:329,11,0,- +BRDA:329,11,1,12 +DA:333,12 +DA:340,6 +BRDA:340,12,0,- +BRDA:340,12,1,6 +DA:344,6 +FN:352,Reserve.addToken +FNDA:6,Reserve.addToken +DA:353,6 +BRDA:353,13,0,- +BRDA:353,13,1,6 +DA:354,6 +DA:355,6 +DA:356,6 +DA:357,6 +FN:366,Reserve.removeToken +FNDA:0,Reserve.removeToken +DA:370,0 +BRDA:370,14,0,- +BRDA:370,14,1,- +DA:374,0 +DA:375,0 +DA:376,0 +DA:377,0 +DA:378,0 +DA:379,0 +FN:387,Reserve.addOtherReserveAddress +FNDA:0,Reserve.addOtherReserveAddress +DA:390,0 +BRDA:390,15,0,- +BRDA:390,15,1,- +DA:394,0 +DA:395,0 +DA:396,0 +DA:397,0 +FN:406,Reserve.removeOtherReserveAddress +FNDA:0,Reserve.removeOtherReserveAddress +DA:410,0 +BRDA:410,16,0,- +BRDA:410,16,1,- +DA:414,0 +BRDA:414,17,0,- +BRDA:414,17,1,- +DA:419,0 +DA:420,0 +DA:423,0 +DA:424,0 +DA:425,0 +DA:426,0 +FN:433,Reserve.addSpender +FNDA:0,Reserve.addSpender +DA:434,0 +BRDA:434,18,0,- +BRDA:434,18,1,- +DA:435,0 +DA:436,0 +FN:443,Reserve.removeSpender +FNDA:0,Reserve.removeSpender +DA:444,0 +BRDA:444,19,0,- +BRDA:444,19,1,- +DA:445,0 +DA:446,0 +FN:456,Reserve.isAllowedToSpendExchange +FNDA:0,Reserve.isAllowedToSpendExchange +DA:457,0 +BRDA:457,20,0,- +BRDA:457,20,1,- +FN:469,Reserve.addExchangeSpender +FNDA:6,Reserve.addExchangeSpender +DA:470,6 +BRDA:470,21,0,- +BRDA:470,21,1,6 +DA:471,6 +BRDA:471,22,0,- +BRDA:471,22,1,6 +DA:475,6 +DA:476,6 +DA:477,6 +FN:485,Reserve.removeExchangeSpender +FNDA:0,Reserve.removeExchangeSpender +DA:489,0 +DA:490,0 +DA:491,0 +BRDA:491,23,0,- +BRDA:491,23,1,- +DA:492,0 +BRDA:492,24,0,- +BRDA:492,24,1,- +DA:496,0 +DA:498,0 +BRDA:498,25,0,- +DA:499,0 +DA:504,0 +DA:505,0 +DA:506,0 +FN:515,Reserve.getExchangeSpenders +FNDA:0,Reserve.getExchangeSpenders +DA:516,0 +FN:525,Reserve.transferGold +FNDA:0,Reserve.transferGold +DA:529,0 +BRDA:529,26,0,- +BRDA:529,26,1,- +DA:533,0 +BRDA:533,27,0,- +BRDA:533,27,1,- +DA:537,0 +DA:538,0 +BRDA:538,28,0,- +DA:539,0 +DA:540,0 +DA:541,0 +DA:545,0 +BRDA:545,29,0,- +BRDA:545,29,1,- +DA:546,0 +DA:547,0 +FN:558,Reserve.transferCollateralAsset +FNDA:0,Reserve.transferCollateralAsset +DA:563,0 +BRDA:563,30,0,- +BRDA:563,30,1,- +DA:567,0 +BRDA:567,31,0,- +BRDA:567,31,1,- +DA:571,0 +BRDA:571,32,0,- +BRDA:571,32,1,- +DA:575,0 +DA:576,0 +BRDA:576,33,0,- +DA:577,0 +DA:580,0 +DA:581,0 +DA:587,0 +DA:590,0 +BRDA:590,34,0,- +BRDA:590,34,1,- +DA:592,0 +DA:595,0 +FN:605,Reserve._transferCollateralAsset +FNDA:2,Reserve._transferCollateralAsset +DA:610,2 +BRDA:610,35,0,- +BRDA:610,35,1,2 +DA:615,2 +DA:616,2 +DA:622,2 +FN:633,Reserve.transferExchangeCollateralAsset +FNDA:2,Reserve.transferExchangeCollateralAsset +DA:638,2 +BRDA:638,36,0,- +BRDA:638,36,1,2 +DA:639,2 +FN:648,Reserve._transferGold +FNDA:0,Reserve._transferGold +DA:652,0 +BRDA:652,37,0,- +BRDA:652,37,1,- +DA:654,0 +DA:655,0 +DA:656,0 +FN:666,Reserve.transferExchangeGold +FNDA:0,Reserve.transferExchangeGold +DA:670,0 +FN:678,Reserve.getOrComputeTobinTax +FNDA:0,Reserve.getOrComputeTobinTax +DA:684,0 +BRDA:684,38,0,- +DA:685,0 +DA:686,0 +DA:688,0 +FN:698,Reserve.getTokens +FNDA:0,Reserve.getTokens +DA:699,0 +FN:706,Reserve.getOtherReserveAddresses +FNDA:0,Reserve.getOtherReserveAddresses +DA:711,0 +FN:718,Reserve.getAssetAllocationSymbols +FNDA:0,Reserve.getAssetAllocationSymbols +DA:723,0 +FN:730,Reserve.getAssetAllocationWeights +FNDA:0,Reserve.getAssetAllocationWeights +DA:735,0 +DA:737,0 +DA:738,0 +DA:740,0 +FN:747,Reserve.getUnfrozenBalance +FNDA:0,Reserve.getUnfrozenBalance +DA:748,0 +DA:749,0 +DA:750,0 +FN:757,Reserve.getReserveGoldBalance +FNDA:0,Reserve.getReserveGoldBalance +DA:758,0 +FN:765,Reserve.getOtherReserveAddressesGoldBalance +FNDA:0,Reserve.getOtherReserveAddressesGoldBalance +DA:770,0 +DA:772,0 +DA:773,0 +DA:777,0 +FN:784,Reserve.getUnfrozenReserveGoldBalance +FNDA:0,Reserve.getUnfrozenReserveGoldBalance +DA:785,0 +FN:794,Reserve.getReserveAddressesCollateralAssetBalance +FNDA:0,Reserve.getReserveAddressesCollateralAssetBalance +DA:797,2 +BRDA:797,39,0,- +BRDA:797,39,1,2 +DA:801,2 +DA:803,2 +DA:805,0 +DA:809,2 +DA:810,2 +FN:820,Reserve.addCollateralAsset +FNDA:0,Reserve.addCollateralAsset +DA:823,6 +BRDA:823,40,0,- +BRDA:823,40,1,6 +DA:827,6 +BRDA:827,41,0,- +BRDA:827,41,1,6 +DA:828,6 +DA:829,6 +DA:830,6 +DA:831,6 +FN:840,Reserve.removeCollateralAsset +FNDA:0,Reserve.removeCollateralAsset +DA:844,0 +BRDA:844,42,0,- +BRDA:844,42,1,- +DA:848,0 +BRDA:848,43,0,- +BRDA:848,43,1,- +DA:853,0 +DA:856,0 +DA:857,0 +DA:858,0 +DA:859,0 +FN:867,Reserve.checkIsCollateralAsset +FNDA:0,Reserve.checkIsCollateralAsset +DA:870,14 +FN:877,Reserve.getFrozenReserveGoldBalance +FNDA:0,Reserve.getFrozenReserveGoldBalance +DA:878,0 +DA:879,0 +DA:880,0 +DA:881,0 +DA:882,0 +FN:893,Reserve.getReserveRatio +FNDA:0,Reserve.getReserveRatio +DA:894,0 +DA:897,0 +DA:898,0 +DA:899,0 +DA:900,0 +DA:905,0 +DA:906,0 +DA:907,0 +DA:909,0 +DA:911,0 +BRDA:911,45,0,- +DA:914,0 +DA:915,0 +DA:918,0 +DA:923,0 +DA:924,0 +FN:939,Reserve.computeTobinTax +FNDA:0,Reserve.computeTobinTax +DA:944,0 +DA:945,0 +BRDA:945,46,0,- +BRDA:945,46,1,- +DA:946,0 +DA:948,0 +FN:952,Reserve.isStableAsset +FNDA:20,Reserve.isStableAsset +DA:953,20 +FNF:47 +FNH:7 +LF:198 +LH:76 +BRF:86 +BRH:20 +end_of_record +TN: SF:node_modules/@celo/contracts/common/FixidityLib.sol FN:26,FixidityLib.digits FNDA:0,FixidityLib.digits DA:27,0 FN:37,FixidityLib.fixed1 +FNDA:24,FixidityLib.fixed1 +DA:38,24 +FN:47,FixidityLib.wrap +FNDA:42,FixidityLib.wrap +DA:48,42 +FN:54,FixidityLib.unwrap +FNDA:0,FixidityLib.unwrap +DA:55,0 +FN:62,FixidityLib.mulPrecision +FNDA:0,FixidityLib.mulPrecision +DA:63,0 +FN:71,FixidityLib.maxNewFixed +FNDA:0,FixidityLib.maxNewFixed +DA:72,0 +FN:82,FixidityLib.newFixed +FNDA:0,FixidityLib.newFixed +DA:83,0 +BRDA:83,0,0,- +BRDA:83,0,1,- +DA:84,0 +FN:91,FixidityLib.fromFixed +FNDA:0,FixidityLib.fromFixed +DA:92,0 +FN:106,FixidityLib.newFixedFraction +FNDA:0,FixidityLib.newFixedFraction +DA:111,0 +DA:112,0 +DA:113,0 +FN:123,FixidityLib.integer +FNDA:0,FixidityLib.integer +DA:124,0 +FN:135,FixidityLib.fractional +FNDA:0,FixidityLib.fractional +DA:136,0 +FN:147,FixidityLib.add +FNDA:12,FixidityLib.add +DA:148,12 +DA:149,12 +BRDA:149,1,0,- +BRDA:149,1,1,12 +DA:150,12 +FN:158,FixidityLib.subtract +FNDA:0,FixidityLib.subtract +DA:159,0 +BRDA:159,2,0,- +BRDA:159,2,1,- +DA:160,0 +FN:176,FixidityLib.multiply +FNDA:0,FixidityLib.multiply +DA:177,0 +DA:178,0 +DA:179,0 +DA:183,0 +DA:184,0 +DA:185,0 +DA:186,0 +DA:189,0 +DA:190,0 +BRDA:190,6,0,- +BRDA:190,7,0,- +BRDA:190,7,1,- +DA:194,0 +DA:195,0 +BRDA:195,8,0,- +BRDA:195,9,0,- +BRDA:195,9,1,- +DA:196,0 +DA:198,0 +DA:199,0 +BRDA:199,10,0,- +BRDA:199,11,0,- +BRDA:199,11,1,- +DA:201,0 +DA:202,0 +BRDA:202,12,0,- +BRDA:202,13,0,- +BRDA:202,13,1,- +DA:204,0 +DA:205,0 +DA:206,0 +DA:207,0 +BRDA:207,14,0,- +BRDA:207,15,0,- +BRDA:207,15,1,- +DA:210,0 +DA:211,0 +DA:212,0 +DA:213,0 +DA:214,0 +FN:226,FixidityLib.reciprocal +FNDA:0,FixidityLib.reciprocal +DA:227,0 +BRDA:227,16,0,- +BRDA:227,16,1,- +DA:228,0 +FN:244,FixidityLib.divide +FNDA:0,FixidityLib.divide +DA:245,0 +BRDA:245,17,0,- +BRDA:245,17,1,- +DA:246,0 +DA:247,0 +BRDA:247,18,0,- +BRDA:247,18,1,- +DA:248,0 +FN:254,FixidityLib.gt +FNDA:0,FixidityLib.gt +DA:255,0 +FN:261,FixidityLib.gte +FNDA:0,FixidityLib.gte +DA:262,0 +FN:268,FixidityLib.lt +FNDA:0,FixidityLib.lt +DA:269,0 +FN:275,FixidityLib.lte +FNDA:18,FixidityLib.lte +DA:276,18 +FN:282,FixidityLib.equals +FNDA:6,FixidityLib.equals +DA:283,6 +FN:289,FixidityLib.isProperFraction +FNDA:0,FixidityLib.isProperFraction +DA:290,0 +FN:26,FixidityLib.digits +FNDA:0,FixidityLib.digits +DA:27,0 +FN:37,FixidityLib.fixed1 FNDA:13,FixidityLib.fixed1 DA:38,13 FN:47,FixidityLib.wrap FNDA:27,FixidityLib.wrap DA:48,27 FN:54,FixidityLib.unwrap -FNDA:26,FixidityLib.unwrap -DA:55,26 +FNDA:50,FixidityLib.unwrap +DA:55,50 FN:62,FixidityLib.mulPrecision FNDA:28,FixidityLib.mulPrecision DA:63,28 FN:71,FixidityLib.maxNewFixed -FNDA:40,FixidityLib.maxNewFixed -DA:72,40 +FNDA:88,FixidityLib.maxNewFixed +DA:72,88 FN:82,FixidityLib.newFixed -FNDA:40,FixidityLib.newFixed -DA:83,40 +FNDA:88,FixidityLib.newFixed +DA:83,88 BRDA:83,0,0,- -BRDA:83,0,1,40 -DA:84,40 +BRDA:83,0,1,88 +DA:84,88 FN:91,FixidityLib.fromFixed FNDA:14,FixidityLib.fromFixed DA:92,14 FN:106,FixidityLib.newFixedFraction -FNDA:13,FixidityLib.newFixedFraction -DA:111,13 -DA:112,13 -DA:113,13 +FNDA:37,FixidityLib.newFixedFraction +DA:111,37 +DA:112,37 +DA:113,37 FN:123,FixidityLib.integer FNDA:28,FixidityLib.integer DA:124,28 @@ -1262,15 +1820,15 @@ BRDA:227,16,0,- BRDA:227,16,1,- DA:228,0 FN:244,FixidityLib.divide -FNDA:26,FixidityLib.divide -DA:245,26 +FNDA:50,FixidityLib.divide +DA:245,50 BRDA:245,17,0,- -BRDA:245,17,1,26 -DA:246,26 -DA:247,26 +BRDA:245,17,1,50 +DA:246,50 +DA:247,50 BRDA:247,18,0,- -BRDA:247,18,1,26 -DA:248,26 +BRDA:247,18,1,50 +DA:248,50 FN:254,FixidityLib.gt FNDA:0,FixidityLib.gt DA:255,0 @@ -1289,32 +1847,62 @@ DA:283,0 FN:289,FixidityLib.isProperFraction FNDA:0,FixidityLib.isProperFraction DA:290,0 -FNF:22 -FNH:13 -LF:56 -LH:45 -BRF:27 -BRH:10 +FNF:44 +FNH:18 +LF:112 +LH:52 +BRF:54 +BRH:11 end_of_record TN: SF:node_modules/@celo/contracts/common/Initializable.sol FN:7,Initializable. -FNDA:30,Initializable. -DA:8,30 +FNDA:6,Initializable. +DA:8,6 BRDA:8,0,0,- DA:9,0 FN:13,Initializable.initializer -FNDA:30,Initializable.initializer -DA:14,30 +FNDA:6,Initializable.initializer +DA:14,6 BRDA:14,1,0,- -BRDA:14,1,1,30 -DA:15,30 +BRDA:14,1,1,6 +DA:15,6 +FN:7,Initializable. +FNDA:36,Initializable. +DA:8,36 +BRDA:8,0,0,- +DA:9,0 +FN:13,Initializable.initializer +FNDA:36,Initializable.initializer +DA:14,36 +BRDA:14,1,0,- +BRDA:14,1,1,36 +DA:15,36 +FNF:4 +FNH:4 +LF:8 +LH:6 +BRF:6 +BRH:2 +end_of_record +TN: +SF:node_modules/@celo/contracts/common/libraries/ReentrancyGuard.sol +FN:13,ReentrancyGuard. +FNDA:6,ReentrancyGuard. +DA:16,6 +FN:26,ReentrancyGuard.nonReentrant +FNDA:0,ReentrancyGuard.nonReentrant +DA:27,0 +DA:28,0 +DA:30,0 +BRDA:30,0,0,- +BRDA:30,0,1,- FNF:2 -FNH:2 +FNH:1 LF:4 -LH:3 -BRF:3 -BRH:1 +LH:1 +BRF:2 +BRH:0 end_of_record TN: SF:test/unit/goodDollar/BancorExchangeProvider.t.sol