Skip to content

Commit

Permalink
feat: update contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
afistfulofstraycathair committed Jul 31, 2024
1 parent 231d7b2 commit 0b46430
Show file tree
Hide file tree
Showing 15 changed files with 7,282 additions and 97 deletions.
20 changes: 20 additions & 0 deletions contracts/.gitignore
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
13 changes: 13 additions & 0 deletions contracts/README.md
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
```
97 changes: 0 additions & 97 deletions contracts/SwapOracle.sol

This file was deleted.

Empty file removed contracts/USDC.sol
Empty file.
83 changes: 83 additions & 0 deletions contracts/contracts/3Swap.sol
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.
99 changes: 99 additions & 0 deletions contracts/contracts/SwapOracle.sol
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;
}
}
13 changes: 13 additions & 0 deletions contracts/contracts/Tokens/USDC.sol
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.
13 changes: 13 additions & 0 deletions contracts/contracts/Tokens/WETH.sol
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);
}
}
23 changes: 23 additions & 0 deletions contracts/hardhat.config.ts
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;
Loading

0 comments on commit 0b46430

Please sign in to comment.