Hello.
Iāve been fiddling with these test scripts, Iām back to having it almost exactly as Filip did in the solution video. The problem is I canāt be sure what is wrong with my code. Below is my dex.sol code, but Iām more interested in what Iām doing wrong with the test:
dex.sol:
pragma solidity ^0.8.4;
pragma experimental ABIEncoderV2;
import "./wallet.sol";
contract Dex is Wallet{
using SafeMath for uint256;
enum Side{
BUY,
SELL
}
struct Order{
uint id;
//some way to implement timestamp from the JS front end to resolve equal orders
address trader;
Side side;
string ticker;
uint amount;
uint price;
}
uint public orderIds = 0;
mapping(string => mapping(uint => Order[])) public orderBook;
receive ()external payable{
depositEth();
}
// fallback () external payable{
// depositEth();
// }
function getOrderBook(string memory _ticker, Side side) public view returns(Order[] memory){
return orderBook[_ticker][uint(side)];
}
function incrimentOrderIds() private{
orderIds ++;
}
function depositEth() public payable{
balances[msg.sender]["ETH"] = balances[msg.sender]["ETH"].add(msg.value);
}
function shouldISwap(uint price1, uint price2, Side side) private pure returns(bool){
bool doSwap;
if(side == Side.SELL){
if(price1 > price2){ return true;}
}
if(side == Side.BUY){
if(price1 < price2){ return true;}
}
return false;
}
function bubbleSortOrderBook(string memory ticker, Side side, uint sortWasMade) internal returns(bool){
//test if cheaper to use nested loops, or include a recursive function call as part of process
//designing function arguments to use function recursively
bool isSorted;
if(sortWasMade == 0){ return true; }
Order[] storage bookToSort = orderBook[ticker][uint(side)];
sortWasMade = 0;
for(uint i = 0; i < bookToSort.length - 2; i++){
if(shouldISwap(bookToSort[i].price, bookToSort[i + 1].price, side)){
//swapOrders(ticker, side, i, i+1);
Order memory tempOrder = bookToSort[1];
bookToSort[i] = bookToSort[i + 1];
bookToSort[i + 1] = tempOrder;
sortWasMade++;
}
}
//at this point if no new sort was made, we will pass a 0 to the bubblesort call again, yielding a true return
return bubbleSortOrderBook(ticker, side, sortWasMade);
}
function swapOrders(string memory ticker, Side side, uint firstOrderIndex, uint secondOrderIndex) internal {
Order memory tempOrder = orderBook[ticker][uint(side)][firstOrderIndex];
orderBook[ticker][uint(side)][firstOrderIndex] = orderBook[ticker][uint(side)][secondOrderIndex];
orderBook[ticker][uint(side)][secondOrderIndex] = tempOrder;
}
function createLimitOrder(Side side, string memory ticker, uint amount, uint price) public returns(bool){
if(side == Side.BUY){
require(balances[msg.sender]["ETH"] >= amount.mul(price));
}
else if(side == Side.SELL){
require(balances[msg.sender][ticker] >= amount);
}
Order[] storage orders = orderBook[ticker][uint(side)];
orders.push(
Order(orderIds, msg.sender, side, ticker, amount, price)
);
if(side == Side.BUY){
bubbleSortOrderBook(ticker, side, 1);
}
else if(side == Side.SELL){
bubbleSortOrderBook(ticker, side, 1);
}
orderIds ++;
bubbleSortOrderBook(ticker, side, 1);
return true;
}
}
When I run the test script dextest.js:
const Dex = artifacts.require("Dex");
const Link = artifacts.require("Link");
const truffleAssert = require('truffle-assertions');
contract("Dex", accounts => {
it("should throw an error if ETH balance is too low when creating BUY limit order", async () => {
let dex = await Dex.deployed()
let link = await Link.deployed()
//await truffleAssert.reverts(
// dex.createLimitOrder(0, "LINK", 10, 1)
//)
dex.depositEth({value: 10})
await truffleAssert.passes(
dex.createLImitOrder(0, "LINK", 10, 1)
)
})
//user must have enough tokens deposited such that the token balance >= sell order amount
it("should throw an error if token balance is too low when creating SELL limit order", async () => {
let dex = await Dex.deployed()
let link = await Link.deployed()
await truffleAssert.reverts(
dex.createLimitOrder(1, "LINK", 10, 1)
)
await link.approve(dex.address, 500)
await dex.deposit(10, "LINK")
truffleAssert.passes(
dex.createLimitOrder(1, "LINK", 10, 1)
)
})
//The BUY order book should be ordered on price from hightest to lowest starting at index 0
it("The BUY order book should be ordered on price from hightest to lowest starting at index 0", async () => {
let dex = await Dex.deployed()
let link = await Link.deployed()
await link.approve(dex.address, 500)
await dex.depositEth({value: 3000})
await dex.createLimitOrder(0, "LINK", 1, 300)
await dex.createLimitOrder(0, "LINK", 1, 100)
await dex.createLimitOrder(0, "LINK", 1, 200)
let orderbook = await dex.getOrderBook("LINK", Side.BUY)
assert(orderbook.length > 0)
//aorderbook[0] = await new dex.Order(1011, msg.sender, BUY, "LINK", 23, 32)
for(let i = 0; i < orderbook.length - 1; i++) {
assert(orderbook[i] >= orderbook[i+1], "not right order in the BUY book")
}
})
//The SELL order book should be ordered on price from lowest to highest starting at index 0
it("SELL order book should be ordered on price from lowest to hightest starting at index 0", async () => {
let dex = await Dex.deployed()
let link = await Link.deployed()
await link.approve(dex.address, 500)
await dex.createLimitOrder(1, "LINK", 1, 300)
await dex.createLimitOrder(1, "LINK", 1, 100)
await dex.createLimitOrder(1, "LINK", 1, 200)
new Promise(() => console.log(dex.balances[msg.sender]["LINK"]));
//console.log(dex.balances[msg.sender]["ETH"]);
let orderbook = await dex.getOrderBook("LINK", 1)
assert(orderbook.length > 0);
for (let i = 0; i < orderbook.length - 1; i++){
assert(orderbook[i] <= orderbook[i + 1], "check your SELL orderbook ordering")
}
})
})
I get the following errors:
1) Contract: Dex
should throw an error if ETH balance is too low when creating BUY limit order:
TypeError: dex.createLImitOrder is not a function
at Context.<anonymous> (test\dextests.js:17:17)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
2) Contract: Dex
should throw an error if token balance is too low when creating SELL limit order:
Error: Returned error: VM Exception while processing transaction: revert token does not exist -- Reason given: token does not exist.
at Context.<anonymous> (test\dextests.js:28:19)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
3) Contract: Dex
The BUY order book should be ordered on price from hightest to lowest starting at index 0:
Error: Returned error: VM Exception while processing transaction: revert
at Context.<anonymous> (test\dextests.js:40:19)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
4) Contract: Dex
SELL order book should be ordered on price from lowest to hightest starting at index 0:
Error: Returned error: VM Exception while processing transaction: revert
at Context.<anonymous> (test\dextests.js:56:19)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
Part of me wonders if maybe Iām exceeding the gas limit for a single function call? The tests from the wallettest.js file from earlier in the course pass just fine.
Also, Iād like to know what Iām doing that wonāt allow console.log() to work from inside my truffle test.
Iām sure my contract needs some work, but until I know what Iām doing thatās causing my tests to fail, I canāt really tell if Iām making proper changes or not. Thanks for the input!
David