npm install -g embark
$ embark --version
4.1.0
embark new <Project Name>
pragma solidity 0.4.24;
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
contract MyFioriToken is ERC20 {
string public name;
string public symbol;
uint256 public decimals;
constructor(string _name, string _symbol, uint8 _decimals)
ERC20()
public
{
name = _name;
symbol = _symbol;
decimals = _decimals;
}
function deposit() public payable returns (bool) {
uint256 value = msg.value * 10**decimals;
increaseAllowance(msg.sender, value);
return mint(msg.sender, value);
}
function mint(address to, uint256 amount) public returns (bool) {
_mint(to, amount);
return true;
}
}
embark.json
file."solc":
and update the line to read "solc": "0.4.24",
.embark.json
file.contracts.js
file.contracts
sectioncontracts: {
// example:
//SimpleStorage: {
// args: [ 100 ]
//}
}
contracts: {
MyFioriToken: {
args: [ "My Fiori Token", "FIO", 0 ]
}
}
contracts.js
file.npm install openzeppelin-solidity@2.0.0
embark build
in your terminal and you should see that the contract has been compiled and deployed locally. The output would contain key messages "Finished deploying" and "Finished building" highlighted in green similar to the below:Web3.js.
This library helps connecting to an Ethereum node (either local or remote) and test a contract on the network through JavaScript and its libraries.embark test
, our contract will be automatically built and deployed locally.web3
will be exposed for all tests as a global object and its methods can be consumed directly.assert
will be exposed globally without additional dependencies.const MyFioriToken = require('Embark/contracts/MyFioriToken');
contract("MyFioriToken", function (accounts) {
const _name = "Fiori Token";
const _symbol = "FIO";
const _decimals = 0;
let fcInstance;
beforeEach(async function () {
fcInstance = await MyFioriToken.deploy({ arguments: [_name, _symbol, _decimals] }).send();
});
it("Should do something as Test Case 1", async function () {
...
});
it("Should do something as Test Case 2", async function () {
...
});
});
web3
before. There's a send()
method call, which interacts with the blockchain network and alters its state by deploying the contract. You should use the send()
every time you would like to call a contract's method, which forces execution of a transaction in the network (setter functions). On the other hand, the call()
method is used for contract's methods, which don't alter the state of the network (getter functions).await
operator in the deploy
call inside of the async
function. The operator is used there in order to wait for the resolution of a JavaScript Promise. Asynchronous calls are used a lot in blockchain tests because smart contract calls changing the contract state are sent to the network as transactions and must be mined, which can take considerable time.deposit
.it("Should create a contract with zero supply", async function () {
let result = await fcInstance.methods.totalSupply().call();
assert.equal(result, 0);
});
it("Should create a contract with zero balance for an account", async function () {
const account0 = accounts[0];
let result = await fcInstance.methods.balanceOf(account0).call();
assert.equal(result, 0);
});
deposit
method:it("Should mint tokens for an account", async function () {
const account0 = accounts[0];
await fcInstance.methods.deposit().send({ from: account0, value: 10 });
const result = await fcInstance.methods.balanceOf(account0).call();
const balance = parseFloat(result);
assert.equal(balance, 10);
});
it("Should pass tokens between accounts", async function () {
const account0 = accounts[0];
const account1 = accounts[1];
await fcInstance.methods.deposit().send({ from: account0, value: 10 });
const result0 = await fcInstance.methods.balanceOf(account0).call();
const balance0 = parseFloat(result0);
assert.equal(balance0, 10);
await fcInstance.methods.deposit().send({ from: account1, value: 10 });
const result1 = await fcInstance.methods.balanceOf(account1).call();
const balance1 = parseFloat(result1);
assert.equal(balance1, 10);
await fcInstance.methods.transfer(account1, 2).send({ from: account0 });
const result2 = await fcInstance.methods.balanceOf(account1).call();
const balance2 = parseFloat(result2);
assert.equal(balance2, 12);
const result3 = await fcInstance.methods.balanceOf(account0).call();
const balance3 = parseFloat(result3);
assert.equal(balance3, 8);
});
it("Should not allow minting tokens for same account twice", async function () {
const account0 = accounts[0];
await fcInstance.methods.deposit().send({ from: account0, value: 10 });
await fcInstance.methods.deposit().send({ from: account0, value: 10 });
const result = await fcInstance.methods.balanceOf(account0).call();
const balance = parseFloat(result);
assert.equal(balance, 10);
});
_toppedUpAccounts
and enhance the deposit
method with an additional check:pragma solidity 0.4.24;
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
contract MyFioriToken is ERC20 {
string public name;
string public symbol;
uint256 public decimals;
mapping(address => bool) private _toppedUpAccounts;
constructor(string _name, string _symbol, uint8 _decimals)
ERC20()
public
{
name = _name;
symbol = _symbol;
decimals = _decimals;
}
function deposit() public payable returns (bool) {
bool result = false;
if (!_toppedUpAccounts[msg.sender]) {
uint256 value = msg.value * 10**decimals;
increaseAllowance(msg.sender, value);
result = mint(msg.sender, value);
if (result) {
_toppedUpAccounts[msg.sender] = result;
}
}
return result;
}
function mint(address to, uint256 amount) public returns (bool) {
_mint(to, amount);
return true;
}
}
embark test
:You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
35 | |
25 | |
13 | |
7 | |
7 | |
6 | |
6 | |
6 | |
5 | |
4 |