Hi, i am following the dex course and unfortunatly i spent a lot of time trying to solve an issue during the first test: āshould throw an error if ETH balance is too low when creating BUY limit orderā.
I saw and compare with the final code and i still get this error : AssertionError: Failed with Error: Returned error: VM Exception while processing transaction.
Did someone find what does it means ?
There is my code
Blockquote
Blockquote
pragma solidity >=0.4.22 <0.9.0;
pragma experimental ABIEncoderV2;
import ā./Wallet.solā;
contract Dex is Wallet {
using SafeMath for uint256;
enum Side {
BUY,
SELL
}
struct Order{
uint id;
address trader;
bool byOrder;
bytes32 ticker;
uint amount;
uint price;
}
mapping (bytes32 => mapping(uint => Order[])) public orderBook;
function getOrderBook(bytes32 ticker, Side side) view public returns(Order[] memory) {
return orderBook[ticker][uint(side)];
}
function createLimitOrder(Side side, bytes32 ticker, uint amount, uint price) public {
if(side == Side.BUY){
require(balances[msg.sender]["ETH"] >= amount.mul(price), "ETH balance is too low");
}else if (side == Side.SELL) {
require(balances[msg.sender][ticker] >= amount, "Low token balance");
}
}
}
Blockquote
contract Wallet is Ownable {
using SafeMath for uint256;
struct Token {
bytes32 ticker;
address tokenAddress;
}
mapping(bytes32 => Token) public tokenMapping;
bytes32[] public tokenList;
/**
* bytes32 pour faciliter les comparaisons car en solidity elles ne fonctionnent pas avec des string
*/
mapping(address => mapping(bytes32 => uint256)) public balances;
modifier tokenExist(bytes32 ticker) {
require(tokenMapping[ticker].tokenAddress != address(0), "Token doen't exist"); // check if the address exist so different to 0
_;
}
function addToken(bytes32 ticker, address tokenAddress) external onlyOwner {
tokenMapping[ticker] = Token(ticker, tokenAddress);
tokenList.push(ticker);
}
function deposit(uint amount, bytes32 ticker) public payable tokenExist(ticker) returns (uint) {
IERC20(tokenMapping[ticker].tokenAddress).transferFrom(msg.sender, address(this), amount);
balances[msg.sender][ticker] = balances[msg.sender][ticker].add(amount);
}
function withdraw(uint amount, bytes32 ticker) external tokenExist(ticker) returns (uint){
require(balances[msg.sender][ticker] >= amount, "Balance not sufficient"); // check the sufficient fund
balances[msg.sender][ticker] = balances[msg.sender][ticker].sub(amount);
IERC20(tokenMapping[ticker].tokenAddress).transfer(msg.sender, amount);
}
function depositEth() payable external {
balances[msg.sender][bytes32("ETH")] = balances[msg.sender][bytes32("ETH")].add(msg.value);
}
function withdrawEth(uint amount) external {
require(balances[msg.sender][bytes32("ETH")] >= amount,'Insuffient balance');
balances[msg.sender][bytes32("ETH")] = balances[msg.sender][bytes32("ETH")].sub(amount);
msg.sender.call{value:amount}("");
}
}
const Dex = artifacts.require(ādexā);
const Link = artifacts.require(āLinkā);
const truffleAssert = require(ātruffle-assertionsā);
contract(ādexā, function (accounts) {
it(āshould throw an error if ETH balance is too low when creating BUY limit orderā, async function () {
let dex = await Dex.deployed();
let link = await Link.deployed();
await truffleAssert.reverts(
dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 10, 1), "ETH balance is too low"
)
dex.depositEth({value: 10})
await truffleAssert.passes(
dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 10, 1)
)
});
it(āshould throw an error if token balance is too low when creating SELL limit orderā, async function () {
let dex = await Dex.deployed();
let link = await Link.deployed();
await truffleAssert.reverts(
dex.createLimitOrder(1, web3.utils.fromUtf8("LINK"), 10, 1)
)
await link.approve(dex.address, 500)
await dex.addToken(web3.utils.fromUtf8("LINK"), link.address, {from: accounts[0]})
await dex.deposit(10, web3.utils.fromUtf8("LINK"));
await truffleAssert.passes(
dex.createLimitOrder(1, web3.utils.fromUtf8, 10, 1)
)
});
it(āThe BUY order should be ordered on price from highest to lowest starting at index 0ā, async function () {
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, web3.utils.fromUtf8(āLINKā), 1, 300)
await dex.createLimitOrder(0, web3.utils.fromUtf8(āLINKā), 1, 100)
await dex.createLimitOrder(0, web3.utils.fromUtf8(āLINKā), 1, 200)
let orderbook = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 0)
console.log(orderbook)
for (let i = 0; i < orderbook.length - 1; i++) {
assert(orderbook[i].price >= orderbook[i+1].price, "not the right order in buy book")
}
});
it(āThe SELL order should be ordered on price from lowest to highest starting at index 0ā, async function () {
let dex = await Dex.deployed();
let link = await Link.deployed();
await link.approve(dex.address, 500)
await dex.depositEth({value: 3000});
await dex.createLimitOrder(1, web3.utils.fromUtf8(āLINKā), 1, 300)
await dex.createLimitOrder(1, web3.utils.fromUtf8(āLINKā), 1, 100)
await dex.createLimitOrder(1, web3.utils.fromUtf8(āLINKā), 1, 200)
let orderbook = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 1)
console.log(orderbook)
for (let i = 0; i < orderbook.length - 1; i++) {
assert(orderbook[i].price <= orderbook[i+1].price, "not the right order in buy book")
}
});
});