From 8a1f3384028e7c12a374d6e191d5c30ea7d28af2 Mon Sep 17 00:00:00 2001 From: deepesh KN Date: Fri, 19 Jan 2018 16:07:23 +0530 Subject: [PATCH 01/21] Contract: Added Pricer.sol, PricerInterface.sol --- contracts/OpsManaged.sol | 112 ++++++++++++++ contracts/Owned.sol | 74 +++++++++ contracts/PriceOracleInterface.sol | 55 +++++++ contracts/Pricer.sol | 240 +++++++++++++++++++++++++++++ contracts/PricerInterface.sol | 127 +++++++++++++++ 5 files changed, 608 insertions(+) create mode 100644 contracts/OpsManaged.sol create mode 100644 contracts/Owned.sol create mode 100644 contracts/PriceOracleInterface.sol create mode 100644 contracts/Pricer.sol create mode 100644 contracts/PricerInterface.sol diff --git a/contracts/OpsManaged.sol b/contracts/OpsManaged.sol new file mode 100644 index 0000000..3403787 --- /dev/null +++ b/contracts/OpsManaged.sol @@ -0,0 +1,112 @@ +pragma solidity ^0.4.17; + +// Copyright 2017 OpenST Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ---------------------------------------------------------------------------- +// Common: Admin / Ops Permission Model +// +// http://www.simpletoken.org/ +// +// ---------------------------------------------------------------------------- + +import "./Owned.sol"; + +/** + @title OpsManaged + @notice Implements OpenST ownership and permission model +*/ +contract OpsManaged is Owned { + + address public opsAddress; + address public adminAddress; + + event AdminAddressChanged(address indexed _newAddress); + event OpsAddressChanged(address indexed _newAddress); + + + function OpsManaged() public + Owned() + { + } + + + modifier onlyAdmin() { + require(isAdmin(msg.sender)); + _; + } + + + modifier onlyAdminOrOps() { + require(isAdmin(msg.sender) || isOps(msg.sender)); + _; + } + + + modifier onlyOwnerOrAdmin() { + require(isOwner(msg.sender) || isAdmin(msg.sender)); + _; + } + + + modifier onlyOps() { + require(isOps(msg.sender)); + _; + } + + + function isAdmin(address _address) internal view returns (bool) { + return (adminAddress != address(0) && _address == adminAddress); + } + + + function isOps(address _address) internal view returns (bool) { + return (opsAddress != address(0) && _address == opsAddress); + } + + + function isOwnerOrOps(address _address) internal view returns (bool) { + return (isOwner(_address) || isOps(_address)); + } + + + // Owner and Admin can change the admin address. Address can also be set to 0 to 'disable' it. + function setAdminAddress(address _adminAddress) external onlyOwnerOrAdmin returns (bool) { + require(_adminAddress != owner); + require(_adminAddress != address(this)); + require(!isOps(_adminAddress)); + + adminAddress = _adminAddress; + + AdminAddressChanged(_adminAddress); + + return true; + } + + + // Owner and Admin can change the operations address. Address can also be set to 0 to 'disable' it. + function setOpsAddress(address _opsAddress) external onlyOwnerOrAdmin returns (bool) { + require(_opsAddress != owner); + require(_opsAddress != address(this)); + require(!isAdmin(_opsAddress)); + + opsAddress = _opsAddress; + + OpsAddressChanged(_opsAddress); + + return true; + } +} + + diff --git a/contracts/Owned.sol b/contracts/Owned.sol new file mode 100644 index 0000000..d748cf7 --- /dev/null +++ b/contracts/Owned.sol @@ -0,0 +1,74 @@ +pragma solidity ^0.4.17; + +// Copyright 2017 OpenST Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ---------------------------------------------------------------------------- +// Common: Basic Ownership Implementation +// +// http://www.simpletoken.org/ +// +// ---------------------------------------------------------------------------- + +/** + @title Owned + @notice Implements basic ownership with 2-step transfers +*/ +contract Owned { + + address public owner; + address public proposedOwner; + + event OwnershipTransferInitiated(address indexed _proposedOwner); + event OwnershipTransferCompleted(address indexed _newOwner); + + + function Owned() public { + owner = msg.sender; + } + + + modifier onlyOwner() { + require(isOwner(msg.sender)); + _; + } + + + function isOwner(address _address) internal view returns (bool) { + return (_address == owner); + } + + + function initiateOwnershipTransfer(address _proposedOwner) public onlyOwner returns (bool) { + proposedOwner = _proposedOwner; + + OwnershipTransferInitiated(_proposedOwner); + + return true; + } + + + function completeOwnershipTransfer() public returns (bool) { + require(msg.sender == proposedOwner); + + owner = proposedOwner; + proposedOwner = address(0); + + OwnershipTransferCompleted(owner); + + return true; + } +} + + diff --git a/contracts/PriceOracleInterface.sol b/contracts/PriceOracleInterface.sol new file mode 100644 index 0000000..937f0a7 --- /dev/null +++ b/contracts/PriceOracleInterface.sol @@ -0,0 +1,55 @@ +pragma solidity ^0.4.17; + +// Copyright 2017 OpenST Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ---------------------------------------------------------------------------- +// Utility Chain: PriceOracleInterface +// +// http://www.simpletoken.org/ +// +// -------------------------- +// This contract keeps in storage an updated baseCurrency/quoteCurrency price, +// which is updated in a particular duration. +// There is an expiry duration for a currency pair +// +contract PriceOracleInterface{ + + /* + * Events + */ + event PriceOracleUpdated( + uint256 _price, + uint256 _expirationHeight); + + event PriceExpired( + uint256 _expirationHeight); + + // Price is stored as fixed point integer value similar as wei unit. + function TOKEN_DECIMALS() + public + returns (uint8); + + /* + * Functions + */ + function setPrice( + uint256 _price) + external + returns(uint256 expirationHeight); + + function getPrice() + public + returns (uint256 price); +} \ No newline at end of file diff --git a/contracts/Pricer.sol b/contracts/Pricer.sol new file mode 100644 index 0000000..90cdd07 --- /dev/null +++ b/contracts/Pricer.sol @@ -0,0 +1,240 @@ +pragma solidity ^0.4.17; + +// Copyright 2018 OpenST Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ---------------------------------------------------------------------------- +// Utility chain: Pricer +// +// http://www.simpletoken.org/ +// +// ---------------------------------------------------------------------------- + + +import "./openst-protocol/EIP20Interface.sol"; +import "./openst-protocol/UtilityTokenInterface.sol"; +import "./OpsManaged.sol"; +import "./SafeMath.sol"; +import "./PriceOracleInterface.sol"; +import "./PricerInterface.sol"; + +contract Pricer is OpsManaged, PricerInterface { + using SafeMath for uint256; + + /* + * Storage + */ + ///BrandedToken address + address public brandedToken; + + ///currency to Margin mapping, Absolute +/- range in currency in which the price point will be accepted + mapping(bytes3 /* currency */ => uint64 /* margin */) public acceptedMargins; + + ///currency to Price Oracles address mapping + mapping(bytes3 /* currency */ => address /* price oracle address */) public priceOracles; + + /* + * Events + */ + + ///Event for PaymentComplete + event Payment( + address _beneficiary, + uint256 _transferAmount, + address _commissionBeneficiary, + uint256 _commissionAmount, + bytes3 _currency, + uint256 _intendedPricePoint, + uint256 _actualPricePoint); + + ///Event for priceOracles Updates for currency + event PriceOracleSet( + bytes3 _currency, + address _address); + + ///Event for AcceptedMargin update for currency + event AcceptedMargin( + bytes3 _currency, + uint64 relativeIntendedPriceRange); + + /* + * Public functions + */ + + function Pricer( + address _brandedToken) + public + OpsManaged() + { + brandedToken = _brandedToken; + } + + /// @dev Takes _currency, _oracleAddress; + /// Updated the Price Oracle address for a given currency + /// Emits PriceOracleSet Event; + /// Only called by ops + /// @param _currency currency + /// @param _oracleAddress oracleAddress + /// @return bool isSuccess + function setPriceOracle( + bytes3 _currency, + address _oracleAddress) + onlyOps + public + returns (bool /* success */) + { + require(_oracleAddress != address(0)); + require(_currency != ""); + priceOracles[_currency] = _oracleAddress; + + //Trigger PriceOracleSet event + PriceOracleSet(_currency, _oracleAddress); + return true; + } + + /// @dev Takes _currency, _acceptedMargin; + /// Updated the acceptable margin range for a given currency + /// Emits AcceptedMargin Event; + /// Only called by ops + /// @param _currency currency + /// @param _acceptedMargin acceptedMargin + /// @return bool isSuccess + function setAcceptedMargin( + bytes3 _currency, + uint64 _acceptedMargin) + onlyOps + public + returns (bool /* success */) + { + acceptedMargins[_currency] = _acceptedMargin; + // Trigger Event for Intended Price Acceptable Range Update + AcceptedMargin(_currency, _acceptedMargin); + return true; + } + + /// @dev Takes _beneficiary, _transferAmount, _commissionBeneficiary, _commissionAmount, _currency, _intendedPricePoint; + /// Validates if the currentPrice from PriceOracle is in accepatble margin of _intendedPricePoint (If _ currency is not 0) + /// If _currency is 0 then it transfer the Branded tokens equal to _transferAmount to _beneficiary and Branded tokens equal to _commissionAmount to _commissionBeneficiary (Floating value transaction); + /// If _currency is not 0 then it transfer the Branded tokens equivalant to _transferAmount in currency value to _beneficiary and Branded tokens equivalant to _commissionAmount in currency value to _commissionBeneficiary (Fixed value transaction); + /// Emits Payment Event; + /// Public method + /// @param _beneficiary beneficiary + /// @param _transferAmount transferAmount + /// @param _commissionBeneficiary commissionBeneficiary + /// @param _commissionAmount commissionAmount + /// @param _currency currency + /// @param _intendedPricePoint _intendedPricePoint + /// @return bool isSuccess + function pay( + address _beneficiary, + uint256 _transferAmount, + address _commissionBeneficiary, + uint256 _commissionAmount, + bytes3 _currency, + uint256 _intendedPricePoint) + public + returns (bool success) + { + require(_beneficiary != address(0)); + require(_transferAmount != 0); + + if(_commissionAmount > 0) { + require(_commissionBeneficiary != address(0)); + } + + uint256 tokenAmount = _transferAmount; + uint256 commissionTokenAmount = _commissionAmount; + uint256 pricePoint = _intendedPricePoint; + if(_currency != 0) { + uint8 tokenDecimals = 0; + (pricePoint, tokenDecimals) = getPricePoint(_currency); + require(pricePoint > 0); + require(isPricePointInRange(_intendedPricePoint, pricePoint, acceptedMargins[_currency])); + (tokenAmount, commissionTokenAmount) = getBTAmountFromCurrencyValue(pricePoint, tokenDecimals, _transferAmount, _commissionAmount); + } + + require(EIP20Interface(brandedToken).transferFrom(msg.sender, _beneficiary, tokenAmount)); + if(_commissionBeneficiary != address(0)) { + require(EIP20Interface(brandedToken).transferFrom(msg.sender, _commissionBeneficiary, commissionTokenAmount)); + } + + //Trigger Event for PaymentComplete + Payment(_beneficiary, _transferAmount, _commissionBeneficiary, _commissionAmount, _currency, _intendedPricePoint, pricePoint); + return true; + } + + /// @dev Takes _currency; + /// gets current price point and token decimal for the priceOracle for the give currency; + /// Public method + /// @param _currency currency + /// @return (currentPrice, TokenDecimals) + function getPricePoint( + bytes3 _currency) + public + returns (uint256 /* pricePoint */, uint8 /* TokenDecimal*/) + { + require(_currency != ""); + PriceOracleInterface currentPriceOracle = PriceOracleInterface(priceOracles[_currency]); + require(currentPriceOracle != address(0)); + return (currentPriceOracle.getPrice(), currentPriceOracle.TOKEN_DECIMALS()); + } + + /// @dev Takes _intendedPricePoint, _currentPricePoint, _acceptedMargin; + /// Checks if the current price point is in the acceptable range of intendedPricePoint; + /// Private method + /// @param _intendedPricePoint intendedPricePoint + /// @param _currentPricePoint currentPricePoint + /// @param _acceptedMargin acceptedMargin + /// @return bool isValid + function isPricePointInRange( + uint256 _intendedPricePoint, + uint256 _currentPricePoint, + uint64 _acceptedMargin) + private + returns (bool /*isValid*/) + { + bool isValid = true; + if (_intendedPricePoint >= _acceptedMargin) { + isValid = SafeMath.sub(_intendedPricePoint, _acceptedMargin) <= _currentPricePoint; + } + if (isValid) { + isValid = _currentPricePoint <= SafeMath.add(_intendedPricePoint, _acceptedMargin); + } + return isValid; + } + + + /// @dev Takes _pricePoint, _tokenDecimals, _transferAmount, _commissionAmount; + /// Calculated the number of branded token equivalant to the currency amount; + /// Private method + /// @param _pricePoint pricePoint + /// @param _tokenDecimals tokenDecimals + /// @param _transferAmount transferAmount + /// @param _commissionAmount commissionAmount + /// @return (amountBT,commissionAmountBT) + function getBTAmountFromCurrencyValue(uint256 _pricePoint, + uint8 _tokenDecimals, + uint256 _transferAmount, + uint256 _commissionAmount) + private + returns (uint256 /* number of BT */, uint256 /* number of commission BT */) + { + uint256 conversionRate = UtilityTokenInterface(brandedToken).conversionRate(); + require(conversionRate > 0); + uint256 adjConversionRate = SafeMath.mul(conversionRate, 10**uint256(_tokenDecimals)); + uint256 amountBT = SafeMath.div(SafeMath.mul(_transferAmount, adjConversionRate), _pricePoint); + uint256 commissionAmountBT = SafeMath.div(SafeMath.mul(_commissionAmount, adjConversionRate), _pricePoint); + return (amountBT, commissionAmountBT); + } +} diff --git a/contracts/PricerInterface.sol b/contracts/PricerInterface.sol new file mode 100644 index 0000000..3d4e4fe --- /dev/null +++ b/contracts/PricerInterface.sol @@ -0,0 +1,127 @@ +pragma solidity ^0.4.17; + +// Copyright 2017 OpenST Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ---------------------------------------------------------------------------- +// Utility chain: PricerInterface +// +// http://www.simpletoken.org/ +// +// ---------------------------------------------------------------------------- + +contract PricerInterface { + + event Payment(address _beneficiary, + uint256 _transferAmount, + address _commissionBeneficiary, + uint256 _commissionAmount, + bytes3 _currency, + uint256 _intendedPricePoint, + uint256 _actualPricePoint); + + event PriceOracleSet(bytes3 _currency, + address _address); + + event AcceptedMargin(bytes3 _currency, + uint64 relativeIntendedPriceRange); + + /// @dev Returns address of the branded token; + /// Public; + /// @return address + function brandedToken() + public + returns (address); + + /// @dev Takes _currency; + /// Returns Acceptable margin for the given currency; + /// Public; + /// @param _currency currency + /// @return uint64 margin + function acceptedMargins( + bytes3 _currency) + public + returns (uint64); + + /// @dev Takes _currency; + /// Returns address of Price Oracle for the given currency; + /// Public + /// @param _currency currency + /// @return address + function priceOracles( + bytes3 _currency) + public + returns (address); + + /// @dev Takes _currency, _oracleAddress; + /// Updated the Price Oracle address for a given currency; + /// Emits PriceOracleSet Event; + /// Only called by ops + /// @param _currency currency + /// @param _oracleAddress oracleAddress + /// @return bool isSuccess + function setPriceOracle( + bytes3 _currency, + address _oracleAddress) + public + returns (bool); + + /// @dev Takes _currency, _acceptedMargin; + /// Updated the acceptable margin range for a given currency; + /// Emits AcceptedMargin Event; + /// Only called by ops + /// @param _currency currency + /// @param _acceptedMargin acceptedMargin + /// @return bool isSuccess + function setAcceptedMargin( + bytes3 _currency, + uint64 _acceptedMargin) + public + returns (bool); + + /// @dev Takes _beneficiary, _transferAmount, _commissionBeneficiary, _commissionAmount, _currency, _intendedPricePoint; + /// Validates if the currentPrice from PriceOracle is in accepatble margin of _intendedPricePoint (If _ currency is not 0); + /// If _currency is 0 then it transfer the Branded tokens equal to _transferAmount to _beneficiary and Branded tokens equal to _commissionAmount to _commissionBeneficiary (Floating value transaction); + /// If _currency is not 0 then it transfer the Branded tokens equivalant to _transferAmount in currecncy value to _beneficiary and Branded tokens equivalant to _commissionAmount in currency value to _commissionBeneficiary (Fixed value transaction); + /// Emits Payment Event; + /// Public method + /// @param _beneficiary beneficiary + /// @param _transferAmount transferAmount + /// @param _commissionBeneficiary commissionBeneficiary + /// @param _commissionAmount commissionAmount + /// @param _currency currency + /// @param _intendedPricePoint _intendedPricePoint + /// @return bool isSuccess + function pay( + address _beneficiary, + uint256 _transferAmount, + address _commissionBeneficiary, + uint256 _commissionAmount, + bytes3 _currency, + uint256 _intendedPricePoint) + public + returns (bool success); + + /// @dev Takes _currency; + /// gets current price point and token decimal for the priceOracle for the give currency; + /// Public method + /// @param _currency currency + /// @return (currentPrice, TokenDecimals) + function getPricePoint( + bytes3 _currency) + public + returns (uint256, uint8); + + +} \ No newline at end of file From 37b08d73920c5d1ae3e6d48b6c2586bda28ff624 Mon Sep 17 00:00:00 2001 From: deepesh KN Date: Fri, 19 Jan 2018 16:37:23 +0530 Subject: [PATCH 02/21] Contract: Edited PriceOracleInterface.sol --- contracts/PriceOracleInterface.sol | 95 +++++++++++++++++++++--------- contracts/Pricer.sol | 2 +- contracts/PricerInterface.sol | 2 +- 3 files changed, 70 insertions(+), 29 deletions(-) diff --git a/contracts/PriceOracleInterface.sol b/contracts/PriceOracleInterface.sol index 937f0a7..f6b4201 100644 --- a/contracts/PriceOracleInterface.sol +++ b/contracts/PriceOracleInterface.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.17; -// Copyright 2017 OpenST Ltd. +// Copyright 2018 OpenST Ltd. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -26,30 +26,71 @@ pragma solidity ^0.4.17; // contract PriceOracleInterface{ - /* - * Events - */ - event PriceOracleUpdated( - uint256 _price, - uint256 _expirationHeight); - - event PriceExpired( - uint256 _expirationHeight); - - // Price is stored as fixed point integer value similar as wei unit. - function TOKEN_DECIMALS() - public - returns (uint8); - - /* - * Functions - */ - function setPrice( - uint256 _price) - external - returns(uint256 expirationHeight); - - function getPrice() - public - returns (uint256 price); + /* + * Events + */ + + /// @dev event emitted whenever price is updated + /// @return _price + /// @return _expirationHeight + event PriceOracleUpdated(uint256 _price, + uint256 _expirationHeight); + + /// @dev event emitted when price expires + /// @return _expirationHeight + event PriceExpired(uint256 _expirationHeight); + + /* + * Functions + */ + + /// @dev Price is stored as fixed point integer value similar as wei unit. + /// Use this variable in case decimal value need to be evaluated + /// @return TOKEN_DECIMALS + function TOKEN_DECIMALS() + public + constant + returns( + uint8); + + /// @dev block height at which the price expires + /// @return expirationHeight + function expirationHeight() + public + view + returns( + uint256); + + /// @dev get baseCurrency bytes3 code + /// @return base currency + function baseCurrency() + public + view + returns( + bytes3); + + /// @dev returns quoteCurrency bytes3 code + /// @return quote currency + function quoteCurrency() + public + view + returns( + bytes3); + + /// @dev use this function to update oracle price + /// @param _price price + /// @return expirationHeight + function setPrice( + uint256 _price) + external + returns( + uint256); + + /// @dev use this function to get price + /// @return baseCurrency/quoteCurrency value + function getPrice() + public + returns( + uint256); + } \ No newline at end of file diff --git a/contracts/Pricer.sol b/contracts/Pricer.sol index 90cdd07..2606f5e 100644 --- a/contracts/Pricer.sol +++ b/contracts/Pricer.sol @@ -144,7 +144,7 @@ contract Pricer is OpsManaged, PricerInterface { bytes3 _currency, uint256 _intendedPricePoint) public - returns (bool success) + returns (bool /* success */) { require(_beneficiary != address(0)); require(_transferAmount != 0); diff --git a/contracts/PricerInterface.sol b/contracts/PricerInterface.sol index 3d4e4fe..135e8de 100644 --- a/contracts/PricerInterface.sol +++ b/contracts/PricerInterface.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.17; -// Copyright 2017 OpenST Ltd. +// Copyright 2018 OpenST Ltd. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. From 6c68cacfdc0023ce0a1e8325b54627c2bb5c8553 Mon Sep 17 00:00:00 2001 From: deepesh KN Date: Fri, 19 Jan 2018 16:59:34 +0530 Subject: [PATCH 03/21] Docs: Pricer.md specifications --- docs/md/Pricer.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/md/Pricer.md diff --git a/docs/md/Pricer.md b/docs/md/Pricer.md new file mode 100644 index 0000000..e69de29 From 094b96c2931112f7038dfc3cce3914a5f3dec48c Mon Sep 17 00:00:00 2001 From: deepesh-kn Date: Fri, 19 Jan 2018 19:55:36 +0530 Subject: [PATCH 04/21] Initial specification draft for Pricer contract. --- docs/md/Pricer.md | 112 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/docs/md/Pricer.md b/docs/md/Pricer.md index e69de29..f64b323 100644 --- a/docs/md/Pricer.md +++ b/docs/md/Pricer.md @@ -0,0 +1,112 @@ +## Pricer Contract + +### Context +Member companies can create their branded token economy through the OST dashboard. +Member company does the following when they mint the Branded Token. +- Define the OST to BT conversion rate. +- Define various transactions which includes the following. + - Transaction Type (User to user, user to company, company to user). + - Transaction Name. + - Transaction Value is at fixed rate (in currency/fiat) or floating rate (in BT). + - Transaction Commission in percentage (inclusive for user-to-company, exclusive for user-to-user). + +### Requirements +- Pricer makes two ```transferFrom``` calls. +- Pricer contract needs to be set a sufficient allowance on the account to spend (for both BT-valued and fiat-valued transfers). +- Cheaper gas than repeated transfers. +- In case of fiat-valued transfer the amount of BT needed is determined on-chain (limited by allowance and by mechanism below). + +### Specifications +- Pricer Contract is OpsManaged. +- Every Pricer contract has one interface to a Branded Token. +- Transaction to Pricer provides intended price point as parameter. If intended price point is further than margin outside of Oracle’s price point then transfer fails. If within margin of Oracle price point then Oracle price point is used +- This contract stores Branded Token address. This will be helpful to directly get the conversion rate and perform transfer functions. +- This contract stores the AcceptedMargin value for each currency. This specifies the absolute +/- range in currency value in which the price point from the PriceOracle will be accepted. Only ops will be able to update this value. The transaction will be performed only if the following condition will be true. Else it will result in to failed transaction. +
```(IntendedPrice - AcceptedMargin) <= PricePoint from PriceOracle <= (IntendedPrice + AcceptedMargin)``` +- This contract stores the PriceOracle address for each currency. PriceOracle is instanced for a fiat value. This will allow to add support of adding new fiat value at any time. Only ops will be able to set/update this value. +- This contract makes two transferFrom calls. The amount to be transferred is in currency value if its a fixed transaction type, else its in Branded token if its a floating type transaction. +- In case of fixed transaction type, this contract also validates for currency price point fluctuations. To achieve this and intended price point is specified while making transfers and this intended price point is validated against the current price point from the PriceOracle contract. The current price should be in acceptable range of intended price point. + +### Details about the Pay functions. +Pay function is public. This function accepts beneficiary address and its amount, commisionBeneficiary address and its amount, Currency type and intendedPricePoint. +On successful transfer this function emits PaymentComplete Event. +Currency type can have the following value. + +- Currency type can be byte3 value e.g USD, EUR, ETH ... etc:
+This means that the transactions are happening in USD, EUR, ETH Fiat value. +This is a fixed value type transaction. +This will get the price point from the price oracle contract.``` _transferAmount``` and ```_commisionAmount``` are in given currency type i.e USD, EUR, ETH.. etc. +This function calculate the equivalent branded tokens needed for transfer for a given currency value. +The price point value should be in acceptable range of intendedPricePoint for transaction to be successful. + +- Currency type with no value e.g "":
+This means that the transactions are happening in BrandedToken. +This is a floating value type transaction. +This will not get Price point from Price oracle contract. +```_transferAmount``` and ```_commisionAmount``` are in BrandedTokens. + +The interface for pay function is as below. +``` +function pay( + address _beneficiary, + uint256 _transferAmount, + address _commissionBeneficiary, + uint256 _commissionAmount, + bytes3 _currency, + uint256 _intendedPricePoint) + public + returns (bool success); +``` + +### Details about the Accepted Margin. + +The Accepted Margin for any currency can be updated in this contract. This can be only called by Ops. +This specifies the absolute +/- range in fiat in which the Price point will be accepted +For fixed transaction types, this value helps to validated that if the transfer is done within the range of intended price point. + +The interface for this is as below +``` +// getter +function acceptedMargins( + bytes3 _currency) + public + returns (uint64); + +// setter +function setAcceptedMargin( + bytes3 _currency, + uint64 _acceptedMargin) + public + returns (bool); +``` + +### Details about the Price Oracles. + +This contract provides the flexibility to add, remove or update a PriceOracle contract reference for a given currency type. +Price Oracles are the contracts that determines the price of OST and is derived from tracking its value across all exchanges globally. + +The interface for this is as below +``` +// getter +function priceOracles( + bytes3 _currency) + public + returns (address); + +// setter +function setPriceOracle( + bytes3 _currency, + address _oracleAddress) + public + returns (bool); +``` + +### Details about the currency value to number of Branded token conversions. +The amounts i.e ```_transferAmount``` and ```_commissionAmount``` are always in currency value (If currency is not ""). +The conversion from currency value to number of tokens is based on the following assumptions. +- The Transfer amounts are in wei (10^18) +- The Price point from the Price Oracle is in wei (10^18) +- The number of Branded token is also in wei. + +```number of BT = (conversionRate * transferAmount * 10^18)/PricePoint``` + From 10923a9e8cee2c22a9e0ad7dd99767c2d38d5d1b Mon Sep 17 00:00:00 2001 From: deepesh KN Date: Mon, 22 Jan 2018 13:14:06 +0530 Subject: [PATCH 05/21] Contract: changed storage variable to private, and moved PriceOravleInterface.sol to ost-price-oracle directory --- contracts/Pricer.sol | 60 +++++++++++++++---- .../PriceOracleInterface.sol | 0 2 files changed, 48 insertions(+), 12 deletions(-) rename contracts/{ => ost-price-oracle}/PriceOracleInterface.sol (100%) diff --git a/contracts/Pricer.sol b/contracts/Pricer.sol index 2606f5e..6b7d9f2 100644 --- a/contracts/Pricer.sol +++ b/contracts/Pricer.sol @@ -24,9 +24,9 @@ pragma solidity ^0.4.17; import "./openst-protocol/EIP20Interface.sol"; import "./openst-protocol/UtilityTokenInterface.sol"; +import "./ost-price-oracle/PriceOracleInterface.sol"; import "./OpsManaged.sol"; import "./SafeMath.sol"; -import "./PriceOracleInterface.sol"; import "./PricerInterface.sol"; contract Pricer is OpsManaged, PricerInterface { @@ -36,13 +36,13 @@ contract Pricer is OpsManaged, PricerInterface { * Storage */ ///BrandedToken address - address public brandedToken; + address private pricerBrandedToken; ///currency to Margin mapping, Absolute +/- range in currency in which the price point will be accepted - mapping(bytes3 /* currency */ => uint64 /* margin */) public acceptedMargins; + mapping(bytes3 /* currency */ => uint64 /* margin */) private pricerAcceptedMargins; ///currency to Price Oracles address mapping - mapping(bytes3 /* currency */ => address /* price oracle address */) public priceOracles; + mapping(bytes3 /* currency */ => address /* price oracle address */) private pricerPriceOracles; /* * Events @@ -77,7 +77,43 @@ contract Pricer is OpsManaged, PricerInterface { public OpsManaged() { - brandedToken = _brandedToken; + pricerBrandedToken = _brandedToken; + } + + /// @dev Returns address of the branded token; + /// Public; + /// @return address + function brandedToken() + public + returns (address) + { + return pricerBrandedToken; + } + + /// @dev Takes _currency; + /// Returns Acceptable margin for the given currency; + /// Public; + /// @param _currency currency + /// @return uint64 margin + function acceptedMargins( + bytes3 _currency) + public + returns (uint64) + { + return pricerAcceptedMargins[_currency]; + } + + /// @dev Takes _currency; + /// Returns address of Price Oracle for the given currency; + /// Public + /// @param _currency currency + /// @return address + function priceOracles( + bytes3 _currency) + public + returns (address) + { + return pricerPriceOracles[_currency]; } /// @dev Takes _currency, _oracleAddress; @@ -96,7 +132,7 @@ contract Pricer is OpsManaged, PricerInterface { { require(_oracleAddress != address(0)); require(_currency != ""); - priceOracles[_currency] = _oracleAddress; + pricerPriceOracles[_currency] = _oracleAddress; //Trigger PriceOracleSet event PriceOracleSet(_currency, _oracleAddress); @@ -117,7 +153,7 @@ contract Pricer is OpsManaged, PricerInterface { public returns (bool /* success */) { - acceptedMargins[_currency] = _acceptedMargin; + pricerAcceptedMargins[_currency] = _acceptedMargin; // Trigger Event for Intended Price Acceptable Range Update AcceptedMargin(_currency, _acceptedMargin); return true; @@ -160,13 +196,13 @@ contract Pricer is OpsManaged, PricerInterface { uint8 tokenDecimals = 0; (pricePoint, tokenDecimals) = getPricePoint(_currency); require(pricePoint > 0); - require(isPricePointInRange(_intendedPricePoint, pricePoint, acceptedMargins[_currency])); + require(isPricePointInRange(_intendedPricePoint, pricePoint, pricerAcceptedMargins[_currency])); (tokenAmount, commissionTokenAmount) = getBTAmountFromCurrencyValue(pricePoint, tokenDecimals, _transferAmount, _commissionAmount); } - require(EIP20Interface(brandedToken).transferFrom(msg.sender, _beneficiary, tokenAmount)); + require(EIP20Interface(pricerBrandedToken).transferFrom(msg.sender, _beneficiary, tokenAmount)); if(_commissionBeneficiary != address(0)) { - require(EIP20Interface(brandedToken).transferFrom(msg.sender, _commissionBeneficiary, commissionTokenAmount)); + require(EIP20Interface(pricerBrandedToken).transferFrom(msg.sender, _commissionBeneficiary, commissionTokenAmount)); } //Trigger Event for PaymentComplete @@ -185,7 +221,7 @@ contract Pricer is OpsManaged, PricerInterface { returns (uint256 /* pricePoint */, uint8 /* TokenDecimal*/) { require(_currency != ""); - PriceOracleInterface currentPriceOracle = PriceOracleInterface(priceOracles[_currency]); + PriceOracleInterface currentPriceOracle = PriceOracleInterface(pricerPriceOracles[_currency]); require(currentPriceOracle != address(0)); return (currentPriceOracle.getPrice(), currentPriceOracle.TOKEN_DECIMALS()); } @@ -230,7 +266,7 @@ contract Pricer is OpsManaged, PricerInterface { private returns (uint256 /* number of BT */, uint256 /* number of commission BT */) { - uint256 conversionRate = UtilityTokenInterface(brandedToken).conversionRate(); + uint256 conversionRate = UtilityTokenInterface(pricerBrandedToken).conversionRate(); require(conversionRate > 0); uint256 adjConversionRate = SafeMath.mul(conversionRate, 10**uint256(_tokenDecimals)); uint256 amountBT = SafeMath.div(SafeMath.mul(_transferAmount, adjConversionRate), _pricePoint); diff --git a/contracts/PriceOracleInterface.sol b/contracts/ost-price-oracle/PriceOracleInterface.sol similarity index 100% rename from contracts/PriceOracleInterface.sol rename to contracts/ost-price-oracle/PriceOracleInterface.sol From aca7686eb9f559df8ca4c00063e37927afac168d Mon Sep 17 00:00:00 2001 From: deepesh KN Date: Mon, 22 Jan 2018 13:27:07 +0530 Subject: [PATCH 06/21] Contract: Updated PriceOracleInterface.sol --- contracts/Pricer.sol | 10 +- .../ost-price-oracle/PriceOracleInterface.sol | 130 +++++++++--------- 2 files changed, 74 insertions(+), 66 deletions(-) diff --git a/contracts/Pricer.sol b/contracts/Pricer.sol index 6b7d9f2..cfba5c2 100644 --- a/contracts/Pricer.sol +++ b/contracts/Pricer.sol @@ -84,7 +84,7 @@ contract Pricer is OpsManaged, PricerInterface { /// Public; /// @return address function brandedToken() - public + public returns (address) { return pricerBrandedToken; @@ -97,7 +97,7 @@ contract Pricer is OpsManaged, PricerInterface { /// @return uint64 margin function acceptedMargins( bytes3 _currency) - public + public returns (uint64) { return pricerAcceptedMargins[_currency]; @@ -110,7 +110,7 @@ contract Pricer is OpsManaged, PricerInterface { /// @return address function priceOracles( bytes3 _currency) - public + public returns (address) { return pricerPriceOracles[_currency]; @@ -217,7 +217,7 @@ contract Pricer is OpsManaged, PricerInterface { /// @return (currentPrice, TokenDecimals) function getPricePoint( bytes3 _currency) - public + public returns (uint256 /* pricePoint */, uint8 /* TokenDecimal*/) { require(_currency != ""); @@ -238,6 +238,7 @@ contract Pricer is OpsManaged, PricerInterface { uint256 _currentPricePoint, uint64 _acceptedMargin) private + pure returns (bool /*isValid*/) { bool isValid = true; @@ -264,6 +265,7 @@ contract Pricer is OpsManaged, PricerInterface { uint256 _transferAmount, uint256 _commissionAmount) private + view returns (uint256 /* number of BT */, uint256 /* number of commission BT */) { uint256 conversionRate = UtilityTokenInterface(pricerBrandedToken).conversionRate(); diff --git a/contracts/ost-price-oracle/PriceOracleInterface.sol b/contracts/ost-price-oracle/PriceOracleInterface.sol index f6b4201..509b0b9 100644 --- a/contracts/ost-price-oracle/PriceOracleInterface.sol +++ b/contracts/ost-price-oracle/PriceOracleInterface.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.17; -// Copyright 2018 OpenST Ltd. +// Copyright 2018 OST.com Ltd. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,77 +20,83 @@ pragma solidity ^0.4.17; // http://www.simpletoken.org/ // // -------------------------- -// This contract keeps in storage an updated baseCurrency/quoteCurrency price, -// which is updated in a particular duration. -// There is an expiry duration for a currency pair -// + +/// @title PriceOracleInterface - Interface of PriceOracle contract contract PriceOracleInterface{ - /* - * Events - */ + /* + * Events + */ + + /// @dev event emitted whenever price is updated + /// @return _price + /// @return _expirationHeight + event PriceUpdated(uint256 _price, + uint256 _expirationHeight); - /// @dev event emitted whenever price is updated - /// @return _price - /// @return _expirationHeight - event PriceOracleUpdated(uint256 _price, - uint256 _expirationHeight); + /// @dev event emitted when price expires + /// @return _expirationHeight + event PriceExpired(uint256 _expirationHeight); - /// @dev event emitted when price expires - /// @return _expirationHeight - event PriceExpired(uint256 _expirationHeight); + /* + * Functions + */ - /* - * Functions - */ + /// @dev Price is stored as fixed point integer value similar as wei unit. + /// Use this variable in case decimal value need to be evaluated + /// @return token decimals + function tokenDecimals() + public + view + returns( + uint8); - /// @dev Price is stored as fixed point integer value similar as wei unit. - /// Use this variable in case decimal value need to be evaluated - /// @return TOKEN_DECIMALS - function TOKEN_DECIMALS() - public - constant - returns( - uint8); + /// @dev use this function to get price validity duration + /// @return price validity duration + function priceValidityDuration() + public + view + returns( + uint256); - /// @dev block height at which the price expires - /// @return expirationHeight - function expirationHeight() - public - view - returns( - uint256); + /// @dev block height at which the price expires + /// @return expirationHeight + function expirationHeight() + public + view + returns( + uint256); - /// @dev get baseCurrency bytes3 code - /// @return base currency - function baseCurrency() - public - view - returns( - bytes3); + /// @dev get baseCurrency bytes3 code + /// @return baseCurrency + function baseCurrency() + public + view + returns( + bytes3); - /// @dev returns quoteCurrency bytes3 code - /// @return quote currency - function quoteCurrency() - public - view - returns( - bytes3); + /// @dev returns quoteCurrency bytes3 code + /// @return quoteCurrency + function quoteCurrency() + public + view + returns( + bytes3); - /// @dev use this function to update oracle price - /// @param _price price - /// @return expirationHeight - function setPrice( - uint256 _price) - external - returns( - uint256); + /// @dev use this function to update oracle price + /// @param _price price + /// @return expirationHeight + function setPrice( + uint256 _price) + external + returns( + uint256); - /// @dev use this function to get price - /// @return baseCurrency/quoteCurrency value - function getPrice() - public - returns( - uint256); + /// @dev use this function to get price + /// @return quoteCurrency/baseCurrency value + function getPrice() + public + returns( + uint256); } \ No newline at end of file From 8629f37e52eb7b247f1287a8a65870bf860471d9 Mon Sep 17 00:00:00 2001 From: deepesh KN Date: Mon, 22 Jan 2018 14:26:32 +0530 Subject: [PATCH 07/21] Contract: Added unsetPriceOracle function --- contracts/Pricer.sol | 24 ++++++++++++++++++++++++ contracts/PricerInterface.sol | 23 ++++++++++++++++++++--- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/contracts/Pricer.sol b/contracts/Pricer.sol index cfba5c2..b95d388 100644 --- a/contracts/Pricer.sol +++ b/contracts/Pricer.sol @@ -62,6 +62,10 @@ contract Pricer is OpsManaged, PricerInterface { event PriceOracleSet( bytes3 _currency, address _address); + + ///Event for priceOracles Delete + event PriceOracleUnset( + bytes3 _currency); ///Event for AcceptedMargin update for currency event AcceptedMargin( @@ -139,6 +143,26 @@ contract Pricer is OpsManaged, PricerInterface { return true; } + /// @dev Takes _currency; + /// Removes the Price Oracle address for a given currency + /// Emits PriceOracleUnSet Event; + /// Only called by ops + /// @param _currency currency + /// @return bool isSuccess + function unsetPriceOracle( + bytes3 _currency) + onlyOps + public + returns (bool /* success */) + { + require(pricerPriceOracles[_currency] != 0); + pricerPriceOracles[_currency] = 0; + + //Trigger PriceOracleUnset event + PriceOracleUnset(_currency); + return true; + } + /// @dev Takes _currency, _acceptedMargin; /// Updated the acceptable margin range for a given currency /// Emits AcceptedMargin Event; diff --git a/contracts/PricerInterface.sol b/contracts/PricerInterface.sol index 135e8de..ebb8487 100644 --- a/contracts/PricerInterface.sol +++ b/contracts/PricerInterface.sol @@ -31,10 +31,15 @@ contract PricerInterface { uint256 _intendedPricePoint, uint256 _actualPricePoint); - event PriceOracleSet(bytes3 _currency, + event PriceOracleSet( + bytes3 _currency, address _address); - event AcceptedMargin(bytes3 _currency, + event PriceOracleUnset( + bytes3 _currency); + + event AcceptedMargin( + bytes3 _currency, uint64 relativeIntendedPriceRange); /// @dev Returns address of the branded token; @@ -77,6 +82,18 @@ contract PricerInterface { public returns (bool); + /// @dev Takes _currency; + /// Removes the Price Oracle address for a given currency + /// Emits PriceOracleUnSet Event; + /// Only called by ops + /// @param _currency currency + /// @return bool isSuccess + function unsetPriceOracle( + bytes3 _currency) + public + returns (bool); + + /// @dev Takes _currency, _acceptedMargin; /// Updated the acceptable margin range for a given currency; /// Emits AcceptedMargin Event; @@ -111,7 +128,7 @@ contract PricerInterface { bytes3 _currency, uint256 _intendedPricePoint) public - returns (bool success); + returns (bool); /// @dev Takes _currency; /// gets current price point and token decimal for the priceOracle for the give currency; From 3b4612bd128bedecaabb90182bbd7c798412c77a Mon Sep 17 00:00:00 2001 From: deepesh KN Date: Mon, 22 Jan 2018 16:09:47 +0530 Subject: [PATCH 08/21] Contract: Added SafeMath.sol and compile.sh --- contracts/Pricer.sol | 2 +- contracts/PricerInterface.sol | 2 +- contracts/SafeMath.sol | 67 +++++++++++++++++++++++++++++++++++ contracts/compile.sh | 16 +++++++++ 4 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 contracts/SafeMath.sol create mode 100644 contracts/compile.sh diff --git a/contracts/Pricer.sol b/contracts/Pricer.sol index b95d388..10dfe26 100644 --- a/contracts/Pricer.sol +++ b/contracts/Pricer.sol @@ -247,7 +247,7 @@ contract Pricer is OpsManaged, PricerInterface { require(_currency != ""); PriceOracleInterface currentPriceOracle = PriceOracleInterface(pricerPriceOracles[_currency]); require(currentPriceOracle != address(0)); - return (currentPriceOracle.getPrice(), currentPriceOracle.TOKEN_DECIMALS()); + return (currentPriceOracle.getPrice(), currentPriceOracle.tokenDecimals()); } /// @dev Takes _intendedPricePoint, _currentPricePoint, _acceptedMargin; diff --git a/contracts/PricerInterface.sol b/contracts/PricerInterface.sol index ebb8487..ee84eee 100644 --- a/contracts/PricerInterface.sol +++ b/contracts/PricerInterface.sol @@ -23,7 +23,7 @@ pragma solidity ^0.4.17; contract PricerInterface { - event Payment(address _beneficiary, + event Payment(address _beneficiary, uint256 _transferAmount, address _commissionBeneficiary, uint256 _commissionAmount, diff --git a/contracts/SafeMath.sol b/contracts/SafeMath.sol new file mode 100644 index 0000000..379f7be --- /dev/null +++ b/contracts/SafeMath.sol @@ -0,0 +1,67 @@ +pragma solidity ^0.4.17; + +// Copyright 2017 OpenST Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ---------------------------------------------------------------------------- +// Common: SafeMath Library Implementation +// +// http://www.simpletoken.org/ +// +// Based on the SafeMath library by the OpenZeppelin team. +// Copyright (c) 2016 Smart Contract Solutions, Inc. +// https://github.com/OpenZeppelin/zeppelin-solidity +// The MIT License. +// ---------------------------------------------------------------------------- + + +/** + @title SafeMath + @notice Implements SafeMath +*/ +library SafeMath { + + function mul(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 c = a * b; + + assert(a == 0 || c / a == b); + + return c; + } + + + function div(uint256 a, uint256 b) internal pure returns (uint256) { + // Solidity automatically throws when dividing by 0 + uint256 c = a / b; + + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + return c; + } + + + function sub(uint256 a, uint256 b) internal pure returns (uint256) { + assert(b <= a); + + return a - b; + } + + + function add(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 c = a + b; + + assert(c >= a); + + return c; + } +} diff --git a/contracts/compile.sh b/contracts/compile.sh new file mode 100644 index 0000000..10891e2 --- /dev/null +++ b/contracts/compile.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +CONTRACTDIR=./contracts/*.sol +ABIDIRUTILITY=./contracts/abi +BINDIRVALUE=./contracts/bin + +mkdir -p "$ABIDIRUTILITY" +mkdir -p "$BINDIRVALUE" + +for filename in $CONTRACTDIR; do + echo "" + echo "Compiling ${filename}" + echo "" + solc --abi --optimize --optimize-runs 200 --overwrite ${filename} -o $ABIDIRUTILITY + solc --bin --optimize --optimize-runs 200 --overwrite ${filename} -o $BINDIRVALUE +done \ No newline at end of file From a8a4785b8889c7a1a74a07c9b93c4648d813af15 Mon Sep 17 00:00:00 2001 From: Jason Banks Date: Mon, 22 Jan 2018 12:03:09 +0530 Subject: [PATCH 09/21] Docs: tweak Pricer spec language. Addresses #9 --- docs/md/Pricer.md | 89 +++++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 42 deletions(-) diff --git a/docs/md/Pricer.md b/docs/md/Pricer.md index f64b323..853edd1 100644 --- a/docs/md/Pricer.md +++ b/docs/md/Pricer.md @@ -1,49 +1,48 @@ ## Pricer Contract ### Context -Member companies can create their branded token economy through the OST dashboard. -Member company does the following when they mint the Branded Token. +Users can create their branded token economy through the OST dashboard. +User does the following when creating and administering a BrandedToken. - Define the OST to BT conversion rate. -- Define various transactions which includes the following. +- Define various transactions, which may include the following attributes: - Transaction Type (User to user, user to company, company to user). - Transaction Name. - - Transaction Value is at fixed rate (in currency/fiat) or floating rate (in BT). + - Transaction Value is a fixed (in currency) or floating rate (in BT). - Transaction Commission in percentage (inclusive for user-to-company, exclusive for user-to-user). ### Requirements -- Pricer makes two ```transferFrom``` calls. -- Pricer contract needs to be set a sufficient allowance on the account to spend (for both BT-valued and fiat-valued transfers). -- Cheaper gas than repeated transfers. -- In case of fiat-valued transfer the amount of BT needed is determined on-chain (limited by allowance and by mechanism below). +- Pricer makes two `transferFrom` calls (for value and commission; less gas than repeated transfers). +- Pricer contract needs to be approved for a sufficient allowance on the account to spend (for both BT-valued and currency-valued transfers). +- In case of currency-valued payments, the amount of BT needed is determined on-chain (limited by allowance and by mechanism below). ### Specifications -- Pricer Contract is OpsManaged. -- Every Pricer contract has one interface to a Branded Token. -- Transaction to Pricer provides intended price point as parameter. If intended price point is further than margin outside of Oracle’s price point then transfer fails. If within margin of Oracle price point then Oracle price point is used -- This contract stores Branded Token address. This will be helpful to directly get the conversion rate and perform transfer functions. -- This contract stores the AcceptedMargin value for each currency. This specifies the absolute +/- range in currency value in which the price point from the PriceOracle will be accepted. Only ops will be able to update this value. The transaction will be performed only if the following condition will be true. Else it will result in to failed transaction. +- Pricer contract is OpsManaged. +- Every Pricer contract has one interface to a BrandedToken. +- Transaction to Pricer provides intended price point as parameter. If Oracle's price point is further than margin outside of intended price point, the transfer is not permitted. If within margin of Oracle price point, then Oracle price point is used +- This contract stores a BrandedToken address. This will be helpful to directly get the conversion rate and perform transfer functions. +- This contract stores the AcceptedMargin value for each currency. This specifies the absolute +/- range in currency value in which the price point from the PriceOracle will be accepted. Only ops will be able to update this value. The transaction will be performed only if the following condition will be true. Else it will result in a failed transaction.
```(IntendedPrice - AcceptedMargin) <= PricePoint from PriceOracle <= (IntendedPrice + AcceptedMargin)``` -- This contract stores the PriceOracle address for each currency. PriceOracle is instanced for a fiat value. This will allow to add support of adding new fiat value at any time. Only ops will be able to set/update this value. -- This contract makes two transferFrom calls. The amount to be transferred is in currency value if its a fixed transaction type, else its in Branded token if its a floating type transaction. -- In case of fixed transaction type, this contract also validates for currency price point fluctuations. To achieve this and intended price point is specified while making transfers and this intended price point is validated against the current price point from the PriceOracle contract. The current price should be in acceptable range of intended price point. +- Because PriceOracle is instantiated for a currency value, this contract stores a PriceOracle address for each currency and allows adding/updating a PriceOracle for a currency value at any time. Only ops will be able to set/update this value. +- This contract makes two transferFrom calls. The amount to be transferred is in currency value if its a fixed transaction type, else its in branded token if its a floating type transaction. +- In case of fixed transaction type, this contract also validates for currency price point fluctuations. To achieve this, an intended price point is specified for pay transactions and this intended price point is validated against the current price point from the PriceOracle contract. The current price should be in acceptable range of intended price point. ### Details about the Pay functions. -Pay function is public. This function accepts beneficiary address and its amount, commisionBeneficiary address and its amount, Currency type and intendedPricePoint. -On successful transfer this function emits PaymentComplete Event. -Currency type can have the following value. +Pay function is public. This function accepts beneficiary address and amount, commisionBeneficiary address and amount, currency type and intendedPricePoint. +On success, this function emits a `Payment` Event. +Currency type is bytes3 and: -- Currency type can be byte3 value e.g USD, EUR, ETH ... etc:
-This means that the transactions are happening in USD, EUR, ETH Fiat value. +- can indicate a currency e.g "USD", "EUR", "ETH" ... etc:
+This means that the transactions are priced a currency value. This is a fixed value type transaction. -This will get the price point from the price oracle contract.``` _transferAmount``` and ```_commisionAmount``` are in given currency type i.e USD, EUR, ETH.. etc. -This function calculate the equivalent branded tokens needed for transfer for a given currency value. -The price point value should be in acceptable range of intendedPricePoint for transaction to be successful. +This will get the price point from the price oracle contract. ` _transferAmount` and `_commisionAmount` are in given in amounts reflecting their currency type i.e USD, EUR, ETH.. etc. +This function calculates the equivalent branded tokens needed for transfer for a given currency value. +The price point should be in acceptable range of the intended price point for the transaction to be successful. -- Currency type with no value e.g "":
-This means that the transactions are happening in BrandedToken. +- can be empty, e.g "":
+This means that the transactions are priced in branded tokens. This is a floating value type transaction. -This will not get Price point from Price oracle contract. -```_transferAmount``` and ```_commisionAmount``` are in BrandedTokens. +This will not get a price point from a PriceOracle contract. +`_transferAmount` and `_commisionAmount` are in branded tokens. The interface for pay function is as below. ``` @@ -61,18 +60,18 @@ function pay( ### Details about the Accepted Margin. The Accepted Margin for any currency can be updated in this contract. This can be only called by Ops. -This specifies the absolute +/- range in fiat in which the Price point will be accepted -For fixed transaction types, this value helps to validated that if the transfer is done within the range of intended price point. +This specifies the absolute +/- range in currency in which the price point will be accepted +For fixed transaction types, this value helps to validated that the transfer is done within an acceptable range of the intended price point. The interface for this is as below ``` -// getter +/// getter function acceptedMargins( bytes3 _currency) public returns (uint64); -// setter +/// setter function setAcceptedMargin( bytes3 _currency, uint64 _acceptedMargin) @@ -82,31 +81,37 @@ function setAcceptedMargin( ### Details about the Price Oracles. -This contract provides the flexibility to add, remove or update a PriceOracle contract reference for a given currency type. -Price Oracles are the contracts that determines the price of OST and is derived from tracking its value across all exchanges globally. +This contract provides the flexibility to add, update, and unset a PriceOracle contract reference for a given currency type. +Price oracles are the contracts that provide the price of OST in a specific currency. The interface for this is as below ``` -// getter +/// getter function priceOracles( bytes3 _currency) public returns (address); -// setter +/// setter function setPriceOracle( bytes3 _currency, address _oracleAddress) public returns (bool); + +/// unsetter +function unsetPriceOracle( + bytes3 _currency) + public + onlyOps + returns (bool); ``` ### Details about the currency value to number of Branded token conversions. -The amounts i.e ```_transferAmount``` and ```_commissionAmount``` are always in currency value (If currency is not ""). -The conversion from currency value to number of tokens is based on the following assumptions. -- The Transfer amounts are in wei (10^18) -- The Price point from the Price Oracle is in wei (10^18) -- The number of Branded token is also in wei. +The amounts i.e ```_transferAmount``` and ```_commissionAmount``` are always in currency value amounts if currency is not "". +The conversion from currency value to amount of tokens is based on the following assumptions: +- The transfer amounts match the token decimals denomination provided by the PriceOracle (10^tokenDecimals, such as 10^18) +- The price point from the PriceOracle matches the token decimals denomination provided by the Price Oracle (10^tokenDecimals, such as 10^18) -```number of BT = (conversionRate * transferAmount * 10^18)/PricePoint``` +```number of BT = (conversionRate * transferAmount * 10^tokenDecimals)/PricePoint``` From 024d344eaab694cdb8b24d072b320667e67c1480 Mon Sep 17 00:00:00 2001 From: deepesh KN Date: Mon, 22 Jan 2018 16:46:20 +0530 Subject: [PATCH 10/21] Contract: unsetPriceOracle function changed to use delete. --- contracts/Pricer.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/Pricer.sol b/contracts/Pricer.sol index 10dfe26..84da68d 100644 --- a/contracts/Pricer.sol +++ b/contracts/Pricer.sol @@ -156,7 +156,7 @@ contract Pricer is OpsManaged, PricerInterface { returns (bool /* success */) { require(pricerPriceOracles[_currency] != 0); - pricerPriceOracles[_currency] = 0; + delete pricerPriceOracles[_currency]; //Trigger PriceOracleUnset event PriceOracleUnset(_currency); From eba67d689d5e2730b3837d3614b8cb6195e11e2e Mon Sep 17 00:00:00 2001 From: deepesh KN Date: Mon, 22 Jan 2018 17:27:53 +0530 Subject: [PATCH 11/21] Contract: Fixed Linter errors for Pricer.sol and PricerInterface.sol --- contracts/Pricer.sol | 511 +++++++++++++++++----------------- contracts/PricerInterface.sol | 217 ++++++++------- 2 files changed, 368 insertions(+), 360 deletions(-) diff --git a/contracts/Pricer.sol b/contracts/Pricer.sol index 84da68d..46e1ef5 100644 --- a/contracts/Pricer.sol +++ b/contracts/Pricer.sol @@ -29,274 +29,279 @@ import "./OpsManaged.sol"; import "./SafeMath.sol"; import "./PricerInterface.sol"; -contract Pricer is OpsManaged, PricerInterface { - using SafeMath for uint256; - - /* - * Storage - */ - ///BrandedToken address - address private pricerBrandedToken; - ///currency to Margin mapping, Absolute +/- range in currency in which the price point will be accepted - mapping(bytes3 /* currency */ => uint64 /* margin */) private pricerAcceptedMargins; - - ///currency to Price Oracles address mapping - mapping(bytes3 /* currency */ => address /* price oracle address */) private pricerPriceOracles; - - /* - * Events - */ +contract Pricer is OpsManaged, PricerInterface { + using SafeMath for uint256; - ///Event for PaymentComplete - event Payment( - address _beneficiary, - uint256 _transferAmount, - address _commissionBeneficiary, - uint256 _commissionAmount, - bytes3 _currency, - uint256 _intendedPricePoint, - uint256 _actualPricePoint); - - ///Event for priceOracles Updates for currency - event PriceOracleSet( - bytes3 _currency, - address _address); - - ///Event for priceOracles Delete - event PriceOracleUnset( - bytes3 _currency); + /* + * Storage + */ + ///BrandedToken address + address private pricerBrandedToken; - ///Event for AcceptedMargin update for currency - event AcceptedMargin( - bytes3 _currency, - uint64 relativeIntendedPriceRange); - - /* - * Public functions - */ + ///currency to Margin mapping, Absolute +/- range in currency in which the price point will be accepted + mapping(bytes3 /* currency */ => uint64 /* margin */) private pricerAcceptedMargins; + + ///currency to Price Oracles address mapping + mapping(bytes3 /* currency */ => address /* price oracle address */) private pricerPriceOracles; - function Pricer( - address _brandedToken) - public - OpsManaged() - { - pricerBrandedToken = _brandedToken; - } + /* + * Events + */ + ///Event for PaymentComplete + event Payment( + address _beneficiary, + uint256 _transferAmount, + address _commissionBeneficiary, + uint256 _commissionAmount, + bytes3 _currency, + uint256 _intendedPricePoint, + uint256 _actualPricePoint); + + ///Event for priceOracles Updates for currency + event PriceOracleSet( + bytes3 _currency, + address _address); + + ///Event for priceOracles Delete + event PriceOracleUnset( + bytes3 _currency); - /// @dev Returns address of the branded token; - /// Public; - /// @return address - function brandedToken() - public - returns (address) - { - return pricerBrandedToken; - } + ///Event for AcceptedMargin update for currency + event AcceptedMargin( + bytes3 _currency, + uint64 relativeIntendedPriceRange); + + /* + * Public functions + */ + function Pricer( + address _brandedToken) + public + OpsManaged() + { + pricerBrandedToken = _brandedToken; + } - /// @dev Takes _currency; - /// Returns Acceptable margin for the given currency; - /// Public; - /// @param _currency currency - /// @return uint64 margin - function acceptedMargins( - bytes3 _currency) - public - returns (uint64) - { - return pricerAcceptedMargins[_currency]; - } + /// @dev Returns address of the branded token; + /// Public; + /// @return address + function brandedToken() + public + returns (address) + { + return pricerBrandedToken; + } - /// @dev Takes _currency; - /// Returns address of Price Oracle for the given currency; - /// Public - /// @param _currency currency - /// @return address - function priceOracles( - bytes3 _currency) - public - returns (address) - { - return pricerPriceOracles[_currency]; - } + /// @dev Takes _currency; + /// Returns Acceptable margin for the given currency; + /// Public; + /// @param _currency currency + /// @return uint64 margin + function acceptedMargins( + bytes3 _currency) + public + returns (uint64) + { + return pricerAcceptedMargins[_currency]; + } - /// @dev Takes _currency, _oracleAddress; - /// Updated the Price Oracle address for a given currency - /// Emits PriceOracleSet Event; - /// Only called by ops - /// @param _currency currency - /// @param _oracleAddress oracleAddress - /// @return bool isSuccess - function setPriceOracle( - bytes3 _currency, - address _oracleAddress) - onlyOps - public - returns (bool /* success */) - { - require(_oracleAddress != address(0)); - require(_currency != ""); - pricerPriceOracles[_currency] = _oracleAddress; + /// @dev Takes _currency; + /// Returns address of Price Oracle for the given currency; + /// Public + /// @param _currency currency + /// @return address + function priceOracles( + bytes3 _currency) + public + returns (address) + { + return pricerPriceOracles[_currency]; + } - //Trigger PriceOracleSet event - PriceOracleSet(_currency, _oracleAddress); - return true; - } + /// @dev Takes _currency, _oracleAddress; + /// Updated the Price Oracle address for a given currency + /// Emits PriceOracleSet Event; + /// Only called by ops + /// @param _currency currency + /// @param _oracleAddress oracleAddress + /// @return bool isSuccess + function setPriceOracle( + bytes3 _currency, + address _oracleAddress) + public + onlyOps + returns (bool /* success */) + { + require(_oracleAddress != address(0)); + require(_currency != ""); + pricerPriceOracles[_currency] = _oracleAddress; - /// @dev Takes _currency; - /// Removes the Price Oracle address for a given currency - /// Emits PriceOracleUnSet Event; - /// Only called by ops - /// @param _currency currency - /// @return bool isSuccess - function unsetPriceOracle( - bytes3 _currency) - onlyOps - public - returns (bool /* success */) - { - require(pricerPriceOracles[_currency] != 0); - delete pricerPriceOracles[_currency]; + //Trigger PriceOracleSet event + PriceOracleSet(_currency, _oracleAddress); + return true; + } - //Trigger PriceOracleUnset event - PriceOracleUnset(_currency); - return true; - } + /// @dev Takes _currency; + /// Removes the Price Oracle address for a given currency + /// Emits PriceOracleUnSet Event; + /// Only called by ops + /// @param _currency currency + /// @return bool isSuccess + function unsetPriceOracle( + bytes3 _currency) + public + onlyOps + returns (bool /* success */) + { + require(pricerPriceOracles[_currency] != 0); + delete pricerPriceOracles[_currency]; - /// @dev Takes _currency, _acceptedMargin; - /// Updated the acceptable margin range for a given currency - /// Emits AcceptedMargin Event; - /// Only called by ops - /// @param _currency currency - /// @param _acceptedMargin acceptedMargin - /// @return bool isSuccess - function setAcceptedMargin( - bytes3 _currency, - uint64 _acceptedMargin) - onlyOps - public - returns (bool /* success */) - { - pricerAcceptedMargins[_currency] = _acceptedMargin; - // Trigger Event for Intended Price Acceptable Range Update - AcceptedMargin(_currency, _acceptedMargin); - return true; - } + //Trigger PriceOracleUnset event + PriceOracleUnset(_currency); + return true; + } - /// @dev Takes _beneficiary, _transferAmount, _commissionBeneficiary, _commissionAmount, _currency, _intendedPricePoint; - /// Validates if the currentPrice from PriceOracle is in accepatble margin of _intendedPricePoint (If _ currency is not 0) - /// If _currency is 0 then it transfer the Branded tokens equal to _transferAmount to _beneficiary and Branded tokens equal to _commissionAmount to _commissionBeneficiary (Floating value transaction); - /// If _currency is not 0 then it transfer the Branded tokens equivalant to _transferAmount in currency value to _beneficiary and Branded tokens equivalant to _commissionAmount in currency value to _commissionBeneficiary (Fixed value transaction); - /// Emits Payment Event; - /// Public method - /// @param _beneficiary beneficiary - /// @param _transferAmount transferAmount - /// @param _commissionBeneficiary commissionBeneficiary - /// @param _commissionAmount commissionAmount - /// @param _currency currency - /// @param _intendedPricePoint _intendedPricePoint - /// @return bool isSuccess - function pay( - address _beneficiary, - uint256 _transferAmount, - address _commissionBeneficiary, - uint256 _commissionAmount, - bytes3 _currency, - uint256 _intendedPricePoint) - public - returns (bool /* success */) - { - require(_beneficiary != address(0)); - require(_transferAmount != 0); + /// @dev Takes _currency, _acceptedMargin; + /// Updated the acceptable margin range for a given currency + /// Emits AcceptedMargin Event; + /// Only called by ops + /// @param _currency currency + /// @param _acceptedMargin acceptedMargin + /// @return bool isSuccess + function setAcceptedMargin( + bytes3 _currency, + uint64 _acceptedMargin) + public + onlyOps + returns (bool /* success */) + { + pricerAcceptedMargins[_currency] = _acceptedMargin; + // Trigger Event for Intended Price Acceptable Range Update + AcceptedMargin(_currency, _acceptedMargin); + return true; + } - if(_commissionAmount > 0) { - require(_commissionBeneficiary != address(0)); - } + /// @dev Takes _beneficiary, _transferAmount, _commissionBeneficiary, _commissionAmount, + /// _currency, _intendedPricePoint;Validates if the currentPrice from PriceOracle is + /// in accepatble margin of _intendedPricePoint (If _ currency is not 0) + /// If _currency is 0 then it transfer the Branded tokens equal to _transferAmount + /// to _beneficiary and Branded tokens equal to _commissionAmount to _commissionBeneficiary + /// (Floating value transaction); If _currency is not 0 then it transfer the Branded tokens + /// equivalant to _transferAmount in currency value to _beneficiary and Branded tokens + /// equivalant to _commissionAmount in currency value to _commissionBeneficiary + /// (Fixed value transaction); Emits Payment Event; + /// Public method + /// @param _beneficiary beneficiary + /// @param _transferAmount transferAmount + /// @param _commissionBeneficiary commissionBeneficiary + /// @param _commissionAmount commissionAmount + /// @param _currency currency + /// @param _intendedPricePoint _intendedPricePoint + /// @return bool isSuccess + function pay( + address _beneficiary, + uint256 _transferAmount, + address _commissionBeneficiary, + uint256 _commissionAmount, + bytes3 _currency, + uint256 _intendedPricePoint) + public + returns (bool /* success */) + { + require(_beneficiary != address(0)); + require(_transferAmount != 0); - uint256 tokenAmount = _transferAmount; - uint256 commissionTokenAmount = _commissionAmount; - uint256 pricePoint = _intendedPricePoint; - if(_currency != 0) { - uint8 tokenDecimals = 0; - (pricePoint, tokenDecimals) = getPricePoint(_currency); - require(pricePoint > 0); - require(isPricePointInRange(_intendedPricePoint, pricePoint, pricerAcceptedMargins[_currency])); - (tokenAmount, commissionTokenAmount) = getBTAmountFromCurrencyValue(pricePoint, tokenDecimals, _transferAmount, _commissionAmount); - } - - require(EIP20Interface(pricerBrandedToken).transferFrom(msg.sender, _beneficiary, tokenAmount)); - if(_commissionBeneficiary != address(0)) { - require(EIP20Interface(pricerBrandedToken).transferFrom(msg.sender, _commissionBeneficiary, commissionTokenAmount)); - } - - //Trigger Event for PaymentComplete - Payment(_beneficiary, _transferAmount, _commissionBeneficiary, _commissionAmount, _currency, _intendedPricePoint, pricePoint); - return true; - } + if (_commissionAmount > 0) { + require(_commissionBeneficiary != address(0)); + } - /// @dev Takes _currency; - /// gets current price point and token decimal for the priceOracle for the give currency; - /// Public method - /// @param _currency currency - /// @return (currentPrice, TokenDecimals) - function getPricePoint( - bytes3 _currency) - public - returns (uint256 /* pricePoint */, uint8 /* TokenDecimal*/) - { - require(_currency != ""); - PriceOracleInterface currentPriceOracle = PriceOracleInterface(pricerPriceOracles[_currency]); - require(currentPriceOracle != address(0)); - return (currentPriceOracle.getPrice(), currentPriceOracle.tokenDecimals()); - } - - /// @dev Takes _intendedPricePoint, _currentPricePoint, _acceptedMargin; - /// Checks if the current price point is in the acceptable range of intendedPricePoint; - /// Private method - /// @param _intendedPricePoint intendedPricePoint - /// @param _currentPricePoint currentPricePoint - /// @param _acceptedMargin acceptedMargin - /// @return bool isValid - function isPricePointInRange( - uint256 _intendedPricePoint, - uint256 _currentPricePoint, - uint64 _acceptedMargin) - private - pure - returns (bool /*isValid*/) - { - bool isValid = true; - if (_intendedPricePoint >= _acceptedMargin) { - isValid = SafeMath.sub(_intendedPricePoint, _acceptedMargin) <= _currentPricePoint; - } - if (isValid) { - isValid = _currentPricePoint <= SafeMath.add(_intendedPricePoint, _acceptedMargin); - } - return isValid; - } - + uint256 tokenAmount = _transferAmount; + uint256 commissionTokenAmount = _commissionAmount; + uint256 pricePoint = _intendedPricePoint; + if (_currency != 0) { + uint8 tokenDecimals = 0; + (pricePoint, tokenDecimals) = getPricePoint(_currency); + require(pricePoint > 0); + require(isPricePointInRange(_intendedPricePoint, pricePoint, pricerAcceptedMargins[_currency])); + (tokenAmount, commissionTokenAmount) = getBTAmountFromCurrencyValue(pricePoint, + tokenDecimals, _transferAmount, _commissionAmount); + } + + require(EIP20Interface(pricerBrandedToken).transferFrom(msg.sender, _beneficiary, tokenAmount)); + if (_commissionBeneficiary != address(0)) { + require(EIP20Interface(pricerBrandedToken).transferFrom(msg.sender, + _commissionBeneficiary, commissionTokenAmount)); + } + + //Trigger Event for PaymentComplete + Payment(_beneficiary, _transferAmount, _commissionBeneficiary, + _commissionAmount, _currency, _intendedPricePoint, pricePoint); + return true; + } - /// @dev Takes _pricePoint, _tokenDecimals, _transferAmount, _commissionAmount; - /// Calculated the number of branded token equivalant to the currency amount; - /// Private method - /// @param _pricePoint pricePoint - /// @param _tokenDecimals tokenDecimals - /// @param _transferAmount transferAmount - /// @param _commissionAmount commissionAmount - /// @return (amountBT,commissionAmountBT) - function getBTAmountFromCurrencyValue(uint256 _pricePoint, - uint8 _tokenDecimals, - uint256 _transferAmount, - uint256 _commissionAmount) - private - view - returns (uint256 /* number of BT */, uint256 /* number of commission BT */) - { - uint256 conversionRate = UtilityTokenInterface(pricerBrandedToken).conversionRate(); - require(conversionRate > 0); - uint256 adjConversionRate = SafeMath.mul(conversionRate, 10**uint256(_tokenDecimals)); - uint256 amountBT = SafeMath.div(SafeMath.mul(_transferAmount, adjConversionRate), _pricePoint); - uint256 commissionAmountBT = SafeMath.div(SafeMath.mul(_commissionAmount, adjConversionRate), _pricePoint); - return (amountBT, commissionAmountBT); - } + /// @dev Takes _currency; + /// gets current price point and token decimal for the priceOracle for the give currency; + /// Public method + /// @param _currency currency + /// @return (currentPrice, TokenDecimals) + function getPricePoint( + bytes3 _currency) + public + returns (uint256, uint8) /* pricePoint, TokenDecimal*/ + { + require(_currency != ""); + PriceOracleInterface currentPriceOracle = PriceOracleInterface(pricerPriceOracles[_currency]); + require(currentPriceOracle != address(0)); + return (currentPriceOracle.getPrice(), currentPriceOracle.tokenDecimals()); + } + + /// @dev Takes _intendedPricePoint, _currentPricePoint, _acceptedMargin; + /// Checks if the current price point is in the acceptable range of intendedPricePoint; + /// Private method + /// @param _intendedPricePoint intendedPricePoint + /// @param _currentPricePoint currentPricePoint + /// @param _acceptedMargin acceptedMargin + /// @return bool isValid + function isPricePointInRange( + uint256 _intendedPricePoint, + uint256 _currentPricePoint, + uint64 _acceptedMargin) + private + pure + returns (bool /*isValid*/) + { + bool isValid = true; + if (_intendedPricePoint >= _acceptedMargin) { + isValid = SafeMath.sub(_intendedPricePoint, _acceptedMargin) <= _currentPricePoint; + } + if (isValid) { + isValid = _currentPricePoint <= SafeMath.add(_intendedPricePoint, _acceptedMargin); + } + return isValid; + } + + /// @dev Takes _pricePoint, _tokenDecimals, _transferAmount, _commissionAmount; + /// Calculated the number of branded token equivalant to the currency amount; + /// Private method + /// @param _pricePoint pricePoint + /// @param _tokenDecimals tokenDecimals + /// @param _transferAmount transferAmount + /// @param _commissionAmount commissionAmount + /// @return (amountBT,commissionAmountBT) + function getBTAmountFromCurrencyValue(uint256 _pricePoint, + uint8 _tokenDecimals, + uint256 _transferAmount, + uint256 _commissionAmount) + private + view + returns (uint256, uint256) /* number of BT ,number of commission BT */ + { + uint256 conversionRate = UtilityTokenInterface(pricerBrandedToken).conversionRate(); + require(conversionRate > 0); + uint256 adjConversionRate = SafeMath.mul(conversionRate, 10**uint256(_tokenDecimals)); + uint256 amountBT = SafeMath.div(SafeMath.mul(_transferAmount, adjConversionRate), _pricePoint); + uint256 commissionAmountBT = SafeMath.div(SafeMath.mul(_commissionAmount, adjConversionRate), _pricePoint); + return (amountBT, commissionAmountBT); + } } diff --git a/contracts/PricerInterface.sol b/contracts/PricerInterface.sol index ee84eee..017aa84 100644 --- a/contracts/PricerInterface.sol +++ b/contracts/PricerInterface.sol @@ -23,122 +23,125 @@ pragma solidity ^0.4.17; contract PricerInterface { - event Payment(address _beneficiary, - uint256 _transferAmount, - address _commissionBeneficiary, - uint256 _commissionAmount, - bytes3 _currency, - uint256 _intendedPricePoint, - uint256 _actualPricePoint); + event Payment(address _beneficiary, + uint256 _transferAmount, + address _commissionBeneficiary, + uint256 _commissionAmount, + bytes3 _currency, + uint256 _intendedPricePoint, + uint256 _actualPricePoint); - event PriceOracleSet( - bytes3 _currency, - address _address); - - event PriceOracleUnset( - bytes3 _currency); - - event AcceptedMargin( - bytes3 _currency, - uint64 relativeIntendedPriceRange); + event PriceOracleSet( + bytes3 _currency, + address _address); + + event PriceOracleUnset( + bytes3 _currency); - /// @dev Returns address of the branded token; - /// Public; - /// @return address - function brandedToken() - public - returns (address); + event AcceptedMargin( + bytes3 _currency, + uint64 relativeIntendedPriceRange); - /// @dev Takes _currency; - /// Returns Acceptable margin for the given currency; - /// Public; - /// @param _currency currency - /// @return uint64 margin - function acceptedMargins( - bytes3 _currency) - public - returns (uint64); + /// @dev Returns address of the branded token; + /// Public; + /// @return address + function brandedToken() + public + returns (address); - /// @dev Takes _currency; - /// Returns address of Price Oracle for the given currency; - /// Public - /// @param _currency currency - /// @return address - function priceOracles( - bytes3 _currency) - public - returns (address); + /// @dev Takes _currency; + /// Returns Acceptable margin for the given currency; + /// Public; + /// @param _currency currency + /// @return uint64 margin + function acceptedMargins( + bytes3 _currency) + public + returns (uint64); - /// @dev Takes _currency, _oracleAddress; - /// Updated the Price Oracle address for a given currency; - /// Emits PriceOracleSet Event; - /// Only called by ops - /// @param _currency currency - /// @param _oracleAddress oracleAddress - /// @return bool isSuccess - function setPriceOracle( - bytes3 _currency, - address _oracleAddress) - public - returns (bool); + /// @dev Takes _currency; + /// Returns address of Price Oracle for the given currency; + /// Public + /// @param _currency currency + /// @return address + function priceOracles( + bytes3 _currency) + public + returns (address); - /// @dev Takes _currency; - /// Removes the Price Oracle address for a given currency - /// Emits PriceOracleUnSet Event; - /// Only called by ops - /// @param _currency currency - /// @return bool isSuccess - function unsetPriceOracle( - bytes3 _currency) - public - returns (bool); - + /// @dev Takes _currency, _oracleAddress; + /// Updated the Price Oracle address for a given currency; + /// Emits PriceOracleSet Event; + /// Only called by ops + /// @param _currency currency + /// @param _oracleAddress oracleAddress + /// @return bool isSuccess + function setPriceOracle( + bytes3 _currency, + address _oracleAddress) + public + returns (bool); - /// @dev Takes _currency, _acceptedMargin; - /// Updated the acceptable margin range for a given currency; - /// Emits AcceptedMargin Event; - /// Only called by ops - /// @param _currency currency - /// @param _acceptedMargin acceptedMargin - /// @return bool isSuccess - function setAcceptedMargin( - bytes3 _currency, - uint64 _acceptedMargin) - public - returns (bool); + /// @dev Takes _currency; + /// Removes the Price Oracle address for a given currency + /// Emits PriceOracleUnSet Event; + /// Only called by ops + /// @param _currency currency + /// @return bool isSuccess + function unsetPriceOracle( + bytes3 _currency) + public + returns (bool); + + /// @dev Takes _currency, _acceptedMargin; + /// Updated the acceptable margin range for a given currency; + /// Emits AcceptedMargin Event; + /// Only called by ops + /// @param _currency currency + /// @param _acceptedMargin acceptedMargin + /// @return bool isSuccess + function setAcceptedMargin( + bytes3 _currency, + uint64 _acceptedMargin) + public + returns (bool); - /// @dev Takes _beneficiary, _transferAmount, _commissionBeneficiary, _commissionAmount, _currency, _intendedPricePoint; - /// Validates if the currentPrice from PriceOracle is in accepatble margin of _intendedPricePoint (If _ currency is not 0); - /// If _currency is 0 then it transfer the Branded tokens equal to _transferAmount to _beneficiary and Branded tokens equal to _commissionAmount to _commissionBeneficiary (Floating value transaction); - /// If _currency is not 0 then it transfer the Branded tokens equivalant to _transferAmount in currecncy value to _beneficiary and Branded tokens equivalant to _commissionAmount in currency value to _commissionBeneficiary (Fixed value transaction); - /// Emits Payment Event; - /// Public method - /// @param _beneficiary beneficiary - /// @param _transferAmount transferAmount - /// @param _commissionBeneficiary commissionBeneficiary - /// @param _commissionAmount commissionAmount - /// @param _currency currency - /// @param _intendedPricePoint _intendedPricePoint - /// @return bool isSuccess - function pay( - address _beneficiary, - uint256 _transferAmount, - address _commissionBeneficiary, - uint256 _commissionAmount, - bytes3 _currency, - uint256 _intendedPricePoint) - public - returns (bool); + /// @dev Takes _beneficiary, _transferAmount, _commissionBeneficiary, _commissionAmount, + /// _currency, _intendedPricePoint;Validates if the currentPrice from PriceOracle is + /// in accepatble margin of _intendedPricePoint (If _ currency is not 0) + /// If _currency is 0 then it transfer the Branded tokens equal to _transferAmount + /// to _beneficiary and Branded tokens equal to _commissionAmount to _commissionBeneficiary + /// (Floating value transaction); If _currency is not 0 then it transfer the Branded tokens + /// equivalant to _transferAmount in currency value to _beneficiary and Branded tokens + /// equivalant to _commissionAmount in currency value to _commissionBeneficiary + /// (Fixed value transaction); Emits Payment Event; + /// Public method + /// @param _beneficiary beneficiary + /// @param _transferAmount transferAmount + /// @param _commissionBeneficiary commissionBeneficiary + /// @param _commissionAmount commissionAmount + /// @param _currency currency + /// @param _intendedPricePoint _intendedPricePoint + /// @return bool isSuccess + function pay( + address _beneficiary, + uint256 _transferAmount, + address _commissionBeneficiary, + uint256 _commissionAmount, + bytes3 _currency, + uint256 _intendedPricePoint) + public + returns (bool); - /// @dev Takes _currency; - /// gets current price point and token decimal for the priceOracle for the give currency; - /// Public method - /// @param _currency currency - /// @return (currentPrice, TokenDecimals) - function getPricePoint( - bytes3 _currency) - public - returns (uint256, uint8); + /// @dev Takes _currency; + /// gets current price point and token decimal for the priceOracle for the give currency; + /// Public method + /// @param _currency currency + /// @return (currentPrice, TokenDecimals) + function getPricePoint( + bytes3 _currency) + public + returns (uint256, uint8); } \ No newline at end of file From 00dc4495f672b93fda8a0f9564519a8a01b38730 Mon Sep 17 00:00:00 2001 From: deepesh KN Date: Mon, 22 Jan 2018 19:10:23 +0530 Subject: [PATCH 12/21] Contract: comment corrections and removed the event declaration from Pricer.sol --- contracts/Pricer.sol | 92 +++++++++++++---------------------- contracts/PricerInterface.sol | 79 +++++++++++++++++------------- 2 files changed, 79 insertions(+), 92 deletions(-) diff --git a/contracts/Pricer.sol b/contracts/Pricer.sol index 46e1ef5..5fed457 100644 --- a/contracts/Pricer.sol +++ b/contracts/Pricer.sol @@ -39,39 +39,12 @@ contract Pricer is OpsManaged, PricerInterface { ///BrandedToken address address private pricerBrandedToken; - ///currency to Margin mapping, Absolute +/- range in currency in which the price point will be accepted + ///currency to accepted margin mapping, absolute +/- range in currency in which the price point will be accepted mapping(bytes3 /* currency */ => uint64 /* margin */) private pricerAcceptedMargins; - ///currency to Price Oracles address mapping + ///currency to price oracles address mapping mapping(bytes3 /* currency */ => address /* price oracle address */) private pricerPriceOracles; - /* - * Events - */ - ///Event for PaymentComplete - event Payment( - address _beneficiary, - uint256 _transferAmount, - address _commissionBeneficiary, - uint256 _commissionAmount, - bytes3 _currency, - uint256 _intendedPricePoint, - uint256 _actualPricePoint); - - ///Event for priceOracles Updates for currency - event PriceOracleSet( - bytes3 _currency, - address _address); - - ///Event for priceOracles Delete - event PriceOracleUnset( - bytes3 _currency); - - ///Event for AcceptedMargin update for currency - event AcceptedMargin( - bytes3 _currency, - uint64 relativeIntendedPriceRange); - /* * Public functions */ @@ -84,7 +57,7 @@ contract Pricer is OpsManaged, PricerInterface { } /// @dev Returns address of the branded token; - /// Public; + /// public method; /// @return address function brandedToken() public @@ -94,8 +67,8 @@ contract Pricer is OpsManaged, PricerInterface { } /// @dev Takes _currency; - /// Returns Acceptable margin for the given currency; - /// Public; + /// returns acceptable margin for the given currency; + /// public method; /// @param _currency currency /// @return uint64 margin function acceptedMargins( @@ -107,8 +80,8 @@ contract Pricer is OpsManaged, PricerInterface { } /// @dev Takes _currency; - /// Returns address of Price Oracle for the given currency; - /// Public + /// returns address of price oracle for the given currency; + /// public method; /// @param _currency currency /// @return address function priceOracles( @@ -120,9 +93,10 @@ contract Pricer is OpsManaged, PricerInterface { } /// @dev Takes _currency, _oracleAddress; - /// Updated the Price Oracle address for a given currency - /// Emits PriceOracleSet Event; - /// Only called by ops + /// updates the price oracle address for a given currency; + /// emits PriceOracleSet event; + /// only called by ops; + /// public method; /// @param _currency currency /// @param _oracleAddress oracleAddress /// @return bool isSuccess @@ -143,9 +117,10 @@ contract Pricer is OpsManaged, PricerInterface { } /// @dev Takes _currency; - /// Removes the Price Oracle address for a given currency - /// Emits PriceOracleUnSet Event; - /// Only called by ops + /// removes the price oracle address for a given currency; + /// emits PriceOracleUnSet event; + /// only called by ops; + /// public method; /// @param _currency currency /// @return bool isSuccess function unsetPriceOracle( @@ -163,9 +138,10 @@ contract Pricer is OpsManaged, PricerInterface { } /// @dev Takes _currency, _acceptedMargin; - /// Updated the acceptable margin range for a given currency - /// Emits AcceptedMargin Event; - /// Only called by ops + /// updates the acceptable margin range for a given currency; + /// emits AcceptedMargin event; + /// only called by ops; + /// public method; /// @param _currency currency /// @param _acceptedMargin acceptedMargin /// @return bool isSuccess @@ -177,21 +153,21 @@ contract Pricer is OpsManaged, PricerInterface { returns (bool /* success */) { pricerAcceptedMargins[_currency] = _acceptedMargin; - // Trigger Event for Intended Price Acceptable Range Update + // Trigger AcceptedMargin event AcceptedMargin(_currency, _acceptedMargin); return true; } /// @dev Takes _beneficiary, _transferAmount, _commissionBeneficiary, _commissionAmount, - /// _currency, _intendedPricePoint;Validates if the currentPrice from PriceOracle is - /// in accepatble margin of _intendedPricePoint (If _ currency is not 0) - /// If _currency is 0 then it transfer the Branded tokens equal to _transferAmount - /// to _beneficiary and Branded tokens equal to _commissionAmount to _commissionBeneficiary - /// (Floating value transaction); If _currency is not 0 then it transfer the Branded tokens - /// equivalant to _transferAmount in currency value to _beneficiary and Branded tokens + /// _currency, _intendedPricePoint;Validates if the currentPrice from price oracle is + /// in accepatble margin of _intendedPricePoint (if _ currency is not 0) + /// if _currency is 0 then it transfer the branded tokens equal to _transferAmount + /// to _beneficiary and branded tokens equal to _commissionAmount to _commissionBeneficiary + /// (floating value transaction); if _currency is not 0 then it transfer the branded tokens + /// equivalant to _transferAmount in currency value to _beneficiary and branded tokens /// equivalant to _commissionAmount in currency value to _commissionBeneficiary - /// (Fixed value transaction); Emits Payment Event; - /// Public method + /// (fixed value transaction); emits payment event; + /// public method /// @param _beneficiary beneficiary /// @param _transferAmount transferAmount /// @param _commissionBeneficiary commissionBeneficiary @@ -241,8 +217,8 @@ contract Pricer is OpsManaged, PricerInterface { } /// @dev Takes _currency; - /// gets current price point and token decimal for the priceOracle for the give currency; - /// Public method + /// gets current price point and token decimal for the price oracle for the give currency; + /// public method; /// @param _currency currency /// @return (currentPrice, TokenDecimals) function getPricePoint( @@ -257,8 +233,8 @@ contract Pricer is OpsManaged, PricerInterface { } /// @dev Takes _intendedPricePoint, _currentPricePoint, _acceptedMargin; - /// Checks if the current price point is in the acceptable range of intendedPricePoint; - /// Private method + /// checks if the current price point is in the acceptable range of intendedPricePoint; + /// private method; /// @param _intendedPricePoint intendedPricePoint /// @param _currentPricePoint currentPricePoint /// @param _acceptedMargin acceptedMargin @@ -282,8 +258,8 @@ contract Pricer is OpsManaged, PricerInterface { } /// @dev Takes _pricePoint, _tokenDecimals, _transferAmount, _commissionAmount; - /// Calculated the number of branded token equivalant to the currency amount; - /// Private method + /// calculates the number of branded token equivalant to the currency amount; + /// private method; /// @param _pricePoint pricePoint /// @param _tokenDecimals tokenDecimals /// @param _transferAmount transferAmount diff --git a/contracts/PricerInterface.sol b/contracts/PricerInterface.sol index 017aa84..11eea76 100644 --- a/contracts/PricerInterface.sol +++ b/contracts/PricerInterface.sol @@ -23,35 +23,43 @@ pragma solidity ^0.4.17; contract PricerInterface { - event Payment(address _beneficiary, - uint256 _transferAmount, - address _commissionBeneficiary, - uint256 _commissionAmount, - bytes3 _currency, - uint256 _intendedPricePoint, + /* + * Events + */ + ///Event for payment complete + event Payment( + address _beneficiary, + uint256 _transferAmount, + address _commissionBeneficiary, + uint256 _commissionAmount, + bytes3 _currency, + uint256 _intendedPricePoint, uint256 _actualPricePoint); - - event PriceOracleSet( - bytes3 _currency, + + ///Event for price oracles updates for currency + event PriceOracleSet( + bytes3 _currency, address _address); + ///Event for price oracles delete event PriceOracleUnset( bytes3 _currency); + ///Event for accepted margin update for currency event AcceptedMargin( - bytes3 _currency, + bytes3 _currency, uint64 relativeIntendedPriceRange); /// @dev Returns address of the branded token; - /// Public; + /// public method; /// @return address function brandedToken() public returns (address); /// @dev Takes _currency; - /// Returns Acceptable margin for the given currency; - /// Public; + /// returns acceptable margin for the given currency; + /// public method; /// @param _currency currency /// @return uint64 margin function acceptedMargins( @@ -60,8 +68,8 @@ contract PricerInterface { returns (uint64); /// @dev Takes _currency; - /// Returns address of Price Oracle for the given currency; - /// Public + /// returns address of price oracle for the given currency; + /// public method; /// @param _currency currency /// @return address function priceOracles( @@ -70,9 +78,10 @@ contract PricerInterface { returns (address); /// @dev Takes _currency, _oracleAddress; - /// Updated the Price Oracle address for a given currency; - /// Emits PriceOracleSet Event; - /// Only called by ops + /// updates the price oracle address for a given currency; + /// emits PriceOracleSet event; + /// only called by ops; + /// public method; /// @param _currency currency /// @param _oracleAddress oracleAddress /// @return bool isSuccess @@ -83,9 +92,10 @@ contract PricerInterface { returns (bool); /// @dev Takes _currency; - /// Removes the Price Oracle address for a given currency - /// Emits PriceOracleUnSet Event; - /// Only called by ops + /// removes the price oracle address for a given currency; + /// emits PriceOracleUnSet event; + /// only called by ops; + /// public method; /// @param _currency currency /// @return bool isSuccess function unsetPriceOracle( @@ -94,9 +104,10 @@ contract PricerInterface { returns (bool); /// @dev Takes _currency, _acceptedMargin; - /// Updated the acceptable margin range for a given currency; - /// Emits AcceptedMargin Event; - /// Only called by ops + /// updates the acceptable margin range for a given currency; + /// emits AcceptedMargin event; + /// only called by ops; + /// public method; /// @param _currency currency /// @param _acceptedMargin acceptedMargin /// @return bool isSuccess @@ -107,15 +118,15 @@ contract PricerInterface { returns (bool); /// @dev Takes _beneficiary, _transferAmount, _commissionBeneficiary, _commissionAmount, - /// _currency, _intendedPricePoint;Validates if the currentPrice from PriceOracle is - /// in accepatble margin of _intendedPricePoint (If _ currency is not 0) - /// If _currency is 0 then it transfer the Branded tokens equal to _transferAmount - /// to _beneficiary and Branded tokens equal to _commissionAmount to _commissionBeneficiary - /// (Floating value transaction); If _currency is not 0 then it transfer the Branded tokens - /// equivalant to _transferAmount in currency value to _beneficiary and Branded tokens + /// _currency, _intendedPricePoint;Validates if the currentPrice from price oracle is + /// in accepatble margin of _intendedPricePoint (if _ currency is not 0) + /// if _currency is 0 then it transfer the branded tokens equal to _transferAmount + /// to _beneficiary and branded tokens equal to _commissionAmount to _commissionBeneficiary + /// (floating value transaction); if _currency is not 0 then it transfer the branded tokens + /// equivalant to _transferAmount in currency value to _beneficiary and branded tokens /// equivalant to _commissionAmount in currency value to _commissionBeneficiary - /// (Fixed value transaction); Emits Payment Event; - /// Public method + /// (fixed value transaction); emits payment event; + /// public method /// @param _beneficiary beneficiary /// @param _transferAmount transferAmount /// @param _commissionBeneficiary commissionBeneficiary @@ -134,8 +145,8 @@ contract PricerInterface { returns (bool); /// @dev Takes _currency; - /// gets current price point and token decimal for the priceOracle for the give currency; - /// Public method + /// gets current price point and token decimal for the price oracle for the give currency; + /// public method; /// @param _currency currency /// @return (currentPrice, TokenDecimals) function getPricePoint( From 8f7e8a71dcdb15a656f1422fa24cee75c91e0586 Mon Sep 17 00:00:00 2001 From: deepesh KN Date: Mon, 22 Jan 2018 20:26:56 +0530 Subject: [PATCH 13/21] Contract: Pull request changes --- contracts/Pricer.sol | 8 ++++---- contracts/PricerInterface.sol | 6 +++--- .../ost-price-oracle/PriceOracleInterface.sol | 20 +++++++++---------- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/contracts/Pricer.sol b/contracts/Pricer.sol index 5fed457..f0e67fd 100644 --- a/contracts/Pricer.sol +++ b/contracts/Pricer.sol @@ -153,8 +153,8 @@ contract Pricer is OpsManaged, PricerInterface { returns (bool /* success */) { pricerAcceptedMargins[_currency] = _acceptedMargin; - // Trigger AcceptedMargin event - AcceptedMargin(_currency, _acceptedMargin); + // Trigger AcceptedMarginSet event + AcceptedMarginSet(_currency, _acceptedMargin); return true; } @@ -220,11 +220,11 @@ contract Pricer is OpsManaged, PricerInterface { /// gets current price point and token decimal for the price oracle for the give currency; /// public method; /// @param _currency currency - /// @return (currentPrice, TokenDecimals) + /// @return (currentPrice, tokenDecimals) function getPricePoint( bytes3 _currency) public - returns (uint256, uint8) /* pricePoint, TokenDecimal*/ + returns (uint256, uint8) /* pricePoint, tokenDecimals*/ { require(_currency != ""); PriceOracleInterface currentPriceOracle = PriceOracleInterface(pricerPriceOracles[_currency]); diff --git a/contracts/PricerInterface.sol b/contracts/PricerInterface.sol index 11eea76..7566740 100644 --- a/contracts/PricerInterface.sol +++ b/contracts/PricerInterface.sol @@ -46,9 +46,9 @@ contract PricerInterface { bytes3 _currency); ///Event for accepted margin update for currency - event AcceptedMargin( + event AcceptedMarginSet( bytes3 _currency, - uint64 relativeIntendedPriceRange); + uint64 _acceptedMargin); /// @dev Returns address of the branded token; /// public method; @@ -148,7 +148,7 @@ contract PricerInterface { /// gets current price point and token decimal for the price oracle for the give currency; /// public method; /// @param _currency currency - /// @return (currentPrice, TokenDecimals) + /// @return (currentPrice, tokenDecimals) function getPricePoint( bytes3 _currency) public diff --git a/contracts/ost-price-oracle/PriceOracleInterface.sol b/contracts/ost-price-oracle/PriceOracleInterface.sol index 509b0b9..5b9d6e0 100644 --- a/contracts/ost-price-oracle/PriceOracleInterface.sol +++ b/contracts/ost-price-oracle/PriceOracleInterface.sol @@ -22,12 +22,11 @@ pragma solidity ^0.4.17; // -------------------------- /// @title PriceOracleInterface - Interface of PriceOracle contract -contract PriceOracleInterface{ +contract PriceOracleInterface { /* * Events */ - /// @dev event emitted whenever price is updated /// @return _price /// @return _expirationHeight @@ -41,6 +40,14 @@ contract PriceOracleInterface{ /* * Functions */ + /// @dev use this function to update oracle price + /// @param _price price + /// @return expirationHeight + function setPrice( + uint256 _price) + external + returns( + uint256); /// @dev Price is stored as fixed point integer value similar as wei unit. /// Use this variable in case decimal value need to be evaluated @@ -83,15 +90,6 @@ contract PriceOracleInterface{ returns( bytes3); - /// @dev use this function to update oracle price - /// @param _price price - /// @return expirationHeight - function setPrice( - uint256 _price) - external - returns( - uint256); - /// @dev use this function to get price /// @return quoteCurrency/baseCurrency value function getPrice() From 165af47810b46c33ed0cac63955f1bcc97cd2405 Mon Sep 17 00:00:00 2001 From: Jason Banks Date: Mon, 29 Jan 2018 14:49:07 +0100 Subject: [PATCH 14/21] Add EIP20TokenMock to facilitate testing payments functionality. Relates to #12 --- contracts/EIP20TokenMock.sol | 84 +++++++++++++++ contracts/openst-protocol/EIP20Token.sol | 132 +++++++++++++++++++++++ 2 files changed, 216 insertions(+) create mode 100644 contracts/EIP20TokenMock.sol create mode 100644 contracts/openst-protocol/EIP20Token.sol diff --git a/contracts/EIP20TokenMock.sol b/contracts/EIP20TokenMock.sol new file mode 100644 index 0000000..71851f6 --- /dev/null +++ b/contracts/EIP20TokenMock.sol @@ -0,0 +1,84 @@ +/* solhint-disable-next-line compiler-fixed */ +pragma solidity ^0.4.17; + +// Copyright 2018 OpenST Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ---------------------------------------------------------------------------- +// Utility chain: EIP20TokenMock +// +// http://www.simpletoken.org/ +// +// ---------------------------------------------------------------------------- + + +import "./openst-protocol/EIP20Token.sol"; + + +/// @title EIP20TokenMock - Provides EIP20Token with mock functionality to facilitate testing payments +contract EIP20TokenMock is EIP20Token { + uint256 public conversionRate; + + /// @dev Takes _conversionRate, _symbol, _name, _decimals + /// @param _conversionRate conversionRate + /// @param _symbol symbol + /// @param _name name + /// @param _decimals decimals + function EIP20TokenMock( + uint256 _conversionRate, + string _symbol, + string _name, + uint8 _decimals) + /* solhint-disable-next-line visibility-modifier-order */ + EIP20Token(_symbol, _name, _decimals) + public + { + conversionRate = _conversionRate; + } + + /// @dev Returns 0 as mock total supply + function totalSupply() + public + view + returns (uint256 /* mock total supply */) + { + return 0; + } + + /// @dev Takes _owner, _value; sets balance of _owner to _value + /// @param _owner owner + /// @param _value value + /// @return bool success + function setBalance( + address _owner, + uint256 _value) + public + returns (bool /* success */) + { + balances[_owner] = _value; + return true; + } + + /// @dev Takes _conversionRate; sets conversionRate to _conversionRate + /// @param _conversionRate conversionRate + /// @return bool success + function setConverionRate( + uint256 _conversionRate) + public + returns (bool /* success */) + { + conversionRate = _conversionRate; + return true; + } +} diff --git a/contracts/openst-protocol/EIP20Token.sol b/contracts/openst-protocol/EIP20Token.sol new file mode 100644 index 0000000..bf64bdd --- /dev/null +++ b/contracts/openst-protocol/EIP20Token.sol @@ -0,0 +1,132 @@ +pragma solidity ^0.4.17; + +// Copyright 2017 OpenST Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ---------------------------------------------------------------------------- +// Utility chain: EIP20 Token Implementation +// +// http://www.simpletoken.org/ +// +// ---------------------------------------------------------------------------- + +import "./EIP20Interface.sol"; +import "../SafeMath.sol"; + +/** + @title EIP20Token + @notice Implements EIP20 token +*/ +contract EIP20Token is EIP20Interface { + using SafeMath for uint256; + + string private tokenName; + string private tokenSymbol; + uint8 private tokenDecimals; + + mapping(address => uint256) balances; + mapping(address => mapping (address => uint256)) allowed; + + + function EIP20Token(string _symbol, string _name, uint8 _decimals) public + { + tokenSymbol = _symbol; + tokenName = _name; + tokenDecimals = _decimals; + } + + + function name() public view returns (string) { + return tokenName; + } + + + function symbol() public view returns (string) { + return tokenSymbol; + } + + + function decimals() public view returns (uint8) { + return tokenDecimals; + } + + + function balanceOf(address _owner) public view returns (uint256) { + return balances[_owner]; + } + + + function allowance(address _owner, address _spender) public view returns (uint256 remaining) { + return allowed[_owner][_spender]; + } + + + function transfer(address _to, uint256 _value) public returns (bool success) { + // According to the EIP20 spec, "transfers of 0 values MUST be treated as normal + // transfers and fire the Transfer event". + // Also, should throw if not enough balance. This is taken care of by SafeMath. + balances[msg.sender] = balances[msg.sender].sub(_value); + balances[_to] = balances[_to].add(_value); + + Transfer(msg.sender, _to, _value); + + return true; + } + + + function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { + balances[_from] = balances[_from].sub(_value); + allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); + balances[_to] = balances[_to].add(_value); + + Transfer(_from, _to, _value); + + return true; + } + + + function approve(address _spender, uint256 _value) public returns (bool success) { + + allowed[msg.sender][_spender] = _value; + + Approval(msg.sender, _spender, _value); + + return true; + } + + + function claimEIP20(address _beneficiary, uint256 _amount) internal returns (bool success) { + // claimable tokens are minted in the contract address to be pulled on claim + balances[address(this)] = balances[address(this)].sub(_amount); + balances[_beneficiary] = balances[_beneficiary].add(_amount); + + Transfer(address(this), _beneficiary, _amount); + + return true; + } + + + function mintEIP20(uint256 _amount) internal returns (bool /* success */) { + // mint EIP20 tokens in contract address for them to be claimed + balances[address(this)] = balances[address(this)].add(_amount); + + return true; + } + + function burnEIP20(uint256 _amount) internal returns (bool /* success */) { + balances[msg.sender] = balances[msg.sender].sub(_amount); + + return true; + } +} From 4a75a9c090946421876cc99057d9fab2e84da559 Mon Sep 17 00:00:00 2001 From: deepesh KN Date: Tue, 30 Jan 2018 20:40:27 +0530 Subject: [PATCH 15/21] Contract: Issue 20, 21, 23 --- contracts/Pricer.sol | 91 +++++++++++++++++++++++++++++++---- contracts/PricerInterface.sol | 40 +++++++++++++-- 2 files changed, 118 insertions(+), 13 deletions(-) diff --git a/contracts/Pricer.sol b/contracts/Pricer.sol index f0e67fd..89d81ac 100644 --- a/contracts/Pricer.sol +++ b/contracts/Pricer.sol @@ -45,15 +45,32 @@ contract Pricer is OpsManaged, PricerInterface { ///currency to price oracles address mapping mapping(bytes3 /* currency */ => address /* price oracle address */) private pricerPriceOracles; + /// specifies the base currency value e.g. "OST" + bytes3 private pricerBaseCurrency; + + /// Pricer decimal + uint8 private pricerDecimals; + + /// conversionRate + uint256 private pricerConversionRate; + /* * Public functions */ + /// @dev Takes _brandedToken, _baseCurrency; + /// constructor; + /// public method; + /// @param _brandedToken _brandedToken + /// @param _baseCurrency _baseCurrency function Pricer( - address _brandedToken) + address _brandedToken, + bytes3 _baseCurrency) public OpsManaged() { pricerBrandedToken = _brandedToken; + pricerBaseCurrency = _baseCurrency; + pricerDecimals = EIP20Interface(pricerBrandedToken).decimals(); } /// @dev Returns address of the branded token; @@ -92,6 +109,36 @@ contract Pricer is OpsManaged, PricerInterface { return pricerPriceOracles[_currency]; } + /// @dev Returns address of the base currency; + /// public method; + /// @return bytes3 + function baseCurrency() + public + returns (bytes3) + { + return pricerBaseCurrency; + } + + /// @dev Returns pricer decimal; + /// public method; + /// @return bytes3 + function decimals() + public + returns (uint8) + { + return pricerDecimals; + } + + /// @dev Returns conversion rate; + /// public method; + /// @return bytes3 + function conversionRate() + public + returns (uint256) + { + return pricerConversionRate; + } + /// @dev Takes _currency, _oracleAddress; /// updates the price oracle address for a given currency; /// emits PriceOracleSet event; @@ -109,6 +156,8 @@ contract Pricer is OpsManaged, PricerInterface { { require(_oracleAddress != address(0)); require(_currency != ""); + require(PriceOracleInterface(_oracleAddress).baseCurrency() == pricerBaseCurrency); + require(PriceOracleInterface(_oracleAddress).tokenDecimals() == pricerDecimals); pricerPriceOracles[_currency] = _oracleAddress; //Trigger PriceOracleSet event @@ -158,6 +207,32 @@ contract Pricer is OpsManaged, PricerInterface { return true; } + /// @dev Takes _transferAmount, _commissionAmount, _currency; + /// public method + /// @param _transferAmount transferAmount + /// @param _commissionAmount commissionAmount + /// @param _currency currency + /// @return (pricePoint, calculatedTransferAmount, calculatedCommissionAmount) + function getPricePointAndCalculatedAmount( + uint256 _transferAmount, + uint256 _commissionAmount, + bytes3 _currency) + public + returns (uint256, uint256, uint256) /* pricePoint, calculated transfer amount, calculated commission amount*/ + { + uint256 tokenAmount = _transferAmount; + uint256 commissionTokenAmount = _commissionAmount; + uint256 pricePoint = 0; + if (_currency != 0) { + uint8 tokenDecimals = 0; + (pricePoint, tokenDecimals) = getPricePoint(_currency); + require(pricePoint > 0); + (tokenAmount, commissionTokenAmount) = getBTAmountFromCurrencyValue(pricePoint, + _transferAmount, _commissionAmount); + } + return (pricePoint, tokenAmount, commissionTokenAmount); + } + /// @dev Takes _beneficiary, _transferAmount, _commissionBeneficiary, _commissionAmount, /// _currency, _intendedPricePoint;Validates if the currentPrice from price oracle is /// in accepatble margin of _intendedPricePoint (if _ currency is not 0) @@ -198,10 +273,10 @@ contract Pricer is OpsManaged, PricerInterface { if (_currency != 0) { uint8 tokenDecimals = 0; (pricePoint, tokenDecimals) = getPricePoint(_currency); - require(pricePoint > 0); + require(pricePoint > 0); require(isPricePointInRange(_intendedPricePoint, pricePoint, pricerAcceptedMargins[_currency])); (tokenAmount, commissionTokenAmount) = getBTAmountFromCurrencyValue(pricePoint, - tokenDecimals, _transferAmount, _commissionAmount); + _transferAmount, _commissionAmount); } require(EIP20Interface(pricerBrandedToken).transferFrom(msg.sender, _beneficiary, tokenAmount)); @@ -217,7 +292,7 @@ contract Pricer is OpsManaged, PricerInterface { } /// @dev Takes _currency; - /// gets current price point and token decimal for the price oracle for the give currency; + /// gets current price point for the price oracle for the give currency; /// public method; /// @param _currency currency /// @return (currentPrice, tokenDecimals) @@ -257,25 +332,21 @@ contract Pricer is OpsManaged, PricerInterface { return isValid; } - /// @dev Takes _pricePoint, _tokenDecimals, _transferAmount, _commissionAmount; + /// @dev Takes _pricePoint, _transferAmount, _commissionAmount; /// calculates the number of branded token equivalant to the currency amount; /// private method; /// @param _pricePoint pricePoint - /// @param _tokenDecimals tokenDecimals /// @param _transferAmount transferAmount /// @param _commissionAmount commissionAmount /// @return (amountBT,commissionAmountBT) function getBTAmountFromCurrencyValue(uint256 _pricePoint, - uint8 _tokenDecimals, uint256 _transferAmount, uint256 _commissionAmount) private view returns (uint256, uint256) /* number of BT ,number of commission BT */ { - uint256 conversionRate = UtilityTokenInterface(pricerBrandedToken).conversionRate(); - require(conversionRate > 0); - uint256 adjConversionRate = SafeMath.mul(conversionRate, 10**uint256(_tokenDecimals)); + uint256 adjConversionRate = SafeMath.mul(pricerConversionRate, 10**uint256(pricerDecimals)); uint256 amountBT = SafeMath.div(SafeMath.mul(_transferAmount, adjConversionRate), _pricePoint); uint256 commissionAmountBT = SafeMath.div(SafeMath.mul(_commissionAmount, adjConversionRate), _pricePoint); return (amountBT, commissionAmountBT); diff --git a/contracts/PricerInterface.sol b/contracts/PricerInterface.sol index 7566740..8ba4a82 100644 --- a/contracts/PricerInterface.sol +++ b/contracts/PricerInterface.sol @@ -77,6 +77,27 @@ contract PricerInterface { public returns (address); + /// @dev Returns address of the base currency; + /// public method; + /// @return bytes3 + function baseCurrency() + public + returns (bytes3); + + /// @dev Returns pricer decimal; + /// public method; + /// @return bytes3 + function decimals() + public + returns (uint8); + + /// @dev Returns conversion rate; + /// public method; + /// @return bytes3 + function conversionRate() + public + returns (uint256); + /// @dev Takes _currency, _oracleAddress; /// updates the price oracle address for a given currency; /// emits PriceOracleSet event; @@ -115,7 +136,20 @@ contract PricerInterface { bytes3 _currency, uint64 _acceptedMargin) public - returns (bool); + returns (bool); + + /// @dev Takes _transferAmount, _commissionAmount, _currency; + /// public method + /// @param _transferAmount transferAmount + /// @param _commissionAmount commissionAmount + /// @param _currency currency + /// @return (pricePoint, calculatedTransferAmount, calculatedCommissionAmount) + function getPricePointAndCalculatedAmount( + uint256 _transferAmount, + uint256 _commissionAmount, + bytes3 _currency) + public + returns (uint256, uint256, uint256); /// @dev Takes _beneficiary, _transferAmount, _commissionBeneficiary, _commissionAmount, /// _currency, _intendedPricePoint;Validates if the currentPrice from price oracle is @@ -145,10 +179,10 @@ contract PricerInterface { returns (bool); /// @dev Takes _currency; - /// gets current price point and token decimal for the price oracle for the give currency; + /// gets current price point for the price oracle for the give currency; /// public method; /// @param _currency currency - /// @return (currentPrice, tokenDecimals) + /// @return (currentPrice) function getPricePoint( bytes3 _currency) public From 87e0447098ee9df1bec5fe6cd1e956421febc704 Mon Sep 17 00:00:00 2001 From: deepesh KN Date: Tue, 30 Jan 2018 20:45:51 +0530 Subject: [PATCH 16/21] Contract: Comment reverted --- contracts/PricerInterface.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/PricerInterface.sol b/contracts/PricerInterface.sol index 8ba4a82..4510efa 100644 --- a/contracts/PricerInterface.sol +++ b/contracts/PricerInterface.sol @@ -179,10 +179,10 @@ contract PricerInterface { returns (bool); /// @dev Takes _currency; - /// gets current price point for the price oracle for the give currency; + /// gets current price point and token decimal for the price oracle for the give currency; /// public method; /// @param _currency currency - /// @return (currentPrice) + /// @return (currentPrice, tokenDecimals) function getPricePoint( bytes3 _currency) public From 3696ad25587e42ee2f32366d56319841af819570 Mon Sep 17 00:00:00 2001 From: deepesh KN Date: Tue, 30 Jan 2018 20:56:40 +0530 Subject: [PATCH 17/21] Contract: changed getPricePoint function to return only price point --- contracts/Pricer.sol | 12 +++++------- contracts/PricerInterface.sol | 6 +++--- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/contracts/Pricer.sol b/contracts/Pricer.sol index 89d81ac..8074bcf 100644 --- a/contracts/Pricer.sol +++ b/contracts/Pricer.sol @@ -224,8 +224,7 @@ contract Pricer is OpsManaged, PricerInterface { uint256 commissionTokenAmount = _commissionAmount; uint256 pricePoint = 0; if (_currency != 0) { - uint8 tokenDecimals = 0; - (pricePoint, tokenDecimals) = getPricePoint(_currency); + pricePoint = getPricePoint(_currency); require(pricePoint > 0); (tokenAmount, commissionTokenAmount) = getBTAmountFromCurrencyValue(pricePoint, _transferAmount, _commissionAmount); @@ -271,8 +270,7 @@ contract Pricer is OpsManaged, PricerInterface { uint256 commissionTokenAmount = _commissionAmount; uint256 pricePoint = _intendedPricePoint; if (_currency != 0) { - uint8 tokenDecimals = 0; - (pricePoint, tokenDecimals) = getPricePoint(_currency); + pricePoint = getPricePoint(_currency); require(pricePoint > 0); require(isPricePointInRange(_intendedPricePoint, pricePoint, pricerAcceptedMargins[_currency])); (tokenAmount, commissionTokenAmount) = getBTAmountFromCurrencyValue(pricePoint, @@ -295,16 +293,16 @@ contract Pricer is OpsManaged, PricerInterface { /// gets current price point for the price oracle for the give currency; /// public method; /// @param _currency currency - /// @return (currentPrice, tokenDecimals) + /// @return (currentPrice) function getPricePoint( bytes3 _currency) public - returns (uint256, uint8) /* pricePoint, tokenDecimals*/ + returns (uint256) /* pricePoint */ { require(_currency != ""); PriceOracleInterface currentPriceOracle = PriceOracleInterface(pricerPriceOracles[_currency]); require(currentPriceOracle != address(0)); - return (currentPriceOracle.getPrice(), currentPriceOracle.tokenDecimals()); + return (currentPriceOracle.getPrice()); } /// @dev Takes _intendedPricePoint, _currentPricePoint, _acceptedMargin; diff --git a/contracts/PricerInterface.sol b/contracts/PricerInterface.sol index 4510efa..f2f28b6 100644 --- a/contracts/PricerInterface.sol +++ b/contracts/PricerInterface.sol @@ -179,14 +179,14 @@ contract PricerInterface { returns (bool); /// @dev Takes _currency; - /// gets current price point and token decimal for the price oracle for the give currency; + /// gets current price point for the price oracle for the give currency; /// public method; /// @param _currency currency - /// @return (currentPrice, tokenDecimals) + /// @return (currentPrice) function getPricePoint( bytes3 _currency) public - returns (uint256, uint8); + returns (uint256); } \ No newline at end of file From dd37bc381a96123ba15baeb9976915bad2b3c06a Mon Sep 17 00:00:00 2001 From: deepesh KN Date: Wed, 31 Jan 2018 16:38:55 +0530 Subject: [PATCH 18/21] Contract: PR changes --- contracts/Pricer.sol | 32 +++++++++++-------- contracts/PricerInterface.sol | 8 ++--- .../ost-price-oracle/PriceOracleInterface.sol | 6 ++-- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/contracts/Pricer.sol b/contracts/Pricer.sol index 8074bcf..493148a 100644 --- a/contracts/Pricer.sol +++ b/contracts/Pricer.sol @@ -43,7 +43,7 @@ contract Pricer is OpsManaged, PricerInterface { mapping(bytes3 /* currency */ => uint64 /* margin */) private pricerAcceptedMargins; ///currency to price oracles address mapping - mapping(bytes3 /* currency */ => address /* price oracle address */) private pricerPriceOracles; + mapping(bytes3 /* currency */ => PriceOracleInterface /* price oracle address */) private pricerPriceOracles; /// specifies the base currency value e.g. "OST" bytes3 private pricerBaseCurrency; @@ -68,9 +68,12 @@ contract Pricer is OpsManaged, PricerInterface { public OpsManaged() { + require(_brandedToken != address(0)); + require(_baseCurrency != ""); pricerBrandedToken = _brandedToken; pricerBaseCurrency = _baseCurrency; pricerDecimals = EIP20Interface(pricerBrandedToken).decimals(); + pricerConversionRate = UtilityTokenInterface(_brandedToken).conversionRate(); } /// @dev Returns address of the branded token; @@ -157,8 +160,9 @@ contract Pricer is OpsManaged, PricerInterface { require(_oracleAddress != address(0)); require(_currency != ""); require(PriceOracleInterface(_oracleAddress).baseCurrency() == pricerBaseCurrency); - require(PriceOracleInterface(_oracleAddress).tokenDecimals() == pricerDecimals); - pricerPriceOracles[_currency] = _oracleAddress; + require(PriceOracleInterface(_oracleAddress).quoteCurrency() == _currency); + require(PriceOracleInterface(_oracleAddress).decimals() == pricerDecimals); + pricerPriceOracles[_currency] = PriceOracleInterface(_oracleAddress); //Trigger PriceOracleSet event PriceOracleSet(_currency, _oracleAddress); @@ -178,7 +182,7 @@ contract Pricer is OpsManaged, PricerInterface { onlyOps returns (bool /* success */) { - require(pricerPriceOracles[_currency] != 0); + require(pricerPriceOracles[_currency] != address(0)); delete pricerPriceOracles[_currency]; //Trigger PriceOracleUnset event @@ -213,16 +217,19 @@ contract Pricer is OpsManaged, PricerInterface { /// @param _commissionAmount commissionAmount /// @param _currency currency /// @return (pricePoint, calculatedTransferAmount, calculatedCommissionAmount) - function getPricePointAndCalculatedAmount( + function getPricePointAndCalculatedAmounts( uint256 _transferAmount, uint256 _commissionAmount, bytes3 _currency) public - returns (uint256, uint256, uint256) /* pricePoint, calculated transfer amount, calculated commission amount*/ + returns ( + uint256 pricePoint, + uint256 tokenAmount, + uint256 commissionTokenAmount) { - uint256 tokenAmount = _transferAmount; - uint256 commissionTokenAmount = _commissionAmount; - uint256 pricePoint = 0; + tokenAmount = _transferAmount; + commissionTokenAmount = _commissionAmount; + pricePoint = 0; if (_currency != 0) { pricePoint = getPricePoint(_currency); require(pricePoint > 0); @@ -290,17 +297,16 @@ contract Pricer is OpsManaged, PricerInterface { } /// @dev Takes _currency; - /// gets current price point for the price oracle for the give currency; + /// gets current price point for the price oracle for the given currency; /// public method; /// @param _currency currency - /// @return (currentPrice) + /// @return (pricePoint) function getPricePoint( bytes3 _currency) public returns (uint256) /* pricePoint */ { - require(_currency != ""); - PriceOracleInterface currentPriceOracle = PriceOracleInterface(pricerPriceOracles[_currency]); + PriceOracleInterface currentPriceOracle = pricerPriceOracles[_currency]; require(currentPriceOracle != address(0)); return (currentPriceOracle.getPrice()); } diff --git a/contracts/PricerInterface.sol b/contracts/PricerInterface.sol index f2f28b6..3d4f703 100644 --- a/contracts/PricerInterface.sol +++ b/contracts/PricerInterface.sol @@ -143,8 +143,8 @@ contract PricerInterface { /// @param _transferAmount transferAmount /// @param _commissionAmount commissionAmount /// @param _currency currency - /// @return (pricePoint, calculatedTransferAmount, calculatedCommissionAmount) - function getPricePointAndCalculatedAmount( + /// @return (pricePoint, tokenAmount, commissionTokenAmount) + function getPricePointAndCalculatedAmounts( uint256 _transferAmount, uint256 _commissionAmount, bytes3 _currency) @@ -179,10 +179,10 @@ contract PricerInterface { returns (bool); /// @dev Takes _currency; - /// gets current price point for the price oracle for the give currency; + /// gets current price point for the price oracle for the given currency; /// public method; /// @param _currency currency - /// @return (currentPrice) + /// @return (pricePoint) function getPricePoint( bytes3 _currency) public diff --git a/contracts/ost-price-oracle/PriceOracleInterface.sol b/contracts/ost-price-oracle/PriceOracleInterface.sol index 5b9d6e0..663ca3e 100644 --- a/contracts/ost-price-oracle/PriceOracleInterface.sol +++ b/contracts/ost-price-oracle/PriceOracleInterface.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.17; -// Copyright 2018 OST.com Ltd. +// Copyright 2017 OST.com Ltd. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ contract PriceOracleInterface { event PriceUpdated(uint256 _price, uint256 _expirationHeight); - /// @dev event emitted when price expires + /// @dev event emitted if price has expired /// @return _expirationHeight event PriceExpired(uint256 _expirationHeight); @@ -52,7 +52,7 @@ contract PriceOracleInterface { /// @dev Price is stored as fixed point integer value similar as wei unit. /// Use this variable in case decimal value need to be evaluated /// @return token decimals - function tokenDecimals() + function decimals() public view returns( From 6d83089f6bad44c8f4b05dae883747266fbae4cd Mon Sep 17 00:00:00 2001 From: deepesh KN Date: Wed, 31 Jan 2018 16:54:13 +0530 Subject: [PATCH 19/21] Contract: Added require check for currency in getPricePointAndCalculatedAmounts --- contracts/Pricer.sol | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/contracts/Pricer.sol b/contracts/Pricer.sol index 493148a..f61124e 100644 --- a/contracts/Pricer.sol +++ b/contracts/Pricer.sol @@ -227,15 +227,11 @@ contract Pricer is OpsManaged, PricerInterface { uint256 tokenAmount, uint256 commissionTokenAmount) { - tokenAmount = _transferAmount; - commissionTokenAmount = _commissionAmount; - pricePoint = 0; - if (_currency != 0) { - pricePoint = getPricePoint(_currency); - require(pricePoint > 0); - (tokenAmount, commissionTokenAmount) = getBTAmountFromCurrencyValue(pricePoint, + require(_currency != 0); + pricePoint = getPricePoint(_currency); + require(pricePoint > 0); + (tokenAmount, commissionTokenAmount) = getBTAmountFromCurrencyValue(pricePoint, _transferAmount, _commissionAmount); - } return (pricePoint, tokenAmount, commissionTokenAmount); } From a4d5153440065e2e5bfd42a8134432c8208ecac6 Mon Sep 17 00:00:00 2001 From: deepesh KN Date: Thu, 1 Feb 2018 19:11:23 +0530 Subject: [PATCH 20/21] Contracts: changed uint64 to uint256 for acceptedMargin --- contracts/Pricer.sol | 13 +++++++------ contracts/PricerInterface.sol | 8 ++++---- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/contracts/Pricer.sol b/contracts/Pricer.sol index f61124e..574b375 100644 --- a/contracts/Pricer.sol +++ b/contracts/Pricer.sol @@ -40,7 +40,7 @@ contract Pricer is OpsManaged, PricerInterface { address private pricerBrandedToken; ///currency to accepted margin mapping, absolute +/- range in currency in which the price point will be accepted - mapping(bytes3 /* currency */ => uint64 /* margin */) private pricerAcceptedMargins; + mapping(bytes3 /* currency */ => uint256 /* margin */) private pricerAcceptedMargins; ///currency to price oracles address mapping mapping(bytes3 /* currency */ => PriceOracleInterface /* price oracle address */) private pricerPriceOracles; @@ -90,11 +90,11 @@ contract Pricer is OpsManaged, PricerInterface { /// returns acceptable margin for the given currency; /// public method; /// @param _currency currency - /// @return uint64 margin + /// @return uint256 margin function acceptedMargins( bytes3 _currency) public - returns (uint64) + returns (uint256) { return pricerAcceptedMargins[_currency]; } @@ -200,7 +200,7 @@ contract Pricer is OpsManaged, PricerInterface { /// @return bool isSuccess function setAcceptedMargin( bytes3 _currency, - uint64 _acceptedMargin) + uint256 _acceptedMargin) public onlyOps returns (bool /* success */) @@ -317,7 +317,7 @@ contract Pricer is OpsManaged, PricerInterface { function isPricePointInRange( uint256 _intendedPricePoint, uint256 _currentPricePoint, - uint64 _acceptedMargin) + uint256 _acceptedMargin) private pure returns (bool /*isValid*/) @@ -339,7 +339,8 @@ contract Pricer is OpsManaged, PricerInterface { /// @param _transferAmount transferAmount /// @param _commissionAmount commissionAmount /// @return (amountBT,commissionAmountBT) - function getBTAmountFromCurrencyValue(uint256 _pricePoint, + function getBTAmountFromCurrencyValue( + uint256 _pricePoint, uint256 _transferAmount, uint256 _commissionAmount) private diff --git a/contracts/PricerInterface.sol b/contracts/PricerInterface.sol index 3d4f703..6fed0f4 100644 --- a/contracts/PricerInterface.sol +++ b/contracts/PricerInterface.sol @@ -48,7 +48,7 @@ contract PricerInterface { ///Event for accepted margin update for currency event AcceptedMarginSet( bytes3 _currency, - uint64 _acceptedMargin); + uint256 _acceptedMargin); /// @dev Returns address of the branded token; /// public method; @@ -61,11 +61,11 @@ contract PricerInterface { /// returns acceptable margin for the given currency; /// public method; /// @param _currency currency - /// @return uint64 margin + /// @return uint256 margin function acceptedMargins( bytes3 _currency) public - returns (uint64); + returns (uint256); /// @dev Takes _currency; /// returns address of price oracle for the given currency; @@ -134,7 +134,7 @@ contract PricerInterface { /// @return bool isSuccess function setAcceptedMargin( bytes3 _currency, - uint64 _acceptedMargin) + uint256 _acceptedMargin) public returns (bool); From 7d235bc5edc226b6b8f39f0eb5597d7156d31d79 Mon Sep 17 00:00:00 2001 From: deepesh KN Date: Fri, 2 Feb 2018 15:57:05 +0530 Subject: [PATCH 21/21] Travis: Updated .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3f20573..495a961 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,7 @@ before_install: install: - npm install before_script: - - nohup ./tools/runTestRpc.sh /dev/null 2>&1 & + - nohup sh tools/runTestRpc.sh /dev/null 2>&1 & script: - truffle test after_script: