-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
231d7b2
commit 0b46430
Showing
15 changed files
with
7,282 additions
and
97 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
node_modules | ||
.env | ||
|
||
# Hardhat files | ||
/cache | ||
/artifacts | ||
|
||
# TypeChain files | ||
/typechain | ||
/typechain-types | ||
|
||
# solidity-coverage files | ||
/coverage | ||
/coverage.json | ||
|
||
# Hardhat Ignition Files | ||
/ignition | ||
|
||
# Hardhat Ignition default folder for deployments against a local node | ||
/ignition/deployments/chain-31337 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Sample Hardhat Project | ||
|
||
This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, and a Hardhat Ignition module that deploys that contract. | ||
|
||
Try running some of the following tasks: | ||
|
||
```shell | ||
npx hardhat help | ||
npx hardhat test | ||
REPORT_GAS=true npx hardhat test | ||
npx hardhat node | ||
npx hardhat ignition deploy ./ignition/modules/Lock.ts | ||
``` |
This file was deleted.
Oops, something went wrong.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
|
||
interface IOracle { | ||
function oracleValues(string memory key) external view returns (string memory value, uint256 blockNumber); | ||
} | ||
|
||
contract TokenSwap { | ||
enum TokenType { WBTC, WETH, USDC } | ||
|
||
IERC20[3] public tokens; | ||
IOracle public oracle; | ||
string[2] public oracleKeys; | ||
uint256 public constant DECIMALS = 18; | ||
uint256 public constant FIXED_USDC_PRICE = 1 * 10**DECIMALS; | ||
|
||
constructor(IERC20 _wbtc, IERC20 _weth, IERC20 _usdc, IOracle _oracle) { | ||
tokens[uint256(TokenType.WBTC)] = _wbtc; | ||
tokens[uint256(TokenType.WETH)] = _weth; | ||
tokens[uint256(TokenType.USDC)] = _usdc; | ||
oracle = _oracle; | ||
oracleKeys[0] = "BTC/USD"; | ||
oracleKeys[1] = "ETH/USD"; | ||
} | ||
|
||
function _getPriceFromOracle(TokenType tokenType) internal view returns (uint256) { | ||
if (tokenType == TokenType.USDC) { | ||
return FIXED_USDC_PRICE; | ||
} else if (tokenType == TokenType.WBTC) { | ||
(string memory priceStr,) = oracle.oracleValues(oracleKeys[0]); | ||
return _stringToUint(priceStr); | ||
} else if (tokenType == TokenType.WETH) { | ||
(string memory priceStr,) = oracle.oracleValues(oracleKeys[1]); | ||
return _stringToUint(priceStr); | ||
} else { | ||
revert("Unsupported token type"); | ||
} | ||
} | ||
|
||
function _stringToUint(string memory s) internal pure returns (uint256) { | ||
bytes memory b = bytes(s); | ||
uint256 result = 0; | ||
bool decimalPoint = false; | ||
uint256 decimalPlaces = 0; | ||
|
||
for (uint256 i = 0; i < b.length; i++) { | ||
if (b[i] >= 0x30 && b[i] <= 0x39) { | ||
result = result * 10 + (uint256(uint8(b[i])) - 48); | ||
if (decimalPoint) { | ||
decimalPlaces++; | ||
} | ||
} else if (b[i] == 0x2E) { | ||
decimalPoint = true; | ||
} | ||
} | ||
|
||
// Adjust the result to have 18 decimal places | ||
if (decimalPlaces < DECIMALS) { | ||
result = result * (10**(DECIMALS - decimalPlaces)); | ||
} else if (decimalPlaces > DECIMALS) { | ||
result = result / (10**(decimalPlaces - DECIMALS)); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
function swap(uint256 amount, TokenType from, TokenType to) external returns (uint256) { | ||
require(from != to, "Cannot swap the same token"); | ||
|
||
uint256 priceFrom = _getPriceFromOracle(from); | ||
uint256 priceTo = _getPriceFromOracle(to); | ||
|
||
// Adjust for decimal places | ||
uint256 amountTo = (amount * priceFrom * 10**DECIMALS) / priceTo; | ||
|
||
require(tokens[uint256(from)].transferFrom(msg.sender, address(this), amount), "Token transfer failed"); | ||
require(tokens[uint256(to)].transfer(msg.sender, amountTo), "Token transfer failed"); | ||
|
||
return amountTo; | ||
} | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
|
||
interface IOracle { | ||
function oracleValues(string memory key) external view returns (string memory value, uint256 blockNumber); | ||
} | ||
|
||
contract TokenSwap { | ||
|
||
IERC20 public wbtc; | ||
IERC20 public weth; | ||
IERC20 public usdc; | ||
IOracle public oracle; | ||
string public constant ORACLE_KEY_BTC = "BTC/USD"; | ||
string public constant ORACLE_KEY_ETH = "ETH/USD"; | ||
uint256 public constant DECIMALS = 18; | ||
uint256 public constant FIXED_USDC_PRICE = 1 * 10**DECIMALS; | ||
|
||
constructor(IERC20 _wbtc, IERC20 _weth, IERC20 _usdc, IOracle _oracle) { | ||
wbtc = _wbtc; | ||
weth = _weth; | ||
usdc = _usdc; | ||
oracle = _oracle; | ||
} | ||
|
||
function _getPriceFromOracle(string memory key) internal view returns (uint256) { | ||
(string memory priceStr,) = oracle.oracleValues(key); | ||
return _stringToUint(priceStr); | ||
} | ||
|
||
function _stringToUint(string memory s) internal pure returns (uint256) { | ||
bytes memory b = bytes(s); | ||
uint256 result = 0; | ||
bool decimalPoint = false; | ||
uint256 decimalPlaces = 0; | ||
|
||
for (uint256 i = 0; i < b.length; i++) { | ||
if (b[i] >= 0x30 && b[i] <= 0x39) { | ||
result = result * 10 + (uint256(uint8(b[i])) - 48); | ||
if (decimalPoint) { | ||
decimalPlaces++; | ||
} | ||
} else if (b[i] == 0x2E) { | ||
decimalPoint = true; | ||
} | ||
} | ||
|
||
// Adjust the result to have 18 decimal places | ||
if (decimalPlaces < DECIMALS) { | ||
result = result * (10**(DECIMALS - decimalPlaces)); | ||
} else if (decimalPlaces > DECIMALS) { | ||
result = result / (10**(decimalPlaces - DECIMALS)); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
function swapWBTCToUSDC(uint256 amountWBTC) external returns (uint256) { | ||
uint256 priceWBTC = _getPriceFromOracle(ORACLE_KEY_BTC); | ||
uint256 amountUSDC = amountWBTC.mul(priceWBTC).div(FIXED_USDC_PRICE); | ||
|
||
require(wbtc.transferFrom(msg.sender, address(this), amountWBTC), "WBTC transfer failed"); | ||
require(usdc.transfer(msg.sender, amountUSDC), "USDC transfer failed"); | ||
|
||
return amountUSDC; | ||
} | ||
|
||
function swapWETHToUSDC(uint256 amountWETH) external returns (uint256) { | ||
uint256 priceWETH = _getPriceFromOracle(ORACLE_KEY_ETH); | ||
uint256 amountUSDC = amountWETH.mul(priceWETH).div(FIXED_USDC_PRICE); | ||
|
||
require(weth.transferFrom(msg.sender, address(this), amountWETH), "WETH transfer failed"); | ||
require(usdc.transfer(msg.sender, amountUSDC), "USDC transfer failed"); | ||
|
||
return amountUSDC; | ||
} | ||
|
||
function swapUSDCToWBTC(uint256 amountUSDC) external returns (uint256) { | ||
uint256 priceWBTC = _getPriceFromOracle(ORACLE_KEY_BTC); | ||
uint256 amountWBTC = amountUSDC.mul(FIXED_USDC_PRICE).div(priceWBTC); | ||
|
||
require(usdc.transferFrom(msg.sender, address(this), amountUSDC), "USDC transfer failed"); | ||
require(wbtc.transfer(msg.sender, amountWBTC), "WBTC transfer failed"); | ||
|
||
return amountWBTC; | ||
} | ||
|
||
function swapUSDCToWETH(uint256 amountUSDC) external returns (uint256) { | ||
uint256 priceWETH = _getPriceFromOracle(ORACLE_KEY_ETH); | ||
uint256 amountWETH = amountUSDC.mul(FIXED_USDC_PRICE).div(priceWETH); | ||
|
||
require(usdc.transferFrom(msg.sender, address(this), amountUSDC), "USDC transfer failed"); | ||
require(weth.transfer(msg.sender, amountWETH), "WETH transfer failed"); | ||
|
||
return amountWETH; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | ||
import "@openzeppelin/contracts/access/Ownable.sol"; | ||
|
||
contract USDC is ERC20, Ownable { | ||
constructor() ERC20("USDC", "USDC") Ownable(msg.sender) {} | ||
|
||
function mint(address to, uint256 amount) external onlyOwner { | ||
_mint(to, amount); | ||
} | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | ||
import "@openzeppelin/contracts/access/Ownable.sol"; | ||
|
||
contract USDC is ERC20, Ownable { | ||
constructor() ERC20("USDC", "USDC") Ownable(msg.sender) {} | ||
|
||
function mint(address to, uint256 amount) external onlyOwner { | ||
_mint(to, amount); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { HardhatUserConfig } from "hardhat/config"; | ||
import "@nomiclabs/hardhat-ethers"; | ||
import "@nomiclabs/hardhat-waffle"; | ||
|
||
const config: HardhatUserConfig = { | ||
solidity: "0.8.0", | ||
paths: { | ||
sources: "./contracts", | ||
tests: "./test", | ||
cache: "./cache", | ||
artifacts: "./artifacts", | ||
}, | ||
networks: { | ||
hardhat: { | ||
chainId: 1337, | ||
}, | ||
localhost: { | ||
url: "http://127.0.0.1:8545", | ||
}, | ||
}, | ||
}; | ||
|
||
export default config; |
Oops, something went wrong.