Skip to content

Commit

Permalink
Add smart contract tests (Truffle)
Browse files Browse the repository at this point in the history
  • Loading branch information
DeltaBalances committed Oct 17, 2018
1 parent f873469 commit 089920c
Show file tree
Hide file tree
Showing 12 changed files with 575 additions and 3 deletions.
23 changes: 23 additions & 0 deletions smart_contract/contracts/Migrations.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
pragma solidity ^0.4.17;

contract Migrations {
address public owner;
uint public last_completed_migration;

modifier restricted() {
if (msg.sender == owner) _;
}

constructor() public {
owner = msg.sender;
}

function setCompleted(uint completed) public restricted {
last_completed_migration = completed;
}

function upgrade(address new_address) public restricted {
Migrations upgraded = Migrations(new_address);
upgraded.setCompleted(last_completed_migration);
}
}
File renamed without changes.
41 changes: 41 additions & 0 deletions smart_contract/contracts/test/DummyExchange.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
pragma solidity ^0.4.24;

// a dummy exchange implementation to test deposited balances


contract SafeMath {
function safeAdd(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = a + b;
require(c >= a);
return c;
}
}

contract Token {
function balanceOf(address _owner) external view returns (uint256 balance);
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
}

contract DummyExchange is SafeMath{

mapping (address => mapping (address => uint)) public balances;

constructor() public {}

function deposit() external payable {
balances[0][msg.sender] = safeAdd(balances[0][msg.sender], msg.value);
}

// requires token.approve
function depositToken(address token, uint amount) external {
require(token != address(0x0));

require(Token(token).transferFrom(msg.sender, address(this), amount));
balances[token][msg.sender] = safeAdd(balances[token][msg.sender], amount);
}

function balanceOf(address token, address user) external view returns (uint) {
return balances[token][user];
}
}

170 changes: 170 additions & 0 deletions smart_contract/contracts/test/ERC20.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
pragma solidity ^0.4.24;

// erc20 implementations for testing
// needs some SafeMath for actual usage

// deliberately missing allowance() and balanceOf()
contract IncompleteERC20 {
uint256 constant internal MAX_UINT256 = 2**256 - 1;
mapping (address => uint256) public balances;
mapping (address => mapping (address => uint256)) public allowed;

uint256 public totalSupply;

string public name;
uint8 public decimals;
string public symbol;

event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);

constructor (
uint256 _initialAmount,
string _tokenName,
uint8 _decimalUnits,
string _tokenSymbol
) public {
balances[msg.sender] = _initialAmount;
totalSupply = _initialAmount;
name = _tokenName;
decimals = _decimalUnits;
symbol = _tokenSymbol;
}

function transfer(address _to, uint256 _value) public returns (bool success) {
require(balances[msg.sender] >= _value);
balances[msg.sender] -= _value;
balances[_to] += _value;
emit Transfer(msg.sender, _to, _value);
return true;
}

function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
uint256 allowance = allowed[_from][msg.sender];
require(balances[_from] >= _value && allowance >= _value);
balances[_to] += _value;
balances[_from] -= _value;
if (allowance < MAX_UINT256) {
allowed[_from][msg.sender] -= _value;
}
emit Transfer(_from, _to, _value);
return true;
}

/*
function balanceOf(address _owner) public view returns (uint256 balance) {
return balances[_owner];
}
*/

function approve(address _spender, uint256 _value) public returns (bool success) {
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value); //solhint-disable-line indent, no-unused-vars
return true;
}

/*
function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
return allowed[_owner][_spender];
}
*/
}

//make it a valid ERC20
contract ERC20 is IncompleteERC20 {

constructor (
uint256 _initialAmount,
string _tokenName,
uint8 _decimalUnits,
string _tokenSymbol
) IncompleteERC20(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol)
public { }

function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
return allowed[_owner][_spender];
}

function balanceOf(address _owner) public view returns (uint256 balance) {
return balances[_owner];
}
}

// ERC20 with failing functions
contract BadERC20 is IncompleteERC20 {

constructor (
uint256 _initialAmount,
string _tokenName,
uint8 _decimalUnits,
string _tokenSymbol
) IncompleteERC20(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol)
public { }

function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
require(false);
return 0;
}

function balanceOf(address _owner) public view returns (uint256 balance) {
require(false);
return 0;
}
}

//erc20 contract that can selfdestruct
contract KillERC20 is ERC20 {

constructor (
uint256 _initialAmount,
string _tokenName,
uint8 _decimalUnits,
string _tokenSymbol
) ERC20(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol)
public { }

function kill() external {
selfdestruct(msg.sender);
}
}

// ERC20 with public variables instead of normal functions
contract AltERC20 is IncompleteERC20 {

mapping (address => uint256) public balanceOf;
mapping (address => mapping (address => uint256)) public allowance;

constructor (
uint256 _initialAmount,
string _tokenName,
uint8 _decimalUnits,
string _tokenSymbol
) IncompleteERC20(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol)
public { }

function transfer(address _to, uint256 _value) public returns (bool success) {
require(balanceOf[msg.sender] >= _value);
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
emit Transfer(msg.sender, _to, _value);
return true;
}

function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
uint256 allowance2 = allowance[_from][msg.sender];
require(balances[_from] >= _value && allowance2 >= _value);
balances[_to] += _value;
balances[_from] -= _value;
if (allowance2 < MAX_UINT256) {
allowance[_from][msg.sender] -= _value;
}
emit Transfer(_from, _to, _value);
return true;
}

function approve(address _spender, uint256 _value) public returns (bool success) {
allowance[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
}
1 change: 0 additions & 1 deletion smart_contract/deltabalances.sol.interface

This file was deleted.

1 change: 0 additions & 1 deletion smart_contract/etherdelta.sol.interface

This file was deleted.

5 changes: 5 additions & 0 deletions smart_contract/migrations/1_initial_migration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var Migrations = artifacts.require("./Migrations.sol");

module.exports = function(deployer) {
deployer.deploy(Migrations);
};
5 changes: 5 additions & 0 deletions smart_contract/migrations/2_contract_migration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const DeltaBalances = artifacts.require("DeltaBalances");

module.exports = function(deployer) {
deployer.deploy(DeltaBalances);
};
24 changes: 24 additions & 0 deletions smart_contract/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Contract `deltabalances.sol` is located in `./test`
Deployed on mainnet at [0x40a38911e470fc088beeb1a9480c2d69c847bcec](https://etherscan.io/address/0x40a38911e470fc088beeb1a9480c2d69c847bcec)


# Testing with Truffle

**Install**
Install the following to be able to run the tests
`npm install -g truffle` (Ethereum Development suite)
`npm install -g ganache-cli` (Virtual Ethereum node)


**Setup tests**
Before testing, start ganache (port 7545, as defined in truffle-config.js)
`ganache-cli -p 7545`

Build and deploy the virtual contracts
`truffle migrate`

**Run all tests**
`truffle test`
**Run a specific test file**
`truffle test ./test/filename.js`

Loading

0 comments on commit 089920c

Please sign in to comment.