From 9c320eb62f5399129c16909e9c65f9ebd8429e44 Mon Sep 17 00:00:00 2001 From: amaqkkg <16919110+amaqkkg@users.noreply.github.com> Date: Sun, 5 Jan 2025 10:39:47 +0700 Subject: [PATCH] Fix logic of both contract --- src/BankHub.sol | 31 ++++++++++++++++--------------- src/IDRCoin.sol | 39 ++++++++++++++++++++++++++++----------- src/interfaces/IUSDT.sol | 10 ++++++---- 3 files changed, 50 insertions(+), 30 deletions(-) diff --git a/src/BankHub.sol b/src/BankHub.sol index 11bcc66..96a4a50 100644 --- a/src/BankHub.sol +++ b/src/BankHub.sol @@ -3,13 +3,14 @@ pragma solidity 0.8.28; import {IDRCoin} from "./IDRCoin.sol"; -import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -contract BankHub is UUPSUpgradeable { +contract BankHub { // constants uint32 public constant MIN_INTEREST_RATE = 5; + uint32 public constant MAX_INTEREST_RATE = 100; uint32 public constant DENOMINATOR = 100; uint256 public constant MIN_LOAN_AMOUNT = 10e18; + uint256 public constant MAX_LOAN_AMOUNT = 100e18; // state variables address public owner; @@ -47,12 +48,8 @@ contract BankHub is UUPSUpgradeable { event Withdraw(address indexed user, address indexed bank, uint256 amount); event Approved(address indexed bank); - constructor() { - _disableInitializers(); - } - - function initialize() public initializer { - owner = msg.sender; + constructor(address _owner) { + owner = _owner; } // user function @@ -95,9 +92,9 @@ contract BankHub is UUPSUpgradeable { idrcoin.mint(msg.sender, interest); // transfer amount - idrcoin.transferFrom(address(_fromBank), msg.sender, _amount); + idrcoin.transferFrom(_fromBank, msg.sender, _amount); - emit Withdraw(msg.sender, _fromBank, _amount); + emit Withdraw(msg.sender, _fromBank, _amount + interest); } // bank function @@ -110,6 +107,9 @@ contract BankHub is UUPSUpgradeable { if (_amount < MIN_LOAN_AMOUNT) { revert insufficientLoanAmount(); } + if (_amount > MAX_LOAN_AMOUNT) { + revert insufficientLoanAmount(); + } idrcoin.mint(_bank, _amount); } @@ -126,6 +126,11 @@ contract BankHub is UUPSUpgradeable { owner = _newOwner; } + // set IDRCoin address + function setIDRCoin(address _idrcoin) public onlyOwner { + idrcoin = IDRCoin(_idrcoin); + } + // whitelist partner bank, set interest rate and approve unlimited IDRCoin transfer by this contract function whiteList(address _bank) public onlyOwner { whiteListed[_bank] = true; @@ -137,17 +142,13 @@ contract BankHub is UUPSUpgradeable { // revoke whitelist from partner bank // collect all IDRCoin from bank + // this is used to punish bank that misbehave function revokeWhiteList(address _bank) public onlyOwner { if (idrcoin.balanceOf(_bank) > 0) { idrcoin.transferFrom(_bank, owner, idrcoin.balanceOf(_bank)); } } - // Implementation of the required UUPSUpgradeable function - function _authorizeUpgrade(address newImplementation) internal override { - require(msg.sender == owner, "only owner can authorize upgrades"); - } - // view function function isWhiteListed(address _bank) public view returns (bool) { return whiteListed[_bank]; diff --git a/src/IDRCoin.sol b/src/IDRCoin.sol index 1001cc0..bd7719e 100644 --- a/src/IDRCoin.sol +++ b/src/IDRCoin.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.28; + import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {IUSDT} from "./interfaces/IUSDT.sol"; import {IBankHub} from "./interfaces/IBankHub.sol"; @@ -18,11 +19,12 @@ contract IDRCoin is ERC20 { // constant // convertion rate from USDT to IDR - uint256 constant public CONVERSION_RATE = 16000; + uint256 public constant CONVERSION_RATE = 16000; + uint8 public constant DECIMALS = 18; // enforce ppn 12% for ALL MINTING transaction involving IDRC token - uint256 constant public TAX = 12; - uint256 constant public DENOMINATOR = 100; + uint256 public constant TAX = 12; + uint256 public constant DENOMINATOR = 100; modifier onlyAdmin() { if (msg.sender != admin) { @@ -47,8 +49,16 @@ contract IDRCoin is ERC20 { error BankCannotManualApprove(); // event - event IDRC_Transfer(address indexed from, address indexed to, uint256 value); - event IDRC_Approval(address indexed owner, address indexed spender, uint256 value); + event IDRC_Transfer( + address indexed from, + address indexed to, + uint256 value + ); + event IDRC_Approval( + address indexed owner, + address indexed spender, + uint256 value + ); event IDRC_Mint(address indexed to, uint256 value); event IDRC_Burn(address indexed from, uint256 value); @@ -81,9 +91,12 @@ contract IDRCoin is ERC20 { // external/public function // anyone can buy IDRC with USDT with fixed conversion rate function convertUSDtoIDR(uint256 amountInUSD) external { - usdt.transfer(address(this), amountInUSD); - uint256 amountInIDR = amountInUSD * CONVERSION_RATE * decimals(); - _mint(msg.sender, amountInIDR); + usdt.transferFrom(msg.sender, address(this), amountInUSD); + // first we normalize the amount in usd by dividing it with its own decimals + // then we multiply it with the conversion rate and IDRC decimals + // result is the amount of IDRC to mint with the correct decimals + uint256 amountInIDR = (amountInUSD / 10 ** usdt.decimals()) *CONVERSION_RATE * 10 ** decimals(); + mint_(msg.sender, amountInIDR); emit IDRC_Mint(msg.sender, amountInIDR); } @@ -93,8 +106,8 @@ contract IDRCoin is ERC20 { address _spender, uint256 _amount ) public override returns (bool) { - // we dont want the bank to manually approve - // because it can be exploited by the bank, they can set _amount to 0 and the BankHub + // we dont want the bank to manually approve + // because it can be exploited by the bank, they can set _amount to 0 and the BankHub // cannot spend the loaned IDRC if (IBankHub(bankHub).isWhiteListed(msg.sender)) { revert BankCannotManualApprove(); @@ -178,6 +191,10 @@ contract IDRCoin is ERC20 { return balances[_addr]; } + function decimals() public pure override returns (uint8) { + return DECIMALS; + } + // setter/admin function // set the bankHub address function setBankHub(address _bankHub) external onlyAdmin { @@ -194,7 +211,7 @@ contract IDRCoin is ERC20 { admin = admin; } - // change taxCollector address + // change taxCollector address function changeTaxCollector(address _taxCollector) external onlyAdmin { taxCollector = _taxCollector; } diff --git a/src/interfaces/IUSDT.sol b/src/interfaces/IUSDT.sol index 9e3a868..3f5a9b8 100644 --- a/src/interfaces/IUSDT.sol +++ b/src/interfaces/IUSDT.sol @@ -2,11 +2,13 @@ pragma solidity 0.8.28; interface IUSDT { - function decimals() external returns (uint); + function decimals() external returns (uint256); - function balanceOf(address who) external returns (uint); + function balanceOf(address who) external returns (uint256); - function transfer(address to, uint value) external; + function transfer(address to, uint256 value) external; - function approve(address spender, uint value) external; + function transferFrom(address from, address to, uint256 value) external; + + function approve(address spender, uint256 value) external; }