Commit 49466459 authored by kirtisingh's avatar kirtisingh

Atomic swap, orderbook implemented

parents
Pipeline #1720 canceled with stages
node_modules
.env
coverage
coverage.json
typechain
typechain-types
#Hardhat files
cache
artifacts
176891e3485093b0b58498a83b898a0cfef87d0d6f3dd919174ddcecf40aeb54
\ No newline at end of file
# Sample Hardhat Project
This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, and a script 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 run scripts/deploy.js
```
const express = require('express');
const morgan = require('morgan');
const mongoose = require('mongoose');
const txns = require('./models/txns');
// express app
const app = express();
// app.use(express.static(__dirname + '/public'));
app.listen(3000);
// connect to mongodb & listen for requests
const dbURI = "mongodb+srv://redkirti:Strong1234@cluster0.4oandf8.mongodb.net/orderbook?retryWrites=true&w=majority";
const connectionParams={
useNewUrlParser: true,
useUnifiedTopology: true
}
mongoose.connect(dbURI,connectionParams)
.then( () => {
console.log('Connected to the database ')
})
.catch( (err) => {
console.error(`Error connecting to the database. n${err}`);
})
// register view engine
app.set('view engine', 'ejs');
// middleware & static files
app.use(express.static('public'));
app.use(express.urlencoded({ extended: true}));
app.use(morgan('dev'));
app.use((req, res, next) => {
res.locals.path = req.path;
next();
});
app.post('/txns', (req, res) => {
console.log(req.body);
const txn = new txns(req.body);
txn.save().then((result) => {
res.send(result)
})
.catch((err) => {
console.log(err);
})
});
app.get('/txns', (req,res) => {
txns.find().then((result) => {
res.render('orderbook', {title: 'All Transactions', txns: result})
})
.catch((err) => {
console.log(err);
})
})
app.get('/', (req, res) => {
res.render('index');
});
// 404 page
app.use((req, res) => {
res.status(404).render('404', { title: '404' });
});
\ No newline at end of file
0xC6CD342cEba445bBfB98B9d5Da99c62B2B98CFbe - ONT
0x6EF8fd109f067F51f8ae25B41FD56b1a7b8f042B - ONT
0x8909Dff24b48790c9A0590F706Dc8f3B1709ce88 - ETH
\ No newline at end of file
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.16 <0.9.0;
contract EthereumContract {
enum Status {
Blank,
Initiated,
Locked, // ETH was locked by buyer
Set, //intitiator address set by buyer
Refunded, // ETH was refunded to buyer
Claimed // ETH was sucessfully claimed by order initiator
}
struct respondOrder {
address initiatorEthAddress;
address buyerOntAddress;
address buyerEthAddress;
bytes32 hashlock;
uint mxbid;
uint refundTimelock;
uint bidTimelock;
string secret;
Status status;
}
mapping (bytes32 => respondOrder) public orderList; // hashlock => order data
uint timelockDuration = 600; // set to 600 seconds for testing purposes
uint bidtime = 300; //set to 300 seconds for testing
//Can we do it without this function
function initiateBidding(bytes32 hashlock) public {
if((orderList[hashlock].bidTimelock!=0) && (block.timestamp>orderList[hashlock].bidTimelock) && (block.timestamp-orderList[hashlock].bidTimelock>900)){
clear(hashlock);
}
require(orderList[hashlock].status == Status.Blank, "Still in progress");
orderList[hashlock].bidTimelock = block.timestamp + bidtime;
orderList[hashlock].status = Status.Initiated;
orderList[hashlock].refundTimelock = block.timestamp + timelockDuration;
}
function bid(bytes32 hashlock, address buyerOntAddress) public payable {
require(orderList[hashlock].status == Status.Initiated || orderList[hashlock].status==Status.Locked, "Transaction in Invalid State");
require(block.timestamp<=orderList[hashlock].bidTimelock, "Bidding Period Ended");
require(msg.value>orderList[hashlock].mxbid,"Bidding price should be greater than the highest bid");
// If no one bid for the exchange control won't come here
if(orderList[hashlock].status == Status.Locked){
payable(orderList[hashlock].buyerEthAddress).transfer(orderList[hashlock].mxbid);
}
orderList[hashlock].mxbid = msg.value;
orderList[hashlock].buyerEthAddress = msg.sender;
orderList[hashlock].buyerOntAddress = buyerOntAddress;
orderList[hashlock].status = Status.Locked;
}
//setting initiator address
function setInitiatorAddr(bytes32 hashlock, address initiatorEthAddress) public{
require(orderList[hashlock].buyerEthAddress==msg.sender, "Access Denied"); //Only max bidder can enter
require(orderList[hashlock].refundTimelock>block.timestamp, "Time Ended");
require(orderList[hashlock].status==Status.Locked, "Wrong state");
orderList[hashlock].initiatorEthAddress = initiatorEthAddress;
orderList[hashlock].status = Status.Set;
}
function claimEth (bytes32 hashlock, string memory secret) public {
require(orderList[hashlock].initiatorEthAddress == msg.sender, "Can only be perfomed by initiator");
require(orderList[hashlock].status == Status.Set, "Order status should be Set");
require(orderList[hashlock].refundTimelock>block.timestamp, "Claim Time Finished");
require(sha256(abi.encodePacked(secret)) == hashlock, "Secret does not match the hashlock");
orderList[hashlock].secret = secret;
orderList[hashlock].status = Status.Claimed;
payable(msg.sender).transfer(orderList[hashlock].mxbid);
//Transaction Finished. Make the hash ready for probable other txn
clear(hashlock);
}
function refundEth (bytes32 hashlock) public {
require(orderList[hashlock].buyerEthAddress == msg.sender, "Can only be perfomed by order initiator");
require(block.timestamp >= orderList[hashlock].refundTimelock, "Timelock is not over");
require(orderList[hashlock].status == Status.Set || orderList[hashlock].status==Status.Locked, "Order should be in Set state for refund");
orderList[hashlock].status = Status.Refunded;
payable(msg.sender).transfer(orderList[hashlock].mxbid);
//Transaction Finished. Make the hash ready for probable other txn
clear(hashlock);
}
function clear(bytes32 hashlock) private {
orderList[hashlock] = respondOrder({
buyerOntAddress: address(0),
buyerEthAddress: address(0),
initiatorEthAddress: address(0),
hashlock: bytes32(0),
mxbid: 0,
refundTimelock: 0,
bidTimelock: 0,
secret: "",
status: Status.Blank
});
}
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.16 <0.9.0;
contract OntologyContract {
enum Status {
Blank,
Locked, // ONT tokens were locked by initiator
Set,
Refunded, // ONT was refunded to buyer
Claimed // ONT was sucessfully claimed by order initiators
}
struct initiatedOrder {
address initiatorOntAddress;
address initiatorEthAddress;
address buyerOntAddress;
address buyerEthAddress;
bytes32 hashlock;
uint amountOnt;
uint refundTimelock;
uint initiatedTime;
string secret;
Status status;
}
mapping (bytes32 => initiatedOrder) public orderList; // hashlock => order data
uint timelockDuration = 900; // set to 900 seconds for testing purposes
function initiateOrder (bytes32 hashlock, address initiatorEthAddress) public payable {
//For clearing an intermediate left txn
if((orderList[hashlock].status!=Status.Blank) && ((block.timestamp-orderList[hashlock].initiatedTime)>1200)){
clear(hashlock);
}
require(orderList[hashlock].status==Status.Blank, "Already in Use");
orderList[hashlock].initiatorOntAddress = msg.sender;
orderList[hashlock].initiatorEthAddress = initiatorEthAddress;
orderList[hashlock].refundTimelock = block.timestamp + timelockDuration;
orderList[hashlock].status = Status.Locked;
orderList[hashlock].amountOnt = msg.value;
}
//ALICE HAS TO CHECK WHETHER BIDDING HAS FINISHED
function setBuyerAddr(bytes32 hashlock, address buyerOntAddress) public {
require(orderList[hashlock].initiatorOntAddress == msg.sender, "Only initiator can set buyer address");
require(orderList[hashlock].status == Status.Locked, "Transaction in Invalid State");
require(orderList[hashlock].refundTimelock>block.timestamp, "Time Ended");
// Only initiator can reach here
orderList[hashlock].buyerOntAddress = buyerOntAddress;
orderList[hashlock].status = Status.Set;
}
function claimOnt (bytes32 hashlock, string memory secret) public {
require(orderList[hashlock].buyerOntAddress == msg.sender, "Can only be perfomed by order buyer");
require(orderList[hashlock].status == Status.Set, "Order status should be Locked");
require(orderList[hashlock].refundTimelock>block.timestamp, "Claim time finished");
require(sha256(abi.encodePacked(secret)) == hashlock, "Secret does not match the hashlock");
orderList[hashlock].status = Status.Claimed;
payable(msg.sender).transfer(orderList[hashlock].amountOnt);
//Transaction Finished. Make the hash ready for probable other txn
clear(hashlock);
}
function refundOnt (bytes32 hashlock) public {
require(orderList[hashlock].initiatorOntAddress == msg.sender, "Can only be perfomed by order initiator");
require(block.timestamp >= orderList[hashlock].refundTimelock, "Timelock is not over");
orderList[hashlock].status = Status.Refunded;
payable(msg.sender).transfer(orderList[hashlock].amountOnt);
//Transaction Finished. Make the hash ready for probable other txn
clear(hashlock);
}
function clear(bytes32 hashlock) private {
orderList[hashlock] = initiatedOrder({
buyerOntAddress: address(0),
buyerEthAddress: address(0),
initiatorOntAddress: address(0),
initiatorEthAddress: address(0),
hashlock: bytes32(0),
amountOnt: 0,
refundTimelock: 0,
initiatedTime: 0,
secret: "",
status: Status.Blank
});
}
}
require("@nomicfoundation/hardhat-toolbox");
const fs = require('fs');
const privateKey = fs.readFileSync(".secret").toString().trim();
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: {
version: "0.8.17",
settings: {
optimizer: {
enabled: true,
runs: 200
}
}
},
networks: {
hardhat: {},
ontology_testnet: {
url: "http://polaris2.ont.io:20339",
chainId: 5851,
accounts: [privateKey],
allowUnlimitedContractSize: true
},
goerli: {
url: "https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161",
accounts: [privateKey],
chainId: 5,
allowUnlimitedContractSize: true
}
},
};
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const txnsSchema = new Schema({
hashlock: {
type: String,
required: true,
},
amountOnt: {
type: String,
required: true,
},
bidTimelock: {
type: String,
required: true
},
}, { timestamps: true });
const txns = mongoose.model('txns', txnsSchema);
module.exports = txns;
\ No newline at end of file
This diff is collapsed.
{
"name": "finalproject",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@nomicfoundation/hardhat-toolbox": "^2.0.0",
"hardhat": "^2.12.2"
},
"dependencies": {
"ejs": "^3.1.8",
"mongodb": "^4.12.0",
"mongoose": "^6.7.2",
"morgan": "^1.10.0",
"web3": "^1.8.1"
}
}
This diff is collapsed.
.netbut {
background-color: black !important;
}
.centeralign{
text-align:center;
}
.setmargin{
margin-left: 2%;
}
.mnbt {
display: inline;
margin: 10px 0;
padding: 10px;
width: 24%;
}
.mnbt2 {
display: inline;
margin: 10px 0;
padding: 10px;
width: 19%;
}
.mytext {
width: 300px;
}
body{
background-image: url('/background.jpg');
background-repeat: no-repeat;
background-attachment: fixed;
background-size: cover;
}
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td, th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
const { ethers } = require("hardhat");
async function main() {
const [deployer] = await ethers.getSigners();
console.log('Deploying contracts with the account: ' + deployer.address);
// Deploy First
const EthereumContract = await ethers.getContractFactory('EthereumContract');
const first = await EthereumContract.deploy();
// Deploy Second
// const Second = await ethers.getContractFactory('SecondContract');
// const second = await Second.deploy(first.address);
console.log( "First: " + first.address );
// console.log( "Second: " + second.address );
}
main()
.then(() => process.exit())
.catch(error => {
console.error(error);
process.exit(1);
})
\ No newline at end of file
const { ethers } = require("hardhat");
async function main() {
const [deployer] = await ethers.getSigners();
console.log('Deploying contracts with the account: ' + deployer.address);
// Deploy First
const OntologyContract = await ethers.getContractFactory('OntologyContract');
const first = await OntologyContract.deploy();
// Deploy Second
// const Second = await ethers.getContractFactory('SecondContract');
// const second = await Second.deploy(first.address);
console.log( "First: " + first.address );
// console.log( "Second: " + second.address );
}
main()
.then(() => process.exit())
.catch(error => {
console.error(error);
process.exit(1);
})
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>Atomic Swap</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<script src='/web3.min.js'></script>
<link rel="stylesheet" href="/style.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<h1 class="centeralign"">Atomic Swap</h1>
<br >
<div class="centeralign">
<h4>Select Chain</h4>
<button type="button" class="btn btn-primary" id="ONTBut" onclick="hideElement('ETH'); showElement('ONT');">ONT</button>
<button type="button" class="btn btn-primary" id="ETHBut" onclick="hideElement('ONT'); showElement('ETH');">ETH</button>
</div>
<hr>
<div class="centeralign" id = "ONT">
<!-- ORDER STATUS -->
<div>
<label for="hashlock">Enter hash: </label>
<input type="text" name="hashlock" id="hash5">
<button onclick="printOrderListOnt(document.getElementById('hash5').value);">Get Order Details</button>
<div id="orderListOnt"></div>
<div id="bidtimer1"></div>
</div>
<hr>
<!-- BUTTONS TO SELECT STEPS -->
<div>
<button class="mnbt" id="ibl" onclick="showhide('ibl');">Initiate by Locking</button>
<button class="mnbt" id="sba" onclick="showhide('sba');">Set Buyer Address</button>
<button class="mnbt" id="co" onclick="showhide('co');">Claim ONT</button>
<button class="mnbt" id="ro" onclick="showhide('ro');">Refund ONT</button>
</div>
<hr>
<!-- INITIATING EXCHANGE BY LOCKING TOKENS -->
<div name="block" id="ibl1">
<label for="hashlock">Enter hash: </label>
<input type="text" name="hashlock" id="hash1"><br><br>
<label for="amountOnt">Enter ONT tokens to exchange: </label>
<input type="text" name="amountOnt" id="amountOnt"><br><br>
<label for="initiatorEthAddress">Enter your ETH Address:</label>
<input type="text" name="initiatorEthAddress" id="initiatorEthAddress1"><br><br>
<button onclick="initiateOrder(document.getElementById('hash1').value, document.getElementById('amountOnt').value, document.getElementById('initiatorEthAddress1').value);">Initiate by Locking</button>
</div>
<!-- SETTING BUYER ADDRESS -->
<div name="block" id="sba1">
<label for="hashlock">Enter hash: </label>
<input type="text" name="hashlock" id="hash2"><br><br>
<label for="buyerOntAddress">Enter Buyer ONT Address: </label>
<input type="text" name="buyerOntAddress" id="buyerOntAddress1"><br><br>
<button onclick="setBuyerAddr(document.getElementById('hash2').value, document.getElementById('buyerOntAddress1').value);">Set Buyer Address</button>
</div>
<!-- CLAIM ONT TOKENS BY 2ND PARTY -->
<div name="block" id="co1">
<label for="hashlock">Enter hash: </label>
<input type="text" name="hashlock" id="hash3"><br><br>
<label for="secret">Enter Secret: </label>
<input type="text" name="secret" id="secret1"><br><br>
<button onclick="claimOnt(document.getElementById('hash3').value, document.getElementById('secret1').value);">Claim ONT</button>
</div>
<!-- REFUND ONT TOKENS BY INTITIATOR -->
<div name="block" id="ro1">
<label for="hashlock">Enter hash: </label>
<input type="text" name="hashlock" id="hash4"><br><br>
<button onclick="refundOnt(document.getElementById('hash4').value);">Refund ONT</button>
</div>
<hr>
</div>
<!-- ==================================================================================================================================== -->
<div class="centeralign" id = "ETH" >
<!-- ORDER STATUS -->
<div>
<label for="hashlock">Enter hash: </label>
<input type="text" name="hashlock" id="hash6">
<button onclick="printOrderListEth(document.getElementById('hash6').value);">Get Order Details</button>
<div id="orderListEth"></div>
<div id="bidtimer2"></div>
</div>
<hr>
<!-- BUTTONS TO SELECT STEPS -->
<div>
<button class="mnbt2" id="ib" onclick="showhide2('ib');">Initiate Bidding</button>
<button class="mnbt2" id="b" onclick="showhide2('b');">Bid</button>
<button class="mnbt2" id="sia" onclick="showhide2('sia');">Set Initiator Address</button>
<button class="mnbt2" id="ce" onclick="showhide2('ce');">Claim ETH</button>
<button class="mnbt2" id="re" onclick="showhide2('re');">Refund ETH</button>
</div>
<!-- INITIATE BIDDING -->
<div name="block2" id="ib1">
<label for="hashlock">Enter hash: </label>
<input type="text" name="hashlock" id="hash11"><br><br>
<button onclick="getBidTimeLock(document.getElementById('hash11').value, 'bidtimer1');">Initiate Bidding</button>
</div>
<iframe name="votar" style="display:none;"></iframe>
<form id="todb" action="/txns" method="post" target="votar">
<input type="hidden" name="hashlock" id="hash12"><br><br>
<input type="hidden" name="amountOnt" id="amountOnt3"><br><br>
<input type="hidden" name="bidTimelock" id="bidTimelock3"><br><br>
<input style="display: none;" type="submit" value="Send to Database">
</form>
<!-- BIDDING -->
<div name="block2" id="b1">
<label for="hashlock">Enter hash: </label>
<input type="text" name="hashlock" id="hash7"><br><br>
<label for="bidprice">Enter tokens to Bid: </label>
<input type="text" name="bidprice" id="bidprice"><br><br>
<label for="buyerOntAddress">Enter your ONT Address:</label>
<input type="text" name="buyerOntAddress" id="buyerOntAddress2"><br><br>
<button onclick="bid(document.getElementById('hash7').value, document.getElementById('bidprice').value, document.getElementById('buyerOntAddress2').value);">Bid</button>
</div>
<!-- SET INITIATOR ADDRESS -->
<div name="block2" id="sia1">
<label for="hashlock">Enter hash: </label>
<input type="text" name="hashlock" id="hash8"><br><br>
<label for="initiatorEthAddress">Enter Initiator ETH Address: </label>
<input type="text" name="initiatorEthAddress" id="initiatorEthAddress2"><br><br>
<button onclick="setInitiatorAddr(document.getElementById('hash8').value, document.getElementById('initiatorEthAddress2').value);">Set Initiator Address</button>
</div>
<!-- CLAIM ETH TOKENS BY 2ND PARTY -->
<div name="block2" id="ce1">
<label for="hashlock">Enter hash: </label>
<input type="text" name="hashlock" id="hash9"><br><br>
<label for="secret">Enter Secret: </label>
<input type="text" name="secret" id="secret2"><br><br>
<button onclick="claimEth(document.getElementById('hash9').value, document.getElementById('secret2').value);">Claim ETH</button>
</div>
<!-- REFUND ETH TOKENS BY INTITIATOR -->
<div name="block2" id="re1">
<label for="hashlock">Enter hash: </label>
<input type="text" name="hashlock" id="hash10"><br><br>
<button onclick="refundEth(document.getElementById('hash10').value);">Refund ETH</button>
</div>
<hr>
</div>
<div>
Status: <span id="status">Loading...</span>
</div>
<script src="/script.js"></script>
</body>
</html>
<html lang="en">
<head>
<meta charset='utf-8'>
<!-- <meta http-equiv='X-UA-Compatible' content='IE=edge'> -->
<!-- <meta http-equiv="refresh" content="15"> -->
<title><%= title %></title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel="stylesheet" href="/style.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="centeralign setmargin">
<h1><strong>Transactions</strong></h1>
<br>
<% if (txns.length > 0) { %>
<table>
<tr><th>Hash</th><th>Amount ONT Locked</th><th>Bid Time</th></tr>
<% txns.forEach(txn => { %>
<tr>
<td><%= txn.hashlock %></td>
<td><%= txn.amountOnt %></td>
<td><%= txn.bidTimelock %></td>
</tr>
<% }) %>
</table>
<% } else { %>
<p>There are no transactions to display...</p>
<% } %>
</div>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment