Skip to content

Commit dcaf252

Browse files
committed
price decimals fix
1 parent 48ebad2 commit dcaf252

File tree

6 files changed

+132
-23
lines changed

6 files changed

+132
-23
lines changed

script/HelperConfig.s.sol

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ contract HelperConfig is Script {
1616
}
1717

1818
uint8 public constant DECIMALS = 8;
19-
int256 public constant ETH_USD_PRICE = 2400e8;
20-
int256 public constant BTC_USD_PRICE = 54000e8;
19+
int256 public constant ETH_USD_PRICE = 2_000e8;
20+
int256 public constant BTC_USD_PRICE = 80_000e8;
2121
uint256 public DEFAULT_ANVIL_KEY = 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80;
2222

2323
NetworkConfig public activeNetworkConfig;
@@ -47,10 +47,12 @@ contract HelperConfig is Script {
4747

4848
vm.startBroadcast();
4949
MockV3Aggregator ethUsdPriceFeed = new MockV3Aggregator(DECIMALS, ETH_USD_PRICE);
50-
ERC20Mock wethMock = new ERC20Mock("WETH", "WETH", msg.sender, 1000e8);
50+
//weth has 18 decimals on ethereum
51+
ERC20Mock wethMock = new ERC20Mock("WETH", "WETH", uint8(18), msg.sender, 1000e18);
5152

53+
// wbt has 8 decimals on ethereum
5254
MockV3Aggregator btcUsdPriceFeed = new MockV3Aggregator(DECIMALS, BTC_USD_PRICE);
53-
ERC20Mock wbtcMock = new ERC20Mock("WBTC", "WBTC", msg.sender, 1000e8);
55+
ERC20Mock wbtcMock = new ERC20Mock("WBTC", "WBTC", uint8(8), msg.sender, 1000e8);
5456

5557
vm.stopBroadcast();
5658

src/DSCEngine.sol

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pragma solidity ^0.8.24;
44

55
import {DecentralizedStableCoin} from "./DecentralizedStableCoin.sol";
66
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
7-
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
7+
import {IERC20} from "src/interfaces/IERC20.sol";
88
import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
99

1010
import {console} from "forge-std/Test.sol";
@@ -320,17 +320,18 @@ contract DSCEngine is ReentrancyGuard {
320320
return s_CollateralDeposited[user][collateral];
321321
}
322322

323+
//returns value of token in usd with 18 decimals
323324
function getUsdValue(address token, uint256 amount) public view returns (uint256) {
324325
AggregatorV3Interface priceFeed = AggregatorV3Interface(s_priceFeeds[token]);
325326
(, int256 price,,,) = priceFeed.latestRoundData();
326-
return ((uint256(price) * ADITIONAL_FEED_PRECISION) * amount) / PRECISION;
327+
return ((uint256(price) * ADITIONAL_FEED_PRECISION) * amount) / uint256(10 ** IERC20(token).decimals());
327328
}
328329

330+
//returns usd value(in 18 deciamls) to tokenAmount ( in token deciamls)
329331
function getTokenAmountFromUsd(address token, uint256 usdAmountInWei) public view returns (uint256) {
330332
AggregatorV3Interface priceFeed = AggregatorV3Interface(s_priceFeeds[token]);
331333
(, int256 price,,,) = priceFeed.latestRoundData();
332-
333-
return (usdAmountInWei * PRECISION) / (uint256(price) * ADITIONAL_FEED_PRECISION);
334+
return (usdAmountInWei * uint256(10 ** IERC20(token).decimals())) / (uint256(price) * ADITIONAL_FEED_PRECISION);
334335
}
335336

336337
function getPriceFeedFromToken(address tokenAddress) public view returns (address) {

src/interfaces/IERC20.sol

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// SPDX-License-Identifier: MIT
2+
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
3+
4+
pragma solidity ^0.8.20;
5+
6+
/**
7+
* @dev Interface of the ERC20 standard as defined in the EIP.
8+
*/
9+
interface IERC20 {
10+
/**
11+
* @dev Emitted when `value` tokens are moved from one account (`from`) to
12+
* another (`to`).
13+
*
14+
* Note that `value` may be zero.
15+
*/
16+
event Transfer(address indexed from, address indexed to, uint256 value);
17+
18+
/**
19+
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
20+
* a call to {approve}. `value` is the new allowance.
21+
*/
22+
event Approval(address indexed owner, address indexed spender, uint256 value);
23+
24+
/**
25+
* @dev Returns the value of tokens in existence.
26+
*/
27+
function totalSupply() external view returns (uint256);
28+
29+
/**
30+
* @dev Returns the deciamls used in token
31+
*/
32+
function decimals() external view returns (uint8);
33+
34+
/**
35+
* @dev Returns the value of tokens owned by `account`.
36+
*/
37+
function balanceOf(address account) external view returns (uint256);
38+
39+
/**
40+
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
41+
*
42+
* Returns a boolean value indicating whether the operation succeeded.
43+
*
44+
* Emits a {Transfer} event.
45+
*/
46+
function transfer(address to, uint256 value) external returns (bool);
47+
48+
/**
49+
* @dev Returns the remaining number of tokens that `spender` will be
50+
* allowed to spend on behalf of `owner` through {transferFrom}. This is
51+
* zero by default.
52+
*
53+
* This value changes when {approve} or {transferFrom} are called.
54+
*/
55+
function allowance(address owner, address spender) external view returns (uint256);
56+
57+
/**
58+
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
59+
* caller's tokens.
60+
*
61+
* Returns a boolean value indicating whether the operation succeeded.
62+
*
63+
* IMPORTANT: Beware that changing an allowance with this method brings the risk
64+
* that someone may use both the old and the new allowance by unfortunate
65+
* transaction ordering. One possible solution to mitigate this race
66+
* condition is to first reduce the spender's allowance to 0 and set the
67+
* desired value afterwards:
68+
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
69+
*
70+
* Emits an {Approval} event.
71+
*/
72+
function approve(address spender, uint256 value) external returns (bool);
73+
74+
/**
75+
* @dev Moves a `value` amount of tokens from `from` to `to` using the
76+
* allowance mechanism. `value` is then deducted from the caller's
77+
* allowance.
78+
*
79+
* Returns a boolean value indicating whether the operation succeeded.
80+
*
81+
* Emits a {Transfer} event.
82+
*/
83+
function transferFrom(address from, address to, uint256 value) external returns (bool);
84+
}

test/fuzz/Handler.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ contract Handler is Test {
4545
uint256 maxCollateralToRedeem = engine.getAccountCollateralBalance(msg.sender, address(weth));
4646
collateralAmount = bound(collateralAmount, 0, maxCollateralToRedeem);
4747

48-
if(collateralAmount ==0){
48+
if (collateralAmount == 0) {
4949
return; // aur use vm.assume
5050
}
5151

test/mocks/ERC20Mock.sol

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,21 @@ pragma solidity ^0.8.24;
44
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
55

66
contract ERC20Mock is ERC20 {
7-
constructor(string memory name, string memory symbol, address initialAccount, uint256 initialBalance)
8-
payable
9-
ERC20(name, symbol)
10-
{
7+
uint8 i_deciamls;
8+
9+
constructor(
10+
string memory name,
11+
string memory symbol,
12+
uint8 deciamls,
13+
address initialAccount,
14+
uint256 initialBalance
15+
) payable ERC20(name, symbol) {
1116
_mint(initialAccount, initialBalance);
17+
i_deciamls = deciamls;
18+
}
19+
20+
function decimals() public view override returns (uint8) {
21+
return i_deciamls;
1222
}
1323

1424
function mint(address account, uint256 amount) public {

test/unit/DSCEngineTest.t.sol

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
pragma solidity ^0.8.24;
44

5-
import {Test, console} from "forge-std/Test.sol";
5+
import {Test, console, console2} from "forge-std/Test.sol";
66

77
import {DeployDSC} from "script/DeployDSC.s.sol";
88
import {DecentralizedStableCoin} from "../../src/DecentralizedStableCoin.sol";
@@ -44,10 +44,20 @@ contract DSCEngineTest is Test {
4444
uint256 public constant MINT_DSC_AMOUNT = 100e18; // 100 USD
4545
uint256 public constant COLLATERAL_TO_COVER = 20 ether;
4646

47+
uint256 constant WBTC_PRECISION = 1e8;
48+
uint256 constant WETH_PRECISION = 1e18;
49+
uint256 constant PRICEFEED_PRECISION = 1e8;
50+
uint256 public currentEthPrice;
51+
uint256 public currentBtcPrice;
52+
4753
function setUp() public {
4854
deployer = new DeployDSC();
4955
(dsc, engine, helperConfig) = deployer.run();
5056
(ethUsdPriceFeed, btcUsdPriceFeed, weth, wbtc, deployerKey) = helperConfig.activeNetworkConfig();
57+
(, int256 ethPrice,,,) = MockV3Aggregator(ethUsdPriceFeed).latestRoundData();
58+
currentEthPrice = uint256(ethPrice);
59+
(, int256 btcPrice,,,) = MockV3Aggregator(btcUsdPriceFeed).latestRoundData();
60+
currentBtcPrice = uint256(btcPrice);
5161
ERC20Mock(weth).mint(USER, STARTING_ERC20_BALANCE); // 100 weth
5262
ERC20Mock(wbtc).mint(USER, STARTING_ERC20_BALANCE); // 100 wbtc
5363

@@ -70,20 +80,22 @@ contract DSCEngineTest is Test {
7080
//////////////////////////////////////////////
7181
/// View Function Tests ///
7282
//////////////////////////////////////////////
73-
function test_GetUsdValue() public view {
74-
uint256 ethAmount = 2;
75-
uint256 expectedValue = 2 * 2400;
76-
uint256 actualValue = engine.getUsdValue(weth, ethAmount);
77-
console.log("Value in USD: %d", actualValue);
83+
function test_getUsdValue() public view {
84+
uint256 btcAmount = 2e8;
85+
uint256 expectedValue = btcAmount * currentBtcPrice * 1e18 / (WBTC_PRECISION * PRICEFEED_PRECISION);
86+
// / wbtc decimals * priceFeedDecimals
87+
uint256 actualValue = engine.getUsdValue(wbtc, btcAmount);
88+
console.log("expected value :", expectedValue);
89+
console.log("actual value :", actualValue);
7890
assert(expectedValue == actualValue);
7991
}
8092

8193
function test_getTokenAmountFromUsd() public view {
82-
uint256 usdAmount = 2400 * 1e18;
83-
uint256 expectedValue = (2400 * 1e18) / 2400;
84-
uint256 actualValue = engine.getTokenAmountFromUsd(weth, usdAmount);
94+
uint256 usdAmount = 80_000 * 1e18;
95+
uint256 expectedBtc = usdAmount * WBTC_PRECISION * PRICEFEED_PRECISION / (currentBtcPrice * 1e18);
96+
uint256 actualValue = engine.getTokenAmountFromUsd(wbtc, usdAmount);
8597
console.log("Value in ETH: %d", actualValue);
86-
assert(expectedValue == actualValue);
98+
assert(expectedBtc == actualValue);
8799
}
88100

89101
function test_getAccountCollateralValue() public view {}

0 commit comments

Comments
 (0)