Hello, I am having an issue here and was wondering if someone could assist me please. There seems to be a migration issue in my code since truffle test is not recognizing functions in Wallet/Dex file. My createLimitOrder function is not complete at the moment, however the first 6 tests should be passing but only 4 are at the moment. Here is my full code
wallet.sol
pragma solidity ^0.8.0;
import “…/node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol”;
import “…/node_modules/@openzeppelin/contracts/utils/math/SafeMath.sol”;
import “…/node_modules/@openzeppelin/upgrades/contracts/ownership/Ownable.sol”;
contract Wallet is OpenZeppelinUpgradesOwnable {
using SafeMath for uint256;
struct Token {
bytes32 ticker;
address tokenAddress;
}
mapping(bytes32 => Token) public tokenMapping;
bytes32[] public tokenList;
mapping(address => mapping(bytes32 => uint256)) public balances;
modifier tokenExists(bytes32 ticker){
require(tokenMapping[ticker].tokenAddress != address(0), "Token does not exist");
_;
}
function addToken(bytes32 ticker, address tokenAddress) onlyOwner external {
tokenMapping[ticker] = Token(ticker, tokenAddress);
tokenList.push(ticker);
}
function deposit(uint amount, bytes32 ticker) tokenExists(ticker) external {
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) tokenExists(ticker) external {
require(balances[msg.sender][ticker] >= amount, "Balance not sufficient");
balances[msg.sender][ticker] = balances[msg.sender][ticker].sub(amount);
IERC20(tokenMapping[ticker].tokenAddress).transfer(msg.sender, amount);
}
}
dex.sol
pragma solidity ^0.8.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;
Side side;
bytes32 ticker;
uint amount;
uint price;
}
uint public nextOrderId = 0;
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));
}
else if(side == Side.SELL){
require(balances[msg.sender]["ticker"] >= amount);
}
Order[] storage orders = orderBook[ticker][uint(side)];
orders.push(
Order(nextOrderId, msg.sender, side, ticker, amount, price)
);
//Bubble sort
if(side == Side.BUY){
}
else if(side == side.SELL){
}
nextOrderId++;
}
}
Migrations.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
contract Migrations {
address public owner = msg.sender;
uint public last_completed_migration;
modifier restricted() {
require(
msg.sender == owner,
“This function is restricted to the contract’s owner”
);
_;
}
function setCompleted(uint completed) public restricted {
last_completed_migration = completed;
}
}
toke.sol
pragma solidity ^0.8.0;
import “…/node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol”;
contract Link is ERC20 {
constructor() ERC20(“Chainlink”, “Link”) public {
_mint(msg.sender, 1000);
}
}
The following are my 3 migration files:
1_initial_migration.js
const Migrations = artifacts.require(“Migrations”);
module.exports = function (deployer) {
deployer.deploy(Migrations);
};
2_dex_migration.js
const Dex = artifacts.require(“Dex”);
module.exports = function (deployer) {
deployer.deploy(Dex);
};
3_token_migration.js
const Link = artifacts.require(“Link”);
const Dex = artifacts.require(“Dex”);
module.exports = async function (deployer, network, accounts) {
await deployer.deploy(Link);
};
Please see my following test files:
wallettest.js
const Dex = artifacts.require(“Dex”)
const Link = artifacts.require(“Link”)
const truffleAssert = require(‘truffle-assertions’);
contract(“Dex”, accounts => {
it(“should only 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(“AAVE”), link.address, {from: accounts[1]})
)
})
it(“should should handle deposits correctly”, async () => {
let dex = await Dex.deployed()
let link = await Link.deployed()
await link.approve(dex.address, 500);
await dex.deposit(100, web3.utils.fromUtf8(“LINK”));
let balance = await dex.balances(accounts[0], web3.utils.fromUtf8(“LINK”))
assert.equal( balance.toNumber(), 100 )
})
it(“should should handle faulty withdrawls correctly”, async () => {
let dex = await Dex.deployed()
let link = await Link.deployed()
await truffleAssert.reverts(dex.withdraw(500, web3.utils.fromUtf8(“LINK”)))
})
it(“should should handle correct withdrawls correctly”, async () => {
let dex = await Dex.deployed()
let link = await Link.deployed()
await truffleAssert.passes(dex.withdraw(100, web3.utils.fromUtf8(“LINK”)))
})
})
dextest.js
const Dex = artifacts.require(“Dex”)
const Link = artifacts.require(“Link”)
const truffleAssert = require(‘truffle-assertions’);
contract(“Dex”, accounts => {
//The user must have ETH deposited such that deposited eth >= buy order value
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, web3.utils.fromUtf8(“LINK”), 10, 1)
)
dex.depositEth({value: 10})
await truffleAssert.passes(
dex.createLimitOrder(0, web3.utils.fromUtf8(“LINK”), 10, 1)
)
})
//The user must have anough tokens deposited such that 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 truffleAsset.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(web3.utils.fromUtf8(“LINK”), 10)
await truffleAssert.passes(
dex.createLimitOrder(1, web3.utils.fromUtf8(“LINK”), 10, 1)
)
})
//The BUY order book should be ordered on price from highest to lowest starting at index 0
it(“The BUY order book should be ordered on price from highest 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 createLimitOrder(0, web3.utils.fromUtf8(“LINK”), 1, 300)
await createLimitOrder(0, web3.utils.fromUtf8(“LINK”), 1, 100)
await createLimitOrder(0, web3.utils.fromUtf8(“LINK”), 1, 200)
let oderbok = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 0);
assert(orderbook.length > 0);
for (let i = 0; i < oderbook.length -1; i++) {
assert(orderbook[i].price >= orderbook[i+1].price, "not right order in buy book")
}
})
//The SELL order book should be ordered on price from lowest to highest starting at index 0
it(“he SELL order book should be ordered on price from lowest to highest starting at index 0”, async () => {
let dex = await Dex.deployed()
let link = await Link.deployed()
await link.approve(dex.address, 500)
await createLimitOrder(1, web3.utils.fromUtf8(“LINK”), 1, 300)
await createLimitOrder(1, web3.utils.fromUtf8(“LINK”), 1, 100)
await createLimitOrder(1, web3.utils.fromUtf8(“LINK”), 1, 200)
let oderbok = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 1);
assert(orderbook.length > 0);
for (let i = 0; i < oderbook.length -1; i++) {
assert(orderbook[i].price <= orderbook[i+1].price, "not right order in sell book")
}
})
})
When running this code with truffle test I get the following errors:
Contract: Dex
√ should only possible for owner to add tokens (1130ms)
√ should should handle deposits correctly (1540ms)
√ should should handle faulty withdrawls correctly (1071ms)
√ should should handle correct withdrawls correctly (1118ms)
4 passing (10s)
4 failing
-
Contract: Dex
should throw an error if ETH balance is too low when creating BUY limit order:
TypeError: dex.depositEth is not a function
at Context. (test\dextest.js:12:13)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
-
Contract: Dex
should throw an error if token balance is too low when creating SELL limit order:
ReferenceError: truffleAsset is not defined
at Context. (test\dextest.js:21:9)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
-
Contract: Dex
The BUY order book should be ordered on price from highest to lowest starting at index 0:
TypeError: dex.depositEth is not a function
at Context. (test\dextest.js:36:19)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
-
Contract: Dex
he SELL order book should be ordered on price from lowest to highest starting at index 0:
ReferenceError: createLimitOrder is not defined
at Context. (test\dextest.js:53:7)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
functions are not recognized for some reason, which makes me believe that this is a migration issue. However I went through the videos again and I cannot find any difference between mine and Filip’s code. Since Dex inherits from Wallet I think that Wallet does not need its own migration file right?
Any help would be greatly appreciated.
Thank you,
Youssef