can u share your other code files. seems to be an issue with your migratons the compiler isnt recognising aritfacts.require()
@Tomahawk also sorry just forgot to say are you definitely initialising dex and then adding, approving and depositing before you create the limit order. sorry meant to ask that just going off the small code snipit your provided above.
Sorry, you are right. I just forgot that since I had to have a pause for a week It is better to do it continuously. When I did all the steps (I basically copied commands from dextest.js) it went through ok.
However I tried it with my previous bubble sort and createLimitOrder works as well. So it is weird that with both solutions all steps and createLimitOrder goes through ok manually, but dextest.js goes wrong on the 1) test only with my solution.
Yeah i cant rember fully but when i tried it myself with your code i think i was getting an index out of range error. but thats great that its working now. You should play around and write more tests. manually doing them also is a great way to understand exactly what your code is doing. If you go to the forum for the final dex project i wrote a samll post sharing some tips that i found helpful when doing this myself and debuging (because i too was struggling a lot for awhile) if you go read it youll see what i mean (in terms of debugging). I found it really helpful going through my code line by line on paper and eventually youll find the line where your code fails.
Thanks I read your tips and I actually also did it with paper and pen in previous projects. Not in this one thou.
Anyway, it still does not work, except one part To make it easier for now to go through the testing for the first time, I actually copied bubble sort from Philipâs final code on github and also I copied some parts of the testing. Here is the link for my code:
https://github.com/tommahawk25/Dex-v2
And I started to test it manually line by line. Everything works except the 3rd test âBuy order book should be ordered from highest to lowestâ
when I run
assert(orderbook[0].price >= orderbook[1].price, ânot right order in buy bookâ)
It says undefined instead of giving me true or false. Donât really understand what could be wrong here, since for example assert(orderbook.length >0)
does work. And also console.log(orderbook[0].price)
does work.
This is really strange. Any idea?
Ohh ok i see. You should actually not do the actually asserts in the console. Undefined is not an error. Its much like when you say let dex = await Dex.deployed() and when you press enter it says undefined. If you want to manually test in the console like you are now to see if your orderbook is soted correctly you can do this.
truffle(develop)> let orderBook = dex.getOrderbook(uint(side), ticker)
//where uint(side) is 0 or 1 depending on what side of the orderbook your oder is in
//and ticker just is the ticker
**(Note make sure you have actually written the get orderbook function. If you dont it just returns the orderBook struct, but i think Filip covers it in one of the videos so you should have it)**
then when you what you can do is call orderBook like this
truffle(develop)> orderBook
and it will return all of the entries in the orderbook and you can just compare them it should be ordered highest to lowest by price. Now that you know if they are then when you run truffle test
, your tests should pass.
The only thing that may cause you hiccups sometimes is the await keyword. But what you should know is if you do it like ive shown above and the orderbook is ordered then your tests should pass, if they dont just play around with them and be careful with the await keyword and the order in which you declare vairiables.
Everything you said I actually already did. I know that the order is right. I just coudnât get this assert. I thought when assert(orderbook.length >0)
works then the other assert has to work as well. But okay.
However truffle test
does not work. I have the 3rd test according to Filipâs one.
This is what is strange. Manually it is okay but with dextest.js it gives errors
Is this the same as with manual? That the assert gives undefined and therefore test goes wrong with AssertionError?
@Tomahawk, Yeah this is what i meant about the await keyword Now im not too adept in javascript but i think because these are all async functions the some of the function calls dont all finish at the same time so this fact can cause issues thats my theory anyway but i could be wrong so take that with a grain of salt⌠When i was doing my testing i ran into these issues the whole time aswell even when i know my tests should pass because i had manually tested them but sometimes they didnt. Its a weird one you just have to play around with your tests. If you can push your code again ill play around with your tests later this evening and see what i can do. Its just all about trying different things and sticking at it. I remember it took me a whole day alone to get my limit order tests working lol
@mcgrane5 I have checked âawaitâ already before according to Filipâs code. There wasnât the problem.
However I finally found the mistake! Stupid typo in dextest.js! Rofl. I didinât really checked for typos because I was used to .sol file where it gave the errors. Didnât know that .js files doesnât give errors. Learnt something new at least.
Now I can continue with my code. Thank you for your time! I know it was really exhausting.
const Link = artifacts.require("Link");
const Dex = artifacts.require("Dex");
module.exports = async function (deployer, network, accounts) {
await deployer.deploy(Link);
let dex = await Dex.deployed()
let link = await Link.deployed()
await link.approve(dex.address, 500)
dex.addToken(web3.utils.fromUtf8("LINK"), link.address)
await dex.deposit(100, web3.utils.fromUtf8("LINK"))
let balanmceOfLink = dex.balances(accounts[0], web3.utils.fromUtf8("LINK"));
console.log(balanmceOfLink);
};
const Dex = artifacts.require(âDexâ);
module.exports = function (deployer) {
deployer.deploy(Dex);
};
````const Migrations = artifacts.require("Migrations");
module.exports = function (deployer) {
deployer.deploy(Migrations);
};``
const Dex = artifacts.reqiure(âDexâ)
const Link = artifacts.reqiure(âLINKâ)
const truffleAssert = require(âtruffle-assertionsâ);
contract(âDexâ, accounts => {
it(âshould only be possible for owner to add tokensâ, async () => {
let dex = await Dex.deployed()
let link = await Link.deployed()
await truffleAssert.passes(
dex.addToken(web3.utils.fromUtf8(âLINKâ), link.address, {from: accounts[0]})
)
await truffleAssert.reverts(
dex.addToken(web3.utils.fromUtf8(âLINKâ), link.address, {from: accounts[1]})
)
})
it(âshould handle deposits correctlyâ, async () => {
let dex = await Dex.deployed()
let link = await Link.deployed()
link.approve(dex.address, 500);
dex.deposit(100, web3.utils.fromUtf8(âLINKâ));
let balance = await dex.balances(accounts[0], web3.utils.fromUtf8(âLINKâ))
truffleAssert.equal(balanc.toNumber(), 100 )
})
it("should handle withdraws correctly", async () => {
let dex = await Dex.deployed()
let link = await Link.deployed()
await truffleAssert.reverts(dex.withdraw(500, web3.utils.fromUtf8("LINK")))
})
it("should handle correct withdraws correctly", async () => {
let dex = await Dex.deployed()
let link = await Link.deployed()
await truffleAssert.passes(dex.withdraw(500, web3.utils.fromUtf8("LINK")))
})
})
const Dex = artifacts.reqiure("Dex")
const Link = artifacts.reqiure("LINK")
const truffleAssert = require('truffle-assertions');
contract("Dex", accounts => {
it("should only be possible for owner to add tokens", async () => {
let dex = await Dex.deployed()
let link = await Link.deployed()
await truffleAssert.passes(
dex.addToken(web3.utils.fromUtf8("LINK"), link.address, {from: accounts[0]})
)
await truffleAssert.reverts(
dex.addToken(web3.utils.fromUtf8("LINK"), link.address, {from: accounts[1]})
)
})
it("should handle deposits correctly", async () => {
let dex = await Dex.deployed()
let link = await Link.deployed()
link.approve(dex.address, 500);
dex.deposit(100, web3.utils.fromUtf8("LINK"));
let balance = await dex.balances(accounts[0], web3.utils.fromUtf8("LINK"))
truffleAssert.equal(balanc.toNumber(), 100 )
})
it("should handle withdraws correctly", async () => {
let dex = await Dex.deployed()
let link = await Link.deployed()
await truffleAssert.reverts(dex.withdraw(500, web3.utils.fromUtf8("LINK")))
})
it("should handle correct withdraws correctly", async () => {
let dex = await Dex.deployed()
let link = await Link.deployed()
await truffleAssert.passes(dex.withdraw(500, web3.utils.fromUtf8("LINK")))
})
})
const Link = artifacts.require("Link");
const Dex = artifacts.require("Dex");
module.exports = async function (deployer, network, accounts) {
await deployer.deploy(Link);
let dex = await Dex.deployed()
let link = await Link.deployed()
await link.approve(dex.address, 500)
dex.addToken(web3.utils.fromUtf8("LINK"), link.address)
await dex.deposit(100, web3.utils.fromUtf8("LINK"))
let balanmceOfLink = dex.balances(accounts[0], web3.utils.fromUtf8("LINK"));
console.log(balanmceOfLink);
};
My deposit function looks different from filipâs, but I wondered if approval is necessary to complete the transfer effectively. If I am not mistaken, the approved statement checks if the funds are sufficient to send before allowing it to go through. So does this make my second require statement a little repetitive or not? Also is it okay to leave the approve statement even though filip never used it?
Hi,
can I have a quick question? In javascript test, why donât we have âawaitâ here at dex.depositEth({value: 20})
?
In Filipâs codes there are some tests, which contain dex.depositEth with await and some tests, which contain dex.depositEth without await. That is something I canâ understand. Thanks.
it("ETH deposit >= buy order value", async () => {
let dex = await Dex.deployed()
let link = await Link.deployed()
await dex.addToken(web3.utils.sha3("LINK"), link.address, {from: accounts[0]})
await truffleAssert.reverts(
//function createLimitOrder(side, ticker, amount, price)
dex.createLimitOrder(0, web3.utils.sha3("LINK"), 10, 1)
)
dex.depositEth({value: 20})
await truffleAssert.passes(
//function createLimitOrder(side, ticker, amount, price)
dex.createLimitOrder(0, web3.utils.sha3("LINK"), 10, 1)
)
})
Hi @DJaySplash
This statement is not correct:
If I am not mistaken, the approved statement checks if the funds are sufficient to send before allowing it to go through.
The approve statement sets an allowance from _spender and allows that address to move funds from another wallet.
Check out the approval function code
Cheers,
Dani
Hi @Tomahawk
All contract interactions are async so you should always use await.
Using await makes sure that the code is executed before moving to the next line of code.
Cheers,
Dani
Hi All,
Here is my code with the Bubble Sort implemented. Pardon me if this code looks too long and not optimized enough. Would like to get it reviewed with @dan-i and @mcgrane5.
DEX.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
import "../contracts/wallet.sol";
contract Dex is Wallet {
using SafeMath for uint256;
enum Side {
BUY,
SELL
}
struct Order {
uint id;
address trader;
Side side;
bytes32 ticker;
uint amount;
uint price;
}
mapping(bytes32 => mapping(uint => Order[])) public orderBook;
uint orderId = 0;
function getOrderBook(bytes32 ticker, Side side) view public returns (Order[] memory) {
return orderBook[ticker][uint(side)];
}
function createLimitOrder(bytes32 ticker, Side side, uint amount, uint price) public {
uint ethBalance;
uint tokenBalance;
Order memory _order = Order(orderId, msg.sender, side, ticker, amount, price);
ethBalance = balances[msg.sender][bytes32("ETH")];
tokenBalance = balances[msg.sender][ticker];
if (side == Side.BUY){
require(ethBalance >= amount.mul(price), "Eth balance is not enough");
orderBook[ticker][uint(side)].push(_order);
sortDescending(orderBook[ticker][uint(side)]);
orderId++;
}
if (side == Side.SELL){
require(tokenBalance >= amount, "Token balance is not enough");
orderBook[ticker][uint(side)].push(_order);
sortAescending(orderBook[ticker][uint(side)]);
orderId++ ;
}
}
function sortDescending(Order[] memory orders) private pure{
// Bubble Sort
uint l = orders.length;
bool swap = true;
uint numSwap = 0;
while(swap){
for(uint i = 0; i < l -1; i++){
Order memory temp;
if (orders[i].price < orders[i+1].price){
temp = orders[i];
orders[i] = orders[i+1];
orders[i+1] = temp;
numSwap++;
swap = true;
}
}
if (numSwap == 0){
swap = false;
}
}
}
function sortAescending(Order[] memory orders) private pure{
// Bubble Sort
uint l = orders.length;
bool swap = true;
uint numSwap = 0;
while(swap){
for(uint i = 0; i < l -1; i++){
Order memory temp;
if (orders[i].price > orders[i+1].price){
temp = orders[i];
orders[i] = orders[i+1];
orders[i+1] = temp;
numSwap++;
swap = true;
}
}
if (numSwap == 0){
swap = false;
}
}
}
}
code is also updated in github https://github.com/rays70/DEX
Cheers!