Skip to content

Instantly share code, notes, and snippets.

@aviexk
Created January 4, 2021 17:20
Show Gist options
  • Save aviexk/a78f72b4d302fe9b0f3ce5630b682c19 to your computer and use it in GitHub Desktop.
Save aviexk/a78f72b4d302fe9b0f3ce5630b682c19 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.7.4+commit.3f05b770.js&optimize=false&runs=200&gist=
///SPDX-License-Identifier: MIT
pragma solidity ^0.7.3;
import 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.2.0-solc-0.7/contracts/token/ERC20/ERC20.sol';
contract CollateralToken is ERC20 {
constructor() ERC20("METH", "METH") {
_setupDecimals(0);
_mint(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4, 100000); //tokenSponser
_mint(0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2, 100000); //Liquidator
_mint(0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db, 100000); //Disputor
}
}
///SPDX-License-Identifier: MIT
pragma solidity ^0.7.3;
import "./SyntheticToken.sol";
import "./TokenFactory.sol";
import "./CollateralToken.sol";
import "./Timer.sol";
import "./Oracle.sol";
contract FinancialContract {
SyntheticToken public syntheticToken;
TokenFactory public tokenFactory;
CollateralToken public collateralToken;
Timer public timer;
Oracle public oracle;
//store created positions
struct Position {
uint256 tokensOutstanding;
uint256 collateralAmount;
}
string public priceIdentifier;
enum ContractStatus {
Open,
Settled
}
uint256 public finalPrice;
ContractStatus public currentStatus;
mapping(address => Position) public positions;
uint256 public minimumNumberOfTokens;
uint256 public collateralRatioRequired;
constructor() {
minimumNumberOfTokens = 100;
tokenFactory = TokenFactory(0x8862090A79412D034d9Fb8C9DBFd3194C8D2a2EE);
syntheticToken = tokenFactory.createToken("SyntheticToken", "SNT");
collateralToken = CollateralToken(0xC5862Ba753F3DabC4120E9803c01e0B13D7905F2);
timer = Timer(0x9AeB0ff23DF8c3d3a251AC31a0923419d8bCB43C);
oracle = Oracle(0x9C9fF5DE0968dF850905E74bAA6a17FED1Ba042a);
priceIdentifier = "METH/USD";
currentStatus = ContractStatus.Open;
collateralRatioRequired = 2;
require(oracle.isSupportedIdentifier(priceIdentifier), "Not supported Price Identifier");
}
//createPosition
function createPosition(uint256 _numberOfTokens, uint256 _collateralAmount) public {
require(_collateralAmount / _numberOfTokens > collateralRatioRequired, " Vellow collateral ratio");
require(currentStatus == ContractStatus.Open, "Contract is not open");
require(_numberOfTokens >= minimumNumberOfTokens, "Below minimum amount of tokens");
Position storage currentPosition = positions[msg.sender];
currentPosition.tokensOutstanding = _numberOfTokens;
currentPosition.collateralAmount = _collateralAmount;
syntheticToken.mint(msg.sender, _numberOfTokens);
collateralToken.transferFrom(msg.sender, address(this), _collateralAmount);
}
enum LiquidationStatus {
Liquidated,
PendingDispute,
DisputeSucceeded,
DisputeFailed
}
struct Liquidation {
address sponsor;
address liquidator;
uint256 liquidationTime;
address disputer;
uint256 settlementPrice;
uint256 collateralLocked;
uint256 liquidationCollateral;
uint256 tokensLiquidated;
LiquidationStatus status;
}
uint256 public numberOfLiquidations;
mapping(uint256 => Liquidation) public liquidations;
//createLiquidation
function createLiquidation(address _tokenSponsor) public {
numberOfLiquidations = numberOfLiquidations + 1;
Position storage positionToLiquidate = positions[_tokenSponsor];
Liquidation storage newLiquidation = liquidations[numberOfLiquidations];
newLiquidation.sponsor = _tokenSponsor;
newLiquidation.liquidator = msg.sender;
newLiquidation.liquidationTime = timer.getTime();
newLiquidation.disputer = address(0);
newLiquidation.settlementPrice = 0;
newLiquidation.collateralLocked = positionToLiquidate.collateralAmount;
newLiquidation.liquidationCollateral = positionToLiquidate.collateralAmount;
newLiquidation.tokensLiquidated = positionToLiquidate.tokensOutstanding;
newLiquidation.status = LiquidationStatus.Liquidated;
uint256 tokensToLiquidate = positionToLiquidate.tokensOutstanding;
syntheticToken.transferFrom(msg.sender, address(this), tokensToLiquidate);
syntheticToken.burn(tokensToLiquidate);
collateralToken.transferFrom(msg.sender, address(this), positionToLiquidate.collateralAmount);
delete positions[_tokenSponsor];
}
//disputeLiqudation
function disputeLiqudation(uint256 _liquidationId) public {
Liquidation storage liquidation = liquidations[_liquidationId];
liquidation.disputer = msg.sender;
liquidation.settlementPrice = oracle.getPrice(priceIdentifier);
liquidation.collateralLocked = liquidation.collateralLocked + liquidation.liquidationCollateral;
collateralToken.transferFrom(msg.sender, address(this), liquidation.liquidationCollateral);
}
//settlePosition
function settlePosition(uint256 _liquidationId) public {
Liquidation storage liquidation = liquidations[_liquidationId];
require((msg.sender == liquidation.disputer) ||
(msg.sender == liquidation.liquidator) ||
(msg.sender == liquidation.sponsor),
"Caller cannot withdraw rewards");
uint256 tokenRedemtionValue = liquidation.tokensLiquidated * liquidation.settlementPrice;
uint256 requiredCollateral = tokenRedemtionValue * collateralRatioRequired;
bool disputeSucceeded = liquidation.liquidationCollateral >= requiredCollateral;
liquidation.status = disputeSucceeded ? LiquidationStatus.DisputeSucceeded : LiquidationStatus.DisputeFailed;
if (disputeSucceeded) {
collateralToken.transfer(liquidation.disputer, liquidation.collateralLocked);
} else {
collateralToken.transfer(liquidation.liquidator, liquidation.collateralLocked);
}
delete liquidations[_liquidationId];
}
function settle() public {
currentStatus = ContractStatus.Settled;
finalPrice = oracle.getPrice(priceIdentifier);
}
}
///SPDX-License-Identifier: MIT
pragma solidity ^0.7.3;
contract Oracle {
//save priceidentifiers - eth/usd, btc/usd
mapping(string => uint256) private prices;
//make identifiers supported
mapping(string => bool) private supportedIdentifiers;
function setPrice(string memory _identifier, uint256 _price) public {
require(isSupportedIdentifier(_identifier), "Identifier not supported");
prices[_identifier] = _price;
}
function getPrice(string memory _identifier) public view returns (uint256) {
return prices[_identifier];
}
function addIdentifier(string memory _identifier) public {
supportedIdentifiers[_identifier] = true;
}
function isSupportedIdentifier(string memory _identifier) public view returns (bool) {
return supportedIdentifiers[_identifier];
}
}
///SPDX-License-Identifier: MIT
pragma solidity ^0.7.3;
import 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.2.0-solc-0.7/contracts/token/ERC20/ERC20.sol';
contract SyntheticToken is ERC20 {
constructor(string memory _tokenName, string memory _tokenSymbol)
ERC20(_tokenName, _tokenSymbol)
{
_setupDecimals(0);
}
function mint(address _recipient, uint256 _value) public returns (bool) {
_mint(_recipient, _value);
return true;
}
function burn(uint256 _value) public {
_burn(msg.sender, _value);
}
}
///SPDX-License-Identifier: MIT
pragma solidity ^0.7.3;
contract Timer {
uint256 private currentTime;
constructor() {
currentTime = 0;
}
function setTime(uint256 _newTime) public{
currentTime = _newTime;
}
function getTime() public view returns (uint256) {
return currentTime;
}
}
///SPDX-License-Identifier: MIT
pragma solidity ^0.7.3;
import './SyntheticToken.sol';
contract TokenFactory {
function createToken(string memory _name, string memory _symbol) public returns (SyntheticToken) {
SyntheticToken newSyntheticToken = new SyntheticToken(_name, _symbol);
return newSyntheticToken;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment