Skip to content

Instantly share code, notes, and snippets.

@samnet
Created May 24, 2022 12:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save samnet/a8ead5344c9abd7ebbe0423c63d1693f to your computer and use it in GitHub Desktop.
Save samnet/a8ead5344c9abd7ebbe0423c63d1693f 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.8.7+commit.e28d00a7.js&optimize=false&runs=200&gist=
pragma solidity >=0.7.0 <0.9.0;
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract simpleTestCDF {
address payable buyer;
address payable seller;
AggregatorV3Interface private priceFeed; // price oracle
int private initialPrice;
bool private activeContract;
uint private initialFundingRequirement;
/**
* Aggregator: Kovan, Chainlink, ETH/USD
* Address: 0x9326BFA02ADD2366b30bacB125260Af641031331
*/
constructor() {
priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331);
activeContract = false;
initialFundingRequirement = 1e14;
buyer = payable(address(0));
seller = payable(address(0));
}
/**
* @dev Return Buyer address
* @return address of Buyer
*/
function getBuyer() external view returns (address) {
return buyer;
}
/**
* @dev Return Seller address
* @return address of Seller
*/
function getSeller() external view returns (address) {
return seller;
}
/**
* @dev Return initialPrice
* @return initialPrice
*/
function getInitialPrice() external view returns (int) {
return initialPrice;
}
/**
* @dev Return activeContract
* @return activeContract
*/
function getContractState() external view returns (bool) {
return activeContract;
}
// liquidate contract
function liquidateContract() external {
require(activeContract, "Contract is inactive.");
int currentPrice = getLatestPrice();
int currentMinusInitial = currentPrice - initialPrice;
require(currentMinusInitial != 0, "Price is same as when contract was signed.");
if (currentMinusInitial < 0) { // price went down; good for the seller
(bool sent, bytes memory data) = seller.call{value: address(this).balance}("");
require(sent, "Failed to send Ether to seller.");
} else { // price went up; good for the buyer
(bool sent, bytes memory data) = buyer.call{value: address(this).balance}("");
require(sent, "Failed to send Ether to buyer.");
}
buyer = payable(address(0));
seller = payable(address(0));
activeContract = false;
}
// withdraw from contract
function withdrawFromContract() external {
int currentPrice = getLatestPrice();
int currentMinusInitial = currentPrice - initialPrice;
if (currentMinusInitial != 0) {
require(!activeContract, "Contract is already active. You cannot withdraw.");
}
if (msg.sender == buyer){
(bool sent, bytes memory data) = buyer.call{value: address(this).balance}("");
require(sent, "Failed to send Ether to buyer.");
buyer = payable(address(0));
}
if (msg.sender == seller){
(bool sent, bytes memory data) = seller.call{value: address(this).balance}("");
require(sent, "Failed to send Ether to seller.");
seller = payable(address(0));
}
}
/**
* Returns the latest price
*/
function getLatestPrice() public view returns (int) {
(
/*uint80 roundID*/,
int price,
/*uint startedAt*/,
/*uint timeStamp*/,
/*uint80 answeredInRound*/
) = priceFeed.latestRoundData();
return price;
}
function activateContract() private {
require(!activeContract, "Contract is already active.");
activeContract = true;
initialPrice = getLatestPrice();
}
// enter contract / set buyer/seller, if counterparty exists, this is equivalent to starting the contract
function enterContractAsBuyer() payable external {
require(!activeContract, "Contract is already active. You cannot enter.");
require(buyer == address(0), "There is already a buyer for this CfD contract." );
require(msg.value > initialFundingRequirement, "You need to provide a funding buffer / margin.");
buyer = payable(msg.sender);
if (seller != address(0)){
activateContract();
}
}
// enter contract / set buyer/seller, if counterparty exists, this is equivalent to starting the contract
function enterContractAsSeller() payable external {
require(!activeContract, "Contract is already active. You cannot enter.");
require(seller == address(0), "There is already a seller for this CfD contract." );
require(msg.value > initialFundingRequirement, "You need to provide a funding buffer / margin.");
seller = payable(msg.sender);
if (buyer != address(0)){
activateContract();
}
}
// modifier to check if there is already a buyer
modifier buyerDNE() {
require(buyer == address(0), "There is already a Buyer for this contract instance");
_;
}
// modifier to check if there is already a buyer
modifier sellerDNE() {
require(seller == address(0), "There is already a Seller for this contract instance");
_;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment